Skip to content

Commit

Permalink
Merge branch 'master' into opstate_2_56_msg_event
Browse files Browse the repository at this point in the history
  • Loading branch information
cecille authored Sep 25, 2024
2 parents 448d627 + e9d7b2f commit aba20dd
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 195 deletions.
2 changes: 1 addition & 1 deletion src/darwin/Framework/CHIP/MTRCertificates.mm
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ + (BOOL)isCertificate:(MTRCertificateDERBytes)certificate1 equalTo:(MTRCertifica
MTR_LOG_ERROR("Can't extract public key from second certificate: %s", ErrorStr(err));
return NO;
}
P256PublicKeySpan keySpan2(pubKey1.ConstBytes());
P256PublicKeySpan keySpan2(pubKey2.ConstBytes());

if (!keySpan1.data_equal(keySpan2)) {
return NO;
Expand Down
6 changes: 2 additions & 4 deletions src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3533,6 +3533,8 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray<NSDictionary<NSSt
NSNumber * dataVersion = attributeDataValue[MTRDataVersionKey];
MTRClusterPath * clusterPath = [MTRClusterPath clusterPathWithEndpointID:attributePath.endpoint clusterID:attributePath.cluster];
if (dataVersion) {
[self _noteDataVersion:dataVersion forClusterPath:clusterPath];

// Remove data version from what we cache in memory
attributeDataValue = [self _dataValueWithoutDataVersion:attributeDataValue];
}
Expand All @@ -3545,10 +3547,6 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray<NSDictionary<NSSt
#endif
// Now that we have grabbed previousValue, update our cache with the attribute value.
if (readCacheValueChanged) {
if (dataVersion) {
[self _noteDataVersion:dataVersion forClusterPath:clusterPath];
}

[self _pruneStoredDataForPath:attributePath missingFrom:attributeDataValue];

if (!_deviceConfigurationChanged) {
Expand Down
6 changes: 3 additions & 3 deletions src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ - (void)handleBDXTransferSessionBeginForFileDesignator:(NSString *)fileDesignato
abortHandler:(AbortHandler)abortHandler;
{
assertChipStackLockedByCurrentThread();
MTR_LOG("BDX Transfer Session Begin: %@", fileDesignator);
MTR_LOG("BDX Transfer Session Begin for log download: %@", fileDesignator);

auto * download = [_downloads get:fileDesignator fabricIndex:fabricIndex nodeID:nodeID];
VerifyOrReturn(nil != download, completion([MTRError errorForCHIPErrorCode:CHIP_ERROR_NOT_FOUND]));
Expand All @@ -492,7 +492,7 @@ - (void)handleBDXTransferSessionDataForFileDesignator:(NSString *)fileDesignator
completion:(MTRStatusCompletion)completion
{
assertChipStackLockedByCurrentThread();
MTR_LOG("BDX Transfer Session Data: %@: %@", fileDesignator, data);
MTR_LOG("BDX Transfer Session Data for log download: %@: %@", fileDesignator, data);

auto * download = [_downloads get:fileDesignator fabricIndex:fabricIndex nodeID:nodeID];
VerifyOrReturn(nil != download, completion([MTRError errorForCHIPErrorCode:CHIP_ERROR_NOT_FOUND]));
Expand All @@ -510,7 +510,7 @@ - (void)handleBDXTransferSessionEndForFileDesignator:(NSString *)fileDesignator
error:(NSError * _Nullable)error
{
assertChipStackLockedByCurrentThread();
MTR_LOG("BDX Transfer Session End: %@: %@", fileDesignator, error);
MTR_LOG("BDX Transfer Session End for log download: %@: %@", fileDesignator, error);

auto * download = [_downloads get:fileDesignator fabricIndex:fabricIndex nodeID:nodeID];
VerifyOrReturn(nil != download);
Expand Down
123 changes: 79 additions & 44 deletions src/darwin/Framework/CHIPTests/MTRDeviceTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -3746,11 +3746,16 @@ - (void)test035_TestMTRDeviceSubscriptionNotEstablishedOverXPC
}

- (NSArray<NSDictionary<NSString *, id> *> *)_testAttributeReportWithValue:(unsigned int)testValue
{
return [self _testAttributeReportWithValue:testValue dataVersion:testValue];
}

- (NSArray<NSDictionary<NSString *, id> *> *)_testAttributeReportWithValue:(unsigned int)testValue dataVersion:(unsigned int)dataVersion
{
return @[ @{
MTRAttributePathKey : [MTRAttributePath attributePathWithEndpointID:@(0) clusterID:@(MTRClusterIDTypeLevelControlID) attributeID:@(MTRAttributeIDTypeClusterLevelControlAttributeCurrentLevelID)],
MTRDataKey : @ {
MTRDataVersionKey : @(testValue),
MTRDataVersionKey : @(dataVersion),
MTRTypeKey : MTRUnsignedIntegerValueType,
MTRValueKey : @(testValue),
}
Expand Down Expand Up @@ -3809,7 +3814,7 @@ - (void)test036_TestStorageBehaviorConfiguration
[device setDelegate:delegate queue:queue];

// Use a counter that will be incremented for each report as the value.
unsigned int currentTestValue = 1;
__block unsigned int currentTestValue = 1;

// Initial setup: Inject report and see that the attribute persisted. No delay is
// expected for the first (priming) report.
Expand Down Expand Up @@ -3928,54 +3933,84 @@ - (void)test036_TestStorageBehaviorConfiguration
XCTAssertLessThan(reportToPersistenceDelay, baseTestDelayTime * 2 * 5 * 1.3);

// Test 4: test reporting excessively, and see that persistence does not happen until
// reporting frequency goes back above the threshold
reportEndTime = nil;
dataPersistedTime = nil;
XCTestExpectation * dataPersisted4 = [self expectationWithDescription:@"data persisted 4"];
delegate.onClusterDataPersisted = ^{
os_unfair_lock_lock(&lock);
if (!dataPersistedTime) {
dataPersistedTime = [NSDate now];
}
os_unfair_lock_unlock(&lock);
[dataPersisted4 fulfill];
};

// Set report times with short delay and check that the multiplier is engaged
[device unitTestSetMostRecentReportTimes:[NSMutableArray arrayWithArray:@[
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 0.1 * 4)],
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 0.1 * 3)],
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 0.1 * 2)],
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 0.1)],
]]];

