f1f09f3ab5
Export trends report with plugin and support report with static libraries. Change-Id: I05bff52c30b50387b7ad880709e3ce09f6f6ae9d
1182 lines
51 KiB
Python
1182 lines
51 KiB
Python
# Copyright 2013: Mirantis Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import datetime as dt
|
|
import json
|
|
import os.path
|
|
import sys
|
|
|
|
import ddt
|
|
import mock
|
|
import six
|
|
|
|
import rally
|
|
from rally import api
|
|
from rally.cli import cliutils
|
|
from rally.cli.commands import task
|
|
from rally.common import yamlutils as yaml
|
|
from rally import consts
|
|
from rally import exceptions
|
|
from tests.unit import fakes
|
|
from tests.unit import test
|
|
|
|
|
|
@ddt.ddt
|
|
class TaskCommandsTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(TaskCommandsTestCase, self).setUp()
|
|
self.task = task.TaskCommands()
|
|
self.fake_api = fakes.FakeAPI()
|
|
|
|
with mock.patch("rally.api.API.check_db_revision"):
|
|
self.real_api = api.API()
|
|
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
def test__load_and_validate_task(self, mock_open):
|
|
input_task = "{'ab': {{test}}}"
|
|
input_args = "{'test': 2}"
|
|
|
|
mock_open.side_effect = [
|
|
mock.mock_open(read_data=input_task).return_value,
|
|
mock.mock_open(read_data="{'test': 1}").return_value
|
|
]
|
|
task_conf = self.task._load_and_validate_task(
|
|
self.real_api, "in_task", args_file="in_args_path")
|
|
self.assertEqual({"ab": 1}, task_conf)
|
|
|
|
mock_open.side_effect = [
|
|
mock.mock_open(read_data=input_task).return_value
|
|
]
|
|
task_conf = self.task._load_and_validate_task(
|
|
self.real_api, "in_task", raw_args=input_args)
|
|
self.assertEqual({"ab": 2}, task_conf)
|
|
|
|
mock_open.side_effect = [
|
|
mock.mock_open(read_data=input_task).return_value,
|
|
mock.mock_open(read_data="{'test': 1}").return_value
|
|
]
|
|
task_conf = self.task._load_and_validate_task(
|
|
self.real_api, "in_task", raw_args=input_args,
|
|
args_file="any_file")
|
|
self.assertEqual({"ab": 2}, task_conf)
|
|
|
|
mock_open.side_effect = [
|
|
mock.mock_open(read_data=input_task).return_value,
|
|
mock.mock_open(read_data="{'test': 1}").return_value
|
|
]
|
|
task_conf = self.task._load_and_validate_task(
|
|
self.real_api, "in_task", raw_args="test=2",
|
|
args_file="any_file")
|
|
self.assertEqual({"ab": 2}, task_conf)
|
|
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
def test__load_task_wrong_task_args_file(self, mock_open):
|
|
|
|
def open_return_value(filename):
|
|
if filename == "in_task":
|
|
return mock.Mock()
|
|
else:
|
|
raise IOError()
|
|
|
|
mock_open.side_effect = open_return_value
|
|
|
|
e = self.assertRaises(task.FailedToLoadTask,
|
|
self.task._load_and_validate_task,
|
|
self.fake_api, task_file="in_task",
|
|
args_file="in_args_path")
|
|
self.assertEqual("Invalid --task-args-file passed:\n\n\t Error "
|
|
"reading in_args_path: ", e.format_message())
|
|
|
|
@mock.patch("rally.cli.commands.task.yaml.safe_load")
|
|
def test__load_task_wrong_input_task_args(self, mock_safe_load):
|
|
mock_safe_load.side_effect = yaml.ParserError("foo")
|
|
# use real file to avoid mocking open
|
|
task_file = __file__
|
|
|
|
e = self.assertRaises(task.FailedToLoadTask,
|
|
self.task._load_and_validate_task, self.real_api,
|
|
task_file, raw_args="{'test': {}")
|
|
self.assertEqual("Invalid --task-args passed:\n\n\t Value has to be "
|
|
"YAML or JSON. Details:\n\nfoo", e.format_message())
|
|
mock_safe_load.assert_called_once_with("{'test': {}")
|
|
|
|
# the case #2
|
|
mock_safe_load.reset_mock()
|
|
e = self.assertRaises(task.FailedToLoadTask,
|
|
self.task._load_and_validate_task, self.real_api,
|
|
task_file, raw_args="[]")
|
|
self.assertEqual("Invalid --task-args passed:\n\n\t Value has to be "
|
|
"YAML or JSON. Details:\n\nfoo", e.format_message())
|
|
mock_safe_load.assert_called_once_with("[]")
|
|
|
|
# the case #3
|
|
mock_safe_load.reset_mock()
|
|
e = self.assertRaises(task.FailedToLoadTask,
|
|
self.task._load_and_validate_task, self.real_api,
|
|
task_file, raw_args="foo")
|
|
self.assertEqual("Invalid --task-args passed:\n\n\t Value has to be "
|
|
"YAML or JSON. Details:\n\nfoo", e.format_message())
|
|
mock_safe_load.assert_called_once_with("foo")
|
|
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
def test__load_task_task_render_raise_exc(self, mock_open):
|
|
mock_open.side_effect = [
|
|
mock.mock_open(read_data="{'test': {{t}}}").return_value
|
|
]
|
|
e = self.assertRaises(task.FailedToLoadTask,
|
|
self.task._load_and_validate_task, self.real_api,
|
|
"in_task")
|
|
self.assertEqual("Invalid --task passed:\n\n\t Failed to render task "
|
|
"template.\n\nPlease specify template task argument: "
|
|
"t", e.format_message())
|
|
|
|
@mock.patch("rally.cli.commands.task.yaml")
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
def test__load_task_task_not_in_yaml(self, mock_open, mock_yaml):
|
|
mock_open.side_effect = [
|
|
mock.mock_open(read_data="{'test': {}").return_value
|
|
]
|
|
mock_yaml.safe_load.side_effect = Exception("ERROR!!!PANIC!!!")
|
|
|
|
e = self.assertRaises(task.FailedToLoadTask,
|
|
self.task._load_and_validate_task, self.fake_api,
|
|
"in_task")
|
|
self.assertEqual("Invalid --task passed:\n\n\t Wrong format of "
|
|
"rendered input task. It should be YAML or JSON. "
|
|
"Details:\n\nERROR!!!PANIC!!!", e.format_message())
|
|
|
|
def test_load_task_including_other_template(self):
|
|
other_template_path = os.path.join(
|
|
os.path.dirname(rally.__file__), os.pardir,
|
|
"samples/tasks/scenarios/dummy/dummy.json")
|
|
input_task = "{%% include \"%s\" %%}" % os.path.basename(
|
|
other_template_path)
|
|
expect = self.task._load_and_validate_task(self.real_api,
|
|
other_template_path)
|
|
|
|
with mock.patch("rally.cli.commands.task.open",
|
|
create=True) as mock_open:
|
|
mock_open.side_effect = [
|
|
mock.mock_open(read_data=input_task).return_value
|
|
]
|
|
input_task_file = os.path.join(
|
|
os.path.dirname(other_template_path), "input_task.json")
|
|
actual = self.task._load_and_validate_task(self.real_api,
|
|
input_task_file)
|
|
self.assertEqual(expect, actual)
|
|
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
def test__load_and_validate_file_failed(self, mock_open):
|
|
mock_open.side_effect = IOError
|
|
|
|
e = self.assertRaises(task.FailedToLoadTask,
|
|
self.task._load_and_validate_task,
|
|
api=self.fake_api, task_file="some_task",
|
|
raw_args="task_args", args_file="task_args_file")
|
|
self.assertEqual(
|
|
"Invalid --task passed:\n\n\t Error reading some_task: ",
|
|
e.format_message())
|
|
|
|
@mock.patch("rally.cli.commands.task.version")
|
|
@mock.patch("rally.cli.commands.task.TaskCommands.use")
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._detailed")
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._load_and_validate_task",
|
|
return_value={"some": "json"})
|
|
def test_start(self, mock__load_and_validate_task, mock__detailed,
|
|
mock_use, mock_version):
|
|
deployment_id = "e0617de9-77d1-4875-9b49-9d5789e29f20"
|
|
task_path = "path_to_config.json"
|
|
fake_task = fakes.FakeTask(uuid="some_new_uuid", tags=["tag"])
|
|
mock__detailed.return_value = 1
|
|
self.fake_api.task.create.return_value = fake_task
|
|
self.fake_api.task.validate.return_value = fakes.FakeTask(
|
|
some="json", uuid="some_uuid", temporary=True)
|
|
|
|
val = self.task.start(self.fake_api, task_path,
|
|
deployment_id, do_use=True)
|
|
self.assertEqual(2, val)
|
|
mock_version.version_string.assert_called_once_with()
|
|
self.fake_api.task.create.assert_called_once_with(
|
|
deployment=deployment_id, tags=None)
|
|
self.fake_api.task.start.assert_called_once_with(
|
|
deployment=deployment_id,
|
|
config=mock__load_and_validate_task.return_value,
|
|
task=fake_task["uuid"],
|
|
abort_on_sla_failure=False)
|
|
mock__load_and_validate_task.assert_called_once_with(
|
|
self.fake_api, task_path, args_file=None, raw_args=None)
|
|
mock_use.assert_called_once_with(self.fake_api, "some_new_uuid")
|
|
mock__detailed.assert_called_once_with(self.fake_api,
|
|
task_id=fake_task["uuid"])
|
|
mock__detailed.return_value = 0
|
|
val1 = self.task.start(self.fake_api, task_path,
|
|
deployment_id, do_use=True)
|
|
self.assertEqual(0, val1)
|
|
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._detailed")
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._load_and_validate_task",
|
|
return_value="some_config")
|
|
def test_start_on_unfinished_deployment(self, mock__load_and_validate_task,
|
|
mock__detailed):
|
|
deployment_id = "e0617de9-77d1-4875-9b49-9d5789e29f20"
|
|
deployment_name = "xxx_name"
|
|
task_path = "path_to_config.json"
|
|
fake_task = fakes.FakeTask(uuid="some_new_uuid", tag="tag")
|
|
self.fake_api.task.create.return_value = fake_task
|
|
|
|
exc = exceptions.DeploymentNotFinishedStatus(
|
|
name=deployment_name,
|
|
uuid=deployment_id,
|
|
status=consts.DeployStatus.DEPLOY_INIT)
|
|
self.fake_api.task.create.side_effect = exc
|
|
self.assertEqual(1, self.task.start(self.fake_api, task_path,
|
|
deployment="any",
|
|
tags=["some_tag"]))
|
|
self.assertFalse(mock__detailed.called)
|
|
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._detailed")
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._load_and_validate_task",
|
|
return_value="some_config")
|
|
def test_start_with_task_args(self, mock__load_and_validate_task,
|
|
mock__detailed):
|
|
fake_task = fakes.FakeTask(uuid="new_uuid", tags=["some_tag"])
|
|
self.fake_api.task.create.return_value = fakes.FakeTask(
|
|
uuid="new_uuid", tags=["some_tag"])
|
|
self.fake_api.task.validate.return_value = fakes.FakeTask(
|
|
uuid="some_id")
|
|
|
|
task_path = "path_to_config.json"
|
|
task_args = "task_args"
|
|
task_args_file = "task_args_file"
|
|
self.task.start(self.fake_api, task_path, deployment="any",
|
|
task_args=task_args, task_args_file=task_args_file,
|
|
tags=["some_tag"])
|
|
|
|
mock__load_and_validate_task.assert_called_once_with(
|
|
self.fake_api, task_path, raw_args=task_args,
|
|
args_file=task_args_file)
|
|
|
|
self.fake_api.task.start.assert_called_once_with(
|
|
deployment="any",
|
|
config=mock__load_and_validate_task.return_value,
|
|
task=fake_task["uuid"],
|
|
abort_on_sla_failure=False)
|
|
mock__detailed.assert_called_once_with(
|
|
self.fake_api,
|
|
task_id=fake_task["uuid"])
|
|
self.fake_api.task.create.assert_called_once_with(
|
|
deployment="any", tags=["some_tag"])
|
|
|
|
@mock.patch("rally.cli.commands.task.envutils.get_global")
|
|
def test_start_no_deployment_id(self, mock_get_global):
|
|
mock_get_global.side_effect = exceptions.InvalidArgumentsException
|
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
|
self.task.start, "path_to_config.json", None)
|
|
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._detailed")
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._load_and_validate_task")
|
|
def test_start_invalid_task(self, mock__load_and_validate_task,
|
|
mock__detailed):
|
|
task_obj = fakes.FakeTask(temporary=False, tag="tag", uuid="uuid")
|
|
self.fake_api.task.create.return_value = task_obj
|
|
exc = exceptions.InvalidTaskException("foo")
|
|
|
|
mock__load_and_validate_task.side_effect = exc
|
|
|
|
self.assertRaises(exceptions.InvalidTaskException,
|
|
self.task.start, self.fake_api, "task_path",
|
|
"deployment", tags=["tag"])
|
|
|
|
self.assertFalse(self.fake_api.task.create.called)
|
|
self.assertFalse(self.fake_api.task.start.called)
|
|
|
|
# the case 2
|
|
task_cfg = {"some": "json"}
|
|
mock__load_and_validate_task.side_effect = (task_cfg, )
|
|
self.fake_api.task.start.side_effect = KeyError()
|
|
|
|
self.assertRaises(KeyError,
|
|
self.task.start, self.fake_api, "task_path",
|
|
"deployment", tags=["tag"])
|
|
|
|
self.fake_api.task.create.assert_called_once_with(
|
|
deployment="deployment", tags=["tag"])
|
|
|
|
self.fake_api.task.start.assert_called_once_with(
|
|
deployment="deployment", config=task_cfg,
|
|
task=task_obj["uuid"],
|
|
abort_on_sla_failure=False)
|
|
|
|
self.assertFalse(mock__detailed.called)
|
|
|
|
def test_abort(self):
|
|
test_uuid = "17860c43-2274-498d-8669-448eff7b073f"
|
|
self.task.abort(self.fake_api, test_uuid)
|
|
self.fake_api.task.abort.assert_called_once_with(
|
|
task_uuid=test_uuid, soft=False, wait=True)
|
|
|
|
@mock.patch("rally.cli.commands.task.envutils.get_global")
|
|
def test_abort_no_task_id(self, mock_get_global):
|
|
mock_get_global.side_effect = exceptions.InvalidArgumentsException
|
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
|
self.task.abort, self.fake_api, None)
|
|
|
|
def test_status(self):
|
|
test_uuid = "a3e7cefb-bec2-4802-89f6-410cc31f71af"
|
|
value = {"task_id": "task", "status": "status"}
|
|
self.fake_api.task.get.return_value = value
|
|
self.task.status(self.fake_api, test_uuid)
|
|
self.fake_api.task.get.assert_called_once_with(task_id=test_uuid)
|
|
|
|
@mock.patch("rally.cli.commands.task.envutils.get_global")
|
|
def test_status_no_task_id(self, mock_get_global):
|
|
mock_get_global.side_effect = exceptions.InvalidArgumentsException
|
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
|
self.task.status, None)
|
|
|
|
@ddt.data({"iterations_data": False, "has_output": True,
|
|
"filters": None},
|
|
{"iterations_data": True, "has_output": False,
|
|
"filters": ["scenario=fake_name", "sla_failures"]})
|
|
@ddt.unpack
|
|
def test_detailed(self, iterations_data, has_output, filters):
|
|
test_uuid = "c0d874d4-7195-4fd5-8688-abe82bfad36f"
|
|
detailed_value = {
|
|
"id": "task", "uuid": test_uuid,
|
|
"pass_sla": False, "status": "finished",
|
|
"subtasks": [{"workloads": [{
|
|
"name": "fake_name", "position": "fake_pos",
|
|
"args": "args", "contexts": "context", "sla": "sla",
|
|
"runner": "runner", "hooks": [],
|
|
"statistics": {
|
|
"durations": {
|
|
"atomics": [
|
|
{
|
|
"name": "foo",
|
|
"display_name": "foo (x2)",
|
|
"count_per_iteration": 2,
|
|
"children": [
|
|
{"name": "inner_foo",
|
|
"display_name": "inner_foo",
|
|
"count_per_iteration": 1,
|
|
"children": [],
|
|
"data": {
|
|
"min": 1,
|
|
"median": 2,
|
|
"90%ile": 1.5,
|
|
"95%ile": 1.6,
|
|
"max": 3,
|
|
"avg": 1.4,
|
|
"success": 3,
|
|
"iteration_count": 3}
|
|
}
|
|
],
|
|
"data": {
|
|
"min": 1,
|
|
"median": 2,
|
|
"90%ile": 1.5,
|
|
"95%ile": 1.6,
|
|
"max": 3,
|
|
"avg": 1.4,
|
|
"success": 3,
|
|
"iteration_count": 3}},
|
|
{
|
|
"name": "bar",
|
|
"display_name": "bar",
|
|
"count_per_iteration": 1,
|
|
"children": [],
|
|
"data": {
|
|
"min": 1.1,
|
|
"median": 2.2,
|
|
"90%ile": 1.6,
|
|
"95%ile": 1.65,
|
|
"max": 3,
|
|
"avg": 1.5,
|
|
"success": 3,
|
|
"iteration_count": 3}
|
|
}],
|
|
"total": {
|
|
"name": "total",
|
|
"display_name": "bar",
|
|
"count_per_iteration": 1,
|
|
"children": [],
|
|
"data": {
|
|
"min": 1,
|
|
"median": 2.1,
|
|
"90%ile": 1.55,
|
|
"95%ile": 1.62,
|
|
"max": 3,
|
|
"avg": 1.45,
|
|
"success": 6,
|
|
"iteration_count": 6}}}},
|
|
"load_duration": 3.2,
|
|
"full_duration": 3.5,
|
|
"total_iteration_count": 4,
|
|
"data": [
|
|
{
|
|
"duration": 0.9,
|
|
"idle_duration": 0.1,
|
|
"output": {"additive": [], "complete": []},
|
|
"atomic_actions": [
|
|
{"name": "foo", "started_at": 0.0,
|
|
"finished_at": 0.6, "children": []},
|
|
{"name": "bar", "started_at": 0.6,
|
|
"finished_at": 1.3, "children": []}
|
|
],
|
|
"error": ["type", "message", "traceback"]
|
|
},
|
|
{
|
|
"duration": 1.2,
|
|
"idle_duration": 0.3,
|
|
"output": {"additive": [], "complete": []},
|
|
"atomic_actions": [
|
|
{"name": "foo", "started_at": 0.0,
|
|
"finished_at": 0.6, "children": []},
|
|
{"name": "bar", "started_at": 0.6,
|
|
"finished_at": 1.3, "children": []}
|
|
],
|
|
"error": ["type", "message", "traceback"]
|
|
},
|
|
{
|
|
"duration": 0.7,
|
|
"idle_duration": 0.5,
|
|
"output": {
|
|
"additive": [
|
|
{"data": [("foo", 0.6), ("bar", 0.7)],
|
|
"title": "Scenario output",
|
|
"description": "",
|
|
"chart_plugin": "StackedArea"}
|
|
],
|
|
"complete": []
|
|
},
|
|
"atomic_actions": [
|
|
{"name": "foo", "started_at": 0.0,
|
|
"finished_at": 0.6, "children": []},
|
|
{"name": "bar", "started_at": 0.6,
|
|
"finished_at": 1.3, "children": []}
|
|
],
|
|
"error": ["type", "message", "traceback"]
|
|
},
|
|
{
|
|
"duration": 0.5,
|
|
"idle_duration": 0.5,
|
|
"atomic_actions": [
|
|
{"name": "foo", "started_at": 0.0,
|
|
"finished_at": 0.6, "children": []},
|
|
{"name": "bar", "started_at": 0.6,
|
|
"finished_at": 1.3, "children": []}
|
|
],
|
|
"error": ["type", "message", "traceback"]
|
|
}],
|
|
}]}]}
|
|
if has_output:
|
|
detailed_value["subtasks"][0]["workloads"][0]["output"] = {
|
|
"additive": [], "complete": []}
|
|
self.fake_api.task.get.return_value = detailed_value
|
|
self.task.detailed(self.fake_api, test_uuid,
|
|
iterations_data=iterations_data,
|
|
filters=filters)
|
|
self.fake_api.task.get.assert_called_once_with(
|
|
task_id=test_uuid, detailed=True)
|
|
|
|
@mock.patch("rally.cli.commands.task.sys.stdout")
|
|
@mock.patch("rally.cli.commands.task.logging")
|
|
@ddt.data({"debug": True},
|
|
{"debug": False})
|
|
@ddt.unpack
|
|
def test_detailed_task_failed(self, mock_logging, mock_stdout, debug):
|
|
test_uuid = "test_task_id"
|
|
value = {
|
|
"id": "task",
|
|
"uuid": test_uuid,
|
|
"status": consts.TaskStatus.CRASHED,
|
|
"results": [],
|
|
"validation_result": {"etype": "error_type",
|
|
"msg": "error_message",
|
|
"trace": "error_traceback"}
|
|
}
|
|
self.fake_api.task.get.return_value = value
|
|
|
|
mock_logging.is_debug.return_value = debug
|
|
self.task.detailed(self.fake_api, test_uuid)
|
|
if debug:
|
|
expected_calls = [
|
|
mock.call("Task test_task_id: crashed"),
|
|
mock.call("%s" % value["validation_result"]["trace"])]
|
|
mock_stdout.write.assert_has_calls(expected_calls, any_order=True)
|
|
else:
|
|
expected_calls = [
|
|
mock.call("Task test_task_id: crashed"),
|
|
mock.call("%s" % value["validation_result"]["etype"]),
|
|
mock.call("%s" % value["validation_result"]["msg"]),
|
|
mock.call("\nFor more details run:\n"
|
|
"rally -d task detailed %s" % test_uuid)]
|
|
mock_stdout.write.assert_has_calls(expected_calls, any_order=True)
|
|
|
|
@mock.patch("rally.cli.commands.task.sys.stdout")
|
|
def test_detailed_task_status_not_in_finished_abort(self, mock_stdout):
|
|
test_uuid = "test_task_id"
|
|
value = {
|
|
"id": "task",
|
|
"uuid": test_uuid,
|
|
"status": consts.TaskStatus.INIT,
|
|
"results": []
|
|
}
|
|
self.fake_api.task.get.return_value = value
|
|
self.task.detailed(self.fake_api, test_uuid)
|
|
expected_calls = [mock.call("Task test_task_id: init"),
|
|
mock.call("\nThe task test_task_id marked as "
|
|
"'init'. Results available when it "
|
|
"is 'finished'.")]
|
|
mock_stdout.write.assert_has_calls(expected_calls, any_order=True)
|
|
|
|
@mock.patch("rally.cli.commands.task.envutils.get_global")
|
|
def test_detailed_no_task_id(self, mock_get_global):
|
|
mock_get_global.side_effect = exceptions.InvalidArgumentsException
|
|
self.assertRaises(exceptions.InvalidArgumentsException,
|
|
self.task.detailed, None)
|
|
|
|
def test_detailed_wrong_id(self):
|
|
test_uuid = "eb290c30-38d8-4c8f-bbcc-fc8f74b004ae"
|
|
self.fake_api.task.get.side_effect = None
|
|
self.task.detailed(self.fake_api, test_uuid)
|
|
self.fake_api.task.get.assert_called_once_with(
|
|
task_id=test_uuid, detailed=True)
|
|
|
|
def _make_task(self, status=None, data=None):
|
|
return {
|
|
"status": status or consts.TaskStatus.FINISHED,
|
|
"subtasks": [{"workloads": [{
|
|
"full_duration": 1, "load_duration": 2,
|
|
"created_at": "2017-09-27T07:22:55",
|
|
"name": "Foo.bar", "description": "descr",
|
|
"position": 2,
|
|
"args": {"key1": "value1"},
|
|
"runner_type": "rruunneerr",
|
|
"runner": {"arg1": "args2"},
|
|
"hooks": [],
|
|
"sla": {"failure_rate": {"max": 0}},
|
|
"sla_results": {"sla": [{"success": True}]},
|
|
"contexts": {"users": {}},
|
|
"data": data or []}]}]}
|
|
|
|
@mock.patch("rally.cli.commands.task.json.dumps")
|
|
def test_results(self, mock_json_dumps):
|
|
task_id = "foo_task_id"
|
|
|
|
task_obj = self._make_task(data=[{"atomic_actions": {"foo": 1.1}}])
|
|
task_obj["subtasks"][0]["workloads"][0]["hooks"] = [{
|
|
"config": {
|
|
"action": ("foo", "arg"),
|
|
"trigger": ("bar", "arg2")
|
|
},
|
|
"summary": {"success": 1}}
|
|
]
|
|
|
|
def fix_r(workload):
|
|
cfg = workload["runner"]
|
|
cfg["type"] = workload["runner_type"]
|
|
return cfg
|
|
|
|
result = map(
|
|
lambda x: {
|
|
"key": {"kw": {"sla": x["sla"],
|
|
"args": x["args"],
|
|
"context": x["contexts"],
|
|
"runner": fix_r(x),
|
|
"hooks": [{"description": "",
|
|
"name": "foo",
|
|
"args": "arg",
|
|
"trigger": {"name": "bar",
|
|
"args": "arg2"}}]},
|
|
"pos": x["position"],
|
|
"name": x["name"],
|
|
"description": x["description"]},
|
|
"result": x["data"],
|
|
"load_duration": x["load_duration"],
|
|
"full_duration": x["full_duration"],
|
|
"created_at": dt.datetime.strptime(
|
|
x["created_at"], "%Y-%m-%dT%H:%M:%S").strftime(
|
|
"%Y-%d-%mT%H:%M:%S"),
|
|
"hooks": [{
|
|
"config": {"description": "",
|
|
"name": "foo",
|
|
"args": "arg",
|
|
"trigger": {"name": "bar", "args": "arg2"}},
|
|
"summary": {"success": 1}}],
|
|
"sla": x["sla_results"]["sla"]},
|
|
task_obj["subtasks"][0]["workloads"])
|
|
|
|
self.fake_api.task.get.return_value = task_obj
|
|
|
|
self.assertIsNone(self.task.results(self.fake_api, task_id))
|
|
self.assertEqual(1, mock_json_dumps.call_count)
|
|
self.assertEqual(1, len(mock_json_dumps.call_args[0]))
|
|
self.assertSequenceEqual(result, mock_json_dumps.call_args[0][0])
|
|
self.assertEqual({"sort_keys": False, "indent": 4},
|
|
mock_json_dumps.call_args[1])
|
|
self.fake_api.task.get.assert_called_once_with(
|
|
task_id=task_id, detailed=True)
|
|
|
|
@mock.patch("rally.cli.commands.task.sys.stdout")
|
|
def test_results_no_data(self, mock_stdout):
|
|
task_id = "foo"
|
|
self.fake_api.task.get.return_value = self._make_task(
|
|
status=consts.TaskStatus.CRASHED)
|
|
|
|
self.assertEqual(1, self.task.results(self.fake_api, task_id))
|
|
|
|
self.fake_api.task.get.assert_called_once_with(
|
|
task_id=task_id, detailed=True)
|
|
|
|
expected_out = ("Task status is %s. Results "
|
|
"available when it is one of %s.") % (
|
|
consts.TaskStatus.CRASHED,
|
|
", ".join((consts.TaskStatus.FINISHED,
|
|
consts.TaskStatus.ABORTED)))
|
|
mock_stdout.write.assert_has_calls([mock.call(expected_out)])
|
|
|
|
def test_trends(self):
|
|
self.task.export = mock.MagicMock()
|
|
self.task.trends(self.fake_api,
|
|
tasks=["uuid"],
|
|
out="output.html")
|
|
self.task.export.assert_called_once_with(
|
|
self.fake_api, tasks=["uuid"], output_type="trends-html",
|
|
output_dest="output.html", open_it=False)
|
|
|
|
def test_trends_no_tasks_given(self):
|
|
ret = self.task.trends(self.fake_api, tasks=[],
|
|
out="output.html", out_format="html")
|
|
self.assertEqual(1, ret)
|
|
|
|
def test_report(self):
|
|
self.task.export = mock.MagicMock()
|
|
self.task.report(self.fake_api, tasks="uuid",
|
|
out="out", open_it=False, out_format="junit-xml")
|
|
self.task.export.assert_called_once_with(
|
|
self.fake_api, tasks="uuid", output_type="junit-xml",
|
|
output_dest="out", open_it=False, deployment=None
|
|
)
|
|
|
|
@mock.patch("rally.cli.commands.task.cliutils.print_list")
|
|
@mock.patch("rally.cli.commands.task.envutils.get_global",
|
|
return_value="123456789")
|
|
def test_list(self, mock_get_global, mock_print_list):
|
|
self.fake_api.task.list.return_value = [
|
|
{"uuid": "a",
|
|
"created_at": "2007-01-01T00:00:01",
|
|
"updated_at": "2007-01-01T00:00:03",
|
|
"status": consts.TaskStatus.RUNNING,
|
|
"tags": ["d"],
|
|
"deployment_name": "some_name"}]
|
|
self.task.list(self.fake_api, status="running")
|
|
self.fake_api.task.list.assert_called_once_with(
|
|
deployment=mock_get_global.return_value,
|
|
status=consts.TaskStatus.RUNNING)
|
|
|
|
headers = ["UUID", "Deployment name", "Created at", "Load duration",
|
|
"Status", "Tag(s)"]
|
|
|
|
mock_print_list.assert_called_once_with(
|
|
self.fake_api.task.list.return_value, fields=headers,
|
|
normalize_field_names=True,
|
|
sortby_index=headers.index("Created at"),
|
|
formatters=mock.ANY)
|
|
|
|
@mock.patch("rally.cli.commands.task.envutils.get_global",
|
|
return_value="123456789")
|
|
def test_list_uuids_only(self, mock_get_global):
|
|
self.fake_api.task.list.return_value = [
|
|
{"uuid": "a",
|
|
"created_at": "2007-01-01T00:00:01",
|
|
"updated_at": "2007-01-01T00:00:03",
|
|
"status": consts.TaskStatus.RUNNING,
|
|
"tags": ["d"],
|
|
"deployment_name": "some_name"}]
|
|
out = six.StringIO()
|
|
with mock.patch.object(sys, "stdout", new=out):
|
|
self.task.list(self.fake_api, status="running", uuids_only=True)
|
|
self.assertEqual("a\n", out.getvalue())
|
|
self.fake_api.task.list.assert_called_once_with(
|
|
deployment=mock_get_global.return_value,
|
|
status=consts.TaskStatus.RUNNING)
|
|
|
|
def test_list_wrong_status(self):
|
|
self.assertEqual(1, self.task.list(self.fake_api, deployment="fake",
|
|
status="wrong non existing status"))
|
|
|
|
def test_list_no_results(self):
|
|
self.fake_api.task.list.return_value = []
|
|
self.assertIsNone(self.task.list(self.fake_api, deployment="fake",
|
|
all_deployments=True))
|
|
self.fake_api.task.list.assert_called_once_with()
|
|
self.fake_api.task.list.reset_mock()
|
|
|
|
self.assertIsNone(self.task.list(self.fake_api, deployment="d",
|
|
status=consts.TaskStatus.RUNNING))
|
|
self.fake_api.task.list.assert_called_once_with(
|
|
deployment="d", status=consts.TaskStatus.RUNNING)
|
|
|
|
@mock.patch("rally.cli.commands.task.envutils.get_global",
|
|
return_value="123456789")
|
|
def test_list_output(self, mock_get_global):
|
|
self.fake_api.task.list.return_value = [
|
|
{"uuid": "UUID-1",
|
|
"created_at": "2007-01-01T00:00:01",
|
|
"task_duration": 0.0000009,
|
|
"status": consts.TaskStatus.INIT,
|
|
"tags": [],
|
|
"deployment_name": "some_name"},
|
|
{"uuid": "UUID-2",
|
|
"created_at": "2007-02-01T00:00:01",
|
|
"task_duration": 123.99992,
|
|
"status": consts.TaskStatus.FINISHED,
|
|
"tags": ["tag-1", "tag-2"],
|
|
"deployment_name": "some_name"}]
|
|
|
|
# It is a hard task to mock default value of function argument, so we
|
|
# need to apply this workaround
|
|
original_print_list = cliutils.print_list
|
|
print_list_calls = []
|
|
|
|
def print_list(*args, **kwargs):
|
|
print_list_calls.append(six.StringIO())
|
|
kwargs["out"] = print_list_calls[-1]
|
|
original_print_list(*args, **kwargs)
|
|
|
|
with mock.patch.object(task.cliutils, "print_list",
|
|
new=print_list):
|
|
self.task.list(self.fake_api, status="running")
|
|
|
|
self.assertEqual(1, len(print_list_calls))
|
|
|
|
self.assertEqual(
|
|
"+--------+-----------------+---------------------"
|
|
"+---------------+----------+------------------+\n"
|
|
"| UUID | Deployment name | Created at "
|
|
"| Load duration | Status | Tag(s) |\n"
|
|
"+--------+-----------------+---------------------"
|
|
"+---------------+----------+------------------+\n"
|
|
"| UUID-1 | some_name | 2007-01-01 00:00:01 "
|
|
"| 0.0 | init | |\n"
|
|
"| UUID-2 | some_name | 2007-02-01 00:00:01 "
|
|
"| 124.0 | finished | 'tag-1', 'tag-2' |\n"
|
|
"+--------+-----------------+---------------------"
|
|
"+---------------+----------+------------------+\n",
|
|
print_list_calls[0].getvalue())
|
|
|
|
def test_delete(self):
|
|
task_uuid = "8dcb9c5e-d60b-4022-8975-b5987c7833f7"
|
|
force = False
|
|
self.task.delete(self.fake_api, task_uuid, force=force)
|
|
self.fake_api.task.delete.assert_called_once_with(
|
|
task_uuid=task_uuid, force=force)
|
|
|
|
def test_delete_multiple_uuid(self):
|
|
task_uuids = ["4bf35b06-5916-484f-9547-12dce94902b7",
|
|
"52cad69d-d3e4-47e1-b445-dec9c5858fe8",
|
|
"6a3cb11c-ac75-41e7-8ae7-935732bfb48f",
|
|
"018af931-0e5a-40d5-9d6f-b13f4a3a09fc"]
|
|
force = False
|
|
self.task.delete(self.fake_api, task_uuids, force=force)
|
|
self.assertTrue(
|
|
self.fake_api.task.delete.call_count == len(task_uuids))
|
|
expected_calls = [mock.call(task_uuid=task_uuid,
|
|
force=force) for task_uuid in task_uuids]
|
|
self.assertTrue(self.fake_api.task.delete.mock_calls == expected_calls)
|
|
|
|
@mock.patch("rally.cli.commands.task.cliutils.print_list")
|
|
def test_sla_check(self, mock_print_list):
|
|
task_obj = self._make_task()
|
|
task_obj["subtasks"][0]["workloads"][0]["sla_results"]["sla"] = [
|
|
{"benchmark": "KeystoneBasic.create_user",
|
|
"criterion": "max_seconds_per_iteration",
|
|
"pos": 0, "success": False, "detail": "Max foo, actually bar"}]
|
|
|
|
self.fake_api.task.get.return_value = task_obj
|
|
result = self.task.sla_check(self.fake_api, task_id="fake_task_id")
|
|
self.assertEqual(1, result)
|
|
self.fake_api.task.get.assert_called_with(
|
|
task_id="fake_task_id", detailed=True)
|
|
|
|
task_obj["subtasks"][0]["workloads"][0]["sla_results"]["sla"][0][
|
|
"success"] = True
|
|
|
|
result = self.task.sla_check(self.fake_api, task_id="fake_task_id",
|
|
tojson=True)
|
|
self.assertEqual(0, result)
|
|
|
|
@mock.patch("rally.cli.commands.task.os.path.isfile", return_value=True)
|
|
@mock.patch("rally.cli.commands.task.open",
|
|
side_effect=mock.mock_open(read_data="{\"some\": \"json\"}"),
|
|
create=True)
|
|
def test_validate(self, mock_open, mock_os_path_isfile):
|
|
self.fake_api.task.render_template = self.real_api.task.render_template
|
|
|
|
self.task.validate(self.fake_api, "path_to_config.json", "fake_id")
|
|
|
|
self.fake_api.task.validate.assert_called_once_with(
|
|
deployment="fake_id", config={"some": "json"})
|
|
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._load_and_validate_task",
|
|
side_effect=task.FailedToLoadTask)
|
|
def test_validate_failed_to_load_task(self, mock__load_and_validate_task):
|
|
args = "args"
|
|
args_file = "args_file"
|
|
|
|
mock__load_and_validate_task.side_effect = KeyError("foo")
|
|
|
|
self.assertRaises(KeyError, self.task.validate, self.real_api,
|
|
"path_to_task", "fake_deployment_id",
|
|
task_args=args, task_args_file=args_file)
|
|
self.assertFalse(self.fake_api.task.validate.called)
|
|
|
|
mock__load_and_validate_task.assert_called_once_with(
|
|
self.real_api, "path_to_task", raw_args=args, args_file=args_file)
|
|
|
|
@mock.patch("rally.cli.commands.task.TaskCommands._load_and_validate_task")
|
|
def test_validate_invalid(self, mock__load_and_validate_task):
|
|
exc = exceptions.InvalidTaskException("foo")
|
|
self.fake_api.task.validate.side_effect = exc
|
|
self.assertRaises(exceptions.InvalidTaskException,
|
|
self.task.validate, self.fake_api, "path_to_task",
|
|
"deployment")
|
|
self.fake_api.task.validate.assert_called_once_with(
|
|
deployment="deployment",
|
|
config=mock__load_and_validate_task.return_value)
|
|
|
|
@mock.patch("rally.common.fileutils._rewrite_env_file")
|
|
def test_use(self, mock__rewrite_env_file):
|
|
task_id = "80422553-5774-44bd-98ac-38bd8c7a0feb"
|
|
self.task.use(self.fake_api, task_id)
|
|
mock__rewrite_env_file.assert_called_once_with(
|
|
os.path.expanduser("~/.rally/globals"),
|
|
["RALLY_TASK=%s\n" % task_id])
|
|
|
|
def test_use_not_found(self):
|
|
task_id = "ddc3f8ba-082a-496d-b18f-72cdf5c10a14"
|
|
exc = exceptions.DBRecordNotFound(criteria="uuid: %s" % task_id,
|
|
table="tasks")
|
|
self.fake_api.task.get.side_effect = exc
|
|
self.assertRaises(exceptions.DBRecordNotFound, self.task.use,
|
|
self.fake_api, task_id)
|
|
|
|
@mock.patch("rally.cli.commands.task.os.path")
|
|
@mock.patch("rally.cli.commands.task.webbrowser.open_new_tab")
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
@mock.patch("rally.cli.commands.task.print")
|
|
def test_export(self, mock_print, mock_open, mock_open_new_tab,
|
|
mock_path):
|
|
|
|
# file
|
|
self.fake_api.task.export.return_value = {
|
|
"files": {"output_dest": "content"}, "open": "output_dest"}
|
|
mock_path.exists.side_effect = [False, True, False]
|
|
mock_path.expanduser.return_value = "output_file"
|
|
mock_path.realpath.return_value = "real_path"
|
|
mock_fd = mock.mock_open()
|
|
mock_open.side_effect = mock_fd
|
|
self.task._load_task_results_file = mock.MagicMock(
|
|
return_value=[{"task": "task_1"}, {"task": "task2"}])
|
|
|
|
self.task.export(self.fake_api, tasks=["uuid", "file"],
|
|
output_type="json", output_dest="output_dest",
|
|
open_it=True)
|
|
|
|
self.fake_api.task.export.assert_called_once_with(
|
|
tasks=["uuid"] + self.task._load_task_results_file.return_value,
|
|
output_type="json",
|
|
output_dest="output_dest"
|
|
)
|
|
mock_open.assert_called_once_with("output_file", "w+")
|
|
mock_fd.return_value.write.assert_called_once_with("content")
|
|
|
|
# print
|
|
self.fake_api.task.export.reset_mock()
|
|
self.fake_api.task.export.return_value = {"print": "content"}
|
|
self.task.export(self.fake_api, tasks="uuid", output_type="json")
|
|
self.fake_api.task.export.assert_called_once_with(
|
|
tasks=["uuid"],
|
|
output_type="json", output_dest=None
|
|
)
|
|
mock_print.assert_called_once_with("content")
|
|
|
|
@mock.patch("rally.cli.commands.task.sys.stdout")
|
|
@ddt.data({"error_type": "test_no_trace_type",
|
|
"error_message": "no_trace_error_message",
|
|
"error_traceback": None,
|
|
},
|
|
{"error_type": "test_error_type",
|
|
"error_message": "test_error_message",
|
|
"error_traceback": "test\nerror\ntraceback",
|
|
})
|
|
@ddt.unpack
|
|
def test_show_task_errors_no_trace(self, mock_stdout,
|
|
error_type, error_message,
|
|
error_traceback=None):
|
|
test_uuid = "test_task_id"
|
|
error_data = [error_type, error_message]
|
|
if error_traceback:
|
|
error_data.append(error_traceback)
|
|
self.fake_api.task.get.return_value = {
|
|
"id": "task",
|
|
"uuid": test_uuid,
|
|
"status": "finished",
|
|
"pass_sla": True,
|
|
"subtasks": [{"workloads": [{
|
|
"name": "fake_name",
|
|
"position": "fake_pos",
|
|
"args": {}, "runner_type": "foo",
|
|
"runner": {}, "contexts": {}, "sla": {},
|
|
"hooks": {},
|
|
"load_duration": 3.2,
|
|
"full_duration": 3.5,
|
|
"statistics": {
|
|
"durations": {
|
|
"atomics": [
|
|
{
|
|
"name": "foo",
|
|
"display_name": "foo (x2)",
|
|
"count_per_iteration": 2,
|
|
"children": [],
|
|
"data": {
|
|
"min": 1,
|
|
"median": 2,
|
|
"90%ile": 1.5,
|
|
"95%ile": 1.6,
|
|
"max": 3,
|
|
"avg": 1.4,
|
|
"success": 3,
|
|
"iteration_count": 3}},
|
|
{
|
|
"name": "bar",
|
|
"display_name": "bar",
|
|
"count_per_iteration": 1,
|
|
"children": [],
|
|
"data": {
|
|
"min": 1.1,
|
|
"median": 2.2,
|
|
"90%ile": 1.6,
|
|
"95%ile": 1.65,
|
|
"max": 3,
|
|
"avg": 1.5,
|
|
"success": 3,
|
|
"iteration_count": 3}
|
|
}],
|
|
"total": {
|
|
"name": "total",
|
|
"display_name": "bar",
|
|
"count_per_iteration": 1,
|
|
"children": [],
|
|
"data": {
|
|
"min": 1,
|
|
"median": 2.1,
|
|
"90%ile": 1.55,
|
|
"95%ile": 1.62,
|
|
"max": 3,
|
|
"avg": 1.45,
|
|
"success": 6,
|
|
"iteration_count": 6}}}
|
|
},
|
|
"total_iteration_count": 1,
|
|
"total_iteration_failed": 1,
|
|
"data": [
|
|
{"duration": 0.9,
|
|
"idle_duration": 0.1,
|
|
"output": {"additive": [], "complete": []},
|
|
"atomic_actions": {"foo": 0.6, "bar": 0.7},
|
|
"error": error_data
|
|
},
|
|
]},
|
|
]}],
|
|
"validation_result": json.dumps([error_type, error_message,
|
|
error_traceback])
|
|
}
|
|
self.task.detailed(self.fake_api, test_uuid)
|
|
self.fake_api.task.get.assert_called_once_with(
|
|
task_id=test_uuid, detailed=True)
|
|
mock_stdout.write.assert_has_calls([
|
|
mock.call(error_traceback or "No traceback available.")
|
|
], any_order=False)
|
|
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
@mock.patch("rally.cli.commands.task.json.loads")
|
|
@mock.patch("rally.cli.commands.task.jsonschema.validate",
|
|
return_value=None)
|
|
def test__load_task_results_file(self, mock_validate, mock_loads,
|
|
mock_open):
|
|
task_file = "/tmp/task.json"
|
|
workload = {
|
|
"uuid": "n/a",
|
|
"full_duration": 2, "load_duration": 1,
|
|
"created_at": "2017-07-01T07:03:01",
|
|
"updated_at": "2017-07-01T07:03:03",
|
|
"total_iteration_count": 2,
|
|
"failed_iteration_count": 1,
|
|
"min_duration": 3,
|
|
"max_duration": 5,
|
|
"start_time": 1,
|
|
"name": "Foo.bar", "description": "descr",
|
|
"position": 2,
|
|
"args": {"key1": "value1"},
|
|
"runner_type": "constant",
|
|
"runner": {"time": 3},
|
|
"hooks": [{"config": {
|
|
"description": "descr",
|
|
"action": ("foo", {"arg1": "v1"}),
|
|
"trigger": ("t", {"a2", "v2"})}}],
|
|
"pass_sla": True,
|
|
"sla": {"failure_rate": {"max": 0}},
|
|
"sla_results": {"sla": [{"success": True}]},
|
|
"contexts": {"users": {}},
|
|
"contexts_results": [],
|
|
"data": [{"timestamp": 1, "atomic_actions": {"foo": 1.0,
|
|
"bar": 1.0},
|
|
"duration": 5, "idle_duration": 0, "error": [{}]},
|
|
{"timestamp": 2, "atomic_actions": {"bar": 1.1},
|
|
"duration": 3, "idle_duration": 0, "error": []}],
|
|
"statistics": {"durations": mock.ANY}
|
|
}
|
|
|
|
results = [{
|
|
"hooks": [{
|
|
"config": {
|
|
"name": "foo",
|
|
"args": {"arg1": "v1"},
|
|
"description": "descr",
|
|
"trigger": {"name": "t", "args": {"a2", "v2"}}}}],
|
|
"key": {
|
|
"name": workload["name"],
|
|
"description": workload["description"],
|
|
"pos": workload["position"],
|
|
"kw": {
|
|
"args": workload["args"],
|
|
"runner": {"type": "constant", "time": 3},
|
|
"hooks": [{
|
|
"name": "foo",
|
|
"args": {"arg1": "v1"},
|
|
"description": "descr",
|
|
"trigger": {"name": "t", "args": {"a2", "v2"}}}],
|
|
"sla": workload["sla"],
|
|
"context": workload["contexts"]}},
|
|
"sla": workload["sla_results"]["sla"],
|
|
"result": workload["data"],
|
|
"full_duration": workload["full_duration"],
|
|
"load_duration": workload["load_duration"],
|
|
"created_at": "2017-01-07T07:03:01"}
|
|
]
|
|
mock_loads.return_value = results
|
|
ret = self.task._load_task_results_file(self.fake_api, task_file)
|
|
self.assertEqual([{
|
|
"version": 2,
|
|
"title": "Task loaded from a file.",
|
|
"description": "Auto-ported from task format V1.",
|
|
"uuid": "n/a",
|
|
"env_uuid": "n/a",
|
|
"env_name": "n/a",
|
|
"status": "finished",
|
|
"tags": [],
|
|
"subtasks": [{
|
|
"title": "A SubTask",
|
|
"description": "",
|
|
"workloads": [workload]}]}], ret)
|
|
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
@mock.patch("rally.cli.commands.task.json.loads")
|
|
@mock.patch("rally.cli.commands.task.jsonschema.validate")
|
|
def test__load_task_new_results_file(self, mock_validate,
|
|
mock_loads, mock_open):
|
|
task_file = "/tmp/task.json"
|
|
results = {
|
|
"tasks": [{
|
|
"env_uuid": "env-uuid-1",
|
|
"env_name": "env-name-1",
|
|
"subtasks": [{
|
|
"workloads": [{
|
|
"contexts": "contexts",
|
|
"scenario": {"Foo.bar": {}},
|
|
"runner": {"constant": {
|
|
"times": 100,
|
|
"concurrency": 5
|
|
}}
|
|
}]
|
|
}]
|
|
}]
|
|
}
|
|
|
|
mock_loads.return_value = results
|
|
ret = self.task._load_task_results_file(self.fake_api, task_file)
|
|
self.assertEqual([{
|
|
"env_uuid": "env-uuid-1",
|
|
"env_name": "env-name-1",
|
|
"subtasks": [{
|
|
"workloads": [{
|
|
"args": {},
|
|
"name": "Foo.bar",
|
|
"contexts": "contexts",
|
|
"contexts_results": [],
|
|
"runner_type": "constant",
|
|
"runner": {
|
|
"times": 100,
|
|
"concurrency": 5
|
|
}
|
|
}]
|
|
}]
|
|
}], ret)
|
|
|
|
@mock.patch("rally.cli.commands.task.open", create=True)
|
|
@mock.patch("rally.cli.commands.task.json.loads")
|
|
def test__load_task_results_file_wrong_format(self, mock_loads, mock_open):
|
|
task_id = "/tmp/task.json"
|
|
mock_loads.return_value = "results"
|
|
self.assertRaises(task.FailedToLoadResults,
|
|
self.task._load_task_results_file,
|
|
api=self.real_api, task_id=task_id)
|
|
|
|
mock_loads.return_value = ["results"]
|
|
self.assertRaises(task.FailedToLoadResults,
|
|
self.task._load_task_results_file,
|
|
api=self.real_api, task_id=task_id)
|
|
|
|
@mock.patch("rally.cli.commands.task.os.path")
|
|
def test_import_results(self, mock_os_path):
|
|
mock_os_path.exists.return_value = True
|
|
mock_os_path.expanduser = lambda path: path
|
|
self.task._load_task_results_file = mock.MagicMock(
|
|
return_value=["results"]
|
|
)
|
|
|
|
self.task.import_results(self.fake_api,
|
|
"deployment_uuid",
|
|
"task_file", tags=["tag"])
|
|
|
|
self.task._load_task_results_file.assert_called_once_with(
|
|
self.fake_api, "task_file"
|
|
)
|
|
self.fake_api.task.import_results.assert_called_once_with(
|
|
deployment="deployment_uuid", task_results="results",
|
|
tags=["tag"])
|
|
|
|
# not exist
|
|
mock_os_path.exists.return_value = False
|
|
self.assertEqual(
|
|
1,
|
|
self.task.import_results(self.fake_api,
|
|
"deployment_uuid",
|
|
"task_file", ["tag"])
|
|
)
|