2525#include < clusters/UserLabel/Enums.h>
2626#include < clusters/UserLabel/Metadata.h>
2727#include < clusters/UserLabel/Structs.h>
28+ #include < platform/DeviceInfoProvider.h>
2829
2930namespace {
3031
@@ -35,21 +36,55 @@ using namespace chip::app::Clusters::UserLabel;
3536using namespace chip ::app::Clusters::UserLabel::Attributes;
3637using namespace chip ::Test;
3738
39+ // Mock DeviceInfoProvider for testing
40+ class MockDeviceInfoProvider : public DeviceLayer ::DeviceInfoProvider
41+ {
42+ public:
43+ MockDeviceInfoProvider () = default ;
44+ ~MockDeviceInfoProvider () override = default ;
45+
46+ FixedLabelIterator * IterateFixedLabel (EndpointId endpoint) override { return nullptr ; }
47+ UserLabelIterator * IterateUserLabel (EndpointId endpoint) override { return nullptr ; }
48+ SupportedCalendarTypesIterator * IterateSupportedCalendarTypes () override { return nullptr ; }
49+ SupportedLocalesIterator * IterateSupportedLocales () override { return nullptr ; }
50+
51+ protected:
52+ // Simple no-op implementations - we only need these to return success
53+ // so that the cluster's validation logic can be tested
54+ CHIP_ERROR SetUserLabelLength (EndpointId endpoint, size_t val) override { return CHIP_NO_ERROR; }
55+ CHIP_ERROR GetUserLabelLength (EndpointId endpoint, size_t & val) override
56+ {
57+ val = 0 ;
58+ return CHIP_NO_ERROR;
59+ }
60+ CHIP_ERROR SetUserLabelAt (EndpointId endpoint, size_t index, const UserLabelType & userLabel) override { return CHIP_NO_ERROR; }
61+ CHIP_ERROR DeleteUserLabelAt (EndpointId endpoint, size_t index) override { return CHIP_NO_ERROR; }
62+ };
63+
3864struct TestUserLabelCluster : public ::testing::Test
3965{
4066 static void SetUpTestSuite () { ASSERT_EQ (chip::Platform::MemoryInit (), CHIP_NO_ERROR); }
4167
4268 static void TearDownTestSuite () { chip::Platform::MemoryShutdown (); }
4369
44- void SetUp () override { ASSERT_EQ (userLabel.Startup (context), CHIP_NO_ERROR); }
70+ void SetUp () override
71+ {
72+ DeviceLayer::SetDeviceInfoProvider (&mDeviceInfoProvider );
73+ ASSERT_EQ (userLabel.Startup (context), CHIP_NO_ERROR);
74+ }
4575
46- void TearDown () override { userLabel.Shutdown (); }
76+ void TearDown () override
77+ {
78+ userLabel.Shutdown ();
79+ DeviceLayer::SetDeviceInfoProvider (nullptr );
80+ }
4781
4882 TestUserLabelCluster () : context(testContext.Create()), userLabel(kRootEndpointId ) {}
4983
5084 chip::Test::TestServerClusterContext testContext;
5185 ServerClusterContext context;
5286 UserLabelCluster userLabel;
87+ MockDeviceInfoProvider mDeviceInfoProvider ;
5388};
5489
5590} // namespace
@@ -83,3 +118,56 @@ TEST_F(TestUserLabelCluster, ReadAttributeTest)
83118 ASSERT_GT (it.GetValue ().label .size (), 0u );
84119 }
85120}
121+
122+ TEST_F (TestUserLabelCluster, WriteValidLabelListTest)
123+ {
124+ ClusterTester tester (userLabel);
125+ Structs::LabelStruct::Type labels[] = {
126+ { .label = " room" _span, .value = " bedroom 2" _span },
127+ { .label = " orientation" _span, .value = " North" _span },
128+ };
129+ ASSERT_EQ (tester.WriteAttribute (LabelList::Id, DataModel::List (labels)), CHIP_NO_ERROR);
130+ }
131+
132+ TEST_F (TestUserLabelCluster, WriteLabelWithLabelTooLongTest)
133+ {
134+ ClusterTester tester (userLabel);
135+ constexpr auto tooLongLabel = " this_label_is_way_too_long" _span;
136+ static_assert (tooLongLabel.size () > UserLabelCluster::kMaxLabelSize );
137+ Structs::LabelStruct::Type labels[] = {
138+ { .label = tooLongLabel, .value = " value" _span },
139+ };
140+ ASSERT_EQ (tester.WriteAttribute (LabelList::Id, DataModel::List (labels)), CHIP_IM_GLOBAL_STATUS (ConstraintError));
141+ }
142+
143+ TEST_F (TestUserLabelCluster, WriteLabelWithValueTooLongTest)
144+ {
145+ ClusterTester tester (userLabel);
146+ constexpr auto tooLongValue = " this_value_is_way_too_long" _span;
147+ static_assert (tooLongValue.size () > UserLabelCluster::kMaxValueSize );
148+ Structs::LabelStruct::Type labels[] = {
149+ { .label = " room" _span, .value = tooLongValue },
150+ };
151+ ASSERT_EQ (tester.WriteAttribute (LabelList::Id, DataModel::List (labels)), CHIP_IM_GLOBAL_STATUS (ConstraintError));
152+ }
153+
154+ TEST_F (TestUserLabelCluster, WriteEmptyLabelsTest)
155+ {
156+ ClusterTester tester (userLabel);
157+ Structs::LabelStruct::Type labels[] = {
158+ { .label = " " _span, .value = " " _span }, // empty label and value are allowed per spec
159+ };
160+ ASSERT_EQ (tester.WriteAttribute (LabelList::Id, DataModel::List (labels)), CHIP_NO_ERROR);
161+ }
162+
163+ TEST_F (TestUserLabelCluster, WriteMaxSizeLabelListTest)
164+ {
165+ ClusterTester tester (userLabel);
166+ std::array<Structs::LabelStruct::Type, chip::DeviceLayer::kMaxUserLabelListLength > labels;
167+ for (size_t i = 0 ; i < labels.size (); i++)
168+ {
169+ labels[i].label = " label" _span;
170+ labels[i].value = " value" _span;
171+ }
172+ ASSERT_EQ (tester.WriteAttribute (LabelList::Id, DataModel::List (labels.data (), labels.size ())), CHIP_NO_ERROR);
173+ }
0 commit comments