Skip to content

Commit ef1caa5

Browse files
[WebRTC] Align test scripts with test plan trickle ICE update (project-chip#41990)
* [WebRTC] Align with test plan trickle ICE update * Update src/controller/python/matter/webrtc/browser_peer_connection.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update src/controller/python/matter/webrtc/libdatachannel_peer_connection.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update src/controller/python/matter/webrtc/libdatachannel_peer_connection.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Address gemini review comments * Call set_remote_ice_candidates asyncrously * Fix docstring return type mismatch * Address gemini review comment --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent c50fcb2 commit ef1caa5

File tree

8 files changed

+56
-105
lines changed

8 files changed

+56
-105
lines changed

src/controller/python/matter/webrtc/browser_peer_connection.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ async def set_remote_ice_candidates(self, remote_candidates: list[IceCandidate])
120120
"""Sets the remote ICE candidates for the WebRTC peer connection.
121121
122122
Args:
123-
remote_candidates (list[str]): A list of remote ICE candidates to be set.
123+
remote_candidates (list[IceCandidate]): A list of remote ICE candidates to be set.
124124
"""
125125
# for candidate in remote_candidates:
126126
await self.set_remote_icecandidates(remote_candidates)
@@ -219,14 +219,14 @@ async def get_remote_answer(self, timeout_s: Optional[int] = None) -> tuple[int,
219219
return await self._remote_events[Events.ANSWER].get(timeout_s)
220220

221221
async def get_remote_ice_candidates(self, timeout_s: Optional[int] = None) -> tuple[int, list[IceCandidate]]:
222-
"""Waits for a remote SDP answer to be received through a matter command.
222+
"""Waits for a list of remote ICE Candidates to be received through a matter command.
223223
224224
Args:
225-
timeout_s (Optional[int]): The maximum time in seconds to wait for a remote offer.
225+
timeout_s (Optional[int]): The maximum time in seconds to wait for a list of remote candidates.
226226
If None, the function will wait indefinitely.
227227
228228
Returns:
229-
tuple[int, list[str]]: A tuple containing the session ID and list of ice candidate strings.
229+
tuple[int, list[IceCandidate]]: A tuple containing the session ID and list of IceCandidate objects.
230230
231231
Raises:
232232
asyncio.TimeoutError: If no remote offer is received within the specified timeout period.
@@ -324,5 +324,17 @@ def on_remote_answer(self, sessionId: int, answer_sdp: str) -> None:
324324
self._remote_events[Events.ANSWER].put((sessionId, answer_sdp))
325325

326326
def on_remote_ice_candidates(self, sessionId: int, candidates: list[IceCandidate]) -> None:
327-
"""Callback function called when a remote ICE candidates are received through a matter command."""
327+
"""Callback function called when a remote ICE candidates are received through a matter command.
328+
329+
Implements trickle ICE by scheduling candidates to be applied to the peer connection.
330+
Also stores them in the event queue for tests that may need to wait for and verify them.
331+
"""
332+
# Schedule candidates to be applied for trickle ICE support
333+
LOGGER.debug(f"Scheduling {len(candidates)} candidates for trickle ICE support: {candidates}")
334+
asyncio.run_coroutine_threadsafe(
335+
self.set_remote_ice_candidates(candidates),
336+
self.event_loop
337+
)
338+
339+
# Also put in event queue for any waiting consumers
328340
self._remote_events[Events.ICE_CANDIDATE].put((sessionId, candidates))

src/controller/python/matter/webrtc/libdatachannel_peer_connection.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def set_remote_ice_candidates(self, remote_candidates: list[IceCandidate]) -> No
118118
"""Sets the remote ICE candidates for the WebRTC peer connection.
119119
120120
Args:
121-
remote_candidates (list[str]): A list of remote ICE candidates to be set.
121+
remote_candidates (list[IceCandidate]): A list of remote ICE candidates to be set.
122122
"""
123123
for candidate in remote_candidates:
124124
self.add_ice_candidate(candidate.candidate, candidate.sdpMid or "video")
@@ -216,15 +216,15 @@ async def get_remote_answer(self, timeout_s: Optional[int] = None) -> tuple[int,
216216
LOGGER.debug("Waiting for remote answer")
217217
return await self._remote_events[Events.ANSWER].get(timeout_s)
218218

219-
async def get_remote_ice_candidates(self, timeout_s: Optional[int] = None) -> tuple[int, list[str]]:
220-
"""Waits for a remote SDP answer to be received through a matter command.
219+
async def get_remote_ice_candidates(self, timeout_s: Optional[int] = None) -> tuple[int, list[IceCandidate]]:
220+
"""Waits for a list of remote ICE Candidates to be received through a matter command.
221221
222222
Args:
223-
timeout_s (Optional[int]): The maximum time in seconds to wait for a remote offer.
223+
timeout_s (Optional[int]): The maximum time in seconds to wait for a list of remote candidates.
224224
If None, the function will wait indefinitely.
225225
226226
Returns:
227-
tuple[int, list[str]]: A tuple containing the session ID and list of ice candidate strings.
227+
tuple[int, list[IceCandidate]]: A tuple containing the session ID and list of ice candidate strings.
228228
229229
Raises:
230230
asyncio.TimeoutError: If no remote offer is received within the specified timeout period.
@@ -331,8 +331,17 @@ def on_remote_answer(self, sessionId: int, answer_sdp: str) -> None:
331331
"""Callback function called when a remote SDP answer is received through a matter command."""
332332
self._remote_events[Events.ANSWER].put((sessionId, answer_sdp))
333333

334-
def on_remote_ice_candidates(self, sessionId: int, candidates: list[str]) -> None:
335-
"""Callback function called when a remote ICE candidates are received through a matter command."""
334+
def on_remote_ice_candidates(self, sessionId: int, candidates: list[IceCandidate]) -> None:
335+
"""Callback function called when a remote ICE candidates are received through a matter command.
336+
337+
Implements trickle ICE by immediately applying received candidates to the peer connection.
338+
Also stores them in the event queue for tests that may need to wait for and verify them.
339+
"""
340+
# Immediately apply candidates for trickle ICE support
341+
LOGGER.debug(f"Applying {len(candidates)} candidates for trickle ICE support: {candidates}")
342+
self.set_remote_ice_candidates(candidates)
343+
344+
# Also put in event queue for any waiting consumers
336345
self._remote_events[Events.ICE_CANDIDATE].put((sessionId, candidates))
337346

338347
def on_remote_end(self, sessionId: int, reason: int) -> None:

src/python_testing/TC_WEBRTC_1_1.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,14 @@ def steps_TC_WEBRTC_1_1(self) -> list[TestStep]:
6666
TestStep(3, description="TH sends the SUCCESS status code to the DUT."),
6767
TestStep(
6868
4,
69-
description="TH sends the ProvideICECandidates command with a its ICE candidates to the DUT.",
69+
description="TH sends the ProvideICECandidates command with its ICE candidates to the DUT.",
7070
expectation="DUT responds with SUCCESS status code.",
7171
),
7272
TestStep(
73-
5,
74-
description="DUT sends ICECandidates command to the TH/WEBRTCR.",
75-
expectation="Verify that ICECandidates command contains the same WebRTCSessionID saved in step 1 and contain a non-empty ICE candidates.",
73+
5, description="TH waits for 10 seconds.", expectation="Verify the WebRTC session has been successfully established."
7674
),
7775
TestStep(
78-
6, description="TH waits for 5 seconds", expectation="Verify the WebRTC session has been successfully established."
79-
),
80-
TestStep(
81-
7,
76+
6,
8277
description="TH sends the EndSession command with the WebRTCSessionID saved in step 1 to the DUT.",
8378
expectation="DUT responds with SUCCESS status code.",
8479
),
@@ -162,21 +157,14 @@ async def test_TC_WEBRTC_1_1(self):
162157
)
163158

164159
self.step(5)
165-
ice_session_id, remote_candidates = await webrtc_peer.get_remote_ice_candidates()
166-
asserts.assert_equal(session_id, ice_session_id, "ProvideIceCandidates invoked with wrong session id")
167-
asserts.assert_true(len(remote_candidates) > 0, "Invalid remote ice candidates received")
168-
169-
webrtc_peer.set_remote_ice_candidates(remote_candidates)
170-
171-
self.step(6)
172160
if not await webrtc_peer.check_for_session_establishment():
173161
logging.error("Failed to establish webrtc session")
174162
raise Exception("Failed to establish webrtc session")
175163

176164
if not self.is_pics_sdk_ci_only and aVideoStreamID != NullValue:
177165
self.user_verify_video_stream("Verify WebRTC session by validating if video is received")
178166

179-
self.step(7)
167+
self.step(6)
180168
await self.send_single_cmd(
181169
cmd=WebRTCTransportProvider.Commands.EndSession(
182170
webRTCSessionID=session_id, reason=Objects.Globals.Enums.WebRTCEndReasonEnum.kUserHangup

src/python_testing/TC_WEBRTC_1_2.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,16 @@ def steps_TC_WEBRTC_1_2(self) -> list[TestStep]:
7171
TestStep(4, "TH sends the SUCCESS status code to the DUT."),
7272
TestStep(
7373
5,
74-
description="TH sends the ProvideICECandidates command with a its ICE candidates to the DUT.",
74+
description="TH sends the ProvideICECandidates command with its ICE candidates to the DUT.",
7575
expectation="DUT responds with SUCCESS status code.",
7676
),
7777
TestStep(
7878
6,
79-
description="TH waits up to 30 seconds for ICECandidates command from the DUT.",
80-
expectation="Verify that ICECandidates command contains the same WebRTCSessionID saved in step 1 and contain a non-empty ICE candidates.",
81-
),
82-
TestStep(
83-
7,
8479
description="TH waits for 10 seconds.",
8580
expectation="Verify the WebRTC session has been successfully established.",
8681
),
8782
TestStep(
88-
8,
83+
7,
8984
description="TH sends the EndSession command with the WebRTCSessionID saved in step 1 to the DUT.",
9085
expectation="DUT responds with SUCCESS status code.",
9186
),
@@ -169,20 +164,14 @@ async def test_TC_WEBRTC_1_2(self):
169164
)
170165

171166
self.step(6)
172-
ice_session_id, remote_candidates = await webrtc_peer.get_remote_ice_candidates()
173-
asserts.assert_equal(prev_sessionid, ice_session_id, "ProvideIceCandidates invoked with wrong session id")
174-
asserts.assert_true(len(remote_candidates) > 0, "Invalid remote ice candidates received")
175-
webrtc_peer.set_remote_ice_candidates(remote_candidates)
176-
177-
self.step(7)
178-
if not webrtc_peer.is_session_connected():
167+
if not await webrtc_peer.check_for_session_establishment():
179168
logging.error("Failed to establish webrtc session")
180169
raise Exception("Failed to establish webrtc session")
181170

182171
if not self.is_pics_sdk_ci_only:
183172
self.user_verify_video_stream("Verify WebRTC session by validating if video is received")
184173

185-
self.step(8)
174+
self.step(7)
186175
await self.send_single_cmd(
187176
cmd=WebRTCTransportProvider.Commands.EndSession(
188177
webRTCSessionID=prev_sessionid, reason=Objects.Globals.Enums.WebRTCEndReasonEnum.kUserHangup
@@ -226,9 +215,6 @@ async def establish_webrtc_session(webrtc_manager, webrtc_peer, endpoint, ctrl,
226215
payloadCapability=TransportPayloadCapability.LARGE_PAYLOAD,
227216
)
228217

229-
ice_session_id, remote_candidates = await webrtc_peer.get_remote_ice_candidates()
230-
webrtc_peer.set_remote_ice_candidates(remote_candidates)
231-
232218
return await webrtc_peer.check_for_session_establishment()
233219

234220

src/python_testing/TC_WEBRTC_1_3.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,11 @@ def steps_TC_WEBRTC_1_3(self) -> list[TestStep]:
7373
),
7474
TestStep(
7575
5,
76-
description="TH waits up to 30 seconds for ICECandidates command from the DUT.",
77-
expectation="Verify that ICECandidates command contains the same WebRTCSessionID saved in step 1 and contain a non-empty ICE candidates.",
78-
),
79-
TestStep(
80-
6,
8176
description="TH waits for 10 seconds.",
8277
expectation="Verify the WebRTC session has been successfully established.",
8378
),
8479
TestStep(
85-
7,
80+
6,
8681
description="TH sends the EndSession command with the WebRTCSessionID saved in step 1 to the DUT.",
8782
expectation="DUT responds with SUCCESS status code.",
8883
),
@@ -152,20 +147,14 @@ async def test_TC_WEBRTC_1_3(self):
152147
)
153148

154149
self.step(5)
155-
ice_session_id, remote_candidates = await webrtc_peer.get_remote_ice_candidates(timeout_s=30)
156-
asserts.assert_equal(ice_session_id, session_id, "Invalid session id")
157-
asserts.assert_true(len(remote_candidates) > 0, "Invalid ice candidates received")
158-
webrtc_peer.set_remote_ice_candidates(remote_candidates)
159-
160-
self.step(6)
161150
if not await webrtc_peer.check_for_session_establishment():
162151
logging.error("Failed to establish webrtc session")
163152
raise Exception("Failed to establish webrtc session")
164153

165154
if not self.is_pics_sdk_ci_only:
166155
self.user_verify_video_stream("Verify WebRTC session by validating if video is received")
167156

168-
self.step(7)
157+
self.step(6)
169158
await self.send_single_cmd(
170159
cmd=WebRTCTransportProvider.Commands.EndSession(
171160
webRTCSessionID=session_id, reason=Objects.Globals.Enums.WebRTCEndReasonEnum.kUserHangup

src/python_testing/TC_WEBRTC_1_4.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,11 @@ def steps_TC_WEBRTC_1_4(self) -> list[TestStep]:
7575
),
7676
TestStep(
7777
6,
78-
description="TH waits up to 30 seconds for ICECandidates command from the DUT.",
79-
expectation="Verify that ICECandidates command contains the same WebRTCSessionID saved in step 1 and contain a non-empty ICE candidates.",
80-
),
81-
TestStep(
82-
7,
8378
description="TH waits for 10 seconds.",
8479
expectation="Verify the WebRTC session has been successfully established.",
8580
),
8681
TestStep(
87-
8,
82+
7,
8883
description="TH sends the EndSession command with the WebRTCSessionID saved in step 1 to the DUT.",
8984
expectation="DUT responds with SUCCESS status code.",
9085
),
@@ -169,20 +164,14 @@ async def test_TC_WEBRTC_1_4(self):
169164
)
170165

171166
self.step(6)
172-
ice_session_id, remote_candidates = await webrtc_peer.get_remote_ice_candidates(timeout_s=30)
173-
asserts.assert_equal(ice_session_id, session_id, "Invalid session id")
174-
asserts.assert_true(len(remote_candidates) > 0, "Invalid ice candidates received")
175-
webrtc_peer.set_remote_ice_candidates(remote_candidates)
176-
177-
self.step(7)
178167
if not await webrtc_peer.check_for_session_establishment():
179168
logging.error("Failed to establish webrtc session")
180169
raise Exception("Failed to establish webrtc session")
181170

182171
if not self.is_pics_sdk_ci_only:
183172
self.user_verify_video_stream("Verify WebRTC session by validating if video is received")
184173

185-
self.step(8)
174+
self.step(7)
186175
await self.send_single_cmd(
187176
cmd=WebRTCTransportProvider.Commands.EndSession(
188177
webRTCSessionID=session_id, reason=Objects.Globals.Enums.WebRTCEndReasonEnum.kUserHangup

src/python_testing/TC_WEBRTC_1_5.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,10 @@ def steps_TC_WEBRTC_1_5(self) -> list[TestStep]:
6868
expectation="DUT responds with SUCCESS status code.",
6969
),
7070
TestStep(
71-
5,
72-
description="DUT sends ProvideICECandidates command to the TH",
73-
expectation="Verify that ProvideICECandidates command contains the same WebRTCSessionID saved in step 1 and contain a non-empty ICE candidates.",
71+
5, description="TH waits for 10 seconds", expectation="Verify the WebRTC session has been successfully established."
7472
),
7573
TestStep(
76-
6, description="TH waits for 5 seconds", expectation="Verify the WebRTC session has been successfully established."
77-
),
78-
TestStep(
79-
7,
74+
6,
8075
description="TH sends the End command with the WebRTCSessionID saved in step 1 to the DUT.",
8176
expectation="DUT responds with SUCCESS status code.",
8277
),
@@ -141,20 +136,14 @@ async def test_TC_WEBRTC_1_5(self):
141136
)
142137

143138
self.step(5)
144-
ice_session_id, remote_candidates = await webrtc_peer.get_remote_ice_candidates(timeout=30)
145-
asserts.assert_equal(ice_session_id, session_id, "Invalid session id")
146-
asserts.assert_true(len(remote_candidates) > 0, "Invalid ice candidates received")
147-
webrtc_peer.set_remote_ice_candidates(remote_candidates)
148-
149-
self.step(6)
150139
if not await webrtc_peer.check_for_session_establishment():
151140
logging.error("Failed to establish webrtc session")
152141
raise Exception("Failed to establish webrtc session")
153142

154143
if not self.is_pics_sdk_ci_only:
155144
self.user_verify_video_stream("Verify WebRTC session by validating if video is received")
156145

157-
self.step(7)
146+
self.step(6)
158147
await self.send_single_cmd(
159148
cmd=WebRTCTransportRequestor.Commands.End(
160149
webRTCSessionID=session_id, reason=Objects.Globals.Enums.WebRTCEndReasonEnum.kUserHangup

0 commit comments

Comments
 (0)