Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add water heater mode cluster test scripts #34347

Merged
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
883072d
Add water heater mode cluster test scripts
PeterC1965 Jul 16, 2024
0e02488
Merge branch 'master' into add-water-heater-mode-test-scripts
PeterC1965 Jul 18, 2024
5125015
Add TC_EWATERHTRM_2_1.py
PeterC1965 Jul 22, 2024
fb6885c
Fix lint errors
PeterC1965 Jul 22, 2024
2b9ba5e
Restyled by isort
restyled-commits Jul 22, 2024
9914961
Merge branch 'master' into add-water-heater-mode-test-scripts
PeterC1965 Jul 25, 2024
8728531
Merge branch 'master' into add-water-heater-mode-test-scripts
PeterC1965 Jul 25, 2024
08ec0b7
Merge branch 'master' into add-water-heater-mode-test-scripts
PeterC1965 Jul 28, 2024
9714248
Renamed read_mod_attribute_expect_success to read_mode_attribute_expe…
jamesharrow Jul 28, 2024
4c38843
Merge remote-tracking branch 'origin/add-water-heater-mode-test-scrip…
jamesharrow Jul 28, 2024
c9f5b40
Changed test runner to run All-clusters-app where waterheater mode is…
jamesharrow Jul 28, 2024
927a3ef
Added Test scripts to CI test.yaml (TC_EWATERHTRM_1_2.py & TC_EWATERH…
jamesharrow Jul 28, 2024
ebd1509
Corrected checking of modes for WaterHeaterModes which must be includ…
jamesharrow Jul 28, 2024
cabc6d1
Alignment (autowrapping)
jamesharrow Jul 28, 2024
a55d702
Merge branch 'master' into add-water-heater-mode-test-scripts
jamesharrow Jul 28, 2024
cb83726
Update tests.yaml - fixed test script name
jamesharrow Jul 29, 2024
bc9f7bc
Merge branch 'master' into add-water-heater-mode-test-scripts
PeterC1965 Jul 29, 2024
fbb424f
Merge branch 'master' into add-water-heater-mode-test-scripts
PeterC1965 Jul 29, 2024
0673e3c
Merge branch 'master' into add-water-heater-mode-test-scripts
PeterC1965 Jul 29, 2024
01dae06
Address review comments from Andrei
PeterC1965 Jul 29, 2024
f1fe689
Merge branch 'master' into add-water-heater-mode-test-scripts
PeterC1965 Jul 30, 2024
ec9b92f
Address comments from Cecille
PeterC1965 Jul 30, 2024
d6318f6
Restyled by autopep8
restyled-commits Jul 30, 2024
8bf5dca
Rename tests as PICS=WHM
PeterC1965 Jul 30, 2024
88178a3
Adding a TODO
PeterC1965 Jul 30, 2024
9166de5
Remove unnecessary blank line
PeterC1965 Jul 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ jobs:
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEVSE_2_5.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EPM_2_1.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EPM_2_2.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EWATERHTRM_1_2.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EWATERHTRM_2_1.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_FAN_3_1.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_FAN_3_2.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_FAN_3_3.py'
Expand Down
158 changes: 158 additions & 0 deletions src/python_testing/TC_EWATERHTRM_1_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#
# Copyright (c) 2024 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.
#

# === BEGIN CI TEST ARGUMENTS ===
# test-runner-runs: run1
jamesharrow marked this conversation as resolved.
Show resolved Hide resolved
# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
# test-runner-run/run1/factoryreset: True
# test-runner-run/run1/quiet: True
# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
# === END CI TEST ARGUMENTS ===

import logging

import chip.clusters as Clusters
from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
from mobly import asserts


class TC_EWATERHTRM_1_2(MatterBaseTest):

async def read_mode_attribute_expect_success(self, endpoint, attribute):
cluster = Clusters.Objects.WaterHeaterMode
return await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attribute)

def desc_TC_EWATERHTRM_1_2(self) -> str:
return "[TC-EWATERHTRM-1.2] Cluster attributes with DUT as Server"

def steps_TC_EWATERHTRM_1_2(self) -> list[TestStep]:
jamesharrow marked this conversation as resolved.
Show resolved Hide resolved
steps = [
TestStep(1, "Commissioning, already done", is_commissioning=True),
TestStep(2, "Read the SupportedModes attribute"),
TestStep(3, "Read the CurrentMode attribute"),
]
return steps

def pics_TC_EWATERHTRM_1_2(self) -> list[str]:
pics = [
"EWATERHTRM.S",
]
return pics

@async_test_body
async def test_TC_EWATERHTRM_1_2(self):

endpoint = self.user_params.get("endpoint", 1)

attributes = Clusters.WaterHeaterMode.Attributes

self.step(1)

