Skip to content

Commit

Permalink
Automation for new TC-CGEN-2.4 (#24560)
Browse files Browse the repository at this point in the history
* Python OpenWindow plumbing, fix RevokeCommissioning

Fixes two issues:
1) Revoke Commissioning leaves the failsafe timer armed which means
   you can't revoke then re-open the commissioning window
2) The python layer returned prematurely on window open and didn't
   plumb through the returne SetupPayload, so the enhanced window
   wasn't useable

Also adds a test for these two things.

* Fix return type

* automation for  CGEN-2.4

* Try again for cirque

* Restyled by autopep8

* Restyled by isort

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
2 people authored and pull[bot] committed Nov 28, 2023
1 parent b58dbd1 commit c64b152
Show file tree
Hide file tree
Showing 13 changed files with 601 additions and 18 deletions.
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=(
"SplitCommissioningTest"
"CommissioningFailureTest"
"CommissioningFailureOnReportTest"
"CommissioningWindowTest"
)

BOLD_GREEN_TEXT="\033[1;32m"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ bool emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(
{
ChipLogProgress(Zcl, "Received command to close commissioning window");

Server::GetInstance().GetFailSafeContext().ForceFailSafeTimerExpiry();

if (!Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen())
{
ChipLogError(Zcl, "Commissioning window is currently not open");
Expand Down
11 changes: 6 additions & 5 deletions src/controller/AutoCommissioner.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ class AutoCommissioner : public CommissioningDelegate
CommissioningStage GetNextCommissioningStage(CommissioningStage currentStage, CHIP_ERROR & lastErr);
DeviceCommissioner * GetCommissioner() { return mCommissioner; }
CHIP_ERROR PerformStep(CommissioningStage nextStage);
CommissioneeDeviceProxy * GetCommissioneeDeviceProxy() { return mCommissioneeDeviceProxy; }
/**
* The device argument to GetCommandTimeout is the device whose session will
* be used for sending the relevant command.
*/
Optional<System::Clock::Timeout> GetCommandTimeout(DeviceProxy * device, CommissioningStage stage) const;

private:
DeviceProxy * GetDeviceProxyForStep(CommissioningStage nextStage);
Expand All @@ -64,11 +70,6 @@ class AutoCommissioner : public CommissioningDelegate
ByteSpan GetPAI() const { return ByteSpan(mPAI, mPAILen); }

CHIP_ERROR NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, IdentityProtectionKeySpan ipk, NodeId adminSubject);
/**
* The device argument to GetCommandTimeout is the device whose session will
* be used for sending the relevant command.
*/
Optional<System::Clock::Timeout> GetCommandTimeout(DeviceProxy * device, CommissioningStage stage) const;
EndpointId GetEndpoint(const CommissioningStage & stage) const;
CommissioningStage GetNextCommissioningStageInternal(CommissioningStage currentStage, CHIP_ERROR & lastErr);

Expand Down
17 changes: 15 additions & 2 deletions src/controller/python/ChipDeviceController-ScriptBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ PyChipError pychip_ScriptDevicePairingDelegate_SetCommissioningCompleteCallback(
PyChipError pychip_ScriptDevicePairingDelegate_SetCommissioningStatusUpdateCallback(
chip::Controller::DeviceCommissioner * devCtrl,
chip::Controller::DevicePairingDelegate_OnCommissioningStatusUpdateFunct callback);
PyChipError pychip_ScriptDevicePairingDelegate_SetOpenWindowCompleteCallback(
chip::Controller::DeviceCommissioner * devCtrl, chip::Controller::DevicePairingDelegate_OnWindowOpenCompleteFunct callback);

// BLE
PyChipError pychip_DeviceCommissioner_CloseBleConnection(chip::Controller::DeviceCommissioner * devCtrl);
Expand Down Expand Up @@ -524,6 +526,13 @@ PyChipError pychip_DeviceController_DiscoverCommissionableNodesCommissioningEnab
return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter));
}

PyChipError pychip_ScriptDevicePairingDelegate_SetOpenWindowCompleteCallback(
chip::Controller::DeviceCommissioner * devCtrl, chip::Controller::DevicePairingDelegate_OnWindowOpenCompleteFunct callback)
{
sPairingDelegate.SetCommissioningWindowOpenCallback(callback);
return ToPyChipError(CHIP_NO_ERROR);
}

