github.com/bpfs/defs@v0.0.15/afero/tarfs/tarfs_test.go (about) 1 // Most of the tests are stolen from the zipfs implementation 2 package tarfs 3 4 import ( 5 "archive/tar" 6 "errors" 7 "fmt" 8 "io" 9 "os" 10 "path/filepath" 11 "reflect" 12 "strings" 13 "syscall" 14 "testing" 15 16 "github.com/bpfs/defs/afero" 17 ) 18 19 var files = []struct { 20 name string 21 exists bool 22 isdir bool 23 size int64 24 content string 25 contentAt4k string 26 }{ 27 {"/", true, true, 0, "", ""}, 28 {"/sub", true, true, 0, "", ""}, 29 {"/sub/testDir2", true, true, 0, "", ""}, 30 {"/sub/testDir2/testFile", true, false, 8192, "cccccccc", "ccccdddd"}, 31 {"/testFile", true, false, 8192, "aaaaaaaa", "aaaabbbb"}, 32 {"/testDir1/testFile", true, false, 8192, "bbbbbbbb", "bbbbcccc"}, 33 34 {"/nonExisting", false, false, 0, "", ""}, 35 } 36 37 var dirs = []struct { 38 name string 39 children []string 40 }{ 41 {"/", []string{"sub", "testDir1", "testFile"}}, 42 {"/sub", []string{"testDir2"}}, 43 {"/sub/testDir2", []string{"testFile"}}, 44 {"/testDir1", []string{"testFile"}}, 45 } 46 47 var afs *afero.Afero 48 49 func TestMain(m *testing.M) { 50 tf, err := os.Open("testdata/t.tar") 51 if err != nil { 52 fmt.Print(err) 53 os.Exit(1) 54 } 55 56 tfs := New(tar.NewReader(tf)) 57 afs = &afero.Afero{Fs: tfs} 58 59 // Check that an empty reader does not panic. 60 _ = New(tar.NewReader(strings.NewReader(""))) 61 os.Exit(m.Run()) 62 } 63 64 func TestFsOpen(t *testing.T) { 65 for _, f := range files { 66 file, err := afs.Open(f.name) 67 if (err == nil) != f.exists { 68 t.Errorf("%v exists = %v, but got err = %v", f.name, f.exists, err) 69 } 70 71 if !f.exists { 72 continue 73 } 74 if err != nil { 75 t.Fatalf("%v: %v", f.name, err) 76 } 77 78 if file.Name() != filepath.FromSlash(f.name) { 79 t.Errorf("Name(), got %v, expected %v", file.Name(), filepath.FromSlash(f.name)) 80 } 81 82 s, err := file.Stat() 83 if err != nil { 84 t.Fatalf("stat %v: got error '%v'", file.Name(), err) 85 } 86 87 if isdir := s.IsDir(); isdir != f.isdir { 88 t.Errorf("%v directory, got: %v, expected: %v", file.Name(), isdir, f.isdir) 89 } 90 91 if size := s.Size(); size != f.size { 92 t.Errorf("%v size, got: %v, expected: %v", file.Name(), size, f.size) 93 } 94 } 95 } 96 97 func TestRead(t *testing.T) { 98 for _, f := range files { 99 if !f.exists { 100 continue 101 } 102 103 file, err := afs.Open(f.name) 104 if err != nil { 105 t.Fatalf("opening %v: %v", f.name, err) 106 } 107 108 buf := make([]byte, 8) 109 n, err := file.Read(buf) 110 if err != nil { 111 if f.isdir && (err != syscall.EISDIR) { 112 t.Errorf("%v got error %v, expected EISDIR", f.name, err) 113 } else if !f.isdir { 114 t.Errorf("%v: %v", f.name, err) 115 } 116 } else if n != 8 { 117 t.Errorf("%v: got %d read bytes, expected 8", f.name, n) 118 } else if string(buf) != f.content { 119 t.Errorf("%v: got <%s>, expected <%s>", f.name, f.content, string(buf)) 120 } 121 122 } 123 } 124 125 func TestReadAt(t *testing.T) { 126 for _, f := range files { 127 if !f.exists { 128 continue 129 } 130 131 file, err := afs.Open(f.name) 132 if err != nil { 133 t.Fatalf("opening %v: %v", f.name, err) 134 } 135 136 buf := make([]byte, 8) 137 n, err := file.ReadAt(buf, 4092) 138 if err != nil { 139 if f.isdir && (err != syscall.EISDIR) { 140 t.Errorf("%v got error %v, expected EISDIR", f.name, err) 141 } else if !f.isdir { 142 t.Errorf("%v: %v", f.name, err) 143 } 144 } else if n != 8 { 145 t.Errorf("%v: got %d read bytes, expected 8", f.name, n) 146 } else if string(buf) != f.contentAt4k { 147 t.Errorf("%v: got <%s>, expected <%s>", f.name, f.contentAt4k, string(buf)) 148 } 149 150 } 151 } 152 153 func TestSeek(t *testing.T) { 154 for _, f := range files { 155 if !f.exists { 156 continue 157 } 158 159 file, err := afs.Open(f.name) 160 if err != nil { 161 t.Fatalf("opening %v: %v", f.name, err) 162 } 163 164 tests := []struct { 165 offin int64 166 whence int 167 offout int64 168 }{ 169 {0, io.SeekStart, 0}, 170 {10, io.SeekStart, 10}, 171 {1, io.SeekCurrent, 11}, 172 {10, io.SeekCurrent, 21}, 173 {0, io.SeekEnd, f.size}, 174 {-1, io.SeekEnd, f.size - 1}, 175 } 176 177 for _, s := range tests { 178 n, err := file.Seek(s.offin, s.whence) 179 if err != nil { 180 if f.isdir && err == syscall.EISDIR { 181 continue 182 } 183 184 t.Errorf("%v: %v", f.name, err) 185 } 186 187 if n != s.offout { 188 t.Errorf("%v: (off: %v, whence: %v): got %v, expected %v", f.name, s.offin, s.whence, n, s.offout) 189 } 190 } 191 192 } 193 } 194 195 func TestName(t *testing.T) { 196 for _, f := range files { 197 if !f.exists { 198 continue 199 } 200 201 file, err := afs.Open(f.name) 202 if err != nil { 203 t.Fatalf("opening %v: %v", f.name, err) 204 } 205 206 n := file.Name() 207 if n != filepath.FromSlash(f.name) { 208 t.Errorf("got: %v, expected: %v", n, filepath.FromSlash(f.name)) 209 } 210 211 } 212 } 213 214 func TestClose(t *testing.T) { 215 for _, f := range files { 216 if !f.exists { 217 continue 218 } 219 220 file, err := afs.Open(f.name) 221 if err != nil { 222 t.Fatalf("opening %v: %v", f.name, err) 223 } 224 225 err = file.Close() 226 if err != nil { 227 t.Errorf("%v: %v", f.name, err) 228 } 229 230 err = file.Close() 231 if err == nil { 232 t.Errorf("%v: closing twice should return an error", f.name) 233 } 234 235 buf := make([]byte, 8) 236 n, err := file.Read(buf) 237 if n != 0 || err == nil { 238 t.Errorf("%v: could read from a closed file", f.name) 239 } 240 241 n, err = file.ReadAt(buf, 256) 242 if n != 0 || err == nil { 243 t.Errorf("%v: could readAt from a closed file", f.name) 244 } 245 246 off, err := file.Seek(0, io.SeekStart) 247 if off != 0 || err == nil { 248 t.Errorf("%v: could seek from a closed file", f.name) 249 } 250 } 251 } 252 253 func TestOpenFile(t *testing.T) { 254 for _, f := range files { 255 file, err := afs.OpenFile(f.name, os.O_RDONLY, 0o400) 256 if !f.exists { 257 if !errors.Is(err, syscall.ENOENT) { 258 t.Errorf("%v: got %v, expected%v", f.name, err, syscall.ENOENT) 259 } 260 261 continue 262 } 263 264 if err != nil { 265 t.Fatalf("%v: %v", f.name, err) 266 } 267 file.Close() 268 269 _, err = afs.OpenFile(f.name, os.O_CREATE, 0o600) 270 if !errors.Is(err, syscall.EPERM) { 271 t.Errorf("%v: open for write: got %v, expected %v", f.name, err, syscall.EPERM) 272 } 273 274 } 275 } 276 277 func TestFsStat(t *testing.T) { 278 for _, f := range files { 279 fi, err := afs.Stat(f.name) 280 if !f.exists { 281 if !errors.Is(err, syscall.ENOENT) { 282 t.Errorf("%v: got %v, expected%v", f.name, err, syscall.ENOENT) 283 } 284 285 continue 286 } 287 288 if err != nil { 289 t.Fatalf("stat %v: got error '%v'", f.name, err) 290 } 291 292 if isdir := fi.IsDir(); isdir != f.isdir { 293 t.Errorf("%v directory, got: %v, expected: %v", f.name, isdir, f.isdir) 294 } 295 296 if size := fi.Size(); size != f.size { 297 t.Errorf("%v size, got: %v, expected: %v", f.name, size, f.size) 298 } 299 } 300 } 301 302 func TestReaddir(t *testing.T) { 303 for _, d := range dirs { 304 dir, err := afs.Open(d.name) 305 if err != nil { 306 t.Fatal(err) 307 } 308 309 fi, err := dir.Readdir(0) 310 if err != nil { 311 t.Fatal(err) 312 } 313 var names []string 314 for _, f := range fi { 315 names = append(names, f.Name()) 316 } 317 318 if !reflect.DeepEqual(names, d.children) { 319 t.Errorf("%v: children, got '%v', expected '%v'", d.name, names, d.children) 320 } 321 322 fi, err = dir.Readdir(1) 323 if err != nil { 324 t.Fatal(err) 325 } 326 327 names = []string{} 328 for _, f := range fi { 329 names = append(names, f.Name()) 330 } 331 332 if !reflect.DeepEqual(names, d.children[0:1]) { 333 t.Errorf("%v: children, got '%v', expected '%v'", d.name, names, d.children[0:1]) 334 } 335 } 336 337 dir, err := afs.Open("/testFile") 338 if err != nil { 339 t.Fatal(err) 340 } 341 342 _, err = dir.Readdir(-1) 343 if err != syscall.ENOTDIR { 344 t.Fatal("Expected error") 345 } 346 } 347 348 func TestReaddirnames(t *testing.T) { 349 for _, d := range dirs { 350 dir, err := afs.Open(d.name) 351 if err != nil { 352 t.Fatal(err) 353 } 354 355 names, err := dir.Readdirnames(0) 356 if err != nil { 357 t.Fatal(err) 358 } 359 360 if !reflect.DeepEqual(names, d.children) { 361 t.Errorf("%v: children, got '%v', expected '%v'", d.name, names, d.children) 362 } 363 364 names, err = dir.Readdirnames(1) 365 if err != nil { 366 t.Fatal(err) 367 } 368 369 if !reflect.DeepEqual(names, d.children[0:1]) { 370 t.Errorf("%v: children, got '%v', expected '%v'", d.name, names, d.children[0:1]) 371 } 372 } 373 374 dir, err := afs.Open("/testFile") 375 if err != nil { 376 t.Fatal(err) 377 } 378 379 _, err = dir.Readdir(-1) 380 if err != syscall.ENOTDIR { 381 t.Fatal("Expected error") 382 } 383 } 384 385 func TestGlob(t *testing.T) { 386 for _, s := range []struct { 387 glob string 388 entries []string 389 }{ 390 {filepath.FromSlash("/*"), []string{filepath.FromSlash("/sub"), filepath.FromSlash("/testDir1"), filepath.FromSlash("/testFile")}}, 391 {filepath.FromSlash("*"), []string{filepath.FromSlash("sub"), filepath.FromSlash("testDir1"), filepath.FromSlash("testFile")}}, 392 {filepath.FromSlash("sub/*"), []string{filepath.FromSlash("sub/testDir2")}}, 393 {filepath.FromSlash("sub/testDir2/*"), []string{filepath.FromSlash("sub/testDir2/testFile")}}, 394 {filepath.FromSlash("testDir1/*"), []string{filepath.FromSlash("testDir1/testFile")}}, 395 } { 396 entries, err := afero.Glob(afs.Fs, s.glob) 397 if err != nil { 398 t.Error(err) 399 } 400 if reflect.DeepEqual(entries, s.entries) { 401 t.Logf("glob: %s: glob ok", s.glob) 402 } else { 403 t.Errorf("glob: %s: got %#v, expected %#v", s.glob, entries, s.entries) 404 } 405 } 406 }