1+ // File: third_party/matter_sdk/src/app/tests/TestColorControlServer.cpp
2+ /*
3+ * Copyright (c) 2025 Project CHIP Authors
4+ *
5+ * Licensed under the Apache License, Version 2.0 (the "License");
6+ * you may not use this file except in compliance with the License.
7+ * You may obtain a copy of the License at
8+ *
9+ * http://www.apache.org/licenses/LICENSE-2.0
10+ *
11+ * Unless required by applicable law or agreed to in writing, software
12+ * distributed under the License is distributed on an "AS IS" BASIS,
13+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+ * See the License for the specific language governing permissions and
15+ * limitations under the License.
16+ */
17+
18+ #include < pw_unit_test/framework.h>
19+
20+ #include < app-common/zap-generated/attributes/Accessors.h>
21+ #include < app/tests/test-ember-api.h>
22+ #include < app/util/mock/Functions.h>
23+ #include < app/util/mock/MockNodeConfig.h>
24+ #include < lib/support/BitMask.h>
25+ #include < lib/support/CHIPMem.h>
26+ #include < limits>
27+
28+ #define private public
29+ #define protected public
30+ #include < app/clusters/color-control-server/color-control-server.h>
31+ #undef private
32+ #undef protected
33+
34+ using namespace chip ;
35+ using namespace chip ::app;
36+ using namespace chip ::app::Clusters;
37+ using chip::BitMask;
38+ using OptionsBitmap = ColorControl::OptionsBitmap;
39+
40+ namespace {
41+
42+ constexpr EndpointId kTestEndpoint = 1 ;
43+
44+ Test::MockNodeConfig gMockNodeConfig ({
45+ Test::MockEndpointConfig (
46+ kTestEndpoint ,
47+ {
48+ Test::MockClusterConfig (
49+ ColorControl::Id,
50+ {
51+ Test::MockAttributeConfig (ColorControl::Attributes::FeatureMap::Id, ZCL_BITMAP32_ATTRIBUTE_TYPE),
52+ Test::MockAttributeConfig (ColorControl::Attributes::Options::Id, ZCL_BITMAP8_ATTRIBUTE_TYPE),
53+ }),
54+ Test::MockClusterConfig (
55+ OnOff::Id,
56+ {
57+ Test::MockAttributeConfig (OnOff::Attributes::OnOff::Id, ZCL_BOOLEAN_ATTRIBUTE_TYPE),
58+ Test::MockAttributeConfig (OnOff::Attributes::FeatureMap::Id, ZCL_BITMAP32_ATTRIBUTE_TYPE),
59+ }),
60+ })
61+ });
62+
63+ } // namespace
64+
65+ class TestColorControlServer : public ::testing::Test
66+ {
67+ public:
68+ static void SetUpTestSuite ()
69+ {
70+ ASSERT_EQ (Platform::MemoryInit (), CHIP_NO_ERROR);
71+ Test::SetMockNodeConfig (gMockNodeConfig );
72+ Test::numEndpoints = static_cast <EndpointId>(gMockNodeConfig .endpoints .size ());
73+ }
74+
75+ static void TearDownTestSuite ()
76+ {
77+ Test::ResetMockNodeConfig ();
78+ Test::numEndpoints = 0 ;
79+ Platform::MemoryShutdown ();
80+ }
81+
82+ void SetUp () override
83+ {
84+ ColorControl::Attributes::FeatureMap::Set (kTestEndpoint , 0 );
85+ ColorControl::Attributes::Options::Set (kTestEndpoint , BitMask<OptionsBitmap>());
86+ OnOff::Attributes::OnOff::Set (kTestEndpoint , true );
87+ }
88+
89+ ColorControlServer & Server () { return ColorControlServer::Instance (); }
90+ };
91+
92+ TEST_F (TestColorControlServer, HasFeatureReflectsFeatureMapBits)
93+ {
94+ EXPECT_FALSE (Server ().HasFeature (kTestEndpoint , ColorControlServer::Feature::kXy ));
95+
96+ uint32_t featureMap = to_underlying (ColorControlServer::Feature::kXy ) |
97+ to_underlying (ColorControlServer::Feature::kHueAndSaturation );
98+ ColorControl::Attributes::FeatureMap::Set (kTestEndpoint , featureMap);
99+
100+ EXPECT_TRUE (Server ().HasFeature (kTestEndpoint , ColorControlServer::Feature::kXy ));
101+ EXPECT_TRUE (Server ().HasFeature (kTestEndpoint , ColorControlServer::Feature::kHueAndSaturation ));
102+ EXPECT_FALSE (Server ().HasFeature (kTestEndpoint , ColorControlServer::Feature::kColorTemperature ));
103+ }
104+
105+ TEST_F (TestColorControlServer, ShouldExecuteIfOffReturnsTrueWhenDeviceOn)
106+ {
107+ OnOff::Attributes::OnOff::Set (kTestEndpoint , true );
108+ EXPECT_TRUE (Server ().shouldExecuteIfOff (kTestEndpoint , BitMask<OptionsBitmap>(), BitMask<OptionsBitmap>()));
109+ }
110+
111+ TEST_F (TestColorControlServer, ShouldExecuteIfOffHonorsExecuteIfOffAttribute)
112+ {
113+ OnOff::Attributes::OnOff::Set (kTestEndpoint , false );
114+
115+ BitMask<OptionsBitmap> options;
116+ options.Set (OptionsBitmap::kExecuteIfOff );
117+ ColorControl::Attributes::Options::Set (kTestEndpoint , options);
118+
119+ auto absent = BitMask<OptionsBitmap>(static_cast <uint8_t >(0xFF ));
120+ EXPECT_TRUE (Server ().shouldExecuteIfOff (kTestEndpoint , absent, absent));
121+ }
122+
123+ TEST_F (TestColorControlServer, ShouldExecuteIfOffDefaultsToFalseWithoutExecuteBit)
124+ {
125+ OnOff::Attributes::OnOff::Set (kTestEndpoint , false );
126+
127+ auto absent = BitMask<OptionsBitmap>(static_cast <uint8_t >(0xFF ));
128+ EXPECT_FALSE (Server ().shouldExecuteIfOff (kTestEndpoint , absent, absent));
129+ }
130+
131+ TEST_F (TestColorControlServer, ShouldExecuteIfOffUsesOverrideWhenMaskProvided)
132+ {
133+ OnOff::Attributes::OnOff::Set (kTestEndpoint , false );
134+ ColorControl::Attributes::Options::Set (kTestEndpoint , BitMask<OptionsBitmap>());
135+
136+ BitMask<OptionsBitmap> mask;
137+ mask.Set (OptionsBitmap::kExecuteIfOff );
138+
139+ BitMask<OptionsBitmap> overrideMask;
140+ overrideMask.Set (OptionsBitmap::kExecuteIfOff );
141+ EXPECT_TRUE (Server ().shouldExecuteIfOff (kTestEndpoint , mask, overrideMask));
142+
143+ overrideMask.Clear (OptionsBitmap::kExecuteIfOff );
144+ EXPECT_FALSE (Server ().shouldExecuteIfOff (kTestEndpoint , mask, overrideMask));
145+ }
146+
147+ TEST_F (TestColorControlServer, ComputeTransitionTimeHandlesZeroRate)
148+ {
149+ ColorControlServer::Color16uTransitionState state{};
150+ state.currentValue = 10 ;
151+ state.finalValue = 100 ;
152+
153+ EXPECT_EQ (Server ().computeTransitionTimeFromStateAndRate (&state, 0 ), std::numeric_limits<uint16_t >::max ());
154+ }
155+
156+ TEST_F (TestColorControlServer, ComputeTransitionTimeProducesMinimumOneStep)
157+ {
158+ ColorControlServer::Color16uTransitionState state{};
159+ state.currentValue = 10 ;
160+ state.finalValue = 11 ;
161+
162+ EXPECT_EQ (Server ().computeTransitionTimeFromStateAndRate (&state, 100 ), 1 );
163+ }
164+
165+ TEST_F (TestColorControlServer, ComputeTransitionTimeIsAbsolute)
166+ {
167+ ColorControlServer::Color16uTransitionState state{};
168+ state.currentValue = 90 ;
169+ state.finalValue = 10 ;
170+
171+ EXPECT_EQ (Server ().computeTransitionTimeFromStateAndRate (&state, 20 ), 40 );
172+ }
173+
174+ #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_XY
175+ TEST_F (TestColorControlServer, FindNewColorValueFromStepClampsToLimits)
176+ {
177+ EXPECT_EQ (Server ().findNewColorValueFromStep (500 , 1000 ), ColorControlServer::MAX_CIE_XY_VALUE);
178+ EXPECT_EQ (Server ().findNewColorValueFromStep (500 , static_cast <int16_t >(-2000 )), ColorControlServer::MIN_CIE_XY_VALUE);
179+ }
180+ #endif // MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_XY
181+
182+ #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_HSV
183+ TEST_F (TestColorControlServer, AddHueWrapsAroundMax)
184+ {
185+ EXPECT_EQ (Server ().addHue (ColorControlServer::MAX_HUE_VALUE - 2 , 5 ), 2 );
186+ }
187+
188+ TEST_F (TestColorControlServer, SubtractHueWrapsAroundZero)
189+ {
190+ EXPECT_EQ (Server ().subtractHue (3 , 10 ), static_cast <uint8_t >(ColorControlServer::MAX_HUE_VALUE - 6 ));
191+ }
192+
193+ TEST_F (TestColorControlServer, AddSaturationSaturatesAtMax)
194+ {
195+ EXPECT_EQ (Server ().addSaturation (ColorControlServer::MAX_SATURATION_VALUE - 1 , 10 ), ColorControlServer::MAX_SATURATION_VALUE);
196+ }
197+
198+ TEST_F (TestColorControlServer, SubtractSaturationClampsAtMin)
199+ {
200+ EXPECT_EQ (Server ().subtractSaturation (5 , 10 ), ColorControlServer::MIN_SATURATION_VALUE);
201+ }
202+ #endif // MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_HSV
0 commit comments