@@ -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
@@ -406,6 +456,7 @@ - (void)test005_Subscribe
406
456
// Subscribe
407
457
XCTestExpectation * expectation = [self expectationWithDescription:@"subscribe OnOff attribute"];
408
458
__auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(1) maxInterval:@(10)];
459
+ params.resubscribeAutomatically = NO;
409
460
[device subscribeToAttributesWithEndpointID:@1
410
461
clusterID:@6
411
462
attributeID:@0
@@ -1278,8 +1329,7 @@ - (void)test015_FailedSubscribeWithQueueAcrossShutdown
1278
1329
__auto_type clusterStateCacheContainer = [[MTRAttributeCacheContainer alloc] init];
1279
1330
__auto_type * params = [[MTRSubscribeParams alloc] init];
1280
1331
params.resubscribeAutomatically = NO;
1281
- params.replaceExistingSubscriptions = NO ; // Not strictly needed, but checking that doing this does not
1282
- // affect this subscription erroring out correctly.
1332
+ params.replaceExistingSubscriptions = NO; // Not strictly needed, but checking that doing this does not affect this subscription erroring out correctly.
1283
1333
[device subscribeWithQueue:queue
1284
1334
minInterval:1
1285
1335
maxInterval:2
@@ -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
@@ -2149,6 +2194,7 @@ - (void)test023_SubscribeMultipleAttributes
2149
2194
// Subscribe
2150
2195
XCTestExpectation * expectation = [self expectationWithDescription:@"subscribe OnOff attribute"];
2151
2196
__auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(1) maxInterval:@(10)];
2197
+ params.resubscribeAutomatically = NO;
2152
2198
2153
2199
NSNumber * failClusterId = @5678;
2154
2200
NSNumber * failEndpointId = @1000;
@@ -2406,6 +2452,7 @@ - (void)test025_SubscribeMultipleEvents
2406
2452
// Subscribe
2407
2453
XCTestExpectation * expectation = [self expectationWithDescription:@"subscribe multiple events"];
2408
2454
__auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(1) maxInterval:@(10)];
2455
+ params.resubscribeAutomatically = NO;
2409
2456
2410
2457
NSArray<MTREventRequestPath *> * eventPaths = @[
2411
2458
// Startup event.
@@ -2634,11 +2681,6 @@ - (void)test028_TimeZoneAndDST
2634
2681
2635
2682
- (void)test029_MTRDeviceWriteCoalescing
2636
2683
{
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
2684
__auto_type * device = [MTRDevice deviceWithNodeID:kDeviceId deviceController:sController];
2643
2685
dispatch_queue_t queue = dispatch_get_main_queue();
2644
2686
@@ -2971,15 +3013,8 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage
2971
3013
{
2972
3014
dispatch_queue_t queue = dispatch_get_main_queue();
2973
3015
2974
- // First start with clean slate by removing the MTRDevice and clearing the persisted cache
3016
+ // Get the subscription primed
2975
3017
__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
3018
XCTestExpectation * gotReportsExpectation = [self expectationWithDescription:@"Attribute and Event reports have been received"];
2984
3019
XCTestExpectation * gotDeviceCachePrimed = [self expectationWithDescription:@"Device cache primed for the first time"];
2985
3020
__auto_type * delegate = [[MTRDeviceTestDelegate alloc] init];
@@ -3038,12 +3073,6 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage
3038
3073
}
3039
3074
NSUInteger storedAttributeCountDifferenceFromMTRDeviceReport = dataStoreAttributeCountAfterSecondSubscription - attributesReportedWithSecondSubscription;
3040
3075
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
3076
}
3048
3077
3049
3078
- (void)test032_MTRPathClassesEncoding
@@ -3175,11 +3204,6 @@ + (void)checkAttributeReportTriggersConfigurationChanged:(MTRAttributeIDType)att
3175
3204
3176
3205
- (void)test033_TestMTRDeviceDeviceConfigurationChanged
3177
3206
{
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
3207
__auto_type * device = [MTRDevice deviceWithNodeID:kDeviceId deviceController:sController];
3184
3208
dispatch_queue_t queue = dispatch_get_main_queue();
3185
3209
@@ -3274,7 +3298,7 @@ - (void)test033_TestMTRDeviceDeviceConfigurationChanged
3274
3298
3275
3299
[device setDelegate:delegate queue:queue];
3276
3300
3277
- // Wait for subscription set up and intitial reports received.
3301
+ // Wait for subscription set up and initial reports received.
3278
3302
[self waitForExpectations:@[
3279
3303
subscriptionExpectation,
3280
3304
gotInitialReportsExpectation,
@@ -3500,11 +3524,90 @@ - (void)test033_TestMTRDeviceDeviceConfigurationChanged
3500
3524
3501
3525
[device unitTestInjectAttributeReport:attributeReport];
3502
3526
[self waitForExpectations:@[ gotAttributeReportWithMultipleAttributesExpectation, gotAttributeReportWithMultipleAttributesEndExpectation, deviceConfigurationChangedExpectationForAttributeReportWithMultipleAttributes ] timeout:kTimeoutInSeconds];
3527
+ }
3503
3528
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.
3529
+ - (void)test034_TestMTRDeviceHistoricalEvents
3530
+ {
3531
+ dispatch_queue_t queue = dispatch_get_main_queue();
3532
+
3533
+ NSDictionary * storedClusterDataAfterClear = [sController.controllerDataStore getStoredClusterDataForNodeID:@(kDeviceId)];
3534
+ XCTAssertEqual(storedClusterDataAfterClear.count, 0);
3535
+
3536
+ // Set up a subscription via mConnectedDevice that will send us continuous
3537
+ // reports.
3538
+ XCTestExpectation * firstSubscriptionExpectation = [self expectationWithDescription:@"First subscription established"];
3539
+
3540
+ MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(0) maxInterval:@(0)];
3541
+ params.resubscribeAutomatically = NO;
3542
+
3543
+ [mConnectedDevice subscribeToAttributesWithEndpointID:@(0)
3544
+ clusterID:@(MTRClusterIDTypeBasicInformationID)
3545
+ attributeID:@(0)
3546
+ params:params
3547
+ queue:queue
3548
+ reportHandler:^(id _Nullable values, NSError * _Nullable error) {
3549
+ }
3550
+ subscriptionEstablished:^() {
3551
+ [firstSubscriptionExpectation fulfill];
3552
+ }];
3553
+
3554
+ [self waitForExpectations:@[ firstSubscriptionExpectation ] timeout:kTimeoutInSeconds];
3555
+
3556
+ // Now set up our MTRDevice and do a subscribe. Make sure all the events we
3557
+ // get are marked "historical".
3558
+ __auto_type * device = [MTRDevice deviceWithNodeID:kDeviceId deviceController:sController];
3559
+ XCTestExpectation * secondSubscriptionExpectation = [self expectationWithDescription:@"Second subscription established"];
3560
+ XCTestExpectation * gotFirstReportsExpectation = [self expectationWithDescription:@"First Attribute and Event reports have been received"];
3561
+
3562
+ __auto_type * delegate = [[MTRDeviceTestDelegate alloc] init];
3563
+ delegate.onReachable = ^() {
3564
+ [secondSubscriptionExpectation fulfill];
3565
+ };
3566
+
3567
+ __block unsigned eventReportsReceived = 0;
3568
+ delegate.onEventDataReceived = ^(NSArray<NSDictionary<NSString *, id> *> * eventReport) {
3569
+ eventReportsReceived += eventReport.count;
3570
+ for (NSDictionary<NSString *, id> * eventDict in eventReport) {
3571
+ NSNumber * reportIsHistorical = eventDict[MTREventIsHistoricalKey];
3572
+ XCTAssertTrue(reportIsHistorical.boolValue);
3573
+ }
3574
+ };
3575
+
3576
+ delegate.onReportEnd = ^() {
3577
+ [gotFirstReportsExpectation fulfill];
3578
+ };
3579
+
3580
+ [device setDelegate:delegate queue:queue];
3581
+
3582
+ [self waitForExpectations:@[ secondSubscriptionExpectation, gotFirstReportsExpectation ] timeout:60];
3583
+
3584
+ // Must have gotten some events (at least StartUp!)
3585
+ XCTAssertTrue(eventReportsReceived > 0);
3586
+
3587
+ // Remove the device, then try again, now with us having stored cluster
3588
+ // data. All the events should still be reported as historical.
3507
3589
[sController removeDevice:device];
3590
+
3591
+ eventReportsReceived = 0;
3592
+
3593
+ device = [MTRDevice deviceWithNodeID:kDeviceId deviceController:sController];
3594
+ XCTestExpectation * thirdSubscriptionExpectation = [self expectationWithDescription:@"Third subscription established"];
3595
+ XCTestExpectation * gotSecondReportsExpectation = [self expectationWithDescription:@"Second Attribute and Event reports have been received"];
3596
+
3597
+ delegate.onReachable = ^() {
3598
+ [thirdSubscriptionExpectation fulfill];
3599
+ };
3600
+
3601
+ delegate.onReportEnd = ^() {
3602
+ [gotSecondReportsExpectation fulfill];
3603
+ };
3604
+
3605
+ [device setDelegate:delegate queue:queue];
3606
+
3607
+ [self waitForExpectations:@[ thirdSubscriptionExpectation, gotSecondReportsExpectation ] timeout:60];
3608
+
3609
+ // Must have gotten some events (at least StartUp!)
3610
+ XCTAssertTrue(eventReportsReceived > 0);
3508
3611
}
3509
3612
3510
3613
@end
0 commit comments