@neurodevs/node-lsl 17.1.0 → 18.0.0
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/.claude/settings.local.json +10 -0
- package/.regressionproof.json +7 -0
- package/.vscode/launch.json +3 -2
- package/README.md +9 -35
- package/build/.spruce/settings.json +5 -1
- package/build/__tests__/AbstractPackageTest.d.ts +4 -4
- package/build/__tests__/AbstractPackageTest.js +9 -11
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/LslBackpressureMonitor.test.d.ts +7 -0
- package/build/__tests__/impl/LslBackpressureMonitor.test.js +26 -0
- package/build/__tests__/impl/LslBackpressureMonitor.test.js.map +1 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.d.ts +34 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js +243 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +1 -0
- package/build/__tests__/impl/LslStreamInfo.test.d.ts +0 -3
- package/build/__tests__/impl/LslStreamInfo.test.js +2 -27
- package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInlet.test.d.ts +22 -8
- package/build/__tests__/impl/LslStreamInlet.test.js +240 -66
- package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamOutlet.test.d.ts +3 -7
- package/build/__tests__/impl/LslStreamOutlet.test.js +36 -46
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
- package/build/__tests__/impl/LslWebSocketBridge.test.js +16 -17
- package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
- package/build/assertions.d.ts +1 -1
- package/build/assertions.js.map +1 -1
- package/build/impl/LslBackpressureMonitor.d.ts +8 -0
- package/build/impl/LslBackpressureMonitor.js +8 -0
- package/build/impl/LslBackpressureMonitor.js.map +1 -0
- package/build/impl/LslEventMarkerEmitter.d.ts +35 -0
- package/build/impl/LslEventMarkerEmitter.js +86 -0
- package/build/impl/LslEventMarkerEmitter.js.map +1 -0
- package/build/impl/LslStreamInfo.d.ts +4 -8
- package/build/impl/LslStreamInfo.js +8 -21
- package/build/impl/LslStreamInfo.js.map +1 -1
- package/build/impl/LslStreamInlet.d.ts +31 -47
- package/build/impl/LslStreamInlet.js +82 -143
- package/build/impl/LslStreamInlet.js.map +1 -1
- package/build/impl/LslStreamOutlet.d.ts +15 -18
- package/build/impl/LslStreamOutlet.js +39 -47
- package/build/impl/LslStreamOutlet.js.map +1 -1
- package/build/impl/LslWebSocketBridge.d.ts +4 -5
- package/build/impl/LslWebSocketBridge.js +8 -8
- package/build/impl/LslWebSocketBridge.js.map +1 -1
- package/build/impl/workers/inlet/LslStreamInlet.worker.d.ts +22 -0
- package/build/impl/workers/inlet/LslStreamInlet.worker.js +42 -0
- package/build/impl/workers/inlet/LslStreamInlet.worker.js.map +1 -0
- package/build/impl/workers/inlet/StreamInletWorker.d.ts +73 -0
- package/build/impl/workers/inlet/StreamInletWorker.js +253 -0
- package/build/impl/workers/inlet/StreamInletWorker.js.map +1 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.d.ts +32 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js +82 -0
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js.map +1 -0
- package/build/index.d.ts +12 -14
- package/build/index.js +14 -16
- package/build/index.js.map +1 -1
- package/build/scripts/finalizeHandles.d.ts +2 -0
- package/build/scripts/finalizeHandles.js +48 -0
- package/build/scripts/finalizeHandles.js.map +1 -0
- package/build/scripts/runLslEventMarkerEmitter.js +11 -0
- package/build/scripts/runLslEventMarkerEmitter.js.map +1 -0
- package/build/scripts/runOutletToInlet.js +7 -6
- package/build/scripts/runOutletToInlet.js.map +1 -1
- package/build/scripts/testDestroyOutlet.d.ts +1 -0
- package/build/scripts/testDestroyOutlet.js +4 -0
- package/build/scripts/testDestroyOutlet.js.map +1 -0
- package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.d.ts +6 -0
- package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.js +10 -0
- package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.d.ts +17 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js +30 -0
- package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.d.ts +10 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js +23 -0
- package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.d.ts +9 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js +19 -0
- package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js.map +1 -0
- package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +3 -3
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js +3 -3
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
- package/build/testDoubles/StreamInlet/FakeStreamInlet.d.ts +8 -10
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js +6 -7
- package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +1 -1
- package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +2 -5
- package/build/testDoubles/StreamInlet/SpyStreamInlet.js +2 -8
- package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +1 -1
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.d.ts +7 -9
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +5 -8
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
- package/build/testDoubles/WorkerThreads/FakeWorker.d.ts +27 -0
- package/build/testDoubles/WorkerThreads/FakeWorker.js +67 -0
- package/build/testDoubles/WorkerThreads/FakeWorker.js.map +1 -0
- package/build/validations.js +0 -2
- package/build/validations.js.map +1 -1
- package/package.json +24 -8
- package/src/.spruce/settings.json +5 -1
- package/src/__tests__/AbstractPackageTest.ts +13 -15
- package/src/__tests__/impl/LslBackpressureMonitor.test.ts +25 -0
- package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +322 -0
- package/src/__tests__/impl/LslStreamInfo.test.ts +3 -40
- package/src/__tests__/impl/LslStreamInlet.test.ts +366 -95
- package/src/__tests__/impl/LslStreamOutlet.test.ts +61 -69
- package/src/__tests__/impl/LslWebSocketBridge.test.ts +18 -18
- package/src/assertions.ts +2 -1
- package/src/impl/LslBackpressureMonitor.ts +13 -0
- package/src/impl/LslEventMarkerEmitter.ts +133 -0
- package/src/impl/LslStreamInfo.ts +17 -29
- package/src/impl/LslStreamInlet.ts +105 -208
- package/src/impl/LslStreamOutlet.ts +54 -78
- package/src/impl/LslWebSocketBridge.ts +12 -12
- package/src/impl/workers/inlet/LslStreamInlet.worker.ts +74 -0
- package/src/impl/workers/inlet/StreamInletWorker.ts +348 -0
- package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +144 -0
- package/src/index.ts +14 -17
- package/src/scripts/finalizeHandles.ts +63 -0
- package/src/scripts/runLslEventMarkerEmitter.ts +15 -0
- package/src/scripts/runOutletToInlet.ts +10 -8
- package/src/scripts/testDestroyOutlet.ts +5 -0
- package/src/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.ts +13 -0
- package/src/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.ts +46 -0
- package/src/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.ts +31 -0
- package/src/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.ts +29 -0
- package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +4 -4
- package/src/testDoubles/StreamInlet/FakeStreamInlet.ts +11 -17
- package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +3 -16
- package/src/testDoubles/StreamOutlet/FakeStreamOutlet.ts +12 -15
- package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -1
- package/src/testDoubles/WorkerThreads/FakeWorker.ts +99 -0
- package/src/validations.ts +0 -2
- package/build/__tests__/impl/LiblslAdapter.test.d.ts +0 -79
- package/build/__tests__/impl/LiblslAdapter.test.js +0 -688
- package/build/__tests__/impl/LiblslAdapter.test.js.map +0 -1
- package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +0 -21
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js +0 -160
- package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +0 -1
- package/build/handleError.d.ts +0 -8
- package/build/handleError.js +0 -25
- package/build/handleError.js.map +0 -1
- package/build/impl/LiblslAdapter.d.ts +0 -159
- package/build/impl/LiblslAdapter.js +0 -317
- package/build/impl/LiblslAdapter.js.map +0 -1
- package/build/impl/LslEventMarkerOutlet.d.ts +0 -28
- package/build/impl/LslEventMarkerOutlet.js +0 -63
- package/build/impl/LslEventMarkerOutlet.js.map +0 -1
- package/build/scripts/runLslEventMarkerOutlet.js +0 -18
- package/build/scripts/runLslEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.d.ts +0 -13
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js +0 -26
- package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.d.ts +0 -17
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js +0 -46
- package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.d.ts +0 -9
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js +0 -19
- package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts +0 -9
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js +0 -19
- package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +0 -1
- package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +0 -50
- package/build/testDoubles/Liblsl/FakeLiblsl.js +0 -126
- package/build/testDoubles/Liblsl/FakeLiblsl.js.map +0 -1
- package/src/__tests__/impl/LiblslAdapter.test.ts +0 -817
- package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +0 -195
- package/src/handleError.ts +0 -24
- package/src/impl/LiblslAdapter.ts +0 -548
- package/src/impl/LslEventMarkerOutlet.ts +0 -97
- package/src/scripts/runLslEventMarkerOutlet.ts +0 -23
- package/src/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.ts +0 -36
- package/src/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.ts +0 -75
- package/src/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.ts +0 -24
- package/src/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.ts +0 -28
- package/src/testDoubles/Liblsl/FakeLiblsl.ts +0 -182
- /package/build/scripts/{runLslEventMarkerOutlet.d.ts → runLslEventMarkerEmitter.d.ts} +0 -0
|
@@ -196,7 +196,7 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
196
196
|
assert.isEqualDeep(
|
|
197
197
|
this.fakeLiblsl.lastAppendChannelsToStreamInfoOptions,
|
|
198
198
|
{
|
|
199
|
-
|
|
199
|
+
infoHandle: this.instance.infoHandle,
|
|
200
200
|
channels: this.channelNames.map((label: string) => ({
|
|
201
201
|
label,
|
|
202
202
|
units: this.units,
|
|
@@ -212,49 +212,12 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
212
212
|
this.instance.destroy()
|
|
213
213
|
|
|
214
214
|
assert.isEqualDeep(
|
|
215
|
-
this.fakeLiblsl.lastDestroyStreamInfoOptions?.
|
|
216
|
-
this.instance.
|
|
215
|
+
this.fakeLiblsl.lastDestroyStreamInfoOptions?.infoHandle,
|
|
216
|
+
this.instance.infoHandle,
|
|
217
217
|
'Should have called destroyStreamInfo!'
|
|
218
218
|
)
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
@test()
|
|
222
|
-
protected static async doesNotCreateNewStreamInfoIfPassedBoundInfo() {
|
|
223
|
-
this.LslStreamInfo({
|
|
224
|
-
boundInfo: this.instance.boundInfo,
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
assert.isEqual(
|
|
228
|
-
this.fakeLiblsl.createStreamInfoHitCount,
|
|
229
|
-
1,
|
|
230
|
-
'Should not have created new stream info!'
|
|
231
|
-
)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
@test()
|
|
235
|
-
protected static async setsBoundInfoWhenPassed() {
|
|
236
|
-
const instance = this.LslStreamInfo({
|
|
237
|
-
boundInfo: this.instance.boundInfo,
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
assert.isEqualDeep(
|
|
241
|
-
instance.boundInfo,
|
|
242
|
-
this.instance.boundInfo,
|
|
243
|
-
'Should have set bound stream info!'
|
|
244
|
-
)
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
@test()
|
|
248
|
-
protected static async cachesInfoAttributesByBoundInfo() {
|
|
249
|
-
const cached = LslStreamInfo.From(this.instance.boundInfo)
|
|
250
|
-
|
|
251
|
-
assert.isEqualDeep(
|
|
252
|
-
cached,
|
|
253
|
-
this.instance,
|
|
254
|
-
'Should have set bound stream info!'
|
|
255
|
-
)
|
|
256
|
-
}
|
|
257
|
-
|
|
258
221
|
private static readonly defaultOptions = {
|
|
259
222
|
name: this.name,
|
|
260
223
|
type: this.type,
|
|
@@ -1,17 +1,61 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Worker } from 'node:worker_threads'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { FakeLiblsl } from '@neurodevs/ndx-native'
|
|
4
|
+
import { test, assert } from '@neurodevs/node-tdd'
|
|
5
|
+
import {
|
|
6
|
+
createPointer,
|
|
7
|
+
DataType,
|
|
8
|
+
FieldType,
|
|
9
|
+
JsExternal,
|
|
10
|
+
PointerType,
|
|
11
|
+
unwrapPointer,
|
|
12
|
+
} from 'ffi-rs'
|
|
13
|
+
|
|
14
|
+
import LslStreamInlet, {
|
|
15
|
+
StreamInletOptions,
|
|
16
|
+
} from '../../impl/LslStreamInlet.js'
|
|
17
|
+
import StreamInletWorker from '../../impl/workers/inlet/StreamInletWorker.js'
|
|
4
18
|
import { SpyStreamInlet } from '../../testDoubles/StreamInlet/SpyStreamInlet.js'
|
|
19
|
+
import FakeWorker from '../../testDoubles/WorkerThreads/FakeWorker.js'
|
|
5
20
|
import AbstractPackageTest from '../AbstractPackageTest.js'
|
|
6
21
|
|
|
7
22
|
export default class LslStreamInletTest extends AbstractPackageTest {
|
|
8
23
|
private static instance: SpyStreamInlet
|
|
9
24
|
|
|
10
25
|
private static callsToOnData: {
|
|
11
|
-
samples:
|
|
12
|
-
timestamps:
|
|
26
|
+
samples: number[]
|
|
27
|
+
timestamps: number[]
|
|
13
28
|
}[]
|
|
14
29
|
|
|
30
|
+
private static readonly sampleBufferPtr = unwrapPointer(
|
|
31
|
+
createPointer({
|
|
32
|
+
paramsType: [DataType.U8Array],
|
|
33
|
+
paramsValue: [new Float32Array(this.channelCount * this.chunkSize)],
|
|
34
|
+
})
|
|
35
|
+
)[0]
|
|
36
|
+
|
|
37
|
+
private static readonly timestampBufferPtr = unwrapPointer(
|
|
38
|
+
createPointer({
|
|
39
|
+
paramsType: [DataType.U8Array],
|
|
40
|
+
paramsValue: [new Float64Array(this.chunkSize)],
|
|
41
|
+
})
|
|
42
|
+
)[0]
|
|
43
|
+
|
|
44
|
+
private static readonly errorCodePtr = unwrapPointer(
|
|
45
|
+
createPointer({
|
|
46
|
+
paramsType: [DataType.U8Array],
|
|
47
|
+
paramsValue: [new Int32Array(1)],
|
|
48
|
+
})
|
|
49
|
+
)[0]
|
|
50
|
+
|
|
51
|
+
protected static async beforeAll() {
|
|
52
|
+
assert.isEqual(
|
|
53
|
+
LslStreamInlet.waitAfterOpenStreamMs,
|
|
54
|
+
100,
|
|
55
|
+
'Default waitAfterOpenStreamMs should be 100!'
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
15
59
|
protected static async beforeEach() {
|
|
16
60
|
await super.beforeEach()
|
|
17
61
|
|
|
@@ -21,6 +65,16 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
21
65
|
|
|
22
66
|
this.callsToOnData = []
|
|
23
67
|
|
|
68
|
+
LslStreamInlet.waitAfterOpenStreamMs = 0
|
|
69
|
+
|
|
70
|
+
LslStreamInlet.Worker = FakeWorker as unknown as typeof Worker
|
|
71
|
+
FakeWorker.resetTestDoubles()
|
|
72
|
+
|
|
73
|
+
StreamInletWorker.lsl = this.fakeLiblsl
|
|
74
|
+
StreamInletWorker.freePointer = () => {}
|
|
75
|
+
|
|
76
|
+
FakeWorker.fakeOnData = this.onData
|
|
77
|
+
|
|
24
78
|
this.instance = await this.LslStreamInlet()
|
|
25
79
|
}
|
|
26
80
|
|
|
@@ -31,42 +85,102 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
31
85
|
|
|
32
86
|
@test()
|
|
33
87
|
protected static async callsBindingsToCreateStreamInlet() {
|
|
34
|
-
|
|
88
|
+
await this.startPulling()
|
|
35
89
|
|
|
36
|
-
assert.isTruthy(
|
|
90
|
+
assert.isTruthy(this.inletHandle, 'Should have created stream info!')
|
|
37
91
|
|
|
38
92
|
assert.isEqualDeep(
|
|
39
93
|
this.fakeLiblsl.lastCreateInletOptions,
|
|
40
94
|
{
|
|
41
|
-
|
|
95
|
+
infoHandle: this.inletHandle,
|
|
42
96
|
maxBufferedMs: this.maxBufferedMs,
|
|
43
97
|
},
|
|
44
98
|
'Should have called createInlet!'
|
|
45
99
|
)
|
|
100
|
+
|
|
101
|
+
this.stopPulling()
|
|
46
102
|
}
|
|
47
103
|
|
|
48
104
|
@test()
|
|
49
|
-
protected static async
|
|
50
|
-
this.instance.
|
|
105
|
+
protected static async flushInletCallsLslBinding() {
|
|
106
|
+
this.instance.flushInlet()
|
|
51
107
|
|
|
52
108
|
assert.isEqualDeep(
|
|
53
109
|
this.fakeLiblsl.lastFlushInletOptions,
|
|
54
|
-
{
|
|
110
|
+
{ inletHandle: this.inletHandle },
|
|
55
111
|
'Should have called flushInlet!'
|
|
56
112
|
)
|
|
57
113
|
}
|
|
58
114
|
|
|
59
115
|
@test()
|
|
60
116
|
protected static async destroyCallsLslBinding() {
|
|
61
|
-
this.
|
|
117
|
+
await this.startPullingThenDestroy()
|
|
62
118
|
|
|
63
119
|
assert.isEqualDeep(
|
|
64
120
|
this.fakeLiblsl.lastDestroyInletOptions,
|
|
65
|
-
{
|
|
121
|
+
{ inletHandle: this.inletHandle },
|
|
66
122
|
'Did not destroy inlet!'
|
|
67
123
|
)
|
|
68
124
|
}
|
|
69
125
|
|
|
126
|
+
@test()
|
|
127
|
+
protected static async destroyFreesAllPointers() {
|
|
128
|
+
interface FreePointerParams {
|
|
129
|
+
paramsType: FieldType[]
|
|
130
|
+
paramsValue: JsExternal[]
|
|
131
|
+
pointerType: PointerType
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let calls: FreePointerParams[] = []
|
|
135
|
+
|
|
136
|
+
StreamInletWorker.freePointer = (params: FreePointerParams) => {
|
|
137
|
+
calls.push(params)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
await this.startPullingThenDestroy()
|
|
141
|
+
|
|
142
|
+
const { paramsType, pointerType } = calls[0]
|
|
143
|
+
|
|
144
|
+
assert.isEqualDeep(
|
|
145
|
+
{ paramsType, pointerType },
|
|
146
|
+
{
|
|
147
|
+
paramsType: [
|
|
148
|
+
DataType.U8Array,
|
|
149
|
+
DataType.U8Array,
|
|
150
|
+
DataType.U8Array,
|
|
151
|
+
DataType.U8Array,
|
|
152
|
+
],
|
|
153
|
+
pointerType: PointerType.CPointer,
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
'Destroy did not free all pointers!'
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@test()
|
|
161
|
+
protected static async destroyCallsStopIfIsRunning() {
|
|
162
|
+
await this.startPulling()
|
|
163
|
+
this.destroy()
|
|
164
|
+
|
|
165
|
+
assert.isFalse(
|
|
166
|
+
this.instance.isRunning,
|
|
167
|
+
'Did not stop inlet before destroying!'
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@test()
|
|
172
|
+
protected static async destroyDoesNotCallStopIfNotRunning() {
|
|
173
|
+
let wasHit = false
|
|
174
|
+
|
|
175
|
+
this.instance.stopPulling = () => {
|
|
176
|
+
wasHit = true
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.instance.destroy()
|
|
180
|
+
|
|
181
|
+
assert.isFalse(wasHit, 'Stop should not have been called!')
|
|
182
|
+
}
|
|
183
|
+
|
|
70
184
|
@test()
|
|
71
185
|
protected static async exposesIsRunningFieldThatIsFalseAtFirst() {
|
|
72
186
|
assert.isFalse(this.isRunning, 'isRunning should be false at first!')
|
|
@@ -74,14 +188,135 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
74
188
|
|
|
75
189
|
@test()
|
|
76
190
|
protected static async startPullingSetsIsRunningToTrue() {
|
|
77
|
-
this.startPulling()
|
|
78
|
-
await this.wait(10)
|
|
191
|
+
await this.startPulling()
|
|
79
192
|
|
|
80
193
|
assert.isTrue(this.isRunning, 'isRunning should be true!')
|
|
81
194
|
|
|
82
195
|
this.stopPulling()
|
|
83
196
|
}
|
|
84
197
|
|
|
198
|
+
@test()
|
|
199
|
+
protected static async doesNotStartPullingTwiceIfAlreadyRunning() {
|
|
200
|
+
await this.startPulling()
|
|
201
|
+
await this.startPulling()
|
|
202
|
+
|
|
203
|
+
assert.isEqual(
|
|
204
|
+
FakeWorker.callsToPostMessage.filter(
|
|
205
|
+
(msg) => msg.type === 'startPulling'
|
|
206
|
+
).length,
|
|
207
|
+
1,
|
|
208
|
+
'startPulling did not return early!'
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
this.stopPulling()
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@test()
|
|
215
|
+
protected static async startPullingOpensInletStream() {
|
|
216
|
+
await this.startPulling()
|
|
217
|
+
|
|
218
|
+
const aboutOneYearInMs = 32000000 * 1000
|
|
219
|
+
|
|
220
|
+
assert.isEqualDeep(
|
|
221
|
+
this.fakeLiblsl.lastOpenStreamOptions,
|
|
222
|
+
{
|
|
223
|
+
inletHandle: this.inletHandle,
|
|
224
|
+
timeoutMs: aboutOneYearInMs,
|
|
225
|
+
errorCodePtr: this.errorCodePtr,
|
|
226
|
+
},
|
|
227
|
+
'Did not open inlet stream!'
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
this.stopPulling()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@test()
|
|
234
|
+
protected static async opensInletStreamWithPassedTimeout() {
|
|
235
|
+
const openStreamTimeoutMs = 1000 * Math.random()
|
|
236
|
+
|
|
237
|
+
const instance = await this.LslStreamInlet({
|
|
238
|
+
openStreamTimeoutMs,
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
await this.startPulling(instance)
|
|
242
|
+
|
|
243
|
+
assert.isEqualDeep(
|
|
244
|
+
this.fakeLiblsl.lastOpenStreamOptions,
|
|
245
|
+
{
|
|
246
|
+
inletHandle: this.inletHandle,
|
|
247
|
+
timeoutMs: openStreamTimeoutMs,
|
|
248
|
+
errorCodePtr: this.errorCodePtr,
|
|
249
|
+
},
|
|
250
|
+
'Did not open inlet stream with passed timeout!'
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
instance.stopPulling()
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@test()
|
|
257
|
+
protected static async waitsAfterOpeningStreamWithPassedOption() {
|
|
258
|
+
const waitAfterOpenStreamMs = 10
|
|
259
|
+
|
|
260
|
+
const instance = await this.LslStreamInlet({
|
|
261
|
+
waitAfterOpenStreamMs,
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
let t0 = Date.now()
|
|
265
|
+
await this.startPulling(instance)
|
|
266
|
+
let elapsed = Date.now() - t0
|
|
267
|
+
|
|
268
|
+
instance.stopPulling()
|
|
269
|
+
|
|
270
|
+
assert.isAbove(
|
|
271
|
+
elapsed,
|
|
272
|
+
waitAfterOpenStreamMs * 0.8,
|
|
273
|
+
'Did not wait after opening stream!'
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@test()
|
|
278
|
+
protected static async stopPullingClosesInletStream() {
|
|
279
|
+
await this.startPulling()
|
|
280
|
+
this.stopPulling()
|
|
281
|
+
|
|
282
|
+
assert.isEqualDeep(
|
|
283
|
+
this.fakeLiblsl.lastCloseStreamOptions,
|
|
284
|
+
{
|
|
285
|
+
inletHandle: this.inletHandle,
|
|
286
|
+
},
|
|
287
|
+
'Did not close inlet stream!'
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
@test()
|
|
292
|
+
protected static async stopPullingFlushesInletByDefault() {
|
|
293
|
+
await this.startPulling()
|
|
294
|
+
this.stopPulling()
|
|
295
|
+
|
|
296
|
+
assert.isEqualDeep(
|
|
297
|
+
this.fakeLiblsl.lastFlushInletOptions,
|
|
298
|
+
{
|
|
299
|
+
inletHandle: this.inletHandle,
|
|
300
|
+
},
|
|
301
|
+
'Did not flush inlet!'
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
@test()
|
|
306
|
+
protected static async stopPullingDoesNotFlushInletIfPassedOption() {
|
|
307
|
+
const instance = await this.LslStreamInlet({
|
|
308
|
+
flushInletOnStop: false,
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
await this.startPulling(instance)
|
|
312
|
+
instance.stopPulling()
|
|
313
|
+
|
|
314
|
+
assert.isUndefined(
|
|
315
|
+
this.fakeLiblsl.lastFlushInletOptions,
|
|
316
|
+
'Should not have flushed inlet!'
|
|
317
|
+
)
|
|
318
|
+
}
|
|
319
|
+
|
|
85
320
|
@test()
|
|
86
321
|
protected static async stopPullingSetsIsRunningToFalse() {
|
|
87
322
|
await this.startThenStop()
|
|
@@ -113,16 +348,16 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
113
348
|
|
|
114
349
|
@test()
|
|
115
350
|
protected static async callsPullSampleIfChunkSizeIsOne() {
|
|
116
|
-
|
|
351
|
+
await this.runChunkSizeOne()
|
|
117
352
|
|
|
118
353
|
assert.isEqualDeep(
|
|
119
354
|
this.fakeLiblsl.lastPullSampleOptions,
|
|
120
355
|
{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
356
|
+
inletHandle: this.inletHandle,
|
|
357
|
+
sampleBufferPtr: this.sampleBufferPtr,
|
|
358
|
+
sampleBufferElements: this.channelCount,
|
|
359
|
+
timeoutMs: 0,
|
|
360
|
+
errorCodePtr: this.errorCodePtr,
|
|
126
361
|
},
|
|
127
362
|
'Should have called pullSample!'
|
|
128
363
|
)
|
|
@@ -135,46 +370,114 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
135
370
|
assert.isEqualDeep(
|
|
136
371
|
this.fakeLiblsl.lastPullChunkOptions,
|
|
137
372
|
{
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
timestampBufferPtr: this.
|
|
141
|
-
|
|
373
|
+
inletHandle: this.inletHandle,
|
|
374
|
+
sampleBufferPtr: this.sampleBufferPtr,
|
|
375
|
+
timestampBufferPtr: this.timestampBufferPtr,
|
|
376
|
+
sampleBufferElements: this.chunkSize * this.channelCount,
|
|
142
377
|
timestampBufferElements: this.chunkSize,
|
|
143
|
-
|
|
144
|
-
|
|
378
|
+
timeoutMs: 0,
|
|
379
|
+
errorCodePtr: this.errorCodePtr,
|
|
145
380
|
},
|
|
146
381
|
'Should have called pullChunk!'
|
|
147
382
|
)
|
|
148
383
|
}
|
|
149
384
|
|
|
385
|
+
@test()
|
|
386
|
+
protected static async pushSampleHandlesErrorCode() {
|
|
387
|
+
let passedErrorCode: number | undefined
|
|
388
|
+
|
|
389
|
+
StreamInletWorker.handleError = (errorCode: number) => {
|
|
390
|
+
passedErrorCode = errorCode
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const fakeErrorCode = [-4, -3, -2, -1, 0][Math.floor(Math.random() * 5)]
|
|
394
|
+
const worker = this.getFakeWorker()
|
|
395
|
+
|
|
396
|
+
worker['inletWorker']['pullErrorBuffer'].writeInt32LE(fakeErrorCode)
|
|
397
|
+
|
|
398
|
+
await this.startThenStop()
|
|
399
|
+
|
|
400
|
+
assert.isEqualDeep(
|
|
401
|
+
passedErrorCode,
|
|
402
|
+
FakeLiblsl.fakeErrorCode,
|
|
403
|
+
'Did not pass the expected error code to handleError!'
|
|
404
|
+
)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
@test()
|
|
408
|
+
protected static async waitsBetweenPullsIfPassedOption() {
|
|
409
|
+
const waitBetweenPullsMs = 10
|
|
410
|
+
|
|
411
|
+
const instance = await this.LslStreamInlet({
|
|
412
|
+
waitBetweenPullsMs,
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
let pulls = 0
|
|
416
|
+
|
|
417
|
+
const inletWorker = this.getFakeWorker(instance)['inletWorker']
|
|
418
|
+
const original = inletWorker['pullDataOnce'].bind(inletWorker)
|
|
419
|
+
|
|
420
|
+
inletWorker['pullDataOnce'] = async () => {
|
|
421
|
+
pulls++
|
|
422
|
+
await original()
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const t0 = Date.now()
|
|
426
|
+
const promise = this.startPulling(instance)
|
|
427
|
+
|
|
428
|
+
while (pulls < 2) {
|
|
429
|
+
await this.wait(1)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const elapsed = Date.now() - t0
|
|
433
|
+
|
|
434
|
+
assert.isAbove(
|
|
435
|
+
elapsed,
|
|
436
|
+
waitBetweenPullsMs * 0.8,
|
|
437
|
+
'Did not wait between pulls'
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
instance.stopPulling()
|
|
441
|
+
await promise
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
@test()
|
|
445
|
+
protected static async waitsOneMillisecondBetweenPullsIfNotPassed() {
|
|
446
|
+
assert.isEqual(
|
|
447
|
+
this.instance['waitBetweenPullsMs'],
|
|
448
|
+
1,
|
|
449
|
+
'Default waitBetweenPullsMs should be 1!'
|
|
450
|
+
)
|
|
451
|
+
}
|
|
452
|
+
|
|
150
453
|
@test()
|
|
151
454
|
protected static async passesTimeoutMsOptionToPullSample() {
|
|
152
|
-
const
|
|
455
|
+
const pullTimeoutMs = 1000 * Math.random()
|
|
153
456
|
|
|
154
457
|
await this.runInletWithOptions({
|
|
155
458
|
chunkSize: 1,
|
|
156
|
-
|
|
459
|
+
pullTimeoutMs,
|
|
157
460
|
})
|
|
158
461
|
|
|
159
462
|
assert.isEqual(
|
|
160
|
-
this.fakeLiblsl.lastPullSampleOptions?.
|
|
161
|
-
|
|
162
|
-
'Did not pass
|
|
463
|
+
this.fakeLiblsl.lastPullSampleOptions?.timeoutMs,
|
|
464
|
+
pullTimeoutMs,
|
|
465
|
+
'Did not pass pullTimeoutMs to pullSample!'
|
|
163
466
|
)
|
|
164
467
|
}
|
|
165
468
|
|
|
166
469
|
@test()
|
|
167
470
|
protected static async passesTimeoutMsOptionToPullChunk() {
|
|
168
|
-
const
|
|
471
|
+
const pullTimeoutMs = 1000 * Math.random()
|
|
169
472
|
|
|
170
473
|
await this.runInletWithOptions({
|
|
171
474
|
chunkSize: this.chunkSize,
|
|
172
|
-
|
|
475
|
+
pullTimeoutMs,
|
|
173
476
|
})
|
|
174
477
|
|
|
175
478
|
assert.isEqual(
|
|
176
|
-
this.fakeLiblsl.lastPullChunkOptions?.
|
|
177
|
-
|
|
479
|
+
this.fakeLiblsl.lastPullChunkOptions?.timeoutMs,
|
|
480
|
+
pullTimeoutMs,
|
|
178
481
|
'Did not pass timeoutMs to pullChunk!'
|
|
179
482
|
)
|
|
180
483
|
}
|
|
@@ -193,57 +496,9 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
193
496
|
)
|
|
194
497
|
}
|
|
195
498
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
-999,
|
|
200
|
-
`An unknown liblsl error has occurred!`
|
|
201
|
-
)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
@test()
|
|
205
|
-
protected static async throwsWithErrorCodeNegativeOne() {
|
|
206
|
-
await this.assertThrowsWithErrorCode(
|
|
207
|
-
-1,
|
|
208
|
-
`The liblsl operation failed due to a timeout!`
|
|
209
|
-
)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
@test()
|
|
213
|
-
protected static async throwsWithErrorCodeNegativeTwo() {
|
|
214
|
-
await this.assertThrowsWithErrorCode(
|
|
215
|
-
-2,
|
|
216
|
-
`The liblsl stream has been lost!`
|
|
217
|
-
)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
@test()
|
|
221
|
-
protected static async throwsWithErrorCodeNegativeThree() {
|
|
222
|
-
await this.assertThrowsWithErrorCode(
|
|
223
|
-
-3,
|
|
224
|
-
'A liblsl argument was incorrectly specified!'
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
@test()
|
|
229
|
-
protected static async throwsWithErrorCodeNegativeFour() {
|
|
230
|
-
await this.assertThrowsWithErrorCode(
|
|
231
|
-
-4,
|
|
232
|
-
'An internal liblsl error has occurred!'
|
|
233
|
-
)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
private static async assertThrowsWithErrorCode(
|
|
237
|
-
errorCode: number,
|
|
238
|
-
message: string
|
|
239
|
-
) {
|
|
240
|
-
await this.startThenStop()
|
|
241
|
-
|
|
242
|
-
this.instance['errorCodeBuffer'].writeInt32LE(errorCode)
|
|
243
|
-
|
|
244
|
-
assert.doesThrow(() => {
|
|
245
|
-
this.instance['handleErrorCodeIfPresent']()
|
|
246
|
-
}, message)
|
|
499
|
+
private static async startPullingThenDestroy() {
|
|
500
|
+
await this.startPulling()
|
|
501
|
+
this.destroy()
|
|
247
502
|
}
|
|
248
503
|
|
|
249
504
|
private static async runChunkSizeOne() {
|
|
@@ -262,31 +517,47 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
262
517
|
|
|
263
518
|
private static async startThenStop(inlet?: SpyStreamInlet) {
|
|
264
519
|
const instance = inlet || this.instance
|
|
265
|
-
|
|
520
|
+
await this.startPulling(instance)
|
|
266
521
|
await this.wait(10)
|
|
267
522
|
instance.stopPulling()
|
|
268
523
|
}
|
|
269
524
|
|
|
270
|
-
private static startPulling() {
|
|
271
|
-
this.instance
|
|
525
|
+
private static async startPulling(instance?: SpyStreamInlet) {
|
|
526
|
+
const inst = instance || this.instance
|
|
527
|
+
const startPullingPromise = inst.startPulling()
|
|
528
|
+
|
|
529
|
+
while (!this.getFakeWorker(inst).createInletPromise) {
|
|
530
|
+
await this.wait(1)
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
await this.getFakeWorker(inst).createInletPromise
|
|
534
|
+
inst['workerReady'] = true
|
|
535
|
+
|
|
536
|
+
await startPullingPromise
|
|
272
537
|
}
|
|
273
538
|
|
|
274
539
|
private static stopPulling() {
|
|
275
540
|
this.instance.stopPulling()
|
|
276
541
|
}
|
|
277
542
|
|
|
543
|
+
private static destroy() {
|
|
544
|
+
this.instance.destroy()
|
|
545
|
+
}
|
|
546
|
+
|
|
278
547
|
private static get isRunning() {
|
|
279
548
|
return this.instance.isRunning
|
|
280
549
|
}
|
|
281
550
|
|
|
282
|
-
private static get
|
|
283
|
-
return this.
|
|
551
|
+
private static get inletHandle() {
|
|
552
|
+
return this.getFakeWorker()['inletWorker']['inletHandle']
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
private static getFakeWorker(instance?: SpyStreamInlet) {
|
|
556
|
+
const inst = instance || this.instance
|
|
557
|
+
return inst['worker'] as unknown as FakeWorker
|
|
284
558
|
}
|
|
285
559
|
|
|
286
|
-
private static onData = (
|
|
287
|
-
samples: Float32Array,
|
|
288
|
-
timestamps: Float64Array
|
|
289
|
-
) => {
|
|
560
|
+
private static onData = (samples: number[], timestamps: number[]) => {
|
|
290
561
|
this.callsToOnData.push({ samples, timestamps })
|
|
291
562
|
}
|
|
292
563
|
|