blob: d268898c94615b389e48b323d34f50dd567099aa [file]
/*
* Copyright (c) 2026 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 <pw_unit_test/framework.h>
#include <app/clusters/microwave-oven-control-server/MicrowaveOvenControlCluster.h>
#include <app/server-cluster/AttributeListBuilder.h>
#include <app/server-cluster/testing/AttributeTesting.h>
#include <app/server-cluster/testing/ClusterTester.h>
#include <app/server-cluster/testing/TestServerClusterContext.h>
#include <app/server-cluster/testing/ValidateGlobalAttributes.h>
namespace {
using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::MicrowaveOvenControl;
using namespace chip::app::Clusters::MicrowaveOvenControl::Attributes;
using namespace chip::Testing;
using Status = Protocols::InteractionModel::Status;
using AppDelegate = MicrowaveOvenControl::AppDelegate;
constexpr uint32_t kDefaultCookTimeSec = 30u;
class TestIntegrationDelegate : public IntegrationDelegate
{
public:
virtual uint8_t GetCurrentOperationalState() const override { return 0; }
virtual CHIP_ERROR GetNormalOperatingMode(uint8_t & mode) const override
{
mode = 0;
return CHIP_NO_ERROR;
}
virtual bool IsSupportedMode(uint8_t mode) const override { return mode == 0; }
virtual bool IsSupportedOperationalStateCommand(EndpointId endpointId, CommandId commandId) const override
{
return endpointId == kRootEndpointId && commandId == OperationalState::Commands::Start::Id;
}
};
class TestDelegate : public AppDelegate
{
public:
Protocols::InteractionModel::Status HandleSetCookingParametersCallback(uint8_t cookMode, uint32_t cookTimeSec,
bool startAfterSetting,
Optional<uint8_t> powerSettingNum,
Optional<uint8_t> wattSettingIndex) override
{
return Protocols::InteractionModel::Status::Success;
}
Protocols::InteractionModel::Status HandleModifyCookTimeSecondsCallback(uint32_t finalcookTimeSec) override
{
return Protocols::InteractionModel::Status::Success;
}
CHIP_ERROR GetWattSettingByIndex(uint8_t index, uint16_t & wattSetting) override
{
VerifyOrReturnError(index < MATTER_ARRAY_SIZE(mWattSettingList), CHIP_ERROR_NOT_FOUND);
wattSetting = mWattSettingList[index];
return CHIP_NO_ERROR;
}
uint8_t GetPowerSettingNum() const override { return mPowerSettingNum; }
uint8_t GetMinPowerNum() const override { return kMinPowerNum; }
uint8_t GetMaxPowerNum() const override { return kMaxPowerNum; }
uint8_t GetPowerStepNum() const override { return kPowerStepNum; }
uint8_t GetCurrentWattIndex() const override { return mSelectedWattIndex; };
uint32_t GetMaxCookTimeSec() const override { return kMaxCookTimeSec; }
uint16_t GetWattRating() const override { return mWattRating; };
private:
static constexpr uint8_t kMinPowerNum = 20u;
static constexpr uint8_t kMaxPowerNum = 90u;
static constexpr uint8_t kPowerStepNum = 10u;
static constexpr uint32_t kMaxCookTimeSec = 86400u;
static constexpr uint8_t kDefaultPowerSettingNum = kMaxPowerNum;
uint8_t mPowerSettingNum = kDefaultPowerSettingNum;
uint8_t mSelectedWattIndex = 0;
uint16_t mWattRating = 0;
const uint16_t mWattSettingList[5] = { 100u, 300u, 500u, 800u, 1000u };
};
struct TestMicrowaveOvenControlCluster : public ::testing::Test
{
static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); }
static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); }
TestMicrowaveOvenControlCluster() {}
TestServerClusterContext testContext;
TestDelegate testDelegate;
bool supportsAddMoreTime{};
MicrowaveOvenControlCluster::OptionalAttributeSet optionalAttributeSet{};
TestIntegrationDelegate testIntegrationDelegate;
MicrowaveOvenControlCluster::Config defaultConfig{
.feature = BitFlags<Feature>{},
.optionalAttributeSet = optionalAttributeSet,
.supportsAddMoreTime = supportsAddMoreTime,
.integrationDelegate = testIntegrationDelegate,
.appDelegate = testDelegate,
};
};
void TestMandatoryAttributes(ClusterTester & tester, Feature feature, TestDelegate & delegate)
{
uint16_t revision{};
ASSERT_EQ(tester.ReadAttribute(ClusterRevision::Id, revision), CHIP_NO_ERROR);
ASSERT_EQ(revision, MicrowaveOvenControl::kRevision);
uint32_t featureMap{};
ASSERT_EQ(tester.ReadAttribute(FeatureMap::Id, featureMap), CHIP_NO_ERROR);
ASSERT_EQ(featureMap, to_underlying(feature));
uint32_t cookTime{};
ASSERT_EQ(tester.ReadAttribute(CookTime::Id, cookTime), CHIP_NO_ERROR);
ASSERT_EQ(cookTime, kDefaultCookTimeSec);
uint32_t maxCookTime{};
ASSERT_EQ(tester.ReadAttribute(MaxCookTime::Id, maxCookTime), CHIP_NO_ERROR);
ASSERT_EQ(maxCookTime, delegate.GetMaxCookTimeSec());
}
} // namespace
TEST_F(TestMicrowaveOvenControlCluster, AttributeTest)
{
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
EXPECT_TRUE(IsAttributesListEqualTo(cluster,
{
CookTime::kMetadataEntry,
MaxCookTime::kMetadataEntry,
}));
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.optionalAttributeSet.Set<WattRating::Id>();
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
EXPECT_TRUE(IsAttributesListEqualTo(cluster,
{
CookTime::kMetadataEntry,
MaxCookTime::kMetadataEntry,
WattRating::kMetadataEntry,
}));
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.feature = Feature::kPowerAsNumber;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
EXPECT_TRUE(IsAttributesListEqualTo(cluster,
{
CookTime::kMetadataEntry,
MaxCookTime::kMetadataEntry,
PowerSetting::kMetadataEntry,
}));
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.feature = Feature::kPowerNumberLimits;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
EXPECT_TRUE(IsAttributesListEqualTo(cluster,
{
CookTime::kMetadataEntry,
MaxCookTime::kMetadataEntry,
MinPower::kMetadataEntry,
MaxPower::kMetadataEntry,
PowerStep::kMetadataEntry,
}));
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.feature = Feature::kPowerInWatts;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
EXPECT_TRUE(IsAttributesListEqualTo(cluster,
{
CookTime::kMetadataEntry,
MaxCookTime::kMetadataEntry,
SupportedWatts::kMetadataEntry,
SelectedWattIndex::kMetadataEntry,
}));
}
}
TEST_F(TestMicrowaveOvenControlCluster, ReadAttributeTest)
{
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ClusterTester tester(cluster);
TestMandatoryAttributes(tester, config.feature, testDelegate);
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.optionalAttributeSet.Set<WattRating::Id>();
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ClusterTester tester(cluster);
TestMandatoryAttributes(tester, config.feature, testDelegate);
uint16_t wattRating{};
ASSERT_EQ(tester.ReadAttribute(WattRating::Id, wattRating), CHIP_NO_ERROR);
ASSERT_EQ(wattRating, testDelegate.GetWattRating());
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.feature = Feature::kPowerAsNumber;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ClusterTester tester(cluster);
TestMandatoryAttributes(tester, config.feature, testDelegate);
uint8_t powerSetting{};
ASSERT_EQ(tester.ReadAttribute(PowerSetting::Id, powerSetting), CHIP_NO_ERROR);
ASSERT_EQ(powerSetting, testDelegate.GetPowerSettingNum());
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.feature = Feature::kPowerNumberLimits;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ClusterTester tester(cluster);
TestMandatoryAttributes(tester, config.feature, testDelegate);
uint8_t minPower{};
ASSERT_EQ(tester.ReadAttribute(MinPower::Id, minPower), CHIP_NO_ERROR);
ASSERT_EQ(minPower, testDelegate.GetMinPowerNum());
uint8_t maxPower{};
ASSERT_EQ(tester.ReadAttribute(MaxPower::Id, maxPower), CHIP_NO_ERROR);
ASSERT_EQ(maxPower, testDelegate.GetMaxPowerNum());
uint8_t powerStep{};
ASSERT_EQ(tester.ReadAttribute(PowerStep::Id, powerStep), CHIP_NO_ERROR);
ASSERT_EQ(powerStep, testDelegate.GetPowerStepNum());
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.feature = Feature::kPowerInWatts;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ClusterTester tester(cluster);
TestMandatoryAttributes(tester, config.feature, testDelegate);
DataModel::DecodableList<uint16_t> supportedWatts;
ASSERT_EQ(tester.ReadAttribute(SupportedWatts::Id, supportedWatts), CHIP_NO_ERROR);
auto it = supportedWatts.begin();
ASSERT_TRUE(it.Next());
ASSERT_TRUE(it.GetValue() == 100u);
ASSERT_TRUE(it.Next());
ASSERT_TRUE(it.GetValue() == 300u);
ASSERT_TRUE(it.Next());
ASSERT_TRUE(it.GetValue() == 500u);
ASSERT_TRUE(it.Next());
ASSERT_TRUE(it.GetValue() == 800u);
ASSERT_TRUE(it.Next());
ASSERT_TRUE(it.GetValue() == 1000u);
ASSERT_FALSE(it.Next());
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
}
TEST_F(TestMicrowaveOvenControlCluster, SetCookTimeSecTest)
{
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ASSERT_EQ(cluster.SetCookTimeSec(0), CHIP_IM_GLOBAL_STATUS(ConstraintError));
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ASSERT_EQ(cluster.SetCookTimeSec(1), CHIP_NO_ERROR);
ASSERT_EQ(cluster.GetCookTimeSec(), 1u);
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ASSERT_EQ(cluster.SetCookTimeSec(testDelegate.GetMaxCookTimeSec()), CHIP_NO_ERROR);
ASSERT_EQ(cluster.GetCookTimeSec(), testDelegate.GetMaxCookTimeSec());
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ASSERT_EQ(cluster.SetCookTimeSec(testDelegate.GetMaxCookTimeSec() + 1), CHIP_IM_GLOBAL_STATUS(ConstraintError));
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
}
TEST_F(TestMicrowaveOvenControlCluster, AcceptedCommandsTest)
{
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ReadOnlyBufferBuilder<DataModel::AcceptedCommandEntry> builder;
ASSERT_EQ(cluster.AcceptedCommands(ConcreteClusterPath(kRootEndpointId, MicrowaveOvenControl::Id), builder), CHIP_NO_ERROR);
ReadOnlyBuffer<DataModel::AcceptedCommandEntry> acceptedCommands = builder.TakeBuffer();
ASSERT_EQ(acceptedCommands.size(), 1u);
ASSERT_EQ(acceptedCommands[0].commandId, MicrowaveOvenControl::Commands::SetCookingParameters::Id);
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
{
MicrowaveOvenControlCluster::Config config = defaultConfig;
config.supportsAddMoreTime = true;
MicrowaveOvenControlCluster cluster(kRootEndpointId, config);
ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR);
ReadOnlyBufferBuilder<DataModel::AcceptedCommandEntry> builder;
ASSERT_EQ(cluster.AcceptedCommands(ConcreteClusterPath(kRootEndpointId, MicrowaveOvenControl::Id), builder), CHIP_NO_ERROR);
ReadOnlyBuffer<DataModel::AcceptedCommandEntry> acceptedCommands = builder.TakeBuffer();
ASSERT_EQ(acceptedCommands.size(), 2u);
ASSERT_EQ(acceptedCommands[0].commandId, MicrowaveOvenControl::Commands::SetCookingParameters::Id);
ASSERT_EQ(acceptedCommands[1].commandId, MicrowaveOvenControl::Commands::AddMoreTime::Id);
cluster.Shutdown(ClusterShutdownType::kClusterShutdown);
}
}