Line data Source code
1 : /*
2 : * Copyright (c) 2025 Project CHIP Authors
3 : *
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 :
17 : #pragma once
18 : #include "AttributeTesting.h"
19 :
20 : #include <app/server-cluster/DefaultServerCluster.h>
21 : #include <app/server-cluster/ServerClusterInterface.h>
22 : #include <lib/core/CHIPError.h>
23 : #include <lib/support/ReadOnlyBuffer.h>
24 : #include <vector>
25 :
26 : namespace chip {
27 : namespace Testing {
28 :
29 : /// Compares the attributes of a cluster against an expected set.
30 : ///
31 : /// This function retrieves the attributes for the first path returned by `cluster.GetPaths()`
32 : /// and compares them against the `expected` list. Global attributes are automatically
33 : /// added to the `expected` list, as they must always be present.
34 : ///
35 : /// Parameters:
36 : /// cluster - The cluster interface to test.
37 : /// expected - initializer_list or any other iterable of expected attribute entries supporting `std::size(container)` syntax.
38 : /// May be empty for global attributes only.
39 : ///
40 : /// @note This function will assert (die) if `cluster.GetPaths()` does not return exactly one path.
41 : ///
42 : /// Example Usage:
43 : /// ```
44 : /// ClusterImpl cluster(kTestEndpointId, ....);
45 : /// ASSERT_TRUE(IsAttributesListEqualTo(cluster, { Attributes::SomeAttribute::kMetadataEntry }));
46 : /// ```
47 :
48 : template <class T>
49 139 : bool IsAttributesListEqualTo(app::ServerClusterInterface & cluster, const T & expected)
50 : {
51 139 : VerifyOrDie(cluster.GetPaths().size() == 1);
52 139 : auto path = cluster.GetPaths()[0];
53 139 : ReadOnlyBufferBuilder<app::DataModel::AttributeEntry> attributesBuilder;
54 278 : if (CHIP_ERROR err = cluster.Attributes(path, attributesBuilder); err != CHIP_NO_ERROR)
55 : {
56 0 : ChipLogError(Test, "Failed to get attributes list from cluster. Error: %" CHIP_ERROR_FORMAT, err.Format());
57 0 : return false;
58 : }
59 :
60 139 : ReadOnlyBufferBuilder<app::DataModel::AttributeEntry> expectedBuilder;
61 :
62 139 : SuccessOrDie(expectedBuilder.EnsureAppendCapacity(std::size(expected)));
63 956 : for (const auto & entry : expected)
64 : {
65 817 : SuccessOrDie(expectedBuilder.Append(entry));
66 : }
67 :
68 139 : SuccessOrDie(expectedBuilder.AppendElements(app::DefaultServerCluster::GlobalAttributes()));
69 :
70 139 : return EqualAttributeSets(attributesBuilder.TakeBuffer(), expectedBuilder.TakeBuffer());
71 139 : }
72 :
73 : // Overload for std::initializer_list to not get "template argument deduction failed" when calling `IsAttributesListEqualTo(cluster,
74 : // {...})`
75 : template <typename T = const app::DataModel::AttributeEntry>
76 123 : bool IsAttributesListEqualTo(app::ServerClusterInterface & cluster, std::initializer_list<T> expected)
77 : {
78 123 : return IsAttributesListEqualTo<std::initializer_list<T>>(cluster, expected);
79 : }
80 :
81 : /// Compares the accepted commands of a cluster against an expected set.
82 : ///
83 : /// This function retrieves the accepted commands for the first path returned by `cluster.GetPaths()`
84 : /// and compares them against the `expected` list of items.
85 : ///
86 : /// Parameters:
87 : /// cluster - The cluster interface to test.
88 : /// expected - initializer_list or any other iterable of expected accepted command entries supporting `std::size(container)`
89 : /// syntax. May be empty.
90 : ///
91 : /// @note This function will assert (die) if `cluster.GetPaths()` does not return exactly one path.
92 : ///
93 : /// Example Usage:
94 : ///
95 : /// ```
96 : /// ClusterImpl cluster(kTestEndpointId, ...);
97 : /// ASSERT_TRUE(IsAcceptedCommandsListEqualTo(cluster, { Commands::SomeCommand::kMetadataEntry }));
98 : /// ```
99 : template <class T>
100 64 : bool IsAcceptedCommandsListEqualTo(app::ServerClusterInterface & cluster, const T & expected)
101 : {
102 64 : VerifyOrDie(cluster.GetPaths().size() == 1);
103 64 : auto path = cluster.GetPaths()[0];
104 64 : ReadOnlyBufferBuilder<app::DataModel::AcceptedCommandEntry> commandsBuilder;
105 128 : if (CHIP_ERROR err = cluster.AcceptedCommands(path, commandsBuilder); err != CHIP_NO_ERROR)
106 : {
107 0 : ChipLogError(Test, "Failed to get accepted commands list from cluster. Error: %" CHIP_ERROR_FORMAT, err.Format());
108 0 : return false;
109 : }
110 :
111 64 : ReadOnlyBufferBuilder<app::DataModel::AcceptedCommandEntry> expectedBuilder;
112 :
113 64 : SuccessOrDie(expectedBuilder.EnsureAppendCapacity(std::size(expected)));
114 236 : for (const auto & entry : expected)
115 : {
116 172 : SuccessOrDie(expectedBuilder.Append(entry));
117 : }
118 :
119 64 : return EqualAcceptedCommandSets(commandsBuilder.TakeBuffer(), expectedBuilder.TakeBuffer());
120 64 : }
121 :
122 : // Overload for std::initializer_list to not get "template argument deduction failed" when calling
123 : // `IsAcceptedCommandsListEqualTo(cluster, {...})`
124 : template <typename T = const app::DataModel::AcceptedCommandEntry>
125 64 : bool IsAcceptedCommandsListEqualTo(app::ServerClusterInterface & cluster, std::initializer_list<T> expected)
126 : {
127 64 : return IsAcceptedCommandsListEqualTo<std::initializer_list<T>>(cluster, expected);
128 : }
129 :
130 : /// Compares the generated commands of a cluster against an expected set.
131 : ///
132 : /// This function retrieves the generated commands for the first path returned by `cluster.GetPaths()`
133 : /// and compares them against the `expected` list of items.
134 : ///
135 : /// Parameters:
136 : /// cluster - The cluster interface to test.
137 : /// expected - initializer_list or any other iterable of expected generated command entries supporting `std::size(container)`
138 : /// syntax. May be empty.
139 : ///
140 : /// @note This function will assert (die) if `cluster.GetPaths()` does not return exactly one path.
141 : ///
142 : /// Example Usage:
143 : /// ```
144 : /// ClusterImpl cluster(kTestEndpointId, ...);
145 : /// ASSERT_TRUE(IsGeneratedCommandsListEqualTo(cluster, { Commands::SomeCommandResponse::kMetadataEntry }));
146 : /// ```
147 : template <class T>
148 17 : bool IsGeneratedCommandsListEqualTo(app::ServerClusterInterface & cluster, const T & expected)
149 : {
150 17 : VerifyOrDie(cluster.GetPaths().size() == 1);
151 17 : auto path = cluster.GetPaths()[0];
152 17 : ReadOnlyBufferBuilder<CommandId> commandsBuilder;
153 34 : if (CHIP_ERROR err = cluster.GeneratedCommands(path, commandsBuilder); err != CHIP_NO_ERROR)
154 : {
155 0 : ChipLogError(Test, "Failed to get generated commands list from cluster. Error: %" CHIP_ERROR_FORMAT, err.Format());
156 0 : return false;
157 : }
158 :
159 17 : ReadOnlyBufferBuilder<CommandId> expectedBuilder;
160 :
161 17 : SuccessOrDie(expectedBuilder.EnsureAppendCapacity(std::size(expected)));
162 29 : for (const auto & entry : expected)
163 : {
164 12 : SuccessOrDie(expectedBuilder.Append(entry));
165 : }
166 :
167 17 : return EqualGeneratedCommandSets(commandsBuilder.TakeBuffer(), expectedBuilder.TakeBuffer());
168 17 : }
169 :
170 : // Overload for std::initializer_list to not get "template argument deduction failed" when calling
171 : // `IsGeneratedCommandsListEqualTo(cluster, {...})`
172 : template <typename T = const CommandId>
173 17 : bool IsGeneratedCommandsListEqualTo(app::ServerClusterInterface & cluster, std::initializer_list<T> expected)
174 : {
175 17 : return IsGeneratedCommandsListEqualTo<std::initializer_list<T>>(cluster, expected);
176 : }
177 :
178 : } // namespace Testing
179 : } // namespace chip
|