Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2675672
[qa] Add mocks in base SSH unit tests
purhan Apr 18, 2021
68fa3ce
[qa] Add mocks in OpenWRT SSH unit tests
purhan Apr 18, 2021
6421847
[qa] Add mocks in OpenWRT SSH tests
purhan Apr 20, 2021
3c20fd8
[qa] Format json files
purhan Apr 20, 2021
a87cc39
[qa] Add back negative results test
purhan Apr 20, 2021
6a9095a
[qa] Mock testcases for OpenWRT SNMP backend
purhan Apr 23, 2021
f73205f
[qa] Mock testcases for AirOS SSH backend
purhan Apr 24, 2021
dece4a0
[qa] Mock tests for airos snmp backend
purhan May 9, 2021
bd30ed4
[chores] Remove redundant lines
purhan May 9, 2021
2a3e444
[qa] Mock remaining tests for SNMP AirOS
purhan May 19, 2021
4485d43
[chores] Rename function for clarity
purhan May 19, 2021
6a000db
[change] Remove the requirement of test-settings.json from unittests
purhan May 20, 2021
26c4f52
[chores] Include http tests in __init__.py
purhan May 20, 2021
f6f4eb5
[qa] Allow disabling mocks to use real devices in tests
purhan May 21, 2021
d4298bf
Revert "[qa] Allow disabling mocks to use real devices in tests"
purhan May 22, 2021
ea5398c
[qa] Allow running tests on real devices
purhan May 22, 2021
873b6dc
[chores] Add newline at the end of the file
purhan May 22, 2021
4e240ec
[change] Mock only external libraries
purhan May 23, 2021
7cddc92
[chores/requested-changes] Improvements to SNMP tests
purhan May 25, 2021
edf1ace
[chores] Merge branch master
purhan May 26, 2021
74b1646
[qa] Create spy mocks
purhan May 26, 2021
5fd4ab4
[chores] Change exception test
purhan May 27, 2021
6fddaff
[chores] Remove redundant lines
purhan May 27, 2021
87de032
Merge branch 'master' into mock-ssh-base
purhan May 28, 2021
740b7ef
[chores] Fix failing test
purhan May 28, 2021
eeac44e
[chores] Move logic to utils.py
purhan May 28, 2021
bba187c
[chores] Fix default settings file name
purhan May 28, 2021
7a40cf1
[chores/docs] Add file extension in docs
purhan May 28, 2021
61fc7ae
[chores/docs] Add file extension in docs
purhan May 28, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions docs/source/topics/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,24 @@ 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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@purhan this should not be necessary, please double check

pip install -r requirements-test.txt

Clone repo::

git clone git://github.com/openwisp/netengine

cd netengine/
./runtests.py

Edit settings json file according to your network::
To run tests on real devices, first copy the settings file::

cp test-settings.example.json test-settings.json
vim test-settings.json

Run tests with::
Then change the credentials accordingly, now run tests with::

nosetests
DISABLE_MOCKS=1 TEST_SETTINGS_FILE='test-settings.json' ./runtests.py

See test coverage with::

Expand All @@ -62,3 +62,6 @@ Run specific tests by specifying the relative path::
nosetests tests.snmp
# snmp openwrt specific tests
nosetests tests.snmp.openwrt

# run without mocks with a custom test file
DISABLE_MOCKS=1 TEST_SETTINGS_FILE='test-settings.json' nosetests tests.snmp
8 changes: 5 additions & 3 deletions netengine/backends/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json

from netengine.shortcuts import OrderedDict
from netaddr import EUI, NotRegisteredError, AddrFormatError
from netaddr import EUI, NotRegisteredError


