Browse Source

Update `core:container` tests

Jeroen van Rijn 1 year ago
parent
commit
a463e282db

+ 1 - 1
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

+ 1 - 1
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

+ 36 - 35
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
 	}

+ 0 - 26
tests/core/container/test_core_container.odin

@@ -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)
-}

+ 46 - 44
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
 	}

+ 36 - 33
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)
-
-    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 })
+	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)
+	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)
+
+	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 }))
+}
 
-    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 })
+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
 }