From 2675672d145804b5b1666e4b5c5226a2d176bcbd Mon Sep 17 00:00:00 2001 From: purhan Date: Sun, 18 Apr 2021 17:28:34 +0530 Subject: [PATCH 01/26] [qa] Add mocks in base SSH unit tests --- requirements.txt | 3 +- tests/ssh/base.py | 51 +++++++++++++++++++++------------ tests/static/__init__.py | 14 +++++++++ tests/static/test-base-ssh.json | 5 ++++ 4 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 tests/static/__init__.py create mode 100644 tests/static/test-base-ssh.json diff --git a/requirements.txt b/requirements.txt index b187fb1..ad1ceca 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,5 @@ pysnmp ipaddress cached-property argparse -mechanize \ No newline at end of file +mechanize +mock \ No newline at end of file diff --git a/tests/ssh/base.py b/tests/ssh/base.py index 6fb59c7..36ffa30 100644 --- a/tests/ssh/base.py +++ b/tests/ssh/base.py @@ -1,40 +1,50 @@ import unittest +import mock from netengine.backends.ssh import SSH from netengine.exceptions import NetEngineError from ..settings import settings +from ..static import MockOutputMixin __all__ = ['TestSSH'] -class TestSSH(unittest.TestCase): - - def setUp(self): - self.host = settings['base-ssh']['host'] - self.username = settings['base-ssh']['username'] - self.password = settings['base-ssh'].get('password', '') - self.port = settings['base-ssh'].get('port', 22) - +class TestSSH(unittest.TestCase, MockOutputMixin): + @mock.patch('paramiko.SSHClient.connect') + def setUp(self, mocked_connect): + self.host = 'test-host.com' + self.username = 'test-user' + self.password = 'test-password' + self.port = 22 self.device = SSH(self.host, self.username, self.password, self.port) self.assertTrue(self.device.__netengine__) self.device.connect() - - def test_validate_negative_result(self): - wrong = SSH('10.40.0.254', 'root', 'pwd') - self.assertRaises(NetEngineError, wrong.validate) - - def test_validate_positive_result(self): + mocked_connect.assert_called_once_with( + self.host, username=self.username, password=self.password, port=self.port + ) + ssh_mock_data = self._load_mock_json('/test-base-ssh.json') + self.exec_command_patcher = mock.patch( + 'netengine.backends.ssh.base.SSH.run', + side_effect=lambda x: self._get_mocked_value(oid=x, data=ssh_mock_data), + ) + self.exec_command_patcher.start() + + @mock.patch('paramiko.SSHClient.close') + @mock.patch('paramiko.SSHClient.connect') + def test_validate_positive_result(self, mocked_connect, mocked_close): self.device.disconnect() self.device.validate() - + mocked_connect.assert_called_once() + mocked_close.assert_called() + def test_olsr(self): print(self.device.olsr) - + def test_not_implemented_methods(self): device = self.device - + with self.assertRaises(NotImplementedError): device.os with self.assertRaises(NotImplementedError): @@ -59,12 +69,12 @@ def test_not_implemented_methods(self): device.wireless_dbm with self.assertRaises(NotImplementedError): device.wireless_noise - + device.disconnect() def test_iwconfig(self): self.assertIs(type(self.device.iwconfig()), list) - + def test_ifconfig(self): self.assertIs(type(self.device.ifconfig()), list) @@ -73,3 +83,6 @@ def test_get_interface_mtu(self): # ensure MTU for first 2 interfaces is not empty self.assertNotEqual(interfaces[0]['mtu'], '') self.assertNotEqual(interfaces[1]['mtu'], '') + + def tearDown(self): + self.exec_command_patcher.stop() diff --git a/tests/static/__init__.py b/tests/static/__init__.py new file mode 100644 index 0000000..88c295f --- /dev/null +++ b/tests/static/__init__.py @@ -0,0 +1,14 @@ +import json +import os + +class MockOutputMixin(object): + @staticmethod + def _load_mock_json(file): + base_dir = os.path.dirname(os.path.abspath(__file__)) + with open(base_dir + file) as f: + data = json.load(f) + return data + + @staticmethod + def _get_mocked_value(oid, data, *args, **kwargs): + return data[oid] diff --git a/tests/static/test-base-ssh.json b/tests/static/test-base-ssh.json new file mode 100644 index 0000000..f3ffab5 --- /dev/null +++ b/tests/static/test-base-ssh.json @@ -0,0 +1,5 @@ +{ + "ifconfig": "br-lan Link encap:Ethernet HWaddr 08:00:27:EA:D5:D7 \n inet addr:192.168.56.2 Bcast:192.168.56.255 Mask:255.255.255.0\n inet6 addr: fd13:3fc2:e81f::1/60 Scope:Global\n inet6 addr: fe80::a00:27ff:feea:d5d7/64 Scope:Link\n UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1\n RX packets:50 errors:0 dropped:0 overruns:0 frame:0\n TX packets:43 errors:0 dropped:0 overruns:0 carrier:0\n collisions:0 txqueuelen:1000 \n RX bytes:7379 (7.2 KiB) TX bytes:6912 (6.7 KiB)\n\neth0 Link encap:Ethernet HWaddr 08:00:27:EA:D5:D7 \n UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1\n RX packets:51 errors:0 dropped:0 overruns:0 frame:0\n TX packets:43 errors:0 dropped:0 overruns:0 carrier:0\n collisions:0 txqueuelen:1000 \n RX bytes:8145 (7.9 KiB) TX bytes:6930 (6.7 KiB)\n\neth1 Link encap:Ethernet HWaddr 08:00:27:D9:10:14 \n inet addr:10.0.2.4 Bcast:10.0.2.255 Mask:255.255.255.0\n inet6 addr: fe80::a00:27ff:fed9:1014/64 Scope:Link\n UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1\n RX packets:19 errors:0 dropped:0 overruns:0 frame:0\n TX packets:31 errors:0 dropped:0 overruns:0 carrier:0\n collisions:0 txqueuelen:1000 \n RX bytes:2984 (2.9 KiB) TX bytes:3524 (3.4 KiB)\n\nlo Link encap:Local Loopback \n inet addr:127.0.0.1 Mask:255.0.0.0\n inet6 addr: ::1/128 Scope:Host\n UP LOOPBACK RUNNING MTU:65536 Metric:1\n RX packets:20 errors:0 dropped:0 overruns:0 frame:0\n TX packets:20 errors:0 dropped:0 overruns:0 carrier:0\n collisions:0 txqueuelen:1000 \n RX bytes:1728 (1.6 KiB) TX bytes:1728 (1.6 KiB)", + "olsrd -v": "*** olsr.org - 0.9.7-git_0000000-hash_0e6c6b8511b8405eee05046434d38c1b ***\n http://www.olsr.org\n\nTerminated", + "iwconfig": "lo no wireless extensions.\n\nenp1s0 no wireless extensions.\n\nwlp2s0 IEEE 802.11 ESSID:\"MY ROUTER\" \n Mode:Managed Frequency:2.457 GHz Access Point: 83:A8:1C:62:A3:56 \n Bit Rate=150 Mb/s Tx-Power=20 dBm \n Retry short limit:7 RTS thr:off Fragment thr:off\n Power Management:off\n Link Quality=62/70 Signal level=-48 dBm \n Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0\n Tx excessive retries:1 Invalid misc:348 Missed beacon:0\n" +} \ No newline at end of file From 68fa3ce305e9dae1b67ed1f324f78387a033d00a Mon Sep 17 00:00:00 2001 From: purhan Date: Sun, 18 Apr 2021 12:04:17 +0530 Subject: [PATCH 02/26] [qa] Add mocks in OpenWRT SSH unit tests --- requirements.txt | 3 ++- tests/ssh/openwrt.py | 43 ++++++++++++++++++------------ tests/static/__init__.py | 14 ++++++++++ tests/static/test-openwrt-ssh.json | 15 +++++++++++ 4 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 tests/static/__init__.py create mode 100644 tests/static/test-openwrt-ssh.json diff --git a/requirements.txt b/requirements.txt index b187fb1..8614fef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,5 @@ pysnmp ipaddress cached-property argparse -mechanize \ No newline at end of file +mechanize +mock diff --git a/tests/ssh/openwrt.py b/tests/ssh/openwrt.py index 64de271..6901677 100644 --- a/tests/ssh/openwrt.py +++ b/tests/ssh/openwrt.py @@ -1,58 +1,67 @@ import unittest +import mock from netengine.backends.ssh import OpenWRT from ..settings import settings +from ..static import MockOutputMixin __all__ = ['TestSSHOpenWRT'] -class TestSSHOpenWRT(unittest.TestCase): - - def setUp(self): - self.host = settings['openwrt-ssh']['host'] - self.username = settings['openwrt-ssh']['username'] - self.password = settings['openwrt-ssh']['password'] - self.port = settings['openwrt-ssh'].get('port', 22) - - self.device = OpenWRT(self.host, self.username, self.password, self.port) +class TestSSHOpenWRT(unittest.TestCase, MockOutputMixin): + + @mock.patch('paramiko.SSHClient.connect') + def setUp(self, mocked_connect): + self.device = OpenWRT('test-host.com', 'test-user', 'test-pass', 22) self.device.connect() - + mocked_connect.assert_called_once() + ssh_mock_data = self._load_mock_json('/test-openwrt-ssh.json') + self.ssh_patcher = mock.patch( + 'netengine.backends.ssh.openwrt.SSH.run', + side_effect=lambda x: self._get_mocked_value( + oid=x, data=ssh_mock_data + ), + ) + self.ssh_patcher.start() + def test_properties(self): device = self.device - device.os device.name device.olsr device.disconnect() - + def test_wireless_mode(self): self.assertTrue(self.device.wireless_mode in ['ap', 'sta']) - + def test_RAM_total(self): self.assertTrue(type(self.device.RAM_total) == int) def test_uptime(self): self.assertTrue(type(self.device.uptime) == int) - + def test_interfaces_to_dict(self): self.assertTrue(type(self.device.interfaces_to_dict) == dict) def test_uptime_tuple(self): self.assertTrue(type(self.device.uptime_tuple) == tuple) - + def test_to_dict(self): self.assertTrue(isinstance(self.device.to_dict(), dict)) def test_filter_radio_interfaces(self): self.assertTrue(isinstance(self.device._filter_radio_interfaces(), dict)) - + def test_filter_radio(self): self.assertTrue(isinstance(self.device._filter_radio(), dict)) - + def test_manufacturer(self): self.assertTrue(type(self.device.manufacturer) == str) def test_filter_routing_protocols(self): self.assertTrue(isinstance(self.device._filter_routing_protocols(), list)) + + def tearDown(self): + self.ssh_patcher.stop() diff --git a/tests/static/__init__.py b/tests/static/__init__.py new file mode 100644 index 0000000..88c295f --- /dev/null +++ b/tests/static/__init__.py @@ -0,0 +1,14 @@ +import json +import os + +class MockOutputMixin(object): + @staticmethod + def _load_mock_json(file): + base_dir = os.path.dirname(os.path.abspath(__file__)) + with open(base_dir + file) as f: + data = json.load(f) + return data + + @staticmethod + def _get_mocked_value(oid, data, *args, **kwargs): + return data[oid] diff --git a/tests/static/test-openwrt-ssh.json b/tests/static/test-openwrt-ssh.json new file mode 100644 index 0000000..f6c14e5 --- /dev/null +++ b/tests/static/test-openwrt-ssh.json @@ -0,0 +1,15 @@ +{ + "ubus call network.interface.loopback status": "{\n\t\"up\": true,\n\t\"pending\": false,\n\t\"available\": true,\n\t\"autostart\": true,\n\t\"dynamic\": false,\n\t\"uptime\": 1797,\n\t\"l3_device\": \"lo\",\n\t\"proto\": \"static\",\n\t\"device\": \"lo\",\n\t\"updated\": [\n\t\t\"addresses\"\n\t],\n\t\"metric\": 0,\n\t\"dns_metric\": 0,\n\t\"delegation\": true,\n\t\"ipv4-address\": [\n\t\t{\n\t\t\t\"address\": \"127.0.0.1\",\n\t\t\t\"mask\": 8\n\t\t}\n\t],\n\t\"ipv6-address\": [\n\t\t\n\t],\n\t\"ipv6-prefix\": [\n\t\t\n\t],\n\t\"ipv6-prefix-assignment\": [\n\t\t\n\t],\n\t\"route\": [\n\t\t\n\t],\n\t\"dns-server\": [\n\t\t\n\t],\n\t\"dns-search\": [\n\t\t\n\t],\n\t\"neighbors\": [\n\t\t\n\t],\n\t\"inactive\": {\n\t\t\"ipv4-address\": [\n\t\t\t\n\t\t],\n\t\t\"ipv6-address\": [\n\t\t\t\n\t\t],\n\t\t\"route\": [\n\t\t\t\n\t\t],\n\t\t\"dns-server\": [\n\t\t\t\n\t\t],\n\t\t\"dns-search\": [\n\t\t\t\n\t\t],\n\t\t\"neighbors\": [\n\t\t\t\n\t\t]\n\t},\n\t\"data\": {\n\t\t\n\t}\n}\n", + "cat /etc/openwrt_release": "DISTRIB_ID='OpenWrt'\nDISTRIB_RELEASE='19.07.7'\nDISTRIB_REVISION='r11306-c4a6851c72'\nDISTRIB_TARGET='x86/64'\nDISTRIB_ARCH='x86_64'\nDISTRIB_DESCRIPTION='OpenWrt 19.07.7 r11306-c4a6851c72'\nDISTRIB_TAINTS=''", + "uname -a": "Linux OpenWrt 4.14.221 #0 SMP Mon Feb 15 15:22:37 2021 x86_64 GNU/Linux\n", + "olsrd -v": "*** olsr.org - 0.9.7-git_0000000-hash_0e6c6b8511b8405eee05046434d38c1b ***\nhttp://www.olsr.org\nTerminated", + "cat /proc/meminfo | grep MemTotal | awk '{print $2}'": "115080", + "iwconfig 2>/dev/null | grep Mode | awk '{print $4}' | awk -F ':' '{print $2}'": "Master", + "ubus list": "dhcp\ndnsmasq\nfile\niwinfo\nlog\nluci\nluci-rpc\nnetwork\nnetwork.device\nnetwork.interface\nnetwork.interface.loopback\nnetwork.interface.mng\nnetwork.interface.wan\nnetwork.rrdns\nnetwork.wireless\nservice\nsession\nsystem\nuci\n", + "iwinfo | grep -i hardware": "168C:002A 0777:E805 [Ubiquiti Bullet M5]", + "cat /proc/uptime": "1805.66 1800.76", + "ubus call network.interface.wan status": "{\n\t\"up\": true,\n\t\"pending\": false,\n\t\"available\": true,\n\t\"autostart\": true,\n\t\"dynamic\": false,\n\t\"uptime\": 1795,\n\t\"l3_device\": \"eth1\",\n\t\"proto\": \"dhcp\",\n\t\"device\": \"eth1\",\n\t\"metric\": 0,\n\t\"dns_metric\": 0,\n\t\"delegation\": true,\n\t\"ipv4-address\": [\n\t\t{\n\t\t\t\"address\": \"10.0.2.4\",\n\t\t\t\"mask\": 24\n\t\t}\n\t],\n\t\"ipv6-address\": [\n\t\t\n\t],\n\t\"ipv6-prefix\": [\n\t\t\n\t],\n\t\"ipv6-prefix-assignment\": [\n\t\t\n\t],\n\t\"route\": [\n\t\t{\n\t\t\t\"target\": \"0.0.0.0\",\n\t\t\t\"mask\": 0,\n\t\t\t\"nexthop\": \"10.0.2.1\",\n\t\t\t\"source\": \"10.0.2.4/32\"\n\t\t}\n\t],\n\t\"dns-server\": [\n\t\t\"10.0.2.1\"\n\t],\n\t\"dns-search\": [\n\t\t\n\t],\n\t\"neighbors\": [\n\t\t\n\t],\n\t\"inactive\": {\n\t\t\"ipv4-address\": [\n\t\t\t\n\t\t],\n\t\t\"ipv6-address\": [\n\t\t\t\n\t\t],\n\t\t\"route\": [\n\t\t\t\n\t\t],\n\t\t\"dns-server\": [\n\t\t\t\n\t\t],\n\t\t\"dns-search\": [\n\t\t\t\n\t\t],\n\t\t\"neighbors\": [\n\t\t\t\n\t\t]\n\t},\n\t\"data\": {\n\t\t\"leasetime\": 600\n\t}\n}\n", + "ubus call network.device status": "{\n\t\"br-lan\": {\n\t\t\"external\": false,\n\t\t\"present\": true,\n\t\t\"type\": \"bridge\",\n\t\t\"up\": true,\n\t\t\"carrier\": true,\n\t\t\"bridge-members\": [\n\t\t\t\"eth0\"\n\t\t],\n\t\t\"mtu\": 1500,\n\t\t\"mtu6\": 1500,\n\t\t\"macaddr\": \"08:00:27:ea:d5:d7\",\n\t\t\"txqueuelen\": 1000,\n\t\t\"ipv6\": true,\n\t\t\"promisc\": false,\n\t\t\"rpfilter\": 0,\n\t\t\"acceptlocal\": false,\n\t\t\"igmpversion\": 0,\n\t\t\"mldversion\": 0,\n\t\t\"neigh4reachabletime\": 30000,\n\t\t\"neigh6reachabletime\": 30000,\n\t\t\"neigh4gcstaletime\": 60,\n\t\t\"neigh6gcstaletime\": 60,\n\t\t\"neigh4locktime\": 100,\n\t\t\"dadtransmits\": 1,\n\t\t\"multicast\": true,\n\t\t\"sendredirects\": true,\n\t\t\"statistics\": {\n\t\t\t\"collisions\": 0,\n\t\t\t\"rx_frame_errors\": 0,\n\t\t\t\"tx_compressed\": 0,\n\t\t\t\"multicast\": 21,\n\t\t\t\"rx_length_errors\": 0,\n\t\t\t\"tx_dropped\": 0,\n\t\t\t\"rx_bytes\": 158016,\n\t\t\t\"rx_missed_errors\": 0,\n\t\t\t\"tx_errors\": 0,\n\t\t\t\"rx_compressed\": 0,\n\t\t\t\"rx_over_errors\": 0,\n\t\t\t\"tx_fifo_errors\": 0,\n\t\t\t\"rx_crc_errors\": 0,\n\t\t\t\"rx_packets\": 1148,\n\t\t\t\"tx_heartbeat_errors\": 0,\n\t\t\t\"rx_dropped\": 0,\n\t\t\t\"tx_aborted_errors\": 0,\n\t\t\t\"tx_packets\": 1134,\n\t\t\t\"rx_errors\": 0,\n\t\t\t\"tx_bytes\": 228238,\n\t\t\t\"tx_window_errors\": 0,\n\t\t\t\"rx_fifo_errors\": 0,\n\t\t\t\"tx_carrier_errors\": 0\n\t\t}\n\t},\n\t\"eth0\": {\n\t\t\"external\": false,\n\t\t\"present\": true,\n\t\t\"type\": \"Network device\",\n\t\t\"up\": true,\n\t\t\"carrier\": true,\n\t\t\"link-advertising\": [\n\t\t\t\"10baseT-H\",\n\t\t\t\"10baseT-F\",\n\t\t\t\"100baseT-H\",\n\t\t\t\"100baseT-F\",\n\t\t\t\"1000baseT-F\"\n\t\t],\n\t\t\"link-partner-advertising\": [\n\t\t\t\n\t\t],\n\t\t\"link-supported\": [\n\t\t\t\"10baseT-H\",\n\t\t\t\"10baseT-F\",\n\t\t\t\"100baseT-H\",\n\t\t\t\"100baseT-F\",\n\t\t\t\"1000baseT-F\"\n\t\t],\n\t\t\"speed\": \"1000F\",\n\t\t\"autoneg\": true,\n\t\t\"mtu\": 1500,\n\t\t\"mtu6\": 1500,\n\t\t\"macaddr\": \"08:00:27:ea:d5:d7\",\n\t\t\"txqueuelen\": 1000,\n\t\t\"ipv6\": false,\n\t\t\"promisc\": false,\n\t\t\"rpfilter\": 0,\n\t\t\"acceptlocal\": false,\n\t\t\"igmpversion\": 0,\n\t\t\"mldversion\": 0,\n\t\t\"neigh4reachabletime\": 30000,\n\t\t\"neigh6reachabletime\": 30000,\n\t\t\"neigh4gcstaletime\": 60,\n\t\t\"neigh6gcstaletime\": 60,\n\t\t\"neigh4locktime\": 100,\n\t\t\"dadtransmits\": 1,\n\t\t\"multicast\": true,\n\t\t\"sendredirects\": true,\n\t\t\"statistics\": {\n\t\t\t\"collisions\": 0,\n\t\t\t\"rx_frame_errors\": 0,\n\t\t\t\"tx_compressed\": 0,\n\t\t\t\"multicast\": 21,\n\t\t\t\"rx_length_errors\": 0,\n\t\t\t\"tx_dropped\": 0,\n\t\t\t\"rx_bytes\": 174148,\n\t\t\t\"rx_missed_errors\": 0,\n\t\t\t\"tx_errors\": 0,\n\t\t\t\"rx_compressed\": 0,\n\t\t\t\"rx_over_errors\": 0,\n\t\t\t\"tx_fifo_errors\": 0,\n\t\t\t\"rx_crc_errors\": 0,\n\t\t\t\"rx_packets\": 1149,\n\t\t\t\"tx_heartbeat_errors\": 0,\n\t\t\t\"rx_dropped\": 0,\n\t\t\t\"tx_aborted_errors\": 0,\n\t\t\t\"tx_packets\": 1164,\n\t\t\t\"rx_errors\": 0,\n\t\t\t\"tx_bytes\": 251356,\n\t\t\t\"tx_window_errors\": 0,\n\t\t\t\"rx_fifo_errors\": 0,\n\t\t\t\"tx_carrier_errors\": 0\n\t\t}\n\t},\n\t\"eth1\": {\n\t\t\"external\": false,\n\t\t\"present\": true,\n\t\t\"type\": \"Network device\",\n\t\t\"up\": true,\n\t\t\"carrier\": true,\n\t\t\"link-advertising\": [\n\t\t\t\"10baseT-H\",\n\t\t\t\"10baseT-F\",\n\t\t\t\"100baseT-H\",\n\t\t\t\"100baseT-F\",\n\t\t\t\"1000baseT-F\"\n\t\t],\n\t\t\"link-partner-advertising\": [\n\t\t\t\n\t\t],\n\t\t\"link-supported\": [\n\t\t\t\"10baseT-H\",\n\t\t\t\"10baseT-F\",\n\t\t\t\"100baseT-H\",\n\t\t\t\"100baseT-F\",\n\t\t\t\"1000baseT-F\"\n\t\t],\n\t\t\"speed\": \"1000F\",\n\t\t\"autoneg\": true,\n\t\t\"mtu\": 1500,\n\t\t\"mtu6\": 1500,\n\t\t\"macaddr\": \"08:00:27:d9:10:14\",\n\t\t\"txqueuelen\": 1000,\n\t\t\"ipv6\": true,\n\t\t\"promisc\": false,\n\t\t\"rpfilter\": 0,\n\t\t\"acceptlocal\": false,\n\t\t\"igmpversion\": 0,\n\t\t\"mldversion\": 0,\n\t\t\"neigh4reachabletime\": 30000,\n\t\t\"neigh6reachabletime\": 30000,\n\t\t\"neigh4gcstaletime\": 60,\n\t\t\"neigh6gcstaletime\": 60,\n\t\t\"neigh4locktime\": 100,\n\t\t\"dadtransmits\": 1,\n\t\t\"multicast\": true,\n\t\t\"sendredirects\": true,\n\t\t\"statistics\": {\n\t\t\t\"collisions\": 0,\n\t\t\t\"rx_frame_errors\": 0,\n\t\t\t\"tx_compressed\": 0,\n\t\t\t\"multicast\": 0,\n\t\t\t\"rx_length_errors\": 0,\n\t\t\t\"tx_dropped\": 0,\n\t\t\t\"rx_bytes\": 16434,\n\t\t\t\"rx_missed_errors\": 0,\n\t\t\t\"tx_errors\": 0,\n\t\t\t\"rx_compressed\": 0,\n\t\t\t\"rx_over_errors\": 0,\n\t\t\t\"tx_fifo_errors\": 0,\n\t\t\t\"rx_crc_errors\": 0,\n\t\t\t\"rx_packets\": 151,\n\t\t\t\"tx_heartbeat_errors\": 0,\n\t\t\t\"rx_dropped\": 0,\n\t\t\t\"tx_aborted_errors\": 0,\n\t\t\t\"tx_packets\": 159,\n\t\t\t\"rx_errors\": 0,\n\t\t\t\"tx_bytes\": 15274,\n\t\t\t\"tx_window_errors\": 0,\n\t\t\t\"rx_fifo_errors\": 0,\n\t\t\t\"tx_carrier_errors\": 0\n\t\t}\n\t},\n\t\"lo\": {\n\t\t\"external\": false,\n\t\t\"present\": true,\n\t\t\"type\": \"Network device\",\n\t\t\"up\": true,\n\t\t\"carrier\": true,\n\t\t\"mtu\": 65536,\n\t\t\"mtu6\": 65536,\n\t\t\"macaddr\": \"00:00:00:00:00:00\",\n\t\t\"txqueuelen\": 1000,\n\t\t\"ipv6\": true,\n\t\t\"promisc\": false,\n\t\t\"rpfilter\": 0,\n\t\t\"acceptlocal\": false,\n\t\t\"igmpversion\": 0,\n\t\t\"mldversion\": 0,\n\t\t\"neigh4reachabletime\": 30000,\n\t\t\"neigh6reachabletime\": 30000,\n\t\t\"neigh4gcstaletime\": 60,\n\t\t\"neigh6gcstaletime\": 60,\n\t\t\"neigh4locktime\": 100,\n\t\t\"dadtransmits\": 1,\n\t\t\"multicast\": false,\n\t\t\"sendredirects\": true,\n\t\t\"statistics\": {\n\t\t\t\"collisions\": 0,\n\t\t\t\"rx_frame_errors\": 0,\n\t\t\t\"tx_compressed\": 0,\n\t\t\t\"multicast\": 0,\n\t\t\t\"rx_length_errors\": 0,\n\t\t\t\"tx_dropped\": 0,\n\t\t\t\"rx_bytes\": 1728,\n\t\t\t\"rx_missed_errors\": 0,\n\t\t\t\"tx_errors\": 0,\n\t\t\t\"rx_compressed\": 0,\n\t\t\t\"rx_over_errors\": 0,\n\t\t\t\"tx_fifo_errors\": 0,\n\t\t\t\"rx_crc_errors\": 0,\n\t\t\t\"rx_packets\": 20,\n\t\t\t\"tx_heartbeat_errors\": 0,\n\t\t\t\"rx_dropped\": 0,\n\t\t\t\"tx_aborted_errors\": 0,\n\t\t\t\"tx_packets\": 20,\n\t\t\t\"rx_errors\": 0,\n\t\t\t\"tx_bytes\": 1728,\n\t\t\t\"tx_window_errors\": 0,\n\t\t\t\"rx_fifo_errors\": 0,\n\t\t\t\"tx_carrier_errors\": 0\n\t\t}\n\t}\n}\n", + "iw wlan0 station dump": "Station 84:d8:1b:62:a3:55 (on wlan0)\n\tinactive time:\t208 ms\n\trx bytes:\t22432510\n\trx packets:\t49028\n\ttx bytes:\t3212386\n\ttx packets:\t17833\n\ttx retries:\t0\n\ttx failed:\t0\n\tbeacon loss:\t0\n\tbeacon rx:\t12855\n\trx drop misc:\t271\n\tsignal: \t-40 [-40] dBm\n\tsignal avg:\t-40 [-40] dBm\n\tbeacon signal avg:\t-39 dBm\n\ttx bitrate:\t121.5 MBit/s MCS 6 40MHz\n\ttx duration:\t0 us\n\trx bitrate:\t135.0 MBit/s MCS 7 40MHz\n\trx duration:\t0 us\n\tauthorized:\tyes\n\tauthenticated:\tyes\n\tassociated:\tyes\n\tpreamble:\tlong\n\tWMM/WME:\tyes\n\tMFP:\t\tno\n\tTDLS peer:\tno\n\tDTIM period:\t1\n\tbeacon interval:100\n\tshort slot time:yes\n\tconnected time:\t1344 seconds\n\tassociated at [boottime]:\t5406.973s\n\tassociated at:\t1618721846934 ms\n\tcurrent time:\t1618723190901 ms\n", + "ubus call network.interface.mng status": "{\n\t\"up\": true,\n\t\"pending\": false,\n\t\"available\": true,\n\t\"autostart\": true,\n\t\"dynamic\": false,\n\t\"uptime\": 1797,\n\t\"l3_device\": \"br-lan\",\n\t\"proto\": \"static\",\n\t\"device\": \"br-lan\",\n\t\"updated\": [\n\t\t\"addresses\"\n\t],\n\t\"metric\": 0,\n\t\"dns_metric\": 0,\n\t\"delegation\": true,\n\t\"ipv4-address\": [\n\t\t{\n\t\t\t\"address\": \"192.168.56.2\",\n\t\t\t\"mask\": 24\n\t\t}\n\t],\n\t\"ipv6-address\": [\n\t\t\n\t],\n\t\"ipv6-prefix\": [\n\t\t\n\t],\n\t\"ipv6-prefix-assignment\": [\n\t\t\n\t],\n\t\"route\": [\n\t\t\n\t],\n\t\"dns-server\": [\n\t\t\n\t],\n\t\"dns-search\": [\n\t\t\n\t],\n\t\"neighbors\": [\n\t\t\n\t],\n\t\"inactive\": {\n\t\t\"ipv4-address\": [\n\t\t\t\n\t\t],\n\t\t\"ipv6-address\": [\n\t\t\t\n\t\t],\n\t\t\"route\": [\n\t\t\t\n\t\t],\n\t\t\"dns-server\": [\n\t\t\t\n\t\t],\n\t\t\"dns-search\": [\n\t\t\t\n\t\t],\n\t\t\"neighbors\": [\n\t\t\t\n\t\t]\n\t},\n\t\"data\": {\n\t\t\n\t}\n}\n" +} \ No newline at end of file From 3c20fd81375bfe8d58304986e0e44c46bece7f40 Mon Sep 17 00:00:00 2001 From: purhan Date: Tue, 20 Apr 2021 15:05:28 +0530 Subject: [PATCH 03/26] [qa] Format json files --- tests/static/__init__.py | 5 +- tests/static/test-base-ssh.json | 59 +++- tests/static/test-openwrt-ssh.json | 548 ++++++++++++++++++++++++++++- 3 files changed, 593 insertions(+), 19 deletions(-) diff --git a/tests/static/__init__.py b/tests/static/__init__.py index 88c295f..75da0e7 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -11,4 +11,7 @@ def _load_mock_json(file): @staticmethod def _get_mocked_value(oid, data, *args, **kwargs): - return data[oid] + result = data[oid] + if type(result) == list: + result = "\n".join(result[0:]) + return result diff --git a/tests/static/test-base-ssh.json b/tests/static/test-base-ssh.json index f3ffab5..c82ab70 100644 --- a/tests/static/test-base-ssh.json +++ b/tests/static/test-base-ssh.json @@ -1,5 +1,56 @@ { - "ifconfig": "br-lan Link encap:Ethernet HWaddr 08:00:27:EA:D5:D7 \n inet addr:192.168.56.2 Bcast:192.168.56.255 Mask:255.255.255.0\n inet6 addr: fd13:3fc2:e81f::1/60 Scope:Global\n inet6 addr: fe80::a00:27ff:feea:d5d7/64 Scope:Link\n UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1\n RX packets:50 errors:0 dropped:0 overruns:0 frame:0\n TX packets:43 errors:0 dropped:0 overruns:0 carrier:0\n collisions:0 txqueuelen:1000 \n RX bytes:7379 (7.2 KiB) TX bytes:6912 (6.7 KiB)\n\neth0 Link encap:Ethernet HWaddr 08:00:27:EA:D5:D7 \n UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1\n RX packets:51 errors:0 dropped:0 overruns:0 frame:0\n TX packets:43 errors:0 dropped:0 overruns:0 carrier:0\n collisions:0 txqueuelen:1000 \n RX bytes:8145 (7.9 KiB) TX bytes:6930 (6.7 KiB)\n\neth1 Link encap:Ethernet HWaddr 08:00:27:D9:10:14 \n inet addr:10.0.2.4 Bcast:10.0.2.255 Mask:255.255.255.0\n inet6 addr: fe80::a00:27ff:fed9:1014/64 Scope:Link\n UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1\n RX packets:19 errors:0 dropped:0 overruns:0 frame:0\n TX packets:31 errors:0 dropped:0 overruns:0 carrier:0\n collisions:0 txqueuelen:1000 \n RX bytes:2984 (2.9 KiB) TX bytes:3524 (3.4 KiB)\n\nlo Link encap:Local Loopback \n inet addr:127.0.0.1 Mask:255.0.0.0\n inet6 addr: ::1/128 Scope:Host\n UP LOOPBACK RUNNING MTU:65536 Metric:1\n RX packets:20 errors:0 dropped:0 overruns:0 frame:0\n TX packets:20 errors:0 dropped:0 overruns:0 carrier:0\n collisions:0 txqueuelen:1000 \n RX bytes:1728 (1.6 KiB) TX bytes:1728 (1.6 KiB)", - "olsrd -v": "*** olsr.org - 0.9.7-git_0000000-hash_0e6c6b8511b8405eee05046434d38c1b ***\n http://www.olsr.org\n\nTerminated", - "iwconfig": "lo no wireless extensions.\n\nenp1s0 no wireless extensions.\n\nwlp2s0 IEEE 802.11 ESSID:\"MY ROUTER\" \n Mode:Managed Frequency:2.457 GHz Access Point: 83:A8:1C:62:A3:56 \n Bit Rate=150 Mb/s Tx-Power=20 dBm \n Retry short limit:7 RTS thr:off Fragment thr:off\n Power Management:off\n Link Quality=62/70 Signal level=-48 dBm \n Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0\n Tx excessive retries:1 Invalid misc:348 Missed beacon:0\n" -} \ No newline at end of file + "ifconfig": [ + "br-lan Link encap:Ethernet HWaddr 08:00:27:EA:D5:D7 ", + " inet addr:192.168.56.2 Bcast:192.168.56.255 Mask:255.255.255.0", + " inet6 addr: fd13:3fc2:e81f::1/60 Scope:Global", + " inet6 addr: fe80::a00:27ff:feea:d5d7/64 Scope:Link", + " UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1", + " RX packets:50 errors:0 dropped:0 overruns:0 frame:0", + " TX packets:43 errors:0 dropped:0 overruns:0 carrier:0", + " collisions:0 txqueuelen:1000 ", + " RX bytes:7379 (7.2 KiB) TX bytes:6912 (6.7 KiB)", + "", + "eth0 Link encap:Ethernet HWaddr 08:00:27:EA:D5:D7 ", + " UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1", + " RX packets:51 errors:0 dropped:0 overruns:0 frame:0", + " TX packets:43 errors:0 dropped:0 overruns:0 carrier:0", + " collisions:0 txqueuelen:1000 ", + " RX bytes:8145 (7.9 KiB) TX bytes:6930 (6.7 KiB)", + "", + "eth1 Link encap:Ethernet HWaddr 08:00:27:D9:10:14 ", + " inet addr:10.0.2.4 Bcast:10.0.2.255 Mask:255.255.255.0", + " inet6 addr: fe80::a00:27ff:fed9:1014/64 Scope:Link", + " UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1", + " RX packets:19 errors:0 dropped:0 overruns:0 frame:0", + " TX packets:31 errors:0 dropped:0 overruns:0 carrier:0", + " collisions:0 txqueuelen:1000 ", + " RX bytes:2984 (2.9 KiB) TX bytes:3524 (3.4 KiB)", + "", + "lo Link encap:Local Loopback ", + " inet addr:127.0.0.1 Mask:255.0.0.0", + " inet6 addr: ::1/128 Scope:Host", + " UP LOOPBACK RUNNING MTU:65536 Metric:1", + " RX packets:20 errors:0 dropped:0 overruns:0 frame:0", + " TX packets:20 errors:0 dropped:0 overruns:0 carrier:0", + " collisions:0 txqueuelen:1000 ", + " RX bytes:1728 (1.6 KiB) TX bytes:1728 (1.6 KiB)" + ], + "olsrd -v": [ + "*** olsr.org - 0.9.7-git_0000000-hash_0e6c6b8511b8405eee05046434d38c1b ***", + " http://www.olsr.org", + "", + "Terminated" + ], + "iwconfig": [ + "eth0 no wireless extensions.", + "", + "lo no wireless extensions.", + "", + "eth1 no wireless extensions.", + "", + "br-lan no wireless extensions.", + "", + "eth2 no wireless extensions.", + "" + ] +} diff --git a/tests/static/test-openwrt-ssh.json b/tests/static/test-openwrt-ssh.json index f6c14e5..a27f9a7 100644 --- a/tests/static/test-openwrt-ssh.json +++ b/tests/static/test-openwrt-ssh.json @@ -1,15 +1,535 @@ { - "ubus call network.interface.loopback status": "{\n\t\"up\": true,\n\t\"pending\": false,\n\t\"available\": true,\n\t\"autostart\": true,\n\t\"dynamic\": false,\n\t\"uptime\": 1797,\n\t\"l3_device\": \"lo\",\n\t\"proto\": \"static\",\n\t\"device\": \"lo\",\n\t\"updated\": [\n\t\t\"addresses\"\n\t],\n\t\"metric\": 0,\n\t\"dns_metric\": 0,\n\t\"delegation\": true,\n\t\"ipv4-address\": [\n\t\t{\n\t\t\t\"address\": \"127.0.0.1\",\n\t\t\t\"mask\": 8\n\t\t}\n\t],\n\t\"ipv6-address\": [\n\t\t\n\t],\n\t\"ipv6-prefix\": [\n\t\t\n\t],\n\t\"ipv6-prefix-assignment\": [\n\t\t\n\t],\n\t\"route\": [\n\t\t\n\t],\n\t\"dns-server\": [\n\t\t\n\t],\n\t\"dns-search\": [\n\t\t\n\t],\n\t\"neighbors\": [\n\t\t\n\t],\n\t\"inactive\": {\n\t\t\"ipv4-address\": [\n\t\t\t\n\t\t],\n\t\t\"ipv6-address\": [\n\t\t\t\n\t\t],\n\t\t\"route\": [\n\t\t\t\n\t\t],\n\t\t\"dns-server\": [\n\t\t\t\n\t\t],\n\t\t\"dns-search\": [\n\t\t\t\n\t\t],\n\t\t\"neighbors\": [\n\t\t\t\n\t\t]\n\t},\n\t\"data\": {\n\t\t\n\t}\n}\n", - "cat /etc/openwrt_release": "DISTRIB_ID='OpenWrt'\nDISTRIB_RELEASE='19.07.7'\nDISTRIB_REVISION='r11306-c4a6851c72'\nDISTRIB_TARGET='x86/64'\nDISTRIB_ARCH='x86_64'\nDISTRIB_DESCRIPTION='OpenWrt 19.07.7 r11306-c4a6851c72'\nDISTRIB_TAINTS=''", - "uname -a": "Linux OpenWrt 4.14.221 #0 SMP Mon Feb 15 15:22:37 2021 x86_64 GNU/Linux\n", - "olsrd -v": "*** olsr.org - 0.9.7-git_0000000-hash_0e6c6b8511b8405eee05046434d38c1b ***\nhttp://www.olsr.org\nTerminated", - "cat /proc/meminfo | grep MemTotal | awk '{print $2}'": "115080", - "iwconfig 2>/dev/null | grep Mode | awk '{print $4}' | awk -F ':' '{print $2}'": "Master", - "ubus list": "dhcp\ndnsmasq\nfile\niwinfo\nlog\nluci\nluci-rpc\nnetwork\nnetwork.device\nnetwork.interface\nnetwork.interface.loopback\nnetwork.interface.mng\nnetwork.interface.wan\nnetwork.rrdns\nnetwork.wireless\nservice\nsession\nsystem\nuci\n", - "iwinfo | grep -i hardware": "168C:002A 0777:E805 [Ubiquiti Bullet M5]", - "cat /proc/uptime": "1805.66 1800.76", - "ubus call network.interface.wan status": "{\n\t\"up\": true,\n\t\"pending\": false,\n\t\"available\": true,\n\t\"autostart\": true,\n\t\"dynamic\": false,\n\t\"uptime\": 1795,\n\t\"l3_device\": \"eth1\",\n\t\"proto\": \"dhcp\",\n\t\"device\": \"eth1\",\n\t\"metric\": 0,\n\t\"dns_metric\": 0,\n\t\"delegation\": true,\n\t\"ipv4-address\": [\n\t\t{\n\t\t\t\"address\": \"10.0.2.4\",\n\t\t\t\"mask\": 24\n\t\t}\n\t],\n\t\"ipv6-address\": [\n\t\t\n\t],\n\t\"ipv6-prefix\": [\n\t\t\n\t],\n\t\"ipv6-prefix-assignment\": [\n\t\t\n\t],\n\t\"route\": [\n\t\t{\n\t\t\t\"target\": \"0.0.0.0\",\n\t\t\t\"mask\": 0,\n\t\t\t\"nexthop\": \"10.0.2.1\",\n\t\t\t\"source\": \"10.0.2.4/32\"\n\t\t}\n\t],\n\t\"dns-server\": [\n\t\t\"10.0.2.1\"\n\t],\n\t\"dns-search\": [\n\t\t\n\t],\n\t\"neighbors\": [\n\t\t\n\t],\n\t\"inactive\": {\n\t\t\"ipv4-address\": [\n\t\t\t\n\t\t],\n\t\t\"ipv6-address\": [\n\t\t\t\n\t\t],\n\t\t\"route\": [\n\t\t\t\n\t\t],\n\t\t\"dns-server\": [\n\t\t\t\n\t\t],\n\t\t\"dns-search\": [\n\t\t\t\n\t\t],\n\t\t\"neighbors\": [\n\t\t\t\n\t\t]\n\t},\n\t\"data\": {\n\t\t\"leasetime\": 600\n\t}\n}\n", - "ubus call network.device status": "{\n\t\"br-lan\": {\n\t\t\"external\": false,\n\t\t\"present\": true,\n\t\t\"type\": \"bridge\",\n\t\t\"up\": true,\n\t\t\"carrier\": true,\n\t\t\"bridge-members\": [\n\t\t\t\"eth0\"\n\t\t],\n\t\t\"mtu\": 1500,\n\t\t\"mtu6\": 1500,\n\t\t\"macaddr\": \"08:00:27:ea:d5:d7\",\n\t\t\"txqueuelen\": 1000,\n\t\t\"ipv6\": true,\n\t\t\"promisc\": false,\n\t\t\"rpfilter\": 0,\n\t\t\"acceptlocal\": false,\n\t\t\"igmpversion\": 0,\n\t\t\"mldversion\": 0,\n\t\t\"neigh4reachabletime\": 30000,\n\t\t\"neigh6reachabletime\": 30000,\n\t\t\"neigh4gcstaletime\": 60,\n\t\t\"neigh6gcstaletime\": 60,\n\t\t\"neigh4locktime\": 100,\n\t\t\"dadtransmits\": 1,\n\t\t\"multicast\": true,\n\t\t\"sendredirects\": true,\n\t\t\"statistics\": {\n\t\t\t\"collisions\": 0,\n\t\t\t\"rx_frame_errors\": 0,\n\t\t\t\"tx_compressed\": 0,\n\t\t\t\"multicast\": 21,\n\t\t\t\"rx_length_errors\": 0,\n\t\t\t\"tx_dropped\": 0,\n\t\t\t\"rx_bytes\": 158016,\n\t\t\t\"rx_missed_errors\": 0,\n\t\t\t\"tx_errors\": 0,\n\t\t\t\"rx_compressed\": 0,\n\t\t\t\"rx_over_errors\": 0,\n\t\t\t\"tx_fifo_errors\": 0,\n\t\t\t\"rx_crc_errors\": 0,\n\t\t\t\"rx_packets\": 1148,\n\t\t\t\"tx_heartbeat_errors\": 0,\n\t\t\t\"rx_dropped\": 0,\n\t\t\t\"tx_aborted_errors\": 0,\n\t\t\t\"tx_packets\": 1134,\n\t\t\t\"rx_errors\": 0,\n\t\t\t\"tx_bytes\": 228238,\n\t\t\t\"tx_window_errors\": 0,\n\t\t\t\"rx_fifo_errors\": 0,\n\t\t\t\"tx_carrier_errors\": 0\n\t\t}\n\t},\n\t\"eth0\": {\n\t\t\"external\": false,\n\t\t\"present\": true,\n\t\t\"type\": \"Network device\",\n\t\t\"up\": true,\n\t\t\"carrier\": true,\n\t\t\"link-advertising\": [\n\t\t\t\"10baseT-H\",\n\t\t\t\"10baseT-F\",\n\t\t\t\"100baseT-H\",\n\t\t\t\"100baseT-F\",\n\t\t\t\"1000baseT-F\"\n\t\t],\n\t\t\"link-partner-advertising\": [\n\t\t\t\n\t\t],\n\t\t\"link-supported\": [\n\t\t\t\"10baseT-H\",\n\t\t\t\"10baseT-F\",\n\t\t\t\"100baseT-H\",\n\t\t\t\"100baseT-F\",\n\t\t\t\"1000baseT-F\"\n\t\t],\n\t\t\"speed\": \"1000F\",\n\t\t\"autoneg\": true,\n\t\t\"mtu\": 1500,\n\t\t\"mtu6\": 1500,\n\t\t\"macaddr\": \"08:00:27:ea:d5:d7\",\n\t\t\"txqueuelen\": 1000,\n\t\t\"ipv6\": false,\n\t\t\"promisc\": false,\n\t\t\"rpfilter\": 0,\n\t\t\"acceptlocal\": false,\n\t\t\"igmpversion\": 0,\n\t\t\"mldversion\": 0,\n\t\t\"neigh4reachabletime\": 30000,\n\t\t\"neigh6reachabletime\": 30000,\n\t\t\"neigh4gcstaletime\": 60,\n\t\t\"neigh6gcstaletime\": 60,\n\t\t\"neigh4locktime\": 100,\n\t\t\"dadtransmits\": 1,\n\t\t\"multicast\": true,\n\t\t\"sendredirects\": true,\n\t\t\"statistics\": {\n\t\t\t\"collisions\": 0,\n\t\t\t\"rx_frame_errors\": 0,\n\t\t\t\"tx_compressed\": 0,\n\t\t\t\"multicast\": 21,\n\t\t\t\"rx_length_errors\": 0,\n\t\t\t\"tx_dropped\": 0,\n\t\t\t\"rx_bytes\": 174148,\n\t\t\t\"rx_missed_errors\": 0,\n\t\t\t\"tx_errors\": 0,\n\t\t\t\"rx_compressed\": 0,\n\t\t\t\"rx_over_errors\": 0,\n\t\t\t\"tx_fifo_errors\": 0,\n\t\t\t\"rx_crc_errors\": 0,\n\t\t\t\"rx_packets\": 1149,\n\t\t\t\"tx_heartbeat_errors\": 0,\n\t\t\t\"rx_dropped\": 0,\n\t\t\t\"tx_aborted_errors\": 0,\n\t\t\t\"tx_packets\": 1164,\n\t\t\t\"rx_errors\": 0,\n\t\t\t\"tx_bytes\": 251356,\n\t\t\t\"tx_window_errors\": 0,\n\t\t\t\"rx_fifo_errors\": 0,\n\t\t\t\"tx_carrier_errors\": 0\n\t\t}\n\t},\n\t\"eth1\": {\n\t\t\"external\": false,\n\t\t\"present\": true,\n\t\t\"type\": \"Network device\",\n\t\t\"up\": true,\n\t\t\"carrier\": true,\n\t\t\"link-advertising\": [\n\t\t\t\"10baseT-H\",\n\t\t\t\"10baseT-F\",\n\t\t\t\"100baseT-H\",\n\t\t\t\"100baseT-F\",\n\t\t\t\"1000baseT-F\"\n\t\t],\n\t\t\"link-partner-advertising\": [\n\t\t\t\n\t\t],\n\t\t\"link-supported\": [\n\t\t\t\"10baseT-H\",\n\t\t\t\"10baseT-F\",\n\t\t\t\"100baseT-H\",\n\t\t\t\"100baseT-F\",\n\t\t\t\"1000baseT-F\"\n\t\t],\n\t\t\"speed\": \"1000F\",\n\t\t\"autoneg\": true,\n\t\t\"mtu\": 1500,\n\t\t\"mtu6\": 1500,\n\t\t\"macaddr\": \"08:00:27:d9:10:14\",\n\t\t\"txqueuelen\": 1000,\n\t\t\"ipv6\": true,\n\t\t\"promisc\": false,\n\t\t\"rpfilter\": 0,\n\t\t\"acceptlocal\": false,\n\t\t\"igmpversion\": 0,\n\t\t\"mldversion\": 0,\n\t\t\"neigh4reachabletime\": 30000,\n\t\t\"neigh6reachabletime\": 30000,\n\t\t\"neigh4gcstaletime\": 60,\n\t\t\"neigh6gcstaletime\": 60,\n\t\t\"neigh4locktime\": 100,\n\t\t\"dadtransmits\": 1,\n\t\t\"multicast\": true,\n\t\t\"sendredirects\": true,\n\t\t\"statistics\": {\n\t\t\t\"collisions\": 0,\n\t\t\t\"rx_frame_errors\": 0,\n\t\t\t\"tx_compressed\": 0,\n\t\t\t\"multicast\": 0,\n\t\t\t\"rx_length_errors\": 0,\n\t\t\t\"tx_dropped\": 0,\n\t\t\t\"rx_bytes\": 16434,\n\t\t\t\"rx_missed_errors\": 0,\n\t\t\t\"tx_errors\": 0,\n\t\t\t\"rx_compressed\": 0,\n\t\t\t\"rx_over_errors\": 0,\n\t\t\t\"tx_fifo_errors\": 0,\n\t\t\t\"rx_crc_errors\": 0,\n\t\t\t\"rx_packets\": 151,\n\t\t\t\"tx_heartbeat_errors\": 0,\n\t\t\t\"rx_dropped\": 0,\n\t\t\t\"tx_aborted_errors\": 0,\n\t\t\t\"tx_packets\": 159,\n\t\t\t\"rx_errors\": 0,\n\t\t\t\"tx_bytes\": 15274,\n\t\t\t\"tx_window_errors\": 0,\n\t\t\t\"rx_fifo_errors\": 0,\n\t\t\t\"tx_carrier_errors\": 0\n\t\t}\n\t},\n\t\"lo\": {\n\t\t\"external\": false,\n\t\t\"present\": true,\n\t\t\"type\": \"Network device\",\n\t\t\"up\": true,\n\t\t\"carrier\": true,\n\t\t\"mtu\": 65536,\n\t\t\"mtu6\": 65536,\n\t\t\"macaddr\": \"00:00:00:00:00:00\",\n\t\t\"txqueuelen\": 1000,\n\t\t\"ipv6\": true,\n\t\t\"promisc\": false,\n\t\t\"rpfilter\": 0,\n\t\t\"acceptlocal\": false,\n\t\t\"igmpversion\": 0,\n\t\t\"mldversion\": 0,\n\t\t\"neigh4reachabletime\": 30000,\n\t\t\"neigh6reachabletime\": 30000,\n\t\t\"neigh4gcstaletime\": 60,\n\t\t\"neigh6gcstaletime\": 60,\n\t\t\"neigh4locktime\": 100,\n\t\t\"dadtransmits\": 1,\n\t\t\"multicast\": false,\n\t\t\"sendredirects\": true,\n\t\t\"statistics\": {\n\t\t\t\"collisions\": 0,\n\t\t\t\"rx_frame_errors\": 0,\n\t\t\t\"tx_compressed\": 0,\n\t\t\t\"multicast\": 0,\n\t\t\t\"rx_length_errors\": 0,\n\t\t\t\"tx_dropped\": 0,\n\t\t\t\"rx_bytes\": 1728,\n\t\t\t\"rx_missed_errors\": 0,\n\t\t\t\"tx_errors\": 0,\n\t\t\t\"rx_compressed\": 0,\n\t\t\t\"rx_over_errors\": 0,\n\t\t\t\"tx_fifo_errors\": 0,\n\t\t\t\"rx_crc_errors\": 0,\n\t\t\t\"rx_packets\": 20,\n\t\t\t\"tx_heartbeat_errors\": 0,\n\t\t\t\"rx_dropped\": 0,\n\t\t\t\"tx_aborted_errors\": 0,\n\t\t\t\"tx_packets\": 20,\n\t\t\t\"rx_errors\": 0,\n\t\t\t\"tx_bytes\": 1728,\n\t\t\t\"tx_window_errors\": 0,\n\t\t\t\"rx_fifo_errors\": 0,\n\t\t\t\"tx_carrier_errors\": 0\n\t\t}\n\t}\n}\n", - "iw wlan0 station dump": "Station 84:d8:1b:62:a3:55 (on wlan0)\n\tinactive time:\t208 ms\n\trx bytes:\t22432510\n\trx packets:\t49028\n\ttx bytes:\t3212386\n\ttx packets:\t17833\n\ttx retries:\t0\n\ttx failed:\t0\n\tbeacon loss:\t0\n\tbeacon rx:\t12855\n\trx drop misc:\t271\n\tsignal: \t-40 [-40] dBm\n\tsignal avg:\t-40 [-40] dBm\n\tbeacon signal avg:\t-39 dBm\n\ttx bitrate:\t121.5 MBit/s MCS 6 40MHz\n\ttx duration:\t0 us\n\trx bitrate:\t135.0 MBit/s MCS 7 40MHz\n\trx duration:\t0 us\n\tauthorized:\tyes\n\tauthenticated:\tyes\n\tassociated:\tyes\n\tpreamble:\tlong\n\tWMM/WME:\tyes\n\tMFP:\t\tno\n\tTDLS peer:\tno\n\tDTIM period:\t1\n\tbeacon interval:100\n\tshort slot time:yes\n\tconnected time:\t1344 seconds\n\tassociated at [boottime]:\t5406.973s\n\tassociated at:\t1618721846934 ms\n\tcurrent time:\t1618723190901 ms\n", - "ubus call network.interface.mng status": "{\n\t\"up\": true,\n\t\"pending\": false,\n\t\"available\": true,\n\t\"autostart\": true,\n\t\"dynamic\": false,\n\t\"uptime\": 1797,\n\t\"l3_device\": \"br-lan\",\n\t\"proto\": \"static\",\n\t\"device\": \"br-lan\",\n\t\"updated\": [\n\t\t\"addresses\"\n\t],\n\t\"metric\": 0,\n\t\"dns_metric\": 0,\n\t\"delegation\": true,\n\t\"ipv4-address\": [\n\t\t{\n\t\t\t\"address\": \"192.168.56.2\",\n\t\t\t\"mask\": 24\n\t\t}\n\t],\n\t\"ipv6-address\": [\n\t\t\n\t],\n\t\"ipv6-prefix\": [\n\t\t\n\t],\n\t\"ipv6-prefix-assignment\": [\n\t\t\n\t],\n\t\"route\": [\n\t\t\n\t],\n\t\"dns-server\": [\n\t\t\n\t],\n\t\"dns-search\": [\n\t\t\n\t],\n\t\"neighbors\": [\n\t\t\n\t],\n\t\"inactive\": {\n\t\t\"ipv4-address\": [\n\t\t\t\n\t\t],\n\t\t\"ipv6-address\": [\n\t\t\t\n\t\t],\n\t\t\"route\": [\n\t\t\t\n\t\t],\n\t\t\"dns-server\": [\n\t\t\t\n\t\t],\n\t\t\"dns-search\": [\n\t\t\t\n\t\t],\n\t\t\"neighbors\": [\n\t\t\t\n\t\t]\n\t},\n\t\"data\": {\n\t\t\n\t}\n}\n" -} \ No newline at end of file + "uname -a": "Linux OpenWrt 4.14.221 #0 SMP Mon Feb 15 15:22:37 2021 x86_64 GNU/Linux", + "cat /etc/openwrt_release": [ + "DISTRIB_ID='OpenWrt'", + "DISTRIB_RELEASE='19.07.7'", + "DISTRIB_REVISION='r11306-c4a6851c72'", + "DISTRIB_TARGET='x86/64'", + "DISTRIB_ARCH='x86_64'", + "DISTRIB_DESCRIPTION='OpenWrt 19.07.7 r11306-c4a6851c72'", + "DISTRIB_TAINTS=''" + ], + "olsrd -v": [ + "*** olsr.org - 0.9.7-git_0000000-hash_0e6c6b8511b8405eee05046434d38c1b ***", + "http://www.olsr.org", + "Terminated" + ], + "ubus call network.interface.loopback status": [ + "{", + " \"up\": true,", + " \"pending\": false,", + " \"available\": true,", + " \"autostart\": true,", + " \"dynamic\": false,", + " \"uptime\": 1797,", + " \"l3_device\": \"lo\",", + " \"proto\": \"static\",", + " \"device\": \"lo\",", + " \"updated\": [", + " \"addresses\"", + " ],", + " \"metric\": 0,", + " \"dns_metric\": 0,", + " \"delegation\": true,", + " \"ipv4-address\": [", + " {", + " \"address\": \"127.0.0.1\",", + " \"mask\": 8", + " }", + " ],", + " \"ipv6-address\": [", + " ", + " ],", + " \"ipv6-prefix\": [", + " ", + " ],", + " \"ipv6-prefix-assignment\": [", + " ", + " ],", + " \"route\": [", + " ", + " ],", + " \"dns-server\": [", + " ", + " ],", + " \"dns-search\": [", + " ", + " ],", + " \"neighbors\": [", + " ", + " ],", + " \"inactive\": {", + " \"ipv4-address\": [", + " ", + " ],", + " \"ipv6-address\": [", + " ", + " ],", + " \"route\": [", + " ", + " ],", + " \"dns-server\": [", + " ", + " ],", + " \"dns-search\": [", + " ", + " ],", + " \"neighbors\": [", + " ", + " ]", + " },", + " \"data\": {", + " ", + " }", + " }", + " " + ], + "cat /proc/meminfo | grep MemTotal | awk '{print $2}'": "115080", + "iwconfig 2>/dev/null | grep Mode | awk '{print $4}' | awk -F ':' '{print $2}'": "Master", + "ubus list": [ + "dhcp", + "dnsmasq", + "file", + "iwinfo", + "log", + "luci", + "luci-rpc", + "network", + "network.device", + "network.interface", + "network.interface.loopback", + "network.interface.mng", + "network.interface.wan", + "network.rrdns", + "network.wireless", + "service", + "session", + "system", + "uci" + ], + "iwinfo | grep -i hardware": "168C:002A 0777:E805 [Ubiquiti Bullet M5]", + "cat /proc/uptime": "1805.66 1800.76", + "ubus call network.interface.wan status": [ + "{", + " \"up\": true,", + " \"pending\": false,", + " \"available\": true,", + " \"autostart\": true,", + " \"dynamic\": false,", + " \"uptime\": 1795,", + " \"l3_device\": \"eth1\",", + " \"proto\": \"dhcp\",", + " \"device\": \"eth1\",", + " \"metric\": 0,", + " \"dns_metric\": 0,", + " \"delegation\": true,", + " \"ipv4-address\": [", + " {", + " \"address\": \"10.0.2.4\",", + " \"mask\": 24", + " }", + " ],", + " \"ipv6-address\": [", + " ", + " ],", + " \"ipv6-prefix\": [", + " ", + " ],", + " \"ipv6-prefix-assignment\": [", + " ", + " ],", + " \"route\": [", + " {", + " \"target\": \"0.0.0.0\",", + " \"mask\": 0,", + " \"nexthop\": \"10.0.2.1\",", + " \"source\": \"10.0.2.4/32\"", + " }", + " ],", + " \"dns-server\": [", + " \"10.0.2.1\"", + " ],", + " \"dns-search\": [", + " ", + " ],", + " \"neighbors\": [", + " ", + " ],", + " \"inactive\": {", + " \"ipv4-address\": [", + " ", + " ],", + " \"ipv6-address\": [", + " ", + " ],", + " \"route\": [", + " ", + " ],", + " \"dns-server\": [", + " ", + " ],", + " \"dns-search\": [", + " ", + " ],", + " \"neighbors\": [", + " ", + " ]", + " },", + " \"data\": {", + " \"leasetime\": 600", + " }", + " }", + " " + ], + "ubus call network.device status": [ + "{", + " \"br-lan\": {", + " \"external\": false,", + " \"present\": true,", + " \"type\": \"bridge\",", + " \"up\": true,", + " \"carrier\": true,", + " \"bridge-members\": [", + " \"eth0\"", + " ],", + " \"mtu\": 1500,", + " \"mtu6\": 1500,", + " \"macaddr\": \"08:00:27:ea:d5:d7\",", + " \"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\": 21,", + " \"rx_length_errors\": 0,", + " \"tx_dropped\": 0,", + " \"rx_bytes\": 158016,", + " \"rx_missed_errors\": 0,", + " \"tx_errors\": 0,", + " \"rx_compressed\": 0,", + " \"rx_over_errors\": 0,", + " \"tx_fifo_errors\": 0,", + " \"rx_crc_errors\": 0,", + " \"rx_packets\": 1148,", + " \"tx_heartbeat_errors\": 0,", + " \"rx_dropped\": 0,", + " \"tx_aborted_errors\": 0,", + " \"tx_packets\": 1134,", + " \"rx_errors\": 0,", + " \"tx_bytes\": 228238,", + " \"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\": [", + " \"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\": \"1000F\",", + " \"autoneg\": true,", + " \"mtu\": 1500,", + " \"mtu6\": 1500,", + " \"macaddr\": \"08:00:27:ea:d5:d7\",", + " \"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\": 21,", + " \"rx_length_errors\": 0,", + " \"tx_dropped\": 0,", + " \"rx_bytes\": 174148,", + " \"rx_missed_errors\": 0,", + " \"tx_errors\": 0,", + " \"rx_compressed\": 0,", + " \"rx_over_errors\": 0,", + " \"tx_fifo_errors\": 0,", + " \"rx_crc_errors\": 0,", + " \"rx_packets\": 1149,", + " \"tx_heartbeat_errors\": 0,", + " \"rx_dropped\": 0,", + " \"tx_aborted_errors\": 0,", + " \"tx_packets\": 1164,", + " \"rx_errors\": 0,", + " \"tx_bytes\": 251356,", + " \"tx_window_errors\": 0,", + " \"rx_fifo_errors\": 0,", + " \"tx_carrier_errors\": 0", + " }", + " },", + " \"eth1\": {", + " \"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\": [", + " ", + " ],", + " \"link-supported\": [", + " \"10baseT-H\",", + " \"10baseT-F\",", + " \"100baseT-H\",", + " \"100baseT-F\",", + " \"1000baseT-F\"", + " ],", + " \"speed\": \"1000F\",", + " \"autoneg\": true,", + " \"mtu\": 1500,", + " \"mtu6\": 1500,", + " \"macaddr\": \"08:00:27:d9:10:14\",", + " \"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\": 16434,", + " \"rx_missed_errors\": 0,", + " \"tx_errors\": 0,", + " \"rx_compressed\": 0,", + " \"rx_over_errors\": 0,", + " \"tx_fifo_errors\": 0,", + " \"rx_crc_errors\": 0,", + " \"rx_packets\": 151,", + " \"tx_heartbeat_errors\": 0,", + " \"rx_dropped\": 0,", + " \"tx_aborted_errors\": 0,", + " \"tx_packets\": 159,", + " \"rx_errors\": 0,", + " \"tx_bytes\": 15274,", + " \"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\": 1728,", + " \"rx_missed_errors\": 0,", + " \"tx_errors\": 0,", + " \"rx_compressed\": 0,", + " \"rx_over_errors\": 0,", + " \"tx_fifo_errors\": 0,", + " \"rx_crc_errors\": 0,", + " \"rx_packets\": 20,", + " \"tx_heartbeat_errors\": 0,", + " \"rx_dropped\": 0,", + " \"tx_aborted_errors\": 0,", + " \"tx_packets\": 20,", + " \"rx_errors\": 0,", + " \"tx_bytes\": 1728,", + " \"tx_window_errors\": 0,", + " \"rx_fifo_errors\": 0,", + " \"tx_carrier_errors\": 0", + " }", + " }", + " }", + " " + ], + "iw wlan0 station dump": [ + "Station 84:d8:1b:62:a3:55 (on wlan0)", + " inactive time: 208 ms", + " rx bytes: 22432510", + " rx packets: 49028", + " tx bytes: 3212386", + " tx packets: 17833", + " tx retries: 0", + " tx failed: 0", + " beacon loss: 0", + " beacon rx: 12855", + " rx drop misc: 271", + " signal: -40 [-40] dBm", + " signal avg: -40 [-40] dBm", + " beacon signal avg: -39 dBm", + " tx bitrate: 121.5 MBit/s MCS 6 40MHz", + " tx duration: 0 us", + " rx bitrate: 135.0 MBit/s MCS 7 40MHz", + " rx duration: 0 us", + " authorized: yes", + " authenticated: yes", + " associated: yes", + " preamble: long", + " WMM/WME: yes", + " MFP: no", + " TDLS peer: no", + " DTIM period: 1", + " beacon interval:100", + " short slot time:yes", + " connected time: 1344 seconds", + " associated at [boottime]: 5406.973s", + " associated at: 1618721846934 ms", + " current time: 1618723190901 ms", + "" + ], + "ubus call network.interface.mng status": [ + "{", + " \"up\": true,", + " \"pending\": false,", + " \"available\": true,", + " \"autostart\": true,", + " \"dynamic\": false,", + " \"uptime\": 1797,", + " \"l3_device\": \"br-lan\",", + " \"proto\": \"static\",", + " \"device\": \"br-lan\",", + " \"updated\": [", + " \"addresses\"", + " ],", + " \"metric\": 0,", + " \"dns_metric\": 0,", + " \"delegation\": true,", + " \"ipv4-address\": [", + " {", + " \"address\": \"192.168.56.2\",", + " \"mask\": 24", + " }", + " ],", + " \"ipv6-address\": [", + " ", + " ],", + " \"ipv6-prefix\": [", + " ", + " ],", + " \"ipv6-prefix-assignment\": [", + " ", + " ],", + " \"route\": [", + " ", + " ],", + " \"dns-server\": [", + " ", + " ],", + " \"dns-search\": [", + " ", + " ],", + " \"neighbors\": [", + " ", + " ],", + " \"inactive\": {", + " \"ipv4-address\": [", + " ", + " ],", + " \"ipv6-address\": [", + " ", + " ],", + " \"route\": [", + " ", + " ],", + " \"dns-server\": [", + " ", + " ],", + " \"dns-search\": [", + " ", + " ],", + " \"neighbors\": [", + " ", + " ]", + " },", + " \"data\": {", + " ", + " }", + " }", + " " + ] +} From a87cc398b37aeda9bb619d3f145c0795bc2221e8 Mon Sep 17 00:00:00 2001 From: purhan Date: Tue, 20 Apr 2021 15:30:16 +0530 Subject: [PATCH 04/26] [qa] Add back negative results test --- tests/ssh/base.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/ssh/base.py b/tests/ssh/base.py index 36ffa30..84a28ca 100644 --- a/tests/ssh/base.py +++ b/tests/ssh/base.py @@ -3,6 +3,7 @@ from netengine.backends.ssh import SSH from netengine.exceptions import NetEngineError +from paramiko.ssh_exception import SSHException from ..settings import settings from ..static import MockOutputMixin @@ -31,13 +32,19 @@ def setUp(self, mocked_connect): ) self.exec_command_patcher.start() + @mock.patch('paramiko.SSHClient.connect') + def test_validate_negative_result(self, mocked_connect): + mocked_connect.side_effect = SSHException + wrong = SSH('10.40.0.254', 'root', 'pwd') + self.assertRaises(NetEngineError, wrong.validate) + @mock.patch('paramiko.SSHClient.close') @mock.patch('paramiko.SSHClient.connect') def test_validate_positive_result(self, mocked_connect, mocked_close): self.device.disconnect() self.device.validate() mocked_connect.assert_called_once() - mocked_close.assert_called() + self.assertEqual(mocked_close.call_count, 2) def test_olsr(self): print(self.device.olsr) From 6a9095a949528e021cc91ff994d88a8852cdd4d7 Mon Sep 17 00:00:00 2001 From: purhan Date: Fri, 23 Apr 2021 13:48:06 +0530 Subject: [PATCH 05/26] [qa] Mock testcases for OpenWRT SNMP backend --- tests/snmp/openwrt.py | 76 +++++++++++++++++++------ tests/static/test-openwrt-snmp-oid.json | 49 ++++++++++++++++ 2 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 tests/static/test-openwrt-snmp-oid.json diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index eabb5d2..99d2d60 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -1,14 +1,14 @@ import unittest +import mock from netengine.backends.snmp import OpenWRT from ..settings import settings - +from ..static import MockOutputMixin __all__ = ['TestSNMPOpenWRT'] -class TestSNMPOpenWRT(unittest.TestCase): - +class TestSNMPOpenWRT(unittest.TestCase, MockOutputMixin): def setUp(self): self.host = settings['openwrt-snmp']['host'] self.community = settings['openwrt-snmp']['community'] @@ -16,11 +16,25 @@ def setUp(self): self.device = OpenWRT(self.host, self.community, self.port) + self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') + self.get_value_patcher = mock.patch( + 'netengine.backends.snmp.openwrt.OpenWRT.get_value', + side_effect=lambda x: self._get_mocked_value( + oid=x, data=self.oid_mock_data + ).encode('ascii', 'ignore'), + ) + self.get_value_patcher.start() + def test_os(self): self.assertTrue(type(self.device.os) == tuple) - def test_manufacturer(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') + def test_manufacturer(self, mock_nextcmd, mock_value_to_retr): + mock_value_to_retr.return_value = [1, 2, 3, 4, 5] + mock_nextcmd.return_value = [0, 0, 0, [0] * 5] self.assertIsNotNone(self.device.manufacturer) + mock_nextcmd.assert_called_once_with('1.3.6.1.2.1.2.2.1.6.') def test_name(self): self.assertTrue(type(self.device.name) == str) @@ -31,41 +45,71 @@ def test_uptime(self): def test_uptime_tuple(self): self.assertTrue(type(self.device.uptime_tuple) == tuple) - def test_get_interfaces(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + def test_get_interfaces(self, mock_interfaces_count): + mock_interfaces_count.return_value = [1, 2, 3, 4, 5] self.assertTrue(type(self.device.get_interfaces()) == list) def test_interfaces_speed(self): self.assertTrue(type(self.device.interfaces_speed) == list) - def test_interfaces_bytes(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + def test_interfaces_bytes(self, mock_interfaces_count): self.assertTrue(type(self.device.interfaces_bytes) == list) - def test_interfaces_MAC(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') + def test_interfaces_MAC(self, mock_nextcmd, mock_interfaces_count): + mock_interfaces_count.return_value = [1, 2, 3, 4, 5] + mock_nextcmd.return_value = [0, 0, 0, [0] * 5] self.assertTrue(type(self.device.interfaces_MAC) == list) - def test_interfaces_type(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + def test_interfaces_type(self, mock_interfaces_count): + mock_interfaces_count.return_value = [1, 2, 3, 4, 5] self.assertTrue(type(self.device.interfaces_type) == list) - def test_interfaces_mtu(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + def test_interfaces_mtu(self, mock_interfaces_count): + mock_interfaces_count.return_value = [1, 2, 3, 4, 5] self.assertTrue(type(self.device.interfaces_mtu) == list) - def test_interfaces_state(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + def test_interfaces_state(self, mock_interfaces_count): + mock_interfaces_count.return_value = [1, 2, 3, 4, 5] self.assertTrue(type(self.device.interfaces_state) == list) - def test_interfaces_to_dict(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') + def test_interfaces_to_dict(self, mock_nextcmd): + mock_nextcmd.return_value = (0, 0, 0, []) self.assertTrue(type(self.device.interfaces_to_dict) == list) - def test_interface_addr_and_mask(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') + def test_interface_addr_and_mask(self, mock_nextcmd): + mock_nextcmd.return_value = (0, 0, 0, []) self.assertTrue(type(self.device.interface_addr_and_mask) == dict) def test_RAM_total(self): self.assertTrue(type(self.device.RAM_total) == int) - def test_to_dict(self): + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') + def test_to_dict(self, mock_nextcmd, mock_interfaces_count): + mock_interfaces_count.return_value = [1, 2, 3, 4, 5] + mock_nextcmd.return_value = [0, 0, 0, [0] * 5] device_dict = self.device.to_dict() self.assertTrue(isinstance(device_dict, dict)) - self.assertEqual(len(device_dict['interfaces']), len(self.device.get_interfaces())) - - def test_manufacturer_to_dict(self): + self.assertEqual( + len(device_dict['interfaces']), len(self.device.get_interfaces()) + ) + + @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') + @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') + def test_manufacturer_to_dict(self, mock_nextcmd, mock_interfaces_count): + mock_interfaces_count.return_value = [1, 2, 3, 4, 5] + mock_nextcmd.return_value = [0, 0, 0, [0] * 5] self.assertIsNotNone(self.device.to_dict()['manufacturer']) + + def tearDown(self): + self.get_value_patcher.stop() diff --git a/tests/static/test-openwrt-snmp-oid.json b/tests/static/test-openwrt-snmp-oid.json new file mode 100644 index 0000000..2db1140 --- /dev/null +++ b/tests/static/test-openwrt-snmp-oid.json @@ -0,0 +1,49 @@ +{ + "1.3.6.1.2.1.25.2.3.1.5.1": "115080", + "1.3.6.1.2.1.2.2.1.2.1": "lo", + "1.3.6.1.2.1.2.2.1.2.2": "Device 8086:100e", + "1.3.6.1.2.1.2.2.1.2.3": "Device 8086:100e", + "1.3.6.1.2.1.2.2.1.2.4": "Device 8086:100e", + "1.3.6.1.2.1.2.2.1.2.5": "br-lan", + "1.3.6.1.2.1.2.2.1.16.1": "719914", + "1.3.6.1.2.1.2.2.1.10.1": "719914", + "1.3.6.1.2.1.2.2.1.16.2": "806244", + "1.3.6.1.2.1.2.2.1.10.2": "758983", + "1.3.6.1.2.1.2.2.1.16.3": "3326302", + "1.3.6.1.2.1.2.2.1.10.3": "9723560", + "1.3.6.1.2.1.2.2.1.10.5": "647519", + "1.3.6.1.2.1.2.2.1.16.4": "0", + "1.3.6.1.2.1.2.2.1.10.4": "0", + "1.3.6.1.2.1.2.2.1.16.5": "805932", + "1.3.6.1.2.1.2.2.1.8.1": "1", + "1.3.6.1.2.1.2.2.1.8.2": "1", + "1.3.6.1.2.1.2.2.1.8.3": "1", + "1.3.6.1.2.1.2.2.1.8.4": "2", + "1.3.6.1.2.1.2.2.1.8.5": "1", + "1.3.6.1.2.1.2.2.1.4.1": "65536", + "1.3.6.1.2.1.2.2.1.4.2": "1500", + "1.3.6.1.2.1.2.2.1.4.3": "1500", + "1.3.6.1.2.1.2.2.1.4.4": "1500", + "1.3.6.1.2.1.2.2.1.4.5": "1500", + "1.3.6.1.2.1.2.2.1.5.1": "10000000", + "1.3.6.1.2.1.2.2.1.5.2": "1000000000", + "1.3.6.1.2.1.2.2.1.5.3": "1000000000", + "1.3.6.1.2.1.2.2.1.5.4": "1000000000", + "1.3.6.1.2.1.2.2.1.5.5": "0", + "1.3.6.1.2.1.2.2.1.2.6": "", + "1.3.6.1.2.1.2.2.1.2.7": "", + "1.3.6.1.2.1.2.2.1.2.8": "", + "1.3.6.1.2.1.2.2.1.3.1": "24", + "1.3.6.1.2.1.2.2.1.3.2": "6", + "1.3.6.1.2.1.2.2.1.3.3": "6", + "1.3.6.1.2.1.2.2.1.3.4": "6", + "1.3.6.1.2.1.2.2.1.3.5": "6", + "1.3.6.1.2.1.1.3.0": "1033939", + "1.3.6.1.2.1.1.5.0": "HeartOfGold", + "1.3.6.1.2.1.1.1.0": "Linux 08-00-27-0A-F7-6A 4.14.221 #0 SMP Mon Feb 15 15:22:37 2021 x86_64", + "1.3.6.1.2.1.2.2.1.6.1": "\b\u0000''�\u0010\u0014", + "1.3.6.1.2.1.2.2.1.6.2": "\b\u0000''�\u0010\u0000", + "1.3.6.1.2.1.2.2.1.6.3": "\b\u0000''�\u0010\u0014", + "1.3.6.1.2.1.2.2.1.6.4": "\b\u0000''�\u0010\u0000", + "1.3.6.1.2.1.2.2.1.6.5": "\b\u0000''�\u0010\u0015" +} From f73205f0baf8d51212c29764b7dc718b893753bc Mon Sep 17 00:00:00 2001 From: purhan Date: Sun, 25 Apr 2021 00:53:09 +0530 Subject: [PATCH 06/26] [qa] Mock testcases for AirOS SSH backend --- tests/ssh/airos.py | 18 ++++++-- tests/static/test-airos-ssh.json | 74 ++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 tests/static/test-airos-ssh.json diff --git a/tests/ssh/airos.py b/tests/ssh/airos.py index bf17d1c..47cdcb0 100644 --- a/tests/ssh/airos.py +++ b/tests/ssh/airos.py @@ -1,17 +1,20 @@ import json import unittest +import mock from netengine.backends.ssh import AirOS from ..settings import settings +from ..static import MockOutputMixin __all__ = ['TestSSHAirOS'] -class TestSSHAirOS(unittest.TestCase): +class TestSSHAirOS(unittest.TestCase, MockOutputMixin): - def setUp(self): + @mock.patch('paramiko.SSHClient.connect') + def setUp(self, mocked_connect): self.host = settings['airos-ssh']['host'] self.username = settings['airos-ssh']['username'] self.password = settings['airos-ssh']['password'] @@ -19,6 +22,15 @@ def setUp(self): self.device = AirOS(self.host, self.username, self.password, self.port) self.device.connect() + mocked_connect.assert_called_once() + ssh_mock_data = self._load_mock_json('/test-airos-ssh.json') + self.ssh_patcher = mock.patch( + 'netengine.backends.ssh.airos.SSH.run', + side_effect=lambda x: self._get_mocked_value( + oid=x, data=ssh_mock_data + ), + ) + self.ssh_patcher.start() def test_to_dict(self): self.assertTrue(isinstance(self.device.to_dict(), dict)) @@ -58,6 +70,6 @@ def test_temp_methods(self): self.assertTrue(type(device.get_ipv6_of_interface('eth0')) in [str, type(None)]) self.assertTrue(type(device.get_ipv6_of_interface('wrong')) is type(None)) device.disconnect() - + def test_uptime(self): self.assertIs(type(self.device.uptime), int) diff --git a/tests/static/test-airos-ssh.json b/tests/static/test-airos-ssh.json new file mode 100644 index 0000000..468b7b0 --- /dev/null +++ b/tests/static/test-airos-ssh.json @@ -0,0 +1,74 @@ +{ + "ls -l": "total 0", + "ip -6 addr show eth0": [ + "eth0: mtu 1500 state UP qlen 1000", + " inet6 fe80::a00:27ff:fed9:1014/64 scope link ", + " valid_lft forever preferred_lft forever" + ], + "uname -a": "Linux (DeviceName) 2.6.32.71 #1 Wed May 23 18:10:52 EEST 2018 mips GNU/Linux ", + "ip -6 addr show wrong": "Device \"wrong\" does not exist.", + "iwconfig": [ + "eth0 no wireless extensions.", + "", + "lo no wireless extensions.", + "", + "eth1 no wireless extensions.", + "", + "br-mng no wireless extensions.", + "", + "eth2 no wireless extensions." + ], + "ifconfig": [ + "br-mng Link encap:Ethernet HWaddr 08:00:27:EA:D5:D7 ", + " inet addr:192.168.56.2 Bcast:192.168.56.255 Mask:255.255.255.0", + " inet6 addr: fe80::a00:27ff:feea:d5d7/64 Scope:Link", + " UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1", + " RX packets:2772 errors:0 dropped:0 overruns:0 frame:0", + " TX packets:2032 errors:0 dropped:0 overruns:0 carrier:0", + " collisions:0 txqueuelen:1000 ", + " RX bytes:421352 (411.4 KiB) TX bytes:319310 (311.8 KiB)", + "", + "eth0 Link encap:Ethernet HWaddr 08:00:27:EA:D5:D7 ", + " UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1", + " RX packets:2780 errors:0 dropped:0 overruns:0 frame:0", + " TX packets:2032 errors:0 dropped:0 overruns:0 carrier:0", + " collisions:0 txqueuelen:1000 ", + " RX bytes:460688 (449.8 KiB) TX bytes:319370 (311.8 KiB)", + "", + "eth1 Link encap:Ethernet HWaddr 08:00:27:D9:10:14 ", + " inet addr:10.0.2.4 Bcast:10.0.2.255 Mask:255.255.255.0", + " inet6 addr: fe80::a00:27ff:fed9:1014/64 Scope:Link", + " UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1", + " RX packets:787 errors:0 dropped:0 overruns:0 frame:0", + " TX packets:628 errors:0 dropped:0 overruns:0 carrier:0", + " collisions:0 txqueuelen:1000 ", + " RX bytes:796361 (777.6 KiB) TX bytes:47397 (46.2 KiB)", + "", + "lo Link encap:Local Loopback ", + " inet addr:127.0.0.1 Mask:255.0.0.0", + " inet6 addr: ::1/128 Scope:Host", + " UP LOOPBACK RUNNING MTU:65536 Metric:1", + " RX packets:72 errors:0 dropped:0 overruns:0 frame:0", + " TX packets:72 errors:0 dropped:0 overruns:0 carrier:0", + " collisions:0 txqueuelen:1000 ", + " RX bytes:6950 (6.7 KiB) TX bytes:6950 (6.7 KiB)" + ], + "olsrd -v": [ + "*** olsr.org - 0.9.7-git_0000000-hash_0e6c6b8511b8405eee05046434d38c1b ***", + "http://www.olsr.org", + "Terminated" + ], + "ubntbox mca-status" : "deviceName=DEVICE,deviceId=00:XX:XX:XX:XX:XX,firmwareVersion=XM.ar7240.v5.5.4.16501.130308.1015,platform=Bullet M2,deviceIp=XXX.XXX.XXX.XXX,uptime=1149847,memTotal=29524,lanSpeed=100Mbps-Full,wlanOpmode=ap,freq=2452,signal=-66,noise=-90", + "cat /tmp/system.cfg": [ + "(ip address)", + "netconf.3.ip=10.168.0.100", + "", + "(network mask)", + "netconf.3.netmask=255.255.255.0", + "", + "(gateway)", + "route.1.gateway=10.168.0.254", + "radio.1.ieee_mode=11nxht40plus", + "radio.1.txpower=54" + ] +} From dece4a08735b6b6584622fc0cad194a2c9cd6479 Mon Sep 17 00:00:00 2001 From: purhan Date: Sun, 9 May 2021 09:59:00 +0530 Subject: [PATCH 07/26] [qa] Mock tests for airos snmp backend --- tests/snmp/airos.py | 76 +++++++++++++++++++++++++------ tests/static/__init__.py | 7 +++ tests/static/test-airos-snmp.json | 50 ++++++++++++++++++++ 3 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 tests/static/test-airos-snmp.json diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index eb3719a..683204b 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -1,14 +1,16 @@ import unittest +from mock import patch from netengine.backends.snmp import AirOS from netengine.exceptions import NetEngineError from ..settings import settings +from ..static import MockOutputMixin __all__ = ['TestSNMPAirOS'] -class TestSNMPAirOS(unittest.TestCase): +class TestSNMPAirOS(unittest.TestCase, MockOutputMixin): def setUp(self): self.host = settings['airos-snmp']['host'] @@ -16,29 +18,56 @@ def setUp(self): self.port = settings['airos-snmp'].get('port', 161) self.device = AirOS(self.host, self.community, port=self.port) + self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') + self.interfaces_patcher = patch( + 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', + return_value=[1, 2, 3, 4, 5] + ) + self.get_value_patcher = patch( + 'netengine.backends.snmp.airos.AirOS.get', + side_effect=lambda x: self._get_mocked_getcmd( + oid=x, data=self.oid_mock_data + ), + ) + self.get_value_patcher.start() def test_get_value_error(self): - with self.assertRaises(NetEngineError): - self.device.get_value('.') + self.get_value_patcher.stop() + with patch( + 'netengine.backends.snmp.openwrt.SNMP.get', + side_effect=lambda x: self.device._oid(x) + ): + with self.assertRaises(NetEngineError): + self.device.get_value('.') def test_validate_negative_result(self): - wrong = AirOS('10.40.0.254', 'wrong', 'wrong') - self.assertRaises(NetEngineError, wrong.validate) + self.get_value_patcher.stop() + with patch( + 'netengine.backends.snmp.openwrt.SNMP.get', + side_effect=lambda x: self.device._oid(x) + ): + wrong = AirOS('10.40.0.254', 'wrong', 'wrong') + self.assertRaises(NetEngineError, wrong.validate) def test_validate_positive_result(self): self.device.validate() def test_get(self): + self.get_value_patcher.stop() with self.assertRaises(AttributeError): self.device.get({}) with self.assertRaises(AttributeError): self.device.get(object) - self.device.get('1,3,6,1,2,1,1,5,0') - self.device.get(u'1,3,6,1,2,1,1,5,0') - self.device.get((1,3,6,1,2,1,1,5,0)) - self.device.get([1,3,6,1,2,1,1,5,0]) + with patch( + 'netengine.backends.snmp.openwrt.SNMP.get', + side_effect=lambda x: self.device._oid(x) + ): + self.device.get('1,3,6,1,2,1,1,5,0') + self.device.get(u'1,3,6,1,2,1,1,5,0') + self.device.get((1,3,6,1,2,1,1,5,0)) + self.device.get([1,3,6,1,2,1,1,5,0]) def test_properties(self): device = self.device @@ -57,30 +86,40 @@ def test_os(self): self.assertTrue(type(self.device.os) == tuple) def test_get_interfaces(self): + self.interfaces_patcher.start() self.assertTrue(type(self.device.get_interfaces()) == list) def test_get_interfaces_mtu(self): + self.interfaces_patcher.start() self.assertTrue(type(self.device.interfaces_mtu) == list) def test_interfaces_state(self): + self.interfaces_patcher.start() self.assertTrue(type(self.device.interfaces_state) == list) def test_interfaces_speed(self): + self.interfaces_patcher.start() self.assertTrue(type(self.device.interfaces_speed) == list) def test_interfaces_bytes(self): + self.interfaces_patcher.start() self.assertTrue(type(self.device.interfaces_bytes) == list) def test_interfaces_MAC(self): + self.interfaces_patcher.start() self.assertTrue(type(self.device.interfaces_MAC) == list) def test_interfaces_type(self): + self.interfaces_patcher.start() self.assertTrue(type(self.device.interfaces_type) == list) def test_interfaces_to_dict(self): + self.interfaces_patcher.start() self.assertTrue(type(self.device.interfaces_to_dict) == list) - - def test_wireless_dbm(self): + + @patch('netengine.backends.snmp.openwrt.SNMP.next') + def test_wireless_dbm(self, mock_nextcmd): + mock_nextcmd.return_value = [0, 0, 0, [[[0, 0]]] * 5] self.assertTrue(type(self.device.wireless_dbm) == list) def test_interfaces_number(self): @@ -95,13 +134,19 @@ def test_RAM_free(self): def test_RAM_total(self): self.assertTrue(type(self.device.RAM_total) == int) - def test_to_dict(self): - self.assertTrue(isinstance(self.device.to_dict(), dict)) + def test_to_dict(self, mock_nextcmd): + self.interfaces_patcher.start() + with patch( + 'netengine.backends.snmp.openwrt.SNMP.next', + return_value=[0, 0, 0, [[[0, 0,]]] * 5] + ): + self.assertTrue(isinstance(self.device.to_dict(), dict)) def test_manufacturer_to_dict(self): self.assertIsNotNone(self.device.to_dict()['manufacturer']) def test_manufacturer(self): + self.interfaces_patcher.start() self.assertIsNotNone(self.device.manufacturer) def test_model(self): @@ -114,4 +159,7 @@ def test_uptime(self): self.assertTrue(type(self.device.uptime) == int) def test_uptime_tuple(self): - self.assertTrue(type(self.device.uptime_tuple) == tuple) \ No newline at end of file + self.assertTrue(type(self.device.uptime_tuple) == tuple) + + def tearDown(self): + self.get_value_patcher.stop() \ No newline at end of file diff --git a/tests/static/__init__.py b/tests/static/__init__.py index 75da0e7..0916a26 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -15,3 +15,10 @@ def _get_mocked_value(oid, data, *args, **kwargs): if type(result) == list: result = "\n".join(result[0:]) return result + + @staticmethod + def _get_mocked_getcmd(oid, data, *args, **kwargs): + result = data[oid] + if type(result) == list: + result = "\n".join(result[0:]) + return [0, 0, 0, [[0, result.encode('ascii', 'ignore')], 0]] diff --git a/tests/static/test-airos-snmp.json b/tests/static/test-airos-snmp.json new file mode 100644 index 0000000..f54ee6a --- /dev/null +++ b/tests/static/test-airos-snmp.json @@ -0,0 +1,50 @@ +{ + "1.3.6.1.2.1.1.5.0": "DeviceName", + "1.3.6.1.2.1.1.3.0": "37352", + "1.3.6.1.2.1.1.1.0": "Linux DeviceName 2.6.32.71 #1 Wed May 23 18:10:52 EEST 2018 mips GNU/Linux", + "1.3.6.1.2.1.2.1.0": "5", + "1.3.6.1.4.1.10002.1.1.1.1.2.0": "65504", + "1.3.6.1.4.1.10002.1.1.1.1.1.0": "126272", + "1.2.840.10036.3.1.2.1.4.5": "XM.ar7240.v5.5.12536.120406.1455", + "1.2.840.10036.3.1.2.1.3.5": "NanoStation Loco M2", + "1.3.6.1.2.1.2.2.1.2.1": "wired0", + "1.3.6.1.2.1.2.2.1.2.2": "eth0", + "1.3.6.1.2.1.2.2.1.2.3": "wifi1", + "1.3.6.1.2.1.2.2.1.2.4": "internal_svc", + "1.3.6.1.2.1.2.2.1.2.5": "primarylan1", + "1.3.6.1.2.1.2.2.1.6.1": "\b\u0000''�\u0010\u0014", + "1.3.6.1.2.1.2.2.1.6.2": "\b\u0000''�\u0010\u0000", + "1.3.6.1.2.1.2.2.1.6.3": "\b\u0000''�\u0010\u0015", + "1.3.6.1.2.1.2.2.1.6.4": "\b\u0000''�\u0010\u0015", + "1.3.6.1.2.1.2.2.1.6.5": "\b\u0000''�\u0010\u0015", + "1.3.6.1.2.1.2.2.1.3.1": "24", + "1.3.6.1.2.1.2.2.1.3.2": "6", + "1.3.6.1.2.1.2.2.1.3.3": "6", + "1.3.6.1.2.1.2.2.1.3.4": "6", + "1.3.6.1.2.1.2.2.1.3.5": "6", + "1.3.6.1.2.1.2.2.1.16.1": "3214378817", + "1.3.6.1.2.1.2.2.1.16.2": "2438196185", + "1.3.6.1.2.1.2.2.1.16.3": "3214378817", + "1.3.6.1.2.1.2.2.1.16.4": "2438196185", + "1.3.6.1.2.1.2.2.1.16.5": "3214378817", + "1.3.6.1.2.1.2.2.1.10.1": "3214378817", + "1.3.6.1.2.1.2.2.1.10.2": "2438196185", + "1.3.6.1.2.1.2.2.1.10.3": "3214378817", + "1.3.6.1.2.1.2.2.1.10.4": "2438196185", + "1.3.6.1.2.1.2.2.1.10.5": "3214378817", + "1.3.6.1.2.1.2.2.1.8.1": "1", + "1.3.6.1.2.1.2.2.1.8.2": "1", + "1.3.6.1.2.1.2.2.1.8.3": "2", + "1.3.6.1.2.1.2.2.1.8.4": "2", + "1.3.6.1.2.1.2.2.1.8.5": "2", + "1.3.6.1.2.1.2.2.1.4.1": "65536", + "1.3.6.1.2.1.2.2.1.4.2": "1500", + "1.3.6.1.2.1.2.2.1.4.3": "1500", + "1.3.6.1.2.1.2.2.1.4.4": "1500", + "1.3.6.1.2.1.2.2.1.4.5": "1500", + "1.3.6.1.2.1.2.2.1.5.1": "10000000", + "1.3.6.1.2.1.2.2.1.5.2": "0", + "1.3.6.1.2.1.2.2.1.5.3": "0", + "1.3.6.1.2.1.2.2.1.5.4": "0", + "1.3.6.1.2.1.2.2.1.5.5": "0" +} From bd30ed47d9039f76b46246bd8876fb338a09d259 Mon Sep 17 00:00:00 2001 From: purhan Date: Sun, 9 May 2021 19:36:06 +0530 Subject: [PATCH 08/26] [chores] Remove redundant lines --- tests/snmp/airos.py | 86 +++++++++++++---------------- tests/snmp/openwrt.py | 124 ++++++++++++++++++++---------------------- 2 files changed, 95 insertions(+), 115 deletions(-) diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index 683204b..efedb6c 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -23,6 +23,10 @@ def setUp(self): 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', return_value=[1, 2, 3, 4, 5] ) + self.nextcmd_patcher = patch( + 'netengine.backends.snmp.openwrt.SNMP.next', + return_value=[0, 0, 0, [[[0, 0,]]] * 5] + ) self.get_value_patcher = patch( 'netengine.backends.snmp.airos.AirOS.get', side_effect=lambda x: self._get_mocked_getcmd( @@ -32,20 +36,14 @@ def setUp(self): self.get_value_patcher.start() def test_get_value_error(self): - self.get_value_patcher.stop() - with patch( - 'netengine.backends.snmp.openwrt.SNMP.get', - side_effect=lambda x: self.device._oid(x) - ): + with self.get_value_patcher as p: + p.side_effect = lambda x: self.device._oid(x) with self.assertRaises(NetEngineError): self.device.get_value('.') def test_validate_negative_result(self): - self.get_value_patcher.stop() - with patch( - 'netengine.backends.snmp.openwrt.SNMP.get', - side_effect=lambda x: self.device._oid(x) - ): + with self.get_value_patcher as p: + p.side_effect = lambda x: self.device._oid(x) wrong = AirOS('10.40.0.254', 'wrong', 'wrong') self.assertRaises(NetEngineError, wrong.validate) @@ -53,17 +51,12 @@ def test_validate_positive_result(self): self.device.validate() def test_get(self): - self.get_value_patcher.stop() - with self.assertRaises(AttributeError): - self.device.get({}) - - with self.assertRaises(AttributeError): - self.device.get(object) - - with patch( - 'netengine.backends.snmp.openwrt.SNMP.get', - side_effect=lambda x: self.device._oid(x) - ): + with self.get_value_patcher as p: + p.side_effect = lambda x: self.device._oid(x) + with self.assertRaises(AttributeError): + self.device.get({}) + with self.assertRaises(AttributeError): + self.device.get(object) self.device.get('1,3,6,1,2,1,1,5,0') self.device.get(u'1,3,6,1,2,1,1,5,0') self.device.get((1,3,6,1,2,1,1,5,0)) @@ -86,41 +79,40 @@ def test_os(self): self.assertTrue(type(self.device.os) == tuple) def test_get_interfaces(self): - self.interfaces_patcher.start() - self.assertTrue(type(self.device.get_interfaces()) == list) + with self.interfaces_patcher: + self.assertTrue(type(self.device.get_interfaces()) == list) def test_get_interfaces_mtu(self): - self.interfaces_patcher.start() - self.assertTrue(type(self.device.interfaces_mtu) == list) + with self.interfaces_patcher: + self.assertTrue(type(self.device.interfaces_mtu) == list) def test_interfaces_state(self): - self.interfaces_patcher.start() - self.assertTrue(type(self.device.interfaces_state) == list) + with self.interfaces_patcher: + self.assertTrue(type(self.device.interfaces_state) == list) def test_interfaces_speed(self): - self.interfaces_patcher.start() - self.assertTrue(type(self.device.interfaces_speed) == list) + with self.interfaces_patcher: + self.assertTrue(type(self.device.interfaces_speed) == list) def test_interfaces_bytes(self): - self.interfaces_patcher.start() - self.assertTrue(type(self.device.interfaces_bytes) == list) + with self.interfaces_patcher: + self.assertTrue(type(self.device.interfaces_bytes) == list) def test_interfaces_MAC(self): - self.interfaces_patcher.start() - self.assertTrue(type(self.device.interfaces_MAC) == list) + with self.interfaces_patcher: + self.assertTrue(type(self.device.interfaces_MAC) == list) def test_interfaces_type(self): - self.interfaces_patcher.start() - self.assertTrue(type(self.device.interfaces_type) == list) + with self.interfaces_patcher: + self.assertTrue(type(self.device.interfaces_type) == list) def test_interfaces_to_dict(self): - self.interfaces_patcher.start() - self.assertTrue(type(self.device.interfaces_to_dict) == list) + with self.interfaces_patcher: + self.assertTrue(type(self.device.interfaces_to_dict) == list) - @patch('netengine.backends.snmp.openwrt.SNMP.next') - def test_wireless_dbm(self, mock_nextcmd): - mock_nextcmd.return_value = [0, 0, 0, [[[0, 0]]] * 5] - self.assertTrue(type(self.device.wireless_dbm) == list) + def test_wireless_dbm(self): + with self.nextcmd_patcher: + self.assertTrue(type(self.device.wireless_dbm) == list) def test_interfaces_number(self): self.assertTrue(type(self.device.interfaces_number) == int) @@ -135,19 +127,15 @@ def test_RAM_total(self): self.assertTrue(type(self.device.RAM_total) == int) def test_to_dict(self, mock_nextcmd): - self.interfaces_patcher.start() - with patch( - 'netengine.backends.snmp.openwrt.SNMP.next', - return_value=[0, 0, 0, [[[0, 0,]]] * 5] - ): + with self.interfaces_patcher, self.nextcmd_patcher: self.assertTrue(isinstance(self.device.to_dict(), dict)) def test_manufacturer_to_dict(self): self.assertIsNotNone(self.device.to_dict()['manufacturer']) def test_manufacturer(self): - self.interfaces_patcher.start() - self.assertIsNotNone(self.device.manufacturer) + with self.interfaces_patcher: + self.assertIsNotNone(self.device.manufacturer) def test_model(self): self.assertTrue(type(self.device.model) == str) @@ -162,4 +150,4 @@ def test_uptime_tuple(self): self.assertTrue(type(self.device.uptime_tuple) == tuple) def tearDown(self): - self.get_value_patcher.stop() \ No newline at end of file + self.get_value_patcher.stop() diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index 99d2d60..ed5a832 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -1,5 +1,5 @@ import unittest -import mock +from mock import patch from netengine.backends.snmp import OpenWRT from ..settings import settings @@ -17,7 +17,15 @@ def setUp(self): self.device = OpenWRT(self.host, self.community, self.port) self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') - self.get_value_patcher = mock.patch( + self.interfaces_count_patcher = patch( + 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', + return_value=[1, 2, 3, 4, 5] + ) + self.nextcmd_patcher = patch( + 'netengine.backends.snmp.openwrt.SNMP.next', + return_value=[0, 0, 0, [0] * 5] + ) + self.get_value_patcher = patch( 'netengine.backends.snmp.openwrt.OpenWRT.get_value', side_effect=lambda x: self._get_mocked_value( oid=x, data=self.oid_mock_data @@ -28,13 +36,11 @@ def setUp(self): def test_os(self): self.assertTrue(type(self.device.os) == tuple) - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') - def test_manufacturer(self, mock_nextcmd, mock_value_to_retr): - mock_value_to_retr.return_value = [1, 2, 3, 4, 5] - mock_nextcmd.return_value = [0, 0, 0, [0] * 5] - self.assertIsNotNone(self.device.manufacturer) - mock_nextcmd.assert_called_once_with('1.3.6.1.2.1.2.2.1.6.') + def test_manufacturer(self): + with self.interfaces_count_patcher: + with self.nextcmd_patcher as p: + self.assertIsNotNone(self.device.manufacturer) + p.assert_called_once_with('1.3.6.1.2.1.2.2.1.6.') def test_name(self): self.assertTrue(type(self.device.name) == str) @@ -45,71 +51,57 @@ def test_uptime(self): def test_uptime_tuple(self): self.assertTrue(type(self.device.uptime_tuple) == tuple) - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - def test_get_interfaces(self, mock_interfaces_count): - mock_interfaces_count.return_value = [1, 2, 3, 4, 5] - self.assertTrue(type(self.device.get_interfaces()) == list) + def test_get_interfaces(self): + with self.interfaces_count_patcher: + self.assertTrue(type(self.device.get_interfaces()) == list) def test_interfaces_speed(self): self.assertTrue(type(self.device.interfaces_speed) == list) - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - def test_interfaces_bytes(self, mock_interfaces_count): - self.assertTrue(type(self.device.interfaces_bytes) == list) - - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') - def test_interfaces_MAC(self, mock_nextcmd, mock_interfaces_count): - mock_interfaces_count.return_value = [1, 2, 3, 4, 5] - mock_nextcmd.return_value = [0, 0, 0, [0] * 5] - self.assertTrue(type(self.device.interfaces_MAC) == list) - - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - def test_interfaces_type(self, mock_interfaces_count): - mock_interfaces_count.return_value = [1, 2, 3, 4, 5] - self.assertTrue(type(self.device.interfaces_type) == list) - - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - def test_interfaces_mtu(self, mock_interfaces_count): - mock_interfaces_count.return_value = [1, 2, 3, 4, 5] - self.assertTrue(type(self.device.interfaces_mtu) == list) - - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - def test_interfaces_state(self, mock_interfaces_count): - mock_interfaces_count.return_value = [1, 2, 3, 4, 5] - self.assertTrue(type(self.device.interfaces_state) == list) - - @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') - def test_interfaces_to_dict(self, mock_nextcmd): - mock_nextcmd.return_value = (0, 0, 0, []) - self.assertTrue(type(self.device.interfaces_to_dict) == list) - - @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') - def test_interface_addr_and_mask(self, mock_nextcmd): - mock_nextcmd.return_value = (0, 0, 0, []) - self.assertTrue(type(self.device.interface_addr_and_mask) == dict) + def test_interfaces_bytes(self): + with self.interfaces_count_patcher: + self.assertTrue(type(self.device.interfaces_bytes) == list) - def test_RAM_total(self): - self.assertTrue(type(self.device.RAM_total) == int) + def test_interfaces_MAC(self): + with self.interfaces_count_patcher, self.nextcmd_patcher: + self.assertTrue(type(self.device.interfaces_MAC) == list) - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') - def test_to_dict(self, mock_nextcmd, mock_interfaces_count): - mock_interfaces_count.return_value = [1, 2, 3, 4, 5] - mock_nextcmd.return_value = [0, 0, 0, [0] * 5] - device_dict = self.device.to_dict() + def test_interfaces_type(self): + with self.interfaces_count_patcher: + self.assertTrue(type(self.device.interfaces_type) == list) - self.assertTrue(isinstance(device_dict, dict)) - self.assertEqual( - len(device_dict['interfaces']), len(self.device.get_interfaces()) - ) + def test_interfaces_mtu(self): + with self.interfaces_count_patcher: + self.assertTrue(type(self.device.interfaces_mtu) == list) + + def test_interfaces_state(self): + with self.interfaces_count_patcher: + self.assertTrue(type(self.device.interfaces_state) == list) + + def test_interfaces_to_dict(self): + with self.nextcmd_patcher as p: + p.return_value = (0, 0, 0, []) + self.assertTrue(type(self.device.interfaces_to_dict) == list) + + def test_interface_addr_and_mask(self): + with self.nextcmd_patcher as p: + p.return_value = (0, 0, 0, []) + self.assertTrue(type(self.device.interface_addr_and_mask) == dict) + + def test_RAM_total(self): + self.assertTrue(type(self.device.RAM_total) == int) - @mock.patch('netengine.backends.snmp.openwrt.SNMP._value_to_retrieve') - @mock.patch('netengine.backends.snmp.openwrt.SNMP.next') - def test_manufacturer_to_dict(self, mock_nextcmd, mock_interfaces_count): - mock_interfaces_count.return_value = [1, 2, 3, 4, 5] - mock_nextcmd.return_value = [0, 0, 0, [0] * 5] - self.assertIsNotNone(self.device.to_dict()['manufacturer']) + def test_to_dict(self): + with self.interfaces_count_patcher, self.nextcmd_patcher: + device_dict = self.device.to_dict() + self.assertTrue(isinstance(device_dict, dict)) + self.assertEqual( + len(device_dict['interfaces']), len(self.device.get_interfaces()) + ) + + def test_manufacturer_to_dict(self): + with self.interfaces_count_patcher, self.nextcmd_patcher: + self.assertIsNotNone(self.device.to_dict()['manufacturer']) def tearDown(self): self.get_value_patcher.stop() From 2a3e44477e05c49fd029c8c035608ada3532b8b1 Mon Sep 17 00:00:00 2001 From: purhan Date: Wed, 19 May 2021 18:39:59 +0530 Subject: [PATCH 09/26] [qa] Mock remaining tests for SNMP AirOS --- tests/snmp/airos.py | 13 +++++++++---- tests/static/__init__.py | 9 +++++++++ tests/static/test-airos-snmp.json | 10 +++++----- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index efedb6c..6bfe781 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -118,7 +118,9 @@ def test_interfaces_number(self): self.assertTrue(type(self.device.interfaces_number) == int) def test_wireless_to_dict(self): - self.assertTrue(type(self.device.wireless_links) == list) + with self.interfaces_patcher, self.nextcmd_patcher as np: + np.side_effect = lambda x: self._get_mocked_wireless_links(oid=x) + self.assertTrue(type(self.device.wireless_links) == list) def test_RAM_free(self): self.assertTrue(type(self.device.RAM_free) == int) @@ -126,12 +128,15 @@ def test_RAM_free(self): def test_RAM_total(self): self.assertTrue(type(self.device.RAM_total) == int) - def test_to_dict(self, mock_nextcmd): - with self.interfaces_patcher, self.nextcmd_patcher: + def test_to_dict(self): + with self.interfaces_patcher, self.nextcmd_patcher as np: + np.side_effect = lambda x: self._get_mocked_wireless_links(oid=x) self.assertTrue(isinstance(self.device.to_dict(), dict)) def test_manufacturer_to_dict(self): - self.assertIsNotNone(self.device.to_dict()['manufacturer']) + with self.interfaces_patcher, self.nextcmd_patcher as np: + np.side_effect = lambda x: self._get_mocked_wireless_links(oid=x) + self.assertIsNotNone(self.device.to_dict()['manufacturer']) def test_manufacturer(self): with self.interfaces_patcher: diff --git a/tests/static/__init__.py b/tests/static/__init__.py index 0916a26..1ac85b9 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -22,3 +22,12 @@ def _get_mocked_getcmd(oid, data, *args, **kwargs): if type(result) == list: result = "\n".join(result[0:]) return [0, 0, 0, [[0, result.encode('ascii', 'ignore')], 0]] + + @staticmethod + def _get_mocked_wireless_links(oid): + return_data = { + '1.3.6.1.4.1.14988.1.1.1.2.1': [0, 0, 0, [[[0, 0], 0]] * 28], + '1.3.6.1.4.1.14988.1.1.1.2.1.3': [0, 0, 0, [0, 0]], + '1.3.6.1.4.1.14988.1.1.1.2.1.3.0': [None, 0, 0, []], + } + return return_data[oid] diff --git a/tests/static/test-airos-snmp.json b/tests/static/test-airos-snmp.json index f54ee6a..e470631 100644 --- a/tests/static/test-airos-snmp.json +++ b/tests/static/test-airos-snmp.json @@ -7,11 +7,11 @@ "1.3.6.1.4.1.10002.1.1.1.1.1.0": "126272", "1.2.840.10036.3.1.2.1.4.5": "XM.ar7240.v5.5.12536.120406.1455", "1.2.840.10036.3.1.2.1.3.5": "NanoStation Loco M2", - "1.3.6.1.2.1.2.2.1.2.1": "wired0", - "1.3.6.1.2.1.2.2.1.2.2": "eth0", - "1.3.6.1.2.1.2.2.1.2.3": "wifi1", - "1.3.6.1.2.1.2.2.1.2.4": "internal_svc", - "1.3.6.1.2.1.2.2.1.2.5": "primarylan1", + "1.3.6.1.2.1.2.2.1.2.1": "\\xd4\\xa0*", + "1.3.6.1.2.1.2.2.1.2.2": "\\xd4\\xa0*", + "1.3.6.1.2.1.2.2.1.2.3": "\\xd4\\xa0*", + "1.3.6.1.2.1.2.2.1.2.4": "\\xd4\\xa0*", + "1.3.6.1.2.1.2.2.1.2.5": "\\xd4\\xa0*", "1.3.6.1.2.1.2.2.1.6.1": "\b\u0000''�\u0010\u0014", "1.3.6.1.2.1.2.2.1.6.2": "\b\u0000''�\u0010\u0000", "1.3.6.1.2.1.2.2.1.6.3": "\b\u0000''�\u0010\u0015", From 4485d43af977a6b2f51c99d0a0e9ff5527d5c629 Mon Sep 17 00:00:00 2001 From: purhan Date: Wed, 19 May 2021 18:42:48 +0530 Subject: [PATCH 10/26] [chores] Rename function for clarity --- tests/snmp/airos.py | 2 +- tests/static/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index 6bfe781..4b57ea6 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -29,7 +29,7 @@ def setUp(self): ) self.get_value_patcher = patch( 'netengine.backends.snmp.airos.AirOS.get', - side_effect=lambda x: self._get_mocked_getcmd( + side_effect=lambda x: self._get_encoded_mocked_value( oid=x, data=self.oid_mock_data ), ) diff --git a/tests/static/__init__.py b/tests/static/__init__.py index 1ac85b9..1e0ec02 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -17,7 +17,7 @@ def _get_mocked_value(oid, data, *args, **kwargs): return result @staticmethod - def _get_mocked_getcmd(oid, data, *args, **kwargs): + def _get_encoded_mocked_value(oid, data, *args, **kwargs): result = data[oid] if type(result) == list: result = "\n".join(result[0:]) From 6a000dbd033b748887af98300d2ac39ed84771a5 Mon Sep 17 00:00:00 2001 From: purhan Date: Thu, 20 May 2021 15:38:48 +0530 Subject: [PATCH 11/26] [change] Remove the requirement of test-settings.json from unittests --- docs/source/topics/usage.rst | 5 ----- test-settings.example.json | 33 --------------------------------- tests/base.py | 3 ++- tests/http/airos.py | 6 +----- tests/http/base.py | 7 +------ tests/settings.py | 2 -- tests/snmp/airos.py | 7 +------ tests/snmp/base.py | 7 +++---- tests/snmp/openwrt.py | 8 +------- tests/ssh/airos.py | 8 +------- tests/ssh/base.py | 1 - tests/ssh/openwrt.py | 1 - 12 files changed, 10 insertions(+), 78 deletions(-) delete mode 100644 test-settings.example.json diff --git a/docs/source/topics/usage.rst b/docs/source/topics/usage.rst index d143e54..c52271b 100755 --- a/docs/source/topics/usage.rst +++ b/docs/source/topics/usage.rst @@ -40,11 +40,6 @@ Clone repo:: cd netengine/ -Edit settings json file according to your network:: - - cp test-settings.example.json test-settings.json - vim test-settings.json - Run tests with:: nosetests diff --git a/test-settings.example.json b/test-settings.example.json deleted file mode 100644 index 1208c68..0000000 --- a/test-settings.example.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "base-ssh": { - "host": "yourhost", - "username": "root", - "password": "password" - }, - "airos-ssh": { - "host": "your_airos_device", - "username": "root", - "password": "password" - }, - "openwrt-ssh": { - "host": "your_openwrt_device", - "username": "root", - "password": "password" - }, - - "base-snmp": { - "host": "yourhost", - "community": "public", - "port": 161 - }, - "airos-snmp": { - "host": "your_airos_device", - "community": "public", - "port": 161 - }, - "openwrt-snmp": { - "host": "your_openwrt_device", - "community": "public", - "port": 161 - } -} \ No newline at end of file diff --git a/tests/base.py b/tests/base.py index ff42c19..0079aca 100644 --- a/tests/base.py +++ b/tests/base.py @@ -89,4 +89,5 @@ def test_base_backend(self): def test_get_manufacturer_unicode(self): device = BaseBackend() - self.assertIsNone(device.get_manufacturer(u"wrong MAC")) + with self.assertRaises(NetEngineError): + device.get_manufacturer(u"wrong MAC") diff --git a/tests/http/airos.py b/tests/http/airos.py index 263af8b..3044eec 100644 --- a/tests/http/airos.py +++ b/tests/http/airos.py @@ -1,7 +1,6 @@ import unittest from netengine.backends.http import AirOS -from ..settings import settings __all__ = ['TestHTTP'] @@ -10,10 +9,7 @@ class TestHTTP(unittest.TestCase): def setUp(self): - self.host = settings['base-http']['host'] - self.username = settings['base-http']['username'] - self.password = settings['base-http']['password'] - self.device = AirOS(self.host, self.username, self.password) + self.device = AirOS('test-host.com', 'test-user', 'test-password') self.assertTrue(self.device.__netengine__) def test_info(self): diff --git a/tests/http/base.py b/tests/http/base.py index 0952eb1..d1d10d1 100644 --- a/tests/http/base.py +++ b/tests/http/base.py @@ -3,8 +3,6 @@ from netengine.backends.http import HTTP from netengine.exceptions import NetEngineError -from ..settings import settings - __all__ = ['TestHTTP'] @@ -12,8 +10,5 @@ class TestHTTP(unittest.TestCase): def setUp(self): - self.host = settings['base-http']['host'] - self.username = settings['base-http']['username'] - self.password = settings['base-http']['password'] - self.device = HTTP(self.host, self.username, self.password) + self.device = HTTP('test-host.com', 'test-user', 'test-password') self.assertTrue(self.device.__netengine__) diff --git a/tests/settings.py b/tests/settings.py index eb963c7..0349a44 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1,3 +1 @@ import json - -settings = json.loads(open('./test-settings.json').read()) \ No newline at end of file diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index 4b57ea6..bd464d3 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -3,7 +3,6 @@ from netengine.backends.snmp import AirOS from netengine.exceptions import NetEngineError -from ..settings import settings from ..static import MockOutputMixin @@ -13,11 +12,7 @@ class TestSNMPAirOS(unittest.TestCase, MockOutputMixin): def setUp(self): - self.host = settings['airos-snmp']['host'] - self.community = settings['airos-snmp']['community'] - self.port = settings['airos-snmp'].get('port', 161) - - self.device = AirOS(self.host, self.community, port=self.port) + self.device = AirOS('0.0.0.0', 'public', 161) self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') self.interfaces_patcher = patch( 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', diff --git a/tests/snmp/base.py b/tests/snmp/base.py index 347f4e3..5c01444 100644 --- a/tests/snmp/base.py +++ b/tests/snmp/base.py @@ -3,7 +3,6 @@ from netengine.backends.snmp import SNMP from netengine.exceptions import NetEngineError -from ..settings import settings __all__ = ['TestSNMP'] @@ -12,9 +11,9 @@ class TestSNMP(unittest.TestCase): def setUp(self): - self.host = settings['base-snmp']['host'] - self.community = settings['base-snmp']['community'] - self.port = settings['base-snmp'].get('port', 161) + self.host = '0.0.0.0' + self.community = 'public' + self.port = 161 def test_instantiation(self): device = SNMP(self.host, self.community, self.port) diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index ed5a832..34f54ea 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -2,7 +2,6 @@ from mock import patch from netengine.backends.snmp import OpenWRT -from ..settings import settings from ..static import MockOutputMixin __all__ = ['TestSNMPOpenWRT'] @@ -10,12 +9,7 @@ class TestSNMPOpenWRT(unittest.TestCase, MockOutputMixin): def setUp(self): - self.host = settings['openwrt-snmp']['host'] - self.community = settings['openwrt-snmp']['community'] - self.port = settings['openwrt-snmp'].get('port', 161) - - self.device = OpenWRT(self.host, self.community, self.port) - + self.device = OpenWRT('0.0.0.0', 'public', 161) self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') self.interfaces_count_patcher = patch( 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', diff --git a/tests/ssh/airos.py b/tests/ssh/airos.py index 47cdcb0..2803375 100644 --- a/tests/ssh/airos.py +++ b/tests/ssh/airos.py @@ -4,7 +4,6 @@ from netengine.backends.ssh import AirOS -from ..settings import settings from ..static import MockOutputMixin @@ -15,12 +14,7 @@ class TestSSHAirOS(unittest.TestCase, MockOutputMixin): @mock.patch('paramiko.SSHClient.connect') def setUp(self, mocked_connect): - self.host = settings['airos-ssh']['host'] - self.username = settings['airos-ssh']['username'] - self.password = settings['airos-ssh']['password'] - self.port = settings['airos-ssh'].get('port', 22) - - self.device = AirOS(self.host, self.username, self.password, self.port) + self.device = AirOS('test-host.com', 'test-user', 'test-pass', 22) self.device.connect() mocked_connect.assert_called_once() ssh_mock_data = self._load_mock_json('/test-airos-ssh.json') diff --git a/tests/ssh/base.py b/tests/ssh/base.py index 84a28ca..38a05ed 100644 --- a/tests/ssh/base.py +++ b/tests/ssh/base.py @@ -5,7 +5,6 @@ from netengine.exceptions import NetEngineError from paramiko.ssh_exception import SSHException -from ..settings import settings from ..static import MockOutputMixin diff --git a/tests/ssh/openwrt.py b/tests/ssh/openwrt.py index 6901677..b4db589 100644 --- a/tests/ssh/openwrt.py +++ b/tests/ssh/openwrt.py @@ -3,7 +3,6 @@ from netengine.backends.ssh import OpenWRT -from ..settings import settings from ..static import MockOutputMixin From 26c4f52a64f0d8e3d77ccf8191e53ffde7beb026 Mon Sep 17 00:00:00 2001 From: purhan Date: Thu, 20 May 2021 18:59:32 +0530 Subject: [PATCH 12/26] [chores] Include http tests in __init__.py --- tests/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/__init__.py b/tests/__init__.py index bab0017..4f5255a 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -3,3 +3,4 @@ from .ssh import * from .snmp import * from .bin import * +from .http import * From f6f4eb538f051f4ca1fa05f30adb905e2ee84c54 Mon Sep 17 00:00:00 2001 From: purhan Date: Fri, 21 May 2021 15:51:26 +0530 Subject: [PATCH 13/26] [qa] Allow disabling mocks to use real devices in tests --- docs/source/topics/usage.rst | 20 +++++++++----- requirements-test.txt | 1 + runtests.py | 32 ++++++++++++++++++++++ test-settings.example.json | 44 ++++++++++++++++++++++++++++++ tests/http/airos.py | 6 +++- tests/http/base.py | 7 ++++- tests/settings.py | 5 ++++ tests/snmp/airos.py | 12 +++++++- tests/snmp/base.py | 7 +++-- tests/snmp/openwrt.py | 12 +++++++- tests/ssh/airos.py | 21 ++++++++++---- tests/ssh/base.py | 53 ++++++++++++++++++++---------------- tests/ssh/openwrt.py | 21 ++++++++++---- tests/static/__init__.py | 41 ++++++++++++++++++++++++++++ 14 files changed, 235 insertions(+), 47 deletions(-) create mode 100644 requirements-test.txt create mode 100755 runtests.py create mode 100644 test-settings.example.json diff --git a/docs/source/topics/usage.rst b/docs/source/topics/usage.rst index c52271b..a4a19ec 100755 --- a/docs/source/topics/usage.rst +++ b/docs/source/topics/usage.rst @@ -30,19 +30,22 @@ Further example will be found inside dedicated docs for every backend Running tests ************* -Install nose:: +Install test reqirements:: - pip install nose + pip install -r reqirements.txt + pip install -r requirements-test.txt -Clone repo:: +Run tests with:: - git clone git://github.com/ninuxorg/netengine + ./runtests - cd netengine/ +To run tests on real devices, first copy the settings file:: -Run tests with:: + cp test-settings.example.json test-settings.json - nosetests +Then change the credentials accordingly, now run tests with:: + + ./runtests --disable-mocks=1 --test-settings='test-settings.json' See test coverage with:: @@ -62,3 +65,6 @@ Run specific tests by specifying the relative path:: nosetests tests.ssh # ssh airos specific tests nosetests tests.ssh.airos + + # run without mocks with a custom test file + DISABLE_MOCKS=1 TEST_SETTINGS_FILE='test-settings.json' nosetests tests.ssh diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 0000000..f3c7e8e --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1 @@ +nose diff --git a/runtests.py b/runtests.py new file mode 100755 index 0000000..cc4d89c --- /dev/null +++ b/runtests.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import argparse +import os +try: + import nose +except: + message = """nose package not installed, install test requirements with: + pip install -r requirements-test.txt + """ + raise ImportError(message) + +if __name__ == "__main__": + file_path = os.path.abspath(__file__) + tests_path = os.path.join(os.path.abspath(os.path.dirname(file_path)), "tests") + parser = argparse.ArgumentParser() + parser.add_argument('--disable-mocks', default='1') + parser.add_argument('--test-settings', default='test-settings.example.json') + args = parser.parse_args(args=None) + os.environ["DISABLE_MOCKS"] = args.disable_mocks + os.environ["TEST_SETTINGS_FILE"] = os.path.join( + os.path.dirname(file_path), args.test_settings + ) + result = nose.run( + argv=[ + os.path.abspath(__file__), + "--with-cov", + "--cover-package=netengine", + tests_path + ] + ) diff --git a/test-settings.example.json b/test-settings.example.json new file mode 100644 index 0000000..7babb20 --- /dev/null +++ b/test-settings.example.json @@ -0,0 +1,44 @@ +{ + "base-ssh": { + "host": "yourhost", + "username": "root", + "password": "password" + }, + "airos-ssh": { + "host": "your_airos_device", + "username": "root", + "password": "password" + }, + "openwrt-ssh": { + "host": "your_openwrt_device", + "username": "root", + "password": "password" + }, + + "base-snmp": { + "host": "0.0.0.0", + "community": "public", + "port": 161 + }, + "airos-snmp": { + "host": "0.0.0.0", + "community": "public", + "port": 161 + }, + "openwrt-snmp": { + "host": "0.0.0.0", + "community": "public", + "port": 161 + }, + + "base-http": { + "host": "test-host.com", + "username": "test-username", + "password": "test-password" + }, + "airos-http": { + "host": "test-host.com", + "username": "test-username", + "password": "test-password" + } +} diff --git a/tests/http/airos.py b/tests/http/airos.py index 3044eec..263af8b 100644 --- a/tests/http/airos.py +++ b/tests/http/airos.py @@ -1,6 +1,7 @@ import unittest from netengine.backends.http import AirOS +from ..settings import settings __all__ = ['TestHTTP'] @@ -9,7 +10,10 @@ class TestHTTP(unittest.TestCase): def setUp(self): - self.device = AirOS('test-host.com', 'test-user', 'test-password') + self.host = settings['base-http']['host'] + self.username = settings['base-http']['username'] + self.password = settings['base-http']['password'] + self.device = AirOS(self.host, self.username, self.password) self.assertTrue(self.device.__netengine__) def test_info(self): diff --git a/tests/http/base.py b/tests/http/base.py index d1d10d1..0952eb1 100644 --- a/tests/http/base.py +++ b/tests/http/base.py @@ -3,6 +3,8 @@ from netengine.backends.http import HTTP from netengine.exceptions import NetEngineError +from ..settings import settings + __all__ = ['TestHTTP'] @@ -10,5 +12,8 @@ class TestHTTP(unittest.TestCase): def setUp(self): - self.device = HTTP('test-host.com', 'test-user', 'test-password') + self.host = settings['base-http']['host'] + self.username = settings['base-http']['username'] + self.password = settings['base-http']['password'] + self.device = HTTP(self.host, self.username, self.password) self.assertTrue(self.device.__netengine__) diff --git a/tests/settings.py b/tests/settings.py index 0349a44..519fbcb 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1 +1,6 @@ import json +import os + +settings_file = os.getenv('TEST_SETTINGS_FILE', './test-settings.json') +settings = json.loads(open(settings_file).read()) +settings['disable_mocks'] = os.getenv('DISABLE_MOCKS', '0') is '1' diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index bd464d3..0fcba81 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -3,6 +3,7 @@ from netengine.backends.snmp import AirOS from netengine.exceptions import NetEngineError +from ..settings import settings from ..static import MockOutputMixin @@ -12,7 +13,12 @@ class TestSNMPAirOS(unittest.TestCase, MockOutputMixin): def setUp(self): - self.device = AirOS('0.0.0.0', 'public', 161) + self.host = settings['airos-snmp']['host'] + self.community = settings['airos-snmp']['community'] + self.port = settings['airos-snmp'].get('port', 161) + self.device = AirOS(self.host, self.community, port=self.port) + + # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') self.interfaces_patcher = patch( 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', @@ -28,6 +34,10 @@ def setUp(self): oid=x, data=self.oid_mock_data ), ) + if settings['disable_mocks']: + self.interfaces_patcher = self.DisableMock() + self.nextcmd_patcher = self.DisableMock() + self.get_value_patcher = self.DisableMock() self.get_value_patcher.start() def test_get_value_error(self): diff --git a/tests/snmp/base.py b/tests/snmp/base.py index 5c01444..347f4e3 100644 --- a/tests/snmp/base.py +++ b/tests/snmp/base.py @@ -3,6 +3,7 @@ from netengine.backends.snmp import SNMP from netengine.exceptions import NetEngineError +from ..settings import settings __all__ = ['TestSNMP'] @@ -11,9 +12,9 @@ class TestSNMP(unittest.TestCase): def setUp(self): - self.host = '0.0.0.0' - self.community = 'public' - self.port = 161 + self.host = settings['base-snmp']['host'] + self.community = settings['base-snmp']['community'] + self.port = settings['base-snmp'].get('port', 161) def test_instantiation(self): device = SNMP(self.host, self.community, self.port) diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index 34f54ea..1bcc77e 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -2,6 +2,7 @@ from mock import patch from netengine.backends.snmp import OpenWRT +from ..settings import settings from ..static import MockOutputMixin __all__ = ['TestSNMPOpenWRT'] @@ -9,7 +10,12 @@ class TestSNMPOpenWRT(unittest.TestCase, MockOutputMixin): def setUp(self): - self.device = OpenWRT('0.0.0.0', 'public', 161) + self.host = settings['openwrt-snmp']['host'] + self.community = settings['openwrt-snmp']['community'] + self.port = settings['openwrt-snmp'].get('port', 161) + self.device = OpenWRT(self.host, self.community, self.port) + + # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') self.interfaces_count_patcher = patch( 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', @@ -25,6 +31,10 @@ def setUp(self): oid=x, data=self.oid_mock_data ).encode('ascii', 'ignore'), ) + if settings['disable_mocks']: + self.interfaces_count_patcher = self.DisableMock() + self.nextcmd_patcher = self.DisableMock() + self.get_value_patcher = self.DisableMock() self.get_value_patcher.start() def test_os(self): diff --git a/tests/ssh/airos.py b/tests/ssh/airos.py index 2803375..abb2f6d 100644 --- a/tests/ssh/airos.py +++ b/tests/ssh/airos.py @@ -4,6 +4,7 @@ from netengine.backends.ssh import AirOS +from ..settings import settings from ..static import MockOutputMixin @@ -12,11 +13,14 @@ class TestSSHAirOS(unittest.TestCase, MockOutputMixin): - @mock.patch('paramiko.SSHClient.connect') - def setUp(self, mocked_connect): - self.device = AirOS('test-host.com', 'test-user', 'test-pass', 22) - self.device.connect() - mocked_connect.assert_called_once() + def setUp(self): + self.host = settings['airos-ssh']['host'] + self.username = settings['airos-ssh']['username'] + self.password = settings['airos-ssh']['password'] + self.port = settings['airos-ssh'].get('port', 22) + self.device = AirOS(self.host, self.username, self.password, self.port) + + # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-airos-ssh.json') self.ssh_patcher = mock.patch( 'netengine.backends.ssh.airos.SSH.run', @@ -24,6 +28,13 @@ def setUp(self, mocked_connect): oid=x, data=ssh_mock_data ), ) + self.connect_patcher = mock.patch('paramiko.SSHClient.connect') + if settings['disable_mocks']: + self.ssh_patcher = self.DisableMock() + self.connect_patcher = self.DisableMock() + with self.connect_patcher as p: + self.device.connect() + p.assert_called_once() self.ssh_patcher.start() def test_to_dict(self): diff --git a/tests/ssh/base.py b/tests/ssh/base.py index 38a05ed..8ad77bd 100644 --- a/tests/ssh/base.py +++ b/tests/ssh/base.py @@ -5,6 +5,7 @@ from netengine.exceptions import NetEngineError from paramiko.ssh_exception import SSHException +from ..settings import settings from ..static import MockOutputMixin @@ -12,38 +13,44 @@ class TestSSH(unittest.TestCase, MockOutputMixin): - @mock.patch('paramiko.SSHClient.connect') - def setUp(self, mocked_connect): - self.host = 'test-host.com' - self.username = 'test-user' - self.password = 'test-password' - self.port = 22 + + def setUp(self): + self.host = settings['base-ssh']['host'] + self.username = settings['base-ssh']['username'] + self.password = settings['base-ssh']['password'] + self.port = settings['base-ssh'].get('port', 22) self.device = SSH(self.host, self.username, self.password, self.port) self.assertTrue(self.device.__netengine__) - self.device.connect() - mocked_connect.assert_called_once_with( - self.host, username=self.username, password=self.password, port=self.port - ) + + # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-base-ssh.json') self.exec_command_patcher = mock.patch( 'netengine.backends.ssh.base.SSH.run', side_effect=lambda x: self._get_mocked_value(oid=x, data=ssh_mock_data), ) + self.connect_patcher = mock.patch('paramiko.SSHClient.connect') + self.close_patcher = mock.patch('paramiko.SSHClient.close') + if settings['disable_mocks']: + self.exec_command_patcher = self. self.DisableMock() + with self.connect_patcher as p: + self.device.connect() + p.assert_called_once_with( + self.host, username=self.username, password=self.password, port=self.port + ) self.exec_command_patcher.start() - @mock.patch('paramiko.SSHClient.connect') - def test_validate_negative_result(self, mocked_connect): - mocked_connect.side_effect = SSHException - wrong = SSH('10.40.0.254', 'root', 'pwd') - self.assertRaises(NetEngineError, wrong.validate) - - @mock.patch('paramiko.SSHClient.close') - @mock.patch('paramiko.SSHClient.connect') - def test_validate_positive_result(self, mocked_connect, mocked_close): - self.device.disconnect() - self.device.validate() - mocked_connect.assert_called_once() - self.assertEqual(mocked_close.call_count, 2) + def test_validate_negative_result(self): + with self.connect_patcher as p: + p.side_effect = SSHException + wrong = SSH('10.40.0.254', 'root', 'pwd') + self.assertRaises(NetEngineError, wrong.validate) + + def test_validate_positive_result(self): + with self.connect_patcher as cn, self.close_patcher as cl: + self.device.disconnect() + self.device.validate() + cn.assert_called_once() + self.assertEqual(cl.call_count, 2) def test_olsr(self): print(self.device.olsr) diff --git a/tests/ssh/openwrt.py b/tests/ssh/openwrt.py index b4db589..4446962 100644 --- a/tests/ssh/openwrt.py +++ b/tests/ssh/openwrt.py @@ -3,6 +3,7 @@ from netengine.backends.ssh import OpenWRT +from ..settings import settings from ..static import MockOutputMixin @@ -11,11 +12,14 @@ class TestSSHOpenWRT(unittest.TestCase, MockOutputMixin): - @mock.patch('paramiko.SSHClient.connect') - def setUp(self, mocked_connect): - self.device = OpenWRT('test-host.com', 'test-user', 'test-pass', 22) - self.device.connect() - mocked_connect.assert_called_once() + def setUp(self): + self.host = settings['openwrt-ssh']['host'] + self.username = settings['openwrt-ssh']['username'] + self.password = settings['openwrt-ssh']['password'] + self.port = settings['openwrt-ssh'].get('port', 22) + self.device = OpenWRT(self.host, self.username, self.password, self.port) + + # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-openwrt-ssh.json') self.ssh_patcher = mock.patch( 'netengine.backends.ssh.openwrt.SSH.run', @@ -23,6 +27,13 @@ def setUp(self, mocked_connect): oid=x, data=ssh_mock_data ), ) + self.connect_patcher = mock.patch('paramiko.SSHClient.connect') + if settings['disable_mocks']: + self.ssh_patcher = self.DisableMock() + self.connect_patcher = self.DisableMock() + with self.connect_patcher as p: + self.device.connect() + p.assert_called_once() self.ssh_patcher.start() def test_properties(self): diff --git a/tests/static/__init__.py b/tests/static/__init__.py index 1e0ec02..8e62b04 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -1,7 +1,48 @@ import json import os + class MockOutputMixin(object): + + class DisableMock(object): + """ + Disables the mock object in context managers restoring the mocked + function to its original state + """ + + def assert_called(*args, **kwargs): + pass + + def assert_not_called(*args, **kwargs): + pass + + def assert_called_once(*args, **kwargs): + pass + + def assert_called_with(*args, **kwargs): + pass + + def assert_called_once_with(*args, **kwargs): + pass + + def assert_has_calls(*args, **kwargs): + pass + + def assert_any_call(*args, **kwargs): + pass + + def start(self): + pass + + def stop(self): + pass + + def __enter__(self, *args, **kwargs): + return self + + def __exit__(self, *args, **kwargs): + pass + @staticmethod def _load_mock_json(file): base_dir = os.path.dirname(os.path.abspath(__file__)) From d4298bff42906f82defabeaf512649e062851ff4 Mon Sep 17 00:00:00 2001 From: purhan Date: Sat, 22 May 2021 12:05:07 +0530 Subject: [PATCH 14/26] Revert "[qa] Allow disabling mocks to use real devices in tests" This reverts commit f6f4eb538f051f4ca1fa05f30adb905e2ee84c54. --- docs/source/topics/usage.rst | 20 +++++--------- requirements-test.txt | 1 - runtests.py | 32 ---------------------- test-settings.example.json | 44 ------------------------------ tests/http/airos.py | 6 +--- tests/http/base.py | 7 +---- tests/settings.py | 5 ---- tests/snmp/airos.py | 12 +------- tests/snmp/base.py | 7 ++--- tests/snmp/openwrt.py | 12 +------- tests/ssh/airos.py | 21 ++++---------- tests/ssh/base.py | 53 ++++++++++++++++-------------------- tests/ssh/openwrt.py | 21 ++++---------- tests/static/__init__.py | 41 ---------------------------- 14 files changed, 47 insertions(+), 235 deletions(-) delete mode 100644 requirements-test.txt delete mode 100755 runtests.py delete mode 100644 test-settings.example.json diff --git a/docs/source/topics/usage.rst b/docs/source/topics/usage.rst index a4a19ec..c52271b 100755 --- a/docs/source/topics/usage.rst +++ b/docs/source/topics/usage.rst @@ -30,22 +30,19 @@ Further example will be found inside dedicated docs for every backend Running tests ************* -Install test reqirements:: +Install nose:: - pip install -r reqirements.txt - pip install -r requirements-test.txt + pip install nose -Run tests with:: - - ./runtests +Clone repo:: -To run tests on real devices, first copy the settings file:: + git clone git://github.com/ninuxorg/netengine - cp test-settings.example.json test-settings.json + cd netengine/ -Then change the credentials accordingly, now run tests with:: +Run tests with:: - ./runtests --disable-mocks=1 --test-settings='test-settings.json' + nosetests See test coverage with:: @@ -65,6 +62,3 @@ Run specific tests by specifying the relative path:: nosetests tests.ssh # ssh airos specific tests nosetests tests.ssh.airos - - # run without mocks with a custom test file - DISABLE_MOCKS=1 TEST_SETTINGS_FILE='test-settings.json' nosetests tests.ssh diff --git a/requirements-test.txt b/requirements-test.txt deleted file mode 100644 index f3c7e8e..0000000 --- a/requirements-test.txt +++ /dev/null @@ -1 +0,0 @@ -nose diff --git a/runtests.py b/runtests.py deleted file mode 100755 index cc4d89c..0000000 --- a/runtests.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import argparse -import os -try: - import nose -except: - message = """nose package not installed, install test requirements with: - pip install -r requirements-test.txt - """ - raise ImportError(message) - -if __name__ == "__main__": - file_path = os.path.abspath(__file__) - tests_path = os.path.join(os.path.abspath(os.path.dirname(file_path)), "tests") - parser = argparse.ArgumentParser() - parser.add_argument('--disable-mocks', default='1') - parser.add_argument('--test-settings', default='test-settings.example.json') - args = parser.parse_args(args=None) - os.environ["DISABLE_MOCKS"] = args.disable_mocks - os.environ["TEST_SETTINGS_FILE"] = os.path.join( - os.path.dirname(file_path), args.test_settings - ) - result = nose.run( - argv=[ - os.path.abspath(__file__), - "--with-cov", - "--cover-package=netengine", - tests_path - ] - ) diff --git a/test-settings.example.json b/test-settings.example.json deleted file mode 100644 index 7babb20..0000000 --- a/test-settings.example.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "base-ssh": { - "host": "yourhost", - "username": "root", - "password": "password" - }, - "airos-ssh": { - "host": "your_airos_device", - "username": "root", - "password": "password" - }, - "openwrt-ssh": { - "host": "your_openwrt_device", - "username": "root", - "password": "password" - }, - - "base-snmp": { - "host": "0.0.0.0", - "community": "public", - "port": 161 - }, - "airos-snmp": { - "host": "0.0.0.0", - "community": "public", - "port": 161 - }, - "openwrt-snmp": { - "host": "0.0.0.0", - "community": "public", - "port": 161 - }, - - "base-http": { - "host": "test-host.com", - "username": "test-username", - "password": "test-password" - }, - "airos-http": { - "host": "test-host.com", - "username": "test-username", - "password": "test-password" - } -} diff --git a/tests/http/airos.py b/tests/http/airos.py index 263af8b..3044eec 100644 --- a/tests/http/airos.py +++ b/tests/http/airos.py @@ -1,7 +1,6 @@ import unittest from netengine.backends.http import AirOS -from ..settings import settings __all__ = ['TestHTTP'] @@ -10,10 +9,7 @@ class TestHTTP(unittest.TestCase): def setUp(self): - self.host = settings['base-http']['host'] - self.username = settings['base-http']['username'] - self.password = settings['base-http']['password'] - self.device = AirOS(self.host, self.username, self.password) + self.device = AirOS('test-host.com', 'test-user', 'test-password') self.assertTrue(self.device.__netengine__) def test_info(self): diff --git a/tests/http/base.py b/tests/http/base.py index 0952eb1..d1d10d1 100644 --- a/tests/http/base.py +++ b/tests/http/base.py @@ -3,8 +3,6 @@ from netengine.backends.http import HTTP from netengine.exceptions import NetEngineError -from ..settings import settings - __all__ = ['TestHTTP'] @@ -12,8 +10,5 @@ class TestHTTP(unittest.TestCase): def setUp(self): - self.host = settings['base-http']['host'] - self.username = settings['base-http']['username'] - self.password = settings['base-http']['password'] - self.device = HTTP(self.host, self.username, self.password) + self.device = HTTP('test-host.com', 'test-user', 'test-password') self.assertTrue(self.device.__netengine__) diff --git a/tests/settings.py b/tests/settings.py index 519fbcb..0349a44 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1,6 +1 @@ import json -import os - -settings_file = os.getenv('TEST_SETTINGS_FILE', './test-settings.json') -settings = json.loads(open(settings_file).read()) -settings['disable_mocks'] = os.getenv('DISABLE_MOCKS', '0') is '1' diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index 0fcba81..bd464d3 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -3,7 +3,6 @@ from netengine.backends.snmp import AirOS from netengine.exceptions import NetEngineError -from ..settings import settings from ..static import MockOutputMixin @@ -13,12 +12,7 @@ class TestSNMPAirOS(unittest.TestCase, MockOutputMixin): def setUp(self): - self.host = settings['airos-snmp']['host'] - self.community = settings['airos-snmp']['community'] - self.port = settings['airos-snmp'].get('port', 161) - self.device = AirOS(self.host, self.community, port=self.port) - - # mock calls being made to devices + self.device = AirOS('0.0.0.0', 'public', 161) self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') self.interfaces_patcher = patch( 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', @@ -34,10 +28,6 @@ def setUp(self): oid=x, data=self.oid_mock_data ), ) - if settings['disable_mocks']: - self.interfaces_patcher = self.DisableMock() - self.nextcmd_patcher = self.DisableMock() - self.get_value_patcher = self.DisableMock() self.get_value_patcher.start() def test_get_value_error(self): diff --git a/tests/snmp/base.py b/tests/snmp/base.py index 347f4e3..5c01444 100644 --- a/tests/snmp/base.py +++ b/tests/snmp/base.py @@ -3,7 +3,6 @@ from netengine.backends.snmp import SNMP from netengine.exceptions import NetEngineError -from ..settings import settings __all__ = ['TestSNMP'] @@ -12,9 +11,9 @@ class TestSNMP(unittest.TestCase): def setUp(self): - self.host = settings['base-snmp']['host'] - self.community = settings['base-snmp']['community'] - self.port = settings['base-snmp'].get('port', 161) + self.host = '0.0.0.0' + self.community = 'public' + self.port = 161 def test_instantiation(self): device = SNMP(self.host, self.community, self.port) diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index 1bcc77e..34f54ea 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -2,7 +2,6 @@ from mock import patch from netengine.backends.snmp import OpenWRT -from ..settings import settings from ..static import MockOutputMixin __all__ = ['TestSNMPOpenWRT'] @@ -10,12 +9,7 @@ class TestSNMPOpenWRT(unittest.TestCase, MockOutputMixin): def setUp(self): - self.host = settings['openwrt-snmp']['host'] - self.community = settings['openwrt-snmp']['community'] - self.port = settings['openwrt-snmp'].get('port', 161) - self.device = OpenWRT(self.host, self.community, self.port) - - # mock calls being made to devices + self.device = OpenWRT('0.0.0.0', 'public', 161) self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') self.interfaces_count_patcher = patch( 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', @@ -31,10 +25,6 @@ def setUp(self): oid=x, data=self.oid_mock_data ).encode('ascii', 'ignore'), ) - if settings['disable_mocks']: - self.interfaces_count_patcher = self.DisableMock() - self.nextcmd_patcher = self.DisableMock() - self.get_value_patcher = self.DisableMock() self.get_value_patcher.start() def test_os(self): diff --git a/tests/ssh/airos.py b/tests/ssh/airos.py index abb2f6d..2803375 100644 --- a/tests/ssh/airos.py +++ b/tests/ssh/airos.py @@ -4,7 +4,6 @@ from netengine.backends.ssh import AirOS -from ..settings import settings from ..static import MockOutputMixin @@ -13,14 +12,11 @@ class TestSSHAirOS(unittest.TestCase, MockOutputMixin): - def setUp(self): - self.host = settings['airos-ssh']['host'] - self.username = settings['airos-ssh']['username'] - self.password = settings['airos-ssh']['password'] - self.port = settings['airos-ssh'].get('port', 22) - self.device = AirOS(self.host, self.username, self.password, self.port) - - # mock calls being made to devices + @mock.patch('paramiko.SSHClient.connect') + def setUp(self, mocked_connect): + self.device = AirOS('test-host.com', 'test-user', 'test-pass', 22) + self.device.connect() + mocked_connect.assert_called_once() ssh_mock_data = self._load_mock_json('/test-airos-ssh.json') self.ssh_patcher = mock.patch( 'netengine.backends.ssh.airos.SSH.run', @@ -28,13 +24,6 @@ def setUp(self): oid=x, data=ssh_mock_data ), ) - self.connect_patcher = mock.patch('paramiko.SSHClient.connect') - if settings['disable_mocks']: - self.ssh_patcher = self.DisableMock() - self.connect_patcher = self.DisableMock() - with self.connect_patcher as p: - self.device.connect() - p.assert_called_once() self.ssh_patcher.start() def test_to_dict(self): diff --git a/tests/ssh/base.py b/tests/ssh/base.py index 8ad77bd..38a05ed 100644 --- a/tests/ssh/base.py +++ b/tests/ssh/base.py @@ -5,7 +5,6 @@ from netengine.exceptions import NetEngineError from paramiko.ssh_exception import SSHException -from ..settings import settings from ..static import MockOutputMixin @@ -13,44 +12,38 @@ class TestSSH(unittest.TestCase, MockOutputMixin): - - def setUp(self): - self.host = settings['base-ssh']['host'] - self.username = settings['base-ssh']['username'] - self.password = settings['base-ssh']['password'] - self.port = settings['base-ssh'].get('port', 22) + @mock.patch('paramiko.SSHClient.connect') + def setUp(self, mocked_connect): + self.host = 'test-host.com' + self.username = 'test-user' + self.password = 'test-password' + self.port = 22 self.device = SSH(self.host, self.username, self.password, self.port) self.assertTrue(self.device.__netengine__) - - # mock calls being made to devices + self.device.connect() + mocked_connect.assert_called_once_with( + self.host, username=self.username, password=self.password, port=self.port + ) ssh_mock_data = self._load_mock_json('/test-base-ssh.json') self.exec_command_patcher = mock.patch( 'netengine.backends.ssh.base.SSH.run', side_effect=lambda x: self._get_mocked_value(oid=x, data=ssh_mock_data), ) - self.connect_patcher = mock.patch('paramiko.SSHClient.connect') - self.close_patcher = mock.patch('paramiko.SSHClient.close') - if settings['disable_mocks']: - self.exec_command_patcher = self. self.DisableMock() - with self.connect_patcher as p: - self.device.connect() - p.assert_called_once_with( - self.host, username=self.username, password=self.password, port=self.port - ) self.exec_command_patcher.start() - def test_validate_negative_result(self): - with self.connect_patcher as p: - p.side_effect = SSHException - wrong = SSH('10.40.0.254', 'root', 'pwd') - self.assertRaises(NetEngineError, wrong.validate) - - def test_validate_positive_result(self): - with self.connect_patcher as cn, self.close_patcher as cl: - self.device.disconnect() - self.device.validate() - cn.assert_called_once() - self.assertEqual(cl.call_count, 2) + @mock.patch('paramiko.SSHClient.connect') + def test_validate_negative_result(self, mocked_connect): + mocked_connect.side_effect = SSHException + wrong = SSH('10.40.0.254', 'root', 'pwd') + self.assertRaises(NetEngineError, wrong.validate) + + @mock.patch('paramiko.SSHClient.close') + @mock.patch('paramiko.SSHClient.connect') + def test_validate_positive_result(self, mocked_connect, mocked_close): + self.device.disconnect() + self.device.validate() + mocked_connect.assert_called_once() + self.assertEqual(mocked_close.call_count, 2) def test_olsr(self): print(self.device.olsr) diff --git a/tests/ssh/openwrt.py b/tests/ssh/openwrt.py index 4446962..b4db589 100644 --- a/tests/ssh/openwrt.py +++ b/tests/ssh/openwrt.py @@ -3,7 +3,6 @@ from netengine.backends.ssh import OpenWRT -from ..settings import settings from ..static import MockOutputMixin @@ -12,14 +11,11 @@ class TestSSHOpenWRT(unittest.TestCase, MockOutputMixin): - def setUp(self): - self.host = settings['openwrt-ssh']['host'] - self.username = settings['openwrt-ssh']['username'] - self.password = settings['openwrt-ssh']['password'] - self.port = settings['openwrt-ssh'].get('port', 22) - self.device = OpenWRT(self.host, self.username, self.password, self.port) - - # mock calls being made to devices + @mock.patch('paramiko.SSHClient.connect') + def setUp(self, mocked_connect): + self.device = OpenWRT('test-host.com', 'test-user', 'test-pass', 22) + self.device.connect() + mocked_connect.assert_called_once() ssh_mock_data = self._load_mock_json('/test-openwrt-ssh.json') self.ssh_patcher = mock.patch( 'netengine.backends.ssh.openwrt.SSH.run', @@ -27,13 +23,6 @@ def setUp(self): oid=x, data=ssh_mock_data ), ) - self.connect_patcher = mock.patch('paramiko.SSHClient.connect') - if settings['disable_mocks']: - self.ssh_patcher = self.DisableMock() - self.connect_patcher = self.DisableMock() - with self.connect_patcher as p: - self.device.connect() - p.assert_called_once() self.ssh_patcher.start() def test_properties(self): diff --git a/tests/static/__init__.py b/tests/static/__init__.py index 8e62b04..1e0ec02 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -1,48 +1,7 @@ import json import os - class MockOutputMixin(object): - - class DisableMock(object): - """ - Disables the mock object in context managers restoring the mocked - function to its original state - """ - - def assert_called(*args, **kwargs): - pass - - def assert_not_called(*args, **kwargs): - pass - - def assert_called_once(*args, **kwargs): - pass - - def assert_called_with(*args, **kwargs): - pass - - def assert_called_once_with(*args, **kwargs): - pass - - def assert_has_calls(*args, **kwargs): - pass - - def assert_any_call(*args, **kwargs): - pass - - def start(self): - pass - - def stop(self): - pass - - def __enter__(self, *args, **kwargs): - return self - - def __exit__(self, *args, **kwargs): - pass - @staticmethod def _load_mock_json(file): base_dir = os.path.dirname(os.path.abspath(__file__)) From ea5398c4ffa483cacdb81f90af6aab0b51fc6efc Mon Sep 17 00:00:00 2001 From: purhan Date: Sat, 22 May 2021 14:13:14 +0530 Subject: [PATCH 15/26] [qa] Allow running tests on real devices --- docs/source/topics/usage.rst | 20 ++++++++----- runtests.py | 23 +++++++++++++++ test-settings.example.json | 44 +++++++++++++++++++++++++++++ tests/http/airos.py | 6 +++- tests/http/base.py | 7 ++++- tests/settings.py | 5 ++++ tests/snmp/airos.py | 15 ++++++---- tests/snmp/base.py | 7 +++-- tests/snmp/openwrt.py | 15 ++++++---- tests/ssh/airos.py | 21 +++++++++----- tests/ssh/base.py | 55 ++++++++++++++++++++---------------- tests/ssh/openwrt.py | 21 +++++++++----- tests/static/__init__.py | 50 ++++++++++++++++++++++++++++++++ 13 files changed, 228 insertions(+), 61 deletions(-) create mode 100644 runtests.py create mode 100644 test-settings.example.json diff --git a/docs/source/topics/usage.rst b/docs/source/topics/usage.rst index c52271b..e3bfe20 100755 --- a/docs/source/topics/usage.rst +++ b/docs/source/topics/usage.rst @@ -30,19 +30,22 @@ Further example will be found inside dedicated docs for every backend Running tests ************* -Install nose:: +Install test reqirements:: - pip install nose + pip install -r reqirements.txt + pip install -r requirements-test.txt -Clone repo:: +Run tests with:: - git clone git://github.com/ninuxorg/netengine + ./runtests - cd netengine/ +To run tests on real devices, first copy the settings file:: -Run tests with:: + cp test-settings.example.json test-settings.json - nosetests +Then change the credentials accordingly, now run tests with:: + + DISABLE_MOCKS=1 TEST_SETTINGS_FILE='test-settings.json' ./runtests See test coverage with:: @@ -62,3 +65,6 @@ Run specific tests by specifying the relative path:: nosetests tests.ssh # ssh airos specific tests nosetests tests.ssh.airos + + # run without mocks with a custom test file + DISABLE_MOCKS=1 TEST_SETTINGS_FILE='test-settings.json' nosetests tests.ssh diff --git a/runtests.py b/runtests.py new file mode 100644 index 0000000..c253020 --- /dev/null +++ b/runtests.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os +try: + import nose +except: + message = """nose package not installed, install test requirements with: + pip install -r requirements-test.txt + """ + raise ImportError(message) + +if __name__ == "__main__": + file_path = os.path.abspath(__file__) + tests_path = os.path.join(os.path.abspath(os.path.dirname(file_path)), "tests") + result = nose.run( + argv=[ + os.path.abspath(__file__), + "--with-cov", + "--cover-package=netengine", + tests_path + ] + ) diff --git a/test-settings.example.json b/test-settings.example.json new file mode 100644 index 0000000..9a1fc06 --- /dev/null +++ b/test-settings.example.json @@ -0,0 +1,44 @@ +{ + "base-ssh": { + "host": "yourhost", + "username": "root", + "password": "password" + }, + "airos-ssh": { + "host": "your_airos_device", + "username": "root", + "password": "password" + }, + "openwrt-ssh": { + "host": "your_openwrt_device", + "username": "root", + "password": "password" + }, + + "base-snmp": { + "host": "0.0.0.0", + "community": "public", + "port": 161 + }, + "airos-snmp": { + "host": "0.0.0.0", + "community": "public", + "port": 161 + }, + "openwrt-snmp": { + "host": "0.0.0.0", + "community": "public", + "port": 161 + }, + + "base-http": { + "host": "test-host.com", + "username": "test-username", + "password": "test-password" + }, + "airos-http": { + "host": "test-host.com", + "username": "test-username", + "password": "test-password" + } +} \ No newline at end of file diff --git a/tests/http/airos.py b/tests/http/airos.py index 3044eec..263af8b 100644 --- a/tests/http/airos.py +++ b/tests/http/airos.py @@ -1,6 +1,7 @@ import unittest from netengine.backends.http import AirOS +from ..settings import settings __all__ = ['TestHTTP'] @@ -9,7 +10,10 @@ class TestHTTP(unittest.TestCase): def setUp(self): - self.device = AirOS('test-host.com', 'test-user', 'test-password') + self.host = settings['base-http']['host'] + self.username = settings['base-http']['username'] + self.password = settings['base-http']['password'] + self.device = AirOS(self.host, self.username, self.password) self.assertTrue(self.device.__netengine__) def test_info(self): diff --git a/tests/http/base.py b/tests/http/base.py index d1d10d1..0952eb1 100644 --- a/tests/http/base.py +++ b/tests/http/base.py @@ -3,6 +3,8 @@ from netengine.backends.http import HTTP from netengine.exceptions import NetEngineError +from ..settings import settings + __all__ = ['TestHTTP'] @@ -10,5 +12,8 @@ class TestHTTP(unittest.TestCase): def setUp(self): - self.device = HTTP('test-host.com', 'test-user', 'test-password') + self.host = settings['base-http']['host'] + self.username = settings['base-http']['username'] + self.password = settings['base-http']['password'] + self.device = HTTP(self.host, self.username, self.password) self.assertTrue(self.device.__netengine__) diff --git a/tests/settings.py b/tests/settings.py index 0349a44..519fbcb 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1 +1,6 @@ import json +import os + +settings_file = os.getenv('TEST_SETTINGS_FILE', './test-settings.json') +settings = json.loads(open(settings_file).read()) +settings['disable_mocks'] = os.getenv('DISABLE_MOCKS', '0') is '1' diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index bd464d3..bf9e904 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -1,8 +1,8 @@ import unittest -from mock import patch from netengine.backends.snmp import AirOS from netengine.exceptions import NetEngineError +from ..settings import settings from ..static import MockOutputMixin @@ -12,17 +12,22 @@ class TestSNMPAirOS(unittest.TestCase, MockOutputMixin): def setUp(self): - self.device = AirOS('0.0.0.0', 'public', 161) + self.host = settings['airos-snmp']['host'] + self.community = settings['airos-snmp']['community'] + self.port = settings['airos-snmp'].get('port', 161) + self.device = AirOS(self.host, self.community, port=self.port) + + # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') - self.interfaces_patcher = patch( + self.interfaces_patcher = self._patch( 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', return_value=[1, 2, 3, 4, 5] ) - self.nextcmd_patcher = patch( + self.nextcmd_patcher = self._patch( 'netengine.backends.snmp.openwrt.SNMP.next', return_value=[0, 0, 0, [[[0, 0,]]] * 5] ) - self.get_value_patcher = patch( + self.get_value_patcher = self._patch( 'netengine.backends.snmp.airos.AirOS.get', side_effect=lambda x: self._get_encoded_mocked_value( oid=x, data=self.oid_mock_data diff --git a/tests/snmp/base.py b/tests/snmp/base.py index 5c01444..347f4e3 100644 --- a/tests/snmp/base.py +++ b/tests/snmp/base.py @@ -3,6 +3,7 @@ from netengine.backends.snmp import SNMP from netengine.exceptions import NetEngineError +from ..settings import settings __all__ = ['TestSNMP'] @@ -11,9 +12,9 @@ class TestSNMP(unittest.TestCase): def setUp(self): - self.host = '0.0.0.0' - self.community = 'public' - self.port = 161 + self.host = settings['base-snmp']['host'] + self.community = settings['base-snmp']['community'] + self.port = settings['base-snmp'].get('port', 161) def test_instantiation(self): device = SNMP(self.host, self.community, self.port) diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index 34f54ea..2a96075 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -1,7 +1,7 @@ import unittest -from mock import patch from netengine.backends.snmp import OpenWRT +from ..settings import settings from ..static import MockOutputMixin __all__ = ['TestSNMPOpenWRT'] @@ -9,17 +9,22 @@ class TestSNMPOpenWRT(unittest.TestCase, MockOutputMixin): def setUp(self): - self.device = OpenWRT('0.0.0.0', 'public', 161) + self.host = settings['openwrt-snmp']['host'] + self.community = settings['openwrt-snmp']['community'] + self.port = settings['openwrt-snmp'].get('port', 161) + self.device = OpenWRT(self.host, self.community, self.port) + + # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') - self.interfaces_count_patcher = patch( + self.interfaces_count_patcher = self._patch( 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', return_value=[1, 2, 3, 4, 5] ) - self.nextcmd_patcher = patch( + self.nextcmd_patcher = self._patch( 'netengine.backends.snmp.openwrt.SNMP.next', return_value=[0, 0, 0, [0] * 5] ) - self.get_value_patcher = patch( + self.get_value_patcher = self._patch( 'netengine.backends.snmp.openwrt.OpenWRT.get_value', side_effect=lambda x: self._get_mocked_value( oid=x, data=self.oid_mock_data diff --git a/tests/ssh/airos.py b/tests/ssh/airos.py index 2803375..0ab7767 100644 --- a/tests/ssh/airos.py +++ b/tests/ssh/airos.py @@ -1,9 +1,9 @@ import json import unittest -import mock from netengine.backends.ssh import AirOS +from ..settings import settings from ..static import MockOutputMixin @@ -12,18 +12,25 @@ class TestSSHAirOS(unittest.TestCase, MockOutputMixin): - @mock.patch('paramiko.SSHClient.connect') - def setUp(self, mocked_connect): - self.device = AirOS('test-host.com', 'test-user', 'test-pass', 22) - self.device.connect() - mocked_connect.assert_called_once() + def setUp(self): + self.host = settings['airos-ssh']['host'] + self.username = settings['airos-ssh']['username'] + self.password = settings['airos-ssh']['password'] + self.port = settings['airos-ssh'].get('port', 22) + self.device = AirOS(self.host, self.username, self.password, self.port) + + # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-airos-ssh.json') - self.ssh_patcher = mock.patch( + self.ssh_patcher = self._patch( 'netengine.backends.ssh.airos.SSH.run', side_effect=lambda x: self._get_mocked_value( oid=x, data=ssh_mock_data ), ) + self.connect_patcher = self._patch('paramiko.SSHClient.connect') + with self.connect_patcher as p: + self.device.connect() + p.assert_called_once() self.ssh_patcher.start() def test_to_dict(self): diff --git a/tests/ssh/base.py b/tests/ssh/base.py index 38a05ed..316fd7d 100644 --- a/tests/ssh/base.py +++ b/tests/ssh/base.py @@ -1,10 +1,10 @@ import unittest -import mock from netengine.backends.ssh import SSH from netengine.exceptions import NetEngineError from paramiko.ssh_exception import SSHException +from ..settings import settings from ..static import MockOutputMixin @@ -12,38 +12,43 @@ class TestSSH(unittest.TestCase, MockOutputMixin): - @mock.patch('paramiko.SSHClient.connect') - def setUp(self, mocked_connect): - self.host = 'test-host.com' - self.username = 'test-user' - self.password = 'test-password' - self.port = 22 + + def setUp(self): + self.host = settings['base-ssh']['host'] + self.username = settings['base-ssh']['username'] + self.password = settings['base-ssh']['password'] + self.port = settings['base-ssh'].get('port', 22) self.device = SSH(self.host, self.username, self.password, self.port) self.assertTrue(self.device.__netengine__) - self.device.connect() - mocked_connect.assert_called_once_with( - self.host, username=self.username, password=self.password, port=self.port - ) + + # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-base-ssh.json') - self.exec_command_patcher = mock.patch( + self.exec_command_patcher = self._patch( 'netengine.backends.ssh.base.SSH.run', side_effect=lambda x: self._get_mocked_value(oid=x, data=ssh_mock_data), ) + self.connect_patcher = self._patch('paramiko.SSHClient.connect') + self.close_patcher = self._patch('paramiko.SSHClient.close') + with self.connect_patcher as p: + self.device.connect() + p.assert_called_once_with( + self.host, username=self.username, password=self.password, port=self.port + ) self.exec_command_patcher.start() - @mock.patch('paramiko.SSHClient.connect') - def test_validate_negative_result(self, mocked_connect): - mocked_connect.side_effect = SSHException - wrong = SSH('10.40.0.254', 'root', 'pwd') - self.assertRaises(NetEngineError, wrong.validate) - - @mock.patch('paramiko.SSHClient.close') - @mock.patch('paramiko.SSHClient.connect') - def test_validate_positive_result(self, mocked_connect, mocked_close): - self.device.disconnect() - self.device.validate() - mocked_connect.assert_called_once() - self.assertEqual(mocked_close.call_count, 2) + def test_validate_negative_result(self): + with self.connect_patcher as p: + p.side_effect = SSHException + wrong = SSH('10.40.0.254', 'root', 'pwd') + self.assertRaises(NetEngineError, wrong.validate) + + def test_validate_positive_result(self): + with self.connect_patcher as cn, self.close_patcher as cl: + self.device.disconnect() + self.device.validate() + cn.assert_called_once() + if not settings['disable_mocks']: + self.assertEqual(cl.call_count, 2) def test_olsr(self): print(self.device.olsr) diff --git a/tests/ssh/openwrt.py b/tests/ssh/openwrt.py index b4db589..2dd1eda 100644 --- a/tests/ssh/openwrt.py +++ b/tests/ssh/openwrt.py @@ -1,8 +1,8 @@ import unittest -import mock from netengine.backends.ssh import OpenWRT +from ..settings import settings from ..static import MockOutputMixin @@ -11,18 +11,25 @@ class TestSSHOpenWRT(unittest.TestCase, MockOutputMixin): - @mock.patch('paramiko.SSHClient.connect') - def setUp(self, mocked_connect): - self.device = OpenWRT('test-host.com', 'test-user', 'test-pass', 22) - self.device.connect() - mocked_connect.assert_called_once() + def setUp(self): + self.host = settings['openwrt-ssh']['host'] + self.username = settings['openwrt-ssh']['username'] + self.password = settings['openwrt-ssh']['password'] + self.port = settings['openwrt-ssh'].get('port', 22) + self.device = OpenWRT(self.host, self.username, self.password, self.port) + + # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-openwrt-ssh.json') - self.ssh_patcher = mock.patch( + self.ssh_patcher = self._patch( 'netengine.backends.ssh.openwrt.SSH.run', side_effect=lambda x: self._get_mocked_value( oid=x, data=ssh_mock_data ), ) + self.connect_patcher = self._patch('paramiko.SSHClient.connect') + with self.connect_patcher as p: + self.device.connect() + p.assert_called_once() self.ssh_patcher.start() def test_properties(self): diff --git a/tests/static/__init__.py b/tests/static/__init__.py index 1e0ec02..b807f19 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -1,7 +1,57 @@ import json +import mock import os +from ..settings import settings + + class MockOutputMixin(object): + + class DisableMockMixin(object): + """ + Disables the mock object in context managers restoring the mocked + function to its original state + """ + def assert_called(self, *args, **kwargs): + pass + + def assert_not_called(self, *args, **kwargs): + pass + + def assert_called_once(self, *args, **kwargs): + pass + + def assert_called_with(self, *args, **kwargs): + pass + + def assert_called_once_with(self, *args, **kwargs): + pass + + def assert_has_calls(self, *args, **kwargs): + pass + + def assert_any_call(self, *args, **kwargs): + pass + + def start(self): + pass + + def stop(self): + pass + + def __enter__(self, *args, **kwargs): + return self + + def __exit__(self, *args, **kwargs): + return True + + + def _patch(self, *args, **kwargs): + if settings['disable_mocks']: + return self.DisableMockMixin() + else: + return mock.patch(*args, **kwargs) + @staticmethod def _load_mock_json(file): base_dir = os.path.dirname(os.path.abspath(__file__)) From 873b6dc9c4ce1a8f946ebd5a252aefaadc03cc57 Mon Sep 17 00:00:00 2001 From: Purhan Kaushik Date: Sat, 22 May 2021 14:16:30 +0530 Subject: [PATCH 16/26] [chores] Add newline at the end of the file --- test-settings.example.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-settings.example.json b/test-settings.example.json index 9a1fc06..7babb20 100644 --- a/test-settings.example.json +++ b/test-settings.example.json @@ -41,4 +41,4 @@ "username": "test-username", "password": "test-password" } -} \ No newline at end of file +} From 4e240ecdeae6613a3444257c065a47d1511158d9 Mon Sep 17 00:00:00 2001 From: purhan Date: Sun, 23 May 2021 11:24:22 +0530 Subject: [PATCH 17/26] [change] Mock only external libraries --- tests/snmp/airos.py | 78 +++++++++++++++++++--------------------- tests/snmp/openwrt.py | 51 +++++++++++++------------- tests/ssh/airos.py | 7 ++-- tests/ssh/base.py | 7 ++-- tests/ssh/openwrt.py | 8 +++-- tests/static/__init__.py | 23 ++++++++---- 6 files changed, 93 insertions(+), 81 deletions(-) diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index bf9e904..8b76a04 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -19,31 +19,27 @@ def setUp(self): # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') - self.interfaces_patcher = self._patch( - 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', - return_value=[1, 2, 3, 4, 5] - ) self.nextcmd_patcher = self._patch( - 'netengine.backends.snmp.openwrt.SNMP.next', - return_value=[0, 0, 0, [[[0, 0,]]] * 5] + 'netengine.backends.snmp.base.cmdgen.CommandGenerator.nextCmd', + return_value=[0, 0, 0, [[[0, 1]]] * 5] ) - self.get_value_patcher = self._patch( - 'netengine.backends.snmp.airos.AirOS.get', - side_effect=lambda x: self._get_encoded_mocked_value( - oid=x, data=self.oid_mock_data - ), + self.getcmd_patcher = self._patch( + 'netengine.backends.snmp.base.cmdgen.CommandGenerator.getCmd', + side_effect=lambda *args: self._get_mocked_getcmd( + data=self.oid_mock_data, input=args + ) ) - self.get_value_patcher.start() + self.getcmd_patcher.start() def test_get_value_error(self): - with self.get_value_patcher as p: - p.side_effect = lambda x: self.device._oid(x) + with self.getcmd_patcher as p: + p.side_effect = NetEngineError with self.assertRaises(NetEngineError): self.device.get_value('.') def test_validate_negative_result(self): - with self.get_value_patcher as p: - p.side_effect = lambda x: self.device._oid(x) + with self.getcmd_patcher as p: + p.side_effect = NetEngineError wrong = AirOS('10.40.0.254', 'wrong', 'wrong') self.assertRaises(NetEngineError, wrong.validate) @@ -51,16 +47,14 @@ def test_validate_positive_result(self): self.device.validate() def test_get(self): - with self.get_value_patcher as p: - p.side_effect = lambda x: self.device._oid(x) - with self.assertRaises(AttributeError): - self.device.get({}) - with self.assertRaises(AttributeError): - self.device.get(object) - self.device.get('1,3,6,1,2,1,1,5,0') - self.device.get(u'1,3,6,1,2,1,1,5,0') - self.device.get((1,3,6,1,2,1,1,5,0)) - self.device.get([1,3,6,1,2,1,1,5,0]) + with self.assertRaises(AttributeError): + self.device.get({}) + with self.assertRaises(AttributeError): + self.device.get(object) + self.device.get('1,3,6,1,2,1,1,5,0') + self.device.get(u'1,3,6,1,2,1,1,5,0') + self.device.get((1,3,6,1,2,1,1,5,0)) + self.device.get([1,3,6,1,2,1,1,5,0]) def test_properties(self): device = self.device @@ -79,35 +73,35 @@ def test_os(self): self.assertTrue(type(self.device.os) == tuple) def test_get_interfaces(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertTrue(type(self.device.get_interfaces()) == list) def test_get_interfaces_mtu(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertTrue(type(self.device.interfaces_mtu) == list) def test_interfaces_state(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertTrue(type(self.device.interfaces_state) == list) def test_interfaces_speed(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertTrue(type(self.device.interfaces_speed) == list) def test_interfaces_bytes(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertTrue(type(self.device.interfaces_bytes) == list) def test_interfaces_MAC(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertTrue(type(self.device.interfaces_MAC) == list) def test_interfaces_type(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertTrue(type(self.device.interfaces_type) == list) def test_interfaces_to_dict(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertTrue(type(self.device.interfaces_to_dict) == list) def test_wireless_dbm(self): @@ -118,8 +112,8 @@ def test_interfaces_number(self): self.assertTrue(type(self.device.interfaces_number) == int) def test_wireless_to_dict(self): - with self.interfaces_patcher, self.nextcmd_patcher as np: - np.side_effect = lambda x: self._get_mocked_wireless_links(oid=x) + with self.nextcmd_patcher as np: + np.side_effect = lambda *args: self._get_mocked_wireless_links(data=args) self.assertTrue(type(self.device.wireless_links) == list) def test_RAM_free(self): @@ -129,17 +123,17 @@ def test_RAM_total(self): self.assertTrue(type(self.device.RAM_total) == int) def test_to_dict(self): - with self.interfaces_patcher, self.nextcmd_patcher as np: - np.side_effect = lambda x: self._get_mocked_wireless_links(oid=x) + with self.nextcmd_patcher as np: + np.side_effect = lambda *args: self._get_mocked_wireless_links(data=args) self.assertTrue(isinstance(self.device.to_dict(), dict)) def test_manufacturer_to_dict(self): - with self.interfaces_patcher, self.nextcmd_patcher as np: - np.side_effect = lambda x: self._get_mocked_wireless_links(oid=x) + with self.nextcmd_patcher as np: + np.side_effect = lambda *args: self._get_mocked_wireless_links(data=args) self.assertIsNotNone(self.device.to_dict()['manufacturer']) def test_manufacturer(self): - with self.interfaces_patcher: + with self.nextcmd_patcher: self.assertIsNotNone(self.device.manufacturer) def test_model(self): @@ -155,4 +149,4 @@ def test_uptime_tuple(self): self.assertTrue(type(self.device.uptime_tuple) == tuple) def tearDown(self): - self.get_value_patcher.stop() + self.getcmd_patcher.stop() diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index 2a96075..d78dc49 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -16,30 +16,25 @@ def setUp(self): # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') - self.interfaces_count_patcher = self._patch( - 'netengine.backends.snmp.openwrt.SNMP._value_to_retrieve', - return_value=[1, 2, 3, 4, 5] - ) self.nextcmd_patcher = self._patch( - 'netengine.backends.snmp.openwrt.SNMP.next', + 'netengine.backends.snmp.base.cmdgen.CommandGenerator.nextCmd', return_value=[0, 0, 0, [0] * 5] ) - self.get_value_patcher = self._patch( - 'netengine.backends.snmp.openwrt.OpenWRT.get_value', - side_effect=lambda x: self._get_mocked_value( - oid=x, data=self.oid_mock_data - ).encode('ascii', 'ignore'), + self.getcmd_patcher = self._patch( + 'netengine.backends.snmp.base.cmdgen.CommandGenerator.getCmd', + side_effect=lambda *args: self._get_mocked_getcmd( + data=self.oid_mock_data, input=args + ) ) - self.get_value_patcher.start() + self.getcmd_patcher.start() def test_os(self): self.assertTrue(type(self.device.os) == tuple) def test_manufacturer(self): - with self.interfaces_count_patcher: - with self.nextcmd_patcher as p: - self.assertIsNotNone(self.device.manufacturer) - p.assert_called_once_with('1.3.6.1.2.1.2.2.1.6.') + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + self.assertIsNotNone(self.device.manufacturer) def test_name(self): self.assertTrue(type(self.device.name) == str) @@ -51,30 +46,36 @@ def test_uptime_tuple(self): self.assertTrue(type(self.device.uptime_tuple) == tuple) def test_get_interfaces(self): - with self.interfaces_count_patcher: + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] self.assertTrue(type(self.device.get_interfaces()) == list) def test_interfaces_speed(self): self.assertTrue(type(self.device.interfaces_speed) == list) def test_interfaces_bytes(self): - with self.interfaces_count_patcher: + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] self.assertTrue(type(self.device.interfaces_bytes) == list) def test_interfaces_MAC(self): - with self.interfaces_count_patcher, self.nextcmd_patcher: + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] self.assertTrue(type(self.device.interfaces_MAC) == list) def test_interfaces_type(self): - with self.interfaces_count_patcher: + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] self.assertTrue(type(self.device.interfaces_type) == list) def test_interfaces_mtu(self): - with self.interfaces_count_patcher: + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] self.assertTrue(type(self.device.interfaces_mtu) == list) def test_interfaces_state(self): - with self.interfaces_count_patcher: + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] self.assertTrue(type(self.device.interfaces_state) == list) def test_interfaces_to_dict(self): @@ -91,7 +92,8 @@ def test_RAM_total(self): self.assertTrue(type(self.device.RAM_total) == int) def test_to_dict(self): - with self.interfaces_count_patcher, self.nextcmd_patcher: + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] device_dict = self.device.to_dict() self.assertTrue(isinstance(device_dict, dict)) self.assertEqual( @@ -99,8 +101,9 @@ def test_to_dict(self): ) def test_manufacturer_to_dict(self): - with self.interfaces_count_patcher, self.nextcmd_patcher: + with self.nextcmd_patcher as p: + p.return_value = [0, 0, 0, [[[0, 1]]] * 5] self.assertIsNotNone(self.device.to_dict()['manufacturer']) def tearDown(self): - self.get_value_patcher.stop() + self.getcmd_patcher.stop() diff --git a/tests/ssh/airos.py b/tests/ssh/airos.py index 0ab7767..fc605a0 100644 --- a/tests/ssh/airos.py +++ b/tests/ssh/airos.py @@ -22,9 +22,9 @@ def setUp(self): # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-airos-ssh.json') self.ssh_patcher = self._patch( - 'netengine.backends.ssh.airos.SSH.run', - side_effect=lambda x: self._get_mocked_value( - oid=x, data=ssh_mock_data + 'paramiko.SSHClient.exec_command', + side_effect=lambda x: self._get_mocked_exec_command( + command=x, data = ssh_mock_data ), ) self.connect_patcher = self._patch('paramiko.SSHClient.connect') @@ -32,6 +32,7 @@ def setUp(self): self.device.connect() p.assert_called_once() self.ssh_patcher.start() + self.connect_patcher.start() def test_to_dict(self): self.assertTrue(isinstance(self.device.to_dict(), dict)) diff --git a/tests/ssh/base.py b/tests/ssh/base.py index 316fd7d..bbcac79 100644 --- a/tests/ssh/base.py +++ b/tests/ssh/base.py @@ -24,8 +24,10 @@ def setUp(self): # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-base-ssh.json') self.exec_command_patcher = self._patch( - 'netengine.backends.ssh.base.SSH.run', - side_effect=lambda x: self._get_mocked_value(oid=x, data=ssh_mock_data), + 'paramiko.SSHClient.exec_command', + side_effect=lambda x: self._get_mocked_exec_command( + command=x, data = ssh_mock_data + ), ) self.connect_patcher = self._patch('paramiko.SSHClient.connect') self.close_patcher = self._patch('paramiko.SSHClient.close') @@ -35,6 +37,7 @@ def setUp(self): self.host, username=self.username, password=self.password, port=self.port ) self.exec_command_patcher.start() + self.connect_patcher.start() def test_validate_negative_result(self): with self.connect_patcher as p: diff --git a/tests/ssh/openwrt.py b/tests/ssh/openwrt.py index 2dd1eda..733e77a 100644 --- a/tests/ssh/openwrt.py +++ b/tests/ssh/openwrt.py @@ -21,9 +21,9 @@ def setUp(self): # mock calls being made to devices ssh_mock_data = self._load_mock_json('/test-openwrt-ssh.json') self.ssh_patcher = self._patch( - 'netengine.backends.ssh.openwrt.SSH.run', - side_effect=lambda x: self._get_mocked_value( - oid=x, data=ssh_mock_data + 'paramiko.SSHClient.exec_command', + side_effect=lambda x: self._get_mocked_exec_command( + command=x, data = ssh_mock_data ), ) self.connect_patcher = self._patch('paramiko.SSHClient.connect') @@ -31,6 +31,7 @@ def setUp(self): self.device.connect() p.assert_called_once() self.ssh_patcher.start() + self.connect_patcher.start() def test_properties(self): device = self.device @@ -71,3 +72,4 @@ def test_filter_routing_protocols(self): def tearDown(self): self.ssh_patcher.stop() + self.connect_patcher.stop() diff --git a/tests/static/__init__.py b/tests/static/__init__.py index b807f19..7dec742 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -1,6 +1,7 @@ import json import mock import os +from StringIO import StringIO from ..settings import settings @@ -60,24 +61,32 @@ def _load_mock_json(file): return data @staticmethod - def _get_mocked_value(oid, data, *args, **kwargs): - result = data[oid] + def _get_mocked_getcmd(data, input): + oid = input[2] + result = data[oid].encode('ascii', 'ignore') if type(result) == list: result = "\n".join(result[0:]) - return result + return [0, 0, 0, [[0, result]]] @staticmethod - def _get_encoded_mocked_value(oid, data, *args, **kwargs): - result = data[oid] + def _get_mocked_exec_command(command, data): + result = data[command] if type(result) == list: result = "\n".join(result[0:]) - return [0, 0, 0, [[0, result.encode('ascii', 'ignore')], 0]] + stdout = stderr = StringIO() + stdout.write(result) + stderr.write(None) + stdout.seek(0) + stderr.seek(0) + return 0, stdout, stderr @staticmethod - def _get_mocked_wireless_links(oid): + def _get_mocked_wireless_links(data): + oid = data[2] return_data = { '1.3.6.1.4.1.14988.1.1.1.2.1': [0, 0, 0, [[[0, 0], 0]] * 28], '1.3.6.1.4.1.14988.1.1.1.2.1.3': [0, 0, 0, [0, 0]], '1.3.6.1.4.1.14988.1.1.1.2.1.3.0': [None, 0, 0, []], + '1.3.6.1.2.1.1.9.1.1': [0, 0, 0, [[[0, 1]]] * 5] } return return_data[oid] From 7cddc92262e790ab7528dc4e0bca83fb4ed1c98c Mon Sep 17 00:00:00 2001 From: purhan Date: Tue, 25 May 2021 15:30:33 +0530 Subject: [PATCH 18/26] [chores/requested-changes] Improvements to SNMP tests --- netengine/backends/snmp/base.py | 5 ++- requirements-test.txt | 1 + tests/snmp/airos.py | 56 ++++++++++++++++----------------- tests/snmp/openwrt.py | 32 +++++++++---------- 4 files changed, 48 insertions(+), 46 deletions(-) create mode 100644 requirements-test.txt diff --git a/netengine/backends/snmp/base.py b/netengine/backends/snmp/base.py index 4a629d3..f9a5f00 100644 --- a/netengine/backends/snmp/base.py +++ b/netengine/backends/snmp/base.py @@ -102,7 +102,10 @@ def get_value(self, oid): returns value of oid, or raises NetEngineError Exception is anything wrong :oid string|tuple|list: string, tuple or list representing the OID to get """ - result = self.get(oid) + try: + result = self.get(oid) + except Exception as e: + raise NetEngineError('pysnmp raised an exception: {0}'.format(e)) try: return str(result[3][0][1]) # snmp stores results in several arrays except IndexError: diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 0000000..f3c7e8e --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1 @@ +nose diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index 8b76a04..054953b 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -20,11 +20,11 @@ def setUp(self): # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') self.nextcmd_patcher = self._patch( - 'netengine.backends.snmp.base.cmdgen.CommandGenerator.nextCmd', + 'pysnmp.entity.rfc3413.oneliner.cmdgen.CommandGenerator.nextCmd', return_value=[0, 0, 0, [[[0, 1]]] * 5] ) self.getcmd_patcher = self._patch( - 'netengine.backends.snmp.base.cmdgen.CommandGenerator.getCmd', + 'pysnmp.entity.rfc3413.oneliner.cmdgen.CommandGenerator.getCmd', side_effect=lambda *args: self._get_mocked_getcmd( data=self.oid_mock_data, input=args ) @@ -32,16 +32,14 @@ def setUp(self): self.getcmd_patcher.start() def test_get_value_error(self): - with self.getcmd_patcher as p: - p.side_effect = NetEngineError - with self.assertRaises(NetEngineError): - self.device.get_value('.') + self.getcmd_patcher.stop() + with self.assertRaises(NetEngineError): + self.device.get_value('.') def test_validate_negative_result(self): - with self.getcmd_patcher as p: - p.side_effect = NetEngineError - wrong = AirOS('10.40.0.254', 'wrong', 'wrong') - self.assertRaises(NetEngineError, wrong.validate) + self.getcmd_patcher.stop() + wrong = AirOS('10.40.0.254', 'wrong', 'wrong') + self.assertRaises(NetEngineError, wrong.validate) def test_validate_positive_result(self): self.device.validate() @@ -67,60 +65,60 @@ def test_properties(self): device.uptime_tuple def test_name(self): - self.assertTrue(type(self.device.name) == str) + self.assertIsInstance(self.device.name, str) def test_os(self): - self.assertTrue(type(self.device.os) == tuple) + self.assertIsInstance(self.device.os, tuple) def test_get_interfaces(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.get_interfaces()) == list) + self.assertIsInstance(self.device.get_interfaces(), list) def test_get_interfaces_mtu(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.interfaces_mtu) == list) + self.assertIsInstance(self.device.interfaces_mtu, list) def test_interfaces_state(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.interfaces_state) == list) + self.assertIsInstance(self.device.interfaces_state, list) def test_interfaces_speed(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.interfaces_speed) == list) + self.assertIsInstance(self.device.interfaces_speed, list) def test_interfaces_bytes(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.interfaces_bytes) == list) + self.assertIsInstance(self.device.interfaces_bytes, list) def test_interfaces_MAC(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.interfaces_MAC) == list) + self.assertIsInstance(self.device.interfaces_MAC, list) def test_interfaces_type(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.interfaces_type) == list) + self.assertIsInstance(self.device.interfaces_type, list) def test_interfaces_to_dict(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.interfaces_to_dict) == list) + self.assertIsInstance(self.device.interfaces_to_dict, list) def test_wireless_dbm(self): with self.nextcmd_patcher: - self.assertTrue(type(self.device.wireless_dbm) == list) + self.assertIsInstance(self.device.wireless_dbm, list) def test_interfaces_number(self): - self.assertTrue(type(self.device.interfaces_number) == int) + self.assertIsInstance(self.device.interfaces_number, int) def test_wireless_to_dict(self): with self.nextcmd_patcher as np: np.side_effect = lambda *args: self._get_mocked_wireless_links(data=args) - self.assertTrue(type(self.device.wireless_links) == list) + self.assertIsInstance(self.device.wireless_links, list) def test_RAM_free(self): - self.assertTrue(type(self.device.RAM_free) == int) + self.assertIsInstance(self.device.RAM_free, int) def test_RAM_total(self): - self.assertTrue(type(self.device.RAM_total) == int) + self.assertIsInstance(self.device.RAM_total, int) def test_to_dict(self): with self.nextcmd_patcher as np: @@ -137,16 +135,16 @@ def test_manufacturer(self): self.assertIsNotNone(self.device.manufacturer) def test_model(self): - self.assertTrue(type(self.device.model) == str) + self.assertIsInstance(self.device.model, str) def test_firmware(self): - self.assertTrue(type(self.device.firmware) == str) + self.assertIsInstance(self.device.firmware, str) def test_uptime(self): - self.assertTrue(type(self.device.uptime) == int) + self.assertIsInstance(self.device.uptime, int) def test_uptime_tuple(self): - self.assertTrue(type(self.device.uptime_tuple) == tuple) + self.assertIsInstance(self.device.uptime_tuple, tuple) def tearDown(self): self.getcmd_patcher.stop() diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index d78dc49..041b06a 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -17,11 +17,11 @@ def setUp(self): # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') self.nextcmd_patcher = self._patch( - 'netengine.backends.snmp.base.cmdgen.CommandGenerator.nextCmd', + 'pysnmp.entity.rfc3413.oneliner.cmdgen.CommandGenerator.nextCmd', return_value=[0, 0, 0, [0] * 5] ) self.getcmd_patcher = self._patch( - 'netengine.backends.snmp.base.cmdgen.CommandGenerator.getCmd', + 'pysnmp.entity.rfc3413.oneliner.cmdgen.CommandGenerator.getCmd', side_effect=lambda *args: self._get_mocked_getcmd( data=self.oid_mock_data, input=args ) @@ -29,7 +29,7 @@ def setUp(self): self.getcmd_patcher.start() def test_os(self): - self.assertTrue(type(self.device.os) == tuple) + self.assertIsInstance(self.device.os, tuple) def test_manufacturer(self): with self.nextcmd_patcher as p: @@ -37,59 +37,59 @@ def test_manufacturer(self): self.assertIsNotNone(self.device.manufacturer) def test_name(self): - self.assertTrue(type(self.device.name) == str) + self.assertIsInstance(self.device.name, str) def test_uptime(self): - self.assertTrue(type(self.device.uptime) == int) + self.assertIsInstance(self.device.uptime, int) def test_uptime_tuple(self): - self.assertTrue(type(self.device.uptime_tuple) == tuple) + self.assertIsInstance(self.device.uptime_tuple, tuple) def test_get_interfaces(self): with self.nextcmd_patcher as p: p.return_value = [0, 0, 0, [[[0, 1]]] * 5] - self.assertTrue(type(self.device.get_interfaces()) == list) + self.assertIsInstance(self.device.get_interfaces(), list) def test_interfaces_speed(self): - self.assertTrue(type(self.device.interfaces_speed) == list) + self.assertIsInstance(self.device.interfaces_speed, list) def test_interfaces_bytes(self): with self.nextcmd_patcher as p: p.return_value = [0, 0, 0, [[[0, 1]]] * 5] - self.assertTrue(type(self.device.interfaces_bytes) == list) + self.assertIsInstance(self.device.interfaces_bytes, list) def test_interfaces_MAC(self): with self.nextcmd_patcher as p: p.return_value = [0, 0, 0, [[[0, 1]]] * 5] - self.assertTrue(type(self.device.interfaces_MAC) == list) + self.assertIsInstance(self.device.interfaces_MAC, list) def test_interfaces_type(self): with self.nextcmd_patcher as p: p.return_value = [0, 0, 0, [[[0, 1]]] * 5] - self.assertTrue(type(self.device.interfaces_type) == list) + self.assertIsInstance(self.device.interfaces_type, list) def test_interfaces_mtu(self): with self.nextcmd_patcher as p: p.return_value = [0, 0, 0, [[[0, 1]]] * 5] - self.assertTrue(type(self.device.interfaces_mtu) == list) + self.assertIsInstance(self.device.interfaces_mtu, list) def test_interfaces_state(self): with self.nextcmd_patcher as p: p.return_value = [0, 0, 0, [[[0, 1]]] * 5] - self.assertTrue(type(self.device.interfaces_state) == list) + self.assertIsInstance(self.device.interfaces_state, list) def test_interfaces_to_dict(self): with self.nextcmd_patcher as p: p.return_value = (0, 0, 0, []) - self.assertTrue(type(self.device.interfaces_to_dict) == list) + self.assertIsInstance(self.device.interfaces_to_dict, list) def test_interface_addr_and_mask(self): with self.nextcmd_patcher as p: p.return_value = (0, 0, 0, []) - self.assertTrue(type(self.device.interface_addr_and_mask) == dict) + self.assertIsInstance(self.device.interface_addr_and_mask, dict) def test_RAM_total(self): - self.assertTrue(type(self.device.RAM_total) == int) + self.assertIsInstance(self.device.RAM_total, int) def test_to_dict(self): with self.nextcmd_patcher as p: From 74b1646aaf6183704765ba62b9b69bf09e0e09c1 Mon Sep 17 00:00:00 2001 From: purhan Date: Wed, 26 May 2021 12:46:18 +0530 Subject: [PATCH 19/26] [qa] Create spy mocks --- tests/snmp/airos.py | 38 ++++++++++++++++----- tests/snmp/openwrt.py | 35 +++++++++++--------- tests/static/__init__.py | 71 ++++++++-------------------------------- 3 files changed, 62 insertions(+), 82 deletions(-) diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index 054953b..562f0d8 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -1,9 +1,10 @@ import unittest from netengine.backends.snmp import AirOS from netengine.exceptions import NetEngineError +from pysnmp.entity.rfc3413.oneliner import cmdgen from ..settings import settings -from ..static import MockOutputMixin +from ..static import MockOutputMixin, SpyMock __all__ = ['TestSNMPAirOS'] @@ -19,15 +20,19 @@ def setUp(self): # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') - self.nextcmd_patcher = self._patch( - 'pysnmp.entity.rfc3413.oneliner.cmdgen.CommandGenerator.nextCmd', + self.nextcmd_patcher = SpyMock._patch( + target=cmdgen.CommandGenerator, + attribute='nextCmd', + wrap_obj=self.device._command, return_value=[0, 0, 0, [[[0, 1]]] * 5] ) - self.getcmd_patcher = self._patch( - 'pysnmp.entity.rfc3413.oneliner.cmdgen.CommandGenerator.getCmd', + self.getcmd_patcher = SpyMock._patch( + target=cmdgen.CommandGenerator, + attribute='getCmd', + wrap_obj=self.device._command, side_effect=lambda *args: self._get_mocked_getcmd( data=self.oid_mock_data, input=args - ) + ), ) self.getcmd_patcher.start() @@ -111,7 +116,12 @@ def test_interfaces_number(self): def test_wireless_to_dict(self): with self.nextcmd_patcher as np: - np.side_effect = lambda *args: self._get_mocked_wireless_links(data=args) + SpyMock._update_patch( + np, + _mock_side_effect=lambda *args: self._get_mocked_wireless_links( + data=args + ), + ) self.assertIsInstance(self.device.wireless_links, list) def test_RAM_free(self): @@ -122,12 +132,22 @@ def test_RAM_total(self): def test_to_dict(self): with self.nextcmd_patcher as np: - np.side_effect = lambda *args: self._get_mocked_wireless_links(data=args) + SpyMock._update_patch( + np, + _mock_side_effect=lambda *args: self._get_mocked_wireless_links( + data=args + ), + ) self.assertTrue(isinstance(self.device.to_dict(), dict)) def test_manufacturer_to_dict(self): with self.nextcmd_patcher as np: - np.side_effect = lambda *args: self._get_mocked_wireless_links(data=args) + SpyMock._update_patch( + np, + _mock_side_effect=lambda *args: self._get_mocked_wireless_links( + data=args + ), + ) self.assertIsNotNone(self.device.to_dict()['manufacturer']) def test_manufacturer(self): diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index 041b06a..d85f54e 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -1,8 +1,9 @@ import unittest from netengine.backends.snmp import OpenWRT +from pysnmp.entity.rfc3413.oneliner import cmdgen from ..settings import settings -from ..static import MockOutputMixin +from ..static import MockOutputMixin, SpyMock __all__ = ['TestSNMPOpenWRT'] @@ -16,15 +17,19 @@ def setUp(self): # mock calls being made to devices self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') - self.nextcmd_patcher = self._patch( - 'pysnmp.entity.rfc3413.oneliner.cmdgen.CommandGenerator.nextCmd', + self.nextcmd_patcher = SpyMock._patch( + target=cmdgen.CommandGenerator, + attribute='nextCmd', + wrap_obj=self.device._command, return_value=[0, 0, 0, [0] * 5] ) - self.getcmd_patcher = self._patch( - 'pysnmp.entity.rfc3413.oneliner.cmdgen.CommandGenerator.getCmd', + self.getcmd_patcher = SpyMock._patch( + target=cmdgen.CommandGenerator, + attribute='getCmd', + wrap_obj=self.device._command, side_effect=lambda *args: self._get_mocked_getcmd( data=self.oid_mock_data, input=args - ) + ), ) self.getcmd_patcher.start() @@ -33,7 +38,7 @@ def test_os(self): def test_manufacturer(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) self.assertIsNotNone(self.device.manufacturer) def test_name(self): @@ -47,7 +52,7 @@ def test_uptime_tuple(self): def test_get_interfaces(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) self.assertIsInstance(self.device.get_interfaces(), list) def test_interfaces_speed(self): @@ -55,27 +60,27 @@ def test_interfaces_speed(self): def test_interfaces_bytes(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) self.assertIsInstance(self.device.interfaces_bytes, list) def test_interfaces_MAC(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) self.assertIsInstance(self.device.interfaces_MAC, list) def test_interfaces_type(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) self.assertIsInstance(self.device.interfaces_type, list) def test_interfaces_mtu(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) self.assertIsInstance(self.device.interfaces_mtu, list) def test_interfaces_state(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) self.assertIsInstance(self.device.interfaces_state, list) def test_interfaces_to_dict(self): @@ -93,7 +98,7 @@ def test_RAM_total(self): def test_to_dict(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) device_dict = self.device.to_dict() self.assertTrue(isinstance(device_dict, dict)) self.assertEqual( @@ -102,7 +107,7 @@ def test_to_dict(self): def test_manufacturer_to_dict(self): with self.nextcmd_patcher as p: - p.return_value = [0, 0, 0, [[[0, 1]]] * 5] + SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) self.assertIsNotNone(self.device.to_dict()['manufacturer']) def tearDown(self): diff --git a/tests/static/__init__.py b/tests/static/__init__.py index 7dec742..6e05705 100644 --- a/tests/static/__init__.py +++ b/tests/static/__init__.py @@ -1,58 +1,25 @@ import json import mock import os -from StringIO import StringIO from ..settings import settings +class SpyMock: + @staticmethod + def _patch(*args, **kwargs): + if not settings['disable_mocks']: + return mock.patch.object(*args, **kwargs) + wraps = getattr(kwargs['wrap_obj'], kwargs['attribute']) + return mock.patch.object(kwargs['target'], kwargs['attribute'], wraps=wraps) -class MockOutputMixin(object): - - class DisableMockMixin(object): - """ - Disables the mock object in context managers restoring the mocked - function to its original state - """ - def assert_called(self, *args, **kwargs): - pass - - def assert_not_called(self, *args, **kwargs): - pass - - def assert_called_once(self, *args, **kwargs): - pass - - def assert_called_with(self, *args, **kwargs): - pass - - def assert_called_once_with(self, *args, **kwargs): - pass - - def assert_has_calls(self, *args, **kwargs): - pass - - def assert_any_call(self, *args, **kwargs): - pass - - def start(self): - pass - - def stop(self): - pass - - def __enter__(self, *args, **kwargs): - return self - - def __exit__(self, *args, **kwargs): - return True - - - def _patch(self, *args, **kwargs): + @staticmethod + def _update_patch(mock_obj, *args, **kwargs): if settings['disable_mocks']: - return self.DisableMockMixin() - else: - return mock.patch(*args, **kwargs) + return + mock_obj.__dict__.update(*args, **kwargs) + +class MockOutputMixin(object): @staticmethod def _load_mock_json(file): base_dir = os.path.dirname(os.path.abspath(__file__)) @@ -68,18 +35,6 @@ def _get_mocked_getcmd(data, input): result = "\n".join(result[0:]) return [0, 0, 0, [[0, result]]] - @staticmethod - def _get_mocked_exec_command(command, data): - result = data[command] - if type(result) == list: - result = "\n".join(result[0:]) - stdout = stderr = StringIO() - stdout.write(result) - stderr.write(None) - stdout.seek(0) - stderr.seek(0) - return 0, stdout, stderr - @staticmethod def _get_mocked_wireless_links(data): oid = data[2] From 5fd4ab4820cef0a5deb63837ea9a4d7c2c5c4bb6 Mon Sep 17 00:00:00 2001 From: purhan Date: Thu, 27 May 2021 16:17:21 +0530 Subject: [PATCH 20/26] [chores] Change exception test --- netengine/backends/snmp/base.py | 5 +---- tests/snmp/airos.py | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/netengine/backends/snmp/base.py b/netengine/backends/snmp/base.py index f9a5f00..4a629d3 100644 --- a/netengine/backends/snmp/base.py +++ b/netengine/backends/snmp/base.py @@ -102,10 +102,7 @@ def get_value(self, oid): returns value of oid, or raises NetEngineError Exception is anything wrong :oid string|tuple|list: string, tuple or list representing the OID to get """ - try: - result = self.get(oid) - except Exception as e: - raise NetEngineError('pysnmp raised an exception: {0}'.format(e)) + result = self.get(oid) try: return str(result[3][0][1]) # snmp stores results in several arrays except IndexError: diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index 562f0d8..7cb7a41 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -2,6 +2,7 @@ from netengine.backends.snmp import AirOS from netengine.exceptions import NetEngineError from pysnmp.entity.rfc3413.oneliner import cmdgen +from pysnmp.smi.error import NoSuchObjectError from ..settings import settings from ..static import MockOutputMixin, SpyMock @@ -38,7 +39,7 @@ def setUp(self): def test_get_value_error(self): self.getcmd_patcher.stop() - with self.assertRaises(NetEngineError): + with self.assertRaises(NoSuchObjectError): self.device.get_value('.') def test_validate_negative_result(self): From 6fddaffd1bde0b48dbfa8cffcd7438e79405d5bf Mon Sep 17 00:00:00 2001 From: purhan Date: Thu, 27 May 2021 16:29:32 +0530 Subject: [PATCH 21/26] [chores] Remove redundant lines --- tests/snmp/openwrt.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index d85f54e..3349d40 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -21,7 +21,7 @@ def setUp(self): target=cmdgen.CommandGenerator, attribute='nextCmd', wrap_obj=self.device._command, - return_value=[0, 0, 0, [0] * 5] + return_value=[0, 0, 0, [[[0, 1]]] * 5] ) self.getcmd_patcher = SpyMock._patch( target=cmdgen.CommandGenerator, @@ -37,8 +37,7 @@ def test_os(self): self.assertIsInstance(self.device.os, tuple) def test_manufacturer(self): - with self.nextcmd_patcher as p: - SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) + with self.nextcmd_patcher: self.assertIsNotNone(self.device.manufacturer) def test_name(self): @@ -51,36 +50,30 @@ def test_uptime_tuple(self): self.assertIsInstance(self.device.uptime_tuple, tuple) def test_get_interfaces(self): - with self.nextcmd_patcher as p: - SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) + with self.nextcmd_patcher: self.assertIsInstance(self.device.get_interfaces(), list) def test_interfaces_speed(self): self.assertIsInstance(self.device.interfaces_speed, list) def test_interfaces_bytes(self): - with self.nextcmd_patcher as p: - SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) + with self.nextcmd_patcher: self.assertIsInstance(self.device.interfaces_bytes, list) def test_interfaces_MAC(self): - with self.nextcmd_patcher as p: - SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) + with self.nextcmd_patcher: self.assertIsInstance(self.device.interfaces_MAC, list) def test_interfaces_type(self): - with self.nextcmd_patcher as p: - SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) + with self.nextcmd_patcher: self.assertIsInstance(self.device.interfaces_type, list) def test_interfaces_mtu(self): - with self.nextcmd_patcher as p: - SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) + with self.nextcmd_patcher: self.assertIsInstance(self.device.interfaces_mtu, list) def test_interfaces_state(self): - with self.nextcmd_patcher as p: - SpyMock._update_patch(p, _mock_return_value=[0, 0, 0, [[[0, 1]]] * 5]) + with self.nextcmd_patcher: self.assertIsInstance(self.device.interfaces_state, list) def test_interfaces_to_dict(self): From 740b7efc1a6602b4e36674b9beab8eed79484245 Mon Sep 17 00:00:00 2001 From: purhan Date: Fri, 28 May 2021 10:11:21 +0530 Subject: [PATCH 22/26] [chores] Fix failing test --- netengine/backends/base.py | 8 +++++--- tests/base.py | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/netengine/backends/base.py b/netengine/backends/base.py index 51a54c8..da893c0 100644 --- a/netengine/backends/base.py +++ b/netengine/backends/base.py @@ -1,7 +1,7 @@ import json from netengine.shortcuts import OrderedDict -from netaddr import EUI, NotRegisteredError, AddrFormatError +from netaddr import EUI, NotRegisteredError __all__ = [ @@ -135,7 +135,9 @@ def get_interfaces(self): def get_manufacturer(self, mac_address): """ returns the manufacturer of the network interface """ + if not mac_address: + return '' try: return EUI(mac_address).oui.registration().org - except (NotRegisteredError, AddrFormatError): - return None + except NotRegisteredError: + return '' diff --git a/tests/base.py b/tests/base.py index 0079aca..225e62c 100644 --- a/tests/base.py +++ b/tests/base.py @@ -2,7 +2,7 @@ from netengine import get_version, __version__ from netengine.backends import BaseBackend -from netengine.exceptions import NetEngineError +from netaddr import AddrFormatError __all__ = ['TestBaseBackend'] @@ -89,5 +89,5 @@ def test_base_backend(self): def test_get_manufacturer_unicode(self): device = BaseBackend() - with self.assertRaises(NetEngineError): + with self.assertRaises(AddrFormatError): device.get_manufacturer(u"wrong MAC") From eeac44eb1b197b9082861d0af38affa8f6a60881 Mon Sep 17 00:00:00 2001 From: purhan Date: Fri, 28 May 2021 10:21:34 +0530 Subject: [PATCH 23/26] [chores] Move logic to utils.py --- requirements-test.txt | 1 + tests/snmp/airos.py | 4 ++-- tests/snmp/openwrt.py | 4 ++-- tests/{static/__init__.py => utils.py} | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) rename tests/{static/__init__.py => utils.py} (97%) diff --git a/requirements-test.txt b/requirements-test.txt index f3c7e8e..a6c88f5 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1 +1,2 @@ nose +coverage diff --git a/tests/snmp/airos.py b/tests/snmp/airos.py index 7cb7a41..43aa1fe 100644 --- a/tests/snmp/airos.py +++ b/tests/snmp/airos.py @@ -5,7 +5,7 @@ from pysnmp.smi.error import NoSuchObjectError from ..settings import settings -from ..static import MockOutputMixin, SpyMock +from ..utils import MockOutputMixin, SpyMock __all__ = ['TestSNMPAirOS'] @@ -20,7 +20,7 @@ def setUp(self): self.device = AirOS(self.host, self.community, port=self.port) # mock calls being made to devices - self.oid_mock_data = self._load_mock_json('/test-airos-snmp.json') + self.oid_mock_data = self._load_mock_json('/static/test-airos-snmp.json') self.nextcmd_patcher = SpyMock._patch( target=cmdgen.CommandGenerator, attribute='nextCmd', diff --git a/tests/snmp/openwrt.py b/tests/snmp/openwrt.py index 3349d40..8a9a19c 100644 --- a/tests/snmp/openwrt.py +++ b/tests/snmp/openwrt.py @@ -3,7 +3,7 @@ from pysnmp.entity.rfc3413.oneliner import cmdgen from ..settings import settings -from ..static import MockOutputMixin, SpyMock +from ..utils import MockOutputMixin, SpyMock __all__ = ['TestSNMPOpenWRT'] @@ -16,7 +16,7 @@ def setUp(self): self.device = OpenWRT(self.host, self.community, self.port) # mock calls being made to devices - self.oid_mock_data = self._load_mock_json('/test-openwrt-snmp-oid.json') + self.oid_mock_data = self._load_mock_json('/static/test-openwrt-snmp-oid.json') self.nextcmd_patcher = SpyMock._patch( target=cmdgen.CommandGenerator, attribute='nextCmd', diff --git a/tests/static/__init__.py b/tests/utils.py similarity index 97% rename from tests/static/__init__.py rename to tests/utils.py index 6e05705..ee167f3 100644 --- a/tests/static/__init__.py +++ b/tests/utils.py @@ -2,7 +2,7 @@ import mock import os -from ..settings import settings +from .settings import settings class SpyMock: @staticmethod From bba187c7c57e42a92aea624b15d8138d2eb621f5 Mon Sep 17 00:00:00 2001 From: purhan Date: Fri, 28 May 2021 10:30:18 +0530 Subject: [PATCH 24/26] [chores] Fix default settings file name --- tests/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/settings.py b/tests/settings.py index 519fbcb..65c5c40 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1,6 +1,6 @@ import json import os -settings_file = os.getenv('TEST_SETTINGS_FILE', './test-settings.json') +settings_file = os.getenv('TEST_SETTINGS_FILE', './test-settings.example.json') settings = json.loads(open(settings_file).read()) settings['disable_mocks'] = os.getenv('DISABLE_MOCKS', '0') is '1' From 7a40cf19d2a12c52df2bc8f74819cc0703fcd9fb Mon Sep 17 00:00:00 2001 From: Purhan Kaushik Date: Fri, 28 May 2021 18:46:37 +0530 Subject: [PATCH 25/26] [chores/docs] Add file extension in docs Co-authored-by: Gagan Deep --- docs/source/topics/usage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/topics/usage.rst b/docs/source/topics/usage.rst index 5264dbe..2a09d19 100755 --- a/docs/source/topics/usage.rst +++ b/docs/source/topics/usage.rst @@ -39,7 +39,7 @@ Clone repo:: git clone git://github.com/openwisp/netengine - ./runtests + ./runtests.py To run tests on real devices, first copy the settings file:: From 61fc7ae323731dc83cf3a2d6c384b04dde568c11 Mon Sep 17 00:00:00 2001 From: Purhan Kaushik Date: Fri, 28 May 2021 18:46:49 +0530 Subject: [PATCH 26/26] [chores/docs] Add file extension in docs Co-authored-by: Gagan Deep --- docs/source/topics/usage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/topics/usage.rst b/docs/source/topics/usage.rst index 2a09d19..6c97c54 100755 --- a/docs/source/topics/usage.rst +++ b/docs/source/topics/usage.rst @@ -47,7 +47,7 @@ To run tests on real devices, first copy the settings file:: Then change the credentials accordingly, now run tests with:: - DISABLE_MOCKS=1 TEST_SETTINGS_FILE='test-settings.json' ./runtests + DISABLE_MOCKS=1 TEST_SETTINGS_FILE='test-settings.json' ./runtests.py See test coverage with::