diff --git a/plugins/restful/handle.c b/plugins/restful/handle.c index c552aeebc..21c27e62a 100644 --- a/plugins/restful/handle.c +++ b/plugins/restful/handle.c @@ -107,9 +107,6 @@ static struct neu_http_handler cors_handler[] = { { .url = "/api/v2/password", }, - { - .url = "/api/v2/logs", - }, { .url = "/api/v2/log/level", }, @@ -366,12 +363,6 @@ static struct neu_http_handler rest_handlers[] = { .url = "/api/v2/node/state", .value.handler = handle_get_node_state, }, - { - .method = NEU_HTTP_METHOD_GET, - .type = NEU_HTTP_HANDLER_FUNCTION, - .url = "/api/v2/logs", - .value.handler = handle_logs_files, - }, { .method = NEU_HTTP_METHOD_PUT, .type = NEU_HTTP_HANDLER_FUNCTION, diff --git a/plugins/restful/log_handle.c b/plugins/restful/log_handle.c index 6b7c674e8..81b3ca66f 100644 --- a/plugins/restful/log_handle.c +++ b/plugins/restful/log_handle.c @@ -42,70 +42,6 @@ #include "log_handle.h" #include "utils/utarray.h" -void handle_logs_files(nng_aio *aio) -{ - void * data = NULL; - size_t len = 0; - int rv = 0; - - NEU_VALIDATE_JWT(aio); - - /* check whether the neuron directory exists */ - rv = access("../neuron", F_OK); - if (0 != rv) { - nlog_error("The neuron directory does not exists"); - NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_NOT_EXIST, { - neu_http_response(aio, error_code.error, result_error); - }); - return; - } - - rv = system("rm -rf /tmp/neuron_debug.tar.gz"); - nlog_warn("remove old neuron_debug.tar.gz, rv: %d", rv); - /* tar the neuron directory */ - rv = system("tar -zcvf /tmp/neuron_debug.tar.gz " - "--exclude='persistence/neuron.lic' ../neuron"); - if (rv == -1) { - nlog_error("failed to create neuron_debug.tar.gz, rv: %d", rv); - NEU_JSON_RESPONSE_ERROR(NEU_ERR_COMMAND_EXECUTION_FAILED, { - neu_http_response(aio, error_code.error, result_error); - }); - return; - } else { - if (WIFEXITED(rv)) { - if (WEXITSTATUS(rv) < 0) { - nlog_error("failed to create neuron_debug.tar.gz, rv: %d", - WEXITSTATUS(rv)); - NEU_JSON_RESPONSE_ERROR(NEU_ERR_COMMAND_EXECUTION_FAILED, { - neu_http_response(aio, error_code.error, result_error); - }); - return; - } - } else { - nlog_error("failed to create neuron_debug.tar.gz, rv: %d", - WEXITSTATUS(rv)); - NEU_JSON_RESPONSE_ERROR(NEU_ERR_COMMAND_EXECUTION_FAILED, { - neu_http_response(aio, error_code.error, result_error); - }); - return; - } - } - - rv = read_file("/tmp/neuron_debug.tar.gz", &data, &len); - if (0 != rv) { - NEU_JSON_RESPONSE_ERROR( - rv, { neu_http_response(aio, error_code.error, result_error); }); - return; - } - - /* handle http response */ - rv = neu_http_response_file(aio, data, len, - "attachment; filename=neuron_debug.tar.gz"); - - free(data); - nlog_notice("download neuron_debug.tar.gz, ret: %d", rv); -} - void handle_log_level(nng_aio *aio) { neu_plugin_t *plugin = neu_rest_get_plugin(); @@ -156,44 +92,4 @@ void handle_log_level(nng_aio *aio) } } }) -} - -int read_file(const char *file_name, void **datap, size_t *lenp) -{ - int rv = 0; - FILE * f; - struct stat st; - size_t len; - void * data; - - if (stat(file_name, &st) != 0) { - return NEU_ERR_FILE_NOT_EXIST; - } - - if ((f = fopen(file_name, "rb")) == NULL) { - nlog_error("open fail: %s", file_name); - return NEU_ERR_FILE_OPEN_FAILURE; - } - - len = st.st_size; - if (len > 0) { - if ((data = malloc(len)) == NULL) { - rv = NEU_ERR_EINTERNAL; - goto done; - } - if (fread(data, 1, len, f) != len) { - nlog_error("file read failued, errno = %d", errno); - rv = NEU_ERR_FILE_READ_FAILURE; - free(data); - goto done; - } - } else { - data = NULL; - } - - *datap = data; - *lenp = len; -done: - fclose(f); - return (rv); } \ No newline at end of file diff --git a/plugins/restful/log_handle.h b/plugins/restful/log_handle.h index cff2b9137..dc991937e 100644 --- a/plugins/restful/log_handle.h +++ b/plugins/restful/log_handle.h @@ -23,9 +23,6 @@ #include // void handle_get_log(nng_aio *aio); -void handle_logs_files(nng_aio *aio); void handle_log_level(nng_aio *aio); -int read_file(const char *file_name, void **datap, size_t *lenp); - #endif diff --git a/tests/ft/driver/test_modbus.py b/tests/ft/driver/test_modbus.py index 3e2742eae..ad2195227 100644 --- a/tests/ft/driver/test_modbus.py +++ b/tests/ft/driver/test_modbus.py @@ -896,6 +896,20 @@ def test_read_tag_length_exceeds_250(self, param): node=param[0], group='group', tag=hold_string_l1[0]['name']) assert 'b' == api.read_tag( node=param[0], group='group', tag=hold_string_l2[0]['name']) + + @description(given="created modbus node ,groups and tags", when="write/read gtags", then="write/read success") + def test_write_read_gtags(self, param): + modbus_write_gtags = {"node": param[0], "groups": [{"group": "group", "tags" : [{"tag": "hold_uint16", "value": 1}, {"tag": "hold_string", "value": 'hello'}, + {"tag": "coil_bit_1", "value": 1}, {"tag": "hold_double_decimal", "value": 513.11}, {"tag": "hold_bytes", "value": [0x1, 0x2, 0x3, 0x4]}]}, + {"group": "group1", "tags" : [{"tag": "hold_int16", "value": 1}]}]} + response = api.write_gtags(json=modbus_write_gtags) + assert 200 == response.status_code + assert error.NEU_ERR_SUCCESS == response.json()['error'] + time.sleep(1.0) + assert 1 == api.read_tag( + node=param[0], group='group', tag=hold_uint16[0]['name']) + assert 1 == api.read_tag( + node=param[0], group='group1', tag=hold_int16[0]['name']) @description(given="created modbus device_error_test node/tag", when="read tag", then="read failed") def test_read_modbus_device_err(self, param): diff --git a/tests/ft/http_api/__init__.py b/tests/ft/http_api/__init__.py new file mode 100644 index 000000000..6da127712 --- /dev/null +++ b/tests/ft/http_api/__init__.py @@ -0,0 +1,3 @@ +import sys + +sys.path.append("tests/ft") diff --git a/tests/ft/http_api/test_http_api.py b/tests/ft/http_api/test_http_api.py new file mode 100644 index 000000000..f7533045d --- /dev/null +++ b/tests/ft/http_api/test_http_api.py @@ -0,0 +1,199 @@ +import neuron.api as api +import neuron.error as error +import neuron.config as config +from neuron.common import * + +hold_int16 = [{"name": "hold_int16", "address": "1!400001", + "attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16}] + +global_config = { + "nodes": [ + { + "plugin": "MQTT", + "name": "mqtt" + }, + { + "plugin": "Modbus TCP", + "name": "modbus" + } + ], + "groups": [ + { + "driver": "modbus", + "group": "group", + "tag_count": 1, + "interval": 100 + } + ], + "tags": [ + { + "tags": [ + { + "type": 3, + "name": "hold_int16", + "attribute": 3, + "precision": 0, + "decimal": 0.0, + "address": "1!400001", + "description": "" + } + ], + "driver": "modbus", + "group": "group" + } + ], + "subscriptions": [ + { + "groups": [ + { + "driver": "modbus", + "group": "group" + } + ], + "app": "mqtt" + } + ], + "settings": [ + { + "node": "mqtt", + "params": { + "client-id": "neuron_aBcDeF", + "qos": 0, + "format": 0, + "write-req-topic": "/neuron/mqtt/write/req", + "write-resp-topic": "/neuron/mqtt/write/resp", + "offline-cache": False, + "cache-sync-interval": 100, + "host": "broker.emqx.io", + "port": 1883, + "username": "", + "password": "", + "ssl": False + } + }, + { + "node": "modbus", + "params": { + "connection_mode": 0, + "transport_mode": 0, + "interval": 0, + "host": "127.0.0.1", + "port": 502, + "timeout": 3000, + "max_retries": 2 + } + } + ] +} + +class TestHttp: + + @description(given="running neuron", when="add driver/app node/group/tag, app subscribes driver group, and get global config", then="success") + def test_get_global_config(self): + response = api.put_global_config(json=global_config) + assert 200 == response.status_code + assert error.NEU_ERR_SUCCESS == response.json()['error'] + + response = api.get_global_config() + assert 200 == response.status_code + + config_data = response.json() + + assert 'nodes' in config_data + assert len(config_data['nodes']) == 2 + assert config_data['nodes'][0]['plugin'] == 'MQTT' + assert config_data['nodes'][1]['plugin'] == 'Modbus TCP' + + assert 'groups' in config_data + assert len(config_data['groups']) == 1 + assert config_data['groups'][0]['driver'] == 'modbus' + + assert 'tags' in config_data + assert len(config_data['tags']) == 1 + assert config_data['tags'][0]['driver'] == 'modbus' + assert len(config_data['tags'][0]['tags']) == 1 + + assert 'subscriptions' in config_data + assert len(config_data['subscriptions']) == 1 + assert config_data['subscriptions'][0]['app'] == 'mqtt' + + assert 'settings' in config_data + assert len(config_data['settings']) == 2 + assert config_data['settings'][0]['node'] == 'mqtt' + + response = api.del_node_check(node='modbus') + + response = api.get_global_config() + assert 200 == response.status_code + + config_data = response.json() + + assert 'nodes' in config_data + assert len(config_data['nodes']) == 1 + assert config_data['nodes'][0]['plugin'] == 'MQTT' + + assert 'groups' in config_data + assert len(config_data['groups']) == 0 + + assert 'tags' in config_data + assert len(config_data['tags']) == 0 + + assert 'subscriptions' in config_data + assert len(config_data['subscriptions']) == 0 + + assert 'settings' in config_data + assert len(config_data['settings']) == 1 + assert config_data['settings'][0]['node'] == 'mqtt' + + @description(given="running neuron", when="get mqtt shcema", then="success") + def test_get_plugin_schema(self): + response = api.get_plugin_schema(plugin='mqtt') + assert 200 == response.status_code + + response = api.get_plugin_schema(plugin='modbus-tcp') + assert 200 == response.status_code + + response = api.get_plugin_schema(plugin='invalid') + assert 404 == response.status_code + assert response.json()['status'] == 'error' + + @description(given="running neuron", when="get plugin", then="success") + def test_get_plugin(self): + response = api.get_plugin() + assert 200 == response.status_code + + @description(given="running neuron", when="get version", then="success") + def test_get_version(self): + response = api.get_version() + assert 200 == response.status_code + + @description(given="running neuron", when="test ndriver", then="failed because it is not supported yet") + def test_ndriver(self): + api.add_node_check(node='modbus', plugin=config.PLUGIN_MODBUS_TCP) + api.add_group_check(node='modbus', group='group') + api.add_tags_check(node='modbus', group='group', tags=hold_int16) + response = api.subscribe_group(app='mqtt', driver='modbus', group='group') + assert 200 == response.status_code + assert error.NEU_ERR_SUCCESS == response.json()['error'] + + response = api.post_ndriver_map(ndriver='mqtt', driver='modbus', group='group') + assert 400 == response.status_code + + response = api.get_ndriver_map(ndriver='mqtt') + assert 400 == response.status_code + + ndriver_tag_param = {"ndriver": "mqtt", "driver": "modbus", "group": "group", "tags": [ + {"name": "hold_int16", "params": {"address": "1!400002"}}]} + response = api.put_ndriver_tag_param(json=ndriver_tag_param) + assert 200 == response.status_code + + ndriver_tag_info = {"ndriver": "mqtt", "driver": "modbus", "group": "group", "tags": [ + {"name": "hold_int16", "address": "1!400002"}]} + response = api.put_ndriver_tag_info(json=ndriver_tag_info) + assert 200 == response.status_code + + response = api.get_ndriver_tag(ndriver='mqtt', driver='modbus', group='group') + assert 200 == response.status_code + + response = api.delete_ndriver_map(ndriver='mqtt', driver='modbus', group='group') + assert 200 == response.status_code \ No newline at end of file diff --git a/tests/ft/log/test_log.py b/tests/ft/log/test_log.py index 81b7de066..67a38ce4b 100644 --- a/tests/ft/log/test_log.py +++ b/tests/ft/log/test_log.py @@ -121,4 +121,8 @@ def test_change_node_log_level_only(self): response = api.get_nodes_state('modbus-tcp-1') assert 200 == response.status_code assert "notice" == response.json()['neuron_core'] - assert "info" == response.json()['log_level'] \ No newline at end of file + assert "info" == response.json()['log_level'] + + response = api.get_nodes_state(node='') + assert 200 == response.status_code + assert "notice" == response.json()['neuron_core'] \ No newline at end of file diff --git a/tests/ft/neuron/api.py b/tests/ft/neuron/api.py index 68ff10fcf..174d20f00 100644 --- a/tests/ft/neuron/api.py +++ b/tests/ft/neuron/api.py @@ -194,6 +194,9 @@ def write_tag(node, group, tag, value): def write_tags(node, group, tag_values): return requests.post(url=config.BASE_URL + "/api/v2/write/tags", headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "tags": tag_values}) +def write_gtags(json): + return requests.post(url=config.BASE_URL + "/api/v2/write/gtags", headers={"Authorization": config.default_jwt}, json=json) + def add_plugin(library_name, so_file, schema_file): return requests.post(url=config.BASE_URL + "/api/v2/plugin", json={"library": library_name, "so_file": so_file, "schema_file": schema_file}, headers={"Authorization": config.default_jwt}) @@ -293,6 +296,39 @@ def unsubscribe_group(app, driver, group): def get_metrics(category="global", node=""): return requests.get(url=config.BASE_URL + "/api/v2/metrics?category=" + category + "&node=" + node, headers={"Authorization": config.default_jwt}) +def get_global_config(): + return requests.get(url=config.BASE_URL + "/api/v2/global/config", headers={"Authorization": config.default_jwt}) + +def put_global_config(json): + return requests.put(url=config.BASE_URL + "/api/v2/global/config", headers={"Authorization": config.default_jwt}, json=json) + +def get_plugin_schema(plugin): + return requests.get(url=config.BASE_URL + "/api/v2/schema?schema_name=" + plugin, headers={"Authorization": config.default_jwt}) + +def get_plugin(): + return requests.get(url=config.BASE_URL + "/api/v2/plugin", headers={"Authorization": config.default_jwt}) + +def get_version(): + return requests.get(url=config.BASE_URL + "/api/v2/version", headers={"Authorization": config.default_jwt}) + +def post_ndriver_map(ndriver, driver, group): + return requests.post(url=config.BASE_URL + "/api/v2/ndriver/map", headers={"Authorization": config.default_jwt}, json={"ndriver": ndriver, "driver": driver, "group":group}) + +def delete_ndriver_map(ndriver, driver, group): + return requests.delete(url=config.BASE_URL + "/api/v2/ndriver/map", headers={"Authorization": config.default_jwt}, json={"ndriver": ndriver, "driver": driver, "group":group}) + +def get_ndriver_map(ndriver): + return requests.delete(url=config.BASE_URL + "/api/v2/ndriver/map?ndriver=" + ndriver, headers={"Authorization": config.default_jwt}) + +def put_ndriver_tag_param(json): + return requests.put(url=config.BASE_URL + "/api/v2/ndriver/tag/param", headers={"Authorization": config.default_jwt}, json=json) + +def put_ndriver_tag_info(json): + return requests.put(url=config.BASE_URL + "/api/v2/ndriver/tag/info", headers={"Authorization": config.default_jwt}, json=json) + +def get_ndriver_tag(ndriver, driver, group): + return requests.get(url=config.BASE_URL + "/api/v2/ndriver/tag?ndriver=" + ndriver + "&driver=" + driver + "&group=" + group, headers={"Authorization": config.default_jwt}) + # plugin setting