Skip to content

Commit 49b07aa

Browse files
committed
TC-IDM-XX: try both PASE and CASE for basic comp tests.
These tests are disruptive at cert because they could run over PASE or CASE and defaulted to PASE. This meant that they couldn't be run in sequence with other tests that require commissioning. Because the PASE setup required a qr or manual code, it also meant that these needed special parameters to run. Now: - can use discriminator and passcode for PASE connection - device tries both PASE and CASE and runs over whichever works first.
1 parent b367512 commit 49b07aa

5 files changed

+115
-19
lines changed

src/controller/python/ChipDeviceController-Discovery.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@
2323
*
2424
*/
2525

26+
#include <string>
27+
2628
#include <controller/CHIPDeviceController.h>
2729
#include <controller/python/chip/native/PyChipError.h>
2830
#include <json/json.h>
2931
#include <lib/core/CHIPError.h>
3032
#include <lib/core/TLV.h>
3133
#include <lib/dnssd/Resolver.h>
34+
#include <setup_payload/SetupPayload.h>
35+
#include <setup_payload/ManualSetupPayloadGenerator.h>
3236

3337
using namespace chip;
3438

@@ -186,4 +190,21 @@ bool pychip_DeviceController_GetIPForDiscoveredDevice(Controller::DeviceCommissi
186190
}
187191
return false;
188192
}
193+
194+
PyChipError pychip_CreateManualCode(uint16_t longDiscriminator, uint32_t passcode, char* manualCodeBuffer, size_t bufsize){
195+
SetupPayload payload;
196+
SetupDiscriminator discriminator;
197+
discriminator.SetLongValue(longDiscriminator);
198+
payload.discriminator = discriminator;
199+
payload.setUpPINCode = passcode;
200+
std::string setupManualCode;
201+
202+
CHIP_ERROR err = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(setupManualCode);
203+
if (err == CHIP_NO_ERROR) {
204+
MutableCharSpan span(manualCodeBuffer, bufsize);
205+
CopyCharSpanToMutableCharSpan(CharSpan(setupManualCode.c_str(), setupManualCode.length()), span);
206+
}
207+
208+
return ToPyChipError(err);
189209
}
210+
}

src/controller/python/chip/ChipDeviceCtrl.py

+13
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,16 @@ def InitGroupTestingData(self):
17111711
self.devCtrl)
17121712
).raise_on_error()
17131713

1714+
def CreateManualCode(self, discriminator: int, passcode: int) -> str:
1715+
""" Creates a standard flow manual code from the given discriminator and passcode."""
1716+
# 64 bytes is WAY more than required, but let's be safe
1717+
size = 64
1718+
buf = create_string_buffer(size)
1719+
self._ChipStack.Call(
1720+
lambda: self._dmLib.pychip_CreateManualCode(discriminator, passcode, buf, size)
1721+
).raise_on_error()
1722+
return buf.value.decode()
1723+
17141724
# ----- Private Members -----
17151725
def _InitLib(self):
17161726
if self._dmLib is None:
@@ -1938,6 +1948,9 @@ def _InitLib(self):
19381948
self._dmLib.pychip_DeviceProxy_GetRemoteSessionParameters.restype = PyChipError
19391949
self._dmLib.pychip_DeviceProxy_GetRemoteSessionParameters.argtypes = [c_void_p, c_char_p]
19401950

1951+
self._dmLib.pychip_CreateManualCode.restype = PyChipError
1952+
self._dmLib.pychip_CreateManualCode.argtypes = [c_uint16, c_uint32, c_char_p, c_size_t]
1953+
19411954

