package ring_buffer_tests

import "core:testing"

import "lib:container/ring_buffer"

@(test)
test_append_at_start :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb)
	defer ring_buffer.destroy(&rb)

	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	testing.expect(t, rb.off == 0 && rb.len == 6, "failed to append Foobar")
}

@(test)
test_append_at_mid :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb)
	defer ring_buffer.destroy(&rb)

	rb.off += rb.cap / 2
	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	testing.expect(t, rb.off == rb.cap / 2 && rb.len == 6, "failed to append Foobar")
}

@(test)
test_append_multi :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb)
	defer ring_buffer.destroy(&rb)

	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	testing.expect(t, rb.off == 0 && rb.len == 12, "failed to append Foobar")
}

@(test)
test_append_over_border :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb)
	defer ring_buffer.destroy(&rb)

	rb.off += rb.cap - 3
	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	testing.expect(t, rb.off == rb.cap - 3 && rb.len == 6, "failed to append Foobar")
}

@(test)
test_consume_at_start :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb)
	defer ring_buffer.destroy(&rb)

	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	buf := ring_buffer.consume_front(&rb, 6)
	defer delete(buf)
	testing.expectf(t, buf != nil && len(buf) == 6, "couldn't consume: %s", buf)
}

@(test)
test_consume_over_border :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb)
	defer ring_buffer.destroy(&rb)

	rb.off += rb.cap - 3
	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	buf := ring_buffer.consume_front(&rb, 6)
	defer delete(buf)
	testing.expectf(t, buf != nil && len(buf) == 6 && rb.off < rb.cap, "couldn't consume: %s", buf)
}

@(test)
test_grow_contained :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb)
	defer ring_buffer.destroy(&rb)

	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	cap := rb.cap
	ring_buffer.grow(&rb)
	testing.expect(t, rb.len == 6 && cap * 2 == rb.cap && string(rb.buf[:6]) == "Foobar", "couldn't grow")
}

@(test)
test_grow_over_border :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb)
	defer ring_buffer.destroy(&rb)

	rb.off += rb.cap - 3
	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	cap := rb.cap
	ring_buffer.grow(&rb)
	testing.expect(t, rb.len == 6 && cap * 2 == rb.cap && string(rb.buf[:6]) == "Foobar", "couldn't grow")
}

@(test)
test_grow_with_append :: proc(t: ^testing.T) {
	rb: ring_buffer.Ring_Buffer
	ring_buffer.init(&rb, 4)
	defer ring_buffer.destroy(&rb)

	ring_buffer.append(&rb, {'F', 'o', 'o', 'b', 'a', 'r'})
	testing.expect(t, rb.len == 6 && rb.cap == 8 && string(rb.buf[:6]) == "Foobar", "couldn't grow")
}