Skip to content

Commit 89528df

Browse files
su-shankarzr
authored andcommitted
SwitchAll: Pull request #2843: UIC-3445: UT for Switch All CC
Relate-to: #145 Signed-off-by: Philippe Coval <[email protected]>
1 parent 558d857 commit 89528df

File tree

3 files changed

+296
-15
lines changed

3 files changed

+296
-15
lines changed

applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_all.cpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,7 @@ zwave_frame_generator frame_generator(COMMAND_CLASS_SWITCH_ALL);
6363
///////////////////////////////////////////////////////////////////////////////
6464
// Helper functions
6565
///////////////////////////////////////////////////////////////////////////////
66-
zwave_cc_version_t get_current_switch_all_version(attribute_store_node_t node)
67-
{
68-
zwave_cc_version_t version
69-
= zwave_command_class_get_version_from_node(node, COMMAND_CLASS_SWITCH_ALL);
70-
71-
if (version == 0) {
72-
sl_log_error(LOG_TAG, "switch_all Command Class Version not found");
73-
}
7466

75-
return version;
76-
}
7767
///////////////////////////////////////////////////////////////////////////////
7868
// Resolution functions
7969
///////////////////////////////////////////////////////////////////////////////
@@ -143,12 +133,12 @@ static sl_status_t zwave_command_class_switch_all_set(
143133
try {
144134
attribute_store::attribute value_node(node);
145135
// Creating the frame
146-
if (value_node.type() == ATTRIBUTE(MODE)) {
147-
frame_generator.initialize_frame(SWITCH_ALL_SET, frame, 3);
148-
frame_generator.add_value(value_node, DESIRED_ATTRIBUTE);
149-
frame_generator.validate_frame(frame_length);
136+
if (value_node.type() != ATTRIBUTE(MODE)) {
137+
return SL_STATUS_INVALID_TYPE;
150138
}
151-
return SL_STATUS_INVALID_TYPE;
139+
frame_generator.initialize_frame(SWITCH_ALL_SET, frame, 3);
140+
frame_generator.add_value(value_node, DESIRED_ATTRIBUTE);
141+
frame_generator.validate_frame(frame_length);
152142
} catch (const std::exception &e) {
153143
sl_log_error(LOG_TAG,
154144
"Error while generating switch_all Set frame : %s",
@@ -195,6 +185,7 @@ static sl_status_t zwave_command_class_switch_all_handle_report(
195185
e.what());
196186
return SL_STATUS_FAIL;
197187
}
188+
198189
return SL_STATUS_OK;
199190
}
200191

@@ -296,6 +287,13 @@ sl_status_t zwave_command_class_unify_switch_all_write_attributes_callback(
296287
if (changed.on_off) {
297288
for (auto node: home.children()) {
298289
auto ep = node.child_by_type(ATTRIBUTE_ENDPOINT_ID);
290+
if (!ep.child_by_type(ATTRIBUTE(MODE)).is_valid()) {
291+
sl_log_debug(LOG_TAG,
292+
"Switch All CC not supported by ep %u of node %x",
293+
ep.reported<uint8_t>(),
294+
node.reported<uint16_t>());
295+
continue;
296+
}
299297
auto on_off
300298
= ep.emplace_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_ALL_ON_OFF);
301299

applications/zpc/components/zwave_command_classes/test/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,3 +902,23 @@ target_add_unittest(
902902
zwave_tx_mock
903903
zwave_tx_scheme_selector_mock
904904
)
905+
906+
907+
# Switch All Command Class Test
908+
target_add_unittest(
909+
zwave_command_classes
910+
NAME
911+
zwave_command_class_switch_all_test
912+
SOURCES
913+
zwave_command_class_switch_all_test.cpp
914+
DEPENDS
915+
zpc_attribute_store_test_helper
916+
zwave_command_class_test_helpers
917+
zwave_controller
918+
zwave_command_handler_mock
919+
uic_attribute_resolver_mock
920+
zpc_attribute_resolver_mock
921+
zpc_attribute_store_mock
922+
uic_dotdot_mqtt_mock
923+
)
924+
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
/******************************************************************************
2+
* # License
3+
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
4+
******************************************************************************
5+
* The licensor of this software is Silicon Laboratories Inc. Your use of this
6+
* software is governed by the terms of Silicon Labs Master Software License
7+
* Agreement (MSLA) available at
8+
* www.silabs.com/about-us/legal/master-software-license-agreement. This
9+
* software is distributed to you in Source Code format and is governed by the
10+
* sections of the MSLA applicable to Source Code.
11+
*
12+
*****************************************************************************/
13+
// Base class
14+
#include "zwave_command_class_switch_all.h"
15+
#include "zwave_command_classes_utils.h"
16+
#include "unity.h"
17+
18+
// Generic includes
19+
#include <string.h>
20+
21+
// Unify
22+
#include "datastore.h"
23+
#include "attribute_store.h"
24+
#include "attribute_store_fixt.h"
25+
// Interface includes
26+
#include "ZW_classcmd.h"
27+
28+
// ZPC includes
29+
#include "attribute_store_defined_attribute_types.h"
30+
#include "zpc_attribute_store_type_registration.h"
31+
32+
// Test helpers
33+
#include "zwave_command_class_test_helper.hpp"
34+
35+
36+
constexpr uint8_t SWITCH_ALL_ON_VALUE = 1;
37+
constexpr uint8_t SWITCH_ALL_OFF_VALUE = 0;
38+
39+
// Attribute macro, shortening those long defines for attribute types:
40+
#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_SWITCH_ALL_##type
41+
42+
43+
using namespace zwave_command_class_test_helper;
44+
45+
extern "C" {
46+
47+
// Mock helper
48+
#include "dotdot_mqtt_mock.h"
49+
#include "zpc_attribute_store_network_helper_mock.h"
50+
51+
static uic_mqtt_dotdot_unify_switch_all_write_attributes_callback_t switch_all_mock_callback;
52+
static void uic_mqtt_dotdot_unify_switch_all_write_attributes_callback_stub(
53+
const uic_mqtt_dotdot_unify_switch_all_write_attributes_callback_t callback,
54+
int cmock_num_calls)
55+
{
56+
switch_all_mock_callback = callback;
57+
}
58+
59+
/// Setup the test suite (called once before all test_xxx functions are called)
60+
void suiteSetUp()
61+
{
62+
datastore_init(":memory:");
63+
attribute_store_init();
64+
zpc_attribute_store_register_known_attribute_types();
65+
}
66+
67+
/// Teardown the test suite (called once after all test_xxx functions are called)
68+
int suiteTearDown(int num_failures)
69+
{
70+
attribute_store_teardown();
71+
datastore_teardown();
72+
return num_failures;
73+
}
74+
75+
// Tested command class handler
76+
const zwave_struct_handler_args command_class_handler
77+
= {.command_class_id = COMMAND_CLASS_SWITCH_ALL,
78+
.supported_version = SWITCH_ALL_VERSION};
79+
// Get Set function map
80+
const resolver_function_map attribute_bindings = {
81+
{ATTRIBUTE(MODE), {SWITCH_ALL_GET, SWITCH_ALL_SET}},
82+
{ATTRIBUTE(ON_OFF), {0, SWITCH_ALL_ON}},
83+
{ATTRIBUTE(ON_OFF), {0, SWITCH_ALL_OFF}}
84+
};
85+
86+
/// Called before each and every test
87+
void setUp()
88+
{
89+
uic_mqtt_dotdot_set_unify_switch_all_write_attributes_callback_Stub(uic_mqtt_dotdot_unify_switch_all_write_attributes_callback_stub);
90+
zwave_setUp(command_class_handler,
91+
&zwave_command_class_switch_all_init,
92+
attribute_bindings);
93+
}
94+
95+
///////////////////////////////////////////////////////////////////////////////
96+
// Test cases
97+
///////////////////////////////////////////////////////////////////////////////
98+
void test_switch_all_interview_happy_case()
99+
{
100+
helper_set_version(SWITCH_ALL_VERSION);
101+
102+
// Verify that we have the correct node(s)
103+
helper_test_node_exists(ATTRIBUTE(MODE));
104+
helper_test_node_exists(ATTRIBUTE(ON_OFF));
105+
}
106+
107+
void test_switch_all_get_happy_case()
108+
{
109+
helper_set_version(SWITCH_ALL_VERSION);
110+
111+
auto mode_node = helper_test_and_get_node(ATTRIBUTE(MODE));
112+
113+
helper_test_get_set_frame_happy_case(SWITCH_ALL_GET, mode_node);
114+
}
115+
116+
void test_switch_all_set_happy_case()
117+
{
118+
helper_set_version(SWITCH_ALL_VERSION);
119+
120+
auto mode_node = helper_test_and_get_node(ATTRIBUTE(MODE));
121+
uint8_t mode = 0xFF;
122+
123+
// Test with desired value
124+
mode_node.set_desired(mode);
125+
helper_test_get_set_frame_happy_case(SWITCH_ALL_SET,
126+
mode_node,
127+
{mode});
128+
}
129+
130+
void test_switch_all_set_on_happy_case()
131+
{
132+
helper_set_version(SWITCH_ALL_VERSION);
133+
134+
auto mode_node = helper_test_and_get_node(ATTRIBUTE(MODE));
135+
auto on_off_node = helper_test_and_get_node(ATTRIBUTE(ON_OFF));
136+
uint8_t mode = 0xFF;
137+
138+
// Test with desired value
139+
mode_node.set_reported(mode);
140+
on_off_node.set_desired(SWITCH_ALL_ON_VALUE);
141+
helper_test_get_set_frame_happy_case(SWITCH_ALL_ON,
142+
on_off_node);
143+
}
144+
145+
void test_switch_all_set_on_fail_case()
146+
{
147+
helper_set_version(SWITCH_ALL_VERSION);
148+
149+
auto mode_node = helper_test_and_get_node(ATTRIBUTE(MODE));
150+
auto on_off_node = helper_test_and_get_node(ATTRIBUTE(ON_OFF));
151+
uint8_t mode = 0x00;
152+
153+
// Test with desired value
154+
mode_node.set_reported(mode);
155+
on_off_node.set_desired(SWITCH_ALL_ON_VALUE);
156+
helper_test_get_set_fail_case(SWITCH_ALL_ON,
157+
SL_STATUS_OK,
158+
on_off_node);
159+
160+
helper_test_get_set_fail_case(SWITCH_ALL_ON,
161+
SL_STATUS_INVALID_TYPE);
162+
163+
mode = 0xFF;
164+
mode_node.set_reported(mode);
165+
on_off_node.set_desired<uint8_t>(0xFF);
166+
helper_test_get_set_fail_case(SWITCH_ALL_ON,
167+
SL_STATUS_INVALID_RANGE,
168+
on_off_node);
169+
170+
}
171+
172+
void test_switch_all_report_happy_case()
173+
{
174+
helper_set_version(SWITCH_ALL_VERSION);
175+
auto mode_node = helper_test_and_get_node(ATTRIBUTE(MODE));
176+
uint8_t mode = 0;
177+
178+
attribute_store_network_helper_get_endpoint_node_IgnoreAndReturn(cpp_endpoint_id_node);
179+
helper_test_report_frame(SWITCH_ALL_REPORT, {mode});
180+
TEST_ASSERT_EQUAL(mode, mode_node.reported<uint8_t>());
181+
182+
mode = 0x02;
183+
helper_test_report_frame(SWITCH_ALL_REPORT, {mode});
184+
attribute_store_network_helper_get_endpoint_node_StopIgnore();
185+
TEST_ASSERT_EQUAL(mode, mode_node.reported<uint8_t>());
186+
}
187+
188+
void test_switch_all_report_fail_case()
189+
{
190+
helper_set_version(SWITCH_ALL_VERSION);
191+
uint8_t mode = 0;
192+
193+
attribute_store_network_helper_get_endpoint_node_IgnoreAndReturn(cpp_endpoint_id_node);
194+
helper_test_report_frame(SWITCH_ALL_REPORT, {mode, mode}, SL_STATUS_FAIL);
195+
attribute_store_network_helper_get_endpoint_node_StopIgnore();
196+
}
197+
198+
void test_switch_all_set_off_happy_case()
199+
{
200+
helper_set_version(SWITCH_ALL_VERSION);
201+
202+
auto mode_node = helper_test_and_get_node(ATTRIBUTE(MODE));
203+
auto on_off_node = helper_test_and_get_node(ATTRIBUTE(ON_OFF));
204+
uint8_t mode = 0xFF;
205+
206+
// Test with desired value
207+
mode_node.set_reported(mode);
208+
on_off_node.set_desired(SWITCH_ALL_OFF_VALUE);
209+
helper_test_get_set_frame_happy_case(SWITCH_ALL_OFF,
210+
on_off_node);
211+
}
212+
213+
void test_switch_all_set_off_fail_case()
214+
{
215+
helper_set_version(SWITCH_ALL_VERSION);
216+
217+
auto mode_node = helper_test_and_get_node(ATTRIBUTE(MODE));
218+
auto on_off_node = helper_test_and_get_node(ATTRIBUTE(ON_OFF));
219+
uint8_t mode = 0x0;
220+
221+
// Test with desired value
222+
mode_node.set_reported(mode);
223+
on_off_node.set_desired(SWITCH_ALL_OFF_VALUE);
224+
helper_test_get_set_fail_case(SWITCH_ALL_OFF,
225+
SL_STATUS_OK,
226+
on_off_node);
227+
228+
helper_test_get_set_fail_case(SWITCH_ALL_OFF,
229+
SL_STATUS_INVALID_TYPE);
230+
}
231+
232+
void test_switch_all_write_command_handler()
233+
{
234+
helper_set_version(SWITCH_ALL_VERSION);
235+
236+
attribute_store::attribute home_node(home_id_node);
237+
238+
auto unid_node_second = home_node.add_node(ATTRIBUTE_NODE_ID);
239+
unid_node_second.set_reported<std::string>("zw-CAFECAFE-0008");
240+
auto ep_node_second = unid_node_second.emplace_node<>(ATTRIBUTE_ENDPOINT_ID, endpoint_id);
241+
helper_set_version(SWITCH_ALL_VERSION, ep_node_second);
242+
243+
attribute_store_network_helper_get_home_id_node_ExpectAndReturn("zw-CAFECAFE-0008", home_node);
244+
attribute_store_network_helper_get_node_id_node_ExpectAndReturn("zw-CAFECAFE-0008", unid_node_second);
245+
uic_mqtt_dotdot_unify_switch_all_state_t state = {0xFF, 1};
246+
uic_mqtt_dotdot_unify_switch_all_updated_state_t updates = {true, false};
247+
switch_all_mock_callback("zw-CAFECAFE-0008", endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
248+
state, updates);
249+
auto dotdot_mode_second = helper_test_and_get_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_ALL_MODE, ep_node_second);
250+
TEST_ASSERT_EQUAL(state.mode, dotdot_mode_second.desired<uint8_t>());
251+
252+
attribute_store_network_helper_get_home_id_node_ExpectAndReturn("zw-CAFECAFE-0008", home_node);
253+
updates.mode = false;
254+
updates.on_off = true;
255+
switch_all_mock_callback("zw-CAFECAFE-0008", endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
256+
state, updates);
257+
auto dotdot_onoff_second = helper_test_and_get_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_ALL_ON_OFF, ep_node_second);
258+
auto dotdot_onoff = helper_test_and_get_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_ALL_ON_OFF, cpp_endpoint_id_node);
259+
TEST_ASSERT_EQUAL(state.on_off, dotdot_onoff.desired<uint8_t>());
260+
TEST_ASSERT_EQUAL(state.on_off, dotdot_onoff_second.desired<uint8_t>());
261+
}
262+
263+
} // extern "C"

0 commit comments

Comments
 (0)