ringBuffer.test.ts139 lines · main
1import { describe, expect, it } from 'vitest'
2
3import { RingBuffer } from './ringBuffer'
4
5describe('RingBuffer', () => {
6 it('follows FIFO order when popping from the front', () => {
7 const buffer = new RingBuffer<number>(5)
8
9 buffer.pushBack(1)
10 buffer.pushBack(2)
11 buffer.pushBack(3)
12
13 expect(buffer.popFront()).toBe(1)
14 expect(buffer.popFront()).toBe(2)
15 expect(buffer.popFront()).toBe(3)
16 expect(buffer.popFront()).toBeUndefined()
17 })
18
19 it('supports popping from the back', () => {
20 const buffer = new RingBuffer<number>(3)
21
22 buffer.pushBack(1)
23 buffer.pushBack(2)
24 buffer.pushBack(3)
25
26 expect(buffer.popBack()).toBe(3)
27 expect(buffer.popBack()).toBe(2)
28 expect(buffer.popBack()).toBe(1)
29 expect(buffer.popBack()).toBeUndefined()
30 })
31
32 it('drops the oldest element when full', () => {
33 const buffer = new RingBuffer<number>(3)
34
35 buffer.pushBack(1)
36 buffer.pushBack(2)
37 buffer.pushBack(3)
38 buffer.pushBack(4)
39
40 expect(buffer.length).toBe(3)
41 expect(buffer.popFront()).toBe(2)
42 expect(buffer.popFront()).toBe(3)
43 expect(buffer.popFront()).toBe(4)
44 })
45
46 it('handles mixed operations correctly', () => {
47 const buffer = new RingBuffer<string>(2)
48
49 buffer.pushBack('a')
50 buffer.pushBack('b')
51
52 expect(buffer.popFront()).toBe('a')
53
54 buffer.pushBack('c')
55 buffer.pushBack('d')
56
57 expect(buffer.length).toBe(2)
58 expect(buffer.popBack()).toBe('d')
59 expect(buffer.popFront()).toBe('c')
60 expect(buffer.popFront()).toBeUndefined()
61 })
62
63 it('returns undefined when popping from an empty buffer', () => {
64 const buffer = new RingBuffer<number>(1)
65
66 expect(buffer.popFront()).toBeUndefined()
67 expect(buffer.popBack()).toBeUndefined()
68 })
69
70 it('requires a positive integer capacity', () => {
71 expect(() => new RingBuffer(0)).toThrow('positive integer')
72 expect(() => new RingBuffer(-1)).toThrow('positive integer')
73 expect(() => new RingBuffer(1.5 as unknown as number)).toThrow('positive integer')
74 })
75
76 it('returns the full contents in order via toArray', () => {
77 const buffer = new RingBuffer<number>(5)
78
79 buffer.pushBack(1)
80 buffer.pushBack(2)
81 buffer.pushBack(3)
82
83 expect(buffer.toArray()).toEqual([1, 2, 3])
84 })
85
86 it('supports slice-style bounds for toArray', () => {
87 const buffer = new RingBuffer<number>(5)
88
89 buffer.pushBack(1)
90 buffer.pushBack(2)
91 buffer.pushBack(3)
92 buffer.pushBack(4)
93
94 expect(buffer.toArray(1, 3)).toEqual([2, 3])
95 expect(buffer.toArray(2)).toEqual([3, 4])
96 })
97
98 it('handles negative and overflowing bounds in toArray', () => {
99 const buffer = new RingBuffer<number>(4)
100
101 buffer.pushBack(10)
102 buffer.pushBack(20)
103 buffer.pushBack(30)
104 buffer.pushBack(40)
105
106 expect(buffer.toArray(-2)).toEqual([30, 40])
107 expect(buffer.toArray(0, -1)).toEqual([10, 20, 30])
108 expect(buffer.toArray(-5, 10)).toEqual([10, 20, 30, 40])
109 })
110
111 it('returns an empty array when the slice is empty', () => {
112 const buffer = new RingBuffer<number>(3)
113
114 buffer.pushBack(1)
115 buffer.pushBack(2)
116
117 expect(buffer.toArray(5)).toEqual([])
118 expect(buffer.toArray(2, 2)).toEqual([])
119 expect(buffer.toArray(2, 1)).toEqual([])
120
121 const emptyBuffer = new RingBuffer<number>(3)
122 expect(emptyBuffer.toArray()).toEqual([])
123 expect(emptyBuffer.toArray(1)).toEqual([])
124 })
125
126 it('returns entries in order after overwriting oldest values', () => {
127 const buffer = new RingBuffer<number>(3)
128
129 buffer.pushBack(1)
130 buffer.pushBack(2)
131 buffer.pushBack(3)
132 buffer.pushBack(4)
133 buffer.pushBack(5)
134
135 expect(buffer.toArray()).toEqual([3, 4, 5])
136 expect(buffer.toArray(1)).toEqual([4, 5])
137 expect(buffer.toArray(-1)).toEqual([5])
138 })
139})