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 base
21 from yardstick.benchmark.contexts import dummy
22 from yardstick.benchmark.core import task
23 from yardstick.common import constants as consts
24 from yardstick.common import exceptions
25 from yardstick.common import task_template
26 from yardstick.common import utils
29 class TaskTestCase(unittest.TestCase):
31 @mock.patch.object(task, 'Context')
32 def test_parse_nodes_with_context_same_context(self, mock_context):
42 "key_filename": "/root/.ssh/id_rsa"
44 mock_context.get_server.return_value = server_info
46 context_cfg = task.parse_nodes_with_context(scenario_cfg)
48 self.assertEqual(context_cfg["host"], server_info)
49 self.assertEqual(context_cfg["target"], server_info)
51 def test_set_dispatchers(self):
53 output_config = {"DEFAULT": {"dispatcher": "file, http"}}
54 t._set_dispatchers(output_config)
55 self.assertEqual(output_config, output_config)
57 @mock.patch.object(task, 'DispatcherBase')
58 def test__do_output(self, mock_dispatcher):
60 output_config = {"DEFAULT": {"dispatcher": "file, http"}}
62 dispatcher1 = mock.MagicMock()
63 dispatcher1.__dispatcher_type__ = 'file'
65 dispatcher2 = mock.MagicMock()
66 dispatcher2.__dispatcher_type__ = 'http'
68 mock_dispatcher.get = mock.MagicMock(return_value=[dispatcher1,
70 self.assertIsNone(t._do_output(output_config, {}))
72 @mock.patch.object(task, 'Context')
73 def test_parse_networks_from_nodes(self, mock_context):
78 'network_name': 'mgmt',
81 'network_name': 'uplink_0',
84 'network_name': 'downlink_0',
91 'network_name': 'mgmt',
94 'network_name': 'uplink_0',
97 'network_name': 'downlink_0',
103 mock_context.get_network.side_effect = iter([
107 'network_type': 'flat',
112 'subnet_cidr': '10.20.0.0/16',
115 'name': 'downlink_0',
116 'segmentation_id': '1001',
123 # one for each interface
124 expected_get_network_calls = 6
126 'mgmt': {'name': 'mgmt', 'network_type': 'flat'},
127 'uplink_0': {'name': 'uplink_0', 'subnet_cidr': '10.20.0.0/16'},
128 'uplink_1': {'name': 'uplink_1'},
129 'downlink_0': {'name': 'downlink_0', 'segmentation_id': '1001'},
132 networks = task.get_networks_from_nodes(nodes)
133 self.assertEqual(mock_context.get_network.call_count, expected_get_network_calls)
134 self.assertDictEqual(networks, expected)
136 @mock.patch.object(task, 'Context')
137 @mock.patch.object(task, 'base_runner')
138 def test_run(self, mock_base_runner, *args):
140 'host': 'athena.demo',
141 'target': 'ares.demo',
152 runner.join.return_value = 0
153 runner.get_output.return_value = {}
154 runner.get_result.return_value = []
155 mock_base_runner.Runner.get.return_value = runner
156 t._run([scenario], False, "yardstick.out")
157 runner.run.assert_called_once()
159 @mock.patch.object(os, 'environ')
160 def test_check_precondition(self, mock_os_environ):
163 'installer_type': 'compass',
164 'deploy_scenarios': 'os-nosdn',
165 'pod_name': 'huawei-pod1'
169 t = task.TaskParser('/opt')
170 mock_os_environ.get.side_effect = ['compass',
173 result = t._check_precondition(cfg)
174 self.assertTrue(result)
176 def test_parse_suite_no_constraint_no_args(self):
177 SAMPLE_SCENARIO_PATH = "no_constraint_no_args_scenario_sample.yaml"
178 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
179 with mock.patch.object(os, 'environ',
180 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
181 task_files, task_args, task_args_fnames = t.parse_suite()
183 self.assertEqual(task_files[0], self.change_to_abspath(
184 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
185 self.assertEqual(task_files[1], self.change_to_abspath(
186 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
187 self.assertIsNone(task_args[0])
188 self.assertIsNone(task_args[1])
189 self.assertIsNone(task_args_fnames[0])
190 self.assertIsNone(task_args_fnames[1])
192 def test_parse_suite_no_constraint_with_args(self):
193 SAMPLE_SCENARIO_PATH = "no_constraint_with_args_scenario_sample.yaml"
194 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
195 with mock.patch.object(os, 'environ',
196 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
197 task_files, task_args, task_args_fnames = t.parse_suite()
199 self.assertEqual(task_files[0], self.change_to_abspath(
200 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
201 self.assertEqual(task_files[1], self.change_to_abspath(
202 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
203 self.assertIsNone(task_args[0])
204 self.assertEqual(task_args[1],
205 '{"host": "node1.LF","target": "node2.LF"}')
206 self.assertIsNone(task_args_fnames[0])
207 self.assertIsNone(task_args_fnames[1])
209 def test_parse_suite_with_constraint_no_args(self):
210 SAMPLE_SCENARIO_PATH = "with_constraint_no_args_scenario_sample.yaml"
211 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
212 with mock.patch.object(os, 'environ',
213 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
214 task_files, task_args, task_args_fnames = t.parse_suite()
215 self.assertEqual(task_files[0], self.change_to_abspath(
216 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
217 self.assertEqual(task_files[1], self.change_to_abspath(
218 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
219 self.assertIsNone(task_args[0])
220 self.assertIsNone(task_args[1])
221 self.assertIsNone(task_args_fnames[0])
222 self.assertIsNone(task_args_fnames[1])
224 def test_parse_suite_with_constraint_with_args(self):
225 SAMPLE_SCENARIO_PATH = "with_constraint_with_args_scenario_sample.yaml"
226 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
227 with mock.patch('os.environ',
228 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
229 task_files, task_args, task_args_fnames = t.parse_suite()
231 self.assertEqual(task_files[0], self.change_to_abspath(
232 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
233 self.assertEqual(task_files[1], self.change_to_abspath(
234 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
235 self.assertIsNone(task_args[0])
236 self.assertEqual(task_args[1],
237 '{"host": "node1.LF","target": "node2.LF"}')
238 self.assertIsNone(task_args_fnames[0])
239 self.assertIsNone(task_args_fnames[1])
241 def test_parse_options(self):
244 'EXTERNAL_NETWORK': '$network'
246 'nodes': ['node1', '$node'],
252 'network': 'ext-net',
254 'host': 'server.yardstick'
259 'EXTERNAL_NETWORK': 'ext-net'
261 'nodes': ['node1', 'node2'],
262 'host': 'server.yardstick'
265 actual_result = t._parse_options(options)
266 self.assertEqual(expected_result, actual_result)
268 def test_parse_options_no_teardown(self):
271 'EXTERNAL_NETWORK': '$network'
273 'nodes': ['node1', '$node'],
275 'contexts' : {'name': "my-context",
281 'network': 'ext-net',
283 'host': 'server.yardstick'
288 'EXTERNAL_NETWORK': 'ext-net'
290 'nodes': ['node1', 'node2'],
291 'host': 'server.yardstick',
292 'contexts': {'name': 'my-context',
297 actual_result = t._parse_options(options)
298 self.assertEqual(expected_result, actual_result)
300 @mock.patch('six.moves.builtins.open', side_effect=mock.mock_open())
301 @mock.patch.object(task, 'utils')
302 @mock.patch('logging.root')
303 def test_set_log(self, mock_logging_root, *args):
304 task_obj = task.Task()
305 task_obj.task_id = 'task_id'
307 mock_logging_root.addHandler.assert_called()
309 def _get_file_abspath(self, filename):
310 curr_path = os.path.dirname(os.path.abspath(__file__))
311 file_path = os.path.join(curr_path, filename)
314 def change_to_abspath(self, filepath):
315 return os.path.join(consts.YARDSTICK_ROOT_PATH, filepath)
318 class TaskParserTestCase(unittest.TestCase):
321 {% set value1 = value1 or 'var1' %}
322 {% set value2 = value2 or 'var2' %}
327 TASK_RENDERED_1 = u"""
334 TASK_RENDERED_2 = u"""
342 self.parser = task.TaskParser('fake/path')
344 'host': 'athena.demo',
345 'target': 'kratos.demo',
347 'ares.demo', 'mars.demo'
351 'host': 'jupiter.demo',
352 'target': 'saturn.demo',
356 'tg__0': 'tg_0.demo',
357 'vnf__0': 'vnf_0.demo',
362 def _remove_contexts():
363 for context in base.Context.list:
364 context._delete_context()
365 base.Context.list = []
367 def test__change_node_names(self):
371 'task_id': '1234567890',
380 my_context = dummy.DummyContext()
381 self.addCleanup(self._remove_contexts)
382 my_context.init(ctx_attrs)
384 expected_scenario = {
385 'host': 'athena.demo-12345678',
386 'target': 'kratos.demo-12345678',
388 'ares.demo-12345678', 'mars.demo-12345678'
392 'host': 'jupiter.demo-12345678',
393 'target': 'saturn.demo-12345678',
397 'tg__0': 'tg_0.demo-12345678',
398 'vnf__0': 'vnf_0.demo-12345678',
402 scenario = copy.deepcopy(self.scenario)
404 self.parser._change_node_names(scenario, [my_context])
405 self.assertEqual(scenario, expected_scenario)
407 def test__change_node_names_context_not_found(self):
408 scenario = copy.deepcopy(self.scenario)
409 self.assertRaises(exceptions.ScenarioConfigContextNameNotFound,
410 self.parser._change_node_names,
413 def test__change_node_names_context_name_unchanged(self):
416 'task_id': '1234567890',
423 my_context = dummy.DummyContext()
424 self.addCleanup(self._remove_contexts)
425 my_context.init(ctx_attrs)
427 scenario = copy.deepcopy(self.scenario)
428 expected_scenario = copy.deepcopy(self.scenario)
430 self.parser._change_node_names(scenario, [my_context])
431 self.assertEqual(scenario, expected_scenario)
433 def test__change_node_names_options_empty(self):
436 'task_id': '1234567890'
439 my_context = dummy.DummyContext()
440 self.addCleanup(self._remove_contexts)
441 my_context.init(ctx_attrs)
442 scenario = copy.deepcopy(self.scenario)
443 scenario['options'] = None
445 self.parser._change_node_names(scenario, [my_context])
446 self.assertIsNone(scenario['options'])
448 def test__change_node_names_options_server_name_empty(self):
451 'task_id': '1234567890'
454 my_context = dummy.DummyContext()
455 self.addCleanup(self._remove_contexts)
456 my_context.init(ctx_attrs)
457 scenario = copy.deepcopy(self.scenario)
458 scenario['options']['server_name'] = None
460 self.parser._change_node_names(scenario, [my_context])
461 self.assertIsNone(scenario['options']['server_name'])
463 def test__parse_tasks(self):
464 task_obj = task.Task()
466 task_obj.task_id = _uuid
467 task_files = ['/directory/task_file_name.yml']
468 mock_parser = mock.Mock()
469 mock_parser.parse_task.return_value = {'rendered': 'File content'}
470 mock_args = mock.Mock()
471 mock_args.render_only = False
473 tasks = task_obj._parse_tasks(mock_parser, task_files, mock_args,
474 ['arg1'], ['file_arg1'])
476 [{'rendered': 'File content', 'case_name': 'task_file_name'}],
478 mock_parser.parse_task.assert_called_once_with(
479 _uuid, 'arg1', 'file_arg1')
481 @mock.patch.object(sys, 'exit')
482 @mock.patch.object(utils, 'write_file')
483 @mock.patch.object(utils, 'makedirs')
484 def test__parse_tasks_render_only(self, mock_makedirs, mock_write_file,
486 task_obj = task.Task()
488 task_obj.task_id = _uuid
489 task_files = ['/directory/task_file_name.yml']
490 mock_parser = mock.Mock()
491 mock_parser.parse_task.return_value = {'rendered': 'File content'}
492 mock_args = mock.Mock()
493 mock_args.render_only = '/output_directory'
495 task_obj._parse_tasks(mock_parser, task_files, mock_args,
496 ['arg1'], ['file_arg1'])
497 mock_makedirs.assert_called_once_with('/output_directory')
498 mock_write_file.assert_called_once_with(
499 '/output_directory/000-task_file_name.yml', 'File content')
500 mock_exit.assert_called_once_with(0)
502 def test__render_task_no_args(self):
503 task_parser = task.TaskParser('task_file')
504 task_str = io.StringIO(six.text_type(self.TASK))
505 with mock.patch.object(six.moves.builtins, 'open',
506 return_value=task_str) as mock_open:
507 parsed, rendered = task_parser._render_task(None, None)
509 self.assertEqual(self.TASK_RENDERED_1, rendered)
510 self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
511 mock_open.assert_called_once_with('task_file')
513 def test__render_task_arguments(self):
514 task_parser = task.TaskParser('task_file')
515 task_str = io.StringIO(six.text_type(self.TASK))
516 with mock.patch.object(six.moves.builtins, 'open',
517 return_value=task_str) as mock_open:
518 parsed, rendered = task_parser._render_task('value1: "var1"', None)
520 self.assertEqual(self.TASK_RENDERED_1, rendered)
521 self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
522 mock_open.assert_called_once_with('task_file')
524 def test__render_task_file_arguments(self):
525 task_parser = task.TaskParser('task_file')
526 with mock.patch.object(six.moves.builtins, 'open') as mock_open:
527 mock_open.side_effect = (
528 io.StringIO(six.text_type('value2: var4')),
529 io.StringIO(six.text_type(self.TASK))
531 parsed, rendered = task_parser._render_task('value1: "var3"',
534 self.assertEqual(self.TASK_RENDERED_2, rendered)
535 self.assertEqual({'key1': 'var3', 'key2': ['var4']}, parsed)
536 mock_open.assert_has_calls([mock.call('args_file'),
537 mock.call('task_file')])
539 def test__render_task_error_arguments(self):
540 with self.assertRaises(exceptions.TaskRenderArgumentError):
541 task.TaskParser('task_file')._render_task('value1="var3"', None)
543 def test__render_task_error_task_file(self):
544 task_parser = task.TaskParser('task_file')
545 with mock.patch.object(six.moves.builtins, 'open') as mock_open:
546 mock_open.side_effect = (
547 io.StringIO(six.text_type('value2: var4')),
550 with self.assertRaises(exceptions.TaskReadError):
551 task_parser._render_task('value1: "var3"', 'args_file')
553 mock_open.assert_has_calls([mock.call('args_file'),
554 mock.call('task_file')])
556 def test__render_task_render_error(self):
557 task_parser = task.TaskParser('task_file')
558 with mock.patch.object(six.moves.builtins, 'open') as mock_open, \
559 mock.patch.object(task_template.TaskTemplate, 'render',
560 side_effect=TypeError) as mock_render:
561 mock_open.side_effect = (
562 io.StringIO(six.text_type('value2: var4')),
563 io.StringIO(six.text_type(self.TASK))
565 with self.assertRaises(exceptions.TaskRenderError):
566 task_parser._render_task('value1: "var3"', 'args_file')
568 mock_open.assert_has_calls([mock.call('args_file'),
569 mock.call('task_file')])
570 mock_render.assert_has_calls(
571 [mock.call(self.TASK, value1='var3', value2='var4')])