Skip to content

Commit ad60c95

Browse files
yufengwangcaCopilotrestyled-commits
authored
[WEBRTCR] Send command to DUT via websocket in CI (#41486)
* [WEBRTCR] Send command to DUT via websocket in CI * Update src/python_testing/TC_WEBRTCR_2_2.py Co-authored-by: Copilot <[email protected]> * Update src/python_testing/TC_WEBRTCR_2_6.py Co-authored-by: Copilot <[email protected]> * Update src/python_testing/TC_WEBRTCR_2_7.py Co-authored-by: Copilot <[email protected]> * Restyled by autopep8 * Restyled by isort * Address review comments --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Restyled.io <[email protected]>
1 parent d77d989 commit ad60c95

File tree

9 files changed

+174
-59
lines changed

9 files changed

+174
-59
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#
2+
# Copyright (c) 2025 Project CHIP Authors
3+
# All rights reserved.
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+
18+
import logging
19+
20+
import websockets
21+
22+
from matter.testing.matter_testing import MatterBaseTest
23+
24+
# WebSocket server URI for sending commands to the DUT
25+
SERVER_URI = "ws://localhost:9002"
26+
27+
28+
class WEBRTCRTestBase(MatterBaseTest):
29+
"""
30+
Base class for WebRTC Transport Requestor test cases.
31+
32+
Provides common functionality including:
33+
- WebSocket-based command sending to the DUT
34+
- Shared SERVER_URI constant
35+
"""
36+
37+
async def send_command(self, command):
38+
"""
39+
Send a command to the DUT via WebSocket and wait for response.
40+
41+
Args:
42+
command: The command string to send to the DUT
43+
44+
This method:
45+
1. Connects to the WebSocket server at SERVER_URI
46+
2. Sends the command
47+
3. Waits for and receives the response
48+
4. Logs the connection, command, and response status
49+
50+
Raises:
51+
Exception: Re-raises any exceptions after logging them clearly
52+
"""
53+
try:
54+
async with websockets.connect(SERVER_URI) as websocket:
55+
logging.info(f"Connected to {SERVER_URI}")
56+
57+
# Send command
58+
logging.info(f"Sending command: {command}")
59+
await websocket.send(command)
60+
61+
# Receive response
62+
await websocket.recv()
63+
logging.info("Received command response")
64+
65+
except ConnectionRefusedError as e:
66+
logging.error(f"Failed to connect to WebSocket server at {SERVER_URI}: Connection refused. "
67+
f"Is the DUT WebSocket server running? Error: {e}")
68+
raise
69+
70+
except websockets.exceptions.WebSocketException as e:
71+
logging.error(f"WebSocket error while communicating with {SERVER_URI}: {e}")
72+
raise
73+
74+
except OSError as e:
75+
logging.error(f"Network error while connecting to {SERVER_URI}: {e}")
76+
raise
77+
78+
except Exception as e:
79+
logging.error(f"Unexpected error while sending command '{command}' to {SERVER_URI}: {e}")
80+
raise

src/python_testing/TC_WEBRTCR_2_1.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
# === BEGIN CI TEST ARGUMENTS ===
2222
# test-runner-runs:
2323
# run1:
24+
# app: ${CAMERA_CONTROLLER_APP}
25+
# app-args: interactive server
2426
# script-args: >
2527
# --PICS src/app/tests/suites/certification/ci-pics-values
2628
# --storage-path admin_storage.json
@@ -38,14 +40,15 @@
3840
from time import sleep
3941

4042
from mobly import asserts
43+
from TC_WEBRTCRTestBase import WEBRTCRTestBase
4144

4245
import matter.clusters as Clusters
4346
from matter import ChipDeviceCtrl
4447
from matter.testing.apps import AppServerSubprocess
45-
from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
48+
from matter.testing.matter_testing import TestStep, async_test_body, default_matter_test_main
4649

4750

48-
class TC_WebRTCR_2_1(MatterBaseTest):
51+
class TC_WebRTCR_2_1(WEBRTCRTestBase):
4952
def setup_class(self):
5053
super().setup_class()
5154

@@ -151,7 +154,7 @@ async def test_TC_WebRTCR_2_1(self):
151154
)
152155

153156
if self.is_pics_sdk_ci_only:
154-
# TODO: send command to DUT via websocket
157+
await self.send_command(f"pairing onnetwork 1 {passcode}")
155158
resp = 'Y'
156159
else:
157160
resp = self.wait_for_user_input(prompt_msg)
@@ -200,8 +203,17 @@ async def test_TC_WebRTCR_2_1(self):
200203
)
201204

202205
if self.is_pics_sdk_ci_only:
203-
# TODO: send command to DUT via websocket
204-
resp = 'Y'
206+
self.th_server.set_output_match("NOT_FOUND")
207+
self.th_server.event.clear()
208+
209+
try:
210+
await self.send_command("webrtc establish-session 1 --offer-type 1")
211+
# Wait up to 90s until the provider logs that the data‑channel opened
212+
if not self.th_server.event.wait(90):
213+
raise TimeoutError("PeerConnection is not connected within 90s")
214+
resp = 'Y'
215+
except TimeoutError:
216+
resp = 'N'
205217
else:
206218
resp = self.wait_for_user_input(prompt_msg)
207219

