1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
20 from yardstick.benchmark.contexts import dummy
21 from yardstick.benchmark.core import task
22 from yardstick.common import constants as consts
23 from yardstick.common import exceptions
24 from yardstick.common import task_template
25 from yardstick.common import utils
28 class TaskTestCase(unittest.TestCase):
30 @mock.patch.object(task, 'Context')
31 def test_parse_nodes_with_context_same_context(self, mock_context):
41 "key_filename": "/root/.ssh/id_rsa"
43 mock_context.get_server.return_value = server_info
45 context_cfg = task.parse_nodes_with_context(scenario_cfg)
47 self.assertEqual(context_cfg["host"], server_info)
48 self.assertEqual(context_cfg["target"], server_info)
50 def test_set_dispatchers(self):
52 output_config = {"DEFAULT": {"dispatcher": "file, http"}}
53 t._set_dispatchers(output_config)
54 self.assertEqual(output_config, output_config)
56 @mock.patch.object(task, 'DispatcherBase')
57 def test__do_output(self, mock_dispatcher):
59 output_config = {"DEFAULT": {"dispatcher": "file, http"}}
61 dispatcher1 = mock.MagicMock()
62 dispatcher1.__dispatcher_type__ = 'file'
64 dispatcher2 = mock.MagicMock()
65 dispatcher2.__dispatcher_type__ = 'http'
67 mock_dispatcher.get = mock.MagicMock(return_value=[dispatcher1,
69 self.assertIsNone(t._do_output(output_config, {}))
71 @mock.patch.object(task, 'Context')
72 def test_parse_networks_from_nodes(self, mock_context):
77 'network_name': 'mgmt',
80 'network_name': 'uplink_0',
83 'network_name': 'downlink_0',
90 'network_name': 'mgmt',
93 'network_name': 'uplink_0',
96 'network_name': 'downlink_0',
102 mock_context.get_network.side_effect = iter([
106 'network_type': 'flat',
111 'subnet_cidr': '10.20.0.0/16',
114 'name': 'downlink_0',
115 'segmentation_id': '1001',
122 # one for each interface
123 expected_get_network_calls = 6
125 'mgmt': {'name': 'mgmt', 'network_type': 'flat'},
126 'uplink_0': {'name': 'uplink_0', 'subnet_cidr': '10.20.0.0/16'},
127 'uplink_1': {'name': 'uplink_1'},
128 'downlink_0': {'name': 'downlink_0', 'segmentation_id': '1001'},
131 networks = task.get_networks_from_nodes(nodes)
132 self.assertEqual(mock_context.get_network.call_count, expected_get_network_calls)
133 self.assertDictEqual(networks, expected)
135 @mock.patch.object(task, 'Context')
136 @mock.patch.object(task, 'base_runner')
137 def test_run(self, mock_base_runner, *args):
139 'host': 'athena.demo',
140 'target': 'ares.demo',
151 runner.join.return_value = 0
152 runner.get_output.return_value = {}
153 runner.get_result.return_value = []
154 mock_base_runner.Runner.get.return_value = runner
155 t._run([scenario], False, "yardstick.out")
156 runner.run.assert_called_once()
158 @mock.patch.object(os, 'environ')
159 def test_check_precondition(self, mock_os_environ):
162 'installer_type': 'compass',
163 'deploy_scenarios': 'os-nosdn',
164 'pod_name': 'huawei-pod1'
168 t = task.TaskParser('/opt')
169 mock_os_environ.get.side_effect = ['compass',
172 result = t._check_precondition(cfg)
173 self.assertTrue(result)
175 def test_parse_suite_no_constraint_no_args(self):
176 SAMPLE_SCENARIO_PATH = "no_constraint_no_args_scenario_sample.yaml"
177 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
178 with mock.patch.object(os, 'environ',
179 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
180 task_files, task_args, task_args_fnames = t.parse_suite()
182 self.assertEqual(task_files[0], self.change_to_abspath(
183 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
184 self.assertEqual(task_files[1], self.change_to_abspath(
185 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
186 self.assertIsNone(task_args[0])
187 self.assertIsNone(task_args[1])
188 self.assertIsNone(task_args_fnames[0])
189 self.assertIsNone(task_args_fnames[1])
191 def test_parse_suite_no_constraint_with_args(self):
192 SAMPLE_SCENARIO_PATH = "no_constraint_with_args_scenario_sample.yaml"
193 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
194 with mock.patch.object(os, 'environ',
195 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
196 task_files, task_args, task_args_fnames = t.parse_suite()
198 self.assertEqual(task_files[0], self.change_to_abspath(
199 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
200 self.assertEqual(task_files[1], self.change_to_abspath(
201 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
202 self.assertIsNone(task_args[0])
203 self.assertEqual(task_args[1],
204 '{"host": "node1.LF","target": "node2.LF"}')
205 self.assertIsNone(task_args_fnames[0])
206 self.assertIsNone(task_args_fnames[1])
208 def test_parse_suite_with_constraint_no_args(self):
209 SAMPLE_SCENARIO_PATH = "with_constraint_no_args_scenario_sample.yaml"
210 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
211 with mock.patch.object(os, 'environ',
212 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
213 task_files, task_args, task_args_fnames = t.parse_suite()
214 self.assertEqual(task_files[0], self.change_to_abspath(
215 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
216 self.assertEqual(task_files[1], self.change_to_abspath(
217 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
218 self.assertIsNone(task_args[0])
219 self.assertIsNone(task_args[1])
220 self.assertIsNone(task_args_fnames[0])
221 self.assertIsNone(task_args_fnames[1])
223 def test_parse_suite_with_constraint_with_args(self):
224 SAMPLE_SCENARIO_PATH = "with_constraint_with_args_scenario_sample.yaml"
225 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
226 with mock.patch('os.environ',
227 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
228 task_files, task_args, task_args_fnames = t.parse_suite()
230 self.assertEqual(task_files[0], self.change_to_abspath(
231 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
232 self.assertEqual(task_files[1], self.change_to_abspath(
233 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
234 self.assertIsNone(task_args[0])
235 self.assertEqual(task_args[1],
236 '{"host": "node1.LF","target": "node2.LF"}')
237 self.assertIsNone(task_args_fnames[0])
238 self.assertIsNone(task_args_fnames[1])
240 def test_parse_options(self):
243 'EXTERNAL_NETWORK': '$network'
245 'nodes': ['node1', '$node'],
251 'network': 'ext-net',
253 'host': 'server.yardstick'
258 'EXTERNAL_NETWORK': 'ext-net'
260 'nodes': ['node1', 'node2'],
261 'host': 'server.yardstick'
264 actual_result = t._parse_options(options)
265 self.assertEqual(expected_result, actual_result)
267 def test_parse_options_no_teardown(self):
270 'EXTERNAL_NETWORK': '$network'
272 'nodes': ['node1', '$node'],
274 'contexts' : {'name': "my-context",
280 'network': 'ext-net',
282 'host': 'server.yardstick'
287 'EXTERNAL_NETWORK': 'ext-net'
289 'nodes': ['node1', 'node2'],
290 'host': 'server.yardstick',
291 'contexts': {'name': 'my-context',
296 actual_result = t._parse_options(options)
297 self.assertEqual(expected_result, actual_result)
299 @mock.patch('six.moves.builtins.open', side_effect=mock.mock_open())
300 @mock.patch.object(task, 'utils')
301 @mock.patch('logging.root')
302 def test_set_log(self, mock_logging_root, *args):
303 task_obj = task.Task()
304 task_obj.task_id = 'task_id'
306 mock_logging_root.addHandler.assert_called()
308 def _get_file_abspath(self, filename):
309 curr_path = os.path.dirname(os.path.abspath(__file__))
310 file_path = os.path.join(curr_path, filename)
313 def change_to_abspath(self, filepath):
314 return os.path.join(consts.YARDSTICK_ROOT_PATH, filepath)
317 class TaskParserTestCase(unittest.TestCase):
320 {% set value1 = value1 or 'var1' %}
321 {% set value2 = value2 or 'var2' %}
326 TASK_RENDERED_1 = u"""
333 TASK_RENDERED_2 = u"""
341 self.parser = task.TaskParser('fake/path')
343 'host': 'athena.demo',
344 'target': 'kratos.demo',
346 'ares.demo', 'mars.demo'
350 'host': 'jupiter.demo',
351 'target': 'saturn.demo',
355 'tg__0': 'tg_0.demo',
356 'vnf__0': 'vnf_0.demo',
361 def _remove_context(context):
363 context._delete_context()
365 def test__change_node_names(self):
369 'task_id': '1234567890',
378 my_context = dummy.DummyContext()
379 self.addCleanup(self._remove_context, my_context)
380 my_context.init(ctx_attrs)
382 expected_scenario = {
383 'host': 'athena.demo-12345678',
384 'target': 'kratos.demo-12345678',
386 'ares.demo-12345678', 'mars.demo-12345678'
390 'host': 'jupiter.demo-12345678',
391 'target': 'saturn.demo-12345678',
395 'tg__0': 'tg_0.demo-12345678',
396 'vnf__0': 'vnf_0.demo-12345678',
400 scenario = copy.deepcopy(self.scenario)
402 self.parser._change_node_names(scenario, [my_context])
403 self.assertEqual(scenario, expected_scenario)
405 def test__change_node_names_context_not_found(self):
406 scenario = copy.deepcopy(self.scenario)
407 self.assertRaises(exceptions.ScenarioConfigContextNameNotFound,
408 self.parser._change_node_names,
411 def test__change_node_names_context_name_unchanged(self):
414 'task_id': '1234567890',
421 my_context = dummy.DummyContext()
422 self.addCleanup(self._remove_context, my_context)
423 my_context.init(ctx_attrs)
425 scenario = copy.deepcopy(self.scenario)
426 expected_scenario = copy.deepcopy(self.scenario)
428 self.parser._change_node_names(scenario, [my_context])
429 self.assertEqual(scenario, expected_scenario)
431 def test__change_node_names_options_empty(self):
434 'task_id': '1234567890'
437 my_context = dummy.DummyContext()
438 self.addCleanup(self._remove_context, my_context)
439 my_context.init(ctx_attrs)
440 scenario = copy.deepcopy(self.scenario)
441 scenario['options'] = None
443 self.parser._change_node_names(scenario, [my_context])
444 self.assertIsNone(scenario['options'])
446 def test__change_node_names_options_server_name_empty(self):
449 'task_id': '1234567890'
452 my_context = dummy.DummyContext()
453 self.addCleanup(self._remove_context, my_context)
454 my_context.init(ctx_attrs)
455 scenario = copy.deepcopy(self.scenario)
456 scenario['options']['server_name'] = None
458 self.parser._change_node_names(scenario, [my_context])
459 self.assertIsNone(scenario['options']['server_name'])
461 def test__parse_tasks(self):
462 task_obj = task.Task()
464 task_obj.task_id = _uuid
465 task_files = ['/directory/task_file_name.yml']
466 mock_parser = mock.Mock()
467 mock_parser.parse_task.return_value = {'rendered': 'File content'}
468 mock_args = mock.Mock()
469 mock_args.render_only = False
471 tasks = task_obj._parse_tasks(mock_parser, task_files, mock_args,
472 ['arg1'], ['file_arg1'])
474 [{'rendered': 'File content', 'case_name': 'task_file_name'}],
476 mock_parser.parse_task.assert_called_once_with(
477 _uuid, 'arg1', 'file_arg1')
479 @mock.patch.object(sys, 'exit')
480 @mock.patch.object(utils, 'write_file')
481 @mock.patch.object(utils, 'makedirs')
482 def test__parse_tasks_render_only(self, mock_makedirs, mock_write_file,
484 task_obj = task.Task()
486 task_obj.task_id = _uuid
487 task_files = ['/directory/task_file_name.yml']
488 mock_parser = mock.Mock()
489 mock_parser.parse_task.return_value = {'rendered': 'File content'}
490 mock_args = mock.Mock()
491 mock_args.render_only = '/output_directory'
493 task_obj._parse_tasks(mock_parser, task_files, mock_args,
494 ['arg1'], ['file_arg1'])
495 mock_makedirs.assert_called_once_with('/output_directory')
496 mock_write_file.assert_called_once_with(
497 '/output_directory/000-task_file_name.yml', 'File content')
498 mock_exit.assert_called_once_with(0)
500 def test__render_task_no_args(self):
501 task_parser = task.TaskParser('task_file')
502 task_str = io.StringIO(six.text_type(self.TASK))
503 with mock.patch.object(six.moves.builtins, 'open',
504 return_value=task_str) as mock_open:
505 parsed, rendered = task_parser._render_task(None, None)
507 self.assertEqual(self.TASK_RENDERED_1, rendered)
508 self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
509 mock_open.assert_called_once_with('task_file')
511 def test__render_task_arguments(self):
512 task_parser = task.TaskParser('task_file')
513 task_str = io.StringIO(six.text_type(self.TASK))
514 with mock.patch.object(six.moves.builtins, 'open',
515 return_value=task_str) as mock_open:
516 parsed, rendered = task_parser._render_task('value1: "var1"', None)
518 self.assertEqual(self.TASK_RENDERED_1, rendered)
519 self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
520 mock_open.assert_called_once_with('task_file')
522 def test__render_task_file_arguments(self):
523 task_parser = task.TaskParser('task_file')
524 with mock.patch.object(six.moves.builtins, 'open') as mock_open:
525 mock_open.side_effect = (
526 io.StringIO(six.text_type('value2: var4')),
527 io.StringIO(six.text_type(self.TASK))
529 parsed, rendered = task_parser._render_task('value1: "var3"',
532 self.assertEqual(self.TASK_RENDERED_2, rendered)
533 self.assertEqual({'key1': 'var3', 'key2': ['var4']}, parsed)
534 mock_open.assert_has_calls([mock.call('args_file'),
535 mock.call('task_file')])
537 def test__render_task_error_arguments(self):
538 with self.assertRaises(exceptions.TaskRenderArgumentError):
539 task.TaskParser('task_file')._render_task('value1="var3"', None)
541 def test__render_task_error_task_file(self):
542 task_parser = task.TaskParser('task_file')
543 with mock.patch.object(six.moves.builtins, 'open') as mock_open:
544 mock_open.side_effect = (
545 io.StringIO(six.text_type('value2: var4')),
548 with self.assertRaises(exceptions.TaskReadError):
549 task_parser._render_task('value1: "var3"', 'args_file')
551 mock_open.assert_has_calls([mock.call('args_file'),
552 mock.call('task_file')])
554 def test__render_task_render_error(self):
555 task_parser = task.TaskParser('task_file')
556 with mock.patch.object(six.moves.builtins, 'open') as mock_open, \
557 mock.patch.object(task_template.TaskTemplate, 'render',
558 side_effect=TypeError) as mock_render:
559 mock_open.side_effect = (
560 io.StringIO(six.text_type('value2: var4')),
561 io.StringIO(six.text_type(self.TASK))
563 with self.assertRaises(exceptions.TaskRenderError):
564 task_parser._render_task('value1: "var3"', 'args_file')
566 mock_open.assert_has_calls([mock.call('args_file'),
567 mock.call('task_file')])
568 mock_render.assert_has_calls(
569 [mock.call(self.TASK, value1='var3', value2='var4')])