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

Python testing: id range check functions #33510

Merged
merged 9 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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 @@ -562,6 +562,8 @@ jobs:
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCOPSTATE_2_4.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
scripts/run_in_python_env.sh out/venv './src/python_testing/test_testing/test_TC_DA_1_2.py'
scripts/run_in_python_env.sh out/venv './src/python_testing/test_testing/test_TC_ICDM_2_1.py'
scripts/run_in_python_env.sh out/venv './src/python_testing/TestIdChecks.py'

- name: Uploading core files
uses: actions/upload-artifact@v4
if: ${{ failure() && !env.ACT }}
Expand Down
230 changes: 230 additions & 0 deletions src/python_testing/TestIdChecks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
#
# 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.
#

from global_attribute_ids import *
from matter_testing_support import MatterBaseTest, default_matter_test_main
from mobly import asserts


class TestIdChecks(MatterBaseTest):
def test_device_type_ids(self):
standard_good = [0x0000_0000, 0x0000_BFFF]
standard_bad = [0x0000_C000]

manufacturer_good = [0x0001_0000, 0x0001_BFFF, 0xFFF0_0000, 0xFFF0_BFFF]
manufacturer_bad = [0x0001_C000, 0xFFF0_C000]

test_good = [0xFFF1_0000, 0xFFF1_BFFF, 0xFFF4_0000, 0xFFF4_BFFF]
test_bad = [0xFFF1_C000, 0xFFF4_C000]

prefix_bad = [0xFFF5_0000, 0xFFF5_BFFFF, 0xFFF5_C000]

def check_standard(id):
msg = f"Incorrect device type range assessment, expecting standard {id:08x}"
asserts.assert_true(standard_device_type_range(id), msg)
asserts.assert_false(manufacturer_device_type_range(id), msg)
asserts.assert_false(test_device_type_range(id), msg)
asserts.assert_true(valid_device_type_range(id, allow_test=True), msg)
asserts.assert_true(valid_device_type_range(id, allow_test=False), msg)

def check_manufacturer(id):
msg = f"Incorrect device type range assessment, expecting manufacturer {id:08x}"
asserts.assert_false(standard_device_type_range(id), msg)
asserts.assert_true(manufacturer_device_type_range(id), msg)
asserts.assert_false(test_device_type_range(id), msg)
asserts.assert_true(valid_device_type_range(id, allow_test=True), msg)
asserts.assert_true(valid_device_type_range(id, allow_test=False), msg)

def check_test(id):
msg = f"Incorrect device type range assessment, expecting test {id:08x}"
asserts.assert_false(standard_device_type_range(id), msg)
asserts.assert_false(manufacturer_device_type_range(id), msg)
asserts.assert_true(test_device_type_range(id), msg)
asserts.assert_true(valid_device_type_range(id, allow_test=True), msg)
asserts.assert_false(valid_device_type_range(id, allow_test=False), msg)

def check_all_bad(id):
msg = f"Incorrect device type range assessment, expecting invalid {id:08x}"
asserts.assert_false(standard_device_type_range(id), msg)
asserts.assert_false(manufacturer_device_type_range(id), msg)
asserts.assert_false(valid_device_type_range(id, allow_test=True), msg)
asserts.assert_false(valid_device_type_range(id, allow_test=False), msg)

for id in standard_good:
check_standard(id)

for id in standard_bad:
check_all_bad(id)

for id in manufacturer_good:
check_manufacturer(id)

for id in manufacturer_bad:
check_all_bad(id)

for id in test_good:
check_test(id)

for id in test_bad:
check_all_bad(id)

for id in prefix_bad:
check_all_bad(id)

def test_cluster_ids(self):
standard_good = [0x0000_0000, 0x0000_7FFF]
standard_bad = [0x0000_8000]

manufacturer_good = [0x0001_FC00, 0x0001_FFFE, 0xFFF0_FC00, 0xFFF0_FFFE]
manufacturer_bad = [0x0001_0000, 0x0001_7FFF, 0x0001_FFFF, 0xFFF0_0000, 0xFFF0_7FFF, 0xFFF0_FFFF]

test_good = [0xFFF1_FC00, 0xFFF1_FFFE, 0xFFF4_FC00, 0xFFF4_FFFE]
test_bad = [0xFFF1_0000, 0xFFF1_7FFF, 0xFFF1_FFFF, 0xFFF4_0000, 0xFFF4_7FFF, 0xFFF4_FFFF]

prefix_bad = [0xFFF5_0000, 0xFFF5_FC00, 0xFFF5_FFFF]

def check_standard(id):
msg = f"Incorrect cluster range assessment, expecting standard {id:08x}"
asserts.assert_true(standard_cluster_range(id), msg)
asserts.assert_false(manufacturer_cluster_range(id), msg)
asserts.assert_false(test_cluster_range(id), msg)
asserts.assert_true(valid_cluster_range(id, allow_test=True), msg)
asserts.assert_true(valid_cluster_range(id, allow_test=False), msg)

