From 5a9ae85462fa9aa2455f0111117ef14ce9950cc4 Mon Sep 17 00:00:00 2001 From: Abdul Samad Date: Tue, 9 Jul 2024 12:53:22 -0500 Subject: [PATCH] Add arg tests for new methods in `CommissioningWindowOpener` --- src/controller/CHIPDeviceController.h | 19 +- src/controller/tests/BUILD.gn | 5 +- .../tests/TestCommissioningWindowOpener.cpp | 183 ++++++++++++++++++ 3 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 src/controller/tests/TestCommissioningWindowOpener.cpp diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 1ab85ca0dc182b..85eeeae165a099 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -167,6 +167,16 @@ struct CommissionerInitParams : public ControllerInitParams Credentials::DeviceAttestationVerifier * deviceAttestationVerifier = nullptr; }; +// Interface class for DeviceController methods that need to be mocked +class IDeviceController +{ +public: + virtual ~IDeviceController() = default; + virtual CHIP_ERROR GetConnectedDevice(NodeId peerNodeId, chip::Callback::Callback * onConnection, + chip::Callback::Callback * onFailure, + TransportPayloadCapability transportPayloadCapability) = 0; +}; + /** * @brief * Controller applications can use this class to communicate with already paired CHIP devices. The @@ -175,7 +185,7 @@ struct CommissionerInitParams : public ControllerInitParams * and device pairing information for individual devices). Alternatively, this class can retrieve the * relevant information when the application tries to communicate with the device */ -class DLL_EXPORT DeviceController : public AbstractDnssdDiscoveryController +class DLL_EXPORT DeviceController : public AbstractDnssdDiscoveryController, IDeviceController { public: DeviceController(); @@ -243,9 +253,10 @@ class DLL_EXPORT DeviceController : public AbstractDnssdDiscoveryController * An error return from this function means that neither callback has been * called yet, and neither callback will be called in the future. */ - CHIP_ERROR GetConnectedDevice(NodeId peerNodeId, Callback::Callback * onConnection, - chip::Callback::Callback * onFailure, - TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload) + CHIP_ERROR + GetConnectedDevice(NodeId peerNodeId, Callback::Callback * onConnection, + chip::Callback::Callback * onFailure, + TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload) override { VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); mSystemState->CASESessionMgr()->FindOrEstablishSession(ScopedNodeId(peerNodeId, GetFabricIndex()), onConnection, onFailure, diff --git a/src/controller/tests/BUILD.gn b/src/controller/tests/BUILD.gn index 1e2b15d7778beb..638ebfc1e24562 100644 --- a/src/controller/tests/BUILD.gn +++ b/src/controller/tests/BUILD.gn @@ -21,7 +21,10 @@ import("${chip_root}/build/chip/chip_test_suite.gni") chip_test_suite("tests") { output_name = "libControllerTests" - test_sources = [ "TestCommissionableNodeController.cpp" ] + test_sources = [ + "TestCommissionableNodeController.cpp", + "TestCommissioningWindowOpener.cpp", + ] if (chip_device_platform != "mbed" && chip_device_platform != "efr32" && chip_device_platform != "esp32") { diff --git a/src/controller/tests/TestCommissioningWindowOpener.cpp b/src/controller/tests/TestCommissioningWindowOpener.cpp new file mode 100644 index 00000000000000..52f1f4194aed1e --- /dev/null +++ b/src/controller/tests/TestCommissioningWindowOpener.cpp @@ -0,0 +1,183 @@ +/* + * + * Copyright (c) 2024 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. + */ + +#include + +#include +#include +#include +#include + +using namespace chip; + +namespace { + +class MockDeviceController : public Controller::DeviceController +{ +public: + CHIP_ERROR + GetConnectedDevice(NodeId peerNodeId, Callback::Callback * onConnection, + Callback::Callback * onFailure, + TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload) override + { + return CHIP_NO_ERROR; + } +}; + +// Valid crypto values from src/protocols/secure_channel/tests/TestPASESession.cpp +constexpr uint32_t sTestSpake2p01_PinCode = 20202021; +constexpr uint32_t sTestSpake2p01_IterationCount = 1000; +constexpr uint8_t sTestSpake2p01_Salt[] = { 0x53, 0x50, 0x41, 0x4B, 0x45, 0x32, 0x50, 0x20, + 0x4B, 0x65, 0x79, 0x20, 0x53, 0x61, 0x6C, 0x74 }; +constexpr Crypto::Spake2pVerifierSerialized sTestSpake2p01_SerializedVerifier = { + 0xB9, 0x61, 0x70, 0xAA, 0xE8, 0x03, 0x34, 0x68, 0x84, 0x72, 0x4F, 0xE9, 0xA3, 0xB2, 0x87, 0xC3, 0x03, 0x30, 0xC2, 0xA6, + 0x60, 0x37, 0x5D, 0x17, 0xBB, 0x20, 0x5A, 0x8C, 0xF1, 0xAE, 0xCB, 0x35, 0x04, 0x57, 0xF8, 0xAB, 0x79, 0xEE, 0x25, 0x3A, + 0xB6, 0xA8, 0xE4, 0x6B, 0xB0, 0x9E, 0x54, 0x3A, 0xE4, 0x22, 0x73, 0x6D, 0xE5, 0x01, 0xE3, 0xDB, 0x37, 0xD4, 0x41, 0xFE, + 0x34, 0x49, 0x20, 0xD0, 0x95, 0x48, 0xE4, 0xC1, 0x82, 0x40, 0x63, 0x0C, 0x4F, 0xF4, 0x91, 0x3C, 0x53, 0x51, 0x38, 0x39, + 0xB7, 0xC0, 0x7F, 0xCC, 0x06, 0x27, 0xA1, 0xB8, 0x57, 0x3A, 0x14, 0x9F, 0xCD, 0x1F, 0xA4, 0x66, 0xCF +}; + +static void OCWPasscodeCallback(void * context, NodeId deviceId, CHIP_ERROR status, SetupPayload payload) {} +static void OCWVerifierCallback(void * context, NodeId deviceId, CHIP_ERROR status) {} + +class TestCommissioningWindowOpener : public ::testing::Test +{ +public: + static void SetUpTestSuite() { ASSERT_EQ(Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { Platform::MemoryShutdown(); } + +protected: + // Initialize with a null pointer for now, replace with a valid controller pointer if available + MockDeviceController mockController; + Controller::CommissioningWindowOpener opener = Controller::CommissioningWindowOpener(&mockController); +}; + +TEST_F(TestCommissioningWindowOpener, OpenCommissioningWindowVerifier_Success) +{ + Callback::Callback callback(OCWVerifierCallback, this); + + CHIP_ERROR err = opener.OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams() + .SetNodeId(0x1234) + .SetTimeout(300) + .SetIteration(sTestSpake2p01_IterationCount) + .SetDiscriminator(3840) + .SetSalt(ByteSpan(sTestSpake2p01_Salt)) + .SetVerifier(ByteSpan(sTestSpake2p01_SerializedVerifier)), + &callback); + EXPECT_EQ(err, CHIP_NO_ERROR); +} + +TEST_F(TestCommissioningWindowOpener, OpenCommissioningWindowVerifier_Failure_NoSalt) +{ + Callback::Callback callback(OCWVerifierCallback, this); + + CHIP_ERROR err = opener.OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams() + .SetNodeId(0x1234) + .SetTimeout(300) + .SetIteration(sTestSpake2p01_IterationCount) + .SetDiscriminator(3840) + .SetVerifier(ByteSpan(sTestSpake2p01_SerializedVerifier)), + &callback); + EXPECT_EQ(err, CHIP_ERROR_INVALID_ARGUMENT); +} + +TEST_F(TestCommissioningWindowOpener, OpenCommissioningWindowVerifier_Failure_NoVerifier) +{ + Callback::Callback callback(OCWVerifierCallback, this); + + CHIP_ERROR err = opener.OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams() + .SetNodeId(0x1234) + .SetTimeout(300) + .SetIteration(sTestSpake2p01_IterationCount) + .SetDiscriminator(3840) + .SetSalt(ByteSpan(sTestSpake2p01_Salt)), + &callback); + EXPECT_EQ(err, CHIP_ERROR_INVALID_ARGUMENT); +} + +TEST_F(TestCommissioningWindowOpener, OpenCommissioningWindowVerifier_Failure_InvalidIteration) +{ + Callback::Callback callback(OCWVerifierCallback, this); + + CHIP_ERROR err = opener.OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams() + .SetNodeId(0x1234) + .SetTimeout(300) + .SetIteration(0) + .SetDiscriminator(3840) + .SetSalt(ByteSpan(sTestSpake2p01_Salt)) + .SetVerifier(ByteSpan(sTestSpake2p01_SerializedVerifier)), + &callback); + EXPECT_EQ(err, CHIP_ERROR_INVALID_ARGUMENT); +} + +TEST_F(TestCommissioningWindowOpener, OpenCommissioningWindowPasscode_Success) +{ + SetupPayload ignored; + Callback::Callback callback(OCWPasscodeCallback, this); + CHIP_ERROR err = opener.OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams() + .SetNodeId(0x1234) + .SetTimeout(300) + .SetIteration(sTestSpake2p01_IterationCount) + .SetDiscriminator(3840) + .SetSetupPIN(sTestSpake2p01_PinCode) + .SetReadVIDPIDAttributes(true) + .SetSalt(ByteSpan(sTestSpake2p01_Salt)), + &callback, ignored); + EXPECT_EQ(err, CHIP_NO_ERROR); +} + +TEST_F(TestCommissioningWindowOpener, OpenCommissioningWindowPasscode_Success_NoPin) +{ + SetupPayload ignored; + Callback::Callback callback(OCWPasscodeCallback, this); + CHIP_ERROR err = opener.OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams() + .SetNodeId(0x1234) + .SetTimeout(300) + .SetIteration(sTestSpake2p01_IterationCount) + .SetDiscriminator(3840) + .SetSalt(ByteSpan(sTestSpake2p01_Salt)), + &callback, ignored); + EXPECT_EQ(err, CHIP_NO_ERROR); +} + +TEST_F(TestCommissioningWindowOpener, OpenCommissioningWindowPasscode_Success_NoSalt) +{ + SetupPayload ignored; + Callback::Callback callback(OCWPasscodeCallback, this); + CHIP_ERROR err = opener.OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams() + .SetNodeId(0x1234) + .SetTimeout(300) + .SetIteration(sTestSpake2p01_IterationCount) + .SetDiscriminator(3840) + .SetSetupPIN(sTestSpake2p01_PinCode), + &callback, ignored); + EXPECT_EQ(err, CHIP_NO_ERROR); +} + +TEST_F(TestCommissioningWindowOpener, OpenCommissioningWindowPasscode_Failure_InvalidIteration) +{ + SetupPayload ignored; + Callback::Callback callback(OCWPasscodeCallback, this); + CHIP_ERROR err = opener.OpenCommissioningWindow( + Controller::CommissioningWindowPasscodeParams().SetNodeId(0x1234).SetTimeout(300).SetIteration(0).SetDiscriminator(3840), + &callback, ignored); + EXPECT_EQ(err, CHIP_ERROR_INVALID_ARGUMENT); +} + +// Add more test cases as needed to cover different scenarios +} // namespace