tree_test.odin (4053B)
1 package scan 2 3 import "core:strings" 4 import "core:testing" 5 6 @(private = "file") 7 fresh :: proc(t: ^testing.T, writers := 1) -> Tree { 8 tree: Tree 9 testing.expect_value(t, tree_init(&tree, writers), Error.None) 10 return tree 11 } 12 13 @(test) 14 test_claim_hands_out_distinct_slots :: proc(t: ^testing.T) { 15 tree := fresh(t) 16 defer tree_destroy(&tree) 17 w := writer(&tree) 18 19 a, a_err := claim(&w, 3) 20 b, b_err := claim(&w, 2) 21 testing.expect_value(t, a_err, Error.None) 22 testing.expect_value(t, b_err, Error.None) 23 testing.expect_value(t, a, u32(0)) 24 testing.expect_value(t, b, u32(3)) 25 testing.expect_value(t, tree.count, u32(5)) 26 } 27 28 @(test) 29 test_claim_grows_across_blocks :: proc(t: ^testing.T) { 30 // Crossing a block boundary is where a growable store goes wrong, so write a 31 // marker either side of one and read both back. 32 tree := fresh(t) 33 defer tree_destroy(&tree) 34 w := writer(&tree) 35 36 first, err := claim(&w, BLOCK_NODES + 16) 37 testing.expect_value(t, err, Error.None) 38 testing.expect_value(t, first, u32(0)) 39 40 node(&tree, 0).size = 11 41 node(&tree, BLOCK_NODES - 1).size = 22 42 node(&tree, BLOCK_NODES).size = 33 43 node(&tree, BLOCK_NODES + 15).size = 44 44 45 testing.expect_value(t, node(&tree, 0).size, u64(11)) 46 testing.expect_value(t, node(&tree, BLOCK_NODES - 1).size, u64(22)) 47 testing.expect_value(t, node(&tree, BLOCK_NODES).size, u64(33)) 48 testing.expect_value(t, node(&tree, BLOCK_NODES + 15).size, u64(44)) 49 } 50 51 @(test) 52 test_reserve_makes_every_slot_addressable :: proc(t: ^testing.T) { 53 // A reader that indexes by its own numbering needs the whole range at once. 54 tree := fresh(t) 55 defer tree_destroy(&tree) 56 testing.expect_value(t, reserve(&tree, 100_000), Error.None) 57 testing.expect_value(t, tree.count, u32(100_000)) 58 node(&tree, 99_999).size = 7 59 testing.expect_value(t, node(&tree, 99_999).size, u64(7)) 60 } 61 62 @(test) 63 test_interned_names_outlive_the_source :: proc(t: ^testing.T) { 64 tree := fresh(t) 65 defer tree_destroy(&tree) 66 w := writer(&tree) 67 68 buf := [8]byte{'r', 'e', 'p', 'o', 'r', 't', 0, 0} 69 name := intern(&w, string(buf[:6])) 70 buf = {'x', 'x', 'x', 'x', 'x', 'x', 0, 0} // the source is reused, as a read buffer is 71 testing.expect_value(t, name, "report") 72 } 73 74 @(test) 75 test_path_walks_to_a_root :: proc(t: ^testing.T) { 76 tree := fresh(t) 77 defer tree_destroy(&tree) 78 w := writer(&tree) 79 first, _ := claim(&w, 3) 80 testing.expect_value(t, first, u32(0)) 81 82 node(&tree, 0)^ = Node { 83 parent = 0, 84 name = "C:", 85 flags = {.Used, .Directory}, 86 } 87 node(&tree, 1)^ = Node { 88 parent = 0, 89 name = "Windows", 90 flags = {.Used, .Directory}, 91 } 92 node(&tree, 2)^ = Node { 93 parent = 1, 94 name = "notepad.exe", 95 flags = {.Used}, 96 } 97 98 // Written with the separator of the machine showing the path, not the one the 99 // names came from, so this is built rather than spelled. 100 want := strings.concatenate( 101 {"C:", SEPARATOR, "Windows", SEPARATOR, "notepad.exe"}, 102 context.temp_allocator, 103 ) 104 testing.expect_value(t, path(&tree, 2, context.temp_allocator), want) 105 testing.expect_value(t, path(&tree, 0, context.temp_allocator), "C:") 106 } 107 108 @(test) 109 test_path_stops_at_a_cycle :: proc(t: ^testing.T) { 110 // A corrupt source can name a parent that leads back round. The walk must end 111 // rather than run forever. 112 tree := fresh(t) 113 defer tree_destroy(&tree) 114 w := writer(&tree) 115 claim(&w, 2) 116 node(&tree, 0)^ = Node { 117 parent = 1, 118 name = "a", 119 flags = {.Used, .Directory}, 120 } 121 node(&tree, 1)^ = Node { 122 parent = 0, 123 name = "b", 124 flags = {.Used, .Directory}, 125 } 126 127 p := path(&tree, 0, context.temp_allocator) 128 testing.expect(t, len(p) > 0, "a cycle produced no path at all") 129 } 130 131 @(test) 132 test_cancel_is_visible_to_a_reader :: proc(t: ^testing.T) { 133 tree := fresh(t) 134 defer tree_destroy(&tree) 135 testing.expect(t, !cancelled(&tree)) 136 cancel(&tree) 137 testing.expect(t, cancelled(&tree)) 138 } 139 140 @(test) 141 test_progress_accumulates :: proc(t: ^testing.T) { 142 tree := fresh(t) 143 defer tree_destroy(&tree) 144 progress(&tree, 3, 300) 145 progress(&tree, 4, 400) 146 testing.expect_value(t, tree.nodes_done, u64(7)) 147 testing.expect_value(t, tree.bytes_done, u64(700)) 148 }