def check_manufacturer(id):
msg = f"Incorrect cluster range assessment, expecting manufacturer {id:08x}"
asserts.assert_false(standard_cluster_range(id), msg)
asserts.assert_true(manufacturer_cluster_range(id), msg)
asserts.assert_false(test_cluster_range(id), msg)
asserts.assert_true(valid_cluster_range(id, allow_test=True), msg)
asserts.assert_true(valid_cluster_range(id, allow_test=False), msg)

def check_test(id):
msg = f"Incorrect cluster range assessment, expecting test {id:08x}"
asserts.assert_false(standard_cluster_range(id), msg)
asserts.assert_false(manufacturer_cluster_range(id), msg)
asserts.assert_true(test_cluster_range(id), msg)
asserts.assert_true(valid_cluster_range(id, allow_test=True), msg)
asserts.assert_false(valid_cluster_range(id, allow_test=False), msg)

def check_all_bad(id):
msg = f"Incorrect cluster range assessment, expecting invalid {id:08x}"
asserts.assert_false(standard_cluster_range(id), msg)
asserts.assert_false(manufacturer_cluster_range(id), msg)
asserts.assert_false(test_cluster_range(id), msg)
asserts.assert_false(valid_cluster_range(id, allow_test=True), msg)
asserts.assert_false(valid_cluster_range(id, allow_test=False), msg)

for id in standard_good:
check_standard(id)

for id in standard_bad:
check_all_bad(id)

for id in manufacturer_good:
check_manufacturer(id)

for id in manufacturer_bad:
check_all_bad(id)

for id in test_good:
check_test(id)

for id in test_bad:
check_all_bad(id)

for id in prefix_bad:
check_all_bad(id)

def test_attribute_ids(self):
standard_global_good = [0x0000_F000, 0x0000_FFFE]
standard_global_bad = [0x0000_FFFF]
standard_non_global_good = [0x0000_0000, 0x0000_4FFF]
standard_non_global_bad = [0x0000_5000]
manufacturer_good = [0x0001_0000, 0x0001_4FFF, 0xFFF0_0000, 0xFFF0_4FFF]
manufacturer_bad = [0x0001_5000, 0x0001_F000, 0x0001_FFFFF, 0xFFF0_5000, 0xFFF0_F000, 0xFFF0_FFFF]
test_good = [0xFFF1_0000, 0xFFF1_4FFF, 0xFFF4_0000, 0xFFF4_4FFF]
test_bad = [0xFFF1_5000, 0xFFF1_F000, 0xFFF1_FFFFF, 0xFFF4_5000, 0xFFF4_F000, 0xFFF4_FFFF]
prefix_bad = [0xFFF5_0000, 0xFFF5_4FFF, 0xFFF5_5000, 0xFFF5_F000, 0xFFF5_FFFF]

def check_standard_global(id):
msg = f"Incorrect attribute range assessment, expecting standard global {id:08x}"
asserts.assert_true(standard_global_attribute_range(id), msg)
asserts.assert_false(standard_non_global_attribute_range(id), msg)
asserts.assert_false(manufacturer_attribute_range(id), msg)
asserts.assert_false(test_attribute_range(id), msg)
asserts.assert_true(valid_attribute_range(id, allow_test=True), msg)
asserts.assert_true(valid_attribute_range(id, allow_test=False), msg)

def check_standard_non_global(id):
msg = f"Incorrect attribute range assessment, expecting standard non-global {id:08x}"
asserts.assert_false(standard_global_attribute_range(id), msg)
asserts.assert_true(standard_non_global_attribute_range(id), msg)
asserts.assert_false(manufacturer_attribute_range(id), msg)
asserts.assert_false(test_attribute_range(id), msg)
asserts.assert_true(valid_attribute_range(id, allow_test=True), msg)
asserts.assert_true(valid_attribute_range(id, allow_test=False), msg)

def check_manufacturer(id):
msg = f"Incorrect attribute range assessment, expecting manufacturer {id:08x}"
asserts.assert_false(standard_global_attribute_range(id), msg)
asserts.assert_false(standard_non_global_attribute_range(id), msg)
asserts.assert_true(manufacturer_attribute_range(id), msg)
asserts.assert_false(test_attribute_range(id), msg)
asserts.assert_true(valid_attribute_range(id, allow_test=True), msg)
asserts.assert_true(valid_attribute_range(id, allow_test=False), msg)

def check_test(id):
msg = f"Incorrect attribute range assessment, expecting test {id:08x}"
asserts.assert_false(standard_global_attribute_range(id), msg)
asserts.assert_false(standard_non_global_attribute_range(id), msg)
asserts.assert_false(manufacturer_attribute_range(id), msg)
asserts.assert_true(test_attribute_range(id), msg)
asserts.assert_true(valid_attribute_range(id, allow_test=True), msg)
asserts.assert_false(valid_attribute_range(id, allow_test=False), msg)

