Skip to content

Commit 4a578ea

Browse files
Documentation for mocked BLE-WiFi commissioning (project-chip#41359)
* Add missing codeblock language specifiers in docs/testing * Documentation for mocked BLE-WiFi commissioning * Add more verbose doc for WPA supplicant mock class * Restyled by prettier-markdown * Fix doc build and add marmaid support --------- Co-authored-by: Restyled.io <[email protected]>
1 parent f8b6907 commit 4a578ea

File tree

10 files changed

+245
-140
lines changed

10 files changed

+245
-140
lines changed

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ jobs:
368368
./scripts/run_in_build_env.sh \
369369
"./scripts/tests/run_test_suite.py \
370370
--runner chip_tool_python \
371-
--target TestCommissionerNodeId \
371+
--target TestOperationalState \
372372
--chip-tool ./out/linux-x64-chip-tool${CHIP_TOOL_VARIANT}-${BUILD_VARIANT}/chip-tool \
373373
run \
374374
--iterations 1 \

docs/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
extensions = [
2222
"myst_parser",
2323
"external_content",
24+
"sphinxcontrib.mermaid",
2425
]
2526
exclude_patterns = [
2627
"_build",
@@ -61,7 +62,7 @@
6162
"myst.xref_missing",
6263
]
6364
myst_enable_extensions = ["html_image"]
64-
65+
myst_fence_as_directive = ["mermaid"]
6566

6667
# -- Options for external_content --------------------------------------------
6768

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
docutils==0.21.2
22
Sphinx==8.2.3
33
sphinx-book-theme
4+
sphinxcontrib-mermaid
45
myst-parser>=2.0.0
56
breathe>=4.34
67
pydata-sphinx-theme==0.16.1

docs/testing/fuzz_testing.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ test. Each fuzzer function is defined using
2222

2323
The Fuzzer must be located in a Test Folder : `src/some_directory/tests/`
2424

25-
```
25+
```cpp
2626
#include <cstddef>
2727
#include <cstdint>
2828

@@ -39,7 +39,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t len)
3939

4040
return 0;
4141
}
42-
4342
```
4443

4544
See
@@ -104,11 +103,11 @@ for an example of a simple fuzz test.
104103
```
105104
106105
- Build all fuzzers
107-
```
106+
```shell
108107
./scripts/build/build_examples.py --target <host>-<compiler>-tests-asan-libfuzzer-clang build
109108
```
110109
e.g.
111-
```
110+
```shell
112111
./scripts/build/build_examples.py --target darwin-arm64-tests-asan-libfuzzer-clang build
113112
```
114113
\*\* Make sure to put the right host and compiler
@@ -263,14 +262,14 @@ There are several ways to run the tests:
263262

264263
1. Unit-test mode (where the inputs are only fuzzed for a second):
265264

266-
```bash
265+
```shell
267266
./fuzz-chip-cert-pw
268267
```
269268

270269
2. Continuous fuzzing mode; we need to first list the tests, then specify the
271270
FuzzTestCase to run:
272271

273-
```bash
272+
```console
274273
$ ./fuzz-chip-cert-pw --list_fuzz_tests
275274
[.] Sanitizer coverage enabled. Counter map size: 11134, Cmp map size: 262144
276275
[*] Fuzz test: ChipCert.ChipCertFuzzer
@@ -281,20 +280,19 @@ $ ./fuzz-chip-cert-pw --fuzz=ChipCert.DecodeChipCertFuzzer
281280

282281
3. Running all Tests in a TestSuite for a specific time, e.g for 10 minutes
283282

284-
```bash
285-
#both Fuzz Tests will be run for 10 minutes each
283+
```shell
284+
# both Fuzz Tests will be run for 10 minutes each
286285
./fuzz-chip-cert-pw --fuzz_for=10m
287286
```
288287

289288
4. For Help
290289

291-
```bash
290+
```shell
292291
# FuzzTest related help
293292
./fuzz-chip-cert-pw --helpfull
294293

295294
# gtest related help
296295
./fuzz-chip-cert-pw --help
297-
298296
```
299297

300298
### Coverage Report Generation

docs/testing/integration_test_utilities.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ To add new fault injection code paths:
9999

100100
### Fault Injection example
101101

102-
```
102+
```cpp
103103
CHIP_ERROR CASEServer::OnMessageReceived(Messaging::ExchangeContext * ec,
104104
const PayloadHeader & payloadHeader,
105105
System::PacketBufferHandle && payload)
@@ -110,7 +110,6 @@ CHIP_ERROR CASEServer::OnMessageReceived(Messaging::ExchangeContext * ec,
110110
CHIP_FAULT_INJECT(FaultInjection::kFault_CASEServerBusy, busy = true);
111111
if (busy)
112112
{
113-
114113
```
115114
116115
### Fault Injection cluster

