Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Darwin] Add internal method to get report of all attributes to MTRDevice #35463

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/darwin/Framework/CHIP/MTRDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,17 @@ - (NSDictionary *)_dataValueWithoutDataVersion:(NSDictionary *)attributeValue
}
}

- (NSArray<NSDictionary<NSString *, id> *> *)getAllAttributesReport
{
#define MTRDeviceErrorStr "MTRDevice getAllAttributesReport must be handled by subclasses that support it"
MTR_LOG_ERROR(MTRDeviceErrorStr);
#ifdef DEBUG
NSAssert(NO, @MTRDeviceErrorStr);
#endif // DEBUG
#undef MTRDeviceErrorStr
return nil;
}

#ifdef DEBUG
- (NSUInteger)unitTestAttributeCount
{
Expand Down
27 changes: 27 additions & 0 deletions src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3092,6 +3092,12 @@ - (void)_performScheduledExpirationCheck
- (NSDictionary<NSString *, id> *)_attributeValueDictionaryForAttributePath:(MTRAttributePath *)attributePath
{
std::lock_guard lock(_lock);
return [self _lockedAttributeValueDictionaryForAttributePath:attributePath];
}

- (NSDictionary<NSString *, id> *)_lockedAttributeValueDictionaryForAttributePath:(MTRAttributePath *)attributePath
{
os_unfair_lock_assert_owner(&self->_lock);

// First check expected value cache
NSArray * expectedValue = _expectedValueCache[attributePath];
Expand Down Expand Up @@ -3478,6 +3484,27 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray<NSDictionary<NSSt
return attributesToReport;
}

- (NSArray<NSDictionary<NSString *, id> *> *)getAllAttributesReport
{
std::lock_guard lock(_lock);

NSMutableArray * attributeReport = [NSMutableArray array];
for (MTRClusterPath * clusterPath in [self _knownClusters]) {
MTRDeviceClusterData * clusterData = [self _clusterDataForPath:clusterPath];

for (NSNumber * attributeID in clusterData.attributes) {
auto * attributePath = [MTRAttributePath attributePathWithEndpointID:clusterPath.endpoint
clusterID:clusterPath.cluster
attributeID:attributeID];

// Using _lockedAttributeValueDictionaryForAttributePath because it takes into consideration expected values too
[attributeReport addObject:[self _lockedAttributeValueDictionaryForAttributePath:attributePath]];
}
}

return attributeReport;
}

#ifdef DEBUG
- (NSUInteger)unitTestAttributeCount
{
Expand Down
3 changes: 3 additions & 0 deletions src/darwin/Framework/CHIP/MTRDevice_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ MTR_DIRECT_MEMBERS
- (void)_callFirstDelegateSynchronouslyWithBlock:(void (^)(id<MTRDeviceDelegate> delegate))block;
#endif

// Used to generate attribute report that contains all known attributes, taking into consideration expected values
- (NSArray<NSDictionary<NSString *, id> *> *)getAllAttributesReport;

@end

#pragma mark - MTRDevice internal state monitoring
Expand Down
56 changes: 56 additions & 0 deletions src/darwin/Framework/CHIPTests/MTRDeviceTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -4022,6 +4022,7 @@ - (void)test037_MTRDeviceMultipleDelegatesGetReports
// For unit test no real data is needed, but timestamp is required
};
}

- (void)test038_MTRDeviceMultipleDelegatesInterestedPaths
{
dispatch_queue_t queue = dispatch_get_main_queue();
Expand Down Expand Up @@ -4274,6 +4275,61 @@ - (void)test038_MTRDeviceMultipleDelegatesInterestedPaths
XCTAssertEqual(eventsReceived4, 36);
}

- (void)test039_GetAllAttributesReport
{
dispatch_queue_t queue = dispatch_get_main_queue();

// First start with clean slate by removing the MTRDevice and clearing the persisted cache
__auto_type * device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sController];
[sController removeDevice:device];
[sController.controllerDataStore clearAllStoredClusterData];
NSDictionary * storedClusterDataAfterClear = [sController.controllerDataStore getStoredClusterDataForNodeID:@(kDeviceId)];
XCTAssertEqual(storedClusterDataAfterClear.count, 0);

// Now recreate device and get subscription primed
device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sController];
XCTestExpectation * gotReportEnd = [self expectationWithDescription:@"Report end for delegate"];

__auto_type * delegate = [[MTRDeviceTestDelegateWithSubscriptionSetupOverride alloc] init];
delegate.skipSetupSubscription = YES;
__weak __auto_type weakdelegate = delegate;
__block NSUInteger attributesReceived = 0;
delegate.onAttributeDataReceived = ^(NSArray<NSDictionary<NSString *, id> *> * data) {
attributesReceived += data.count;
};
delegate.onReportEnd = ^{
[gotReportEnd fulfill];
__strong __auto_type strongDelegate = weakdelegate;
strongDelegate.onReportEnd = nil;
};

[device addDelegate:delegate queue:queue];

// Now inject attributes and check that each delegate gets the right set of attributes
NSMutableArray * attributeReport = [NSMutableArray array];
// Construct 36 attributes with endpoints 1~4, clusters 11 ~ 33, and attributes 111~333
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 3; j++) {
for (int k = 1; k <= 3; k++) {
int endpointID = i;
int clusterID = i * 10 + j;
int attributeID = i * 100 + j * 10 + k;
int value = attributeID + 10000;
[attributeReport addObject:[self _testAttributeResponseValueWithEndpointID:@(endpointID) clusterID:@(clusterID) attributeID:@(attributeID) value:value]];
}
}
}
[device unitTestInjectAttributeReport:attributeReport fromSubscription:YES];

[self waitForExpectations:@[ gotReportEnd ] timeout:60];

XCTAssertEqual(attributesReceived, 36);

NSArray * allAttributesReport = [device getAllAttributesReport];

XCTAssertEqual(allAttributesReport.count, 36);
}

@end

@interface MTRDeviceEncoderTests : XCTestCase
Expand Down
Loading