36
36
# 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.
37
37
TEST_LAUNCHURL_MAX_WAIT_SEC = 10
38
38
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
+
39
42
# File names of logs for the Linux tv-casting-app and the Linux tv-app.
40
43
LINUX_TV_APP_LOGS = 'Linux-tv-app-logs.txt'
41
44
LINUX_TV_CASTING_APP_LOGS = 'Linux-tv-casting-app-logs.txt'
46
49
PRODUCT_ID = 0x8001 # Test product id
47
50
DEVICE_TYPE_CASTING_VIDEO_PLAYER = 0x23 # Device type library 10.3: Casting Video Player
48
51
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
+
49
56
50
57
class ProcessManager :
51
58
"""A context manager for managing subprocesses.
@@ -96,13 +103,19 @@ def extract_value_from_string(line: str) -> str:
96
103
97
104
The string is expected to be in the following format as it is received
98
105
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:
99
109
\x1b [0;34m[1713741926895] [7276:9521344] [DIS] Vendor ID: 65521\x1b [0m
100
110
The integer value to be extracted here is 65521.
101
111
Or:
102
112
\x1b [0;34m[1714583616179] [7029:2386956] [SVR] device Name: Test TV casting app\x1b [0m
103
113
The substring to be extracted here is 'Test TV casting app'.
104
114
"""
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' , '' )
106
119
107
120
return value
108
121
@@ -221,7 +234,7 @@ def validate_identification_declaration_message_on_tv_app(tv_app_info: Tuple[sub
221
234
linux_tv_app_log_file .flush ()
222
235
223
236
if 'Identification Declaration Start' in tv_app_line :
224
- logging .info ('" Identification Declaration" block from the Linux tv-app output:' )
237
+ logging .info ('Found the ` Identification Declaration` block in the Linux tv-app output:' )
225
238
logging .info (tv_app_line .rstrip ('\n ' ))
226
239
parsing_identification_block = True
227
240
elif parsing_identification_block :
@@ -310,6 +323,56 @@ def validate_commissioning_success(tv_casting_app_info: Tuple[subprocess.Popen,
310
323
return True
311
324
312
325
326
+ def parse_tv_casting_app_for_report_data_msg (tv_casting_app_info : Tuple [subprocess .Popen , TextIO ], log_paths : List [str ]):
327
+ """Parse the Linux tv-casting-app for `ReportDataMessage` block and return the first message block with valid `Cluster` and `Attribute` values."""
328
+ tv_casting_app_process , linux_tv_casting_app_log_file = tv_casting_app_info
329
+
330
+ continue_parsing = False
331
+ report_data_message = []
332
+
333
+ start_wait_time = time .time ()
334
+
335
+ while True :
336
+ # Check if we exceeded the maximum wait time to parse the Linux tv-casting-app output for `ReportDataMessage` block.
337
+ if time .time () - start_wait_time > VERIFY_SUBSCRIPTION_STATE_MAX_WAIT_SEC :
338
+ logging .error (
339
+ 'The relevant `ReportDataMessage` block was not found in the Linux tv-casting-app process within the timeout.' )
340
+ report_data_message .clear ()
341
+ return report_data_message
342
+
343
+ tv_casting_line = tv_casting_app_process .stdout .readline ()
344
+
345
+ if tv_casting_line :
346
+ linux_tv_casting_app_log_file .write (tv_casting_line )
347
+ linux_tv_casting_app_log_file .flush ()
348
+
349
+ if 'ReportDataMessage =' in tv_casting_line :
350
+ report_data_message .append (tv_casting_line .rstrip ('\n ' ))
351
+ continue_parsing = True
352
+ elif continue_parsing :
353
+ report_data_message .append (tv_casting_line .rstrip ('\n ' ))
354
+
355
+ if 'Cluster =' in tv_casting_line :
356
+ cluster_value = extract_value_from_string (tv_casting_line )
357
+ if cluster_value != CLUSTER_MEDIA_PLAYBACK :
358
+ report_data_message .clear ()
359
+ continue_parsing = False
360
+
361
+ elif 'Attribute =' in tv_casting_line :
362
+ attribute_value = extract_value_from_string (tv_casting_line )
363
+ if attribute_value != ATTRIBUTE_CURRENT_PLAYBACK_STATE :
364
+ report_data_message .clear ()
365
+ continue_parsing = False
366
+
367
+ elif 'InteractionModelRevision' in tv_casting_line :
368
+ # Capture the closing brace `}` of the `ReportDataMessage` block.
369
+ tv_casting_line = tv_casting_app_process .stdout .readline ()
370
+ linux_tv_casting_app_log_file .write (tv_casting_line )
371
+ linux_tv_casting_app_log_file .flush ()
372
+ report_data_message .append (tv_casting_line .rstrip ('\n ' ))
373
+ return report_data_message
374
+
375
+
313
376
def parse_tv_app_output_for_launchUrl_msg_success (tv_app_info : Tuple [subprocess .Popen , TextIO ], log_paths : List [str ]):
314
377
"""Parse the Linux tv-app output for the relevant string indicating that the launchUrl was received."""
315
378
@@ -359,7 +422,7 @@ def parse_tv_casting_app_output_for_launchUrl_msg_success(tv_casting_app_info: T
359
422
linux_tv_casting_app_log_file .flush ()
360
423
361
424
if 'InvokeResponseMessage =' in tv_casting_line :
362
- logging .info ('Found the InvokeResponseMessage block in the Linux tv-casting-app output:' )
425
+ logging .info ('Found the ` InvokeResponseMessage` block in the Linux tv-casting-app output:' )
363
426
logging .info (tv_casting_line .rstrip ('\n ' ))
364
427
continue_parsing_invoke_response_msg_block = True
365
428
@@ -415,7 +478,7 @@ def test_discovery_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], log_
415
478
416
479
# A valid commissioner has VENDOR_ID, PRODUCT_ID, and DEVICE TYPE in its list of entries.
417
480
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 :' )
481
+ logging .info ('Found a valid commissioner in the Linux tv-casting-app output :' )
419
482
logging .info (valid_discovered_commissioner )
420
483
logging .info (valid_vendor_id )
421
484
logging .info (valid_product_id )
@@ -445,6 +508,23 @@ def test_commissioning_fn(valid_discovered_commissioner_number, tv_casting_app_i
445
508
handle_casting_failure ('Commissioning' , log_paths )
446
509
447
510
511
+ def test_subscription_fn (tv_casting_app_info : Tuple [subprocess .Popen , TextIO ], log_paths : List [str ]):
512
+ """Test the subscription state of the Linux tv-casting-app by validating the `ReportDataMessage` block."""
513
+
514
+ valid_report_data_msg = parse_tv_casting_app_for_report_data_msg (tv_casting_app_info , log_paths )
515
+
516
+ if valid_report_data_msg :
517
+ logging .info ('Found the `ReportDataMessage` block in the Linux tv-casting-app output:' )
518
+
519
+ for line in valid_report_data_msg :
520
+ logging .info (line )
521
+
522
+ logging .info ('Testing subscription success!\n ' )
523
+ valid_report_data_msg .clear ()
524
+ else :
525
+ handle_casting_failure ('Testing subscription' , log_paths )
526
+
527
+
448
528
def test_launchUrl_fn (tv_casting_app_info : Tuple [subprocess .Popen , TextIO ], tv_app_info : Tuple [subprocess .Popen , TextIO ], log_paths : List [str ]):
449
529
"""Test that the Linux tv-casting-app sent the launchUrl and that the Linux tv-app received the launchUrl."""
450
530
@@ -454,7 +534,7 @@ def test_launchUrl_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], tv_a
454
534
if not parse_tv_casting_app_output_for_launchUrl_msg_success (tv_casting_app_info , log_paths ):
455
535
handle_casting_failure ('Testing launchUrl' , log_paths )
456
536
457
- logging .info ('Testing launchUrl success!\n ' )
537
+ logging .info ('Testing launchUrl success!' )
458
538
459
539
460
540
@click .command ()
@@ -504,7 +584,7 @@ def test_casting_fn(tv_app_rel_path, tv_casting_app_rel_path):
504
584
valid_discovered_commissioner_number = valid_discovered_commissioner .split ('#' )[- 1 ].replace ('\x1b [0m' , '' )
505
585
506
586
test_commissioning_fn (valid_discovered_commissioner_number , tv_casting_app_info , tv_app_info , log_paths )
507
-
587
+ test_subscription_fn ( tv_casting_app_info , log_paths )
508
588
test_launchUrl_fn (tv_casting_app_info , tv_app_info , log_paths )
509
589
510
590
0 commit comments