48
48
// commissioning flows that have such a delegate.
49
49
@interface NoOpAttestationDelegate : NSObject <MTRDeviceAttestationDelegate>
50
50
@property (nonatomic ) XCTestExpectation * expectation;
51
+ @property (nonatomic ) BOOL blockCommissioning;
51
52
52
53
- (instancetype )initWithExpectation : (XCTestExpectation *)expectation ;
54
+ // If blockCommissioning is YES, this delegate will never proceed from
55
+ // its attestation verification callback.
56
+ - (instancetype )initWithExpectation : (XCTestExpectation *)expectation blockCommissioning : (BOOL )blockCommissioning ;
53
57
@end
54
58
55
59
@implementation NoOpAttestationDelegate
60
+
56
61
- (instancetype )initWithExpectation : (XCTestExpectation *)expectation
62
+ {
63
+ return [self initWithExpectation: expectation blockCommissioning: NO ];
64
+ }
65
+
66
+ - (instancetype )initWithExpectation : (XCTestExpectation *)expectation blockCommissioning : (BOOL )blockCommissioning ;
57
67
{
58
68
if (!(self = [super init ])) {
59
69
return nil ;
60
70
}
61
71
62
72
_expectation = expectation;
73
+ _blockCommissioning = blockCommissioning;
63
74
return self;
64
75
}
65
76
@@ -74,7 +85,10 @@ - (void)deviceAttestationCompletedForController:(MTRDeviceController *)controlle
74
85
XCTAssertEqualObjects (attestationDeviceInfo.productID , @(0x8001 ));
75
86
XCTAssertEqualObjects (attestationDeviceInfo.basicInformationVendorID , @(0xFFF1 ));
76
87
XCTAssertEqualObjects (attestationDeviceInfo.basicInformationProductID , @(0x8000 ));
77
- [controller continueCommissioningDevice: opaqueDeviceHandle ignoreAttestationFailure: NO error: nil ];
88
+
89
+ if (!self.blockCommissioning ) {
90
+ [controller continueCommissioningDevice: opaqueDeviceHandle ignoreAttestationFailure: NO error: nil ];
91
+ }
78
92
}
79
93
80
94
@end
@@ -241,7 +255,7 @@ - (void)test004_PairWithAttestationDelegateFailsafeExtensionLong
241
255
[self waitForExpectations: @[ expectation ] timeout: kTimeoutInSeconds ];
242
256
}
243
257
244
- - (void )doPairingAndWaitForProgress : (NSString *)trigger
258
+ - (void )doPairingAndWaitForProgress : (NSString *)trigger attestationDelegate : (nullable id <MTRDeviceAttestationDelegate>) attestationDelegate
245
259
{
246
260
XCTestExpectation * expectation = [self expectationWithDescription: @" Trigger message seen" ];
247
261
expectation.assertForOverFulfill = NO ;
@@ -251,9 +265,19 @@ - (void)doPairingAndWaitForProgress:(NSString *)trigger
251
265
}
252
266
});
253
267
268
+ XCTestExpectation * attestationExpectation;
269
+ if (attestationDelegate == nil ) {
270
+ attestationExpectation = [self expectationWithDescription: @" Attestation delegate called" ];
271
+ attestationDelegate = [[NoOpAttestationDelegate alloc ] initWithExpectation: attestationExpectation];
272
+ }
273
+
274
+ // Make sure we exercise the codepath that has an attestation delegate and
275
+ // extends the fail-safe while waiting for that delegate. And make sure our
276
+ // fail-safe extension is long enough that we actually trigger a fail-safe
277
+ // extension (so longer than the 1-minute default).
254
278
__auto_type * controllerDelegate = [[MTRPairingTestControllerDelegate alloc ] initWithExpectation: nil
255
- attestationDelegate: nil
256
- failSafeExtension: nil ];
279
+ attestationDelegate: attestationDelegate
280
+ failSafeExtension: @( 90 ) ];
257
281
[sController setDeviceControllerDelegate: controllerDelegate queue: dispatch_get_main_queue ()];
258
282
self.controllerDelegate = controllerDelegate;
259
283
@@ -264,13 +288,17 @@ - (void)doPairingAndWaitForProgress:(NSString *)trigger
264
288
XCTAssertNil (error);
265
289
266
290
[self waitForExpectations: @[ expectation ] timeout: kPairingTimeoutInSeconds ];
291
+
292
+ if (attestationExpectation) {
293
+ [self waitForExpectations: @[ attestationExpectation ] timeout: kTimeoutInSeconds ];
294
+ }
267
295
MTRSetLogCallback (0 , nil );
268
296
}
269
297
270
- - (void )doPairingTestAfterCancellationAtProgress : (NSString *)trigger
298
+ - (void )doPairingTestAfterCancellationAtProgress : (NSString *)trigger attestationDelegate : (nullable id <MTRDeviceAttestationDelegate>) attestationDelegate
271
299
{
272
300
// Run pairing up and wait for the trigger
273
- [self doPairingAndWaitForProgress: trigger];
301
+ [self doPairingAndWaitForProgress: trigger attestationDelegate: attestationDelegate ];
274
302
275
303
// Call StopPairing and wait for the commissioningComplete callback
276
304
XCTestExpectation * expectation = [self expectationWithDescription: @" commissioningComplete delegate method called" ];
@@ -289,6 +317,11 @@ - (void)doPairingTestAfterCancellationAtProgress:(NSString *)trigger
289
317
[self doPairingTestWithAttestationDelegate: nil failSafeExtension: nil ];
290
318
}
291
319
320
+ - (void )doPairingTestAfterCancellationAtProgress : (NSString *)trigger
321
+ {
322
+ [self doPairingTestAfterCancellationAtProgress: trigger attestationDelegate: nil ];
323
+ }
324
+
292
325
- (void )test005_pairingAfterCancellation_ReadCommissioningInfo
293
326
{
294
327
// @"Sending read request for commissioning information"
@@ -306,4 +339,16 @@ - (void)test007_pairingAfterCancellation_FindOperational
306
339
[self doPairingTestAfterCancellationAtProgress: @" FindOrEstablishSession:" ];
307
340
}
308
341
342
+ - (void )test008_pairingAfterCancellation_DeviceAttestationVerification
343
+ {
344
+ // Cancel pairing while we are waiting for our client to decide what to do
345
+ // with the attestation information we got.
346
+ XCTestExpectation * attestationExpectation = [self expectationWithDescription: @" Blocking attestation delegate called" ];
347
+ __auto_type * attestationDelegate = [[NoOpAttestationDelegate alloc ] initWithExpectation: attestationExpectation blockCommissioning: YES ];
348
+
349
+ [self doPairingTestAfterCancellationAtProgress: @" Successfully extended fail-safe timer to handle DA failure" attestationDelegate: attestationDelegate];
350
+
351
+ [self waitForExpectations: @[ attestationExpectation ] timeout: kTimeoutInSeconds ];
352
+ }
353
+
309
354
@end
0 commit comments