PyChipError pychip_DeviceController_OpenCommissioningWindow(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeid,
uint16_t timeout, uint32_t iteration, uint16_t discriminator,
uint8_t optionInt)
Expand All @@ -538,8 +547,12 @@ PyChipError pychip_DeviceController_OpenCommissioningWindow(chip::Controller::De
if (option == Controller::CommissioningWindowOpener::CommissioningWindowOption::kTokenWithRandomPIN)
{
SetupPayload payload;
return ToPyChipError(Controller::AutoCommissioningWindowOpener::OpenCommissioningWindow(
devCtrl, nodeid, System::Clock::Seconds16(timeout), iteration, discriminator, NullOptional, NullOptional, payload));
auto opener =
Platform::New<Controller::CommissioningWindowOpener>(static_cast<chip::Controller::DeviceController *>(devCtrl));
PyChipError err = ToPyChipError(opener->OpenCommissioningWindow(nodeid, System::Clock::Seconds16(timeout), iteration,
discriminator, NullOptional, NullOptional,
sPairingDelegate.GetOpenWindowCallback(opener), payload));
return err;
}

return ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,21 @@
#include "ChipDeviceController-ScriptDevicePairingDelegate.h"
#include "lib/support/TypeTraits.h"
#include <controller/python/chip/native/PyChipError.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>

namespace chip {
namespace Controller {

namespace {
void OnWindowCompleteStatic(void * context, NodeId deviceId, CHIP_ERROR status, SetupPayload payload)
{
auto self = reinterpret_cast<ScriptDevicePairingDelegate *>(context);
self->OnOpenCommissioningWindow(deviceId, status, payload);
}
} // namespace

ScriptDevicePairingDelegate::ScriptDevicePairingDelegate() : mOpenWindowCallback(OnWindowCompleteStatic, this) {}

void ScriptDevicePairingDelegate::SetKeyExchangeCallback(DevicePairingDelegate_OnPairingCompleteFunct callback)
{
mOnPairingCompleteCallback = callback;
Expand All @@ -34,6 +45,11 @@ void ScriptDevicePairingDelegate::SetCommissioningCompleteCallback(DevicePairing
mOnCommissioningCompleteCallback = callback;
}

void ScriptDevicePairingDelegate::SetCommissioningWindowOpenCallback(DevicePairingDelegate_OnWindowOpenCompleteFunct callback)
{
mOnWindowOpenCompleteCallback = callback;
}

void ScriptDevicePairingDelegate::SetCommissioningSuccessCallback(DevicePairingDelegate_OnCommissioningSuccessFunct callback)
{
mOnCommissioningSuccessCallback = callback;
Expand Down Expand Up @@ -91,5 +107,28 @@ void ScriptDevicePairingDelegate::OnCommissioningStatusUpdate(PeerId peerId, Com
}
}

void ScriptDevicePairingDelegate::OnOpenCommissioningWindow(NodeId deviceId, CHIP_ERROR status, SetupPayload payload)
{
if (mOnWindowOpenCompleteCallback != nullptr)
{
QRCodeSetupPayloadGenerator generator(payload);
std::string code;
generator.payloadBase38Representation(code);
ChipLogProgress(Zcl, "code = %s", code.c_str());
mOnWindowOpenCompleteCallback(deviceId, payload.setUpPINCode, code.c_str(), ToPyChipError(status));
}
if (mWindowOpener != nullptr)
{
Platform::Delete(mWindowOpener);
mWindowOpener = nullptr;
}
}
Callback::Callback<Controller::OnOpenCommissioningWindow> *
ScriptDevicePairingDelegate::GetOpenWindowCallback(Controller::CommissioningWindowOpener * context)
{
mWindowOpener = context;
return &mOpenWindowCallback;
}

} // namespace Controller
} // namespace chip
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#pragma once

#include <controller/CHIPDeviceController.h>
#include <controller/CommissioningWindowOpener.h>
#include <controller/python/chip/native/PyChipError.h>

namespace chip {
Expand All @@ -34,6 +35,8 @@ namespace Controller {
extern "C" {
typedef void (*DevicePairingDelegate_OnPairingCompleteFunct)(PyChipError err);
typedef void (*DevicePairingDelegate_OnCommissioningCompleteFunct)(NodeId nodeId, PyChipError err);
typedef void (*DevicePairingDelegate_OnWindowOpenCompleteFunct)(NodeId nodeId, uint32_t setupPinCode, const char * setupCode,
PyChipError err);

// Used for testing by OpCredsBinding
typedef void (*DevicePairingDelegate_OnCommissioningSuccessFunct)(PeerId peerId);
Expand All @@ -48,25 +51,33 @@ typedef void (*DevicePairingDelegate_OnCommissioningStatusUpdateFunct)(PeerId pe
class ScriptDevicePairingDelegate final : public Controller::DevicePairingDelegate
{
public:
ScriptDevicePairingDelegate();
~ScriptDevicePairingDelegate() = default;
void SetKeyExchangeCallback(DevicePairingDelegate_OnPairingCompleteFunct callback);
void SetCommissioningCompleteCallback(DevicePairingDelegate_OnCommissioningCompleteFunct callback);
void SetCommissioningStatusUpdateCallback(DevicePairingDelegate_OnCommissioningStatusUpdateFunct callback);
void SetCommissioningSuccessCallback(DevicePairingDelegate_OnCommissioningSuccessFunct callback);
void SetCommissioningFailureCallback(DevicePairingDelegate_OnCommissioningFailureFunct callback);
void SetCommissioningWindowOpenCallback(DevicePairingDelegate_OnWindowOpenCompleteFunct callback);
void OnPairingComplete(CHIP_ERROR error) override;
void OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) override;
void OnCommissioningSuccess(PeerId peerId) override;
void OnCommissioningFailure(PeerId peerId, CHIP_ERROR error, CommissioningStage stageFailed,
Optional<Credentials::AttestationVerificationResult> additionalErrorInfo) override;
void OnCommissioningStatusUpdate(PeerId peerId, CommissioningStage stageCompleted, CHIP_ERROR error) override;
Callback::Callback<Controller::OnOpenCommissioningWindow> *
GetOpenWindowCallback(Controller::CommissioningWindowOpener * context);
void OnOpenCommissioningWindow(NodeId deviceId, CHIP_ERROR status, SetupPayload payload);

private:
DevicePairingDelegate_OnPairingCompleteFunct mOnPairingCompleteCallback = nullptr;
DevicePairingDelegate_OnCommissioningCompleteFunct mOnCommissioningCompleteCallback = nullptr;
DevicePairingDelegate_OnWindowOpenCompleteFunct mOnWindowOpenCompleteCallback = nullptr;
DevicePairingDelegate_OnCommissioningSuccessFunct mOnCommissioningSuccessCallback = nullptr;
DevicePairingDelegate_OnCommissioningFailureFunct mOnCommissioningFailureCallback = nullptr;
DevicePairingDelegate_OnCommissioningStatusUpdateFunct mOnCommissioningStatusUpdateCallback = nullptr;
Callback::Callback<Controller::OnOpenCommissioningWindow> mOpenWindowCallback;
Controller::CommissioningWindowOpener * mWindowOpener = nullptr;
};

} // namespace Controller
Expand Down
63 changes: 61 additions & 2 deletions src/controller/python/OpCredsBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,30 @@ class TestCommissioner : public chip::Controller::AutoCommissioner
// Pretend we received an error from the device during this stage
err = CHIP_ERROR_INTERNAL;
}
if (mPrematureCompleteAfter == report.stageCompleted)
{
auto commissioner = chip::Controller::AutoCommissioner::GetCommissioner();
auto proxy = chip::Controller::AutoCommissioner::GetCommissioneeDeviceProxy();
auto stage = chip::Controller::CommissioningStage::kSendComplete;
auto params = chip::Controller::CommissioningParameters();
commissioner->PerformCommissioningStep(proxy, stage, params, this, 0, GetCommandTimeout(proxy, stage));
return CHIP_NO_ERROR;
}

if (mPrematureCompleteAfter != chip::Controller::CommissioningStage::kError &&
report.stageCompleted == chip::Controller::CommissioningStage::kSendComplete)
{
if (report.Is<chip::Controller::CommissioningErrorInfo>())
{
uint8_t code = chip::to_underlying(report.Get<chip::Controller::CommissioningErrorInfo>().commissioningError);
mCompletionError = chip::ChipError(chip::ChipError::SdkPart::kIMClusterStatus, code);
}
else
{
mCompletionError = err;
}
}

return chip::Controller::AutoCommissioner::CommissioningStepFinished(err, report);
}
// This will cause the COMMISSIONER to fail after the given stage. Setting this to kSecurePairing will cause the
Expand All @@ -156,6 +180,15 @@ class TestCommissioner : public chip::Controller::AutoCommissioner
mFailOnReportAfterStage = stage;
return true;
}
bool PrematureCompleteAfter(chip::Controller::CommissioningStage stage)
{
if (!ValidStage(stage) && stage != chip::Controller::CommissioningStage::kError)
{
return false;
}
mPrematureCompleteAfter = stage;
return true;
}
bool CheckCallbacks()
{
bool successFailureOk;
Expand Down Expand Up @@ -208,6 +241,7 @@ class TestCommissioner : public chip::Controller::AutoCommissioner
}
mSimulateFailureOnStage = chip::Controller::CommissioningStage::kError;
mFailOnReportAfterStage = chip::Controller::CommissioningStage::kError;
mPrematureCompleteAfter = chip::Controller::CommissioningStage::kError;
}
bool GetTestCommissionerUsed() { return mTestCommissionerUsed; }
void OnCommissioningSuccess(chip::PeerId peerId) { mReceivedCommissioningSuccess = true; }
Expand All @@ -226,19 +260,35 @@ class TestCommissioner : public chip::Controller::AutoCommissioner
{
mReceivedStageFailure[chip::to_underlying(stageCompleted)] = true;
}
if (stageCompleted == chip::Controller::CommissioningStage::kCleanup &&
mPrematureCompleteAfter != chip::Controller::CommissioningStage::kError)
{
// We need to manually clean up the proxy here because we're doing bad things in the name of testing
ChipLogProgress(Controller, "Cleaning up dangling proxies");
auto commissioner = chip::Controller::AutoCommissioner::GetCommissioner();
auto proxy = chip::Controller::AutoCommissioner::GetCommissioneeDeviceProxy();
if (proxy != nullptr)
{
commissioner->StopPairing(proxy->GetDeviceId());
}
}
}

