Skip to content

Commit c9b88fe

Browse files
committed
Make TestSubscriptionResumption an async test
The current test implementation starves the asyncio event loop by synchronously waiting for the threading.Condition. This prevents making the SubscriptionTransaction fully leveraging the async paradigm. It probably would be possible to mix asyncio.sleep() and threading, but instead embrace the async pradigm for this test.
1 parent 8e81418 commit c9b88fe

File tree

2 files changed

+18
-19
lines changed

2 files changed

+18
-19
lines changed

src/controller/python/test/test_scripts/base.py

+15-17
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,7 @@ def TestFabricScopedCommandDuringPase(self, nodeid: int):
13361336

13371337
return status == IM.Status.UnsupportedAccess
13381338

1339-
def TestSubscriptionResumption(self, nodeid: int, endpoint: int, remote_ip: str, ssh_port: int, remote_server_app: str):
1339+
async def TestSubscriptionResumption(self, nodeid: int, endpoint: int, remote_ip: str, ssh_port: int, remote_server_app: str):
13401340
'''
13411341
This test validates that the device can resume the subscriptions after restarting.
13421342
It is executed in Linux Cirque tests and the steps of this test are:
@@ -1345,42 +1345,40 @@ def TestSubscriptionResumption(self, nodeid: int, endpoint: int, remote_ip: str,
13451345
3. Validate that the controller can receive a report from the remote server app
13461346
'''
13471347
desiredPath = None
1348-
receivedUpdate = False
1349-
updateLock = threading.Lock()
1350-
updateCv = threading.Condition(updateLock)
1348+
updateEvent = asyncio.Event()
1349+
loop = asyncio.get_running_loop()
13511350

13521351
def OnValueReport(path: Attribute.TypedAttributePath, transaction: Attribute.SubscriptionTransaction) -> None:
1353-
nonlocal desiredPath, updateCv, updateLock, receivedUpdate
1352+
nonlocal desiredPath, updateEvent, receivedUpdate
13541353
if path.Path != desiredPath:
13551354
return
13561355

13571356
data = transaction.GetAttribute(path)
13581357
logger.info(
13591358
f"Received report from server: path: {path.Path}, value: {data}")
1360-
with updateLock:
1361-
receivedUpdate = True
1362-
updateCv.notify_all()
1359+
loop.call_soon_threadsafe(updateEvent.set)
13631360

13641361
try:
13651362
desiredPath = Clusters.Attribute.AttributePath(
13661363
EndpointId=0, ClusterId=0x28, AttributeId=5)
13671364
# BasicInformation Cluster, NodeLabel Attribute
1368-
subscription = self.devCtrl.ZCLSubscribeAttribute(
1369-
"BasicInformation", "NodeLabel", nodeid, endpoint, 1, 50, keepSubscriptions=True, autoResubscribe=False)
1365+
subscription = await self.devCtrl.ReadAttribute(nodeid, [(endpoint, Clusters.BasicInformation.Attributes.NodeLabel)], None, False, reportInterval=(1, 50),
1366+
keepSubscriptions=True, autoResubscribe=False)
13701367
subscription.SetAttributeUpdateCallback(OnValueReport)
13711368

1372-
self.logger.info("Restart remote deivce")
1369+
self.logger.info("Restart remote device")
13731370
restartRemoteThread = restartRemoteDevice(
13741371
remote_ip, ssh_port, "root", "admin", remote_server_app, "--thread --discriminator 3840")
13751372
restartRemoteThread.start()
13761373
# After device restarts, the attribute will be set dirty so the subscription can receive
13771374
# the update
1378-
with updateCv:
1379-
while receivedUpdate is False:
1380-
if not updateCv.wait(10.0):
1381-
self.logger.error(
1382-
"Failed to receive subscription resumption report")
1383-
break
1375+
receivedUpdate = False
1376+
try:
1377+
await asyncio.wait_for(updateEvent.wait(), 10)
1378+
receivedUpdate = True
1379+
except TimeoutError:
1380+
self.logger.error(
1381+
"Failed to receive subscription resumption report")
13841382

13851383
restartRemoteThread.join(10.0)
13861384

src/controller/python/test/test_scripts/subscription_resumption_test.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
# Commissioning test.
2121

22+
import asyncio
2223
import os
2324
import sys
2425
from optparse import OptionParser
@@ -115,8 +116,8 @@ def main():
115116
"Failed on on-network commissioing")
116117

117118
FailIfNot(
118-
test.TestSubscriptionResumption(options.nodeid, TEST_ENDPOINT_ID, options.deviceAddress,
119-
TEST_SSH_PORT, options.remoteServerApp), "Failed to resume subscription")
119+
asyncio.run(test.TestSubscriptionResumption(options.nodeid, TEST_ENDPOINT_ID, options.deviceAddress,
120+
TEST_SSH_PORT, options.remoteServerApp), "Failed to resume subscription"))
120121

121122
timeoutTicker.stop()
122123

0 commit comments

Comments
 (0)