@onekeyfe/hd-core 1.2.0-alpha.112 → 1.2.0-alpha.113
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__/DeviceCommands.test.ts +2 -2
- package/__tests__/device-lifecycle-events.test.ts +1 -1
- package/__tests__/device-state-mapper.test.ts +4 -4
- package/__tests__/device-utils.test.ts +1 -1
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +116 -0
- package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +89 -36
- package/__tests__/get-device-state.test.ts +8 -8
- package/__tests__/protocol-v2-resources.test.ts +0 -20
- package/__tests__/protocol-v2.test.ts +240 -219
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +3 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
- package/dist/index.d.ts +20 -5
- package/dist/index.js +230 -140
- package/dist/protocols/protocol-v2/features.d.ts +4 -4
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
- package/dist/types/settings.d.ts +19 -4
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV3.ts +29 -19
- package/src/api/FirmwareUpdateV4.ts +178 -85
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
- package/src/api/protocol-v2/DeviceInfoGet.ts +3 -3
- package/src/data/messages/messages-protocol-v2.json +14 -31
- package/src/device/DeviceStateMapper.ts +15 -15
- package/src/deviceProfile/buildDeviceFeatures.ts +3 -3
- package/src/protocols/protocol-v2/features.ts +6 -6
- package/src/protocols/protocol-v2/resources.ts +49 -10
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -1
- package/src/types/settings.ts +19 -4
|
@@ -613,7 +613,7 @@ const protocolV2BootloaderDeviceInfo: ProtocolV2DeviceInfo = {
|
|
|
613
613
|
hw: {
|
|
614
614
|
serial_no: 'PR9999999999',
|
|
615
615
|
},
|
|
616
|
-
|
|
616
|
+
fw: {
|
|
617
617
|
bootloader: {
|
|
618
618
|
version: '0.0.1',
|
|
619
619
|
},
|
|
@@ -677,7 +677,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
677
677
|
const deviceInfo: ProtocolV2DeviceInfo = {
|
|
678
678
|
protocol_version: 1,
|
|
679
679
|
hw: { serial_no: 'P2-STATIC' },
|
|
680
|
-
|
|
680
|
+
fw: { application: { version: '1.0.0' } },
|
|
681
681
|
coprocessor: { bt_adv_name: 'Pro2 STATIC' },
|
|
682
682
|
};
|
|
683
683
|
const deviceStatus: DeviceStatus = {
|
|
@@ -751,7 +751,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
751
751
|
Device_type: DeviceType.PRO2,
|
|
752
752
|
serial_no: 'PR2SERIAL',
|
|
753
753
|
},
|
|
754
|
-
|
|
754
|
+
fw: {
|
|
755
755
|
romloader: {
|
|
756
756
|
version: '0.1.0',
|
|
757
757
|
build_id: 'rom-build',
|
|
@@ -841,7 +841,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
841
841
|
hw: {
|
|
842
842
|
serial_no: 'PR2BOOT',
|
|
843
843
|
},
|
|
844
|
-
|
|
844
|
+
fw: {
|
|
845
845
|
bootloader: {
|
|
846
846
|
version: '0.2.0',
|
|
847
847
|
},
|
|
@@ -863,7 +863,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
863
863
|
const features = normalizeProtocolV2Features(descriptor as any, {
|
|
864
864
|
protocol_version: 1,
|
|
865
865
|
hw: { serial_no: 'PR2NORMAL' },
|
|
866
|
-
|
|
866
|
+
fw: { bootloader: { version: '0.2.0' } },
|
|
867
867
|
});
|
|
868
868
|
|
|
869
869
|
expect(features.mode).toBe('normal');
|
|
@@ -876,7 +876,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
876
876
|
hw: {
|
|
877
877
|
serial_no: 'PR2ROM',
|
|
878
878
|
},
|
|
879
|
-
|
|
879
|
+
fw: {
|
|
880
880
|
romloader: {
|
|
881
881
|
version: '1.0.0',
|
|
882
882
|
},
|
|
@@ -917,17 +917,17 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
917
917
|
|
|
918
918
|
expect(
|
|
919
919
|
getProtocolV2RuntimeMode(legacyProtocolInfo, {
|
|
920
|
-
|
|
920
|
+
fw: { bootloader: { version: '0.2.0' } },
|
|
921
921
|
})
|
|
922
922
|
).toBe('bootloader');
|
|
923
923
|
expect(
|
|
924
924
|
getProtocolV2RuntimeMode(legacyProtocolInfo, {
|
|
925
|
-
|
|
925
|
+
fw: { romloader: { version: '1.0.0' } },
|
|
926
926
|
})
|
|
927
927
|
).toBe('romloader');
|
|
928
928
|
expect(
|
|
929
929
|
getProtocolV2RuntimeMode(legacyProtocolInfo, {
|
|
930
|
-
|
|
930
|
+
fw: {
|
|
931
931
|
application: { version: '1.2.3' },
|
|
932
932
|
bootloader: { version: '0.2.0' },
|
|
933
933
|
},
|
|
@@ -1998,7 +1998,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
1998
1998
|
{ ...descriptor, protocolType: 'V2' } as any,
|
|
1999
1999
|
{
|
|
2000
2000
|
protocol_version: 2,
|
|
2001
|
-
|
|
2001
|
+
fw: { application: { version: '1.2.3' } },
|
|
2002
2002
|
se1: { application: { version: '4.5.6' } },
|
|
2003
2003
|
status: { unlocked: false, passphrase_enabled: false },
|
|
2004
2004
|
}
|
|
@@ -2035,7 +2035,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
2035
2035
|
deviceInfo: {
|
|
2036
2036
|
protocol_version: 1,
|
|
2037
2037
|
hw: { serial_no: 'PR9999999999' },
|
|
2038
|
-
|
|
2038
|
+
fw: { application: { version: '1.0.0' } },
|
|
2039
2039
|
},
|
|
2040
2040
|
deviceStatus: {
|
|
2041
2041
|
device_id: 'firmware-reconnect-id',
|
|
@@ -2400,7 +2400,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
2400
2400
|
(device as any).features = {
|
|
2401
2401
|
...normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any, {
|
|
2402
2402
|
hw: { serial_no: 'PR2SERIAL' },
|
|
2403
|
-
|
|
2403
|
+
fw: { application: { version: '4.15.0' } },
|
|
2404
2404
|
status: { passphrase_enabled: true },
|
|
2405
2405
|
}),
|
|
2406
2406
|
unlocked: true,
|
|
@@ -2825,7 +2825,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
2825
2825
|
type: 'DeviceInfo',
|
|
2826
2826
|
message: {
|
|
2827
2827
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
2828
|
-
|
|
2828
|
+
fw: { application: { version: '1.2.3' } },
|
|
2829
2829
|
},
|
|
2830
2830
|
}),
|
|
2831
2831
|
};
|
|
@@ -2846,7 +2846,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
2846
2846
|
{
|
|
2847
2847
|
targets: {
|
|
2848
2848
|
hw: true,
|
|
2849
|
-
|
|
2849
|
+
fw: true,
|
|
2850
2850
|
coprocessor: true,
|
|
2851
2851
|
},
|
|
2852
2852
|
types: {
|
|
@@ -2955,7 +2955,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
2955
2955
|
const device = stubDevice({
|
|
2956
2956
|
originalDescriptor: { protocolType: 'V2' },
|
|
2957
2957
|
features: normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any, {
|
|
2958
|
-
|
|
2958
|
+
fw: {
|
|
2959
2959
|
application: {
|
|
2960
2960
|
version: '4.14.0',
|
|
2961
2961
|
},
|
|
@@ -3009,7 +3009,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3009
3009
|
type: 'DeviceInfo',
|
|
3010
3010
|
message: {
|
|
3011
3011
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3012
|
-
|
|
3012
|
+
fw: { application: { version: '1.2.3' } },
|
|
3013
3013
|
},
|
|
3014
3014
|
})
|
|
3015
3015
|
.mockResolvedValueOnce({
|
|
@@ -3044,7 +3044,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3044
3044
|
{
|
|
3045
3045
|
targets: {
|
|
3046
3046
|
hw: true,
|
|
3047
|
-
|
|
3047
|
+
fw: true,
|
|
3048
3048
|
coprocessor: true,
|
|
3049
3049
|
},
|
|
3050
3050
|
types: {
|
|
@@ -3073,7 +3073,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3073
3073
|
type: 'DeviceInfo',
|
|
3074
3074
|
message: {
|
|
3075
3075
|
hw: { serial_no: 'PR2SERIAL' },
|
|
3076
|
-
|
|
3076
|
+
fw: { bootloader: { version: '0.2.0' } },
|
|
3077
3077
|
se1: {},
|
|
3078
3078
|
},
|
|
3079
3079
|
})
|
|
@@ -3123,7 +3123,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3123
3123
|
|
|
3124
3124
|
await device.probeProtocolV2RuntimeState({
|
|
3125
3125
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3126
|
-
|
|
3126
|
+
fw: { romloader: { version: '1.0.0' } },
|
|
3127
3127
|
});
|
|
3128
3128
|
|
|
3129
3129
|
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
@@ -3151,7 +3151,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3151
3151
|
await expect(
|
|
3152
3152
|
device.probeProtocolV2RuntimeState({
|
|
3153
3153
|
hw: { Device_type: DeviceType.PRO, serial_no: 'PRO-SERIAL' },
|
|
3154
|
-
|
|
3154
|
+
fw: { romloader: { version: '1.0.0' } },
|
|
3155
3155
|
})
|
|
3156
3156
|
).rejects.toMatchObject({ errorCode: HardwareErrorCode.DeviceInitializeFailed });
|
|
3157
3157
|
|
|
@@ -3176,7 +3176,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3176
3176
|
|
|
3177
3177
|
await device.probeProtocolV2RuntimeState({
|
|
3178
3178
|
hw: { serial_no: 'PR2SERIAL' },
|
|
3179
|
-
|
|
3179
|
+
fw: { application: { version: '1.2.3' } },
|
|
3180
3180
|
});
|
|
3181
3181
|
|
|
3182
3182
|
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
@@ -3208,7 +3208,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3208
3208
|
|
|
3209
3209
|
await device.probeProtocolV2RuntimeState({
|
|
3210
3210
|
hw: { serial_no: 'PR2SERIAL' },
|
|
3211
|
-
|
|
3211
|
+
fw: { application: { version: '1.2.3' } },
|
|
3212
3212
|
});
|
|
3213
3213
|
|
|
3214
3214
|
expect(typedCall).toHaveBeenCalledTimes(2);
|
|
@@ -3236,7 +3236,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3236
3236
|
|
|
3237
3237
|
await device.probeProtocolV2RuntimeState({
|
|
3238
3238
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3239
|
-
|
|
3239
|
+
fw: { bootloader: { version: '0.2.0' } },
|
|
3240
3240
|
});
|
|
3241
3241
|
|
|
3242
3242
|
expect(device.features).toMatchObject({
|
|
@@ -3265,7 +3265,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3265
3265
|
await expect(
|
|
3266
3266
|
device.probeProtocolV2RuntimeState({
|
|
3267
3267
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3268
|
-
|
|
3268
|
+
fw: { application: { version: '1.2.3' } },
|
|
3269
3269
|
})
|
|
3270
3270
|
).rejects.toBe(linkError);
|
|
3271
3271
|
|
|
@@ -3290,7 +3290,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3290
3290
|
await expect(
|
|
3291
3291
|
device.probeProtocolV2RuntimeState({
|
|
3292
3292
|
hw: { serial_no: 'PR2SERIAL' },
|
|
3293
|
-
|
|
3293
|
+
fw: { application: { version: '1.2.3' } },
|
|
3294
3294
|
})
|
|
3295
3295
|
).rejects.toMatchObject({ errorCode: HardwareErrorCode.DeviceInitializeFailed });
|
|
3296
3296
|
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
@@ -3307,7 +3307,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3307
3307
|
type: 'DeviceInfo',
|
|
3308
3308
|
message: {
|
|
3309
3309
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3310
|
-
|
|
3310
|
+
fw: { bootloader: { version: '0.2.0' } },
|
|
3311
3311
|
},
|
|
3312
3312
|
})
|
|
3313
3313
|
.mockResolvedValueOnce({
|
|
@@ -3357,7 +3357,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3357
3357
|
await device.probeProtocolV2RuntimeState(
|
|
3358
3358
|
{
|
|
3359
3359
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3360
|
-
|
|
3360
|
+
fw: { application: { version: '1.2.3' } },
|
|
3361
3361
|
},
|
|
3362
3362
|
5000
|
|
3363
3363
|
);
|
|
@@ -3402,7 +3402,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3402
3402
|
|
|
3403
3403
|
await device.probeProtocolV2RuntimeState({
|
|
3404
3404
|
hw: { Device_type: DeviceType.NEO, serial_no: 'NEOSERIAL' },
|
|
3405
|
-
|
|
3405
|
+
fw: { bootloader: { version: '0.2.0' } },
|
|
3406
3406
|
});
|
|
3407
3407
|
|
|
3408
3408
|
expect(typedCall).toHaveBeenNthCalledWith(1, 'ProtocolInfoRequest', 'ProtocolInfo', {
|
|
@@ -3436,7 +3436,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3436
3436
|
|
|
3437
3437
|
await device.probeProtocolV2RuntimeState({
|
|
3438
3438
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3439
|
-
|
|
3439
|
+
fw: { romloader: { version: '1.0.0' } },
|
|
3440
3440
|
});
|
|
3441
3441
|
|
|
3442
3442
|
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
@@ -3474,7 +3474,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3474
3474
|
await expect(
|
|
3475
3475
|
device.probeProtocolV2RuntimeState({
|
|
3476
3476
|
hw: { serial_no: 'PR2SERIAL' },
|
|
3477
|
-
|
|
3477
|
+
fw: { application: { version: '1.0.0' } },
|
|
3478
3478
|
})
|
|
3479
3479
|
).rejects.toThrow('state update failed');
|
|
3480
3480
|
|
|
@@ -3499,7 +3499,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3499
3499
|
type: 'DeviceInfo',
|
|
3500
3500
|
message: {
|
|
3501
3501
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3502
|
-
|
|
3502
|
+
fw: { application: { version: '1.2.3' } },
|
|
3503
3503
|
},
|
|
3504
3504
|
})
|
|
3505
3505
|
.mockResolvedValueOnce({
|
|
@@ -3514,7 +3514,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3514
3514
|
type: 'DeviceInfo',
|
|
3515
3515
|
message: {
|
|
3516
3516
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3517
|
-
|
|
3517
|
+
fw: { application: { version: '1.2.4' } },
|
|
3518
3518
|
},
|
|
3519
3519
|
})
|
|
3520
3520
|
.mockResolvedValueOnce({
|
|
@@ -3546,7 +3546,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3546
3546
|
{
|
|
3547
3547
|
targets: {
|
|
3548
3548
|
hw: true,
|
|
3549
|
-
|
|
3549
|
+
fw: true,
|
|
3550
3550
|
coprocessor: true,
|
|
3551
3551
|
},
|
|
3552
3552
|
types: {
|
|
@@ -3567,7 +3567,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3567
3567
|
type: 'DeviceInfo',
|
|
3568
3568
|
message: {
|
|
3569
3569
|
hw: { serial_no: 'PR2SERIAL' },
|
|
3570
|
-
|
|
3570
|
+
fw: { application: { version: '1.2.4' } },
|
|
3571
3571
|
},
|
|
3572
3572
|
})
|
|
3573
3573
|
.mockResolvedValueOnce({
|
|
@@ -3644,7 +3644,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3644
3644
|
{ ...descriptor, protocolType: 'V2' } as any,
|
|
3645
3645
|
{
|
|
3646
3646
|
hw: { Device_type: DeviceType.PRO2, serial_no: 'PR2SERIAL' },
|
|
3647
|
-
|
|
3647
|
+
fw: { application: { version: '1.2.3' } },
|
|
3648
3648
|
status: { init_states: true },
|
|
3649
3649
|
}
|
|
3650
3650
|
);
|
|
@@ -3684,7 +3684,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3684
3684
|
{ ...descriptor, protocolType: 'V2' } as any,
|
|
3685
3685
|
{
|
|
3686
3686
|
hw: { serial_no: 'PR2SERIAL' },
|
|
3687
|
-
|
|
3687
|
+
fw: { application: { version: '4.15.0' } },
|
|
3688
3688
|
status: { passphrase_enabled: false },
|
|
3689
3689
|
}
|
|
3690
3690
|
);
|
|
@@ -3731,7 +3731,7 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
3731
3731
|
(device as any).features = normalizeProtocolV2Features(
|
|
3732
3732
|
{ ...descriptor, protocolType: 'V2' } as any,
|
|
3733
3733
|
{
|
|
3734
|
-
|
|
3734
|
+
fw: { application: { version: '1.2.3' } },
|
|
3735
3735
|
status: { unlocked: false },
|
|
3736
3736
|
}
|
|
3737
3737
|
);
|
|
@@ -4160,7 +4160,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
4160
4160
|
type: 'DeviceInfo',
|
|
4161
4161
|
message: {
|
|
4162
4162
|
hw: { serial_no: 'BLE-PRO2-SERIAL' },
|
|
4163
|
-
|
|
4163
|
+
fw: {
|
|
4164
4164
|
bootloader: { version: '0.0.0' },
|
|
4165
4165
|
application: { version: '0.0.0' },
|
|
4166
4166
|
},
|
|
@@ -4212,7 +4212,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
4212
4212
|
{
|
|
4213
4213
|
targets: {
|
|
4214
4214
|
hw: true,
|
|
4215
|
-
|
|
4215
|
+
fw: true,
|
|
4216
4216
|
coprocessor: true,
|
|
4217
4217
|
se1: true,
|
|
4218
4218
|
se2: true,
|
|
@@ -4631,6 +4631,43 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
4631
4631
|
expect(method.postTipMessage).toHaveBeenCalledWith('GoToBootloaderSuccess');
|
|
4632
4632
|
});
|
|
4633
4633
|
|
|
4634
|
+
test('keeps an ambiguous legacy runtime on the direct loader update path', async () => {
|
|
4635
|
+
const method = new FirmwareUpdateV4({
|
|
4636
|
+
id: 1,
|
|
4637
|
+
payload: {
|
|
4638
|
+
method: 'firmwareUpdateV4',
|
|
4639
|
+
},
|
|
4640
|
+
});
|
|
4641
|
+
(method as any).device = stubDevice({
|
|
4642
|
+
originalDescriptor: { id: 'usb-id', path: 'legacy-path', protocolType: 'V2' },
|
|
4643
|
+
state: {
|
|
4644
|
+
raw: {
|
|
4645
|
+
protocolV2ProtocolInfo: {
|
|
4646
|
+
version: 1,
|
|
4647
|
+
build_fingerprint: '',
|
|
4648
|
+
supported_messages: [],
|
|
4649
|
+
protobuf_definition: null,
|
|
4650
|
+
},
|
|
4651
|
+
},
|
|
4652
|
+
},
|
|
4653
|
+
features: {
|
|
4654
|
+
deviceType: 'pro2',
|
|
4655
|
+
mode: 'bootloader',
|
|
4656
|
+
bootloaderMode: true,
|
|
4657
|
+
capabilities: [],
|
|
4658
|
+
},
|
|
4659
|
+
isBootloader: () => true,
|
|
4660
|
+
isRomloader: () => false,
|
|
4661
|
+
});
|
|
4662
|
+
(method as any).protocolV2Reboot = jest.fn();
|
|
4663
|
+
method.postTipMessage = jest.fn();
|
|
4664
|
+
|
|
4665
|
+
await expect((method as any).enterProtocolV2BootloaderMode()).resolves.toBe(false);
|
|
4666
|
+
|
|
4667
|
+
expect((method as any).protocolV2LegacyDirectUpdate).toBe(true);
|
|
4668
|
+
expect((method as any).protocolV2Reboot).not.toHaveBeenCalled();
|
|
4669
|
+
});
|
|
4670
|
+
|
|
4634
4671
|
test('keeps Protocol V2 romloader active before firmware transfer', async () => {
|
|
4635
4672
|
const method = new FirmwareUpdateV4({
|
|
4636
4673
|
id: 1,
|
|
@@ -5079,7 +5116,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5079
5116
|
type: 'DeviceInfo',
|
|
5080
5117
|
message: {
|
|
5081
5118
|
hw: { serial_no: 'PR2SERIAL' },
|
|
5082
|
-
|
|
5119
|
+
fw: { application: { version: '1.0.0' } },
|
|
5083
5120
|
},
|
|
5084
5121
|
});
|
|
5085
5122
|
(method as any).protocolV2ExpectedSerialNumber = 'expected-serial';
|
|
@@ -5206,50 +5243,49 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5206
5243
|
);
|
|
5207
5244
|
});
|
|
5208
5245
|
|
|
5209
|
-
test('
|
|
5246
|
+
test('requires an explicit Protocol V2 update ACK before entering install state', async () => {
|
|
5210
5247
|
const method = new FirmwareUpdateV4({
|
|
5211
5248
|
id: 1,
|
|
5212
5249
|
payload: {
|
|
5213
5250
|
method: 'firmwareUpdateV4',
|
|
5214
5251
|
},
|
|
5215
5252
|
});
|
|
5216
|
-
const
|
|
5217
|
-
|
|
5218
|
-
|
|
5253
|
+
const typedCall = jest
|
|
5254
|
+
.fn()
|
|
5255
|
+
.mockRejectedValue(
|
|
5256
|
+
Object.assign(
|
|
5257
|
+
new Error("Failed to execute 'open' on 'USBDevice': The device was disconnected"),
|
|
5258
|
+
{ name: 'NotFoundError' }
|
|
5259
|
+
)
|
|
5260
|
+
);
|
|
5219
5261
|
|
|
5220
5262
|
(method as any).device = stubDevice({
|
|
5221
|
-
getCommands: () => ({ typedCall
|
|
5263
|
+
getCommands: () => ({ typedCall }),
|
|
5222
5264
|
});
|
|
5223
5265
|
method.postTipMessage = jest.fn();
|
|
5224
5266
|
method.postProgressMessage = jest.fn();
|
|
5225
5267
|
|
|
5226
5268
|
await expect(
|
|
5227
|
-
(method as any).protocolV2StartFirmwareUpdate({
|
|
5228
|
-
|
|
5269
|
+
(method as any).protocolV2StartFirmwareUpdate({
|
|
5270
|
+
targets: [{ target_id: 4, path: 'vol1:firmware.bin' }],
|
|
5271
|
+
})
|
|
5272
|
+
).rejects.toThrow();
|
|
5229
5273
|
|
|
5230
|
-
expect(
|
|
5231
|
-
expect(
|
|
5232
|
-
'DeviceFirmwareUpdateRequest',
|
|
5233
|
-
{},
|
|
5234
|
-
{ returnAfterWrite: true }
|
|
5235
|
-
);
|
|
5236
|
-
expect(typedCall.mock.invocationCallOrder[0]).toBeLessThan(call.mock.invocationCallOrder[0]);
|
|
5237
|
-
expect(method.postTipMessage).toHaveBeenCalledWith('FirmwareUpdating');
|
|
5238
|
-
expect(method.postProgressMessage).toHaveBeenCalledWith(0, 'installingFirmware');
|
|
5274
|
+
expect(method.postTipMessage).not.toHaveBeenCalled();
|
|
5275
|
+
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
5239
5276
|
});
|
|
5240
5277
|
|
|
5241
|
-
test('does not
|
|
5278
|
+
test('does not poll Protocol V2 install status when the update ACK times out', async () => {
|
|
5242
5279
|
const method = new FirmwareUpdateV4({
|
|
5243
5280
|
id: 1,
|
|
5244
5281
|
payload: {
|
|
5245
5282
|
method: 'firmwareUpdateV4',
|
|
5246
5283
|
},
|
|
5247
5284
|
});
|
|
5248
|
-
const typedCall = jest.fn().mockRejectedValue(new Error('
|
|
5249
|
-
const call = jest.fn();
|
|
5285
|
+
const typedCall = jest.fn().mockRejectedValue(new Error('LIBUSB_TRANSFER_TIMED_OUT'));
|
|
5250
5286
|
|
|
5251
5287
|
(method as any).device = stubDevice({
|
|
5252
|
-
getCommands: () => ({ typedCall
|
|
5288
|
+
getCommands: () => ({ typedCall }),
|
|
5253
5289
|
});
|
|
5254
5290
|
method.postTipMessage = jest.fn();
|
|
5255
5291
|
method.postProgressMessage = jest.fn();
|
|
@@ -5258,26 +5294,78 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5258
5294
|
(method as any).protocolV2StartFirmwareUpdate({
|
|
5259
5295
|
targets: [{ target_id: 4, path: 'vol1:application_p1.bin' }],
|
|
5260
5296
|
})
|
|
5261
|
-
).rejects.toThrow('
|
|
5297
|
+
).rejects.toThrow('LIBUSB_TRANSFER_TIMED_OUT');
|
|
5262
5298
|
|
|
5263
|
-
expect(call).not.toHaveBeenCalled();
|
|
5264
5299
|
expect(method.postTipMessage).not.toHaveBeenCalled();
|
|
5265
5300
|
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
5266
5301
|
});
|
|
5267
5302
|
|
|
5268
|
-
test(
|
|
5303
|
+
test.each([
|
|
5304
|
+
'Failure_InvalidMessage,Handler not registered',
|
|
5305
|
+
'Failure_InvalidMessage,Unsupported message',
|
|
5306
|
+
])('reboots a legacy App when the direct update endpoint is unavailable: %s', async message => {
|
|
5307
|
+
const method = new FirmwareUpdateV4({
|
|
5308
|
+
id: 1,
|
|
5309
|
+
payload: {
|
|
5310
|
+
method: 'firmwareUpdateV4',
|
|
5311
|
+
},
|
|
5312
|
+
});
|
|
5313
|
+
const targets = [{ target_id: 4, path: 'vol0:/application_p1.bin' }];
|
|
5314
|
+
const appTypedCall = jest.fn().mockRejectedValueOnce(new Error(message));
|
|
5315
|
+
const bootloaderTypedCall = jest
|
|
5316
|
+
.fn()
|
|
5317
|
+
.mockResolvedValueOnce({ type: 'Success', message: { message: '' } });
|
|
5318
|
+
let activeCommands = { typedCall: appTypedCall };
|
|
5319
|
+
|
|
5320
|
+
(method as any).device = stubDevice({
|
|
5321
|
+
getCommands: () => activeCommands,
|
|
5322
|
+
});
|
|
5323
|
+
(method as any).protocolV2LegacyDirectUpdate = true;
|
|
5324
|
+
(method as any).rebootProtocolV2ToBootloader = jest.fn().mockImplementation(() => {
|
|
5325
|
+
activeCommands = { typedCall: bootloaderTypedCall };
|
|
5326
|
+
return Promise.resolve(true);
|
|
5327
|
+
});
|
|
5328
|
+
method.postTipMessage = jest.fn();
|
|
5329
|
+
method.postProgressMessage = jest.fn();
|
|
5330
|
+
|
|
5331
|
+
await expect((method as any).protocolV2StartFirmwareUpdate({ targets })).resolves.toEqual({
|
|
5332
|
+
type: 'Success',
|
|
5333
|
+
message: { message: '' },
|
|
5334
|
+
});
|
|
5335
|
+
|
|
5336
|
+
expect(appTypedCall).toHaveBeenCalledTimes(1);
|
|
5337
|
+
expect(appTypedCall).toHaveBeenCalledWith(
|
|
5338
|
+
'DeviceFirmwareUpdateRequest',
|
|
5339
|
+
'Success',
|
|
5340
|
+
{ targets },
|
|
5341
|
+
{ timeoutMs: 180000 }
|
|
5342
|
+
);
|
|
5343
|
+
expect(bootloaderTypedCall).toHaveBeenCalledTimes(1);
|
|
5344
|
+
expect(bootloaderTypedCall).toHaveBeenCalledWith(
|
|
5345
|
+
'DeviceFirmwareUpdateRequest',
|
|
5346
|
+
'Success',
|
|
5347
|
+
{ targets },
|
|
5348
|
+
{ timeoutMs: 180000 }
|
|
5349
|
+
);
|
|
5350
|
+
expect((method as any).rebootProtocolV2ToBootloader).toHaveBeenCalledTimes(1);
|
|
5351
|
+
expect(method.postTipMessage).toHaveBeenCalledWith('FirmwareUpdating');
|
|
5352
|
+
expect(method.postProgressMessage).toHaveBeenCalledWith(0, 'installingFirmware');
|
|
5353
|
+
});
|
|
5354
|
+
|
|
5355
|
+
test('does not replay a legacy direct update after a link failure', async () => {
|
|
5269
5356
|
const method = new FirmwareUpdateV4({
|
|
5270
5357
|
id: 1,
|
|
5271
5358
|
payload: {
|
|
5272
5359
|
method: 'firmwareUpdateV4',
|
|
5273
5360
|
},
|
|
5274
5361
|
});
|
|
5275
|
-
const typedCall = jest.fn().
|
|
5276
|
-
const call = jest.fn().mockRejectedValue(new Error('write failed'));
|
|
5362
|
+
const typedCall = jest.fn().mockRejectedValue(new Error('LIBUSB_TRANSFER_TIMED_OUT'));
|
|
5277
5363
|
|
|
5278
5364
|
(method as any).device = stubDevice({
|
|
5279
|
-
getCommands: () => ({ typedCall
|
|
5365
|
+
getCommands: () => ({ typedCall }),
|
|
5280
5366
|
});
|
|
5367
|
+
(method as any).protocolV2LegacyDirectUpdate = true;
|
|
5368
|
+
(method as any).rebootProtocolV2ToBootloader = jest.fn();
|
|
5281
5369
|
method.postTipMessage = jest.fn();
|
|
5282
5370
|
method.postProgressMessage = jest.fn();
|
|
5283
5371
|
|
|
@@ -5285,9 +5373,10 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5285
5373
|
(method as any).protocolV2StartFirmwareUpdate({
|
|
5286
5374
|
targets: [{ target_id: 4, path: 'vol0:/application_p1.bin' }],
|
|
5287
5375
|
})
|
|
5288
|
-
).rejects.toThrow('
|
|
5376
|
+
).rejects.toThrow('LIBUSB_TRANSFER_TIMED_OUT');
|
|
5289
5377
|
|
|
5290
|
-
expect(
|
|
5378
|
+
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
5379
|
+
expect((method as any).rebootProtocolV2ToBootloader).not.toHaveBeenCalled();
|
|
5291
5380
|
expect(method.postTipMessage).not.toHaveBeenCalled();
|
|
5292
5381
|
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
5293
5382
|
});
|
|
@@ -5335,21 +5424,26 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5335
5424
|
expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
|
|
5336
5425
|
});
|
|
5337
5426
|
|
|
5338
|
-
test('accepts
|
|
5427
|
+
test('accepts a missing firmware status handler only after confirming normal mode', async () => {
|
|
5339
5428
|
const method = new FirmwareUpdateV4({
|
|
5340
5429
|
id: 1,
|
|
5341
5430
|
payload: {
|
|
5342
5431
|
method: 'firmwareUpdateV4',
|
|
5343
5432
|
},
|
|
5344
5433
|
});
|
|
5345
|
-
const typedCall = jest
|
|
5434
|
+
const typedCall = jest
|
|
5435
|
+
.fn()
|
|
5436
|
+
.mockRejectedValue(new Error('Failure: Handler not registered for this message'));
|
|
5346
5437
|
const reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
|
|
5347
5438
|
|
|
5348
5439
|
(method as any).device = stubDevice({
|
|
5349
5440
|
getCommands: () => ({ typedCall }),
|
|
5350
5441
|
});
|
|
5351
5442
|
(method as any).reconnectProtocolV2Device = reconnectProtocolV2Device;
|
|
5352
|
-
|
|
5443
|
+
const deviceInfo = { hw: { serial_no: 'PRO2-PHYSICAL-1' } };
|
|
5444
|
+
(method as any).verifyProtocolV2ReconnectIdentity = jest.fn().mockResolvedValue(deviceInfo);
|
|
5445
|
+
(method as any).probeProtocolV2NormalMode = jest.fn().mockResolvedValue(true);
|
|
5446
|
+
(method as any).protocolV2InstallAckReceived = true;
|
|
5353
5447
|
method.postProgressMessage = jest.fn();
|
|
5354
5448
|
|
|
5355
5449
|
await (method as any).waitForProtocolV2FirmwareUpdateComplete([
|
|
@@ -5358,7 +5452,47 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5358
5452
|
|
|
5359
5453
|
expect(reconnectProtocolV2Device).toHaveBeenCalledTimes(1);
|
|
5360
5454
|
expect(typedCall.mock.calls.map(call => call[0])).toEqual(['DeviceFirmwareUpdateStatusGet']);
|
|
5361
|
-
expect((method as any).
|
|
5455
|
+
expect((method as any).probeProtocolV2NormalMode).toHaveBeenCalledWith(deviceInfo);
|
|
5456
|
+
expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
|
|
5457
|
+
});
|
|
5458
|
+
|
|
5459
|
+
test('accepts an empty firmware status dump only after confirming normal mode', async () => {
|
|
5460
|
+
const method = new FirmwareUpdateV4({
|
|
5461
|
+
id: 1,
|
|
5462
|
+
payload: {
|
|
5463
|
+
method: 'firmwareUpdateV4',
|
|
5464
|
+
},
|
|
5465
|
+
});
|
|
5466
|
+
const typedCall = jest.fn().mockResolvedValue({
|
|
5467
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
5468
|
+
message: { records: [] },
|
|
5469
|
+
});
|
|
5470
|
+
const deviceInfo = { hw: { serial_no: 'PRO2-PHYSICAL-1' } };
|
|
5471
|
+
let now = 0;
|
|
5472
|
+
jest.spyOn(Date, 'now').mockImplementation(() => now);
|
|
5473
|
+
jest.spyOn(global, 'setTimeout').mockImplementation(((callback: () => void) => {
|
|
5474
|
+
now += 31 * 1000;
|
|
5475
|
+
callback();
|
|
5476
|
+
return 0 as any;
|
|
5477
|
+
}) as typeof setTimeout);
|
|
5478
|
+
|
|
5479
|
+
(method as any).device = stubDevice({
|
|
5480
|
+
getCommands: () => ({ typedCall }),
|
|
5481
|
+
});
|
|
5482
|
+
(method as any).reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
|
|
5483
|
+
(method as any).verifyProtocolV2ReconnectIdentity = jest.fn().mockResolvedValue(deviceInfo);
|
|
5484
|
+
(method as any).probeProtocolV2NormalMode = jest.fn().mockResolvedValue(true);
|
|
5485
|
+
(method as any).protocolV2InstallAckReceived = true;
|
|
5486
|
+
method.postProgressMessage = jest.fn();
|
|
5487
|
+
|
|
5488
|
+
await expect(
|
|
5489
|
+
(method as any).waitForProtocolV2FirmwareUpdateComplete([
|
|
5490
|
+
{ target_id: 4, path: 'vol0:/application_p1.bin' },
|
|
5491
|
+
])
|
|
5492
|
+
).resolves.toBeUndefined();
|
|
5493
|
+
|
|
5494
|
+
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
5495
|
+
expect((method as any).probeProtocolV2NormalMode).toHaveBeenCalledWith(deviceInfo);
|
|
5362
5496
|
expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
|
|
5363
5497
|
});
|
|
5364
5498
|
|
|
@@ -5672,7 +5806,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5672
5806
|
);
|
|
5673
5807
|
});
|
|
5674
5808
|
|
|
5675
|
-
test('polls target status after
|
|
5809
|
+
test('polls target status after update ACK and finishes when all targets complete', async () => {
|
|
5676
5810
|
const method = new FirmwareUpdateV4({
|
|
5677
5811
|
id: 1,
|
|
5678
5812
|
payload: {
|
|
@@ -5707,7 +5841,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5707
5841
|
expect(reconnectProtocolV2Device).toHaveBeenCalledTimes(1);
|
|
5708
5842
|
expect(typedCall).toHaveBeenCalledWith(
|
|
5709
5843
|
'DeviceFirmwareUpdateStatusGet',
|
|
5710
|
-
|
|
5844
|
+
'DeviceFirmwareUpdateStatus',
|
|
5711
5845
|
expect.anything(),
|
|
5712
5846
|
expect.anything()
|
|
5713
5847
|
);
|
|
@@ -5983,7 +6117,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5983
6117
|
});
|
|
5984
6118
|
expect(typedCall).toHaveBeenCalledWith(
|
|
5985
6119
|
'DeviceFirmwareUpdateStatusGet',
|
|
5986
|
-
|
|
6120
|
+
'DeviceFirmwareUpdateStatus',
|
|
5987
6121
|
{
|
|
5988
6122
|
fields: {
|
|
5989
6123
|
status: true,
|
|
@@ -7183,10 +7317,9 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7183
7317
|
],
|
|
7184
7318
|
};
|
|
7185
7319
|
const zip = new JSZip();
|
|
7186
|
-
zip.file('
|
|
7187
|
-
zip.file('
|
|
7188
|
-
zip.file('
|
|
7189
|
-
zip.file('pro2-resource/build-info.txt', 'ignored');
|
|
7320
|
+
zip.file('manifest.json', JSON.stringify(manifest));
|
|
7321
|
+
zip.file('bundles/images/images.okpkg', imagesBinary);
|
|
7322
|
+
zip.file('loaders/bootloader/boot_resource.okpkg', bootResourceBinary);
|
|
7190
7323
|
const resourceArchiveBinary = await zip.generateAsync({ type: 'arraybuffer' });
|
|
7191
7324
|
const applicationP1Binary = new Uint8Array([7, 8, 9]).buffer;
|
|
7192
7325
|
const bootloaderBinary = new Uint8Array([10, 11, 12]).buffer;
|
|
@@ -7262,39 +7395,6 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7262
7395
|
}
|
|
7263
7396
|
});
|
|
7264
7397
|
|
|
7265
|
-
test('accepts a local resource ZIP without manifest.json', async () => {
|
|
7266
|
-
const imagesBinary = new Uint8Array([1, 2, 3]).buffer;
|
|
7267
|
-
const bootResourceBinary = new Uint8Array([4, 5, 6]).buffer;
|
|
7268
|
-
const zip = new JSZip();
|
|
7269
|
-
zip.file('pro2-resource/bundles/images/images.okpkg', imagesBinary);
|
|
7270
|
-
zip.file('pro2-resource/loaders/bootloader/boot_resource.okpkg', bootResourceBinary);
|
|
7271
|
-
zip.file('pro2-resource/build-info.txt', 'ignored');
|
|
7272
|
-
const method = new FirmwareUpdateV4({
|
|
7273
|
-
id: 1,
|
|
7274
|
-
payload: {
|
|
7275
|
-
method: 'firmwareUpdateV4',
|
|
7276
|
-
platform: 'web',
|
|
7277
|
-
targetsToUpdate: ['resource'],
|
|
7278
|
-
},
|
|
7279
|
-
});
|
|
7280
|
-
method.init();
|
|
7281
|
-
|
|
7282
|
-
await expect(
|
|
7283
|
-
(method as any).prepareProtocolV2LocalResourceArchive(
|
|
7284
|
-
await zip.generateAsync({ type: 'arraybuffer' })
|
|
7285
|
-
)
|
|
7286
|
-
).resolves.toMatchObject({
|
|
7287
|
-
materializedEntries: [
|
|
7288
|
-
{ entryName: 'manifest.json' },
|
|
7289
|
-
{ entryName: 'bundles/images/images.okpkg', binary: imagesBinary },
|
|
7290
|
-
{
|
|
7291
|
-
entryName: 'loaders/bootloader/boot_resource.okpkg',
|
|
7292
|
-
binary: bootResourceBinary,
|
|
7293
|
-
},
|
|
7294
|
-
],
|
|
7295
|
-
});
|
|
7296
|
-
});
|
|
7297
|
-
|
|
7298
7398
|
test('rejects a local resource ZIP whose file hash does not match its manifest', async () => {
|
|
7299
7399
|
const resourceBinary = new Uint8Array([1, 2, 3]).buffer;
|
|
7300
7400
|
const bootResourceBinary = new Uint8Array([4, 5, 6]).buffer;
|
|
@@ -7385,57 +7485,18 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7385
7485
|
|
|
7386
7486
|
test('rejects an oversized ZIP entry before allocating its decompressed bytes', async () => {
|
|
7387
7487
|
const extractEntry = jest.fn();
|
|
7388
|
-
const
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
size: oversizedFileSize,
|
|
7397
|
-
sha256: '0'.repeat(64),
|
|
7398
|
-
signed: true,
|
|
7399
|
-
sig_algo: 'ed25519',
|
|
7400
|
-
},
|
|
7401
|
-
{
|
|
7402
|
-
archive_path: 'bundles/images/images.okpkg',
|
|
7403
|
-
original_name: 'images.okpkg',
|
|
7404
|
-
device_path: 'vol0:/bundles/images/images.okpkg',
|
|
7405
|
-
size: oversizedFileSize,
|
|
7406
|
-
sha256: '0'.repeat(64),
|
|
7407
|
-
signed: true,
|
|
7408
|
-
sig_algo: 'ed25519',
|
|
7488
|
+
const loadSpy = jest.spyOn(JSZip, 'loadAsync').mockResolvedValue({
|
|
7489
|
+
files: {
|
|
7490
|
+
'manifest.json': {
|
|
7491
|
+
name: 'manifest.json',
|
|
7492
|
+
dir: false,
|
|
7493
|
+
_data: {
|
|
7494
|
+
compressedSize: 1,
|
|
7495
|
+
uncompressedSize: 2 * 1024 * 1024,
|
|
7409
7496
|
},
|
|
7410
|
-
|
|
7411
|
-
})
|
|
7412
|
-
);
|
|
7413
|
-
const zipFiles = {
|
|
7414
|
-
'manifest.json': {
|
|
7415
|
-
name: 'manifest.json',
|
|
7416
|
-
dir: false,
|
|
7417
|
-
_data: {
|
|
7418
|
-
compressedSize: manifestBinary.byteLength,
|
|
7419
|
-
uncompressedSize: manifestBinary.byteLength,
|
|
7497
|
+
async: extractEntry,
|
|
7420
7498
|
},
|
|
7421
|
-
async: jest.fn().mockResolvedValue(manifestBinary.buffer),
|
|
7422
|
-
},
|
|
7423
|
-
'loaders/bootloader/boot_resource.okpkg': {
|
|
7424
|
-
name: 'loaders/bootloader/boot_resource.okpkg',
|
|
7425
|
-
dir: false,
|
|
7426
|
-
_data: { compressedSize: 1, uncompressedSize: oversizedFileSize },
|
|
7427
|
-
async: extractEntry,
|
|
7428
7499
|
},
|
|
7429
|
-
'bundles/images/images.okpkg': {
|
|
7430
|
-
name: 'bundles/images/images.okpkg',
|
|
7431
|
-
dir: false,
|
|
7432
|
-
_data: { compressedSize: 1, uncompressedSize: oversizedFileSize },
|
|
7433
|
-
async: extractEntry,
|
|
7434
|
-
},
|
|
7435
|
-
};
|
|
7436
|
-
const loadSpy = jest.spyOn(JSZip, 'loadAsync').mockResolvedValue({
|
|
7437
|
-
files: zipFiles,
|
|
7438
|
-
file: (name: string) => zipFiles[name as keyof typeof zipFiles] ?? null,
|
|
7439
7500
|
} as unknown as JSZip);
|
|
7440
7501
|
const method = new FirmwareUpdateV4({
|
|
7441
7502
|
id: 1,
|
|
@@ -7450,7 +7511,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7450
7511
|
try {
|
|
7451
7512
|
await expect(
|
|
7452
7513
|
(method as any).prepareProtocolV2LocalResourceArchive(new Uint8Array([1]).buffer)
|
|
7453
|
-
).rejects.toThrow('declared size
|
|
7514
|
+
).rejects.toThrow('declared size exceeds the allowed limit');
|
|
7454
7515
|
expect(extractEntry).not.toHaveBeenCalled();
|
|
7455
7516
|
} finally {
|
|
7456
7517
|
loadSpy.mockRestore();
|
|
@@ -7746,7 +7807,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7746
7807
|
expect(writePayloads.map(payload => payload.file.data.byteLength)).toEqual([4000, 97]);
|
|
7747
7808
|
expect(writePayloads.map(payload => payload.overwrite)).toEqual([true, false]);
|
|
7748
7809
|
expect(writePayloads.every(payload => payload.append === false)).toBe(true);
|
|
7749
|
-
expect(writePayloads.map(payload => payload.ui_percentage)).toEqual([0,
|
|
7810
|
+
expect(writePayloads.map(payload => payload.ui_percentage)).toEqual([0, 100]);
|
|
7750
7811
|
expect(method.postMessage).toHaveBeenLastCalledWith({
|
|
7751
7812
|
event: 'UI_EVENT',
|
|
7752
7813
|
type: UI_REQUEST.FIRMWARE_PROGRESS,
|
|
@@ -7827,9 +7888,9 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7827
7888
|
|
|
7828
7889
|
const writePayloads = typedCall.mock.calls.map(call => call[2]);
|
|
7829
7890
|
const deviceProgress = writePayloads.map(payload => payload.ui_percentage);
|
|
7830
|
-
expect(deviceProgress).toEqual([0, 50, 99,
|
|
7891
|
+
expect(deviceProgress).toEqual([0, 50, 99, 100]);
|
|
7831
7892
|
expect(deviceProgress.filter(progress => progress === 0)).toHaveLength(1);
|
|
7832
|
-
expect(deviceProgress.filter(progress => progress === 100)).toHaveLength(
|
|
7893
|
+
expect(deviceProgress.filter(progress => progress === 100)).toHaveLength(1);
|
|
7833
7894
|
expect(method.postTipMessage).toHaveBeenCalledTimes(2);
|
|
7834
7895
|
expect(method.postTipMessage).toHaveBeenNthCalledWith(1, 'StartTransferData');
|
|
7835
7896
|
expect(method.postTipMessage).toHaveBeenNthCalledWith(2, 'ConfirmOnDevice');
|
|
@@ -8147,7 +8208,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8147
8208
|
const writePayloads = typedCall.mock.calls.map(call => call[2]);
|
|
8148
8209
|
expect(writePayloads.map(payload => payload.file.offset)).toEqual([0, 1800]);
|
|
8149
8210
|
expect(writePayloads.map(payload => payload.file.data.byteLength)).toEqual([1800, 1]);
|
|
8150
|
-
expect(writePayloads.map(payload => payload.ui_percentage)).toEqual([0,
|
|
8211
|
+
expect(writePayloads.map(payload => payload.ui_percentage)).toEqual([0, 100]);
|
|
8151
8212
|
expect(typedCall.mock.calls.map(call => call[3])).toEqual([
|
|
8152
8213
|
expect.objectContaining({
|
|
8153
8214
|
writeWithResponse: false,
|
|
@@ -8206,24 +8267,23 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8206
8267
|
expect(writePayloads.map(payload => payload.file.data.byteLength)).toEqual([1960, 1]);
|
|
8207
8268
|
});
|
|
8208
8269
|
|
|
8209
|
-
test('starts install progress only after
|
|
8270
|
+
test('ends device confirmation and starts install progress only after Protocol V2 ACK', async () => {
|
|
8210
8271
|
const method = new FirmwareUpdateV4({
|
|
8211
8272
|
id: 1,
|
|
8212
8273
|
payload: {
|
|
8213
8274
|
method: 'firmwareUpdateV4',
|
|
8214
8275
|
},
|
|
8215
8276
|
});
|
|
8216
|
-
let
|
|
8217
|
-
const typedCall = jest.fn().
|
|
8218
|
-
const call = jest.fn().mockImplementation(
|
|
8277
|
+
let resolveRequest: ((value: unknown) => void) | undefined;
|
|
8278
|
+
const typedCall = jest.fn().mockImplementation(
|
|
8219
8279
|
() =>
|
|
8220
8280
|
new Promise(resolve => {
|
|
8221
|
-
|
|
8281
|
+
resolveRequest = resolve;
|
|
8222
8282
|
})
|
|
8223
8283
|
);
|
|
8224
8284
|
|
|
8225
8285
|
(method as any).device = stubDevice({
|
|
8226
|
-
getCommands: () => ({ typedCall
|
|
8286
|
+
getCommands: () => ({ typedCall }),
|
|
8227
8287
|
});
|
|
8228
8288
|
method.postProgressMessage = jest.fn();
|
|
8229
8289
|
method.postTipMessage = jest.fn();
|
|
@@ -8231,31 +8291,21 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8231
8291
|
const startPromise = (method as any).protocolV2StartFirmwareUpdate({
|
|
8232
8292
|
targets: [{ target_id: 4, path: 'vol1:firmware.bin' }],
|
|
8233
8293
|
});
|
|
8234
|
-
await
|
|
8235
|
-
setImmediate(resolve);
|
|
8236
|
-
});
|
|
8294
|
+
await Promise.resolve();
|
|
8237
8295
|
|
|
8238
|
-
expect(typedCall.mock.calls[0]).
|
|
8239
|
-
|
|
8240
|
-
'Success',
|
|
8241
|
-
{ targets: [{ target_id: 4, path: 'vol1:firmware.bin' }] },
|
|
8242
|
-
]);
|
|
8243
|
-
expect(call).toHaveBeenCalledWith(
|
|
8244
|
-
'DeviceFirmwareUpdateRequest',
|
|
8245
|
-
{},
|
|
8246
|
-
{ returnAfterWrite: true }
|
|
8247
|
-
);
|
|
8296
|
+
expect(typedCall.mock.calls[0][1]).toBe('Success');
|
|
8297
|
+
expect(typedCall.mock.calls[0][3]).toEqual(expect.objectContaining({ timeoutMs: 180_000 }));
|
|
8248
8298
|
expect(method.postTipMessage).not.toHaveBeenCalled();
|
|
8249
8299
|
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
8250
8300
|
|
|
8251
|
-
|
|
8301
|
+
resolveRequest?.({ type: 'Success', message: { message: 'ok' } });
|
|
8252
8302
|
await startPromise;
|
|
8253
8303
|
expect(method.postTipMessage).toHaveBeenCalledWith('FirmwareUpdating');
|
|
8254
8304
|
expect(method.postProgressMessage).toHaveBeenCalledWith(0, 'installingFirmware');
|
|
8255
8305
|
expect(method.postTipMessage).toHaveBeenCalledTimes(1);
|
|
8256
8306
|
});
|
|
8257
8307
|
|
|
8258
|
-
test('
|
|
8308
|
+
test('requests only a Success ACK for Protocol V2 firmware install', async () => {
|
|
8259
8309
|
const method = new FirmwareUpdateV4({
|
|
8260
8310
|
id: 1,
|
|
8261
8311
|
payload: {
|
|
@@ -8266,10 +8316,9 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8266
8316
|
type: 'Success',
|
|
8267
8317
|
message: { message: 'accepted' },
|
|
8268
8318
|
});
|
|
8269
|
-
const call = jest.fn().mockResolvedValue({ type: 'WriteCompleted', message: {} });
|
|
8270
8319
|
|
|
8271
8320
|
(method as any).device = stubDevice({
|
|
8272
|
-
getCommands: () => ({ typedCall
|
|
8321
|
+
getCommands: () => ({ typedCall }),
|
|
8273
8322
|
});
|
|
8274
8323
|
method.postProgressMessage = jest.fn();
|
|
8275
8324
|
method.postTipMessage = jest.fn();
|
|
@@ -8278,12 +8327,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8278
8327
|
targets: [{ target_id: 4, path: 'vol1:firmware.bin' }],
|
|
8279
8328
|
});
|
|
8280
8329
|
|
|
8281
|
-
expect(typedCall.mock.calls[0][
|
|
8282
|
-
expect(call).toHaveBeenCalledWith(
|
|
8283
|
-
'DeviceFirmwareUpdateRequest',
|
|
8284
|
-
{},
|
|
8285
|
-
{ returnAfterWrite: true }
|
|
8286
|
-
);
|
|
8330
|
+
expect(typedCall.mock.calls[0][1]).toBe('Success');
|
|
8287
8331
|
expect(method.postTipMessage).toHaveBeenCalledWith('FirmwareUpdating');
|
|
8288
8332
|
});
|
|
8289
8333
|
});
|
|
@@ -9178,29 +9222,6 @@ describe('Protocol V2 protected method execution', () => {
|
|
|
9178
9222
|
}
|
|
9179
9223
|
);
|
|
9180
9224
|
|
|
9181
|
-
test('skips DeviceStatus and unlock when Protocol V2 is not initialized', async () => {
|
|
9182
|
-
const method = {
|
|
9183
|
-
name: 'firmwareUpdateV4',
|
|
9184
|
-
unlockPolicy: 'unlock-before-run',
|
|
9185
|
-
run: jest.fn().mockResolvedValue({ message: 'updating' }),
|
|
9186
|
-
};
|
|
9187
|
-
const device = {
|
|
9188
|
-
state: { status: { initialized: false } },
|
|
9189
|
-
commands: { typedCall: jest.fn() },
|
|
9190
|
-
isProtocolV2: () => true,
|
|
9191
|
-
isBootloader: () => false,
|
|
9192
|
-
isRomloader: () => false,
|
|
9193
|
-
unlockDevice: jest.fn(),
|
|
9194
|
-
};
|
|
9195
|
-
|
|
9196
|
-
await expect(runMethodWithUnlockPolicy(method as any, device as any)).resolves.toEqual({
|
|
9197
|
-
message: 'updating',
|
|
9198
|
-
});
|
|
9199
|
-
expect(device.commands.typedCall).not.toHaveBeenCalled();
|
|
9200
|
-
expect(device.unlockDevice).not.toHaveBeenCalled();
|
|
9201
|
-
expect(method.run).toHaveBeenCalledTimes(1);
|
|
9202
|
-
});
|
|
9203
|
-
|
|
9204
9225
|
test('keeps Protocol V1 and lock-free methods outside the preflight path', async () => {
|
|
9205
9226
|
for (const [isProtocolV2, unlockPolicy] of [
|
|
9206
9227
|
[false, 'unlock-before-run'],
|
|
@@ -9380,7 +9401,7 @@ describe('Protocol V2 current low-level methods', () => {
|
|
|
9380
9401
|
info: {
|
|
9381
9402
|
version: undefined,
|
|
9382
9403
|
serial_number: 'PR2SERIAL',
|
|
9383
|
-
|
|
9404
|
+
burn_in_completed: true,
|
|
9384
9405
|
factory_test_completed: undefined,
|
|
9385
9406
|
manufacture_time: undefined,
|
|
9386
9407
|
},
|
|
@@ -9630,7 +9651,7 @@ describe('Protocol V2 raw device info method', () => {
|
|
|
9630
9651
|
'DeviceInfoGet',
|
|
9631
9652
|
'DeviceInfo',
|
|
9632
9653
|
{
|
|
9633
|
-
targets: { hw: true,
|
|
9654
|
+
targets: { hw: true, fw: true, coprocessor: true },
|
|
9634
9655
|
types: { version: true, specific: true },
|
|
9635
9656
|
},
|
|
9636
9657
|
{ timeoutMs: PROTOCOL_V2_DEVICE_INFO_TIMEOUT_MS }
|