3 # Copyright (c) 2016 Orange and others.
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 """Define the classes required to fully cover odl."""
17 from keystoneauth1.exceptions import auth_plugins
19 from robot.errors import DataError, RobotError
20 from robot.result import model
21 from robot.utils.robottime import timestamp_to_secs
23 from six.moves import urllib
25 from functest.core import testcase
26 from functest.opnfv_tests.sdn.odl import odl
28 __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
31 class ODLVisitorTesting(unittest.TestCase):
33 """The class testing ODLResultVisitor."""
34 # pylint: disable=missing-docstring
37 self.visitor = odl.ODLResultVisitor()
40 self.assertFalse(self.visitor.get_data())
43 data = {'name': 'foo',
46 'starttime': "20161216 16:00:00.000",
47 'endtime': "20161216 16:00:01.000",
49 'text': 'Hello, World!',
51 test = model.TestCase(
52 name=data['name'], status=data['status'], message=data['text'],
53 starttime=data['starttime'], endtime=data['endtime'])
54 test.parent = mock.Mock()
55 config = {'name': data['parent'],
56 'criticality.test_is_critical.return_value': data[
58 test.parent.configure_mock(**config)
59 self.visitor.visit_test(test)
60 self.assertEqual(self.visitor.get_data(), [data])
63 class ODLTesting(unittest.TestCase):
65 """The super class which testing classes could inherit."""
66 # pylint: disable=missing-docstring
68 logging.disable(logging.CRITICAL)
70 _keystone_ip = "127.0.0.1"
71 _neutron_url = "http://127.0.0.2:9696"
72 _sdn_controller_ip = "127.0.0.3"
73 _os_auth_url = "http://{}:5000/v3".format(_keystone_ip)
74 _os_tenantname = "admin"
75 _os_username = "admin"
76 _os_password = "admin"
78 _odl_restconfport = "8181"
79 _odl_username = "admin"
80 _odl_password = "admin"
81 _os_userdomainname = 'Default'
82 _os_projectdomainname = 'Default'
85 for var in ("INSTALLER_TYPE", "SDN_CONTROLLER", "SDN_CONTROLLER_IP"):
88 os.environ["OS_AUTH_URL"] = self._os_auth_url
89 os.environ["OS_USERNAME"] = self._os_username
90 os.environ["OS_USER_DOMAIN_NAME"] = self._os_userdomainname
91 os.environ["OS_PASSWORD"] = self._os_password
92 os.environ["OS_TENANT_NAME"] = self._os_tenantname
93 os.environ["OS_PROJECT_DOMAIN_NAME"] = self._os_projectdomainname
94 os.environ["OS_PASSWORD"] = self._os_password
95 self.test = odl.ODLTests(case_name='odl', project_name='functest')
96 self.defaultargs = {'odlusername': self._odl_username,
97 'odlpassword': self._odl_password,
98 'neutronurl': "http://{}:9696".format(
100 'osauthurl': self._os_auth_url,
101 'osusername': self._os_username,
102 'osuserdomainname': self._os_userdomainname,
103 'ostenantname': self._os_tenantname,
104 'osprojectdomainname': self._os_projectdomainname,
105 'ospassword': self._os_password,
106 'odlip': self._keystone_ip,
107 'odlwebport': self._odl_webport,
108 'odlrestconfport': self._odl_restconfport,
112 class ODLParseResultTesting(ODLTesting):
114 """The class testing ODLTests.parse_results()."""
115 # pylint: disable=missing-docstring
117 _config = {'name': 'dummy', 'starttime': '20161216 16:00:00.000',
118 'endtime': '20161216 16:00:01.000'}
120 @mock.patch('robot.api.ExecutionResult', side_effect=DataError)
121 def test_raises_exc(self, mock_method):
122 with self.assertRaises(DataError):
123 self.test.parse_results()
124 mock_method.assert_called_once_with(
125 os.path.join(odl.ODLTests.res_dir, 'output.xml'))
127 def _test_result(self, config, result):
129 suite.configure_mock(**config)
130 with mock.patch('robot.api.ExecutionResult',
131 return_value=mock.Mock(suite=suite)):
132 self.test.parse_results()
133 self.assertEqual(self.test.result, result)
134 self.assertEqual(self.test.start_time,
135 timestamp_to_secs(config['starttime']))
136 self.assertEqual(self.test.stop_time,
137 timestamp_to_secs(config['endtime']))
138 self.assertEqual(self.test.details,
139 {'description': config['name'], 'tests': []})
141 def test_null_passed(self):
142 self._config.update({'statistics.critical.passed': 0,
143 'statistics.critical.total': 20})
144 self._test_result(self._config, 0)
146 def test_no_test(self):
147 self._config.update({'statistics.critical.passed': 20,
148 'statistics.critical.total': 0})
149 self._test_result(self._config, 0)
151 def test_half_success(self):
152 self._config.update({'statistics.critical.passed': 10,
153 'statistics.critical.total': 20})
154 self._test_result(self._config, 50)
156 def test_success(self):
157 self._config.update({'statistics.critical.passed': 20,
158 'statistics.critical.total': 20})
159 self._test_result(self._config, 100)
162 class ODLRobotTesting(ODLTesting):
164 """The class testing ODLTests.set_robotframework_vars()."""
165 # pylint: disable=missing-docstring
167 @mock.patch('fileinput.input', side_effect=Exception())
168 def test_set_vars_ko(self, mock_method):
169 self.assertFalse(self.test.set_robotframework_vars())
170 mock_method.assert_called_once_with(
171 os.path.join(odl.ODLTests.odl_test_repo,
172 'csit/variables/Variables.robot'), inplace=True)
174 @mock.patch('fileinput.input', return_value=[])
175 def test_set_vars_empty(self, mock_method):
176 self.assertTrue(self.test.set_robotframework_vars())
177 mock_method.assert_called_once_with(
178 os.path.join(odl.ODLTests.odl_test_repo,
179 'csit/variables/Variables.robot'), inplace=True)
181 @mock.patch('sys.stdout', new_callable=six.StringIO)
182 def _test_set_vars(self, msg1, msg2, *args):
183 line = mock.MagicMock()
184 line.__iter__.return_value = [msg1]
185 with mock.patch('fileinput.input', return_value=line) as mock_method:
186 self.assertTrue(self.test.set_robotframework_vars())
187 mock_method.assert_called_once_with(
188 os.path.join(odl.ODLTests.odl_test_repo,
189 'csit/variables/Variables.robot'), inplace=True)
190 self.assertEqual(args[0].getvalue(), "{}\n".format(msg2))
192 def test_set_vars_auth_default(self):
195 "@{AUTH} admin admin")
197 def test_set_vars_auth1(self):
202 @mock.patch('sys.stdout', new_callable=six.StringIO)
203 def test_set_vars_auth_foo(self, *args):
204 line = mock.MagicMock()
205 line.__iter__.return_value = ["@{AUTH} "]
206 with mock.patch('fileinput.input', return_value=line) as mock_method:
207 self.assertTrue(self.test.set_robotframework_vars('foo', 'bar'))
208 mock_method.assert_called_once_with(
209 os.path.join(odl.ODLTests.odl_test_repo,
210 'csit/variables/Variables.robot'), inplace=True)
216 class ODLMainTesting(ODLTesting):
218 """The class testing ODLTests.run_suites()."""
219 # pylint: disable=missing-docstring
221 def _get_run_suites_kwargs(self, key=None):
222 kwargs = {'odlusername': self._odl_username,
223 'odlpassword': self._odl_password,
224 'neutronurl': self._neutron_url,
225 'osauthurl': self._os_auth_url,
226 'osusername': self._os_username,
227 'osuserdomainname': self._os_userdomainname,
228 'ostenantname': self._os_tenantname,
229 'osprojectdomainname': self._os_projectdomainname,
230 'ospassword': self._os_password,
231 'odlip': self._sdn_controller_ip,
232 'odlwebport': self._odl_webport,
233 'odlrestconfport': self._odl_restconfport}
238 def _test_run_suites(self, status, *args):
239 kwargs = self._get_run_suites_kwargs()
240 self.assertEqual(self.test.run_suites(**kwargs), status)
242 args[0].assert_called_once_with(
243 odl.ODLTests.res_dir)
246 'KEYSTONEURL:{}://{}'.format(
247 urllib.parse.urlparse(self._os_auth_url).scheme,
248 urllib.parse.urlparse(self._os_auth_url).netloc),
249 'NEUTRONURL:{}'.format(self._neutron_url),
250 'OS_AUTH_URL:"{}"'.format(self._os_auth_url),
251 'OSUSERNAME:"{}"'.format(self._os_username),
252 'OSUSERDOMAINNAME:"{}"'.format(self._os_userdomainname),
253 'OSTENANTNAME:"{}"'.format(self._os_tenantname),
254 'OSPROJECTDOMAINNAME:"{}"'.format(self._os_projectdomainname),
255 'OSPASSWORD:"{}"'.format(self._os_password),
256 'ODL_SYSTEM_IP:{}'.format(self._sdn_controller_ip),
257 'PORT:{}'.format(self._odl_webport),
258 'RESTCONFPORT:{}'.format(self._odl_restconfport)]
259 args[1].assert_called_once_with(
260 odl.ODLTests.basic_suite_dir,
261 odl.ODLTests.neutron_suite_dir,
263 output=os.path.join(odl.ODLTests.res_dir, 'output.xml'),
268 args[2].assert_called_with(
269 os.path.join(odl.ODLTests.res_dir, 'stdout.txt'))
271 def _test_no_keyword(self, key):
272 kwargs = self._get_run_suites_kwargs(key)
273 self.assertEqual(self.test.run_suites(**kwargs),
274 testcase.TestCase.EX_RUN_ERROR)
276 def test_no_odlusername(self):
277 self._test_no_keyword('odlusername')
279 def test_no_odlpassword(self):
280 self._test_no_keyword('odlpassword')
282 def test_no_neutronurl(self):
283 self._test_no_keyword('neutronurl')
285 def test_no_osauthurl(self):
286 self._test_no_keyword('osauthurl')
288 def test_no_osusername(self):
289 self._test_no_keyword('osusername')
291 def test_no_ostenantname(self):
292 self._test_no_keyword('ostenantname')
294 def test_no_ospassword(self):
295 self._test_no_keyword('ospassword')
297 def test_no_odlip(self):
298 self._test_no_keyword('odlip')
300 def test_no_odlwebport(self):
301 self._test_no_keyword('odlwebport')
303 def test_no_odlrestconfport(self):
304 self._test_no_keyword('odlrestconfport')
306 def test_set_vars_ko(self):
307 with mock.patch.object(self.test, 'set_robotframework_vars',
308 return_value=False) as mock_object:
309 self._test_run_suites(testcase.TestCase.EX_RUN_ERROR)
310 mock_object.assert_called_once_with(
311 self._odl_username, self._odl_password)
313 @mock.patch('os.makedirs', side_effect=Exception)
314 def test_makedirs_exc(self, mock_method):
315 with mock.patch.object(self.test, 'set_robotframework_vars',
316 return_value=True), \
317 self.assertRaises(Exception):
318 self._test_run_suites(testcase.TestCase.EX_RUN_ERROR,
321 @mock.patch('os.makedirs', side_effect=OSError)
322 def test_makedirs_oserror(self, mock_method):
323 with mock.patch.object(self.test, 'set_robotframework_vars',
325 self._test_run_suites(testcase.TestCase.EX_RUN_ERROR,
328 @mock.patch('robot.run', side_effect=RobotError)
329 @mock.patch('os.makedirs')
330 def test_run_ko(self, *args):
331 with mock.patch.object(self.test, 'set_robotframework_vars',
332 return_value=True), \
333 self.assertRaises(RobotError):
334 self._test_run_suites(testcase.TestCase.EX_RUN_ERROR, *args)
336 @mock.patch('robot.run')
337 @mock.patch('os.makedirs')
338 def test_parse_results_ko(self, *args):
339 with mock.patch.object(self.test, 'set_robotframework_vars',
340 return_value=True), \
341 mock.patch.object(self.test, 'parse_results',
342 side_effect=RobotError):
343 self._test_run_suites(testcase.TestCase.EX_RUN_ERROR, *args)
345 @mock.patch('robot.run')
346 @mock.patch('os.makedirs')
347 def test_ok(self, *args):
348 with mock.patch.object(self.test, 'set_robotframework_vars',
349 return_value=True), \
350 mock.patch.object(self.test, 'parse_results'):
351 self._test_run_suites(testcase.TestCase.EX_OK, *args)
353 @mock.patch('robot.run')
354 @mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, ''))
355 def test_makedirs_oserror17(self, *args):
356 with mock.patch.object(self.test, 'set_robotframework_vars',
357 return_value=True), \
358 mock.patch.object(self.test, 'parse_results'):
359 self._test_run_suites(testcase.TestCase.EX_OK, *args)
361 @mock.patch('robot.run', return_value=1)
362 @mock.patch('os.makedirs')
363 def test_testcases_in_failure(self, *args):
364 with mock.patch.object(self.test, 'set_robotframework_vars',
365 return_value=True), \
366 mock.patch.object(self.test, 'parse_results'):
367 self._test_run_suites(testcase.TestCase.EX_OK, *args)
370 class ODLRunTesting(ODLTesting):
372 """The class testing ODLTests.run()."""
373 # pylint: disable=missing-docstring
375 def _test_no_env_var(self, var):
376 with mock.patch('functest.utils.openstack_utils.get_endpoint',
377 return_value=ODLTesting._neutron_url):
379 self.assertEqual(self.test.run(),
380 testcase.TestCase.EX_RUN_ERROR)
382 def _test_run(self, status=testcase.TestCase.EX_OK,
383 exception=None, **kwargs):
384 odlip = kwargs['odlip'] if 'odlip' in kwargs else '127.0.0.3'
385 odlwebport = kwargs['odlwebport'] if 'odlwebport' in kwargs else '8080'
386 odlrestconfport = (kwargs['odlrestconfport']
387 if 'odlrestconfport' in kwargs else '8181')
389 with mock.patch('functest.utils.openstack_utils.get_endpoint',
390 return_value=ODLTesting._neutron_url):
392 self.test.run_suites = mock.Mock(side_effect=exception)
394 self.test.run_suites = mock.Mock(return_value=status)
395 self.assertEqual(self.test.run(), status)
396 self.test.run_suites.assert_called_once_with(
397 odl.ODLTests.default_suites,
398 neutronurl=self._neutron_url,
399 odlip=odlip, odlpassword=self._odl_password,
400 odlrestconfport=odlrestconfport,
401 odlusername=self._odl_username, odlwebport=odlwebport,
402 osauthurl=self._os_auth_url,
403 ospassword=self._os_password, ostenantname=self._os_tenantname,
404 osusername=self._os_username,
405 osprojectdomainname=self._os_projectdomainname,
406 osuserdomainname=self._os_userdomainname)
408 def _test_multiple_suites(self, suites,
409 status=testcase.TestCase.EX_OK, **kwargs):
410 odlip = kwargs['odlip'] if 'odlip' in kwargs else '127.0.0.3'
411 odlwebport = kwargs['odlwebport'] if 'odlwebport' in kwargs else '8080'
412 odlrestconfport = (kwargs['odlrestconfport']
413 if 'odlrestconfport' in kwargs else '8181')
414 with mock.patch('functest.utils.openstack_utils.get_endpoint',
415 return_value=ODLTesting._neutron_url):
416 self.test.run_suites = mock.Mock(return_value=status)
417 self.assertEqual(self.test.run(suites=suites), status)
418 self.test.run_suites.assert_called_once_with(
420 neutronurl=self._neutron_url,
421 odlip=odlip, odlpassword=self._odl_password,
422 odlrestconfport=odlrestconfport,
423 odlusername=self._odl_username, odlwebport=odlwebport,
424 osauthurl=self._os_auth_url,
425 ospassword=self._os_password, ostenantname=self._os_tenantname,
426 osusername=self._os_username,
427 osprojectdomainname=self._os_projectdomainname,
428 osuserdomainname=self._os_userdomainname)
431 with mock.patch('functest.utils.openstack_utils.get_endpoint',
432 side_effect=auth_plugins.MissingAuthPlugin()):
433 self.assertEqual(self.test.run(),
434 testcase.TestCase.EX_RUN_ERROR)
436 def test_no_os_auth_url(self):
437 self._test_no_env_var("OS_AUTH_URL")
439 def test_no_os_username(self):
440 self._test_no_env_var("OS_USERNAME")
442 def test_no_os_password(self):
443 self._test_no_env_var("OS_PASSWORD")
445 def test_no_os_tenant_name(self):
446 self._test_no_env_var("OS_TENANT_NAME")
448 def test_run_suites_false(self):
449 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
450 self._test_run(testcase.TestCase.EX_RUN_ERROR,
451 odlip=self._sdn_controller_ip,
452 odlwebport=self._odl_webport)
454 def test_run_suites_exc(self):
455 with self.assertRaises(Exception):
456 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
457 self._test_run(status=testcase.TestCase.EX_RUN_ERROR,
458 exception=Exception(),
459 odlip=self._sdn_controller_ip,
460 odlwebport=self._odl_webport)
462 def test_no_sdn_controller_ip(self):
463 with mock.patch('functest.utils.openstack_utils.get_endpoint',
464 return_value=ODLTesting._neutron_url):
465 self.assertEqual(self.test.run(),
466 testcase.TestCase.EX_RUN_ERROR)
468 def test_without_installer_type(self):
469 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
470 self._test_run(testcase.TestCase.EX_OK,
471 odlip=self._sdn_controller_ip,
472 odlwebport=self._odl_webport)
474 def test_suites(self):
475 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
476 self._test_multiple_suites(
477 [odl.ODLTests.basic_suite_dir],
478 testcase.TestCase.EX_OK,
479 odlip=self._sdn_controller_ip,
480 odlwebport=self._odl_webport)
483 os.environ["INSTALLER_TYPE"] = "fuel"
484 self._test_run(testcase.TestCase.EX_OK,
485 odlip=urllib.parse.urlparse(self._neutron_url).hostname,
487 odlrestconfport='8282')
489 def test_apex_no_controller_ip(self):
490 with mock.patch('functest.utils.openstack_utils.get_endpoint',
491 return_value=ODLTesting._neutron_url):
492 os.environ["INSTALLER_TYPE"] = "apex"
493 self.assertEqual(self.test.run(),
494 testcase.TestCase.EX_RUN_ERROR)
497 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
498 os.environ["INSTALLER_TYPE"] = "apex"
499 self._test_run(testcase.TestCase.EX_OK,
500 odlip=self._sdn_controller_ip, odlwebport='8081',
501 odlrestconfport='8081')
503 def test_netvirt_no_controller_ip(self):
504 with mock.patch('functest.utils.openstack_utils.get_endpoint',
505 return_value=ODLTesting._neutron_url):
506 os.environ["INSTALLER_TYPE"] = "netvirt"
507 self.assertEqual(self.test.run(),
508 testcase.TestCase.EX_RUN_ERROR)
510 def test_netvirt(self):
511 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
512 os.environ["INSTALLER_TYPE"] = "netvirt"
513 self._test_run(testcase.TestCase.EX_OK,
514 odlip=self._sdn_controller_ip, odlwebport='8081',
515 odlrestconfport='8081')
517 def test_joid_no_controller_ip(self):
518 with mock.patch('functest.utils.openstack_utils.get_endpoint',
519 return_value=ODLTesting._neutron_url):
520 os.environ["INSTALLER_TYPE"] = "joid"
521 self.assertEqual(self.test.run(),
522 testcase.TestCase.EX_RUN_ERROR)
525 os.environ["SDN_CONTROLLER"] = self._sdn_controller_ip
526 os.environ["INSTALLER_TYPE"] = "joid"
527 self._test_run(testcase.TestCase.EX_OK,
528 odlip=self._sdn_controller_ip, odlwebport='8080')
530 def test_compass(self):
531 os.environ["INSTALLER_TYPE"] = "compass"
532 self._test_run(testcase.TestCase.EX_OK,
533 odlip=urllib.parse.urlparse(self._neutron_url).hostname,
534 odlrestconfport='8080')
536 def test_daisy_no_controller_ip(self):
537 with mock.patch('functest.utils.openstack_utils.get_endpoint',
538 return_value=ODLTesting._neutron_url):
539 os.environ["INSTALLER_TYPE"] = "daisy"
540 self.assertEqual(self.test.run(),
541 testcase.TestCase.EX_RUN_ERROR)
543 def test_daisy(self):
544 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
545 os.environ["INSTALLER_TYPE"] = "daisy"
546 self._test_run(testcase.TestCase.EX_OK,
547 odlip=self._sdn_controller_ip, odlwebport='8181',
548 odlrestconfport='8087')
551 class ODLArgParserTesting(ODLTesting):
553 """The class testing ODLParser."""
554 # pylint: disable=missing-docstring
557 self.parser = odl.ODLParser()
558 super(ODLArgParserTesting, self).setUp()
560 def test_default(self):
561 self.assertEqual(self.parser.parse_args(), self.defaultargs)
563 def test_basic(self):
564 self.defaultargs['neutronurl'] = self._neutron_url
565 self.defaultargs['odlip'] = self._sdn_controller_ip
567 self.parser.parse_args(
568 ["--neutronurl={}".format(self._neutron_url),
569 "--odlip={}".format(self._sdn_controller_ip)]),
572 @mock.patch('sys.stderr', new_callable=six.StringIO)
573 def test_fail(self, mock_method):
574 self.defaultargs['foo'] = 'bar'
575 with self.assertRaises(SystemExit):
576 self.parser.parse_args(["--foo=bar"])
577 self.assertTrue(mock_method.getvalue().startswith("usage:"))
579 def _test_arg(self, arg, value):
580 self.defaultargs[arg] = value
582 self.parser.parse_args(["--{}={}".format(arg, value)]),
585 def test_odlusername(self):
586 self._test_arg('odlusername', 'foo')
588 def test_odlpassword(self):
589 self._test_arg('odlpassword', 'foo')
591 def test_osauthurl(self):
592 self._test_arg('osauthurl', 'http://127.0.0.4:5000/v2')
594 def test_neutronurl(self):
595 self._test_arg('neutronurl', 'http://127.0.0.4:9696')
597 def test_osusername(self):
598 self._test_arg('osusername', 'foo')
600 def test_osuserdomainname(self):
601 self._test_arg('osuserdomainname', 'domain')
603 def test_ostenantname(self):
604 self._test_arg('ostenantname', 'foo')
606 def test_osprojectdomainname(self):
607 self._test_arg('osprojectdomainname', 'domain')
609 def test_ospassword(self):
610 self._test_arg('ospassword', 'foo')
612 def test_odlip(self):
613 self._test_arg('odlip', '127.0.0.4')
615 def test_odlwebport(self):
616 self._test_arg('odlwebport', '80')
618 def test_odlrestconfport(self):
619 self._test_arg('odlrestconfport', '80')
621 def test_pushtodb(self):
622 self.defaultargs['pushtodb'] = True
623 self.assertEqual(self.parser.parse_args(["--{}".format('pushtodb')]),
626 def test_multiple_args(self):
627 self.defaultargs['neutronurl'] = self._neutron_url
628 self.defaultargs['odlip'] = self._sdn_controller_ip
630 self.parser.parse_args(
631 ["--neutronurl={}".format(self._neutron_url),
632 "--odlip={}".format(self._sdn_controller_ip)]),
636 if __name__ == "__main__":
637 logging.disable(logging.CRITICAL)
638 unittest.main(verbosity=2)