sonar

Scan files at memory bandwidth speed.
Log | Files | Refs

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 }