@neurodevs/node-lsl 8.0.1 → 8.0.3
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.
- package/.vscode/settings.json +17 -20
- package/build/.spruce/errors/errors.types.js +0 -2
- package/build/.spruce/errors/errors.types.js.map +1 -1
- package/build/__tests__/behavioral/LslOutlet.test.js +9 -14
- package/build/__tests__/behavioral/LslOutlet.test.js.map +1 -1
- package/build/__tests__/behavioral/TimeMarkerOutlet.test.js.map +1 -1
- package/build/__tests__/implementation/Liblsl.test.js +17 -4
- package/build/__tests__/implementation/Liblsl.test.js.map +1 -1
- package/build/__tests__/support/consts.js.map +1 -1
- package/build/__tests__/support/generateRandomOutletOptions.js.map +1 -1
- package/build/assertions.js.map +1 -1
- package/build/consts.js.map +1 -1
- package/build/errors/SpruceError.d.ts +1 -1
- package/build/errors/SpruceError.js.map +1 -1
- package/build/errors/failedToLoadLiblsl.builder.js.map +1 -1
- package/build/implementations/Liblsl.js +22 -6
- package/build/implementations/Liblsl.js.map +1 -1
- package/build/implementations/LslOutlet.js +6 -14
- package/build/implementations/LslOutlet.js.map +1 -1
- package/build/implementations/TimeMarkerOutlet.js +4 -1
- package/build/implementations/TimeMarkerOutlet.js.map +1 -1
- package/build/nodeLsl.types.d.ts +2 -2
- package/build/testDoubles/FakeLiblsl.js.map +1 -1
- package/build/testDoubles/MockTimeMarkerOutlet.js.map +1 -1
- package/build/testDoubles/SpyExtendsTimeMarkerOutlet.js.map +1 -1
- package/build/testDoubles/SpyImplementsTimeMarkerOutlet.js.map +1 -1
- package/build/validations.js.map +1 -1
- package/eslint.config.mjs +3 -0
- package/package.json +26 -26
- package/src/.spruce/errors/errors.types.ts +0 -3
- package/src/__tests__/behavioral/LslOutlet.test.ts +272 -267
- package/src/__tests__/behavioral/TimeMarkerOutlet.test.ts +144 -141
- package/src/__tests__/implementation/Liblsl.test.ts +461 -438
- package/src/__tests__/support/consts.ts +22 -22
- package/src/__tests__/support/generateRandomOutletOptions.ts +13 -13
- package/src/assertions.ts +39 -39
- package/src/consts.ts +16 -16
- package/src/errors/SpruceError.ts +16 -16
- package/src/errors/failedToLoadLiblsl.builder.ts +8 -8
- package/src/implementations/Liblsl.ts +205 -181
- package/src/implementations/LslOutlet.ts +114 -114
- package/src/implementations/TimeMarkerOutlet.ts +50 -50
- package/src/nodeLsl.types.ts +60 -63
- package/src/testDoubles/FakeLiblsl.ts +58 -56
- package/src/testDoubles/MockTimeMarkerOutlet.ts +56 -56
- package/src/testDoubles/SpyExtendsTimeMarkerOutlet.ts +11 -11
- package/src/testDoubles/SpyImplementsTimeMarkerOutlet.ts +28 -28
- package/src/validations.ts +6 -6
- package/tsconfig.json +3 -4
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -3
|
@@ -1,449 +1,472 @@
|
|
|
1
1
|
import { randomInt } from 'crypto'
|
|
2
2
|
import AbstractSpruceTest, {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
test,
|
|
4
|
+
assert,
|
|
5
|
+
errorAssert,
|
|
6
|
+
generateId,
|
|
7
7
|
} from '@sprucelabs/test-utils'
|
|
8
8
|
import { DataType, OpenParams } from 'ffi-rs'
|
|
9
9
|
import LiblslImpl from '../../implementations/Liblsl'
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
BoundChild,
|
|
12
|
+
BoundDescription,
|
|
13
|
+
BoundOutlet,
|
|
14
|
+
BoundStreamInfo,
|
|
15
|
+
FfiRsDefineOptions,
|
|
16
|
+
Liblsl,
|
|
17
|
+
LiblslBindings,
|
|
18
|
+
LslChannel,
|
|
19
19
|
} from '../../nodeLsl.types'
|
|
20
20
|
import FakeLiblsl from '../../testDoubles/FakeLiblsl'
|
|
21
21
|
|
|
22
22
|
export default class LiblslTest extends AbstractSpruceTest {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
23
|
+
private static lsl: Liblsl
|
|
24
|
+
private static libraryPath?: string
|
|
25
|
+
private static libraryOptions?: Record<string, any>
|
|
26
|
+
private static fakeBindings: LiblslBindings
|
|
27
|
+
private static fakeStreamInfo: BoundStreamInfo
|
|
28
|
+
private static fakeOutlet: BoundOutlet
|
|
29
|
+
private static fakeDesc: BoundDescription
|
|
30
|
+
private static fakeChildNamedChannels: BoundChild
|
|
31
|
+
private static createStreamInfoParams?: any[]
|
|
32
|
+
private static appendChildParams: any[] = []
|
|
33
|
+
private static createOutletParams?: any[]
|
|
34
|
+
private static destroyOutletParams?: any[]
|
|
35
|
+
private static localClockParams?: any[]
|
|
36
|
+
private static pushSampleFloatTimestampParams?: any[]
|
|
37
|
+
private static pushSampleStringTimestampParams?: any[]
|
|
38
|
+
private static appendChildValueParams: any[]
|
|
39
|
+
private static shouldThrowWhenCreatingBindings: boolean
|
|
40
|
+
private static getDescriptionParams?: [BoundStreamInfo]
|
|
41
|
+
private static fakeChildNamedChannel: BoundChild
|
|
42
|
+
private static appendChildHitCount: number
|
|
43
|
+
private static ffiRsOpenOptions?: OpenParams
|
|
44
|
+
private static ffiRsDefineOptions: FfiRsDefineOptions
|
|
45
|
+
|
|
46
|
+
protected static async beforeEach() {
|
|
47
|
+
await super.beforeEach()
|
|
48
|
+
|
|
49
|
+
delete this.libraryPath
|
|
50
|
+
delete this.libraryOptions
|
|
51
|
+
delete this.createStreamInfoParams
|
|
52
|
+
delete this.createOutletParams
|
|
53
|
+
delete this.destroyOutletParams
|
|
54
|
+
delete this.pushSampleFloatTimestampParams
|
|
55
|
+
delete this.getDescriptionParams
|
|
56
|
+
this.appendChildParams = []
|
|
57
|
+
this.appendChildValueParams = []
|
|
58
|
+
|
|
59
|
+
process.env.LIBLSL_PATH = generateId()
|
|
60
|
+
|
|
61
|
+
this.fakeStreamInfo = {}
|
|
62
|
+
this.fakeDesc = {}
|
|
63
|
+
this.fakeOutlet = {}
|
|
64
|
+
this.fakeChildNamedChannels = {}
|
|
65
|
+
this.fakeChildNamedChannel = {}
|
|
66
|
+
this.fakeBindings = this.FakeBindings()
|
|
67
|
+
|
|
68
|
+
this.shouldThrowWhenCreatingBindings = false
|
|
69
|
+
|
|
70
|
+
this.appendChildHitCount = 0
|
|
71
|
+
|
|
72
|
+
delete this.ffiRsOpenOptions
|
|
73
|
+
LiblslImpl.ffiRsOpen = (options) => {
|
|
74
|
+
this.ffiRsOpenOptions = options
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
LiblslImpl.ffiRsDefine = (options) => {
|
|
78
|
+
this.ffiRsDefineOptions = options
|
|
79
|
+
if (this.shouldThrowWhenCreatingBindings) {
|
|
80
|
+
throw new Error('Failed to create bindings!')
|
|
81
|
+
}
|
|
82
|
+
return this.fakeBindings as any
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
LiblslImpl.resetInstance()
|
|
86
|
+
this.lsl = LiblslImpl.getInstance()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@test()
|
|
90
|
+
protected static async throwsWithMissingEnv() {
|
|
91
|
+
delete process.env.LIBLSL_PATH
|
|
92
|
+
LiblslImpl.resetInstance()
|
|
93
|
+
|
|
94
|
+
const err = assert.doesThrow(() => LiblslImpl.getInstance())
|
|
95
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
96
|
+
parameters: ['env.LIBLSL_PATH'],
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@test()
|
|
101
|
+
protected static async throwsWhenBindingsFailToLoad() {
|
|
102
|
+
this.shouldThrowWhenCreatingBindings = true
|
|
103
|
+
LiblslImpl.resetInstance()
|
|
104
|
+
|
|
105
|
+
const err = assert.doesThrow(() => LiblslImpl.getInstance())
|
|
106
|
+
errorAssert.assertError(err, 'FAILED_TO_LOAD_LIBLSL', {
|
|
107
|
+
liblslPath: process.env.LIBLSL_PATH,
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@test()
|
|
112
|
+
protected static async callsOpenOnFfiRs() {
|
|
113
|
+
assert.isEqualDeep(this.ffiRsOpenOptions, {
|
|
114
|
+
library: 'lsl',
|
|
115
|
+
path: process.env.LIBLSL_PATH,
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@test()
|
|
120
|
+
protected static throwsWhenCreateStreamInfoIsMissingRequiredParams() {
|
|
121
|
+
//@ts-ignore
|
|
122
|
+
const err = assert.doesThrow(() => this.lsl.createStreamInfo())
|
|
123
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
124
|
+
parameters: [
|
|
125
|
+
'name',
|
|
126
|
+
'type',
|
|
127
|
+
'channelCount',
|
|
128
|
+
'sampleRate',
|
|
129
|
+
'channelFormat',
|
|
130
|
+
'sourceId',
|
|
131
|
+
],
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@test()
|
|
136
|
+
protected static async throwsWhenAppendChannelsIsMissingRequiredParams() {
|
|
137
|
+
const err = assert.doesThrow(() =>
|
|
138
|
+
//@ts-ignore
|
|
139
|
+
this.lsl.appendChannelsToStreamInfo({})
|
|
140
|
+
)
|
|
141
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
142
|
+
parameters: ['info', 'channels'],
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@test()
|
|
147
|
+
protected static async throwsWhenCreateOutletIsMissingRequiredParams() {
|
|
148
|
+
//@ts-ignore
|
|
149
|
+
const err = assert.doesThrow(() => this.lsl.createOutlet({}))
|
|
150
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
151
|
+
parameters: ['info', 'chunkSize', 'maxBuffered'],
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@test()
|
|
156
|
+
protected static async throwsWhenPushSampleFloatTimestampIsMissingRequiredParams() {
|
|
157
|
+
//@ts-ignore
|
|
158
|
+
const err = assert.doesThrow(() => this.lsl.pushSampleFloatTimestamp())
|
|
159
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
160
|
+
parameters: ['outlet', 'sample', 'timestamp'],
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@test()
|
|
165
|
+
protected static async throwsWhenPushSampleStringTimestampIsMissingRequiredParams() {
|
|
166
|
+
//@ts-ignore
|
|
167
|
+
const err = assert.doesThrow(() => this.lsl.pushSampleFloatTimestamp())
|
|
168
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
169
|
+
parameters: ['outlet', 'sample', 'timestamp'],
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@test()
|
|
174
|
+
protected static async worksAsASingleton() {
|
|
175
|
+
const liblsl = LiblslImpl.getInstance()
|
|
176
|
+
//@ts-ignore
|
|
177
|
+
assert.isInstanceOf(liblsl, LiblslImpl)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@test()
|
|
181
|
+
protected static async singletonIsTheSame() {
|
|
182
|
+
assert.isEqual(LiblslImpl.getInstance(), LiblslImpl.getInstance())
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@test()
|
|
186
|
+
protected static canSetInstance() {
|
|
187
|
+
const fake = new FakeLiblsl()
|
|
188
|
+
LiblslImpl.setInstance(fake)
|
|
189
|
+
assert.isEqual(LiblslImpl.getInstance(), fake)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@test()
|
|
193
|
+
protected static async createsExpectedBindingsWithFfiRs() {
|
|
194
|
+
assert.isEqualDeep(this.ffiRsDefineOptions, {
|
|
195
|
+
lsl_create_streaminfo: {
|
|
196
|
+
library: 'lsl',
|
|
197
|
+
retType: DataType.External,
|
|
198
|
+
paramsType: [
|
|
199
|
+
DataType.String,
|
|
200
|
+
DataType.String,
|
|
201
|
+
DataType.I32,
|
|
202
|
+
DataType.Double,
|
|
203
|
+
DataType.I32,
|
|
204
|
+
DataType.String,
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
lsl_create_outlet: {
|
|
208
|
+
library: 'lsl',
|
|
209
|
+
retType: DataType.External,
|
|
210
|
+
paramsType: [DataType.External, DataType.I32, DataType.I32],
|
|
211
|
+
},
|
|
212
|
+
lsl_destroy_outlet: {
|
|
213
|
+
library: 'lsl',
|
|
214
|
+
retType: DataType.Void,
|
|
215
|
+
paramsType: [DataType.External],
|
|
216
|
+
},
|
|
217
|
+
lsl_local_clock: {
|
|
218
|
+
library: 'lsl',
|
|
219
|
+
retType: DataType.Double,
|
|
220
|
+
paramsType: [],
|
|
221
|
+
},
|
|
222
|
+
lsl_push_sample_ft: {
|
|
223
|
+
library: 'lsl',
|
|
224
|
+
retType: DataType.Void,
|
|
225
|
+
paramsType: [
|
|
226
|
+
DataType.External,
|
|
227
|
+
DataType.FloatArray,
|
|
228
|
+
DataType.Double,
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
lsl_push_sample_strt: {
|
|
232
|
+
library: 'lsl',
|
|
233
|
+
retType: DataType.Void,
|
|
234
|
+
paramsType: [
|
|
235
|
+
DataType.External,
|
|
236
|
+
DataType.StringArray,
|
|
237
|
+
DataType.Double,
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
lsl_get_desc: {
|
|
241
|
+
library: 'lsl',
|
|
242
|
+
retType: DataType.External,
|
|
243
|
+
paramsType: [DataType.External],
|
|
244
|
+
},
|
|
245
|
+
lsl_append_child: {
|
|
246
|
+
library: 'lsl',
|
|
247
|
+
retType: DataType.External,
|
|
248
|
+
paramsType: [DataType.External, DataType.String],
|
|
249
|
+
},
|
|
250
|
+
lsl_append_child_value: {
|
|
251
|
+
library: 'lsl',
|
|
252
|
+
retType: DataType.External,
|
|
253
|
+
paramsType: [
|
|
254
|
+
DataType.External,
|
|
255
|
+
DataType.String,
|
|
256
|
+
DataType.String,
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@test()
|
|
263
|
+
protected static async canCreateStreamInfoWithRequiredParams() {
|
|
264
|
+
const options = this.generateRandomCreateStreamInfoOptions()
|
|
265
|
+
const actual = this.lsl.createStreamInfo(options)
|
|
266
|
+
|
|
267
|
+
assert.isEqual(actual, this.fakeStreamInfo)
|
|
268
|
+
assert.isEqualDeep(this.createStreamInfoParams, Object.values(options))
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@test()
|
|
272
|
+
protected static async canCreateOutletWithRequiredParams() {
|
|
273
|
+
const { options, outlet } = this.createRandomOutlet()
|
|
274
|
+
assert.isEqualDeep(this.createOutletParams, Object.values(options))
|
|
275
|
+
assert.isEqual(outlet, this.fakeOutlet)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
@test()
|
|
279
|
+
protected static async canPushFloatSample() {
|
|
280
|
+
const expected = [1.0, 2.0, 3.0]
|
|
281
|
+
const timestamp = randomInt(100)
|
|
282
|
+
const options = {
|
|
283
|
+
outlet: this.fakeOutlet,
|
|
284
|
+
sample: expected,
|
|
285
|
+
timestamp,
|
|
286
|
+
}
|
|
287
|
+
this.lsl.pushSampleFloatTimestamp(options)
|
|
288
|
+
|
|
289
|
+
assert.isEqualDeep(this.pushSampleFloatTimestampParams, [
|
|
290
|
+
this.fakeOutlet,
|
|
291
|
+
expected,
|
|
292
|
+
timestamp,
|
|
293
|
+
])
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@test()
|
|
297
|
+
protected static async canPushStringSample() {
|
|
298
|
+
const expected = [generateId()]
|
|
299
|
+
const timestamp = randomInt(100)
|
|
300
|
+
const options = {
|
|
301
|
+
outlet: this.fakeOutlet,
|
|
302
|
+
sample: expected,
|
|
303
|
+
timestamp,
|
|
304
|
+
}
|
|
305
|
+
this.lsl.pushSampleStringTimestamp(options)
|
|
306
|
+
assert.isEqual(
|
|
307
|
+
this.pushSampleStringTimestampParams?.[0],
|
|
308
|
+
this.fakeOutlet
|
|
309
|
+
)
|
|
310
|
+
assert.isEqualDeep(this.pushSampleStringTimestampParams?.[1], expected)
|
|
311
|
+
assert.isEqual(this.pushSampleStringTimestampParams?.[2], timestamp)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
@test()
|
|
315
|
+
protected static async addingSingleChannelGetsDescription() {
|
|
316
|
+
const info = this.createRandomStreamInfo()
|
|
317
|
+
const channel: LslChannel = this.generateRandomChannelValues()
|
|
318
|
+
|
|
319
|
+
this.lsl.appendChannelsToStreamInfo({
|
|
320
|
+
info,
|
|
321
|
+
channels: [channel],
|
|
322
|
+
})
|
|
323
|
+
assert.isEqualDeep(this.getDescriptionParams?.[0], [info])
|
|
324
|
+
|
|
325
|
+
assert.isEqual(this.appendChildParams?.[0][0], this.fakeDesc)
|
|
326
|
+
assert.isEqual(this.appendChildParams?.[0][1], 'channels')
|
|
327
|
+
|
|
328
|
+
assert.isEqual(
|
|
329
|
+
this.appendChildParams?.[1][0],
|
|
330
|
+
this.fakeChildNamedChannels
|
|
331
|
+
)
|
|
332
|
+
assert.isEqual(this.appendChildParams?.[1][1], 'channel')
|
|
333
|
+
|
|
334
|
+
assert.isLength(this.appendChildValueParams, 3)
|
|
335
|
+
|
|
336
|
+
for (let i = 0; i < 3; i++) {
|
|
337
|
+
const param = this.appendChildValueParams[i]
|
|
338
|
+
assert.isEqual(param[0], this.fakeChildNamedChannel)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
assert.isEqual(this.appendChildValueParams[0][1], 'label')
|
|
342
|
+
assert.isEqual(this.appendChildValueParams[1][1], 'unit')
|
|
343
|
+
assert.isEqual(this.appendChildValueParams[2][1], 'type')
|
|
344
|
+
|
|
345
|
+
assert.isEqual(this.appendChildValueParams[0][2], channel.label)
|
|
346
|
+
assert.isEqual(this.appendChildValueParams[1][2], channel.unit)
|
|
347
|
+
assert.isEqual(this.appendChildValueParams[2][2], channel.type)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
@test()
|
|
351
|
+
protected static async addingMultpleChannelsAddsChildrenToChannelsChild() {
|
|
352
|
+
const info = this.createRandomStreamInfo()
|
|
353
|
+
const channel1 = this.generateRandomChannelValues()
|
|
354
|
+
const channel2 = this.generateRandomChannelValues()
|
|
355
|
+
|
|
356
|
+
this.lsl.appendChannelsToStreamInfo({
|
|
357
|
+
info,
|
|
358
|
+
channels: [channel1, channel2],
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
assert.isEqual(
|
|
362
|
+
this.appendChildParams?.[2][0],
|
|
363
|
+
this.fakeChildNamedChannels
|
|
364
|
+
)
|
|
365
|
+
assert.isEqual(this.appendChildParams?.[2][1], 'channel')
|
|
366
|
+
|
|
367
|
+
assert.isEqual(this.appendChildValueParams[3][2], channel2.label)
|
|
368
|
+
assert.isEqual(this.appendChildValueParams[4][2], channel2.unit)
|
|
369
|
+
assert.isEqual(this.appendChildValueParams[5][2], channel2.type)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
@test()
|
|
373
|
+
protected static async canDestroyOutlet() {
|
|
374
|
+
const outlet = this.createRandomOutlet()
|
|
375
|
+
const options = { outlet }
|
|
376
|
+
this.lsl.destroyOutlet(options)
|
|
377
|
+
|
|
378
|
+
assert.isEqualDeep(this.destroyOutletParams, Object.values(options))
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
@test()
|
|
382
|
+
protected static async callingLocalClockTwiceReturnsDifferentTimestamps() {
|
|
383
|
+
const t1 = this.lsl.localClock()
|
|
384
|
+
await this.wait(10)
|
|
385
|
+
const t2 = this.lsl.localClock()
|
|
386
|
+
assert.isNotEqual(t1, t2)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
@test()
|
|
390
|
+
protected static async localClockBindingReceivesEmptyArray() {
|
|
391
|
+
delete this.localClockParams
|
|
392
|
+
this.lsl.localClock()
|
|
393
|
+
assert.isEqualDeep(this.localClockParams, [])
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private static createRandomStreamInfo() {
|
|
397
|
+
return this.lsl.createStreamInfo(
|
|
398
|
+
this.generateRandomCreateStreamInfoOptions()
|
|
399
|
+
)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
private static createRandomOutlet() {
|
|
403
|
+
const info = this.createRandomStreamInfo()
|
|
404
|
+
const options = {
|
|
405
|
+
info,
|
|
406
|
+
chunkSize: randomInt(10),
|
|
407
|
+
maxBuffered: randomInt(10),
|
|
408
|
+
}
|
|
409
|
+
const outlet = this.lsl.createOutlet(options)
|
|
410
|
+
return { options, outlet }
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
private static generateRandomChannelValues() {
|
|
414
|
+
return {
|
|
415
|
+
label: generateId(),
|
|
416
|
+
type: generateId(),
|
|
417
|
+
unit: generateId(),
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private static generateRandomCreateStreamInfoOptions() {
|
|
422
|
+
return {
|
|
423
|
+
name: generateId(),
|
|
424
|
+
type: generateId(),
|
|
425
|
+
channelCount: randomInt(1, 10),
|
|
426
|
+
sampleRate: randomInt(100),
|
|
427
|
+
channelFormat: randomInt(7),
|
|
428
|
+
sourceId: generateId(),
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private static FakeBindings() {
|
|
433
|
+
return {
|
|
434
|
+
lsl_create_streaminfo: (params: any[]) => {
|
|
435
|
+
this.createStreamInfoParams = params
|
|
436
|
+
return this.fakeStreamInfo
|
|
437
|
+
},
|
|
438
|
+
lsl_create_outlet: (params: any[]) => {
|
|
439
|
+
this.createOutletParams = params
|
|
440
|
+
return this.fakeOutlet
|
|
441
|
+
},
|
|
442
|
+
lsl_destroy_outlet: (params: any[]) => {
|
|
443
|
+
this.destroyOutletParams = params
|
|
444
|
+
},
|
|
445
|
+
lsl_push_sample_ft: (params: any[]) => {
|
|
446
|
+
this.pushSampleFloatTimestampParams = params
|
|
447
|
+
},
|
|
448
|
+
lsl_push_sample_strt: (params: any[]) => {
|
|
449
|
+
this.pushSampleStringTimestampParams = params
|
|
450
|
+
},
|
|
451
|
+
lsl_local_clock: (params: []) => {
|
|
452
|
+
this.localClockParams = params
|
|
453
|
+
return new Date().getTime()
|
|
454
|
+
},
|
|
455
|
+
lsl_get_desc: (info: BoundStreamInfo) => {
|
|
456
|
+
this.getDescriptionParams = [info]
|
|
457
|
+
return this.fakeDesc
|
|
458
|
+
},
|
|
459
|
+
lsl_append_child: (params: any) => {
|
|
460
|
+
this.appendChildParams.push(params)
|
|
461
|
+
if (this.appendChildHitCount === 0) {
|
|
462
|
+
this.appendChildHitCount++
|
|
463
|
+
return this.fakeChildNamedChannels
|
|
464
|
+
}
|
|
465
|
+
return this.fakeChildNamedChannel
|
|
466
|
+
},
|
|
467
|
+
lsl_append_child_value: (params: any[]) => {
|
|
468
|
+
this.appendChildValueParams.push(params)
|
|
469
|
+
},
|
|
470
|
+
}
|
|
471
|
+
}
|
|
449
472
|
}
|