@volley/recognition-client-sdk 0.1.423 → 0.1.621

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,335 @@
1
+ /**
2
+ * Audio Ring Buffer Tests
3
+ */
4
+
5
+ import { AudioRingBuffer } from './audio-ring-buffer.js';
6
+
7
+ describe('AudioRingBuffer', () => {
8
+ describe('constructor', () => {
9
+ it('should initialize with correct buffer size', () => {
10
+ const buffer = new AudioRingBuffer({
11
+ maxBufferDurationSec: 10,
12
+ chunksPerSecond: 100
13
+ });
14
+
15
+ expect(buffer.isEmpty()).toBe(true);
16
+ expect(buffer.getBufferedCount()).toBe(0);
17
+ expect(buffer.isOverflowing()).toBe(false);
18
+ });
19
+
20
+ it('should accept logger function', () => {
21
+ const logger = jest.fn();
22
+ const buffer = new AudioRingBuffer({
23
+ maxBufferDurationSec: 1,
24
+ chunksPerSecond: 10,
25
+ logger
26
+ });
27
+
28
+ expect(buffer).toBeDefined();
29
+ });
30
+ });
31
+
32
+ describe('write', () => {
33
+ it('should write ArrayBuffer data', () => {
34
+ const buffer = new AudioRingBuffer({
35
+ maxBufferDurationSec: 1,
36
+ chunksPerSecond: 10
37
+ });
38
+
39
+ const data = new ArrayBuffer(100);
40
+ buffer.write(data);
41
+
42
+ expect(buffer.isEmpty()).toBe(false);
43
+ expect(buffer.getBufferedCount()).toBe(1);
44
+ });
45
+
46
+ it('should write ArrayBufferView data', () => {
47
+ const buffer = new AudioRingBuffer({
48
+ maxBufferDurationSec: 1,
49
+ chunksPerSecond: 10
50
+ });
51
+
52
+ const data = new Uint8Array(100);
53
+ buffer.write(data);
54
+
55
+ expect(buffer.isEmpty()).toBe(false);
56
+ expect(buffer.getBufferedCount()).toBe(1);
57
+ });
58
+
59
+ it('should track total buffered bytes', () => {
60
+ const buffer = new AudioRingBuffer({
61
+ maxBufferDurationSec: 1,
62
+ chunksPerSecond: 10
63
+ });
64
+
65
+ buffer.write(new ArrayBuffer(100));
66
+ buffer.write(new ArrayBuffer(200));
67
+
68
+ const stats = buffer.getStats();
69
+ expect(stats.totalBufferedBytes).toBe(300);
70
+ expect(stats.chunksBuffered).toBe(2);
71
+ });
72
+
73
+ it('should handle multiple writes', () => {
74
+ const buffer = new AudioRingBuffer({
75
+ maxBufferDurationSec: 1,
76
+ chunksPerSecond: 100
77
+ });
78
+
79
+ for (let i = 0; i < 50; i++) {
80
+ buffer.write(new ArrayBuffer(10));
81
+ }
82
+
83
+ expect(buffer.getBufferedCount()).toBe(50);
84
+ expect(buffer.isOverflowing()).toBe(false);
85
+ });
86
+ });
87
+
88
+ describe('overflow detection', () => {
89
+ it('should detect overflow when buffer is full', () => {
90
+ const buffer = new AudioRingBuffer({
91
+ maxBufferDurationSec: 1,
92
+ chunksPerSecond: 5 // Small buffer of 5 chunks
93
+ });
94
+
95
+ // Write more than buffer can hold
96
+ for (let i = 0; i < 10; i++) {
97
+ buffer.write(new ArrayBuffer(10));
98
+ }
99
+
100
+ expect(buffer.isOverflowing()).toBe(true);
101
+ const stats = buffer.getStats();
102
+ expect(stats.hasWrapped).toBe(true);
103
+ expect(stats.overflowCount).toBeGreaterThan(0);
104
+ });
105
+
106
+ it('should call logger on overflow', () => {
107
+ const logger = jest.fn();
108
+ const buffer = new AudioRingBuffer({
109
+ maxBufferDurationSec: 1,
110
+ chunksPerSecond: 3, // Small buffer
111
+ logger
112
+ });
113
+
114
+ // Fill buffer to overflow
115
+ for (let i = 0; i < 10; i++) {
116
+ buffer.write(new ArrayBuffer(10));
117
+ }
118
+
119
+ // Logger should have been called with overflow message
120
+ expect(logger).toHaveBeenCalledWith(
121
+ 'debug',
122
+ expect.stringContaining('overflow'),
123
+ expect.any(Object)
124
+ );
125
+ });
126
+ });
127
+
128
+ describe('read', () => {
129
+ it('should return null when buffer is empty', () => {
130
+ const buffer = new AudioRingBuffer({
131
+ maxBufferDurationSec: 1,
132
+ chunksPerSecond: 10
133
+ });
134
+
135
+ expect(buffer.read()).toBeNull();
136
+ });
137
+
138
+ it('should return data in FIFO order', () => {
139
+ const buffer = new AudioRingBuffer({
140
+ maxBufferDurationSec: 1,
141
+ chunksPerSecond: 10
142
+ });
143
+
144
+ const data1 = new Uint8Array([1, 2, 3]);
145
+ const data2 = new Uint8Array([4, 5, 6]);
146
+
147
+ buffer.write(data1);
148
+ buffer.write(data2);
149
+
150
+ const chunk1 = buffer.read();
151
+ expect(chunk1).not.toBeNull();
152
+ expect(chunk1!.data).toBe(data1);
153
+
154
+ const chunk2 = buffer.read();
155
+ expect(chunk2).not.toBeNull();
156
+ expect(chunk2!.data).toBe(data2);
157
+ });
158
+
159
+ it('should decrement buffered count after read', () => {
160
+ const buffer = new AudioRingBuffer({
161
+ maxBufferDurationSec: 1,
162
+ chunksPerSecond: 10
163
+ });
164
+
165
+ buffer.write(new ArrayBuffer(10));
166
+ buffer.write(new ArrayBuffer(10));
167
+
168
+ expect(buffer.getBufferedCount()).toBe(2);
169
+
170
+ buffer.read();
171
+ expect(buffer.getBufferedCount()).toBe(1);
172
+
173
+ buffer.read();
174
+ expect(buffer.getBufferedCount()).toBe(0);
175
+ expect(buffer.isEmpty()).toBe(true);
176
+ });
177
+ });
178
+
179
+ describe('readAll', () => {
180
+ it('should return empty array when buffer is empty', () => {
181
+ const buffer = new AudioRingBuffer({
182
+ maxBufferDurationSec: 1,
183
+ chunksPerSecond: 10
184
+ });
185
+
186
+ expect(buffer.readAll()).toEqual([]);
187
+ });
188
+
189
+ it('should return all chunks without removing them', () => {
190
+ const buffer = new AudioRingBuffer({
191
+ maxBufferDurationSec: 1,
192
+ chunksPerSecond: 10
193
+ });
194
+
195
+ buffer.write(new ArrayBuffer(10));
196
+ buffer.write(new ArrayBuffer(20));
197
+ buffer.write(new ArrayBuffer(30));
198
+
199
+ const chunks = buffer.readAll();
200
+ expect(chunks).toHaveLength(3);
201
+
202
+ // Should still have all chunks
203
+ expect(buffer.getBufferedCount()).toBe(3);
204
+ });
205
+ });
206
+
207
+ describe('flush', () => {
208
+ it('should return all chunks and clear buffer', () => {
209
+ const buffer = new AudioRingBuffer({
210
+ maxBufferDurationSec: 1,
211
+ chunksPerSecond: 10
212
+ });
213
+
214
+ buffer.write(new ArrayBuffer(10));
215
+ buffer.write(new ArrayBuffer(20));
216
+
217
+ const chunks = buffer.flush();
218
+ expect(chunks).toHaveLength(2);
219
+ expect(buffer.isEmpty()).toBe(true);
220
+ expect(buffer.getBufferedCount()).toBe(0);
221
+ });
222
+ });
223
+
224
+ describe('clear', () => {
225
+ it('should reset all state', () => {
226
+ const buffer = new AudioRingBuffer({
227
+ maxBufferDurationSec: 1,
228
+ chunksPerSecond: 5
229
+ });
230
+
231
+ // Fill and overflow
232
+ for (let i = 0; i < 10; i++) {
233
+ buffer.write(new ArrayBuffer(100));
234
+ }
235
+
236
+ expect(buffer.isOverflowing()).toBe(true);
237
+
238
+ buffer.clear();
239
+
240
+ expect(buffer.isEmpty()).toBe(true);
241
+ expect(buffer.getBufferedCount()).toBe(0);
242
+ expect(buffer.isOverflowing()).toBe(false);
243
+
244
+ const stats = buffer.getStats();
245
+ expect(stats.chunksBuffered).toBe(0);
246
+ expect(stats.totalBufferedBytes).toBe(0);
247
+ expect(stats.overflowCount).toBe(0);
248
+ expect(stats.hasWrapped).toBe(false);
249
+ });
250
+
251
+ it('should call logger when clearing', () => {
252
+ const logger = jest.fn();
253
+ const buffer = new AudioRingBuffer({
254
+ maxBufferDurationSec: 1,
255
+ chunksPerSecond: 10,
256
+ logger
257
+ });
258
+
259
+ buffer.write(new ArrayBuffer(10));
260
+ buffer.clear();
261
+
262
+ expect(logger).toHaveBeenCalledWith(
263
+ 'debug',
264
+ expect.stringContaining('cleared')
265
+ );
266
+ });
267
+ });
268
+
269
+ describe('getStats', () => {
270
+ it('should return correct statistics', () => {
271
+ const buffer = new AudioRingBuffer({
272
+ maxBufferDurationSec: 1,
273
+ chunksPerSecond: 10
274
+ });
275
+
276
+ buffer.write(new ArrayBuffer(100));
277
+ buffer.write(new ArrayBuffer(200));
278
+
279
+ const stats = buffer.getStats();
280
+
281
+ expect(stats.chunksBuffered).toBe(2);
282
+ expect(stats.currentBufferedChunks).toBe(2);
283
+ expect(stats.totalBufferedBytes).toBe(300);
284
+ expect(stats.hasWrapped).toBe(false);
285
+ expect(stats.overflowCount).toBe(0);
286
+ });
287
+ });
288
+
289
+ describe('getBufferedCount with wraparound', () => {
290
+ it('should correctly count after partial read and more writes', () => {
291
+ const buffer = new AudioRingBuffer({
292
+ maxBufferDurationSec: 1,
293
+ chunksPerSecond: 10 // Buffer size of 10
294
+ });
295
+
296
+ // Write 5 chunks
297
+ for (let i = 0; i < 5; i++) {
298
+ buffer.write(new ArrayBuffer(10));
299
+ }
300
+ expect(buffer.getBufferedCount()).toBe(5);
301
+
302
+ // Read 3 chunks
303
+ buffer.read();
304
+ buffer.read();
305
+ buffer.read();
306
+ expect(buffer.getBufferedCount()).toBe(2);
307
+
308
+ // Write 4 more (wraps around in buffer)
309
+ for (let i = 0; i < 4; i++) {
310
+ buffer.write(new ArrayBuffer(10));
311
+ }
312
+
313
+ // Should have 2 + 4 = 6 chunks
314
+ expect(buffer.getBufferedCount()).toBe(6);
315
+ expect(buffer.isOverflowing()).toBe(false);
316
+ });
317
+
318
+ it('should handle buffer overflow correctly', () => {
319
+ const buffer = new AudioRingBuffer({
320
+ maxBufferDurationSec: 1,
321
+ chunksPerSecond: 3 // Buffer size of 3
322
+ });
323
+
324
+ // Write 5 chunks (more than buffer can hold)
325
+ for (let i = 0; i < 5; i++) {
326
+ buffer.write(new ArrayBuffer(10));
327
+ }
328
+
329
+ // Buffer should be full but not exceed capacity
330
+ // Ring buffer drops oldest when full
331
+ expect(buffer.getBufferedCount()).toBeLessThanOrEqual(3);
332
+ expect(buffer.isOverflowing()).toBe(true);
333
+ });
334
+ });
335
+ });