Skip to content

Commit

Permalink
THNETDIR / WIFINM: Test scripts and small fixes (#34469)
Browse files Browse the repository at this point in the history
* Thread Network Directory GetOperationalDataset does not required timed invoke

See CHIP-Specifications/connectedhomeip-spec#10106

* Actually return the dataset in GetOperationalDataset

* Add test scripts for THNETDIR cluster

Base on CHIP-Specifications/chip-test-plans#4322
but contains some additional steps which will be added to the test plan.

Some validations depend on PR #34487 and are commented out.

* Darwin: Avoid linker issues with pigweed clang

* Prefix network-manager binary name with matter-

* Run THNETDIR tests against network-manager app in CI

* Add test script for WIFINM cluster and include in CI

* Add network-manager app to darwin-tests.yaml

* Update WIFINM cluster definition and test to match latest spec

Based on CHIP-Specifications/connectedhomeip-spec#10025

* zap_regen_all

* Disable tests for NEEDS_TIMED_INTERACTION for now

These currently fail when run with darwin-framework-tool because
Matter.framework automatically defaults to using a timed interaction when the
cluster command requires it, defeating the test.

* Fix network-manager-app zap/matter files

* Add apiMaturity attributes

* Add missing attribute read step and improve step names
  • Loading branch information
ksperling-apple authored Jul 29, 2024
1 parent ea94b7d commit e8fb908
Show file tree
Hide file tree
Showing 48 changed files with 886 additions and 56 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/darwin-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ jobs:
--target darwin-x64-lit-icd-${BUILD_VARIANT} \
--target darwin-x64-microwave-oven-${BUILD_VARIANT} \
--target darwin-x64-rvc-${BUILD_VARIANT} \
--target darwin-x64-network-manager-${BUILD_VARIANT} \
build \
--copy-artifacts-to objdir-clone \
"
Expand All @@ -116,6 +117,7 @@ jobs:
--bridge-app ./out/darwin-x64-bridge-${BUILD_VARIANT}/chip-bridge-app \
--microwave-oven-app ./out/darwin-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \
--rvc-app ./out/darwin-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \
--network-manager-app ./out/darwin-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \
"
- name: Run OTA Test
run: |
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ jobs:
src/app/zap-templates/zcl/data-model/chip/thermostat-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/thread-border-router-management-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/thread-network-diagnostics-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/thread-network-directory-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/time-format-localization-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/time-synchronization-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/timer-cluster.xml \
Expand Down Expand Up @@ -223,6 +224,7 @@ jobs:
--target linux-x64-lit-icd-${BUILD_VARIANT} \
--target linux-x64-microwave-oven-${BUILD_VARIANT} \
--target linux-x64-rvc-${BUILD_VARIANT} \
--target linux-x64-network-manager-${BUILD_VARIANT} \
build \
--copy-artifacts-to objdir-clone \
"
Expand All @@ -245,6 +247,7 @@ jobs:
--lit-icd-app ./out/linux-x64-lit-icd-${BUILD_VARIANT}/lit-icd-app \
--microwave-oven-app ./out/linux-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \
--rvc-app ./out/linux-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \
--network-manager-app ./out/linux-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \
"
- name: Run purposeful failure tests using the python parser sending commands to chip-tool
Expand Down Expand Up @@ -286,6 +289,7 @@ jobs:
--lit-icd-app ./out/linux-x64-lit-icd-${BUILD_VARIANT}/lit-icd-app \
--microwave-oven-app ./out/linux-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \
--rvc-app ./out/linux-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \
--network-manager-app ./out/linux-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \
"
- name: Run Tests using chip-repl (including slow)
if: github.event_name == 'push'
Expand All @@ -305,6 +309,7 @@ jobs:
--lit-icd-app ./out/linux-x64-lit-icd-${BUILD_VARIANT}/lit-icd-app \
--microwave-oven-app ./out/linux-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \
--rvc-app ./out/linux-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \
--network-manager-app ./out/linux-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \
"
- name: Uploading core files
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -373,6 +378,7 @@ jobs:
--target darwin-x64-lit-icd-${BUILD_VARIANT} \
--target darwin-x64-microwave-oven-${BUILD_VARIANT} \
--target darwin-x64-rvc-${BUILD_VARIANT} \
--target darwin-x64-network-manager-${BUILD_VARIANT} \
build \
--copy-artifacts-to objdir-clone \
"
Expand All @@ -396,6 +402,7 @@ jobs:
--lit-icd-app ./out/darwin-x64-lit-icd-${BUILD_VARIANT}/lit-icd-app \
--microwave-oven-app ./out/darwin-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \
--rvc-app ./out/darwin-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \
--network-manager-app ./out/darwin-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \
"
- name: Run purposeful failure tests using the python parser sending commands to chip-tool
Expand Down
10 changes: 9 additions & 1 deletion build/config/compiler/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import("//build_overrides/build.gni")
import("//build_overrides/pigweed.gni")
import("//build_overrides/pigweed_environment.gni")
import("${build_root}/chip/java/config.gni")
import("${build_root}/config/compiler/compiler.gni")
import("${build_root}/config/sysroot.gni")
Expand Down Expand Up @@ -348,7 +349,14 @@ config("cosmetic_default") {
}

config("runtime_default") {
if (is_clang) { # Using Pigweed clang instead of Darwin host clang
if (is_clang &&
current_os == "mac") { # Using Pigweed clang instead of Darwin host clang
# Without pw_env_setup_CIPD_PIGWEED defined the hostclang:no_system_libcpp
# config silently uses the system libc++, usually resulting in linker errors.
assert(
defined(pw_env_setup_CIPD_PIGWEED),
"//build_overrides/pigweed_environment.gni must define pw_env_setup_CIPD_PIGWEED when using pigweed clang")

configs = [
"$dir_pw_toolchain/host_clang:no_system_libcpp",
"$dir_pw_toolchain/host_clang:xcode_sysroot",
Expand Down
4 changes: 2 additions & 2 deletions examples/network-manager-app/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import("//build_overrides/build.gni")
import("//build_overrides/chip.gni")

executable("network-manager-app") {
executable("matter-network-manager-app") {
sources = [
"include/CHIPProjectAppConfig.h",
"main.cpp",
Expand All @@ -32,7 +32,7 @@ executable("network-manager-app") {
}

group("linux") {
deps = [ ":network-manager-app" ]
deps = [ ":matter-network-manager-app" ]
}

group("default") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1193,10 +1193,11 @@ cluster GroupKeyManagement = 63 {
}

/** Functionality to retrieve operational information about a managed Wi-Fi network. */
cluster WiFiNetworkManagement = 1105 {
provisional cluster WiFiNetworkManagement = 1105 {
revision 1;

readonly attribute nullable octet_string<32> ssid = 1;
readonly attribute nullable octet_string<32> ssid = 0;
readonly attribute access(read: manage) nullable int64u passphraseSurrogate = 1;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
Expand All @@ -1209,11 +1210,11 @@ cluster WiFiNetworkManagement = 1105 {
}

/** Request the current WPA-Personal passphrase or PSK associated with the managed Wi-Fi network. */
command access(invoke: administer) NetworkPassphraseRequest(): NetworkPassphraseResponse = 0;
command access(invoke: manage) NetworkPassphraseRequest(): NetworkPassphraseResponse = 0;
}

/** Manages the names and credentials of Thread networks visible to the user. */
cluster ThreadNetworkDirectory = 1107 {
provisional cluster ThreadNetworkDirectory = 1107 {
revision 1;

struct ThreadNetworkStruct {
Expand Down Expand Up @@ -1254,7 +1255,7 @@ cluster ThreadNetworkDirectory = 1107 {
/** Removes an entry from the ThreadNetworks list. */
timed command access(invoke: manage) RemoveNetwork(RemoveNetworkRequest): DefaultSuccess = 1;
/** Retrieves a Thread Operational Dataset from the ThreadNetworks list. */
timed command GetOperationalDataset(GetOperationalDatasetRequest): OperationalDatasetResponse = 2;
command GetOperationalDataset(GetOperationalDatasetRequest): OperationalDatasetResponse = 2;
}

endpoint 0 {
Expand Down Expand Up @@ -1525,6 +1526,7 @@ endpoint 1 {

server cluster WiFiNetworkManagement {
callback attribute ssid;
callback attribute passphraseSurrogate;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3238,7 +3238,7 @@
"attributes": [
{
"name": "SSID",
"code": 1,
"code": 0,
"mfgCode": null,
"side": "server",
"type": "octet_string",
Expand All @@ -3252,6 +3252,22 @@
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "PassphraseSurrogate",
"code": 1,
"mfgCode": null,
"side": "server",
"type": "int64u",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "GeneratedCommandList",
"code": 65528,
Expand Down
3 changes: 3 additions & 0 deletions scripts/build/builders/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ def OutputNames(self):
elif self == HostApp.LIT_ICD:
yield 'lit-icd-app'
yield 'lit-icd-app.map'
elif self == HostApp.NETWORK_MANAGER:
yield 'matter-network-manager-app'
yield 'matter-network-manager-app.map'
elif self == HostApp.ENERGY_MANAGEMENT:
yield 'chip-energy-management-app'
yield 'chip-energy-management-app.map'
Expand Down
2 changes: 2 additions & 0 deletions scripts/tests/chiptest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ def target_for_name(name: str):
return TestTarget.MWO
if name.startswith("Test_TC_RVCRUNM_") or name.startswith("Test_TC_RVCCLEANM_") or name.startswith("Test_TC_RVCOPSTATE_"):
return TestTarget.RVC
if name.startswith("Test_TC_THNETDIR_") or name.startswith("Test_TC_WIFINM_"):
return TestTarget.NETWORK_MANAGER
return TestTarget.ALL_CLUSTERS


Expand Down
1 change: 1 addition & 0 deletions scripts/tests/chiptest/linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ def PathsWithNetworkNamespaces(paths: ApplicationPaths) -> ApplicationPaths:
lit_icd_app='ip netns exec app'.split() + paths.lit_icd_app,
microwave_oven_app='ip netns exec app'.split() + paths.microwave_oven_app,
rvc_app='ip netns exec app'.split() + paths.rvc_app,
network_manager_app='ip netns exec app'.split() + paths.network_manager_app,
bridge_app='ip netns exec app'.split() + paths.bridge_app,
chip_repl_yaml_tester_cmd='ip netns exec tool'.split() + paths.chip_repl_yaml_tester_cmd,
chip_tool_with_python_cmd='ip netns exec tool'.split() + paths.chip_tool_with_python_cmd,
Expand Down
6 changes: 5 additions & 1 deletion scripts/tests/chiptest/test_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class TestTarget(Enum):
LIT_ICD = auto()
MWO = auto()
RVC = auto()
NETWORK_MANAGER = auto()


@dataclass
Expand All @@ -193,10 +194,11 @@ class ApplicationPaths:
chip_repl_yaml_tester_cmd: typing.List[str]
chip_tool_with_python_cmd: typing.List[str]
rvc_app: typing.List[str]
network_manager_app: typing.List[str]

def items(self):
return [self.chip_tool, self.all_clusters_app, self.lock_app, self.ota_provider_app, self.ota_requestor_app,
self.tv_app, self.bridge_app, self.lit_icd_app, self.microwave_oven_app, self.chip_repl_yaml_tester_cmd, self.chip_tool_with_python_cmd, self.rvc_app]
self.tv_app, self.bridge_app, self.lit_icd_app, self.microwave_oven_app, self.chip_repl_yaml_tester_cmd, self.chip_tool_with_python_cmd, self.rvc_app, self.network_manager_app]


@dataclass
Expand Down Expand Up @@ -309,6 +311,8 @@ def Run(self, runner, apps_register, paths: ApplicationPaths, pics_file: str,
target_app = paths.microwave_oven_app
elif self.target == TestTarget.RVC:
target_app = paths.rvc_app
elif self.target == TestTarget.NETWORK_MANAGER:
target_app = paths.network_manager_app
else:
raise Exception("Unknown test target - "
"don't know which application to run")
Expand Down
9 changes: 8 additions & 1 deletion scripts/tests/run_test_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ def cmd_list(context):
@click.option(
'--rvc-app',
help='what rvc app to use')
@click.option(
'--network-manager-app',
help='what network-manager app to use')
@click.option(
'--chip-repl-yaml-tester',
help='what python script to use for running yaml tests using chip-repl as controller')
Expand Down Expand Up @@ -291,7 +294,7 @@ def cmd_list(context):
help='Number of tests that are expected to fail in each iteration. Overall test will pass if the number of failures matches this. Nonzero values require --keep-going')
@click.pass_context
def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, ota_requestor_app,
tv_app, bridge_app, lit_icd_app, microwave_oven_app, rvc_app, chip_repl_yaml_tester, chip_tool_with_python, pics_file, keep_going, test_timeout_seconds, expected_failures):
tv_app, bridge_app, lit_icd_app, microwave_oven_app, rvc_app, network_manager_app, chip_repl_yaml_tester, chip_tool_with_python, pics_file, keep_going, test_timeout_seconds, expected_failures):
if expected_failures != 0 and not keep_going:
logging.exception(f"'--expected-failures {expected_failures}' used without '--keep-going'")
sys.exit(2)
Expand Down Expand Up @@ -327,6 +330,9 @@ def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, o
if rvc_app is None:
rvc_app = paths_finder.get('chip-rvc-app')

if network_manager_app is None:
network_manager_app = paths_finder.get('matter-network-manager-app')

if chip_repl_yaml_tester is None:
chip_repl_yaml_tester = paths_finder.get('yamltest_with_chip_repl_tester.py')

Expand All @@ -348,6 +354,7 @@ def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, o
lit_icd_app=[lit_icd_app],
microwave_oven_app=[microwave_oven_app],
rvc_app=[rvc_app],
network_manager_app=[network_manager_app],
chip_repl_yaml_tester_cmd=['python3'] + [chip_repl_yaml_tester],
chip_tool_with_python_cmd=['python3'] + [chip_tool_with_python],
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,10 @@ void ThreadNetworkDirectoryServer::HandleOperationalDatasetRequest(

uint8_t datasetBuffer[kSizeOperationalDataset];
MutableByteSpan datasetSpan(datasetBuffer);
OperationalDatasetResponse::Type response;
SuccessOrExit(err = mStorage.GetNetworkDataset(ExtendedPanId(req.extendedPanID), datasetSpan));
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, IMStatus::Success);
response.operationalDataset = datasetSpan;
ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
return;
exit:
ChipLogError(Zcl, "GetOperationalDataset: %" CHIP_ERROR_FORMAT, err.Format());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <app/InteractionModelEngine.h>
#include <app/reporting/reporting.h>
#include <lib/support/CodeUtils.h>
#include <system/SystemClock.h>

#include <algorithm>
#include <cctype>
Expand Down Expand Up @@ -99,11 +100,20 @@ CHIP_ERROR WiFiNetworkManagementServer::SetNetworkCredentials(ByteSpan ssid, Byt
VerifyOrDie(mPassphrase.SetLength(passphrase.size()) == CHIP_NO_ERROR);
memcpy(mPassphrase.Bytes(), passphrase.data(), passphrase.size());

// Note: The spec currently defines no way to signal a passphrase change
if (ssidChanged)
{
MatterReportingAttributeChangeCallback(GetEndpointId(), WiFiNetworkManagement::Id, Ssid::Id);
}
if (passphraseChanged)
{
mPassphraseSurrogate++;
System::Clock::Milliseconds64 realtime;
if (System::SystemClock().GetClock_RealTimeMS(realtime) == CHIP_NO_ERROR)
{
mPassphraseSurrogate = std::max(mPassphraseSurrogate, realtime.count());
}
MatterReportingAttributeChangeCallback(GetEndpointId(), WiFiNetworkManagement::Id, PassphraseSurrogate::Id);
}
return CHIP_NO_ERROR;
}

Expand All @@ -113,6 +123,8 @@ CHIP_ERROR WiFiNetworkManagementServer::Read(const ConcreteReadAttributePath & a
{
case Ssid::Id:
return HaveNetworkCredentials() ? aEncoder.Encode(SsidSpan()) : aEncoder.EncodeNull();
case PassphraseSurrogate::Id:
return HaveNetworkCredentials() ? aEncoder.Encode(mPassphraseSurrogate) : aEncoder.EncodeNull();
}
return CHIP_NO_ERROR;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class WiFiNetworkManagementServer : private AttributeAccessInterface, private Co
static_assert(std::numeric_limits<decltype(mSsidLen)>::max() >= sizeof(mSsid));
ByteSpan SsidSpan() const { return ByteSpan(mSsid, mSsidLen); }

uint64_t mPassphraseSurrogate = 0;
Crypto::SensitiveDataBuffer<64> mPassphrase;
ByteSpan PassphraseSpan() const { return mPassphrase.Span(); }

Expand Down
16 changes: 16 additions & 0 deletions src/app/tests/suites/certification/PICS.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10199,3 +10199,19 @@ PICS:

- label: "Does the device implement the ActiveEndpoints attribute?"
id: PWRTL.S.A0001

#
# Thread Network Directory Cluster
#
- label:
"Does the device implement the Thread Network Directory cluster as a
server"
id: THNETDIR.S

#
# Wi-Fi Network Management Cluster
#
- label:
"Does the device implement the Wi-Fi Network Management cluster as a
server"
id: WIFINM.S
Loading

0 comments on commit e8fb908

Please sign in to comment.