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 ##############################################################################
18 from six.moves import builtins
22 from yardstick.benchmark.contexts import base
23 from yardstick.benchmark.contexts import dummy
24 from yardstick.benchmark.core import task
25 from yardstick.common import constants as consts
26 from yardstick.common import exceptions
27 from yardstick.common import task_template
28 from yardstick.common import utils
31 class TaskTestCase(unittest.TestCase):
33 @mock.patch.object(base, 'Context')
34 def test_parse_nodes_with_context_same_context(self, mock_context):
44 "key_filename": "/root/.ssh/id_rsa"
46 mock_context.get_server.return_value = server_info
48 context_cfg = task.parse_nodes_with_context(scenario_cfg)
50 self.assertEqual(context_cfg["host"], server_info)
51 self.assertEqual(context_cfg["target"], server_info)
53 def test_set_dispatchers(self):
55 output_config = {"DEFAULT": {"dispatcher": "file, http"}}
56 t._set_dispatchers(output_config)
57 self.assertEqual(output_config, output_config)
59 @mock.patch.object(task, 'DispatcherBase')
60 def test__do_output(self, mock_dispatcher):
62 output_config = {"DEFAULT": {"dispatcher": "file, http"}}
64 dispatcher1 = mock.MagicMock()
65 dispatcher1.__dispatcher_type__ = 'file'
67 dispatcher2 = mock.MagicMock()
68 dispatcher2.__dispatcher_type__ = 'http'
70 mock_dispatcher.get = mock.MagicMock(return_value=[dispatcher1,
72 self.assertIsNone(t._do_output(output_config, {}))
74 @mock.patch.object(base, 'Context')
75 def test_parse_networks_from_nodes(self, mock_context):
80 'network_name': 'mgmt',
83 'network_name': 'uplink_0',
86 'network_name': 'downlink_0',
93 'network_name': 'mgmt',
96 'network_name': 'uplink_0',
99 'network_name': 'downlink_0',
105 mock_context.get_network.side_effect = iter([
109 'network_type': 'flat',
114 'subnet_cidr': '10.20.0.0/16',
117 'name': 'downlink_0',
118 'segmentation_id': '1001',
125 # one for each interface
126 expected_get_network_calls = 6
128 'mgmt': {'name': 'mgmt', 'network_type': 'flat'},
129 'uplink_0': {'name': 'uplink_0', 'subnet_cidr': '10.20.0.0/16'},
130 'uplink_1': {'name': 'uplink_1'},
131 'downlink_0': {'name': 'downlink_0', 'segmentation_id': '1001'},
134 networks = task.get_networks_from_nodes(nodes)
135 self.assertEqual(mock_context.get_network.call_count, expected_get_network_calls)
136 self.assertDictEqual(networks, expected)
138 @mock.patch.object(base, 'Context')
139 @mock.patch.object(task, 'base_runner')
140 def test_run(self, mock_base_runner, *args):
142 'host': 'athena.demo',
143 'target': 'ares.demo',
154 runner.join.return_value = 0
155 runner.get_output.return_value = {}
156 runner.get_result.return_value = []
157 mock_base_runner.Runner.get.return_value = runner
158 t._run([scenario], False, "yardstick.out")
159 runner.run.assert_called_once()
161 @mock.patch.object(base, 'Context')
162 @mock.patch.object(task, 'base_runner')
163 def test_run_ProxDuration(self, mock_base_runner, *args):
165 'host': 'athena.demo',
166 'target': 'ares.demo',
172 'type': 'ProxDuration'
179 runner.join.return_value = 0
180 runner.get_output.return_value = {}
181 runner.get_result.return_value = []
182 mock_base_runner.Runner.get.return_value = runner
183 t._run([scenario], False, "yardstick.out")
184 runner.run.assert_called_once()
186 @mock.patch.object(os, 'environ')
187 def test_check_precondition(self, mock_os_environ):
190 'installer_type': 'compass',
191 'deploy_scenarios': 'os-nosdn',
192 'pod_name': 'huawei-pod1'
196 t = task.TaskParser('/opt')
197 mock_os_environ.get.side_effect = ['compass',
200 result = t._check_precondition(cfg)
201 self.assertTrue(result)
203 def test_parse_suite_no_constraint_no_args(self):
204 SAMPLE_SCENARIO_PATH = "no_constraint_no_args_scenario_sample.yaml"
205 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
206 with mock.patch.object(os, 'environ',
207 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
208 task_files, task_args, task_args_fnames = t.parse_suite()
210 self.assertEqual(task_files[0], self.change_to_abspath(
211 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
212 self.assertEqual(task_files[1], self.change_to_abspath(
213 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
214 self.assertIsNone(task_args[0])
215 self.assertIsNone(task_args[1])
216 self.assertIsNone(task_args_fnames[0])
217 self.assertIsNone(task_args_fnames[1])
219 def test_parse_suite_no_constraint_with_args(self):
220 SAMPLE_SCENARIO_PATH = "no_constraint_with_args_scenario_sample.yaml"
221 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
222 with mock.patch.object(os, 'environ',
223 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
224 task_files, task_args, task_args_fnames = t.parse_suite()
226 self.assertEqual(task_files[0], self.change_to_abspath(
227 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
228 self.assertEqual(task_files[1], self.change_to_abspath(
229 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
230 self.assertIsNone(task_args[0])
231 self.assertEqual(task_args[1],
232 '{"host": "node1.LF","target": "node2.LF"}')
233 self.assertIsNone(task_args_fnames[0])
234 self.assertIsNone(task_args_fnames[1])
236 def test_parse_suite_with_constraint_no_args(self):
237 SAMPLE_SCENARIO_PATH = "with_constraint_no_args_scenario_sample.yaml"
238 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
239 with mock.patch.object(os, 'environ',
240 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
241 task_files, task_args, task_args_fnames = t.parse_suite()
242 self.assertEqual(task_files[0], self.change_to_abspath(
243 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
244 self.assertEqual(task_files[1], self.change_to_abspath(
245 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
246 self.assertIsNone(task_args[0])
247 self.assertIsNone(task_args[1])
248 self.assertIsNone(task_args_fnames[0])
249 self.assertIsNone(task_args_fnames[1])
251 def test_parse_suite_with_constraint_with_args(self):
252 SAMPLE_SCENARIO_PATH = "with_constraint_with_args_scenario_sample.yaml"
253 t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
254 with mock.patch('os.environ',
255 new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
256 task_files, task_args, task_args_fnames = t.parse_suite()
258 self.assertEqual(task_files[0], self.change_to_abspath(
259 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
260 self.assertEqual(task_files[1], self.change_to_abspath(
261 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
262 self.assertIsNone(task_args[0])
263 self.assertEqual(task_args[1],
264 '{"host": "node1.LF","target": "node2.LF"}')
265 self.assertIsNone(task_args_fnames[0])
266 self.assertIsNone(task_args_fnames[1])
268 def test_parse_options(self):
271 'EXTERNAL_NETWORK': '$network'
273 'nodes': ['node1', '$node'],
279 'network': 'ext-net',
281 'host': 'server.yardstick'
286 'EXTERNAL_NETWORK': 'ext-net'
288 'nodes': ['node1', 'node2'],
289 'host': 'server.yardstick'
292 actual_result = t._parse_options(options)
293 self.assertEqual(expected_result, actual_result)
295 def test_parse_options_no_teardown(self):
298 'EXTERNAL_NETWORK': '$network'
300 'nodes': ['node1', '$node'],
302 'contexts' : {'name': "my-context",
308 'network': 'ext-net',
310 'host': 'server.yardstick'
315 'EXTERNAL_NETWORK': 'ext-net'
317 'nodes': ['node1', 'node2'],
318 'host': 'server.yardstick',
319 'contexts': {'name': 'my-context',
324 actual_result = t._parse_options(options)
325 self.assertEqual(expected_result, actual_result)
327 @mock.patch.object(builtins, 'open', side_effect=mock.mock_open())
328 @mock.patch.object(task, 'utils')
329 @mock.patch.object(logging, 'root')
330 def test_set_log(self, mock_logging_root, *args):
331 task_obj = task.Task()
332 task_obj.task_id = 'task_id'
334 mock_logging_root.addHandler.assert_called()
336 def _get_file_abspath(self, filename):
337 curr_path = os.path.dirname(os.path.abspath(__file__))
338 file_path = os.path.join(curr_path, filename)
341 def change_to_abspath(self, filepath):
342 return os.path.join(consts.YARDSTICK_ROOT_PATH, filepath)
345 class TaskParserTestCase(unittest.TestCase):
348 {% set value1 = value1 or 'var1' %}
349 {% set value2 = value2 or 'var2' %}
354 TASK_RENDERED_1 = u"""
361 TASK_RENDERED_2 = u"""
369 self.parser = task.TaskParser('fake/path')
371 'host': 'athena.demo',
372 'target': 'kratos.demo',
374 'ares.demo', 'mars.demo'
378 'host': 'jupiter.demo',
379 'target': 'saturn.demo',
383 'tg__0': 'tg_0.demo',
384 'vnf__0': 'vnf_0.demo',
389 def _remove_contexts():
390 for context in base.Context.list:
391 context._delete_context()
392 base.Context.list = []
394 def test__change_node_names(self):
398 'task_id': '1234567890',
407 my_context = dummy.DummyContext()
408 self.addCleanup(self._remove_contexts)
409 my_context.init(ctx_attrs)
411 expected_scenario = {
412 'host': 'athena.demo-12345678',
413 'target': 'kratos.demo-12345678',
415 'ares.demo-12345678', 'mars.demo-12345678'
419 'host': 'jupiter.demo-12345678',
420 'target': 'saturn.demo-12345678',
424 'tg__0': 'tg_0.demo-12345678',
425 'vnf__0': 'vnf_0.demo-12345678',
429 scenario = copy.deepcopy(self.scenario)
431 self.parser._change_node_names(scenario, [my_context])
432 self.assertEqual(scenario, expected_scenario)
434 def test__change_node_names_context_not_found(self):
435 scenario = copy.deepcopy(self.scenario)
436 self.assertRaises(exceptions.ScenarioConfigContextNameNotFound,
437 self.parser._change_node_names,
440 def test__change_node_names_context_name_unchanged(self):
443 'task_id': '1234567890',
450 my_context = dummy.DummyContext()
451 self.addCleanup(self._remove_contexts)
452 my_context.init(ctx_attrs)
454 scenario = copy.deepcopy(self.scenario)
455 expected_scenario = copy.deepcopy(self.scenario)
457 self.parser._change_node_names(scenario, [my_context])
458 self.assertEqual(scenario, expected_scenario)
460 def test__change_node_names_options_empty(self):
463 'task_id': '1234567890'
466 my_context = dummy.DummyContext()
467 self.addCleanup(self._remove_contexts)
468 my_context.init(ctx_attrs)
469 scenario = copy.deepcopy(self.scenario)
470 scenario['options'] = None
472 self.parser._change_node_names(scenario, [my_context])
473 self.assertIsNone(scenario['options'])
475 def test__change_node_names_options_server_name_empty(self):
478 'task_id': '1234567890'
481 my_context = dummy.DummyContext()
482 self.addCleanup(self._remove_contexts)
483 my_context.init(ctx_attrs)
484 scenario = copy.deepcopy(self.scenario)
485 scenario['options']['server_name'] = None
487 self.parser._change_node_names(scenario, [my_context])
488 self.assertIsNone(scenario['options']['server_name'])
490 def test__parse_tasks(self):
491 task_obj = task.Task()
493 task_obj.task_id = _uuid
494 task_files = ['/directory/task_file_name.yml']
495 mock_parser = mock.Mock()
496 mock_parser.parse_task.return_value = {'rendered': 'File content'}
497 mock_args = mock.Mock()
498 mock_args.render_only = False
500 tasks = task_obj._parse_tasks(mock_parser, task_files, mock_args,
501 ['arg1'], ['file_arg1'])
503 [{'rendered': 'File content', 'case_name': 'task_file_name'}],
505 mock_parser.parse_task.assert_called_once_with(
506 _uuid, 'arg1', 'file_arg1')
508 @mock.patch.object(sys, 'exit')
509 @mock.patch.object(utils, 'write_file')
510 @mock.patch.object(utils, 'makedirs')
511 def test__parse_tasks_render_only(self, mock_makedirs, mock_write_file,
513 task_obj = task.Task()
515 task_obj.task_id = _uuid
516 task_files = ['/directory/task_file_name.yml']
517 mock_parser = mock.Mock()
518 mock_parser.parse_task.return_value = {'rendered': 'File content'}
519 mock_args = mock.Mock()
520 mock_args.render_only = '/output_directory'
522 task_obj._parse_tasks(mock_parser, task_files, mock_args,
523 ['arg1'], ['file_arg1'])
524 mock_makedirs.assert_called_once_with('/output_directory')
525 mock_write_file.assert_called_once_with(
526 '/output_directory/000-task_file_name.yml', 'File content')
527 mock_exit.assert_called_once_with(0)
529 def test__render_task_no_args(self):
530 task_parser = task.TaskParser('task_file')
531 task_str = io.StringIO(six.text_type(self.TASK))
532 with mock.patch.object(six.moves.builtins, 'open',
533 return_value=task_str) as mock_open:
534 parsed, rendered = task_parser._render_task(None, None)
536 self.assertEqual(self.TASK_RENDERED_1, rendered)
537 self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
538 mock_open.assert_called_once_with('task_file')
540 def test__render_task_arguments(self):
541 task_parser = task.TaskParser('task_file')
542 task_str = io.StringIO(six.text_type(self.TASK))
543 with mock.patch.object(six.moves.builtins, 'open',
544 return_value=task_str) as mock_open:
545 parsed, rendered = task_parser._render_task('value1: "var1"', None)
547 self.assertEqual(self.TASK_RENDERED_1, rendered)
548 self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
549 mock_open.assert_called_once_with('task_file')
551 def test__render_task_file_arguments(self):
552 task_parser = task.TaskParser('task_file')
553 with mock.patch.object(six.moves.builtins, 'open') as mock_open:
554 mock_open.side_effect = (
555 io.StringIO(six.text_type('value2: var4')),
556 io.StringIO(six.text_type(self.TASK))
558 parsed, rendered = task_parser._render_task('value1: "var3"',
561 self.assertEqual(self.TASK_RENDERED_2, rendered)
562 self.assertEqual({'key1': 'var3', 'key2': ['var4']}, parsed)
563 mock_open.assert_has_calls([mock.call('args_file'),
564 mock.call('task_file')])
566 @mock.patch.object(builtins, 'print')
567 def test__render_task_error_arguments(self, *args):
568 with self.assertRaises(exceptions.TaskRenderArgumentError):
569 task.TaskParser('task_file')._render_task('value1="var3"', None)
571 def test__render_task_error_task_file(self):
572 task_parser = task.TaskParser('task_file')
573 with mock.patch.object(six.moves.builtins, 'open') as mock_open:
574 mock_open.side_effect = (
575 io.StringIO(six.text_type('value2: var4')),
578 with self.assertRaises(exceptions.TaskReadError):
579 task_parser._render_task('value1: "var3"', 'args_file')
581 mock_open.assert_has_calls([mock.call('args_file'),
582 mock.call('task_file')])
584 def test__render_task_render_error(self):
585 task_parser = task.TaskParser('task_file')
586 with mock.patch.object(six.moves.builtins, 'open') as mock_open, \
587 mock.patch.object(task_template.TaskTemplate, 'render',
588 side_effect=TypeError) as mock_render:
589 mock_open.side_effect = (
590 io.StringIO(six.text_type('value2: var4')),
591 io.StringIO(six.text_type(self.TASK))
593 with self.assertRaises(exceptions.TaskRenderError):
594 task_parser._render_task('value1: "var3"', 'args_file')
596 mock_open.assert_has_calls([mock.call('args_file'),
597 mock.call('task_file')])
598 mock_render.assert_has_calls(
599 [mock.call(self.TASK, value1='var3', value2='var4')])