From 91f319ab9fcb5dfef087a23ebf89a235881cff0c Mon Sep 17 00:00:00 2001 From: Kapil Bansal Date: Tue, 20 Jul 2021 23:45:04 +0530 Subject: [PATCH] [test] Added automated tests for lua code using mocks + test coverage Closes #27 --- .github/workflows/ci.yml | 12 +- .luacheckrc | 3 + README.rst | 24 +- install-dev.sh | 22 +- .../files/lib/openwisp/dhcp.lua | 63 +- .../files/lib/openwisp/interfaces.lua | 320 ++++----- .../files/lib/openwisp/monitoring.lua | 16 +- .../files/lib/openwisp/monitoring_utils.lua | 64 +- .../files/lib/openwisp/neighbors.lua | 98 +-- .../files/lib/openwisp/resources.lua | 54 +- .../files/lib/openwisp/wifi.lua | 62 +- .../files/monitoring.agent | 104 +-- .../files/monitoring.init | 92 +-- .../files/sbin/netjson-monitoring.lua | 295 ++++----- openwrt-openwisp-monitoring/tests/.luacov | 5 + .../tests/basic_env.lua | 58 ++ .../tests/main_env.lua | 79 +++ .../tests/test_dhcp.lua | 82 +++ .../tests/test_files/address_data.lua | 61 ++ .../tests/test_files/dhcp_data.lua | 65 ++ .../tests/test_files/dhcp_leases.txt | 1 + .../tests/test_files/disk_usage.txt | 6 + .../tests/test_files/interface_data.lua | 298 +++++++++ .../tests/test_files/ip_json_neigh.txt | 1 + .../tests/test_files/ip_neigh.txt | 6 + .../tests/test_files/lte_sample.txt | 33 + .../tests/test_files/modem_data.txt | 99 +++ .../tests/test_files/neighbors_data.lua | 18 + .../tests/test_files/network_data.lua | 608 ++++++++++++++++++ .../tests/test_files/nixio_data.lua | 284 ++++++++ .../tests/test_files/openvpn_data.lua | 56 ++ .../tests/test_files/parse_app.txt | 4 + .../tests/test_files/resources_data.lua | 30 + .../tests/test_files/umts_sample.txt | 38 ++ .../tests/test_files/wireless_data.lua | 456 +++++++++++++ .../tests/test_interfaces.lua | 173 +++++ .../tests/test_neighbors.lua | 70 ++ .../tests/test_resources.lua | 73 +++ .../tests/test_utils.lua | 64 ++ .../tests/test_wifi.lua | 142 ++++ runtests | 11 + 41 files changed, 3467 insertions(+), 583 deletions(-) create mode 100644 .luacheckrc create mode 100644 openwrt-openwisp-monitoring/tests/.luacov create mode 100644 openwrt-openwisp-monitoring/tests/basic_env.lua create mode 100644 openwrt-openwisp-monitoring/tests/main_env.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_dhcp.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/address_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/dhcp_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/dhcp_leases.txt create mode 100644 openwrt-openwisp-monitoring/tests/test_files/disk_usage.txt create mode 100644 openwrt-openwisp-monitoring/tests/test_files/interface_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/ip_json_neigh.txt create mode 100644 openwrt-openwisp-monitoring/tests/test_files/ip_neigh.txt create mode 100644 openwrt-openwisp-monitoring/tests/test_files/lte_sample.txt create mode 100644 openwrt-openwisp-monitoring/tests/test_files/modem_data.txt create mode 100644 openwrt-openwisp-monitoring/tests/test_files/neighbors_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/network_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/nixio_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/openvpn_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/parse_app.txt create mode 100644 openwrt-openwisp-monitoring/tests/test_files/resources_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_files/umts_sample.txt create mode 100644 openwrt-openwisp-monitoring/tests/test_files/wireless_data.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_interfaces.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_neighbors.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_resources.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_utils.lua create mode 100644 openwrt-openwisp-monitoring/tests/test_wifi.lua create mode 100755 runtests diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9fce632..1517783 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,16 @@ jobs: - name: QA-Checks run: ./run-qa-checks + - name: Tests + run: ./runtests + + - name: Upload Coverage + run: | + cd openwrt-openwisp-monitoring/tests + luacov-coveralls -v + env: + COVERALLS_REPO_TOKEN: ${{ github.token }} + build: name: Build and upload package as artifacts needs: tests @@ -85,7 +95,7 @@ jobs: export_default_credentials: true - name: Upload compiled packages to downloads.openwisp.io - if: ${{ github.event_name == 'push' }} + if: ${{ github.event_name=='push' }} run: gsutil -m rsync -r ${{ env.SRC_URL }} ${{ env.DST_URL }} env: SRC_URL: ${{ env.DOWNLOADS_DIR }}/${{ env.START_TIME }}/openwisp diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..da42b76 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,3 @@ +files["openwrt-openwisp-monitoring/tests"]={ + ignore={"Test.*"} +} diff --git a/README.rst b/README.rst index cb6ca36..055e9ad 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,14 @@ openwrt-openwisp-monitoring =========================== +.. image:: https://github.com/openwisp/openwrt-openwisp-monitoring/workflows/OpenWRT%20OPENWISP%20MONITORING%20CI%20Build/badge.svg?branch=master + :target: https://github.com/openwisp/openwrt-openwisp-monitoring/actions?query=OpenWRT+OPENWISP+MONITORING+CI+Build%22 + :alt: CI build status + +.. image:: https://coveralls.io/repos/github/openwisp/openwrt-openwisp-monitoring/badge.svg + :target: https://coveralls.io/github/openwisp/openwrt-openwisp-monitoring + :alt: Test Coverage + .. image:: http://img.shields.io/github/release/openwisp/openwrt-openwisp-monitoring.svg :target: https://github.com/openwisp/openwrt-openwisp-monitoring/releases @@ -53,7 +61,7 @@ The following procedure illustrates how to compile all variants of *openwisp-mon git clone https://git.openwrt.org/openwrt/openwrt.git cd openwrt - git checkout openwrt-19.07 + git checkout openwrt-21.02 # configure feeds echo "src-git monitoring https://github.com/openwisp/openwrt-openwisp-monitoring.git" > feeds.conf @@ -130,12 +138,24 @@ a look at the `install-dev.sh /dev/null'):lines() do - if line:sub(1, 10) ~= 'IP address' then - local ip, _, _, mac, _, dev = line:match("(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)") - table.insert(arp_info, { - ip = ip, - mac = mac, - interface = dev, - state = '' - }) - end + local arp_info={} + for line in io.popen('cat /proc/net/arp 2> /dev/null'):lines() do + if line:sub(1, 10) ~='IP address' then + local ip, _, _, mac, _, dev=line:match("(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)") + table.insert(arp_info, { + ip=ip, + mac=mac, + interface=dev, + state='' + }) end - return arp_info + end + return arp_info end function neighbors.get_ip_neigh_json() - local arp_info = {} - local output = io.popen('ip -json neigh 2> /dev/null'):read() - if output ~= nil and pcall(cjson.decode, output) then - local json_output = cjson.decode(output) - for _, arp_entry in pairs(json_output) do - table.insert(arp_info, { - ip = arp_entry["dst"], - mac = arp_entry["lladdr"], - interface = arp_entry["dev"], - state = arp_entry["state"][1] - }) - end + local arp_info={} + local output=io.popen('ip -json neigh 2> /dev/null'):read() + if output ~=nil and pcall(cjson.decode, output) then + local json_output=cjson.decode(output) + for _, arp_entry in pairs(json_output) do + table.insert(arp_info, { + ip=arp_entry["dst"], + mac=arp_entry["lladdr"], + interface=arp_entry["dev"], + state=arp_entry["state"][1] + }) end - return arp_info + end + return arp_info end function neighbors.get_ip_neigh() - local arp_info = {} - local output = io.popen('ip neigh 2> /dev/null') - for line in output:lines() do - local ip, dev, mac, state = line:match("(%S+)%s+dev%s+(%S+)%s+lladdr%s+(%S+).*%s(%S+)") - if mac ~= nil then - table.insert(arp_info, { - ip = ip, - mac = mac, - interface = dev, - state = state - }) - end + local arp_info={} + local output=io.popen('ip neigh 2> /dev/null') + for line in output:lines() do + local ip, dev, mac, state=line:match("(%S+)%s+dev%s+(%S+)%s+lladdr%s+(%S+).*%s(%S+)") + if mac ~=nil then + table.insert(arp_info, { + ip=ip, + mac=mac, + interface=dev, + state=state + }) end - return arp_info + end + return arp_info end function neighbors.get_neighbors() - local arp_table = neighbors.get_ip_neigh_json() - if next(arp_table) == nil then - arp_table = neighbors.get_ip_neigh() - end - if next(arp_table) == nil then - arp_table = neighbors.parse_arp() - end - return arp_table + local arp_table=neighbors.get_ip_neigh_json() + if next(arp_table)==nil then + arp_table=neighbors.get_ip_neigh() + end + if next(arp_table)==nil then + arp_table=neighbors.parse_arp() + end + return arp_table end return neighbors diff --git a/openwrt-openwisp-monitoring/files/lib/openwisp/resources.lua b/openwrt-openwisp-monitoring/files/lib/openwisp/resources.lua index 33b906c..dea1205 100644 --- a/openwrt-openwisp-monitoring/files/lib/openwisp/resources.lua +++ b/openwrt-openwisp-monitoring/files/lib/openwisp/resources.lua @@ -1,36 +1,38 @@ -- retrieve resources usage -local resources = {} +local io=require('io') + +local resources={} function resources.parse_disk_usage() - local file = io.popen('df') - local disk_usage_info = {} - for line in file:lines() do - if line:sub(1, 10) ~= 'Filesystem' then - local filesystem, size, used, available, percent, location = - line:match('(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)') - if filesystem ~= 'tmpfs' and not string.match(filesystem, 'overlayfs') then - percent = percent:gsub('%W', '') - -- available, size and used are in KiB - table.insert(disk_usage_info, { - filesystem = filesystem, - available_bytes = tonumber(available) * 1024, - size_bytes = tonumber(size) * 1024, - used_bytes = tonumber(used) * 1024, - used_percent = tonumber(percent), - mount_point = location - }) - end - end + local file=io.popen('df') + local disk_usage_info={} + for line in file:lines() do + if line:sub(1, 10) ~='Filesystem' then + local filesystem, size, used, available, percent, location= + line:match('(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)') + if filesystem ~='tmpfs' and not string.match(filesystem, 'overlayfs') then + percent=percent:gsub('%W', '') + -- available, size and used are in KiB + table.insert(disk_usage_info, { + filesystem=filesystem, + available_bytes=tonumber(available) * 1024, + size_bytes=tonumber(size) * 1024, + used_bytes=tonumber(used) * 1024, + used_percent=tonumber(percent), + mount_point=location + }) + end end - file:close() - return disk_usage_info + end + file:close() + return disk_usage_info end function resources.get_cpus() - local processors = io.popen('cat /proc/cpuinfo | grep -c processor') - local cpus = tonumber(processors:read('*a')) - processors:close() - return cpus + local processors=io.popen('cat /proc/cpuinfo | grep -c processor') + local cpus=tonumber(processors:read('*a')) + processors:close() + return cpus end return resources diff --git a/openwrt-openwisp-monitoring/files/lib/openwisp/wifi.lua b/openwrt-openwisp-monitoring/files/lib/openwisp/wifi.lua index cd1e32c..9c2aabe 100644 --- a/openwrt-openwisp-monitoring/files/lib/openwisp/wifi.lua +++ b/openwrt-openwisp-monitoring/files/lib/openwisp/wifi.lua @@ -1,59 +1,59 @@ -local wifi = {} +local wifi={} -- helpers -wifi.iwinfo_modes = { - ['Master'] = 'access_point', - ['Client'] = 'station', - ['Mesh Point'] = '802.11s', - ['Ad-Hoc'] = 'adhoc' +wifi.iwinfo_modes={ + ['Master']='access_point', + ['Client']='station', + ['Mesh Point']='802.11s', + ['Ad-Hoc']='adhoc' } function wifi.needs_inversion(interface) - return interface.type == 'wireless' and interface.wireless.mode == 'access_point' + return interface.type=='wireless' and interface.wireless.mode=='access_point' end function wifi.invert_rx_tx(interface) - for k, v in pairs(interface) do - if string.sub(k, 0, 3) == "rx_" then - local tx_key = "tx_" .. string.sub(k, 4) - local tx_val = interface[tx_key] - interface[tx_key] = v - interface[k] = tx_val - end + for k, v in pairs(interface) do + if string.sub(k, 0, 3)=="rx_" then + local tx_key="tx_" .. string.sub(k, 4) + local tx_val=interface[tx_key] + interface[tx_key]=v + interface[k]=tx_val end - return interface + end + return interface end function wifi.parse_hostapd_clients(clients) - local data = {} + local data={} for mac, properties in pairs(clients) do - properties.mac = mac - table.insert(data, properties) + properties.mac=mac + table.insert(data, properties) end return data end function wifi.parse_iwinfo_clients(clients) - local data = {} + local data={} for _, p in pairs(clients) do - local client = {} - client.ht = p.rx.ht - client.mac = p.mac - client.authorized = p.authorized - client.vht = p.rx.vht - client.wmm = p.wme - client.mfp = p.mfp - client.auth = p.authenticated - client.signal = p.signal - client.noise = p.noise - table.insert(data, client) + local client={} + client.ht=p.rx.ht + client.mac=p.mac + client.authorized=p.authorized + client.vht=p.rx.vht + client.wmm=p.wme + client.mfp=p.mfp + client.auth=p.authenticated + client.signal=p.signal + client.noise=p.noise + table.insert(data, client) end return data end -- takes ubus wireless.status clients output and converts it to NetJSON function wifi.netjson_clients(clients, is_mesh) - return (is_mesh and wifi.parse_iwinfo_clients(clients) or wifi.parse_hostapd_clients(clients)) + return (is_mesh and wifi.parse_iwinfo_clients(clients) or wifi.parse_hostapd_clients(clients)) end return wifi diff --git a/openwrt-openwisp-monitoring/files/monitoring.agent b/openwrt-openwisp-monitoring/files/monitoring.agent index fed5138..1c5866c 100755 --- a/openwrt-openwisp-monitoring/files/monitoring.agent +++ b/openwrt-openwisp-monitoring/files/monitoring.agent @@ -1,74 +1,74 @@ #!/bin/sh while [ -n "$1" ]; do - case "$1" in - --version|-v) export VERSION=1; break;; - --url) export BASE_URL="$2"; shift;; - --uuid) export UUID="$2"; shift;; - --key) export KEY="$2"; shift;; - --verify_ssl) export verify_ssl="$2"; shift;; - --interval) export INTERVAL="$2"; shift;; - --monitored_interfaces) export MONITORED_INTERFACES=$2; shift;; - -*) - echo "Invalid option: $1" - exit 1 - ;; - *) break; - esac - shift; + case "$1" in + --version|-v) export VERSION=1; break;; + --url) export BASE_URL="$2"; shift;; + --uuid) export UUID="$2"; shift;; + --key) export KEY="$2"; shift;; + --verify_ssl) export verify_ssl="$2"; shift;; + --interval) export INTERVAL="$2"; shift;; + --monitored_interfaces) export MONITORED_INTERFACES=$2; shift;; + -*) + echo "Invalid option: $1" + exit 1 + ;; + *) break; + esac + shift; done if [ "$VERSION" -eq "1" ]; then - VERSION=$(cat /etc/openwisp/monitoring/VERSION) - echo "openwisp-monitoring $VERSION" - exit 0 + VERSION=$(cat /etc/openwisp/monitoring/VERSION) + echo "openwisp-monitoring $VERSION" + exit 0 fi CURL_COMMAND='curl' if [ "$verify_ssl" == 0 ]; then - CURL_COMMAND="$CURL_COMMAND -k" + CURL_COMMAND="$CURL_COMMAND -k" fi URL="$BASE_URL/api/v1/monitoring/device/$UUID/?key=$KEY" collect_data(){ - n=0 - logger -s "Collecting NetJSoN Monitoring data" \ - -t monitoring \ - -p daemon.info + n=0 + logger -s "Collecting NetJSoN Monitoring data" \ + -t monitoring \ + -p daemon.info - until [ "$n" -ge 5 ] - do - echo "$(/usr/sbin/netjson_monitoring "$MONITORED_INTERFACES")" && break - - if [ "$n" -eq 5 ]; then - logger -s "Collecting data failed! Retrying" \ - -t monitoring \ - -p daemon.err - fi - n=$((n+1)) - sleep 5 - done + until [ "$n" -ge 5 ] + do + echo "$(/usr/sbin/netjson_monitoring "$MONITORED_INTERFACES")" && break + + if [ "$n" -eq 5 ]; then + logger -s "Collecting data failed! Retrying" \ + -t monitoring \ + -p daemon.err + fi + n=$((n+1)) + sleep 5 + done } while true do - data="$(collect_data)" - #send data - $($CURL_COMMAND -H "Content-Type: application/json" \ - -X POST \ - -d "$data" \ - -v "$URL") - exit_code=$? - if [ "$exit_code" == "0" ]; then - logger -s "Data sent successfully." \ - -t monitoring \ - -p daemon.info - else - logger -s "Data not sent successfully. Exit code is $exit_code" \ - -t monitoring \ - -p daemon.err - fi + data="$(collect_data)" + #send data + $($CURL_COMMAND -H "Content-Type: application/json" \ + -X POST \ + -d "$data" \ + -v "$URL") + exit_code=$? + if [ "$exit_code" == "0" ]; then + logger -s "Data sent successfully." \ + -t monitoring \ + -p daemon.info + else + logger -s "Data not sent successfully. Exit code is $exit_code" \ + -t monitoring \ + -p daemon.err + fi - sleep "$INTERVAL" & wait $! + sleep "$INTERVAL" & wait $! done diff --git a/openwrt-openwisp-monitoring/files/monitoring.init b/openwrt-openwisp-monitoring/files/monitoring.init index b877e62..e9a8c5f 100755 --- a/openwrt-openwisp-monitoring/files/monitoring.init +++ b/openwrt-openwisp-monitoring/files/monitoring.init @@ -7,65 +7,65 @@ PROG="/usr/sbin/openwisp_monitoring" PROG_NAME="OpenWISP monitoring daemon" time_to_seconds() { - time=$1 + time=$1 - { [ "$time" -ge 1 ] 2>/dev/null && seconds="$time"; } || - { [ "${time%s}" -ge 1 ] 2>/dev/null && seconds="${time%s}"; } || - { [ "${time%m}" -ge 1 ] 2>/dev/null && seconds=$((${time%m} * 60)); } || - { [ "${time%h}" -ge 1 ] 2>/dev/null && seconds=$((${time%h} * 3600)); } || - { [ "${time%d}" -ge 1 ] 2>/dev/null && seconds=$((${time%d} * 86400)); } + { [ "$time" -ge 1 ] 2>/dev/null && seconds="$time"; } || + { [ "${time%s}" -ge 1 ] 2>/dev/null && seconds="${time%s}"; } || + { [ "${time%m}" -ge 1 ] 2>/dev/null && seconds=$((${time%m} * 60)); } || + { [ "${time%h}" -ge 1 ] 2>/dev/null && seconds=$((${time%h} * 3600)); } || + { [ "${time%d}" -ge 1 ] 2>/dev/null && seconds=$((${time%d} * 86400)); } - echo $seconds - unset seconds - unset time + echo $seconds + unset seconds + unset time } start_service() { - # for openwisp_config - config_load openwisp - config_get base_url http url - config_get uuid http uuid - config_get key http key - config_get_bool verify_ssl http verify_ssl "1" - config_get respawn_threshold http respawn_threshold - config_get respawn_timeout http respawn_timeout - config_get respawn_retry http respawn_retry + # for openwisp_config + config_load openwisp + config_get base_url http url + config_get uuid http uuid + config_get key http key + config_get_bool verify_ssl http verify_ssl "1" + config_get respawn_threshold http respawn_threshold + config_get respawn_timeout http respawn_timeout + config_get respawn_retry http respawn_retry - [ -n "$base_url" ] && base_url="--url $base_url" - [ -n "$uuid" ] && uuid="--uuid $uuid" - [ -n "$key" ] && key="--key $key" - [ -n "$verify_ssl" ] && verify_ssl="--verify_ssl $verify_ssl" + [ -n "$base_url" ] && base_url="--url $base_url" + [ -n "$uuid" ] && uuid="--uuid $uuid" + [ -n "$key" ] && key="--key $key" + [ -n "$verify_ssl" ] && verify_ssl="--verify_ssl $verify_ssl" - # for openwisp_monitoring - config_load openwisp_monitoring - config_get monitored_interfaces monitoring monitored_interfaces "*" - config_get interval monitoring interval "300" + # for openwisp_monitoring + config_load openwisp_monitoring + config_get monitored_interfaces monitoring monitored_interfaces "*" + config_get interval monitoring interval "300" - interval="$(time_to_seconds "$interval")" - if [ "$interval" -lt 1 ]; then - logger -s "Interval is invalid. Use time value(eg: '10', '2m', '3h', '1d')" \ - -t monitoring \ - -p daemon.err - exit 1 - fi - interval="--interval $interval" - monitored_interfaces="--monitored_interfaces $monitored_interfaces" + interval="$(time_to_seconds "$interval")" + if [ "$interval" -lt 1 ]; then + logger -s "Interval is invalid. Use time value(eg: '10', '2m', '3h', '1d')" \ + -t monitoring \ + -p daemon.err + exit 1 + fi + interval="--interval $interval" + monitored_interfaces="--monitored_interfaces $monitored_interfaces" - procd_open_instance "openwisp_monitoring_monitoring" - procd_set_param command $PROG "$base_url" "$uuid" "$key" "$verify_ssl" "$interval" "$monitored_interfaces" - procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" - procd_close_instance - logger -s "$PROG_NAME started" \ - -t monitoring \ - -p daemon.info + procd_open_instance "openwisp_monitoring_monitoring" + procd_set_param command $PROG "$base_url" "$uuid" "$key" "$verify_ssl" "$interval" "$monitored_interfaces" + procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" + procd_close_instance + logger -s "$PROG_NAME started" \ + -t monitoring \ + -p daemon.info } stop_service() { - logger -s "$PROG_NAME stopping" \ - -t monitoring \ - -p daemon.info + logger -s "$PROG_NAME stopping" \ + -t monitoring \ + -p daemon.info } service_triggers() { - procd_add_reload_trigger "openwisp" "monitoring" + procd_add_reload_trigger "openwisp" "monitoring" } diff --git a/openwrt-openwisp-monitoring/files/sbin/netjson-monitoring.lua b/openwrt-openwisp-monitoring/files/sbin/netjson-monitoring.lua index d519578..b4e3175 100755 --- a/openwrt-openwisp-monitoring/files/sbin/netjson-monitoring.lua +++ b/openwrt-openwisp-monitoring/files/sbin/netjson-monitoring.lua @@ -1,187 +1,190 @@ #!/usr/bin/env lua -- retrieve monitoring information -- and return it as NetJSON Output -local cjson = require('cjson') -local io = require('io') +package.path=package.path .. ";../files/lib/?.lua" -local ubus_lib = require('ubus') -local ubus = ubus_lib.connect() +local cjson=require('cjson') +local io=require('io') + +local ubus_lib=require('ubus') +local ubus=ubus_lib.connect() if not ubus then - error('Failed to connect to ubusd') + error('Failed to connect to ubusd') end -local monitoring = require('openwisp.monitoring') +local monitoring=require('openwisp.monitoring') -- collect system info -local system_info = ubus:call('system', 'info', {}) -local board = ubus:call('system', 'board', {}) -local loadavg_output = io.popen('cat /proc/loadavg'):read() -loadavg_output = monitoring.utils.split(loadavg_output, ' ') -local load_average = {tonumber(loadavg_output[1]), tonumber(loadavg_output[2]), tonumber(loadavg_output[3])} - +local system_info=ubus:call('system', 'info', {}) +local board=ubus:call('system', 'board', {}) +local loadavg_output=io.popen('cat /proc/loadavg'):read() +loadavg_output=monitoring.utils.split(loadavg_output, ' ') +local load_average={tonumber(loadavg_output[1]), tonumber(loadavg_output[2]), tonumber(loadavg_output[3])} -- init netjson data structure -local netjson = { - type = 'DeviceMonitoring', - general = { - hostname = board.hostname, - local_time = system_info.localtime, - uptime = system_info.uptime - }, - resources = { - load = load_average, - memory = system_info.memory, - swap = system_info.swap, - cpus = monitoring.resources.get_cpus(), - disk = monitoring.resources.parse_disk_usage() - } +local netjson={ + type='DeviceMonitoring', + general={ + hostname=board.hostname, + local_time=system_info.localtime, + uptime=system_info.uptime + }, + resources={ + load=load_average, + memory=system_info.memory, + swap=system_info.swap, + cpus=monitoring.resources.get_cpus(), + disk=monitoring.resources.parse_disk_usage() + } } -local dhcp_leases = monitoring.dhcp.get_dhcp_leases() +local dhcp_leases=monitoring.dhcp.get_dhcp_leases() if not monitoring.utils.is_table_empty(dhcp_leases) then - netjson.dhcp_leases = dhcp_leases + netjson.dhcp_leases=dhcp_leases end -local host_neighbors = monitoring.neighbors.get_neighbors() +local host_neighbors=monitoring.neighbors.get_neighbors() if not monitoring.utils.is_table_empty(host_neighbors) then - netjson.neighbors = host_neighbors + netjson.neighbors=host_neighbors end -- determine the interfaces to monitor -local traffic_monitored = arg[1] -local include_stats = {} -if traffic_monitored and traffic_monitored ~= '*' then - traffic_monitored = monitoring.utils.split(traffic_monitored, ' ') - for _, name in pairs(traffic_monitored) do - include_stats[name] = true - end +local arg={...} +local traffic_monitored=arg[1] +local include_stats={} +if traffic_monitored and traffic_monitored ~='*' then + traffic_monitored=monitoring.utils.split(traffic_monitored, ' ') + for _, name in pairs(traffic_monitored) do + include_stats[name]=true + end end -- collect device data -local network_status = ubus:call('network.device', 'status', {}) -local wireless_status = ubus:call('network.wireless', 'status', {}) -local vpn_interfaces = monitoring.interfaces.get_vpn_interfaces() -local wireless_interfaces = {} -local host_interfaces = {} -local dns_servers = {} -local dns_search = {} +local network_status=ubus:call('network.device', 'status', {}) +local wireless_status=ubus:call('network.wireless', 'status', {}) +local vpn_interfaces=monitoring.interfaces.get_vpn_interfaces() +local wireless_interfaces={} +local host_interfaces={} +local dns_servers={} +local dns_search={} -- collect relevant wireless interface stats -- (traffic and connected clients) for _, radio in pairs(wireless_status) do - for _, interface in ipairs(radio.interfaces) do - local name = interface.ifname - local is_mesh = false - local clients = nil - if name and not monitoring.utils.is_excluded(name) then - local iwinfo = ubus:call('iwinfo', 'info', { - device = name - }) - local netjson_interface = { - name = name, - type = 'wireless', - wireless = { - ssid = iwinfo.ssid, - mode = monitoring.wifi.iwinfo_modes[iwinfo.mode] or iwinfo.mode, - channel = iwinfo.channel, - frequency = iwinfo.frequency, - tx_power = iwinfo.txpower, - signal = iwinfo.signal, - noise = iwinfo.noise, - country = iwinfo.country - } - } - if iwinfo.mode == 'Ad-Hoc' or iwinfo.mode == 'Mesh Point' then - clients = ubus:call('iwinfo', 'assoclist', { - device = name - }).results - is_mesh = true - else - local hostapd_output = ubus:call('hostapd.' .. name, 'get_clients', {}) - if hostapd_output then - clients = hostapd_output.clients - end - end - if not monitoring.utils.is_table_empty(clients) then - netjson_interface.wireless.clients = monitoring.wifi.netjson_clients(clients, is_mesh) - end - wireless_interfaces[name] = netjson_interface + for _, interface in ipairs(radio.interfaces) do + local name=interface.ifname + local is_mesh=false + local clients=nil + if name and not monitoring.utils.is_excluded(name) then + local iwinfo=ubus:call('iwinfo', 'info', { + device=name + }) + local netjson_interface={ + name=name, + type='wireless', + wireless={ + ssid=iwinfo.ssid, + mode=monitoring.wifi.iwinfo_modes[iwinfo.mode] or iwinfo.mode, + channel=iwinfo.channel, + frequency=iwinfo.frequency, + tx_power=iwinfo.txpower, + signal=iwinfo.signal, + noise=iwinfo.noise, + country=iwinfo.country + } + } + if iwinfo.mode=='Ad-Hoc' or iwinfo.mode=='Mesh Point' then + clients=ubus:call('iwinfo', 'assoclist', { + device=name + }).results + is_mesh=true + else + local hostapd_output=ubus:call('hostapd.' .. name, 'get_clients', {}) + if hostapd_output then + clients=hostapd_output.clients end + end + if not monitoring.utils.is_table_empty(clients) then + netjson_interface.wireless.clients=monitoring.wifi.netjson_clients(clients, is_mesh) + end + wireless_interfaces[name]=netjson_interface end + end end -- collect interface stats for name, interface in pairs(network_status) do - -- only collect data from iterfaces which have not been excluded - if not monitoring.utils.is_excluded(name) then - local netjson_interface = { - name = name, - type = string.lower(interface.type), - up = interface.up, - mac = interface.macaddr, - txqueuelen = interface.txqueuelen, - mtu = interface.mtu, - speed = interface.speed, - bridge_members = interface['bridge-members'], - multicast = interface.multicast - } - if wireless_interfaces[name] then - monitoring.utils.dict_merge(wireless_interfaces[name], netjson_interface) - interface.type = netjson_interface.type - end - if interface.type == 'Network device' then - local link_supported = interface['link-supported'] - if link_supported and next(link_supported) then - netjson_interface.type = 'ethernet' - netjson_interface.link_supported = link_supported - elseif vpn_interfaces[name] then - netjson_interface.type = 'virtual' - else - netjson_interface.type = 'other' - end - end - if include_stats[name] or traffic_monitored == '*' then - if monitoring.wifi.needs_inversion(netjson_interface) then - --- ensure wifi access point interfaces - --- show download and upload values from - --- the user's perspective and not from the router perspective - interface.statistics = monitoring.wifi.invert_rx_tx(interface.statistics) - end - netjson_interface.statistics = interface.statistics - end - local addresses = monitoring.interfaces.get_addresses(name) - if next(addresses) then - netjson_interface.addresses = addresses - end - local info = monitoring.interfaces.get_interface_info(name, netjson_interface) - if info.stp ~= nil then - netjson_interface.stp = info.stp - end - if info.specialized then - for key, value in pairs(info.specialized) do - netjson_interface[key] = value - end - end - table.insert(host_interfaces, netjson_interface) - -- DNS info is independent from interface - if info.dns_servers then - monitoring.utils.array_concat(info.dns_servers, dns_servers) - end - if info.dns_search then - monitoring.utils.array_concat(info.dns_search, dns_search) - end + -- only collect data from iterfaces which have not been excluded + if not monitoring.utils.is_excluded(name) then + local netjson_interface={ + name=name, + type=string.lower(interface.type), + up=interface.up, + mac=interface.macaddr, + txqueuelen=interface.txqueuelen, + mtu=interface.mtu, + speed=interface.speed, + bridge_members=interface['bridge-members'], + multicast=interface.multicast + } + if wireless_interfaces[name] then + monitoring.utils.dict_merge(wireless_interfaces[name], netjson_interface) + interface.type=netjson_interface.type + end + if interface.type=='Network device' then + local link_supported=interface['link-supported'] + if link_supported and next(link_supported) then + netjson_interface.type='ethernet' + netjson_interface.link_supported=link_supported + elseif vpn_interfaces[name] then + netjson_interface.type='virtual' + else + netjson_interface.type='other' + end + end + if include_stats[name] or traffic_monitored=='*' then + if monitoring.wifi.needs_inversion(netjson_interface) then + --- ensure wifi access point interfaces + --- show download and upload values from + --- the user's perspective and not from the router perspective + interface.statistics=monitoring.wifi.invert_rx_tx(interface.statistics) + end + netjson_interface.statistics=interface.statistics + end + local addresses=monitoring.interfaces.get_addresses(name) + if next(addresses) then + netjson_interface.addresses=addresses + end + local info=monitoring.interfaces.get_interface_info(name, netjson_interface) + if info.stp ~=nil then + netjson_interface.stp=info.stp + end + if info.specialized then + for key, value in pairs(info.specialized) do + netjson_interface[key]=value + end + end + table.insert(host_interfaces, netjson_interface) + -- DNS info is independent from interface + if info.dns_servers then + monitoring.utils.array_concat(info.dns_servers, dns_servers) + end + if info.dns_search then + monitoring.utils.array_concat(info.dns_search, dns_search) end + end end -if next(host_interfaces) ~= nil then - netjson.interfaces = host_interfaces +if next(host_interfaces) ~=nil then + netjson.interfaces=host_interfaces end -if next(dns_servers) ~= nil then - netjson.dns_servers = dns_servers +if next(dns_servers) ~=nil then + netjson.dns_servers=dns_servers end -if next(dns_search) ~= nil then - netjson.dns_search = dns_search +if next(dns_search) ~=nil then + netjson.dns_search=dns_search end -print(cjson.encode(netjson)) +io.write(cjson.encode(netjson)) +return cjson.encode(netjson) diff --git a/openwrt-openwisp-monitoring/tests/.luacov b/openwrt-openwisp-monitoring/tests/.luacov new file mode 100644 index 0000000..909a517 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/.luacov @@ -0,0 +1,5 @@ +return { + ['exclude']={ + 'luaunit$' + } +} diff --git a/openwrt-openwisp-monitoring/tests/basic_env.lua b/openwrt-openwisp-monitoring/tests/basic_env.lua new file mode 100644 index 0000000..3693a47 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/basic_env.lua @@ -0,0 +1,58 @@ +local env={} +env.io={ + popen=function(arg) + if arg=='cat /proc/loadavg' then + local f=assert(io.tmpfile()) + f:write('0.37 0.95 1.23 2/873 56899\n') + f:seek('set',0) + return f + end + local f=assert(io.tmpfile()) + f:write('') + f:seek('set',0) + return f + end, + open=function(arg) + return nil + end, + write=function(...) + return nil + end +} + +env.ubus={ + connect=function() + return { + call=function(...) + local arg={...} + if arg[2]=='system' and arg[3]=='board' then + return {hostname="08-00-27-56-92-F5"} + elseif arg[2]=='system' and arg[3]=='info' then + return { + memory=nil, + local_time=nil, + uptime=nil, + swap=nil + } + else + return {} + end + end + } + end +} + +env.uci={ + cursor=function() + return { + get_all=function(...) + return nil + end, + get=function(...) + return nil + end + } + end +} + +return env diff --git a/openwrt-openwisp-monitoring/tests/main_env.lua b/openwrt-openwisp-monitoring/tests/main_env.lua new file mode 100644 index 0000000..19d06cf --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/main_env.lua @@ -0,0 +1,79 @@ +package.path=package.path .. ";../files/lib/?.lua" + +local env={} +local dhcp_data=require('test_files/dhcp_data') +local test_file_dir='./test_files/' + +env.uci={ + cursor=function() + return { + get_all=function(...) + local arg={...} + if arg[2]=='dhcp' then + return dhcp_data.config + elseif arg[2]=='openvpn' then + return require('test_files/openvpn_data') + end + end, + get=function(...) + local arg={...} + if arg[1]=='network' and arg[3]=='ula_prefix' then + return "fdf7:0c44:27ae::/48" + elseif arg[1]=='network' and arg[3]=='stp' then + return '1' + elseif arg[1]=='network' and arg[3]=='device' then + return '/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb2/2-1' + end + end + } + end +} + +env.io={ + popen=function(arg) + if arg=='df' then + return io.open(test_file_dir .. 'disk_usage.txt') + elseif arg=='cat /proc/cpuinfo | grep -c processor' then + local f=assert(io.tmpfile()) + f:write('8') + f:seek('set',0) + return f + elseif arg=='cat /proc/net/arp 2> /dev/null' then + return io.open(test_file_dir .. 'parse_app.txt') + elseif arg=='ip -json neigh 2> /dev/null' then + return io.open(test_file_dir .. 'ip_json_neigh.txt') + elseif arg=='ip neigh 2> /dev/null' then + return io.open(test_file_dir .. 'ip_neigh.txt') + else + local modem='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb2/2-1' + if arg=='mmcli --output-json -m '.. modem then + return io.open(test_file_dir .. 'modem_data.txt') + elseif arg=='mmcli --output-json -m '..modem..' --signal-get' then + return io.open(test_file_dir .. 'umts_sample.txt') + end + end + end, + open=function(arg) + if arg=='/tmp/dhcp.leases' then + return io.open(test_file_dir .. 'dhcp_leases.txt') + else + return io.open(arg) + end + end +} + +env.ubus={ + connect=function() + return { + call=function(...) + local arg={...} + if arg[2]=='network.interface' and arg[3]=='dump' then + local f=require('test_files/interface_data') + return f.interface_data + end + end + } + end +} + +return env diff --git a/openwrt-openwisp-monitoring/tests/test_dhcp.lua b/openwrt-openwisp-monitoring/tests/test_dhcp.lua new file mode 100644 index 0000000..4da5335 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_dhcp.lua @@ -0,0 +1,82 @@ +package.path=package.path .. ";../files/lib/openwisp/?.lua;../files/sbin/?.lua" + +local dhcp_data=require('test_files/dhcp_data') + +local luaunit=require('luaunit') + +TestDhcp={ + setUp=function() + local env=require('main_env') + package.loaded.uci=env.uci + package.loaded.io=env.io + end, + tearDown=function() + end +} + +TestNetJSON={ + setUp=function() + local env=require('basic_env') + local test_file_dir='./test_files/' + package.loaded.ubus=env.ubus + package.loaded.io={ + popen=function(arg) + local f=assert(io.tmpfile()) + if arg=='cat /proc/loadavg' then + f:write('0.37 0.95 1.23 2/873 56899\n') + else + f:write('') + end + f:seek('set',0) + return f + end, + open=function(arg) + if arg=='/tmp/dhcp.leases' then + return io.open(test_file_dir .. 'dhcp_leases.txt') + else + return nil + end + end, + write=function(...) + return nil + end + } + package.loaded.uci={ + cursor=function() + return { + get_all=function(...) + local arg={...} + if arg[2]=='dhcp' then + return dhcp_data.config + else + return nil + end + end, + get=function(...) + return nil + end + } + end + } + end, + tearDown=function() + end +} + +function TestDhcp.test_dhcp_leases() + local dhcp_functions=require('dhcp') + + luaunit.assertEquals(dhcp_functions.get_dhcp_leases(), dhcp_data.leases) + luaunit.assertEquals(dhcp_functions.parse_dhcp_lease_file('/tmp/dhcp.leases',{}), dhcp_data.leases) + luaunit.assertEquals(dhcp_functions.parse_dhcp_lease_file('/tmp/no_dhcp.leases',{}), {}) +end + +function TestNetJSON.test_netjson_monitoring_dhcp() + local netjson=require('netjson-monitoring') + luaunit.assertNotNil(string.find(netjson, '"mac":"e8:6a:64:3e:4a:3c"')) + luaunit.assertNotNil(string.find(netjson, '"client_id":"01:e8:6a:64:3e:4a:3c"')) + luaunit.assertNotNil(string.find(netjson, '"ip":"192.168.1.136"')) + luaunit.assertNotNil(string.find(netjson, '"expiry":1620788343')) +end + +os.exit( luaunit.LuaUnit.run() ) diff --git a/openwrt-openwisp-monitoring/tests/test_files/address_data.lua b/openwrt-openwisp-monitoring/tests/test_files/address_data.lua new file mode 100644 index 0000000..cae8d82 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/address_data.lua @@ -0,0 +1,61 @@ +local test_data={} + + +test_data.eth2_interface={ + autostart=true, + available=true, + data={ + hostname="08-00-27-4F-CB-2E", + leasetime=86400 + }, + delegation=true, + device="eth2", + ["dns-search"]={}, + ["dns-server"]={ "192.168.0.1" }, + dns_metric=0, + dynamic=false, + inactive={ + ["dns-search"]={}, + ["dns-server"]={}, + ["ipv4-address"]={}, + ["ipv6-address"]={}, + neighbors={}, + route={} + }, + interface="lan", + ["ipv4-address"]={ { + address="192.168.0.144", + mask=24 + } }, + ["ipv6-address"]={}, + ["ipv6-prefix"]={}, + ["ipv6-prefix-assignment"]={}, + l3_device="eth2", + metric=0, + neighbors={}, + pending=false, + proto="dhcp", + route={ { + mask=0, + nexthop="192.168.0.1", + source="192.168.0.144/32", + target="0.0.0.0" + } }, + up=true, + updated={ "addresses", "routes", "data" }, + uptime=1973 +} + +test_data.routes=test_data.eth2_interface.route + +test_data.ipv4_address=test_data.eth2_interface['ipv4-address'][1] + +test_data.address_array={ + address="192.168.0.144", + family="ipv4", + gateway="192.168.0.1", + mask=24, + proto="dhcp" +} + +return test_data diff --git a/openwrt-openwisp-monitoring/tests/test_files/dhcp_data.lua b/openwrt-openwisp-monitoring/tests/test_files/dhcp_data.lua new file mode 100644 index 0000000..becdd90 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/dhcp_data.lua @@ -0,0 +1,65 @@ +local dhcp={} + +dhcp.config={ + dnsmasq1={ + [".anonymous"]=false, + [".index"]=0, + [".name"]="dnsmasq1", + [".type"]="dnsmasq", + authoritative="1", + boguspriv="1", + domain="lan", + domainneeded="1", + expandhosts="1", + filterwin2k="0", + leasefile="/tmp/dhcp.leases", + localise_queries="1", + localservice="1", + nonegcache="0", + nonwildcard="1", + readethers="1", + rebind_localhost="1", + rebind_protection="1", + resolvfile="/tmp/resolv.conf.auto" + }, + lan={ + [".anonymous"]=false, + [".index"]=1, + [".name"]="lan", + [".type"]="dhcp", + dhcpv6="server", + interface="lan", + leasetime="12h", + limit="150", + ra="server", + start="100" + }, + odhcpd={ + [".anonymous"]=false, + [".index"]=3, + [".name"]="odhcpd", + [".type"]="odhcpd", + leasefile="/tmp/hosts/odhcpd", + leasetrigger="/usr/sbin/odhcpd-update", + loglevel="4", + maindhcp="0" + }, + wan={ + [".anonymous"]=false, + [".index"]=2, + [".name"]="wan", + [".type"]="dhcp", + ignore="1", + interface="wan" + } +} + +dhcp.leases={ { + client_id="01:e8:6a:64:3e:4a:3c", + client_name="FRIDAY", + expiry=1620788343, + ip="192.168.1.136", + mac="e8:6a:64:3e:4a:3c" + } } + +return dhcp diff --git a/openwrt-openwisp-monitoring/tests/test_files/dhcp_leases.txt b/openwrt-openwisp-monitoring/tests/test_files/dhcp_leases.txt new file mode 100644 index 0000000..911a2b2 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/dhcp_leases.txt @@ -0,0 +1 @@ +1620788343 e8:6a:64:3e:4a:3c 192.168.1.136 FRIDAY 01:e8:6a:64:3e:4a:3c diff --git a/openwrt-openwisp-monitoring/tests/test_files/disk_usage.txt b/openwrt-openwisp-monitoring/tests/test_files/disk_usage.txt new file mode 100644 index 0000000..f522faf --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/disk_usage.txt @@ -0,0 +1,6 @@ +Filesystem 1K-blocks Used Available Use% Mounted on +/dev/root 258016 18912 233864 7% / +tmpfs 508440 72 508368 0% /tmp +/dev/sda1 16112 3872 11916 25% /boot +/dev/sda1 16112 3872 11916 25% /boot +tmpfs 512 0 512 0% /dev diff --git a/openwrt-openwisp-monitoring/tests/test_files/interface_data.lua b/openwrt-openwisp-monitoring/tests/test_files/interface_data.lua new file mode 100644 index 0000000..fcba133 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/interface_data.lua @@ -0,0 +1,298 @@ +local test_data={} + +test_data.interface_data={ + interface={ { + autostart=true, + available=true, + data={ + hostname="08-00-27-4F-CB-2E", + leasetime=86400 + }, + delegation=true, + device="eth2", + ["dns-search"]={}, + ["dns-server"]={ "192.168.0.1" }, + dns_metric=0, + dynamic=false, + inactive={ + ["dns-search"]={}, + ["dns-server"]={}, + ["ipv4-address"]={}, + ["ipv6-address"]={}, + neighbors={}, + route={} + }, + interface="lan", + ["ipv4-address"]={ { + address="192.168.0.144", + mask=24 + } }, + ["ipv6-address"]={}, + ["ipv6-prefix"]={}, + ["ipv6-prefix-assignment"]={}, + l3_device="eth2", + metric=0, + neighbors={}, + pending=false, + proto="dhcp", + route={ { + mask=0, + nexthop="192.168.0.1", + source="192.168.0.144/32", + target="0.0.0.0" + } }, + up=true, + updated={ "addresses", "routes", "data" }, + uptime=132 + }, { + autostart=true, + available=true, + data={ + leasetime=86400 + }, + delegation=true, + device="br-lan", + ["dns-search"]={}, + ["dns-server"]={ + "8.8.8.8", + "8.8.4.4" + }, + dns_metric=0, + dynamic=false, + inactive={ + ["dns-search"]={}, + ["dns-server"]={}, + ["ipv4-address"]={}, + ["ipv6-address"]={}, + neighbors={}, + route={} + }, + interface="lan", + ["ipv4-address"]={ { + address="192.168.1.41", + mask=24 + } }, + ["ipv6-address"]={}, + ["ipv6-prefix"]={}, + ["ipv6-prefix-assignment"]={ + { + address="fd78:adb4:afb2::", + mask=60, + } + }, + l3_device="br-lan", + metric=0, + neighbors={}, + pending=false, + proto="dhcp", + route={ + { + target="0.0.0.0", + mask=0, + nexthop="192.168.1.1", + source="192.168.1.41/32" + } + }, + up=true, + updated={ "addresses" }, + uptime=773875 + },{ + autostart=true, + available=true, + data={}, + delegation=true, + device="lan2", + ["dns-search"]={}, + ["dns-server"]={}, + dns_metric=0, + dynamic=false, + inactive={ + ["dns-search"]={}, + ["dns-server"]={}, + ["ipv4-address"]={}, + ["ipv6-address"]={}, + neighbors={}, + route={} + }, + interface="modem", + ["ipv4-address"]={}, + ["ipv6-address"]={}, + ["ipv6-prefix"]={}, + ["ipv6-prefix-assignment"]={}, + l3_device="lan2", + metric=0, + neighbors={}, + pending=false, + proto="modemmanager", + route={}, + up=true, + updated={ "addresses" }, + uptime=7738 + },{ + autostart=true, + available=true, + data={}, + delegation=true, + device="lo", + ["dns-search"]={}, + ["dns-server"]={}, + dns_metric=0, + dynamic=false, + inactive={ + ["dns-search"]={}, + ["dns-server"]={}, + ["ipv4-address"]={}, + ["ipv6-address"]={}, + neighbors={}, + route={} + }, + interface="loopback", + ["ipv4-address"]={ { + address="127.0.0.1", + mask=8 + } }, + ["ipv6-address"]={}, + ["ipv6-prefix"]={}, + ["ipv6-prefix-assignment"]={}, + l3_device="lo", + metric=0, + neighbors={}, + pending=false, + proto="static", + route={}, + up=true, + updated={ "addresses" }, + uptime=135 + }, { + autostart=true, + available=true, + data={}, + delegation=true, + device="br-mng", + ["dns-search"]={}, + ["dns-server"]={}, + dns_metric=0, + dynamic=false, + inactive={ + ["dns-search"]={}, + ["dns-server"]={}, + ["ipv4-address"]={}, + ["ipv6-address"]={}, + neighbors={}, + route={} + }, + interface="mng", + ["ipv4-address"]={ { + address="192.168.56.2", + mask=24 + } }, + ["ipv6-address"]={}, + ["ipv6-prefix"]={}, + ["ipv6-prefix-assignment"]={}, + l3_device="br-mng", + metric=0, + neighbors={}, + pending=false, + proto="static", + route={}, + up=true, + updated={ "addresses" }, + uptime=135 + }, { + autostart=true, + available=true, + data={ + leasetime=600 + }, + delegation=true, + device="eth1", + ["dns-search"]={}, + ["dns-server"]={ "10.0.2.1" }, + dns_metric=0, + dynamic=false, + inactive={ + ["dns-search"]={}, + ["dns-server"]={}, + ["ipv4-address"]={}, + ["ipv6-address"]={}, + neighbors={}, + route={} + }, + interface="wan", + ["ipv4-address"]={ { + address="10.0.2.4", + mask=24 + } }, + ["ipv6-address"]={ { + address="2001:0db8:85a3:0000:0000:8a2e:0370:7334" + }}, + ["ipv6-prefix"]={}, + ["ipv6-prefix-assignment"]={}, + l3_device="eth1", + metric=0, + neighbors={}, + pending=false, + proto="dhcp", + route={ { + mask=0, + nexthop="10.0.2.1", + source="10.0.2.4/32", + target="0.0.0.0" + } }, + up=true, + updated={ "addresses", "routes", "data" }, + uptime=132 + } } +} + +test_data.random_interface_address={} + +test_data.eth1_addresses={ + {address="10.0.2.4", family="ipv4", gateway="10.0.2.1", mask=24, proto="dhcp"}, + {address="2001:0db8:85a3:0000:0000:8a2e:0370:7334", family="ipv6", gateway="10.0.2.1", proto="dhcp"}, + {address="10.0.3.15", family="ipv4", mask=24, proto="dhcp"}, + {address="fe80::a00:27ff:fe71:2291", family="ipv6", mask=64, proto="static"}, +} + +test_data.eth2_addresses={ + {address="192.168.0.144", family="ipv4", gateway="192.168.0.1", mask=24, proto="dhcp"}, + {address="192.168.0.146", family="ipv4", mask=24, proto="dhcp"}, + {address="fdf7:0c44:27ae:fe48:be0a", family="ipv6", mask=64, proto="static"} +} + +test_data.br_mng_addresses={ + {address="192.168.56.2", family="ipv4", mask=24, proto="static"}, + {address="fe81::a00:27ff:fed1:90b0", family="ipv6", mask=64, proto="dhcp"} +} + +test_data.br_lan_interface={ + addresses={ { + address="192.168.1.41", + family="ipv4", + gateway="192.168.1.1", + mask=24, + proto="dhcp" + } }, + bridge_members={ "lan1", "lan2", "mesh0", "mesh1", "wan", "wlan0", "wlan1" }, + mac="00:00:00:00:00:00", + mtu=1500, + multicast=true, + name="br-lan", + txqueuelen=1000, + type="bridge", + up=true +} + +test_data.lan2_interface={ + link_supported={ "10baseT-H", "10baseT-F", "100baseT-H", "100baseT-F", "1000baseT-F" }, + mac="00:00:00:00:00:00", + mtu=1500, + multicast=true, + name="lan2", + speed="-1F", + txqueuelen=1000, + type="ethernet", + up=true +} + +return test_data diff --git a/openwrt-openwisp-monitoring/tests/test_files/ip_json_neigh.txt b/openwrt-openwisp-monitoring/tests/test_files/ip_json_neigh.txt new file mode 100644 index 0000000..d06c761 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/ip_json_neigh.txt @@ -0,0 +1 @@ +[{"dst":"10.0.2.1","dev":"eth1","lladdr":"52:54:00:12:35:00","state":["REACHABLE"]},{"dst":"192.168.56.1","dev":"br-mng","lladdr":"0a:00:27:00:00:00","state":["REACHABLE"]},{"dst":"192.168.0.1","dev":"eth2","lladdr":"bc:0f:9a:17:5a:5c","state":["STALE"]},{"dst":"fe80::800:27ff:fe00:0","dev":"br-mng","lladdr":"0a:00:27:00:00:00","state":["STALE"]},{"dst":"fe80::22a6:cff:feb2:da10","dev":"eth2","lladdr":"20:a6:0c:b2:da:10","state":["STALE"]},{"dst":"fe80::bfca:28ed:f368:6cbc","dev":"eth2","lladdr":"98:3b:8f:98:b1:fb","state":["STALE"]}] diff --git a/openwrt-openwisp-monitoring/tests/test_files/ip_neigh.txt b/openwrt-openwisp-monitoring/tests/test_files/ip_neigh.txt new file mode 100644 index 0000000..a90e83c --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/ip_neigh.txt @@ -0,0 +1,6 @@ +10.0.2.1 dev eth1 lladdr 52:54:00:12:35:00 ref 1 used 0/0/0 probes 4 REACHABLE +192.168.56.1 dev br-mng lladdr 0a:00:27:00:00:00 ref 1 used 0/0/0 probes 1 REACHABLE +192.168.0.1 dev eth2 lladdr bc:0f:9a:17:5a:5c used 0/0/0 probes 4 STALE +fe80::800:27ff:fe00:0 dev br-mng lladdr 0a:00:27:00:00:00 used 0/0/0 probes 0 STALE +fe80::22a6:cff:feb2:da10 dev eth2 lladdr 20:a6:0c:b2:da:10 used 0/0/0 probes 4 STALE +fe80::bfca:28ed:f368:6cbc dev eth2 lladdr 98:3b:8f:98:b1:fb used 0/0/0 probes 4 STALE diff --git a/openwrt-openwisp-monitoring/tests/test_files/lte_sample.txt b/openwrt-openwisp-monitoring/tests/test_files/lte_sample.txt new file mode 100644 index 0000000..75e5c85 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/lte_sample.txt @@ -0,0 +1,33 @@ +{ + "modem": { + "signal": { + "cdma1x": { + "ecio": "--", + "rssi": "--" + }, + "evdo": { + "ecio": "--", + "io": "--", + "rssi": "--", + "sinr": "--" + }, + "gsm": { + "rssi": "--" + }, + "lte": { + "rsrp": "-92.00", + "rsrq": "-9.00", + "rssi": "-64.00", + "snr": "19.20" + }, + "refresh": { + "rate": "3" + }, + "umts": { + "ecio": "--", + "rscp": "--", + "rssi": "--" + } + } + } +} diff --git a/openwrt-openwisp-monitoring/tests/test_files/modem_data.txt b/openwrt-openwisp-monitoring/tests/test_files/modem_data.txt new file mode 100644 index 0000000..d5e7854 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/modem_data.txt @@ -0,0 +1,99 @@ +{ + "modem": { + "3gpp": { + "enabled-locks": [ + "fixed-dialing" + ], + "eps": { + "initial-bearer": { + "dbus-path": "--", + "settings": { + "apn": "APN.WAP", + "ip-type": "ipv4v6", + "password": "--", + "user": "--" + } + }, + "ue-mode-operation": "csps-1" + }, + "imei": "000000000000000", + "operator-code": "00000", + "operator-name": "OperatorName", + "pco": "--", + "registration-state": "home" + }, + "cdma": { + "activation-state": "--", + "cdma1x-registration-state": "--", + "esn": "--", + "evdo-registration-state": "--", + "meid": "--", + "nid": "--", + "sid": "--" + }, + "dbus-path": "/org/freedesktop/ModemManager1/Modem/0", + "generic": { + "access-technologies": [ + "hsdpa", + "hsupa" + ], + "bearers": [ + "/org/freedesktop/ModemManager1/Bearer/5" + ], + "carrier-configuration": "--", + "carrier-configuration-revision": "--", + "current-bands": [], + "current-capabilities": [ + "gsm-umts, lte" + ], + "current-modes": "allowed: 3g, 4g; preferred: none", + "device": "/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb2/2-1", + "device-identifier": "0000000000000000000000000000000000000000", + "drivers": [ + "cdc_mbim", + "option1" + ], + "equipment-identifier": "869710030159564", + "hardware-revision": "EM12-G", + "manufacturer": "Quectel", + "model": "EM12-G", + "own-numbers": [], + "plugin": "quectel", + "ports": [ + "cdc-wdm0 (mbim)", + "ttyUSB0 (qcdm)", + "ttyUSB2 (at)", + "ttyUSB3 (at)", + "wwan0 (net)" + ], + "power-state": "on", + "primary-port": "cdc-wdm0", + "primary-sim-slot": "--", + "revision": "EM12GPAR01A16M4G", + "signal-quality": { + "recent": "yes", + "value": "29" + }, + "sim": "/org/freedesktop/ModemManager1/SIM/0", + "sim-slots": [], + "state": "connected", + "state-failed-reason": "--", + "supported-bands": [], + "supported-capabilities": [ + "gsm-umts, lte" + ], + "supported-ip-families": [ + "ipv4", + "ipv6", + "ipv4v6" + ], + "supported-modes": [ + "allowed: 3g, 4g; preferred: none" + ], + "unlock-required": "--", + "unlock-retries": [ + "sim-pin2 (3)" + ] + } + } +} diff --git a/openwrt-openwisp-monitoring/tests/test_files/neighbors_data.lua b/openwrt-openwisp-monitoring/tests/test_files/neighbors_data.lua new file mode 100644 index 0000000..0f6dd6d --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/neighbors_data.lua @@ -0,0 +1,18 @@ +local test_data={} + +test_data.sample_parse_arp={ + {interface="eth1", ip="10.0.2.1", mac="52:54:00:12:35:00", state=""}, + {interface="br-mng", ip="192.168.56.1", mac="0a:00:27:00:00:00", state=""}, + {interface="eth2", ip="192.168.0.1", mac="bc:0f:9a:17:5a:5c", state=""} +} + +test_data.sample_ip_neigh={ + {interface="eth1", ip="10.0.2.1", mac="52:54:00:12:35:00", state="REACHABLE"}, + {interface="br-mng", ip="192.168.56.1", mac="0a:00:27:00:00:00", state="REACHABLE"}, + {interface="eth2", ip="192.168.0.1", mac="bc:0f:9a:17:5a:5c", state="STALE"}, + {interface="br-mng", ip="fe80::800:27ff:fe00:0", mac="0a:00:27:00:00:00", state="STALE"}, + {interface="eth2", ip="fe80::22a6:cff:feb2:da10", mac="20:a6:0c:b2:da:10", state="STALE"}, + {interface="eth2", ip="fe80::bfca:28ed:f368:6cbc", mac="98:3b:8f:98:b1:fb", state="STALE"} +} + +return test_data diff --git a/openwrt-openwisp-monitoring/tests/test_files/network_data.lua b/openwrt-openwisp-monitoring/tests/test_files/network_data.lua new file mode 100644 index 0000000..2fb033b --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/network_data.lua @@ -0,0 +1,608 @@ +local test_data={} + +test_data.wireless={ + mesh0={ + external=true, + present=true, + type="Network device", + up=true, + carrier=true, + mtu=1500, + mtu6=1500, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=false, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=7445, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=97, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=2367514, + rx_errors=0, + tx_bytes=564745121, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + }, + mesh1={ + external=true, + present=true, + type="Network device", + up=true, + carrier=true, + mtu=1500, + mtu6=1500, + macaddr="00:00:00:00:00:00", + xqueuelen=1000, + ipv6=false, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=24917085991, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=94311062, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=138182411, + rx_errors=0, + tx_bytes=151599685066, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + }, + wan={ + external=false, + present=true, + type="Network device", + up=true, + carrier=true, + ["link-advertising"]={ + "10baseT-H", + "10baseT-F", + "100baseT-H", + "100baseT-F", + "1000baseT-F" + }, + ["link-partner-advertising"]={ + "10baseT-H", + "10baseT-F", + "100baseT-H", + "100baseT-F", + "1000baseT-F" + }, + ["link-supported"]={ + "10baseT-H", + "10baseT-F", + "100baseT-H", + "100baseT-F", + "1000baseT-F" + }, + speed="1000F", + autoneg=true, + mtu=1500, + mtu6=1500, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=false, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=143754196868, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=138808630, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=94997043, + rx_errors=0, + tx_bytes=25110735945, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + }, + wlan0={ + external=true, + present=true, + type="Network device", + up=true, + carrier=true, + mtu=1500, + mtu6=1500, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=false, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=25967, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=198, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=2367747, + rx_errors=0, + tx_bytes=531641723, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + }, + wlan1={ + external=true, + present=true, + type="Network device", + up=true, + carrier=true, + mtu=1500, + mtu6=1500, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=false, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=0, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=0, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=2367515, + rx_errors=0, + tx_bytes=531596854, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + } +} + +test_data.devices={ + ["br-lan"]={ + external=false, + present=true, + type="bridge", + up=true, + carrier=true, + ["bridge-members"]={ + "lan1", + "lan2", + "mesh0", + "mesh1", + "wan", + "wlan0", + "wlan1" + }, + mtu=1500, + mtu6=1500, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=true, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=2130506, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=608294869, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=2988694, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=688324, + rx_errors=0, + tx_bytes=194322964, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + }, + eth0={ + external=false, + present=true, + type="Network device", + up=true, + carrier=true, + ["link-advertising"]={"1000baseT-F"}, + ["link-partner-advertising"]={}, + ["link-supported"]={ + "1000baseT-F" + }, + speed="1000F", + autoneg=true, + mtu=1504, + mtu6=1504, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=true, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=146274315993, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=138825694, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=95269376, + rx_errors=0, + tx_bytes=25943790384, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + }, + lan1={ + external=false, + present=true, + type="Network device", + up=true, + carrier=false, + ["link-advertising"]={ + "10baseT-H", + "10baseT-F", + "100baseT-H", + "100baseT-F", + "1000baseT-F" + }, + ["link-partner-advertising"]={}, + ["link-supported"]={ + "10baseT-H", + "10baseT-F", + "100baseT-H", + "100baseT-F", + "1000baseT-F" + }, + speed="-1F", + autoneg=true, + mtu=1500, + mtu6=1500, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=false, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=84054, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=1108, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=263386, + rx_errors=0, + tx_bytes=60746152, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + }, + lan2={ + external=false, + present=true, + type="Network device", + up=true, + carrier=false, + ["link-advertising"]={ + "10baseT-H", + "10baseT-F", + "100baseT-H", + "100baseT-F", + "1000baseT-F" + }, + ["link-partner-advertising"]={}, + ["link-supported"]={ + "10baseT-H", + "10baseT-F", + "100baseT-H", + "100baseT-F", + "1000baseT-F" + }, + speed="-1F", + autoneg=true, + mtu=1500, + mtu6=1500, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=false, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=true, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=0, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=0, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=0, + rx_errors=0, + tx_bytes=0, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + }, + lo={ + external=false, + present=true, + type="Network device", + up=true, + carrier=true, + mtu=65536, + mtu6=65536, + macaddr="00:00:00:00:00:00", + txqueuelen=1000, + ipv6=true, + promisc=false, + rpfilter=0, + acceptlocal=false, + igmpversion=0, + mldversion=0, + neigh4reachabletime=30000, + neigh6reachabletime=30000, + neigh4gcstaletime=60, + neigh6gcstaletime=60, + neigh4locktime=100, + dadtransmits=1, + multicast=false, + sendredirects=true, + statistics={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=17830347, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=181937, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=181937, + rx_errors=0, + tx_bytes=17830347, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 + } + } +} + +test_data.wlan1_stats={ + collisions=0, + rx_frame_errors=0, + tx_compressed=0, + multicast=0, + rx_length_errors=0, + tx_dropped=0, + rx_bytes=0, + rx_missed_errors=0, + tx_errors=0, + rx_compressed=0, + rx_over_errors=0, + tx_fifo_errors=0, + rx_crc_errors=0, + rx_packets=0, + tx_heartbeat_errors=0, + rx_dropped=0, + tx_aborted_errors=0, + tx_packets=2367515, + rx_errors=0, + tx_bytes=531596854, + tx_window_errors=0, + rx_fifo_errors=0, + tx_carrier_errors=0 +} + +return test_data diff --git a/openwrt-openwisp-monitoring/tests/test_files/nixio_data.lua b/openwrt-openwisp-monitoring/tests/test_files/nixio_data.lua new file mode 100644 index 0000000..8d7fb40 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/nixio_data.lua @@ -0,0 +1,284 @@ +local nixio_data={ { + addr="00:00:00:00:00:00", + broadaddr="00:00:00:00:00:00", + data={ + collisions=0, + multicast=0, + rx_bytes=19931, + rx_dropped=0, + rx_errors=0, + rx_packets=196, + tx_bytes=19931, + tx_dropped=0, + tx_errors=0, + tx_packets=196 + }, + dstaddr="00:00:00:00:00:00", + family="packet", + flags={ + broadcast=false, + loopback=true, + multicast=false, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + hatype=772, + ifindex=1, + name="lo" + }, { + addr="08:00:27:d1:90:b0", + broadaddr="ff:ff:ff:ff:ff:ff", + data={ + collisions=0, + multicast=105, + rx_bytes=524164, + rx_dropped=0, + rx_errors=0, + rx_packets=5397, + tx_bytes=808210, + tx_dropped=0, + tx_errors=0, + tx_packets=5520 + }, + dstaddr="ff:ff:ff:ff:ff:ff", + family="packet", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + hatype=1, + ifindex=2, + name="eth0" + }, { + addr="08:00:27:71:22:91", + broadaddr="ff:ff:ff:ff:ff:ff", + data={ + collisions=0, + multicast=0, + rx_bytes=6120, + rx_dropped=0, + rx_errors=0, + rx_packets=50, + tx_bytes=6906, + tx_dropped=0, + tx_errors=0, + tx_packets=68 + }, + dstaddr="ff:ff:ff:ff:ff:ff", + family="packet", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + hatype=1, + ifindex=3, + name="eth1" + }, { + addr="08:00:27:48:be:0a", + broadaddr="ff:ff:ff:ff:ff:ff", + data={ + collisions=0, + multicast=103, + rx_bytes=4560379, + rx_dropped=0, + rx_errors=0, + rx_packets=3825, + tx_bytes=142661, + tx_dropped=0, + tx_errors=0, + tx_packets=1749 + }, + dstaddr="ff:ff:ff:ff:ff:ff", + family="packet", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + hatype=1, + ifindex=4, + name="eth2" + }, { + addr="08:00:27:d1:90:b0", + broadaddr="ff:ff:ff:ff:ff:ff", + data={ + collisions=0, + multicast=0, + rx_bytes=448294, + rx_dropped=0, + rx_errors=0, + rx_packets=5391, + tx_bytes=806630, + tx_dropped=0, + tx_errors=0, + tx_packets=5519 + }, + dstaddr="ff:ff:ff:ff:ff:ff", + family="packet", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + hatype=1, + ifindex=5, + name="br-mng" + }, { + addr="127.0.0.1", + broadaddr="127.0.0.1", + data={}, + dstaddr="127.0.0.1", + family="inet", + flags={ + broadcast=false, + loopback=true, + multicast=false, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + name="lo", + netmask="255.0.0.0", + prefix=8 + }, { + addr="10.0.3.15", + broadaddr="10.0.3.255", + data={}, + dstaddr="10.0.3.255", + family="inet", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + name="eth1", + netmask="255.255.255.0", + prefix=24 + }, { + addr="192.168.0.146", + broadaddr="192.168.0.255", + data={}, + dstaddr="192.168.0.255", + family="inet", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + name="eth2", + netmask="255.255.255.0", + prefix=24 + }, { + addr="192.168.56.2", + broadaddr="192.168.56.255", + data={}, + dstaddr="192.168.56.255", + family="inet", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + name="br-mng", + netmask="255.255.255.0", + prefix=24 + }, { + addr="::1", + data={}, + family="inet6", + flags={ + broadcast=false, + loopback=true, + multicast=false, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + name="lo", + netmask="ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + prefix=128 + }, { + addr="fe80::a00:27ff:fe71:2291", + data={}, + family="inet6", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + name="eth1", + netmask="ffff:ffff:ffff:ffff::", + prefix=64 + }, { + addr="fdf7:0c44:27ae:fe48:be0a", + data={}, + family="inet6", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + name="eth2", + netmask="ffff:ffff:ffff:ffff::", + prefix=64 + }, { + addr="fe81::a00:27ff:fed1:90b0", + data={}, + family="inet6", + flags={ + broadcast=true, + loopback=false, + multicast=true, + noarp=false, + pointtopoint=false, + promisc=false, + up=true + }, + name="br-mng", + netmask="ffff:ffff:ffff:ffff::", + prefix=64 + } } + +return nixio_data diff --git a/openwrt-openwisp-monitoring/tests/test_files/openvpn_data.lua b/openwrt-openwisp-monitoring/tests/test_files/openvpn_data.lua new file mode 100644 index 0000000..5a707b2 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/openvpn_data.lua @@ -0,0 +1,56 @@ +local openvpn={ + custom_config={ + [".anonymous"]=false, + [".index"]=0, + [".name"]="custom_config", + [".type"]="openvpn", + config="/etc/openvpn/my-vpn.conf", + enabled="0" + }, + sample_client={ + [".anonymous"]=false, + [".index"]=2, + [".name"]="sample_client", + [".type"]="openvpn", + ca="/etc/openvpn/ca.crt", + cert="/etc/openvpn/client.crt", + client="1", + compress="lzo", + dev="tun", + enabled="0", + key="/etc/openvpn/client.key", + nobind="1", + persist_key="1", + persist_tun="1", + proto="udp", + remote={ "my_server_1 1194" }, + resolv_retry="infinite", + user="nobody", + verb="3" + }, + sample_server={ + [".anonymous"]=false, + [".index"]=1, + [".name"]="sample_server", + [".type"]="openvpn", + ca="/etc/openvpn/ca.crt", + cert="/etc/openvpn/server.crt", + compress="lzo", + dev="tun", + dh="/etc/openvpn/dh1024.pem", + enabled="0", + ifconfig_pool_persist="/tmp/ipp.txt", + keepalive="10 120", + key="/etc/openvpn/server.key", + persist_key="1", + persist_tun="1", + port="1194", + proto="udp", + server="10.8.0.0 255.255.255.0", + status="/tmp/openvpn-status.log", + user="nobody", + verb="3" + } +} + +return openvpn diff --git a/openwrt-openwisp-monitoring/tests/test_files/parse_app.txt b/openwrt-openwisp-monitoring/tests/test_files/parse_app.txt new file mode 100644 index 0000000..4ec841c --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/parse_app.txt @@ -0,0 +1,4 @@ +IP address HW type Flags HW address Mask Device +10.0.2.1 0x1 0x2 52:54:00:12:35:00 * eth1 +192.168.56.1 0x1 0x2 0a:00:27:00:00:00 * br-mng +192.168.0.1 0x1 0x2 bc:0f:9a:17:5a:5c * eth2 diff --git a/openwrt-openwisp-monitoring/tests/test_files/resources_data.lua b/openwrt-openwisp-monitoring/tests/test_files/resources_data.lua new file mode 100644 index 0000000..40a52ea --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/resources_data.lua @@ -0,0 +1,30 @@ +local test_data={} + +test_data.disk_usage={ + { + available_bytes=239476736, + filesystem="/dev/root", + mount_point="/", + size_bytes=264208384, + used_bytes=19365888, + used_percent=7 + }, + { + available_bytes=12201984, + filesystem="/dev/sda1", + mount_point="/boot", + size_bytes=16498688, + used_bytes=3964928, + used_percent=25 + }, + { + available_bytes=12201984, + filesystem="/dev/sda1", + mount_point="/boot", + size_bytes=16498688, + used_bytes=3964928, + used_percent=25 + } +} + +return test_data diff --git a/openwrt-openwisp-monitoring/tests/test_files/umts_sample.txt b/openwrt-openwisp-monitoring/tests/test_files/umts_sample.txt new file mode 100644 index 0000000..0b04128 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/umts_sample.txt @@ -0,0 +1,38 @@ +{ + "modem": { + "signal": { + "5g": { + "rsrp": "--", + "rsrq": "--", + "snr": "--" + }, + "cdma1x": { + "ecio": "--", + "rssi": "--" + }, + "evdo": { + "ecio": "--", + "io": "--", + "rssi": "--", + "sinr": "--" + }, + "gsm": { + "rssi": "--" + }, + "lte": { + "rsrp": "--", + "rsrq": "--", + "rssi": "--", + "snr": "--" + }, + "refresh": { + "rate": "10" + }, + "umts": { + "ecio": "-3.50", + "rscp": "-96.00", + "rssi": "--" + } + } + } +} diff --git a/openwrt-openwisp-monitoring/tests/test_files/wireless_data.lua b/openwrt-openwisp-monitoring/tests/test_files/wireless_data.lua new file mode 100644 index 0000000..7338ca8 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_files/wireless_data.lua @@ -0,0 +1,456 @@ +local test_data={} + +test_data.wireless_status={ + radio0={ + up=true, + pending=false, + autostart=true, + disabled=false, + retry_setup_failed=false, + config={ + channel="11", + hwmode="11g", + path="1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0", + htmode="HT20", + log_level=0, + disabled=false + }, + interfaces={ + { + section="wifi_mesh0", + ifname="mesh0", + config={ + ifname="mesh0", + encryption="psk2+ccmp", + key="password", + mesh_id="meshid", + mode="mesh", + network={"lan"} + }, + vlans={}, + stations={} + }, + { + section="wifi_wlan0", + ifname="wlan0", + config={ + ifname="wlan0", + encryption="psk2", + key="password", + ssid="OpenWRT", + ieee80211r=true, + ft_over_ds=true, + ft_psk_generate_local=true, + rsn_preauth=true, + mode="ap", + network={"lan"} + }, + vlans={}, + stations={} + } + } + }, + radio1={ + up=true, + pending=false, + autostart=true, + disabled=false, + retry_setup_failed=false, + config={ + hwmode="11a", + path="1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0", + htmode="VHT80", + channel="40", + log_level=0, + disabled=false + }, + interfaces={ + { + section="wifi_mesh1", + ifname="mesh1", + config={ + ifname="mesh1", + encryption="psk2+ccmp", + key="password", + mesh_id="meshID", + mode="mesh", + network={"lan"} + }, + vlans={}, + stations={} + }, + { + section="wifi_wlan1", + ifname="wlan1", + config={ + ifname="wlan1", + encryption="psk2", + key="password", + ssid="ssid", + ieee80211r=true, + ft_over_ds=true, + ft_psk_generate_local=true, + rsn_preauth=true, + mode="ap", + network={"lan"} + }, + vlans={}, + stations={} + } + } + } +} + +test_data.wlan0_clients={} + +test_data.wlan1_clients={ + ["20:a6:0c:b2:da:10"]={ + aid=2, + assoc=true, + auth=true, + authorized=true, + ht=true, + mfp=false, + preauth=false, + rrm={ 0, 0, 0, 0, 0 }, + vht=true, + wds=false, + wmm=true, + wps=false + }, + ["98:3b:8f:98:b1:fb"]={ + aid=1, + assoc=true, + auth=true, + authorized=true, + ht=true, + mfp=false, + preauth=false, + rrm={ 0, 0, 0, 0, 0 }, + vht=true, + wds=false, + wmm=true, + wps=false + } +} + +test_data.wlan0_iwinfo={ + phy="phy0", + ssid="OpenWRT", + mode="Client", + channel=13, + txpower=20, + country="00", + noise=0, + frequency=2472, + signal=-62 +} + +test_data.wlan1_iwinfo={ + phy="phy1", + ssid="ssid", + mode="Master", + channel=13, + txpower=20, + country="00", + noise=0, + frequency=5180, + signal=-33 +} + +test_data.mesh0_iwinfo={ + phy="phy0", + ssid="meshID", + bssid="00:00:00:00:00:00", + country="00", + mode="Mesh Point", + channel=11, + frequency=2462, + frequency_offset=0, + txpower=20, + txpower_offset=0, + quality=43, + quality_max=70, + signal=-67, + noise=0, + bitrate=6500, + encryption={ + enabled=true, + wpa={3}, + authentication={"sae"}, + ciphers={"ccmp"} + }, + htmodes={ + "HT20", + "HT40" + }, + hwmodes={ + "b", + "g", + "n" + }, + hwmode="n", + htmode="HT20", + hardware={ + id={ + 5315, + 30211, + 5315, + 30211 + }, + name="MediaTek MT7603E" + } +} + +test_data.mesh1_iwinfo={ + phy="phy1", + ssid="meshID", + bssid="00:00:00:00:00:00", + country="00", + mode="Mesh Point", + channel=40, + frequency=5200, + frequency_offset=0, + txpower=20, + txpower_offset=0, + quality=34, + quality_max=70, + signal=-76, + noise=-87, + bitrate=195100, + encryption={ + enabled=true, + wpa={3}, + authentication={"sae"}, + ciphers={"ccmp"} + }, + htmodes={ + "HT20", + "HT40", + "VHT20", + "VHT40", + "VHT80", + "VHT80+80", + "VHT160" + }, + hwmodes={ + "ac", + "n" + }, + hwmode="ac", + htmode="VHT80", + hardware={ + id={ + 5315, + 30229, + 30229, + 5315 + }, + name="MediaTek MT7615E" + } +} + +test_data.mesh0_clients={ + results={ + { + mac="00:00:00:00:00:00", + signal=-76, + signal_avg=-76, + noise=-87, + inactive=0, + connected_time=314439, + thr=148687, + authorized=true, + authenticated=true, + preamble="long", + wme=true, + mfp=true, + tdls=false, + ["mesh llid"]=0, + ["mesh plid"]=0, + ["mesh plink"]="ESTAB", + ["mesh local PS"]="ACTIVE", + ["mesh peer PS"]="ACTIVE", + ["mesh non-peer PS"]="ACTIVE", + rx={ + drop_misc=610279, + packets=40424675, + bytes=280218466, + ht=false, + vht=true, + mhz=80, + rate=195000, + mcs=1, + nss=3, + short_gi=true + }, + tx={ + failed=2377, + retries=11358818, + packets=50325775, + bytes=124429140, + ht=false, + vht=true, + mhz=80, + rate=195000, + mcs=1, + nss=3, + short_gi=true + } + } + } +} + +test_data.mesh1_clients={ + results={ + { + mac="00:00:00:00:00:00", + signal=-67, + signal_avg=-65, + noise=0, + inactive=6996, + connected_time=314507, + thr=4500, + authorized=true, + authenticated=true, + preamble="long", + wme=true, + mfp=true, + tdls=false, + ["mesh llid"]=0, + ["mesh plid"]=0, + ["mesh plink"]="ESTAB", + ["mesh local PS"]="ACTIVE", + ["mesh peer PS"]="ACTIVE", + ["mesh non-peer PS"]="ACTIVE", + rx={ + drop_misc=585666, + packets=5533127, + bytes=445412093, + ht=true, + vht=false, + mhz=20, + rate=6500, + mcs=0, + ["40mhz"]=false, + short_gi=false + }, + tx={ + failed=0, + retries=5, + packets=12, + bytes=1173, + ht=true, + vht=false, + mhz=20, + rate=6500, + mcs=0, + ["40mhz"]=false, + short_gi=false + } + } + } +} + +test_data.parsed_clients={ + { + aid=1, + assoc=true, + auth=true, + authorized=true, + ht=true, + mac="98:3b:8f:98:b1:fb", + mfp=false, + preauth=false, + rrm={0, 0, 0, 0, 0}, + vht=true, + wds=false, + wmm=true, + wps=false + }, + { + aid=2, + assoc=true, + auth=true, + authorized=true, + ht=true, + mac="20:a6:0c:b2:da:10", + mfp=false, + preauth=false, + rrm={0, 0, 0, 0, 0}, + vht=true, + wds=false, + wmm=true, + wps=false + } +} + +test_data.mesh0_parsed_clients={ + { + auth=true, + authorized=true, + ht=false, + mac="00:00:00:00:00:00", + mfp=true, + noise=-87, + signal=-76, + vht=true, + wmm=true + } +} + +test_data.mesh1_parsed_clients={ + { + auth=true, + authorized=true, + ht=true, + mac="00:00:00:00:00:00", + mfp=true, + noise=0, + signal=-67, + vht=false, + wmm=true + } +} + +test_data.wlan0_interface={ + mac="00:00:00:00:00:00", + mtu=1500, + multicast=true, + name="wlan0", + txqueuelen=1000, + type="wireless", + up=true, + wireless={ + channel=13, + country="00", + frequency=2472, + mode="station", + noise=0, + signal=-62, + ssid="OpenWRT", + tx_power=20 + } +} + +test_data.wlan1_interface={ + mac="00:00:00:00:00:00", + mtu=1500, + multicast=true, + name="wlan1", + txqueuelen=1000, + type="wireless", + up=true, + wireless={ + channel=13, + country="00", + frequency=5180, + mode="access_point", + noise=0, + signal=-33, + ssid="ssid", + tx_power=20 + } +} + +return test_data diff --git a/openwrt-openwisp-monitoring/tests/test_interfaces.lua b/openwrt-openwisp-monitoring/tests/test_interfaces.lua new file mode 100644 index 0000000..f52bdf2 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_interfaces.lua @@ -0,0 +1,173 @@ +package.path=package.path .. ";../files/lib/openwisp/?.lua" + +local luaunit=require('luaunit') + +local address_data=require('test_files/address_data') +local interface_data=require('test_files/interface_data') + +TestInterface={ + setUp=function() + local env=require('main_env') + package.loaded.uci=env.uci + package.loaded.ubus=env.ubus + package.loaded.io=env.io + package.loaded.nixio={ + getifaddrs=function() + return require('test_files/nixio_data') + end + } + end, + tearDown=function() + end +} + +TestNetJSON={ + setUp=function() + local test_file_dir='./test_files/' + package.loaded.io={ + popen=function(arg) + if arg=='cat /proc/loadavg' then + local f=assert(io.tmpfile()) + f:write('0.37 0.95 1.23 2/873 56899\n') + f:seek('set',0) + return f + else + local modem='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb2/2-1' + if arg=='mmcli --output-json -m '.. modem then + return io.open(test_file_dir .. 'modem_data.txt') + elseif arg=='mmcli --output-json -m '..modem..' --signal-get' then + return io.open(test_file_dir .. 'lte_sample.txt') + end + end + local f=assert(io.tmpfile()) + f:write('') + f:seek('set',0) + return f + end, + open=function(arg) + return nil + end, + write=function(...) + return nil + end + } + package.loaded.uci={ + cursor=function() + return { + get_all=function(...) + return nil + end, + get=function(...) + local arg={...} + if arg[1]=='network' and arg[3]=='stp' then + return '1' + elseif arg[1]=='network' and arg[3]=='device' then + return '/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb2/2-1' + end + return nil + end + } + end + } + + package.loaded.ubus={ + connect=function() + return { + call=function(...) + local arg={...} + if arg[2]=='system' and arg[3]=='board' then + return {hostname="08-00-27-56-92-F5"} + elseif arg[2]=='system' and arg[3]=='info' then + return { + memory=nil, + local_time=nil, + uptime=nil, + swap=nil + } + elseif arg[2]=='network.device' and arg[3]=='status' then + return require('test_files/network_data').devices + elseif arg[2]=='network.interface' and arg[3]=='dump' then + local f=require('test_files/interface_data') + return f.interface_data + else + return {} + end + end + } + end + } + package.loaded.nixio={ + getifaddrs=function() + return require('test_files/nixio_data') + end + } + end, + tearDown=function() + end +} + +function TestInterface.test_find_default_gateway() + local interface_functions=require('interfaces') + luaunit.assertEquals(interface_functions.find_default_gateway(address_data.routes), "192.168.0.1") +end + +function TestInterface.test_new_address_array() + local interface_functions=require('interfaces') + luaunit.assertEquals(interface_functions.new_address_array( + address_data.ipv4_address, + address_data.eth2_interface, 'ipv4'), + address_data.address_array) +end + +function TestInterface.test_get_vpn_interfaces() + local interface_functions=require('interfaces') + luaunit.assertEquals(interface_functions.get_vpn_interfaces(), {tun=true}) +end + +function TestInterface.test_get_addresses() + local interface_functions=require('interfaces') + luaunit.assertEquals(interface_functions.get_addresses('random'), interface_data.random_interface_address) + luaunit.assertEquals(interface_functions.get_addresses('eth1'), interface_data.eth1_addresses) + luaunit.assertEquals(interface_functions.get_addresses('eth2'), interface_data.eth2_addresses) + luaunit.assertEquals(interface_functions.get_addresses('br-mng'), interface_data.br_mng_addresses) +end + +function TestInterface.test_get_interface_info() + local interface_functions=require('interfaces') + local interface_info=interface_functions.get_interface_info('br-lan', interface_data.br_lan_interface) + luaunit.assertEquals( + interface_info, {dns_servers={"8.8.8.8", "8.8.4.4"}, stp=true} + ) +end + +function TestInterface.test_specialized_info() + local interface_functions=require('interfaces') + local interface_info=interface_functions.get_interface_info('lan2', interface_data.lan2_interface) + luaunit.assertNotNil(interface_info) + luaunit.assertNotNil(interface_info.specialized) + local specialized_info=interface_info.specialized.mobile + luaunit.assertEquals(specialized_info.connection_status, "connected") + luaunit.assertEquals(specialized_info.manufacturer, "Quectel") + luaunit.assertEquals(specialized_info.model, "EM12-G") + luaunit.assertEquals(specialized_info.power_status, "on") + luaunit.assertNil(specialized_info.signal["5g"]) + luaunit.assertNil(specialized_info.signal["evdo"]) + luaunit.assertNil(specialized_info.signal["gsm"]) + luaunit.assertNil(specialized_info.signal["lte"]) + luaunit.assertNotNil(specialized_info.signal["umts"]) + luaunit.assertEquals(specialized_info.signal.umts.ecio, -3.5) + luaunit.assertEquals(specialized_info.signal.umts.rscp, -96) + luaunit.assertEquals(specialized_info.signal.umts.rssi, nil) +end + +function TestNetJSON.test_netjson_monitoring() + local netjson_file=assert(loadfile('../files/sbin/netjson-monitoring.lua')) + local netjson=netjson_file('*') + luaunit.assertNil(string.find(netjson, '"umts"', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"address":"192.168.1.41"', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"stp":true', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"lte":{"snr":19.2,"rssi":-64,"rsrq":-9,"rsrp":-92}', 1, true)) + luaunit.assertNotNil(string.find(netjson, 'dns_servers":["8.8.8.8","8.8.4.4"]', 1, true)) +end + +os.exit( luaunit.LuaUnit.run() ) diff --git a/openwrt-openwisp-monitoring/tests/test_neighbors.lua b/openwrt-openwisp-monitoring/tests/test_neighbors.lua new file mode 100644 index 0000000..cdf893d --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_neighbors.lua @@ -0,0 +1,70 @@ +package.path=package.path .. ";../files/lib/openwisp/?.lua;../files/sbin/?.lua" + +local luaunit=require('luaunit') + +local neighbor_data=require('test_files/neighbors_data') + +TestNeighbor={ + setUp=function() + local env=require('main_env') + package.loaded.io=env.io + end, + tearDown=function() + end +} + +TestNetJSON={ + setUp=function() + local env=require('basic_env') + package.loaded.uci=env.uci + package.loaded.ubus=env.ubus + end, + tearDown=function() + end +} + +function TestNeighbor.testArpTable() + local neighbor=require('neighbors') + + luaunit.assertEquals(neighbor.parse_arp(), neighbor_data.sample_parse_arp) + + luaunit.assertEquals(neighbor.get_ip_neigh_json(), neighbor_data.sample_ip_neigh) + + luaunit.assertEquals(neighbor.get_ip_neigh(), neighbor_data.sample_ip_neigh) + + luaunit.assertEquals(neighbor.get_neighbors(), neighbor_data.sample_ip_neigh) +end + +function TestNetJSON.test_netjson_monitoring_neighbors() + local test_file_dir='./test_files/' + package.loaded.io={ + popen=function(arg) + local f=assert(io.tmpfile()) + if arg=='cat /proc/loadavg' then + f:write('0.37 0.95 1.23 2/873 56899\n') + elseif arg=='ip -json neigh 2> /dev/null' then + f:write("Not Valid JSoN") + elseif arg=='ip neigh 2> /dev/null' then + return io.open(test_file_dir .. 'ip_neigh.txt') + else + f:write('') + end + f:seek('set',0) + return f + end, + open=function(arg) + return nil + end, + write=function(...) + return nil + end + } + local netjson=require('netjson-monitoring') + luaunit.assertNotNil(test_file_dir .. 'ip_neigh.txt') + luaunit.assertNotNil(string.find(netjson, '"mac":"bc:0f:9a:17:5a:5c"')) + luaunit.assertNotNil(string.find(netjson, '"ip":"fe80::bfca:28ed:f368:6cbc"')) + luaunit.assertNotNil(string.find(netjson, '"interface":"eth1"')) + +end + +os.exit( luaunit.LuaUnit.run() ) diff --git a/openwrt-openwisp-monitoring/tests/test_resources.lua b/openwrt-openwisp-monitoring/tests/test_resources.lua new file mode 100644 index 0000000..6e53612 --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_resources.lua @@ -0,0 +1,73 @@ +package.path=package.path .. ";../files/lib/openwisp/?.lua;../files/sbin/?.lua" + +local luaunit=require('luaunit') + +local resources_data=require('test_files/resources_data') + +TestResources={ + setUp=function() + local env=require('main_env') + package.loaded.io=env.io + end, + tearDown=function() + end +} + +TestNetJSON={ + setUp=function() + local env=require('basic_env') + package.loaded.uci=env.uci + package.loaded.ubus=env.ubus + end, + tearDown=function() + end +} + +function TestResources.test_disk_usage() + local resources=require('resources') + + luaunit.assertEquals(resources.parse_disk_usage(), resources_data.disk_usage) +end + +function TestResources.test_get_cpus() + local resources=require('resources') + + luaunit.assertEquals(resources.get_cpus(), 8) +end + +function TestNetJSON.test_resources() + local test_file_dir='./test_files/' + package.loaded.io={ + popen=function(arg) + local f=assert(io.tmpfile()) + if arg=='cat /proc/loadavg' then + f:write('0.37 0.95 1.23 2/873 56899\n') + f:seek('set',0) + return f + elseif arg=='df' then + return io.open(test_file_dir .. 'disk_usage.txt') + elseif arg=='cat /proc/cpuinfo | grep -c processor' then + f:write('8') + f:seek('set',0) + return f + else + f:write('') + end + f:seek('set',0) + return f + end, + open=function(arg) + return nil + end, + write=function(...) + return nil + end + } + local netjson=require('netjson-monitoring') + luaunit.assertNotNil(test_file_dir .. 'disk_usage.txt') + luaunit.assertNotNil(string.find(netjson, '"cpus":8')) + luaunit.assertNotNil(string.find(netjson, '"filesystem":"\\/dev\\/root"')) + luaunit.assertNotNil(string.find(netjson, '"used_percent":25')) +end + +os.exit( luaunit.LuaUnit.run() ) diff --git a/openwrt-openwisp-monitoring/tests/test_utils.lua b/openwrt-openwisp-monitoring/tests/test_utils.lua new file mode 100644 index 0000000..868b08f --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_utils.lua @@ -0,0 +1,64 @@ +package.path=package.path .. ";../files/lib/openwisp/?.lua" + +local luaunit=require('luaunit') + +local utils=require('monitoring_utils') + +TestUtils={} + +function TestUtils.testSplitFunction() + -- When pattern is present + luaunit.assertEquals(utils.split("OpenWISP","n"), {"Ope", "WISP"}) + luaunit.assertEquals(utils.split("OpenWISP","WISP"), {"Open"}) + + -- When pattern is not available + luaunit.assertEquals(utils.split("OpenWISP","a"), {"OpenWISP"}) +end + +function TestUtils.testHasValue() + -- When value is present + luaunit.assertEquals(utils.has_value({2,4,5},4), true) + luaunit.assertEquals(utils.has_value({1,2,3,7,9},9), true) + + -- When value is not present + luaunit.assertEquals(utils.has_value({2,4,5},3), false) + luaunit.assertEquals(utils.has_value({1,2,3,7,9},8), false) + +end + +function TestUtils.testStartsWith() + -- When string starts with the substring given + luaunit.assertEquals(utils.starts_with("OpenWISP", "Open"), true) + luaunit.assertEquals(utils.starts_with("NetJSON", "Net"), true) + + -- when string doesn't starts with the substring given + luaunit.assertEquals(utils.starts_with("OpenWISP", "Ov"), false) +end + +function TestUtils.testTableEmpty() + -- When table is empty + luaunit.assertEquals(utils.is_table_empty(nil), true) + luaunit.assertEquals(utils.is_table_empty({}), true) + + -- When table is not empty + luaunit.assertEquals(utils.is_table_empty({1,2,3,4}), false) + luaunit.assertEquals(utils.is_table_empty({"wireless", "wired", "system"}), false) +end + +function TestUtils.testArrayConcat() + luaunit.assertEquals(utils.array_concat({4,5,6},{1,2,3}), {1, 2, 3, 4, 5, 6}) + luaunit.assertEquals(utils.array_concat({"wireless"},{"wired"}), {"wired", "wireless"}) + luaunit.assertEquals(utils.array_concat({"system", "network"},{"firewall"}), {"firewall", "system", "network"}) +end + +function TestUtils.testDictMerge() + luaunit.assertEquals(utils.dict_merge({['1']='OpenWISP'},{['3']='NetJSON'}), {["1"]="OpenWISP", ["3"]="NetJSON"}) + luaunit.assertEquals(utils.dict_merge({['1']='OpenWISP'},{['1']='NetJSON'}), {["1"]="OpenWISP"}) +end + +function TestUtils.testIsExcluded() + luaunit.assertTrue(utils.is_excluded('lo')) + luaunit.assertFalse(utils.is_excluded('wlo1')) +end + +os.exit(luaunit.LuaUnit.run()) diff --git a/openwrt-openwisp-monitoring/tests/test_wifi.lua b/openwrt-openwisp-monitoring/tests/test_wifi.lua new file mode 100644 index 0000000..1f093cf --- /dev/null +++ b/openwrt-openwisp-monitoring/tests/test_wifi.lua @@ -0,0 +1,142 @@ +package.path=package.path .. ";../files/lib/openwisp/?.lua;../files/sbin/?.lua" + +local wifi_data=require('test_files/wireless_data') +local luaunit=require('luaunit') +local wifi_functions=require('wifi') + +local function string_count(base, pattern) + return select(2, string.gsub(base, pattern, "")) +end + +TestWifi={ + setUp=function() + end, + tearDown=function() + end +} + +TestNetJSON={ + setUp=function() + local env=require('basic_env') + package.loaded.io=env.io + package.loaded.uci=env.uci + package.loaded.ubus={ + connect=function() + return { + call=function(...) + local arg={...} + if arg[2]=='system' and arg[3]=='board' then + return {hostname="08-00-27-56-92-F5"} + elseif arg[2]=='system' and arg[3]=='info' then + return { + memory=nil, + local_time=nil, + uptime=nil, + swap=nil + } + elseif arg[2]=='network.device' and arg[3]=='status' then + return require('test_files/network_data').wireless + elseif arg[2]=='network.wireless' and arg[3]=='status' then + return wifi_data.wireless_status + elseif arg[2]=='network.interface' and arg[3]=='dump' then + local f=require('test_files/interface_data') + return f.interface_data + elseif arg[2]=='iwinfo' and arg[3]=='info' then + if arg[4].device=="wlan0" then + return wifi_data.wlan0_iwinfo + elseif arg[4].device=="wlan1" then + return wifi_data.wlan1_iwinfo + elseif arg[4].device=="mesh0" then + return wifi_data.mesh0_iwinfo + elseif arg[4].device=="mesh1" then + return wifi_data.mesh1_iwinfo + end + elseif arg[2]=='iwinfo' and arg[3]=='assoclist' then + if arg[4].device=="mesh0" then + return wifi_data.mesh0_clients + elseif arg[4].device=="mesh1" then + return wifi_data.mesh1_clients + end + else + return {} + end + end + } + end + } + end, + tearDown=function() + end +} + +function TestWifi.test_parse_hostapd_clients() + luaunit.assertEquals(wifi_functions.parse_hostapd_clients(wifi_data.wlan1_clients), wifi_data.parsed_clients) + luaunit.assertEquals(wifi_functions.parse_hostapd_clients(wifi_data.wlan0_clients), {}) +end + +function TestWifi.test_parse_iwinfo_clients() + luaunit.assertEquals( + wifi_functions.parse_iwinfo_clients(wifi_data.mesh0_clients.results), wifi_data.mesh0_parsed_clients + ) + luaunit.assertEquals( + wifi_functions.parse_iwinfo_clients(wifi_data.mesh1_clients.results), wifi_data.mesh1_parsed_clients + ) +end + +function TestWifi.test_netjson_clients() + -- testing hostapd clients + luaunit.assertEquals(wifi_functions.netjson_clients(wifi_data.wlan1_clients, false), wifi_data.parsed_clients) + luaunit.assertEquals(wifi_functions.netjson_clients(wifi_data.wlan0_clients, false), {}) + -- testing iwinfo clients + luaunit.assertEquals( + wifi_functions.netjson_clients(wifi_data.mesh0_clients.results, true), wifi_data.mesh0_parsed_clients + ) + luaunit.assertEquals( + wifi_functions.netjson_clients(wifi_data.mesh1_clients.results, true), wifi_data.mesh1_parsed_clients + ) +end + +function TestWifi.test_needs_inversion() + luaunit.assertFalse(wifi_functions.needs_inversion(wifi_data.wlan0_interface)) + luaunit.assertTrue(wifi_functions.needs_inversion(wifi_data.wlan1_interface)) +end + +function TestWifi.test_invert_rx_tx() + local network_data=require('test_files/network_data') + luaunit.assertNotNil(network_data) + local interface=wifi_functions.invert_rx_tx(network_data.wlan1_stats) + luaunit.assertEquals(interface.rx_bytes, 531596854) + luaunit.assertEquals(interface.tx_bytes, 0) + luaunit.assertEquals(interface.rx_packets, 2367515) + luaunit.assertEquals(interface.tx_packets, 0) +end + +function TestNetJSON.test_wifi_interfaces() + local netjson=require('netjson-monitoring') + luaunit.assertNotNil(string.find(netjson, '"signal":-67', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"signal":-76', 1, true)) + luaunit.assertEquals(string_count(netjson, '"ssid":"meshID"'), 2) + luaunit.assertEquals(string_count(netjson, '"tx_power":20'), 4) + luaunit.assertEquals(string_count(netjson, '"vht":true'), 1) + luaunit.assertEquals(string_count(netjson, '"vht":false'), 1) + luaunit.assertEquals(string_count(netjson, '"tx_power":20'), 4) + luaunit.assertEquals(string_count(netjson, '"frequency":5200'), 1) + luaunit.assertEquals(string_count(netjson, '"mode":"access_point"'), 1) +end + +function TestNetJSON.test_wifi_interfaces_stats_include() + local netjson_file=assert(loadfile('../files/sbin/netjson-monitoring.lua')) + local netjson=netjson_file('wlan0 wlan1 mesh1') + luaunit.assertNotNil(string.find(netjson, '"channel":40', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"mode":"802.11s"', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"rx_packets":198', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"rx_packets":2367515', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"rx_bytes":25967', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"tx_bytes":531641723', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"tx_bytes":151599685066', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"tx_packets":2367747', 1, true)) + luaunit.assertNotNil(string.find(netjson, '"tx_packets":2367747', 1, true)) + luaunit.assertEquals(string_count(netjson, '"tx_errors":0'), 3) +end + +os.exit( luaunit.LuaUnit.run() ) diff --git a/runtests b/runtests new file mode 100755 index 0000000..079339f --- /dev/null +++ b/runtests @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +cd openwrt-openwisp-monitoring/tests/ +# run tests +lua -lluacov test_dhcp.lua -v +lua -lluacov test_interfaces.lua -v +lua -lluacov test_utils.lua -v +lua -lluacov test_neighbors.lua -v +lua -lluacov test_resources.lua -v +lua -lluacov test_wifi.lua -v