Add atomic action names tracking

Here we change the format of the scenario results so that it now stores
the atomic actions data as a dict:

    Before:
        {
            "duration": ...,
            "error": ...,
            "atomic_actions": [
                {"action": "a1", "duration": 0.3},
                {"action": "a2", "duration": 0.1},
                {"action": "a1", "duration": 0.25}
            ],
            ...
        }

    After:
        {
            "duration": ...,
            "error": ...,
            "atomic_actions": {
                "a1": 0.3,
                "a1 (2)": 0.25,
                "a2": 0.1
            },
            ...
        }

We also solve 2 connected problems here:

1. The statistics table that shows up in the CLI after benchmarks complete now
   always has rows for all the atomic actions that were invoked in benchmark
   scenarios. Before this patch, this was not the case since occasionally the
   atomic actions data could not be written due to Exceptions.

2. We've removed lots of ugly code in benchmark/processing/plot.py, since now
   there is no need to make passes through the atomic actions data to collect
   their names.

This patch also:
* contains some removing of code duplicate between plot & CLI output generation;
* adds missing UTs for raw benchmark data processing;
* fixes a minor bug in histograms bins number calculation.

Change-Id: I17f563051bd1c2ec2fb47a385d4cc652895e1f9e
This commit is contained in:
Mikhail Dubov 2014-09-22 10:45:05 +04:00
parent 9f016ee773
commit b55d6dfc63
21 changed files with 164 additions and 164 deletions

View File

@ -42,7 +42,7 @@ class Histogram:
def _calculate_bin_width(self): def _calculate_bin_width(self):
"""Calculate the bin width using a given number of bins.""" """Calculate the bin width using a given number of bins."""
return (self.max_data - self.min_data) / self.number_of_bins return (self.max_data - self.min_data) // self.number_of_bins
def _calculate_x_axis(self): def _calculate_x_axis(self):
"""Return a list with the values of the x axis.""" """Return a list with the values of the x axis."""

View File

