Increased testing for ring
This commit is contained in:
+148
-2
@@ -16,11 +16,17 @@ Ring_Soa :: struct($E: typeid) {
|
||||
next_write_index, len: int,
|
||||
}
|
||||
|
||||
destroy_aos :: #force_inline proc(ring: ^Ring($E)) -> runtime.Allocator_Error {
|
||||
destroy_aos :: #force_inline proc(
|
||||
ring: ^Ring($E),
|
||||
allocator := context.allocator,
|
||||
) -> runtime.Allocator_Error {
|
||||
return delete(ring.data)
|
||||
}
|
||||
|
||||
destroy_soa :: #force_inline proc(ring: ^Ring_Soa($E)) -> runtime.Allocator_Error {
|
||||
destroy_soa :: #force_inline proc(
|
||||
ring: ^Ring_Soa($E),
|
||||
allocator := context.allocator,
|
||||
) -> runtime.Allocator_Error {
|
||||
return delete(ring.data)
|
||||
}
|
||||
|
||||
@@ -53,6 +59,7 @@ create_soa :: #force_inline proc(
|
||||
return ring, err
|
||||
}
|
||||
|
||||
// All contents of `data` will be completely ignored, `data` is treated as an empty slice.
|
||||
init_from_slice_aos :: #force_inline proc(ring: ^Ring($E), data: $T/[]E) {
|
||||
ring.data = data
|
||||
ring.len = 0
|
||||
@@ -60,6 +67,7 @@ init_from_slice_aos :: #force_inline proc(ring: ^Ring($E), data: $T/[]E) {
|
||||
return
|
||||
}
|
||||
|
||||
// All contents of `data` will be completely ignored, `data` is treated as an empty slice.
|
||||
init_from_slice_soa :: #force_inline proc(ring: ^Ring_Soa($E), data: $T/#soa[]E) {
|
||||
ring.data = data
|
||||
ring.len = 0
|
||||
@@ -291,3 +299,141 @@ test_ring_soa :: proc(t: ^testing.T) {
|
||||
testing.expect_value(t, ring.len, 1)
|
||||
testing.expect_value(t, get(ring, 0), Ints{1, 1})
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_ring_aos_init_from_slice :: proc(t: ^testing.T) {
|
||||
// Stack-allocated backing with pre-existing garbage and odd capacity.
|
||||
backing: [7]int = {99, 99, 99, 99, 99, 99, 99}
|
||||
|
||||
ring: Ring(int)
|
||||
init_from_slice(&ring, backing[:])
|
||||
|
||||
// Empty ring invariants after init_from_slice.
|
||||
testing.expect_value(t, ring.len, 0)
|
||||
testing.expect_value(t, ring.next_write_index, 0)
|
||||
testing.expect_value(t, start_index_aos(ring), 0)
|
||||
|
||||
// Partial fill (3 / 7).
|
||||
for i in 1 ..= 3 do append(&ring, i)
|
||||
testing.expect_value(t, ring.len, 3)
|
||||
testing.expect_value(t, ring.next_write_index, 3)
|
||||
testing.expect_value(t, start_index_aos(ring), 0)
|
||||
testing.expect_value(t, get(ring, 0)^, 1)
|
||||
testing.expect_value(t, get(ring, 2)^, 3)
|
||||
testing.expect_value(t, get_last(ring)^, 3)
|
||||
|
||||
// Fill exactly to capacity. Pushing element 7 must make len == cap
|
||||
// AND wrap next_write_index from 6 back to 0 in the same step.
|
||||
for i in 4 ..= 7 do append(&ring, i)
|
||||
testing.expect_value(t, ring.len, 7)
|
||||
testing.expect_value(t, ring.next_write_index, 0)
|
||||
testing.expect_value(t, start_index_aos(ring), 0)
|
||||
testing.expect_value(t, get(ring, 0)^, 1)
|
||||
testing.expect_value(t, get(ring, 6)^, 7)
|
||||
testing.expect_value(t, get_last(ring)^, 7)
|
||||
|
||||
// First overwrite — oldest element shifts by one.
|
||||
append(&ring, 8)
|
||||
testing.expect_value(t, ring.len, 7)
|
||||
testing.expect_value(t, ring.next_write_index, 1)
|
||||
testing.expect_value(t, start_index_aos(ring), 1)
|
||||
testing.expect_value(t, get(ring, 0)^, 2)
|
||||
testing.expect_value(t, get(ring, 6)^, 8)
|
||||
testing.expect_value(t, get_last(ring)^, 8)
|
||||
|
||||
// Stress: 3 more complete wrap cycles (21 more pushes).
|
||||
// After 29 total pushes, ring contains the last 7 (23..=29),
|
||||
// and next_write_index = 29 mod 7 = 1.
|
||||
for i in 9 ..= 29 do append(&ring, i)
|
||||
testing.expect_value(t, ring.len, 7)
|
||||
testing.expect_value(t, ring.next_write_index, 1)
|
||||
testing.expect_value(t, start_index_aos(ring), 1)
|
||||
testing.expect_value(t, get(ring, 0)^, 23)
|
||||
testing.expect_value(t, get(ring, 3)^, 26)
|
||||
testing.expect_value(t, get(ring, 6)^, 29)
|
||||
testing.expect_value(t, get_last(ring)^, 29)
|
||||
|
||||
// Clear returns ring to empty-equivalent state.
|
||||
clear(&ring)
|
||||
testing.expect_value(t, ring.len, 0)
|
||||
testing.expect_value(t, ring.next_write_index, 0)
|
||||
testing.expect_value(t, start_index_aos(ring), 0)
|
||||
|
||||
// Single-element edge case: get_last(len==1) routes through get(ring, 0).
|
||||
append(&ring, 42)
|
||||
testing.expect_value(t, ring.len, 1)
|
||||
testing.expect_value(t, ring.next_write_index, 1)
|
||||
testing.expect_value(t, get(ring, 0)^, 42)
|
||||
testing.expect_value(t, get_last(ring)^, 42)
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_ring_soa_init_from_slice :: proc(t: ^testing.T) {
|
||||
Ints :: struct {
|
||||
x, y: int,
|
||||
}
|
||||
|
||||
// Stack-allocated backing with pre-existing garbage and odd capacity.
|
||||
backing: #soa[7]Ints = {{99, 99}, {99, 99}, {99, 99}, {99, 99}, {99, 99}, {99, 99}, {99, 99}}
|
||||
|
||||
ring: Ring_Soa(Ints)
|
||||
init_from_slice(&ring, backing[:])
|
||||
|
||||
// Empty ring invariants after init_from_slice.
|
||||
testing.expect_value(t, ring.len, 0)
|
||||
testing.expect_value(t, ring.next_write_index, 0)
|
||||
testing.expect_value(t, start_index_soa(ring), 0)
|
||||
|
||||
// Partial fill (3 / 7).
|
||||
for i in 1 ..= 3 do append(&ring, Ints{i, i})
|
||||
testing.expect_value(t, ring.len, 3)
|
||||
testing.expect_value(t, ring.next_write_index, 3)
|
||||
testing.expect_value(t, start_index_soa(ring), 0)
|
||||
testing.expect_value(t, get(ring, 0), Ints{1, 1})
|
||||
testing.expect_value(t, get(ring, 2), Ints{3, 3})
|
||||
testing.expect_value(t, get_last(ring), Ints{3, 3})
|
||||
|
||||
// Fill exactly to capacity. Pushing element 7 must make len == cap
|
||||
// AND wrap next_write_index from 6 back to 0 in the same step.
|
||||
for i in 4 ..= 7 do append(&ring, Ints{i, i})
|
||||
testing.expect_value(t, ring.len, 7)
|
||||
testing.expect_value(t, ring.next_write_index, 0)
|
||||
testing.expect_value(t, start_index_soa(ring), 0)
|
||||
testing.expect_value(t, get(ring, 0), Ints{1, 1})
|
||||
testing.expect_value(t, get(ring, 6), Ints{7, 7})
|
||||
testing.expect_value(t, get_last(ring), Ints{7, 7})
|
||||
|
||||
// First overwrite — oldest element shifts by one.
|
||||
append(&ring, Ints{8, 8})
|
||||
testing.expect_value(t, ring.len, 7)
|
||||
testing.expect_value(t, ring.next_write_index, 1)
|
||||
testing.expect_value(t, start_index_soa(ring), 1)
|
||||
testing.expect_value(t, get(ring, 0), Ints{2, 2})
|
||||
testing.expect_value(t, get(ring, 6), Ints{8, 8})
|
||||
testing.expect_value(t, get_last(ring), Ints{8, 8})
|
||||
|
||||
// Stress: 3 more complete wrap cycles (21 more pushes).
|
||||
// After 29 total pushes, ring contains the last 7 (23..=29),
|
||||
// and next_write_index = 29 mod 7 = 1.
|
||||
for i in 9 ..= 29 do append(&ring, Ints{i, i})
|
||||
testing.expect_value(t, ring.len, 7)
|
||||
testing.expect_value(t, ring.next_write_index, 1)
|
||||
testing.expect_value(t, start_index_soa(ring), 1)
|
||||
testing.expect_value(t, get(ring, 0), Ints{23, 23})
|
||||
testing.expect_value(t, get(ring, 3), Ints{26, 26})
|
||||
testing.expect_value(t, get(ring, 6), Ints{29, 29})
|
||||
testing.expect_value(t, get_last(ring), Ints{29, 29})
|
||||
|
||||
// Clear returns ring to empty-equivalent state.
|
||||
clear(&ring)
|
||||
testing.expect_value(t, ring.len, 0)
|
||||
testing.expect_value(t, ring.next_write_index, 0)
|
||||
testing.expect_value(t, start_index_soa(ring), 0)
|
||||
|
||||
// Single-element edge case: get_last(len==1) routes through get(ring, 0).
|
||||
append(&ring, Ints{42, 42})
|
||||
testing.expect_value(t, ring.len, 1)
|
||||
testing.expect_value(t, ring.next_write_index, 1)
|
||||
testing.expect_value(t, get(ring, 0), Ints{42, 42})
|
||||
testing.expect_value(t, get_last(ring), Ints{42, 42})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user