self.step(2)
supported_modes = await self.read_mode_attribute_expect_success(endpoint=endpoint, attribute=attributes.SupportedModes)
asserts.assert_greater_equal(len(supported_modes), 2,
"SupportedModes must have at least 2 entries!")
asserts.assert_less_equal(len(supported_modes), 255,
"SupportedModes must have at most 255 entries!")
modes = set([m.mode for m in supported_modes])
asserts.assert_equal(len(modes), len(supported_modes),
"SupportedModes must have unique mode values")

labels = set([m.label for m in supported_modes])
asserts.assert_equal(len(labels), len(supported_modes),
"SupportedModes must have unique mode label values")

# common mode tags
commonTags = {0x0: 'Auto',
0x1: 'Quick',
0x2: 'Quiet',
0x3: 'LowNoise',
0x4: 'LowEnergy',
0x5: 'Vacation',
0x6: 'Min',
0x7: 'Max',
0x8: 'Night',
0x9: 'Day'}

# derived cluster defined tags
# kUnknownEnumValue may not be defined
try:
derivedTags = [tag.value for tag in Clusters.WaterHeaterMode.Enums.ModeTag
if tag is not Clusters.WaterHeaterMode.Enums.ModeTag.kUnknownEnumValue]
except AttributeError:
derivedTags = Clusters.WaterHeaterMode.Enums.ModeTag
andy31415 marked this conversation as resolved.
Show resolved Hide resolved

logging.info("Derived tags: %s" % derivedTags)

# According to the Mode spec:
# At least one entry in the SupportedModes attribute SHALL include the Manual mode tag in the ModeTags field list.
# At least one entry in the SupportedModes attribute SHALL include the Off mode tag in the ModeTags field list.
# An entry in the SupportedModes attribute that includes one of an Off, Manual, or Timed tag
# SHALL NOT also include an additional instance of any one of these tag types.
off_present = 0
manual_present = 0
timed_present = 0

for m in supported_modes:
off_manual_timed_present_in_this_mode = 0
for t in m.modeTags:
is_mfg = (0x8000 <= t.value and t.value <= 0xBFFF)
asserts.assert_true(t.value in commonTags.keys() or t.value in derivedTags or is_mfg,
"Found a SupportedModes entry with invalid mode tag value!")
if t.value == Clusters.WaterHeaterMode.Enums.ModeTag.kOff:
off_present += 1
off_manual_timed_present_in_this_mode += 1
andy31415 marked this conversation as resolved.
Show resolved Hide resolved
logging.info(
"Found Off mode tag %s with tag value %s", m.mode, t.value)

if t.value == Clusters.WaterHeaterMode.Enums.ModeTag.kManual:
manual_present += 1
off_manual_timed_present_in_this_mode += 1
logging.info(
"Found Manual mode tag %s with tag value %s", m.mode, t.value)

if t.value == Clusters.WaterHeaterMode.Enums.ModeTag.kTimed:
timed_present += 1
off_manual_timed_present_in_this_mode += 1
logging.info(
"Found Timed mode tag %s with tag value %s", m.mode, t.value)

asserts.assert_less_equal(off_manual_timed_present_in_this_mode, 1,
f"The supported mode ({m.mode}) should only include one of OFF, MANUAL or TIMED, but includes more than one.")

asserts.assert_greater(off_present, 0,
"SupportedModes does not have an entry of Off(0x4000)")
asserts.assert_greater(manual_present, 0,
"SupportedModes does not have an entry of Manual(0x4001)")

asserts.assert_less_equal(off_present, 1,
"SupportedModes cannot have more than one instance of Off(0x4000)")
asserts.assert_less_equal(manual_present, 1,
"SupportedModes cannot have more than one instance of Manual(0x4001)")
asserts.assert_less_equal(timed_present, 1,
"SupportedModes cannot have more than one instance of Timed(0x4002)")

self.step(3)
current_mode = await self.read_mode_attribute_expect_success(endpoint=endpoint, attribute=attributes.CurrentMode)
logging.info("CurrentMode: %s" % current_mode)
asserts.assert_true(current_mode in modes,
"CurrentMode is not a supported mode!")


if __name__ == "__main__":
default_matter_test_main()
164 changes: 164 additions & 0 deletions src/python_testing/TC_EWATERHTRM_2_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
#
# Copyright (c) 2024 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.
#

# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments
# for details about the block below.
#
# === BEGIN CI TEST ARGUMENTS ===
# test-runner-runs: run1
# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
# test-runner-run/run1/factoryreset: True
# test-runner-run/run1/quiet: True
# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json
# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
# === END CI TEST ARGUMENTS ===

import logging

import chip.clusters as Clusters
from chip.interaction_model import Status
from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches
from mobly import asserts


class TC_EWATERHTRM_2_1(MatterBaseTest):

