diff --git a/plugins/restful/adapter_handle.c b/plugins/restful/adapter_handle.c index 465d2bcbb..0a7bc9683 100644 --- a/plugins/restful/adapter_handle.c +++ b/plugins/restful/adapter_handle.c @@ -550,6 +550,7 @@ static int json_to_gdatatags(neu_json_gtag_array_t *gtag_array, gdatatags[i].tags[j].bias = gtag_array->gtags[i].tags[j].bias; gdatatags[i].tags[j].address = gtag_array->gtags[i].tags[j].address; gdatatags[i].tags[j].name = gtag_array->gtags[i].tags[j].name; + gdatatags[i].tags[j].unit = gtag_array->gtags[i].tags[j].unit; if (gtag_array->gtags[i].tags[j].description != NULL) { gdatatags[i].tags[j].description = gtag_array->gtags[i].tags[j].description; @@ -560,6 +561,7 @@ static int json_to_gdatatags(neu_json_gtag_array_t *gtag_array, gtag_array->gtags[i].tags[j].address = NULL; // moved gtag_array->gtags[i].tags[j].name = NULL; // moved gtag_array->gtags[i].tags[j].description = NULL; // moved + gtag_array->gtags[i].tags[j].unit = NULL; // moved } } diff --git a/plugins/restful/global_config_handle.c b/plugins/restful/global_config_handle.c index 4ff798b58..7467fcd53 100644 --- a/plugins/restful/global_config_handle.c +++ b/plugins/restful/global_config_handle.c @@ -1229,10 +1229,12 @@ static int get_driver_tags_resp(context_t *ctx, neu_resp_get_tag_t *tags) gtag->tags[index].precision = tag->precision; gtag->tags[index].decimal = tag->decimal; gtag->tags[index].bias = tag->bias; + gtag->tags[index].unit = tag->unit; gtag->tags[index].t = NEU_JSON_UNDEFINE; tag->name = NULL; // moved tag->address = NULL; // moved tag->description = NULL; // moved + tag->unit = NULL; // moved } end: @@ -1501,9 +1503,10 @@ static int add_tag(context_t *ctx, neu_json_add_tags_req_t *data) cmd.tags[i].name = strdup(data->tags[i].name); cmd.tags[i].description = strdup(data->tags[i].description ? data->tags[i].description : ""); + cmd.tags[i].unit = strdup(data->tags[i].unit ? data->tags[i].unit : ""); if (NULL == cmd.tags[i].address || NULL == cmd.tags[i].name || - NULL == cmd.tags[i].description) { + NULL == cmd.tags[i].description || NULL == cmd.tags[i].unit) { ret = NEU_ERR_EINTERNAL; goto error; } @@ -1517,7 +1520,7 @@ static int add_tag(context_t *ctx, neu_json_add_tags_req_t *data) return ret; error: - for (int j = 0; j < i && j < cmd.n_tag; ++j) { + for (int j = 0; j < cmd.n_tag; ++j) { neu_tag_fini(&cmd.tags[j]); } free(cmd.tags); diff --git a/tests/ft/http_api/test_http_api.py b/tests/ft/http_api/test_http_api.py index db1cce083..91af4f6b8 100644 --- a/tests/ft/http_api/test_http_api.py +++ b/tests/ft/http_api/test_http_api.py @@ -292,6 +292,77 @@ def test_get_global_config(self): for node in global_config['nodes']: api.del_node(node['name']) + @pytest.mark.parametrize("unit", ["°C", "", None], ids=["nonempty", "empty", "missing"]) + def test_global_config_tag_unit_roundtrip(self, unit): + driver = copy.deepcopy(driver_1) + group = driver["groups"][0] + tags = group["tags"] + if unit is None: + tags[0].pop("unit") + else: + tags[0]["unit"] = unit + tags[1].pop("unit") + expected_tags = copy.deepcopy(tags) + for tag in expected_tags: + tag.setdefault("unit", "") + + data = { + "nodes": [{"name": driver["name"], "plugin": driver["plugin"]}], + "groups": [{"driver": driver["name"], "group": group["group"], + "interval": group["interval"], "tag_count": len(tags)}], + "tags": [{"driver": driver["name"], "group": group["group"], "tags": tags}], + "subscriptions": [], + "settings": [] + } + try: + for _ in range(2): + response = api.put_global_config(json=data) + assert 200 == response.status_code + assert error.NEU_ERR_SUCCESS == response.json()["error"] + + response = api.get_tags(driver["name"], group["group"]) + assert 200 == response.status_code + assert expected_tags == response.json()["tags"] + + response = api.get_global_config() + assert 200 == response.status_code + data = response.json() + exported = next(g for g in data["tags"] + if g["driver"] == driver["name"] and g["group"] == group["group"]) + assert expected_tags == exported["tags"] + finally: + api.del_node(driver["name"]) + + @pytest.mark.parametrize("unit", ["°C", "", None], ids=["nonempty", "empty", "missing"]) + def test_driver_tag_unit_roundtrip(self, unit): + driver = copy.deepcopy(driver_1) + tags = driver["groups"][0]["tags"] + if unit is None: + tags[0].pop("unit") + else: + tags[0]["unit"] = unit + tags[1].pop("unit") + expected = copy.deepcopy(driver) + for tag in expected["groups"][0]["tags"]: + tag.setdefault("unit", "") + + try: + for _ in range(2): + response = api.put_drivers([driver]) + assert 200 == response.status_code + assert error.NEU_ERR_SUCCESS == response.json()["error"] + + response = api.get_tags(driver["name"], driver["groups"][0]["group"]) + assert 200 == response.status_code + assert expected["groups"][0]["tags"] == response.json()["tags"] + + response = api.get_driver(driver["name"]) + assert 200 == response.status_code + assert [expected] == response.json()["nodes"] + driver = response.json()["nodes"][0] + finally: + api.del_node(driver["name"]) + @description(given="running neuron", when="put drivers with too long node name", then="should fail") def test_put_drivers_with_long_node_name(self): response = api.put_driver(