read_linux_test.odin (2495B)
1 #+build linux 2 package walk 3 4 import "core:fmt" 5 import "core:os" 6 import "core:slice" 7 import "core:testing" 8 9 import "../scan" 10 11 /* 12 A hole costs nothing and has to be charged nothing. 13 14 This is the one answer that differs from the portable reader, which knows only the 15 length and rounds it up to a guessed block. A file of mostly hole would be charged 16 its whole length that way, which for a tool reporting what fills a disk is not a 17 rounding error but the wrong file. 18 */ 19 @(test) 20 test_a_sparse_file_is_charged_what_it_occupies :: proc(t: ^testing.T) { 21 dir, dir_err := os.temp_directory(context.temp_allocator) 22 testing.expect(t, dir_err == nil, "no temp directory") 23 root := fmt.tprintf("%s/sonar_walk_sparse", dir) 24 os.remove_all(root) 25 defer os.remove_all(root) 26 testing.expect(t, os.make_directory(root) == nil, "could not make the root") 27 28 // One megabyte of nothing at all. 29 hole, hole_err := os.open(fmt.tprintf("%s/hole.bin", root), {.Write, .Create, .Trunc}) 30 testing.expect(t, hole_err == nil, "could not create the sparse file") 31 testing.expect(t, os.truncate(hole, 1 << 20) == nil, "could not extend the sparse file") 32 os.close(hole) 33 34 // The same length, actually written. 35 body := make([]byte, 1 << 20, context.temp_allocator) 36 slice.fill(body, 'x') 37 testing.expect( 38 t, 39 os.write_entire_file(fmt.tprintf("%s/solid.bin", root), body) == nil, 40 "could not write", 41 ) 42 43 tree: scan.Tree 44 testing.expect_value(t, scan.tree_init(&tree, 1), scan.Error.None) 45 defer scan.tree_destroy(&tree) 46 testing.expect_value(t, read(root, &tree, Config{}), Error.None) 47 48 for i in 0 ..< tree.count { 49 n := scan.node(&tree, i) 50 switch n.name { 51 case "hole.bin": 52 testing.expect_value(t, n.size, u64(1 << 20)) 53 testing.expectf(t, n.disk < 64 * 1024, "a hole was charged %d bytes", n.disk) 54 case "solid.bin": 55 testing.expect_value(t, n.size, u64(1 << 20)) 56 testing.expectf(t, n.disk >= 1 << 20, "a full megabyte was charged %d bytes", n.disk) 57 } 58 } 59 } 60 61 // A path the kernel would refuse is refused here, rather than silently truncated to 62 // one that names a different directory. 63 @(test) 64 test_a_path_too_long_is_refused :: proc(t: ^testing.T) { 65 buf: Path 66 long := make([]byte, len(buf), context.temp_allocator) 67 slice.fill(long, 'a') 68 69 _, ok := terminate(string(long), &buf) 70 testing.expect(t, !ok, "an over-long path was accepted") 71 72 fits, fits_ok := terminate("/usr/share", &buf) 73 testing.expect(t, fits_ok, "an ordinary path was refused") 74 testing.expect_value(t, string(fits), "/usr/share") 75 }