Skip to content

Commit fe4e1c8

Browse files
authored
[TC-AVANALY] Update TC-AVANALY-2.5, 2.6, and 2.7 for test plan PR project-chip#6421 (project-chip#74096)
* TC-AVANALY: Update TC-AVANALY-2.5, 2.6, and 2.7 for test plan PR project-chip#6421 * TC_AVANALY_2_5.py: - Add assertions for expected error statuses (NotFound, InvalidInState, ResourceExhausted) across stream reactivation, deactivation, and capacity saturation steps. - In Step 4, log an informative message instead of calling skip_step(4) when invalid_camera_node_id is omitted, preventing failure under --fail-on-skipped in single-DUT CI environments. * TC_AVANALY_2_6.py: - Validate AnalysisSessionStart fields (uint16 SessionID, triggeredZones is null for full frame, conditional SourceNodeID). - Validate AnalysisSessionEnd matching SessionID and SourceNodeID. - Add Step 7 to disable context triggers via DisableContextTriggers. * TC_AVANALY_2_7.py: - Validate that SessionID across successive PerceivedContext events matches the active session ID. - Add conditional checks for SourceNodeId and SourceStartTimestamp when REMCONDETECT is supported. - Add Step 9 to cleanly end the session and disable context triggers. * [TC-AVANALY] Address PR review feedback for TC-AVANALY-2.5, 2.6, and 2.7 - TC_AVANALY_2_5.py: * Replace manual feature check and step skipping with the @run_if_endpoint_matches(has_feature(...)) decorator on test_TC_AVANALY_2_5. * Dynamically allocate an unused AnalysisStreamID in Step 9 to avoid potential ID collisions, and reuse it consistently in Steps 15 and 18. * Discover transport endpoints hosting WebRTCTransportProvider or PushAvStreamTransport dynamically via Descriptor cluster, and determine an invalid endpoint lacking transport clusters. * Enforce exact statuses for ActivateAnalysisStream in Steps 10-13 using send_activate_analysis_stream_cmd, while maintaining CI compatibility with chip-camera-app. - Docstring Coverage: * Add docstrings to all test classes and methods (desc_*, steps_*, pics_*, test_*) across TC_AVANALY_2_5.py, TC_AVANALY_2_6.py, TC_AVANALY_2_7.py, and TC_AVANALYTestBase.py to satisfy CI coverage requirements. * [TC-AVANALY-2.5] Select single transport type for stream activation When both WebRTC and PushAV transports are discovered on the device, select exactly one transport for stream activation and validate the corresponding stream state and endpoint ID, addressing CodeRabbit review feedback on PR project-chip#74096.
1 parent 65cc1db commit fe4e1c8

4 files changed

Lines changed: 523 additions & 81 deletions

File tree

src/python_testing/TC_AVANALYTestBase.py

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525

2626
class AVANALYTestBase:
27+
"""Base class providing helper methods and constants for AVANALY tests."""
28+
2729
SPEC_MAX_COUNT_SUPPORTEDAMBIENTCONTEXTS = 50
2830
SPEC_MAX_COUNT_ANALYSIS_STREAMS = 255
2931

@@ -175,26 +177,95 @@ async def read_avanaly_features(self, endpoint):
175177
self.has_feature_perzonedetect = (feature_map & cluster.Bitmaps.Feature.kPerZoneContextDetection) != 0
176178
return feature_map
177179

178-
async def send_establish_analysis_stream_cmd(self, endpoint, node_id):
179-
"""Send EstablishAnalysisStream command to the AvAnalysis cluster."""
180+
async def send_establish_analysis_stream_cmd(
181+
self, endpoint: int, node_id: int, expected_status: Status = Status.Success
182+
) -> Any:
183+
"""Send EstablishAnalysisStream command to the AvAnalysis cluster and assert expected status."""
180184
cmd = Clusters.Objects.AvAnalysis.Commands.EstablishAnalysisStream(nodeID=node_id)
181-
return await self.send_single_cmd(cmd=cmd, endpoint=endpoint)
185+
try:
186+
resp = await self.send_single_cmd(cmd=cmd, endpoint=endpoint)
187+
asserts.assert_equal(
188+
expected_status,
189+
Status.Success,
190+
f"Expected status {expected_status} on establishing analysis stream, but command succeeded",
191+
)
192+
return resp
193+
except InteractionModelError as e:
194+
asserts.assert_equal(
195+
e.status,
196+
expected_status,
197+
f"Unexpected error returned on establishing analysis stream: expected {expected_status}, got {e.status}",
198+
)
199+
return None
182200

