From c157502a9c65ad59cb8d83be59c264db03c3d2f8 Mon Sep 17 00:00:00 2001 From: Tim Simpson Date: Thu, 17 Oct 2013 14:39:55 -0500 Subject: [PATCH] Simulates events so run_tests.py executes 10x faster This restores some functionality that had been removed earlier to use a class from Oslo. It turns out making it work with the new Oslo RPC manager code wasn't too hard, plus the new version is hopefully easier to follow. Change-Id: I18e4d06359f28605cd764a10ace791997f534ed7 Implements: blueprint bring-back-event-simulator --- run_tests.py | 2 + trove/tests/util/event_simulator.py | 60 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 trove/tests/util/event_simulator.py diff --git a/run_tests.py b/run_tests.py index 3f3af39c5c..1b35e5d88d 100644 --- a/run_tests.py +++ b/run_tests.py @@ -82,6 +82,8 @@ def initialize_fakes(app): wsgi_intercept.add_wsgi_intercept('localhost', CONF.bind_port, wsgi_interceptor) + from trove.tests.util import event_simulator + event_simulator.monkey_patch() def parse_args_for_test_config(): diff --git a/trove/tests/util/event_simulator.py b/trove/tests/util/event_simulator.py new file mode 100644 index 0000000000..f2af50c4b7 --- /dev/null +++ b/trove/tests/util/event_simulator.py @@ -0,0 +1,60 @@ +""" +Simulates time itself to make the fake mode tests run even faster. +""" + + +pending_events = [] +sleep_entrance_count = 0 + + +def event_simulator_spawn_after(time_from_now_in_seconds, func, *args, **kw): + """Fakes events without doing any actual waiting.""" + def __cb(): + func(*args, **kw) + pending_events.append({"time": time_from_now_in_seconds, "func": __cb}) + + +def event_simulator_spawn(func, *args, **kw): + event_simulator_spawn_after(0, func, *args, **kw) + + +def event_simulator_sleep(time_to_sleep): + """Simulates waiting for an event.""" + global sleep_entrance_count + sleep_entrance_count += 1 + time_to_sleep = float(time_to_sleep) + global pending_events + run_once = False # Ensure simulator runs even if the sleep time is zero. + while not run_once or time_to_sleep > 0: + run_once = True + itr_sleep = 0.5 + for i in range(len(pending_events)): + event = pending_events[i] + event["time"] = event["time"] - itr_sleep + if event["func"] is not None and event["time"] < 0: + # Call event, but first delete it so this function can be + # reentrant. + func = event["func"] + event["func"] = None + try: + func() + except Exception: + LOG.exception("Simulated event error.") + time_to_sleep -= itr_sleep + sleep_entrance_count -= 1 + if sleep_entrance_count < 1: + # Clear out old events + pending_events = [event for event in pending_events + if event["func"] is not None] + + +def monkey_patch(): + import time + time.sleep = event_simulator_sleep + import eventlet + from eventlet import greenthread + eventlet.sleep = event_simulator_sleep + greenthread.sleep = event_simulator_sleep + eventlet.spawn_after = event_simulator_spawn_after + eventlet.spawn_n = event_simulator_spawn + eventlet.spawn = NotImplementedError