blob: 23deb27d90422ce515385d9457993b4201c55df4 [file] [log] [blame]
/**
*
* Copyright (c) 2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Matter/Matter.h>
// system dependencies
#import <XCTest/XCTest.h>
#import "MTRTestKeys.h"
#import "MTRTestStorage.h"
static uint16_t kTestVendorId1 = 0xFFF1u;
static uint16_t kTestVendorId2 = 0xFFF2u;
void CheckFabricInfo(NSArray<MTRFabricInfo *> * fabricInfoList, NSMutableSet<NSDictionary *> * expectedSet)
{
XCTAssertEqual([fabricInfoList count], [expectedSet count]);
for (size_t i = 0; i < [fabricInfoList count]; ++i) {
__auto_type * info = fabricInfoList[i];
NSSet<NSDictionary *> * expectedInfoForIndex = [expectedSet objectsPassingTest:^(NSDictionary * obj, BOOL * stop) {
return [info.fabricIndex isEqual:obj[@"fabricIndex"]];
}];
XCTAssertEqual([expectedInfoForIndex count], 1);
__auto_type * expected = [expectedInfoForIndex anyObject];
XCTAssertEqualObjects(info.rootPublicKey, expected[@"rootPublicKey"]);
XCTAssertEqualObjects(info.vendorID, expected[@"vendorID"]);
XCTAssertEqualObjects(info.fabricID, expected[@"fabricID"]);
XCTAssertEqualObjects(info.nodeID, expected[@"nodeID"]);
XCTAssertEqualObjects(info.label, expected[@"label"]);
XCTAssertNotNil(info.rootCertificate);
XCTAssertNotNil(info.rootCertificateTLV);
XCTAssertEqualObjects([MTRCertificates convertX509Certificate:info.rootCertificate], info.rootCertificateTLV);
XCTAssertEqualObjects([MTRCertificates convertMatterCertificate:info.rootCertificateTLV], info.rootCertificate);
XCTAssertEqual((info.intermediateCertificate == nil), (info.intermediateCertificateTLV == nil));
XCTAssertEqualObjects(@(info.intermediateCertificate != nil), expected[@"hasIntermediateCertificate"]);
if (info.intermediateCertificate != nil) {
XCTAssertEqualObjects(
[MTRCertificates convertX509Certificate:info.intermediateCertificate], info.intermediateCertificateTLV);
XCTAssertEqualObjects(
[MTRCertificates convertMatterCertificate:info.intermediateCertificateTLV], info.intermediateCertificate);
}
XCTAssertNotNil(info.operationalCertificate);
XCTAssertNotNil(info.operationalCertificateTLV);
XCTAssertEqualObjects([MTRCertificates convertX509Certificate:info.operationalCertificate], info.operationalCertificateTLV);
XCTAssertEqualObjects(
[MTRCertificates convertMatterCertificate:info.operationalCertificateTLV], info.operationalCertificate);
__auto_type * certInfo = [[MTRCertificateInfo alloc] initWithTLVBytes:info.operationalCertificateTLV];
XCTAssertNotNil(certInfo);
XCTAssertEqualObjects(certInfo.subject.nodeID, info.nodeID);
XCTAssertEqualObjects(certInfo.subject.fabricID, info.fabricID);
XCTAssertEqualObjects(info.fabricIndex, expected[@"fabricIndex"]);
[expectedSet removeObject:expected];
}
}
@interface MTRFabricInfoTests : XCTestCase
@end
@implementation MTRFabricInfoTests
/**
* Override recordIssue to log things better.
*/
- (void)recordIssue:(XCTIssue *)issue
{
for (XCTSourceCodeFrame * stackFrame in issue.sourceCodeContext.callStack) {
__auto_type * location = stackFrame.symbolInfo.location;
if (location != nil) {
fprintf(stderr, " %s:%llu\n", location.fileURL.path.UTF8String, (unsigned long long) location.lineNumber);
}
}
[super recordIssue:issue];
}
- (void)testFabricInfoNoFabrics
{
__auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
XCTAssertNotNil(factory);
XCTAssertFalse([factory isRunning]);
__auto_type * storage = [[MTRTestStorage alloc] init];
__auto_type * factoryParams = [[MTRDeviceControllerFactoryParams alloc] initWithStorage:storage];
XCTAssertTrue([factory startControllerFactory:factoryParams error:nil]);
XCTAssertTrue([factory isRunning]);
__auto_type * fabricInfoList = [factory knownFabrics];
CheckFabricInfo(fabricInfoList, [NSMutableSet set]);
[factory stopControllerFactory];
XCTAssertFalse([factory isRunning]);
}
- (void)testFabricInfoSingleFabric
{
__auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
XCTAssertNotNil(factory);
XCTAssertFalse([factory isRunning]);
__auto_type * storage = [[MTRTestStorage alloc] init];
__auto_type * factoryParams = [[MTRDeviceControllerFactoryParams alloc] initWithStorage:storage];
XCTAssertTrue([factory startControllerFactory:factoryParams error:nil]);
XCTAssertTrue([factory isRunning]);
__auto_type * testKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(testKeys);
const unsigned fabricID = 1;
__auto_type * params = [[MTRDeviceControllerStartupParams alloc] initWithIPK:testKeys.ipk
fabricID:@(fabricID)
nocSigner:testKeys];
XCTAssertNotNil(params);
params.vendorID = @(kTestVendorId1);
MTRDeviceController * controller = [factory createControllerOnNewFabric:params error:nil];
XCTAssertNotNil(controller);
XCTAssertTrue([controller isRunning]);
__auto_type * nodeID = [controller controllerNodeID];
__auto_type * fabricInfoList = [factory knownFabrics];
CheckFabricInfo(fabricInfoList, [NSMutableSet setWithArray:@[ @{
@"rootPublicKey" : [testKeys publicKeyData],
@"vendorID" : @(kTestVendorId1),
@"fabricID" : @(fabricID),
@"nodeID" : nodeID,
@"label" : @"",
@"hasIntermediateCertificate" : @(NO),
@"fabricIndex" : @(1)
} ]]);
[controller shutdown];
XCTAssertFalse([controller isRunning]);
// Should still know about the fabric.
__auto_type * fabricInfoList2 = [factory knownFabrics];
CheckFabricInfo(fabricInfoList2, [NSMutableSet setWithArray:@[ @{
@"rootPublicKey" : [testKeys publicKeyData],
@"vendorID" : @(kTestVendorId1),
@"fabricID" : @(fabricID),
@"nodeID" : nodeID,
@"label" : @"",
@"hasIntermediateCertificate" : @(NO),
@"fabricIndex" : @(1)
} ]]);
[factory stopControllerFactory];
XCTAssertFalse([factory isRunning]);
}
- (void)testFabricInfoTwoFabrics
{
__auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
XCTAssertNotNil(factory);
XCTAssertFalse([factory isRunning]);
__auto_type * storage = [[MTRTestStorage alloc] init];
__auto_type * factoryParams = [[MTRDeviceControllerFactoryParams alloc] initWithStorage:storage];
XCTAssertTrue([factory startControllerFactory:factoryParams error:nil]);
XCTAssertTrue([factory isRunning]);
__auto_type * testKeys1 = [[MTRTestKeys alloc] init];
XCTAssertNotNil(testKeys1);
const unsigned fabricID1 = 8;
__auto_type * params = [[MTRDeviceControllerStartupParams alloc] initWithIPK:testKeys1.ipk
fabricID:@(fabricID1)
nocSigner:testKeys1];
XCTAssertNotNil(params);
params.vendorID = @(kTestVendorId1);
MTRDeviceController * controller1 = [factory createControllerOnNewFabric:params error:nil];
XCTAssertNotNil(controller1);
XCTAssertTrue([controller1 isRunning]);
__auto_type * rootKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(rootKeys);
__auto_type * root = [MTRCertificates createRootCertificate:rootKeys issuerID:nil fabricID:nil error:nil];
XCTAssertNotNil(root);
__auto_type * intermediateKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(intermediateKeys);
__auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys
rootCertificate:root
intermediatePublicKey:intermediateKeys.publicKey
issuerID:nil
fabricID:nil
error:nil];
XCTAssertNotNil(intermediate);
const unsigned fabricID2 = 17;
params = [[MTRDeviceControllerStartupParams alloc] initWithIPK:rootKeys.ipk fabricID:@(fabricID2) nocSigner:intermediateKeys];
XCTAssertNotNil(params);
params.vendorID = @(kTestVendorId2);
params.rootCertificate = root;
params.intermediateCertificate = intermediate;
MTRDeviceController * controller2 = [factory createControllerOnNewFabric:params error:nil];
XCTAssertNotNil(controller2);
XCTAssertTrue([controller2 isRunning]);
__auto_type * nodeID1 = [controller1 controllerNodeID];
__auto_type * nodeID2 = [controller2 controllerNodeID];
__auto_type * fabricInfoList = [factory knownFabrics];
CheckFabricInfo(fabricInfoList, [NSMutableSet setWithArray:@[
@{
@"rootPublicKey" : [testKeys1 publicKeyData],
@"vendorID" : @(kTestVendorId1),
@"fabricID" : @(fabricID1),
@"nodeID" : nodeID1,
@"label" : @"",
@"hasIntermediateCertificate" : @(NO),
@"fabricIndex" : @(1)
},
@{
@"rootPublicKey" : [rootKeys publicKeyData],
@"vendorID" : @(kTestVendorId2),
@"fabricID" : @(fabricID2),
@"nodeID" : nodeID2,
@"label" : @"",
@"hasIntermediateCertificate" : @(YES),
@"fabricIndex" : @(2)
}
]]);
[controller1 shutdown];
XCTAssertFalse([controller1 isRunning]);
XCTAssertTrue([controller2 isRunning]);
// Should still know about the fabrics.
__auto_type * fabricInfoList2 = [factory knownFabrics];
CheckFabricInfo(fabricInfoList2, [NSMutableSet setWithArray:@[
@{
@"rootPublicKey" : [testKeys1 publicKeyData],
@"vendorID" : @(kTestVendorId1),
@"fabricID" : @(fabricID1),
@"nodeID" : nodeID1,
@"label" : @"",
@"hasIntermediateCertificate" : @(NO),
@"fabricIndex" : @(1)
},
@{
@"rootPublicKey" : [rootKeys publicKeyData],
@"vendorID" : @(kTestVendorId2),
@"fabricID" : @(fabricID2),
@"nodeID" : nodeID2,
@"label" : @"",
@"hasIntermediateCertificate" : @(YES),
@"fabricIndex" : @(2)
}
]]);
[controller2 shutdown];
XCTAssertFalse([controller1 isRunning]);
XCTAssertFalse([controller2 isRunning]);
// Should still know about the fabrics.
__auto_type * fabricInfoList3 = [factory knownFabrics];
CheckFabricInfo(fabricInfoList3, [NSMutableSet setWithArray:@[
@{
@"rootPublicKey" : [testKeys1 publicKeyData],
@"vendorID" : @(kTestVendorId1),
@"fabricID" : @(fabricID1),
@"nodeID" : nodeID1,
@"label" : @"",
@"hasIntermediateCertificate" : @(NO),
@"fabricIndex" : @(1)
},
@{
@"rootPublicKey" : [rootKeys publicKeyData],
@"vendorID" : @(kTestVendorId2),
@"fabricID" : @(fabricID2),
@"nodeID" : nodeID2,
@"label" : @"",
@"hasIntermediateCertificate" : @(YES),
@"fabricIndex" : @(2)
}
]]);
[factory stopControllerFactory];
XCTAssertFalse([factory isRunning]);
}
@end