Skip to content

Commit

Permalink
[icd] Add WaitForActive testing in Cirque
Browse files Browse the repository at this point in the history
  • Loading branch information
erjiaqing committed Jul 5, 2024
1 parent 0050994 commit b49d806
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 3 deletions.
10 changes: 10 additions & 0 deletions examples/lit-icd-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,26 @@
#include "AppMain.h"
#include <app-common/zap-generated/ids/Clusters.h>

#include "system/SystemClock.h"

using namespace chip;
using namespace chip::app;
using namespace chip::System::Clock::Literals;

void ApplicationInit() {}

void ApplicationShutdown() {}

void notifyIcdActive(System::Layer * layer, void *)
{
ICDNotifier::GetInstance().NotifyNetworkActivityNotification();
DeviceLayer::SystemLayer().StartTimer(10000_ms32, notifyIcdActive, nullptr);
}

int main(int argc, char * argv[])
{
VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0);
DeviceLayer::SystemLayer().StartTimer(10000_ms32, notifyIcdActive, nullptr);
ChipLinuxAppMainLoop();
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions examples/platform/linux/AppMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ class SampleTestEventTriggerHandler : public TestEventTriggerHandler
/// NOTE: If you copy this for NON-STANDARD CLUSTERS OR USAGES, please use the reserved range FFFF_FFFF_<VID_HEX>_xxxx for your
/// trigger codes. NOTE: Standard codes are <CLUSTER_ID_HEX>_xxxx_xxxx_xxxx.
static constexpr uint64_t kSampleTestEventTriggerAlwaysSuccess = static_cast<uint64_t>(0xFFFF'FFFF'FFF1'0000ull);
static constexpr uint64_t kLitIcdTestEventTrigger = static_cast<uint64_t>(0x0046'0000'0000'0000ull);

public:
CHIP_ERROR HandleEventTrigger(uint64_t eventTrigger) override
Expand Down
1 change: 1 addition & 0 deletions scripts/tests/cirque_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ CIRQUE_TESTS=(
"MobileDeviceTest"
"CommissioningTest"
"InteractionModelTest"
"IcdWaitForActiveTest"
"SplitCommissioningTest"
"CommissioningFailureTest"
"CommissioningFailureOnReportTest"
Expand Down
3 changes: 1 addition & 2 deletions src/controller/python/chip/ChipDeviceCtrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ def OnCheckInCallback(nodeid):
RegisterOnActiveCallback(scopedNodeId, OnCheckInCallback)

try:
async with asyncio.timeout(timeoutSeconds):
await future
asyncio.wait_for(future, timeout=timeoutSeconds)
finally:
UnregisterOnActiveCallback(scopedNodeId, OnCheckInCallback)

Expand Down
20 changes: 19 additions & 1 deletion src/controller/python/test/test_scripts/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def __init__(self, nodeid: int, paaTrustStorePath: str, testCommissioner: bool =
keypair: p256keypair.P256Keypair = None):
chip.native.Init()

self.chipStack = ChipStack('/tmp/repl_storage.json')
self.chipStack = ChipStack('/tmp/repl_storage.json', enableServerInteractions=True)
self.certificateAuthorityManager = chip.CertificateAuthority.CertificateAuthorityManager(chipStack=self.chipStack)
self.certificateAuthority = self.certificateAuthorityManager.NewCertificateAuthority()
self.fabricAdmin = self.certificateAuthority.NewFabricAdmin(vendorId=0xFFF1, fabricId=1)
Expand Down Expand Up @@ -1148,6 +1148,24 @@ def TestResolve(self, nodeid):
self.logger.exception("Failed to resolve. {}".format(ex))
return False

async def TestTriggerTestEventHandler(self, nodeid, enable_key, event_trigger):
self.logger.info("Test trigger test event handler for device = %08x", nodeid)
try:
await self.devCtrl.SendCommand(nodeid, 0, Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=enable_key, eventTrigger=event_trigger))
return True
except Exception as ex:
self.logger.exception("Failed to trigger test event handler {}".format(ex))
return False

async def TestWaitForActive(self, nodeid):
self.logger.info("Test wait for device = %08x", nodeid)
try:
await self.devCtrl.WaitForActive(nodeid)
return True
except Exception as ex:
self.logger.exception("Failed to wait for active. {}".format(ex))
return False

async def TestReadBasicAttributes(self, nodeid: int, endpoint: int):
attrs = Clusters.BasicInformation.Attributes
basic_cluster_attrs = {
Expand Down
161 changes: 161 additions & 0 deletions src/controller/python/test/test_scripts/icd_wait_for_device_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#!/usr/bin/env python3

#
# Copyright (c) 2021 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# Commissioning test.

import asyncio
import os
import sys
from optparse import OptionParser

from base import BaseTestHelper, FailIfNot, TestFail, TestTimeout, logger

TEST_DISCRIMINATOR = 3840
TEST_DISCOVERY_TYPE = 2

ENDPOINT_ID = 0
LIGHTING_ENDPOINT_ID = 1
GROUP_ID = 0


async def waitForActiveAndTriggerCheckIn(test, nodeid):
coro = test.TestWaitForActive(nodeid=nodeid)
await test.TestTriggerTestEventHandler(nodeid, bytes.fromhex("00112233445566778899aabbccddeeff"), 0x0046 << 48)
return await coro


def main():
optParser = OptionParser()
optParser.add_option(
"-t",
"--timeout",
action="store",
dest="testTimeout",
default=75,
type='int',
help="The program will return with timeout after specified seconds.",
metavar="<timeout-second>",
)
optParser.add_option(
"-a",
"--address",
action="store",
dest="deviceAddress",
default='',
type='str',
help="Address of the device",
metavar="<device-addr>",
)
optParser.add_option(
"--setup-payload",
action="store",
dest="setupPayload",
default='',
type='str',
help="Setup Payload (manual pairing code or QR code content)",
metavar="<setup-payload>"
)
optParser.add_option(
"--nodeid",
action="store",
dest="nodeid",
default=1,
type=int,
help="The Node ID issued to the device",
metavar="<nodeid>"
)
optParser.add_option(
"--discriminator",
action="store",
dest="discriminator",
default=TEST_DISCRIMINATOR,
type=int,
help="Discriminator of the device",
metavar="<nodeid>"
)
optParser.add_option(
"-p",
"--paa-trust-store-path",
action="store",
dest="paaTrustStorePath",
default='',
type='str',
help="Path that contains valid and trusted PAA Root Certificates.",
metavar="<paa-trust-store-path>"
)
optParser.add_option(
"--discovery-type",
action="store",
dest="discoveryType",
default=TEST_DISCOVERY_TYPE,
type=int,
help="Discovery type of commissioning. (0: networkOnly 1: networkOnlyWithoutPASEAutoRetry 2: All<Ble & Network>)",
metavar="<discovery-type>"
)
optParser.add_option("--test-step", action="store", dest="testStep", type="str",
help="the step of the test (can be 'commissioning' or 'wait-for-active')", metavar="<test-step>")

(options, remainingArgs) = optParser.parse_args(sys.argv[1:])

timeoutTicker = TestTimeout(options.testTimeout)
timeoutTicker.start()

test = BaseTestHelper(
nodeid=112233, paaTrustStorePath=options.paaTrustStorePath, testCommissioner=True)

logger.info("Testing discovery")
FailIfNot(test.TestDiscovery(discriminator=options.discriminator),
"Failed to discover any devices.")

devCtrl = test.devCtrl
devCtrl.EnableICDRegistration(devCtrl.GenerateICDRegistrationParameters())
if options.deviceAddress:
logger.info("Testing commissioning (IP)")
FailIfNot(test.TestCommissioning(ip=options.deviceAddress,
setuppin=20202021,
nodeid=options.nodeid),
"Failed to finish commissioning")
elif options.setupPayload:
logger.info("Testing commissioning (w/ Setup Payload)")
FailIfNot(test.TestCommissioningWithSetupPayload(setupPayload=options.setupPayload,
nodeid=options.nodeid,
discoveryType=options.discoveryType),
"Failed to finish commissioning")
else:
TestFail("Must provide device address or setup payload to commissioning the device")
logger.info("Commissioning completed")
logger.info("Testing wait for active")
FailIfNot(asyncio.run(waitForActiveAndTriggerCheckIn(test, nodeid=options.nodeid)), "Failed to test wait for active")
logger.info('Successfully handled wait-for-active')

timeoutTicker.stop()

logger.info("Test finished")

# TODO: Python device controller cannot be shutdown clean sometimes and will block on AsyncDNSResolverSockets shutdown.
# Call os._exit(0) to force close it.
os._exit(0)


if __name__ == "__main__":
try:
main()
except Exception as ex:
logger.exception(ex)
TestFail("Exception occurred when running tests.")
124 changes: 124 additions & 0 deletions src/test_driver/linux-cirque/IcdWaitForActiveTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/env python3
"""
Copyright (c) 2021 Project CHIP Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import logging
import os
import sys

from helper.CHIPTestBase import CHIPVirtualHome

logger = logging.getLogger('MobileDeviceTest')
logger.setLevel(logging.INFO)

sh = logging.StreamHandler()
sh.setFormatter(
logging.Formatter(
'%(asctime)s [%(name)s] %(levelname)s %(message)s'))
logger.addHandler(sh)

CHIP_PORT = 5540

CIRQUE_URL = "http://localhost:5000"
CHIP_REPO = os.path.join(os.path.abspath(
os.path.dirname(__file__)), "..", "..", "..")
TEST_EXTPANID = "fedcba9876543210"
TEST_DISCRIMINATOR = 3840
TEST_DISCRIMINATOR2 = 3584
TEST_DISCRIMINATOR3 = 1203
TEST_DISCRIMINATOR4 = 2145
TEST_DISCOVERY_TYPE = [0, 1, 2]
MATTER_DEVELOPMENT_PAA_ROOT_CERTS = "credentials/development/paa-root-certs"

DEVICE_CONFIG = {
'device0': {
'type': 'MobileDevice',
'base_image': '@default',
'capability': ['TrafficControl', 'Mount'],
'rcp_mode': True,
'docker_network': 'Ipv6',
'traffic_control': {'latencyMs': 100},
"mount_pairs": [[CHIP_REPO, CHIP_REPO]],
},
'device1': {
'type': 'CHIPEndDevice',
'base_image': '@default',
'capability': ['Thread', 'TrafficControl', 'Mount'],
'rcp_mode': True,
'docker_network': 'Ipv6',
'traffic_control': {'latencyMs': 100},
"mount_pairs": [[CHIP_REPO, CHIP_REPO]],
}
}


class TestCommissioner(CHIPVirtualHome):
def __init__(self, device_config):
super().__init__(CIRQUE_URL, device_config)
self.logger = logger

def setup(self):
self.initialize_home()

def test_routine(self):
self.run_controller_test()

def run_controller_test(self):
servers = [{
"ip": device['description']['ipv6_addr'],
"id": device['id']
} for device in self.non_ap_devices
if device['type'] == 'CHIPEndDevice']
req_ids = [device['id'] for device in self.non_ap_devices
if device['type'] == 'MobileDevice']

servers[0]['discriminator'] = TEST_DISCRIMINATOR
servers[0]['nodeid'] = 1

for server in servers:
self.execute_device_cmd(
server['id'],
("CHIPCirqueDaemon.py -- run gdb -return-child-result -q -ex \"set pagination off\" "
"-ex run -ex \"bt 25\" --args {} --thread --discriminator {}").format(
os.path.join(CHIP_REPO, "out/debug/lit_icd/lit-icd-app"), server['discriminator']))

self.reset_thread_devices([server['id'] for server in servers])

req_device_id = req_ids[0]

self.execute_device_cmd(req_device_id, "pip3 install {}".format(os.path.join(
CHIP_REPO, "out/debug/linux_x64_gcc/controller/python/chip_clusters-0.0-py3-none-any.whl")))
self.execute_device_cmd(req_device_id, "pip3 install {}".format(os.path.join(
CHIP_REPO, "out/debug/linux_x64_gcc/controller/python/chip_core-0.0-cp37-abi3-linux_x86_64.whl")))
self.execute_device_cmd(req_device_id, "pip3 install {}".format(os.path.join(
CHIP_REPO, "out/debug/linux_x64_gcc/controller/python/chip_repl-0.0-py3-none-any.whl")))

command = ("CHIPCirqueDaemon.py -- run gdb -return-child-result -q -ex run -ex bt --args python3 "
"{} -t 150 -a {} --paa-trust-store-path {} --discriminator {} --nodeid {}").format(
os.path.join(
CHIP_REPO, "src/controller/python/test/test_scripts/icd_wait_for_device_test.py"),
servers[0]['ip'],
os.path.join(CHIP_REPO, MATTER_DEVELOPMENT_PAA_ROOT_CERTS),
servers[0]['discriminator'],
servers[0]['nodeid'])
self.execute_device_cmd(req_device_id, command)

self.assertTrue(self.wait_for_device_output(req_device_id, "Commissioning completed", 10))
self.assertTrue(self.wait_for_device_output(req_device_id, "Successfully handled wait-for-active", 30))


if __name__ == "__main__":
sys.exit(TestCommissioner(DEVICE_CONFIG).run_test())

0 comments on commit b49d806

Please sign in to comment.