__all__ = [
Expand Down Expand Up @@ -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 ''
2 changes: 2 additions & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
nose
coverage
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
netaddr
pysnmp
ipaddress
argparse
argparse
mock
23 changes: 23 additions & 0 deletions runtests.py
Original file line number Diff line number Diff line change
@@ -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
]
)
8 changes: 4 additions & 4 deletions test-settings.example.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"base-snmp": {
"host": "yourhost",
"host": "0.0.0.0",
"community": "public",
"port": 161
},
"airos-snmp": {
"host": "your_airos_device",
"host": "0.0.0.0",
"community": "public",
"port": 161
},
"openwrt-snmp": {
"host": "your_openwrt_device",
"host": "0.0.0.0",
"community": "public",
"port": 161
}
}
}
5 changes: 3 additions & 2 deletions tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand Down Expand Up @@ -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(AddrFormatError):
device.get_manufacturer(u"wrong MAC")
5 changes: 4 additions & 1 deletion tests/settings.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import json
import os

settings = json.loads(open('./test-settings.json').read())
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'
110 changes: 82 additions & 28 deletions tests/snmp/airos.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,49 @@
import unittest
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 ..utils import MockOutputMixin, SpyMock


__all__ = ['TestSNMPAirOS']


class TestSNMPAirOS(unittest.TestCase):
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.oid_mock_data = self._load_mock_json('/static/test-airos-snmp.json')
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 = 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()

def test_get_value_error(self):
with self.assertRaises(NetEngineError):
self.getcmd_patcher.stop()
with self.assertRaises(NoSuchObjectError):
self.device.get_value('.')

def test_validate_negative_result(self):
self.getcmd_patcher.stop()
wrong = AirOS('10.40.0.254', 'wrong', 'wrong')
self.assertRaises(NetEngineError, wrong.validate)

Expand All @@ -31,10 +53,8 @@ def test_validate_positive_result(self):
def test_get(self):
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))
Expand All @@ -51,67 +71,101 @@ 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):
self.assertTrue(type(self.device.get_interfaces()) == list)
with self.nextcmd_patcher:
self.assertIsInstance(self.device.get_interfaces(), list)

def test_get_interfaces_mtu(self):
self.assertTrue(type(self.device.interfaces_mtu) == list)
with self.nextcmd_patcher:
self.assertIsInstance(self.device.interfaces_mtu, list)

def test_interfaces_state(self):
self.assertTrue(type(self.device.interfaces_state) == list)
with self.nextcmd_patcher:
self.assertIsInstance(self.device.interfaces_state, list)

def test_interfaces_speed(self):
self.assertTrue(type(self.device.interfaces_speed) == list)
with self.nextcmd_patcher:
self.assertIsInstance(self.device.interfaces_speed, list)

def test_interfaces_bytes(self):
self.assertTrue(type(self.device.interfaces_bytes) == list)
with self.nextcmd_patcher:
self.assertIsInstance(self.device.interfaces_bytes, list)

def test_interfaces_MAC(self):
self.assertTrue(type(self.device.interfaces_MAC) == list)
with self.nextcmd_patcher:
self.assertIsInstance(self.device.interfaces_MAC, list)

def test_interfaces_type(self):
self.assertTrue(type(self.device.interfaces_type) == list)
with self.nextcmd_patcher:
self.assertIsInstance(self.device.interfaces_type, list)

def test_interfaces_to_dict(self):
self.assertTrue(type(self.device.interfaces_to_dict) == list)

with self.nextcmd_patcher:
self.assertIsInstance(self.device.interfaces_to_dict, list)

def test_wireless_dbm(self):
self.assertTrue(type(self.device.wireless_dbm) == list)
with self.nextcmd_patcher:
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):
self.assertTrue(type(self.device.wireless_links) == list)
with self.nextcmd_patcher as np:
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):
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):
self.assertTrue(isinstance(self.device.to_dict(), dict))
with self.nextcmd_patcher as np:
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):
self.assertIsNotNone(self.device.to_dict()['manufacturer'])
with self.nextcmd_patcher as np:
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):
self.assertIsNotNone(self.device.manufacturer)
with self.nextcmd_patcher:
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()
Loading