@ -39,13 +39,9 @@ def _prepare_data(data, reduce_rows=1000):
for k, v in d1.iteritems(): for k, v in d1.iteritems():
v[-1] = (v[-1] + d2[k]) / 2.0 v[-1] = (v[-1] + d2[k]) / 2.0
zero_atomic_actions = {} atomic_action_names = (data["result"][0]["atomic_actions"].keys()
for row in data["result"]: if data["result"] else [])
# find first non-error result to get atomic actions names zero_atomic_actions = dict([(a, 0) for a in atomic_action_names])
if not row["error"] and "atomic_actions" in row:
zero_atomic_actions = dict([(a["action"], 0)
for a in row["atomic_actions"]])
break
total_durations = {"duration": [], "idle_duration": []} total_durations = {"duration": [], "idle_duration": []}
atomic_durations = dict([(a, []) for a in zero_atomic_actions]) atomic_durations = dict([(a, []) for a in zero_atomic_actions])
@ -74,8 +70,9 @@ def _prepare_data(data, reduce_rows=1000):
"duration": row["duration"], "duration": row["duration"],
"idle_duration": row["idle_duration"], "idle_duration": row["idle_duration"],
} }
new_row_atomic = dict([(a["action"], a["duration"]) new_row_atomic = {}
for a in row["atomic_actions"]]) for k, v in row["atomic_actions"].iteritems():
new_row_atomic[k] = v if v else 0
if store < 1: if store < 1:
_append(total_durations, new_row_total) _append(total_durations, new_row_total)
_append(atomic_durations, new_row_atomic) _append(atomic_durations, new_row_atomic)
@ -136,10 +133,11 @@ def _process_atomic(result, data):
# NOTE(boris-42): In our result["result"] we have next structure: # NOTE(boris-42): In our result["result"] we have next structure:
# {"error": NoneOrDict, # {"error": NoneOrDict,
# "atomic_actions": [ # "atomic_actions": {
# {"action": String, "duration": Float}, # "action1": <duration>,
# ... # "action2": <duration>
# ]} # }
# }
# Our goal is to get next structure: # Our goal is to get next structure:
# [{"key": $atomic_actions.action, # [{"key": $atomic_actions.action,
# "values": [[order, $atomic_actions.duration # "values": [[order, $atomic_actions.duration
@ -149,12 +147,9 @@ def _process_atomic(result, data):
# all iteration. So we should take first non "error" # all iteration. So we should take first non "error"
# iteration. And get in atomitc_iter list: # iteration. And get in atomitc_iter list:
# [{"key": "action", "values":[]}] # [{"key": "action", "values":[]}]
stacked_area = [] stacked_area = ([{"key": a, "values": []}
for r in result["result"]: for a in result["result"][0]["atomic_actions"]]
if not r["error"]: if result["result"] else [])
for action in r["atomic_actions"]:
stacked_area.append({"key": action["action"], "values": []})
break
# NOTE(boris-42): pie is similiar to stacked_area, only difference is in # NOTE(boris-42): pie is similiar to stacked_area, only difference is in
# structure of values. In case of $error we shouldn't put # structure of values. In case of $error we shouldn't put
@ -173,9 +168,15 @@ def _process_atomic(result, data):
continue continue
# in case of non error put real durations to pie and stacked area # in case of non error put real durations to pie and stacked area
for j, action in enumerate(res["atomic_actions"]): for j, action in enumerate(res["atomic_actions"].keys()):
pie[j]["values"].append(action["duration"]) # in case any single atomic action failed, put 0
histogram_data[j]["values"].append(action["duration"]) action_duration = res["atomic_actions"][action] or 0.0
pie[j]["values"].append(action_duration)
histogram_data[j]["values"].append(action_duration)
# filter out empty action lists in pie / histogram to avoid errors
pie = filter(lambda x: x["values"], pie)
histogram_data = filter(lambda x: x["values"], histogram_data)
histograms = [[] for atomic_action in range(len(histogram_data))] histograms = [[] for atomic_action in range(len(histogram_data))]
for i, atomic_action in enumerate(histogram_data): for i, atomic_action in enumerate(histogram_data):
@ -211,28 +212,10 @@ def _process_atomic(result, data):
def _get_atomic_action_durations(result): def _get_atomic_action_durations(result):
raw = result.get('result', []) raw = result.get('result', [])
atomic_actions_names = [] actions_data = utils.get_atomic_actions_data(raw)
for r in raw:
if 'atomic_actions' in r:
for a in r['atomic_actions']:
atomic_actions_names.append(a["action"])
break
action_durations = {}
for atomic_action in atomic_actions_names:
action_durations[atomic_action] = utils.get_durations(
raw,
lambda r: next(a["duration"] for a in r["atomic_actions"]
if a["action"] == atomic_action),
lambda r: any((a["action"] == atomic_action)
for a in r["atomic_actions"]))
table = [] table = []
actions_list = action_durations.keys() for action in actions_data:
action_durations["total"] = utils.get_durations( durations = actions_data[action]
raw, lambda x: x["duration"], lambda r: not r["error"])
actions_list.append("total")
for action in actions_list:
durations = action_durations[action]
if durations: if durations:
data = [action, data = [action,
round(min(durations), 3), round(min(durations), 3),

View File

@ -52,16 +52,20 @@ def percentile(values, percent):
return (d0 + d1) return (d0 + d1)
def get_durations(raw_data, get_duration, is_successful): def get_atomic_actions_data(raw_data):
"""Retrieve the benchmark duration data from a list of records. """Retrieve detailed (by atomic actions & total runtime) benchmark data.
:parameter raw_data: list of records :parameter raw_data: list of raw records (scenario runner output)
:parameter get_duration: function that retrieves the duration data from
a given record
:parameter is_successful: function that returns True if the record contains
a successful benchmark result, False otherwise
:returns: list of float values corresponding to benchmark durations :returns: dictionary containing atomic action + total duration lists
for all atomic action keys
""" """
data = [get_duration(run) for run in raw_data if is_successful(run)] atomic_actions = raw_data[0]["atomic_actions"].keys() if raw_data else []
return data actions_data = {}
for atomic_action in atomic_actions:
actions_data[atomic_action] = [
r["atomic_actions"][atomic_action]
for r in raw_data
if r["atomic_actions"][atomic_action] is not None]
actions_data["total"] = [r["duration"] for r in raw_data if not r["error"]]
return actions_data

View File

@ -38,7 +38,7 @@ def format_result_on_timeout(exc, timeout):
"duration": timeout, "duration": timeout,
"idle_duration": 0, "idle_duration": 0,
"scenario_output": {"errors": "", "data": {}}, "scenario_output": {"errors": "", "data": {}},
"atomic_actions": [], "atomic_actions": {},
"error": utils.format_exc(exc) "error": utils.format_exc(exc)
} }
@ -117,14 +117,9 @@ class ScenarioRunnerResult(dict):
"additionalProperties": False "additionalProperties": False
}, },
"atomic_actions": { "atomic_actions": {
"type": "array", "type": "object",
"items": { "patternProperties": {
"type": "object", ".*": {"type": ["number", "null"]}
"properties": {
"action": {"type": "string"},
"duration": {"type": "number"}
},
"additionalProperties": False
} }
}, },
"error": { "error": {

View File

@ -55,7 +55,7 @@ class Scenario(object):
self._admin_clients = admin_clients self._admin_clients = admin_clients
self._clients = clients self._clients = clients
self._idle_duration = 0 self._idle_duration = 0
self._atomic_actions = [] self._atomic_actions = {}
# TODO(amaretskiy): consider about prefix part of benchmark uuid # TODO(amaretskiy): consider about prefix part of benchmark uuid
@classmethod @classmethod
@ -217,10 +217,17 @@ class Scenario(object):
"""Returns duration of all sleep_between.""" """Returns duration of all sleep_between."""
return self._idle_duration return self._idle_duration
def _register_atomic_action(self, name):
"""Registers an atomic action by its name."""
self._atomic_actions[name] = None
def _atomic_action_registered(self, name):
"""Checks whether an atomic action has been already registered."""
return name in self._atomic_actions
def _add_atomic_actions(self, name, duration): def _add_atomic_actions(self, name, duration):
"""Adds the duration of an atomic action by its 'name'.""" """Adds the duration of an atomic action by its name."""
self._atomic_actions.append( self._atomic_actions[name] = duration
{'action': name, 'duration': duration})
def atomic_actions(self): def atomic_actions(self):
"""Returns the content of each atomic action.""" """Returns the content of each atomic action."""
@ -236,9 +243,8 @@ def atomic_action_timer(name):
def wrap(func): def wrap(func):
@functools.wraps(func) @functools.wraps(func)
def func_atomic_actions(self, *args, **kwargs): def func_atomic_actions(self, *args, **kwargs):
with utils.Timer() as timer: with AtomicAction(self, name):
f = func(self, *args, **kwargs) f = func(self, *args, **kwargs)
self._add_atomic_actions(name, timer.duration())
return f return f
return func_atomic_actions return func_atomic_actions
return wrap return wrap
@ -264,8 +270,25 @@ class AtomicAction(utils.Timer):
""" """
super(AtomicAction, self).__init__() super(AtomicAction, self).__init__()
self.scenario_instance = scenario_instance self.scenario_instance = scenario_instance
self.name = name self.name = self._get_atomic_action_name(name)
self.scenario_instance._register_atomic_action(self.name)
def _get_atomic_action_name(self, name):
if not self.scenario_instance._atomic_action_registered(name):
return name
else:
name_template = name + " (%i)"
atomic_action_iteration = 2
with open("1.txt", "a") as f:
f.write("Enter\n")
f.write(str(dir(self.scenario_instance)) + "\n")
while self.scenario_instance._atomic_action_registered(
name_template % atomic_action_iteration):
atomic_action_iteration += 1
return name_template % atomic_action_iteration
def __exit__(self, type, value, tb): def __exit__(self, type, value, tb):
super(AtomicAction, self).__exit__(type, value, tb) super(AtomicAction, self).__exit__(type, value, tb)
self.scenario_instance._add_atomic_actions(self.name, self.duration()) if type is None:
self.scenario_instance._add_atomic_actions(self.name,
self.duration())

View File

@ -143,23 +143,6 @@ class TaskCommands(object):
formatters=formatters) formatters=formatters)
print() print()
def _get_atomic_action_durations(raw):
atomic_actions_names = []
for r in raw:
if 'atomic_actions' in r:
for a in r['atomic_actions']:
atomic_actions_names.append(a["action"])
break
result = {}
for atomic_action in atomic_actions_names:
result[atomic_action] = utils.get_durations(
raw,
lambda r: next(a["duration"] for a in r["atomic_actions"]
if a["action"] == atomic_action),
lambda r: any((a["action"] == atomic_action)
for a in r["atomic_actions"]))
return result
if task_id == "last": if task_id == "last":
task = db.task_get_detailed_last() task = db.task_get_detailed_last()
task_id = task.uuid task_id = task.uuid
@ -210,13 +193,9 @@ class TaskCommands(object):
for col in float_cols])) for col in float_cols]))
table_rows = [] table_rows = []
action_durations = _get_atomic_action_durations(raw) actions_data = utils.get_atomic_actions_data(raw)
actions_list = action_durations.keys() for action in actions_data:
action_durations["total"] = utils.get_durations( durations = actions_data[action]
raw, lambda x: x["duration"], lambda r: not r["error"])
actions_list.append("total")
for action in actions_list:
durations = action_durations[action]
if durations: if durations:
data = [action, data = [action,
min(durations), min(durations),

View File

@ -90,17 +90,20 @@ class PlotTestCase(test.TestCase):
{ {
"error": [], "error": [],
"duration": 1, "duration": 1,
"idle_duration": 2 "idle_duration": 2,
"atomic_actions": {}
}, },
{ {
"error": True, "error": True,
"duration": 1, "duration": 1,
"idle_duration": 1 "idle_duration": 1,
"atomic_actions": {}
}, },
{ {
"error": [], "error": [],
"duration": 2, "duration": 2,
"idle_duration": 3 "idle_duration": 3,
"atomic_actions": {}
} }
] ]
} }
@ -153,24 +156,24 @@ class PlotTestCase(test.TestCase):
"result": [ "result": [
{ {
"error": [], "error": [],
"atomic_actions": [ "atomic_actions": {
{"action": "action1", "duration": 1}, "action1": 1,
{"action": "action2", "duration": 2} "action2": 2
] }
}, },
{ {
"error": ["some", "error", "occurred"], "error": ["some", "error", "occurred"],
"atomic_actions": [ "atomic_actions": {
{"action": "action1", "duration": 1}, "action1": 1,
{"action": "action2", "duration": 2} "action2": 2
] }
}, },
{ {
"error": [], "error": [],
"atomic_actions": [ "atomic_actions": {
{"action": "action1", "duration": 3}, "action1": 3,
{"action": "action2", "duration": 4} "action2": 4
] }
} }
] ]
} }
@ -262,10 +265,10 @@ class PlotTestCase(test.TestCase):
data = [] data = []
for i in range(100): for i in range(100):
atomic_actions = [ atomic_actions = {
{"action": "a1", "duration": i + 0.1}, "a1": i + 0.1,
{"action": "a2", "duration": i + 0.8}, "a2": i + 0.8
] }
row = { row = {
"duration": i * 3.14, "duration": i * 3.14,
"idle_duration": i * 0.2, "idle_duration": i * 0.2,

View File

@ -18,7 +18,7 @@ from rally import exceptions
from tests import test from tests import test
class ProcessingUtilsTestCase(test.TestCase): class MathTestCase(test.TestCase):
def test_percentile(self): def test_percentile(self):
lst = range(1, 101) lst = range(1, 101)
@ -43,3 +43,43 @@ class ProcessingUtilsTestCase(test.TestCase):
lst = [] lst = []
self.assertRaises(exceptions.InvalidArgumentsException, self.assertRaises(exceptions.InvalidArgumentsException,
utils.mean, lst) utils.mean, lst)
class AtomicActionsDataTestCase(test.TestCase):
def test_get_atomic_actions_data(self):
raw_data = [
{
"error": [],
"duration": 3,
"atomic_actions": {
"action1": 1,
"action2": 2
}
},
{
"error": ["some", "error", "occurred"],
"duration": 1.9,
"atomic_actions": {
"action1": 0.5,
"action2": 1.4
}
},
{
"error": [],
"duration": 8,
"atomic_actions": {
"action1": 4,
"action2": 4
}
}
]
atomic_actions_data = {
"action1": [1, 0.5, 4],
"action2": [2, 1.4, 4],
"total": [3, 8]
}
output = utils.get_atomic_actions_data(raw_data)
self.assertEqual(output, atomic_actions_data)

View File

@ -34,7 +34,7 @@ class ScenarioHelpersTestCase(test.TestCase):
"duration": 100, "duration": 100,
"idle_duration": 0, "idle_duration": 0,
"scenario_output": {"errors": "", "data": {}}, "scenario_output": {"errors": "", "data": {}},
"atomic_actions": [], "atomic_actions": {},
"error": mock_format_exc.return_value "error": mock_format_exc.return_value
} }
@ -94,7 +94,7 @@ class ScenarioHelpersTestCase(test.TestCase):
"idle_duration": 0, "idle_duration": 0,
"error": [], "error": [],
"scenario_output": {"errors": "", "data": {}}, "scenario_output": {"errors": "", "data": {}},
"atomic_actions": [] "atomic_actions": {}
} }
self.assertEqual(expected_result, result) self.assertEqual(expected_result, result)
@ -112,7 +112,7 @@ class ScenarioHelpersTestCase(test.TestCase):
"idle_duration": 0, "idle_duration": 0,
"error": [], "error": [],
"scenario_output": fakes.FakeScenario().with_output(), "scenario_output": fakes.FakeScenario().with_output(),
"atomic_actions": [] "atomic_actions": {}
} }
self.assertEqual(expected_result, result) self.assertEqual(expected_result, result)
@ -128,7 +128,7 @@ class ScenarioHelpersTestCase(test.TestCase):
"duration": fakes.FakeTimer().duration(), "duration": fakes.FakeTimer().duration(),
"idle_duration": 0, "idle_duration": 0,
"scenario_output": {"errors": "", "data": {}}, "scenario_output": {"errors": "", "data": {}},
"atomic_actions": [] "atomic_actions": {}
} }
self.assertEqual(expected_result, result) self.assertEqual(expected_result, result)
self.assertEqual(expected_error[:2], self.assertEqual(expected_error[:2],
@ -146,7 +146,7 @@ class ScenarioRunnerResultTestCase(test.TestCase):
"data": {"test": 1.0}, "data": {"test": 1.0},
"errors": "test error string 1" "errors": "test error string 1"
}, },
"atomic_actions": [{"action": "test1", "duration": 1.0}], "atomic_actions": {"test1": 1.0},
"error": [] "error": []
}, },
{ {
@ -156,7 +156,7 @@ class ScenarioRunnerResultTestCase(test.TestCase):
"data": {"test": 2.0}, "data": {"test": 2.0},
"errors": "test error string 2" "errors": "test error string 2"
}, },
"atomic_actions": [{"action": "test2", "duration": 2.0}], "atomic_actions": {"test2": 2.0},
"error": ["a", "b", "c"] "error": ["a", "b", "c"]
} }
] ]

