From 1632540bf1cb32beae49ddb2487d25187a074116 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 31 Aug 2021 13:42:19 -0700 Subject: [PATCH] Fix operational credentials fabric count attributes (#9303) * Fix operational credentials fabric count attributes * make the PR independet of compressed fabric ID feature * add test to Darwin tests as well * remove invalid check for vendor id * Update unit tests to check for limits * update number of min fabrics in the test * remove upper limit check in SupportedFabrics --- .../templates/partials/test_cluster.zapt | 18 ++ .../chip-tool/templates/tests-commands.zapt | 2 +- .../operational-credentials-server.cpp | 11 +- .../suites/OperationalCredentialsCluster.yaml | 36 ++++ .../CHIP/templates/clusters-tests.zapt | 2 +- .../CHIP/templates/partials/test_cluster.zapt | 6 + .../Framework/CHIPTests/CHIPClustersTests.m | 37 ++++ .../chip-tool/zap-generated/test/Commands.h | 180 ++++++++++++++++++ 8 files changed, 289 insertions(+), 3 deletions(-) create mode 100644 src/app/tests/suites/OperationalCredentialsCluster.yaml diff --git a/examples/chip-tool/templates/partials/test_cluster.zapt b/examples/chip-tool/templates/partials/test_cluster.zapt index d9fe9e4716788f..b9f5b179395d05 100644 --- a/examples/chip-tool/templates/partials/test_cluster.zapt +++ b/examples/chip-tool/templates/partials/test_cluster.zapt @@ -171,6 +171,24 @@ class {{filename}}: public TestCommand return; } {{/if}} + + {{#if expectedConstraints.minValue}} + if ({{asLowerCamelCase name}} < {{expectedConstraints.minValue}}) + { + ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is lower than expected. Min value is {{expectedConstraints.minValue}} but got '%d'", {{asLowerCamelCase name}}); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + {{/if}} + + {{#if expectedConstraints.maxValue}} + if ({{asLowerCamelCase name}} > {{expectedConstraints.maxValue}}) + { + ChipLogError(chipTool, "Error: {{asLowerCamelCase name}} is higher than expected. Max value is {{expectedConstraints.maxValue}} but got '%d'", {{asLowerCamelCase name}}); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + {{/if}} {{/if}} {{/chip_tests_item_response_parameters}} diff --git a/examples/chip-tool/templates/tests-commands.zapt b/examples/chip-tool/templates/tests-commands.zapt index 2a6e42c3d70b16..216c8b23f8ae00 100644 --- a/examples/chip-tool/templates/tests-commands.zapt +++ b/examples/chip-tool/templates/tests-commands.zapt @@ -4,4 +4,4 @@ #include -{{>test_cluster tests="TV_TargetNavigatorCluster, TV_AudioOutputCluster, TV_ApplicationLauncherCluster, TV_KeypadInputCluster, TV_AccountLoginCluster, TV_WakeOnLanCluster, TV_ApplicationBasicCluster, TV_MediaPlaybackCluster, TV_TvChannelCluster, TV_LowPowerCluster, TV_MediaInputCluster, TestCluster, Test_TC_OO_1_1, Test_TC_OO_2_1, Test_TC_OO_2_2, Test_TC_DM_1_1, Test_TC_DM_3_1, Test_TC_CC_3_4, Test_TC_CC_5, Test_TC_CC_6, Test_TC_CC_7, Test_TC_CC_8, Test_TC_WNCV_1_1, Test_TC_WNCV_2_1, Test_TC_BI_1_1, Test_TC_FLW_1_1, Test_TC_TM_1_1, Test_TC_OCC_1_1"}} +{{>test_cluster tests="TV_TargetNavigatorCluster, TV_AudioOutputCluster, TV_ApplicationLauncherCluster, TV_KeypadInputCluster, TV_AccountLoginCluster, TV_WakeOnLanCluster, TV_ApplicationBasicCluster, TV_MediaPlaybackCluster, TV_TvChannelCluster, TV_LowPowerCluster, TV_MediaInputCluster, TestCluster, Test_TC_OO_1_1, Test_TC_OO_2_1, Test_TC_OO_2_2, Test_TC_DM_1_1, Test_TC_DM_3_1, Test_TC_CC_3_4, Test_TC_CC_5, Test_TC_CC_6, Test_TC_CC_7, Test_TC_CC_8, Test_TC_WNCV_1_1, Test_TC_WNCV_2_1, Test_TC_BI_1_1, Test_TC_FLW_1_1, Test_TC_TM_1_1, Test_TC_OCC_1_1, OperationalCredentialsCluster"}} diff --git a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp index 0a25cfd9b57e98..db34f219264d79 100644 --- a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp +++ b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp @@ -122,7 +122,7 @@ CHIP_ERROR writeFabricsIntoFabricsListAttribute() const uint8_t * fabricLabel = pairing.GetFabricLabel(); // Skip over uninitialized fabrics - if (nodeId == kUndefinedNodeId || fabricId == kUndefinedFabricId || vendorId == kUndefinedVendorId) + if (nodeId == kUndefinedNodeId) { emberAfPrintln(EMBER_AF_PRINT_DEBUG, "OpCreds: Skipping over uninitialized fabric with fabricId 0x" ChipLogFormatX64 @@ -158,6 +158,15 @@ CHIP_ERROR writeFabricsIntoFabricsListAttribute() err = CHIP_ERROR_PERSISTED_STORAGE_FAILED; } + if (err == CHIP_NO_ERROR && + app::Clusters::OperationalCredentials::Attributes::SetSupportedFabrics(0, CHIP_CONFIG_MAX_DEVICE_ADMINS) != + EMBER_ZCL_STATUS_SUCCESS) + { + emberAfPrintln(EMBER_AF_PRINT_DEBUG, "OpCreds: Failed to write %" PRIu8 " in supported fabrics count attribute", + CHIP_CONFIG_MAX_DEVICE_ADMINS); + err = CHIP_ERROR_PERSISTED_STORAGE_FAILED; + } + return err; } diff --git a/src/app/tests/suites/OperationalCredentialsCluster.yaml b/src/app/tests/suites/OperationalCredentialsCluster.yaml new file mode 100644 index 00000000000000..a2fbd460c5bd13 --- /dev/null +++ b/src/app/tests/suites/OperationalCredentialsCluster.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2021 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. + +name: Operational Credentials Cluster Tests + +config: + cluster: "Operational Credentials" + endpoint: 0 + +tests: + - label: "Read number of supported fabrics" + command: "readAttribute" + attribute: "SupportedFabrics" + response: + constraints: + type: uint8 + minValue: 4 + + - label: "Read number of commissioned fabrics" + command: "readAttribute" + attribute: "CommissionedFabrics" + response: + constraints: + type: uint8 + minValue: 1 diff --git a/src/darwin/Framework/CHIP/templates/clusters-tests.zapt b/src/darwin/Framework/CHIP/templates/clusters-tests.zapt index d7bbd8676dc7b3..02b259d96ae5cc 100644 --- a/src/darwin/Framework/CHIP/templates/clusters-tests.zapt +++ b/src/darwin/Framework/CHIP/templates/clusters-tests.zapt @@ -207,7 +207,7 @@ CHIPDevice * GetPairedDevice(uint64_t deviceId) [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } -{{>test_cluster tests="TestCluster, Test_TC_OO_1_1, Test_TC_OO_2_1, Test_TC_OO_2_2, Test_TC_DM_1_1, Test_TC_DM_3_1, Test_TC_CC_3_4, Test_TC_CC_5, Test_TC_CC_6, Test_TC_CC_7, Test_TC_CC_8, Test_TC_WNCV_1_1, Test_TC_WNCV_2_1, Test_TC_BI_1_1, Test_TC_FLW_1_1, Test_TC_TM_1_1, Test_TC_OCC_1_1"}} +{{>test_cluster tests="TestCluster, Test_TC_OO_1_1, Test_TC_OO_2_1, Test_TC_OO_2_2, Test_TC_DM_1_1, Test_TC_DM_3_1, Test_TC_CC_3_4, Test_TC_CC_5, Test_TC_CC_6, Test_TC_CC_7, Test_TC_CC_8, Test_TC_WNCV_1_1, Test_TC_WNCV_2_1, Test_TC_BI_1_1, Test_TC_FLW_1_1, Test_TC_TM_1_1, Test_TC_OCC_1_1, OperationalCredentialsCluster"}} {{#chip_client_clusters}} {{#unless (isStrEqual "Test Cluster" name)}} diff --git a/src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt b/src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt index 28d90ec902d3ef..76f49767fdd411 100644 --- a/src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt +++ b/src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt @@ -69,6 +69,12 @@ {{#if expectedConstraints.maxLength}} XCTAssertLessThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] length], {{expectedConstraints.maxLength}}); {{/if}} + {{#if expectedConstraints.minValue}} + XCTAssertGreaterThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedConstraints.minValue}}); + {{/if}} + {{#if expectedConstraints.maxValue}} + XCTAssertLessThanOrEqual([values[@"{{#if parent.isReadAttribute}}value{{else}}{{name}}{{/if}}"] {{asObjectiveCNumberType "" type true}}Value], {{expectedConstraints.maxValue}}); + {{/if}} {{/if}} {{/chip_tests_item_response_parameters}} [expectation fulfill]; diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index 918e2c22db71b5..815117979f4fbd 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -5120,6 +5120,43 @@ - (void)testSendClusterTest_TC_OCC_1_1_000001_ReadAttribute [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } +- (void)testSendClusterOperationalCredentialsCluster_000000_ReadAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Read number of supported fabrics"]; + CHIPDevice * device = GetPairedDevice(kDeviceId); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPOperationalCredentials * cluster = [[CHIPOperationalCredentials alloc] initWithDevice:device endpoint:0 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster readAttributeSupportedFabricsWithResponseHandler:^(NSError * err, NSDictionary * values) { + NSLog(@"Read number of supported fabrics Error: %@", err); + + XCTAssertEqual(err.code, 0); + XCTAssertGreaterThanOrEqual([values[@"value"] unsignedCharValue], 4); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterOperationalCredentialsCluster_000001_ReadAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Read number of commissioned fabrics"]; + CHIPDevice * device = GetPairedDevice(kDeviceId); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPOperationalCredentials * cluster = [[CHIPOperationalCredentials alloc] initWithDevice:device endpoint:0 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster readAttributeCommissionedFabricsWithResponseHandler:^(NSError * err, NSDictionary * values) { + NSLog(@"Read number of commissioned fabrics Error: %@", err); + + XCTAssertEqual(err.code, 0); + XCTAssertGreaterThanOrEqual([values[@"value"] unsignedCharValue], 1); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} + - (void)testSendClusterAccountLoginReadAttributeClusterRevisionWithResponseHandler { XCTestExpectation * expectation = diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 7c2f17be11ba5b..c5db950b963be9 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -19410,6 +19410,185 @@ class Test_TC_OCC_1_1 : public TestCommand } }; +class OperationalCredentialsCluster : public TestCommand +{ +public: + OperationalCredentialsCluster() : TestCommand("OperationalCredentialsCluster"), mTestIndex(0) {} + + /////////// TestCommand Interface ///////// + void NextTest() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + + if (mTestCount == mTestIndex) + { + ChipLogProgress(chipTool, "OperationalCredentialsCluster: Test complete"); + SetCommandExitStatus(CHIP_NO_ERROR); + } + + // Ensure we increment mTestIndex before we start running the relevant + // command. That way if we lose the timeslice after we send the message + // but before our function call returns, we won't end up with an + // incorrect mTestIndex value observed when we get the response. + switch (mTestIndex++) + { + case 0: + err = TestSendClusterOperationalCredentialsCommandReadAttribute_0(); + break; + case 1: + err = TestSendClusterOperationalCredentialsCommandReadAttribute_1(); + break; + } + + if (CHIP_NO_ERROR != err) + { + ChipLogProgress(chipTool, "OperationalCredentialsCluster: %s", chip::ErrorStr(err)); + SetCommandExitStatus(err); + } + } + +private: + std::atomic_uint16_t mTestIndex; + const uint16_t mTestCount = 2; + + // + // Tests methods + // + + // Test Read number of supported fabrics + using SuccessCallback_0 = void (*)(void * context, uint8_t supportedFabrics); + chip::Callback::Callback mOnSuccessCallback_0{ + OnTestSendClusterOperationalCredentialsCommandReadAttribute_0_SuccessResponse, this + }; + chip::Callback::Callback mOnFailureCallback_0{ + OnTestSendClusterOperationalCredentialsCommandReadAttribute_0_FailureResponse, this + }; + bool mIsFailureExpected_0 = 0; + + CHIP_ERROR TestSendClusterOperationalCredentialsCommandReadAttribute_0() + { + ChipLogProgress(chipTool, "Operational Credentials - Read number of supported fabrics: Sending command..."); + + chip::Controller::OperationalCredentialsCluster cluster; + cluster.Associate(mDevice, 0); + + CHIP_ERROR err = CHIP_NO_ERROR; + + err = cluster.ReadAttributeSupportedFabrics(mOnSuccessCallback_0.Cancel(), mOnFailureCallback_0.Cancel()); + + return err; + } + + static void OnTestSendClusterOperationalCredentialsCommandReadAttribute_0_FailureResponse(void * context, uint8_t status) + { + ChipLogProgress(chipTool, "Operational Credentials - Read number of supported fabrics: Failure Response"); + + OperationalCredentialsCluster * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_0 == false) + { + ChipLogError(chipTool, "Error: The test was expecting a success callback. Got failure callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } + + static void OnTestSendClusterOperationalCredentialsCommandReadAttribute_0_SuccessResponse(void * context, + uint8_t supportedFabrics) + { + ChipLogProgress(chipTool, "Operational Credentials - Read number of supported fabrics: Success Response"); + + OperationalCredentialsCluster * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_0 == true) + { + ChipLogError(chipTool, "Error: The test was expecting a failure callback. Got success callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + ChipLogError(chipTool, "Warning: supportedFabrics type checking is not implemented yet. Expected type: '%s'", "uint8"); + + if (supportedFabrics < 4) + { + ChipLogError(chipTool, "Error: supportedFabrics is lower than expected. Min value is 4 but got '%d'", supportedFabrics); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } + + // Test Read number of commissioned fabrics + using SuccessCallback_1 = void (*)(void * context, uint8_t commissionedFabrics); + chip::Callback::Callback mOnSuccessCallback_1{ + OnTestSendClusterOperationalCredentialsCommandReadAttribute_1_SuccessResponse, this + }; + chip::Callback::Callback mOnFailureCallback_1{ + OnTestSendClusterOperationalCredentialsCommandReadAttribute_1_FailureResponse, this + }; + bool mIsFailureExpected_1 = 0; + + CHIP_ERROR TestSendClusterOperationalCredentialsCommandReadAttribute_1() + { + ChipLogProgress(chipTool, "Operational Credentials - Read number of commissioned fabrics: Sending command..."); + + chip::Controller::OperationalCredentialsCluster cluster; + cluster.Associate(mDevice, 0); + + CHIP_ERROR err = CHIP_NO_ERROR; + + err = cluster.ReadAttributeCommissionedFabrics(mOnSuccessCallback_1.Cancel(), mOnFailureCallback_1.Cancel()); + + return err; + } + + static void OnTestSendClusterOperationalCredentialsCommandReadAttribute_1_FailureResponse(void * context, uint8_t status) + { + ChipLogProgress(chipTool, "Operational Credentials - Read number of commissioned fabrics: Failure Response"); + + OperationalCredentialsCluster * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_1 == false) + { + ChipLogError(chipTool, "Error: The test was expecting a success callback. Got failure callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } + + static void OnTestSendClusterOperationalCredentialsCommandReadAttribute_1_SuccessResponse(void * context, + uint8_t commissionedFabrics) + { + ChipLogProgress(chipTool, "Operational Credentials - Read number of commissioned fabrics: Success Response"); + + OperationalCredentialsCluster * runner = reinterpret_cast(context); + + if (runner->mIsFailureExpected_1 == true) + { + ChipLogError(chipTool, "Error: The test was expecting a failure callback. Got success callback"); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + ChipLogError(chipTool, "Warning: commissionedFabrics type checking is not implemented yet. Expected type: '%s'", "uint8"); + + if (commissionedFabrics < 1) + { + ChipLogError(chipTool, "Error: commissionedFabrics is lower than expected. Min value is 1 but got '%d'", + commissionedFabrics); + runner->SetCommandExitStatus(CHIP_ERROR_INTERNAL); + return; + } + + runner->NextTest(); + } +}; + void registerCommandsTests(Commands & commands) { const char * clusterName = "Tests"; @@ -19443,6 +19622,7 @@ void registerCommandsTests(Commands & commands) make_unique(), make_unique(), make_unique(), + make_unique(), }; commands.Register(clusterName, clusterCommands);