src/python_testing/TC_WEBRTCR_2_2.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
# === BEGIN CI TEST ARGUMENTS ===
2222
# test-runner-runs:
2323
# run1:
24+
# app: ${CAMERA_CONTROLLER_APP}
25+
# app-args: interactive server
2426
# script-args: >
2527
# --PICS src/app/tests/suites/certification/ci-pics-values
2628
# --storage-path admin_storage.json
@@ -38,14 +40,15 @@
3840
from time import sleep
3941

4042
from mobly import asserts
43+
from TC_WEBRTCRTestBase import WEBRTCRTestBase
4144

4245
import matter.clusters as Clusters
4346
from matter import ChipDeviceCtrl
4447
from matter.testing.apps import AppServerSubprocess
45-
from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
48+
from matter.testing.matter_testing import TestStep, async_test_body, default_matter_test_main
4649

4750

48-
class TC_WebRTCR_2_2(MatterBaseTest):
51+
class TC_WebRTCR_2_2(WEBRTCRTestBase):
4952
def setup_class(self):
5053
super().setup_class()
5154

@@ -151,7 +154,7 @@ async def test_TC_WebRTCR_2_2(self):
151154
)
152155

153156
if self.is_pics_sdk_ci_only:
154-
# TODO: send command to DUT via websocket
157+
await self.send_command(f"pairing onnetwork 1 {passcode}")
155158
resp = 'Y'
156159
else:
157160
resp = self.wait_for_user_input(prompt_msg)
@@ -200,8 +203,17 @@ async def test_TC_WebRTCR_2_2(self):
200203
)
201204

202205
if self.is_pics_sdk_ci_only:
203-
# TODO: send command to DUT via websocket
204-
resp = 'Y'
206+
self.th_server.set_output_match("NOT_FOUND")
207+
self.th_server.event.clear()
208+
209+
try:
210+
await self.send_command("webrtc establish-session 1")
211+
# Wait up to 90s until the provider logs that the data‑channel opened
212+
if not self.th_server.event.wait(90):
213+
raise TimeoutError("PeerConnection is not connected within 90s")
214+
resp = 'Y'
215+
except TimeoutError:
216+
resp = 'N'
205217
else:
206218
resp = self.wait_for_user_input(prompt_msg)
207219

src/python_testing/TC_WEBRTCR_2_3.py

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,14 @@
3838
import os
3939
import tempfile
4040

41-
import websockets
4241
from mobly import asserts
42+
from TC_WEBRTCRTestBase import WEBRTCRTestBase
4343

4444
from matter.testing.apps import AppServerSubprocess
45-
from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
45+
from matter.testing.matter_testing import TestStep, async_test_body, default_matter_test_main
4646

47-
SERVER_URI = "ws://localhost:9002"
4847

49-
50-
class TC_WebRTCR_2_3(MatterBaseTest):
48+
class TC_WebRTCR_2_3(WEBRTCRTestBase):
5149
def setup_class(self):
5250
super().setup_class()
5351

@@ -119,18 +117,6 @@ def pics_TC_WebRTCR_2_3(self) -> list[str]:
119117
def default_timeout(self) -> int:
120118
return 3 * 60
121119

122-
async def send_command(self, command):
123-
async with websockets.connect(SERVER_URI) as websocket:
124-
logging.info(f"Connected to {SERVER_URI}")
125-
126-
# Send command
127-
logging.info(f"Sending command: {command}")
128-
await websocket.send(command)
129-
130-
# Receive response
131-
await websocket.recv()
132-
logging.info("Received command response")
133-
134120
@async_test_body
135121
async def test_TC_WebRTCR_2_3(self):
136122
"""

src/python_testing/TC_WEBRTCR_2_4.py

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,14 @@
3838
import os
3939
import tempfile
4040

41-
import websockets
4241
from mobly import asserts
42+
from TC_WEBRTCRTestBase import WEBRTCRTestBase
4343

4444
from matter.testing.apps import AppServerSubprocess
45-
from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
45+
from matter.testing.matter_testing import TestStep, async_test_body, default_matter_test_main
4646

47-
SERVER_URI = "ws://localhost:9002"
4847

49-
50-
class TC_WebRTCR_2_4(MatterBaseTest):
48+
class TC_WebRTCR_2_4(WEBRTCRTestBase):
5149
def setup_class(self):
5250
super().setup_class()
5351

@@ -119,18 +117,6 @@ def pics_TC_WebRTCR_2_4(self) -> list[str]:
119117
def default_timeout(self) -> int:
120118
return 3 * 60
121119

122-
async def send_command(self, command):
123-
async with websockets.connect(SERVER_URI) as websocket:
124-
logging.info(f"Connected to {SERVER_URI}")
125-
126-
# Send command
127-
logging.info(f"Sending command: {command}")
128-
await websocket.send(command)
129-
130-
# Receive response
131-
await websocket.recv()
132-
logging.info("Received command response")
133-
134120
@async_test_body
135121
async def test_TC_WebRTCR_2_4(self):
136122
"""

