carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package instancefs
4
5import (
6 "errors"
7 "os"
8 "path/filepath"
9 "syscall"
10 "testing"
11 "time"
12)
13
14// OpenBeneathOrAbsent is the one place absence is decided: absent only
15// when the name is not found beneath the descriptor dir was opened as.
16func TestOpenBeneathOrAbsentDecidesAbsenceBeneathOneDescriptor(t *testing.T) {
17 setup := func(t *testing.T) (dir string) {
18 t.Helper()
19 dir = filepath.Join(t.TempDir(), "inst")
20 if err := os.Mkdir(dir, 0o700); err != nil {
21 t.Fatal(err)
22 }
23 if err := os.WriteFile(filepath.Join(dir, "f"), []byte("bytes"), 0o600); err != nil {
24 t.Fatal(err)
25 }
26 return dir
27 }
28 open := func(t *testing.T, dir, name string) (string, bool, error) {
29 t.Helper()
30 type res struct {
31 b string
32 absent bool
33 err error
34 }
35 done := make(chan res, 1)
36 go func() {
37 f, absent, err := OpenBeneathOrAbsent(dir, name)
38 var b []byte
39 if f != nil {
40 b, _ = readLimit(f, name, 1<<10)
41 f.Close()
42 }
43 done <- res{string(b), absent, err}
44 }()
45 select {
46 case r := <-done:
47 return r.b, r.absent, r.err
48 case <-time.After(20 * time.Second):
49 t.Fatal("OpenBeneathOrAbsent blocked")
50 return "", false, nil
51 }
52 }
53 t.Run("present", func(t *testing.T) {
54 if b, absent, err := open(t, setup(t), "f"); err != nil || absent || b != "bytes" {
55 t.Fatalf("got %q absent=%v %v", b, absent, err)
56 }
57 })
58 t.Run("absent beneath a directory that opened", func(t *testing.T) {
59 if _, absent, err := open(t, setup(t), "g"); err != nil || !absent {
60 t.Fatalf("absent=%v %v", absent, err)
61 }
62 })
63 t.Run("a missing directory is an error", func(t *testing.T) {
64 _, absent, err := open(t, filepath.Join(t.TempDir(), "gone"), "f")
65 if absent || !errors.Is(err, ErrDirUnopened) || !errors.Is(err, os.ErrNotExist) {
66 t.Fatalf("absent=%v %v", absent, err)
67 }
68 })
69 t.Run("a symlinked directory is an error", func(t *testing.T) {
70 dir := setup(t)
71 if err := os.Symlink(dir, dir+".link"); err != nil {
72 t.Fatal(err)
73 }
74 _, absent, err := open(t, dir+".link", "f")
75 if absent || !errors.Is(err, ErrDirUnopened) || !errors.Is(err, ErrSymlink) {
76 t.Fatalf("absent=%v %v", absent, err)
77 }
78 })
79 t.Run("a symlink at the name is the name's, not the directory's", func(t *testing.T) {
80 dir := setup(t)
81 if err := os.Symlink(filepath.Join(dir, "f"), filepath.Join(dir, "l")); err != nil {
82 t.Fatal(err)
83 }
84 _, absent, err := open(t, dir, "l")
85 if absent || !errors.Is(err, ErrSymlink) || errors.Is(err, ErrDirUnopened) {
86 t.Fatalf("absent=%v %v", absent, err)
87 }
88 })
89 t.Run("a FIFO", func(t *testing.T) {
90 dir := setup(t)
91 if err := syscall.Mkfifo(filepath.Join(dir, "p"), 0o600); err != nil {
92 t.Fatal(err)
93 }
94 if _, absent, err := open(t, dir, "p"); absent || !errors.Is(err, ErrNotRegular) {
95 t.Fatalf("absent=%v %v", absent, err)
96 }
97 })
98 // Astra P2: the directory renamed away after it was opened, and an
99 // empty one put at its path, is still the directory looked in. A
100 // lookup that reopened the path would read the file as absent.
101 t.Run("a directory renamed away after the open", func(t *testing.T) {
102 dir := setup(t)
103 prev := betweenDirAndLookup
104 betweenDirAndLookup = func() {
105 if err := os.Rename(dir, dir+".away"); err != nil {
106 t.Error(err)
107 }
108 if err := os.Mkdir(dir, 0o700); err != nil {
109 t.Error(err)
110 }
111 }
112 t.Cleanup(func() { betweenDirAndLookup = prev })
113 if b, absent, err := open(t, dir, "f"); err != nil || absent || b != "bytes" {
114 t.Fatalf("got %q absent=%v %v; want the file the opened directory holds", b, absent, err)
115 }
116 })
117}
118
119// Opus M3: without /proc, OpenRootBeneath is an error, never a fallback to
120// opening the path.
121func TestOpenRootBeneathWithoutProcIsAnError(t *testing.T) {
122 parent := t.TempDir()
123 if err := os.Mkdir(filepath.Join(parent, "d"), 0o700); err != nil {
124 t.Fatal(err)
125 }
126 prev := procSelfFD
127 procSelfFD = filepath.Join(t.TempDir(), "no-proc") + "/"
128 t.Cleanup(func() { procSelfFD = prev })
129 r, err := OpenRootBeneath(parent, "d")
130 if err == nil || r != nil {
131 if r != nil {
132 r.Close()
133 }
134 t.Fatalf("OpenRootBeneath without /proc: root %v, %v; want an error", r != nil, err)
135 }
136}
137