// Inject report that makes MTRDevice detect the device is reporting excessively
[device unitTestInjectAttributeReport:[self _testAttributeReportWithValue:currentTestValue++] fromSubscription:YES];
// reporting frequency goes back below the threshold
__auto_type excessiveReportTest = ^(unsigned int testId, NSArray<NSDictionary<NSString *, id> *> * (^reportGenerator)(void), bool expectPersistence) {
reportEndTime = nil;
dataPersistedTime = nil;
XCTestExpectation * dataPersisted = [self expectationWithDescription:[NSString stringWithFormat:@"data persisted %u", testId]];
dataPersisted.inverted = !expectPersistence;
delegate.onClusterDataPersisted = ^{
os_unfair_lock_lock(&lock);
if (!dataPersistedTime) {
dataPersistedTime = [NSDate now];
}
os_unfair_lock_unlock(&lock);
[dataPersisted fulfill];
};

// Now keep reporting excessively for base delay time max times max multiplier, plus a bit more
NSDate * excessiveStartTime = [NSDate now];
for (;;) {
usleep((useconds_t) (baseTestDelayTime * 0.1 * USEC_PER_SEC));
[device unitTestInjectAttributeReport:[self _testAttributeReportWithValue:currentTestValue++] fromSubscription:YES];
NSTimeInterval elapsed = -[excessiveStartTime timeIntervalSinceNow];
if (elapsed > (baseTestDelayTime * 2 * 5 * 1.2)) {
break;
// Set report times with short delay and check that the multiplier is engaged
[device unitTestSetMostRecentReportTimes:[NSMutableArray arrayWithArray:@[
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 0.1 * 4)],
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 0.1 * 3)],
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 0.1 * 2)],
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 0.1)],
]]];

// Inject report that makes MTRDevice detect the device is reporting excessively
[device unitTestInjectAttributeReport:reportGenerator() fromSubscription:YES];

