Merge "Add a key benefits section in Release Notes"
[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(self):
391         os.environ["INSTALLER_TYPE"] = "fuel"
392         self._test_run(testcase.TestCase.EX_OK, None,
393                        odlip=urllib.parse.urlparse(self._neutron_url).hostname,
394                        odlwebport='8282',
395                        odlrestconfport='8282')
396
397     def test_apex_no_controller_ip(self):
398         os.environ["INSTALLER_TYPE"] = "apex"
399         self._test_missing_value()
400
401     def test_apex(self):
402         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
403         os.environ["INSTALLER_TYPE"] = "apex"
404         self._test_run(testcase.TestCase.EX_OK, None,
405                        odlip=self._sdn_controller_ip, odlwebport='8081',
406                        odlrestconfport='8081')
407
408     def test_netvirt_no_controller_ip(self):
409         os.environ["INSTALLER_TYPE"] = "netvirt"
410         self._test_missing_value()
411
412     def test_netvirt(self):
413         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
414         os.environ["INSTALLER_TYPE"] = "netvirt"
415         self._test_run(testcase.TestCase.EX_OK, None,
416                        odlip=self._sdn_controller_ip, odlwebport='8081',
417                        odlrestconfport='8081')
418
419     def test_compass(self):
420         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
421         os.environ["INSTALLER_TYPE"] = "compass"
422         self._test_run(testcase.TestCase.EX_OK, None,
423                        odlip=self._sdn_controller_ip,
424                        odlrestconfport='8080')
425
426     def test_daisy_no_controller_ip(self):
427         os.environ["INSTALLER_TYPE"] = "daisy"
428         self._test_missing_value()
429
430     def test_daisy(self):
431         os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
432         os.environ["INSTALLER_TYPE"] = "daisy"
433         self._test_run(testcase.TestCase.EX_OK, None,
434                        odlip=self._sdn_controller_ip, odlwebport='8181',
435                        odlrestconfport='8087')
436
437
438 class ODLArgParserTesting(ODLTesting):
439
440     """The class testing ODLParser."""
441     # pylint: disable=missing-docstring
442
443     def setUp(self):
444         self.parser = odl.ODLParser()
445         super(ODLArgParserTesting, self).setUp()
446
447     def test_default(self):
448         self.assertEqual(self.parser.parse_args(), self.defaultargs)
449
450     def test_basic(self):
451         self.defaultargs['neutronurl'] = self._neutron_url
452         self.defaultargs['odlip'] = self._sdn_controller_ip
453         self.assertEqual(
454             self.parser.parse_args(
455                 ["--neutronurl={}".format(self._neutron_url),
456                  "--odlip={}".format(self._sdn_controller_ip)]),
457             self.defaultargs)
458
459     @mock.patch('sys.stderr', new_callable=six.StringIO)
460     def test_fail(self, mock_method):
461         self.defaultargs['foo'] = 'bar'
462         with self.assertRaises(SystemExit):
463             self.parser.parse_args(["--foo=bar"])
464         self.assertTrue(mock_method.getvalue().startswith("usage:"))
465
466     def _test_arg(self, arg, value):
467         self.defaultargs[arg] = value
468         self.assertEqual(
469             self.parser.parse_args(["--{}={}".format(arg, value)]),
470             self.defaultargs)
471
472     def test_odlusername(self):
473         self._test_arg('odlusername', 'foo')
474
475     def test_odlpassword(self):
476         self._test_arg('odlpassword', 'foo')
477
478     def test_osauthurl(self):
479         self._test_arg('osauthurl', 'http://127.0.0.4:5000/v2')
480
481     def test_neutronurl(self):
482         self._test_arg('neutronurl', 'http://127.0.0.4:9696')
483
484     def test_osusername(self):
485         self._test_arg('osusername', 'foo')
486
487     def test_osuserdomainname(self):
488         self._test_arg('osuserdomainname', 'domain')
489
490     def test_osprojectname(self):
491         self._test_arg('osprojectname', 'foo')
492
493     def test_osprojectdomainname(self):
494         self._test_arg('osprojectdomainname', 'domain')
495
496     def test_ospassword(self):
497         self._test_arg('ospassword', 'foo')
498
499     def test_odlip(self):
500         self._test_arg('odlip', '127.0.0.4')
501
502     def test_odlwebport(self):
503         self._test_arg('odlwebport', '80')
504
505     def test_odlrestconfport(self):
506         self._test_arg('odlrestconfport', '80')
507
508     def test_pushtodb(self):
509         self.defaultargs['pushtodb'] = True
510         self.assertEqual(self.parser.parse_args(["--{}".format('pushtodb')]),
511                          self.defaultargs)
512
513     def test_multiple_args(self):
514         self.defaultargs['neutronurl'] = self._neutron_url
515         self.defaultargs['odlip'] = self._sdn_controller_ip
516         self.assertEqual(
517             self.parser.parse_args(
518                 ["--neutronurl={}".format(self._neutron_url),
519                  "--odlip={}".format(self._sdn_controller_ip)]),
520             self.defaultargs)
521
522
523 if __name__ == "__main__":
524     logging.disable(logging.CRITICAL)
525     unittest.main(verbosity=2)