docs/testing/integration_tests.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,104 @@ way that is understandable, readable, and has the features you need
4444
(certs, commissioning, etc), less plumbing if you need to add features,
4545
can use python libraries
4646
- cons: more complex, can be harder to read
47+
48+
## Running integration tests locally
49+
50+
When integration tests are run locally, the test runner (YAML or python) needs
51+
to mock network connectivity between the controller and the device under test,
52+
so that all tests can be run without actual hardware. In case of a simple test
53+
case when a single device is tested with on-network commissioning, nothing
54+
special is needed - the controller can connect to the device directly over the
55+
local (loopback) network interface. However, for more complex test cases that
56+
involve multiple devices or other than on-network commissioning (e.g. ble-wifi
57+
or ble-thread), some additional setup is needed.
58+
59+
### Running tests in Linux network namespaces
60+
61+
The simplest way to mock more complex network topologies is to use Linux network
62+
namespaces. Each device (controller or DUT) is run in its own network namespace,
63+
which allows them to have their own network interfaces and corresponding IP
64+
addresses.
65+
66+
For convenience, there is a script that can set up network namespaces and run a
67+
test case in them:
68+
69+
```shell
70+
# Build the chip-tool and chip-all-clusters-app if not done already
71+
scripts/build/build_examples.py --target linux-x64-chip-tool --target linux-x64-all-clusters build
72+
# Run the TestOperationalState test case in the Linux network namespaces
73+
scripts/tests/run_test_suite.py --runner chip_tool_python \
74+
--chip-tool out/linux-x64-chip-tool/chip-tool \
75+
--target TestOperationalState \
76+
--log-level=debug \
77+
run
78+
```
79+
80+
### Running tests with mocked BLE and Wi-Fi connectivity
81+
82+
For more complex commissioning flows that involve BLE and Wi-Fi, the test runner
83+
needs to mock BLE and Wi-Fi connectivity as well. On Linux, BLE and Wi-Fi are
84+
provided by the BlueZ stack and WPA supplicant, respectively. The SDK uses D-Bus
85+
to interact with these services. This allows the test runner to mock BLE and
86+
Wi-Fi connectivity by simply mocking used D-Bus APIs of these services.
87+
88+
Additionally, the Matter specification forbids device to advertise on more than
89+
one network type at a time, so in case of ble-wifi commissioning, the DUT shall
90+
not be accessible over Wi-Fi until it is commissioned. This can be achieved by
91+
using Linux network namespaces as described above, but instead of setting up
92+
network interfaces before commissioning, the test runner assigns IP address to
93+
the DUT's network interface only after mock Wi-Fi connection is associated.
94+
95+
See the diagram below for an overview of the setup:
96+
97+
```mermaid
98+
flowchart TD
99+
100+
subgraph Mocked BlueZ
101+
BA1[adapter1<br>00:00:00:11:11:11]
102+
BA2[adapter2<br>00:00:00:22:22:22]
103+
end
104+
105+
subgraph Mocked WPA supplicant
106+
WL0[wlan0]
107+
end
108+
109+
subgraph Test D-Bus system bus
110+
direction TB
111+
org.bluez.hci0[org.bluez.Adapter<br>hci0]
112+
org.bluez.hci1[org.bluez.Adapter<br>hci1]
113+
fi.w1[fi.w1.wpa_supplicant1.Interface<br>wlan0]
114+
end
115+
116+
BA1 --- org.bluez.hci0
117+
BA2 --- org.bluez.hci1
118+
WL0 --- fi.w1
119+
120+
subgraph ETH["TOOL network namespace"]
121+
CONTROLLER[chip-tool]
122+
ETH0[eth0<br>fd00:0:1:1::2]
123+
end
124+
125+
subgraph WLAN["DUT network namespace"]
126+
DUT[chip-all-clusters-app]
127+
WLAN0[wlan0<br>not assigned]
128+
end
129+
130+
fi.w1 --- DUT
131+
org.bluez.hci0 --- DUT
132+
org.bluez.hci1 --- CONTROLLER
133+
134+
```
135+
136+
In order to run tests with mocked BLE and Wi-Fi connectivity and Linux network
137+
namespaces use the `--ble-wifi` option to the `run` command of the
138+
`scripts/tests/run_test_suite.py` script:
139+
140+
```shell
141+
# Run the TestOperationalState test case with ble-wifi commissioning
142+
scripts/tests/run_test_suite.py --runner chip_tool_python \
143+
--chip-tool out/linux-x64-chip-tool/chip-tool \
144+
--target TestOperationalState \
145+
--log-level=debug \
146+
run --ble-wifi
147+
```

docs/testing/python.md

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Python tests located in src/python_testing
4545

4646
### A simple test
4747

48-
```
48+
```python
4949
# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments
5050
# for details about the block below.
5151
#
@@ -71,18 +71,16 @@ class TC_MYTEST_1_1(MatterBaseTest):
7171
async def test_TC_MYTEST_1_1(self):
7272

