Skip to content

Commit c0df966

Browse files
Local test to run CI check to if test script passes with timeout set to 2 min.
1 parent 550b1c1 commit c0df966

File tree

2 files changed

+89
-8
lines changed

2 files changed

+89
-8
lines changed

.github/workflows/examples-linux-tv-casting-app.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ jobs:
6767
run: |
6868
./scripts/run_in_build_env.sh \
6969
"python3 ./scripts/tests/run_tv_casting_test.py"
70-
timeout-minutes: 1
70+
timeout-minutes: 2
7171

7272
- name: Uploading Size Reports
7373
uses: ./.github/actions/upload-size-reports

scripts/tests/run_tv_casting_test.py

+88-7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
# The maximum amount of time to test that the launchURL is sent from the Linux tv-casting-app and received on the tv-app before timeout.
3737
TEST_LAUNCHURL_MAX_WAIT_SEC = 10
3838

39+
# The maximum amount of time to verify the subscription state in the Linux tv-casting-app output before timeout.
40+
VERIFY_SUBSCRIPTION_STATE_MAX_WAIT_SEC = 10
41+
3942
# File names of logs for the Linux tv-casting-app and the Linux tv-app.
4043
LINUX_TV_APP_LOGS = 'Linux-tv-app-logs.txt'
4144
LINUX_TV_CASTING_APP_LOGS = 'Linux-tv-casting-app-logs.txt'
@@ -46,6 +49,10 @@
4649
PRODUCT_ID = 0x8001 # Test product id
4750
DEVICE_TYPE_CASTING_VIDEO_PLAYER = 0x23 # Device type library 10.3: Casting Video Player
4851

52+
# Values to verify the subscription state against from the `ReportDataMessage` in the Linux tv-casting-app output.
53+
CLUSTER_MEDIA_PLAYBACK = '0x506' # Application Cluster Spec 6.10.3 Cluster ID: Media Playback
54+
ATTRIBUTE_CURRENT_PLAYBACK_STATE = '0x0000_0000' # Application Cluster Spec 6.10.6 Attribute ID: Current State of Playback
55+
4956

5057
class ProcessManager:
5158
"""A context manager for managing subprocesses.
@@ -96,13 +103,19 @@ def extract_value_from_string(line: str) -> str:
96103
97104
The string is expected to be in the following format as it is received
98105
from the Linux tv-casting-app output:
106+
\x1b[0;34m[1715206773402] [20056:2842184] [DMG] Cluster = 0x506,\x1b[0m
107+
The substring to be extracted here is '0x506'.
108+
Or:
99109
\x1b[0;34m[1713741926895] [7276:9521344] [DIS] Vendor ID: 65521\x1b[0m
100110
The integer value to be extracted here is 65521.
101111
Or:
102112
\x1b[0;34m[1714583616179] [7029:2386956] [SVR] device Name: Test TV casting app\x1b[0m
103113
The substring to be extracted here is 'Test TV casting app'.
104114
"""
105-
value = line.split(':')[-1].strip().replace('\x1b[0m', '')
115+
if '=' in line:
116+
value = line.split('=')[-1].strip().replace(',\x1b[0m', '')
117+
else:
118+
value = line.split(':')[-1].strip().replace('\x1b[0m', '')
106119

107120
return value
108121

