Merge "support fuel&daisy for doctor in functest"
[functest.git] / functest / tests / unit / odl / test_odl.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016 Orange and others.
4 #
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
9
10 """Define the classes required to fully cover odl."""
11
12 import logging
13 import os
14 import unittest
15
16 import mock
17 from robot.errors import RobotError
18 import six
19 from six.moves import urllib
20 from xtesting.core import testcase
21
22 from functest.opnfv_tests.sdn.odl import odl
23
24 __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
25
26
27 class ODLTesting(unittest.TestCase):
28
29     """The super class which testing classes could inherit."""
30     # pylint: disable=missing-docstring
31
32     logging.disable(logging.CRITICAL)
33
34     _keystone_ip = "127.0.0.1"
35     _neutron_url = u"https://127.0.0.1:9696"
36     _sdn_controller_ip = "127.0.0.3"
37     _os_auth_url = "http://{}:5000/v3".format(_keystone_ip)
38     _os_projectname = "admin"
39     _os_username = "admin"
40     _os_password = "admin"
41     _odl_webport = "8080"
42     _odl_restconfport = "8181"
43     _odl_username = "admin"
44     _odl_password = "admin"
45     _os_userdomainname = 'Default'
46     _os_projectdomainname = 'Default'
47
48     def setUp(self):
49         for var in ("INSTALLER_TYPE", "SDN_CONTROLLER", "SDN_CONTROLLER_IP"):
50             if var in os.environ:
51                 del os.environ[var]
52         os.environ["OS_AUTH_URL"] = self._os_auth_url
53         os.environ["OS_USERNAME"] = self._os_username
54         os.environ["OS_USER_DOMAIN_NAME"] = self._os_userdomainname
55         os.environ["OS_PASSWORD"] = self._os_password
56         os.environ["OS_PROJECT_NAME"] = self._os_projectname
57         os.environ["OS_PROJECT_DOMAIN_NAME"] = self._os_projectdomainname
58         os.environ["OS_PASSWORD"] = self._os_password
59         self.test = odl.ODLTests(case_name='odl', project_name='functest')
60         self.defaultargs = {'odlusername': self._odl_username,
61                             'odlpassword': self._odl_password,
62                             'neutronurl': "http://{}:9696".format(
63                                 self._keystone_ip),
64                             'osauthurl': self._os_auth_url,
65                             'osusername': self._os_username,
66                             'osuserdomainname': self._os_userdomainname,
67                             'osprojectname': self._os_projectname,
68                             'osprojectdomainname': self._os_projectdomainname,
69                             'ospassword': self._os_password,
70                             'odlip': self._keystone_ip,
71                             'odlwebport': self._odl_webport,
72                             'odlrestconfport': self._odl_restconfport,
73                             'pushtodb': False}
74
75
76 class ODLRobotTesting(ODLTesting):
77
78     """The class testing ODLTests.set_robotframework_vars()."""
79     # pylint: disable=missing-docstring
80
81     @mock.patch('fileinput.input', side_effect=Exception())
82     def test_set_vars_ko(self, mock_method):
83         self.assertFalse(self.test.set_robotframework_vars())
84         mock_method.assert_called_once_with(
85             os.path.join(odl.ODLTests.odl_test_repo,
86                          'csit/variables/Variables.robot'), inplace=True)
87
88     @mock.patch('fileinput.input', return_value=[])
89     def test_set_vars_empty(self, mock_method):
90         self.assertTrue(self.test.set_robotframework_vars())
91         mock_method.assert_called_once_with(
92             os.path.join(odl.ODLTests.odl_test_repo,
93                          'csit/variables/Variables.robot'), inplace=True)
94
95     @mock.patch('sys.stdout', new_callable=six.StringIO)
96     def _test_set_vars(self, msg1, msg2, *args):
97         line = mock.MagicMock()
98         line.__iter__.return_value = [msg1]
99         with mock.patch('fileinput.input', return_value=line) as mock_method:
100             self.assertTrue(self.test.set_robotframework_vars())
101             mock_method.assert_called_once_with(
102                 os.path.join(odl.ODLTests.odl_test_repo,
103                              'csit/variables/Variables.robot'), inplace=True)
104             self.assertEqual(args[0].getvalue(), "{}\n".format(msg2))
105
106     def test_set_vars_auth_default(self):
107         self._test_set_vars(
108             "@{AUTH} ",
109             "@{AUTH}           admin    admin")
110
111     def test_set_vars_auth1(self):
112         self._test_set_vars(
113             "@{AUTH1}           foo    bar",
114             "@{AUTH1}           foo    bar")
115
116     @mock.patch('sys.stdout', new_callable=six.StringIO)
117     def test_set_vars_auth_foo(self, *args):
118         line = mock.MagicMock()
119         line.__iter__.return_value = ["@{AUTH} "]
120         with mock.patch('fileinput.input', return_value=line) as mock_method:
121             self.assertTrue(self.test.set_robotframework_vars('foo', 'bar'))
122             mock_method.assert_called_once_with(
123                 os.path.join(odl.ODLTests.odl_test_repo,
124                              'csit/variables/Variables.robot'), inplace=True)
125             self.assertEqual(
126                 args[0].getvalue(),
127                 "@{AUTH}           foo    bar\n")
128
129
130 class ODLMainTesting(ODLTesting):
131
132     """The class testing ODLTests.run_suites()."""
133     # pylint: disable=missing-docstring
134
135     def _get_run_suites_kwargs(self, key=None):
136         kwargs = {'odlusername': self._odl_username,
137                   'odlpassword': self._odl_password,
138                   'neutronurl': self._neutron_url,
139                   'osauthurl': self._os_auth_url,
140                   'osusername': self._os_username,
141                   'osuserdomainname': self._os_userdomainname,
142                   'osprojectname': self._os_projectname,
143                   'osprojectdomainname': self._os_projectdomainname,
144                   'ospassword': self._os_password,
145                   'odlip': self._sdn_controller_ip,
146                   'odlwebport': self._odl_webport,
147                   'odlrestconfport': self._odl_restconfport}
148         if key:
149             del kwargs[key]
150         return kwargs
151
152     def _test_run_suites(self, status, *args):
153         kwargs = self._get_run_suites_kwargs()
154         self.assertEqual(self.test.run_suites(**kwargs), status)
155         if args:
156             args[0].assert_called_once_with(self.test.odl_variables_file)
157         if len(args) > 1:
158             variable = [
159                 'KEYSTONEURL:{}://{}'.format(
160                     urllib.parse.urlparse(self._os_auth_url).scheme,
161                     urllib.parse.urlparse(self._os_auth_url).netloc),
162                 'NEUTRONURL:{}'.format(self._neutron_url),
163                 'OS_AUTH_URL:"{}"'.format(self._os_auth_url),
164                 'OSUSERNAME:"{}"'.format(self._os_username),
165                 'OSUSERDOMAINNAME:"{}"'.format(self._os_userdomainname),
166                 'OSTENANTNAME:"{}"'.format(self._os_projectname),
167                 'OSPROJECTDOMAINNAME:"{}"'.format(self._os_projectdomainname),
168                 'OSPASSWORD:"{}"'.format(self._os_password),
169                 'ODL_SYSTEM_IP:{}'.format(self._sdn_controller_ip),
170                 'PORT:{}'.format(self._odl_webport),
171                 'RESTCONFPORT:{}'.format(self._odl_restconfport)]
172             args[1].assert_called_once_with(
173                 odl.ODLTests.basic_suite_dir, odl.ODLTests.neutron_suite_dir,
174                 include=[],
175                 log='NONE',
176                 output=os.path.join(self.test.res_dir, 'output.xml'),
177                 report='NONE', stdout=mock.ANY, variable=variable,
178                 variablefile=[])
179
180     def _test_no_keyword(self, key):
181         kwargs = self._get_run_suites_kwargs(key)
182         self.assertEqual(self.test.run_suites(**kwargs),
183                          testcase.TestCase.EX_RUN_ERROR)
184
185     def test_no_odlusername(self):
186         self._test_no_keyword('odlusername')
187
188     def test_no_odlpassword(self):
189         self._test_no_keyword('odlpassword')
190
191     def test_no_neutronurl(self):
192         self._test_no_keyword('neutronurl')
193
194     def test_no_osauthurl(self):
195         self._test_no_keyword('osauthurl')
196
197     def test_no_osusername(self):
198         self._test_no_keyword('osusername')
199
200     def test_no_osprojectname(self):
201         self._test_no_keyword('osprojectname')
202
203     def test_no_ospassword(self):
204         self._test_no_keyword('ospassword')
205
206     def test_no_odlip(self):
207         self._test_no_keyword('odlip')
208
209     def test_no_odlwebport(self):
210         self._test_no_keyword('odlwebport')
211
212     def test_no_odlrestconfport(self):
213         self._test_no_keyword('odlrestconfport')
214
215     @mock.patch('os.path.isfile', return_value=True)
216     def test_set_vars_ko(self, *args):
217         with mock.patch.object(self.test, 'set_robotframework_vars',
218                                return_value=False) as mock_object:
219             self._test_run_suites(testcase.TestCase.EX_RUN_ERROR)
220             mock_object.assert_called_once_with(
221                 self._odl_username, self._odl_password)
222         args[0].assert_called_once_with(self.test.odl_variables_file)
223
224     @mock.patch('robot.run', side_effect=RobotError)
225     @mock.patch('os.path.isfile', return_value=True)
226     def test_run_ko(self, *args):
227         with mock.patch.object(self.test, 'set_robotframework_vars',
228                                return_value=True), \
229                 self.assertRaises(RobotError):
230             self._test_run_suites(testcase.TestCase.EX_RUN_ERROR, *args)
231
232     @mock.patch('robot.run')
233     @mock.patch('os.path.isfile', return_value=True)
234     def test_parse_results_ko(self, *args):
235         with mock.patch.object(self.test, 'set_robotframework_vars',
236                                return_value=True), \
237                 mock.patch.object(self.test, 'parse_results',
238                                   side_effect=RobotError):
239             self._test_run_suites(testcase.TestCase.EX_RUN_ERROR, *args)
240
241     @mock.patch('robot.run')
242     @mock.patch('os.path.isfile', return_value=True)
243     def test_ok(self, *args):
244         with mock.patch.object(self.test, 'set_robotframework_vars',
245                                return_value=True), \
246                 mock.patch.object(self.test, 'parse_results'):
247             self._test_run_suites(testcase.TestCase.EX_OK, *args)
248
249     @mock.patch('robot.run')
250     @mock.patch('os.path.isfile', return_value=False)
251     def test_ok_no_creds(self, *args):
252         with mock.patch.object(self.test, 'set_robotframework_vars',
253                                return_value=True) as mock_method, \
254                 mock.patch.object(self.test, 'parse_results'):
255             self._test_run_suites(testcase.TestCase.EX_OK, *args)
256             mock_method.assert_not_called()
257
258     @mock.patch('robot.run', return_value=1)
259     @mock.patch('os.path.isfile', return_value=True)
260     def test_testcases_in_failure(self, *args):
261         with mock.patch.object(self.test, 'set_robotframework_vars',
262                                return_value=True), \
263                 mock.patch.object(self.test, 'parse_results'):
264             self._test_run_suites(testcase.TestCase.EX_OK, *args)
265
266
267 class ODLRunTesting(ODLTesting):
268
269     """The class testing ODLTests.run()."""
270     # pylint: disable=missing-docstring
271
272     @mock.patch('snaps.openstack.utils.keystone_utils.get_endpoint',
273                 return_value=ODLTesting._neutron_url)
274     @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.'
275                 'get_credentials')
276     def _test_no_env_var(self, var, *args):
277         del os.environ[var]
278         self.assertEqual(self.test.run(), testcase.TestCase.EX_RUN_ERROR)
279         args[0].assert_called_once_with()
280         args[1].assert_called_once_with(mock.ANY, 'network')
281
282     @mock.patch('snaps.openstack.utils.keystone_utils.get_endpoint',
283                 return_value=ODLTesting._neutron_url)
284     @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.'
285                 'get_credentials')
286     def _test_missing_value(self, *args):
287         self.assertEqual(self.test.run(), testcase.TestCase.EX_RUN_ERROR)
288         args[0].assert_called_once_with()
289         args[1].assert_called_once_with(mock.ANY, 'network')
290
291     @mock.patch('snaps.openstack.utils.keystone_utils.get_endpoint',
292                 return_value=ODLTesting._neutron_url)
293     @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.'
294                 'get_credentials')
295     def _test_run(self, status=testcase.TestCase.EX_OK,
296                   exception=None, *args, **kwargs):
297         odlip = kwargs['odlip'] if 'odlip' in kwargs else '127.0.0.3'
298         odlwebport = kwargs['odlwebport'] if 'odlwebport' in kwargs else '8080'
299         odlrestconfport = (kwargs['odlrestconfport']
300                            if 'odlrestconfport' in kwargs else '8181')
301         if exception:
302             self.test.run_suites = mock.Mock(side_effect=exception)
303         else:
304             self.test.run_suites = mock.Mock(return_value=status)
305         self.assertEqual(self.test.run(), status)
306         self.test.run_suites.assert_called_once_with(
307             odl.ODLTests.default_suites, neutronurl=self._neutron_url,
308             odlip=odlip, odlpassword=self._odl_password,
309             odlrestconfport=odlrestconfport, odlusername=self._odl_username,
310             odlwebport=odlwebport, osauthurl=self._os_auth_url,
311             ospassword=self._os_password, osprojectname=self._os_projectname,
312             osusername=self._os_username,
313             osprojectdomainname=self._os_projectdomainname,
314             osuserdomainname=self._os_userdomainname)
315         args[0].assert_called_once_with()
316         args[1].assert_called_once_with(mock.ANY, 'network')
317
318     @mock.patch('snaps.openstack.utils.keystone_utils.get_endpoint',
319                 return_value=ODLTesting._neutron_url)
320     @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.'
321                 'get_credentials')
322     def _test_multiple_suites(self, suites,
323                               status=testcase.TestCase.EX_OK, *args, **kwargs):
324         odlip = kwargs['odlip'] if 'odlip' in kwargs else '127.0.0.3'
325         odlwebport = kwargs['odlwebport'] if 'odlwebport' in kwargs else '8080'
326         odlrestconfport = (kwargs['odlrestconfport']
327                            if 'odlrestconfport' in kwargs else '8181')
328         self.test.run_suites = mock.Mock(return_value=status)
329         self.assertEqual(self.test.run(suites=suites), status)
330         self.test.run_suites.assert_called_once_with(
331             suites, neutronurl=self._neutron_url, odlip=odlip,
332             odlpassword=self._odl_password, odlrestconfport=odlrestconfport,
333             odlusername=self._odl_username, odlwebport=odlwebport,
334             osauthurl=self._os_auth_url, ospassword=self._os_password,
335             osprojectname=self._os_projectname, osusername=self._os_username,
336             osprojectdomainname=self._os_projectdomainname,
337             osuserdomainname=self._os_userdomainname)
338         args[0].assert_called_once_with()
339         args[1].assert_called_once_with(mock.ANY, 'network')
340
341     def test_exc(self):
342         with mock.patch('snaps.openstack.utils.keystone_utils.get_endpoint',
343                         side_effect=Exception()):
344             self.assertEqual(self.test.run(),
345                              testcase.TestCase.EX_RUN_ERROR)
346
347     def test_no_os_auth_url(self):
348         self._test_no_env_var("OS_AUTH_URL")
349
350     def test_no_os_username(self):
351         self._test_no_env_var("OS_USERNAME")
352
353     def test_no_os_password(self):
354         self._test_no_env_var("OS_PASSWORD")
355
356     def test_no_os__name(self):
357         self._test_no_env_var("OS_PROJECT_NAME")
358
359     def test_run_suites_false(self):
360         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
361         self._test_run(testcase.TestCase.EX_RUN_ERROR, None,
362                        odlip=self._sdn_controller_ip,
363                        odlwebport=self._odl_webport)
364
365     def test_run_suites_exc(self):
366         with self.assertRaises(Exception):
367             os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
368             self._test_run(testcase.TestCase.EX_RUN_ERROR,
369                            Exception(),
370                            odlip=self._sdn_controller_ip,
371                            odlwebport=self._odl_webport)
372
373     def test_no_sdn_controller_ip(self):
374         self._test_missing_value()
375
376     def test_without_installer_type(self):
377         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
378         self._test_run(testcase.TestCase.EX_OK, None,
379                        odlip=self._sdn_controller_ip,
380                        odlwebport=self._odl_webport)
381
382     def test_suites(self):
383         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
384         self._test_multiple_suites(
385             [odl.ODLTests.basic_suite_dir],
386             testcase.TestCase.EX_OK,
387             odlip=self._sdn_controller_ip,
388             odlwebport=self._odl_webport)
389
390     def test_fuel_no_controller_ip(self):
391         os.environ["INSTALLER_TYPE"] = "fuel"
392         self._test_missing_value()
393
394     def test_fuel(self):
395         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
396         os.environ["INSTALLER_TYPE"] = "fuel"
397         self._test_run(testcase.TestCase.EX_OK, None,
398                        odlip=self._sdn_controller_ip,
399                        odlwebport='8282',
400                        odlrestconfport='8282')
401
402     def test_apex_no_controller_ip(self):
403         os.environ["INSTALLER_TYPE"] = "apex"
404         self._test_missing_value()
405
406     def test_apex(self):
407         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
408         os.environ["INSTALLER_TYPE"] = "apex"
409         self._test_run(testcase.TestCase.EX_OK, None,
410                        odlip=self._sdn_controller_ip, odlwebport='8081',
411                        odlrestconfport='8081')
412
413     def test_netvirt_no_controller_ip(self):
414         os.environ["INSTALLER_TYPE"] = "netvirt"
415         self._test_missing_value()
416
417     def test_netvirt(self):
418         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
419         os.environ["INSTALLER_TYPE"] = "netvirt"
420         self._test_run(testcase.TestCase.EX_OK, None,
421                        odlip=self._sdn_controller_ip, odlwebport='8081',
422                        odlrestconfport='8081')
423
424     def test_compass(self):
425         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
426         os.environ["INSTALLER_TYPE"] = "compass"
427         self._test_run(testcase.TestCase.EX_OK, None,
428                        odlip=self._sdn_controller_ip,
429                        odlrestconfport='8080')
430
431     def test_daisy_no_controller_ip(self):
432         os.environ["INSTALLER_TYPE"] = "daisy"
433         self._test_missing_value()
434
435     def test_daisy(self):
436         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
437         os.environ["INSTALLER_TYPE"] = "daisy"
438         self._test_run(testcase.TestCase.EX_OK, None,
439                        odlip=self._sdn_controller_ip, odlwebport='8181',
440                        odlrestconfport='8087')
441
442
443 class ODLArgParserTesting(ODLTesting):
444
445     """The class testing ODLParser."""
446     # pylint: disable=missing-docstring
447
448     def setUp(self):
449         self.parser = odl.ODLParser()
450         super(ODLArgParserTesting, self).setUp()
451
452     def test_default(self):
453         self.assertEqual(self.parser.parse_args(), self.defaultargs)
454
455     def test_basic(self):
456         self.defaultargs['neutronurl'] = self._neutron_url
457         self.defaultargs['odlip'] = self._sdn_controller_ip
458         self.assertEqual(
459             self.parser.parse_args(
460                 ["--neutronurl={}".format(self._neutron_url),
461                  "--odlip={}".format(self._sdn_controller_ip)]),
462             self.defaultargs)
463
464     @mock.patch('sys.stderr', new_callable=six.StringIO)
465     def test_fail(self, mock_method):
466         self.defaultargs['foo'] = 'bar'
467         with self.assertRaises(SystemExit):
468             self.parser.parse_args(["--foo=bar"])
469         self.assertTrue(mock_method.getvalue().startswith("usage:"))
470
471     def _test_arg(self, arg, value):
472         self.defaultargs[arg] = value
473         self.assertEqual(
474             self.parser.parse_args(["--{}={}".format(arg, value)]),
475             self.defaultargs)
476
477     def test_odlusername(self):
478         self._test_arg('odlusername', 'foo')
479
480     def test_odlpassword(self):
481         self._test_arg('odlpassword', 'foo')
482
483     def test_osauthurl(self):
484         self._test_arg('osauthurl', 'http://127.0.0.4:5000/v2')
485
486     def test_neutronurl(self):
487         self._test_arg('neutronurl', 'http://127.0.0.4:9696')
488
489     def test_osusername(self):
490         self._test_arg('osusername', 'foo')
491
492     def test_osuserdomainname(self):
493         self._test_arg('osuserdomainname', 'domain')
494
495     def test_osprojectname(self):
496         self._test_arg('osprojectname', 'foo')
497
498     def test_osprojectdomainname(self):
499         self._test_arg('osprojectdomainname', 'domain')
500
501     def test_ospassword(self):
502         self._test_arg('ospassword', 'foo')
503
504     def test_odlip(self):
505         self._test_arg('odlip', '127.0.0.4')
506
507     def test_odlwebport(self):
508         self._test_arg('odlwebport', '80')
509
510     def test_odlrestconfport(self):
511         self._test_arg('odlrestconfport', '80')
512
513     def test_pushtodb(self):
514         self.defaultargs['pushtodb'] = True
515         self.assertEqual(self.parser.parse_args(["--{}".format('pushtodb')]),
516                          self.defaultargs)
517
518     def test_multiple_args(self):
519         self.defaultargs['neutronurl'] = self._neutron_url
520         self.defaultargs['odlip'] = self._sdn_controller_ip
521         self.assertEqual(
522             self.parser.parse_args(
523                 ["--neutronurl={}".format(self._neutron_url),
524                  "--odlip={}".format(self._sdn_controller_ip)]),
525             self.defaultargs)
526
527
528 if __name__ == "__main__":
529     logging.disable(logging.CRITICAL)
530     unittest.main(verbosity=2)