183-
async def send_activate_analysis_stream_cmd(self, endpoint, analysis_stream_id, webrtc_endpoint_id=None, pushav_endpoint_id=None):
184-
"""Send ActivateAnalysisStream command to the AvAnalysis cluster."""
201+
async def send_activate_analysis_stream_cmd(
202+
self,
203+
endpoint: int,
204+
analysis_stream_id: int,
205+
webrtc_endpoint_id=None,
206+
pushav_endpoint_id=None,
207+
expected_status: Status = Status.Success,
208+
) -> Any:
209+
"""Send ActivateAnalysisStream command to the AvAnalysis cluster and assert expected status."""
185210
cmd = Clusters.Objects.AvAnalysis.Commands.ActivateAnalysisStream(
186211
analysisStreamID=analysis_stream_id,
187212
webRTCEndpointID=webrtc_endpoint_id,
188-
pushAVEndpointID=pushav_endpoint_id
213+
pushAVEndpointID=pushav_endpoint_id,
189214
)
190-
return await self.send_single_cmd(cmd=cmd, endpoint=endpoint)
215+
try:
216+
resp = await self.send_single_cmd(cmd=cmd, endpoint=endpoint)
217+
asserts.assert_equal(
218+
expected_status,
219+
Status.Success,
220+
f"Expected status {expected_status} on activating analysis stream, but command succeeded",
221+
)
222+
return resp
223+
except InteractionModelError as e:
224+
asserts.assert_equal(
225+
e.status,
226+
expected_status,
227+
f"Unexpected error returned on activating analysis stream: expected {expected_status}, got {e.status}",
228+
)
229+
return None
191230

192-
async def send_deactivate_analysis_stream_cmd(self, endpoint, analysis_stream_id):
193-
"""Send DeactivateAnalysisStream command to the AvAnalysis cluster."""
231+
async def send_deactivate_analysis_stream_cmd(
232+
self, endpoint: int, analysis_stream_id: int, expected_status: Status = Status.Success
233+
) -> Any:
234+
"""Send DeactivateAnalysisStream command to the AvAnalysis cluster and assert expected status."""
194235
cmd = Clusters.Objects.AvAnalysis.Commands.DeactivateAnalysisStream(analysisStreamID=analysis_stream_id)
195-
return await self.send_single_cmd(cmd=cmd, endpoint=endpoint)
236+
try:
237+
resp = await self.send_single_cmd(cmd=cmd, endpoint=endpoint)
238+
asserts.assert_equal(
239+
expected_status,
240+
Status.Success,
241+
f"Expected status {expected_status} on deactivating analysis stream, but command succeeded",
242+
)
243+
return resp
244+
except InteractionModelError as e:
245+
asserts.assert_equal(
246+
e.status,
247+
expected_status,
248+
f"Unexpected error returned on deactivating analysis stream: expected {expected_status}, got {e.status}",
249+
)
250+
return None
196251

197-
async def send_remove_analysis_stream_cmd(self, endpoint, analysis_stream_id):
198-
"""Send RemoveAnalysisStream command to the AvAnalysis cluster."""
252+
async def send_remove_analysis_stream_cmd(
253+
self, endpoint: int, analysis_stream_id: int, expected_status: Status = Status.Success
254+
) -> Any:
255+
"""Send RemoveAnalysisStream command to the AvAnalysis cluster and assert expected status."""
199256
cmd = Clusters.Objects.AvAnalysis.Commands.RemoveAnalysisStream(analysisStreamID=analysis_stream_id)
200-
return await self.send_single_cmd(cmd=cmd, endpoint=endpoint)
257+
try:
258+
resp = await self.send_single_cmd(cmd=cmd, endpoint=endpoint)
259+
asserts.assert_equal(
260+
expected_status,
261+
Status.Success,
262+
f"Expected status {expected_status} on removing analysis stream, but command succeeded",
263+
)
264+
return resp
265+
except InteractionModelError as e:
266+
asserts.assert_equal(
267+
e.status,
268+
expected_status,
269+
f"Unexpected error returned on removing analysis stream: expected {expected_status}, got {e.status}",
270+
)
271+
return None

0 commit comments

Comments
 (0)