View File

@ -29,7 +29,7 @@ class SerialScenarioRunnerTestCase(test.TestCase):
def test_run_scenario(self, mock_run_once): def test_run_scenario(self, mock_run_once):
times = 5 times = 5
result = {"duration": 10, "idle_duration": 0, "error": [], result = {"duration": 10, "idle_duration": 0, "error": [],
"scenario_output": {}, "atomic_actions": []} "scenario_output": {}, "atomic_actions": {}}
mock_run_once.return_value = result mock_run_once.return_value = result
expected_results = [result for i in range(times)] expected_results = [result for i in range(times)]

View File

@ -15,7 +15,6 @@
import mock import mock
from rally.benchmark.scenarios.ceilometer import utils from rally.benchmark.scenarios.ceilometer import utils
from tests.benchmark.scenarios import test_base
from tests import fakes from tests import fakes
from tests import test from tests import test
@ -30,8 +29,7 @@ class CeilometerScenarioTestCase(test.TestCase):
return_value=fakes.FakeCeilometerClient()) return_value=fakes.FakeCeilometerClient())
def _test_atomic_action_timer(self, atomic_actions_time, name): def _test_atomic_action_timer(self, atomic_actions_time, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions_time.get(name)
atomic_actions_time, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -18,7 +18,6 @@ from oslo.config import cfg
from oslotest import mockpatch from oslotest import mockpatch
from rally.benchmark.scenarios.cinder import utils from rally.benchmark.scenarios.cinder import utils
from tests.benchmark.scenarios import test_base
from tests import test from tests import test
BM_UTILS = 'rally.benchmark.utils' BM_UTILS = 'rally.benchmark.utils'
@ -43,8 +42,7 @@ class CinderScenarioTestCase(test.TestCase):
self.scenario = utils.CinderScenario() self.scenario = utils.CinderScenario()
def _test_atomic_action_timer(self, atomic_actions, name): def _test_atomic_action_timer(self, atomic_actions, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions.get(name)
atomic_actions, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -17,7 +17,6 @@
import mock import mock
from rally.benchmark.scenarios.designate import utils from rally.benchmark.scenarios.designate import utils
from tests.benchmark.scenarios import test_base
from tests import test from tests import test
@ -31,8 +30,7 @@ class DesignateScenarioTestCase(test.TestCase):
self.domain = mock.Mock() self.domain = mock.Mock()
def _test_atomic_action_timer(self, atomic_actions_time, name): def _test_atomic_action_timer(self, atomic_actions_time, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions_time.get(name)
atomic_actions_time, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -18,7 +18,6 @@ from oslotest import mockpatch
from rally.benchmark.scenarios.glance import utils from rally.benchmark.scenarios.glance import utils
from rally.benchmark import utils as butils from rally.benchmark import utils as butils
from rally import exceptions as rally_exceptions from rally import exceptions as rally_exceptions
from tests.benchmark.scenarios import test_base
from tests import fakes from tests import fakes
from tests import test from tests import test
@ -53,8 +52,7 @@ class GlanceScenarioTestCase(test.TestCase):
image_manager.create('fails', 'url', 'cf', 'df')) image_manager.create('fails', 'url', 'cf', 'df'))
def _test_atomic_action_timer(self, atomic_actions, name): def _test_atomic_action_timer(self, atomic_actions, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions.get(name)
atomic_actions, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -17,7 +17,6 @@ import mock
from oslotest import mockpatch from oslotest import mockpatch
from rally.benchmark.scenarios.heat import utils from rally.benchmark.scenarios.heat import utils
from tests.benchmark.scenarios import test_base
from tests import test from tests import test
BM_UTILS = 'rally.benchmark.utils' BM_UTILS = 'rally.benchmark.utils'
@ -43,8 +42,7 @@ class HeatScenarioTestCase(test.TestCase):
self.scenario = utils.HeatScenario() self.scenario = utils.HeatScenario()
def _test_atomic_action_timer(self, atomic_actions, name): def _test_atomic_action_timer(self, atomic_actions, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions.get(name)
atomic_actions, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -16,7 +16,6 @@
import mock import mock
from rally.benchmark.scenarios.keystone import utils from rally.benchmark.scenarios.keystone import utils
from tests.benchmark.scenarios import test_base
from tests import fakes from tests import fakes
from tests import test from tests import test
@ -52,8 +51,7 @@ class KeystoneUtilsTestCase(test.TestCase):
class KeystoneScenarioTestCase(test.TestCase): class KeystoneScenarioTestCase(test.TestCase):
def _test_atomic_action_timer(self, atomic_actions, name): def _test_atomic_action_timer(self, atomic_actions, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions.get(name)
atomic_actions, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -17,7 +17,6 @@ import mock
import netaddr import netaddr
from rally.benchmark.scenarios.neutron import utils from rally.benchmark.scenarios.neutron import utils
from tests.benchmark.scenarios import test_base
from tests import test from tests import test
@ -31,8 +30,7 @@ class NeutronScenarioTestCase(test.TestCase):
self.network = mock.Mock() self.network = mock.Mock()
def _test_atomic_action_timer(self, atomic_actions_time, name): def _test_atomic_action_timer(self, atomic_actions_time, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions_time.get(name)
atomic_actions_time, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -20,7 +20,6 @@ from oslotest import mockpatch
from rally.benchmark.scenarios.nova import utils from rally.benchmark.scenarios.nova import utils
from rally.benchmark import utils as butils from rally.benchmark import utils as butils
from rally import exceptions as rally_exceptions from rally import exceptions as rally_exceptions
from tests.benchmark.scenarios import test_base
from tests import fakes from tests import fakes
from tests import test from tests import test
@ -51,8 +50,7 @@ class NovaScenarioTestCase(test.TestCase):
self.useFixture(mockpatch.Patch('time.sleep')) self.useFixture(mockpatch.Patch('time.sleep'))
def _test_atomic_action_timer(self, atomic_actions, name): def _test_atomic_action_timer(self, atomic_actions, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions.get(name)
atomic_actions, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -16,7 +16,6 @@
import mock import mock
from rally.benchmark.scenarios.quotas import utils from rally.benchmark.scenarios.quotas import utils
from tests.benchmark.scenarios import test_base
from tests import fakes from tests import fakes
from tests import test from tests import test
@ -27,8 +26,7 @@ class QuotasScenarioTestCase(test.TestCase):
super(QuotasScenarioTestCase, self).setUp() super(QuotasScenarioTestCase, self).setUp()
def _test_atomic_action_timer(self, atomic_actions_time, name): def _test_atomic_action_timer(self, atomic_actions_time, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions_time.get(name)
atomic_actions_time, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -18,7 +18,6 @@ from saharaclient.api import base as sahara_base
from rally.benchmark.scenarios.sahara import utils from rally.benchmark.scenarios.sahara import utils
from rally import exceptions from rally import exceptions
from tests.benchmark.scenarios import test_base
from tests import test from tests import test
@ -28,8 +27,7 @@ SAHARA_UTILS = 'rally.benchmark.scenarios.sahara.utils'
class SaharaNodeGroupTemplatesScenarioTestCase(test.TestCase): class SaharaNodeGroupTemplatesScenarioTestCase(test.TestCase):
def _test_atomic_action_timer(self, atomic_actions, name): def _test_atomic_action_timer(self, atomic_actions, name):
action_duration = test_base.get_atomic_action_timer_value_by_name( action_duration = atomic_actions.get(name)
atomic_actions, name)
self.assertIsNotNone(action_duration) self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float) self.assertIsInstance(action_duration, float)

View File

@ -330,24 +330,17 @@ class ScenarioTestCase(test.TestCase):
class AtomicActionTestCase(test.TestCase): class AtomicActionTestCase(test.TestCase):
def test__init__(self): def test__init__(self):
fake_scenario_instance = mock.MagicMock() fake_scenario_instance = fakes.FakeScenario()
c = base.AtomicAction(fake_scenario_instance, 'asdf') c = base.AtomicAction(fake_scenario_instance, 'asdf')
self.assertEqual(c.scenario_instance, fake_scenario_instance) self.assertEqual(c.scenario_instance, fake_scenario_instance)
self.assertEqual(c.name, 'asdf') self.assertEqual(c.name, 'asdf')
@mock.patch('tests.fakes.FakeScenario._add_atomic_actions')
@mock.patch('rally.utils.time') @mock.patch('rally.utils.time')
def test__exit__(self, mock_time): def test__exit__(self, mock_time, mock__add_atomic_actions):
fake_scenario_instance = mock.Mock() fake_scenario_instance = fakes.FakeScenario()
self.start = mock_time.time() self.start = mock_time.time()
with base.AtomicAction(fake_scenario_instance, "asdf"): with base.AtomicAction(fake_scenario_instance, "asdf"):
pass pass
duration = mock_time.time() - self.start duration = mock_time.time() - self.start
fake_scenario_instance._add_atomic_actions.assert_called_once_with( mock__add_atomic_actions.assert_called_once_with('asdf', duration)
'asdf', duration)
def get_atomic_action_timer_value_by_name(atomic_actions, name):
for action in atomic_actions:
if action['action'] == name:
return action['duration']
return None