Skip to content

Commit 10fae47

Browse files
Addressed PR comments from @andy31415.
1 parent 18f2d5c commit 10fae47

File tree

1 file changed

+54
-25
lines changed

1 file changed

+54
-25
lines changed

scripts/tests/run_tv_casting_test.py

+54-25
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import logging
1818
import os
19+
import re
1920
import subprocess
2021
import sys
2122
import tempfile
@@ -75,6 +76,26 @@ def __exit__(self, exception_type, exception_value, traceback):
7576
self.process.wait()
7677

7778

79+
class LogValueExtractor:
80+
"""A utility class for extracting values from log lines.
81+
82+
This class provides a centralized way to extract values from log lines and manage the error handling and logging process.
83+
"""
84+
85+
def __init__(self, casting_state: str, log_paths: List[str]):
86+
self.casting_state = casting_state
87+
self.log_paths = log_paths
88+
89+
def extract_from(self, line: str, value_name: str):
90+
if value_name in line:
91+
try:
92+
return extract_value_from_string(line, value_name, self.casting_state, self.log_paths)
93+
except ValueError:
94+
logging.error(f'Failed to extract `{value_name}` value from line: {line}')
95+
handle_casting_failure(self.casting_state, self.log_paths)
96+
return None
97+
98+
7899
def dump_temporary_logs_to_console(log_file_path: str):
79100
"""Dump log file to the console; log file will be removed once the function exits."""
80101
"""Write the entire content of `log_file_path` to the console."""
@@ -115,25 +136,32 @@ def extract_value_from_string(line: str, value_name: str, casting_state: str, lo
115136
\x1b[0;34m[1714583616179] [7029:2386956] [SVR] device Name: Test TV casting app\x1b[0m
116137
The substring to be extracted here is 'Test TV casting app'.
117138
"""
118-
if ':' in line:
119-
if '=' in line:
139+
log_line_pattern = r'\x1b\[0;\d+m\[\d+\] \[\d+:\d+\] \[[A-Z]{1,3}\] (.+?)\x1b\[0m'
140+
log_line_match = re.search(log_line_pattern, line)
141+
142+
if log_line_match:
143+
log_text_of_interest = log_line_match.group(1)
144+
145+
if '=' in log_text_of_interest:
120146
delimiter = '='
121-
elif '#' in line:
147+
elif '#' in log_text_of_interest:
122148
delimiter = '#'
123149
else:
124150
delimiter = ':'
125151

126-
value = line.split(delimiter)[-1].strip().replace('\x1b[0m', '').rstrip(',')
152+
return log_text_of_interest.split(delimiter)[-1].strip(' ,')
127153
else:
128-
logging.error(f'Could not extract {value_name} from the following line: {line}')
129-
handle_casting_failure(casting_state, log_paths)
130-
131-
return value
154+
raise ValueError(f'Could not extract {value_name} from the following line: {line}')
132155

133156

134157
def validate_value(casting_state: str, expected_value: Union[str, int], log_paths: List[str], line: str, value_name: str) -> Optional[str]:
135158
"""Validate a value in a string against an expected value during a given casting state."""
136-
value = extract_value_from_string(line, value_name, casting_state, log_paths)
159+
log_value_extractor = LogValueExtractor(casting_state, log_paths)
160+
value = log_value_extractor.extract_from(line, value_name)
161+
if not value:
162+
logging.error(f'Failed to extract {value_name} value from the following line: {line}')
163+
logging.error(f'Failed to validate against the expected {value_name} value: {expected_value}!')
164+
handle_casting_failure(casting_state, log_paths)
137165

138166
if isinstance(expected_value, int):
139167
value = int(value)
@@ -203,6 +231,7 @@ def initiate_cast_request_success(tv_casting_app_info: Tuple[subprocess.Popen, T
203231
def extract_device_info_from_tv_casting_app(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], casting_state: str, log_paths: List[str]) -> Tuple[Optional[str], Optional[int], Optional[int]]:
204232
"""Extract device information from the 'Identification Declaration' block in the Linux tv-casting-app output."""
205233
tv_casting_app_process, linux_tv_casting_app_log_file = tv_casting_app_info
234+
log_value_extractor = LogValueExtractor(casting_state, log_paths)
206235

207236
device_name = None
208237
vendor_id = None
@@ -212,14 +241,12 @@ def extract_device_info_from_tv_casting_app(tv_casting_app_info: Tuple[subproces
212241
linux_tv_casting_app_log_file.write(line)
213242
linux_tv_casting_app_log_file.flush()
214243

215-
if 'device Name' in line:
216-
device_name = extract_value_from_string(line, 'device Name', casting_state, log_paths)
217-
elif 'vendor id' in line:
218-
vendor_id = extract_value_from_string(line, 'vendor id', casting_state, log_paths)
219-
vendor_id = int(vendor_id)
220-
elif 'product id' in line:
221-
product_id = extract_value_from_string(line, 'product id', casting_state, log_paths)
222-
product_id = int(product_id)
244+
if value := log_value_extractor.extract_from(line, 'device Name'):
245+
device_name = value
246+
elif value := log_value_extractor.extract_from(line, 'vendor id'):
247+
vendor_id = int(value)
248+
elif value := log_value_extractor.extract_from(line, 'product id'):
249+
product_id = int(value)
223250

224251
if device_name and vendor_id and product_id:
225252
break
@@ -340,6 +367,7 @@ def validate_commissioning_success(tv_casting_app_info: Tuple[subprocess.Popen,
340367
def parse_tv_casting_app_for_report_data_msg(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]):
341368
"""Parse the Linux tv-casting-app for `ReportDataMessage` block and return the first message block with valid `Cluster` and `Attribute` values."""
342369
tv_casting_app_process, linux_tv_casting_app_log_file = tv_casting_app_info
370+
log_value_extractor = LogValueExtractor('Testing subscription', log_paths)
343371

344372
continue_parsing = False
345373
report_data_message = []
@@ -366,15 +394,12 @@ def parse_tv_casting_app_for_report_data_msg(tv_casting_app_info: Tuple[subproce
366394
elif continue_parsing:
367395
report_data_message.append(tv_casting_line.rstrip('\n'))
368396

369-
if 'Cluster =' in tv_casting_line:
370-
cluster_value = extract_value_from_string(tv_casting_line, 'Cluster value', 'Testing subscription', log_paths)
397+
if cluster_value := log_value_extractor.extract_from(tv_casting_line, 'Cluster ='):
371398
if cluster_value != CLUSTER_MEDIA_PLAYBACK:
372399
report_data_message.clear()
373400
continue_parsing = False
374401

375-
elif 'Attribute =' in tv_casting_line:
376-
attribute_value = extract_value_from_string(
377-
tv_casting_line, 'Attribute value', 'Testing subscription', log_paths)
402+
elif attribute_value := log_value_extractor.extract_from(tv_casting_line, 'Attribute ='):
378403
if attribute_value != ATTRIBUTE_CURRENT_PLAYBACK_STATE:
379404
report_data_message.clear()
380405
continue_parsing = False
@@ -515,7 +540,7 @@ def test_commissioning_fn(valid_discovered_commissioner_number, tv_casting_app_i
515540
tv_casting_app_info, 'Commissioning', log_paths)
516541

517542
if not expected_device_name or not expected_vendor_id or not expected_product_id:
518-
logging.error('The is an error with the expected device info values that were extracted from the `Identification Declaration` block.')
543+
logging.error('There is an error with the expected device info values that were extracted from the `Identification Declaration` block.')
519544
logging.error(
520545
f'expected_device_name: {expected_device_name}, expected_vendor_id: {expected_vendor_id}, expected_product_id: {expected_product_id}')
521546
handle_casting_failure('Commissioning', log_paths)
@@ -601,8 +626,12 @@ def test_casting_fn(tv_app_rel_path, tv_casting_app_rel_path):
601626
handle_casting_failure('Discovery', log_paths)
602627

603628
# We need the valid discovered commissioner number to continue with commissioning.
604-
valid_discovered_commissioner_number = extract_value_from_string(
605-
valid_discovered_commissioner, 'Discovered Commissioner number', 'Commissioning', log_paths)
629+
log_value_extractor = LogValueExtractor('Commissioning', log_paths)
630+
valid_discovered_commissioner_number = log_value_extractor.extract_from(
631+
valid_discovered_commissioner, 'Discovered Commissioner #')
632+
if not valid_discovered_commissioner_number:
633+
logging.error(f'Failed to find `Discovered Commissioner #` in line: {valid_discovered_commissioner}')
634+
handle_casting_failure('Commissioning', log_paths)
606635

607636
test_commissioning_fn(valid_discovered_commissioner_number, tv_casting_app_info, tv_app_info, log_paths)
608637
test_subscription_fn(tv_casting_app_info, log_paths)

0 commit comments

Comments
 (0)