Skip to content

Commit 6ae664f

Browse files
committed
Merging from master
2 parents 78f6ec8 + 74c95db commit 6ae664f

File tree

12 files changed

+147
-33
lines changed

12 files changed

+147
-33
lines changed

.github/workflows/darwin.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ jobs:
8383
-enableUndefinedBehaviorSanitizer YES
8484
- flavor: tsan
8585
arguments: -enableThreadSanitizer YES
86+
# "leaks" does not seem to be very compatible with asan or tsan
87+
- flavor: leaks
88+
defines: ENABLE_LEAK_DETECTION=1
8689
steps:
8790
- name: Checkout
8891
uses: actions/checkout@v4

scripts/setup/constraints.txt

+2-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ colorama==0.4.6
4949
# west
5050
coloredlogs==15.0.1
5151
# via -r requirements.all.txt
52-
construct==2.10.54
52+
construct==2.10.70
5353
# via
5454
# -r requirements.esp32.txt
5555
# esp-coredump
@@ -208,7 +208,7 @@ python-socketio==4.6.1
208208
# via -r requirements.esp32.txt
209209
pytz==2022.7.1
210210
# via pandas
211-
pyyaml==6.0
211+
pyyaml==6.0.1
212212
# via
213213
# esptool
214214
# idf-component-manager
@@ -296,4 +296,3 @@ setuptools==68.0.0
296296
# Higher versions depend on proto-plus, which break
297297
# nanopb code generation (due to name conflict of the 'proto' module)
298298
google-api-core==2.17.0
299-

scripts/setup/requirements.esp32.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ reedsolo>=1.5.3,<=1.5.4
99
bitarray==2.6.0
1010
bitstring>=3.1.6,<4
1111
ecdsa>=0.16.0
12-
construct==2.10.54
12+
construct>=2.10.70
1313
python-socketio<5
1414
itsdangerous<2.1 ; python_version < "3.11"
1515
esp_idf_monitor==1.1.1

src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm

+50-16
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include <lib/core/CASEAuthTag.h>
2424
#include <lib/core/NodeId.h>
25+
#include <lib/support/CodeUtils.h>
2526
#include <lib/support/SafeInt.h>
2627

