@onekeyfe/hd-core 1.2.0-alpha.81 → 1.2.0-alpha.84
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 +266 -0
- package/__tests__/check-firmware-release-protocol-v2.test.ts +36 -0
- package/__tests__/protocol-v2.test.ts +181 -2
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBLEFirmwareRelease.d.ts +1 -1
- package/dist/api/CheckBLEFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/CheckFirmwareRelease.d.ts +1 -1
- package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +1 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +33 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/protocolV2Release.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +202 -66
- package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -0
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkBLEFirmwareRelease.d.ts +1 -1
- package/dist/types/api/checkBLEFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkBootloaderRelease.d.ts +1 -1
- package/dist/types/api/checkBootloaderRelease.d.ts.map +1 -1
- package/dist/types/api/checkFirmwareRelease.d.ts +1 -1
- package/dist/types/api/checkFirmwareRelease.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +76 -5
- package/src/api/CheckBLEFirmwareRelease.ts +4 -10
- package/src/api/CheckBootloaderRelease.ts +1 -8
- package/src/api/CheckFirmwareRelease.ts +6 -12
- package/src/api/FirmwareUpdateV4.ts +61 -21
- package/src/api/firmware/FirmwareUpdatePlan.ts +154 -37
- package/src/api/firmware/protocolV2Release.ts +2 -0
- package/src/types/api/checkAllFirmwareRelease.ts +1 -0
- package/src/types/api/checkBLEFirmwareRelease.ts +1 -1
- package/src/types/api/checkBootloaderRelease.ts +1 -1
- package/src/types/api/checkFirmwareRelease.ts +1 -1
- package/src/utils/deviceFeaturesUtils.ts +2 -2
|
@@ -333,6 +333,15 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
333
333
|
resourceArchive: resourceSource,
|
|
334
334
|
resourcePreparationRequired: true,
|
|
335
335
|
targetsToUpdate: ['boot', 'app_v1', 'resource'],
|
|
336
|
+
firmwareUpdatePlan: {
|
|
337
|
+
executor: 'v4',
|
|
338
|
+
platform: 'web',
|
|
339
|
+
artifacts: [
|
|
340
|
+
{ artifactId: 'component:boot', target: 'boot' },
|
|
341
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
342
|
+
],
|
|
343
|
+
targetsToUpdate: ['boot', 'app_v1'],
|
|
344
|
+
},
|
|
336
345
|
firmware: {
|
|
337
346
|
status: 'required',
|
|
338
347
|
},
|
|
@@ -344,6 +353,260 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
344
353
|
expect(method.getSupportedProtocols()).toEqual(['V1', 'V2']);
|
|
345
354
|
});
|
|
346
355
|
|
|
356
|
+
test('preserves platform and forced firmware targets in the Protocol V2 prepared plan', async () => {
|
|
357
|
+
const method = new CheckAllFirmwareRelease({
|
|
358
|
+
id: 1,
|
|
359
|
+
payload: {
|
|
360
|
+
method: 'checkAllFirmwareRelease',
|
|
361
|
+
firmwareType: EFirmwareType.Universal,
|
|
362
|
+
platform: 'native',
|
|
363
|
+
forceUpdateTargets: ['firmware'],
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
method.init();
|
|
367
|
+
method.device = {
|
|
368
|
+
isProtocolV2: () => true,
|
|
369
|
+
features: {
|
|
370
|
+
deviceType: 'pro2',
|
|
371
|
+
serialNo: 'pro2-device-id',
|
|
372
|
+
firmwareVersion: '1.0.0',
|
|
373
|
+
},
|
|
374
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
375
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
376
|
+
status: { mode: 'normal' },
|
|
377
|
+
versions: currentVersions,
|
|
378
|
+
}),
|
|
379
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
380
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
381
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
382
|
+
|
|
383
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
384
|
+
targetsToUpdate: ['boot', 'app_v1', 'se02', 'se03', 'resource'],
|
|
385
|
+
firmwareUpdatePlan: {
|
|
386
|
+
executor: 'v4',
|
|
387
|
+
deviceIdentity: 'pro2-device-id',
|
|
388
|
+
platform: 'native',
|
|
389
|
+
artifacts: [
|
|
390
|
+
{ artifactId: 'component:boot', target: 'boot' },
|
|
391
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
392
|
+
{ artifactId: 'component:se02', target: 'se02' },
|
|
393
|
+
{ artifactId: 'component:se03', target: 'se03' },
|
|
394
|
+
],
|
|
395
|
+
targetsToUpdate: ['boot', 'app_v1', 'se02', 'se03'],
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test('includes exact Protocol V2 developer force targets in the prepared plan', async () => {
|
|
401
|
+
const currentRelease: IFirmwareReleaseInfo = {
|
|
402
|
+
...release,
|
|
403
|
+
required: false,
|
|
404
|
+
version: [1, 0, 0],
|
|
405
|
+
installOrder: ['applicationP1', 'coprocessor'],
|
|
406
|
+
components: {
|
|
407
|
+
applicationP1: {
|
|
408
|
+
target: 'APPLICATION_P1',
|
|
409
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
410
|
+
version: [1, 0, 0],
|
|
411
|
+
},
|
|
412
|
+
coprocessor: {
|
|
413
|
+
target: 'COPROCESSOR',
|
|
414
|
+
url: 'https://example.com/coprocessor.okpkg',
|
|
415
|
+
version: [1, 0, 0],
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
const method = new CheckAllFirmwareRelease({
|
|
420
|
+
id: 1,
|
|
421
|
+
payload: {
|
|
422
|
+
method: 'checkAllFirmwareRelease',
|
|
423
|
+
platform: 'desktop',
|
|
424
|
+
protocolV2ForceUpdateTargets: ['app_v1', 'coprocessor'],
|
|
425
|
+
},
|
|
426
|
+
});
|
|
427
|
+
method.init();
|
|
428
|
+
method.device = {
|
|
429
|
+
isProtocolV2: () => true,
|
|
430
|
+
features: {
|
|
431
|
+
deviceType: 'pro2',
|
|
432
|
+
serialNo: 'pro2-device-id',
|
|
433
|
+
firmwareVersion: '1.0.0',
|
|
434
|
+
},
|
|
435
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
436
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
437
|
+
status: { mode: 'normal' },
|
|
438
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
439
|
+
}),
|
|
440
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
441
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
|
|
442
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
443
|
+
|
|
444
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
445
|
+
targetsToUpdate: ['app_v1', 'coprocessor', 'resource'],
|
|
446
|
+
firmwareUpdatePlan: {
|
|
447
|
+
executor: 'v4',
|
|
448
|
+
platform: 'desktop',
|
|
449
|
+
artifacts: [
|
|
450
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
451
|
+
{ artifactId: 'component:coprocessor', target: 'coprocessor' },
|
|
452
|
+
],
|
|
453
|
+
targetsToUpdate: ['app_v1', 'coprocessor'],
|
|
454
|
+
},
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
test('keeps exact force targets but omits a Desktop Plan without device identity', async () => {
|
|
459
|
+
const currentRelease: IFirmwareReleaseInfo = {
|
|
460
|
+
...release,
|
|
461
|
+
required: false,
|
|
462
|
+
version: [1, 0, 0],
|
|
463
|
+
installOrder: ['applicationP1'],
|
|
464
|
+
components: {
|
|
465
|
+
applicationP1: {
|
|
466
|
+
target: 'APPLICATION_P1',
|
|
467
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
468
|
+
version: [1, 0, 0],
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
const method = new CheckAllFirmwareRelease({
|
|
473
|
+
id: 1,
|
|
474
|
+
payload: {
|
|
475
|
+
method: 'checkAllFirmwareRelease',
|
|
476
|
+
platform: 'desktop',
|
|
477
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
method.init();
|
|
481
|
+
method.device = {
|
|
482
|
+
isProtocolV2: () => true,
|
|
483
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
484
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
485
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
486
|
+
status: { mode: 'normal' },
|
|
487
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
488
|
+
}),
|
|
489
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
490
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
|
|
491
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
492
|
+
|
|
493
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
494
|
+
targetsToUpdate: ['app_v1', 'resource'],
|
|
495
|
+
firmwareUpdatePlan: undefined,
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
test('rejects Neo-only unsupported exact secure-element targets', async () => {
|
|
500
|
+
const neoRelease: IFirmwareReleaseInfo = {
|
|
501
|
+
...release,
|
|
502
|
+
required: false,
|
|
503
|
+
installOrder: ['se03'],
|
|
504
|
+
components: {
|
|
505
|
+
se03: {
|
|
506
|
+
target: 'SE03',
|
|
507
|
+
url: 'https://example.com/se03.okpkg',
|
|
508
|
+
version: [1, 0, 0],
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
};
|
|
512
|
+
const method = new CheckAllFirmwareRelease({
|
|
513
|
+
id: 1,
|
|
514
|
+
payload: {
|
|
515
|
+
method: 'checkAllFirmwareRelease',
|
|
516
|
+
protocolV2ForceUpdateTargets: ['se03'],
|
|
517
|
+
},
|
|
518
|
+
});
|
|
519
|
+
method.init();
|
|
520
|
+
method.device = {
|
|
521
|
+
isProtocolV2: () => true,
|
|
522
|
+
features: { deviceType: 'neo', firmwareVersion: '1.0.0' },
|
|
523
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
524
|
+
identity: { deviceType: 'neo', firmwareType: EFirmwareType.Universal },
|
|
525
|
+
status: { mode: 'normal' },
|
|
526
|
+
versions: currentVersions,
|
|
527
|
+
}),
|
|
528
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
529
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(neoRelease);
|
|
530
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
531
|
+
|
|
532
|
+
await expect(method.run()).rejects.toMatchObject({
|
|
533
|
+
params: { firmwareUpdateCode: 'FirmwarePlanInvalid' },
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
test('builds a V4 plan for Neo and excludes unsupported secure elements when forced', async () => {
|
|
538
|
+
const neoRelease: IFirmwareReleaseInfo = {
|
|
539
|
+
...release,
|
|
540
|
+
installOrder: ['se01', 'se02', 'se03', 'se04'],
|
|
541
|
+
components: {
|
|
542
|
+
se01: { target: 'SE01', url: 'https://example.com/se01.bin', version: [1, 0, 0] },
|
|
543
|
+
se02: { target: 'SE02', url: 'https://example.com/se02.bin', version: [2, 0, 0] },
|
|
544
|
+
se03: { target: 'SE03', url: 'https://example.com/se03.bin', version: [1, 0, 0] },
|
|
545
|
+
se04: { target: 'SE04', url: 'https://example.com/se04.bin', version: [1, 0, 0] },
|
|
546
|
+
},
|
|
547
|
+
};
|
|
548
|
+
const method = new CheckAllFirmwareRelease({
|
|
549
|
+
id: 1,
|
|
550
|
+
payload: {
|
|
551
|
+
method: 'checkAllFirmwareRelease',
|
|
552
|
+
platform: 'native',
|
|
553
|
+
forceUpdateTargets: ['firmware'],
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
method.init();
|
|
557
|
+
method.device = {
|
|
558
|
+
isProtocolV2: () => true,
|
|
559
|
+
features: {
|
|
560
|
+
deviceType: 'neo',
|
|
561
|
+
serialNo: 'neo-device-id',
|
|
562
|
+
firmwareVersion: '1.0.0',
|
|
563
|
+
},
|
|
564
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
565
|
+
identity: { deviceType: 'neo', firmwareType: EFirmwareType.Universal },
|
|
566
|
+
status: { mode: 'normal' },
|
|
567
|
+
versions: currentVersions,
|
|
568
|
+
}),
|
|
569
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
570
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(neoRelease);
|
|
571
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
572
|
+
|
|
573
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
574
|
+
targetsToUpdate: ['se01', 'se02', 'resource'],
|
|
575
|
+
firmwareUpdatePlan: {
|
|
576
|
+
executor: 'v4',
|
|
577
|
+
deviceModel: 'neo',
|
|
578
|
+
platform: 'native',
|
|
579
|
+
targetsToUpdate: ['se01', 'se02'],
|
|
580
|
+
},
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
test('rejects a forced Protocol V2 resource target without a configured archive', async () => {
|
|
585
|
+
const method = new CheckAllFirmwareRelease({
|
|
586
|
+
id: 1,
|
|
587
|
+
payload: {
|
|
588
|
+
method: 'checkAllFirmwareRelease',
|
|
589
|
+
forceUpdateTargets: ['resource'],
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
method.init();
|
|
593
|
+
method.device = {
|
|
594
|
+
isProtocolV2: () => true,
|
|
595
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
596
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
597
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
598
|
+
status: { mode: 'normal' },
|
|
599
|
+
versions: currentVersions,
|
|
600
|
+
}),
|
|
601
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
602
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
603
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(undefined);
|
|
604
|
+
|
|
605
|
+
await expect(method.run()).rejects.toMatchObject({
|
|
606
|
+
params: { firmwareUpdateCode: 'FirmwarePlanInvalid' },
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
|
|
347
610
|
test('requests and compares firmware hashes only when explicitly enabled', async () => {
|
|
348
611
|
const packageSet: IFirmwareReleaseInfo = {
|
|
349
612
|
...release,
|
|
@@ -467,6 +730,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
467
730
|
resourceStatus: 'unknown',
|
|
468
731
|
resourcePreparationRequired: true,
|
|
469
732
|
targetsToUpdate: ['resource'],
|
|
733
|
+
firmwareUpdatePlan: undefined,
|
|
470
734
|
});
|
|
471
735
|
});
|
|
472
736
|
|
|
@@ -477,6 +741,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
477
741
|
await api.checkAllFirmwareRelease('pro2-connect-id', {
|
|
478
742
|
checkFirmwareHash: true,
|
|
479
743
|
firmwareType: EFirmwareType.Universal,
|
|
744
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
480
745
|
retryCount: 0,
|
|
481
746
|
});
|
|
482
747
|
|
|
@@ -484,6 +749,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
484
749
|
connectId: 'pro2-connect-id',
|
|
485
750
|
checkFirmwareHash: true,
|
|
486
751
|
firmwareType: EFirmwareType.Universal,
|
|
752
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
487
753
|
retryCount: 0,
|
|
488
754
|
method: 'checkAllFirmwareRelease',
|
|
489
755
|
});
|
|
@@ -22,6 +22,10 @@ const release: IFirmwareReleaseInfo = {
|
|
|
22
22
|
'zh-CN': '更新',
|
|
23
23
|
'en-US': 'Update',
|
|
24
24
|
},
|
|
25
|
+
bootloaderChangelog: {
|
|
26
|
+
'zh-CN': '旧版 Bootloader 更新',
|
|
27
|
+
'en-US': 'Legacy bootloader update',
|
|
28
|
+
},
|
|
25
29
|
installOrder: ['bootloader', 'applicationP1', 'coprocessor'],
|
|
26
30
|
components: {
|
|
27
31
|
bootloader: {
|
|
@@ -127,6 +131,7 @@ describe.each(['pro2', 'neo'] as const)('Protocol V2 release checks for %s', dev
|
|
|
127
131
|
await expect(bootloaderMethod.run()).resolves.toMatchObject({
|
|
128
132
|
status: 'outdated',
|
|
129
133
|
shouldUpdate: true,
|
|
134
|
+
changelog: [release.changelog],
|
|
130
135
|
release: {
|
|
131
136
|
protocol: 'V2',
|
|
132
137
|
configKey: 'bootloader',
|
|
@@ -134,6 +139,7 @@ describe.each(['pro2', 'neo'] as const)('Protocol V2 release checks for %s', dev
|
|
|
134
139
|
target: 'BOOTLOADER',
|
|
135
140
|
url: 'https://example.com/bootloader.okpkg',
|
|
136
141
|
version: [2, 0, 0],
|
|
142
|
+
changelog: release.changelog,
|
|
137
143
|
},
|
|
138
144
|
});
|
|
139
145
|
await expect(allMethod.run()).resolves.toMatchObject({
|
|
@@ -162,3 +168,33 @@ describe.each(['pro2', 'neo'] as const)('Protocol V2 release checks for %s', dev
|
|
|
162
168
|
expect(allMethod.getSupportedProtocols()).toEqual(['V1', 'V2']);
|
|
163
169
|
});
|
|
164
170
|
});
|
|
171
|
+
|
|
172
|
+
test('returns null from optional release probes when device features are unavailable', async () => {
|
|
173
|
+
const deviceWithoutFeatures = {
|
|
174
|
+
isProtocolV2: jest.fn(() => true),
|
|
175
|
+
features: undefined,
|
|
176
|
+
getDeviceState: jest.fn(),
|
|
177
|
+
};
|
|
178
|
+
const firmwareMethod = new CheckFirmwareRelease({
|
|
179
|
+
id: 1,
|
|
180
|
+
payload: { method: 'checkFirmwareRelease' },
|
|
181
|
+
});
|
|
182
|
+
const bleMethod = new CheckBLEFirmwareRelease({
|
|
183
|
+
id: 2,
|
|
184
|
+
payload: { method: 'checkBLEFirmwareRelease' },
|
|
185
|
+
});
|
|
186
|
+
const bootloaderMethod = new CheckBootloaderRelease({
|
|
187
|
+
id: 3,
|
|
188
|
+
payload: { method: 'checkBootloaderRelease' },
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
firmwareMethod.device = deviceWithoutFeatures as unknown as CheckFirmwareRelease['device'];
|
|
192
|
+
bleMethod.device = deviceWithoutFeatures as unknown as CheckBLEFirmwareRelease['device'];
|
|
193
|
+
bootloaderMethod.device = deviceWithoutFeatures as unknown as CheckBootloaderRelease['device'];
|
|
194
|
+
|
|
195
|
+
await expect(firmwareMethod.run()).resolves.toBeNull();
|
|
196
|
+
await expect(bleMethod.run()).resolves.toBeNull();
|
|
197
|
+
await expect(bootloaderMethod.run()).resolves.toBeNull();
|
|
198
|
+
expect(deviceWithoutFeatures.isProtocolV2).not.toHaveBeenCalled();
|
|
199
|
+
expect(deviceWithoutFeatures.getDeviceState).not.toHaveBeenCalled();
|
|
200
|
+
});
|
|
@@ -2778,9 +2778,12 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
2778
2778
|
expect(checkedTypes).toEqual(['pro2', 'model_pro2']);
|
|
2779
2779
|
});
|
|
2780
2780
|
|
|
2781
|
-
test(
|
|
2781
|
+
test.each([
|
|
2782
|
+
['Pro2', DeviceType.PRO2],
|
|
2783
|
+
['Neo', DeviceType.NEO],
|
|
2784
|
+
] as const)('uses firmware-v1 as the %s remote firmware config field', (_name, deviceType) => {
|
|
2782
2785
|
const features = normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any, {
|
|
2783
|
-
hw: { Device_type:
|
|
2786
|
+
hw: { Device_type: deviceType },
|
|
2784
2787
|
});
|
|
2785
2788
|
|
|
2786
2789
|
expect(
|
|
@@ -5860,6 +5863,80 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5860
5863
|
getFirmwareLatestReleaseSpy.mockRestore();
|
|
5861
5864
|
});
|
|
5862
5865
|
|
|
5866
|
+
test('downloads only firmware targets that are missing from an explicit mixed payload', async () => {
|
|
5867
|
+
const explicitApplicationBinary = new Uint8Array([1]).buffer;
|
|
5868
|
+
const remoteCoprocessorBinary = new Uint8Array([2]).buffer;
|
|
5869
|
+
const method = new FirmwareUpdateV4({
|
|
5870
|
+
id: 1,
|
|
5871
|
+
payload: {
|
|
5872
|
+
method: 'firmwareUpdateV4',
|
|
5873
|
+
platform: 'web',
|
|
5874
|
+
targetsToUpdate: ['app_v1', 'coprocessor'],
|
|
5875
|
+
},
|
|
5876
|
+
});
|
|
5877
|
+
method.init();
|
|
5878
|
+
|
|
5879
|
+
const getSysResourceBinarySpy = jest
|
|
5880
|
+
.spyOn(firmwareBinaryApi, 'getSysResourceBinary')
|
|
5881
|
+
.mockResolvedValue({ binary: remoteCoprocessorBinary });
|
|
5882
|
+
const getFirmwareLatestReleaseSpy = jest
|
|
5883
|
+
.spyOn(DataManager, 'getFirmwareLatestRelease')
|
|
5884
|
+
.mockReturnValue({
|
|
5885
|
+
required: false,
|
|
5886
|
+
version: [1, 0, 0],
|
|
5887
|
+
url: 'https://example.com/applicationP1.pp.bin',
|
|
5888
|
+
installOrder: ['applicationP1', 'coprocessor'],
|
|
5889
|
+
components: {
|
|
5890
|
+
applicationP1: {
|
|
5891
|
+
target: 'APPLICATION_P1',
|
|
5892
|
+
url: 'https://example.com/applicationP1.pp.bin',
|
|
5893
|
+
},
|
|
5894
|
+
coprocessor: {
|
|
5895
|
+
target: 'COPROCESSOR',
|
|
5896
|
+
url: 'https://example.com/coprocessor.pp.bin',
|
|
5897
|
+
},
|
|
5898
|
+
},
|
|
5899
|
+
fingerprint: '',
|
|
5900
|
+
changelog: {
|
|
5901
|
+
'zh-CN': '',
|
|
5902
|
+
'en-US': '',
|
|
5903
|
+
},
|
|
5904
|
+
});
|
|
5905
|
+
|
|
5906
|
+
const remoteBinaries = await (method as any).prepareRemoteProtocolV2Binaries(
|
|
5907
|
+
'universal',
|
|
5908
|
+
{ deviceType: 'pro2', firmwareVersion: '0.0.0' },
|
|
5909
|
+
[
|
|
5910
|
+
{
|
|
5911
|
+
fileName: 'application_p1.bin',
|
|
5912
|
+
binary: explicitApplicationBinary,
|
|
5913
|
+
targetId: 4,
|
|
5914
|
+
kind: 'firmware',
|
|
5915
|
+
},
|
|
5916
|
+
]
|
|
5917
|
+
);
|
|
5918
|
+
|
|
5919
|
+
expect(getSysResourceBinarySpy).toHaveBeenCalledTimes(1);
|
|
5920
|
+
expect(getSysResourceBinarySpy).toHaveBeenCalledWith('https://example.com/coprocessor.pp.bin');
|
|
5921
|
+
expect(remoteBinaries.installItems).toEqual([
|
|
5922
|
+
{
|
|
5923
|
+
fileName: 'application_p1.bin',
|
|
5924
|
+
binary: explicitApplicationBinary,
|
|
5925
|
+
targetId: 4,
|
|
5926
|
+
kind: 'firmware',
|
|
5927
|
+
},
|
|
5928
|
+
{
|
|
5929
|
+
fileName: 'coprocessor.bin',
|
|
5930
|
+
binary: remoteCoprocessorBinary,
|
|
5931
|
+
targetId: 6,
|
|
5932
|
+
kind: 'firmware',
|
|
5933
|
+
},
|
|
5934
|
+
]);
|
|
5935
|
+
|
|
5936
|
+
getSysResourceBinarySpy.mockRestore();
|
|
5937
|
+
getFirmwareLatestReleaseSpy.mockRestore();
|
|
5938
|
+
});
|
|
5939
|
+
|
|
5863
5940
|
test('ignores an unsupported remote ROMLOADER component when installing selected targets', async () => {
|
|
5864
5941
|
const method = new FirmwareUpdateV4({
|
|
5865
5942
|
id: 1,
|
|
@@ -6195,6 +6272,108 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6195
6272
|
);
|
|
6196
6273
|
});
|
|
6197
6274
|
|
|
6275
|
+
test('downloads every missing firmware target when manifest resources are already prepared', async () => {
|
|
6276
|
+
const resourceBundle = createProtocolV2OkppBinary();
|
|
6277
|
+
const applicationBinary = new Uint8Array([7]).buffer;
|
|
6278
|
+
const remoteBinaries = {
|
|
6279
|
+
bootloaderBinary: null,
|
|
6280
|
+
fwBinaryMap: [
|
|
6281
|
+
{
|
|
6282
|
+
fileName: 'application_p1.bin',
|
|
6283
|
+
binary: applicationBinary,
|
|
6284
|
+
targetId: 4,
|
|
6285
|
+
},
|
|
6286
|
+
],
|
|
6287
|
+
installItems: [
|
|
6288
|
+
{
|
|
6289
|
+
fileName: 'application_p1.bin',
|
|
6290
|
+
binary: applicationBinary,
|
|
6291
|
+
targetId: 4,
|
|
6292
|
+
kind: 'firmware',
|
|
6293
|
+
},
|
|
6294
|
+
],
|
|
6295
|
+
};
|
|
6296
|
+
const method = new FirmwareUpdateV4({
|
|
6297
|
+
id: 1,
|
|
6298
|
+
payload: {
|
|
6299
|
+
method: 'firmwareUpdateV4',
|
|
6300
|
+
platform: 'web',
|
|
6301
|
+
targetsToUpdate: ['app_v1', 'resource'],
|
|
6302
|
+
resourceFiles: [
|
|
6303
|
+
{
|
|
6304
|
+
binary: resourceBundle,
|
|
6305
|
+
devicePath: 'vol0:/bundles/images/images.okpkg',
|
|
6306
|
+
},
|
|
6307
|
+
],
|
|
6308
|
+
},
|
|
6309
|
+
});
|
|
6310
|
+
method.init();
|
|
6311
|
+
(method as any).captureProtocolV2PhysicalIdentity = jest.fn().mockResolvedValue(undefined);
|
|
6312
|
+
(method as any).device = stubDevice({
|
|
6313
|
+
originalDescriptor: { protocolType: 'V2' },
|
|
6314
|
+
features: { deviceType: 'pro2', firmwareVersion: '0.0.0', capabilities: [] },
|
|
6315
|
+
});
|
|
6316
|
+
(method as any).prepareRemoteProtocolV2Binaries = jest.fn().mockResolvedValue(remoteBinaries);
|
|
6317
|
+
(method as any).executeProtocolV2Update = jest.fn().mockResolvedValue(undefined);
|
|
6318
|
+
method.postTipMessage = jest.fn();
|
|
6319
|
+
|
|
6320
|
+
await method.run();
|
|
6321
|
+
|
|
6322
|
+
expect(forceReloadDataSpy).toHaveBeenCalledTimes(1);
|
|
6323
|
+
expect((method as any).prepareRemoteProtocolV2Binaries).toHaveBeenCalledWith(
|
|
6324
|
+
'universal',
|
|
6325
|
+
expect.objectContaining({ deviceType: 'pro2' }),
|
|
6326
|
+
[]
|
|
6327
|
+
);
|
|
6328
|
+
expect((method as any).executeProtocolV2Update).toHaveBeenCalledWith({
|
|
6329
|
+
bootloaderBinary: null,
|
|
6330
|
+
fwBinaryMap: remoteBinaries.fwBinaryMap,
|
|
6331
|
+
installItems: remoteBinaries.installItems,
|
|
6332
|
+
resourceBundles: [
|
|
6333
|
+
{
|
|
6334
|
+
name: 'images.okpkg',
|
|
6335
|
+
binary: resourceBundle,
|
|
6336
|
+
devicePath: 'vol0:/bundles/images/images.okpkg',
|
|
6337
|
+
version: [1, 2, 3],
|
|
6338
|
+
payloadHash: '11'.repeat(64),
|
|
6339
|
+
headerHash: '22'.repeat(64),
|
|
6340
|
+
},
|
|
6341
|
+
],
|
|
6342
|
+
});
|
|
6343
|
+
});
|
|
6344
|
+
|
|
6345
|
+
test('rejects a mixed resource plan when the requested firmware release is unavailable', async () => {
|
|
6346
|
+
const resourceBundle = createProtocolV2OkppBinary();
|
|
6347
|
+
const method = new FirmwareUpdateV4({
|
|
6348
|
+
id: 1,
|
|
6349
|
+
payload: {
|
|
6350
|
+
method: 'firmwareUpdateV4',
|
|
6351
|
+
platform: 'web',
|
|
6352
|
+
targetsToUpdate: ['app_v1', 'resource'],
|
|
6353
|
+
resourceFiles: [
|
|
6354
|
+
{
|
|
6355
|
+
binary: resourceBundle,
|
|
6356
|
+
devicePath: 'vol0:/bundles/images/images.okpkg',
|
|
6357
|
+
},
|
|
6358
|
+
],
|
|
6359
|
+
},
|
|
6360
|
+
});
|
|
6361
|
+
method.init();
|
|
6362
|
+
(method as any).captureProtocolV2PhysicalIdentity = jest.fn().mockResolvedValue(undefined);
|
|
6363
|
+
(method as any).device = stubDevice({
|
|
6364
|
+
originalDescriptor: { protocolType: 'V2' },
|
|
6365
|
+
features: { deviceType: 'pro2', firmwareVersion: '0.0.0', capabilities: [] },
|
|
6366
|
+
});
|
|
6367
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(undefined);
|
|
6368
|
+
(method as any).executeProtocolV2Update = jest.fn();
|
|
6369
|
+
method.postTipMessage = jest.fn();
|
|
6370
|
+
|
|
6371
|
+
await expect(method.run()).rejects.toThrow(
|
|
6372
|
+
'Protocol V2 firmware release is unavailable for requested targets: app_v1'
|
|
6373
|
+
);
|
|
6374
|
+
expect((method as any).executeProtocolV2Update).not.toHaveBeenCalled();
|
|
6375
|
+
});
|
|
6376
|
+
|
|
6198
6377
|
test('combines prepared firmware components with explicit manifest resource files', async () => {
|
|
6199
6378
|
const resourceBundle = createProtocolV2OkppBinary();
|
|
6200
6379
|
const method = new FirmwareUpdateV4({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckAllFirmwareRelease.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"CheckAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckAllFirmwareRelease.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EACV,kBAAkB,EAElB,kCAAkC,EAClC,+BAA+B,EAChC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,UAAU,CAAC;AAgIlB,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,aAAa,CAAC;IAC5B,MAAM,EAAE,+BAA+B,CAAC;IACxC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,kCAAkC,EAAE,CAAC;IACjD,eAAe,EAAE,sBAAsB,EAAE,CAAC;IAC1C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAgB,8BAA8B,CAAC,EAC7C,eAAe,EACf,mBAAwB,EACxB,iBAAyB,EACzB,mBAAwB,EACxB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,eAAe,EAAE,mBAAmB,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAC9D,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B,GAAG,6BAA6B,CAiFhC;AAID,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,UAAU;IAC7D,qBAAqB;IAIrB,IAAI;IAME,GAAG;YAuFK,aAAa;CAmI5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckBLEFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckBLEFirmwareRelease.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CheckBLEFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckBLEFirmwareRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAY1C,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,UAAU;IAC7D,qBAAqB;IAIrB,IAAI;IAUE,GAAG;;;;;;;;;CA2BV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckBootloaderRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckBootloaderRelease.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CheckBootloaderRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckBootloaderRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAc1C,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,UAAU;IAC5D,qBAAqB;IAIrB,IAAI;IAME,GAAG;;;;;;;;;;CAqCV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckFirmwareRelease.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CheckFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckFirmwareRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAa1C,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,UAAU;IAC1D,qBAAqB;IAIrB,IAAI;IAUE,GAAG;;;;;;;;;CA6BV"}
|
|
@@ -40,6 +40,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
40
40
|
private verifyProtocolV2ReconnectIdentity;
|
|
41
41
|
private prepareBootloaderBinary;
|
|
42
42
|
private hasExplicitProtocolV2Payload;
|
|
43
|
+
private getMissingProtocolV2FirmwareTargets;
|
|
43
44
|
private buildProtocolV2InstallItems;
|
|
44
45
|
private getRemoteComponentEntries;
|
|
45
46
|
private getRemoteComponentTarget;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AAyBlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAmB/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AA6CrC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,QAgB/B;AA6UD,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,iBACZ,MAAM,eACR,MAAM,SAsBpB,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,sBAAsB,CAAC,CAAS;IAExC,qBAAqB;IAIrB,OAAO,CAAC,yBAAyB,CAA4B;IAE7D,OAAO,CAAC,2BAA2B,CAAS;IAE5C,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,6BAA6B,CAAC,CAAW;IAEjD,OAAO,CAAC,6BAA6B,CAAS;IAE9C,IAAI;IAoHJ,OAAO,CAAC,8BAA8B;IAwBhC,GAAG;;;;;YAKK,aAAa;
|
|
1
|
+
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AAyBlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAmB/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AA6CrC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,QAgB/B;AA6UD,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,iBACZ,MAAM,eACR,MAAM,SAsBpB,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,sBAAsB,CAAC,CAAS;IAExC,qBAAqB;IAIrB,OAAO,CAAC,yBAAyB,CAA4B;IAE7D,OAAO,CAAC,2BAA2B,CAAS;IAE5C,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,6BAA6B,CAAC,CAAW;IAEjD,OAAO,CAAC,6BAA6B,CAAS;IAE9C,IAAI;IAoHJ,OAAO,CAAC,8BAA8B;IAwBhC,GAAG;;;;;YAKK,aAAa;YAgHb,4BAA4B;YAkB5B,0BAA0B;YAY1B,8BAA8B;YAK9B,+BAA+B;YAqD/B,gCAAgC;YAmDhC,8BAA8B;IAkC5C,OAAO,CAAC,8BAA8B;IA0BtC,OAAO,CAAC,kCAAkC;IAc1C,OAAO,CAAC,gCAAgC;IAsDxC,OAAO,CAAC,6BAA6B;YAsBvB,2BAA2B;IAWzC,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,kCAAkC;IAS1C,OAAO,CAAC,8BAA8B;YAMxB,iCAAiC;YAOjC,iCAAiC;YAkBjC,iCAAiC;IAM/C,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,4BAA4B;IAIpC,OAAO,CAAC,mCAAmC;IAY3C,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,wBAAwB;YAkBlB,iCAAiC;YAmCjC,+BAA+B;IA6E7C,OAAO,CAAC,sCAAsC;IA0C9C,OAAO,CAAC,6BAA6B;YAMvB,8BAA8B;YA8C9B,kCAAkC;IA4BhD,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,yBAAyB;IAc3B,6BAA6B;YAgCrB,+BAA+B;IAkD7C,OAAO,CAAC,6BAA6B;IAkCrC,OAAO,CAAC,8BAA8B;YA8CxB,uBAAuB;YAiCvB,6BAA6B;YAa7B,uBAAuB;YA6CvB,8BAA8B;YA8D9B,6BAA6B;IAuE3C,OAAO,CAAC,mCAAmC;YAI7B,0BAA0B;IAaxC,OAAO,CAAC,4BAA4B;IAyGpC,OAAO,CAAC,6BAA6B;YAcvB,uCAAuC;YA0JvC,gCAAgC;YAehC,yBAAyB;YAQzB,8BAA8B;IAQ5C,OAAO,CAAC,0BAA0B;YAkBpB,mCAAmC;YAWnC,qCAAqC;YAgDrC,yBAAyB;YA8DzB,8BAA8B;IAU5C,OAAO,CAAC,kCAAkC;YAQ5B,cAAc;YAuCd,6BAA6B;YAW7B,0BAA0B;YAS1B,6BAA6B;YAmB7B,gBAAgB;IAiB9B,OAAO,CAAC,qBAAqB;CAM9B"}
|