def check_all_bad(id):
msg = f"Incorrect attribute range assessment, expecting invalid {id:08x}"
asserts.assert_false(standard_global_attribute_range(id), msg)
asserts.assert_false(standard_non_global_attribute_range(id), msg)
asserts.assert_false(manufacturer_attribute_range(id), msg)
asserts.assert_false(test_attribute_range(id), msg)
asserts.assert_false(valid_attribute_range(id, allow_test=True), msg)
asserts.assert_false(valid_attribute_range(id, allow_test=False), msg)

for id in standard_global_good:
check_standard_global(id)
for id in standard_global_bad:
check_all_bad(id)
for id in standard_non_global_good:
check_standard_non_global(id)
for id in standard_non_global_bad:
check_all_bad(id)
for id in manufacturer_good:
check_manufacturer(id)
for id in manufacturer_bad:
check_all_bad(id)
for id in test_good:
check_test(id)
for id in test_bad:
check_all_bad(id)
for id in prefix_bad:
check_all_bad(id)


if __name__ == "__main__":
default_matter_test_main()
93 changes: 93 additions & 0 deletions src/python_testing/global_attribute_ids.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

# This file should be removed once we have a good way to get this from the codegen or XML

from dataclasses import dataclass
from enum import IntEnum


Expand All @@ -38,3 +39,95 @@ def to_name(self) -> str:
return "FeatureMap"
if self == GlobalAttributeIds.CLUSTER_REVISION_ID:
return "ClusterRevision"


@dataclass
class IdRange:
min: int
max: int

def _contains(self, id: int):
return id in range(self.min, self.max+1)


@dataclass
class PrefixIdRange(IdRange):
def contains(self, id: int):
return super()._contains(id >> 16)


class SuffixIdRange(IdRange):
def contains(self, id: int):
return super()._contains(id & 0xFFFF)


STANDARD_PREFIX = PrefixIdRange(0x0000, 0x0000)
MANUFACTURER_PREFIX = PrefixIdRange(0x0001, 0xFFF0)
TEST_PREFIX = PrefixIdRange(0xFFF1, 0xFFF4)

DEVICE_TYPE_ID_RANGE_SUFFIX = SuffixIdRange(0x0000, 0xBFFF)
CLUSTER_ID_STANDARD_RANGE_SUFFIX = SuffixIdRange(0x0000, 0x7FFF)
CLUSTER_ID_MANUFACTURER_RANGE_SUFFIX = SuffixIdRange(0xFC00, 0xFFFE)
ATTRIBUTE_ID_GLOBAL_RANGE_SUFFIX = SuffixIdRange(0xF000, 0xFFFE)
ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX = SuffixIdRange(0x0000, 0x4FFF)


def standard_device_type_range(id: int):
return STANDARD_PREFIX.contains(id) and DEVICE_TYPE_ID_RANGE_SUFFIX.contains(id)


def manufacturer_device_type_range(id: int):
return MANUFACTURER_PREFIX.contains(id) and DEVICE_TYPE_ID_RANGE_SUFFIX.contains(id)


def test_device_type_range(id: int):
return TEST_PREFIX.contains(id) and DEVICE_TYPE_ID_RANGE_SUFFIX.contains(id)


def valid_device_type_range(id: int, allow_test: bool = False):
ret = manufacturer_device_type_range(id) or standard_device_type_range(id)
if allow_test:
ret = ret or test_device_type_range(id)
return ret


def standard_cluster_range(id: int):
return STANDARD_PREFIX.contains(id) and CLUSTER_ID_STANDARD_RANGE_SUFFIX.contains(id)


def manufacturer_cluster_range(id: int):
return MANUFACTURER_PREFIX.contains(id) and CLUSTER_ID_MANUFACTURER_RANGE_SUFFIX.contains(id)


def test_cluster_range(id: int):
return TEST_PREFIX.contains(id) and CLUSTER_ID_MANUFACTURER_RANGE_SUFFIX.contains(id)


def valid_cluster_range(id: int, allow_test: bool = False):
ret = standard_cluster_range(id) or manufacturer_cluster_range(id)
if allow_test:
ret = ret or test_cluster_range(id)
return ret


def standard_non_global_attribute_range(id: int):
return STANDARD_PREFIX.contains(id) and ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX.contains(id)


def standard_global_attribute_range(id: str):
return STANDARD_PREFIX.contains(id) and ATTRIBUTE_ID_GLOBAL_RANGE_SUFFIX.contains(id)


def manufacturer_attribute_range(id: str):
return MANUFACTURER_PREFIX.contains(id) and ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX.contains(id)


def test_attribute_range(id: str):
return TEST_PREFIX.contains(id) and ATTRIBUTE_ID_NON_GLOBAL_RANGE_SUFFIX.contains(id)


def valid_attribute_range(id: str, allow_test: bool = False):
ret = standard_global_attribute_range(id) or standard_non_global_attribute_range(id) or manufacturer_attribute_range(id)
if allow_test:
ret = ret or test_attribute_range(id)
return ret
Loading