2728
// FIXME: Are these good key strings? https://github.com/project-chip/connectedhomeip/issues/28973
@@ -106,7 +107,8 @@ static bool IsValidCATNumber(id _Nullable value)
106107
@implementation MTRDeviceControllerDataStore {
107108
id<MTRDeviceControllerStorageDelegate> _storageDelegate;
108109
dispatch_queue_t _storageDelegateQueue;
109-
MTRDeviceController * _controller;
110+
// Controller owns us, so we have to make sure to not keep it alive.
111+
__weak MTRDeviceController * _controller;
110112
// Array of nodes with resumption info, oldest-stored first.
111113
NSMutableArray<NSNumber *> * _nodesWithResumptionInfo;
112114
}
@@ -126,7 +128,9 @@ - (nullable instancetype)initWithController:(MTRDeviceController *)controller
126128
__block id resumptionNodeList;
127129
dispatch_sync(_storageDelegateQueue, ^{
128130
@autoreleasepool {
129-
resumptionNodeList = [_storageDelegate controller:_controller
131+
// NOTE: controller, not our weak ref, since we know it's still
132+
// valid under this sync dispatch.
133+
resumptionNodeList = [_storageDelegate controller:controller
130134
valueForKey:sResumptionNodeListKey
131135
securityLevel:MTRStorageSecurityLevelSecure
132136
sharingType:MTRStorageSharingTypeNotShared];
@@ -154,9 +158,12 @@ - (nullable instancetype)initWithController:(MTRDeviceController *)controller
154158
- (void)fetchAttributeDataForAllDevices:(MTRDeviceControllerDataStoreClusterDataHandler)clusterDataHandler
155159
{
156160
__block NSDictionary<NSString *, id> * dataStoreSecureLocalValues = nil;
161+
MTRDeviceController * controller = _controller;
162+
VerifyOrReturn(controller != nil); // No way to call delegate without controller.
163+
157164
dispatch_sync(_storageDelegateQueue, ^{
158165
if ([self->_storageDelegate respondsToSelector:@selector(valuesForController:securityLevel:sharingType:)]) {
159-
dataStoreSecureLocalValues = [self->_storageDelegate valuesForController:self->_controller securityLevel:MTRStorageSecurityLevelSecure sharingType:MTRStorageSharingTypeNotShared];
166+
dataStoreSecureLocalValues = [self->_storageDelegate valuesForController:controller securityLevel:MTRStorageSecurityLevelSecure sharingType:MTRStorageSharingTypeNotShared];
160167
}
161168
});
162169

@@ -177,32 +184,35 @@ - (nullable MTRCASESessionResumptionInfo *)findResumptionInfoByResumptionID:(NSD
177184

178185
- (void)storeResumptionInfo:(MTRCASESessionResumptionInfo *)resumptionInfo
179186
{
187+
MTRDeviceController * controller = _controller;
188+
VerifyOrReturn(controller != nil); // No way to call delegate without controller.
189+
180190
auto * oldInfo = [self findResumptionInfoByNodeID:resumptionInfo.nodeID];
181191
dispatch_sync(_storageDelegateQueue, ^{
182192
if (oldInfo != nil) {
183193
// Remove old resumption id key. No need to do that for the
184194
// node id, because we are about to overwrite it.
185-
[_storageDelegate controller:_controller
195+
[_storageDelegate controller:controller
186196
removeValueForKey:ResumptionByResumptionIDKey(oldInfo.resumptionID)
187197
securityLevel:MTRStorageSecurityLevelSecure
188198
sharingType:MTRStorageSharingTypeNotShared];
189199
[_nodesWithResumptionInfo removeObject:resumptionInfo.nodeID];
190200
}
191201

192-
[_storageDelegate controller:_controller
202+
[_storageDelegate controller:controller
193203
storeValue:resumptionInfo
194204
forKey:ResumptionByNodeIDKey(resumptionInfo.nodeID)
195205
securityLevel:MTRStorageSecurityLevelSecure
196206
sharingType:MTRStorageSharingTypeNotShared];
197-
[_storageDelegate controller:_controller
207+
[_storageDelegate controller:controller
198208
storeValue:resumptionInfo
199209
forKey:ResumptionByResumptionIDKey(resumptionInfo.resumptionID)
200210
securityLevel:MTRStorageSecurityLevelSecure
201211
sharingType:MTRStorageSharingTypeNotShared];
202212

203213
// Update our resumption info node list.
204214
[_nodesWithResumptionInfo addObject:resumptionInfo.nodeID];
205-
[_storageDelegate controller:_controller
215+
[_storageDelegate controller:controller
206216
storeValue:[_nodesWithResumptionInfo copy]
207217
forKey:sResumptionNodeListKey
208218
securityLevel:MTRStorageSecurityLevelSecure
@@ -212,17 +222,20 @@ - (void)storeResumptionInfo:(MTRCASESessionResumptionInfo *)resumptionInfo
212222

213223
- (void)clearAllResumptionInfo
214224
{
225+
MTRDeviceController * controller = _controller;
226+
VerifyOrReturn(controller != nil); // No way to call delegate without controller.
227+
215228
// Can we do less dispatch? We would need to have a version of
216229
// _findResumptionInfoWithKey that assumes we are already on the right queue.
217230
for (NSNumber * nodeID in _nodesWithResumptionInfo) {
218231
auto * oldInfo = [self findResumptionInfoByNodeID:nodeID];
219232
if (oldInfo != nil) {
220233
dispatch_sync(_storageDelegateQueue, ^{
221-
[_storageDelegate controller:_controller
234+
[_storageDelegate controller:controller
222235
removeValueForKey:ResumptionByResumptionIDKey(oldInfo.resumptionID)
223236
securityLevel:MTRStorageSecurityLevelSecure
224237
sharingType:MTRStorageSharingTypeNotShared];
225-
[_storageDelegate controller:_controller
238+
[_storageDelegate controller:controller
226239
removeValueForKey:ResumptionByNodeIDKey(oldInfo.nodeID)
227240
securityLevel:MTRStorageSecurityLevelSecure
228241
sharingType:MTRStorageSharingTypeNotShared];
@@ -235,9 +248,12 @@ - (void)clearAllResumptionInfo
235248

236249
- (CHIP_ERROR)storeLastLocallyUsedNOC:(MTRCertificateTLVBytes)noc
237250
{
251+
MTRDeviceController * controller = _controller;
252+
VerifyOrReturnError(controller != nil, CHIP_ERROR_PERSISTED_STORAGE_FAILED); // No way to call delegate without controller.
253+
238254
__block BOOL ok;
239255
dispatch_sync(_storageDelegateQueue, ^{
240-
ok = [_storageDelegate controller:_controller
256+
ok = [_storageDelegate controller:controller
241257
storeValue:noc
242258
forKey:sLastLocallyUsedNOCKey
243259
securityLevel:MTRStorageSecurityLevelSecure
@@ -248,10 +264,13 @@ - (CHIP_ERROR)storeLastLocallyUsedNOC:(MTRCertificateTLVBytes)noc
248264

249265
- (MTRCertificateTLVBytes _Nullable)fetchLastLocallyUsedNOC
250266
{
267+
MTRDeviceController * controller = _controller;
268+
VerifyOrReturnValue(controller != nil, nil); // No way to call delegate without controller.
269+
251270
__block id data;
252271
dispatch_sync(_storageDelegateQueue, ^{
253272
@autoreleasepool {
254-
data = [_storageDelegate controller:_controller
273+
data = [_storageDelegate controller:controller
255274
valueForKey:sLastLocallyUsedNOCKey
256275
securityLevel:MTRStorageSecurityLevelSecure
257276
sharingType:MTRStorageSharingTypeNotShared];
@@ -271,6 +290,9 @@ - (MTRCertificateTLVBytes _Nullable)fetchLastLocallyUsedNOC
271290

272291
- (nullable MTRCASESessionResumptionInfo *)_findResumptionInfoWithKey:(nullable NSString *)key
273292
{
293+
MTRDeviceController * controller = _controller;
294+
VerifyOrReturnValue(controller != nil, nil); // No way to call delegate without controller.
295+
274296
// key could be nil if [NSString stringWithFormat] returns nil for some reason.
275297
if (key == nil) {
276298
return nil;
@@ -279,7 +301,7 @@ - (nullable MTRCASESessionResumptionInfo *)_findResumptionInfoWithKey:(nullable
279301
__block id resumptionInfo;
280302
dispatch_sync(_storageDelegateQueue, ^{
281303
@autoreleasepool {
282-
resumptionInfo = [_storageDelegate controller:_controller
304+
resumptionInfo = [_storageDelegate controller:controller
283305
valueForKey:key
284306
securityLevel:MTRStorageSecurityLevelSecure
285307
sharingType:MTRStorageSharingTypeNotShared];
@@ -318,9 +340,12 @@ - (nullable MTRCASESessionResumptionInfo *)_findResumptionInfoWithKey:(nullable
318340

319341
- (id)_fetchAttributeCacheValueForKey:(NSString *)key expectedClass:(Class)expectedClass;
320342
{
343+
MTRDeviceController * controller = _controller;
344+
VerifyOrReturnValue(controller != nil, nil); // No way to call delegate without controller.
345+
321346
id data;
322347
@autoreleasepool {
323-
data = [_storageDelegate controller:_controller
348+
data = [_storageDelegate controller:controller
324349
valueForKey:key
325350
securityLevel:MTRStorageSecurityLevelSecure
326351
sharingType:MTRStorageSharingTypeNotShared];
@@ -338,7 +363,10 @@ - (id)_fetchAttributeCacheValueForKey:(NSString *)key expectedClass:(Class)expec
338363

339364
- (BOOL)_storeAttributeCacheValue:(id)value forKey:(NSString *)key
340365
{
341-
return [_storageDelegate controller:_controller
366+
MTRDeviceController * controller = _controller;
367+
VerifyOrReturnValue(controller != nil, NO); // No way to call delegate without controller.
368+
369+
return [_storageDelegate controller:controller
342370
storeValue:value
343371
forKey:key
344372
securityLevel:MTRStorageSecurityLevelSecure
@@ -347,15 +375,21 @@ - (BOOL)_storeAttributeCacheValue:(id)value forKey:(NSString *)key
347375

348376
- (BOOL)_bulkStoreAttributeCacheValues:(NSDictionary<NSString *, id<NSSecureCoding>> *)values
349377
{
350-
return [_storageDelegate controller:_controller
378+
MTRDeviceController * controller = _controller;
379+
VerifyOrReturnValue(controller != nil, NO); // No way to call delegate without controller.
380+
381+
return [_storageDelegate controller:controller
351382
storeValues:values
352383
securityLevel:MTRStorageSecurityLevelSecure
353384
sharingType:MTRStorageSharingTypeNotShared];
354385
}
355386

356387
- (BOOL)_removeAttributeCacheValueForKey:(NSString *)key
357388
{
358-
return [_storageDelegate controller:_controller
389+
MTRDeviceController * controller = _controller;
390+
VerifyOrReturnValue(controller != nil, NO); // No way to call delegate without controller.
391+
392+
return [_storageDelegate controller:controller
359393
removeValueForKey:key
360394
securityLevel:MTRStorageSecurityLevelSecure
361395
sharingType:MTRStorageSharingTypeNotShared];

src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m

+6-4
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,12 @@
1616

1717
#import <Matter/Matter.h>
1818

19-
// system dependencies
20-
#import <XCTest/XCTest.h>
21-
2219
#import "MTRDeviceControllerLocalTestStorage.h"
2320
#import "MTRDeviceTestDelegate.h"
2421
#import "MTRDevice_Internal.h"
2522
#import "MTRErrorTestUtils.h"
2623
#import "MTRFabricInfoChecker.h"
24+
#import "MTRTestCase.h"
2725
#import "MTRTestDeclarations.h"
2826
#import "MTRTestKeys.h"
2927
#import "MTRTestPerControllerStorage.h"
@@ -177,7 +175,7 @@ - (void)issueOperationalCertificateForRequest:(MTROperationalCSRInfo *)csrInfo
177175

178176
@end
179177

180-
@interface MTRPerControllerStorageTests : XCTestCase
178+
@interface MTRPerControllerStorageTests : MTRTestCase
181179
@end
182180

183181
@implementation MTRPerControllerStorageTests {
@@ -353,6 +351,8 @@ - (nullable MTRDeviceController *)startControllerWithRootKeys:(MTRTestKeys *)roo
353351

354352
- (void)test001_BasicControllerStartup
355353
{
354+
self.detectLeaks = YES;
355+
356356
__auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
357357
XCTAssertNotNil(factory);
358358

@@ -401,6 +401,8 @@ - (void)test001_BasicControllerStartup
401401

402402
- (void)test002_TryStartingTwoControllersWithSameNodeID
403403
{
404+
self.detectLeaks = YES;
405+
404406
__auto_type * rootKeys = [[MTRTestKeys alloc] init];
405407
XCTAssertNotNil(rootKeys);
406408

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright (c) 2024 Project CHIP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <XCTest/XCTest.h>
18+
19+
NS_ASSUME_NONNULL_BEGIN
20+
21+
@interface MTRTestCase : XCTestCase
22+
// It would be nice to do the leak-detection automatically, but running "leaks"
23+
// on every single sub-test is slow, and some of our tests seem to have leaks
24+
// outside Matter.framework. So have it be opt-in for now, and improve later.
25+
@property (nonatomic) BOOL detectLeaks;
26+
@end
27+
28+
NS_ASSUME_NONNULL_END
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright (c) 2024 Project CHIP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <stdlib.h>
18+
#include <unistd.h>
19+
20+
#import "MTRTestCase.h"
21+
22+
@implementation MTRTestCase
23+
24+
/**
25+
* Unfortunately, doing this in "+ (void)tearDown" (the global suite teardown)
26+
* does not trigger a test failure even if the XCTAssertEqual fails.
27+
*/
28+
- (void)tearDown
29+
{
30+
#if 0
31+
#if defined(ENABLE_LEAK_DETECTION) && ENABLE_LEAK_DETECTION
32+
if (_detectLeaks) {
33+
int pid = getpid();
34+
__auto_type * cmd = [NSString stringWithFormat:@"leaks %d", pid];
35+
int ret = system(cmd.UTF8String);
36+
XCTAssertEqual(ret, 0, "LEAKS DETECTED");
37+
}
38+
#endif
39+
#endif
40+
41+
[super tearDown];
42+
}
43+
44+
@end

src/darwin/Framework/Matter.xcodeproj/project.pbxproj

+6
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
512431282BA0C8BF000BC136 /* SetMRPParametersCommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5124311C2BA0C09A000BC136 /* SetMRPParametersCommand.mm */; };
140140
512431292BA0C8BF000BC136 /* ResetMRPParametersCommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5124311A2BA0C09A000BC136 /* ResetMRPParametersCommand.mm */; };
141141
5129BCFD26A9EE3300122DDF /* MTRError.h in Headers */ = {isa = PBXBuildFile; fileRef = 5129BCFC26A9EE3300122DDF /* MTRError.h */; settings = {ATTRIBUTES = (Public, ); }; };
142+
5131BF662BE2E1B000D5D6BC /* MTRTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5131BF642BE2E1B000D5D6BC /* MTRTestCase.mm */; };
142143
51339B1F2A0DA64D00C798C1 /* MTRCertificateValidityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 51339B1E2A0DA64D00C798C1 /* MTRCertificateValidityTests.m */; };
143144
5136661328067D550025EDAE /* MTRDeviceController_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5136660F28067D540025EDAE /* MTRDeviceController_Internal.h */; };
144145
5136661428067D550025EDAE /* MTRDeviceControllerFactory.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5136661028067D540025EDAE /* MTRDeviceControllerFactory.mm */; };
@@ -549,6 +550,8 @@
549550
5124311B2BA0C09A000BC136 /* SetMRPParametersCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SetMRPParametersCommand.h; sourceTree = "<group>"; };
550551
5124311C2BA0C09A000BC136 /* SetMRPParametersCommand.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SetMRPParametersCommand.mm; sourceTree = "<group>"; };
551552
5129BCFC26A9EE3300122DDF /* MTRError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRError.h; sourceTree = "<group>"; };
553+
5131BF642BE2E1B000D5D6BC /* MTRTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRTestCase.mm; sourceTree = "<group>"; };
554+
5131BF652BE2E1B000D5D6BC /* MTRTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRTestCase.h; sourceTree = "<group>"; };
552555
51339B1E2A0DA64D00C798C1 /* MTRCertificateValidityTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTRCertificateValidityTests.m; sourceTree = "<group>"; };
553556
5136660F28067D540025EDAE /* MTRDeviceController_Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceController_Internal.h; sourceTree = "<group>"; };
554557
5136661028067D540025EDAE /* MTRDeviceControllerFactory.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDeviceControllerFactory.mm; sourceTree = "<group>"; };
@@ -1119,6 +1122,8 @@
11191122
51189FC72A33ACE900184508 /* TestHelpers */ = {
11201123
isa = PBXGroup;
11211124
children = (
1125+
5131BF652BE2E1B000D5D6BC /* MTRTestCase.h */,
1126+
5131BF642BE2E1B000D5D6BC /* MTRTestCase.mm */,
11221127
D437613F285BDC0D0051FEA2 /* MTRTestKeys.h */,
11231128
51C8E3F72825CDB600D47D00 /* MTRTestKeys.m */,
11241129
D4376140285BDC0D0051FEA2 /* MTRTestStorage.h */,
@@ -1974,6 +1979,7 @@
19741979
buildActionMask = 2147483647;
19751980
files = (
19761981
51742B4E29CB6B88009974FE /* MTRPairingTests.m in Sources */,
1982+
5131BF662BE2E1B000D5D6BC /* MTRTestCase.mm in Sources */,
19771983
51669AF02913204400F4AA36 /* MTRBackwardsCompatTests.m in Sources */,
19781984
51D10D2E2808E2CA00E8CA3D /* MTRTestStorage.m in Sources */,
19791985
51D0B12A2B61766F006E3511 /* MTRServerEndpointTests.m in Sources */,

0 commit comments

Comments
 (0)