// Now keep reporting excessively for base delay time max times max multiplier, plus a bit more
NSDate * excessiveStartTime = [NSDate now];
for (;;) {
usleep((useconds_t) (baseTestDelayTime * 0.1 * USEC_PER_SEC));
[device unitTestInjectAttributeReport:reportGenerator() fromSubscription:YES];
NSTimeInterval elapsed = -[excessiveStartTime timeIntervalSinceNow];
if (elapsed > (baseTestDelayTime * 2 * 5 * 1.2)) {
break;
}
}
}

// Check that persistence has not happened because it's now turned off
XCTAssertNil(dataPersistedTime);
// Check that persistence has not happened because it's now turned off
XCTAssertNil(dataPersistedTime);

// Now force report times to large number, to simulate time passage
[device unitTestSetMostRecentReportTimes:[NSMutableArray arrayWithArray:@[
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 10)],
]]];
// Now force report times to large number, to simulate time passage
[device unitTestSetMostRecentReportTimes:[NSMutableArray arrayWithArray:@[
[NSDate dateWithTimeIntervalSinceNow:-(baseTestDelayTime * 10)],
]]];

// And inject a report to trigger MTRDevice to recalculate that this device is no longer
// reporting excessively
[device unitTestInjectAttributeReport:[self _testAttributeReportWithValue:currentTestValue++] fromSubscription:YES];
// And inject a report to trigger MTRDevice to recalculate that this device is no longer
// reporting excessively
[device unitTestInjectAttributeReport:reportGenerator() fromSubscription:YES];

[self waitForExpectations:@[ dataPersisted ] timeout:60];
};

[self waitForExpectations:@[ dataPersisted4 ] timeout:60];
excessiveReportTest(
4, ^{
return [self _testAttributeReportWithValue:currentTestValue++];
}, true);

// Test 5: test reporting excessively with the same value and different data
// versions, and see that persistence does not happen until reporting
// frequency goes back below the threshold.
__block __auto_type dataVersion = currentTestValue;
// We incremented currentTestValue after injecting the last report. Make sure all the new
// reports use that last-reported value.
__auto_type lastReportedValue = currentTestValue - 1;
excessiveReportTest(
5, ^{
return [self _testAttributeReportWithValue:lastReportedValue dataVersion:dataVersion++];
}, true);

// Test 6: test reporting excessively with the same value and same data
// version, and see that persistence does not happen at all.
// We incremented dataVersion after injecting the last report. Make sure all the new
// reports use that last-reported value.
__block __auto_type lastReportedDataVersion = dataVersion - 1;
excessiveReportTest(
6, ^{
return [self _testAttributeReportWithValue:lastReportedValue dataVersion:lastReportedDataVersion];
}, false);

delegate.onReportEnd = nil;
delegate.onClusterDataPersisted = nil;
Expand Down
21 changes: 16 additions & 5 deletions src/darwin/Framework/CHIPTests/TestHelpers/MTRTestCase.mm
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,26 @@ - (void)setUp
- (void)tearDown
{
#if defined(ENABLE_LEAK_DETECTION) && ENABLE_LEAK_DETECTION
/**
* Unfortunately, doing this in "+ (void)tearDown" (the global suite teardown)
* does not trigger a test failure even if the XCTAssertEqual below fails.
*/
if (_detectLeaks) {
int pid = getpid();
__auto_type * cmd = [NSString stringWithFormat:@"leaks %d", pid];
int ret = system(cmd.UTF8String);
/**
* Unfortunately, doing this in "+ (void)tearDown" (the global suite teardown)
* does not trigger a test failure even if the XCTAssertEqual fails.
*/
XCTAssertEqual(ret, 0, "LEAKS DETECTED");
if (WIFEXITED(ret)) {
// leaks ran to completion.
XCTAssertEqual(WEXITSTATUS(ret), 0, "LEAKS DETECTED");
} else {
// leaks failed to actually run to completion (e.g. crashed or ran
// into some other sort of failure trying to do its work). Ideally
// we would fail our tests in that case, but this seems to be
// happening a fair amount, and randomly, on the ARM GitHub runners.
// Just log and ignore for now.
XCTAssertFalse(WIFSTOPPED(ret), "Not expecting a stopped leaks");
NSLog(@"Stopped by signal %d", WTERMSIG(ret));
}
}
#endif

Expand Down
Loading

0 comments on commit aba20dd

Please sign in to comment.