diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 000000000..8531b0313
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,4 @@
+[run]
+omit =
+ lib/jnpr/junos/cfg/phyport/*
+ lib/jnpr/junos/cfg/srx/*
diff --git a/development.txt b/development.txt
index c9377f21e..5b8904b21 100644
--- a/development.txt
+++ b/development.txt
@@ -4,3 +4,4 @@ coverage # http://nedbatchelder.com/code/coverage/
mock # http://www.voidspace.org.uk/python/mock/
nose # http://nose.readthedocs.org/en/latest/
pep8 # https://github.com/jcrocholl/pep8
+pyflakes # https://launchpad.net/pyflakes
\ No newline at end of file
diff --git a/lib/jnpr/junos/device.py b/lib/jnpr/junos/device.py
index 4105e4d84..1fadf7fe3 100644
--- a/lib/jnpr/junos/device.py
+++ b/lib/jnpr/junos/device.py
@@ -294,7 +294,7 @@ def open(self, *vargs, **kvargs):
except socket.gaierror:
# invalid DNS name, so unreachable
- raise EzErrors.ConnectUnknownError(self)
+ raise EzErrors.ConnectUnknownHostError(self)
except Exception as err:
# anything else, we will re-raise as a
diff --git a/lib/jnpr/junos/utils/sw.py b/lib/jnpr/junos/utils/sw.py
index a41568c6b..e720f2350 100644
--- a/lib/jnpr/junos/utils/sw.py
+++ b/lib/jnpr/junos/utils/sw.py
@@ -132,7 +132,7 @@ def _scp_progress(_path, _total, _xfrd):
# execute the secure-copy with the Python SCP module
- with SCP(self._dev, progress=_scp_progress) as scp:
+ with SCP(self._dev, progress=_scp_progress) as scp:
scp.put(package, remote_path)
# -------------------------------------------------------------------------
diff --git a/tests/unit/facts/test_chassis.py b/tests/unit/facts/test_chassis.py
index 6fc7b3bb7..f2ce8e685 100644
--- a/tests/unit/facts/test_chassis.py
+++ b/tests/unit/facts/test_chassis.py
@@ -3,11 +3,13 @@
import unittest
from nose.plugins.attrib import attr
-from mock import patch
+from mock import patch, MagicMock
+from lxml import etree
import os
from jnpr.junos import Device
from jnpr.junos.facts.chassis import facts_chassis as chassis
+from jnpr.junos.exception import ConnectNotMasterError
from ncclient.manager import Manager, make_device_handler
from ncclient.transport import SSHSession
@@ -30,6 +32,12 @@ def test_2RE_true(self, mock_execute):
chassis(self.dev, self.facts)
self.assertTrue(self.facts['2RE'])
+ def test_chassis_exception_ConnectNotMasterError(self):
+ xmldata = etree.XML('')
+ self.dev.rpc.get_chassis_inventory = MagicMock(side_effect=xmldata)
+ with self.assertRaises(ConnectNotMasterError):
+ chassis(self.dev, self.facts)
+
def _read_file(self, fname):
from ncclient.xml_ import NCElement
diff --git a/tests/unit/facts/test_domain.py b/tests/unit/facts/test_domain.py
new file mode 100644
index 000000000..fcdd77639
--- /dev/null
+++ b/tests/unit/facts/test_domain.py
@@ -0,0 +1,42 @@
+__author__ = "Nitin Kumar, Rick Sherman"
+__credits__ = "Jeremy Schulman"
+
+import unittest
+from nose.plugins.attrib import attr
+from mock import patch
+
+from jnpr.junos.facts.domain import facts_domain
+from jnpr.junos import Device
+
+
+@attr('unit')
+class TestDomain(unittest.TestCase):
+
+ def setUp(self):
+ self.dev = Device(host='1.1.1.1', user='rick', password='password123',
+ gather_facts=False)
+ self.facts = {}
+
+ @patch('jnpr.junos.facts.domain.FS.cat')
+ def test_resolv_conf(self, mock_fs_cat):
+ mock_fs_cat.return_value =\
+ """# domain juniper.net
+ search englab.juniper.net spglab.juniper.net juniper.net jnpr.net
+ nameserver 10.11.12.13
+ """
+ self.facts['hostname'] = 'test'
+ facts_domain(self.dev, self.facts)
+ self.assertEqual(self.facts['domain'], 'juniper.net')
+ self.assertEqual(self.facts['fqdn'], 'test.juniper.net')
+
+ @patch('jnpr.junos.facts.domain.FS.cat')
+ def test_resolv_conf_no_domain(self, mock_fs_cat):
+ mock_fs_cat.return_value =\
+ """
+ search englab.juniper.net spglab.juniper.net juniper.net jnpr.net
+ nameserver 10.11.12.13
+ """
+ self.facts['hostname'] = 'test'
+ facts_domain(self.dev, self.facts)
+ self.assertIsNone(self.facts['domain'])
+ self.assertEqual(self.facts['fqdn'], 'test')
diff --git a/tests/unit/facts/test_swver.py b/tests/unit/facts/test_swver.py
index 34ab087c1..4c0a906b2 100644
--- a/tests/unit/facts/test_swver.py
+++ b/tests/unit/facts/test_swver.py
@@ -27,22 +27,22 @@ def test_version_info_repr(self):
'type=R, minor=7, build=5)')
def test_version_info_lt(self):
- self.assertTrue(version_info('13.3-20131120') < (14, 1))
+ self.assertLess(version_info('13.3-20131120'), (14, 1))
def test_version_info_lt_eq(self):
- self.assertTrue(version_info('13.3-20131120') <= (14, 1))
+ self.assertLessEqual(version_info('13.3-20131120'), (14, 1))
def test_version_info_gt(self):
- self.assertTrue(version_info('13.3-20131120') > (12, 1))
+ self.assertGreater(version_info('13.3-20131120'), (12, 1))
def test_version_info_gt_eq(self):
- self.assertTrue(version_info('13.3-20131120') >= (12, 1))
+ self.assertGreaterEqual(version_info('13.3-20131120'), (12, 1))
def test_version_info_eq(self):
- self.assertTrue(version_info('13.3-20131120') == (13, 3))
+ self.assertEqual(version_info('13.3-20131120'), (13, 3))
def test_version_info_not_eq(self):
- self.assertTrue(version_info('13.3-20131120') != (15, 3))
+ self.assertNotEqual(version_info('13.3-20131120'), (15, 3))
@attr('unit')
@@ -63,6 +63,14 @@ def test_swver(self, mock_execute):
software_version(self.dev, self.facts)
self.assertEqual(self.facts['version'], '12.3R6.6')
+ @patch('jnpr.junos.Device.execute')
+ def test_swver_hostname_none(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.facts['master'] = 'RE5'
+ self.facts['version_RE5'] = '15.3R6.6'
+ software_version(self.dev, self.facts)
+ self.assertEqual(self.facts['version'], '15.3R6.6')
+
# --> JLS, there should always be a facts['master'] assigned.
# @patch('jnpr.junos.Device.execute')
# def test_swver_master_none(self, mock_execute):
@@ -73,7 +81,7 @@ def test_swver(self, mock_execute):
@patch('jnpr.junos.Device.execute')
@patch('jnpr.junos.facts.swver.re.findall')
- def test_swver_exception_handling(self, mock_re_findall, mock_execute):
+ def test_swver_exception_handling(self, mock_re_findall, mock_execute):
mock_execute.side_effect = self._mock_manager
mock_re_findall.side_effect = IndexError
self.facts['master'] = 'RE0'
diff --git a/tests/unit/rpc-reply/show-configuration.xml b/tests/unit/rpc-reply/show-configuration.xml
new file mode 100644
index 000000000..ae8852d8d
--- /dev/null
+++ b/tests/unit/rpc-reply/show-configuration.xml
@@ -0,0 +1,154 @@
+
+
+## Last commit: 2014-03-24 16:34:32 UTC by rick
+version 12.1X46-D15.3;
+system {
+ host-name firefly;
+ root-authentication {
+ encrypted-password "$1$kmSqRIU6$9EogG7ow0DWiww9mev8.b."; ## SECRET-DATA
+ }
+ login {
+ user rick {
+ uid 2000;
+ class super-user;
+ authentication {
+ encrypted-password "$1$wDDri7eJ$2Ot4pfE29PgVbeutIveov1"; ## SECRET-DATA
+ }
+ }
+ }
+ services {
+ ssh;
+ netconf {
+ ssh;
+ }
+ web-management {
+ http {
+ interface ge-0/0/0.0;
+ }
+ }
+ }
+ syslog {
+ user * {
+ any emergency;
+ }
+ file messages {
+ any any;
+ authorization info;
+ }
+ file interactive-commands {
+ interactive-commands any;
+ }
+ }
+ license {
+ autoupdate {
+ url https://ae1.juniper.net/junos/key_retrieval;
+ }
+ }
+}
+interfaces {
+ ge-0/0/0 {
+ unit 0 {
+ family inet {
+ address 10.0.0.31/24;
+ }
+ }
+ }
+ ge-0/0/1 {
+ unit 0 {
+ family inet {
+ address 192.168.2.1/24;
+ }
+ }
+ }
+}
+routing-options {
+ static {
+ route 0.0.0.0/0 next-hop 10.0.0.1;
+ }
+}
+security {
+ screen {
+ ids-option untrust-screen {
+ icmp {
+ ping-death;
+ }
+ ip {
+ source-route-option;
+ tear-drop;
+ }
+ tcp {
+ syn-flood {
+ alarm-threshold 1024;
+ attack-threshold 200;
+ source-threshold 1024;
+ destination-threshold 2048;
+ queue-size 2000; ## Warning: 'queue-size' is deprecated
+ timeout 20;
+ }
+ land;
+ }
+ }
+ }
+ policies {
+ from-zone trust to-zone trust {
+ policy default-permit {
+ match {
+ source-address any;
+ destination-address any;
+ application any;
+ }
+ then {
+ permit;
+ }
+ }
+ }
+ from-zone trust to-zone untrust {
+ policy default-permit {
+ match {
+ source-address any;
+ destination-address any;
+ application any;
+ }
+ then {
+ permit;
+ }
+ }
+ }
+ from-zone untrust to-zone trust {
+ policy default-deny {
+ match {
+ source-address any;
+ destination-address any;
+ application any;
+ }
+ then {
+ deny;
+ }
+ }
+ }
+ }
+ zones {
+ security-zone trust {
+ tcp-rst;
+ }
+ security-zone untrust {
+ screen untrust-screen;
+ interfaces {
+ ge-0/0/0.0 {
+ host-inbound-traffic {
+ system-services {
+ http;
+ https;
+ ssh;
+ telnet;
+ dhcp;
+ netconf;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
diff --git a/tests/unit/rpc-reply/show-system-alarms.xml b/tests/unit/rpc-reply/show-system-alarms.xml
new file mode 100644
index 000000000..44c9567a7
--- /dev/null
+++ b/tests/unit/rpc-reply/show-system-alarms.xml
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/tests/unit/rpc-reply/show-system-uptime-rpc.xml b/tests/unit/rpc-reply/show-system-uptime-rpc.xml
new file mode 100644
index 000000000..415366b6c
--- /dev/null
+++ b/tests/unit/rpc-reply/show-system-uptime-rpc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/unit/templates/config-example.xml b/tests/unit/templates/config-example.xml
new file mode 100644
index 000000000..49be2f79b
--- /dev/null
+++ b/tests/unit/templates/config-example.xml
@@ -0,0 +1,4 @@
+system {
+ host-name {{ host_name }};
+ domain-name {{ domain_name }};
+}
diff --git a/tests/unit/test_device.py b/tests/unit/test_device.py
index 061d19766..7837474ba 100644
--- a/tests/unit/test_device.py
+++ b/tests/unit/test_device.py
@@ -1,7 +1,6 @@
-'''
+__author__ = "Rick Sherman, Nitin Kumar"
+__credits__ = "Jeremy Schulman"
-@author: rsherman
-'''
import unittest
from nose.plugins.attrib import attr
from mock import MagicMock, patch, mock_open
@@ -10,10 +9,13 @@
from ncclient.manager import Manager, make_device_handler
from ncclient.transport import SSHSession
+import ncclient.transport.errors as NcErrors
from jnpr.junos.facts.swver import version_info
from jnpr.junos import Device
from jnpr.junos.exception import RpcError
+from jnpr.junos import exception as EzErrors
+
facts = {'domain': None, 'hostname': 'firefly', 'ifd_style': 'CLASSIC',
'version_info': version_info('12.1X46-D15.3'),
@@ -66,6 +68,55 @@ def setUp(self, mock_connect):
def tearDown(self, mock_session):
self.dev.close()
+ @patch('jnpr.junos.device.netconf_ssh')
+ def test_device_ConnectAuthError(self, mock_manager):
+ mock_manager.connect.side_effect = NcErrors.AuthenticationError
+ with self.assertRaises(EzErrors.ConnectAuthError):
+ self.dev.open()
+
+ @patch('jnpr.junos.device.netconf_ssh')
+ def test_device_ConnectRefusedError(self, mock_manager):
+ mock_manager.connect.side_effect = NcErrors.SSHError
+ with self.assertRaises(EzErrors.ConnectRefusedError):
+ self.dev.open()
+
+ @patch('jnpr.junos.device.netconf_ssh')
+ @patch('jnpr.junos.device.datetime')
+ def test_device_ConnectTimeoutError(self, mock_datetime, mock_manager):
+ NcErrors.SSHError.message = 'cannot open'
+ mock_manager.connect.side_effect = NcErrors.SSHError
+ from datetime import timedelta, datetime
+ currenttime = datetime.now()
+ mock_datetime.datetime.now.side_effect = [currenttime,
+ currenttime + timedelta(minutes=4)]
+ with self.assertRaises(EzErrors.ConnectTimeoutError):
+ self.dev.open()
+
+ @patch('jnpr.junos.device.netconf_ssh')
+ @patch('jnpr.junos.device.datetime')
+ def test_device_diff_err_message(self, mock_datetime, mock_manager):
+ NcErrors.SSHError.message = 'why are you trying :)'
+ mock_manager.connect.side_effect = NcErrors.SSHError
+ from datetime import timedelta, datetime
+ currenttime = datetime.now()
+ mock_datetime.datetime.now.side_effect = [currenttime,
+ currenttime + timedelta(minutes=4)]
+ with self.assertRaises(EzErrors.ConnectError):
+ self.dev.open()
+
+ @patch('jnpr.junos.device.netconf_ssh')
+ def test_device_ConnectUnknownHostError(self, mock_manager):
+ import socket
+ mock_manager.connect.side_effect = socket.gaierror
+ with self.assertRaises(EzErrors.ConnectUnknownHostError):
+ self.dev.open()
+
+ @patch('jnpr.junos.device.netconf_ssh')
+ def test_device_other_error(self, mock_manager):
+ mock_manager.connect.side_effect = TypeError
+ with self.assertRaises(EzErrors.ConnectError):
+ self.dev.open()
+
def test_device_property_logfile_isinstance(self):
mock = MagicMock()
with patch('__builtin__.open', mock):
@@ -98,9 +149,22 @@ def test_device_repr(self):
@patch('jnpr.junos.device.os')
@patch('__builtin__.open')
- def test_device__sshconf_lkup(self, os_mock, open_mock):
+ @patch('paramiko.config.SSHConfig.lookup')
+ def test_device__sshconf_lkup(self, os_mock, open_mock, mock_paramiko):
os_mock.path.exists.return_value = True
self.dev._sshconf_lkup()
+ mock_paramiko.assert_called_any()
+
+ @patch('os.getenv')
+ def test_device__sshconf_lkup_path_not_exists(self, mock_env):
+ mock_env.return_value = '/home/test'
+ self.assertIsNone(self.dev._sshconf_lkup())
+
+ @patch('os.getenv')
+ def test_device__sshconf_lkup_home_not_defined(self, mock_env):
+ mock_env.return_value = None
+ self.assertIsNone(self.dev._sshconf_lkup())
+ mock_env.assert_called_with('HOME')
@patch('ncclient.manager.connect')
@patch('jnpr.junos.Device.execute')
@@ -130,24 +194,24 @@ def test_device_facts(self, mock_execute):
assert self.dev.facts['version'] == facts['version']
def test_device_hostname(self):
- assert self.dev.hostname == '1.1.1.1'
+ self.assertEqual(self.dev.hostname, '1.1.1.1')
def test_device_user(self):
- assert self.dev.user == 'rick'
+ self.assertEqual(self.dev.user, 'rick')
def test_device_get_password(self):
- assert self.dev.password is None
+ self.assertIsNone(self.dev.password)
def test_device_set_password(self):
self.dev.password = 'secret'
- assert self.dev._password == 'secret'
+ self.assertEqual(self.dev._password, 'secret')
def test_device_get_timeout(self):
- assert self.dev.timeout == 30
+ self.assertEqual(self.dev.timeout, 30)
def test_device_set_timeout(self):
self.dev.timeout = 10
- assert self.dev.timeout == 10
+ self.assertEqual(self.dev.timeout, 10)
def test_device_manages(self):
self.assertEqual(self.dev.manages, [],
@@ -159,10 +223,26 @@ def test_device_set_facts_exception(self):
except RuntimeError as ex:
self.assertEqual(RuntimeError, type(ex))
- def test_device_cli(self):
- self.dev.execute = MagicMock(name='execute')
- self.dev.cli('show version')
- assert self.dev.execute.call_args[0][0].text == 'show version'
+ @patch('jnpr.junos.Device.execute')
+ def test_device_cli(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.assertEqual(self.dev.cli('show cli directory').tag, 'cli')
+
+ @patch('jnpr.junos.Device.execute')
+ def test_device_cli_conf_info(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.assertIn('ge-0/0/0', self.dev.cli('show configuration'))
+
+ @patch('jnpr.junos.Device.execute')
+ def test_device_cli_output(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.assertIn('Alarm', self.dev.cli('show system alarms'))
+
+ @patch('jnpr.junos.Device.execute')
+ def test_device_cli_rpc(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.assertEqual(self.dev.cli('show system uptime | display xml rpc')\
+ .tag, 'get-system-uptime-information')
def test_device_cli_exception(self):
self.dev.rpc.cli = MagicMock(side_effect=AttributeError)
@@ -171,11 +251,13 @@ def test_device_cli_exception(self):
def test_device_execute(self):
self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager)
- self.dev.execute('')
+ self.assertEqual(self.dev.execute('').tag,
+ 'directory-list')
def test_device_execute_topy(self):
self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager)
- self.dev.execute('', to_py=self._do_nothing)
+ self.assertEqual(self.dev.execute('',
+ to_py=self._do_nothing), 'Nothing')
def test_device_execute_exception(self):
class MyException(Exception):
@@ -206,8 +288,8 @@ def test_device_execute_ValueError(self):
self.assertRaises(ValueError, self.dev.execute, None)
def test_device_rpcmeta(self):
- assert self.dev.rpc.get_software_information.func_doc ==\
- 'get-software-information'
+ self.assertEqual(self.dev.rpc.get_software_information.func_doc,
+ 'get-software-information')
def test_device_probe_timeout_zero(self):
with patch('jnpr.junos.device.socket'):
@@ -227,14 +309,19 @@ def test_device_probe_timeout_exception(self):
mock_time.return_value = None
self.assertFalse(self.dev.probe(.01))
- def test_device_bind(self):
+ def test_device_bind_varg(self):
self.dev.bind()
mock = MagicMock()
- mock.__name__ = 'magic mock'
- #for *args
+ mock.__name__ = 'magic_mock'
self.dev.bind(mock)
- #for **kwargs
+ self.assertEqual(self.dev.magic_mock.__name__, 'magic_mock')
+
+ def test_device_bind_kvarg(self):
+ self.dev.bind()
+ mock = MagicMock()
+ mock.return_value = 'Test'
self.dev.bind(kw=mock)
+ self.assertEqual(self.dev.kw, 'Test')
def test_device_bind_varg_exception(self):
with self.assertRaises(ValueError):
@@ -255,8 +342,18 @@ def test_device_bind_kvarg_exception(self):
self.dev.bind(kw=mock)
def test_device_template(self):
- self.dev._j2ldr = MagicMock()
- self.dev.Template('test')
+ # Try to load the template relative to module base
+ try:
+ template = self.dev.Template('tests/unit/templates/config-example')
+ except:
+ # Try to load the template relative to test base
+ try:
+ template = self.dev.Template('templates/config-example')
+ except:
+ raise
+ self.assertEqual(template.render({'host_name': '1',
+ 'domain_name': '2'}),
+ 'system {\n host-name 1;\n domain-name 2;\n}')
def test_device_close(self):
def close_conn():
@@ -278,6 +375,10 @@ def _read_file(self, fname):
fname == 'get-system-core-dumps.xml'):
rpc_reply = NCElement(foo, self.dev._conn._device_handler
.transform_reply())
+ elif (fname == 'show-configuration.xml' or
+ fname == 'show-system-alarms.xml'):
+ rpc_reply = NCElement(foo, self.dev._conn._device_handler
+ .transform_reply())._NCElement__doc
else:
rpc_reply = NCElement(foo, self.dev._conn._device_handler
.transform_reply())._NCElement__doc[0]
@@ -294,6 +395,12 @@ def _mock_manager(self, *args, **kwargs):
if args[0].tag == 'command':
if args[0].text == 'show cli directory':
return self._read_file('show-cli-directory.xml')
+ elif args[0].text == 'show configuration':
+ return self._read_file('show-configuration.xml')
+ elif args[0].text == 'show system alarms':
+ return self._read_file('show-system-alarms.xml')
+ elif args[0].text == 'show system uptime | display xml rpc':
+ return self._read_file('show-system-uptime-rpc.xml')
else:
raise RpcError
@@ -301,8 +408,5 @@ def _mock_manager(self, *args, **kwargs):
return self._read_file(args[0].tag + '.xml')
def _do_nothing(self, *args, **kwargs):
- return
-
-if __name__ == "__main__":
- #import sys;sys.argv = ['', 'TestDevice.testName']
- unittest.main()
+ return 'Nothing'
+
diff --git a/tests/unit/test_jxml.py b/tests/unit/test_jxml.py
index 1cae06177..47d496e30 100644
--- a/tests/unit/test_jxml.py
+++ b/tests/unit/test_jxml.py
@@ -27,4 +27,9 @@ def test_remove_namespaces(self):
"""
import xml.etree.ElementTree as ET
root = ET.fromstring(xmldata)
- remove_namespaces(root)
+ test = remove_namespaces(root)
+ for elem in test.getiterator():
+ i = elem.tag.find('}')
+ if i > 0:
+ i = i + 1
+ self.assertLessEqual(i, 0)
diff --git a/tests/unit/test_rpcmeta.py b/tests/unit/test_rpcmeta.py
index 7a9096f51..952e4bff7 100644
--- a/tests/unit/test_rpcmeta.py
+++ b/tests/unit/test_rpcmeta.py
@@ -22,9 +22,11 @@ def test_rpcmeta_constructor(self):
self.assertIsInstance(self.rpc._junos, Device)
@patch('jnpr.junos.device.Device.execute')
- def test_rpcmeta_load_config_option(self, mock_execute_fn):
+ def test_rpcmeta_load_config(self, mock_execute_fn):
root = etree.XML('test')
self.rpc.load_config(root)
+ self.assertEqual(mock_execute_fn.call_args[0][0].tag,
+ 'load-configuration')
@patch('jnpr.junos.device.Device.execute')
def test_rpcmeta_load_config_option_action(self, mock_execute_fn):
@@ -33,6 +35,8 @@ def test_rpcmeta_load_config_option_action(self, mock_execute_fn):
set system domain-name test.juniper.net
"""
self.rpc.load_config(set_commands, action='set')
+ self.assertEqual(mock_execute_fn.call_args[0][0].get('action'),
+ 'set')
@patch('jnpr.junos.device.Device.execute')
def test_rpcmeta_option_format(self, mock_execute_fn):
@@ -41,11 +45,17 @@ def test_rpcmeta_option_format(self, mock_execute_fn):
set system domain-name test.juniper.net
"""
self.rpc.load_config(set_commands, format='text')
+ self.assertEqual(mock_execute_fn.call_args[0][0].get('format'),
+ 'text')
@patch('jnpr.junos.device.Device.execute')
def test_rpcmeta_exec_rpc_vargs(self, mock_execute_fn):
self.rpc.system_users_information(dict(format='text'))
+ self.assertEqual(mock_execute_fn.call_args[0][0].get('format'),
+ 'text')
@patch('jnpr.junos.device.Device.execute')
def test_rpcmeta_exec_rpc_kvargs(self, mock_execute_fn):
self.rpc.system_users_information(set_data=('test',))
+ self.assertEqual(mock_execute_fn.call_args[0][0][0].text,
+ 'test')
diff --git a/tests/unit/utils/rpc-reply/checksum.xml b/tests/unit/utils/rpc-reply/checksum.xml
new file mode 100644
index 000000000..07e8ee89d
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/checksum.xml
@@ -0,0 +1,8 @@
+
+
+ xxxx
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/file-archive.xml b/tests/unit/utils/rpc-reply/file-archive.xml
new file mode 100644
index 000000000..2b2f10cd5
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/file-archive.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ /var/tmp//abckLjq
+
+
+
+
+
+
+ /var/tmp//abckLjq
+ abc.tar
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/unit/utils/rpc-reply/file-list_dir.xml b/tests/unit/utils/rpc-reply/file-list_dir.xml
new file mode 100644
index 000000000..1bf53dc26
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/file-list_dir.xml
@@ -0,0 +1,21 @@
+
+
+
+ /var
+ 123
+
+ abc
+
+ 555
+ root
+ xyz
+ 1
+ 2
+ 1392651039
+
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/file-list_file.xml b/tests/unit/utils/rpc-reply/file-list_file.xml
new file mode 100644
index 000000000..32d25303f
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/file-list_file.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ /var/abc.sh
+
+ 755
+ pqr
+ abc
+ 1
+ 2
+ 1394693680
+
+ 1
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/unit/utils/rpc-reply/file-list_symlink.xml b/tests/unit/utils/rpc-reply/file-list_symlink.xml
new file mode 100644
index 000000000..849100721
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/file-list_symlink.xml
@@ -0,0 +1,21 @@
+
+
+
+ /var
+ 123
+
+ abc
+ symlink test
+ 555
+ root
+ xyz
+ 1
+ 2
+ 1392651039
+
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/file-show.xml b/tests/unit/utils/rpc-reply/file-show.xml
new file mode 100644
index 000000000..10c82188e
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/file-show.xml
@@ -0,0 +1,8 @@
+
+
+ testing cat functionality
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/unit/utils/rpc-reply/get-chassis-inventory.xml b/tests/unit/utils/rpc-reply/get-chassis-inventory.xml
new file mode 100644
index 000000000..d15410a03
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/get-chassis-inventory.xml
@@ -0,0 +1,33 @@
+
+
+
+ Chassis
+ aaf5fe5f9b88
+ FIREFLY-PERIMETER
+
+ Midplane
+
+
+ System IO
+
+
+ Routing Engine
+ FIREFLY-PERIMETER RE
+
+
+ FPC 0
+ Virtual FPC
+
+ PIC 0
+ Virtual GE
+
+
+
+ Power Supply 0
+
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/get-checksum-information.xml b/tests/unit/utils/rpc-reply/get-checksum-information.xml
new file mode 100644
index 000000000..3669fab43
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/get-checksum-information.xml
@@ -0,0 +1,12 @@
+
+
+
+ MD5
+ safecopy.tgz
+ 96a35ab371e1ca10408c3caecdbd8a67
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/unit/utils/rpc-reply/get-configuration.xml b/tests/unit/utils/rpc-reply/get-configuration.xml
new file mode 100644
index 000000000..d4b0d42b7
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/get-configuration.xml
@@ -0,0 +1,214 @@
+
+
+ 12.1X46-D15.3
+
+ firefly
+
+ $1$kmSqRIU6$9EogG7ow0DWiww9mev8.b.
+
+
+
+ rick
+ 2000
+ super-user
+
+ $1$wDDri7eJ$2Ot4pfE29PgVbeutIveov1
+
+
+
+
+
+
+
+
+
+
+
+
+ ge-0/0/0.0
+
+
+
+
+
+ *
+
+ any
+
+
+
+
+ messages
+
+ any
+
+
+
+ authorization
+
+
+
+
+ interactive-commands
+
+ interactive-commands
+
+
+
+
+
+
+
+ https://ae1.juniper.net/junos/key_retrieval
+
+
+
+
+
+
+ ge-0/0/0
+
+ 0
+
+
+
+ 10.0.0.31/24
+
+
+
+
+
+
+ ge-0/0/1
+
+ 0
+
+
+
+ 192.168.2.1/24
+
+
+
+
+
+
+
+
+
+ 0.0.0.0/0
+ 10.0.0.1
+
+
+
+
+
+
+ untrust-screen
+
+
+
+
+
+
+
+
+
+ 1024
+ 200
+ 1024
+ 2048
+ 2000
+ 20
+
+
+
+
+
+
+
+ trust
+ trust
+
+ default-permit
+
+ any
+ any
+ any
+
+
+
+
+
+
+
+
+ trust
+ untrust
+
+ default-permit
+
+ any
+ any
+ any
+
+
+
+
+
+
+
+
+ untrust
+ trust
+
+ default-deny
+
+ any
+ any
+ any
+
+
+
+
+
+
+
+
+
+ trust
+
+
+
+ untrust
+ untrust-screen
+
+ ge-0/0/0.0
+
+
+ http
+
+
+ https
+
+
+ ssh
+
+
+ telnet
+
+
+ dhcp
+
+
+ netconf
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/get-route-engine-information.xml b/tests/unit/utils/rpc-reply/get-route-engine-information.xml
new file mode 100644
index 000000000..6dc37692c
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/get-route-engine-information.xml
@@ -0,0 +1,31 @@
+
+
+
+ Testing
+ 2048
+ 819
+ 40
+ 1150
+ 460
+ 40
+ 898
+ 350
+ 39
+ 0
+ 0
+ 0
+ 0
+ 100
+ FIREFLY-PERIMETER RE
+ 2014-03-26 13:15:20 UTC
+ 6 hours, 29 minutes, 30 seconds
+ Router rebooted after a normal shutdown.
+ 0.00
+ 0.00
+ 0.00
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/get-software-information.xml b/tests/unit/utils/rpc-reply/get-software-information.xml
new file mode 100644
index 000000000..6905d08fb
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/get-software-information.xml
@@ -0,0 +1,14 @@
+
+
+ firefly
+ firefly-perimeter
+ firefly-perimeter
+
+ junos
+ JUNOS Software Release [12.1X46-D15.3]
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/get-system-storage.xml b/tests/unit/utils/rpc-reply/get-system-storage.xml
new file mode 100644
index 000000000..0f406885d
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/get-system-storage.xml
@@ -0,0 +1,15 @@
+
+
+
+ /dev/abc
+ 567431
+ 2346455
+ 234234
+ 1
+ /
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/request-package-add.xml b/tests/unit/utils/rpc-reply/request-package-add.xml
new file mode 100644
index 000000000..c4cd1f9bc
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/request-package-add.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ hup
+
+
+
+
+ 0
+
+
\ No newline at end of file
diff --git a/tests/unit/utils/rpc-reply/request-package-rollback.xml b/tests/unit/utils/rpc-reply/request-package-rollback.xml
new file mode 100644
index 000000000..5c8a05b11
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/request-package-rollback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ member1
+
+
+ 1
+
+
+
+
+ {master:member1-re0}
+
+
diff --git a/tests/unit/utils/rpc-reply/request-package-validate.xml b/tests/unit/utils/rpc-reply/request-package-validate.xml
new file mode 100644
index 000000000..bee2495ef
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/request-package-validate.xml
@@ -0,0 +1,40 @@
+
+
+
+ hup
+
+
+
+ 0
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/request-power-off.xml b/tests/unit/utils/rpc-reply/request-power-off.xml
new file mode 100644
index 000000000..408e9e129
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/request-power-off.xml
@@ -0,0 +1,33 @@
+
+
+
+ This command will not halt the other routing-engine.
+ If planning to switch off power, use the both-routing-engines option.
+
+
+
+
+
+ yes
+ Perform the operation
+
+
+
+ no
+ Don't perform the operation
+
+
+ no
+ Power Off the system ? [yes,no] (no)
+
+
+
+
+ Shutdown NOW!
+ [pid 17221]
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/unit/utils/rpc-reply/request-reboot.xml b/tests/unit/utils/rpc-reply/request-reboot.xml
new file mode 100644
index 000000000..a6d1c983e
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/request-reboot.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ yes
+ Perform the operation
+
+
+
+ no
+ Don't perform the operation
+
+
+ no
+ Reboot the system ? [yes,no] (no)
+
+
+
+
+ Shutdown NOW!
+ [pid 17221]
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/request-system-storage-cleanup.xml b/tests/unit/utils/rpc-reply/request-system-storage-cleanup.xml
new file mode 100644
index 000000000..73e0ae04d
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/request-system-storage-cleanup.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ /var/abc.txt
+ 11
+ Apr 25 10:38
+
+
+
+
+
+
+
diff --git a/tests/unit/utils/rpc-reply/show-cli-directory.xml b/tests/unit/utils/rpc-reply/show-cli-directory.xml
new file mode 100644
index 000000000..2eee530a4
--- /dev/null
+++ b/tests/unit/utils/rpc-reply/show-cli-directory.xml
@@ -0,0 +1,8 @@
+
+
+ /cf/var/home/rick
+
+
+
+
+
diff --git a/tests/unit/utils/test_config.py b/tests/unit/utils/test_config.py
index c2fac194c..f222cbc9b 100644
--- a/tests/unit/utils/test_config.py
+++ b/tests/unit/utils/test_config.py
@@ -25,6 +25,17 @@ def test_config_confirm(self):
self.conf.rpc.commit_configuration = MagicMock()
self.assertTrue(self.conf.commit(confirm=True))
+ def test_config_commit_confirm_timeout(self):
+ self.conf.rpc.commit_configuration = MagicMock()
+ self.conf.commit(confirm=10)
+ self.conf.rpc.commit_configuration\
+ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True})
+
+ def test_config_commit_comment(self):
+ self.conf.rpc.commit_configuration = MagicMock()
+ self.conf.commit(comment='Test')
+ self.conf.rpc.commit_configuration.assert_called_with(log='Test')
+
@patch('jnpr.junos.utils.config.JXML.remove_namespaces')
def test_config_commit_exception(self, mock_jxml):
with self.assertRaises(AttributeError):
@@ -81,10 +92,13 @@ def test_config_commit_check_exception_RpcError(self):
def test_config_diff(self):
self.conf.rpc.get_configuration = MagicMock()
self.conf.diff()
+ self.conf.rpc.get_configuration.\
+ assert_called_with({'compare': 'rollback', 'rollback': '0'})
def test_config_pdiff(self):
self.conf.diff = MagicMock(return_value='')
self.conf.pdiff()
+ self.conf.diff.assert_any_call()
def test_config_load(self):
self.assertRaises(RuntimeError, self.conf.load)
@@ -113,25 +127,41 @@ def test_config_load_lset_format_ValueError(self):
@patch('__builtin__.open')
@patch('jnpr.junos.utils.config.etree.XML')
- def test_config_load_path(self, mock_etree, mock_open):
+ def test_config_load_path_xml(self, mock_etree, mock_open):
self.conf.dev.Template = MagicMock()
mock_etree.return_value = 'rpc_contents'
self.conf.rpc.load_config = \
MagicMock(return_value=mock_etree.return_value)
self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents')
+ @patch('__builtin__.open')
+ def test_config_load_path_text(self, mock_open):
+ self.conf.rpc.load_config = MagicMock()
+ self.conf.load(path='test.conf')
+ self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'],
+ 'text')
+
+ @patch('__builtin__.open')
+ def test_config_load_path_set(self, mock_open):
+ self.conf.rpc.load_config = MagicMock()
+ self.conf.load(path='test.set')
+ self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'],
+ 'set')
+
def test_config_load_template_path(self):
self.conf.rpc.load_config = MagicMock()
self.conf.dev.Template = MagicMock()
self.conf.load(template_path='test.xml')
+ self.conf.dev.Template.assert_called_with('test.xml')
def test_config_load_template(self):
class Temp:
filename = 'abc.xml'
render = MagicMock()
self.conf.rpc.load_config = MagicMock()
-
self.conf.load(template=Temp)
+ self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'],
+ 'xml')
def test_config_diff_exception(self):
self.conf.rpc.get_configuration = MagicMock()
diff --git a/tests/unit/utils/test_fs.py b/tests/unit/utils/test_fs.py
new file mode 100644
index 000000000..520a5d1f5
--- /dev/null
+++ b/tests/unit/utils/test_fs.py
@@ -0,0 +1,333 @@
+__author__ = "Nitin Kumar, Rick Sherman"
+__credits__ = "Jeremy Schulman"
+
+import unittest
+from nose.plugins.attrib import attr
+import os
+
+from ncclient.manager import Manager, make_device_handler
+from ncclient.transport import SSHSession
+
+from jnpr.junos import Device
+from jnpr.junos.utils.fs import FS
+
+from mock import patch, MagicMock, call
+
+
+@attr('unit')
+class TestFS(unittest.TestCase):
+
+ @patch('ncclient.manager.connect')
+ def setUp(self, mock_connect):
+ mock_connect.side_effect = self._mock_manager
+ self.dev = Device(host='1.1.1.1', user='rick', password='password123',
+ gather_facts=False)
+ self.dev.open()
+ self.fs = FS(self.dev)
+
+ def test_cat_wrong_path_return_none(self):
+ path = 'test/report'
+ self.assertIsNone(self.fs.cat(path))
+
+ def test_cat(self):
+ self.fs._dev.rpc.file_show = MagicMock(side_effect=self._mock_manager)
+ path = 'test/cat.txt'
+ self.assertIn('testing cat functionality', self.fs.cat(path))
+ self.fs._dev.rpc.file_show.assert_called_with(filename='test/cat.txt')
+
+ def test_cwd(self):
+ self.fs._dev.rpc.set_cli_working_directory = MagicMock()
+ folder = 'test/report'
+ self.fs.cwd(folder)
+ self.fs._dev.rpc.set_cli_working_directory.\
+ assert_called_with(directory='test/report')
+
+ @patch('jnpr.junos.Device.execute')
+ def test_pwd(self, mock_execute):
+ mock_execute.side_effect = MagicMock(side_effect=self._mock_manager)
+ self.fs.pwd()
+ self.assertEqual(self.fs.pwd(), '/cf/var/home/rick')
+
+ def test_checksum_return_none(self):
+ path = 'test/report'
+ self.assertIsNone(self.fs.checksum(path))
+
+ def test_checksum_unknown_calc(self):
+ path = 'test/report'
+ self.assertRaises(ValueError, self.fs.checksum, path=path, calc='abc')
+
+ def test_checksum_return_rsp(self):
+ self.fs.dev.rpc.get_sha256_checksum_information = \
+ MagicMock(side_effect=self._mock_manager)
+ path = 'test/checksum'
+ self.assertEqual(self.fs.checksum(path, 'sha256'), 'xxxx')
+ self.fs.dev.rpc.get_sha256_checksum_information.\
+ assert_called_with(path='test/checksum')
+
+ def test_stat_calling___decode_file(self):
+ path = 'test/stat/decode_file'
+ self.fs.dev.rpc.file_list = \
+ MagicMock(side_effect=self._mock_manager)
+ self.assertDictEqual(self.fs.stat(path),
+ {'owner': 'pqr', 'path': '/var/abc.sh',
+ 'permissions': 755,
+ 'permissions_text': '-rwxr-xr-x', 'size': 2,
+ 'ts_date': 'Mar 13 06:54',
+ 'ts_epoc': '1394693680',
+ 'type': 'file'})
+
+ def test_stat_calling___decode_dir(self):
+ path = 'test/stat/decode_dir'
+ self.fs.dev.rpc.file_list = \
+ MagicMock(side_effect=self._mock_manager)
+ self.assertDictEqual(self.fs.stat(path),
+ {'path': '/var', 'type': 'dir', 'file_count': 1,
+ 'size': 2})
+
+ def test_stat_return_none(self):
+ path = 'test/abc'
+ self.fs.dev.rpc.file_list = MagicMock()
+ self.fs.dev.rpc.file_list.find.return_value = 'output'
+ self.assertIsNone(self.fs.stat(path))
+
+ def test_ls_calling___decode_file(self):
+ path = 'test/stat/decode_file'
+ self.fs.dev.rpc.file_list = \
+ MagicMock(side_effect=self._mock_manager)
+ self.assertDictEqual(self.fs.ls(path),
+ {'owner': 'pqr', 'path': '/var/abc.sh',
+ 'permissions': 755,
+ 'permissions_text': '-rwxr-xr-x', 'size': 2,
+ 'ts_date': 'Mar 13 06:54',
+ 'ts_epoc': '1394693680',
+ 'type': 'file'})
+
+ def test_ls_calling___decode_dir(self):
+ path = 'test/stat/decode_dir'
+ self.fs.dev.rpc.file_list = \
+ MagicMock(side_effect=self._mock_manager)
+ self.assertDictEqual(self.fs.ls(path),
+ {'files':
+ {'abc': {'permissions_text': 'drwxr-xr-x',
+ 'ts_date': 'Feb 17 15:30',
+ 'ts_epoc': '1392651039',
+ 'owner': 'root', 'path': 'abc',
+ 'size': 2, 'type': 'dir',
+ 'permissions': 555}},
+ 'path': '/var', 'type': 'dir',
+ 'file_count': 1,
+ 'size': 2})
+
+ def test_ls_return_none(self):
+ path = 'test/abc'
+ self.fs.dev.rpc.file_list = MagicMock()
+ self.fs.dev.rpc.file_list.find.return_value = 'output'
+ self.assertIsNone(self.fs.ls(path))
+
+ @patch('jnpr.junos.utils.fs.FS._decode_file')
+ def test_ls_link_path_false(self, mock_decode_file):
+ mock_decode_file.get.return_value = False
+ path = 'test/stat/decode_file'
+ self.fs.dev.rpc.file_list = \
+ MagicMock(side_effect=self._mock_manager)
+ op = self.fs.ls(path, followlink=False)
+ mock_decode_file.assert_has_calls(call().get('link'))
+
+ def test_ls_brief_true(self):
+ path = 'test/stat/decode_dir'
+ self.fs.dev.rpc.file_list = \
+ MagicMock(side_effect=self._mock_manager)
+ self.assertDictEqual(self.fs.ls(path, brief=True),
+ {'files': ['abc'], 'path': '/var',
+ 'type': 'dir', 'file_count': 1, 'size': 2})
+
+ def test_ls_calling___decode_dir_type_symbolic_link(self):
+ path = 'test/stat/decode_symbolic_link'
+ self.fs.dev.rpc.file_list = \
+ MagicMock(side_effect=self._mock_manager)
+ self.assertDictEqual(self.fs.ls(path),
+ {'files':
+ {'abc': {'permissions_text': 'drwxr-xr-x',
+ 'ts_date': 'Feb 17 15:30',
+ 'link': 'symlink test',
+ 'ts_epoc': '1392651039',
+ 'owner': 'root', 'path': 'abc',
+ 'size': 2, 'type': 'link',
+ 'permissions': 555}},
+ 'path': '/var', 'type': 'dir', 'file_count': 1,
+ 'size': 2})
+
+ def test_rm_return_true(self):
+ self.fs.dev.rpc.file_delete = MagicMock(return_value=True)
+ path = 'test/abc'
+ self.assertTrue(self.fs.rm(path))
+ self.fs.dev.rpc.file_delete.assert_called_once_with(
+ path='test/abc')
+
+ def test_rm_return_false(self):
+ path = 'test/abc'
+ self.fs.dev.rpc.file_delete = MagicMock(return_value=False)
+ self.assertFalse(self.fs.rm(path))
+ self.fs.dev.rpc.file_delete.assert_called_once_with(
+ path='test/abc')
+
+ def test_copy_return_true(self):
+ self.fs.dev.rpc.file_copy = MagicMock()
+ initial = 'test/abc'
+ final = 'test/xyz'
+ self.assertTrue(self.fs.cp(initial, final))
+ self.fs.dev.rpc.file_copy.assert_called_once_with(
+ source='test/abc',
+ destination='test/xyz')
+
+ def test_copy_return_false(self):
+ initial = 'test/abc'
+ final = 'test/xyz'
+ self.fs.dev.rpc.file_copy = MagicMock(side_effect=Exception)
+ self.assertFalse(self.fs.cp(initial, final))
+ self.fs.dev.rpc.file_copy.assert_called_once_with(
+ source='test/abc',
+ destination='test/xyz')
+
+ def test_move_return_true(self):
+ self.fs.dev.rpc.file_rename = MagicMock(return_value=True)
+ initial = 'test/abc'
+ final = 'test/xyz'
+ self.assertTrue(self.fs.mv(initial, final))
+ self.fs.dev.rpc.file_rename.assert_called_once_with(
+ source='test/abc',
+ destination='test/xyz')
+
+ def test_move_return_false(self):
+ initial = 'test/abc'
+ final = 'test/xyz'
+ self.fs.dev.rpc.file_rename = MagicMock(return_value=False)
+ self.assertFalse(self.fs.mv(initial, final))
+ self.fs.dev.rpc.file_rename.assert_called_once_with(
+ source='test/abc',
+ destination='test/xyz')
+
+ def test_tgz_return_true(self):
+ src = 'test/tgz.txt'
+ dst = 'test/xyz'
+ self.fs.dev.rpc.file_archive = MagicMock(return_value=True)
+ self.assertTrue(self.fs.tgz(src, dst))
+ self.fs.dev.rpc.file_archive.assert_called_once_with(
+ source='test/tgz.txt',
+ destination='test/xyz', compress=True)
+
+ @patch('jnpr.junos.Device.execute')
+ def test_tgz_return_error(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ src = 'test/tgz.txt'
+ dst = 'test/xyz'
+ self.assertIn('testing tgz', self.fs.tgz(src, dst))
+
+ @patch('jnpr.junos.utils.fs.StartShell')
+ def test_rmdir(self, mock_StartShell):
+ path = 'test/rmdir'
+ print self.fs.rmdir(path)
+ calls = [
+ call().__enter__(),
+ call().__enter__().run('rmdir test/rmdir'),
+ call().__exit__(None, None, None)]
+ mock_StartShell.assert_has_calls(calls)
+
+ @patch('jnpr.junos.utils.fs.StartShell')
+ def test_mkdir(self, mock_StartShell):
+ path = 'test/mkdir'
+ print self.fs.mkdir(path)
+ calls = [
+ call().__enter__(),
+ call().__enter__().run('mkdir -p test/mkdir'),
+ call().__exit__(None, None, None)]
+ mock_StartShell.assert_has_calls(calls)
+
+ @patch('jnpr.junos.utils.fs.StartShell')
+ def test_symlink(self, mock_StartShell):
+ src = 'test/tgz.txt'
+ dst = 'test/xyz'
+ print self.fs.symlink(src, dst)
+ calls = [
+ call().__enter__(),
+ call().__enter__().run('ln -sf test/tgz.txt test/xyz'),
+ call().__exit__(None, None, None)]
+ mock_StartShell.assert_has_calls(calls)
+
+ @patch('jnpr.junos.Device.execute')
+ def test_storage_usage(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.assertDictEqual(self.fs.storage_usage(),
+ {'/dev/abc':
+ {'avail_block': 234234,
+ 'used_blocks': 2346455, 'used_pct': '1',
+ 'mount': '/', 'total_blocks': 567431,
+ 'avail': '2F', 'used': '481M',
+ 'total': '4F'}})
+
+ @patch('jnpr.junos.Device.execute')
+ def test_storage_cleanup(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.assertDictEqual(self.fs.storage_cleanup(),
+ {'/var/abc.txt':
+ {'ts_date': 'Apr 25 10:38', 'size': 11}})
+
+ @patch('jnpr.junos.Device.execute')
+ def test_storage_cleanup_check(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.assertDictEqual(self.fs.storage_cleanup_check(),
+ {'/var/abc.txt':
+ {'ts_date': 'Apr 25 10:38', 'size': 11}})
+
+ def _read_file(self, fname):
+ from ncclient.xml_ import NCElement
+ fpath = os.path.join(os.path.dirname(__file__),
+ 'rpc-reply', fname)
+ foo = open(fpath).read()
+
+ if (fname == 'get-rpc-error.xml' or
+ fname == 'get-index-error.xml' or
+ fname == 'get-system-core-dumps.xml'):
+ rpc_reply = NCElement(foo, self.dev._conn._device_handler
+ .transform_reply())
+ elif (fname == 'show-configuration.xml' or
+ fname == 'show-system-alarms.xml'):
+ rpc_reply = NCElement(foo, self.dev._conn._device_handler
+ .transform_reply())._NCElement__doc
+ else:
+ rpc_reply = NCElement(foo, self.dev._conn._device_handler
+ .transform_reply())._NCElement__doc[0]
+ return rpc_reply
+
+ def _mock_manager(self, *args, **kwargs):
+ if kwargs:
+ # if 'path' in kwargs and 'detail' in kwargs:
+ # return self._read_file('dir_list_detail.xml')
+
+ if 'path' in kwargs:
+ if kwargs['path'] == 'test/stat/decode_dir':
+ return self._read_file('file-list_dir.xml')
+ elif kwargs['path'] == 'test/stat/decode_file':
+ return self._read_file('file-list_file.xml')
+ elif kwargs['path'] == 'test/checksum':
+ return self._read_file('checksum.xml')
+ elif kwargs['path'] == 'test/stat/decode_symbolic_link':
+ return self._read_file('file-list_symlink.xml')
+ if 'filename' in kwargs:
+ if kwargs['filename'] == 'test/cat.txt':
+ return self._read_file('file-show.xml')
+ device_params = kwargs['device_params']
+ device_handler = make_device_handler(device_params)
+ session = SSHSession(device_handler)
+ return Manager(session, device_handler)
+
+ elif args:
+ if args[0].tag == 'command':
+ if args[0].text == 'show cli directory':
+ return self._read_file('show-cli-directory.xml')
+ elif args[0].tag == 'get-system-storage':
+ return self._read_file('get-system-storage.xml')
+ elif args[0].tag == 'request-system-storage-cleanup':
+ return self._read_file('request-system-storage-cleanup.xml')
+ elif args[0].tag == 'file-archive':
+ return self._read_file('file-archive.xml')
diff --git a/tests/unit/utils/test_scp.py b/tests/unit/utils/test_scp.py
new file mode 100644
index 000000000..b1eac98c9
--- /dev/null
+++ b/tests/unit/utils/test_scp.py
@@ -0,0 +1,33 @@
+__author__ = "Rick Sherman"
+__credits__ = "Jeremy Schulman, Nitin Kumar"
+
+import unittest
+from nose.plugins.attrib import attr
+
+from jnpr.junos import Device
+from jnpr.junos.utils.scp import SCP
+
+from mock import patch
+
+
+@attr('unit')
+class TestScp(unittest.TestCase):
+ def setUp(self):
+ self.dev = Device(host='1.1.1.1')
+
+ @patch('paramiko.SSHClient')
+ def test_scp_open(self, mock_connect):
+ from scp import SCPClient
+ self.dev.bind(scp=SCP)
+ assert isinstance(self.dev.scp.open(), SCPClient)
+
+ @patch('paramiko.SSHClient')
+ def test_scp_close(self, mock_connect):
+ self.dev.bind(scp=SCP)
+ self.dev.scp.open()
+ self.assertIsNone(self.dev.scp.close())
+
+ @patch('paramiko.SSHClient')
+ def test_scp_context(self, mock_connect):
+ with SCP(self.dev) as scp:
+ scp.get('addrbook.conf')
diff --git a/tests/unit/utils/test_start_shell.py b/tests/unit/utils/test_start_shell.py
new file mode 100644
index 000000000..fb1087da2
--- /dev/null
+++ b/tests/unit/utils/test_start_shell.py
@@ -0,0 +1,52 @@
+__author__ = "Rick Sherman"
+__credits__ = "Jeremy Schulman, Nitin Kumar"
+
+import unittest
+from nose.plugins.attrib import attr
+
+from jnpr.junos import Device
+from jnpr.junos.utils.start_shell import StartShell
+
+from mock import patch, MagicMock, call
+
+
+@attr('unit')
+class TestStartShell(unittest.TestCase):
+ @patch('paramiko.SSHClient')
+ def setUp(self, mock_connect):
+ self.dev = Device(host='1.1.1.1')
+ self.shell = StartShell(self.dev)
+
+ @patch('paramiko.SSHClient')
+ @patch('jnpr.junos.utils.start_shell.StartShell.wait_for')
+ def test_startshell_open(self, mock_connect, mock_wait):
+ self.shell.open()
+ mock_connect.assert_called_with('% ')
+
+ @patch('paramiko.SSHClient')
+ def test_startshell_close(self, mock_connect):
+ self.shell._chan = MagicMock()
+ self.shell._client = MagicMock()
+ self.shell.close()
+ self.shell._client.close.assert_called_once()
+
+ @patch('jnpr.junos.utils.start_shell.StartShell.wait_for')
+ def test_startshell_run(self, mock_wait):
+ self.shell._chan = MagicMock()
+ self.shell.run('ls')
+ self.assertIn(call.send('echo $?'), self.shell._chan.mock_calls)
+
+ @patch('jnpr.junos.utils.start_shell.select')
+ def test_startshell_wait_for(self, mock_select):
+ mock_select.return_value = ['> ', 2, 3]
+ self.shell._chan = MagicMock()
+ self.assertIn(call.endswith('> '),
+ self.shell.wait_for('> ')[0].mock_calls)
+
+ @patch('jnpr.junos.utils.start_shell.StartShell.open')
+ @patch('jnpr.junos.utils.start_shell.StartShell.close')
+ def test_startshell_context(self, mock_open, mock_close):
+ with StartShell(self.dev) as shell:
+ shell._chan = MagicMock()
+ shell.send('test')
+ mock_close.assert_called_once(call())
diff --git a/tests/unit/utils/test_sw.py b/tests/unit/utils/test_sw.py
new file mode 100644
index 000000000..4525d4506
--- /dev/null
+++ b/tests/unit/utils/test_sw.py
@@ -0,0 +1,277 @@
+__author__ = "Nitin Kumar, Rick Sherman"
+__credits__ = "Jeremy Schulman"
+
+import unittest
+from nose.plugins.attrib import attr
+
+import os
+import sys
+from cStringIO import StringIO
+from contextlib import contextmanager
+
+from jnpr.junos import Device
+from jnpr.junos.exception import RpcError
+from jnpr.junos.utils.sw import SW
+from jnpr.junos.facts.swver import version_info
+from ncclient.manager import Manager, make_device_handler
+from ncclient.transport import SSHSession
+
+from jnpr.junos.exception import RpcError
+from lxml import etree
+
+from mock import patch, MagicMock, call, mock_open
+
+
+facts = {'domain': None, 'hostname': 'firefly', 'ifd_style': 'CLASSIC',
+ 'version_info': version_info('12.1X46-D15.3'),
+ '2RE': False, 'serialnumber': 'aaf5fe5f9b88', 'fqdn': 'firefly',
+ 'virtual': True, 'switch_style': 'NONE', 'version': '12.1X46-D15.3',
+ 'HOME': '/cf/var/home/rick', 'srx_cluster': False,
+ 'model': 'FIREFLY-PERIMETER',
+ 'RE0': {'status': 'Testing',
+ 'last_reboot_reason': 'Router rebooted after a '
+ 'normal shutdown.',
+ 'model': 'FIREFLY-PERIMETER RE',
+ 'up_time': '6 hours, 29 minutes, 30 seconds'},
+ 'vc_capable': False, 'personality': 'SRX_BRANCH'}
+
+
+@attr('unit')
+class TestSW(unittest.TestCase):
+
+ @patch('ncclient.manager.connect')
+ def setUp(self, mock_connect):
+ mock_connect.side_effect = self._mock_manager
+ self.dev = Device(host='1.1.1.1', user='rick', password='password123',
+ gather_facts=False)
+ self.dev.open()
+ self.dev._facts = facts
+ self.sw = self.get_sw()
+
+ @patch('jnpr.junos.Device.execute')
+ def get_sw(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ return SW(self.dev)
+
+ @patch('ncclient.operations.session.CloseSession.request')
+ def tearDown(self, mock_session):
+ self.dev.close()
+
+ def test_sw_hashfile(self):
+ with patch('__builtin__.open', mock_open(), create=True) as m:
+ import jnpr.junos.utils.sw
+ with open('foo') as h:
+ h.read.side_effect = ('abc', 'a', '')
+ jnpr.junos.utils.sw._hashfile(h, MagicMock())
+ self.assertEqual(h.read.call_count, 3)
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_constructor_multi_re(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.sw = SW(self.dev)
+ self.assertFalse(self.sw._multi_RE)
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_constructor_multi_mx(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.sw = SW(self.dev)
+ self.assertFalse(self.sw._multi_MX)
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_constructor_multi_vc(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.sw = SW(self.dev)
+ self.assertFalse(self.sw._multi_VC)
+
+ @patch('__builtin__.open')
+ def test_sw_local_sha256(self, mock_built_open):
+ package = 'test.tgz'
+ self.assertEqual(SW.local_sha256(package),
+ 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934'
+ 'ca495991b7852b855')
+
+ @patch('__builtin__.open')
+ def test_sw_local_md5(self, mock_built_open):
+ package = 'test.tgz'
+ self.assertEqual(SW.local_md5(package),
+ 'd41d8cd98f00b204e9800998ecf8427e')
+
+ @patch('__builtin__.open')
+ def test_sw_local_sha1(self, mock_built_open):
+ package = 'test.tgz'
+ self.assertEqual(SW.local_sha1(package),
+ 'da39a3ee5e6b4b0d3255bfef95601890afd80709')
+
+ def test_sw_progress(self):
+ with self.capture(SW.progress, self.dev, 'running') as output:
+ self.assertEqual('1.1.1.1: running\n', output)
+
+ @patch('paramiko.SSHClient')
+ @patch('scp.SCPClient.put')
+ def test_sw_put(self, mock_scp_put, mock_scp):
+ #mock_scp_put.side_effect = self.mock_put
+ package = 'test.tgz'
+ self.sw.put(package)
+ self.assertIn(call('test.tgz', '/var/tmp'),
+ mock_scp_put.mock_calls)
+
+ @patch('jnpr.junos.utils.scp.SCP.__exit__')
+ @patch('jnpr.junos.utils.scp.SCP.__init__')
+ @patch('jnpr.junos.utils.scp.SCP.__enter__')
+ def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit):
+ package = 'test.tgz'
+ mock_scp.side_effect = self._fake_scp
+ self.sw.put(package, progress=self._myprogress)
+ self.assertEqual(mock_scp.call_args_list[0][1]['progress'].by10pct, 50)
+
+ def _fake_scp(self, *args, **kwargs):
+ progress = kwargs['progress']
+ progress('test.tgz', 100, 50)
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_pkgadd(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ package = 'test.tgz'
+ self.assertTrue(self.sw.pkgadd(package))
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_validate(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ package = 'package.tgz'
+ self.assertTrue(self.sw.validate(package))
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_safe_copy(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ package = 'safecopy.tgz'
+ self.sw.put = MagicMock()
+ SW.local_md5 = MagicMock()
+
+ self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True,
+ checksum='96a35ab371e1ca10408c3caecdbd8a67'))
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_safe_copy_return_false(self, mock_execute):
+ # not passing checksum value, will get random from magicmock
+ mock_execute.side_effect = self._mock_manager
+ package = 'safecopy.tgz'
+ self.sw.put = MagicMock()
+ SW.local_md5 = MagicMock()
+
+ self.assertFalse(self.sw.safe_copy(package, progress=self._myprogress,
+ cleanfs=True))
+ SW.local_md5.assert_called_with(package)
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_safe_copy_checksum_none(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ package = 'safecopy.tgz'
+ self.sw.put = MagicMock()
+ SW.local_md5 = MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')
+
+ self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress,
+ cleanfs=True))
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_safe_install(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ package = 'install.tgz'
+ self.sw.put = MagicMock()
+ SW.local_md5 = MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')
+ self.assertTrue(self.sw.install(package, progress=self._myprogress,
+ cleanfs=True))
+
+ @patch('jnpr.junos.utils.sw.SW.safe_copy')
+ def test_sw_safe_install_copy_fail(self, mock_copy):
+ mock_copy.return_value = False
+ self.assertFalse(self.sw.install('file'))
+
+ @patch('jnpr.junos.utils.sw.SW.validate')
+ def test_sw_install_validate(self, mock_validate):
+ mock_validate.return_value = False
+ self.assertFalse(self.sw.install('file', validate=True, no_copy=True))
+
+ @patch('jnpr.junos.utils.sw.SW.pkgadd')
+ def test_sw_install_multi_mx(self, mock_pkgadd):
+ mock_pkgadd.return_value = True
+ self.sw._multi_RE = True
+ self.sw._multi_MX = True
+ self.assertTrue(self.sw.install('file', no_copy=True))
+
+ @patch('jnpr.junos.utils.sw.SW.pkgadd')
+ def test_sw_install_multi_vc(self, mock_pkgadd):
+ mock_pkgadd.return_value = True
+ self.sw._multi_RE = True
+ self.sw._multi_VC = True
+ self.sw._RE_list = ('version_RE0', 'version_RE1')
+ self.assertTrue(self.sw.install('file', no_copy=True))
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_rollback(self, mock_execute):
+ # we need proper xml for this test case, update request-package-roll
+ # back.xml
+ mock_execute.side_effect = self._mock_manager
+ self.assertEqual(self.sw.rollback(), '')
+
+ def test_sw_inventory(self):
+ self.sw.dev.rpc.file_list = \
+ MagicMock(side_effect=self._mock_manager)
+ self.assertDictEqual(self.sw.inventory,
+ {'current': None, 'rollback': None})
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_reboot(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.sw._multi_MX = True
+ self.assertIn('Shutdown NOW', self.sw.reboot())
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_reboot_exception(self, mock_execute):
+ rsp = etree.XML('test')
+ mock_execute.side_effect = RpcError(rsp=rsp)
+ self.assertRaises(Exception, self.sw.reboot)
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_poweroff(self, mock_execute):
+ mock_execute.side_effect = self._mock_manager
+ self.sw._multi_MX = True
+ self.assertIn('Shutdown NOW', self.sw.poweroff())
+
+ @patch('jnpr.junos.Device.execute')
+ def test_sw_poweroff_exception(self, mock_execute):
+ rsp = etree.XML('test')
+ mock_execute.side_effect = RpcError(rsp=rsp)
+ self.assertRaises(Exception, self.sw.poweroff)
+
+ def _myprogress(self, dev, report):
+ pass
+
+ @contextmanager
+ def capture(self, command, *args, **kwargs):
+ out, sys.stdout = sys.stdout, StringIO()
+ command(*args, **kwargs)
+ sys.stdout.seek(0)
+ yield sys.stdout.read()
+ sys.stdout = out
+
+ def _read_file(self, fname):
+ from ncclient.xml_ import NCElement
+
+ fpath = os.path.join(os.path.dirname(__file__),
+ 'rpc-reply', fname)
+ foo = open(fpath).read()
+ rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply())._NCElement__doc[0]
+ return rpc_reply
+
+ def _mock_manager(self, *args, **kwargs):
+ if kwargs:
+ if 'path' in kwargs:
+ if kwargs['path'] == '/packages':
+ return self._read_file('file-list_dir.xml')
+ device_params = kwargs['device_params']
+ device_handler = make_device_handler(device_params)
+ session = SSHSession(device_handler)
+ return Manager(session, device_handler)
+
+ elif args:
+ return self._read_file(args[0].tag + '.xml')
diff --git a/tests/unit/utils/test_util.py b/tests/unit/utils/test_util.py
new file mode 100644
index 000000000..5c6413833
--- /dev/null
+++ b/tests/unit/utils/test_util.py
@@ -0,0 +1,32 @@
+__author__ = "Nitin Kumar, Rick Sherman"
+__credits__ = "Jeremy Schulman"
+
+import unittest
+from nose.plugins.attrib import attr
+
+from jnpr.junos import Device
+from jnpr.junos.utils.util import Util
+
+from mock import patch
+
+
+@attr('unit')
+class TestUtil(unittest.TestCase):
+
+ @patch('ncclient.manager.connect')
+ def setUp(self, mock_connect):
+ self.dev = Device(host='1.1.1.1', user='nitin', password='password123',
+ gather_facts=False)
+ self.dev.open()
+ self.util = Util(self.dev)
+
+ def test_repr(self):
+ self.assertEqual(repr(self.util), 'jnpr.junos.utils.Util(1.1.1.1)')
+
+ def test_dev_setter_exception(self):
+ with self.assertRaises(RuntimeError):
+ self.util.dev = 'abc'
+
+ def test_rpc_setter_exception(self):
+ with self.assertRaises(RuntimeError):
+ self.util.rpc = 'abc'