@@ -211,7 +224,8 @@ def validate_identification_declaration_message_on_tv_app(tv_app_info: Tuple[sub
211224
while True:
212225
# Check if we exceeded the maximum wait time for validating the device information from the Linux tv-app to the corresponding values from the Linux tv-app.
213226
if time.time() - start_wait_time > COMMISSIONING_STAGE_MAX_WAIT_SEC:
214-
logging.erro('The device information from the Linux tv-app output was not validated against the corresponding values from the Linux tv-casting-app output within the timeout.')
227+
logging.error(
228+
'The device information from the Linux tv-app output was not validated against the corresponding values from the Linux tv-casting-app output within the timeout.')
215229
return False
216230

217231
tv_app_line = tv_app_process.stdout.readline()
@@ -221,7 +235,7 @@ def validate_identification_declaration_message_on_tv_app(tv_app_info: Tuple[sub
221235
linux_tv_app_log_file.flush()
222236

223237
if 'Identification Declaration Start' in tv_app_line:
224-
logging.info('"Identification Declaration" block from the Linux tv-app output:')
238+
logging.info('Found the `Identification Declaration` block in the Linux tv-app output:')
225239
logging.info(tv_app_line.rstrip('\n'))
226240
parsing_identification_block = True
227241
elif parsing_identification_block:
@@ -310,6 +324,56 @@ def validate_commissioning_success(tv_casting_app_info: Tuple[subprocess.Popen,
310324
return True
311325

312326

327+
def parse_tv_casting_app_for_report_data_msg(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]):
328+
"""Parse the Linux tv-casting-app for `ReportDataMessage` block and return the first message block with valid `Cluster` and `Attribute` values."""
329+
tv_casting_app_process, linux_tv_casting_app_log_file = tv_casting_app_info
330+
331+
continue_parsing = False
332+
report_data_message = []
333+
334+
start_wait_time = time.time()
335+
336+
while True:
337+
# Check if we exceeded the maximum wait time to parse the Linux tv-casting-app output for `ReportDataMessage` block.
338+
if time.time() - start_wait_time > VERIFY_SUBSCRIPTION_STATE_MAX_WAIT_SEC:
339+
logging.error(
340+
'The relevant `ReportDataMessage` block was not found in the Linux tv-casting-app process within the timeout.')
341+
report_data_message.clear()
342+
return report_data_message
343+
344+
tv_casting_line = tv_casting_app_process.stdout.readline()
345+
346+
if tv_casting_line:
347+
linux_tv_casting_app_log_file.write(tv_casting_line)
348+
linux_tv_casting_app_log_file.flush()
349+
350+
if 'ReportDataMessage =' in tv_casting_line:
351+
report_data_message.append(tv_casting_line.rstrip('\n'))
352+
continue_parsing = True
353+
elif continue_parsing:
354+
report_data_message.append(tv_casting_line.rstrip('\n'))
355+
356+
if 'Cluster =' in tv_casting_line:
357+
cluster_value = extract_value_from_string(tv_casting_line)
358+
if cluster_value != CLUSTER_MEDIA_PLAYBACK:
359+
report_data_message.clear()
360+
continue_parsing = False
361+
362+
elif 'Attribute =' in tv_casting_line:
363+
attribute_value = extract_value_from_string(tv_casting_line)
364+
if attribute_value != ATTRIBUTE_CURRENT_PLAYBACK_STATE:
365+
report_data_message.clear()
366+
continue_parsing = False
367+
368+
elif 'InteractionModelRevision' in tv_casting_line:
369+
# Capture the closing brace `}` of the `ReportDataMessage` block.
370+
tv_casting_line = tv_casting_app_process.stdout.readline()
371+
linux_tv_casting_app_log_file.write(tv_casting_line)
372+
linux_tv_casting_app_log_file.flush()
373+
report_data_message.append(tv_casting_line.rstrip('\n'))
374+
return report_data_message
375+
376+
313377
def parse_tv_app_output_for_launchUrl_msg_success(tv_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]):
314378
"""Parse the Linux tv-app output for the relevant string indicating that the launchUrl was received."""
315379

@@ -359,7 +423,7 @@ def parse_tv_casting_app_output_for_launchUrl_msg_success(tv_casting_app_info: T
359423
linux_tv_casting_app_log_file.flush()
360424

361425
if 'InvokeResponseMessage =' in tv_casting_line:
362-
logging.info('Found the InvokeResponseMessage block in the Linux tv-casting-app output:')
426+
logging.info('Found the `InvokeResponseMessage` block in the Linux tv-casting-app output:')
363427
logging.info(tv_casting_line.rstrip('\n'))
364428
continue_parsing_invoke_response_msg_block = True
365429

@@ -415,7 +479,7 @@ def test_discovery_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], log_
415479

416480
# A valid commissioner has VENDOR_ID, PRODUCT_ID, and DEVICE TYPE in its list of entries.
417481
if valid_vendor_id and valid_product_id and valid_device_type:
418-
logging.info('Found a valid commissioner in the Linux tv-casting-app logs:')
482+
logging.info('Found a valid commissioner in the Linux tv-casting-app output:')
419483
logging.info(valid_discovered_commissioner)
420484
logging.info(valid_vendor_id)
421485
logging.info(valid_product_id)
@@ -445,6 +509,23 @@ def test_commissioning_fn(valid_discovered_commissioner_number, tv_casting_app_i
445509
handle_casting_failure('Commissioning', log_paths)
446510

447511

512+
def test_subscription_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]):
513+
"""Test the subscription state of the Linux tv-casting-app by validating the `ReportDataMessage` block."""
514+
515+
valid_report_data_msg = parse_tv_casting_app_for_report_data_msg(tv_casting_app_info, log_paths)
516+
517+
if valid_report_data_msg:
518+
logging.info('Found the `ReportDataMessage` block in the Linux tv-casting-app output:')
519+
520+
for line in valid_report_data_msg:
521+
logging.info(line)
522+
523+
logging.info('Testing subscription success!\n')
524+
valid_report_data_msg.clear()
525+
else:
526+
handle_casting_failure('Testing subscription', log_paths)
527+
528+
448529
def test_launchUrl_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], tv_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]):
449530
"""Test that the Linux tv-casting-app sent the launchUrl and that the Linux tv-app received the launchUrl."""
450531

@@ -454,7 +535,7 @@ def test_launchUrl_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], tv_a
454535
if not parse_tv_casting_app_output_for_launchUrl_msg_success(tv_casting_app_info, log_paths):
455536
handle_casting_failure('Testing launchUrl', log_paths)
456537

457-
logging.info('Testing launchUrl success!\n')
538+
logging.info('Testing launchUrl success!')
458539

459540

460541
@click.command()
@@ -504,7 +585,7 @@ def test_casting_fn(tv_app_rel_path, tv_casting_app_rel_path):
504585
valid_discovered_commissioner_number = valid_discovered_commissioner.split('#')[-1].replace('\x1b[0m', '')
505586

506587
test_commissioning_fn(valid_discovered_commissioner_number, tv_casting_app_info, tv_app_info, log_paths)
507-
588+
test_subscription_fn(tv_casting_app_info, log_paths)
508589
test_launchUrl_fn(tv_casting_app_info, tv_app_info, log_paths)
509590

510591

0 commit comments

Comments
 (0)