src/python_testing/TC_WEBRTCR_2_5.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
# === BEGIN CI TEST ARGUMENTS ===
2222
# test-runner-runs:
2323
# run1:
24+
# app: ${CAMERA_CONTROLLER_APP}
25+
# app-args: interactive server
2426
# script-args: >
2527
# --PICS src/app/tests/suites/certification/ci-pics-values
2628
# --storage-path admin_storage.json
@@ -38,13 +40,14 @@
3840
from time import sleep
3941

4042
from mobly import asserts
43+
from TC_WEBRTCRTestBase import WEBRTCRTestBase
4144

4245
from matter import ChipDeviceCtrl
4346
from matter.testing.apps import AppServerSubprocess
44-
from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
47+
from matter.testing.matter_testing import TestStep, async_test_body, default_matter_test_main
4548

4649

47-
class TC_WebRTCR_2_5(MatterBaseTest):
50+
class TC_WebRTCR_2_5(WEBRTCRTestBase):
4851
def setup_class(self):
4952
super().setup_class()
5053

@@ -155,7 +158,7 @@ async def test_TC_WebRTCR_2_5(self):
155158
)
156159

157160
if self.is_pics_sdk_ci_only:
158-
# TODO: send command to DUT via websocket
161+
await self.send_command(f"pairing onnetwork 1 {passcode}")
159162
resp = 'Y'
160163
else:
161164
resp = self.wait_for_user_input(prompt_msg)
@@ -203,8 +206,17 @@ async def test_TC_WebRTCR_2_5(self):
203206
)
204207

205208
if self.is_pics_sdk_ci_only:
206-
# TODO: establish session via websocket
207-
resp = 'Y'
209+
self.th_server.set_output_match("PeerConnection State: Connected")
210+
self.th_server.event.clear()
211+
212+
try:
213+
await self.send_command("webrtc establish-session 1")
214+
# Wait up to 90s until the provider logs that the data‑channel opened
215+
if not self.th_server.event.wait(90):
216+
raise TimeoutError("PeerConnection is not connected within 90s")
217+
resp = 'Y'
218+
except TimeoutError:
219+
resp = 'N'
208220
else:
209221
resp = self.wait_for_user_input(prompt_msg)
210222

src/python_testing/TC_WEBRTCR_2_6.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
# === BEGIN CI TEST ARGUMENTS ===
2222
# test-runner-runs:
2323
# run1:
24+
# app: ${CAMERA_CONTROLLER_APP}
25+
# app-args: interactive server
2426
# script-args: >
2527
# --PICS src/app/tests/suites/certification/ci-pics-values
2628
# --storage-path admin_storage.json
@@ -38,14 +40,15 @@
3840
from time import sleep
3941

4042
from mobly import asserts
43+
from TC_WEBRTCRTestBase import WEBRTCRTestBase
4144

4245
import matter.clusters as Clusters
4346
from matter import ChipDeviceCtrl
4447
from matter.testing.apps import AppServerSubprocess
45-
from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main
48+
from matter.testing.matter_testing import TestStep, async_test_body, default_matter_test_main
4649

4750

48-
class TC_WebRTCR_2_6(MatterBaseTest):
51+
class TC_WebRTCR_2_6(WEBRTCRTestBase):
4952
def setup_class(self):
5053
super().setup_class()
5154

@@ -152,7 +155,7 @@ async def test_TC_WebRTCR_2_6(self):
152155
)
153156

154157
if self.is_pics_sdk_ci_only:
155-
# TODO: send command to DUT via websocket
158+
await self.send_command(f"pairing onnetwork 1 {passcode}")
156159
resp = 'Y'
157160
else:
158161
resp = self.wait_for_user_input(prompt_msg)
@@ -202,8 +205,17 @@ async def test_TC_WebRTCR_2_6(self):
202205
)
203206

204207
if self.is_pics_sdk_ci_only:
205-
# TODO: send command to DUT via websocket
206-
resp = 'Y'
208+
self.th_server.set_output_match("NOT_FOUND")
209+
self.th_server.event.clear()
210+
211+
try:
212+
await self.send_command("webrtc establish-session 1")
213+
# Wait up to 90s until the provider logs that the data‑channel opened
214+
if not self.th_server.event.wait(90):
215+
raise TimeoutError("PeerConnection is not connected within 90s")
216+
resp = 'Y'
217+
except TimeoutError:
218+
resp = 'N'
207219
else:
208220
resp = self.wait_for_user_input(prompt_msg)
209221

0 commit comments

Comments
 (0)