diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index daf33207..38b59ab9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -81,15 +81,8 @@ run_memory_test: when: always paths: - timestamp.log - - memory-report-usp-get.xml - - memory-report-usp-operate.xml - - memory-report-usp-schema.xml - - memory-report-usp-instances.xml - - memory-report-cwmp-get.xml - - memory-report-cwmp-operate.xml - - memory-report-cwmp-schema.xml - - memory-report-cwmp-instances.xml - memory-test-coverage.xml + - bbf_out.zip run_uspd: stage: uspd diff --git a/dmdynamicjson.c b/dmdynamicjson.c index c07d0268..650ff478 100644 --- a/dmdynamicjson.c +++ b/dmdynamicjson.c @@ -37,17 +37,24 @@ struct dm_json_obj { struct list_head list; json_object *data; char *name; + int json_version; operation_args command_arg; event_args event_arg; }; -static void save_json_data(struct list_head *json_list, char *name, json_object *data, +enum json_plugin_version { + JSON_VERSION_0, + JSON_VERSION_1 +}; + +static void save_json_data(struct list_head *json_list, char *name, json_object *data, int json_version, const char **in_p, const char **out_p, const char **ev_arg) { struct dm_json_obj *dm_json_obj = dm_dynamic_calloc(&json_memhead, 1, sizeof(struct dm_json_obj)); if (name) dm_json_obj->name = dm_dynamic_strdup(&json_memhead, name); if (data) dm_json_obj->data = data; + dm_json_obj->json_version = json_version; dm_json_obj->command_arg.in = in_p; dm_json_obj->command_arg.out = out_p; dm_json_obj->event_arg.param = ev_arg; @@ -189,7 +196,7 @@ static char *generate_path_without_instance(char *full_obj, bool is_obj) char *str = dm_dynamic_strdup(&json_memhead, full_obj); for (pch = strtok_r(str, ".", &pchr); pch != NULL; pch = strtok_r(NULL, ".", &pchr)) { - if (atoi(pch) == 0) { + if (atoi(pch) == 0 && strcmp(pch, "{i}") != 0) { pos += snprintf(buf + pos, sizeof(buf) - pos, "%s.", pch); } } @@ -215,17 +222,26 @@ static int browse_obj(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, { struct dm_json_obj *pobj = NULL; struct json_object *mapping_obj = NULL; + struct json_object *mapping_0 = NULL; struct json_object *type = NULL; + int json_version = JSON_VERSION_0; char *obj = generate_path_without_instance(parent_node->current_object, true); list_for_each_entry(pobj, &json_list, list) { if (strcmp(pobj->name, obj) == 0) { mapping_obj = pobj->data; + json_version = pobj->json_version; break; } } - json_object_object_get_ex(mapping_obj, "type", &type); + if (json_version == JSON_VERSION_1 && mapping_obj && json_object_get_type(mapping_obj) == json_type_array) { + mapping_0 = json_object_array_get_idx(mapping_obj, 0); + json_object_object_get_ex(mapping_0, "type", &type); + } else { + json_object_object_get_ex(mapping_obj, "type", &type); + } + if (type && strcmp(json_object_get_string(type), "uci") == 0) { char buf_instance[64], buf_alias[64], *object = NULL; struct json_object *uci_obj = NULL; @@ -237,7 +253,7 @@ static int browse_obj(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, struct dmmap_dup *p = NULL; LIST_HEAD(dup_list); - json_object_object_get_ex(mapping_obj, "uci", &uci_obj); + json_object_object_get_ex((mapping_0 && json_version == JSON_VERSION_1) ? mapping_0 : mapping_obj, "uci", &uci_obj); json_object_object_get_ex(uci_obj, "file", &file); json_object_object_get_ex(uci_obj, "section", §ion); json_object_object_get_ex(section, "type", §ion_type); @@ -275,7 +291,7 @@ static int browse_obj(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, struct json_object *key = NULL; char *args1 = NULL; - json_object_object_get_ex(mapping_obj, "ubus", &ubus_obj); + json_object_object_get_ex((mapping_0 && json_version == JSON_VERSION_1) ? mapping_0 : mapping_obj, "ubus", &ubus_obj); json_object_object_get_ex(ubus_obj, "object", &object); json_object_object_get_ex(ubus_obj, "method", &method); json_object_object_get_ex(ubus_obj, "args", &args_obj); @@ -306,18 +322,27 @@ static int add_obj(char *refparam, struct dmctx *ctx, void *data, char **instanc { struct dm_json_obj *pobj = NULL; struct json_object *mapping_obj = NULL; - struct json_object *type = NULL; + struct json_object *mapping_0 = NULL; + struct json_object *obj_type = NULL; + int json_version = JSON_VERSION_0; char *obj = generate_path_without_instance(refparam, true); list_for_each_entry(pobj, &json_list, list) { if (strcmp(pobj->name, obj) == 0) { mapping_obj = pobj->data; + json_version = pobj->json_version; break; } } - json_object_object_get_ex(mapping_obj, "type", &type); - if (type && strcmp(json_object_get_string(type), "uci") == 0) { + if (json_version == JSON_VERSION_1 && mapping_obj && json_object_get_type(mapping_obj) == json_type_array) { + mapping_0 = json_object_array_get_idx(mapping_obj, 0); + json_object_object_get_ex(mapping_0, "type", &obj_type); + } else { + json_object_object_get_ex(mapping_obj, "type", &obj_type); + } + + if (obj_type && strcmp(json_object_get_string(obj_type), "uci") == 0) { struct json_object *uci_obj = NULL; struct json_object *file = NULL; struct json_object *section = NULL; @@ -326,7 +351,7 @@ static int add_obj(char *refparam, struct dmctx *ctx, void *data, char **instanc char *object = NULL; char buf_instance[64]; - json_object_object_get_ex(mapping_obj, "uci", &uci_obj); + json_object_object_get_ex((mapping_0 && json_version == JSON_VERSION_1) ? mapping_0 : mapping_obj, "uci", &uci_obj); json_object_object_get_ex(uci_obj, "file", &file); json_object_object_get_ex(uci_obj, "section", §ion); json_object_object_get_ex(section, "type", §ion_type); @@ -356,17 +381,26 @@ static int delete_obj(char *refparam, struct dmctx *ctx, void *data, char *insta { struct dm_json_obj *pobj = NULL; struct json_object *mapping_obj = NULL; + struct json_object *mapping_0 = NULL; struct json_object *type_obj = NULL; + int json_version = JSON_VERSION_0; char *obj = generate_path_without_instance(refparam, true); list_for_each_entry(pobj, &json_list, list) { if (strcmp(pobj->name, obj) == 0) { mapping_obj = pobj->data; + json_version = pobj->json_version; break; } } - json_object_object_get_ex(mapping_obj, "type", &type_obj); + if (json_version == JSON_VERSION_1 && mapping_obj && json_object_get_type(mapping_obj) == json_type_array) { + mapping_0 = json_object_array_get_idx(mapping_obj, 0); + json_object_object_get_ex(mapping_0, "type", &type_obj); + } else { + json_object_object_get_ex(mapping_obj, "type", &type_obj); + } + if (type_obj && strcmp(json_object_get_string(type_obj), "uci") == 0) { struct json_object *uci_obj = NULL; struct json_object *file = NULL; @@ -374,7 +408,7 @@ static int delete_obj(char *refparam, struct dmctx *ctx, void *data, char *insta struct json_object *section_type = NULL; struct json_object *dmmap_file = NULL; - json_object_object_get_ex(mapping_obj, "uci", &uci_obj); + json_object_object_get_ex((mapping_0 && json_version == JSON_VERSION_1) ? mapping_0 : mapping_obj, "uci", &uci_obj); json_object_object_get_ex(uci_obj, "file", &file); json_object_object_get_ex(uci_obj, "section", §ion); json_object_object_get_ex(section, "type", §ion_type); @@ -436,7 +470,7 @@ static void replace_indexes(struct dmctx *ctx, char *refparam, char *obj, size_t } } -static char *uci_get_value(json_object *mapping_obj, char *refparam, struct dmctx *ctx, void *data, char *instance) +static char *uci_get_value(json_object *mapping_obj, int json_version, char *refparam, struct dmctx *ctx, void *data, char *instance) { struct json_object *obj = NULL; struct json_object *file = NULL; @@ -446,7 +480,6 @@ static char *uci_get_value(json_object *mapping_obj, char *refparam, struct dmct struct json_object *option = NULL; struct json_object *option_name = NULL; struct json_object *path = NULL; - struct json_object *ref = NULL; char *value = ""; json_object_object_get_ex(mapping_obj, "uci", &obj); @@ -457,7 +490,21 @@ static char *uci_get_value(json_object *mapping_obj, char *refparam, struct dmct json_object_object_get_ex(obj, "option", &option); json_object_object_get_ex(option, "name", &option_name); json_object_object_get_ex(obj, "path", &path); - json_object_object_get_ex(obj, "ref", &ref); + + if (file && type && option_name && strstr(refparam, "NumberOfEntries") && json_version == JSON_VERSION_1) { + + if (strcmp(json_object_get_string(option_name), "@Count") != 0) + goto end; + + struct uci_section *s = NULL; + int cnt = 0; + + uci_foreach_sections(json_object_get_string(file), json_object_get_string(type), s) { + cnt++; + } + dmasprintf(&value, "%d", cnt); + goto end; + } if (data && file && type && option_name) { if (strcmp(json_object_get_string(option_name), "@Name") == 0) { @@ -466,13 +513,6 @@ static char *uci_get_value(json_object *mapping_obj, char *refparam, struct dmct char uci_type[32] = {0}; snprintf(uci_type, sizeof(uci_type), "@%s[%d]", json_object_get_string(type), instance ? atoi(instance)-1 : 0); value = bbf_uci_get_value(json_object_get_string(path), json_object_get_string(file), uci_type, json_object_get_string(option_name)); - if (ref) { - char *linker = dmstrdup(value); - adm_entry_get_linker_param(ctx, json_object_get_string(path), linker, &value); - dmfree(linker); - if (value == NULL) - value = ""; - } } } else if (file && section_name && option_name) { value = bbf_uci_get_value(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), json_object_get_string(option_name)); @@ -481,10 +521,11 @@ static char *uci_get_value(json_object *mapping_obj, char *refparam, struct dmct if (strstr(refparam, "Alias") && value[0] == '\0') dmasprintf(&value, "cpe-%s", instance); +end: return value; } -static char *ubus_get_value(json_object *mapping_obj, char *refparam, struct dmctx *ctx, void *data, char *instance) +static char *ubus_get_value(json_object *mapping_obj, int json_version, char *refparam, struct dmctx *ctx, void *data, char *instance) { struct json_object *ubus_obj = NULL; struct json_object *object = NULL; @@ -508,14 +549,14 @@ static char *ubus_get_value(json_object *mapping_obj, char *refparam, struct dmc if ((opt = strstr(json_object_get_string(object), "@Name"))) { *opt = '\0'; snprintf(arg2_1, sizeof(arg2_1), "%s%s", json_object_get_string(object), section_name((struct uci_section *)data)); - } else if ((opt = strstr(json_object_get_string(object), "@i-1"))) { + } else if ((opt = strstr(json_object_get_string(object), (json_version == JSON_VERSION_1) ? "@index" : "@i-1"))) { *opt = '\0'; snprintf(arg2_1, sizeof(arg2_1), "%s%d", json_object_get_string(object), atoi(instance) - 1); } else { DM_STRNCPY(arg2_1, json_object_get_string(object), sizeof(arg2_1)); } - if (args1 && args2) { + if (args1 && args2 && method) { if (data && (strcmp(json_object_get_string(args2), "@Name") == 0)) { dmubus_call(arg2_1, json_object_get_string(method), UBUS_ARGS{{args1, section_name((struct uci_section *)data), String}}, 1, &res); } else if (strstr(json_object_get_string(args2), "{i}")) { @@ -530,23 +571,91 @@ static char *ubus_get_value(json_object *mapping_obj, char *refparam, struct dmc dmubus_call(arg2_1, json_object_get_string(method), UBUS_ARGS{0}, 0, &res); } - if (json_object_get_string(key)) { + if (key && strstr(refparam, "NumberOfEntries") && json_version == JSON_VERSION_1) { + char buf[64] = {0}; + char *str = NULL; + + DM_STRNCPY(buf, json_object_get_string(key), sizeof(buf)); + if ((str = strstr(buf, ".@Count")) == NULL || res == NULL) + goto end; + + json_object *arr_obj = NULL; + int nbre_entries = 0; + *str = 0; + + json_object_object_get_ex(res, buf, &arr_obj); + nbre_entries = (arr_obj) ? json_object_array_length(arr_obj) : 0; + dmasprintf(&value, "%d", nbre_entries); + goto end; + } + + if (key) { char arg6_buf[128] = ""; DM_STRNCPY(arg6_buf, json_object_get_string(key), sizeof(arg6_buf)); - char *is_array = strstr(arg6_buf, "[@i-1]"); + char *is_array = strstr(arg6_buf, (json_version == JSON_VERSION_1) ? "[@index]" : "[@i-1]"); if (is_array) { - char *arguments = is_array + sizeof("[@i-1]"); + char *arguments = (json_version == JSON_VERSION_1) ? is_array + sizeof("[@index]") : is_array + sizeof("[@i-1]"); value = get_param_ubus_value((json_object *)data, arguments); } else { value = get_param_ubus_value(res, arg6_buf); } } +end: return value; } -static char *get_value_from_mapping(json_object *param_obj, char *refparam, struct dmctx *ctx, void *data, char *instance) +static char *uci_v1_get_value(json_object *mapping_obj, char *refparam, struct dmctx *ctx, void *data, char *instance) +{ + struct json_object *data_s = NULL; + struct json_object *key = NULL; + char *value = ""; + + json_object_object_get_ex(mapping_obj, "data", &data_s); + json_object_object_get_ex(mapping_obj, "key", &key); + + if (data == NULL || data_s == NULL || (data_s && strcmp(json_object_get_string(data_s), "@Parent") != 0)) + goto end; + + + if (key) { + if (strcmp(json_object_get_string(key), "@Name") == 0) { + dmasprintf(&value, "%s", section_name((struct uci_section *)data)); + } else { + dmuci_get_value_by_section_string((struct uci_section *)data, json_object_get_string(key), &value); + } + } + +end: + return value; +} + +static char *ubus_v1_get_value(json_object *mapping_obj, char *refparam, struct dmctx *ctx, void *data, char *instance) +{ + struct json_object *data_json = NULL; + struct json_object *key = NULL; + char *value = ""; + + json_object_object_get_ex(mapping_obj, "data", &data_json); + json_object_object_get_ex(mapping_obj, "key", &key); + + if (data == NULL || data_json == NULL || (data_json && strcmp(json_object_get_string(data_json), "@Parent") != 0)) + goto end; + + if (key) { + char key_buf[128] = ""; + + DM_STRNCPY(key_buf, json_object_get_string(key), sizeof(key_buf)); + value = get_param_ubus_value((json_object *)data, key_buf); + + } + +end: + return value; +} + +static char *get_value_from_mapping(json_object *param_obj, int json_version, char *refparam, struct dmctx *ctx, void *data, char *instance) { struct json_object *mapping_arr = NULL, *mapping = NULL; @@ -554,20 +663,30 @@ static char *get_value_from_mapping(json_object *param_obj, char *refparam, stru return ""; json_object_object_get_ex(param_obj, "mapping", &mapping_arr); - if (mapping_arr && json_object_get_type(mapping_arr) == json_type_array) - mapping = json_object_array_get_idx(mapping_arr, 0); + if (mapping_arr && json_object_get_type(mapping_arr) == json_type_array) { - if (mapping) { - struct json_object *type = NULL; + for (int idx = 0; (mapping = json_object_array_get_idx(mapping_arr, idx)) != NULL; idx++) { + struct json_object *type = NULL; + struct json_object *rpc = NULL; - json_object_object_get_ex(mapping, "type", &type); + json_object_object_get_ex(mapping, "rpc", &rpc); + json_object_object_get_ex(mapping, "type", &type); + + if (rpc && json_version == JSON_VERSION_1 && strcmp(json_object_get_string(rpc), "get") != 0) + continue; + + if (type && strcmp(json_object_get_string(type), "uci") == 0) + return uci_get_value(mapping, json_version, refparam, ctx, data, instance); + else if (type && strcmp(json_object_get_string(type), "ubus") == 0) + return ubus_get_value(mapping, json_version, refparam, ctx, data, instance); + else if (type && strcmp(json_object_get_string(type), "uci_sec") == 0 && json_version == JSON_VERSION_1) + return uci_v1_get_value(mapping, refparam, ctx, data, instance); + else if (type && strcmp(json_object_get_string(type), "json") == 0 && json_version == JSON_VERSION_1) + return ubus_v1_get_value(mapping, refparam, ctx, data, instance); + else + return ""; + } - if (type && strcmp(json_object_get_string(type), "uci") == 0) - return uci_get_value(mapping, refparam, ctx, data, instance); - else if (type && strcmp(json_object_get_string(type), "ubus") == 0) - return ubus_get_value(mapping, refparam, ctx, data, instance); - else - return ""; } return ""; @@ -577,20 +696,22 @@ static int getvalue_param(char *refparam, struct dmctx *ctx, void *data, char *i { struct dm_json_obj *pleaf = NULL; json_object *param_obj = NULL; + int json_version = JSON_VERSION_0; char *obj = generate_path_without_instance(refparam, false); list_for_each_entry(pleaf, &json_list, list) { if (strcmp(pleaf->name, obj) == 0) { param_obj = pleaf->data; + json_version = pleaf->json_version; break; } } - *value = get_value_from_mapping(param_obj, refparam, ctx, data, instance); + *value = get_value_from_mapping(param_obj, json_version, refparam, ctx, data, instance); return 0; } -static int ubus_set_operate(json_object *mapping_obj, struct dmctx *ctx, void *data, void *value, char *instance) +static int ubus_set_operate(json_object *mapping_obj, int json_version, struct dmctx *ctx, void *data, void *value, char *instance) { struct json_object *ubus_obj = NULL; struct json_object *object = NULL; @@ -605,7 +726,7 @@ static int ubus_set_operate(json_object *mapping_obj, struct dmctx *ctx, void *d if ((opt = strstr(json_object_get_string(object), "@Name"))) { *opt = '\0'; snprintf(obj_name, sizeof(obj_name), "%s%s", json_object_get_string(object), section_name((struct uci_section *)data)); - } else if ((opt = strstr(json_object_get_string(object), "@i-1"))) { + } else if ((opt = strstr(json_object_get_string(object), (json_version == JSON_VERSION_1) ? "@index" : "@i-1"))) { *opt = '\0'; snprintf(obj_name, sizeof(obj_name), "%s%d", json_object_get_string(object), atoi(instance) - 1); } else { @@ -624,40 +745,6 @@ static int ubus_set_operate(json_object *mapping_obj, struct dmctx *ctx, void *d return CMD_SUCCESS; } -static int setcommand_param(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dm_json_obj *leaf_node = NULL; - struct json_object *p_obj = NULL, *map_arr = NULL, *map_obj = NULL, *type = NULL; - - char *obj = generate_path_without_instance(refparam, false); - list_for_each_entry(leaf_node, &json_list, list) { - if (strcmp(leaf_node->name, obj) == 0) { - p_obj = leaf_node->data; - break; - } - } - - if (p_obj == NULL) { - return CMD_FAIL; - } - - json_object_object_get_ex(p_obj, "mapping", &map_arr); - if (map_arr && json_object_get_type(map_arr) == json_type_array) - map_obj = json_object_array_get_idx(map_arr, 0); - - if (!map_obj) { - return CMD_FAIL; - } - - json_object_object_get_ex(map_obj, "type", &type); - - if (type && strcmp(json_object_get_string(type), "ubus") == 0) { - return ubus_set_operate(map_obj, ctx, data, value, instance); - } - - return CMD_FAIL; -} - static int getcommand_param(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { struct dm_json_obj *leaf = NULL; @@ -680,6 +767,42 @@ static int getcommand_param(char *refparam, struct dmctx *ctx, void *data, char return 0; } +static int setcommand_param(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + struct dm_json_obj *leaf_node = NULL; + struct json_object *p_obj = NULL, *map_arr = NULL, *map_obj = NULL, *type = NULL; + int json_version = JSON_VERSION_0; + + char *obj = generate_path_without_instance(refparam, false); + list_for_each_entry(leaf_node, &json_list, list) { + if (strcmp(leaf_node->name, obj) == 0) { + p_obj = leaf_node->data; + json_version = leaf_node->json_version; + break; + } + } + + if (p_obj == NULL) { + return CMD_FAIL; + } + + json_object_object_get_ex(p_obj, "mapping", &map_arr); + if (map_arr && json_object_get_type(map_arr) == json_type_array) + map_obj = json_object_array_get_idx(map_arr, 0); + + if (!map_obj) { + return CMD_FAIL; + } + + json_object_object_get_ex(map_obj, "type", &type); + + if (type && strcmp(json_object_get_string(type), "ubus") == 0) { + return ubus_set_operate(map_obj, json_version, ctx, data, value, instance); + } + + return CMD_FAIL; +} + static int getevent_param(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { struct dm_json_obj *leaf = NULL; @@ -907,7 +1030,101 @@ static int dm_validate_value(json_object *json_obj, char *value) return 0; } -static void set_value_from_mapping(json_object *param_obj, char *refparam, struct dmctx *ctx, void *data, char *instance, char *value) +static void uci_set_value(json_object *mapping_obj, int json_version, char *refparam, struct dmctx *ctx, void *data, char *instance, char *value) +{ + struct json_object *uci_obj = NULL; + struct json_object *file = NULL; + struct json_object *section = NULL; + struct json_object *type = NULL; + struct json_object *section_name = NULL; + struct json_object *option = NULL; + struct json_object *option_name = NULL; + struct json_object *path = NULL; + + json_object_object_get_ex(mapping_obj, "uci", &uci_obj); + json_object_object_get_ex(uci_obj, "file", &file); + json_object_object_get_ex(uci_obj, "section", §ion); + json_object_object_get_ex(section, "type", &type); + json_object_object_get_ex(section, "name", §ion_name); + json_object_object_get_ex(uci_obj, "option", &option); + json_object_object_get_ex(option, "name", &option_name); + json_object_object_get_ex(uci_obj, "path", &path); + + if (data && file && type && option_name) { + char uci_type[32] = {0}; + + snprintf(uci_type, sizeof(uci_type), "@%s[%d]", json_object_get_string(type), instance ? atoi(instance)-1 : 0); + bbf_uci_set_value(json_object_get_string(path), json_object_get_string(file), uci_type, json_object_get_string(option_name), value); + } else if (file && section_name && option_name) { + bbf_uci_set_value(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), json_object_get_string(option_name), value); + } +} + +static void ubus_set_value(json_object *mapping_obj, int json_version, char *refparam, struct dmctx *ctx, void *data, char *instance, char *value) +{ + struct json_object *ubus_obj = NULL; + struct json_object *object = NULL; + struct json_object *method = NULL; + struct json_object *args = NULL; + char *args1 = NULL, *opt = NULL; + char obj_buf[128] = {0}; + char object_buf[256] = {0}; + + json_object_object_get_ex(mapping_obj, "ubus", &ubus_obj); + json_object_object_get_ex(ubus_obj, "object", &object); + json_object_object_get_ex(ubus_obj, "method", &method); + json_object_object_get_ex(ubus_obj, "args", &args); + json_object_object_foreach(args, arg1, args2) { + args1 = arg1; + } + + DM_STRNCPY(obj_buf, json_object_get_string(object), sizeof(obj_buf)); + + if ((opt = strstr(obj_buf, "@Name"))) { + *opt = '\0'; + snprintf(object_buf, sizeof(object_buf), "%s%s", obj_buf, section_name((struct uci_section *)data)); + } else if ((opt = strstr(obj_buf, (json_version == JSON_VERSION_1) ? "@index" : "@i-1"))) { + *opt = '\0'; + snprintf(object_buf, sizeof(object_buf), "%s%d", obj_buf, atoi(instance) - 1); + } else { + DM_STRNCPY(object_buf, json_object_get_string(object), sizeof(object_buf)); + } + + if (args1 && args2 && method) { + if (data && (strcmp(json_object_get_string(args2), "@Name") == 0)) { + dmubus_call_set(object_buf, json_object_get_string(method), UBUS_ARGS{{args1, section_name((struct uci_section *)data), String}}, 1); + } else if (strstr(json_object_get_string(args2), "{i}")) { + char arg2_buf[512] = {0}; + + replace_indexes(ctx, json_object_get_string(args2), arg2_buf, sizeof(arg2_buf)); + dmubus_call_set(object_buf, json_object_get_string(method), UBUS_ARGS{{args1, arg2_buf, String}}, 1); + } else if (strcmp(json_object_get_string(args2), "@Value") == 0) { + dmubus_call_set(object_buf, json_object_get_string(method), UBUS_ARGS{{args1, value, String}}, 1); + } else { + dmubus_call_set(object_buf, json_object_get_string(method), UBUS_ARGS{{args1, json_object_get_string(args2), String}}, 1); + } + } else { + dmubus_call_set(object_buf, json_object_get_string(method), UBUS_ARGS{0}, 0); + } +} + +static void uci_v1_set_value(json_object *mapping_obj, int json_version, char *refparam, struct dmctx *ctx, void *data, char *instance, char *value) +{ + struct json_object *data_s = NULL; + struct json_object *key = NULL; + + json_object_object_get_ex(mapping_obj, "data", &data_s); + json_object_object_get_ex(mapping_obj, "key", &key); + + if (data == NULL || data_s == NULL || (data_s && strcmp(json_object_get_string(data_s), "@Parent") != 0)) + return; + + if (key) { + dmuci_set_value_by_section((struct uci_section *)data, json_object_get_string(key), value); + } +} + +static void set_value_from_mapping(json_object *param_obj, int json_version, char *refparam, struct dmctx *ctx, void *data, char *instance, char *value) { struct json_object *mapping_arr = NULL, *mapping = NULL; @@ -915,50 +1132,28 @@ static void set_value_from_mapping(json_object *param_obj, char *refparam, struc return; json_object_object_get_ex(param_obj, "mapping", &mapping_arr); - if (mapping_arr && json_object_get_type(mapping_arr) == json_type_array) - mapping = json_object_array_get_idx(mapping_arr, 0); + if (mapping_arr && json_object_get_type(mapping_arr) == json_type_array) { - if (mapping) { - struct json_object *type = NULL; + for (int idx = 0; (mapping = json_object_array_get_idx(mapping_arr, idx)) != NULL; idx++) { + struct json_object *type = NULL; + struct json_object *rpc = NULL; - json_object_object_get_ex(mapping, "type", &type); + json_object_object_get_ex(mapping, "rpc", &rpc); + json_object_object_get_ex(mapping, "type", &type); - if (type && strcmp(json_object_get_string(type), "uci") == 0) { - struct json_object *uci_obj = NULL; - struct json_object *file = NULL; - struct json_object *section = NULL; - struct json_object *section_name = NULL; - struct json_object *option = NULL; - struct json_object *option_name = NULL; - struct json_object *path = NULL; - struct json_object *ref = NULL; + if (rpc && json_version == JSON_VERSION_1 && strcmp(json_object_get_string(rpc), "set") != 0) + continue; - json_object_object_get_ex(mapping, "uci", &uci_obj); - json_object_object_get_ex(uci_obj, "file", &file); - json_object_object_get_ex(uci_obj, "section", §ion); - json_object_object_get_ex(section, "type", &type); - json_object_object_get_ex(section, "name", §ion_name); - json_object_object_get_ex(uci_obj, "option", &option); - json_object_object_get_ex(option, "name", &option_name); - json_object_object_get_ex(uci_obj, "path", &path); - json_object_object_get_ex(uci_obj, "ref", &ref); + if (type && strcmp(json_object_get_string(type), "uci") == 0) + uci_set_value(mapping, json_version, refparam, ctx, data, instance, value); + else if (type && strcmp(json_object_get_string(type), "ubus") == 0) + ubus_set_value(mapping, json_version, refparam, ctx, data, instance, value); + else if (type && strcmp(json_object_get_string(type), "uci_sec") == 0 && json_version == JSON_VERSION_1) + uci_v1_set_value(mapping, json_version, refparam, ctx, data, instance, value); + else + return; + } - if (data && file && type && option_name) { - char uci_type[32] = {0}; - snprintf(uci_type, sizeof(uci_type), "@%s[%d]", json_object_get_string(type), instance ? atoi(instance)-1 : 0); - if (ref) { - char *linker; - adm_entry_get_linker_value(ctx, value, &linker); - if (linker) bbf_uci_set_value(json_object_get_string(path), json_object_get_string(file), uci_type, json_object_get_string(option_name), linker); - dmfree(linker); - } else { - bbf_uci_set_value(json_object_get_string(path), json_object_get_string(file), uci_type, json_object_get_string(option_name), value); - } - } else if (file && section_name && option_name) { - bbf_uci_set_value(json_object_get_string(path), json_object_get_string(file), json_object_get_string(section_name), json_object_get_string(option_name), value); - } - } else - return; } } @@ -966,11 +1161,13 @@ static int setvalue_param(char *refparam, struct dmctx *ctx, void *data, char *i { struct dm_json_obj *pleaf = NULL; json_object *param_obj = NULL; + int json_version = JSON_VERSION_0; char *obj = generate_path_without_instance(refparam, false); list_for_each_entry(pleaf, &json_list, list) { if (strcmp(pleaf->name, obj) == 0) { param_obj = pleaf->data; + json_version = pleaf->json_version; break; } } @@ -981,7 +1178,7 @@ static int setvalue_param(char *refparam, struct dmctx *ctx, void *data, char *i return FAULT_9007; break; case VALUESET: - set_value_from_mapping(param_obj, refparam, ctx, data, instance, value); + set_value_from_mapping(param_obj, json_version, refparam, ctx, data, instance, value); break; } @@ -999,12 +1196,12 @@ static bool is_obj(char *object, json_object *jobj) return false; } -static void parse_mapping_obj(char *object, json_object *mapping_obj, struct list_head *list) +static void parse_mapping_obj(char *object, json_object *mapping_obj, int json_version, struct list_head *list) { if (!mapping_obj) return; - save_json_data(list, object, mapping_obj, NULL, NULL, NULL); + save_json_data(list, object, mapping_obj, json_version, NULL, NULL, NULL); } static bool valid_event_param(char *param) @@ -1044,7 +1241,7 @@ static char** fill_command_param(int count, struct json_object *obj) return res_p; } -static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pleaf, int i, struct list_head *list) +static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pleaf, int i, int json_version, struct list_head *list) { /* PARAM, permission, type, getvalue, setvalue, bbfdm_type(6)*/ struct json_object *type = NULL, *protocols = NULL, *write = NULL, *async = NULL, *version = NULL;; @@ -1120,7 +1317,7 @@ static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pl ev_arg[param_count - 1] = NULL; } - pleaf[i].getvalue = getevent_param; + pleaf[i].getvalue = ev_arg ? getevent_param : NULL; } else if (pleaf[i].type == DMT_COMMAND) { struct json_object *input_obj = NULL, *output_obj = NULL; @@ -1173,12 +1370,10 @@ static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pl //Version json_object_object_get_ex(jobj, "version", &version); - if(version) - DM_STRNCPY(pleaf[i].version, json_object_get_string(version), 10); - + DM_STRNCPY(pleaf[i].version, version ? json_object_get_string(version) : "", 10); snprintf(full_param, sizeof(full_param), "%s%s", object, param); - save_json_data(list, full_param, jobj, (const char**)in_p, (const char**)out_p, (const char**)ev_arg); + save_json_data(list, full_param, jobj, json_version, (const char**)in_p, (const char**)out_p, (const char**)ev_arg); } static void count_obj_param_under_jsonobj(json_object *jsonobj, int *obj_number, int *param_number) @@ -1198,7 +1393,7 @@ static void count_obj_param_under_jsonobj(json_object *jsonobj, int *obj_number, } } -static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, struct list_head *list) +static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, int json_version, struct list_head *list) { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys(13)*/ @@ -1275,20 +1470,22 @@ static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, s pobj[index].get_linker = NULL; } //Version - if(strcmp(key,"version")==0) + if (strcmp(key,"version") == 0) DM_STRNCPY(pobj[index].version, json_object_get_string(json_obj), 10); - if (strcmp(key, "mapping") == 0 && json_object_get_type(json_obj) == json_type_object) { - parse_mapping_obj(full_obj, json_obj, list); + if (strcmp(key, "mapping") == 0 && + ((json_object_get_type(json_obj) == json_type_object && json_version == JSON_VERSION_0) || + (json_object_get_type(json_obj) == json_type_array && json_version == JSON_VERSION_1))) { + parse_mapping_obj(full_obj, json_obj, json_version, list); } if (json_object_get_type(json_obj) == json_type_object && is_obj(key, json_obj)) { - parse_obj(key, json_obj, next_obj, j, list); + parse_obj(key, json_obj, next_obj, j, json_version, list); j++; } if (json_object_get_type(json_obj) == json_type_object && !is_obj(key, json_obj) && strcmp(key, "mapping") != 0) { - parse_param(full_obj, key, json_obj, next_leaf, i, list); + parse_param(full_obj, key, json_obj, next_leaf, i, json_version, list); i++; } } @@ -1306,6 +1503,8 @@ int load_json_dynamic_arrays(struct dmctx *ctx) continue; char buf[512] = {0}; + int json_plugin_version = JSON_VERSION_0; + snprintf(buf, sizeof(buf), "%s/%s", JSON_FOLDER_PATH, ent->d_name); json_object *json = json_object_from_file(buf); @@ -1315,6 +1514,11 @@ int load_json_dynamic_arrays(struct dmctx *ctx) if (!key) break; + if (strcmp(key, "json_plugin_version") == 0) { + json_plugin_version = json_object_get_int(jobj); + continue; + } + DMOBJ *dm_entryobj = NULL; char *obj_prefix = find_prefix_obj(key); @@ -1335,12 +1539,12 @@ int load_json_dynamic_arrays(struct dmctx *ctx) if (dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] == NULL) { dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] = dm_dynamic_calloc(&json_memhead, 2, sizeof(struct dm_obj_s)); - parse_obj(key, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], 0, &json_list); + parse_obj(key, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], 0, json_plugin_version, &json_list); } else { int idx = get_index_of_available_entry(dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0]); dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] = dm_dynamic_realloc(&json_memhead, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], (idx + 2) * sizeof(struct dm_obj_s)); memset(dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s)); - parse_obj(key, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], idx, &json_list); + parse_obj(key, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], idx, json_plugin_version, &json_list); } } save_loaded_json_files(&loaded_json_files, json); diff --git a/dmentry.c b/dmentry.c index 50abf53e..d7c3245f 100644 --- a/dmentry.c +++ b/dmentry.c @@ -206,7 +206,10 @@ int dm_get_supported_dm(struct dmctx *ctx, char *path, bool first_level, schema_ ctx->in_param = path; dmentry_instance_lookup_inparam(ctx); + ctx->stop = false; + ctx->nextlevel = first_level; + switch(schema_type) { case ALL_SCHEMA: ctx->isinfo = 1; @@ -223,7 +226,6 @@ int dm_get_supported_dm(struct dmctx *ctx, char *path, bool first_level, schema_ ctx->iscommand = 1; break; } - ctx->nextlevel = first_level; fault = dm_entry_get_supported_dm(ctx); diff --git a/gitlab-ci/memory-test.sh b/gitlab-ci/memory-test.sh index 575df869..fa8838fa 100755 --- a/gitlab-ci/memory-test.sh +++ b/gitlab-ci/memory-test.sh @@ -4,7 +4,12 @@ echo "Functional API Tests" pwd source ./gitlab-ci/shared.sh +# install required packages +exec_cmd apt update +exec_cmd apt install -y zip + date +%s > timestamp.log + # compile and install libbbf install_libbbf @@ -21,34 +26,36 @@ ret=0 function run_valgrind() { - echo "Running $@ in valgrind" - valgrind --xml=yes --xml-file=/builds/iopsys/bbf/memory-report-usp-get.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes /builds/iopsys/bbf/test/bbf_test/bbf_dm $@ + echo "Running bbf_dm $1 in valgrind" + valgrind --xml=yes --xml-file=/builds/iopsys/bbf/$2 --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes /builds/iopsys/bbf/test/bbf_test/bbf_dm $1 > /builds/iopsys/bbf/$3 ret=$(( ret + $? )) } echo "Running memory check on datamodel" -run_valgrind -u get Device. -# Test memory leak for get_supported_dm -run_valgrind -u get_info Device. 0 -run_valgrind -u get_info Device. 1 -run_valgrind -u get_info Device. 2 -run_valgrind -u get_info Device. 3 -run_valgrind -u get_info Device. 4 +run_valgrind "-u get_info Device. 0" "memory-report-usp-get_info-all-schema.xml" "output-report-usp-get_info-all-schema.log" -run_valgrind -u list_operate +run_valgrind "-u get_info Device. 1" "memory-report-usp-get_info-param-only.xml" "output-report-usp-get_info-param-only.log" -run_valgrind -u get_schema +run_valgrind "-u get_info Device. 2" "memory-report-usp-get_info-event-only.xml" "output-report-usp-get_info-event-only.log" -run_valgrind -u instances Device. +run_valgrind "-u get_info Device. 3" "memory-report-usp-get_info-operate-only.xml" "output-report-usp-get_info-operate-only.log" -run_valgrind -c get Device. +run_valgrind "-u get Device." "memory-report-usp-get.xml" "output-report-usp-get.log" -run_valgrind -c list_operate +run_valgrind "-u list_operate" "memory-report-usp-operate.xml" "output-report-usp-operate.log" -run_valgrind -c get_schema +run_valgrind "-u get_schema" "memory-report-usp-schema.xml" "output-report-usp-schema.log" -run_valgrind -c instances Device. +run_valgrind "-u instances Device." "memory-report-usp-instances.xml" "output-report-usp-instances.log" + +run_valgrind "-c get Device." "memory-report-cwmp-get.xml" "output-report-cwmp-get.log" + +run_valgrind "-c list_operate" "memory-report-cwmp-operate.xml" "output-report-cwmp-operate.log" + +run_valgrind "-c get_schema" "memory-report-cwmp-schema.xml" "output-report-cwmp-schema.log" + +run_valgrind "-c instances Device." "memory-report-cwmp-instances.xml" "output-report-cwmp-instances.log" if [ "$ret" -ne 0 ]; then echo "Memory check failed" @@ -58,6 +65,8 @@ fi supervisorctl stop all supervisorctl status +exec_cmd zip -r bbf_out.zip memory-report-* output-report-* + #report part #GitLab-CI output gcovr -r . 2> /dev/null #throw away stderr diff --git a/test/cmocka/functional_test_bbfd.c b/test/cmocka/functional_test_bbfd.c index 04662481..b4f78132 100644 --- a/test/cmocka/functional_test_bbfd.c +++ b/test/cmocka/functional_test_bbfd.c @@ -181,6 +181,185 @@ static void test_api_bbfdm_get_set_json_parameter(void **state) validate_parameter(ctx, "Device.WiFi.X_IOPSYS_EU_Radio.2.Stats.BytesSent", "14417451", "xsd:unsignedInt"); } +static void test_api_bbfdm_get_set_json_v1_parameter(void **state) +{ + struct dmctx *ctx = (struct dmctx *) *state; + char *value = NULL; + int fault = 0; + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.Password", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.Password", "", "xsd:string"); + + // set value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UCI_TEST_V1.Password", "iopsys_test", NULL); + assert_int_equal(fault, 0); + + // apply value ==> expected "0" error + fault = dm_entry_apply(ctx, CMD_SET_VALUE, "test_key"); + assert_int_equal(fault, 0); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.Password", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.Password", "", "xsd:string"); + + // validate uci config + fault = dmuci_get_option_value_string("users", "user", "password_required", &value); + assert_int_equal(fault, 0); + assert_string_equal(value, "iopsys_test"); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.OWSDNumberOfEntries", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.OWSDNumberOfEntries", "3", "xsd:unsignedInt"); + + // set value ==> expected "9008" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UCI_TEST_V1.OWSDNumberOfEntries", "5", NULL); + assert_int_equal(fault, FAULT_9008); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.OWSD.2.IPv6", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.OWSD.2.IPv6", "off", "xsd:unsignedInt"); + + // set value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UCI_TEST_V1.OWSD.2.IPv6", "on", NULL); + assert_int_equal(fault, 0); + + // apply value ==> expected "0" error + fault = dm_entry_apply(ctx, CMD_SET_VALUE, "key"); + assert_int_equal(fault, 0); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.OWSD.2.IPv6", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.OWSD.2.IPv6", "on", "xsd:unsignedInt"); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.OWSD.1.Port", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.OWSD.1.Port", "80", "xsd:unsignedInt"); + + // set value ==> expected "9007" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UCI_TEST_V1.OWSD.1.Port", "65536", NULL); + assert_int_equal(fault, FAULT_9007); + + // set value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UCI_TEST_V1.OWSD.1.Port", "8081", NULL); + assert_int_equal(fault, 0); + + // apply value ==> expected "0" error + fault = dm_entry_apply(ctx, CMD_SET_VALUE, "key"); + assert_int_equal(fault, 0); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.OWSD.1.Port", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.OWSD.1.Port", "8081", "xsd:unsignedInt"); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.OWSD.3.Password", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.OWSD.3.Password", "", "xsd:string"); + + // set value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UCI_TEST_V1.OWSD.3.Password", "owsd_pwd", NULL); + assert_int_equal(fault, 0); + + // apply value ==> expected "0" error + fault = dm_entry_apply(ctx, CMD_SET_VALUE, "test_key"); + assert_int_equal(fault, 0); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UCI_TEST_V1.OWSD.3.Password", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UCI_TEST_V1.OWSD.3.Password", "", "xsd:string"); + + // validate uci config + fault = dmuci_get_option_value_string("owsd", "@owsd-listen[2]", "password", &value); + assert_int_equal(fault, 0); + assert_string_equal(value, "owsd_pwd"); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UBUS_TEST_V1.Uptime", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UBUS_TEST_V1.Uptime", "5859", "xsd:string"); + + // set value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UBUS_TEST_V1.Uptime", "lan", NULL); + assert_int_equal(fault, 0); + + // apply value ==> expected "0" error + fault = dm_entry_apply(ctx, CMD_SET_VALUE, "test_key"); + assert_int_equal(fault, 0); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UBUS_TEST_V1.InterfaceNumberOfEntries", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UBUS_TEST_V1.InterfaceNumberOfEntries", "4", "xsd:unsignedInt"); + + // set value ==> expected "9008" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UBUS_TEST_V1.InterfaceNumberOfEntries", "5", NULL); + assert_int_equal(fault, FAULT_9008); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UBUS_TEST_V1.Interface.3.MacAddress", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UBUS_TEST_V1.Interface.3.MacAddress", "44:d4:37:71:b8:1f", "xsd:string"); + + // set value ==> expected "9008" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UBUS_TEST_V1.Interface.3.MacAddress", "49:d4:40:71:7e:55", NULL); + assert_int_equal(fault, FAULT_9008); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UBUS_TEST_V1.Interface.4.Ifname", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UBUS_TEST_V1.Interface.4.Ifname", "wl1", "xsd:string"); + + // set value ==> expected "9008" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UBUS_TEST_V1.Interface.4.Ifname", "lan5", NULL); + assert_int_equal(fault, FAULT_9008); + + // get value ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_VALUE, "Device.UBUS_TEST_V1.Interface.2.Media", NULL, NULL); + assert_int_equal(fault, 0); + + // validate parameter : name, type, value + validate_parameter(ctx, "Device.UBUS_TEST_V1.Interface.2.Media", "IEEE 802_3AB_GIGABIT_ETHERNET", "xsd:string"); + + // set value ==> expected "9008" error + fault = dm_entry_param_method(ctx, CMD_SET_VALUE, "Device.UBUS_TEST_V1.Interface.2.Media", "IEEE 802_11AX_5_GHZ", NULL); + assert_int_equal(fault, FAULT_9008); +} + static void test_api_bbfdm_get_set_library_parameter(void **state) { struct dmctx *ctx = (struct dmctx *) *state; @@ -910,6 +1089,48 @@ static void test_api_bbfdm_add_del_json_object(void **state) assert_int_equal(fault, FAULT_9005); } +static void test_api_bbfdm_add_del_json_v1_object(void **state) +{ + struct dmctx *ctx = (struct dmctx *) *state; + int fault = 0; + + // Get name object ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_GET_NAME, "Device.UCI_TEST_V1.OWSD.", "1", NULL); + assert_int_equal(fault, 0); + + // add object ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_ADD_OBJECT, "Device.UCI_TEST_V1.OWSD.", "test", NULL); + assert_int_equal(fault, 0); + + // check the new instance + assert_non_null(ctx->addobj_instance); + assert_string_equal(ctx->addobj_instance, "4"); + + // delete object ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_DEL_OBJECT, "Device.UCI_TEST_V1.OWSD.2.", "test_key", NULL); + assert_int_equal(fault, 0); + + // Get name object after deleting instance 2 ==> expected "9005" error + fault = dm_entry_param_method(ctx, CMD_GET_NAME, "Device.UCI_TEST_V1.OWSD.2.", "1", NULL); + assert_int_equal(fault, FAULT_9005); + + // delete all object ==> expected "0" error + fault = dm_entry_param_method(ctx, CMD_DEL_OBJECT, "Device.UCI_TEST_V1.OWSD.", "test", NULL); + assert_int_equal(fault, 0); + + // Get name object after deleting all instances ==> expected "9005" error + fault = dm_entry_param_method(ctx, CMD_GET_NAME, "Device.UCI_TEST_V1.OWSD.1.", "1", NULL); + assert_int_equal(fault, FAULT_9005); + + // add object ==> expected "9005" error + fault = dm_entry_param_method(ctx, CMD_ADD_OBJECT, "Device.UBUS_TEST_V1.Interface.", "test_key", NULL); + assert_int_equal(fault, FAULT_9005); + + // delete all object ==> expected "9005" error + fault = dm_entry_param_method(ctx, CMD_DEL_OBJECT, "Device.UBUS_TEST_V1.Interface.", "test", NULL); + assert_int_equal(fault, FAULT_9005); +} + static void test_api_bbfdm_add_del_library_object(void **state) { struct dmctx *ctx = (struct dmctx *) *state; @@ -966,6 +1187,77 @@ static void test_api_bbfdm_valid_standard_operate(void **state) } } +static void test_api_bbfdm_valid_standard_list_operate(void **state) +{ + struct dmctx *ctx = (struct dmctx *) *state; + struct dm_parameter *n; + int fault = 0, i = 0; + + fault = dm_entry_param_method(ctx, CMD_USP_LIST_OPERATE, "Device.", NULL, NULL); + assert_int_equal(fault, CMD_SUCCESS); + + list_for_each_entry(n, &ctx->list_parameter, list) { + + if (strcmp(n->name, "Device.FactoryReset()") == 0) { + assert_string_equal(n->type, "xsd:command"); + assert_string_equal(n->additional_data, "sync"); + assert_null(n->data); + } + + if (strcmp(n->name, "Device.DeviceInfo.VendorLogFile.{i}.Upload()") == 0) { + assert_string_equal(n->type, "xsd:command"); + assert_string_equal(n->additional_data, "async"); + operation_args *args = (operation_args *)n->data; + assert_non_null(args); + const char **command_in = args->in; + const char **command_out = args->out; + assert_non_null(command_in); + assert_null(command_out); + + for (i = 0; command_in[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(command_in[i], "URL"); + break; + case 1: + assert_string_equal(command_in[i], "Username"); + break; + case 2: + assert_string_equal(command_in[i], "Password"); + break; + } + } + assert_int_equal(i, 3); + } + + if (strcmp(n->name, "Device.WiFi.NeighboringWiFiDiagnostic()") == 0) { + assert_string_equal(n->type, "xsd:command"); + assert_string_equal(n->additional_data, "async"); + operation_args *args = (operation_args *)n->data; + assert_non_null(args); + const char **command_in = args->in; + const char **command_out = args->out; + assert_null(command_in); + assert_non_null(command_out); + + for (i = 0; command_out[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(command_out[i], "Status"); + break; + case 1: + assert_string_equal(command_out[i], "Result.{i}.Radio"); + break; + case 2: + assert_string_equal(command_out[i], "Result.{i}.SSID"); + break; + } + } + assert_int_equal(i, 18); + } + } +} + static void test_api_bbfdm_valid_library_operate(void **state) { struct dmctx *ctx = (struct dmctx *) *state; @@ -979,6 +1271,59 @@ static void test_api_bbfdm_valid_library_operate(void **state) list_for_each_entry(n, &ctx->list_parameter, list) { assert_string_not_equal(n->data, "0"); assert_string_equal(n->type, "xsd:unsignedInt"); + }} + +static void test_api_bbfdm_valid_library_list_operate(void **state) +{ + struct dmctx *ctx = (struct dmctx *) *state; + struct dm_parameter *n; + int fault = 0, i = 0; + + fault = dm_entry_param_method(ctx, CMD_USP_LIST_OPERATE, "Device.", NULL, NULL); + assert_int_equal(fault, CMD_SUCCESS); + + list_for_each_entry(n, &ctx->list_parameter, list) { + + if (strcmp(n->name, "Device.X_IOPSYS_EU_Reboot()") == 0) { + assert_string_equal(n->type, "xsd:command"); + assert_string_equal(n->additional_data, "sync"); + assert_null(n->data); + } + + if (strcmp(n->name, "Device.X_IOPSYS_EU_PingTEST.Run()") == 0) { + assert_string_equal(n->type, "xsd:command"); + assert_string_equal(n->additional_data, "async"); + operation_args *args = (operation_args *)n->data; + assert_non_null(args); + const char **command_in = args->in; + const char **command_out = args->out; + assert_non_null(command_in); + assert_non_null(command_out); + + for (i = 0; command_in[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(command_in[i], "Host"); + break; + } + } + assert_int_equal(i, 1); + + for (i = 0; command_out[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(command_out[i], "AverageResponseTime"); + break; + case 1: + assert_string_equal(command_out[i], "MinimumResponseTime"); + break; + case 2: + assert_string_equal(command_out[i], "MaximumResponseTime"); + break; + } + } + assert_int_equal(i, 3); + } } } @@ -997,6 +1342,111 @@ static void test_api_bbfdm_valid_json_operate(void **state) } } +static void test_api_bbfdm_valid_json_list_operate(void **state) +{ + struct dmctx *ctx = (struct dmctx *) *state; + struct dm_parameter *n; + int fault = 0, i = 0; + + fault = dm_entry_param_method(ctx, CMD_USP_LIST_OPERATE, "Device.", NULL, NULL); + assert_int_equal(fault, CMD_SUCCESS); + + list_for_each_entry(n, &ctx->list_parameter, list) { + + if (strcmp(n->name, "Device.X_IOPSYS_EU_TEST.{i}.Status()") == 0) { + assert_string_equal(n->type, "xsd:command"); + assert_string_equal(n->additional_data, "async"); + operation_args *args = (operation_args *)n->data; + assert_non_null(args); + const char **command_in = args->in; + const char **command_out = args->out; + assert_non_null(command_in); + assert_non_null(command_out); + + for (i = 0; command_in[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(command_in[i], "Option"); + break; + } + } + assert_int_equal(i, 1); + + for (i = 0; command_out[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(command_out[i], "Result"); + break; + } + } + assert_int_equal(i, 1); + } + } +} + +static void test_api_bbfdm_valid_json_v1_operate(void **state) +{ + struct dmctx *ctx = (struct dmctx *) *state; + struct dm_parameter *n; + int fault = 0; + + fault = dm_entry_param_method(ctx, CMD_USP_OPERATE, "Device.UBUS_TEST_V1.Interface.3.Status()", NULL, NULL); + assert_int_equal(fault, CMD_SUCCESS); + + list_for_each_entry(n, &ctx->list_parameter, list) { + assert_string_not_equal(n->data, "Success"); + assert_string_equal(n->type, "xsd:string"); + } +} + +static void test_api_bbfdm_valid_json_v1_list_operate(void **state) +{ + struct dmctx *ctx = (struct dmctx *) *state; + struct dm_parameter *n; + int fault = 0, i = 0; + + fault = dm_entry_param_method(ctx, CMD_USP_LIST_OPERATE, "Device.", NULL, NULL); + assert_int_equal(fault, CMD_SUCCESS); + + list_for_each_entry(n, &ctx->list_parameter, list) { + + if (strcmp(n->name, "Device.UBUS_TEST_V1.Interface.{i}.Status()") == 0) { + assert_string_equal(n->type, "xsd:command"); + assert_string_equal(n->additional_data, "async"); + operation_args *args = (operation_args *)n->data; + assert_non_null(args); + const char **command_in = args->in; + const char **command_out = args->out; + assert_non_null(command_in); + assert_non_null(command_out); + + for (i = 0; command_in[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(command_in[i], "Option"); + break; + case 1: + assert_string_equal(command_out[i], "Value"); + break; + } + } + assert_int_equal(i, 2); + + for (i = 0; command_out[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(command_out[i], "Result"); + break; + case 1: + assert_string_equal(command_out[i], "Value"); + break; + } + } + assert_int_equal(i, 2); + } + } +} + static void test_api_bbfdm_valid_library_event(void **state) { struct dmctx *ctx = (struct dmctx *) *state; @@ -1040,7 +1490,7 @@ static void test_api_bbfdm_valid_library_event(void **state) idx++; } - assert_int_equal(idx, 4); + assert_int_equal(idx, 6); } static void test_api_bbfdm_valid_json_event(void **state) @@ -1054,12 +1504,12 @@ static void test_api_bbfdm_valid_json_event(void **state) list_for_each_entry(n, &ctx->list_parameter, list) { - if (strcmp(n->name, "Device.X_IOPSYS_EU_TEST.1.Periodic!") == 0) { + if (strcmp(n->name, "Device.X_IOPSYS_EU_TEST.{i}.Periodic!") == 0) { assert_string_equal(n->type, "xsd:event"); assert_null(n->data); } - if (strcmp(n->name, "Device.X_IOPSYS_EU_TEST.1.Push!") == 0) { + if (strcmp(n->name, "Device.X_IOPSYS_EU_TEST.{i}.Push!") == 0) { assert_string_equal(n->type, "xsd:event"); event_args *args = (event_args *)n->data; assert_non_null(args); @@ -1080,7 +1530,49 @@ static void test_api_bbfdm_valid_json_event(void **state) idx++; } - assert_int_equal(idx, 4); + assert_int_equal(idx, 6); +} + +static void test_api_bbfdm_valid_json_v1_event(void **state) +{ + struct dmctx *ctx = (struct dmctx *) *state; + struct dm_parameter *n; + int fault = 0, idx = 0; + + fault = dm_entry_param_method(ctx, CMD_USP_LIST_EVENT, NULL, NULL, NULL); + assert_int_equal(fault, 0); + + list_for_each_entry(n, &ctx->list_parameter, list) { + if (strcmp(n->name, "Device.UBUS_TEST_V1.Interface.{i}.Periodic!") == 0) { + assert_string_equal(n->type, "xsd:event"); + assert_null(n->data); + } + + if (strcmp(n->name, "Device.UBUS_TEST_V1.Interface.{i}.Push!") == 0) { + assert_string_equal(n->type, "xsd:event"); + event_args *args = (event_args *)n->data; + assert_non_null(args); + const char **event_param = args->param; + assert_non_null(event_param); + for (int i = 0; event_param[i] != NULL; i++) { + switch (i) { + case 0: + assert_string_equal(event_param[i], "Data"); + break; + case 1: + assert_string_equal(event_param[i], "Status"); + break; + case 2: + assert_string_equal(event_param[i], "Value"); + break; + } + } + } + + idx++; + } + + assert_int_equal(idx, 6); } int main(void) @@ -1089,6 +1581,7 @@ int main(void) // Get/Set Value method test cases cmocka_unit_test_setup_teardown(test_api_bbfdm_get_set_standard_parameter, setup, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_get_set_json_parameter, setup, teardown_commit), + cmocka_unit_test_setup_teardown(test_api_bbfdm_get_set_json_v1_parameter, setup, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_get_set_library_parameter, setup, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_get_set_standard_parameter_alias, setup_alias, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_input_value_validation_json_parameter, setup, teardown_commit), @@ -1096,16 +1589,23 @@ int main(void) // Add/Delete Object method test cases cmocka_unit_test_setup_teardown(test_api_bbfdm_add_del_standard_object, setup, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_add_del_json_object, setup, teardown_commit), + cmocka_unit_test_setup_teardown(test_api_bbfdm_add_del_json_v1_object, setup, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_add_del_library_object, setup, teardown_commit), // Operate method test cases cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_standard_operate, setup, teardown_commit), + cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_standard_list_operate, setup, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_library_operate, setup, teardown_commit), + cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_library_list_operate, setup, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_json_operate, setup, teardown_commit), + cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_json_list_operate, setup, teardown_commit), + cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_json_v1_operate, setup, teardown_commit), + cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_json_v1_list_operate, setup, teardown_commit), // Event method test cases cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_library_event, setup, teardown_commit), cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_json_event, setup, teardown_commit), + cmocka_unit_test_setup_teardown(test_api_bbfdm_valid_json_v1_event, setup, teardown_commit), }; return cmocka_run_group_tests(tests, group_setup, group_teardown); diff --git a/test/files/etc/bbfdm/json/X_IOPSYS_EU_JSON_TEST_V1.json b/test/files/etc/bbfdm/json/X_IOPSYS_EU_JSON_TEST_V1.json new file mode 100644 index 00000000..50580f63 --- /dev/null +++ b/test/files/etc/bbfdm/json/X_IOPSYS_EU_JSON_TEST_V1.json @@ -0,0 +1,401 @@ +{ + "json_plugin_version": 1, + "Device.UCI_TEST_V1.": { + "type": "object", + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "access": false, + "array": false, + "Password": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "rpc": "get" + }, + { + "rpc": "set", + "type": "uci", + "uci": { + "file": "users", + "section": { + "name": "user" + }, + "option": { + "name": "password_required" + } + } + } + ] + }, + "OWSDNumberOfEntries": { + "type": "unsignedInt", + "read": true, + "write": false, + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "owsd", + "section": { + "type": "owsd-listen" + }, + "option": { + "name": "@Count" + } + } + } + ] + }, + "Device.UCI_TEST_V1.OWSD.{i}.": { + "type": "object", + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "access": true, + "array": true, + "mapping": [ + { + "type": "uci", + "uci": { + "file": "owsd", + "section": { + "type": "owsd-listen" + }, + "dmmapfile": "dmmap_owsd" + } + } + ], + "IPv6": { + "type": "string", + "read": true, + "write": true, + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "data": "@Parent", + "type": "uci_sec", + "key": "ipv6" + } + ] + }, + "Port": { + "type": "unsignedInt", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "range": [ + { + "min": 0, + "max": 65535 + } + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "owsd", + "section": { + "type": "owsd-listen" + }, + "option": { + "name": "port" + } + } + } + ] + }, + "Password": { + "type": "string", + "read": true, + "write": true, + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "rpc": "get" + }, + { + "rpc": "set", + "type": "uci", + "uci": { + "file": "owsd", + "section": { + "type": "owsd-listen" + }, + "option": { + "name": "password" + } + } + } + ] + } + } + }, + "Device.UBUS_TEST_V1.": { + "type": "object", + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "access": false, + "array": false, + "Uptime": { + "type": "string", + "version": "2.14", + "read": true, + "write": true, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "rpc": "get", + "type": "ubus", + "ubus": { + "object": "network.interface", + "method": "status", + "args": { + "interface":"lan" + }, + "key": "uptime" + } + }, + { + "rpc": "set", + "type": "ubus", + "ubus": { + "object": "network.interface", + "method": "status", + "args": {"interface":"@Value"} + } + } + ] + }, + "InterfaceNumberOfEntries": { + "type": "unsignedInt", + "read": true, + "write": false, + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "ubus", + "ubus": { + "object": "ieee1905", + "method": "info", + "args": {}, + "key": "interface.@Count" + } + } + ] + }, + "Device.UBUS_TEST_V1.Interface.{i}.": { + "type": "object", + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "access": false, + "array": true, + "mapping": [ + { + "type": "ubus", + "ubus": { + "object": "ieee1905", + "method": "info", + "args": {}, + "key": "interface" + } + } + ], + "MacAddress": { + "type": "string", + "read": true, + "write": false, + "version": "2.14", + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "data": "@Parent", + "type": "json", + "key": "macaddress" + } + ] + }, + "Ifname": { + "type": "string", + "version": "2.14", + "read": true, + "write": false, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "type": "ubus", + "ubus": { + "object": "ieee1905", + "method": "info", + "args": {}, + "key": "interface[@index].ifname" + } + } + ] + }, + "Media": { + "type": "string", + "version": "2.14", + "read": true, + "write": false, + "protocols": [ + "cwmp", + "usp" + ], + "mapping": [ + { + "rpc": "get", + "type": "ubus", + "ubus": { + "object": "ieee1905", + "method": "info", + "args": {}, + "key": "interface[@index].media" + } + } + ] + }, + "Push!": { + "type": "event", + "version": "2.14", + "protocols": [ + "usp" + ], + "Data": { + "type": "string", + "read": true, + "write": true, + "version": "2.14", + "protocols": [ + "usp" + ] + }, + "Status": { + "type": "string", + "read": true, + "write": true, + "version": "2.14", + "protocols": [ + "usp" + ] + }, + "Value": { + "type": "string", + "read": true, + "write": true, + "version": "2.14", + "protocols": [ + "usp" + ] + } + }, + "Periodic!": { + "type": "event", + "version": "2.13", + "protocols": [ + "usp" + ] + }, + "Status()": { + "type": "command", + "async": true, + "version" : "2.12", + "protocols": [ + "usp" + ], + "input": { + "Option" : { + "type" : "string", + "read" : "true", + "write" : "true", + "protocol" : [ + "usp" + ] + }, + "Value" : { + "type" : "string", + "read" : "true", + "write" : "true", + "protocol" : [ + "usp" + ] + } + }, + "output": { + "Result" : { + "type" : "string", + "read" : "true", + "write" : "false", + "protocol" : [ + "usp" + ] + }, + "Value" : { + "type" : "string", + "read" : "true", + "write" : "false", + "protocol" : [ + "usp" + ] + } + }, + "mapping": [ + { + "type" : "ubus", + "ubus" : { + "object" : "test", + "method" : "status" + } + } + ] + } + } + } +} diff --git a/test/files/etc/config/owsd b/test/files/etc/config/owsd index 62d282ff..c70f554e 100644 --- a/test/files/etc/config/owsd +++ b/test/files/etc/config/owsd @@ -16,7 +16,7 @@ config owsd-listen 'loopback' config owsd-listen 'lan' option port '80' option interface 'lan' - option ipv6 'on' + option ipv6 'off' option ipv6only 'off' option whitelist_interface_as_origin '1' option whitelist_dhcp_domains '1' diff --git a/tools/validate_json_plugin.py b/tools/validate_json_plugin.py index 3781a053..66ca0f8a 100755 --- a/tools/validate_json_plugin.py +++ b/tools/validate_json_plugin.py @@ -7,6 +7,8 @@ import sys import json from jsonschema import validate +JSON_PLUGIN_VERSION = 0 + obj_schema = { "definitions": { "type_t": { @@ -68,6 +70,69 @@ obj_schema = { ] } +obj_schema_v1 = { + "definitions": { + "type_t": { + "type": "string", + "enum": [ + "object" + ] + }, + "map_type_t": { + "type": "string", + "enum": [ + "uci", + "ubus" + ] + }, + "protocols_t": { + "type": "string", + "enum": [ + "cwmp", + "usp" + ] + } + }, + "type" : "object", + "properties" : { + "type" : {"$ref": "#/definitions/type_t"}, + "version" : {"type": "string"}, + "protocols" : {"type" : "array", "items" : {"$ref": "#/definitions/protocols_t"}}, + "uniqueKeys" : {"type" : "array"}, + "access" : {"type" : "boolean"}, + "array" : {"type" : "boolean"}, + "mapping" : {"type" : "array", "items" : { + "type" : "object", "properties" : { + "type" : {"$ref": "#/definitions/map_type_t"}, + "uci" : {"type" : "object", "properties" : { + "file" : {"type": "string"}, + "section" : {"type": "object", "properties" : { + "type" : {"type": "string"} + } + }, + "dmmapfile" : {"type": "string"} + } + }, + "ubus" : {"type" : "object", "properties" : { + "object" : {"type": "string"}, + "method" : {"type": "string"}, + "args" : {"type": "object"}, + "key" : {"type": "string"} + } + } + } + } + } + }, + "required": [ + "type", + "protocols", + "array", + "access", + "version" + ] +} + param_schema = { "definitions": { "type_t": { @@ -91,7 +156,9 @@ param_schema = { "uci", "ubus", "procfs", - "sysfs" + "sysfs", + "json", + "uci_sec" ] }, "protocols_t": { @@ -222,8 +289,10 @@ def parse_value( key , value ): if key.endswith('.') and not key.startswith('Device.'): print(key + " is not a valid path") exit(1) - - if key.endswith('.'): + + if key.endswith('.') and JSON_PLUGIN_VERSION == 1: + __schema = obj_schema_v1 + elif key.endswith('.'): __schema = obj_schema elif key.endswith('!'): __schema = event_schema @@ -246,6 +315,11 @@ json_file = open(sys.argv[1], "r", encoding='utf-8') json_data = json.loads(json_file.read()) for __key, __value in json_data.items(): + + if __key == "json_plugin_version": + JSON_PLUGIN_VERSION = __value + continue + parse_value(__key , __value) print("JSON File is Valid")