def __init__(self, *args):
super().__init__(*args)
self.endpoint = 0

def steps_TC_EWATERHTRM_2_1(self) -> list[TestStep]:
steps = [
TestStep(1, "Commissioning, already done", is_commissioning=True),
TestStep(2, "Read the SupportedModes attribute"),
TestStep(3, "Read the CurrentMode attribute"),
TestStep(4, "Send ChangeToMode command with NewMode"),
TestStep(5, "Manually put the device in a state from which it will FAIL to transition"),
TestStep(6, "Read CurrentMode attribute"),
TestStep(7, "Send ChangeToMode command with NewMode"),
TestStep(8, "Read CurrentMode attribute"),
TestStep(9, "Manually put the device in a state from which it will SUCCESSFULLY transition"),
TestStep(10, "Read CurrentMode attribute"),
TestStep(11, "Send ChangeToMode command with NewMode"),
TestStep(12, "Read CurrentMode attribute"),
TestStep(13, "Send ChangeToMode command with NewMode set to an invalid mode"),
TestStep(14, "Read CurrentMode attribute"),
]
return steps

async def read_mode_attribute_expect_success(self, endpoint, attribute):
cluster = Clusters.Objects.WaterHeaterMode
return await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attribute)

async def send_change_to_mode_cmd(self, newMode) -> Clusters.Objects.WaterHeaterMode.Commands.ChangeToModeResponse:
ret = await self.send_single_cmd(cmd=Clusters.Objects.WaterHeaterMode.Commands.ChangeToMode(newMode=newMode), endpoint=self.endpoint)
asserts.assert_true(type_matches(ret, Clusters.Objects.WaterHeaterMode.Commands.ChangeToModeResponse),
"Unexpected return type for Water Heater Mode ChangeToMode")
return ret

def pics_TC_EWATERHTRM_2_1(self) -> list[str]:
return ["EWATERHTRM.S"]

@async_test_body
async def test_TC_EWATERHTRM_2_1(self):

# Valid modes. Only ModeManual referred to in this test
# ModeOff = 0
ModeManual = 1
# ModeTimed = 2

self.endpoint = self.matter_test_config.endpoint

attributes = Clusters.WaterHeaterMode.Attributes

self.step(1)
# Commission DUT - already done

self.step(2)

supported_modes = await self.read_mode_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.SupportedModes)
andy31415 marked this conversation as resolved.
Show resolved Hide resolved

logging.info(f"SupportedModes: {supported_modes}")

asserts.assert_greater_equal(len(supported_modes), 2,
"SupportedModes must have at least two entries!")

modes = [m.mode for m in supported_modes]
jamesharrow marked this conversation as resolved.
Show resolved Hide resolved

self.step(3)

old_current_mode = await self.read_mode_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.CurrentMode)

logging.info(f"CurrentMode: {old_current_mode}")

# pick a value that's not on the list of supported modes
invalid_mode = max(modes) + 1

self.step(4)

ret = await self.send_change_to_mode_cmd(newMode=old_current_mode)
logging.info(f"ret.status {ret.status}")
asserts.assert_true(ret.status == Status.Success,
jamesharrow marked this conversation as resolved.
Show resolved Hide resolved
"Changing the mode to the current mode should be a no-op")

# Steps 5-9 are not performed as EWATERHTRM.S.M.CAN_TEST_MODE_FAILURE is false
cecille marked this conversation as resolved.
Show resolved Hide resolved
self.step(5)
self.step(6)
self.step(7)
self.step(8)
self.step(9)

self.step(10)

old_current_mode = await self.read_mode_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.CurrentMode)

logging.info(f"CurrentMode: {old_current_mode}")

self.step(11)

ret = await self.send_change_to_mode_cmd(newMode=ModeManual)
asserts.assert_true(ret.status == Status.Success,
f"Changing to mode {ModeManual}must succeed due to the current state of the device")

self.step(12)

current_mode = await self.read_mode_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.CurrentMode)

logging.info(f"CurrentMode: {current_mode}")

asserts.assert_true(current_mode == ModeManual,
"CurrentMode doesn't match the argument of the successful ChangeToMode command!")

self.step(13)

ret = await self.send_change_to_mode_cmd(newMode=invalid_mode)
logging.info(f"ret {ret}")
asserts.assert_true(ret.status == Status.Failure,
f"Attempt to change to invalid mode {invalid_mode} didn't fail as expected")

self.step(14)

current_mode = await self.read_mode_attribute_expect_success(endpoint=self.endpoint, attribute=attributes.CurrentMode)

logging.info(f"CurrentMode: {current_mode}")

asserts.assert_true(current_mode == ModeManual,
"CurrentMode changed after failed ChangeToMode command!")


if __name__ == "__main__":
default_matter_test_main()
Loading