Skip to content

Commit 4edda3f

Browse files
Minor changes for SU 2.5. Added restart and state value tracking.
1 parent 4525982 commit 4edda3f

File tree

2 files changed

+91
-80
lines changed

2 files changed

+91
-80
lines changed

src/python_testing/TC_SUTestBase.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import logging
1919
import tempfile
2020
from os import path
21+
from time import sleep
2122
from typing import Optional
2223

2324
from mobly import asserts
@@ -300,3 +301,40 @@ def create_acl_entry(self,
300301
nodeId=provider_node_id,
301302
attributes=[(0, acl_attribute)]
302303
)
304+
305+
def restart_requestor(self, requestor_th):
306+
"""This method restart the requestor to restore Softwareupdate version.
307+
308+
Args:
309+
controller (_type_): _description_
310+
"""
311+
restart_flag_file = self.get_restart_flag_file()
312+
logger.info(f"RESTART FILE at {restart_flag_file}")
313+
if not restart_flag_file:
314+
# No restart flag file: ask user to manually reboot
315+
self.wait_for_user_input(prompt_msg="Reboot the DUT. Press Enter when ready.\n")
316+
317+
# After manual reboot, expire previous sessions so that we can re-establish connections
318+
logging.info("Expiring sessions after manual device reboot")
319+
requestor_th.ExpireSessions(self.requestor_node_id)
320+
logging.info("Manual device reboot completed")
321+
322+
else:
323+
try:
324+
# Create the restart flag file to signal the test runner
325+
with open(restart_flag_file, "w") as f:
326+
f.write("restart")
327+
logging.info("Created restart flag file to signal app restart")
328+
329+
# The test runner will automatically wait for the app-ready-pattern before continuing
330+
# Waiting 1 second after the app-ready-pattern is detected as we need to wait a tad longer for the app to be ready and stable, otherwise TH2 connection fails later on in test step 14.
331+
sleep(1)
332+
333+
# Expire sessions and re-establish connections
334+
logging.info("Expiring sessions after manual device reboot")
335+
requestor_th.ExpireSessions(self.requestor_node_id)
336+
logging.info("App restart completed successfully")
337+
338+
except Exception as e:
339+
logging.error(f"Failed to restart Requestor: {e}")
340+
asserts.fail(f"Requestor restart failed: {e}")

src/python_testing/TC_SU_2_5.py

Lines changed: 53 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,9 @@
3939
# --trace-to json:${TRACE_TEST_JSON}.json
4040
# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
4141
# --string-arg provider_app_path:${OTA_PROVIDER_APP}
42-
# --string-arg ota_image_step1:${OTA_IMAGE_V2}
43-
# --int-arg ota_image_step1_expected_version:2
44-
# --string-arg ota_image_step2:${OTA_IMAGE_V3}
45-
# --int-arg ota_image_step2_expected_version:3
46-
# --string-arg ota_image_step3:${OTA_IMAGE_V4}
47-
# --int-arg ota_image_step3_expected_version:4
48-
# --string-arg ota_image_step4:${OTA_IMAGE_V5}
49-
# --int-arg ota_image_step4_expected_version:5
50-
# --string-arg ota_image_step5:${OTA_IMAGE_V6}
51-
# --int-arg ota_image_step5_expected_version:6
42+
# --string-arg ota_image:${SU_OTA_REQUESTOR_V2}
43+
# --int-arg ota_image_expected_version:2
44+
# --int-arg ota_provider_port:5541
5245
# factory-reset: true
5346
# quiet: true
5447
# === END CI TEST ARGUMENTS ===
@@ -92,21 +85,22 @@ async def teardown_test(self):
9285
@async_test_body
9386
async def setup_test(self):
9487
# Set up Provider configuration and values for step1
95-
ota_image = self.user_params.get('ota_image_step1', None)
96-
self.expected_software_version = self.user_params.get('ota_image_step1_expected_version')
88+
self.ota_image = self.user_params.get('ota_image', None)
89+
self.expected_software_version = self.user_params.get('ota_image_expected_version')
9790
self.provider_app_path = self.user_params.get('provider_app_path', None)
91+
self.ota_provider_port = self.user_params.get('ota_provider_port', 5541)
9892

9993
self.requestor_node_id = self.dut_node_id # 123 with discriminator 123
10094
self.controller = self.default_controller
10195
# Extra Arguments required for the step 1
10296
extra_arguments = ['--applyUpdateAction', 'proceed', '--delayedApplyActionTimeSec', '0']
10397