19421955
class ChipDeviceController(ChipDeviceControllerBase):
19431956
''' The ChipDeviceCommissioner binding, named as ChipDeviceController

src/python_testing/TC_DeviceBasicComposition.py

+45-1
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,58 @@
1919
# for details about the block below.
2020
#
2121
# === BEGIN CI TEST ARGUMENTS ===
22-
# test-runner-runs: run1
22+
# test-runner-runs: run1 run2 run3 run4
2323
# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
2424
# test-runner-run/run1/factoryreset: True
2525
# test-runner-run/run1/quiet: True
2626
# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json
2727
# test-runner-run/run1/script-args: --storage-path admin_storage.json --manual-code 10054912339 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
28+
#
29+
# test-runner-run/run2/app: ${CHIP_LOCK_APP}
30+
# test-runner-run/run2/factoryreset: True
31+
# test-runner-run/run2/quiet: True
32+
# test-runner-run/run2/app-args: --discriminator 1234 --KVS kvs1
33+
# test-runner-run/run2/script-args: --storage-path admin_storage.json --manual-code 10054912339
34+
#
35+
# test-runner-run/run3/app: ${CHIP_LOCK_APP}
36+
# test-runner-run/run3/factoryreset: True
37+
# test-runner-run/run3/quiet: True
38+
# test-runner-run/run3/app-args: --discriminator 1234 --KVS kvs1
39+
# test-runner-run/run3/script-args: --storage-path admin_storage.json --qr-code MT:-24J0Q1212-10648G00
40+
#
41+
# test-runner-run/run4/app: ${CHIP_LOCK_APP}
42+
# test-runner-run/run4/factoryreset: True
43+
# test-runner-run/run4/quiet: True
44+
# test-runner-run/run4/app-args: --discriminator 1234 --KVS kvs1
45+
# test-runner-run/run4/script-args: --storage-path admin_storage.json --discriminator 1234 --passcode 20202021
46+
#
47+
# test-runner-run/run5/app: ${CHIP_LOCK_APP}
48+
# test-runner-run/run5/factoryreset: True
49+
# test-runner-run/run5/quiet: True
50+
# test-runner-run/run5/app-args: --discriminator 1234 --KVS kvs1
51+
# test-runner-run/run5/script-args: --storage-path admin_storage.json --manual-code 10054912339 --commissioning-method on-network
52+
#
53+
# test-runner-run/run6/app: ${CHIP_LOCK_APP}
54+
# test-runner-run/run6/factoryreset: True
55+
# test-runner-run/run6/quiet: True
56+
# test-runner-run/run6/app-args: --discriminator 1234 --KVS kvs1
57+
# test-runner-run/run6/script-args: --storage-path admin_storage.json --qr-code MT:-24J0Q1212-10648G00 --commissioning-method on-network
58+
#
59+
# test-runner-run/run7/app: ${CHIP_LOCK_APP}
60+
# test-runner-run/run7/factoryreset: True
61+
# test-runner-run/run7/quiet: True
62+
# test-runner-run/run7/app-args: --discriminator 1234 --KVS kvs1
63+
# test-runner-run/run7/script-args: --storage-path admin_storage.json --discriminator 1234 --passcode 20202021 --commissioning-method on-network
2864
# === END CI TEST ARGUMENTS ===
2965

66+
# Run 1: runs through all tests
67+
# Run 2: tests PASE connection using manual code (12.1 only)
68+
# Run 3: tests PASE connection using QR code (12.1 only)
69+
# Run 4: tests PASE connection using discriminator and passcode (12.1 only)
70+
# Run 5: Tests CASE connection using manual code (12.1 only)
71+
# Run 6: Tests CASE connection using QR code (12.1 only)
72+
# Run 7: Tests CASE connection using manual discriminator and passcode (12.1 only)
73+
3074
import logging
3175
from dataclasses import dataclass
3276
from typing import Any, Callable

src/python_testing/basic_composition_support.py

+33-15
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# limitations under the License.
1616
#
1717

18-
18+
import asyncio
1919
import base64
2020
import copy
2121
import json
@@ -98,12 +98,15 @@ def ConvertValue(value) -> Any:
9898

9999

100100
class BasicCompositionTests:
101-
async def connect_over_pase(self, dev_ctrl):
102-
asserts.assert_true(self.matter_test_config.qr_code_content == [] or self.matter_test_config.manual_code == [],
103-
"Cannot have both QR and manual code specified")
104-
setupCode = self.matter_test_config.qr_code_content + self.matter_test_config.manual_code
105-
asserts.assert_equal(len(setupCode), 1, "Require one of either --qr-code or --manual-code.")
106-
await dev_ctrl.FindOrEstablishPASESession(setupCode[0], self.dut_node_id)
101+
def get_code(self, dev_ctrl):
102+
created_codes = []
103+
for idx, d in enumerate(self.matter_test_config.discriminators):
104+
created_codes.append(dev_ctrl.CreateManualCode(d, self.matter_test_config.setup_passcodes[idx]))
105+
106+
setup_codes = self.matter_test_config.qr_code_content + self.matter_test_config.manual_code + created_codes
107+
asserts.assert_equal(len(setup_codes), 1,
108+
"Require exactly one of either --qr-code, --manual-code or (--discriminator and --passcode).")
109+
return setup_codes[0]
107110

108111
def dump_wildcard(self, dump_device_composition_path: typing.Optional[str]):
109112
node_dump_dict = {endpoint_id: MatterTlvToJson(self.endpoints_tlv[endpoint_id]) for endpoint_id in self.endpoints_tlv}
@@ -115,19 +118,34 @@ def dump_wildcard(self, dump_device_composition_path: typing.Optional[str]):
115118
with open(pathlib.Path(dump_device_composition_path).with_suffix(".txt"), "wt+") as outfile:
116119
pprint(self.endpoints, outfile, indent=1, width=200, compact=True)
117120

118-
async def setup_class_helper(self, default_to_pase: bool = True):
121+
async def setup_class_helper(self, allow_pase: bool = True):
119122
dev_ctrl = self.default_controller
120123
self.problems = []
121124

122-
do_test_over_pase = self.user_params.get("use_pase_only", default_to_pase)
123125
dump_device_composition_path: Optional[str] = self.user_params.get("dump_device_composition_path", None)
124126

125-
if do_test_over_pase:
126-
await self.connect_over_pase(dev_ctrl)
127-
node_id = self.dut_node_id
128-
else:
129-
# Using the already commissioned node
130-
node_id = self.dut_node_id
127+
node_id = self.dut_node_id
128+
129+
task_list = []
130+
if allow_pase:
131+
setup_code = self.get_code(dev_ctrl)
132+
pase_future = dev_ctrl.EstablishPASESession(setup_code, self.dut_node_id)
133+
task_list.append(asyncio.create_task(pase_future))
134+
135+
case_future = dev_ctrl.GetConnectedDevice(nodeid=node_id, allowPASE=False)
136+
task_list.append(asyncio.create_task(case_future))
137+
138+
for task in task_list:
139+
asyncio.ensure_future(task)
140+
141+
done, pending = await asyncio.wait(task_list, return_when=asyncio.FIRST_COMPLETED)
142+
143+
for task in pending:
144+
try:
145+
task.cancel()
146+
await task
147+
except asyncio.CancelledError:
148+
pass
131149

132150
wildcard_read = (await dev_ctrl.Read(node_id, [()]))
133151

src/python_testing/matter_testing_support.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1546,9 +1546,6 @@ def populate_commissioning_args(args: argparse.Namespace, config: MatterTestConf
15461546
config.qr_code_content.extend(args.qr_code)
15471547
config.manual_code.extend(args.manual_code)
15481548

1549-
if args.commissioning_method is None:
1550-
return True
1551-
15521549
if args.discriminators == [] and (args.qr_code == [] and args.manual_code == []):
15531550
print("error: Missing --discriminator when no --qr-code/--manual-code present!")
15541551
return False
@@ -1588,6 +1585,9 @@ def populate_commissioning_args(args: argparse.Namespace, config: MatterTestConf
15881585
print("error: Duplicate value in discriminator list")
15891586
return False
15901587

1588+
if args.commissioning_method is None:
1589+
return True
1590+
15911591
if config.commissioning_method == "ble-wifi":
15921592
if args.wifi_ssid is None:
15931593
print("error: missing --wifi-ssid <SSID> for --commissioning-method ble-wifi!")

0 commit comments

Comments
 (0)