7373
vendor_name = await self.read_single_attribute_check_success(
74-
dev_ctrl=self.default_controller, <span style="color:#38761D"># defaults to
75-
self.default_controlller</span>
76-
node_id = self.dut_node_id, <span style="color:#38761D"># defaults to
77-
self.dut_node_id</span>
74+
dev_ctrl=self.default_controller, # defaults to self.default_controller
75+
node_id = self.dut_node_id, # defaults to self.dut_node_id
7876
cluster=Clusters.BasicInformation,
7977
attribute=Clusters.BasicInformation.Attributes.VendorName,
80-
endpoint = 0, <span style="color:#38761D">#defaults to 0</span>
78+
endpoint = 0, # defaults to 0
8179
)
82-
asserts.assert_equal(vendor_name, Test vendor name”, “Unexpected vendor name)
80+
asserts.assert_equal(vendor_name, "Test vendor name", "Unexpected vendor name")
8381

8482
if __name__ == "__main__":
85-
default_matter_test_main()
83+
default_matter_test_main()
8684
```
8785

8886
---
@@ -321,7 +319,7 @@ callbacks are called on update.
321319

322320
Example for setting callbacks:
323321

324-
```
322+
```python
325323
cb = EventSubscriptionHandler(cluster, cluster_id, event_id)
326324

327325
urgent = 1
@@ -345,9 +343,9 @@ PyChipError
345343

346344
Example:
347345

348-
```
346+
```python
349347
res = await devCtrl.WriteAttribute(nodeid=0, attributes=[(0,Clusters.BasicInformation.Attributes.NodeLabel("Test"))])
350-
asserts.assert_equal(ret[0].status, Status.Success, write failed)
348+
asserts.assert_equal(ret[0].status, Status.Success, "write failed")
351349
```
352350

353351
### [SendCommand](./ChipDeviceCtrlAPI.md#sendcommand)
@@ -532,11 +530,11 @@ Note: The name of the pipe can be anything while is a valid file path.
532530

533531
Example of usage:
534532

535-
```bash
536-
First run the app with the desired app-pipe path:
533+
```shell
534+
# First run the app with the desired app-pipe path:
537535
./out/darwin-arm64-all-clusters/chip-all-clusters-app --app-pipe /tmp/ref_alm_2_2
538536

539-
Then execute the test with the app-pipe argument with the value defined while running the app.
537+
# Then execute the test with the app-pipe argument with the value defined while running the app.
540538
python3 src/python_testing/TC_REFALM_2_2.py --commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 --PICS src/app/tests/suites/certification/ci-pics-values --app-pipe /tmp/ref_alm_2_2 --int-arg PIXIT.REFALM.AlarmThreshold:1
541539
```
542540

@@ -682,15 +680,15 @@ First ensure the device is in commissioning mode. Then run the test against the
682680
device by supplying either the QR code, the manual pairing code or the
683681
discriminator / password pair.
684682

685-
```
683+
```shell
686684
python3 TC_DeviceConformance.py --qr-code MT:-24J0AFN00KA0648G00
687685
```
688686

689-
```
687+
```shell
690688
python3 TC_DeviceConformance.py --manual-code 34970112332
691689
```
692690

693-
```
691+
```shell
694692
python3 TC_DeviceConformance.py --discriminator 3840 --passcode 20202021
695693
```
696694

@@ -699,7 +697,7 @@ python3 TC_DeviceConformance.py --discriminator 3840 --passcode 20202021
699697
If the device has already been commissioned into the python testing fabric, you
700698
can run the test directly
701699

702-
```
700+
```shell
703701
python3 TC_DeviceConformance.py
704702
```
705703

@@ -712,7 +710,7 @@ using the `--commissioning-method` flag and the `--qr-code`, `--manual-code` or
712710

713711
For example:
714712

715-
```
713+
```shell
716714
python3 TC_DeviceConformance.py --discriminator 3840 --passcode 20202021 --commissioning-method on-network
717715
```
718716

@@ -736,15 +734,15 @@ the device, they can also be run against a MatterTlvJson machine readable file
736734
without requiring the device to be physically present. To run against a
737735
previously generated MatterTlvJson device dump file:
738736

739-
```
737+
```shell
740738
python3 TC_DeviceConformance.py --string-arg test_from_file:device_dump_0xFFF1_0x8001_1.json
741739
```
742740

743741
You can generate a MatterTlvJson file for a device by leveraging the
744742
certification test that generates these (TC-IDM-12.1, implemented in
745743
TC_DeviceBasicComposition.py).
746744

747-
```
745+
```shell
748746
python3 TC_DeviceBasicComposition.py --qr-code MT:-24J0AFN00KA0648G00 --tests test_TC_IDM_12_1
749747
```
750748

0 commit comments

Comments
 (0)