Skip to content

Commit c4374a6

Browse files
shaoltan-amazonaustina-csa
authored andcommitted
Simplify the implementation of run_tv_casting_test.py for easier addition of future test sequences that verifies that Linux tv-casting-app continues to work with Linux tv-app. (project-chip#33855)
* Simplify the implementation of `run_tv_casting_test.py` for easier addition of future test sequences that verifies that Linux tv-casting-app continues to work with Linux tv-app. * Addressed PR comments from @sharadb-amazon. * Addressed @sharadb-amazon PR comments. Also restructured the code to prevent circular import issues. * Run restyle. * Fixed typo.
1 parent 6438249 commit c4374a6

File tree

3 files changed

+462
-520
lines changed

3 files changed

+462
-520
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env -S python3 -B
2+
3+
# Copyright (c) 2024 Project CHIP Authors
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from enum import Enum
18+
from typing import List, Optional
19+
20+
"""
21+
This file defines the utility classes for creating and managing test sequences to validate the casting experience between
22+
the Linux tv-casting-app and the Linux tv-app. It includes an enumeration for the supported applications (App), a class to
23+
represent individual steps in a test sequence (Step), and a class to represent a complete test sequence (Sequence).
24+
Additionally, it provides helper functions to retrieve specific test sequences or all defined test sequences.
25+
"""
26+
27+
28+
class App(Enum):
29+
"""An enumeration of the supported applications."""
30+
31+
TV_APP = 'tv-app'
32+
TV_CASTING_APP = 'tv-casting-app'
33+
34+
35+
class Step:
36+
"""A class to represent a step in a test sequence for validation.
37+
38+
A `Step` object contains attributes relevant to a test step where each object contains:
39+
- `app` subprocess to parse for `output_msg` or send `input_cmd`
40+
- `timeout_sec` specified the timeout duration for parsing the `output_msg` (optional, defaults to DEFAULT_TIMEOUT_SEC)
41+
- `output_msg` or `input_cmd` (mutually exclusive)
42+
43+
For output message blocks, define the start line, relevant lines, and the last line. If the last line contains trivial closing
44+
characters (e.g., closing brackets, braces, or commas), include the line before it with actual content. For example:
45+
`Step(subprocess_='tv-casting-app', output_msg=['InvokeResponseMessage =', 'exampleData', 'InteractionModelRevision =', '},'])`
46+
47+
For input commands, define the command string with placeholders for variables that need to be updated. For example:
48+
`Step(subprocess_='tv-casting-app', input_cmd='cast request 0\n')`
49+
"""
50+
51+
# The maximum default time to wait while parsing for output string(s).
52+
DEFAULT_TIMEOUT_SEC = 10
53+
54+
def __init__(
55+
self,
56+
app: App,
57+
timeout_sec: Optional[int] = DEFAULT_TIMEOUT_SEC,
58+
output_msg: Optional[List[str]] = None,
59+
input_cmd: Optional[str] = None,
60+
):
61+
# Validate that either `output_msg` or `input_cmd` is provided, but not both.
62+
if output_msg is not None and input_cmd is not None:
63+
raise ValueError(
64+
'Step cannot contain both `output_msg` and `input_cmd`. Either `output_msg` or `input_cmd` should be provided.')
65+
elif output_msg is None and input_cmd is None:
66+
raise ValueError('Step must contain either `output_msg` or `input_cmd`. Both are `None`.')
67+
68+
# Define either `App.TV_APP` or `App.TV_CASTING_APP` on which we need to parse for `output_msg` or send `input_cmd`.
69+
self.app = app
70+
71+
# Define the maximum time in seconds for timeout while parsing for the `output_msg`. If not provided, then we use the DEFAULT_TIMEOUT_SEC.
72+
self.timeout_sec = timeout_sec
73+
74+
# Define the `output_msg` that we need to parse for in a list format.
75+
self.output_msg = output_msg
76+
77+
# Define the `input_cmd` that we need to send to either the `App.TV_APP` or `App.TV_CASTING_APP`.
78+
self.input_cmd = input_cmd
79+
80+
81+
class Sequence:
82+
"""A class representing a sequence of steps for testing the casting experience between the Linux tv-casting-app and the tv-app.
83+
84+
A Sequence object needs to be defined with an appropriate test sequence `name` along with its list of `Step` objects that will
85+
be used for validating the casting experience.
86+
"""
87+
88+
def __init__(self, name: str, steps: List[Step]):
89+
self.name = name
90+
self.steps = steps
91+
92+
@staticmethod
93+
def get_test_sequence_by_name(test_sequences: List['Sequence'], test_sequence_name: str) -> Optional['Sequence']:
94+
"""Retrieve a test sequence from a list of sequences by its name."""
95+
96+
for sequence in test_sequences:
97+
if sequence.name == test_sequence_name:
98+
return sequence
99+
return None
100+
101+
@staticmethod
102+
def get_test_sequences() -> List['Sequence']:
103+
"""Retrieve all the test sequences to validate the casting experience between the Linux tv-casting-app and the Linux tv-app."""
104+
105+
from linux.tv_casting_test_sequences import test_sequences
106+
107+
return test_sequences
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#!/usr/bin/env -S python3 -B
2+
3+
# Copyright (c) 2024 Project CHIP Authors
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from linux.tv_casting_test_sequence_utils import App, Sequence, Step
18+
19+
"""
20+
In this file, we define the test sequences with the relevant steps that will be used in the `scripts/tests/run_tv_casting_test.py`
21+
for validating the casting experience between the Linux tv-casting-app and the Linux tv-app.
22+
23+
At the beginning of each test sequence we need to indicate the start up of the tv-app using the `START_APP` string as the `input_cmd`
24+
followed by the same for the tv-casting-app. On the other hand, at the end of each test sequence we need to ensure that each app will
25+
be stopped by providing the `STOP_APP` string as the `input_cmd`. As noted in the example below of `example_test_sequence`, the first
26+
four steps pertain to starting the apps while the last two are for signaling stopping the apps.
27+
28+
Note: `START_APP` and `STOP_APP` are reserved for signaling the starting and stopping of apps.
29+
30+
Example:
31+
test_sequences = [
32+
Sequence(
33+
name='example_test_sequence',
34+
step=[
35+
# Signal to start the tv-app.
36+
Step(app=App.TV_APP, input_cmd=START_APP),
37+
38+
# Validate that the tv-app is up and running.
39+
Step(app=App.TV_APP, timeout_sec=APP_MAX_START_WAIT_SEC, output_msg=['Started commissioner']),
40+
41+
# Signal to start the tv-casting-app.
42+
Step(app=App.TV_CASTING_APP, input_cmd=START_APP),
43+
44+
# Validate that the server is properly initialized in the tv-casting-app output.
45+
Step(app=App.TV_CASTING_APP, timeout_sec=APP_MAX_START_WAIT_SEC, output_msg=['Server initialization complete']),
46+
47+
# Additional steps for testing the casting experience.
48+
49+
# Signal to stop the tv-casting-app as we finished validation.
50+
Step(app=App.TV_CASTING_APP, input_cmd=STOP_APP),
51+
52+
# Signal to stop the tv-app as we finished validation.
53+
Step(app=App.TV_APP, input_cmd=STOP_APP)
54+
]
55+
)
56+
]
57+
"""
58+
59+
# Signal to start the app.
60+
START_APP = 'START'
61+
62+
# Signal to stop the app.
63+
STOP_APP = 'STOP'
64+
65+
# The maximum amount of time to wait for the Linux tv-app or Linux tv-casting-app to start before timeout.
66+
APP_MAX_START_WAIT_SEC = 2
67+
68+
# Values that identify the Linux tv-app and are noted in the 'Device Configuration' in the Linux tv-app output
69+
# as well as under the 'Discovered Commissioner' details in the Linux tv-casting-app output.
70+
VENDOR_ID = 0xFFF1 # Spec 7.20.2.1 MEI code: test vendor IDs are 0xFFF1 to 0xFFF4
71+
PRODUCT_ID = 0x8001 # Test product id
72+
DEVICE_TYPE_CASTING_VIDEO_PLAYER = 0x23 # Device type library 10.3: Casting Video Player
73+
74+
TEST_TV_CASTING_APP_DEVICE_NAME = 'Test TV casting app' # Test device name for identifying the tv-casting-app
75+
76+
# Values to verify the subscription state against from the `ReportDataMessage` in the Linux tv-casting-app output.
77+
CLUSTER_MEDIA_PLAYBACK = '0x506' # Application Cluster Spec 6.10.3 Cluster ID: Media Playback
78+
ATTRIBUTE_CURRENT_PLAYBACK_STATE = '0x0000_0000' # Application Cluster Spec 6.10.6 Attribute ID: Current State of Playback
79+
80+
test_sequences = [
81+
Sequence(
82+
name='commissionee_generated_passcode_test',
83+
steps=[
84+
# Signal to start the tv-app.
85+
Step(app=App.TV_APP, input_cmd=START_APP),
86+
87+
# Validate that the tv-app is up and running.
88+
Step(app=App.TV_APP, timeout_sec=APP_MAX_START_WAIT_SEC, output_msg=['Started commissioner']),
89+
90+
# Signal to start the tv-casting-app.
91+
Step(app=App.TV_CASTING_APP, input_cmd=START_APP),
92+
93+
# Validate that the server is properly initialized in the tv-casting-app output.
94+
Step(app=App.TV_CASTING_APP, timeout_sec=APP_MAX_START_WAIT_SEC, output_msg=['Server initialization complete']),
95+
96+
# Validate that there is a valid discovered commissioner with {VENDOR_ID}, {PRODUCT_ID}, and {DEVICE_TYPE_CASTING_VIDEO_PLAYER} in the tv-casting-app output.
97+
Step(app=App.TV_CASTING_APP, output_msg=['Discovered Commissioner #0', f'Vendor ID: {VENDOR_ID}', f'Product ID: {PRODUCT_ID}',
98+
f'Device Type: {DEVICE_TYPE_CASTING_VIDEO_PLAYER}', 'Supports Commissioner Generated Passcode: true']),
99+
100+
# Validate that we are ready to send `cast request` command to the tv-casting-app subprocess.
101+
Step(app=App.TV_CASTING_APP, output_msg=['Example: cast request 0']),
102+
103+
# Send `cast request {valid_discovered_commissioner_number}\n` command to the tv-casting-app subprocess.
104+
Step(app=App.TV_CASTING_APP, input_cmd='cast request 0\n'),
105+
106+
# Validate that the `Identification Declaration` message block in the tv-casting-app output has the expected values for `device Name`, `vendor id`, and `product id`.
107+
Step(app=App.TV_CASTING_APP, output_msg=['Identification Declaration Start', f'device Name: {TEST_TV_CASTING_APP_DEVICE_NAME}',
108+
f'vendor id: {VENDOR_ID}', f'product id: {PRODUCT_ID}', 'Identification Declaration End']),
109+
110+
# Validate that the `Identification Declaration` message block in the tv-app output has the expected values for `device Name`, `vendor id`, and `product id`.
111+
Step(app=App.TV_APP, output_msg=['Identification Declaration Start', f'device Name: {TEST_TV_CASTING_APP_DEVICE_NAME}',
112+
f'vendor id: {VENDOR_ID}', f'product id: {PRODUCT_ID}', 'Identification Declaration End']),
113+
114+
# Validate that we received the cast request from the tv-casting-app on the tv-app output.
115+
Step(app=App.TV_APP,
116+
output_msg=['PROMPT USER: Test TV casting app is requesting permission to cast to this TV, approve?']),
117+
118+
# Validate that we received the instructions on the tv-app output for sending the `controller ux ok` command.
119+
Step(app=App.TV_APP, output_msg=['Via Shell Enter: controller ux ok|cancel']),
120+
121+
# Send `controller ux ok` command to the tv-app subprocess.
122+
Step(app=App.TV_APP, input_cmd='controller ux ok\n'),
123+
124+
# Validate that pairing succeeded between the tv-casting-app and the tv-app.
125+
Step(app=App.TV_APP, output_msg=['Secure Pairing Success']),
126+
127+
# Validate that commissioning succeeded in the tv-casting-app output.
128+
Step(app=App.TV_CASTING_APP, output_msg=['Commissioning completed successfully']),
129+
130+
# Validate that commissioning succeeded in the tv-app output.
131+
Step(app=App.TV_APP, output_msg=['------PROMPT USER: commissioning success']),
132+
133+
# Validate the subscription state by looking at the `Cluster` and `Attribute` values in the `ReportDataMessage` block in the tv-casting-app output.
134+
Step(app=App.TV_CASTING_APP, output_msg=[
135+
'ReportDataMessage =', f'Cluster = {CLUSTER_MEDIA_PLAYBACK}', f'Attribute = {ATTRIBUTE_CURRENT_PLAYBACK_STATE}', 'InteractionModelRevision =', '}']),
136+
137+
# Validate the LaunchURL in the tv-app output.
138+
Step(app=App.TV_APP,
139+
output_msg=['ContentLauncherManager::HandleLaunchUrl TEST CASE ContentURL=https://www.test.com/videoid DisplayString=Test video']),
140+
141+
# Validate the LaunchURL in the tv-casting-app output.
142+
Step(app=App.TV_CASTING_APP, output_msg=['InvokeResponseMessage =',
143+
'exampleData', 'InteractionModelRevision =', '},']),
144+
145+
# Signal to stop the tv-casting-app as we finished validation.
146+
Step(app=App.TV_CASTING_APP, input_cmd=STOP_APP),
147+
148+
# Signal to stop the tv-app as we finished validation.
149+
Step(app=App.TV_APP, input_cmd=STOP_APP)
150+
]
151+
)
152+
]

0 commit comments

Comments
 (0)