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."""
16 from keystoneauth1.exceptions import auth_plugins
18 from robot.errors import RobotError
20 from six.moves import urllib
22 from functest.core import testcase
23 from functest.opnfv_tests.sdn.odl import odl
25 __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
28 class ODLTesting(unittest.TestCase):
30 """The super class which testing classes could inherit."""
31 # pylint: disable=missing-docstring
33 logging.disable(logging.CRITICAL)
35 _keystone_ip = "127.0.0.1"
36 _neutron_url = "http://127.0.0.2:9696"
37 _sdn_controller_ip = "127.0.0.3"
38 _os_auth_url = "http://{}:5000/v3".format(_keystone_ip)
39 _os_projectname = "admin"
40 _os_username = "admin"
41 _os_password = "admin"
43 _odl_restconfport = "8181"
44 _odl_username = "admin"
45 _odl_password = "admin"
46 _os_userdomainname = 'Default'
47 _os_projectdomainname = 'Default'
50 for var in ("INSTALLER_TYPE", "SDN_CONTROLLER", "SDN_CONTROLLER_IP"):
53 os.environ["OS_AUTH_URL"] = self._os_auth_url
54 os.environ["OS_USERNAME"] = self._os_username
55 os.environ["OS_USER_DOMAIN_NAME"] = self._os_userdomainname
56 os.environ["OS_PASSWORD"] = self._os_password
57 os.environ["OS_PROJECT_NAME"] = self._os_projectname
58 os.environ["OS_PROJECT_DOMAIN_NAME"] = self._os_projectdomainname
59 os.environ["OS_PASSWORD"] = self._os_password
60 self.test = odl.ODLTests(case_name='odl', project_name='functest')
61 self.defaultargs = {'odlusername': self._odl_username,
62 'odlpassword': self._odl_password,
63 'neutronurl': "http://{}:9696".format(
65 'osauthurl': self._os_auth_url,
66 'osusername': self._os_username,
67 'osuserdomainname': self._os_userdomainname,
68 'osprojectname': self._os_projectname,
69 'osprojectdomainname': self._os_projectdomainname,
70 'ospassword': self._os_password,
71 'odlip': self._keystone_ip,
72 'odlwebport': self._odl_webport,
73 'odlrestconfport': self._odl_restconfport,
77 class ODLRobotTesting(ODLTesting):
79 """The class testing ODLTests.set_robotframework_vars()."""
80 # pylint: disable=missing-docstring
82 @mock.patch('fileinput.input', side_effect=Exception())
83 def test_set_vars_ko(self, mock_method):
84 self.assertFalse(self.test.set_robotframework_vars())
85 mock_method.assert_called_once_with(
86 os.path.join(odl.ODLTests.odl_test_repo,
87 'csit/variables/Variables.robot'), inplace=True)
89 @mock.patch('fileinput.input', return_value=[])
90 def test_set_vars_empty(self, mock_method):
91 self.assertTrue(self.test.set_robotframework_vars())
92 mock_method.assert_called_once_with(
93 os.path.join(odl.ODLTests.odl_test_repo,
94 'csit/variables/Variables.robot'), inplace=True)
96 @mock.patch('sys.stdout', new_callable=six.StringIO)
97 def _test_set_vars(self, msg1, msg2, *args):
98 line = mock.MagicMock()
99 line.__iter__.return_value = [msg1]
100 with mock.patch('fileinput.input', return_value=line) as mock_method:
101 self.assertTrue(self.test.set_robotframework_vars())
102 mock_method.assert_called_once_with(
103 os.path.join(odl.ODLTests.odl_test_repo,
104 'csit/variables/Variables.robot'), inplace=True)
105 self.assertEqual(args[0].getvalue(), "{}\n".format(msg2))
107 def test_set_vars_auth_default(self):
110 "@{AUTH} admin admin")
112 def test_set_vars_auth1(self):
117 @mock.patch('sys.stdout', new_callable=six.StringIO)
118 def test_set_vars_auth_foo(self, *args):
119 line = mock.MagicMock()
120 line.__iter__.return_value = ["@{AUTH} "]
121 with mock.patch('fileinput.input', return_value=line) as mock_method:
122 self.assertTrue(self.test.set_robotframework_vars('foo', 'bar'))
123 mock_method.assert_called_once_with(
124 os.path.join(odl.ODLTests.odl_test_repo,
125 'csit/variables/Variables.robot'), inplace=True)
131 class ODLMainTesting(ODLTesting):
133 """The class testing ODLTests.run_suites()."""
134 # pylint: disable=missing-docstring
136 def _get_run_suites_kwargs(self, key=None):
137 kwargs = {'odlusername': self._odl_username,
138 'odlpassword': self._odl_password,
139 'neutronurl': self._neutron_url,
140 'osauthurl': self._os_auth_url,
141 'osusername': self._os_username,
142 'osuserdomainname': self._os_userdomainname,
143 'osprojectname': self._os_projectname,
144 'osprojectdomainname': self._os_projectdomainname,
145 'ospassword': self._os_password,
146 'odlip': self._sdn_controller_ip,
147 'odlwebport': self._odl_webport,
148 'odlrestconfport': self._odl_restconfport}
153 def _test_run_suites(self, status, *args):
154 kwargs = self._get_run_suites_kwargs()
155 self.assertEqual(self.test.run_suites(**kwargs), status)
157 args[0].assert_called_once_with(self.test.odl_variables_file)
160 'KEYSTONEURL:{}://{}'.format(
161 urllib.parse.urlparse(self._os_auth_url).scheme,
162 urllib.parse.urlparse(self._os_auth_url).netloc),
163 'NEUTRONURL:{}'.format(self._neutron_url),
164 'OS_AUTH_URL:"{}"'.format(self._os_auth_url),
165 'OSUSERNAME:"{}"'.format(self._os_username),
166 'OSUSERDOMAINNAME:"{}"'.format(self._os_userdomainname),
167 'OSTENANTNAME:"{}"'.format(self._os_projectname),
168 'OSPROJECTDOMAINNAME:"{}"'.format(self._os_projectdomainname),
169 'OSPASSWORD:"{}"'.format(self._os_password),
170 'ODL_SYSTEM_IP:{}'.format(self._sdn_controller_ip),
171 'PORT:{}'.format(self._odl_webport),
172 'RESTCONFPORT:{}'.format(self._odl_restconfport)]
173 args[1].assert_called_once_with(
174 odl.ODLTests.basic_suite_dir,
175 odl.ODLTests.neutron_suite_dir,
177 output=os.path.join(self.test.res_dir, 'output.xml'),
182 def _test_no_keyword(self, key):
183 kwargs = self._get_run_suites_kwargs(key)
184 self.assertEqual(self.test.run_suites(**kwargs),
185 testcase.TestCase.EX_RUN_ERROR)
187 def test_no_odlusername(self):
188 self._test_no_keyword('odlusername')
190 def test_no_odlpassword(self):
191 self._test_no_keyword('odlpassword')
193 def test_no_neutronurl(self):
194 self._test_no_keyword('neutronurl')
196 def test_no_osauthurl(self):
197 self._test_no_keyword('osauthurl')
199 def test_no_osusername(self):
200 self._test_no_keyword('osusername')
202 def test_no_osprojectname(self):
203 self._test_no_keyword('osprojectname')
205 def test_no_ospassword(self):
206 self._test_no_keyword('ospassword')
208 def test_no_odlip(self):
209 self._test_no_keyword('odlip')
211 def test_no_odlwebport(self):
212 self._test_no_keyword('odlwebport')
214 def test_no_odlrestconfport(self):
215 self._test_no_keyword('odlrestconfport')
217 @mock.patch('os.path.isfile', return_value=True)
218 def test_set_vars_ko(self, *args):
219 with mock.patch.object(self.test, 'set_robotframework_vars',
220 return_value=False) as mock_object:
221 self._test_run_suites(testcase.TestCase.EX_RUN_ERROR)
222 mock_object.assert_called_once_with(
223 self._odl_username, self._odl_password)
224 args[0].assert_called_once_with(self.test.odl_variables_file)
226 @mock.patch('robot.run', side_effect=RobotError)
227 @mock.patch('os.path.isfile', return_value=True)
228 def test_run_ko(self, *args):
229 with mock.patch.object(self.test, 'set_robotframework_vars',
230 return_value=True), \
231 self.assertRaises(RobotError):
232 self._test_run_suites(testcase.TestCase.EX_RUN_ERROR, *args)
234 @mock.patch('robot.run')
235 @mock.patch('os.path.isfile', return_value=True)
236 def test_parse_results_ko(self, *args):
237 with mock.patch.object(self.test, 'set_robotframework_vars',
238 return_value=True), \
239 mock.patch.object(self.test, 'parse_results',
240 side_effect=RobotError):
241 self._test_run_suites(testcase.TestCase.EX_RUN_ERROR, *args)
243 @mock.patch('robot.run')
244 @mock.patch('os.path.isfile', return_value=True)
245 def test_ok(self, *args):
246 with mock.patch.object(self.test, 'set_robotframework_vars',
247 return_value=True), \
248 mock.patch.object(self.test, 'parse_results'):
249 self._test_run_suites(testcase.TestCase.EX_OK, *args)
251 @mock.patch('robot.run')
252 @mock.patch('os.path.isfile', return_value=False)
253 def test_ok_no_creds(self, *args):
254 with mock.patch.object(self.test, 'set_robotframework_vars',
255 return_value=True) as mock_method, \
256 mock.patch.object(self.test, 'parse_results'):
257 self._test_run_suites(testcase.TestCase.EX_OK, *args)
258 mock_method.assert_not_called()
260 @mock.patch('robot.run', return_value=1)
261 @mock.patch('os.path.isfile', return_value=True)
262 def test_testcases_in_failure(self, *args):
263 with mock.patch.object(self.test, 'set_robotframework_vars',
264 return_value=True), \
265 mock.patch.object(self.test, 'parse_results'):
266 self._test_run_suites(testcase.TestCase.EX_OK, *args)
269 class ODLRunTesting(ODLTesting):
271 """The class testing ODLTests.run()."""
272 # pylint: disable=missing-docstring
274 def _test_no_env_var(self, var):
275 with mock.patch('functest.utils.openstack_utils.get_endpoint',
276 return_value=ODLTesting._neutron_url):
278 self.assertEqual(self.test.run(),
279 testcase.TestCase.EX_RUN_ERROR)
281 def _test_run(self, status=testcase.TestCase.EX_OK,
282 exception=None, **kwargs):
283 odlip = kwargs['odlip'] if 'odlip' in kwargs else '127.0.0.3'
284 odlwebport = kwargs['odlwebport'] if 'odlwebport' in kwargs else '8080'
285 odlrestconfport = (kwargs['odlrestconfport']
286 if 'odlrestconfport' in kwargs else '8181')
288 with mock.patch('functest.utils.openstack_utils.get_endpoint',
289 return_value=ODLTesting._neutron_url):
291 self.test.run_suites = mock.Mock(side_effect=exception)
293 self.test.run_suites = mock.Mock(return_value=status)
294 self.assertEqual(self.test.run(), status)
295 self.test.run_suites.assert_called_once_with(
296 odl.ODLTests.default_suites,
297 neutronurl=self._neutron_url,
298 odlip=odlip, odlpassword=self._odl_password,
299 odlrestconfport=odlrestconfport,
300 odlusername=self._odl_username, odlwebport=odlwebport,
301 osauthurl=self._os_auth_url,
302 ospassword=self._os_password,
303 osprojectname=self._os_projectname,
304 osusername=self._os_username,
305 osprojectdomainname=self._os_projectdomainname,
306 osuserdomainname=self._os_userdomainname)
308 def _test_multiple_suites(self, suites,
309 status=testcase.TestCase.EX_OK, **kwargs):
310 odlip = kwargs['odlip'] if 'odlip' in kwargs else '127.0.0.3'
311 odlwebport = kwargs['odlwebport'] if 'odlwebport' in kwargs else '8080'
312 odlrestconfport = (kwargs['odlrestconfport']
313 if 'odlrestconfport' in kwargs else '8181')
314 with mock.patch('functest.utils.openstack_utils.get_endpoint',
315 return_value=ODLTesting._neutron_url):
316 self.test.run_suites = mock.Mock(return_value=status)
317 self.assertEqual(self.test.run(suites=suites), status)
318 self.test.run_suites.assert_called_once_with(
320 neutronurl=self._neutron_url,
321 odlip=odlip, odlpassword=self._odl_password,
322 odlrestconfport=odlrestconfport,
323 odlusername=self._odl_username, odlwebport=odlwebport,
324 osauthurl=self._os_auth_url,
325 ospassword=self._os_password,
326 osprojectname=self._os_projectname,
327 osusername=self._os_username,
328 osprojectdomainname=self._os_projectdomainname,
329 osuserdomainname=self._os_userdomainname)
332 with mock.patch('functest.utils.openstack_utils.get_endpoint',
333 side_effect=auth_plugins.MissingAuthPlugin()):
334 self.assertEqual(self.test.run(),
335 testcase.TestCase.EX_RUN_ERROR)
337 def test_no_os_auth_url(self):
338 self._test_no_env_var("OS_AUTH_URL")
340 def test_no_os_username(self):
341 self._test_no_env_var("OS_USERNAME")
343 def test_no_os_password(self):
344 self._test_no_env_var("OS_PASSWORD")
346 def test_no_os__name(self):
347 self._test_no_env_var("OS_PROJECT_NAME")
349 def test_run_suites_false(self):
350 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
351 self._test_run(testcase.TestCase.EX_RUN_ERROR,
352 odlip=self._sdn_controller_ip,
353 odlwebport=self._odl_webport)
355 def test_run_suites_exc(self):
356 with self.assertRaises(Exception):
357 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
358 self._test_run(status=testcase.TestCase.EX_RUN_ERROR,
359 exception=Exception(),
360 odlip=self._sdn_controller_ip,
361 odlwebport=self._odl_webport)
363 def test_no_sdn_controller_ip(self):
364 with mock.patch('functest.utils.openstack_utils.get_endpoint',
365 return_value=ODLTesting._neutron_url):
366 self.assertEqual(self.test.run(),
367 testcase.TestCase.EX_RUN_ERROR)
369 def test_without_installer_type(self):
370 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
371 self._test_run(testcase.TestCase.EX_OK,
372 odlip=self._sdn_controller_ip,
373 odlwebport=self._odl_webport)
375 def test_suites(self):
376 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
377 self._test_multiple_suites(
378 [odl.ODLTests.basic_suite_dir],
379 testcase.TestCase.EX_OK,
380 odlip=self._sdn_controller_ip,
381 odlwebport=self._odl_webport)
384 os.environ["INSTALLER_TYPE"] = "fuel"
385 self._test_run(testcase.TestCase.EX_OK,
386 odlip=urllib.parse.urlparse(self._neutron_url).hostname,
388 odlrestconfport='8282')
390 def test_apex_no_controller_ip(self):
391 with mock.patch('functest.utils.openstack_utils.get_endpoint',
392 return_value=ODLTesting._neutron_url):
393 os.environ["INSTALLER_TYPE"] = "apex"
394 self.assertEqual(self.test.run(),
395 testcase.TestCase.EX_RUN_ERROR)
398 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
399 os.environ["INSTALLER_TYPE"] = "apex"
400 self._test_run(testcase.TestCase.EX_OK,
401 odlip=self._sdn_controller_ip, odlwebport='8081',
402 odlrestconfport='8081')
404 def test_netvirt_no_controller_ip(self):
405 with mock.patch('functest.utils.openstack_utils.get_endpoint',
406 return_value=ODLTesting._neutron_url):
407 os.environ["INSTALLER_TYPE"] = "netvirt"
408 self.assertEqual(self.test.run(),
409 testcase.TestCase.EX_RUN_ERROR)
411 def test_netvirt(self):
412 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
413 os.environ["INSTALLER_TYPE"] = "netvirt"
414 self._test_run(testcase.TestCase.EX_OK,
415 odlip=self._sdn_controller_ip, odlwebport='8081',
416 odlrestconfport='8081')
418 def test_joid_no_controller_ip(self):
419 with mock.patch('functest.utils.openstack_utils.get_endpoint',
420 return_value=ODLTesting._neutron_url):
421 os.environ["INSTALLER_TYPE"] = "joid"
422 self.assertEqual(self.test.run(),
423 testcase.TestCase.EX_RUN_ERROR)
426 os.environ["SDN_CONTROLLER"] = self._sdn_controller_ip
427 os.environ["INSTALLER_TYPE"] = "joid"
428 self._test_run(testcase.TestCase.EX_OK,
429 odlip=self._sdn_controller_ip, odlwebport='8080')
431 def test_compass(self):
432 os.environ["INSTALLER_TYPE"] = "compass"
433 self._test_run(testcase.TestCase.EX_OK,
434 odlip=urllib.parse.urlparse(self._neutron_url).hostname,
435 odlrestconfport='8080')
437 def test_daisy_no_controller_ip(self):
438 with mock.patch('functest.utils.openstack_utils.get_endpoint',
439 return_value=ODLTesting._neutron_url):
440 os.environ["INSTALLER_TYPE"] = "daisy"
441 self.assertEqual(self.test.run(),
442 testcase.TestCase.EX_RUN_ERROR)
444 def test_daisy(self):
445 os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
446 os.environ["INSTALLER_TYPE"] = "daisy"
447 self._test_run(testcase.TestCase.EX_OK,
448 odlip=self._sdn_controller_ip, odlwebport='8181',
449 odlrestconfport='8087')
452 class ODLArgParserTesting(ODLTesting):
454 """The class testing ODLParser."""
455 # pylint: disable=missing-docstring
458 self.parser = odl.ODLParser()
459 super(ODLArgParserTesting, self).setUp()
461 def test_default(self):
462 self.assertEqual(self.parser.parse_args(), self.defaultargs)
464 def test_basic(self):
465 self.defaultargs['neutronurl'] = self._neutron_url
466 self.defaultargs['odlip'] = self._sdn_controller_ip
468 self.parser.parse_args(
469 ["--neutronurl={}".format(self._neutron_url),
470 "--odlip={}".format(self._sdn_controller_ip)]),
473 @mock.patch('sys.stderr', new_callable=six.StringIO)
474 def test_fail(self, mock_method):
475 self.defaultargs['foo'] = 'bar'
476 with self.assertRaises(SystemExit):
477 self.parser.parse_args(["--foo=bar"])
478 self.assertTrue(mock_method.getvalue().startswith("usage:"))
480 def _test_arg(self, arg, value):
481 self.defaultargs[arg] = value
483 self.parser.parse_args(["--{}={}".format(arg, value)]),
486 def test_odlusername(self):
487 self._test_arg('odlusername', 'foo')
489 def test_odlpassword(self):
490 self._test_arg('odlpassword', 'foo')
492 def test_osauthurl(self):
493 self._test_arg('osauthurl', 'http://127.0.0.4:5000/v2')
495 def test_neutronurl(self):
496 self._test_arg('neutronurl', 'http://127.0.0.4:9696')
498 def test_osusername(self):
499 self._test_arg('osusername', 'foo')
501 def test_osuserdomainname(self):
502 self._test_arg('osuserdomainname', 'domain')
504 def test_osprojectname(self):
505 self._test_arg('osprojectname', 'foo')
507 def test_osprojectdomainname(self):
508 self._test_arg('osprojectdomainname', 'domain')
510 def test_ospassword(self):
511 self._test_arg('ospassword', 'foo')
513 def test_odlip(self):
514 self._test_arg('odlip', '127.0.0.4')
516 def test_odlwebport(self):
517 self._test_arg('odlwebport', '80')
519 def test_odlrestconfport(self):
520 self._test_arg('odlrestconfport', '80')
522 def test_pushtodb(self):
523 self.defaultargs['pushtodb'] = True
524 self.assertEqual(self.parser.parse_args(["--{}".format('pushtodb')]),
527 def test_multiple_args(self):
528 self.defaultargs['neutronurl'] = self._neutron_url
529 self.defaultargs['odlip'] = self._sdn_controller_ip
531 self.parser.parse_args(
532 ["--neutronurl={}".format(self._neutron_url),
533 "--odlip={}".format(self._sdn_controller_ip)]),
537 if __name__ == "__main__":
538 logging.disable(logging.CRITICAL)
539 unittest.main(verbosity=2)