@onekeyfe/hd-core 1.2.0-alpha.97 → 1.2.0-alpha.99
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/__tests__/check-all-firmware-release-protocol-v2.test.ts +411 -86
- package/__tests__/check-firmware-release-protocol-v2.test.ts +199 -0
- package/__tests__/firmware-memory-host.test.ts +126 -0
- package/__tests__/firmware-update/device-update-bootloader.test.ts +14 -2
- package/__tests__/firmware-update/firmware-host-binding.test.ts +9 -0
- package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +573 -0
- package/__tests__/firmware-update/firmware-prepared-resource-archive.test.ts +150 -0
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +65 -2
- package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +80 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +293 -71
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +53 -1
- package/__tests__/firmware-update/firmware-update-prepared-resource-executors.test.ts +326 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +2 -2
- package/__tests__/protocol-v2-firmware-targets.test.ts +16 -0
- package/__tests__/protocol-v2-resources.test.ts +148 -232
- package/__tests__/protocol-v2.test.ts +1326 -510
- package/dist/api/CheckAllFirmwareRelease.d.ts +2 -3
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBLEFirmwareRelease.d.ts +3 -2
- package/dist/api/CheckBLEFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts +2 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/CheckFirmwareRelease.d.ts +3 -2
- package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +1 -0
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +11 -9
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts +1 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareMemoryHost.d.ts +22 -0
- package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +1 -0
- package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts +11 -0
- package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +48 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +7 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +0 -1
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/protocolV2Release.d.ts +33 -0
- package/dist/api/firmware/protocolV2Release.d.ts.map +1 -0
- package/dist/data-manager/DataManager.d.ts +4 -3
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/index.d.ts +108 -114
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1825 -1006
- package/dist/protocols/protocol-v2/resources.d.ts +10 -28
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +20 -8
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkBLEFirmwareRelease.d.ts +2 -13
- package/dist/types/api/checkBLEFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkBootloaderRelease.d.ts +2 -6
- package/dist/types/api/checkBootloaderRelease.d.ts.map +1 -1
- package/dist/types/api/checkFirmwareRelease.d.ts +2 -13
- package/dist/types/api/checkFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkFirmwareTypeAvailable.d.ts +2 -2
- package/dist/types/api/checkFirmwareTypeAvailable.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -1
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +4 -12
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +2 -2
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -1
- package/dist/types/settings.d.ts +35 -36
- package/dist/types/settings.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +113 -80
- package/src/api/CheckBLEFirmwareRelease.ts +37 -5
- package/src/api/CheckBootloaderRelease.ts +35 -3
- package/src/api/CheckFirmwareRelease.ts +35 -7
- package/src/api/FirmwareUpdateV2.ts +231 -138
- package/src/api/FirmwareUpdateV3.ts +101 -56
- package/src/api/FirmwareUpdateV4.ts +936 -408
- package/src/api/UploadPortfolio.ts +18 -0
- package/src/api/device/DeviceUpdateBootloader.ts +37 -11
- package/src/api/firmware/FirmwareHostBinding.ts +26 -3
- package/src/api/firmware/FirmwareMemoryHost.ts +143 -0
- package/src/api/firmware/FirmwarePreparedResourceArchive.ts +207 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +122 -73
- package/src/api/firmware/FirmwareUpdatePlan.ts +295 -122
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +49 -12
- package/src/api/firmware/protocolV2Release.ts +168 -0
- package/src/data-manager/DataManager.ts +35 -19
- package/src/index.ts +10 -0
- package/src/protocols/protocol-v2/resources.ts +157 -341
- package/src/types/api/checkAllFirmwareRelease.ts +27 -12
- package/src/types/api/checkBLEFirmwareRelease.ts +4 -13
- package/src/types/api/checkBootloaderRelease.ts +2 -6
- package/src/types/api/checkFirmwareRelease.ts +2 -13
- package/src/types/api/checkFirmwareTypeAvailable.ts +2 -2
- package/src/types/api/deviceUpdateBootloader.ts +1 -0
- package/src/types/api/export.ts +6 -1
- package/src/types/api/firmwareUpdate.ts +12 -17
- package/src/types/api/firmwareUpdatePlan.ts +2 -2
- package/src/types/settings.ts +35 -61
- package/src/utils/deviceFeaturesUtils.ts +2 -2
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
2
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
3
|
+
import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
4
|
+
import JSZip from 'jszip';
|
|
5
|
+
|
|
6
|
+
import FirmwareUpdateV2 from '../../src/api/FirmwareUpdateV2';
|
|
7
|
+
import FirmwareUpdateV3 from '../../src/api/FirmwareUpdateV3';
|
|
8
|
+
import { DataManager } from '../../src/data-manager';
|
|
9
|
+
import {
|
|
10
|
+
registerFirmwareUpdateHostBinding,
|
|
11
|
+
unregisterFirmwareUpdateHostBinding,
|
|
12
|
+
} from '../../src/api/firmware/FirmwareHostBinding';
|
|
13
|
+
import { prepareFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePreparedPlan';
|
|
14
|
+
import { digestFirmwareUpdateContract } from '../../src/api/firmware/FirmwareUpdatePlan';
|
|
15
|
+
import {
|
|
16
|
+
updateResourcesFromSources,
|
|
17
|
+
uploadFirmwareFromSource,
|
|
18
|
+
} from '../../src/api/firmware/uploadFirmware';
|
|
19
|
+
import * as utils from '../../src/utils';
|
|
20
|
+
|
|
21
|
+
import type {
|
|
22
|
+
FirmwareArtifactReader,
|
|
23
|
+
FirmwareArtifactReference,
|
|
24
|
+
} from '../../src/types/api/firmwareUpdate';
|
|
25
|
+
import type { FirmwareUpdatePlan } from '../../src/types/api/firmwareUpdatePlan';
|
|
26
|
+
|
|
27
|
+
jest.mock('../../src/data/config', () => ({
|
|
28
|
+
getSDKVersion: jest.fn(() => '1.0.0'),
|
|
29
|
+
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
jest.mock('../../src/api/firmware/getBinary', () => ({
|
|
33
|
+
getBinary: jest.fn(),
|
|
34
|
+
getInfo: jest.fn(),
|
|
35
|
+
getSysResourceBinary: jest.fn(),
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
jest.mock('../../src/api/firmware/uploadFirmware', () => ({
|
|
39
|
+
updateResources: jest.fn(),
|
|
40
|
+
updateResourcesFromSources: jest.fn(),
|
|
41
|
+
uploadFirmwareFromSource: jest.fn(),
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
jest.mock('../../src/device/DevicePool', () => ({
|
|
45
|
+
DevicePool: {
|
|
46
|
+
clearDeviceCache: jest.fn(),
|
|
47
|
+
devicesCache: {},
|
|
48
|
+
},
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
const mockUpdateResourcesFromSources = updateResourcesFromSources as jest.MockedFunction<
|
|
52
|
+
typeof updateResourcesFromSources
|
|
53
|
+
>;
|
|
54
|
+
const mockUploadFirmwareFromSource = uploadFirmwareFromSource as jest.MockedFunction<
|
|
55
|
+
typeof uploadFirmwareFromSource
|
|
56
|
+
>;
|
|
57
|
+
|
|
58
|
+
const createReference = (artifactRef: string, binary: ArrayBuffer): FirmwareArtifactReference => ({
|
|
59
|
+
artifactRef,
|
|
60
|
+
size: binary.byteLength,
|
|
61
|
+
sha256: bytesToHex(sha256(new Uint8Array(binary))),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const createReader = (artifacts: Map<string, ArrayBuffer>): FirmwareArtifactReader => {
|
|
65
|
+
const opened = new Map<string, ArrayBuffer>();
|
|
66
|
+
let sequence = 0;
|
|
67
|
+
return {
|
|
68
|
+
open({ artifactRef }) {
|
|
69
|
+
const binary = artifacts.get(artifactRef);
|
|
70
|
+
if (!binary) throw new Error(`missing artifact: ${artifactRef}`);
|
|
71
|
+
sequence += 1;
|
|
72
|
+
const readerId = `reader-${sequence}`;
|
|
73
|
+
opened.set(readerId, binary);
|
|
74
|
+
return Promise.resolve({ readerId, size: binary.byteLength });
|
|
75
|
+
},
|
|
76
|
+
read({ readerId, offset, length }) {
|
|
77
|
+
const binary = opened.get(readerId);
|
|
78
|
+
if (!binary) throw new Error(`missing reader: ${readerId}`);
|
|
79
|
+
const data = binary.slice(offset, offset + length);
|
|
80
|
+
return Promise.resolve({
|
|
81
|
+
data,
|
|
82
|
+
bytesRead: data.byteLength,
|
|
83
|
+
eof: offset + length === binary.byteLength,
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
close({ readerId }) {
|
|
87
|
+
opened.delete(readerId);
|
|
88
|
+
return Promise.resolve();
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const createPreparedPlan = async (
|
|
94
|
+
executor: 'v2' | 'v3',
|
|
95
|
+
componentTarget: 'firmware' | 'ble' = 'firmware'
|
|
96
|
+
) => {
|
|
97
|
+
const firmwareBinary = Uint8Array.from([5, 6, 7, 8]).buffer;
|
|
98
|
+
const resourceBinary = Uint8Array.from([1, 2, 3, 4]).buffer;
|
|
99
|
+
const zip = new JSZip();
|
|
100
|
+
zip.file('images/logo.bin', resourceBinary);
|
|
101
|
+
const archiveBinary = await zip.generateAsync({ type: 'arraybuffer' });
|
|
102
|
+
const firmwareArtifact = createReference('firmware-artifact', firmwareBinary);
|
|
103
|
+
const archiveArtifact = createReference('resource-archive', archiveBinary);
|
|
104
|
+
const resourceArtifact = createReference('resource-entry', resourceBinary);
|
|
105
|
+
const planWithoutDigest: Omit<FirmwareUpdatePlan, 'planDigest'> = {
|
|
106
|
+
schemaVersion: 2,
|
|
107
|
+
executor,
|
|
108
|
+
deviceIdentity: executor === 'v2' ? 'touch-device' : 'pro-device',
|
|
109
|
+
deviceModel: String(executor === 'v2' ? EDeviceType.Touch : EDeviceType.Pro),
|
|
110
|
+
firmwareType: EFirmwareType.Universal,
|
|
111
|
+
platform: 'desktop',
|
|
112
|
+
artifacts: [
|
|
113
|
+
{
|
|
114
|
+
artifactId: componentTarget,
|
|
115
|
+
role: componentTarget,
|
|
116
|
+
target: componentTarget,
|
|
117
|
+
url: `https://firmware.onekey.so/${componentTarget}.bin`,
|
|
118
|
+
container: 'raw',
|
|
119
|
+
expectedSize: firmwareArtifact.size,
|
|
120
|
+
expectedSha256: firmwareArtifact.sha256,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
artifactId: 'resource',
|
|
124
|
+
role: 'resource',
|
|
125
|
+
target: 'resource',
|
|
126
|
+
url: 'https://firmware.onekey.so/resource.zip',
|
|
127
|
+
container: 'zip',
|
|
128
|
+
expectedSize: archiveArtifact.size,
|
|
129
|
+
expectedSha256: archiveArtifact.sha256,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
targetsToUpdate: [componentTarget, 'resource'],
|
|
133
|
+
};
|
|
134
|
+
const plan: FirmwareUpdatePlan = {
|
|
135
|
+
...planWithoutDigest,
|
|
136
|
+
planDigest: digestFirmwareUpdateContract(planWithoutDigest),
|
|
137
|
+
};
|
|
138
|
+
const preparedPlan = prepareFirmwareUpdatePlan({
|
|
139
|
+
plan,
|
|
140
|
+
leaseRef: `${executor}-resource-executor`,
|
|
141
|
+
artifacts: [
|
|
142
|
+
{ artifactId: componentTarget, artifact: firmwareArtifact },
|
|
143
|
+
{
|
|
144
|
+
artifactId: 'resource',
|
|
145
|
+
artifact: archiveArtifact,
|
|
146
|
+
materializedEntries: [{ entryName: 'images/logo.bin', artifact: resourceArtifact }],
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
});
|
|
150
|
+
return {
|
|
151
|
+
firmwareArtifact,
|
|
152
|
+
firmwareBinary,
|
|
153
|
+
archiveArtifact,
|
|
154
|
+
archiveBinary,
|
|
155
|
+
resourceBinary,
|
|
156
|
+
preparedPlan,
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
describe('prepared resource executors', () => {
|
|
161
|
+
afterEach(() => {
|
|
162
|
+
unregisterFirmwareUpdateHostBinding();
|
|
163
|
+
jest.restoreAllMocks();
|
|
164
|
+
jest.clearAllMocks();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('FirmwareUpdateV3 derives resource bytes from the approved ZIP without duplicate entries', async () => {
|
|
168
|
+
const prepared = await createPreparedPlan('v3');
|
|
169
|
+
const artifactReader = createReader(
|
|
170
|
+
new Map([
|
|
171
|
+
[prepared.firmwareArtifact.artifactRef, prepared.firmwareBinary],
|
|
172
|
+
[prepared.archiveArtifact.artifactRef, prepared.archiveBinary],
|
|
173
|
+
])
|
|
174
|
+
);
|
|
175
|
+
const hostBindingGeneration = registerFirmwareUpdateHostBinding({
|
|
176
|
+
preparedPlanDigest: prepared.preparedPlan.preparedPlanDigest,
|
|
177
|
+
artifactReader,
|
|
178
|
+
});
|
|
179
|
+
const method = new FirmwareUpdateV3({
|
|
180
|
+
id: 1,
|
|
181
|
+
payload: {
|
|
182
|
+
method: 'firmwareUpdateV3',
|
|
183
|
+
platform: 'desktop',
|
|
184
|
+
preparedPlan: prepared.preparedPlan,
|
|
185
|
+
hostBindingGeneration,
|
|
186
|
+
artifacts: { firmware: prepared.firmwareArtifact },
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
method.init();
|
|
190
|
+
|
|
191
|
+
const result = await (method as any).prepareResourceInput(EFirmwareType.Universal);
|
|
192
|
+
expect(result.resourceEntries).toHaveLength(1);
|
|
193
|
+
expect(result.resourceEntries[0].entryName).toBe('logo.bin');
|
|
194
|
+
await expect(result.resourceEntries[0].source.readAt(0, 4)).resolves.toEqual(
|
|
195
|
+
prepared.resourceBinary
|
|
196
|
+
);
|
|
197
|
+
await (method as any).closeArtifactSources();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('FirmwareUpdateV2 executes prepared resources without a live release record', async () => {
|
|
201
|
+
const prepared = await createPreparedPlan('v2');
|
|
202
|
+
const artifactReader = createReader(
|
|
203
|
+
new Map([
|
|
204
|
+
[prepared.firmwareArtifact.artifactRef, prepared.firmwareBinary],
|
|
205
|
+
[prepared.archiveArtifact.artifactRef, prepared.archiveBinary],
|
|
206
|
+
])
|
|
207
|
+
);
|
|
208
|
+
const hostBindingGeneration = registerFirmwareUpdateHostBinding({
|
|
209
|
+
preparedPlanDigest: prepared.preparedPlan.preparedPlanDigest,
|
|
210
|
+
artifactReader,
|
|
211
|
+
});
|
|
212
|
+
const method = new FirmwareUpdateV2({
|
|
213
|
+
id: 1,
|
|
214
|
+
payload: {
|
|
215
|
+
method: 'firmwareUpdateV2',
|
|
216
|
+
connectId: 'touch-connect-id',
|
|
217
|
+
platform: 'desktop',
|
|
218
|
+
updateType: 'firmware',
|
|
219
|
+
artifact: prepared.firmwareArtifact,
|
|
220
|
+
preparedPlan: prepared.preparedPlan,
|
|
221
|
+
hostBindingGeneration,
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
method.init();
|
|
225
|
+
|
|
226
|
+
const typedCall = jest.fn().mockResolvedValue({ type: 'Success' });
|
|
227
|
+
const commands = { typedCall, checkDisposed: jest.fn(), disposed: false };
|
|
228
|
+
method.device = {
|
|
229
|
+
features: {
|
|
230
|
+
deviceType: EDeviceType.Touch,
|
|
231
|
+
serialNo: 'touch-device',
|
|
232
|
+
firmwareVersion: '3.2.0',
|
|
233
|
+
bootloaderVersion: '2.8.0',
|
|
234
|
+
},
|
|
235
|
+
commands,
|
|
236
|
+
getCommands: () => commands,
|
|
237
|
+
getCurrentDeviceType: () => EDeviceType.Touch,
|
|
238
|
+
getCurrentFirmwareType: () => EFirmwareType.Universal,
|
|
239
|
+
getCurrentFirmwareVersionString: () => '3.2.0',
|
|
240
|
+
getCurrentBootloaderVersionString: () => '2.8.0',
|
|
241
|
+
getCurrentSerialNo: () => 'touch-device',
|
|
242
|
+
isBootloader: () => false,
|
|
243
|
+
isProtocolV2: () => false,
|
|
244
|
+
acquire: jest.fn().mockResolvedValue(undefined),
|
|
245
|
+
toMessageObject: jest.fn(() => ({})),
|
|
246
|
+
} as any;
|
|
247
|
+
method.postMessage = jest.fn();
|
|
248
|
+
jest.spyOn(method, 'checkDeviceToBootloader').mockImplementation(() => {
|
|
249
|
+
method.checkPromise = { promise: Promise.resolve(true) } as any;
|
|
250
|
+
});
|
|
251
|
+
jest.spyOn(utils, 'wait').mockResolvedValue(undefined);
|
|
252
|
+
const liveReleaseSpy = jest
|
|
253
|
+
.spyOn(DataManager, 'getSysResourcesLatestRelease')
|
|
254
|
+
.mockReturnValue(undefined);
|
|
255
|
+
mockUpdateResourcesFromSources.mockImplementation(async (_call, _post, _device, entries) => {
|
|
256
|
+
expect(entries).toHaveLength(1);
|
|
257
|
+
expect(entries[0].entryName).toBe('logo.bin');
|
|
258
|
+
await expect(entries[0].source.readAt(0, 4)).resolves.toEqual(prepared.resourceBinary);
|
|
259
|
+
return true;
|
|
260
|
+
});
|
|
261
|
+
mockUploadFirmwareFromSource.mockResolvedValue({ success: true } as any);
|
|
262
|
+
|
|
263
|
+
await expect(method.run()).resolves.toEqual({ success: true });
|
|
264
|
+
expect(liveReleaseSpy).not.toHaveBeenCalled();
|
|
265
|
+
expect(mockUpdateResourcesFromSources).toHaveBeenCalledTimes(1);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test('FirmwareUpdateV2 does not replay a plan resource during its BLE component phase', async () => {
|
|
269
|
+
const prepared = await createPreparedPlan('v2', 'ble');
|
|
270
|
+
const artifactReader = createReader(
|
|
271
|
+
new Map([
|
|
272
|
+
[prepared.firmwareArtifact.artifactRef, prepared.firmwareBinary],
|
|
273
|
+
[prepared.archiveArtifact.artifactRef, prepared.archiveBinary],
|
|
274
|
+
])
|
|
275
|
+
);
|
|
276
|
+
const hostBindingGeneration = registerFirmwareUpdateHostBinding({
|
|
277
|
+
preparedPlanDigest: prepared.preparedPlan.preparedPlanDigest,
|
|
278
|
+
artifactReader,
|
|
279
|
+
});
|
|
280
|
+
const method = new FirmwareUpdateV2({
|
|
281
|
+
id: 1,
|
|
282
|
+
payload: {
|
|
283
|
+
method: 'firmwareUpdateV2',
|
|
284
|
+
connectId: 'touch-connect-id',
|
|
285
|
+
platform: 'desktop',
|
|
286
|
+
updateType: 'ble',
|
|
287
|
+
preparedPlan: prepared.preparedPlan,
|
|
288
|
+
hostBindingGeneration,
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
method.init();
|
|
292
|
+
|
|
293
|
+
const typedCall = jest.fn().mockResolvedValue({ type: 'Success' });
|
|
294
|
+
const commands = { typedCall, checkDisposed: jest.fn(), disposed: false };
|
|
295
|
+
method.device = {
|
|
296
|
+
features: {
|
|
297
|
+
deviceType: EDeviceType.Touch,
|
|
298
|
+
serialNo: 'touch-device',
|
|
299
|
+
firmwareVersion: '3.2.0',
|
|
300
|
+
bootloaderVersion: '2.8.0',
|
|
301
|
+
},
|
|
302
|
+
commands,
|
|
303
|
+
getCommands: () => commands,
|
|
304
|
+
getCurrentDeviceType: () => EDeviceType.Touch,
|
|
305
|
+
getCurrentFirmwareType: () => EFirmwareType.Universal,
|
|
306
|
+
getCurrentFirmwareVersionString: () => '3.2.0',
|
|
307
|
+
getCurrentBootloaderVersionString: () => '2.8.0',
|
|
308
|
+
getCurrentSerialNo: () => 'touch-device',
|
|
309
|
+
isBootloader: () => false,
|
|
310
|
+
isProtocolV2: () => false,
|
|
311
|
+
acquire: jest.fn().mockResolvedValue(undefined),
|
|
312
|
+
toMessageObject: jest.fn(() => ({})),
|
|
313
|
+
} as any;
|
|
314
|
+
method.postMessage = jest.fn();
|
|
315
|
+
jest.spyOn(method, 'checkDeviceToBootloader').mockImplementation(() => {
|
|
316
|
+
method.checkPromise = { promise: Promise.resolve(true) } as any;
|
|
317
|
+
});
|
|
318
|
+
jest.spyOn(utils, 'wait').mockResolvedValue(undefined);
|
|
319
|
+
const liveReleaseSpy = jest.spyOn(DataManager, 'getSysResourcesLatestRelease');
|
|
320
|
+
mockUploadFirmwareFromSource.mockResolvedValue({ success: true } as any);
|
|
321
|
+
|
|
322
|
+
await expect(method.run()).resolves.toEqual({ success: true });
|
|
323
|
+
expect(liveReleaseSpy).not.toHaveBeenCalled();
|
|
324
|
+
expect(mockUpdateResourcesFromSources).not.toHaveBeenCalled();
|
|
325
|
+
});
|
|
326
|
+
});
|
|
@@ -151,7 +151,7 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
|
|
|
151
151
|
jest.restoreAllMocks();
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
it('rejects
|
|
154
|
+
it('rejects a prepared plan combined with legacy inputs during initialization', () => {
|
|
155
155
|
const method = new FirmwareUpdateV2({
|
|
156
156
|
id: 1,
|
|
157
157
|
payload: {
|
|
@@ -173,7 +173,7 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
|
|
|
173
173
|
expect(() => method.init()).toThrow(
|
|
174
174
|
expect.objectContaining({
|
|
175
175
|
errorCode: HardwareErrorCode.CallMethodInvalidParameter,
|
|
176
|
-
message: '
|
|
176
|
+
message: 'Prepared firmware plans cannot be combined with legacy firmware inputs',
|
|
177
177
|
})
|
|
178
178
|
);
|
|
179
179
|
});
|
|
@@ -57,6 +57,22 @@ describe('Protocol V2 firmware target contract', () => {
|
|
|
57
57
|
).toThrow('Neo only supports SE01 and SE02; unsupported firmware targets: se03, se04');
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
+
test('ignores unselected SE binaries when the caller supplied a target subset', () => {
|
|
61
|
+
const params = {
|
|
62
|
+
platform: 'web' as const,
|
|
63
|
+
targetsToUpdate: ['app_v1'] as Array<'app_v1'>,
|
|
64
|
+
se03Binary: new ArrayBuffer(1),
|
|
65
|
+
se04Binary: new ArrayBuffer(1),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
expect(() =>
|
|
69
|
+
assertProtocolV2FirmwareTargetsSupported(EDeviceType.Neo, params, true)
|
|
70
|
+
).not.toThrow();
|
|
71
|
+
expect(() => assertProtocolV2FirmwareTargetsSupported(EDeviceType.Neo, params)).toThrow(
|
|
72
|
+
'Neo only supports SE01 and SE02; unsupported firmware targets: se03, se04'
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
60
76
|
test('keeps all four SE firmware targets available on Pro2', () => {
|
|
61
77
|
expect(() =>
|
|
62
78
|
assertProtocolV2FirmwareTargetsSupported(EDeviceType.Pro2, {
|