@neurodevs/node-lsl 17.1.1 → 18.1.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/.vscode/launch.json +54 -57
- package/.vscode/settings.json +61 -66
- package/.vscode/tasks.json +98 -129
- package/README.md +20 -44
- package/build/__tests__/AbstractPackageTest.d.ts +7 -5
- package/build/__tests__/AbstractPackageTest.js +22 -15
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/BleDeviceController.test.d.ts +54 -0
- package/build/__tests__/impl/BleDeviceController.test.js +333 -0
- package/build/__tests__/impl/BleDeviceController.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 +20 -8
- package/build/__tests__/impl/LslStreamInlet.test.js +224 -69
- 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 +40 -50
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
- package/build/__tests__/impl/LslWebSocketBridge.test.js +19 -20
- 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/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 -50
- package/build/impl/LslStreamInlet.js +79 -149
- 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 +10 -10
- package/build/impl/LslWebSocketBridge.js.map +1 -1
- package/build/impl/controllers/BleDeviceController.d.ts +58 -0
- package/build/impl/controllers/BleDeviceController.js +145 -0
- package/build/impl/controllers/BleDeviceController.js.map +1 -0
- 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 +14 -14
- package/build/index.js +16 -16
- package/build/index.js.map +1 -1
- package/build/scripts/discoverMuse.js +40 -0
- package/build/scripts/discoverMuse.js.map +1 -0
- 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.d.ts +1 -0
- package/build/scripts/runLslEventMarkerEmitter.js +11 -0
- package/build/scripts/runLslEventMarkerEmitter.js.map +1 -0
- package/build/scripts/runMuse.d.ts +1 -0
- package/build/scripts/runMuse.js +40 -0
- package/build/scripts/runMuse.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/BleController/FakeBleController.d.ts +24 -0
- package/build/testDoubles/BleController/FakeBleController.js +42 -0
- package/build/testDoubles/BleController/FakeBleController.js.map +1 -0
- package/build/testDoubles/BleController/SpyBleController.d.ts +14 -0
- package/build/testDoubles/BleController/SpyBleController.js +48 -0
- package/build/testDoubles/BleController/SpyBleController.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 +8 -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/testDoubles/generateRandomOutletOptions.js +1 -1
- package/build/testDoubles/generateRandomOutletOptions.js.map +1 -1
- package/build/validations.js +0 -2
- package/build/validations.js.map +1 -1
- package/eslint.config.js +3 -0
- package/package.json +27 -49
- package/prettier.config.js +3 -0
- package/src/__tests__/AbstractPackageTest.ts +38 -21
- package/src/__tests__/impl/BleDeviceController.test.ts +492 -0
- package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +323 -0
- package/src/__tests__/impl/LslStreamInfo.test.ts +3 -40
- package/src/__tests__/impl/LslStreamInlet.test.ts +344 -97
- package/src/__tests__/impl/LslStreamOutlet.test.ts +65 -73
- package/src/__tests__/impl/LslWebSocketBridge.test.ts +22 -21
- package/src/assertions.ts +2 -1
- package/src/impl/LslEventMarkerEmitter.ts +133 -0
- package/src/impl/LslStreamInfo.ts +17 -29
- package/src/impl/LslStreamInlet.ts +102 -215
- package/src/impl/LslStreamOutlet.ts +54 -78
- package/src/impl/LslWebSocketBridge.ts +14 -14
- package/src/impl/controllers/BleDeviceController.ts +223 -0
- 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 +16 -16
- package/src/scripts/discoverMuse.ts +50 -0
- package/src/scripts/finalizeHandles.ts +63 -0
- package/src/scripts/runLslEventMarkerEmitter.ts +15 -0
- package/src/scripts/runMuse.ts +50 -0
- package/src/scripts/runOutletToInlet.ts +10 -8
- package/src/scripts/testDestroyOutlet.ts +5 -0
- package/src/testDoubles/BleController/FakeBleController.ts +70 -0
- package/src/testDoubles/BleController/SpyBleController.ts +61 -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 +15 -15
- package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -1
- package/src/testDoubles/WorkerThreads/FakeWorker.ts +99 -0
- package/src/testDoubles/generateRandomOutletOptions.ts +2 -1
- package/src/validations.ts +0 -2
- package/tsconfig.json +23 -27
- package/build/.spruce/settings.json +0 -11
- 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 -154
- 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/eslint.config.mjs +0 -3
- package/src/.spruce/settings.json +0 -11
- 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 -543
- 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 → discoverMuse.d.ts} +0 -0
|
@@ -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,46 +85,82 @@ 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
|
+
|
|
70
160
|
@test()
|
|
71
161
|
protected static async destroyCallsStopIfIsRunning() {
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
162
|
+
await this.startPulling()
|
|
163
|
+
this.destroy()
|
|
74
164
|
|
|
75
165
|
assert.isFalse(
|
|
76
166
|
this.instance.isRunning,
|
|
@@ -98,14 +188,135 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
98
188
|
|
|
99
189
|
@test()
|
|
100
190
|
protected static async startPullingSetsIsRunningToTrue() {
|
|
101
|
-
this.startPulling()
|
|
102
|
-
await this.wait(10)
|
|
191
|
+
await this.startPulling()
|
|
103
192
|
|
|
104
193
|
assert.isTrue(this.isRunning, 'isRunning should be true!')
|
|
105
194
|
|
|
106
195
|
this.stopPulling()
|
|
107
196
|
}
|
|
108
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
|
+
|
|
109
320
|
@test()
|
|
110
321
|
protected static async stopPullingSetsIsRunningToFalse() {
|
|
111
322
|
await this.startThenStop()
|
|
@@ -137,16 +348,16 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
137
348
|
|
|
138
349
|
@test()
|
|
139
350
|
protected static async callsPullSampleIfChunkSizeIsOne() {
|
|
140
|
-
|
|
351
|
+
await this.runChunkSizeOne()
|
|
141
352
|
|
|
142
353
|
assert.isEqualDeep(
|
|
143
354
|
this.fakeLiblsl.lastPullSampleOptions,
|
|
144
355
|
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
356
|
+
inletHandle: this.inletHandle,
|
|
357
|
+
sampleBufferPtr: this.sampleBufferPtr,
|
|
358
|
+
sampleBufferElements: this.channelCount,
|
|
359
|
+
timeoutMs: 0,
|
|
360
|
+
errorCodePtr: this.errorCodePtr,
|
|
150
361
|
},
|
|
151
362
|
'Should have called pullSample!'
|
|
152
363
|
)
|
|
@@ -159,46 +370,114 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
159
370
|
assert.isEqualDeep(
|
|
160
371
|
this.fakeLiblsl.lastPullChunkOptions,
|
|
161
372
|
{
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
timestampBufferPtr: this.
|
|
165
|
-
|
|
373
|
+
inletHandle: this.inletHandle,
|
|
374
|
+
sampleBufferPtr: this.sampleBufferPtr,
|
|
375
|
+
timestampBufferPtr: this.timestampBufferPtr,
|
|
376
|
+
sampleBufferElements: this.chunkSize * this.channelCount,
|
|
166
377
|
timestampBufferElements: this.chunkSize,
|
|
167
|
-
|
|
168
|
-
|
|
378
|
+
timeoutMs: 0,
|
|
379
|
+
errorCodePtr: this.errorCodePtr,
|
|
169
380
|
},
|
|
170
381
|
'Should have called pullChunk!'
|
|
171
382
|
)
|
|
172
383
|
}
|
|
173
384
|
|
|
385
|
+
@test()
|
|
386
|
+
protected static async pushSampleHandlesErrorCode() {
|
|
387
|
+
let passedErrorCode: number | undefined
|
|
388
|
+
|
|
389
|
+
StreamInletWorker.handleLslError = (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 handleLslError!'
|
|
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
|
+
|
|
174
453
|
@test()
|
|
175
454
|
protected static async passesTimeoutMsOptionToPullSample() {
|
|
176
|
-
const
|
|
455
|
+
const pullTimeoutMs = 1000 * Math.random()
|
|
177
456
|
|
|
178
457
|
await this.runInletWithOptions({
|
|
179
458
|
chunkSize: 1,
|
|
180
|
-
|
|
459
|
+
pullTimeoutMs,
|
|
181
460
|
})
|
|
182
461
|
|
|
183
462
|
assert.isEqual(
|
|
184
|
-
this.fakeLiblsl.lastPullSampleOptions?.
|
|
185
|
-
|
|
186
|
-
'Did not pass
|
|
463
|
+
this.fakeLiblsl.lastPullSampleOptions?.timeoutMs,
|
|
464
|
+
pullTimeoutMs,
|
|
465
|
+
'Did not pass pullTimeoutMs to pullSample!'
|
|
187
466
|
)
|
|
188
467
|
}
|
|
189
468
|
|
|
190
469
|
@test()
|
|
191
470
|
protected static async passesTimeoutMsOptionToPullChunk() {
|
|
192
|
-
const
|
|
471
|
+
const pullTimeoutMs = 1000 * Math.random()
|
|
193
472
|
|
|
194
473
|
await this.runInletWithOptions({
|
|
195
474
|
chunkSize: this.chunkSize,
|
|
196
|
-
|
|
475
|
+
pullTimeoutMs,
|
|
197
476
|
})
|
|
198
477
|
|
|
199
478
|
assert.isEqual(
|
|
200
|
-
this.fakeLiblsl.lastPullChunkOptions?.
|
|
201
|
-
|
|
479
|
+
this.fakeLiblsl.lastPullChunkOptions?.timeoutMs,
|
|
480
|
+
pullTimeoutMs,
|
|
202
481
|
'Did not pass timeoutMs to pullChunk!'
|
|
203
482
|
)
|
|
204
483
|
}
|
|
@@ -217,57 +496,9 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
217
496
|
)
|
|
218
497
|
}
|
|
219
498
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
-999,
|
|
224
|
-
`An unknown liblsl error has occurred!`
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
@test()
|
|
229
|
-
protected static async throwsWithErrorCodeNegativeOne() {
|
|
230
|
-
await this.assertThrowsWithErrorCode(
|
|
231
|
-
-1,
|
|
232
|
-
`The liblsl operation failed due to a timeout!`
|
|
233
|
-
)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
@test()
|
|
237
|
-
protected static async throwsWithErrorCodeNegativeTwo() {
|
|
238
|
-
await this.assertThrowsWithErrorCode(
|
|
239
|
-
-2,
|
|
240
|
-
`The liblsl stream has been lost!`
|
|
241
|
-
)
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
@test()
|
|
245
|
-
protected static async throwsWithErrorCodeNegativeThree() {
|
|
246
|
-
await this.assertThrowsWithErrorCode(
|
|
247
|
-
-3,
|
|
248
|
-
'A liblsl argument was incorrectly specified!'
|
|
249
|
-
)
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
@test()
|
|
253
|
-
protected static async throwsWithErrorCodeNegativeFour() {
|
|
254
|
-
await this.assertThrowsWithErrorCode(
|
|
255
|
-
-4,
|
|
256
|
-
'An internal liblsl error has occurred!'
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
private static async assertThrowsWithErrorCode(
|
|
261
|
-
errorCode: number,
|
|
262
|
-
message: string
|
|
263
|
-
) {
|
|
264
|
-
await this.startThenStop()
|
|
265
|
-
|
|
266
|
-
this.instance['errorCodeBuffer'].writeInt32LE(errorCode)
|
|
267
|
-
|
|
268
|
-
assert.doesThrow(() => {
|
|
269
|
-
this.instance['handleErrorCodeIfPresent']()
|
|
270
|
-
}, message)
|
|
499
|
+
private static async startPullingThenDestroy() {
|
|
500
|
+
await this.startPulling()
|
|
501
|
+
this.destroy()
|
|
271
502
|
}
|
|
272
503
|
|
|
273
504
|
private static async runChunkSizeOne() {
|
|
@@ -286,31 +517,47 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
286
517
|
|
|
287
518
|
private static async startThenStop(inlet?: SpyStreamInlet) {
|
|
288
519
|
const instance = inlet || this.instance
|
|
289
|
-
|
|
520
|
+
await this.startPulling(instance)
|
|
290
521
|
await this.wait(10)
|
|
291
522
|
instance.stopPulling()
|
|
292
523
|
}
|
|
293
524
|
|
|
294
|
-
private static startPulling() {
|
|
295
|
-
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
|
|
296
537
|
}
|
|
297
538
|
|
|
298
539
|
private static stopPulling() {
|
|
299
540
|
this.instance.stopPulling()
|
|
300
541
|
}
|
|
301
542
|
|
|
543
|
+
private static destroy() {
|
|
544
|
+
this.instance.destroy()
|
|
545
|
+
}
|
|
546
|
+
|
|
302
547
|
private static get isRunning() {
|
|
303
548
|
return this.instance.isRunning
|
|
304
549
|
}
|
|
305
550
|
|
|
306
|
-
private static get
|
|
307
|
-
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
|
|
308
558
|
}
|
|
309
559
|
|
|
310
|
-
private static onData = (
|
|
311
|
-
samples: Float32Array,
|
|
312
|
-
timestamps: Float64Array
|
|
313
|
-
) => {
|
|
560
|
+
private static onData = (samples: number[], timestamps: number[]) => {
|
|
314
561
|
this.callsToOnData.push({ samples, timestamps })
|
|
315
562
|
}
|
|
316
563
|
|