From 1108038400475dbe9b4dc542df57d60f3ef9c3fa Mon Sep 17 00:00:00 2001 From: Matt Hazley Date: Fri, 21 Jul 2023 12:32:19 +0100 Subject: [PATCH] Update to TC_FAN_3_2, addition of TC_FAN_3_3, TC_FAN_3_4, TC_FAN_3_5, & TC_FAN_3_6 (#28106) * Modified TC_FAN_3_2 to be compliant with update test plan. Removed TC_FAN_3_4.yaml as it will be a Python test * Adding TC_FAN_3_3 and TC_FAN_3_4 as Python tests * Making the function parameter naming more consistent for API & Delegate functions. Also fixes small bug where a step when SpeedSetting was null would crash * Command should not send success if no delegate is set * Adding Python test script for TC_FAN_3_5 * Removing unused import from python * Added missing case to Step Handler to handle wrapping to speedMax when speed 1 and lowesfOff is false * Added TC_FAN_3_6 * Fixed copy-paste bug * Added TC_FAN_3_5 to CI * Restyled by prettier-yaml * Restyled by autopep8 * Restyled by isort * Adding 3_6 to disable list in darwin as airflow direction not in matter framework yet * regen tests after Darwin diable * Improving tests with suggestions from PR * Regen codegen * removing incorrectly included file --------- Co-authored-by: Restyled.io --- .github/workflows/tests.yaml | 3 + .../all-clusters-common/src/fan-stub.cpp | 35 +-- examples/all-clusters-app/linux/.kvs | 28 ++ .../fan-control-server/fan-control-delegate.h | 10 +- .../fan-control-server/fan-control-server.cpp | 15 +- .../fan-control-server/fan-control-server.h | 4 +- .../suites/certification/Test_TC_FAN_3_2.yaml | 24 +- ...t_TC_FAN_3_4.yaml => Test_TC_FAN_3_6.yaml} | 52 +++- src/app/tests/suites/ciTests.json | 2 +- src/python_testing/TC_FAN_3_3.py | 90 +++++++ src/python_testing/TC_FAN_3_4.py | 81 ++++++ src/python_testing/TC_FAN_3_5.py | 206 +++++++++++++++ .../chip-tool/zap-generated/test/Commands.h | 121 ++++++--- .../zap-generated/test/Commands.h | 249 +++++++++++++----- 14 files changed, 765 insertions(+), 155 deletions(-) create mode 100644 examples/all-clusters-app/linux/.kvs rename src/app/tests/suites/certification/{Test_TC_FAN_3_4.yaml => Test_TC_FAN_3_6.yaml} (52%) create mode 100644 src/python_testing/TC_FAN_3_3.py create mode 100644 src/python_testing/TC_FAN_3_4.py create mode 100644 src/python_testing/TC_FAN_3_5.py diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index cba40591a9e4fc..0a7c5d6addb91a 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -451,6 +451,9 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_decode 1" --script "src/python_testing/TC_TIMESYNC_3_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_decode 1" --script "src/python_testing/TC_DA_1_5.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_decode 1" --script "src/python_testing/TC_IDM_1_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_decode 1" --script "src/python_testing/TC_FAN_3_3.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_decode 1" --script "src/python_testing/TC_FAN_3_4.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_decode 1" --script "src/python_testing/TC_FAN_3_5.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestMatterTestingSupport.py"' - name: Uploading core files uses: actions/upload-artifact@v3 diff --git a/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp index 1c343f139e71cf..553532622ddcac 100644 --- a/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp @@ -43,14 +43,14 @@ class FanControlManager : public AttributeAccessInterface, public Delegate {} CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; - Status HandleStep(StepDirectionEnum direction, bool wrap, bool off) override; + Status HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) override; private: CHIP_ERROR ReadPercentCurrent(AttributeValueEncoder & aEncoder); CHIP_ERROR ReadSpeedCurrent(AttributeValueEncoder & aEncoder); }; -static FanControlManager * mFanControlManager; +static FanControlManager * mFanControlManager = nullptr; CHIP_ERROR FanControlManager::ReadPercentCurrent(AttributeValueEncoder & aEncoder) { @@ -80,12 +80,12 @@ CHIP_ERROR FanControlManager::ReadSpeedCurrent(AttributeValueEncoder & aEncoder) return aEncoder.Encode(ret); } -Status FanControlManager::HandleStep(StepDirectionEnum direction, bool wrap, bool lowestOff) +Status FanControlManager::HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) { - ChipLogProgress(NotSpecified, "FanControlManager::HandleStep direction %d, wrap %d, lowestOff %d", to_underlying(direction), - wrap, lowestOff); + ChipLogProgress(NotSpecified, "FanControlManager::HandleStep aDirection %d, aWrap %d, aLowestOff %d", to_underlying(aDirection), + aWrap, aLowestOff); - VerifyOrReturnError(direction != StepDirectionEnum::kUnknownEnumValue, Status::InvalidCommand); + VerifyOrReturnError(aDirection != StepDirectionEnum::kUnknownEnumValue, Status::InvalidCommand); uint8_t speedMax; SpeedMax::Get(mEndpoint, &speedMax); @@ -93,9 +93,9 @@ Status FanControlManager::HandleStep(StepDirectionEnum direction, bool wrap, boo DataModel::Nullable speedSetting; SpeedSetting::Get(mEndpoint, speedSetting); - uint8_t newSpeedSetting = speedSetting.Value(); + uint8_t newSpeedSetting = speedSetting.IsNull() ? 0 : speedSetting.Value(); - if (direction == StepDirectionEnum::kIncrease) + if (aDirection == StepDirectionEnum::kIncrease) { if (speedSetting.IsNull()) { @@ -107,17 +107,17 @@ Status FanControlManager::HandleStep(StepDirectionEnum direction, bool wrap, boo } else if (speedSetting.Value() == speedMax) { - if (wrap) + if (aWrap) { - newSpeedSetting = lowestOff ? 0 : 1; + newSpeedSetting = aLowestOff ? 0 : 1; } } } - else if (direction == StepDirectionEnum::kDecrease) + else if (aDirection == StepDirectionEnum::kDecrease) { if (speedSetting.IsNull()) { - newSpeedSetting = lowestOff ? 0 : 1; + newSpeedSetting = aLowestOff ? 0 : 1; } else if ((speedSetting.Value() > 1) && (speedSetting.Value() <= speedMax)) { @@ -125,18 +125,22 @@ Status FanControlManager::HandleStep(StepDirectionEnum direction, bool wrap, boo } else if (speedSetting.Value() == 1) { - if (lowestOff) + if (aLowestOff) { newSpeedSetting = static_cast(speedSetting.Value() - 1); } + else if (aWrap) + { + newSpeedSetting = speedMax; + } } else if (speedSetting.Value() == 0) { - if (wrap) + if (aWrap) { newSpeedSetting = speedMax; } - else if (!lowestOff) + else if (!aLowestOff) { newSpeedSetting = 1; } @@ -167,6 +171,7 @@ CHIP_ERROR FanControlManager::Read(const ConcreteReadAttributePath & aPath, Attr void emberAfFanControlClusterInitCallback(EndpointId endpoint) { + VerifyOrDie(mFanControlManager == nullptr); mFanControlManager = new FanControlManager(endpoint); registerAttributeAccessOverride(mFanControlManager); FanControl::SetDefaultDelegate(endpoint, mFanControlManager); diff --git a/examples/all-clusters-app/linux/.kvs b/examples/all-clusters-app/linux/.kvs new file mode 100644 index 00000000000000..9976ff5b8b7caf --- /dev/null +++ b/examples/all-clusters-app/linux/.kvs @@ -0,0 +1,28 @@ +[DEFAULT] +f/1/ac/0/0=FSQBBSQCAjYDBmm2AQAYNAQY +f/1/g=FSQBACQCACQDACQEACQFACQGASQHABg= +f/1/i=FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQTAhgkBwEkCAEwCUEE3KqJqpPwju/MeqShRDFpusi544wfWj6+gYRG/nor4oHRLfTRz4+zihd9ONWqQ9zwA/CQomn+sjmIvbcRYIYh2DcKNQEpARgkAmAwBBQPVaSOYFdX6pOarWj2mXieOQsSJzAFFGx6kZSTgFw3YQDgKHYjei851xbkGDALQPRuk4wx/ZAQXSmais4GD0JyZl9Jwxq1MM8TUdUQ1nCQ0Q/VuHZqy0pR9HxjgLUDPy2b4YFJIT1rIf8ZYHAeaCMY +f/1/k/0=FSQBACQCATYDFScEUAIAAOx/AAAlBVRMMAYQ7QtLfz7zOjEY6QUsagDDPRgVJAQAJAUAMAYQAAAAAAAAAAAAAAAAAAAAABgVJAQAJAUAMAYQAAAAAAAAAAAAAAAAAAAAABgYJQf//xg= +f/1/m=FSUA8f8sAQAY +f/1/n=FTABAQEkAgE3AyQTAhgmBIAigScmBYAlTTo3BiQVASYRIUM0EhgkBwEkCAEwCUEE7R7vwTlybDjtGBspWXkUMSnID4um6q91pa7EQdCSIioP+AgPAA3zqzXyYunmoZbVijM9UbzOUhvacYvA+2xanzcKNQEoARgkAgE2AwQCBAEYMAQUi5rGWgAt12jH/3fxeswo+bhw+YcwBRQPVaSOYFdX6pOarWj2mXieOQsSJxgwC0AtXja1zqi99vqxUOcDooFbR7g3dR6FHR/DjYJOy2QgtY0m1Krqo9Whb9A//TtnLTpsXj+DKnl4cBJ6Zb1WGdhrGA== +f/1/o=FSQAATABYQTtHu/BOXJsOO0YGylZeRQxKcgPi6bqr3WlrsRB0JIiKg/4CA8ADfOrNfJi6eahltWKMz1RvM5SG9pxi8D7bFqftpuGwM3zJ0gq/ZXqozNld3ZK32h4PWWNKTlq3zM9wUEY +f/1/r=FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQUARgkBwEkCAEwCUEECT5tju37pQzMYxhc2pumcwtyKq7elKv8mcWFxDqluOWVK6RJYxiytMv4NQA+JFg/rN8AVPzfz2txBhBJKEF0UDcKNQEpARgkAmAwBBRsepGUk4BcN2EA4Ch2I3ovOdcW5DAFFGx6kZSTgFw3YQDgKHYjei851xbkGDALQBPAPvpTcPaJ51tb6/5sPfKuU6QWe2ClszX+T9fCPL4ZSeJZq0ukzeGMqOgnlAh3MVzkugI2IKdO9e/lcAib04QY +f/1/s/000000000001B669=FTADEO0xJXt8dKE+RAjHrjhJCREwBCAkLjwW/9P1MAh7PKST7kCABWTyP5W6JnAccoRVc8JXPDAFDAAAAAAAAAAAAAAAABg= +g/a/0/2b/0=BWVuLVVT +g/a/1/102/7=Gw== +g/a/1/300/4001=Ag== +g/a/1/300/7=AAA= +g/a/1/8/0=/g== +g/fidx=FSQAAjYBBAEYGA== +g/gcc=E0Y8Aw== +g/gdc=PtW/BQ== +g/gfl=FSQBASQCARg= +g/im/ec=AAABAAAAAAA= +g/lkgt=FSYAgwxNLBg= +g/s/7TEle3x0oT5ECMeuOEkJEQ\x3d\x3d=FSQBASYCabYBABg= +g/sri=FhUkAQEmAmm2AQAYGA== +g/sum=MAA= +g/ts/tz=FhUgAAAkAQAsAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBg= +wifi-pass= +wifi-ssid= + diff --git a/src/app/clusters/fan-control-server/fan-control-delegate.h b/src/app/clusters/fan-control-server/fan-control-delegate.h index 65a67d2f4915bc..8b70a046268742 100644 --- a/src/app/clusters/fan-control-server/fan-control-delegate.h +++ b/src/app/clusters/fan-control-server/fan-control-delegate.h @@ -38,16 +38,16 @@ class Delegate * @brief * This method handles the step command. This will happen as fast as possible. * - * @param[in] direction direction in which to step - * @param[in] wrap whether the step command wraps or not - * @param[in] wrap whether the step command wraps or not + * @param[in] aDirection the direction in which the speed should step + * @param[in] aWrap whether the speed should wrap or not + * @param[in] aLowestOff whether the device should consider the lowest setting as off * * @return Success On success. * @return Other Value indicating it failed to execute the command. */ - virtual Protocols::InteractionModel::Status HandleStep(StepDirectionEnum direction, bool wrap, bool off) = 0; + virtual Protocols::InteractionModel::Status HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) = 0; - Delegate(EndpointId endpoint) : mEndpoint(endpoint) {} + Delegate(EndpointId aEndpoint) : mEndpoint(aEndpoint) {} virtual ~Delegate() = default; diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 9437d821c0631b..8359e03610b96e 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -58,21 +58,21 @@ namespace app { namespace Clusters { namespace FanControl { -Delegate * GetDelegate(EndpointId endpoint) +Delegate * GetDelegate(EndpointId aEndpoint) { uint16_t ep = - emberAfGetClusterServerEndpointIndex(endpoint, FanControl::Id, EMBER_AF_FAN_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + emberAfGetClusterServerEndpointIndex(aEndpoint, FanControl::Id, EMBER_AF_FAN_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); return (ep >= kFanControlDelegateTableSize ? nullptr : gDelegateTable[ep]); } -void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate) +void SetDefaultDelegate(EndpointId aEndpoint, Delegate * aDelegate) { uint16_t ep = - emberAfGetClusterServerEndpointIndex(endpoint, FanControl::Id, EMBER_AF_FAN_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + emberAfGetClusterServerEndpointIndex(aEndpoint, FanControl::Id, EMBER_AF_FAN_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); // if endpoint is found if (ep < kFanControlDelegateTableSize) { - gDelegateTable[ep] = delegate; + gDelegateTable[ep] = aDelegate; } } @@ -460,8 +460,8 @@ bool emberAfFanControlClusterStepCallback(app::CommandHandler * commandObj, cons EndpointId endpoint = commandPath.mEndpointId; StepDirectionEnum direction = commandData.direction; - bool wrapValue = commandData.wrap.HasValue() ? commandData.wrap.Value() : false; - bool lowestOffValue = commandData.lowestOff.HasValue() ? commandData.lowestOff.Value() : false; + bool wrapValue = commandData.wrap.ValueOr(false); + bool lowestOffValue = commandData.lowestOff.ValueOr(false); Delegate * delegate = GetDelegate(endpoint); if (delegate) @@ -471,6 +471,7 @@ bool emberAfFanControlClusterStepCallback(app::CommandHandler * commandObj, cons else { ChipLogProgress(Zcl, "FanControl has no delegate set for endpoint:%u", endpoint); + status = Status::Failure; } } diff --git a/src/app/clusters/fan-control-server/fan-control-server.h b/src/app/clusters/fan-control-server/fan-control-server.h index d06504c3b87d2a..ff5fcb549d4086 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.h +++ b/src/app/clusters/fan-control-server/fan-control-server.h @@ -27,8 +27,8 @@ namespace app { namespace Clusters { namespace FanControl { -void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate); -Delegate * GetDelegate(EndpointId endpoint); +void SetDefaultDelegate(EndpointId aEndpoint, Delegate * aDelegate); +Delegate * GetDelegate(EndpointId aEndpoint); } // namespace FanControl } // namespace Clusters diff --git a/src/app/tests/suites/certification/Test_TC_FAN_3_2.yaml b/src/app/tests/suites/certification/Test_TC_FAN_3_2.yaml index d2130d7fcf1216..00c34297c69e15 100644 --- a/src/app/tests/suites/certification/Test_TC_FAN_3_2.yaml +++ b/src/app/tests/suites/certification/Test_TC_FAN_3_2.yaml @@ -22,9 +22,6 @@ config: nodeId: 0x12344321 cluster: "Fan Control" endpoint: 1 - ConfigSpeedSetting: - type: int8u - defaultValue: 50 tests: - label: "Step 1: Wait for the commissioned device to be retrieved" @@ -35,12 +32,21 @@ tests: - name: "nodeId" value: nodeId - - label: "Step 2: TH writes SpeedSetting attribute a valid value to DUT" + - label: "Step 2: TH reads from the DUT the SpeedMax attribute" + PICS: FAN.S.A0004 + command: "readAttribute" + attribute: "SpeedMax" + response: + saveAs: rSpeedMax + + - label: + "Step 3: TH writes TH writes to the DUT the a value less than or equal + to the value read in step 2" PICS: FAN.S.A0005 command: "writeAttribute" attribute: "SpeedSetting" arguments: - value: ConfigSpeedSetting + value: rSpeedMax - label: "Wait 1000ms" PICS: FAN.S.A0005 @@ -51,16 +57,16 @@ tests: - name: "ms" value: 1000 - - label: "Step 3: TH reads from the DUT the the SpeedSetting attribute" + - label: "Step 4: TH reads from the DUT the the SpeedSetting attribute" PICS: FAN.S.A0005 command: "readAttribute" attribute: "SpeedSetting" response: - value: ConfigSpeedSetting + value: rSpeedMax - - label: "Step 4: TH reads from the DUT the the SpeedCurrent attribute" + - label: "Step 5: TH reads from the DUT the the SpeedCurrent attribute" PICS: FAN.S.A0006 command: "readAttribute" attribute: "SpeedCurrent" response: - value: ConfigSpeedSetting + value: rSpeedMax diff --git a/src/app/tests/suites/certification/Test_TC_FAN_3_4.yaml b/src/app/tests/suites/certification/Test_TC_FAN_3_6.yaml similarity index 52% rename from src/app/tests/suites/certification/Test_TC_FAN_3_4.yaml rename to src/app/tests/suites/certification/Test_TC_FAN_3_6.yaml index 3b38aa97f30495..8c296d2977f663 100644 --- a/src/app/tests/suites/certification/Test_TC_FAN_3_4.yaml +++ b/src/app/tests/suites/certification/Test_TC_FAN_3_6.yaml @@ -12,19 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -name: 263.2.9. [TC-FAN-3.4] Optional wind functionality with DUT as Server +name: 263.2.7. [TC-FAN-3.2] Optional direction functionality with DUT as Server PICS: - FAN.S - - FAN.S.F03 + - FAN.S.F05 config: nodeId: 0x12344321 cluster: "Fan Control" endpoint: 1 - ConfigWindSetting: - type: bitmap8 - defaultValue: 1 tests: - label: "Step 1: Wait for the commissioned device to be retrieved" @@ -35,15 +32,15 @@ tests: - name: "nodeId" value: nodeId - - label: "Step 2: TH writes WindSetting attribute a valid value to DUT" - PICS: FAN.S.A0008 + - label: "Step 2: TH writes a value of Forward to the DUT" + PICS: FAN.S.A000B command: "writeAttribute" - attribute: "WindSetting" + attribute: "AirflowDirection" arguments: - value: ConfigWindSetting + value: 0 - label: "Wait 1000ms" - PICS: FAN.S.A0008 + PICS: FAN.S.A000B cluster: "DelayCommands" command: "WaitForMs" arguments: @@ -51,9 +48,36 @@ tests: - name: "ms" value: 1000 - - label: "Step 3: TH reads from the DUT the the WindSetting attribute" - PICS: FAN.S.A0008 + - label: + "Step 3: TH reads from the DUT the AirflowDirection attribute and + check it is forwards" + PICS: FAN.S.A000B command: "readAttribute" - attribute: "WindSetting" + attribute: "AirflowDirection" response: - value: ConfigWindSetting + value: 0 + + - label: "Step 4: TH writes a value of Reverse to the DUT" + PICS: FAN.S.A000B + command: "writeAttribute" + attribute: "AirflowDirection" + arguments: + value: 1 + + - label: "Wait 1000ms" + PICS: FAN.S.A000B + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 1000 + + - label: + "Step 5: TH reads from the DUT the AirflowDirection attribute and + check it is reverse" + PICS: FAN.S.A000B + command: "readAttribute" + attribute: "AirflowDirection" + response: + value: 1 diff --git a/src/app/tests/suites/ciTests.json b/src/app/tests/suites/ciTests.json index baa57727b368b4..23f55962015daa 100644 --- a/src/app/tests/suites/ciTests.json +++ b/src/app/tests/suites/ciTests.json @@ -68,7 +68,7 @@ "Test_TC_FAN_2_5", "Test_TC_FAN_3_1", "Test_TC_FAN_3_2", - "Test_TC_FAN_3_4" + "Test_TC_FAN_3_6" ], "GeneralCommissioning": ["Test_TC_CGEN_1_1", "Test_TC_CGEN_2_1"], "GeneralDiagnostics": ["Test_TC_DGGEN_1_1", "Test_TC_DGGEN_2_1"], diff --git a/src/python_testing/TC_FAN_3_3.py b/src/python_testing/TC_FAN_3_3.py new file mode 100644 index 00000000000000..79ac3e1077817f --- /dev/null +++ b/src/python_testing/TC_FAN_3_3.py @@ -0,0 +1,90 @@ +# +# Copyright (c) 2023 Project CHIP Authors +# All rights reserved. +# +# 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 logging +import time + +import chip.clusters as Clusters +from chip.interaction_model import Status +from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main +from mobly import asserts + +logger = logging.getLogger(__name__) + + +class TC_FAN_3_3(MatterBaseTest): + + async def read_fc_attribute_expect_success(self, endpoint, attribute): + cluster = Clusters.Objects.FanControl + return await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attribute) + + async def read_rock_support(self, endpoint): + return await self.read_fc_attribute_expect_success(endpoint, Clusters.FanControl.Attributes.RockSupport) + + async def read_rock_setting(self, endpoint): + return await self.read_fc_attribute_expect_success(endpoint, Clusters.FanControl.Attributes.RockSetting) + + async def write_rock_setting(self, endpoint, rock_setting): + result = await self.default_controller.WriteAttribute(self.dut_node_id, [(endpoint, Clusters.FanControl.Attributes.RockSetting(rock_setting))]) + asserts.assert_equal(result[0].Status, Status.Success, "RockSetting write failed") + + @async_test_body + async def test_TC_FAN_3_3(self): + if not self.check_pics("FAN.S.F02"): + logger.info("Test skipped because PICS FAN.S.F02 is not set") + return + + endpoint = self.user_params.get("endpoint", 1) + + self.print_step(1, "Commissioning, already done") + + self.print_step(2, "Read from the DUT the RockSupport attribute and store") + rock_support = await self.read_rock_support(endpoint=endpoint) + + if rock_support & Clusters.FanControl.Bitmaps.RockBitmap.kRockLeftRight: + self.print_step(3, "RockLeftRight is supported, so write 0x01 to RockSetting") + await self.write_rock_setting(endpoint=endpoint, rock_setting=Clusters.FanControl.Bitmaps.RockBitmap.kRockLeftRight) + time.sleep(1) + + self.print_step(4, "Read from the DUT the RockSetting attribute") + rock_setting = await self.read_rock_setting(endpoint=endpoint) + asserts.assert_equal(rock_setting, Clusters.FanControl.Bitmaps.RockBitmap.kRockLeftRight, "RockSetting is not 0x01") + + if rock_support & Clusters.FanControl.Bitmaps.RockBitmap.kRockUpDown: + self.print_step(5, "RockUpDown is supported, so write 0x02 to RockSetting") + await self.write_rock_setting(endpoint=endpoint, rock_setting=Clusters.FanControl.Bitmaps.RockBitmap.kRockUpDown) + time.sleep(1) + + self.print_step(6, "Read from the DUT the RockSetting attribute") + rock_setting = await self.read_rock_setting(endpoint=endpoint) + asserts.assert_equal(rock_setting, Clusters.FanControl.Bitmaps.RockBitmap.kRockUpDown, "RockSetting is not 0x02") + + if rock_support & Clusters.FanControl.Bitmaps.RockBitmap.kRockRound: + self.print_step(7, "RockRound is supported, so write 0x04 to RockSetting") + await self.write_rock_setting(endpoint=endpoint, rock_setting=Clusters.FanControl.Bitmaps.RockBitmap.kRockRound) + time.sleep(1) + + self.print_step(8, "Read from the DUT the RockSetting attribute") + rock_setting = await self.read_rock_setting(endpoint=endpoint) + asserts.assert_equal(rock_setting, Clusters.FanControl.Bitmaps.RockBitmap.kRockRound, "RockSetting is not 0x04") + + self.print_step(9, "Write RockSetting to 0x00") + await self.write_rock_setting(endpoint=endpoint, rock_setting=0x00) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_FAN_3_4.py b/src/python_testing/TC_FAN_3_4.py new file mode 100644 index 00000000000000..af18ba5082a14a --- /dev/null +++ b/src/python_testing/TC_FAN_3_4.py @@ -0,0 +1,81 @@ +# +# Copyright (c) 2023 Project CHIP Authors +# All rights reserved. +# +# 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 logging +import time + +import chip.clusters as Clusters +from chip.interaction_model import Status +from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main +from mobly import asserts + +logger = logging.getLogger(__name__) + + +class TC_FAN_3_4(MatterBaseTest): + + async def read_fc_attribute_expect_success(self, endpoint, attribute): + cluster = Clusters.Objects.FanControl + return await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attribute) + + async def read_wind_support(self, endpoint): + return await self.read_fc_attribute_expect_success(endpoint, Clusters.FanControl.Attributes.WindSupport) + + async def read_wind_setting(self, endpoint): + return await self.read_fc_attribute_expect_success(endpoint, Clusters.FanControl.Attributes.WindSetting) + + async def write_wind_setting(self, endpoint, wind_setting): + result = await self.default_controller.WriteAttribute(self.dut_node_id, [(endpoint, Clusters.FanControl.Attributes.WindSetting(wind_setting))]) + asserts.assert_equal(result[0].Status, Status.Success, "WindSetting write failed") + + @async_test_body + async def test_TC_FAN_3_4(self): + if not self.check_pics("FAN.S.F03"): + logger.info("Test skipped because PICS FAN.S.F03 is not set") + return + + endpoint = self.user_params.get("endpoint", 1) + + self.print_step(1, "Commissioning, already done") + + self.print_step(2, "Read from the DUT the WindSupport attribute and store") + wind_support = await self.read_wind_support(endpoint=endpoint) + + if wind_support & Clusters.FanControl.Bitmaps.WindBitmap.kSleepWind: + self.print_step(3, "SleepWind is supported, so write 0x01 to WindSetting") + await self.write_wind_setting(endpoint=endpoint, wind_setting=Clusters.FanControl.Bitmaps.WindBitmap.kSleepWind) + time.sleep(1) + + self.print_step(4, "Read from the DUT the WindSetting attribute") + wind_setting = await self.read_wind_setting(endpoint=endpoint) + asserts.assert_equal(wind_setting, Clusters.FanControl.Bitmaps.WindBitmap.kSleepWind, "WindSetting is not 0x01") + + if wind_support & Clusters.FanControl.Bitmaps.WindBitmap.kNaturalWind: + self.print_step(5, "NaturalWind is supported, so write 0x02 to WindSetting") + await self.write_wind_setting(endpoint=endpoint, wind_setting=Clusters.FanControl.Bitmaps.WindBitmap.kNaturalWind) + time.sleep(1) + + self.print_step(6, "Read from the DUT the WindSetting attribute") + wind_setting = await self.read_wind_setting(endpoint=endpoint) + asserts.assert_equal(wind_setting, Clusters.FanControl.Bitmaps.WindBitmap.kNaturalWind, "WindSetting is not 0x02") + + self.print_step(9, "Write WindSetting to 0x00") + await self.write_wind_setting(endpoint=endpoint, wind_setting=0x00) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_FAN_3_5.py b/src/python_testing/TC_FAN_3_5.py new file mode 100644 index 00000000000000..f02f6fd3adf6ab --- /dev/null +++ b/src/python_testing/TC_FAN_3_5.py @@ -0,0 +1,206 @@ +# +# Copyright (c) 2023 Project CHIP Authors +# All rights reserved. +# +# 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 logging +import time + +import chip.clusters as Clusters +from chip.interaction_model import InteractionModelError, Status +from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main +from mobly import asserts + +logger = logging.getLogger(__name__) + + +class TC_FAN_3_5(MatterBaseTest): + + async def read_fc_attribute_expect_success(self, endpoint, attribute): + cluster = Clusters.Objects.FanControl + return await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attribute) + + async def read_percent_current(self, endpoint): + return await self.read_fc_attribute_expect_success(endpoint, Clusters.FanControl.Attributes.PercentCurrent) + + async def read_speed_current(self, endpoint): + return await self.read_fc_attribute_expect_success(endpoint, Clusters.FanControl.Attributes.SpeedCurrent) + + async def read_speed_max(self, endpoint): + return await self.read_fc_attribute_expect_success(endpoint, Clusters.FanControl.Attributes.SpeedMax) + + async def write_percent_setting(self, endpoint, percent_setting): + result = await self.default_controller.WriteAttribute(self.dut_node_id, [(endpoint, Clusters.FanControl.Attributes.PercentSetting(percent_setting))]) + asserts.assert_equal(result[0].Status, Status.Success, "PercentSetting write failed") + + async def write_speed_setting(self, endpoint, speed_setting): + result = await self.default_controller.WriteAttribute(self.dut_node_id, [(endpoint, Clusters.FanControl.Attributes.SpeedSetting(speed_setting))]) + asserts.assert_equal(result[0].Status, Status.Success, "SpeedSetting write failed") + + async def send_step_command(self, endpoint, + direction: Clusters.Objects.FanControl.Enums.StepDirectionEnum, + wrap: bool = False, lowestOff: bool = False, expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.Objects.FanControl.Commands.Step(direction=direction, wrap=wrap, lowestOff=lowestOff), endpoint=endpoint) + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + pass + + @async_test_body + async def test_TC_FAN_3_5(self): + if not self.check_pics("FAN.S.F04"): + logger.info("Test skipped because PICS FAN.S.F04 is not set") + return + + endpoint = self.user_params.get("endpoint", 1) + + # Part 1 + + self.print_step(1, "Commissioning, already done") + + # Part 2 + + self.print_step("2a", "writes to the DUT the PercentSetting attribute with 50") + await self.write_percent_setting(endpoint=endpoint, percent_setting=50) + + time.sleep(1) + + self.print_step("2b", "Read from the DUT the PercentCurrent attribute and store") + percent_current = await self.read_percent_current(endpoint=endpoint) + + self.print_step("2c", "TH sends Step command to DUT with Direction set to Increase") + await self.send_step_command(endpoint=endpoint, direction=Clusters.Objects.FanControl.Enums.StepDirectionEnum.kIncrease) + + time.sleep(1) + + self.print_step("2d", "Read from the DUT the PercentCurrent attribute and check its higher than the stored value") + percent_current_after = await self.read_percent_current(endpoint=endpoint) + asserts.assert_greater(percent_current_after, percent_current, "PercentCurrent did not increase") + + # Part 3 + + self.print_step("3a", "writes to the DUT the PercentSetting attribute with 50") + await self.write_percent_setting(endpoint=endpoint, percent_setting=50) + + time.sleep(1) + + self.print_step("3b", "Read from the DUT the PercentCurrent attribute and store") + percent_current = await self.read_percent_current(endpoint=endpoint) + + self.print_step("3c", "TH sends Step command to DUT with Direction set to Decrease") + await self.send_step_command(endpoint=endpoint, direction=Clusters.Objects.FanControl.Enums.StepDirectionEnum.kDecrease) + + self.print_step("3d", "Read from the DUT the PercentCurrent attribute and check its lower than the stored value") + percent_current_after = await self.read_percent_current(endpoint=endpoint) + asserts.assert_less(percent_current_after, percent_current, "PercentCurrent did not decrease") + + # Part 4 + self.print_step("4a", "TH reads from the DUT the SpeedMax attribute") + speed_max = await self.read_speed_max(endpoint=endpoint) + + self.print_step("4b", "TH writes to the DUT the SpeedSetting attribute with the value of SpeedMax") + await self.write_speed_setting(endpoint=endpoint, speed_setting=speed_max) + + time.sleep(1) + + self.print_step("4c", "TH sends Step command to DUT with Direction set to Increase and Wrap set to False") + await self.send_step_command(endpoint=endpoint, direction=Clusters.Objects.FanControl.Enums.StepDirectionEnum.kIncrease, wrap=False) + + time.sleep(1) + + self.print_step("4d", "Read from the DUT the SpeedCurrent attribute and check its equal to SpeedMax") + speed_current = await self.read_speed_current(endpoint=endpoint) + asserts.assert_equal(speed_current, speed_max, "SpeedCurrent incremented past SpeedMax when wrap was false") + + # Part 5 + self.print_step("5a", "TH writes to the DUT the SpeedSetting attribute with the value of SpeedMax") + await self.write_speed_setting(endpoint=endpoint, speed_setting=speed_max) + + time.sleep(1) + + self.print_step("5b", "TH sends Step command to DUT with Direction set to Increase and Wrap set to True") + await self.send_step_command(endpoint=endpoint, direction=Clusters.Objects.FanControl.Enums.StepDirectionEnum.kIncrease, wrap=True) + + time.sleep(1) + + self.print_step("5c", "Read from the DUT the SpeedCurrent attribute and check its equal to 1") + speed_current = await self.read_speed_current(endpoint=endpoint) + asserts.assert_equal(speed_current, 1, "SpeedCurrent did not wrap to 1 when wrap was true") + + # Part 6 + self.print_step("6a", "TH writes to the DUT the SpeedSetting attribute with the value of SpeedMax") + await self.write_speed_setting(endpoint=endpoint, speed_setting=speed_max) + + time.sleep(1) + + self.print_step("6b", "TH sends Step command to DUT with Direction set to Increase, Wrap set to True and LowestOff set to True") + await self.send_step_command(endpoint=endpoint, direction=Clusters.Objects.FanControl.Enums.StepDirectionEnum.kIncrease, wrap=True, lowestOff=True) + + time.sleep(1) + + self.print_step("6c", "Read from the DUT the SpeedCurrent attribute and check its equal to 0") + speed_current = await self.read_speed_current(endpoint=endpoint) + asserts.assert_equal(speed_current, 0, "SpeedCurrent did not wrap to 0 when wrap was true and lowestOff was true") + + # Part 7 + self.print_step("7a", "TH writes to the DUT the SpeedSetting attribute with the value of 1") + await self.write_speed_setting(endpoint=endpoint, speed_setting=1) + + time.sleep(1) + + self.print_step("7b", "TH sends Step command to DUT with Direction set to Decrease, Wrap set to False and LowestOff set to False") + await self.send_step_command(endpoint=endpoint, direction=Clusters.Objects.FanControl.Enums.StepDirectionEnum.kDecrease, wrap=False, lowestOff=False) + + time.sleep(1) + + self.print_step("7c", "Read from the DUT the SpeedCurrent attribute and check its equal to 1") + speed_current = await self.read_speed_current(endpoint=endpoint) + asserts.assert_equal(speed_current, 1, "SpeedCurrent decremented past 1 when wrap was false and lowestOff was false") + + # Part 8 + self.print_step("8b", "TH writes to the DUT the SpeedSetting attribute with the value of 1") + await self.write_speed_setting(endpoint=endpoint, speed_setting=1) + + time.sleep(1) + + self.print_step("8c", "TH sends Step command to DUT with Direction set to Decrease, Wrap set to True and LowestOff set to False") + await self.send_step_command(endpoint=endpoint, direction=Clusters.Objects.FanControl.Enums.StepDirectionEnum.kDecrease, wrap=True, lowestOff=False) + + time.sleep(1) + + self.print_step("8d", "Read from the DUT the SpeedCurrent attribute and check its equal to SpeedMax") + speed_current = await self.read_speed_current(endpoint=endpoint) + asserts.assert_equal(speed_current, speed_max, + "SpeedCurrent did not wrap to SpeedMax when wrap was true and lowestOff was false") + + # Part 9 + self.print_step("9b", "TH writes to the DUT the SpeedSetting attribute with the value of 0") + await self.write_speed_setting(endpoint=endpoint, speed_setting=0) + + time.sleep(1) + + self.print_step("9c", "TH sends Step command to DUT with Direction set to Decrease, Wrap set to True and LowestOff set to True") + await self.send_step_command(endpoint=endpoint, direction=Clusters.Objects.FanControl.Enums.StepDirectionEnum.kDecrease, wrap=True, lowestOff=True) + + time.sleep(1) + + self.print_step("9d", "Read from the DUT the SpeedCurrent attribute and check its equal to SpeedMax") + speed_current = await self.read_speed_current(endpoint=endpoint) + asserts.assert_equal(speed_current, speed_max, + "SpeedCurrent did not wrap to SpeedMax when wrap was true and lowestOff was true") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 5a4912e5a59c70..bf8de99c1928d7 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -119,7 +119,7 @@ class TestList : public Command printf("Test_TC_FAN_2_5\n"); printf("Test_TC_FAN_3_1\n"); printf("Test_TC_FAN_3_2\n"); - printf("Test_TC_FAN_3_4\n"); + printf("Test_TC_FAN_3_6\n"); printf("Test_TC_CGEN_1_1\n"); printf("Test_TC_CGEN_2_1\n"); printf("Test_TC_DGGEN_1_1\n"); @@ -37678,12 +37678,11 @@ class Test_TC_FAN_3_1Suite : public TestCommand class Test_TC_FAN_3_2Suite : public TestCommand { public: - Test_TC_FAN_3_2Suite(CredentialIssuerCommands * credsIssuerConfig) : TestCommand("Test_TC_FAN_3_2", 5, credsIssuerConfig) + Test_TC_FAN_3_2Suite(CredentialIssuerCommands * credsIssuerConfig) : TestCommand("Test_TC_FAN_3_2", 6, credsIssuerConfig) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); - AddArgument("ConfigSpeedSetting", 0, UINT8_MAX, &mConfigSpeedSetting); AddArgument("timeout", 0, UINT16_MAX, &mTimeout); } @@ -37698,9 +37697,10 @@ class Test_TC_FAN_3_2Suite : public TestCommand chip::Optional mNodeId; chip::Optional mCluster; chip::Optional mEndpoint; - chip::Optional mConfigSpeedSetting; chip::Optional mTimeout; + uint8_t rSpeedMax; + chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; } // @@ -37719,28 +37719,34 @@ class Test_TC_FAN_3_2Suite : public TestCommand break; case 1: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint8_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + rSpeedMax = value; + } break; case 2: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); - shouldContinue = true; break; case 3: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 4: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::app::DataModel::Nullable value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); VerifyOrReturn(CheckValueNonNull("speedSetting", value)); - VerifyOrReturn(CheckValue("speedSetting.Value()", value.Value(), - mConfigSpeedSetting.HasValue() ? mConfigSpeedSetting.Value() : 50U)); + VerifyOrReturn(CheckValue("speedSetting.Value()", value.Value(), rSpeedMax)); } break; - case 4: + case 5: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { uint8_t value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); - VerifyOrReturn( - CheckValue("speedCurrent", value, mConfigSpeedSetting.HasValue() ? mConfigSpeedSetting.Value() : 50U)); + VerifyOrReturn(CheckValue("speedCurrent", value, rSpeedMax)); } break; default: @@ -37766,31 +37772,37 @@ class Test_TC_FAN_3_2Suite : public TestCommand return WaitForCommissionee(kIdentityAlpha, value); } case 1: { - LogStep(1, "Step 2: TH writes SpeedSetting attribute a valid value to DUT"); + LogStep(1, "Step 2: TH reads from the DUT the SpeedMax attribute"); + VerifyOrDo(!ShouldSkip("FAN.S.A0004"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::SpeedMax::Id, true, + chip::NullOptional); + } + case 2: { + LogStep(2, "Step 3: TH writes TH writes to the DUT the a value less than or equal to the value read in step 2"); VerifyOrDo(!ShouldSkip("FAN.S.A0005"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); ListFreer listFreer; chip::app::DataModel::Nullable value; value.SetNonNull(); - value.Value() = mConfigSpeedSetting.HasValue() ? mConfigSpeedSetting.Value() : 50U; + value.Value() = rSpeedMax; return WriteAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::SpeedSetting::Id, value, chip::NullOptional, chip::NullOptional); } - case 2: { - LogStep(2, "Wait 1000ms"); + case 3: { + LogStep(3, "Wait 1000ms"); VerifyOrDo(!ShouldSkip("FAN.S.A0005"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); ListFreer listFreer; chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; value.ms = 1000UL; return WaitForMs(kIdentityAlpha, value); } - case 3: { - LogStep(3, "Step 3: TH reads from the DUT the the SpeedSetting attribute"); + case 4: { + LogStep(4, "Step 4: TH reads from the DUT the the SpeedSetting attribute"); VerifyOrDo(!ShouldSkip("FAN.S.A0005"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::SpeedSetting::Id, true, chip::NullOptional); } - case 4: { - LogStep(4, "Step 4: TH reads from the DUT the the SpeedCurrent attribute"); + case 5: { + LogStep(5, "Step 5: TH reads from the DUT the the SpeedCurrent attribute"); VerifyOrDo(!ShouldSkip("FAN.S.A0006"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::SpeedCurrent::Id, true, chip::NullOptional); @@ -37800,19 +37812,18 @@ class Test_TC_FAN_3_2Suite : public TestCommand } }; -class Test_TC_FAN_3_4Suite : public TestCommand +class Test_TC_FAN_3_6Suite : public TestCommand { public: - Test_TC_FAN_3_4Suite(CredentialIssuerCommands * credsIssuerConfig) : TestCommand("Test_TC_FAN_3_4", 4, credsIssuerConfig) + Test_TC_FAN_3_6Suite(CredentialIssuerCommands * credsIssuerConfig) : TestCommand("Test_TC_FAN_3_6", 7, credsIssuerConfig) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); - AddArgument("ConfigWindSetting", 0, UINT8_MAX, &mConfigWindSetting); AddArgument("timeout", 0, UINT16_MAX, &mTimeout); } - ~Test_TC_FAN_3_4Suite() {} + ~Test_TC_FAN_3_6Suite() {} chip::System::Clock::Timeout GetWaitDuration() const override { @@ -37823,7 +37834,6 @@ class Test_TC_FAN_3_4Suite : public TestCommand chip::Optional mNodeId; chip::Optional mCluster; chip::Optional mEndpoint; - chip::Optional mConfigWindSetting; chip::Optional mTimeout; chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; } @@ -37852,9 +37862,24 @@ class Test_TC_FAN_3_4Suite : public TestCommand case 3: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { - chip::BitMask value; + chip::app::Clusters::FanControl::AirflowDirectionEnum value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); - VerifyOrReturn(CheckValue("windSetting", value, mConfigWindSetting.HasValue() ? mConfigWindSetting.Value() : 1U)); + VerifyOrReturn(CheckValue("airflowDirection", value, 0U)); + } + break; + case 4: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::Clusters::FanControl::AirflowDirectionEnum value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("airflowDirection", value, 1U)); } break; default: @@ -37880,27 +37905,49 @@ class Test_TC_FAN_3_4Suite : public TestCommand return WaitForCommissionee(kIdentityAlpha, value); } case 1: { - LogStep(1, "Step 2: TH writes WindSetting attribute a valid value to DUT"); - VerifyOrDo(!ShouldSkip("FAN.S.A0008"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + LogStep(1, "Step 2: TH writes a value of Forward to the DUT"); + VerifyOrDo(!ShouldSkip("FAN.S.A000B"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); ListFreer listFreer; - chip::BitMask value; - value = mConfigWindSetting.HasValue() ? mConfigWindSetting.Value() - : static_cast>(1U); - return WriteAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::WindSetting::Id, value, - chip::NullOptional, chip::NullOptional); + chip::app::Clusters::FanControl::AirflowDirectionEnum value; + value = static_cast(0); + return WriteAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::AirflowDirection::Id, + value, chip::NullOptional, chip::NullOptional); } case 2: { LogStep(2, "Wait 1000ms"); - VerifyOrDo(!ShouldSkip("FAN.S.A0008"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + VerifyOrDo(!ShouldSkip("FAN.S.A000B"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); ListFreer listFreer; chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; value.ms = 1000UL; return WaitForMs(kIdentityAlpha, value); } case 3: { - LogStep(3, "Step 3: TH reads from the DUT the the WindSetting attribute"); - VerifyOrDo(!ShouldSkip("FAN.S.A0008"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); - return ReadAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::WindSetting::Id, true, + LogStep(3, "Step 3: TH reads from the DUT the AirflowDirection attribute and check it is forwards"); + VerifyOrDo(!ShouldSkip("FAN.S.A000B"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::AirflowDirection::Id, true, + chip::NullOptional); + } + case 4: { + LogStep(4, "Step 4: TH writes a value of Reverse to the DUT"); + VerifyOrDo(!ShouldSkip("FAN.S.A000B"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + ListFreer listFreer; + chip::app::Clusters::FanControl::AirflowDirectionEnum value; + value = static_cast(1); + return WriteAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::AirflowDirection::Id, + value, chip::NullOptional, chip::NullOptional); + } + case 5: { + LogStep(5, "Wait 1000ms"); + VerifyOrDo(!ShouldSkip("FAN.S.A000B"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 1000UL; + return WaitForMs(kIdentityAlpha, value); + } + case 6: { + LogStep(6, "Step 5: TH reads from the DUT the AirflowDirection attribute and check it is reverse"); + VerifyOrDo(!ShouldSkip("FAN.S.A000B"), return ContinueOnChipMainThread(CHIP_NO_ERROR)); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), FanControl::Id, FanControl::Attributes::AirflowDirection::Id, true, chip::NullOptional); } } @@ -134885,7 +134932,7 @@ 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 aba39585a18687..12446940281088 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -106,7 +106,7 @@ class TestList : public Command { printf("Test_TC_FAN_2_5\n"); printf("Test_TC_FAN_3_1\n"); printf("Test_TC_FAN_3_2\n"); - printf("Test_TC_FAN_3_4\n"); + printf("Test_TC_FAN_3_6\n"); printf("Test_TC_CGEN_1_1\n"); printf("Test_TC_CGEN_2_1\n"); printf("Test_TC_DGGEN_1_1\n"); @@ -50592,7 +50592,6 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); - AddArgument("ConfigSpeedSetting", 0, UINT8_MAX, &mConfigSpeedSetting); AddArgument("timeout", 0, UINT16_MAX, &mTimeout); } // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull) @@ -50626,36 +50625,46 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { err = TestStep1WaitForTheCommissionedDeviceToBeRetrieved_0(); break; case 1: - ChipLogProgress(chipTool, " ***** Test Step 1 : Step 2: TH writes SpeedSetting attribute a valid value to DUT\n"); - if (ShouldSkip("FAN.S.A0005")) { + ChipLogProgress(chipTool, " ***** Test Step 1 : Step 2: TH reads from the DUT the SpeedMax attribute\n"); + if (ShouldSkip("FAN.S.A0004")) { NextTest(); return; } - err = TestStep2ThWritesSpeedSettingAttributeAValidValueToDut_1(); + err = TestStep2ThReadsFromTheDutTheSpeedMaxAttribute_1(); break; case 2: - ChipLogProgress(chipTool, " ***** Test Step 2 : Wait 1000ms\n"); + ChipLogProgress(chipTool, + " ***** Test Step 2 : Step 3: TH writes TH writes to the DUT the a value less than or equal to the value read in " + "step 2\n"); if (ShouldSkip("FAN.S.A0005")) { NextTest(); return; } - err = TestWait1000ms_2(); + err = TestStep3ThWritesThWritesToTheDutTheAValueLessThanOrEqualToTheValueReadInStep2_2(); break; case 3: - ChipLogProgress(chipTool, " ***** Test Step 3 : Step 3: TH reads from the DUT the the SpeedSetting attribute\n"); + ChipLogProgress(chipTool, " ***** Test Step 3 : Wait 1000ms\n"); if (ShouldSkip("FAN.S.A0005")) { NextTest(); return; } - err = TestStep3ThReadsFromTheDutTheTheSpeedSettingAttribute_3(); + err = TestWait1000ms_3(); break; case 4: - ChipLogProgress(chipTool, " ***** Test Step 4 : Step 4: TH reads from the DUT the the SpeedCurrent attribute\n"); + ChipLogProgress(chipTool, " ***** Test Step 4 : Step 4: TH reads from the DUT the the SpeedSetting attribute\n"); + if (ShouldSkip("FAN.S.A0005")) { + NextTest(); + return; + } + err = TestStep4ThReadsFromTheDutTheTheSpeedSettingAttribute_4(); + break; + case 5: + ChipLogProgress(chipTool, " ***** Test Step 5 : Step 5: TH reads from the DUT the the SpeedCurrent attribute\n"); if (ShouldSkip("FAN.S.A0006")) { NextTest(); return; } - err = TestStep4ThReadsFromTheDutTheTheSpeedCurrentAttribute_4(); + err = TestStep5ThReadsFromTheDutTheTheSpeedCurrentAttribute_5(); break; } @@ -50683,6 +50692,9 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { case 4: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; } // Go on to the next test. @@ -50696,12 +50708,11 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 5; + const uint16_t mTestCount = 6; chip::Optional mNodeId; chip::Optional mCluster; chip::Optional mEndpoint; - chip::Optional mConfigSpeedSetting; chip::Optional mTimeout; CHIP_ERROR TestStep1WaitForTheCommissionedDeviceToBeRetrieved_0() @@ -50711,8 +50722,31 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; return WaitForCommissionee("alpha", value); } + NSNumber * _Nonnull rSpeedMax; + + CHIP_ERROR TestStep2ThReadsFromTheDutTheSpeedMaxAttribute_1() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeSpeedMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Step 2: TH reads from the DUT the SpeedMax attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + rSpeedMax = value; + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } - CHIP_ERROR TestStep2ThWritesSpeedSettingAttributeAValidValueToDut_1() + CHIP_ERROR TestStep3ThWritesThWritesToTheDutTheAValueLessThanOrEqualToTheValueReadInStep2_2() { MTRBaseDevice * device = GetDevice("alpha"); @@ -50720,22 +50754,22 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); id speedSettingArgument; - speedSettingArgument = mConfigSpeedSetting.HasValue() ? [NSNumber numberWithUnsignedChar:mConfigSpeedSetting.Value()] - : [NSNumber numberWithUnsignedChar:50U]; - [cluster - writeAttributeSpeedSettingWithValue:speedSettingArgument - completion:^(NSError * _Nullable err) { - NSLog(@"Step 2: TH writes SpeedSetting attribute a valid value to DUT Error: %@", err); + speedSettingArgument = [rSpeedMax copy]; + [cluster writeAttributeSpeedSettingWithValue:speedSettingArgument + completion:^(NSError * _Nullable err) { + NSLog(@"Step 3: TH writes TH writes to the DUT the a value less than or equal to the " + @"value read in step 2 Error: %@", + err); - VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); - NextTest(); - }]; + NextTest(); + }]; return CHIP_NO_ERROR; } - CHIP_ERROR TestWait1000ms_2() + CHIP_ERROR TestWait1000ms_3() { chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; @@ -50743,7 +50777,7 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { return WaitForMs("alpha", value); } - CHIP_ERROR TestStep3ThReadsFromTheDutTheTheSpeedSettingAttribute_3() + CHIP_ERROR TestStep4ThReadsFromTheDutTheTheSpeedSettingAttribute_4() { MTRBaseDevice * device = GetDevice("alpha"); @@ -50751,15 +50785,18 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); [cluster readAttributeSpeedSettingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { - NSLog(@"Step 3: TH reads from the DUT the the SpeedSetting attribute Error: %@", err); + NSLog(@"Step 4: TH reads from the DUT the the SpeedSetting attribute Error: %@", err); VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); { id actualValue = value; - VerifyOrReturn(CheckValueNonNull("SpeedSetting", actualValue)); - VerifyOrReturn( - CheckValue("SpeedSetting", actualValue, mConfigSpeedSetting.HasValue() ? mConfigSpeedSetting.Value() : 50U)); + if (rSpeedMax == nil) { + VerifyOrReturn(CheckValueNull("SpeedSetting", actualValue)); + } else { + VerifyOrReturn(CheckValueNonNull("SpeedSetting", actualValue)); + VerifyOrReturn(CheckValue("SpeedSetting", actualValue, rSpeedMax)); + } } NextTest(); @@ -50768,7 +50805,7 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { return CHIP_NO_ERROR; } - CHIP_ERROR TestStep4ThReadsFromTheDutTheTheSpeedCurrentAttribute_4() + CHIP_ERROR TestStep5ThReadsFromTheDutTheTheSpeedCurrentAttribute_5() { MTRBaseDevice * device = GetDevice("alpha"); @@ -50776,14 +50813,13 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); [cluster readAttributeSpeedCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { - NSLog(@"Step 4: TH reads from the DUT the the SpeedCurrent attribute Error: %@", err); + NSLog(@"Step 5: TH reads from the DUT the the SpeedCurrent attribute Error: %@", err); VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); { id actualValue = value; - VerifyOrReturn( - CheckValue("SpeedCurrent", actualValue, mConfigSpeedSetting.HasValue() ? mConfigSpeedSetting.Value() : 50U)); + VerifyOrReturn(CheckValue("SpeedCurrent", actualValue, rSpeedMax)); } NextTest(); @@ -50793,22 +50829,21 @@ class Test_TC_FAN_3_2 : public TestCommandBridge { } }; -class Test_TC_FAN_3_4 : public TestCommandBridge { +class Test_TC_FAN_3_6 : public TestCommandBridge { public: // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced - Test_TC_FAN_3_4() - : TestCommandBridge("Test_TC_FAN_3_4") + Test_TC_FAN_3_6() + : TestCommandBridge("Test_TC_FAN_3_6") , mTestIndex(0) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); - AddArgument("ConfigWindSetting", 0, UINT8_MAX, &mConfigWindSetting); AddArgument("timeout", 0, UINT16_MAX, &mTimeout); } // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull) - ~Test_TC_FAN_3_4() {} + ~Test_TC_FAN_3_6() {} /////////// TestCommand Interface ///////// void NextTest() override @@ -50816,11 +50851,11 @@ class Test_TC_FAN_3_4 : public TestCommandBridge { CHIP_ERROR err = CHIP_NO_ERROR; if (0 == mTestIndex) { - ChipLogProgress(chipTool, " **** Test Start: Test_TC_FAN_3_4\n"); + ChipLogProgress(chipTool, " **** Test Start: Test_TC_FAN_3_6\n"); } if (mTestCount == mTestIndex) { - ChipLogProgress(chipTool, " **** Test Complete: Test_TC_FAN_3_4\n"); + ChipLogProgress(chipTool, " **** Test Complete: Test_TC_FAN_3_6\n"); SetCommandExitStatus(CHIP_NO_ERROR); return; } @@ -50837,28 +50872,54 @@ class Test_TC_FAN_3_4 : public TestCommandBridge { err = TestStep1WaitForTheCommissionedDeviceToBeRetrieved_0(); break; case 1: - ChipLogProgress(chipTool, " ***** Test Step 1 : Step 2: TH writes WindSetting attribute a valid value to DUT\n"); - if (ShouldSkip("FAN.S.A0008")) { + ChipLogProgress(chipTool, " ***** Test Step 1 : Step 2: TH writes a value of Forward to the DUT\n"); + if (ShouldSkip("FAN.S.A000B")) { NextTest(); return; } - err = TestStep2ThWritesWindSettingAttributeAValidValueToDut_1(); + err = TestStep2ThWritesAValueOfForwardToTheDut_1(); break; case 2: ChipLogProgress(chipTool, " ***** Test Step 2 : Wait 1000ms\n"); - if (ShouldSkip("FAN.S.A0008")) { + if (ShouldSkip("FAN.S.A000B")) { NextTest(); return; } err = TestWait1000ms_2(); break; case 3: - ChipLogProgress(chipTool, " ***** Test Step 3 : Step 3: TH reads from the DUT the the WindSetting attribute\n"); - if (ShouldSkip("FAN.S.A0008")) { + ChipLogProgress(chipTool, + " ***** Test Step 3 : Step 3: TH reads from the DUT the AirflowDirection attribute and check it is forwards\n"); + if (ShouldSkip("FAN.S.A000B")) { + NextTest(); + return; + } + err = TestStep3ThReadsFromTheDutTheAirflowDirectionAttributeAndCheckItIsForwards_3(); + break; + case 4: + ChipLogProgress(chipTool, " ***** Test Step 4 : Step 4: TH writes a value of Reverse to the DUT\n"); + if (ShouldSkip("FAN.S.A000B")) { NextTest(); return; } - err = TestStep3ThReadsFromTheDutTheTheWindSettingAttribute_3(); + err = TestStep4ThWritesAValueOfReverseToTheDut_4(); + break; + case 5: + ChipLogProgress(chipTool, " ***** Test Step 5 : Wait 1000ms\n"); + if (ShouldSkip("FAN.S.A000B")) { + NextTest(); + return; + } + err = TestWait1000ms_5(); + break; + case 6: + ChipLogProgress(chipTool, + " ***** Test Step 6 : Step 5: TH reads from the DUT the AirflowDirection attribute and check it is reverse\n"); + if (ShouldSkip("FAN.S.A000B")) { + NextTest(); + return; + } + err = TestStep5ThReadsFromTheDutTheAirflowDirectionAttributeAndCheckItIsReverse_6(); break; } @@ -50883,6 +50944,15 @@ class Test_TC_FAN_3_4 : public TestCommandBridge { 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; } // Go on to the next test. @@ -50896,12 +50966,11 @@ class Test_TC_FAN_3_4 : public TestCommandBridge { private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 4; + const uint16_t mTestCount = 7; chip::Optional mNodeId; chip::Optional mCluster; chip::Optional mEndpoint; - chip::Optional mConfigWindSetting; chip::Optional mTimeout; CHIP_ERROR TestStep1WaitForTheCommissionedDeviceToBeRetrieved_0() @@ -50912,24 +50981,23 @@ class Test_TC_FAN_3_4 : public TestCommandBridge { return WaitForCommissionee("alpha", value); } - CHIP_ERROR TestStep2ThWritesWindSettingAttributeAValidValueToDut_1() + CHIP_ERROR TestStep2ThWritesAValueOfForwardToTheDut_1() { MTRBaseDevice * device = GetDevice("alpha"); __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); - id windSettingArgument; - windSettingArgument = mConfigWindSetting.HasValue() ? [NSNumber numberWithUnsignedChar:mConfigWindSetting.Value()] - : [NSNumber numberWithUnsignedChar:1U]; - [cluster writeAttributeWindSettingWithValue:windSettingArgument - completion:^(NSError * _Nullable err) { - NSLog(@"Step 2: TH writes WindSetting attribute a valid value to DUT Error: %@", err); + id airflowDirectionArgument; + airflowDirectionArgument = [NSNumber numberWithUnsignedChar:0U]; + [cluster writeAttributeAirflowDirectionWithValue:airflowDirectionArgument + completion:^(NSError * _Nullable err) { + NSLog(@"Step 2: TH writes a value of Forward to the DUT Error: %@", err); - VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); - NextTest(); - }]; + NextTest(); + }]; return CHIP_NO_ERROR; } @@ -50942,22 +51010,73 @@ class Test_TC_FAN_3_4 : public TestCommandBridge { return WaitForMs("alpha", value); } - CHIP_ERROR TestStep3ThReadsFromTheDutTheTheWindSettingAttribute_3() + CHIP_ERROR TestStep3ThReadsFromTheDutTheAirflowDirectionAttributeAndCheckItIsForwards_3() { MTRBaseDevice * device = GetDevice("alpha"); __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); - [cluster readAttributeWindSettingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { - NSLog(@"Step 3: TH reads from the DUT the the WindSetting attribute Error: %@", err); + [cluster readAttributeAirflowDirectionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Step 3: TH reads from the DUT the AirflowDirection attribute and check it is forwards Error: %@", err); VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); { id actualValue = value; - VerifyOrReturn( - CheckValue("WindSetting", actualValue, mConfigWindSetting.HasValue() ? mConfigWindSetting.Value() : 1U)); + VerifyOrReturn(CheckValue("AirflowDirection", actualValue, 0U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestStep4ThWritesAValueOfReverseToTheDut_4() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + id airflowDirectionArgument; + airflowDirectionArgument = [NSNumber numberWithUnsignedChar:1U]; + [cluster writeAttributeAirflowDirectionWithValue:airflowDirectionArgument + completion:^(NSError * _Nullable err) { + NSLog(@"Step 4: TH writes a value of Reverse to the DUT Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWait1000ms_5() + { + + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 1000UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestStep5ThReadsFromTheDutTheAirflowDirectionAttributeAndCheckItIsReverse_6() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeAirflowDirectionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Step 5: TH reads from the DUT the AirflowDirection attribute and check it is reverse Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("AirflowDirection", actualValue, 1U)); } NextTest(); @@ -172895,7 +173014,7 @@ void registerCommandsTests(Commands & commands) make_unique(), make_unique(), make_unique(), - make_unique(), + make_unique(), make_unique(), make_unique(), make_unique(),