@@ -218,6 +218,56 @@ - (void)setUp
218
218
{
219
219
[super setUp ];
220
220
[self setContinueAfterFailure: NO ];
221
+
222
+ // Ensure the test starts with clean slate in terms of stored data.
223
+ if (sController != nil ) {
224
+ [sController .controllerDataStore clearAllStoredClusterData ];
225
+ NSDictionary * storedClusterDataAfterClear = [sController .controllerDataStore getStoredClusterDataForNodeID: @(kDeviceId )];
226
+ XCTAssertEqual (storedClusterDataAfterClear.count , 0 );
227
+ }
228
+ }
229
+
230
+ - (void )tearDown
231
+ {
232
+ // Make sure our MTRDevice instances, which are stateful, do not keep that
233
+ // state between different tests.
234
+ if (sController != nil ) {
235
+ __auto_type * device = [MTRDevice deviceWithNodeID: @(kDeviceId ) controller: sController ];
236
+ [sController removeDevice: device];
237
+ }
238
+
239
+ // Try to make sure we don't have any outstanding subscriptions from
240
+ // previous tests, by sending a subscribe request that will get rid of
241
+ // existing subscriptions and then fail out due to requesting a subscribe to
242
+ // a nonexistent cluster.
243
+ if (mConnectedDevice != nil ) {
244
+ dispatch_queue_t queue = dispatch_get_main_queue ();
245
+
246
+ MTRSubscribeParams * params = [[MTRSubscribeParams alloc ] initWithMinInterval: @(0 ) maxInterval: @(10 )];
247
+ params.resubscribeAutomatically = NO ;
248
+ params.replaceExistingSubscriptions = YES ;
249
+
250
+ XCTestExpectation * errorExpectation = [self expectationWithDescription: @" Canceled all subscriptions" ];
251
+
252
+ // There should be no Basic Information cluster on random endpoints.
253
+ [mConnectedDevice subscribeToAttributesWithEndpointID: @10000
254
+ clusterID: @(MTRClusterIDTypeBasicInformationID)
255
+ attributeID: @(0 )
256
+ params: params
257
+ queue: queue
258
+ reportHandler: ^(id _Nullable values, NSError * _Nullable error) {
259
+ XCTAssertNil (values);
260
+ XCTAssertNotNil (error);
261
+ [errorExpectation fulfill ];
262
+ }
263
+ subscriptionEstablished: ^() {
264
+ XCTFail (" Did not expect subscription to Basic Information on random endpoint to succeed" );
265
+ }];
266
+
267
+ [self waitForExpectations: @[ errorExpectation ] timeout: kTimeoutInSeconds ];
268
+ }
269
+
270
+ [super tearDown ];
221
271
}
222
272
223
273
- (void )test001_ReadAttribute
@@ -1387,11 +1437,6 @@ - (void)test016_FailedSubscribeWithCacheReadDuringFailure
1387
1437
1388
1438
- (void )test017_TestMTRDeviceBasics
1389
1439
{
1390
- // Ensure the test starts with clean slate, even with MTRDeviceControllerLocalTestStorage enabled
1391
- [sController .controllerDataStore clearAllStoredClusterData ];
1392
- NSDictionary * storedClusterDataAfterClear = [sController .controllerDataStore getStoredClusterDataForNodeID: @(kDeviceId )];
1393
- XCTAssertEqual (storedClusterDataAfterClear.count , 0 );
1394
-
1395
1440
__auto_type * device = [MTRDevice deviceWithNodeID: kDeviceId deviceController: sController ];
1396
1441
dispatch_queue_t queue = dispatch_get_main_queue ();
1397
1442
@@ -2634,11 +2679,6 @@ - (void)test028_TimeZoneAndDST
2634
2679
2635
2680
- (void )test029_MTRDeviceWriteCoalescing
2636
2681
{
2637
- // Ensure the test starts with clean slate, even with MTRDeviceControllerLocalTestStorage enabled
2638
- [sController .controllerDataStore clearAllStoredClusterData ];
2639
- NSDictionary * storedClusterDataAfterClear = [sController .controllerDataStore getStoredClusterDataForNodeID: @(kDeviceId )];
2640
- XCTAssertEqual (storedClusterDataAfterClear.count , 0 );
2641
-
2642
2682
__auto_type * device = [MTRDevice deviceWithNodeID: kDeviceId deviceController: sController ];
2643
2683
dispatch_queue_t queue = dispatch_get_main_queue ();
2644
2684
@@ -2971,15 +3011,8 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage
2971
3011
{
2972
3012
dispatch_queue_t queue = dispatch_get_main_queue ();
2973
3013
2974
- // First start with clean slate by removing the MTRDevice and clearing the persisted cache
3014
+ // Get the subscription primed
2975
3015
__auto_type * device = [MTRDevice deviceWithNodeID: @(kDeviceId ) controller: sController ];
2976
- [sController removeDevice: device];
2977
- [sController .controllerDataStore clearAllStoredClusterData ];
2978
- NSDictionary * storedClusterDataAfterClear = [sController .controllerDataStore getStoredClusterDataForNodeID: @(kDeviceId )];
2979
- XCTAssertEqual (storedClusterDataAfterClear.count , 0 );
2980
-
2981
- // Now recreate device and get subscription primed
2982
- device = [MTRDevice deviceWithNodeID: @(kDeviceId ) controller: sController ];
2983
3016
XCTestExpectation * gotReportsExpectation = [self expectationWithDescription: @" Attribute and Event reports have been received" ];
2984
3017
XCTestExpectation * gotDeviceCachePrimed = [self expectationWithDescription: @" Device cache primed for the first time" ];
2985
3018
__auto_type * delegate = [[MTRDeviceTestDelegate alloc ] init ];
@@ -3038,12 +3071,6 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage
3038
3071
}
3039
3072
NSUInteger storedAttributeCountDifferenceFromMTRDeviceReport = dataStoreAttributeCountAfterSecondSubscription - attributesReportedWithSecondSubscription;
3040
3073
XCTAssertTrue (storedAttributeCountDifferenceFromMTRDeviceReport > 300 );
3041
-
3042
- // We need to remove the device here since the MTRDevice retains its reachable state. So if the next test needs to start with a clean state,
3043
- // it can't do that since the MTRDevice becomes reachable in the previous test. Since there are no changes detected in reachability,
3044
- // the onReachable callback to the delegate is not called.
3045
- // TODO: #33205 Ensure we have a clean slate w.r.t MTRDevice before running each test.
3046
- [sController removeDevice: device];
3047
3074
}
3048
3075
3049
3076
- (void )test032_MTRPathClassesEncoding
@@ -3175,11 +3202,6 @@ + (void)checkAttributeReportTriggersConfigurationChanged:(MTRAttributeIDType)att
3175
3202
3176
3203
- (void )test033_TestMTRDeviceDeviceConfigurationChanged
3177
3204
{
3178
- // Ensure the test starts with clean slate.
3179
- [sController .controllerDataStore clearAllStoredClusterData ];
3180
- NSDictionary * storedClusterDataAfterClear = [sController .controllerDataStore getStoredClusterDataForNodeID: @(kDeviceId )];
3181
- XCTAssertEqual (storedClusterDataAfterClear.count , 0 );
3182
-
3183
3205
__auto_type * device = [MTRDevice deviceWithNodeID: kDeviceId deviceController: sController ];
3184
3206
dispatch_queue_t queue = dispatch_get_main_queue ();
3185
3207
@@ -3274,7 +3296,7 @@ - (void)test033_TestMTRDeviceDeviceConfigurationChanged
3274
3296
3275
3297
[device setDelegate: delegate queue: queue];
3276
3298
3277
- // Wait for subscription set up and intitial reports received.
3299
+ // Wait for subscription set up and initial reports received.
3278
3300
[self waitForExpectations: @[
3279
3301
subscriptionExpectation,
3280
3302
gotInitialReportsExpectation,
@@ -3500,11 +3522,90 @@ - (void)test033_TestMTRDeviceDeviceConfigurationChanged
3500
3522
3501
3523
[device unitTestInjectAttributeReport: attributeReport];
3502
3524
[self waitForExpectations: @[ gotAttributeReportWithMultipleAttributesExpectation, gotAttributeReportWithMultipleAttributesEndExpectation, deviceConfigurationChangedExpectationForAttributeReportWithMultipleAttributes ] timeout: kTimeoutInSeconds ];
3525
+ }
3526
+
3527
+ - (void )test034_TestMTRDeviceHistoricalEvents
3528
+ {
3529
+ dispatch_queue_t queue = dispatch_get_main_queue ();
3530
+
3531
+ NSDictionary * storedClusterDataAfterClear = [sController .controllerDataStore getStoredClusterDataForNodeID: @(kDeviceId )];
3532
+ XCTAssertEqual (storedClusterDataAfterClear.count , 0 );
3533
+
3534
+ // Set up a subscription via mConnectedDevice that will send us continuous
3535
+ // reports.
3536
+ XCTestExpectation * firstSubscriptionExpectation = [self expectationWithDescription: @" First subscription established" ];
3503
3537
3504
- // We need to remove the device here, because we injected data into its attribute cache
3505
- // that does not match the actual server.
3506
- // TODO: #33205 Ensure we have a clean slate w.r.t MTRDevice before running each test.
3538
+ MTRSubscribeParams * params = [[MTRSubscribeParams alloc ] initWithMinInterval: @(0 ) maxInterval: @(0 )];
3539
+ params.resubscribeAutomatically = NO ;
3540
+
3541
+ [mConnectedDevice subscribeToAttributesWithEndpointID: @(0 )
3542
+ clusterID: @(MTRClusterIDTypeBasicInformationID)
3543
+ attributeID: @(0 )
3544
+ params: params
3545
+ queue: queue
3546
+ reportHandler: ^(id _Nullable values, NSError * _Nullable error) {
3547
+ }
3548
+ subscriptionEstablished: ^() {
3549
+ [firstSubscriptionExpectation fulfill ];
3550
+ }];
3551
+
3552
+ [self waitForExpectations: @[ firstSubscriptionExpectation ] timeout: kTimeoutInSeconds ];
3553
+
3554
+ // Now set up our MTRDevice and do a subscribe. Make sure all the events we
3555
+ // get are marked "historical".
3556
+ __auto_type * device = [MTRDevice deviceWithNodeID: kDeviceId deviceController: sController ];
3557
+ XCTestExpectation * secondSubscriptionExpectation = [self expectationWithDescription: @" Second subscription established" ];
3558
+ XCTestExpectation * gotFirstReportsExpectation = [self expectationWithDescription: @" First Attribute and Event reports have been received" ];
3559
+
3560
+ __auto_type * delegate = [[MTRDeviceTestDelegate alloc ] init ];
3561
+ delegate.onReachable = ^() {
3562
+ [secondSubscriptionExpectation fulfill ];
3563
+ };
3564
+
3565
+ __block unsigned eventReportsReceived = 0 ;
3566
+ delegate.onEventDataReceived = ^(NSArray <NSDictionary <NSString *, id > *> * eventReport) {
3567
+ eventReportsReceived += eventReport.count ;
3568
+ for (NSDictionary <NSString *, id > * eventDict in eventReport) {
3569
+ NSNumber * reportIsHistorical = eventDict[MTREventIsHistoricalKey];
3570
+ XCTAssertTrue (reportIsHistorical.boolValue );
3571
+ }
3572
+ };
3573
+
3574
+ delegate.onReportEnd = ^() {
3575
+ [gotFirstReportsExpectation fulfill ];
3576
+ };
3577
+
3578
+ [device setDelegate: delegate queue: queue];
3579
+
3580
+ [self waitForExpectations: @[ secondSubscriptionExpectation, gotFirstReportsExpectation ] timeout: 60 ];
3581
+
3582
+ // Must have gotten some events (at least StartUp!)
3583
+ XCTAssertTrue (eventReportsReceived > 0 );
3584
+
3585
+ // Remove the device, then try again, now with us having stored cluster
3586
+ // data. All the events should still be reported as historical.
3507
3587
[sController removeDevice: device];
3588
+
3589
+ eventReportsReceived = 0 ;
3590
+
3591
+ device = [MTRDevice deviceWithNodeID: kDeviceId deviceController: sController ];
3592
+ XCTestExpectation * thirdSubscriptionExpectation = [self expectationWithDescription: @" Third subscription established" ];
3593
+ XCTestExpectation * gotSecondReportsExpectation = [self expectationWithDescription: @" Second Attribute and Event reports have been received" ];
3594
+
3595
+ delegate.onReachable = ^() {
3596
+ [thirdSubscriptionExpectation fulfill ];
3597
+ };
3598
+
3599
+ delegate.onReportEnd = ^() {
3600
+ [gotSecondReportsExpectation fulfill ];
3601
+ };
3602
+
3603
+ [device setDelegate: delegate queue: queue];
3604
+
3605
+ [self waitForExpectations: @[ thirdSubscriptionExpectation, gotSecondReportsExpectation ] timeout: 60 ];
3606
+
3607
+ // Must have gotten some events (at least StartUp!)
3608
+ XCTAssertTrue (eventReportsReceived > 0 );
3508
3609
}
3509
3610
3510
3611
@end
0 commit comments