From 6e31453ed626768f9c74bc9e59ffae7a7137999f Mon Sep 17 00:00:00 2001 From: Jake Ororke Date: Sat, 6 Jul 2024 10:28:59 -0700 Subject: [PATCH] [Fix] Proposed resolution of issue #230: remove PICS from timesync tests (#33953) * Created proposed resolution of Github issue #230: * Removed PICS from TC_TIMESYNC_2_1 and TC_TIMESYNC_2_2 in python_testing folder * Added using the wait_for_user_input() to allow user to inform if certain features are present on DUT * Updated TC_TIMESYNC_2_1 test: * Now utilizes Clusters.TimeSynchronization.Bitmaps.Feature to check supported features on DUT in place of PICS or waiting for user input. * Restyled by autopep8 * Applied stylization fix to TC_TIMESYNC_2_2 test module as mentioned in restyled.io check. * Restyled by autopep8 * Removed unnecessary pics_TC_TIMESYNC_2_1() from TC_TIMESYNC_2_1 class as no longer needed with recent changes implemented. * Updates to TC_TIMESYNC_2_1 and 2_2 test modules: - Restored pics_TC_TIMESYNC_2_1 and pics_TC_TIMESYNC_2_2 functions - Added if check for timesource attribute ID for test step 3 in TC_TIMESYNC_2_1 test module - Updated endpoint variable to statically be set to 0 * Restyled by autopep8 * Updated TC_TIMESYNC_2_1 and TC_TIMESYNC_2_2: - Changed method for getting attribute_list -- now using get_single_attribute_expect_success() from matter_testing_support module - Updated time source test step 5 to include if check in TC_TIMESYNC_2_2 test module to match with TC_TIMESYNC_2_1 * Restyled by autopep8 * Updated TC_TIMESYNC_2_2 with suggestions from Cecille - Changed class name value assigned to time_cluster variable - Updated timesync_attr_list and timesource_attr_id variables to contain time_cluster in value in place of Clusters.TimeSynchronization * Apply suggestions from code review from Cecille Adding these suggestions from Cecille after testing in local dev env Co-authored-by: C Freeman --------- Co-authored-by: Restyled.io Co-authored-by: C Freeman --- src/python_testing/TC_TIMESYNC_2_1.py | 92 ++++++++++++--------------- src/python_testing/TC_TIMESYNC_2_2.py | 7 +- 2 files changed, 44 insertions(+), 55 deletions(-) diff --git a/src/python_testing/TC_TIMESYNC_2_1.py b/src/python_testing/TC_TIMESYNC_2_1.py index 1930606b2b245f..febaea6f1e9d49 100644 --- a/src/python_testing/TC_TIMESYNC_2_1.py +++ b/src/python_testing/TC_TIMESYNC_2_1.py @@ -41,28 +41,37 @@ def pics_TC_TIMESYNC_2_1(self) -> list[str]: @async_test_body async def test_TC_TIMESYNC_2_1(self): + endpoint = 0 - endpoint = self.user_params.get("endpoint", 0) + features = await self.read_single_attribute(dev_ctrl=self.default_controller, node_id=self.dut_node_id, + endpoint=endpoint, attribute=Clusters.TimeSynchronization.Attributes.FeatureMap) + + self.supports_time_zone = bool(features & Clusters.TimeSynchronization.Bitmaps.Feature.kTimeZone) + self.supports_ntpc = bool(features & Clusters.TimeSynchronization.Bitmaps.Feature.kNTPClient) + self.supports_ntps = bool(features & Clusters.TimeSynchronization.Bitmaps.Feature.kNTPServer) + self.supports_trusted_time_source = bool(features & Clusters.TimeSynchronization.Bitmaps.Feature.kTimeSyncClient) + + time_cluster = Clusters.TimeSynchronization + timesync_attr_list = time_cluster.Attributes.AttributeList + attribute_list = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=time_cluster, attribute=timesync_attr_list) + timesource_attr_id = time_cluster.Attributes.TimeSource.attribute_id self.print_step(1, "Commissioning, already done") attributes = Clusters.TimeSynchronization.Attributes self.print_step(2, "Read Granularity attribute") - if self.check_pics("TIMESYNC.S.A0001"): - granularity_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.Granularity) - asserts.assert_less(granularity_dut, Clusters.TimeSynchronization.Enums.GranularityEnum.kUnknownEnumValue, - "Granularity is not in valid range") - else: - asserts.assert_true(False, "Granularity is a mandatory attribute and must be present in the PICS file") + granularity_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.Granularity) + asserts.assert_less(granularity_dut, Clusters.TimeSynchronization.Enums.GranularityEnum.kUnknownEnumValue, + "Granularity is not in valid range") self.print_step(3, "Read TimeSource") - if self.check_pics("TIMESYNC.S.A0002"): + if timesource_attr_id in attribute_list: time_source = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeSource) asserts.assert_less(time_source, Clusters.TimeSynchronization.Enums.TimeSourceEnum.kUnknownEnumValue, "TimeSource is not in valid range") self.print_step(4, "Read TrustedTimeSource") - if self.check_pics("TIMESYNC.S.A0003"): + if self.supports_trusted_time_source: trusted_time_source = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TrustedTimeSource) if trusted_time_source is not NullValue: @@ -70,11 +79,9 @@ async def test_TC_TIMESYNC_2_1(self): "FabricIndex for the TrustedTimeSource is out of range") asserts.assert_greater_equal(trusted_time_source.fabricIndex, 1, "FabricIndex for the TrustedTimeSource is out of range") - elif self.check_pics("TIMESYNC.S.F03"): - asserts.assert_true(False, "TrustedTimeSource is mandatory if the TSC feature (TIMESYNC.S.F03) is supported") self.print_step(5, "Read DefaultNTP") - if self.check_pics("TIMESYNC.S.A0004"): + if self.supports_ntpc: default_ntp = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.DefaultNTP) if default_ntp is not NullValue: asserts.assert_less_equal(len(default_ntp), 128, "DefaultNTP length must be less than 128") @@ -87,11 +94,9 @@ async def test_TC_TIMESYNC_2_1(self): is_ip_addr = False pass asserts.assert_true(is_web_addr or is_ip_addr, "Returned DefaultNTP value is not a IP address or web address") - elif self.check_pics("TIMESYNC.S.F01"): - asserts.assert_true(False, "DefaultNTP is mandatory if the NTPC (TIMESYNC.S.F01) feature is supported") self.print_step(6, "Read TimeZone") - if self.check_pics("TIMESYNC.S.A0005"): + if self.supports_time_zone: tz_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeZone) asserts.assert_greater_equal(len(tz_dut), 1, "TimeZone must have at least one entry in the list") asserts.assert_less_equal(len(tz_dut), 2, "TimeZone may have a maximum of two entries in the list") @@ -104,11 +109,9 @@ async def test_TC_TIMESYNC_2_1(self): asserts.assert_equal(tz_dut[0].validAt, 0, "TimeZone list first entry must have a 0 ValidAt time") if len(tz_dut) > 1: asserts.assert_not_equal(tz_dut[1].validAt, 0, "TimeZone list second entry must have a non-zero ValidAt time") - elif self.check_pics("TIMESYNC.S.F00"): - asserts.assert_true(False, "TimeZone is mandatory if the TZ (TIMESYNC.S.F00) feature is supported") self.print_step(7, "Read DSTOffset") - if self.check_pics("TIMESYNC.S.A0006"): + if self.supports_time_zone: dst_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.DSTOffset) last_valid_until = -1 last_valid_starting = -1 @@ -121,28 +124,23 @@ async def test_TC_TIMESYNC_2_1(self): last_valid_until = dst.validUntil if dst.validUntil is NullValue or dst.validUntil is None: asserts.assert_equal(dst, dst_dut[-1], "DSTOffset list must have Null ValidUntil at the end") - elif self.check_pics("TIMESYNC.S.F00"): - asserts.assert_true(False, "DSTOffset is mandatory if the TZ (TIMESYNC.S.F00) feature is supported") self.print_step(8, "Read UTCTime") - if self.check_pics("TIMESYNC.S.A0000"): - utc_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.UTCTime) - if utc_dut is NullValue: - asserts.assert_equal(granularity_dut, Clusters.TimeSynchronization.Enums.GranularityEnum.kNoTimeGranularity) - else: - asserts.assert_not_equal(granularity_dut, Clusters.TimeSynchronization.Enums.GranularityEnum.kNoTimeGranularity) - if granularity_dut is Clusters.TimeSynchronization.Enums.GranularityEnum.kMinutesGranularity: - toleranace = timedelta(minutes=10) - else: - toleranace = timedelta(minutes=1) - delta_us = abs(utc_dut - utc_time_in_matter_epoch()) - delta = timedelta(microseconds=delta_us) - asserts.assert_less_equal(delta, toleranace, "UTC time is not within tolerance of TH") + utc_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.UTCTime) + if utc_dut is NullValue: + asserts.assert_equal(granularity_dut, Clusters.TimeSynchronization.Enums.GranularityEnum.kNoTimeGranularity) else: - asserts.assert_true(False, "UTCTime is a mandatory attribute and must be present in the PICS file") + asserts.assert_not_equal(granularity_dut, Clusters.TimeSynchronization.Enums.GranularityEnum.kNoTimeGranularity) + if granularity_dut is Clusters.TimeSynchronization.Enums.GranularityEnum.kMinutesGranularity: + toleranace = timedelta(minutes=10) + else: + toleranace = timedelta(minutes=1) + delta_us = abs(utc_dut - utc_time_in_matter_epoch()) + delta = timedelta(microseconds=delta_us) + asserts.assert_less_equal(delta, toleranace, "UTC time is not within tolerance of TH") self.print_step(9, "Read LocalTime") - if self.check_pics("TIMESYNC.S.A0007"): + if self.supports_time_zone: utc_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.UTCTime) local_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.LocalTime) if utc_dut is NullValue: @@ -155,45 +153,33 @@ async def test_TC_TIMESYNC_2_1(self): delta = timedelta(microseconds=delta_us) toleranace = timedelta(minutes=1) asserts.assert_less_equal(delta, toleranace, "Local time caluclation is not within tolerance of calculated value") - elif self.check_pics("TIMESYNC.S.F00"): - asserts.assert_true(False, "LocalTime is mandatory if the TZ (TIMESYNC.S.F00) feature is supported") self.print_step(10, "Read TimeZoneDatabase") - if self.check_pics("TIMESYNC.S.A0008"): + if self.supports_time_zone: tz_db_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeZoneDatabase) asserts.assert_less(tz_db_dut, Clusters.TimeSynchronization.Enums.TimeZoneDatabaseEnum.kUnknownEnumValue, "TimeZoneDatabase is not in valid range") - elif self.check_pics("TIMESYNC.S.F00"): - asserts.assert_true(False, "TimeZoneDatabase is mandatory if the TZ (TIMESYNC.S.F00) feature is supported") self.print_step(11, "Read NTPServerAvailable") - if self.check_pics("TIMESYNC.S.A0009"): + if self.supports_ntps: # bool typechecking happens in the test read functions, so all we need to do here is do the read await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.NTPServerAvailable) - elif self.check_pics("TIMESYNC.S.F02"): - asserts.assert_true(False, "NTPServerAvailable is mandatory if the NTPS (TIMESYNC.S.F02) feature is supported") self.print_step(12, "Read TimeZoneListMaxSize") - if self.check_pics("TIMESYNC.S.A000a"): + if self.supports_time_zone: size = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeZoneListMaxSize) asserts.assert_greater_equal(size, 1, "TimeZoneListMaxSize must be at least 1") asserts.assert_less_equal(size, 2, "TimeZoneListMaxSize must be max 2") - elif self.check_pics("TIMESYNC.S.F00"): - asserts.assert_true(False, "TimeZoneListMaxSize is mandatory if the TZ (TIMESYNC.S.F00) feature is supported") self.print_step(13, "Read DSTOffsetListMaxSize") - if self.check_pics("TIMESYNC.S.A000b"): + if self.supports_time_zone: size = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.DSTOffsetListMaxSize) asserts.assert_greater_equal(size, 1, "DSTOffsetListMaxSize must be at least 1") - elif self.check_pics("TIMESYNC.S.F00"): - asserts.assert_true(False, "DSTOffsetListMaxSize is mandatory if the TZ (TIMESYNC.S.F00) feature is supported") self.print_step(14, "Read SupportsDNSResolve") - if self.check_pics("TIMESYNC.S.A0004"): - # bool typechecking happens in the test read functions, so all we need to do here is do the read + # bool typechecking happens in the test read functions, so all we need to do here is do the read + if self.supports_ntpc: await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.SupportsDNSResolve) - elif self.check_pics("TIMESYNC.S.F01"): - asserts.assert_true(False, "SupportsDNSResolve is mandatory if the NTPC (TIMESYNC.S.F01) feature is supported") if __name__ == "__main__": diff --git a/src/python_testing/TC_TIMESYNC_2_2.py b/src/python_testing/TC_TIMESYNC_2_2.py index cb8e6d54d904e3..949fac75f2f4f7 100644 --- a/src/python_testing/TC_TIMESYNC_2_2.py +++ b/src/python_testing/TC_TIMESYNC_2_2.py @@ -45,7 +45,10 @@ async def test_TC_TIMESYNC_2_2(self): # Time sync is required to be on endpoint 0 if it is present endpoint = 0 - time_cluster = Clusters.Objects.TimeSynchronization + time_cluster = Clusters.TimeSynchronization + timesync_attr_list = time_cluster.Attributes.AttributeList + attribute_list = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=time_cluster, attribute=timesync_attr_list) + timesource_attr_id = time_cluster.Attributes.TimeSource.attribute_id self.print_step(1, "Commissioning, already done") attributes = Clusters.TimeSynchronization.Attributes @@ -85,7 +88,7 @@ async def test_TC_TIMESYNC_2_2(self): compare_time(received=utc_dut, utc=th_utc, tolerance=tolerance) self.print_step(5, "Read time source") - if self.check_pics("TIMESYNC.S.A0002"): + if timesource_attr_id in attribute_list: source = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeSource) if utc_dut_initial is NullValue: asserts.assert_equal(source, Clusters.Objects.TimeSynchronization.Enums.TimeSourceEnum.kAdmin)