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(base, '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(base, '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(base, '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(base, 'Context')
160 @mock.patch.object(task, 'base_runner')
161 def test_run_ProxDuration(self, mock_base_runner, *args):
163 'host': 'athena.demo',
164 'target': 'ares.demo',
170 'type': 'ProxDuration'
177 runner.join.return_value = 0
178 runner.get_output.return_value = {}
179 runner.get_result.return_value = []
180 mock_base_runner.Runner.get.return_value = runner
181 t._run([scenario], False, "yardstick.out")
182 runner.run.assert_called_once()
184 @mock.patch.object(os, 'environ')
185 def test_check_precondition(self, mock_os_environ):
188 'installer_type': 'compass',
189 'deploy_scenarios': 'os-nosdn',
190 'pod_name': 'huawei-pod1'
194 t = task.TaskParser('/opt')
195 mock_os_environ.get.side_effect = ['compass',
198 result = t._check_precondition(cfg)
199 self.assertTrue(result)
201 def test_parse_suite_no_constraint_no_args(self):
202 SAMPLE_SCENARIO_PATH = "no_constraint_no_args_scenario_sample.yaml"
203 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
204 with mock.patch.object(os, 'environ',
205 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
206 task_files, task_args, task_args_fnames = t.parse_suite()
208 self.assertEqual(task_files[0], self.change_to_abspath(
209 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
210 self.assertEqual(task_files[1], self.change_to_abspath(
211 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
212 self.assertIsNone(task_args[0])
213 self.assertIsNone(task_args[1])
214 self.assertIsNone(task_args_fnames[0])
215 self.assertIsNone(task_args_fnames[1])
217 def test_parse_suite_no_constraint_with_args(self):
218 SAMPLE_SCENARIO_PATH = "no_constraint_with_args_scenario_sample.yaml"
219 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
220 with mock.patch.object(os, 'environ',
221 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
222 task_files, task_args, task_args_fnames = t.parse_suite()
224 self.assertEqual(task_files[0], self.change_to_abspath(
225 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
226 self.assertEqual(task_files[1], self.change_to_abspath(
227 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
228 self.assertIsNone(task_args[0])
229 self.assertEqual(task_args[1],
230 '{"host": "node1.LF","target": "node2.LF"}')
231 self.assertIsNone(task_args_fnames[0])
232 self.assertIsNone(task_args_fnames[1])
234 def test_parse_suite_with_constraint_no_args(self):
235 SAMPLE_SCENARIO_PATH = "with_constraint_no_args_scenario_sample.yaml"
236 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
237 with mock.patch.object(os, 'environ',
238 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
239 task_files, task_args, task_args_fnames = t.parse_suite()
240 self.assertEqual(task_files[0], self.change_to_abspath(
241 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
242 self.assertEqual(task_files[1], self.change_to_abspath(
243 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
244 self.assertIsNone(task_args[0])
245 self.assertIsNone(task_args[1])
246 self.assertIsNone(task_args_fnames[0])
247 self.assertIsNone(task_args_fnames[1])
249 def test_parse_suite_with_constraint_with_args(self):
250 SAMPLE_SCENARIO_PATH = "with_constraint_with_args_scenario_sample.yaml"
251 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
252 with mock.patch('os.environ',
253 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
254 task_files, task_args, task_args_fnames = t.parse_suite()
256 self.assertEqual(task_files[0], self.change_to_abspath(
257 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
258 self.assertEqual(task_files[1], self.change_to_abspath(
259 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
260 self.assertIsNone(task_args[0])
261 self.assertEqual(task_args[1],
262 '{"host": "node1.LF","target": "node2.LF"}')
263 self.assertIsNone(task_args_fnames[0])
264 self.assertIsNone(task_args_fnames[1])
266 def test_parse_options(self):
269 'EXTERNAL_NETWORK': '$network'
271 'nodes': ['node1', '$node'],
277 'network': 'ext-net',
279 'host': 'server.yardstick'
284 'EXTERNAL_NETWORK': 'ext-net'
286 'nodes': ['node1', 'node2'],
287 'host': 'server.yardstick'
290 actual_result = t._parse_options(options)
291 self.assertEqual(expected_result, actual_result)
293 def test_parse_options_no_teardown(self):
296 'EXTERNAL_NETWORK': '$network'
298 'nodes': ['node1', '$node'],
300 'contexts' : {'name': "my-context",
306 'network': 'ext-net',
308 'host': 'server.yardstick'
313 'EXTERNAL_NETWORK': 'ext-net'
315 'nodes': ['node1', 'node2'],
316 'host': 'server.yardstick',
317 'contexts': {'name': 'my-context',
322 actual_result = t._parse_options(options)
323 self.assertEqual(expected_result, actual_result)
325 @mock.patch('six.moves.builtins.open', side_effect=mock.mock_open())
326 @mock.patch.object(task, 'utils')
327 @mock.patch('logging.root')
328 def test_set_log(self, mock_logging_root, *args):
329 task_obj = task.Task()
330 task_obj.task_id = 'task_id'
332 mock_logging_root.addHandler.assert_called()
334 def _get_file_abspath(self, filename):
335 curr_path = os.path.dirname(os.path.abspath(__file__))
336 file_path = os.path.join(curr_path, filename)
339 def change_to_abspath(self, filepath):
340 return os.path.join(consts.YARDSTICK_ROOT_PATH, filepath)
343 class TaskParserTestCase(unittest.TestCase):
346 {% set value1 = value1 or 'var1' %}
347 {% set value2 = value2 or 'var2' %}
352 TASK_RENDERED_1 = u"""
359 TASK_RENDERED_2 = u"""
367 self.parser = task.TaskParser('fake/path')
369 'host': 'athena.demo',
370 'target': 'kratos.demo',
372 'ares.demo', 'mars.demo'
376 'host': 'jupiter.demo',
377 'target': 'saturn.demo',
381 'tg__0': 'tg_0.demo',
382 'vnf__0': 'vnf_0.demo',
387 def _remove_contexts():
388 for context in base.Context.list:
389 context._delete_context()
390 base.Context.list = []
392 def test__change_node_names(self):
396 'task_id': '1234567890',
405 my_context = dummy.DummyContext()
406 self.addCleanup(self._remove_contexts)
407 my_context.init(ctx_attrs)
409 expected_scenario = {
410 'host': 'athena.demo-12345678',
411 'target': 'kratos.demo-12345678',
413 'ares.demo-12345678', 'mars.demo-12345678'
417 'host': 'jupiter.demo-12345678',
418 'target': 'saturn.demo-12345678',
422 'tg__0': 'tg_0.demo-12345678',
423 'vnf__0': 'vnf_0.demo-12345678',
427 scenario = copy.deepcopy(self.scenario)
429 self.parser._change_node_names(scenario, [my_context])
430 self.assertEqual(scenario, expected_scenario)
432 def test__change_node_names_context_not_found(self):
433 scenario = copy.deepcopy(self.scenario)
434 self.assertRaises(exceptions.ScenarioConfigContextNameNotFound,
435 self.parser._change_node_names,
438 def test__change_node_names_context_name_unchanged(self):
441 'task_id': '1234567890',
448 my_context = dummy.DummyContext()
449 self.addCleanup(self._remove_contexts)
450 my_context.init(ctx_attrs)
452 scenario = copy.deepcopy(self.scenario)
453 expected_scenario = copy.deepcopy(self.scenario)
455 self.parser._change_node_names(scenario, [my_context])
456 self.assertEqual(scenario, expected_scenario)
458 def test__change_node_names_options_empty(self):
461 'task_id': '1234567890'
464 my_context = dummy.DummyContext()
465 self.addCleanup(self._remove_contexts)
466 my_context.init(ctx_attrs)
467 scenario = copy.deepcopy(self.scenario)
468 scenario['options'] = None
470 self.parser._change_node_names(scenario, [my_context])
471 self.assertIsNone(scenario['options'])
473 def test__change_node_names_options_server_name_empty(self):
476 'task_id': '1234567890'
479 my_context = dummy.DummyContext()
480 self.addCleanup(self._remove_contexts)
481 my_context.init(ctx_attrs)
482 scenario = copy.deepcopy(self.scenario)
483 scenario['options']['server_name'] = None
485 self.parser._change_node_names(scenario, [my_context])
486 self.assertIsNone(scenario['options']['server_name'])
488 def test__parse_tasks(self):
489 task_obj = task.Task()
491 task_obj.task_id = _uuid
492 task_files = ['/directory/task_file_name.yml']
493 mock_parser = mock.Mock()
494 mock_parser.parse_task.return_value = {'rendered': 'File content'}
495 mock_args = mock.Mock()
496 mock_args.render_only = False
498 tasks = task_obj._parse_tasks(mock_parser, task_files, mock_args,
499 ['arg1'], ['file_arg1'])
501 [{'rendered': 'File content', 'case_name': 'task_file_name'}],
503 mock_parser.parse_task.assert_called_once_with(
504 _uuid, 'arg1', 'file_arg1')
506 @mock.patch.object(sys, 'exit')
507 @mock.patch.object(utils, 'write_file')
508 @mock.patch.object(utils, 'makedirs')
509 def test__parse_tasks_render_only(self, mock_makedirs, mock_write_file,
511 task_obj = task.Task()
513 task_obj.task_id = _uuid
514 task_files = ['/directory/task_file_name.yml']
515 mock_parser = mock.Mock()
516 mock_parser.parse_task.return_value = {'rendered': 'File content'}
517 mock_args = mock.Mock()
518 mock_args.render_only = '/output_directory'
520 task_obj._parse_tasks(mock_parser, task_files, mock_args,
521 ['arg1'], ['file_arg1'])
522 mock_makedirs.assert_called_once_with('/output_directory')
523 mock_write_file.assert_called_once_with(
524 '/output_directory/000-task_file_name.yml', 'File content')
525 mock_exit.assert_called_once_with(0)
527 def test__render_task_no_args(self):
528 task_parser = task.TaskParser('task_file')
529 task_str = io.StringIO(six.text_type(self.TASK))
530 with mock.patch.object(six.moves.builtins, 'open',
531 return_value=task_str) as mock_open:
532 parsed, rendered = task_parser._render_task(None, None)
534 self.assertEqual(self.TASK_RENDERED_1, rendered)
535 self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
536 mock_open.assert_called_once_with('task_file')
538 def test__render_task_arguments(self):
539 task_parser = task.TaskParser('task_file')
540 task_str = io.StringIO(six.text_type(self.TASK))
541 with mock.patch.object(six.moves.builtins, 'open',
542 return_value=task_str) as mock_open:
543 parsed, rendered = task_parser._render_task('value1: "var1"', None)
545 self.assertEqual(self.TASK_RENDERED_1, rendered)
546 self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
547 mock_open.assert_called_once_with('task_file')
549 def test__render_task_file_arguments(self):
550 task_parser = task.TaskParser('task_file')
551 with mock.patch.object(six.moves.builtins, 'open') as mock_open:
552 mock_open.side_effect = (
553 io.StringIO(six.text_type('value2: var4')),
554 io.StringIO(six.text_type(self.TASK))
556 parsed, rendered = task_parser._render_task('value1: "var3"',
559 self.assertEqual(self.TASK_RENDERED_2, rendered)
560 self.assertEqual({'key1': 'var3', 'key2': ['var4']}, parsed)
561 mock_open.assert_has_calls([mock.call('args_file'),
562 mock.call('task_file')])
564 def test__render_task_error_arguments(self):
565 with self.assertRaises(exceptions.TaskRenderArgumentError):
566 task.TaskParser('task_file')._render_task('value1="var3"', None)
568 def test__render_task_error_task_file(self):
569 task_parser = task.TaskParser('task_file')
570 with mock.patch.object(six.moves.builtins, 'open') as mock_open:
571 mock_open.side_effect = (
572 io.StringIO(six.text_type('value2: var4')),
575 with self.assertRaises(exceptions.TaskReadError):
576 task_parser._render_task('value1: "var3"', 'args_file')
578 mock_open.assert_has_calls([mock.call('args_file'),
579 mock.call('task_file')])
581 def test__render_task_render_error(self):
582 task_parser = task.TaskParser('task_file')
583 with mock.patch.object(six.moves.builtins, 'open') as mock_open, \
584 mock.patch.object(task_template.TaskTemplate, 'render',
585 side_effect=TypeError) as mock_render:
586 mock_open.side_effect = (
587 io.StringIO(six.text_type('value2: var4')),
588 io.StringIO(six.text_type(self.TASK))
590 with self.assertRaises(exceptions.TaskRenderError):
591 task_parser._render_task('value1: "var3"', 'args_file')
593 mock_open.assert_has_calls([mock.call('args_file'),
594 mock.call('task_file')])
595 mock_render.assert_has_calls(
596 [mock.call(self.TASK, value1='var3', value2='var4')])