diff --git a/src/app/tests/suites/certification/PICS.yaml b/src/app/tests/suites/certification/PICS.yaml index a26afe936c7c8f..179a21d48923dc 100644 --- a/src/app/tests/suites/certification/PICS.yaml +++ b/src/app/tests/suites/certification/PICS.yaml @@ -7718,3 +7718,38 @@ PICS: # - label: "Does the DUT(server) support the SetTimeZoneResponse command?" id: TIMESYNC.S.C03.Tx + + ##################################################################################### + # Air Quality Cluster Test Plan + - label: "Does the device implement the Air Quality cluster as a server?" + id: AIRQUAL.S + + - label: "Does the device implement the Air Quality cluster as a client?" + id: AIRQUAL.C + + # + # server / attributes + # + - label: "Does the device implement the AirQuality attribute?" + id: AIRQUAL.S.A0000 + + # + # server / features + # + - label: "Does the device support the Fair feature?" + id: AIRQUAL.S.F00 + + - label: "Does the device support the Moderate feature?" + id: AIRQUAL.S.F01 + + - label: "Does the device support the VeryPoor feature?" + id: AIRQUAL.S.F02 + + - label: "Does the device support the ExtremelyPoor feature?" + id: AIRQUAL.S.F03 + + # + # server / manual + # + - label: "Changes air quality significantly" + id: AIRQUAL.M.AirQualityChange diff --git a/src/app/tests/suites/certification/Test_TC_AIRQUAL_1_1.yaml b/src/app/tests/suites/certification/Test_TC_AIRQUAL_1_1.yaml new file mode 100644 index 00000000000000..5552e06cc47f74 --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_AIRQUAL_1_1.yaml @@ -0,0 +1,125 @@ +# 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. + +name: 164.1.1. [TC-AIRQUAL-1.1] Global Attributes with DUT as Server + +PICS: + - AIRQUAL.S + +config: + nodeId: 0x12344321 + cluster: "Air Quality" + endpoint: 1 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + arguments: + values: + - name: "nodeId" + value: nodeId + + - label: "Read the global attribute: ClusterRevision" + command: "readAttribute" + attribute: "ClusterRevision" + response: + value: 1 + constraints: + type: int16u + + - label: "Read the global attribute: FeatureMap" + command: "readAttribute" + attribute: "FeatureMap" + PICS: + "!AIRQUAL.S.F00 && !AIRQUAL.S.F01 && !AIRQUAL.S.F02 && !AIRQUAL.S.F03" + response: + value: 0 + constraints: + type: bitmap32 + + - label: + "Given AIRQUAL.S.F00(Fair) ensure featuremap has the correct bit set" + command: "readAttribute" + attribute: "FeatureMap" + PICS: AIRQUAL.S.F00 + response: + constraints: + type: bitmap32 + hasMasksSet: [0x1] + + - label: + "Given AIRQUAL.S.F01(Moderate) ensure featuremap has the correct bit + set" + command: "readAttribute" + attribute: "FeatureMap" + PICS: AIRQUAL.S.F01 + response: + constraints: + type: bitmap32 + hasMasksSet: [0x2] + + - label: + "Given AIRQUAL.S.F02(VeryPoor) ensure featuremap has the correct bit + set" + command: "readAttribute" + attribute: "FeatureMap" + PICS: AIRQUAL.S.F02 + response: + constraints: + type: bitmap32 + hasMasksSet: [0x4] + + - label: + "Given AIRQUAL.S.F03(ExtremelyPoor) ensure featuremap has the correct + bit set" + command: "readAttribute" + attribute: "FeatureMap" + PICS: AIRQUAL.S.F03 + response: + constraints: + type: bitmap32 + hasMasksSet: [0x8] + + - label: "Read the global attribute: AttributeList" + command: "readAttribute" + attribute: "AttributeList" + response: + constraints: + type: list + contains: [0, 65528, 65529, 65530, 65531, 65532, 65533] + + - label: "Read the global attribute: AcceptedCommandList" + command: "readAttribute" + attribute: "AcceptedCommandList" + response: + constraints: + type: list + contains: [] + + - label: "Read the global attribute: GeneratedCommandList" + command: "readAttribute" + attribute: "GeneratedCommandList" + response: + value: [] + constraints: + type: list + + - label: "TH reads EventList attribute from DUT" + command: "readAttribute" + attribute: "EventList" + response: + value: [] + constraints: + type: list diff --git a/src/app/tests/suites/certification/Test_TC_AIRQUAL_2_1.yaml b/src/app/tests/suites/certification/Test_TC_AIRQUAL_2_1.yaml new file mode 100644 index 00000000000000..3f5c638317bb52 --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_AIRQUAL_2_1.yaml @@ -0,0 +1,42 @@ +# 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. + +name: 3.2.1. [TC-AIRQUAL-2.1] Attributes with server as DUT + +PICS: + - AIRQUAL.S + +config: + nodeId: 0x12344321 + cluster: "Air Quality" + endpoint: 1 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + arguments: + values: + - name: "nodeId" + value: nodeId + + - label: "TH reads from the DUT the AirQuality attribute." + PICS: AIRQUAL.S.A0000 + command: "readAttribute" + attribute: "AirQuality" + response: + constraints: + type: enum8 + minValue: 0 + maxValue: 6 diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index f61c7d0b99d8db..b8919a98b1c958 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -2099,3 +2099,14 @@ TIMESYNC.S.C04.Rsp=1 TIMESYNC.S.C05.Rsp=1 TIMESYNC.S.C03.Tx=1 TIMESYNC.C=0 + +# Air Quality +AIRQUAL.C=0 +AIRQUAL.S=1 +AIRQUAL.S.F00=1 +AIRQUAL.S.F01=1 +AIRQUAL.S.F02=1 +AIRQUAL.S.F03=1 +AIRQUAL.S.A0000=1 +PICS_USER_PROMPT=0 +AIRQUAL.M.AirQualityChange=0 diff --git a/src/app/tests/suites/ciTests.json b/src/app/tests/suites/ciTests.json index e2384ecbb50ab7..1d588af8f3050c 100644 --- a/src/app/tests/suites/ciTests.json +++ b/src/app/tests/suites/ciTests.json @@ -273,9 +273,11 @@ "Test_TC_G_2_1" ], "Scenes": ["Test_TC_S_1_1"], + "AirQuality": ["Test_TC_AIRQUAL_1_1", "Test_TC_AIRQUAL_2_1"], "collection": [ "AccessControl", "AccessControlEnforcement", + "AirQuality", "BooleanState", "BridgedDeviceBasicInformation", "Actions", diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 9d9732d6d955d4..1d4c20a87fc79e 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -47,6 +47,8 @@ class TestList : public Command printf("Test_TC_ACL_2_10\n"); printf("Test_TC_ACE_1_1\n"); printf("Test_TC_ACE_1_5\n"); + printf("Test_TC_AIRQUAL_1_1\n"); + printf("Test_TC_AIRQUAL_2_1\n"); printf("Test_TC_BOOL_1_1\n"); printf("Test_TC_BOOL_2_1\n"); printf("Test_TC_BRBINFO_1_1\n"); @@ -9435,6 +9437,315 @@ class Test_TC_ACE_1_5Suite : public TestCommand } }; +class Test_TC_AIRQUAL_1_1Suite : public TestCommand +{ +public: + Test_TC_AIRQUAL_1_1Suite(CredentialIssuerCommands * credsIssuerConfig) : + TestCommand("Test_TC_AIRQUAL_1_1", 11, credsIssuerConfig) + { + AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + } + + ~Test_TC_AIRQUAL_1_1Suite() {} + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds)); + } + +private: + chip::Optional mNodeId; + chip::Optional mCluster; + chip::Optional mEndpoint; + chip::Optional mTimeout; + + chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; } + + // + // Tests methods + // + + void OnResponse(const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override + { + bool shouldContinue = false; + + switch (mTestIndex - 1) + { + case 0: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 1: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint16_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("clusterRevision", value, 1U)); + VerifyOrReturn(CheckConstraintType("value", "int16u", "int16u")); + } + break; + case 2: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint32_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("featureMap", value, 0UL)); + VerifyOrReturn(CheckConstraintType("value", "bitmap32", "bitmap32")); + } + break; + case 3: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint32_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "bitmap32", "bitmap32")); + VerifyOrReturn(CheckConstraintHasMasksSet("value", value, 1UL)); + } + break; + case 4: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint32_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "bitmap32", "bitmap32")); + VerifyOrReturn(CheckConstraintHasMasksSet("value", value, 2UL)); + } + break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint32_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "bitmap32", "bitmap32")); + VerifyOrReturn(CheckConstraintHasMasksSet("value", value, 4UL)); + } + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint32_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "bitmap32", "bitmap32")); + VerifyOrReturn(CheckConstraintHasMasksSet("value", value, 8UL)); + } + break; + case 7: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::DecodableList value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "list", "list")); + VerifyOrReturn(CheckConstraintContains("value", value, 0UL)); + VerifyOrReturn(CheckConstraintContains("value", value, 65528UL)); + VerifyOrReturn(CheckConstraintContains("value", value, 65529UL)); + VerifyOrReturn(CheckConstraintContains("value", value, 65530UL)); + VerifyOrReturn(CheckConstraintContains("value", value, 65531UL)); + VerifyOrReturn(CheckConstraintContains("value", value, 65532UL)); + VerifyOrReturn(CheckConstraintContains("value", value, 65533UL)); + } + break; + case 8: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::DecodableList value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "list", "list")); + } + break; + case 9: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::DecodableList value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + { + auto iter_0 = value.begin(); + VerifyOrReturn(CheckNoMoreListItems("generatedCommandList", iter_0, 0)); + } + VerifyOrReturn(CheckConstraintType("value", "list", "list")); + } + break; + case 10: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::DecodableList value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + { + auto iter_0 = value.begin(); + VerifyOrReturn(CheckNoMoreListItems("eventList", iter_0, 0)); + } + VerifyOrReturn(CheckConstraintType("value", "list", "list")); + } + break; + default: + LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT)); + } + + if (shouldContinue) + { + ContinueOnChipMainThread(CHIP_NO_ERROR); + } + } + + CHIP_ERROR DoTestStep(uint16_t testIndex) override + { + using namespace chip::app::Clusters; + switch (testIndex) + { + case 0: { + LogStep(0, "Wait for the commissioned device to be retrieved"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; + return WaitForCommissionee(kIdentityAlpha, value); + } + case 1: { + LogStep(1, "Read the global attribute: ClusterRevision"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::ClusterRevision::Id, true, + chip::NullOptional); + } + case 2: { + LogStep(2, "Read the global attribute: FeatureMap"); + VerifyOrDo(!ShouldSkip("!AIRQUAL.S.F00 && !AIRQUAL.S.F01 && !AIRQUAL.S.F02 && !AIRQUAL.S.F03"), + return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::FeatureMap::Id, true, + chip::NullOptional); + } + case 3: { + LogStep(3, "Given AIRQUAL.S.F00(Fair) ensure featuremap has the correct bit set"); + VerifyOrDo(!ShouldSkip("AIRQUAL.S.F00"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::FeatureMap::Id, true, + chip::NullOptional); + } + case 4: { + LogStep(4, "Given AIRQUAL.S.F01(Moderate) ensure featuremap has the correct bit set"); + VerifyOrDo(!ShouldSkip("AIRQUAL.S.F01"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::FeatureMap::Id, true, + chip::NullOptional); + } + case 5: { + LogStep(5, "Given AIRQUAL.S.F02(VeryPoor) ensure featuremap has the correct bit set"); + VerifyOrDo(!ShouldSkip("AIRQUAL.S.F02"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::FeatureMap::Id, true, + chip::NullOptional); + } + case 6: { + LogStep(6, "Given AIRQUAL.S.F03(ExtremelyPoor) ensure featuremap has the correct bit set"); + VerifyOrDo(!ShouldSkip("AIRQUAL.S.F03"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::FeatureMap::Id, true, + chip::NullOptional); + } + case 7: { + LogStep(7, "Read the global attribute: AttributeList"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::AttributeList::Id, true, + chip::NullOptional); + } + case 8: { + LogStep(8, "Read the global attribute: AcceptedCommandList"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::AcceptedCommandList::Id, + true, chip::NullOptional); + } + case 9: { + LogStep(9, "Read the global attribute: GeneratedCommandList"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::GeneratedCommandList::Id, + true, chip::NullOptional); + } + case 10: { + LogStep(10, "TH reads EventList attribute from DUT"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::EventList::Id, true, + chip::NullOptional); + } + } + return CHIP_NO_ERROR; + } +}; + +class Test_TC_AIRQUAL_2_1Suite : public TestCommand +{ +public: + Test_TC_AIRQUAL_2_1Suite(CredentialIssuerCommands * credsIssuerConfig) : + TestCommand("Test_TC_AIRQUAL_2_1", 2, credsIssuerConfig) + { + AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + } + + ~Test_TC_AIRQUAL_2_1Suite() {} + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds)); + } + +private: + chip::Optional mNodeId; + chip::Optional mCluster; + chip::Optional mEndpoint; + chip::Optional mTimeout; + + chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; } + + // + // Tests methods + // + + void OnResponse(const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override + { + bool shouldContinue = false; + + switch (mTestIndex - 1) + { + case 0: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 1: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::Clusters::AirQuality::AirQualityEnum value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "enum8", "enum8")); + VerifyOrReturn(CheckConstraintMinValue("value", value, 0U)); + VerifyOrReturn(CheckConstraintMaxValue("value", value, 6U)); + } + break; + default: + LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT)); + } + + if (shouldContinue) + { + ContinueOnChipMainThread(CHIP_NO_ERROR); + } + } + + CHIP_ERROR DoTestStep(uint16_t testIndex) override + { + using namespace chip::app::Clusters; + switch (testIndex) + { + case 0: { + LogStep(0, "Wait for the commissioned device to be retrieved"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; + return WaitForCommissionee(kIdentityAlpha, value); + } + case 1: { + LogStep(1, "TH reads from the DUT the AirQuality attribute."); + VerifyOrDo(!ShouldSkip("AIRQUAL.S.A0000"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), AirQuality::Id, AirQuality::Attributes::AirQuality::Id, true, + chip::NullOptional); + } + } + return CHIP_NO_ERROR; + } +}; + class Test_TC_BOOL_1_1Suite : public TestCommand { public: @@ -121768,6 +122079,8 @@ void registerCommandsTests(Commands & commands, CredentialIssuerCommands * creds make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index 5b8921287153fe..48f12352b38286 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -43,6 +43,8 @@ class TestList : public Command { printf("Test_TC_ACL_2_3\n"); printf("Test_TC_ACE_1_1\n"); printf("Test_TC_ACE_1_5\n"); + printf("Test_TC_AIRQUAL_1_1\n"); + printf("Test_TC_AIRQUAL_2_1\n"); printf("Test_TC_BOOL_1_1\n"); printf("Test_TC_BOOL_2_1\n"); printf("Test_TC_BRBINFO_1_1\n"); @@ -6402,6 +6404,520 @@ class Test_TC_ACE_1_5 : public TestCommandBridge { } }; +class Test_TC_AIRQUAL_1_1 : public TestCommandBridge { +public: + // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced + Test_TC_AIRQUAL_1_1() + : TestCommandBridge("Test_TC_AIRQUAL_1_1") + , mTestIndex(0) + { + AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + } + // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull) + + ~Test_TC_AIRQUAL_1_1() {} + + /////////// TestCommand Interface ///////// + void NextTest() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + + if (0 == mTestIndex) { + ChipLogProgress(chipTool, " **** Test Start: Test_TC_AIRQUAL_1_1\n"); + } + + if (mTestCount == mTestIndex) { + ChipLogProgress(chipTool, " **** Test Complete: Test_TC_AIRQUAL_1_1\n"); + SetCommandExitStatus(CHIP_NO_ERROR); + return; + } + + Wait(); + + // 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: + ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n"); + err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); + break; + case 1: + ChipLogProgress(chipTool, " ***** Test Step 1 : Read the global attribute: ClusterRevision\n"); + err = TestReadTheGlobalAttributeClusterRevision_1(); + break; + case 2: + ChipLogProgress(chipTool, " ***** Test Step 2 : Read the global attribute: FeatureMap\n"); + if (ShouldSkip("!AIRQUAL.S.F00 && !AIRQUAL.S.F01 && !AIRQUAL.S.F02 && !AIRQUAL.S.F03")) { + NextTest(); + return; + } + err = TestReadTheGlobalAttributeFeatureMap_2(); + break; + case 3: + ChipLogProgress(chipTool, " ***** Test Step 3 : Given AIRQUAL.S.F00(Fair) ensure featuremap has the correct bit set\n"); + if (ShouldSkip("AIRQUAL.S.F00")) { + NextTest(); + return; + } + err = TestGivenAIRQUALSF00FairEnsureFeaturemapHasTheCorrectBitSet_3(); + break; + case 4: + ChipLogProgress( + chipTool, " ***** Test Step 4 : Given AIRQUAL.S.F01(Moderate) ensure featuremap has the correct bit set\n"); + if (ShouldSkip("AIRQUAL.S.F01")) { + NextTest(); + return; + } + err = TestGivenAIRQUALSF01ModerateEnsureFeaturemapHasTheCorrectBitSet_4(); + break; + case 5: + ChipLogProgress( + chipTool, " ***** Test Step 5 : Given AIRQUAL.S.F02(VeryPoor) ensure featuremap has the correct bit set\n"); + if (ShouldSkip("AIRQUAL.S.F02")) { + NextTest(); + return; + } + err = TestGivenAIRQUALSF02VeryPoorEnsureFeaturemapHasTheCorrectBitSet_5(); + break; + case 6: + ChipLogProgress( + chipTool, " ***** Test Step 6 : Given AIRQUAL.S.F03(ExtremelyPoor) ensure featuremap has the correct bit set\n"); + if (ShouldSkip("AIRQUAL.S.F03")) { + NextTest(); + return; + } + err = TestGivenAIRQUALSF03ExtremelyPoorEnsureFeaturemapHasTheCorrectBitSet_6(); + break; + case 7: + ChipLogProgress(chipTool, " ***** Test Step 7 : Read the global attribute: AttributeList\n"); + err = TestReadTheGlobalAttributeAttributeList_7(); + break; + case 8: + ChipLogProgress(chipTool, " ***** Test Step 8 : Read the global attribute: AcceptedCommandList\n"); + err = TestReadTheGlobalAttributeAcceptedCommandList_8(); + break; + case 9: + ChipLogProgress(chipTool, " ***** Test Step 9 : Read the global attribute: GeneratedCommandList\n"); + err = TestReadTheGlobalAttributeGeneratedCommandList_9(); + break; + case 10: + ChipLogProgress(chipTool, " ***** Test Step 10 : TH reads EventList attribute from DUT\n"); + err = TestThReadsEventListAttributeFromDut_10(); + break; + } + + if (CHIP_NO_ERROR != err) { + ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err)); + SetCommandExitStatus(err); + } + } + + void OnStatusUpdate(const chip::app::StatusIB & status) override + { + switch (mTestIndex - 1) { + case 0: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 1: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 2: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 3: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 4: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 7: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 8: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 9: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 10: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + } + + // Go on to the next test. + ContinueOnChipMainThread(CHIP_NO_ERROR); + } + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds)); + } + +private: + std::atomic_uint16_t mTestIndex; + const uint16_t mTestCount = 11; + + chip::Optional mNodeId; + chip::Optional mCluster; + chip::Optional mEndpoint; + chip::Optional mTimeout; + + CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0() + { + + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; + return WaitForCommissionee("alpha", value); + } + + CHIP_ERROR TestReadTheGlobalAttributeClusterRevision_1() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read the global attribute: ClusterRevision Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("ClusterRevision", actualValue, 1U)); + } + + VerifyOrReturn(CheckConstraintType("clusterRevision", "int16u", "int16u")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadTheGlobalAttributeFeatureMap_2() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read the global attribute: FeatureMap Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("FeatureMap", actualValue, 0UL)); + } + + VerifyOrReturn(CheckConstraintType("featureMap", "bitmap32", "bitmap32")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestGivenAIRQUALSF00FairEnsureFeaturemapHasTheCorrectBitSet_3() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Given AIRQUAL.S.F00(Fair) ensure featuremap has the correct bit set Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("featureMap", "bitmap32", "bitmap32")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestGivenAIRQUALSF01ModerateEnsureFeaturemapHasTheCorrectBitSet_4() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Given AIRQUAL.S.F01(Moderate) ensure featuremap has the correct bit set Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("featureMap", "bitmap32", "bitmap32")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestGivenAIRQUALSF02VeryPoorEnsureFeaturemapHasTheCorrectBitSet_5() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Given AIRQUAL.S.F02(VeryPoor) ensure featuremap has the correct bit set Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("featureMap", "bitmap32", "bitmap32")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestGivenAIRQUALSF03ExtremelyPoorEnsureFeaturemapHasTheCorrectBitSet_6() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Given AIRQUAL.S.F03(ExtremelyPoor) ensure featuremap has the correct bit set Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("featureMap", "bitmap32", "bitmap32")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadTheGlobalAttributeAttributeList_7() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read the global attribute: AttributeList Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("attributeList", "list", "list")); + VerifyOrReturn(CheckConstraintContains("attributeList", value, 0UL)); + VerifyOrReturn(CheckConstraintContains("attributeList", value, 65528UL)); + VerifyOrReturn(CheckConstraintContains("attributeList", value, 65529UL)); + VerifyOrReturn(CheckConstraintContains("attributeList", value, 65530UL)); + VerifyOrReturn(CheckConstraintContains("attributeList", value, 65531UL)); + VerifyOrReturn(CheckConstraintContains("attributeList", value, 65532UL)); + VerifyOrReturn(CheckConstraintContains("attributeList", value, 65533UL)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadTheGlobalAttributeAcceptedCommandList_8() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read the global attribute: AcceptedCommandList Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("acceptedCommandList", "list", "list")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadTheGlobalAttributeGeneratedCommandList_9() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read the global attribute: GeneratedCommandList Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("GeneratedCommandList", [actualValue count], static_cast(0))); + } + + VerifyOrReturn(CheckConstraintType("generatedCommandList", "list", "list")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestThReadsEventListAttributeFromDut_10() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable err) { + NSLog(@"TH reads EventList attribute from DUT Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("EventList", [actualValue count], static_cast(0))); + } + + VerifyOrReturn(CheckConstraintType("eventList", "list", "list")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } +}; + +class Test_TC_AIRQUAL_2_1 : public TestCommandBridge { +public: + // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced + Test_TC_AIRQUAL_2_1() + : TestCommandBridge("Test_TC_AIRQUAL_2_1") + , mTestIndex(0) + { + AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + } + // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull) + + ~Test_TC_AIRQUAL_2_1() {} + + /////////// TestCommand Interface ///////// + void NextTest() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + + if (0 == mTestIndex) { + ChipLogProgress(chipTool, " **** Test Start: Test_TC_AIRQUAL_2_1\n"); + } + + if (mTestCount == mTestIndex) { + ChipLogProgress(chipTool, " **** Test Complete: Test_TC_AIRQUAL_2_1\n"); + SetCommandExitStatus(CHIP_NO_ERROR); + return; + } + + Wait(); + + // 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: + ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n"); + err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); + break; + case 1: + ChipLogProgress(chipTool, " ***** Test Step 1 : TH reads from the DUT the AirQuality attribute.\n"); + if (ShouldSkip("AIRQUAL.S.A0000")) { + NextTest(); + return; + } + err = TestThReadsFromTheDutTheAirQualityAttribute_1(); + break; + } + + if (CHIP_NO_ERROR != err) { + ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err)); + SetCommandExitStatus(err); + } + } + + void OnStatusUpdate(const chip::app::StatusIB & status) override + { + switch (mTestIndex - 1) { + case 0: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 1: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + } + + // Go on to the next test. + ContinueOnChipMainThread(CHIP_NO_ERROR); + } + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds)); + } + +private: + std::atomic_uint16_t mTestIndex; + const uint16_t mTestCount = 2; + + chip::Optional mNodeId; + chip::Optional mCluster; + chip::Optional mEndpoint; + chip::Optional mTimeout; + + CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0() + { + + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; + return WaitForCommissionee("alpha", value); + } + + CHIP_ERROR TestThReadsFromTheDutTheAirQualityAttribute_1() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterAirQuality alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeAirQualityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"TH reads from the DUT the AirQuality attribute. Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("airQuality", "enum8", "enum8")); + VerifyOrReturn(CheckConstraintMinValue("airQuality", [value unsignedCharValue], 0U)); + VerifyOrReturn(CheckConstraintMaxValue("airQuality", [value unsignedCharValue], 6U)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } +}; + class Test_TC_BOOL_1_1 : public TestCommandBridge { public: // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced @@ -146039,6 +146555,8 @@ void registerCommandsTests(Commands & commands) make_unique(), make_unique(), make_unique(), + make_unique(), + make_unique(), make_unique(), make_unique(), make_unique(),