diff --git a/tests/core/Makefile b/tests/core/Makefile index ef76bbbb8..fff46fb69 100644 --- a/tests/core/Makefile +++ b/tests/core/Makefile @@ -40,7 +40,7 @@ compress_test: $(ODIN) test compress $(COMMON) -define:test_progress_width=3 -out:test_core_compress container_test: - $(ODIN) run container $(COMMON) $(COLLECTION) -out:test_core_container + $(ODIN) test container $(COMMON) -define:test_progress_width=4 -out:test_core_container strings_test: $(ODIN) run strings $(COMMON) -out:test_core_strings diff --git a/tests/core/build.bat b/tests/core/build.bat index e33b49531..07432a657 100644 --- a/tests/core/build.bat +++ b/tests/core/build.bat @@ -11,7 +11,7 @@ echo --- echo --- echo Running core:container tests echo --- -%PATH_TO_ODIN% run container %COMMON% %COLLECTION% -out:test_core_container.exe || exit /b +%PATH_TO_ODIN% test container %COMMON% define:test_progress_width=4 -out:test_core_container.exe || exit /b echo --- echo Running core:crypto tests diff --git a/tests/core/container/test_core_avl.odin b/tests/core/container/test_core_avl.odin index 2244ab7f6..37b21a6be 100644 --- a/tests/core/container/test_core_avl.odin +++ b/tests/core/container/test_core_avl.odin @@ -4,22 +4,21 @@ import "core:container/avl" import "core:math/rand" import "core:slice" import "core:testing" -import "core:fmt" -import tc "tests:common" +import "core:log" @(test) test_avl :: proc(t: ^testing.T) { - tc.log(t, fmt.tprintf("Testing avl, using random seed %v, add -define:RANDOM_SEED=%v to reuse it.", random_seed, random_seed)) + log.infof("Testing avl, using random seed %v, add -define:RANDOM_SEED=%v to reuse it.", random_seed, random_seed) // Initialization. tree: avl.Tree(int) avl.init(&tree, slice.cmp_proc(int)) - tc.expect(t, avl.len(&tree) == 0, "empty: len should be 0") - tc.expect(t, avl.first(&tree) == nil, "empty: first should be nil") - tc.expect(t, avl.last(&tree) == nil, "empty: last should be nil") + testing.expect(t, avl.len(&tree) == 0, "empty: len should be 0") + testing.expect(t, avl.first(&tree) == nil, "empty: first should be nil") + testing.expect(t, avl.last(&tree) == nil, "empty: last should be nil") iter := avl.iterator(&tree, avl.Direction.Forward) - tc.expect(t, avl.iterator_get(&iter) == nil, "empty/iterator: first node should be nil") + testing.expect(t, avl.iterator_get(&iter) == nil, "empty/iterator: first node should be nil") r: rand.Rand rand.init(&r, random_seed) @@ -27,30 +26,32 @@ test_avl :: proc(t: ^testing.T) { // Test insertion. NR_INSERTS :: 32 + 1 // Ensure at least 1 collision. inserted_map := make(map[int]^avl.Node(int)) + defer delete(inserted_map) for i := 0; i < NR_INSERTS; i += 1 { v := int(rand.uint32(&r) & 0x1f) existing_node, in_map := inserted_map[v] n, ok, _ := avl.find_or_insert(&tree, v) - tc.expect(t, in_map != ok, "insert: ok should match inverse of map lookup") + testing.expect(t, in_map != ok, "insert: ok should match inverse of map lookup") if ok { inserted_map[v] = n } else { - tc.expect(t, existing_node == n, "insert: expecting existing node") + testing.expect(t, existing_node == n, "insert: expecting existing node") } } nrEntries := len(inserted_map) - tc.expect(t, avl.len(&tree) == nrEntries, "insert: len after") + testing.expect(t, avl.len(&tree) == nrEntries, "insert: len after") validate_avl(t, &tree) // Ensure that all entries can be found. for k, v in inserted_map { - tc.expect(t, v == avl.find(&tree, k), "Find(): Node") - tc.expect(t, k == v.value, "Find(): Node value") + testing.expect(t, v == avl.find(&tree, k), "Find(): Node") + testing.expect(t, k == v.value, "Find(): Node value") } // Test the forward/backward iterators. inserted_values: [dynamic]int + defer delete(inserted_values) for k in inserted_map { append(&inserted_values, k) } @@ -60,38 +61,38 @@ test_avl :: proc(t: ^testing.T) { visited: int for node in avl.iterator_next(&iter) { v, idx := node.value, visited - tc.expect(t, inserted_values[idx] == v, "iterator/forward: value") - tc.expect(t, node == avl.iterator_get(&iter), "iterator/forward: get") + testing.expect(t, inserted_values[idx] == v, "iterator/forward: value") + testing.expect(t, node == avl.iterator_get(&iter), "iterator/forward: get") visited += 1 } - tc.expect(t, visited == nrEntries, "iterator/forward: visited") + testing.expect(t, visited == nrEntries, "iterator/forward: visited") slice.reverse(inserted_values[:]) iter = avl.iterator(&tree, avl.Direction.Backward) visited = 0 for node in avl.iterator_next(&iter) { v, idx := node.value, visited - tc.expect(t, inserted_values[idx] == v, "iterator/backward: value") + testing.expect(t, inserted_values[idx] == v, "iterator/backward: value") visited += 1 } - tc.expect(t, visited == nrEntries, "iterator/backward: visited") + testing.expect(t, visited == nrEntries, "iterator/backward: visited") // Test removal. rand.shuffle(inserted_values[:], &r) for v, i in inserted_values { node := avl.find(&tree, v) - tc.expect(t, node != nil, "remove: find (pre)") + testing.expect(t, node != nil, "remove: find (pre)") ok := avl.remove(&tree, v) - tc.expect(t, ok, "remove: succeeds") - tc.expect(t, nrEntries - (i + 1) == avl.len(&tree), "remove: len (post)") + testing.expect(t, ok, "remove: succeeds") + testing.expect(t, nrEntries - (i + 1) == avl.len(&tree), "remove: len (post)") validate_avl(t, &tree) - tc.expect(t, nil == avl.find(&tree, v), "remove: find (post") + testing.expect(t, nil == avl.find(&tree, v), "remove: find (post") } - tc.expect(t, avl.len(&tree) == 0, "remove: len should be 0") - tc.expect(t, avl.first(&tree) == nil, "remove: first should be nil") - tc.expect(t, avl.last(&tree) == nil, "remove: last should be nil") + testing.expect(t, avl.len(&tree) == 0, "remove: len should be 0") + testing.expect(t, avl.first(&tree) == nil, "remove: first should be nil") + testing.expect(t, avl.last(&tree) == nil, "remove: last should be nil") // Refill the tree. for v in inserted_values { @@ -104,25 +105,25 @@ test_avl :: proc(t: ^testing.T) { v := node.value ok := avl.iterator_remove(&iter) - tc.expect(t, ok, "iterator/remove: success") + testing.expect(t, ok, "iterator/remove: success") ok = avl.iterator_remove(&iter) - tc.expect(t, !ok, "iterator/remove: redundant removes should fail") + testing.expect(t, !ok, "iterator/remove: redundant removes should fail") - tc.expect(t, avl.find(&tree, v) == nil, "iterator/remove: node should be gone") - tc.expect(t, avl.iterator_get(&iter) == nil, "iterator/remove: get should return nil") + testing.expect(t, avl.find(&tree, v) == nil, "iterator/remove: node should be gone") + testing.expect(t, avl.iterator_get(&iter) == nil, "iterator/remove: get should return nil") // Ensure that iterator_next still works. node, ok = avl.iterator_next(&iter) - tc.expect(t, ok == (avl.len(&tree) > 0), "iterator/remove: next should return false") - tc.expect(t, node == avl.first(&tree), "iterator/remove: next should return first") + testing.expect(t, ok == (avl.len(&tree) > 0), "iterator/remove: next should return false") + testing.expect(t, node == avl.first(&tree), "iterator/remove: next should return first") validate_avl(t, &tree) } - tc.expect(t, avl.len(&tree) == nrEntries - 1, "iterator/remove: len should drop by 1") + testing.expect(t, avl.len(&tree) == nrEntries - 1, "iterator/remove: len should drop by 1") avl.destroy(&tree) - tc.expect(t, avl.len(&tree) == 0, "destroy: len should be 0") + testing.expect(t, avl.len(&tree) == 0, "destroy: len should be 0") } @(private) @@ -141,10 +142,10 @@ tree_check_invariants :: proc( } // Validate the parent pointer. - tc.expect(t, parent == node._parent, "invalid parent pointer") + testing.expect(t, parent == node._parent, "invalid parent pointer") // Validate that the balance factor is -1, 0, 1. - tc.expect( + testing.expect( t, node._balance == -1 || node._balance == 0 || node._balance == 1, "invalid balance factor", @@ -155,7 +156,7 @@ tree_check_invariants :: proc( r_height := tree_check_invariants(t, tree, node._right, node) // Validate the AVL invariant and the balance factor. - tc.expect(t, int(node._balance) == r_height - l_height, "AVL balance factor invariant violated") + testing.expect(t, int(node._balance) == r_height - l_height, "AVL balance factor invariant violated") if l_height > r_height { return l_height + 1 } diff --git a/tests/core/container/test_core_container.odin b/tests/core/container/test_core_container.odin deleted file mode 100644 index 7dd4a3628..000000000 --- a/tests/core/container/test_core_container.odin +++ /dev/null @@ -1,26 +0,0 @@ -package test_core_container - -import "core:fmt" -import "core:testing" - -import tc "tests:common" - -expect_equal :: proc(t: ^testing.T, the_slice, expected: []int, loc := #caller_location) { - _eq :: proc(a, b: []int) -> bool { - if len(a) != len(b) do return false - for a, i in a { - if b[i] != a do return false - } - return true - } - tc.expect(t, _eq(the_slice, expected), fmt.tprintf("Expected %v, got %v\n", the_slice, expected), loc) -} - -main :: proc() { - t := testing.T{} - - test_avl(&t) - test_rbtree(&t) - test_small_array(&t) - tc.report(&t) -} diff --git a/tests/core/container/test_core_rbtree.odin b/tests/core/container/test_core_rbtree.odin index 89742b1d0..a4151d120 100644 --- a/tests/core/container/test_core_rbtree.odin +++ b/tests/core/container/test_core_rbtree.odin @@ -3,14 +3,16 @@ package test_core_container import rb "core:container/rbtree" import "core:math/rand" import "core:testing" -import "core:fmt" import "base:intrinsics" import "core:mem" import "core:slice" -import tc "tests:common" +import "core:log" -RANDOM_SEED :: #config(RANDOM_SEED, 0) -random_seed := u64(intrinsics.read_cycle_counter()) when RANDOM_SEED == 0 else u64(RANDOM_SEED) +@(private) +_RANDOM_SEED :: #config(RANDOM_SEED, u64(0)) + +// Exported +random_seed := u64(intrinsics.read_cycle_counter()) when _RANDOM_SEED == 0 else u64(_RANDOM_SEED) test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { track: mem.Tracking_Allocator @@ -21,15 +23,15 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { r: rand.Rand rand.init(&r, random_seed) - tc.log(t, fmt.tprintf("Testing Red-Black Tree($Key=%v,$Value=%v), using random seed %v, add -define:RANDOM_SEED=%v to reuse it.", type_info_of(Key), type_info_of(Value), random_seed, random_seed)) + log.infof("Testing Red-Black Tree($Key=%v,$Value=%v), using random seed %v, add -define:RANDOM_SEED=%v to reuse it.", type_info_of(Key), type_info_of(Value), random_seed, random_seed) tree: rb.Tree(Key, Value) rb.init(&tree) - tc.expect(t, rb.len(&tree) == 0, "empty: len should be 0") - tc.expect(t, rb.first(&tree) == nil, "empty: first should be nil") - tc.expect(t, rb.last(&tree) == nil, "empty: last should be nil") + testing.expect(t, rb.len(&tree) == 0, "empty: len should be 0") + testing.expect(t, rb.first(&tree) == nil, "empty: first should be nil") + testing.expect(t, rb.last(&tree) == nil, "empty: last should be nil") iter := rb.iterator(&tree, .Forward) - tc.expect(t, rb.iterator_get(&iter) == nil, "empty/iterator: first node should be nil") + testing.expect(t, rb.iterator_get(&iter) == nil, "empty/iterator: first node should be nil") // Test insertion. NR_INSERTS :: 32 + 1 // Ensure at least 1 collision. @@ -45,27 +47,27 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { existing_node, in_map := inserted_map[k] n, inserted, _ := rb.find_or_insert(&tree, k, v) - tc.expect(t, in_map != inserted, "insert: inserted should match inverse of map lookup") + testing.expect(t, in_map != inserted, "insert: inserted should match inverse of map lookup") if inserted { inserted_map[k] = n } else { - tc.expect(t, existing_node == n, "insert: expecting existing node") + testing.expect(t, existing_node == n, "insert: expecting existing node") } } entry_count := len(inserted_map) - tc.expect(t, rb.len(&tree) == entry_count, "insert: len after") + testing.expect(t, rb.len(&tree) == entry_count, "insert: len after") validate_rbtree(t, &tree) first := rb.first(&tree) last := rb.last(&tree) - tc.expect(t, first != nil && first.key == min_key, fmt.tprintf("insert: first should be present with key %v", min_key)) - tc.expect(t, last != nil && last.key == max_key, fmt.tprintf("insert: last should be present with key %v", max_key)) + testing.expectf(t, first != nil && first.key == min_key, "insert: first should be present with key %v", min_key) + testing.expectf(t, last != nil && last.key == max_key, "insert: last should be present with key %v", max_key) // Ensure that all entries can be found. for k, v in inserted_map { - tc.expect(t, v == rb.find(&tree, k), "Find(): Node") - tc.expect(t, k == v.key, "Find(): Node key") + testing.expect(t, v == rb.find(&tree, k), "Find(): Node") + testing.expect(t, k == v.key, "Find(): Node key") } // Test the forward/backward iterators. @@ -79,21 +81,21 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { visited: int for node in rb.iterator_next(&iter) { k, idx := node.key, visited - tc.expect(t, inserted_keys[idx] == k, "iterator/forward: key") - tc.expect(t, node == rb.iterator_get(&iter), "iterator/forward: get") + testing.expect(t, inserted_keys[idx] == k, "iterator/forward: key") + testing.expect(t, node == rb.iterator_get(&iter), "iterator/forward: get") visited += 1 } - tc.expect(t, visited == entry_count, "iterator/forward: visited") + testing.expect(t, visited == entry_count, "iterator/forward: visited") slice.reverse(inserted_keys[:]) iter = rb.iterator(&tree, rb.Direction.Backward) visited = 0 for node in rb.iterator_next(&iter) { k, idx := node.key, visited - tc.expect(t, inserted_keys[idx] == k, "iterator/backward: key") + testing.expect(t, inserted_keys[idx] == k, "iterator/backward: key") visited += 1 } - tc.expect(t, visited == entry_count, "iterator/backward: visited") + testing.expect(t, visited == entry_count, "iterator/backward: visited") // Test removal (and on_remove callback) rand.shuffle(inserted_keys[:], &r) @@ -104,19 +106,19 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { } for k, i in inserted_keys { node := rb.find(&tree, k) - tc.expect(t, node != nil, "remove: find (pre)") + testing.expect(t, node != nil, "remove: find (pre)") ok := rb.remove(&tree, k) - tc.expect(t, ok, "remove: succeeds") - tc.expect(t, entry_count - (i + 1) == rb.len(&tree), "remove: len (post)") + testing.expect(t, ok, "remove: succeeds") + testing.expect(t, entry_count - (i + 1) == rb.len(&tree), "remove: len (post)") validate_rbtree(t, &tree) - tc.expect(t, nil == rb.find(&tree, k), "remove: find (post") + testing.expect(t, nil == rb.find(&tree, k), "remove: find (post") } - tc.expect(t, rb.len(&tree) == 0, "remove: len should be 0") - tc.expect(t, callback_count == 0, fmt.tprintf("remove: on_remove should've been called %v times, it was %v", entry_count, callback_count)) - tc.expect(t, rb.first(&tree) == nil, "remove: first should be nil") - tc.expect(t, rb.last(&tree) == nil, "remove: last should be nil") + testing.expect(t, rb.len(&tree) == 0, "remove: len should be 0") + testing.expectf(t, callback_count == 0, "remove: on_remove should've been called %v times, it was %v", entry_count, callback_count) + testing.expect(t, rb.first(&tree) == nil, "remove: first should be nil") + testing.expect(t, rb.last(&tree) == nil, "remove: last should be nil") // Refill the tree. for k in inserted_keys { @@ -130,32 +132,32 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { k := node.key ok := rb.iterator_remove(&iter) - tc.expect(t, ok, "iterator/remove: success") + testing.expect(t, ok, "iterator/remove: success") ok = rb.iterator_remove(&iter) - tc.expect(t, !ok, "iterator/remove: redundant removes should fail") + testing.expect(t, !ok, "iterator/remove: redundant removes should fail") - tc.expect(t, rb.find(&tree, k) == nil, "iterator/remove: node should be gone") - tc.expect(t, rb.iterator_get(&iter) == nil, "iterator/remove: get should return nil") + testing.expect(t, rb.find(&tree, k) == nil, "iterator/remove: node should be gone") + testing.expect(t, rb.iterator_get(&iter) == nil, "iterator/remove: get should return nil") // Ensure that iterator_next still works. node, ok = rb.iterator_next(&iter) - tc.expect(t, ok == (rb.len(&tree) > 0), "iterator/remove: next should return false") - tc.expect(t, node == rb.first(&tree), "iterator/remove: next should return first") + testing.expect(t, ok == (rb.len(&tree) > 0), "iterator/remove: next should return false") + testing.expect(t, node == rb.first(&tree), "iterator/remove: next should return first") validate_rbtree(t, &tree) } - tc.expect(t, rb.len(&tree) == entry_count - 1, "iterator/remove: len should drop by 1") + testing.expect(t, rb.len(&tree) == entry_count - 1, "iterator/remove: len should drop by 1") rb.destroy(&tree) - tc.expect(t, rb.len(&tree) == 0, "destroy: len should be 0") - tc.expect(t, callback_count == 0, fmt.tprintf("remove: on_remove should've been called %v times, it was %v", entry_count, callback_count)) + testing.expect(t, rb.len(&tree) == 0, "destroy: len should be 0") + testing.expectf(t, callback_count == 0, "remove: on_remove should've been called %v times, it was %v", entry_count, callback_count) // print_tree_node(tree._root) delete(inserted_map) delete(inserted_keys) - tc.expect(t, len(track.allocation_map) == 0, fmt.tprintf("Expected 0 leaks, have %v", len(track.allocation_map))) - tc.expect(t, len(track.bad_free_array) == 0, fmt.tprintf("Expected 0 bad frees, have %v", len(track.bad_free_array))) + testing.expectf(t, len(track.allocation_map) == 0, "Expected 0 leaks, have %v", len(track.allocation_map)) + testing.expectf(t, len(track.bad_free_array) == 0, "Expected 0 bad frees, have %v", len(track.bad_free_array)) return } @@ -194,7 +196,7 @@ validate_rbtree :: proc(t: ^testing.T, tree: ^$T/rb.Tree($Key, $Value)) { } verify_rbtree_propery_1 :: proc(t: ^testing.T, n: ^$N/rb.Node($Key, $Value)) { - tc.expect(t, rb.node_color(n) == .Black || rb.node_color(n) == .Red, "Property #1: Each node is either red or black.") + testing.expect(t, rb.node_color(n) == .Black || rb.node_color(n) == .Red, "Property #1: Each node is either red or black.") if n == nil { return } @@ -203,14 +205,14 @@ verify_rbtree_propery_1 :: proc(t: ^testing.T, n: ^$N/rb.Node($Key, $Value)) { } verify_rbtree_propery_2 :: proc(t: ^testing.T, root: ^$N/rb.Node($Key, $Value)) { - tc.expect(t, rb.node_color(root) == .Black, "Property #2: Root node should be black.") + testing.expect(t, rb.node_color(root) == .Black, "Property #2: Root node should be black.") } verify_rbtree_propery_4 :: proc(t: ^testing.T, n: ^$N/rb.Node($Key, $Value)) { if rb.node_color(n) == .Red { // A red node's left, right and parent should be black all_black := rb.node_color(n._left) == .Black && rb.node_color(n._right) == .Black && rb.node_color(n._parent) == .Black - tc.expect(t, all_black, "Property #3: Red node's children + parent must be black.") + testing.expect(t, all_black, "Property #3: Red node's children + parent must be black.") } if n == nil { return @@ -233,7 +235,7 @@ verify_rbtree_propery_5_helper :: proc(t: ^testing.T, n: ^$N/rb.Node($Key, $Valu if path_black_count^ == -1 { path_black_count^ = black_count } else { - tc.expect(t, black_count == path_black_count^, "Property #5: Paths from a node to its leaves contain same black count.") + testing.expect(t, black_count == path_black_count^, "Property #5: Paths from a node to its leaves contain same black count.") } return } diff --git a/tests/core/container/test_core_small_array.odin b/tests/core/container/test_core_small_array.odin index 78998de16..580df793e 100644 --- a/tests/core/container/test_core_small_array.odin +++ b/tests/core/container/test_core_small_array.odin @@ -3,44 +3,47 @@ package test_core_container import "core:testing" import "core:container/small_array" -import tc "tests:common" - -@(test) -test_small_array :: proc(t: ^testing.T) { - tc.log(t, "Testing small_array") - - test_small_array_removes(t) - test_small_array_inject_at(t) -} - @(test) test_small_array_removes :: proc(t: ^testing.T) { - array: small_array.Small_Array(10, int) - small_array.append(&array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + array: small_array.Small_Array(10, int) + small_array.append(&array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - small_array.ordered_remove(&array, 0) - expect_equal(t, small_array.slice(&array), []int { 1, 2, 3, 4, 5, 6, 7, 8, 9 }) - small_array.ordered_remove(&array, 5) - expect_equal(t, small_array.slice(&array), []int { 1, 2, 3, 4, 5, 7, 8, 9 }) - small_array.ordered_remove(&array, 6) - expect_equal(t, small_array.slice(&array), []int { 1, 2, 3, 4, 5, 7, 9 }) - small_array.unordered_remove(&array, 0) - expect_equal(t, small_array.slice(&array), []int { 9, 2, 3, 4, 5, 7 }) - small_array.unordered_remove(&array, 2) - expect_equal(t, small_array.slice(&array), []int { 9, 2, 7, 4, 5 }) - small_array.unordered_remove(&array, 4) - expect_equal(t, small_array.slice(&array), []int { 9, 2, 7, 4 }) + small_array.ordered_remove(&array, 0) + testing.expect(t, slice_equal(small_array.slice(&array), []int { 1, 2, 3, 4, 5, 6, 7, 8, 9 })) + small_array.ordered_remove(&array, 5) + testing.expect(t, slice_equal(small_array.slice(&array), []int { 1, 2, 3, 4, 5, 7, 8, 9 })) + small_array.ordered_remove(&array, 6) + testing.expect(t, slice_equal(small_array.slice(&array), []int { 1, 2, 3, 4, 5, 7, 9 })) + small_array.unordered_remove(&array, 0) + testing.expect(t, slice_equal(small_array.slice(&array), []int { 9, 2, 3, 4, 5, 7 })) + small_array.unordered_remove(&array, 2) + testing.expect(t, slice_equal(small_array.slice(&array), []int { 9, 2, 7, 4, 5 })) + small_array.unordered_remove(&array, 4) + testing.expect(t, slice_equal(small_array.slice(&array), []int { 9, 2, 7, 4 })) } @(test) test_small_array_inject_at :: proc(t: ^testing.T) { - array: small_array.Small_Array(13, int) - small_array.append(&array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + array: small_array.Small_Array(13, int) + small_array.append(&array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - tc.expect(t, small_array.inject_at(&array, 0, 0), "Expected to be able to inject into small array") - expect_equal(t, small_array.slice(&array), []int { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }) - tc.expect(t, small_array.inject_at(&array, 0, 5), "Expected to be able to inject into small array") - expect_equal(t, small_array.slice(&array), []int { 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9 }) - tc.expect(t, small_array.inject_at(&array, 0, small_array.len(array)), "Expected to be able to inject into small array") - expect_equal(t, small_array.slice(&array), []int { 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 0 }) + testing.expect(t, small_array.inject_at(&array, 0, 0), "Expected to be able to inject into small array") + testing.expect(t, slice_equal(small_array.slice(&array), []int { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 })) + testing.expect(t, small_array.inject_at(&array, 0, 5), "Expected to be able to inject into small array") + testing.expect(t, slice_equal(small_array.slice(&array), []int { 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9 })) + testing.expect(t, small_array.inject_at(&array, 0, small_array.len(array)), "Expected to be able to inject into small array") + testing.expect(t, slice_equal(small_array.slice(&array), []int { 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 0 })) +} + +slice_equal :: proc(a, b: []int) -> bool { + if len(a) != len(b) { + return false + } + + for a, i in a { + if b[i] != a { + return false + } + } + return true }