CHIP_ERROR GetCompletionError() { return mCompletionError; }

private:
static constexpr uint8_t kNumCommissioningStages = chip::to_underlying(chip::Controller::CommissioningStage::kCleanup) + 1;
chip::Controller::CommissioningStage mSimulateFailureOnStage = chip::Controller::CommissioningStage::kError;
chip::Controller::CommissioningStage mFailOnReportAfterStage = chip::Controller::CommissioningStage::kError;
chip::Controller::CommissioningStage mPrematureCompleteAfter = chip::Controller::CommissioningStage::kError;
bool mTestCommissionerUsed = false;
bool mReceivedCommissioningSuccess = false;
chip::Controller::CommissioningStage mReceivedCommissioningFailureStage = chip::Controller::CommissioningStage::kError;
bool mReceivedStageSuccess[kNumCommissioningStages];
bool mReceivedStageFailure[kNumCommissioningStages];
bool mIsWifi = false;
bool mIsThread = false;
bool mIsWifi = false;
bool mIsThread = false;
CHIP_ERROR mCompletionError = CHIP_NO_ERROR;
bool ValidStage(chip::Controller::CommissioningStage stage)
{
if (!mIsWifi &&
Expand Down Expand Up @@ -469,5 +519,14 @@ bool pychip_SetTestCommissionerSimulateFailureOnReport(uint8_t failStage)
{
return sTestCommissioner.SimulateFailOnReport(static_cast<chip::Controller::CommissioningStage>(failStage));
}
bool pychip_SetTestCommissionerPrematureCompleteAfter(uint8_t stage)
{
return sTestCommissioner.PrematureCompleteAfter(static_cast<chip::Controller::CommissioningStage>(stage));
}

PyChipError pychip_GetCompletionError()
{
return ToPyChipError(sTestCommissioner.GetCompletionError());
}

} // extern "C"
Loading

0 comments on commit c64b152

Please sign in to comment.