@onekeyfe/hd-core 1.2.0-alpha.97 → 1.2.0-alpha.98
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 +404 -84
- package/__tests__/check-firmware-release-protocol-v2.test.ts +199 -0
- package/__tests__/firmware-memory-host.test.ts +112 -0
- package/__tests__/firmware-update/device-update-bootloader.test.ts +13 -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-plan.test.ts +232 -70
- 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-resources.test.ts +148 -232
- package/__tests__/protocol-v2.test.ts +1236 -516
- 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 +8 -8
- 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/FirmwareUpdatePlan.d.ts +48 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +6 -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 +1633 -967
- 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 +108 -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 +108 -73
- package/src/api/FirmwareUpdateV3.ts +101 -56
- package/src/api/FirmwareUpdateV4.ts +885 -403
- package/src/api/UploadPortfolio.ts +18 -0
- package/src/api/device/DeviceUpdateBootloader.ts +37 -11
- package/src/api/firmware/FirmwareHostBinding.ts +16 -3
- package/src/api/firmware/FirmwareMemoryHost.ts +142 -0
- package/src/api/firmware/FirmwarePreparedResourceArchive.ts +207 -0
- package/src/api/firmware/FirmwareUpdatePlan.ts +282 -122
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +27 -3
- 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
|
@@ -5,7 +5,6 @@ import CheckAllFirmwareRelease, {
|
|
|
5
5
|
} from '../src/api/CheckAllFirmwareRelease';
|
|
6
6
|
import { DataManager } from '../src/data-manager';
|
|
7
7
|
import { createCoreApi } from '../src/inject';
|
|
8
|
-
import { PROTOCOL_V2_RESOURCE_DEVICE_PATHS } from '../src/protocols/protocol-v2/resources';
|
|
9
8
|
|
|
10
9
|
import type { CoreApi } from '../src/types/api';
|
|
11
10
|
import type { DeviceStateVersions, IFirmwareReleaseInfo } from '../src/types';
|
|
@@ -26,6 +25,11 @@ const currentVersions: DeviceStateVersions = {
|
|
|
26
25
|
se04: '1.0.0',
|
|
27
26
|
};
|
|
28
27
|
|
|
28
|
+
const validComponentIntegrity = {
|
|
29
|
+
expectedSize: 1024,
|
|
30
|
+
fingerprint: '1'.repeat(64),
|
|
31
|
+
};
|
|
32
|
+
|
|
29
33
|
const release: IFirmwareReleaseInfo = {
|
|
30
34
|
required: true,
|
|
31
35
|
version: [2, 0, 0],
|
|
@@ -41,21 +45,25 @@ const release: IFirmwareReleaseInfo = {
|
|
|
41
45
|
target: 'BOOTLOADER',
|
|
42
46
|
url: 'https://example.com/bootloader.bin',
|
|
43
47
|
version: [1, 1, 0],
|
|
48
|
+
...validComponentIntegrity,
|
|
44
49
|
},
|
|
45
50
|
applicationP1: {
|
|
46
51
|
target: 'APPLICATION_P1',
|
|
47
52
|
url: 'https://example.com/application-p1.bin',
|
|
48
53
|
version: [2, 0, 0],
|
|
54
|
+
...validComponentIntegrity,
|
|
49
55
|
},
|
|
50
56
|
se02: {
|
|
51
57
|
target: 'SE02',
|
|
52
58
|
url: 'https://example.com/se02.bin',
|
|
53
59
|
version: [2, 0, 0],
|
|
60
|
+
...validComponentIntegrity,
|
|
54
61
|
},
|
|
55
62
|
se03: {
|
|
56
63
|
target: 'SE03',
|
|
57
64
|
url: 'https://example.com/se03.bin',
|
|
58
65
|
version: [1, 0, 0],
|
|
66
|
+
...validComponentIntegrity,
|
|
59
67
|
},
|
|
60
68
|
romloader: {
|
|
61
69
|
target: 'ROMLOADER',
|
|
@@ -63,77 +71,12 @@ const release: IFirmwareReleaseInfo = {
|
|
|
63
71
|
version: [2, 0, 0],
|
|
64
72
|
},
|
|
65
73
|
},
|
|
66
|
-
resourceBundles: [
|
|
67
|
-
{
|
|
68
|
-
name: 'images',
|
|
69
|
-
url: 'https://example.com/images.okpkg',
|
|
70
|
-
devicePath: 'vol0:/bundles/images/images.okpkg',
|
|
71
|
-
version: [1, 0, 0],
|
|
72
|
-
},
|
|
73
|
-
],
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
size: 0x52a0 + index + 1,
|
|
81
|
-
fileHash: 'a'.repeat(64),
|
|
82
|
-
headerHash: index.toString(16).padStart(128, '0'),
|
|
83
|
-
})
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const createFilesystemTypedCall = (missingAll = false) => {
|
|
87
|
-
const resourceByPath = new Map(
|
|
88
|
-
stableResources.map(resource => [
|
|
89
|
-
PROTOCOL_V2_RESOURCE_DEVICE_PATHS[
|
|
90
|
-
resource.type as keyof typeof PROTOCOL_V2_RESOURCE_DEVICE_PATHS
|
|
91
|
-
],
|
|
92
|
-
resource,
|
|
93
|
-
])
|
|
94
|
-
);
|
|
95
|
-
return jest.fn((requestType: string, _responseType: string, payload: Record<string, any>) => {
|
|
96
|
-
if (requestType === 'ResourceInventoryGet') {
|
|
97
|
-
throw new Error('ResourceInventoryGet is unavailable on released firmware');
|
|
98
|
-
}
|
|
99
|
-
if (requestType === 'FilesystemPathInfoQuery') {
|
|
100
|
-
const resource = resourceByPath.get(payload.path);
|
|
101
|
-
return {
|
|
102
|
-
message: {
|
|
103
|
-
exist: Boolean(resource) && !missingAll,
|
|
104
|
-
directory: false,
|
|
105
|
-
size: missingAll ? 0 : resource?.size,
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
if (requestType === 'FilesystemFileRead') {
|
|
110
|
-
const resource = resourceByPath.get(payload.file.path);
|
|
111
|
-
if (!resource || missingAll) throw new Error('missing resource');
|
|
112
|
-
const header = new Uint8Array(0x52a0);
|
|
113
|
-
const view = new DataView(header.buffer);
|
|
114
|
-
'OKPP'.split('').forEach((char, index) => {
|
|
115
|
-
header[index] = char.charCodeAt(0);
|
|
116
|
-
});
|
|
117
|
-
'RESC'.split('').forEach((char, index) => {
|
|
118
|
-
header[0x08 + index] = char.charCodeAt(0);
|
|
119
|
-
});
|
|
120
|
-
view.setUint32(0x0c, header.byteLength, true);
|
|
121
|
-
for (let index = 0; index < resource.headerHash.length / 2; index++) {
|
|
122
|
-
header[0x240 + index] = Number.parseInt(
|
|
123
|
-
resource.headerHash.slice(index * 2, index * 2 + 2),
|
|
124
|
-
16
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
const offset = Number(payload.file.offset);
|
|
128
|
-
const chunkLength = Number(payload.chunk_len);
|
|
129
|
-
return {
|
|
130
|
-
message: {
|
|
131
|
-
data: header.slice(offset, offset + chunkLength),
|
|
132
|
-
},
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
throw new Error(`Unexpected request: ${requestType}`);
|
|
136
|
-
});
|
|
76
|
+
const resourceSource = {
|
|
77
|
+
archiveUrl: 'https://example.com/pro2-resource/pro2-resource.zip',
|
|
78
|
+
archiveSha256: 'a'.repeat(64),
|
|
79
|
+
archiveSize: 16_815_479,
|
|
137
80
|
};
|
|
138
81
|
|
|
139
82
|
describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
@@ -210,7 +153,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
210
153
|
test('detects same-version package hotfixes by P1 and P2 payload hash', () => {
|
|
211
154
|
const packageSet: IFirmwareReleaseInfo = {
|
|
212
155
|
...release,
|
|
213
|
-
resourceBundles: undefined,
|
|
214
156
|
installOrder: ['applicationP1', 'applicationP2'],
|
|
215
157
|
components: {
|
|
216
158
|
applicationP1: {
|
|
@@ -261,7 +203,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
261
203
|
const packageSet: IFirmwareReleaseInfo = {
|
|
262
204
|
...release,
|
|
263
205
|
required: false,
|
|
264
|
-
resourceBundles: undefined,
|
|
265
206
|
installOrder: ['applicationP1'],
|
|
266
207
|
components: {
|
|
267
208
|
applicationP1: {
|
|
@@ -292,7 +233,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
292
233
|
const packageSet: IFirmwareReleaseInfo = {
|
|
293
234
|
...release,
|
|
294
235
|
required: false,
|
|
295
|
-
resourceBundles: undefined,
|
|
296
236
|
installOrder: ['applicationP1'],
|
|
297
237
|
components: {
|
|
298
238
|
applicationP1: {
|
|
@@ -323,7 +263,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
323
263
|
test('updates both application packages when normal mode only reports P1', () => {
|
|
324
264
|
const packageSet: IFirmwareReleaseInfo = {
|
|
325
265
|
...release,
|
|
326
|
-
resourceBundles: undefined,
|
|
327
266
|
installOrder: ['applicationP1', 'applicationP2'],
|
|
328
267
|
components: {
|
|
329
268
|
applicationP1: {
|
|
@@ -370,7 +309,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
370
309
|
status: { mode: 'normal' },
|
|
371
310
|
versions: currentVersions,
|
|
372
311
|
});
|
|
373
|
-
const typedCall =
|
|
312
|
+
const typedCall = jest.fn();
|
|
374
313
|
method.device = {
|
|
375
314
|
isProtocolV2: () => true,
|
|
376
315
|
features: {
|
|
@@ -381,14 +320,24 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
381
320
|
getCommands: () => ({ typedCall }),
|
|
382
321
|
} as unknown as CheckAllFirmwareRelease['device'];
|
|
383
322
|
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
384
|
-
jest.spyOn(DataManager, '
|
|
323
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
385
324
|
|
|
386
325
|
await expect(method.run()).resolves.toMatchObject({
|
|
387
326
|
protocol: 'V2',
|
|
388
327
|
deviceType: 'pro2',
|
|
389
328
|
status: 'required',
|
|
390
329
|
resourceStatus: 'unknown',
|
|
330
|
+
resourceArchive: resourceSource,
|
|
391
331
|
targetsToUpdate: ['boot', 'app_v1'],
|
|
332
|
+
firmwareUpdatePlan: {
|
|
333
|
+
executor: 'v4',
|
|
334
|
+
platform: 'web',
|
|
335
|
+
artifacts: [
|
|
336
|
+
{ artifactId: 'component:boot', target: 'boot' },
|
|
337
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
338
|
+
],
|
|
339
|
+
targetsToUpdate: ['boot', 'app_v1'],
|
|
340
|
+
},
|
|
392
341
|
firmware: {
|
|
393
342
|
status: 'required',
|
|
394
343
|
},
|
|
@@ -400,11 +349,337 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
400
349
|
expect(method.getSupportedProtocols()).toEqual(['V1', 'V2']);
|
|
401
350
|
});
|
|
402
351
|
|
|
352
|
+
test('preserves platform and forced firmware targets in the Protocol V2 prepared plan', async () => {
|
|
353
|
+
const method = new CheckAllFirmwareRelease({
|
|
354
|
+
id: 1,
|
|
355
|
+
payload: {
|
|
356
|
+
method: 'checkAllFirmwareRelease',
|
|
357
|
+
firmwareType: EFirmwareType.Universal,
|
|
358
|
+
platform: 'native',
|
|
359
|
+
forceUpdateTargets: ['firmware'],
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
method.init();
|
|
363
|
+
method.device = {
|
|
364
|
+
isProtocolV2: () => true,
|
|
365
|
+
features: {
|
|
366
|
+
deviceType: 'pro2',
|
|
367
|
+
serialNo: 'pro2-device-id',
|
|
368
|
+
firmwareVersion: '1.0.0',
|
|
369
|
+
},
|
|
370
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
371
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
372
|
+
status: { mode: 'normal' },
|
|
373
|
+
versions: currentVersions,
|
|
374
|
+
}),
|
|
375
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
376
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
377
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
378
|
+
|
|
379
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
380
|
+
targetsToUpdate: ['boot', 'app_v1', 'se02', 'se03'],
|
|
381
|
+
firmwareUpdatePlan: {
|
|
382
|
+
executor: 'v4',
|
|
383
|
+
deviceIdentity: 'pro2-device-id',
|
|
384
|
+
platform: 'native',
|
|
385
|
+
artifacts: [
|
|
386
|
+
{ artifactId: 'component:boot', target: 'boot' },
|
|
387
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
388
|
+
{ artifactId: 'component:se02', target: 'se02' },
|
|
389
|
+
{ artifactId: 'component:se03', target: 'se03' },
|
|
390
|
+
],
|
|
391
|
+
targetsToUpdate: ['boot', 'app_v1', 'se02', 'se03'],
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test('includes exact Protocol V2 developer force targets in the prepared plan', async () => {
|
|
397
|
+
const currentRelease: IFirmwareReleaseInfo = {
|
|
398
|
+
...release,
|
|
399
|
+
required: false,
|
|
400
|
+
version: [1, 0, 0],
|
|
401
|
+
installOrder: ['applicationP1', 'coprocessor'],
|
|
402
|
+
components: {
|
|
403
|
+
applicationP1: {
|
|
404
|
+
target: 'APPLICATION_P1',
|
|
405
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
406
|
+
version: [1, 0, 0],
|
|
407
|
+
...validComponentIntegrity,
|
|
408
|
+
},
|
|
409
|
+
coprocessor: {
|
|
410
|
+
target: 'COPROCESSOR',
|
|
411
|
+
url: 'https://example.com/coprocessor.okpkg',
|
|
412
|
+
version: [1, 0, 0],
|
|
413
|
+
...validComponentIntegrity,
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
const method = new CheckAllFirmwareRelease({
|
|
418
|
+
id: 1,
|
|
419
|
+
payload: {
|
|
420
|
+
method: 'checkAllFirmwareRelease',
|
|
421
|
+
platform: 'desktop',
|
|
422
|
+
protocolV2ForceUpdateTargets: ['app_v1', 'coprocessor'],
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
method.init();
|
|
426
|
+
method.device = {
|
|
427
|
+
isProtocolV2: () => true,
|
|
428
|
+
features: {
|
|
429
|
+
deviceType: 'pro2',
|
|
430
|
+
serialNo: 'pro2-device-id',
|
|
431
|
+
firmwareVersion: '1.0.0',
|
|
432
|
+
},
|
|
433
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
434
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
435
|
+
status: { mode: 'normal' },
|
|
436
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
437
|
+
}),
|
|
438
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
439
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
|
|
440
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
441
|
+
|
|
442
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
443
|
+
targetsToUpdate: ['app_v1', 'coprocessor'],
|
|
444
|
+
firmwareUpdatePlan: {
|
|
445
|
+
executor: 'v4',
|
|
446
|
+
platform: 'desktop',
|
|
447
|
+
artifacts: [
|
|
448
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
449
|
+
{ artifactId: 'component:coprocessor', target: 'coprocessor' },
|
|
450
|
+
],
|
|
451
|
+
targetsToUpdate: ['app_v1', 'coprocessor'],
|
|
452
|
+
},
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
test('builds a Desktop V4 prepared update without device identity', async () => {
|
|
457
|
+
const currentRelease: IFirmwareReleaseInfo = {
|
|
458
|
+
...release,
|
|
459
|
+
required: false,
|
|
460
|
+
version: [1, 0, 0],
|
|
461
|
+
installOrder: ['applicationP1'],
|
|
462
|
+
components: {
|
|
463
|
+
applicationP1: {
|
|
464
|
+
target: 'APPLICATION_P1',
|
|
465
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
466
|
+
version: [1, 0, 0],
|
|
467
|
+
...validComponentIntegrity,
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
};
|
|
471
|
+
const method = new CheckAllFirmwareRelease({
|
|
472
|
+
id: 1,
|
|
473
|
+
payload: {
|
|
474
|
+
method: 'checkAllFirmwareRelease',
|
|
475
|
+
platform: 'desktop',
|
|
476
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
method.init();
|
|
480
|
+
method.device = {
|
|
481
|
+
isProtocolV2: () => true,
|
|
482
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
483
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
484
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
485
|
+
status: { mode: 'normal' },
|
|
486
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
487
|
+
}),
|
|
488
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
489
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
|
|
490
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
491
|
+
|
|
492
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
493
|
+
firmwareUpdatePlan: {
|
|
494
|
+
executor: 'v4',
|
|
495
|
+
deviceIdentity: 'unavailable',
|
|
496
|
+
},
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
test('rejects Neo-only unsupported exact secure-element targets', async () => {
|
|
501
|
+
const neoRelease: IFirmwareReleaseInfo = {
|
|
502
|
+
...release,
|
|
503
|
+
required: false,
|
|
504
|
+
installOrder: ['se03'],
|
|
505
|
+
components: {
|
|
506
|
+
se03: {
|
|
507
|
+
target: 'SE03',
|
|
508
|
+
url: 'https://example.com/se03.okpkg',
|
|
509
|
+
version: [1, 0, 0],
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
};
|
|
513
|
+
const method = new CheckAllFirmwareRelease({
|
|
514
|
+
id: 1,
|
|
515
|
+
payload: {
|
|
516
|
+
method: 'checkAllFirmwareRelease',
|
|
517
|
+
protocolV2ForceUpdateTargets: ['se03'],
|
|
518
|
+
},
|
|
519
|
+
});
|
|
520
|
+
method.init();
|
|
521
|
+
method.device = {
|
|
522
|
+
isProtocolV2: () => true,
|
|
523
|
+
features: { deviceType: 'neo', firmwareVersion: '1.0.0' },
|
|
524
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
525
|
+
identity: { deviceType: 'neo', firmwareType: EFirmwareType.Universal },
|
|
526
|
+
status: { mode: 'normal' },
|
|
527
|
+
versions: currentVersions,
|
|
528
|
+
}),
|
|
529
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
530
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(neoRelease);
|
|
531
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
532
|
+
|
|
533
|
+
await expect(method.run()).rejects.toMatchObject({
|
|
534
|
+
params: { firmwareUpdateCode: 'FirmwarePlanInvalid' },
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
test('builds a V4 plan for Neo and excludes unsupported secure elements when forced', async () => {
|
|
539
|
+
const neoRelease: IFirmwareReleaseInfo = {
|
|
540
|
+
...release,
|
|
541
|
+
installOrder: ['se01', 'se02', 'se03', 'se04'],
|
|
542
|
+
components: {
|
|
543
|
+
se01: {
|
|
544
|
+
target: 'SE01',
|
|
545
|
+
url: 'https://example.com/se01.bin',
|
|
546
|
+
version: [1, 0, 0],
|
|
547
|
+
...validComponentIntegrity,
|
|
548
|
+
},
|
|
549
|
+
se02: {
|
|
550
|
+
target: 'SE02',
|
|
551
|
+
url: 'https://example.com/se02.bin',
|
|
552
|
+
version: [2, 0, 0],
|
|
553
|
+
...validComponentIntegrity,
|
|
554
|
+
},
|
|
555
|
+
se03: { target: 'SE03', url: 'https://example.com/se03.bin', version: [1, 0, 0] },
|
|
556
|
+
se04: { target: 'SE04', url: 'https://example.com/se04.bin', version: [1, 0, 0] },
|
|
557
|
+
},
|
|
558
|
+
};
|
|
559
|
+
const method = new CheckAllFirmwareRelease({
|
|
560
|
+
id: 1,
|
|
561
|
+
payload: {
|
|
562
|
+
method: 'checkAllFirmwareRelease',
|
|
563
|
+
platform: 'native',
|
|
564
|
+
forceUpdateTargets: ['firmware'],
|
|
565
|
+
},
|
|
566
|
+
});
|
|
567
|
+
method.init();
|
|
568
|
+
method.device = {
|
|
569
|
+
isProtocolV2: () => true,
|
|
570
|
+
features: {
|
|
571
|
+
deviceType: 'neo',
|
|
572
|
+
serialNo: 'neo-device-id',
|
|
573
|
+
firmwareVersion: '1.0.0',
|
|
574
|
+
},
|
|
575
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
576
|
+
identity: { deviceType: 'neo', firmwareType: EFirmwareType.Universal },
|
|
577
|
+
status: { mode: 'normal' },
|
|
578
|
+
versions: currentVersions,
|
|
579
|
+
}),
|
|
580
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
581
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(neoRelease);
|
|
582
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
583
|
+
|
|
584
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
585
|
+
targetsToUpdate: ['se01', 'se02'],
|
|
586
|
+
firmwareUpdatePlan: {
|
|
587
|
+
executor: 'v4',
|
|
588
|
+
deviceModel: 'neo',
|
|
589
|
+
platform: 'native',
|
|
590
|
+
targetsToUpdate: ['se01', 'se02'],
|
|
591
|
+
},
|
|
592
|
+
});
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
test('rejects a forced Protocol V2 resource target without a configured archive', async () => {
|
|
596
|
+
const method = new CheckAllFirmwareRelease({
|
|
597
|
+
id: 1,
|
|
598
|
+
payload: {
|
|
599
|
+
method: 'checkAllFirmwareRelease',
|
|
600
|
+
forceUpdateTargets: ['resource'],
|
|
601
|
+
},
|
|
602
|
+
});
|
|
603
|
+
method.init();
|
|
604
|
+
method.device = {
|
|
605
|
+
isProtocolV2: () => true,
|
|
606
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
607
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
608
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
609
|
+
status: { mode: 'normal' },
|
|
610
|
+
versions: currentVersions,
|
|
611
|
+
}),
|
|
612
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
613
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
614
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(undefined);
|
|
615
|
+
|
|
616
|
+
await expect(method.run()).rejects.toMatchObject({
|
|
617
|
+
params: { firmwareUpdateCode: 'FirmwarePlanInvalid' },
|
|
618
|
+
});
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
test('adds a Protocol V2 resource target only when explicitly forced', async () => {
|
|
622
|
+
const currentRelease: IFirmwareReleaseInfo = {
|
|
623
|
+
...release,
|
|
624
|
+
required: false,
|
|
625
|
+
installOrder: ['applicationP1'],
|
|
626
|
+
components: {
|
|
627
|
+
applicationP1: {
|
|
628
|
+
target: 'APPLICATION_P1',
|
|
629
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
630
|
+
version: [1, 0, 0],
|
|
631
|
+
},
|
|
632
|
+
},
|
|
633
|
+
};
|
|
634
|
+
const method = new CheckAllFirmwareRelease({
|
|
635
|
+
id: 1,
|
|
636
|
+
payload: {
|
|
637
|
+
method: 'checkAllFirmwareRelease',
|
|
638
|
+
platform: 'desktop',
|
|
639
|
+
protocolV2ForceUpdateTargets: ['resource'],
|
|
640
|
+
},
|
|
641
|
+
});
|
|
642
|
+
method.init();
|
|
643
|
+
method.device = {
|
|
644
|
+
isProtocolV2: () => true,
|
|
645
|
+
features: {
|
|
646
|
+
deviceType: 'pro2',
|
|
647
|
+
serialNo: 'pro2-device-id',
|
|
648
|
+
firmwareVersion: '1.0.0',
|
|
649
|
+
},
|
|
650
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
651
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
652
|
+
status: { mode: 'normal' },
|
|
653
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
654
|
+
}),
|
|
655
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
656
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
|
|
657
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
658
|
+
|
|
659
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
660
|
+
status: 'valid',
|
|
661
|
+
hasUpgrade: true,
|
|
662
|
+
targetsToUpdate: ['resource'],
|
|
663
|
+
firmwareUpdatePlan: {
|
|
664
|
+
executor: 'v4',
|
|
665
|
+
platform: 'desktop',
|
|
666
|
+
artifacts: [
|
|
667
|
+
{
|
|
668
|
+
artifactId: 'resource:archive',
|
|
669
|
+
target: 'resource',
|
|
670
|
+
role: 'resourceBundle',
|
|
671
|
+
container: 'zip',
|
|
672
|
+
},
|
|
673
|
+
],
|
|
674
|
+
targetsToUpdate: ['resource'],
|
|
675
|
+
},
|
|
676
|
+
});
|
|
677
|
+
});
|
|
678
|
+
|
|
403
679
|
test('requests and compares firmware hashes only when explicitly enabled', async () => {
|
|
404
680
|
const packageSet: IFirmwareReleaseInfo = {
|
|
405
681
|
...release,
|
|
406
682
|
required: false,
|
|
407
|
-
resourceBundles: undefined,
|
|
408
683
|
installOrder: ['applicationP1'],
|
|
409
684
|
components: {
|
|
410
685
|
applicationP1: {
|
|
@@ -437,7 +712,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
437
712
|
getCommands: () => ({ typedCall: jest.fn() }),
|
|
438
713
|
} as unknown as CheckAllFirmwareRelease['device'];
|
|
439
714
|
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(packageSet);
|
|
440
|
-
jest.spyOn(DataManager, '
|
|
715
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(undefined);
|
|
441
716
|
|
|
442
717
|
await expect(method.run()).resolves.toMatchObject({
|
|
443
718
|
status: 'outdated',
|
|
@@ -449,7 +724,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
449
724
|
});
|
|
450
725
|
|
|
451
726
|
test.each(['bootloader', 'romloader'] as const)(
|
|
452
|
-
'
|
|
727
|
+
'does not read vol0 resource inventory in %s mode',
|
|
453
728
|
async mode => {
|
|
454
729
|
const method = new CheckAllFirmwareRelease({
|
|
455
730
|
id: 1,
|
|
@@ -459,7 +734,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
459
734
|
},
|
|
460
735
|
});
|
|
461
736
|
method.init();
|
|
462
|
-
const typedCall =
|
|
737
|
+
const typedCall = jest.fn();
|
|
463
738
|
method.device = {
|
|
464
739
|
isProtocolV2: () => true,
|
|
465
740
|
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
@@ -471,18 +746,61 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
471
746
|
getCommands: () => ({ typedCall }),
|
|
472
747
|
} as unknown as CheckAllFirmwareRelease['device'];
|
|
473
748
|
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
474
|
-
jest.spyOn(DataManager, '
|
|
749
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
475
750
|
|
|
476
751
|
await expect(method.run()).resolves.toMatchObject({
|
|
477
752
|
protocol: 'V2',
|
|
478
|
-
resourceStatus: '
|
|
753
|
+
resourceStatus: 'unknown',
|
|
754
|
+
resourceArchive: resourceSource,
|
|
479
755
|
targetsToUpdate: ['boot', 'app_v1'],
|
|
480
756
|
});
|
|
481
|
-
expect(typedCall.
|
|
482
|
-
expect(typedCall.mock.calls.some(call => call[0] === 'FilesystemFileRead')).toBe(true);
|
|
757
|
+
expect(typedCall).not.toHaveBeenCalled();
|
|
483
758
|
}
|
|
484
759
|
);
|
|
485
760
|
|
|
761
|
+
test('exposes resource archive availability without reporting an unconfirmed update', async () => {
|
|
762
|
+
const currentRelease: IFirmwareReleaseInfo = {
|
|
763
|
+
...release,
|
|
764
|
+
required: false,
|
|
765
|
+
installOrder: ['applicationP1'],
|
|
766
|
+
components: {
|
|
767
|
+
applicationP1: {
|
|
768
|
+
target: 'APPLICATION_P1',
|
|
769
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
770
|
+
version: [1, 0, 0],
|
|
771
|
+
},
|
|
772
|
+
},
|
|
773
|
+
};
|
|
774
|
+
const method = new CheckAllFirmwareRelease({
|
|
775
|
+
id: 1,
|
|
776
|
+
payload: {
|
|
777
|
+
method: 'checkAllFirmwareRelease',
|
|
778
|
+
firmwareType: EFirmwareType.Universal,
|
|
779
|
+
},
|
|
780
|
+
});
|
|
781
|
+
method.init();
|
|
782
|
+
method.device = {
|
|
783
|
+
isProtocolV2: () => true,
|
|
784
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
785
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
786
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
787
|
+
status: { mode: 'normal' },
|
|
788
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
789
|
+
}),
|
|
790
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
791
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
|
|
792
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
793
|
+
|
|
794
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
795
|
+
status: 'valid',
|
|
796
|
+
hasUpgrade: false,
|
|
797
|
+
resourceStatus: 'unknown',
|
|
798
|
+
resourceArchive: resourceSource,
|
|
799
|
+
targetsToUpdate: [],
|
|
800
|
+
firmwareUpdatePlan: undefined,
|
|
801
|
+
});
|
|
802
|
+
});
|
|
803
|
+
|
|
486
804
|
test('continues forwarding the existing public method', async () => {
|
|
487
805
|
const call = jest.fn().mockResolvedValue({ success: true, payload: {} });
|
|
488
806
|
const api = createCoreApi(call as CoreApi['call']) as CoreApi;
|
|
@@ -490,6 +808,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
490
808
|
await api.checkAllFirmwareRelease('pro2-connect-id', {
|
|
491
809
|
checkFirmwareHash: true,
|
|
492
810
|
firmwareType: EFirmwareType.Universal,
|
|
811
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
493
812
|
retryCount: 0,
|
|
494
813
|
});
|
|
495
814
|
|
|
@@ -497,6 +816,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
497
816
|
connectId: 'pro2-connect-id',
|
|
498
817
|
checkFirmwareHash: true,
|
|
499
818
|
firmwareType: EFirmwareType.Universal,
|
|
819
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
500
820
|
retryCount: 0,
|
|
501
821
|
method: 'checkAllFirmwareRelease',
|
|
502
822
|
});
|