10498
self.start_provider(
105-
provier_app_path=self.provider_app_path,
106-
ota_image_path=ota_image,
99+
provider_app_path=self.provider_app_path,
100+
ota_image_path=self.ota_image,
107101
setup_pincode=self.provider_data['setup_pincode'],
108102
discriminator=self.provider_data['discriminator'],
109-
port=5541,
103+
port=self.ota_provider_port,
110104
kvs_path=self.kvs_path,
111105
log_file=self.provider_log,
112106
extra_args=extra_arguments,
@@ -160,29 +154,31 @@ async def test_TC_SU_2_5(self):
160154
self.step(0)
161155

162156
self.step(1)
157+
update_state_attr_handler = AttributeSubscriptionHandler(
158+
expected_cluster=Clusters.OtaSoftwareUpdateRequestor,
159+
expected_attribute=Clusters.OtaSoftwareUpdateRequestor.Attributes.UpdateState
160+
)
161+
await update_state_attr_handler.start(dev_ctrl=self.controller, node_id=self.requestor_node_id, endpoint=0,
162+
fabric_filtered=False, min_interval_sec=0, max_interval_sec=5)
163163
basicinformation_handler = EventSubscriptionHandler(
164164
expected_cluster=Clusters.BasicInformation, expected_event_id=Clusters.BasicInformation.Events.ShutDown.event_id)
165-
await basicinformation_handler.start(self.controller, self.requestor_node_id, endpoint=0, min_interval_sec=0, max_interval_sec=60*8)
166-
event_state_transition = EventSubscriptionHandler(expected_cluster=Clusters.OtaSoftwareUpdateRequestor,
167-
expected_event_id=Clusters.OtaSoftwareUpdateRequestor.Events.StateTransition.event_id)
168-
await event_state_transition.start(self.controller, self.requestor_node_id, endpoint=0, min_interval_sec=0, max_interval_sec=60*7)
165+
await basicinformation_handler.start(self.controller, self.requestor_node_id, endpoint=0, min_interval_sec=0, max_interval_sec=60*2)
169166
await self.announce_ota_provider(self.controller, self.provider_data['node_id'], self.requestor_node_id)
170167

171-
# Wait for Download event this means updating has started
172-
event_report = event_state_transition.wait_for_event_report(
173-
Clusters.OtaSoftwareUpdateRequestor.Events.StateTransition, timeout_sec=30)
174-
logger.info(f"Event report for Querying : {event_report}")
175-
176-
# Wait for Download event this means updating has started
177-
event_report = event_state_transition.wait_for_event_report(
178-
Clusters.OtaSoftwareUpdateRequestor.Events.StateTransition, timeout_sec=30)
179-
logger.info(f"Event report for Downloading : {event_report}")
168+
update_state_match = AttributeMatcher.from_callable(
169+
"Update state is Downloading",
170+
lambda report: report.value == Clusters.OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum.kDownloading)
171+
update_state_attr_handler.await_all_expected_report_matches([update_state_match], timeout_sec=60)
180172

181-
event_state_transition.flush_events()
182-
await event_state_transition.cancel()
173+
update_state_match = AttributeMatcher.from_callable(
174+
"Update state is Applying",
175+
lambda report: report.value == Clusters.OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum.kApplying)
176+
update_state_attr_handler.await_all_expected_report_matches([update_state_match], timeout_sec=60*5)
183177

184178
# Wait for shutdown event ( this is triggered after the SU Completition)
185-
shutdown_event = basicinformation_handler.wait_for_event_report(Clusters.BasicInformation.Events.ShutDown, timeout_sec=60*6)
179+
update_state_attr_handler.flush_reports()
180+
await update_state_attr_handler.cancel()
181+
shutdown_event = basicinformation_handler.wait_for_event_report(Clusters.BasicInformation.Events.ShutDown, timeout_sec=60)
186182
logger.info(f"Event report for ShutDown : {shutdown_event}")
187183
# Cancel eventhandlers
188184

@@ -201,11 +197,10 @@ async def test_TC_SU_2_5(self):
201197
asserts.assert_equal(update_state, Clusters.OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum.kIdle,
202198
"Update state should be idle")
203199
self.current_provider_app_proc.terminate()
200+
self.restart_requestor(self.controller)
204201

205202
self.step(2)
206203
# Set values for step 2
207-
ota_image = self.user_params.get('ota_image_step2', None)
208-
self.expected_software_version = self.user_params.get("ota_image_step2_expected_version")
209204
delayed_apply_action_time = 60*3
210205
current_sw_version = await self.read_single_attribute_check_success(
211206
dev_ctrl=self.controller,
@@ -214,11 +209,11 @@ async def test_TC_SU_2_5(self):
214209
node_id=self.requestor_node_id)
215210
extra_arguments = ['--applyUpdateAction', 'proceed', '--delayedApplyActionTimeSec', str(delayed_apply_action_time)]
216211
self.start_provider(
217-
provier_app_path=self.provider_app_path,
218-
ota_image_path=ota_image,
212+
provider_app_path=self.provider_app_path,
213+
ota_image_path=self.ota_image,
219214
setup_pincode=self.provider_data['setup_pincode'],
220215
discriminator=self.provider_data['discriminator'],
221-
port=5541,
216+
port=self.ota_provider_port,
222217
kvs_path=self.kvs_path,
223218
log_file=self.provider_log,
224219
extra_args=extra_arguments,
@@ -264,8 +259,6 @@ async def test_TC_SU_2_5(self):
264259
asserts.assert_greater_equal(
265260
total_wait_time, delayed_apply_action_time, f"Software Udpate occured before the defined time of: {total_wait_time}")
266261
logger.info(f"Time taken after the update was done applied {total_wait_time} seconds.")
267-
update_state_attr_handler.flush_reports()
268-
await update_state_attr_handler.cancel()
269262
software_version_attr_handler.flush_reports()
270263
await software_version_attr_handler.cancel()
271264
update_state_after = await self.read_single_attribute_check_success(
@@ -278,19 +271,18 @@ async def test_TC_SU_2_5(self):
278271
controller=self.controller, node_id=self.requestor_node_id, target_version=self.expected_software_version)
279272
# Terminate the provider
280273
self.current_provider_app_proc.terminate()
274+
self.restart_requestor(self.controller)
281275

282276
self.step(3)
283-
ota_image = self.user_params.get('ota_image_step3', None)
284-
self.expected_software_version = self.user_params.get("ota_image_step3_expected_version")
285277
delayed_apply_action_time = 60
286278
spec_wait_time = 120
287279
extra_arguments = ['--applyUpdateAction', 'awaitNextAction', '--delayedApplyActionTimeSec', str(delayed_apply_action_time)]
288280
self.start_provider(
289-
provier_app_path=self.provider_app_path,
290-
ota_image_path=ota_image,
281+
provider_app_path=self.provider_app_path,
282+
ota_image_path=self.ota_image,
291283
setup_pincode=self.provider_data['setup_pincode'],
292284
discriminator=self.provider_data['discriminator'],
293-
port=5541,
285+
port=self.ota_provider_port,
294286
kvs_path=self.kvs_path,
295287
log_file=self.provider_log,
296288
extra_args=extra_arguments,
@@ -316,31 +308,15 @@ async def test_TC_SU_2_5(self):
316308
fabric_filtered=False, min_interval_sec=0, max_interval_sec=5)
317309
await self.announce_ota_provider(self.controller, self.provider_data['node_id'], self.requestor_node_id)
318310

319-
update_state_states_seen = set()
320-
update_state_states_stack = []
321-
update_state_previous_state = None
322-
323-
def collect_update_state_data(report):
324-
current_state_value = report.value
325-
nonlocal update_state_states_seen, update_state_states_stack, update_state_previous_state
326-
if current_state_value is None:
327-
return False
328-
if current_state_value not in update_state_states_seen:
329-
update_state_states_seen.add(current_state_value)
330-
update_state_states_stack.append(current_state_value)
331-
332-
if current_state_value == Clusters.OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum.kDelayedOnApply:
333-
return True
334-
335-
update_state_previous_state = current_state_value
336-
return False
311+
update_state_match = AttributeMatcher.from_callable(
312+
"Update state is Downloading",
313+
lambda report: report.value == Clusters.OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum.kDownloading)
314+
update_state_attr_handler.await_all_expected_report_matches([update_state_match], timeout_sec=60)
337315

338-
callable_collect_update_state_data = AttributeMatcher.from_callable(
339-
description="Record the Event Transition Until kDelayedOnApply",
340-
matcher=collect_update_state_data
341-
)
342-
update_state_attr_handler.await_all_expected_report_matches([callable_collect_update_state_data], timeout_sec=60*6)
343-
logger.info(f"Update State Stack secuence: {update_state_states_stack}")
316+
update_state_match = AttributeMatcher.from_callable(
317+
"Update state is kDelayedOnApply",
318+
lambda report: report.value == Clusters.OtaSoftwareUpdateRequestor.Enums.UpdateStateEnum.kDelayedOnApply)
319+
update_state_attr_handler.await_all_expected_report_matches([update_state_match], timeout_sec=60*6)
344320
update_state_attr_handler.reset()
345321
await update_state_attr_handler.cancel()
346322

@@ -354,6 +330,7 @@ def collect_update_state_data(report):
354330

355331
start_time = time()
356332
# Waiting for Software Version to change in the range for spec wait time then verify it did took more than 120 seconds to change the version
333+
# To Apply the new version it should have re send the ApplyUpdateRequest
357334
update_sw_version = AttributeMatcher.from_callable(
358335
f"Sofware version was updated to {self.expected_software_version}",
359336
lambda report: report.value > start_software_version)
@@ -373,18 +350,17 @@ def collect_update_state_data(report):
373350
# Now software version should be in the expected software version
374351
await self.verify_version_applied_basic_information(controller=self.controller, node_id=self.requestor_node_id, target_version=self.expected_software_version)
375352
self.current_provider_app_proc.terminate()
353+
self.restart_requestor(self.controller)
376354

377355
self.step(4)
378-
self.expected_software_version = self.user_params.get("ota_image_step4_expected_version")
379-
ota_image = self.user_params.get('ota_image_step4', None)
380356
delayed_apply_action_time = 180
381357
extra_arguments = ['--applyUpdateAction', 'awaitNextAction', '--delayedApplyActionTimeSec', str(delayed_apply_action_time)]
382358
self.start_provider(
383-
provier_app_path=self.provider_app_path,
384-
ota_image_path=ota_image,
359+
provider_app_path=self.provider_app_path,
360+
ota_image_path=self.ota_image,
385361
setup_pincode=self.provider_data['setup_pincode'],
386362
discriminator=self.provider_data['discriminator'],
387-
port=5541,
363+
port=self.ota_provider_port,
388364
kvs_path=self.kvs_path,
389365
log_file=self.provider_log,
390366
extra_args=extra_arguments,
@@ -438,7 +414,7 @@ def collect_update_state_data(report):
438414
logger.info(f"Update State Stack secuence: {update_state_states_stack}")
439415
update_state_attr_handler.reset()
440416
await update_state_attr_handler.cancel()
441-
# Waiting for Software Version to change in the range for spec wait time then verify it did took more than 120 seconds to change the version
417+
# Waiting for Software Version to change in the range defined in the delayedApplyTimeSec of 180 seconds
442418
update_sw_version = AttributeMatcher.from_callable(
443419
f"Sofware version was updated to {self.expected_software_version}",
444420
lambda report: report.value > start_software_version)
@@ -452,19 +428,17 @@ def collect_update_state_data(report):
452428
await software_version_attr_handler.cancel()
453429
# Verify the version is the same
454430
await self.verify_version_applied_basic_information(controller=self.controller, node_id=self.requestor_node_id, target_version=self.expected_software_version)
455-
456431
self.current_provider_app_proc.terminate()
432+
self.restart_requestor(self.controller)
457433

458434
self.step(5)
459-
self.expected_software_version = self.user_params.get("ota_image_step5_expected_version")
460-
ota_image = self.user_params.get('ota_image_step5', None)
461435
extra_arguments = ['--applyUpdateAction', 'discontinue']
462436
self.start_provider(
463-
provier_app_path=self.provider_app_path,
464-
ota_image_path=ota_image,
437+
provider_app_path=self.provider_app_path,
438+
ota_image_path=self.ota_image,
465439
setup_pincode=self.provider_data['setup_pincode'],
466440
discriminator=self.provider_data['discriminator'],
467-
port=5541,
441+
port=self.ota_provider_port,
468442
kvs_path=self.kvs_path,
469443
log_file=self.provider_log,
470444
extra_args=extra_arguments,
@@ -525,7 +499,6 @@ def collect_update_state_data(report):
525499
Clusters.OtaSoftwareUpdateRequestor, Clusters.OtaSoftwareUpdateRequestor.Attributes.UpdateStateProgress, self.controller, self.requestor_node_id, 0)
526500
asserts.assert_equal(update_state_progress, NullValue, "Progress is not Null")
527501
logger.info(f"Progress is {update_state_progress}")
528-
529502
# Verify version is the same as when it started
530503
await self.verify_version_applied_basic_information(self.controller, self.requestor_node_id, current_sw_version)
531504

0 commit comments

Comments
 (0)