sportident.js 1.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/.dependency-cruiser.js +233 -0
- package/.editorconfig +12 -0
- package/.eslintignore +6 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +35 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- package/.github/workflows/npm.yml +17 -0
- package/LICENSE +21 -0
- package/README.md +31 -0
- package/babel.config.js +21 -0
- package/build-docs.sh +25 -0
- package/docs/index.md +9 -0
- package/docs/typedoc/index.md +11 -0
- package/eslint.base.js +232 -0
- package/install.sh +6 -0
- package/jest.config.ts +49 -0
- package/nx.json +39 -0
- package/package.json +51 -0
- package/src/SiCard/BaseSiCard.test.ts +187 -0
- package/src/SiCard/BaseSiCard.ts +101 -0
- package/src/SiCard/IRaceResultData.ts +16 -0
- package/src/SiCard/ISiCard.ts +23 -0
- package/src/SiCard/ISiCardExamples.ts +4 -0
- package/src/SiCard/index.ts +2 -0
- package/src/SiCard/raceResultTools.test.ts +260 -0
- package/src/SiCard/raceResultTools.ts +150 -0
- package/src/SiCard/types/FCard.test.ts +19 -0
- package/src/SiCard/types/FCard.ts +14 -0
- package/src/SiCard/types/ModernSiCard.test.ts +186 -0
- package/src/SiCard/types/ModernSiCard.ts +241 -0
- package/src/SiCard/types/PCard.test.ts +19 -0
- package/src/SiCard/types/PCard.ts +14 -0
- package/src/SiCard/types/SIAC.test.ts +84 -0
- package/src/SiCard/types/SIAC.ts +19 -0
- package/src/SiCard/types/SiCard10.test.ts +85 -0
- package/src/SiCard/types/SiCard10.ts +17 -0
- package/src/SiCard/types/SiCard11.test.ts +84 -0
- package/src/SiCard/types/SiCard11.ts +19 -0
- package/src/SiCard/types/SiCard5.test.ts +149 -0
- package/src/SiCard/types/SiCard5.ts +129 -0
- package/src/SiCard/types/SiCard6.test.ts +179 -0
- package/src/SiCard/types/SiCard6.ts +222 -0
- package/src/SiCard/types/SiCard8.test.ts +137 -0
- package/src/SiCard/types/SiCard8.ts +129 -0
- package/src/SiCard/types/SiCard9.test.ts +132 -0
- package/src/SiCard/types/SiCard9.ts +128 -0
- package/src/SiCard/types/TCard.test.ts +19 -0
- package/src/SiCard/types/TCard.ts +14 -0
- package/src/SiCard/types/index.test.ts +26 -0
- package/src/SiCard/types/index.ts +15 -0
- package/src/SiCard/types/modernSiCardExamples.ts +364 -0
- package/src/SiCard/types/siCard5Examples.ts +73 -0
- package/src/SiCard/types/siCard6Examples.ts +262 -0
- package/src/SiCard/types/siCard8Examples.ts +152 -0
- package/src/SiCard/types/siCard9Examples.ts +143 -0
- package/src/SiDevice/INavigatorWebSerial.ts +78 -0
- package/src/SiDevice/INavigatorWebUsb.ts +62 -0
- package/src/SiDevice/ISiDevice.ts +48 -0
- package/src/SiDevice/ISiDeviceDriver.ts +35 -0
- package/src/SiDevice/README.md +13 -0
- package/src/SiDevice/SiDevice.test.ts +354 -0
- package/src/SiDevice/SiDevice.ts +132 -0
- package/src/SiDevice/WebSerialSiDeviceDriver.ts +146 -0
- package/src/SiDevice/WebUsbSiDeviceDriver.ts +343 -0
- package/src/SiDevice/index.ts +3 -0
- package/src/SiDevice/testUtils/index.ts +2 -0
- package/src/SiDevice/testUtils/testISiDeviceDriver.ts +63 -0
- package/src/SiDevice/testUtils/testISiDeviceDriverWithAutodetection.ts +72 -0
- package/src/SiStation/BaseSiStation.test.ts +221 -0
- package/src/SiStation/BaseSiStation.ts +253 -0
- package/src/SiStation/CoupledSiStation.test.ts +41 -0
- package/src/SiStation/CoupledSiStation.ts +130 -0
- package/src/SiStation/ISiMainStation.ts +29 -0
- package/src/SiStation/ISiSendTask.ts +9 -0
- package/src/SiStation/ISiStation.ts +88 -0
- package/src/SiStation/ISiTargetMultiplexer.ts +51 -0
- package/src/SiStation/SiMainStation.test.ts +222 -0
- package/src/SiStation/SiMainStation.ts +133 -0
- package/src/SiStation/SiSendTask.ts +50 -0
- package/src/SiStation/SiTargetMultiplexer.targeting.test.ts +112 -0
- package/src/SiStation/SiTargetMultiplexer.test.ts +605 -0
- package/src/SiStation/SiTargetMultiplexer.ts +241 -0
- package/src/SiStation/index.ts +5 -0
- package/src/SiStation/siStationExamples.ts +103 -0
- package/src/constants.test.ts +17 -0
- package/src/constants.ts +92 -0
- package/src/fakes/FakeSiCard/BaseFakeSiCard.test.ts +11 -0
- package/src/fakes/FakeSiCard/BaseFakeSiCard.ts +10 -0
- package/src/fakes/FakeSiCard/IFakeSiCard.ts +6 -0
- package/src/fakes/FakeSiCard/index.ts +2 -0
- package/src/fakes/FakeSiCard/types/FakeModernSiCard.test.ts +62 -0
- package/src/fakes/FakeSiCard/types/FakeModernSiCard.ts +43 -0
- package/src/fakes/FakeSiCard/types/FakeSIAC.ts +17 -0
- package/src/fakes/FakeSiCard/types/FakeSiCard10.ts +17 -0
- package/src/fakes/FakeSiCard/types/FakeSiCard11.ts +17 -0
- package/src/fakes/FakeSiCard/types/FakeSiCard5.test.ts +42 -0
- package/src/fakes/FakeSiCard/types/FakeSiCard5.ts +40 -0
- package/src/fakes/FakeSiCard/types/FakeSiCard6.test.ts +62 -0
- package/src/fakes/FakeSiCard/types/FakeSiCard6.ts +44 -0
- package/src/fakes/FakeSiCard/types/FakeSiCard8.ts +16 -0
- package/src/fakes/FakeSiCard/types/FakeSiCard9.ts +16 -0
- package/src/fakes/FakeSiCard/types/index.ts +7 -0
- package/src/fakes/FakeSiDeviceDriver.ts +148 -0
- package/src/fakes/FakeSiMainStation.test.ts +141 -0
- package/src/fakes/FakeSiMainStation.ts +118 -0
- package/src/fakes/IFakeSiMainStation.ts +15 -0
- package/src/fakes/index.ts +2 -0
- package/src/index.ts +24 -0
- package/src/siProtocol.test.ts +509 -0
- package/src/siProtocol.ts +417 -0
- package/src/storage/SiArray.test.ts +103 -0
- package/src/storage/SiArray.ts +56 -0
- package/src/storage/SiBool.test.ts +81 -0
- package/src/storage/SiBool.ts +47 -0
- package/src/storage/SiDataType.test.ts +81 -0
- package/src/storage/SiDataType.ts +60 -0
- package/src/storage/SiDict.test.ts +115 -0
- package/src/storage/SiDict.ts +60 -0
- package/src/storage/SiEnum.test.ts +77 -0
- package/src/storage/SiEnum.ts +48 -0
- package/src/storage/SiFieldValue.test.ts +58 -0
- package/src/storage/SiFieldValue.ts +23 -0
- package/src/storage/SiInt.test.ts +80 -0
- package/src/storage/SiInt.ts +84 -0
- package/src/storage/SiModified.test.ts +135 -0
- package/src/storage/SiModified.ts +59 -0
- package/src/storage/SiStorage.test.ts +51 -0
- package/src/storage/SiStorage.ts +44 -0
- package/src/storage/index.test.ts +222 -0
- package/src/storage/index.ts +12 -0
- package/src/storage/interfaces.ts +41 -0
- package/src/storage/siStringEncoding.ts +1361 -0
- package/src/testUtils.test.ts +266 -0
- package/src/testUtils.ts +75 -0
- package/src/utils/NumberRange.test.ts +66 -0
- package/src/utils/NumberRange.ts +46 -0
- package/src/utils/NumberRangeRegistry.test.ts +49 -0
- package/src/utils/NumberRangeRegistry.ts +43 -0
- package/src/utils/bytes.test.ts +126 -0
- package/src/utils/bytes.ts +69 -0
- package/src/utils/errors.test.ts +29 -0
- package/src/utils/errors.ts +20 -0
- package/src/utils/events.test.ts +112 -0
- package/src/utils/events.ts +68 -0
- package/src/utils/general.test.ts +139 -0
- package/src/utils/general.ts +69 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/mixins.test.ts +40 -0
- package/src/utils/mixins.ts +13 -0
- package/src/utils/typed.ts +3 -0
- package/tsconfig.base.json +22 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
import { describe, expect, test } from '@jest/globals';
|
|
2
|
+
import { proto } from '../constants';
|
|
3
|
+
import * as siProtocol from '../siProtocol';
|
|
4
|
+
import * as testUtils from '../testUtils';
|
|
5
|
+
import { SiDeviceState, SiDeviceReceiveEvent, type ISiDeviceDriverData } from '../SiDevice/ISiDevice';
|
|
6
|
+
import type { ISiDeviceDriver } from '../SiDevice/ISiDeviceDriver';
|
|
7
|
+
import { SiDevice } from '../SiDevice/SiDevice';
|
|
8
|
+
import { SiTargetMultiplexerDirectMessageEvent, SiTargetMultiplexerMessageEvent, SiTargetMultiplexerRemoteMessageEvent, SiTargetMultiplexerTarget } from './ISiTargetMultiplexer';
|
|
9
|
+
import { SiSendTaskState } from './ISiSendTask';
|
|
10
|
+
import { DIRECT_DEVICE_INITIATED_COMMANDS, SiTargetMultiplexer } from './SiTargetMultiplexer';
|
|
11
|
+
|
|
12
|
+
testUtils.useFakeTimers();
|
|
13
|
+
|
|
14
|
+
function mockDriver(driver: Partial<ISiDeviceDriver<ISiDeviceDriverData<unknown>>>) {
|
|
15
|
+
return driver as unknown as ISiDeviceDriver<ISiDeviceDriverData<unknown>>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('SiTargetMultiplexer', () => {
|
|
19
|
+
test('is unique per device', () => {
|
|
20
|
+
const siDevice = new SiDevice('isUniquePerDevice', {
|
|
21
|
+
driver: mockDriver({ name: 'FakeSiDevice' })
|
|
22
|
+
});
|
|
23
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
24
|
+
const muxer1 = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
25
|
+
expect(muxer1 instanceof SiTargetMultiplexer).toBe(true);
|
|
26
|
+
const muxer2 = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
27
|
+
expect(muxer2).toBe(muxer1);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('handles receiving', () => {
|
|
31
|
+
const siDevice = new SiDevice('handlesReceiving', {
|
|
32
|
+
driver: mockDriver({})
|
|
33
|
+
});
|
|
34
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
35
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
36
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
37
|
+
|
|
38
|
+
const receivedMessages: siProtocol.SiMessage[] = [];
|
|
39
|
+
const recordMessage = (e: SiTargetMultiplexerMessageEvent) => {
|
|
40
|
+
receivedMessages.push(e.message);
|
|
41
|
+
};
|
|
42
|
+
muxer.addEventListener('message', recordMessage);
|
|
43
|
+
|
|
44
|
+
const receivedDirectMessages: siProtocol.SiMessage[] = [];
|
|
45
|
+
const recordDirectMessage = (e: SiTargetMultiplexerDirectMessageEvent) => {
|
|
46
|
+
receivedDirectMessages.push(e.message);
|
|
47
|
+
};
|
|
48
|
+
muxer.addEventListener('directMessage', recordDirectMessage);
|
|
49
|
+
|
|
50
|
+
const receivedRemoteMessages: siProtocol.SiMessage[] = [];
|
|
51
|
+
const recordRemoteMessage = (e: SiTargetMultiplexerRemoteMessageEvent) => {
|
|
52
|
+
receivedRemoteMessages.push(e.message);
|
|
53
|
+
};
|
|
54
|
+
muxer.addEventListener('remoteMessage', recordRemoteMessage);
|
|
55
|
+
|
|
56
|
+
const directOnlyCommands = Object.keys(DIRECT_DEVICE_INITIATED_COMMANDS).map(Number);
|
|
57
|
+
const randomMessage1 = testUtils.getRandomMessage({
|
|
58
|
+
command: testUtils.getRandomByteExcept(directOnlyCommands)
|
|
59
|
+
});
|
|
60
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, siProtocol.render(randomMessage1)));
|
|
61
|
+
expect(receivedMessages).toEqual([randomMessage1]);
|
|
62
|
+
expect(receivedDirectMessages).toEqual([]);
|
|
63
|
+
expect(receivedRemoteMessages).toEqual([]);
|
|
64
|
+
|
|
65
|
+
const randomMessage2 = testUtils.getRandomMessage({
|
|
66
|
+
command: testUtils.getRandomByteExcept(directOnlyCommands)
|
|
67
|
+
});
|
|
68
|
+
muxer.target = SiTargetMultiplexerTarget.Direct;
|
|
69
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, siProtocol.render(randomMessage2)));
|
|
70
|
+
expect(receivedMessages).toEqual([randomMessage1, randomMessage2]);
|
|
71
|
+
expect(receivedDirectMessages).toEqual([randomMessage2]);
|
|
72
|
+
expect(receivedRemoteMessages).toEqual([]);
|
|
73
|
+
|
|
74
|
+
const randomMessage3 = testUtils.getRandomMessage({
|
|
75
|
+
command: testUtils.getRandomByteExcept(directOnlyCommands)
|
|
76
|
+
});
|
|
77
|
+
muxer.target = SiTargetMultiplexerTarget.Remote;
|
|
78
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, siProtocol.render(randomMessage3)));
|
|
79
|
+
expect(receivedMessages).toEqual([randomMessage1, randomMessage2, randomMessage3]);
|
|
80
|
+
expect(receivedDirectMessages).toEqual([randomMessage2]);
|
|
81
|
+
expect(receivedRemoteMessages).toEqual([randomMessage3]);
|
|
82
|
+
|
|
83
|
+
muxer.removeEventListener('message', recordMessage);
|
|
84
|
+
muxer.removeEventListener('directMessage', recordDirectMessage);
|
|
85
|
+
muxer.removeEventListener('remoteMessage', recordRemoteMessage);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('handles simple sending', async () => {
|
|
89
|
+
const siDevice = new SiDevice('handlesSending0', {
|
|
90
|
+
driver: mockDriver({
|
|
91
|
+
send: () => Promise.resolve()
|
|
92
|
+
})
|
|
93
|
+
});
|
|
94
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
95
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
96
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
97
|
+
|
|
98
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
99
|
+
const timeState = { sendingFinished: false };
|
|
100
|
+
muxer.sendMessageToLatestTarget(randomMessage, 0, 1).then((responses) => {
|
|
101
|
+
expect(responses.length).toBe(0);
|
|
102
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
103
|
+
timeState.sendingFinished = true;
|
|
104
|
+
});
|
|
105
|
+
await testUtils.advanceTimersByTime(0);
|
|
106
|
+
expect(timeState).toEqual({ sendingFinished: true });
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('handles sending and waiting for 1 response', async () => {
|
|
110
|
+
const siDevice = new SiDevice('handlesSending1', {
|
|
111
|
+
driver: mockDriver({
|
|
112
|
+
send: () => Promise.resolve()
|
|
113
|
+
})
|
|
114
|
+
});
|
|
115
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
116
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
117
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
118
|
+
|
|
119
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
120
|
+
const timeState = { sendingFinished: false };
|
|
121
|
+
muxer.sendMessageToLatestTarget(randomMessage, 1, 2).then((responses) => {
|
|
122
|
+
expect(responses.length).toBe(1);
|
|
123
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
124
|
+
timeState.sendingFinished = true;
|
|
125
|
+
});
|
|
126
|
+
setTimeout(() => {
|
|
127
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, siProtocol.render(randomMessage)));
|
|
128
|
+
}, 1);
|
|
129
|
+
await testUtils.advanceTimersByTime(0);
|
|
130
|
+
expect(timeState).toEqual({ sendingFinished: false });
|
|
131
|
+
await testUtils.advanceTimersByTime(1);
|
|
132
|
+
expect(timeState).toEqual({ sendingFinished: true });
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('handles sending and waiting for 1 NAK', async () => {
|
|
136
|
+
const siDevice = new SiDevice('handlesSending1NAK', {
|
|
137
|
+
driver: mockDriver({
|
|
138
|
+
send: () => Promise.resolve()
|
|
139
|
+
})
|
|
140
|
+
});
|
|
141
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
142
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
143
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
144
|
+
|
|
145
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
146
|
+
const timeState = { sendingFailed: false };
|
|
147
|
+
muxer.sendMessageToLatestTarget(randomMessage, 1, 2).catch(() => {
|
|
148
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
149
|
+
timeState.sendingFailed = true;
|
|
150
|
+
});
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, siProtocol.render({ mode: proto.NAK })));
|
|
153
|
+
}, 1);
|
|
154
|
+
await testUtils.advanceTimersByTime(0);
|
|
155
|
+
expect(timeState).toEqual({ sendingFailed: false });
|
|
156
|
+
await testUtils.advanceTimersByTime(1);
|
|
157
|
+
expect(timeState).toEqual({ sendingFailed: true });
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('handles sending and waiting for 2 responses', async () => {
|
|
161
|
+
const siDevice = new SiDevice('handlesSending2', {
|
|
162
|
+
driver: mockDriver({
|
|
163
|
+
send: () => Promise.resolve()
|
|
164
|
+
})
|
|
165
|
+
});
|
|
166
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
167
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
168
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
169
|
+
|
|
170
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
171
|
+
const timeState = { receive1: false, receive2: false, sendingFinished: false };
|
|
172
|
+
muxer.sendMessageToLatestTarget(randomMessage, 2, 3).then((responses) => {
|
|
173
|
+
expect(responses.length).toBe(2);
|
|
174
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
175
|
+
timeState.sendingFinished = true;
|
|
176
|
+
});
|
|
177
|
+
setTimeout(() => {
|
|
178
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, siProtocol.render(randomMessage)));
|
|
179
|
+
timeState.receive1 = true;
|
|
180
|
+
}, 1);
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, siProtocol.render(randomMessage)));
|
|
183
|
+
timeState.receive2 = true;
|
|
184
|
+
}, 2);
|
|
185
|
+
await testUtils.advanceTimersByTime(0);
|
|
186
|
+
expect(timeState).toEqual({ receive1: false, receive2: false, sendingFinished: false });
|
|
187
|
+
await testUtils.advanceTimersByTime(1);
|
|
188
|
+
expect(timeState).toEqual({ receive1: true, receive2: false, sendingFinished: false });
|
|
189
|
+
await testUtils.nTimesAsync(10, () => testUtils.advanceTimersByTime(1));
|
|
190
|
+
expect(timeState).toEqual({ receive1: true, receive2: true, sendingFinished: true });
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
test('handles sending and timing out waiting for 1 response', async () => {
|
|
194
|
+
const siDevice = new SiDevice('handlesSending1Timeout', {
|
|
195
|
+
driver: mockDriver({
|
|
196
|
+
send: () => Promise.resolve()
|
|
197
|
+
})
|
|
198
|
+
});
|
|
199
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
200
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
201
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
202
|
+
|
|
203
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
204
|
+
const timeState = { timedOut: false };
|
|
205
|
+
muxer.sendMessageToLatestTarget(randomMessage, 1, 1).catch(() => {
|
|
206
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
207
|
+
timeState.timedOut = true;
|
|
208
|
+
});
|
|
209
|
+
await testUtils.advanceTimersByTime(0);
|
|
210
|
+
expect(timeState).toEqual({ timedOut: false });
|
|
211
|
+
await testUtils.advanceTimersByTime(1);
|
|
212
|
+
expect(timeState).toEqual({ timedOut: true });
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('handles sending and timing out waiting for 2 responses', async () => {
|
|
216
|
+
const siDevice = new SiDevice('handlesSending2Timeout', {
|
|
217
|
+
driver: mockDriver({
|
|
218
|
+
send: () => Promise.resolve()
|
|
219
|
+
})
|
|
220
|
+
});
|
|
221
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
222
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
223
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
224
|
+
|
|
225
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
226
|
+
const timeState = { receive1: false, timedOut: false };
|
|
227
|
+
muxer.sendMessageToLatestTarget(randomMessage, 2, 2).catch(() => {
|
|
228
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
229
|
+
timeState.timedOut = true;
|
|
230
|
+
});
|
|
231
|
+
setTimeout(() => {
|
|
232
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, siProtocol.render(randomMessage)));
|
|
233
|
+
timeState.receive1 = true;
|
|
234
|
+
}, 1);
|
|
235
|
+
await testUtils.advanceTimersByTime(0);
|
|
236
|
+
expect(timeState).toEqual({ receive1: false, timedOut: false });
|
|
237
|
+
await testUtils.advanceTimersByTime(1);
|
|
238
|
+
expect(timeState).toEqual({ receive1: true, timedOut: false });
|
|
239
|
+
await testUtils.advanceTimersByTime(1);
|
|
240
|
+
expect(timeState).toEqual({ receive1: true, timedOut: true });
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('does not time out, if it already succeeded', async () => {
|
|
244
|
+
const siDevice = new SiDevice('noTimeoutIfSucceeded', {
|
|
245
|
+
driver: mockDriver({
|
|
246
|
+
send: () => Promise.resolve()
|
|
247
|
+
})
|
|
248
|
+
});
|
|
249
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
250
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
251
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
252
|
+
|
|
253
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
254
|
+
const timeoutInMiliseconds = 2;
|
|
255
|
+
const timeState = {
|
|
256
|
+
madeSuccessful: false,
|
|
257
|
+
timeoutPassed: false,
|
|
258
|
+
timedOut: false,
|
|
259
|
+
succeeded: false
|
|
260
|
+
};
|
|
261
|
+
muxer
|
|
262
|
+
.sendMessageToLatestTarget(randomMessage, 1, timeoutInMiliseconds)
|
|
263
|
+
.then(() => {
|
|
264
|
+
timeState.succeeded = true;
|
|
265
|
+
})
|
|
266
|
+
.catch(() => {
|
|
267
|
+
timeState.timedOut = true;
|
|
268
|
+
});
|
|
269
|
+
setTimeout(() => {
|
|
270
|
+
muxer._test.sendQueue[0].state = SiSendTaskState.Succeeded;
|
|
271
|
+
timeState.madeSuccessful = true;
|
|
272
|
+
}, 1);
|
|
273
|
+
setTimeout(() => {
|
|
274
|
+
timeState.timeoutPassed = true;
|
|
275
|
+
}, timeoutInMiliseconds);
|
|
276
|
+
await testUtils.advanceTimersByTime(0);
|
|
277
|
+
expect(timeState).toEqual({
|
|
278
|
+
madeSuccessful: false,
|
|
279
|
+
timeoutPassed: false,
|
|
280
|
+
timedOut: false,
|
|
281
|
+
succeeded: false
|
|
282
|
+
});
|
|
283
|
+
await testUtils.advanceTimersByTime(1);
|
|
284
|
+
expect(timeState).toEqual({
|
|
285
|
+
madeSuccessful: true,
|
|
286
|
+
timeoutPassed: false,
|
|
287
|
+
timedOut: false,
|
|
288
|
+
succeeded: false
|
|
289
|
+
});
|
|
290
|
+
await testUtils.advanceTimersByTime(1);
|
|
291
|
+
expect(timeState).toEqual({
|
|
292
|
+
madeSuccessful: true,
|
|
293
|
+
timeoutPassed: true,
|
|
294
|
+
timedOut: false,
|
|
295
|
+
succeeded: false
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test('does not succeed, if response for different command arrives', async () => {
|
|
300
|
+
const siDevice = new SiDevice('differentCommand', {
|
|
301
|
+
driver: mockDriver({
|
|
302
|
+
send: () => Promise.resolve()
|
|
303
|
+
})
|
|
304
|
+
});
|
|
305
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
306
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
307
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
308
|
+
|
|
309
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
310
|
+
const timeState = { receive1: false, timedOut: false, succeeded: false };
|
|
311
|
+
muxer
|
|
312
|
+
.sendMessageToLatestTarget(randomMessage, 1, 2)
|
|
313
|
+
.then(() => {
|
|
314
|
+
timeState.succeeded = true;
|
|
315
|
+
})
|
|
316
|
+
.catch(() => {
|
|
317
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
318
|
+
timeState.timedOut = true;
|
|
319
|
+
});
|
|
320
|
+
setTimeout(() => {
|
|
321
|
+
siDevice.dispatchEvent(
|
|
322
|
+
'receive',
|
|
323
|
+
new SiDeviceReceiveEvent(
|
|
324
|
+
siDevice,
|
|
325
|
+
siProtocol.render({
|
|
326
|
+
command: testUtils.getRandomByteExcept([randomMessage.command]),
|
|
327
|
+
parameters: randomMessage.parameters
|
|
328
|
+
})
|
|
329
|
+
)
|
|
330
|
+
);
|
|
331
|
+
timeState.receive1 = true;
|
|
332
|
+
}, 1);
|
|
333
|
+
await testUtils.advanceTimersByTime(0);
|
|
334
|
+
expect(timeState).toEqual({ receive1: false, timedOut: false, succeeded: false });
|
|
335
|
+
await testUtils.advanceTimersByTime(1);
|
|
336
|
+
expect(timeState).toEqual({ receive1: true, timedOut: false, succeeded: false });
|
|
337
|
+
await testUtils.advanceTimersByTime(1);
|
|
338
|
+
expect(timeState).toEqual({ receive1: true, timedOut: true, succeeded: false });
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test('cannot send to unopened SiDevice', async () => {
|
|
342
|
+
const siDevice = new SiDevice('cannotSendToUnopened', {
|
|
343
|
+
driver: mockDriver({})
|
|
344
|
+
});
|
|
345
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
346
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
347
|
+
|
|
348
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
349
|
+
const timeState = { timedOut: false };
|
|
350
|
+
muxer.sendMessageToLatestTarget(randomMessage, 1, 1).catch(() => {
|
|
351
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
352
|
+
timeState.timedOut = true;
|
|
353
|
+
});
|
|
354
|
+
await testUtils.advanceTimersByTime(0);
|
|
355
|
+
expect(timeState).toEqual({ timedOut: false });
|
|
356
|
+
await testUtils.advanceTimersByTime(1);
|
|
357
|
+
expect(timeState).toEqual({ timedOut: true });
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
test('handles sending as soon as device is openend', async () => {
|
|
361
|
+
const siDevice = new SiDevice('handlesSendingAsSoonAsOpened', {
|
|
362
|
+
driver: mockDriver({
|
|
363
|
+
send: () => Promise.resolve()
|
|
364
|
+
})
|
|
365
|
+
});
|
|
366
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
367
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
368
|
+
|
|
369
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
370
|
+
const timeState = { deviceOpened: false, sendingFinished: false };
|
|
371
|
+
muxer.sendMessageToLatestTarget(randomMessage, 0, 3).then(() => {
|
|
372
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
373
|
+
timeState.sendingFinished = true;
|
|
374
|
+
});
|
|
375
|
+
setTimeout(() => {
|
|
376
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
377
|
+
timeState.deviceOpened = true;
|
|
378
|
+
}, 1);
|
|
379
|
+
await testUtils.advanceTimersByTime(0);
|
|
380
|
+
expect(timeState).toEqual({ deviceOpened: false, sendingFinished: false });
|
|
381
|
+
await testUtils.advanceTimersByTime(1);
|
|
382
|
+
expect(timeState).toEqual({ deviceOpened: true, sendingFinished: false });
|
|
383
|
+
await testUtils.advanceTimersByTime(1);
|
|
384
|
+
expect(timeState).toEqual({ deviceOpened: true, sendingFinished: true });
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
test('sends all as soon as device is openend', async () => {
|
|
388
|
+
const siDevice = new SiDevice('sendsAllAsSoonAsOpened', {
|
|
389
|
+
driver: mockDriver({
|
|
390
|
+
send: () => Promise.resolve()
|
|
391
|
+
})
|
|
392
|
+
});
|
|
393
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
394
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
395
|
+
|
|
396
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
397
|
+
const timeState = { deviceOpened: false, numSuccess: 0, allSendingFinished: false };
|
|
398
|
+
const getMuxerPromise = () =>
|
|
399
|
+
muxer.sendMessageToLatestTarget(randomMessage, 0, 4).then(() => {
|
|
400
|
+
timeState.numSuccess = (timeState.numSuccess || 0) + 1;
|
|
401
|
+
});
|
|
402
|
+
Promise.all([getMuxerPromise(), getMuxerPromise()]).then(() => {
|
|
403
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
404
|
+
timeState.allSendingFinished = true;
|
|
405
|
+
});
|
|
406
|
+
setTimeout(() => {
|
|
407
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
408
|
+
timeState.deviceOpened = true;
|
|
409
|
+
}, 1);
|
|
410
|
+
await testUtils.advanceTimersByTime(0);
|
|
411
|
+
expect(timeState).toEqual({ deviceOpened: false, numSuccess: 0, allSendingFinished: false });
|
|
412
|
+
await testUtils.advanceTimersByTime(1);
|
|
413
|
+
expect(timeState).toEqual({ deviceOpened: true, numSuccess: 0, allSendingFinished: false });
|
|
414
|
+
await testUtils.advanceTimersByTime(1);
|
|
415
|
+
expect(timeState).toEqual({ deviceOpened: true, numSuccess: 1, allSendingFinished: false });
|
|
416
|
+
await testUtils.advanceTimersByTime(1);
|
|
417
|
+
expect(timeState).toEqual({ deviceOpened: true, numSuccess: 2, allSendingFinished: false });
|
|
418
|
+
await testUtils.advanceTimersByTime(0); // for Promise.all
|
|
419
|
+
expect(timeState).toEqual({ deviceOpened: true, numSuccess: 2, allSendingFinished: true });
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
test('aborts sending as soon as device is closed', async () => {
|
|
423
|
+
const siDevice = new SiDevice('abortsAllAsSoonAsClosed', {
|
|
424
|
+
driver: mockDriver({
|
|
425
|
+
send: () => Promise.resolve()
|
|
426
|
+
})
|
|
427
|
+
});
|
|
428
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
429
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
430
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
431
|
+
|
|
432
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
433
|
+
const timeState = {
|
|
434
|
+
numSuccess: 0,
|
|
435
|
+
numAbort: 0,
|
|
436
|
+
deviceClosed: false,
|
|
437
|
+
allSendingFinished: false
|
|
438
|
+
};
|
|
439
|
+
const getMuxerPromise = () =>
|
|
440
|
+
muxer
|
|
441
|
+
.sendMessageToLatestTarget(randomMessage, 0, 4)
|
|
442
|
+
.then(
|
|
443
|
+
() => {
|
|
444
|
+
timeState.numSuccess = (timeState.numSuccess || 0) + 1;
|
|
445
|
+
},
|
|
446
|
+
() => {}
|
|
447
|
+
)
|
|
448
|
+
.then(
|
|
449
|
+
() => {
|
|
450
|
+
timeState.numAbort = (timeState.numAbort || 0) + 1;
|
|
451
|
+
},
|
|
452
|
+
() => {}
|
|
453
|
+
);
|
|
454
|
+
Promise.all([getMuxerPromise(), getMuxerPromise(), getMuxerPromise()]).then(
|
|
455
|
+
() => {
|
|
456
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
457
|
+
timeState.allSendingFinished = true;
|
|
458
|
+
},
|
|
459
|
+
() => {}
|
|
460
|
+
);
|
|
461
|
+
setTimeout(() => {
|
|
462
|
+
siDevice.setState(SiDeviceState.Closing);
|
|
463
|
+
timeState.deviceClosed = true;
|
|
464
|
+
}, 1);
|
|
465
|
+
await testUtils.advanceTimersByTime(0);
|
|
466
|
+
expect(timeState).toEqual({
|
|
467
|
+
numSuccess: 1,
|
|
468
|
+
numAbort: 0,
|
|
469
|
+
deviceClosed: false,
|
|
470
|
+
allSendingFinished: false
|
|
471
|
+
});
|
|
472
|
+
await testUtils.advanceTimersByTime(1);
|
|
473
|
+
expect(timeState).toEqual({
|
|
474
|
+
numSuccess: 1,
|
|
475
|
+
numAbort: 2,
|
|
476
|
+
deviceClosed: true,
|
|
477
|
+
allSendingFinished: false
|
|
478
|
+
});
|
|
479
|
+
await testUtils.advanceTimersByTime(0); // for Promise.all (not called)
|
|
480
|
+
expect(timeState).toEqual({
|
|
481
|
+
numSuccess: 1,
|
|
482
|
+
numAbort: 2,
|
|
483
|
+
deviceClosed: true,
|
|
484
|
+
allSendingFinished: false
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
test('handles device failing to send', async () => {
|
|
489
|
+
const siDevice = new SiDevice('handlesDeviceFailingToSend', {
|
|
490
|
+
driver: mockDriver({
|
|
491
|
+
send: () => Promise.reject(new Error('test'))
|
|
492
|
+
})
|
|
493
|
+
});
|
|
494
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
495
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
496
|
+
expect(muxer instanceof SiTargetMultiplexer).toBe(true);
|
|
497
|
+
|
|
498
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
499
|
+
const timeState = { timedOut: false };
|
|
500
|
+
muxer.sendMessageToLatestTarget(randomMessage, 1, 1).catch(() => {
|
|
501
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
502
|
+
timeState.timedOut = true;
|
|
503
|
+
});
|
|
504
|
+
await testUtils.advanceTimersByTime(0);
|
|
505
|
+
expect(timeState).toEqual({ timedOut: false });
|
|
506
|
+
await testUtils.advanceTimersByTime(1);
|
|
507
|
+
expect(timeState).toEqual({ timedOut: true });
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
test('cannot send to unknown target', async () => {
|
|
511
|
+
const siDevice = new SiDevice('undefinedTarget', { driver: mockDriver({}) });
|
|
512
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
513
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
514
|
+
muxer.latestTarget = SiTargetMultiplexerTarget.Direct;
|
|
515
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
516
|
+
const timeState = { setToUnknownFailed: false };
|
|
517
|
+
muxer.sendMessage(SiTargetMultiplexerTarget.Unknown, randomMessage, 1, 1).catch(() => {
|
|
518
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
519
|
+
timeState.setToUnknownFailed = true;
|
|
520
|
+
});
|
|
521
|
+
await testUtils.advanceTimersByTime(0);
|
|
522
|
+
expect(timeState).toEqual({ setToUnknownFailed: true });
|
|
523
|
+
});
|
|
524
|
+
test('cannot send to switching target', async () => {
|
|
525
|
+
const siDevice = new SiDevice('switchingTarget', { driver: mockDriver({}) });
|
|
526
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
527
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
528
|
+
muxer.latestTarget = SiTargetMultiplexerTarget.Direct;
|
|
529
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
530
|
+
const timeState = { setToSwitchingFailed: false };
|
|
531
|
+
muxer.sendMessage(SiTargetMultiplexerTarget.Switching, randomMessage, 1, 1).catch(() => {
|
|
532
|
+
expect(muxer._test.sendQueue.length).toBe(0);
|
|
533
|
+
timeState.setToSwitchingFailed = true;
|
|
534
|
+
});
|
|
535
|
+
await testUtils.advanceTimersByTime(0);
|
|
536
|
+
expect(timeState).toEqual({ setToSwitchingFailed: true });
|
|
537
|
+
});
|
|
538
|
+
test('handles error switching target', async () => {
|
|
539
|
+
const siDevice = new SiDevice('errorSwitchingTarget', {
|
|
540
|
+
driver: mockDriver({
|
|
541
|
+
send: () => Promise.reject(new Error('test'))
|
|
542
|
+
})
|
|
543
|
+
});
|
|
544
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
545
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
546
|
+
muxer.latestTarget = SiTargetMultiplexerTarget.Direct;
|
|
547
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
548
|
+
const timeState = { setTargetFailed: false };
|
|
549
|
+
muxer.sendMessage(SiTargetMultiplexerTarget.Remote, randomMessage, 1, 1).catch(() => {
|
|
550
|
+
timeState.setTargetFailed = true;
|
|
551
|
+
});
|
|
552
|
+
await testUtils.nTimesAsync(2, () => testUtils.advanceTimersByTime(0));
|
|
553
|
+
expect(muxer.target).toEqual(SiTargetMultiplexerTarget.Unknown);
|
|
554
|
+
expect(timeState).toEqual({ setTargetFailed: true });
|
|
555
|
+
});
|
|
556
|
+
test('handles unclear target switch response', async () => {
|
|
557
|
+
const siDevice = new SiDevice('errorSwitchingTarget', {
|
|
558
|
+
driver: mockDriver({
|
|
559
|
+
send: () => {
|
|
560
|
+
setTimeout(() => {
|
|
561
|
+
siDevice.dispatchEvent(
|
|
562
|
+
'receive',
|
|
563
|
+
new SiDeviceReceiveEvent(
|
|
564
|
+
siDevice,
|
|
565
|
+
siProtocol.render({
|
|
566
|
+
command: proto.cmd.SET_MS,
|
|
567
|
+
parameters: [SiTargetMultiplexerTarget.Direct]
|
|
568
|
+
})
|
|
569
|
+
)
|
|
570
|
+
);
|
|
571
|
+
}, 0);
|
|
572
|
+
return Promise.resolve();
|
|
573
|
+
}
|
|
574
|
+
})
|
|
575
|
+
});
|
|
576
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
577
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
578
|
+
muxer.latestTarget = SiTargetMultiplexerTarget.Direct;
|
|
579
|
+
const randomMessage = testUtils.getRandomMessage({});
|
|
580
|
+
const timeState = { setTargetFailed: false };
|
|
581
|
+
muxer.sendMessage(SiTargetMultiplexerTarget.Remote, randomMessage, 1, 1).catch(() => {
|
|
582
|
+
timeState.setTargetFailed = true;
|
|
583
|
+
});
|
|
584
|
+
await testUtils.nTimesAsync(2, () => testUtils.advanceTimersByTime(0));
|
|
585
|
+
expect(muxer.target).toEqual(SiTargetMultiplexerTarget.Unknown);
|
|
586
|
+
expect(timeState).toEqual({ setTargetFailed: true });
|
|
587
|
+
});
|
|
588
|
+
test('handles direct device-initiated command', async () => {
|
|
589
|
+
const siDevice = new SiDevice('errorSwitchingTarget', {
|
|
590
|
+
driver: mockDriver({
|
|
591
|
+
send: () => Promise.reject(new Error('test'))
|
|
592
|
+
})
|
|
593
|
+
});
|
|
594
|
+
siDevice.setState(SiDeviceState.Opened);
|
|
595
|
+
const muxer = SiTargetMultiplexer.fromSiDevice(siDevice);
|
|
596
|
+
const deviceInitiatedMessage = siProtocol.render({
|
|
597
|
+
command: proto.cmd.SI5_DET,
|
|
598
|
+
parameters: [0x00, 0x0a, 0x00, 0x04, 0x19, 0x02]
|
|
599
|
+
});
|
|
600
|
+
siDevice.dispatchEvent('receive', new SiDeviceReceiveEvent(siDevice, deviceInitiatedMessage));
|
|
601
|
+
await testUtils.nTimesAsync(10, () => testUtils.advanceTimersByTime(1));
|
|
602
|
+
expect(muxer.target).toEqual(SiTargetMultiplexerTarget.Direct);
|
|
603
|
+
expect(muxer.latestTarget).toEqual(SiTargetMultiplexerTarget.Direct);
|
|
604
|
+
});
|
|
605
|
+
});
|