github.com/hanwen/go-fuse@v1.0.0/unionfs/autounion_test.go (about) 1 // Copyright 2016 the Go-FUSE Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package unionfs 6 7 import ( 8 "io/ioutil" 9 "os" 10 "testing" 11 "time" 12 13 "github.com/hanwen/go-fuse/fuse" 14 "github.com/hanwen/go-fuse/fuse/nodefs" 15 "github.com/hanwen/go-fuse/fuse/pathfs" 16 "github.com/hanwen/go-fuse/internal/testutil" 17 ) 18 19 const entryTTL = 100 * time.Millisecond 20 21 var testAOpts = AutoUnionFsOptions{ 22 UnionFsOptions: testOpts, 23 Options: nodefs.Options{ 24 EntryTimeout: entryTTL, 25 AttrTimeout: entryTTL, 26 NegativeTimeout: 0, 27 Debug: testutil.VerboseTest(), 28 LookupKnownChildren: true, 29 }, 30 HideReadonly: true, 31 Version: "version", 32 } 33 34 func init() { 35 testAOpts.Options.Debug = testutil.VerboseTest() 36 } 37 38 func WriteFile(t *testing.T, name string, contents string) { 39 err := ioutil.WriteFile(name, []byte(contents), 0644) 40 if err != nil { 41 t.Fatalf("WriteFile failed: %v", err) 42 } 43 } 44 45 func setup(t *testing.T) (workdir string, server *fuse.Server, cleanup func()) { 46 wd := testutil.TempDir() 47 err := os.Mkdir(wd+"/mnt", 0700) 48 if err != nil { 49 t.Fatalf("Mkdir failed: %v", err) 50 } 51 52 err = os.Mkdir(wd+"/store", 0700) 53 if err != nil { 54 t.Fatalf("Mkdir failed: %v", err) 55 } 56 57 os.Mkdir(wd+"/ro", 0700) 58 if err != nil { 59 t.Fatalf("Mkdir failed: %v", err) 60 } 61 WriteFile(t, wd+"/ro/file1", "file1") 62 WriteFile(t, wd+"/ro/file2", "file2") 63 64 fs := NewAutoUnionFs(wd+"/store", testAOpts) 65 66 nfs := pathfs.NewPathNodeFs(fs, nil) 67 state, _, err := nodefs.MountRoot(wd+"/mnt", nfs.Root(), &testAOpts.Options) 68 if err != nil { 69 t.Fatalf("MountNodeFileSystem failed: %v", err) 70 } 71 go state.Serve() 72 state.WaitMount() 73 74 return wd, state, func() { 75 state.Unmount() 76 os.RemoveAll(wd) 77 } 78 } 79 80 func TestDebug(t *testing.T) { 81 wd, _, clean := setup(t) 82 defer clean() 83 84 c, err := ioutil.ReadFile(wd + "/mnt/status/debug") 85 if err != nil { 86 t.Fatalf("ReadFile failed: %v", err) 87 } 88 if len(c) == 0 { 89 t.Fatal("No debug found.") 90 } 91 } 92 93 func TestVersion(t *testing.T) { 94 wd, _, clean := setup(t) 95 defer clean() 96 97 c, err := ioutil.ReadFile(wd + "/mnt/status/gounionfs_version") 98 if err != nil { 99 t.Fatalf("ReadFile failed: %v", err) 100 } 101 if len(c) == 0 { 102 t.Fatal("No version found.") 103 } 104 } 105 106 func TestAutoFsSymlink(t *testing.T) { 107 wd, server, clean := setup(t) 108 defer clean() 109 110 err := os.Mkdir(wd+"/store/backing1", 0755) 111 if err != nil { 112 t.Fatalf("Mkdir failed: %v", err) 113 } 114 115 err = os.Symlink(wd+"/ro", wd+"/store/backing1/READONLY") 116 if err != nil { 117 t.Fatalf("Symlink failed: %v", err) 118 } 119 120 err = os.Symlink(wd+"/store/backing1", wd+"/mnt/config/manual1") 121 if err != nil { 122 t.Fatalf("Symlink failed: %v", err) 123 } 124 125 fi, err := os.Lstat(wd + "/mnt/manual1/file1") 126 if err != nil { 127 t.Fatalf("Lstat failed: %v", err) 128 } 129 130 entries, err := ioutil.ReadDir(wd + "/mnt") 131 if err != nil { 132 t.Fatalf("ReadDir failed: %v", err) 133 } 134 if len(entries) != 3 { 135 t.Error("readdir mismatch", entries) 136 } 137 138 err = os.Remove(wd + "/mnt/config/manual1") 139 if err != nil { 140 t.Fatalf("Remove failed: %v", err) 141 } 142 143 scan := wd + "/mnt/config/" + _SCAN_CONFIG 144 err = ioutil.WriteFile(scan, []byte("something"), 0644) 145 if err != nil { 146 t.Error("error writing:", err) 147 } 148 149 // If FUSE supports invalid inode notifications we expect this node to be gone. Otherwise we'll just make sure that it's not reachable. 150 if server.KernelSettings().SupportsNotify(fuse.NOTIFY_INVAL_INODE) { 151 fi, _ = os.Lstat(wd + "/mnt/manual1") 152 if fi != nil { 153 t.Error("Should not have file:", fi) 154 } 155 } else { 156 entries, err = ioutil.ReadDir(wd + "/mnt") 157 if err != nil { 158 t.Fatalf("ReadDir failed: %v", err) 159 } 160 for _, e := range entries { 161 if e.Name() == "manual1" { 162 t.Error("Should not have entry: ", e) 163 } 164 } 165 } 166 167 _, err = os.Lstat(wd + "/mnt/backing1/file1") 168 if err != nil { 169 t.Fatalf("Lstat failed: %v", err) 170 } 171 } 172 173 func TestDetectSymlinkedDirectories(t *testing.T) { 174 wd, _, clean := setup(t) 175 defer clean() 176 177 err := os.Mkdir(wd+"/backing1", 0755) 178 if err != nil { 179 t.Fatalf("Mkdir failed: %v", err) 180 } 181 182 err = os.Symlink(wd+"/ro", wd+"/backing1/READONLY") 183 if err != nil { 184 t.Fatalf("Symlink failed: %v", err) 185 } 186 187 err = os.Symlink(wd+"/backing1", wd+"/store/backing1") 188 if err != nil { 189 t.Fatalf("Symlink failed: %v", err) 190 } 191 192 scan := wd + "/mnt/config/" + _SCAN_CONFIG 193 err = ioutil.WriteFile(scan, []byte("something"), 0644) 194 if err != nil { 195 t.Error("error writing:", err) 196 } 197 198 _, err = os.Lstat(wd + "/mnt/backing1") 199 if err != nil { 200 t.Fatalf("Lstat failed: %v", err) 201 } 202 } 203 204 func TestExplicitScan(t *testing.T) { 205 wd, _, clean := setup(t) 206 defer clean() 207 208 err := os.Mkdir(wd+"/store/backing1", 0755) 209 if err != nil { 210 t.Fatalf("Mkdir failed: %v", err) 211 } 212 os.Symlink(wd+"/ro", wd+"/store/backing1/READONLY") 213 if err != nil { 214 t.Fatalf("Symlink failed: %v", err) 215 } 216 217 fi, _ := os.Lstat(wd + "/mnt/backing1") 218 if fi != nil { 219 t.Error("Should not have file:", fi) 220 } 221 222 scan := wd + "/mnt/config/" + _SCAN_CONFIG 223 _, err = os.Lstat(scan) 224 if err != nil { 225 t.Error(".scan_config missing:", err) 226 } 227 228 err = ioutil.WriteFile(scan, []byte("something"), 0644) 229 if err != nil { 230 t.Error("error writing:", err) 231 } 232 233 _, err = os.Lstat(wd + "/mnt/backing1") 234 if err != nil { 235 t.Error("Should have workspace backing1:", err) 236 } 237 } 238 239 func TestCreationChecks(t *testing.T) { 240 wd, _, clean := setup(t) 241 defer clean() 242 243 err := os.Mkdir(wd+"/store/foo", 0755) 244 if err != nil { 245 t.Fatalf("Mkdir failed: %v", err) 246 } 247 os.Symlink(wd+"/ro", wd+"/store/foo/READONLY") 248 if err != nil { 249 t.Fatalf("Symlink failed: %v", err) 250 } 251 252 err = os.Mkdir(wd+"/store/ws2", 0755) 253 if err != nil { 254 t.Fatalf("Mkdir failed: %v", err) 255 } 256 os.Symlink(wd+"/ro", wd+"/store/ws2/READONLY") 257 if err != nil { 258 t.Fatalf("Symlink failed: %v", err) 259 } 260 261 err = os.Symlink(wd+"/store/foo", wd+"/mnt/config/bar") 262 if err != nil { 263 t.Fatalf("Symlink failed: %v", err) 264 } 265 266 err = os.Symlink(wd+"/store/foo", wd+"/mnt/config/foo") 267 code := fuse.ToStatus(err) 268 if code != fuse.EBUSY { 269 t.Error("Should return EBUSY", err) 270 } 271 272 err = os.Symlink(wd+"/store/ws2", wd+"/mnt/config/config") 273 code = fuse.ToStatus(err) 274 if code != fuse.EINVAL { 275 t.Error("Should return EINVAL", err) 276 } 277 }