diff --git a/lib/tests/qunit.h b/lib/include/qunit.h similarity index 100% rename from lib/tests/qunit.h rename to lib/include/qunit.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c65e68..3bd5d49 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,9 +44,31 @@ target_link_libraries (${PROJECT_NAME} event_pthreads ) +# Tests +add_executable (test_device + devices/devices_manager.c + devices/device.c + devices/outlet_dio.c + devices/shutter.c + devices/sprinkler.c + tests/test_device.c +) + +target_link_libraries (test_device + LINK_PUBLIC + nats_static + qlibc-static + json-c +) + + install (TARGETS ${PROJECT_NAME} DESTINATION local/bin) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND cmake -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/../share/domo ${CMAKE_BINARY_DIR}/share/domo COMMENT "Install domo's config files." - ) +) + +add_custom_target (launch_test + COMMAND valgrind --leak-check=full --trace-children=yes --malloc-fill=AE --free-fill=BD --track-origins=yes ${CMAKE_BINARY_DIR}/bin/test_device +) diff --git a/src/devices/devices_manager.c b/src/devices/devices_manager.c index 598d5e6..ec70257 100644 --- a/src/devices/devices_manager.c +++ b/src/devices/devices_manager.c @@ -47,15 +47,24 @@ int load_outlets(devices_manager_t *dm, struct json_object *node); struct json_object *save_outlets(devices_manager_t *dm); -int create_outlet(struct json_object *node); +int create_outlet(devices_manager_t *dm, struct json_object *node); +int remove_outlet(devices_manager_t *dm, uint16_t id); +int update_outlet(devices_manager_t *dm, uint16_t id, struct json_object *node); +int set_outlet_state(devices_manager_t *dm, uint16_t id, bool state); int load_shutters(devices_manager_t *dm, struct json_object *node); struct json_object *save_shutters(devices_manager_t *dm); int create_shutter(devices_manager_t *dm, struct json_object *node); +int remove_shutter(devices_manager_t *dm, uint16_t id); +int update_shutter(devices_manager_t *dm, uint16_t id, struct json_object *node); +int set_shutter_state(devices_manager_t *dm, uint16_t id, bool state); int load_sprinklers(devices_manager_t *dm, struct json_object *node); struct json_object *save_sprinklers(devices_manager_t *dm); int create_sprinkler(devices_manager_t *dm, struct json_object *node); +int remove_sprinkler(devices_manager_t *dm, uint16_t id); +int update_sprinkler(devices_manager_t *dm, uint16_t id, struct json_object *node); +int set_sprinkler_state(devices_manager_t *dm, uint16_t id, bool state); /*----------------------------- PUBLIC FUNCTIONS ----------------------------*/ @@ -111,8 +120,8 @@ void devices_manager_free(devices_manager_t *devices_manager) int devices_manager_load(devices_manager_t *dm, char *config_path) { - struct json_object *the_root_node, *the_value_node; - DEBUG("Devices load...\n"); + struct json_object *the_root_node, *the_value_node; + DEBUG("Devices load...\n"); if (config_path == NULL) { @@ -121,64 +130,64 @@ int devices_manager_load(devices_manager_t *dm, char *config_path) } dm->file_path = config_path; - the_root_node = json_object_from_file(dm->file_path); - if (the_root_node == NULL) - { - fprintf(stderr, "Failed to parse the Devices File (%s).\n", dm->file_path); - return -1; - } + the_root_node = json_object_from_file(dm->file_path); + if (the_root_node == NULL) + { + fprintf(stderr, "Failed to parse the Devices File (%s).\n", dm->file_path); + return -1; + } - if (json_object_object_get_ex(the_root_node, kOutletEntry, &the_value_node)) - { - load_outlets(dm, the_value_node); - } + if (json_object_object_get_ex(the_root_node, kOutletEntry, &the_value_node)) + { + load_outlets(dm, the_value_node); + } - if (json_object_object_get_ex(the_root_node, kShutterEntry, &the_value_node)) - { - load_shutters(dm, the_value_node); - } + if (json_object_object_get_ex(the_root_node, kShutterEntry, &the_value_node)) + { + load_shutters(dm, the_value_node); + } - if (json_object_object_get_ex(the_root_node, kSprinklerEntry, &the_value_node)) - { - load_sprinklers(dm, the_value_node); - } + if (json_object_object_get_ex(the_root_node, kSprinklerEntry, &the_value_node)) + { + load_sprinklers(dm, the_value_node); + } - /* Clean the json object. */ - json_object_put(the_root_node); + /* Clean the json object. */ + json_object_put(the_root_node); - return 0; + return 0; } /*--------------------------------------------------------------------------*/ int devices_manager_save(devices_manager_t *dm) { - int result; - struct json_object *root_node; + int result; + struct json_object *root_node; DEBUG("Devices save...\n"); - root_node = json_object_new_object(); + root_node = json_object_new_object(); - // Outlets - json_object_object_add(root_node, kOutletEntry, save_outlets(dm)); - // Shutters + // Outlets + json_object_object_add(root_node, kOutletEntry, save_outlets(dm)); + // Shutters json_object_object_add(root_node, kShutterEntry, save_shutters(dm)); - // Sprinklers - json_object_object_add(root_node, kSprinklerEntry, save_sprinklers(dm)); + // Sprinklers + json_object_object_add(root_node, kSprinklerEntry, save_sprinklers(dm)); - result = json_object_to_file_ext(dm->file_path, root_node, JSON_C_TO_STRING_PRETTY); + result = json_object_to_file_ext(dm->file_path, root_node, JSON_C_TO_STRING_PRETTY); - /* Clean the json object. */ - json_object_put(root_node); + /* Clean the json object. */ + json_object_put(root_node); - return result; + return result; } /*--------------------------------------------------------------------------*/ char *devices_manager_get(devices_manager_t *dm, const char *capability) { - #warning "TODO" +#warning "TODO" return NULL; } @@ -186,7 +195,7 @@ char *devices_manager_get(devices_manager_t *dm, const char *capability) char *devices_manager_get_by_id(devices_manager_t *dm, const char *capability, uint32_t id) { - #warning "TODO" +#warning "TODO" return NULL; } @@ -194,7 +203,7 @@ char *devices_manager_get_by_id(devices_manager_t *dm, const char *capability, u int devices_manager_set(devices_manager_t *dm, const char *capability, struct json_object *node) { - #warning "TODO" +#warning "TODO" return 0; } @@ -202,36 +211,115 @@ int devices_manager_set(devices_manager_t *dm, const char *capability, struct js int devices_manager_set_state(devices_manager_t *dm, const char *capability, int id, bool state) { - #warning "TODO" - return 0; + int result = -1; + + if (capability == kOutletEntry) + { + result = set_outlet_state(dm, id, state); + } + else if (capability == kShutterEntry) + { + result = set_shutter_state(dm, id, state); + } + else if (capability == kSprinklerEntry) + { + result = set_sprinkler_state(dm, id, state); + } + + if (result == 0) + { + devices_manager_save(dm); + } + + return result; } /*--------------------------------------------------------------------------*/ -int devices_manager_create(devices_manager_t *dm, const char *a_capability, struct json_object *node) +int devices_manager_create(devices_manager_t *dm, const char *capability, struct json_object *node) { - #warning "TODO" - return 0; + if (capability == kOutletEntry) + { + return create_outlet(dm, node); + } + else if (capability == kShutterEntry) + { + return create_shutter(dm, node); + } + else if (capability == kSprinklerEntry) + { + return create_sprinkler(dm, node); + } + + return -1; } /*--------------------------------------------------------------------------*/ -int devices_manager_update(devices_manager_t *dm, const char *a_capability, struct json_object *node) +int devices_manager_update(devices_manager_t *dm, const char *capability, struct json_object *node) { - #warning "TODO" - return 0; + int32_t id = -1; + struct json_object *value_node; + + // id + if (json_object_object_get_ex(node, k_entry_id, &value_node)) + { + id = json_object_get_int(value_node); + } + + // Sanity checks. + if (id == -1) + return -1; + + if (capability == kOutletEntry) + { + return update_outlet(dm, id, node); + } + else if (capability == kShutterEntry) + { + return update_shutter(dm, id, node); + } + else if (capability == kSprinklerEntry) + { + return update_sprinkler(dm, id, node); + } + + return -1; } /*--------------------------------------------------------------------------*/ -int devices_manager_delete(devices_manager_t *dm, const char *a_capability, struct json_object *node) +int devices_manager_delete(devices_manager_t *dm, const char *capability, struct json_object *node) { - #warning "TODO" - return 0; + int32_t id = -1; + struct json_object *value_node; + + // id + if (json_object_object_get_ex(node, k_entry_id, &value_node)) + { + id = json_object_get_int(value_node); + } + + // Sanity checks. + if (id == -1) + return -1; + + if (capability == kOutletEntry) + { + return remove_outlet(dm, id); + } + else if (capability == kShutterEntry) + { + return remove_shutter(dm, id); + } + else if (capability == kSprinklerEntry) + { + return remove_sprinkler(dm, id); + } + + return -1; } - - /*! ---------------------------------------------------------------------------- * @fn load_outlets * @@ -239,39 +327,39 @@ int devices_manager_delete(devices_manager_t *dm, const char *a_capability, stru */ int load_outlets(devices_manager_t *dm, struct json_object *node) { - DEBUG("devicesManager-load_outlets\n"); + DEBUG("devicesManager-load_outlets\n"); - /* Get Outlets */ - if (json_object_get_type(node) == json_type_array) - { - int length; - struct json_object *outlet_node; + /* Get Outlets */ + if (json_object_get_type(node) == json_type_array) + { + int length; + struct json_object *outlet_node; - length = json_object_array_length(node); - for (int i = 0; i < length; i++) - { + length = json_object_array_length(node); + for (int i = 0; i < length; i++) + { outlet_dio_t *outlet = outlet_dio_new(); outlet_node = json_object_array_get_idx(node, i); if (outlet_dio_from_json(outlet, outlet_node) == 0) { qlist_addlast(dm->outlets, outlet, sizeof(outlet_dio_t)); } - } - } + } + } - return 0; + return 0; } /*--------------------------------------------------------------------------*/ struct json_object *save_outlets(devices_manager_t *dm) { - struct json_object *root_node; - outlet_dio_t *outlet; + struct json_object *root_node; + outlet_dio_t *outlet; qlist_obj_t obj; - memset((void *) &obj, 0, sizeof(obj)); - root_node = json_object_new_array(); + memset((void *)&obj, 0, sizeof(obj)); + root_node = json_object_new_array(); while (qlist_getnext(dm->outlets, &obj, true)) { @@ -279,46 +367,88 @@ struct json_object *save_outlets(devices_manager_t *dm) json_object_array_add(root_node, outlet_dio_to_json_object(outlet)); } - return root_node; + return root_node; +} + +/*--------------------------------------------------------------------------*/ + +int create_outlet(devices_manager_t *dm, struct json_object *node) +{ + outlet_dio_t *outlet = outlet_dio_new(); + + if (outlet_dio_from_json(outlet, node) != 0) + { + outlet_dio_free(outlet); + return -1; + } + + device_set_id(outlet->device, ++dm->outlets_max_id); + qlist_addlast(dm->outlets, outlet, sizeof(outlet_dio_t)); + + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int remove_outlet(devices_manager_t *dm, uint16_t id) +{ +#warning "TODO" + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int update_outlet(devices_manager_t *dm, uint16_t id, struct json_object *node) +{ +#warning "TODO" + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int set_outlet_state(devices_manager_t *dm, uint16_t id, bool state) +{ +#warning "TODO" + return 0; } /*--------------------------------------------------------------------------*/ int load_shutters(devices_manager_t *dm, struct json_object *node) { - DEBUG("devicesManager-load_shutters\n"); + DEBUG("devicesManager-load_shutters\n"); - /* Get Shutters */ - if (json_object_get_type(node) == json_type_array) - { - int length; - struct json_object *shutter_node; + /* Get Shutters */ + if (json_object_get_type(node) == json_type_array) + { + int length; + struct json_object *shutter_node; - length = json_object_array_length(node); - for (int i = 0; i < length; i++) - { + length = json_object_array_length(node); + for (int i = 0; i < length; i++) + { shutter_t *shutter = shutter_new(); shutter_node = json_object_array_get_idx(node, i); if (shutter_from_json(shutter, shutter_node) == 0) { qlist_addlast(dm->shutters, shutter, sizeof(shutter_t)); } - } - } + } + } - return 0; + return 0; } /*--------------------------------------------------------------------------*/ struct json_object *save_shutters(devices_manager_t *dm) { - struct json_object *root_node; - shutter_t *shutter; + struct json_object *root_node; + shutter_t *shutter; qlist_obj_t obj; - memset((void *) &obj, 0, sizeof(obj)); - root_node = json_object_new_array(); + memset((void *)&obj, 0, sizeof(obj)); + root_node = json_object_new_array(); while (qlist_getnext(dm->shutters, &obj, true)) { @@ -326,14 +456,48 @@ struct json_object *save_shutters(devices_manager_t *dm) json_object_array_add(root_node, shutter_to_json_object(shutter)); } - return root_node; + return root_node; } /*--------------------------------------------------------------------------*/ int create_shutter(devices_manager_t *dm, struct json_object *node) { - #warning "TODO" + shutter_t *shutter = shutter_new(); + + if (shutter_from_json(shutter, node) != 0) + { + shutter_free(shutter); + return -1; + } + + device_set_id(shutter->outlet_dio->device, ++dm->shutters_max_id); + qlist_addlast(dm->shutters, shutter, sizeof(shutter_t)); + + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int remove_shutter(devices_manager_t *dm, uint16_t id) +{ +#warning "TODO" + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int update_shutter(devices_manager_t *dm, uint16_t id, struct json_object *node) +{ +#warning "TODO" + return 0; +} + +/*--------------------------------------------------------------------------*/ + +int set_shutter_state(devices_manager_t *dm, uint16_t id, bool state) +{ +#warning "TODO" return 0; } @@ -341,39 +505,39 @@ int create_shutter(devices_manager_t *dm, struct json_object *node) int load_sprinklers(devices_manager_t *dm, struct json_object *node) { - DEBUG("devicesManager-load_sprinkler\n"); + DEBUG("devicesManager-load_sprinkler\n"); - /* Get Shutters */ - if (json_object_get_type(node) == json_type_array) - { - int length; - struct json_object *sprinkler_node; + /* Get Shutters */ + if (json_object_get_type(node) == json_type_array) + { + int length; + struct json_object *sprinkler_node; - length = json_object_array_length(node); - for (int i = 0; i < length; i++) - { + length = json_object_array_length(node); + for (int i = 0; i < length; i++) + { sprinkler_t *sprinkler = sprinkler_new(); sprinkler_node = json_object_array_get_idx(node, i); if (sprinkler_from_json(sprinkler, sprinkler_node) == 0) { qlist_addlast(dm->sprinklers, sprinkler, sizeof(sprinkler_t)); } - } - } + } + } - return 0; + return 0; } /*--------------------------------------------------------------------------*/ struct json_object *save_sprinklers(devices_manager_t *dm) { - struct json_object *root_node; - sprinkler_t *sprinkler; + struct json_object *root_node; + sprinkler_t *sprinkler; qlist_obj_t obj; - memset((void *) &obj, 0, sizeof(obj)); - root_node = json_object_new_array(); + memset((void *)&obj, 0, sizeof(obj)); + root_node = json_object_new_array(); while (qlist_getnext(dm->sprinklers, &obj, true)) { @@ -381,13 +545,91 @@ struct json_object *save_sprinklers(devices_manager_t *dm) json_object_array_add(root_node, sprinkler_to_json_object(sprinkler)); } - return root_node; + return root_node; } /*--------------------------------------------------------------------------*/ int create_sprinkler(devices_manager_t *dm, struct json_object *node) { - #warning "TODO" + sprinkler_t *sprinkler = sprinkler_new(); + + if (sprinkler_from_json(sprinkler, node) != 0) + { + sprinkler_free(sprinkler); + return -1; + } + + device_set_id(sprinkler->device, ++dm->sprinklers_max_id); + qlist_addlast(dm->sprinklers, sprinkler, sizeof(sprinkler_t)); + return 0; } + +/*--------------------------------------------------------------------------*/ + +int remove_sprinkler(devices_manager_t *dm, uint16_t id) +{ + qlist_obj_t obj; + sprinkler_t *sprinkler; + int position = 0; + + memset((void *)&obj, 0, sizeof(obj)); + + while (qlist_getnext(dm->sprinklers, &obj, true)) + { + sprinkler = obj.data; + if (sprinkler->device->id == id) + { + qlist_removeat(dm->sprinklers, position); + return 0; + } + position++; + } + + return -1; +} + +/*--------------------------------------------------------------------------*/ + +int update_sprinkler(devices_manager_t *dm, uint16_t id, struct json_object *node) +{ + qlist_obj_t obj; + sprinkler_t *sprinkler; + + memset((void *)&obj, 0, sizeof(obj)); + + while (qlist_getnext(dm->sprinklers, &obj, true)) + { + sprinkler = obj.data; + if (sprinkler->device->id == id) + { + sprinkler_from_json(sprinkler, node); + return 0; + } + } + + return -1; +} + +/*--------------------------------------------------------------------------*/ + +int set_sprinkler_state(devices_manager_t *dm, uint16_t id, bool state) +{ + qlist_obj_t obj; + sprinkler_t *sprinkler; + + memset((void *)&obj, 0, sizeof(obj)); + + while (qlist_getnext(dm->sprinklers, &obj, true)) + { + sprinkler = obj.data; + if (sprinkler->device->id == id) + { + sprinkler->device->state = state; + return 0; + } + } + + return -1; +} diff --git a/src/devices/devices_manager.h b/src/devices/devices_manager.h index dfbc5e4..9c61530 100644 --- a/src/devices/devices_manager.h +++ b/src/devices/devices_manager.h @@ -49,8 +49,11 @@ struct devices_manager_s char *file_path; qlist_t *outlets; + uint16_t outlets_max_id; qlist_t *shutters; + uint16_t shutters_max_id; qlist_t *sprinklers; + uint16_t sprinklers_max_id; }; /*--------------------------- PUBLIC FUNCTIONS -------------------------------*/ @@ -67,8 +70,8 @@ extern char *devices_manager_get_by_id(devices_manager_t *dm, const char *capabi extern int devices_manager_set(devices_manager_t *dm, const char *capability, struct json_object *node); extern int devices_manager_set_state(devices_manager_t *dm, const char *capability, int id, bool state); -extern int devices_manager_create(devices_manager_t *dm, const char *a_capability, struct json_object *node); -extern int devices_manager_update(devices_manager_t *dm, const char *a_capability, struct json_object *node); -extern int devices_manager_delete(devices_manager_t *dm, const char *a_capability, struct json_object *node); +extern int devices_manager_create(devices_manager_t *dm, const char *capability, struct json_object *node); +extern int devices_manager_update(devices_manager_t *dm, const char *capability, struct json_object *node); +extern int devices_manager_delete(devices_manager_t *dm, const char *capability, struct json_object *node); #endif /*_DEVICES_MANAGER_H */ diff --git a/src/tests/test_device.c b/src/tests/test_device.c new file mode 100644 index 0000000..d1ed2e3 --- /dev/null +++ b/src/tests/test_device.c @@ -0,0 +1,92 @@ +/*! + * rest_handler.c + * + * Copyright (c) 2015-2019, NADAL Jean-Baptiste. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * @Author: NADAL Jean-Baptiste + * @Date: 26/12/2019 + * + */ + +// This is an independent project of an individual developer. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com + +#include +#include + +#include "qunit.h" + +#include "domo.h" +#include "devices/devices_manager.h" + +QUNIT_START("Test Data Model"); + + + +TEST("devices_manager create and free") +{ + devices_manager_t *dm; + + dm = devices_manager_new(); + ASSERT_NOT_NULL(dm); + devices_manager_free(dm); +} + +TEST("sprinkler - create set_state remove.") +{ + struct json_object *root_node; + devices_manager_t *dm; + int ret; + dm = devices_manager_new(); + ASSERT_NOT_NULL(dm); + + root_node = json_object_new_object(); + json_object_object_add(root_node, k_entry_name, json_object_new_string("test_name")); + + ret = devices_manager_create(dm, kSprinklerEntry, root_node); + ASSERT_EQUAL_INT(ret, 0); + + /* Clean the json object. */ + json_object_put(root_node); + + devices_manager_free(dm); +} + +#if 0 +devices_manager_t + +kOutletEntry +kShutterEntry +kSprinklerEntry + + +extern int devices_manager_load(devices_manager_t *dm, char *config_path); +extern int devices_manager_save(devices_manager_t *dm); + +extern char *devices_manager_get(devices_manager_t *dm, const char *capability); +extern char *devices_manager_get_by_id(devices_manager_t *dm, const char *capability, uint32_t id); + +extern int devices_manager_set(devices_manager_t *dm, const char *capability, struct json_object *node); +extern int devices_manager_set_state(devices_manager_t *dm, const char *capability, int id, bool state); + +extern int devices_manager_create(devices_manager_t *dm, const char *capability, struct json_object *node); +extern int devices_manager_update(devices_manager_t *dm, const char *capability, struct json_object *node); +extern int devices_manager_delete(devices_manager_t *dm, const char *capability, struct json_object *node); +#endif + +QUNIT_END();