ringbuffer_test.gno
2.76 Kb · 123 lines
1package ringbuffer
2
3import (
4 "strings"
5 "testing"
6
7 "gno.land/p/nt/uassert/v0"
8)
9
10func TestPushPopFIFO(t *testing.T) {
11 r := New(3)
12 r.Push("a")
13 r.Push("b")
14 uassert.Equal(t, 2, r.Len())
15 v, ok := r.Pop()
16 uassert.True(t, ok)
17 uassert.Equal(t, "a", v)
18 v, _ = r.Pop()
19 uassert.Equal(t, "b", v)
20 _, ok = r.Pop()
21 uassert.False(t, ok)
22}
23
24// The defining behaviour: full means overwrite the oldest, and say so.
25func TestOverwriteOldest(t *testing.T) {
26 r := New(3)
27 for _, s := range []string{"a", "b", "c"} {
28 ev, dropped := r.Push(s)
29 uassert.False(t, dropped)
30 uassert.Equal(t, "", ev)
31 }
32 uassert.True(t, r.Full())
33 ev, dropped := r.Push("d")
34 uassert.True(t, dropped)
35 uassert.Equal(t, "a", ev) // the OLDEST went, not the newest
36 uassert.Equal(t, "b,c,d", strings.Join(r.Slice(), ","))
37 uassert.Equal(t, 3, r.Len())
38}
39
40// Wrapping must not corrupt order — the classic ring-buffer bug.
41func TestWrapAroundKeepsOrder(t *testing.T) {
42 r := New(3)
43 for _, s := range []string{"1", "2", "3", "4", "5", "6", "7"} {
44 r.Push(s)
45 }
46 uassert.Equal(t, "5,6,7", strings.Join(r.Slice(), ","))
47 v, _ := r.Peek()
48 uassert.Equal(t, "5", v)
49}
50
51// Interleaving Pop and Push moves head and tail independently.
52func TestInterleavedPushPop(t *testing.T) {
53 r := New(3)
54 r.Push("a")
55 r.Push("b")
56 r.Pop() // drop a
57 r.Push("c")
58 r.Push("d") // fills: b,c,d
59 uassert.Equal(t, "b,c,d", strings.Join(r.Slice(), ","))
60 ev, dropped := r.Push("e")
61 uassert.True(t, dropped)
62 uassert.Equal(t, "b", ev)
63 uassert.Equal(t, "c,d,e", strings.Join(r.Slice(), ","))
64}
65
66func TestAt(t *testing.T) {
67 r := New(3)
68 r.Push("a")
69 r.Push("b")
70 v, ok := r.At(0)
71 uassert.True(t, ok)
72 uassert.Equal(t, "a", v) // 0 is the OLDEST
73 v, _ = r.At(1)
74 uassert.Equal(t, "b", v)
75 _, ok = r.At(2)
76 uassert.False(t, ok)
77 _, ok = r.At(-1)
78 uassert.False(t, ok)
79}
80
81// A zero-capacity buffer stores nothing and admits it rather than pretending.
82func TestZeroCapacity(t *testing.T) {
83 r := New(0)
84 uassert.Equal(t, 0, r.Cap())
85 ev, dropped := r.Push("x")
86 uassert.True(t, dropped)
87 uassert.Equal(t, "x", ev)
88 uassert.True(t, r.Empty())
89 uassert.False(t, r.Full()) // a buffer that holds nothing is never "full"
90 uassert.Equal(t, 0, len(r.Slice()))
91}
92
93func TestEmptyPeekPop(t *testing.T) {
94 r := New(2)
95 _, ok := r.Peek()
96 uassert.False(t, ok)
97 _, ok = r.Pop()
98 uassert.False(t, ok)
99}
100
101func TestReset(t *testing.T) {
102 r := New(3)
103 r.Push("a")
104 r.Push("b")
105 r.Reset()
106 uassert.True(t, r.Empty())
107 uassert.Equal(t, 0, r.Len())
108 r.Push("z")
109 uassert.Equal(t, "z", strings.Join(r.Slice(), ","))
110}
111
112func TestSliceIsACopy(t *testing.T) {
113 r := New(3)
114 r.Push("a")
115 s := r.Slice()
116 s[0] = "mutated"
117 uassert.Equal(t, "a", strings.Join(r.Slice(), ","))
118}
119
120func TestCapClamped(t *testing.T) {
121 uassert.Equal(t, 0, New(-5).Cap())
122 uassert.Equal(t, MaxCap, New(MaxCap+100).Cap())
123}