diff --git a/stacktach/db.py b/stacktach/db.py index 386ac40..9d5290b 100644 --- a/stacktach/db.py +++ b/stacktach/db.py @@ -12,5 +12,11 @@ def create_timing(**kwargs): def find_timings(**kwargs): return models.Timing.objects.select_related().filter(**kwargs) +def create_request_tracker(**kwargs): + return models.RequestTracker(**kwargs) + +def find_request_trackers(**kwargs): + return models.RequestTracker.objects.filter(**kwargs) + def save(obj): obj.save() \ No newline at end of file diff --git a/stacktach/tests.py b/stacktach/tests.py index 370a828..0b55f71 100644 --- a/stacktach/tests.py +++ b/stacktach/tests.py @@ -17,27 +17,6 @@ from test_utils import create_raw import views -class DatetimeToDecimalTestCase(unittest.TestCase): - - def test_datetime_to_and_from_decimal(self): - now = datetime.datetime.utcnow() - d = datetime_to_decimal.dt_to_decimal(now) - daittyme = datetime_to_decimal.dt_from_decimal(d) - self.assertEqual(now, daittyme) - - def test_datetime_to_decimal(self): - expected_decimal = decimal.Decimal('1356093296.123') - utc_datetime = datetime.datetime.utcfromtimestamp(expected_decimal) - actual_decimal = datetime_to_decimal.dt_to_decimal(utc_datetime) - self.assertEqual(actual_decimal, expected_decimal) - - def test_decimal_to_datetime(self): - expected_decimal = decimal.Decimal('1356093296.123') - expected_datetime = datetime.datetime.utcfromtimestamp(expected_decimal) - actual_datetime = datetime_to_decimal.dt_from_decimal(expected_decimal) - self.assertEqual(actual_datetime, expected_datetime) - - class ViewsUtilsTestCase(unittest.TestCase): def test_srt_time_to_unix(self): diff --git a/stacktach/views.py b/stacktach/views.py index f8eb847..b53755f 100644 --- a/stacktach/views.py +++ b/stacktach/views.py @@ -67,7 +67,7 @@ def _compute_update_message(routing_key, body): resp = dict(host=host, instance=instance, publisher=publisher, service=service, event=event, tenant=tenant, request_id=request_id) - payload = data.get('payload', {}) + payload = body.get('payload', {}) resp.update(_extract_states(payload)) return resp @@ -87,15 +87,15 @@ def start_kpi_tracking(lifecycle, raw): if "api" not in raw.host: return - tracker = models.RequestTracker(request_id=raw.request_id, - start=raw.when, - lifecycle=lifecycle, - last_timing=None, - duration=str(0.0)) - tracker.save() + tracker = STACKDB.create_request_tracker(request_id=raw.request_id, + start=raw.when, + lifecycle=lifecycle, + last_timing=None, + duration=str(0.0)) + STACKDB.save(tracker) -def update_kpi(lifecycle, timing, raw): +def update_kpi(timing, raw): """Whenever we get a .end event, use the Timing object to compute our current end-to-end duration. @@ -106,15 +106,14 @@ def update_kpi(lifecycle, timing, raw): Until then, we'll take the lazy route and be aware of these potential fence-post issues.""" - trackers = models.RequestTracker.objects.\ - filter(request_id=raw.request_id) + trackers = STACKDB.find_request_trackers(request_id=raw.request_id) if len(trackers) == 0: return tracker = trackers[0] tracker.last_timing = timing tracker.duration = timing.end_when - tracker.start - tracker.save() + STACKDB.save(tracker) def aggregate_lifecycle(raw): @@ -198,7 +197,7 @@ def aggregate_lifecycle(raw): if timing.start_when: timing.diff = timing.end_when - timing.start_when # Looks like a valid pair ... - update_kpi(lifecycle, timing, raw) + update_kpi(timing, raw) STACKDB.save(timing) diff --git a/tests/__init__.py b/tests/__init__.py index d90f00b..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,6 +0,0 @@ -import os -import sys - -print "!!!!!!! %s" %__package__ - -#sys.path = [os.path.abspath(os.path.dirname(__package__))] + sys.path \ No newline at end of file diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/settings.py b/tests/integration/settings.py new file mode 120000 index 0000000..fff7c2e --- /dev/null +++ b/tests/integration/settings.py @@ -0,0 +1 @@ +settings.py \ No newline at end of file diff --git a/tests/unit/test_datetime_to_decimal.py b/tests/unit/test_datetime_to_decimal.py new file mode 100644 index 0000000..8632640 --- /dev/null +++ b/tests/unit/test_datetime_to_decimal.py @@ -0,0 +1,21 @@ +import datetime +import decimal +import unittest + +import utils +utils.setup_sys_path() +from stacktach import datetime_to_decimal + +class DatetimeToDecimalTestCase(unittest.TestCase): + + def test_datetime_to_decimal(self): + expected_decimal = decimal.Decimal('1356093296.123') + utc_datetime = datetime.datetime.utcfromtimestamp(expected_decimal) + actual_decimal = datetime_to_decimal.dt_to_decimal(utc_datetime) + self.assertEqual(actual_decimal, expected_decimal) + + def test_decimal_to_datetime(self): + expected_decimal = decimal.Decimal('1356093296.123') + expected_datetime = datetime.datetime.utcfromtimestamp(expected_decimal) + actual_datetime = datetime_to_decimal.dt_from_decimal(expected_decimal) + self.assertEqual(actual_datetime, expected_datetime) diff --git a/tests/unit/test_stacktach.py b/tests/unit/test_stacktach.py index 850ea93..2d093a1 100644 --- a/tests/unit/test_stacktach.py +++ b/tests/unit/test_stacktach.py @@ -5,14 +5,16 @@ import unittest import mox -INSTANCE_ID_1 = 'testinstanceid1' -INSTANCE_ID_2 = 'testinstanceid2' - -os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' -sys.path = [os.path.abspath(os.path.dirname('stacktach'))] + sys.path - +import utils +utils.setup_sys_path() +from utils import INSTANCE_ID_1 +from utils import INSTANCE_ID_2 +from utils import MESSAGE_ID_1 +from utils import MESSAGE_ID_2 +from utils import REQUEST_ID_1 +from utils import REQUEST_ID_2 +from utils import REQUEST_ID_3 from stacktach import views -import test_utils as utils class StacktachLifecycleTestCase(unittest.TestCase): def setUp(self): @@ -20,15 +22,77 @@ class StacktachLifecycleTestCase(unittest.TestCase): views.STACKDB = self.mox.CreateMockAnything() def tearDown(self): - pass + self.mox.UnsetStubs() + + def test_start_kpi_tracking_not_update(self): + raw = self.mox.CreateMockAnything() + raw.event = 'compute.instance.create.start' + self.mox.ReplayAll() + views.start_kpi_tracking(None, raw) + self.mox.VerifyAll() + + def test_start_kpi_tracking_not_from_api(self): + raw = self.mox.CreateMockAnything() + raw.event = 'compute.instance.update' + raw.host = 'compute' + self.mox.ReplayAll() + views.start_kpi_tracking(None, raw) + self.mox.VerifyAll() + + def test_start_kpi_tracking(self): + lifecycle = self.mox.CreateMockAnything() + tracker = self.mox.CreateMockAnything() + when = utils.decimal_utcnow() + raw = utils.create_raw(self.mox, when, 'compute.instance.update', + host='api') + views.STACKDB.create_request_tracker(lifecycle=lifecycle, + request_id=REQUEST_ID_1, + start=when, + last_timing=None, + duration=str(0.0))\ + .AndReturn(tracker) + views.STACKDB.save(tracker) + self.mox.ReplayAll() + views.start_kpi_tracking(lifecycle, raw) + self.mox.VerifyAll() + + def test_update_kpi_no_trackers(self): + raw = self.mox.CreateMockAnything() + raw.request_id = REQUEST_ID_1 + views.STACKDB.find_request_trackers(request_id=REQUEST_ID_1)\ + .AndReturn([]) + self.mox.ReplayAll() + views.update_kpi(None, raw) + self.mox.VerifyAll() + + def test_update_kpi(self): + lifecycle = self.mox.CreateMockAnything() + end = utils.decimal_utcnow() + raw = self.mox.CreateMockAnything() + raw.request_id = REQUEST_ID_1 + raw.when=end + timing = utils.create_timing(self.mox, 'compute.instance.create', + lifecycle, end_when=end) + start = utils.decimal_utcnow() + tracker = utils.create_tracker(self.mox, REQUEST_ID_1, lifecycle, + start) + views.STACKDB.find_request_trackers(request_id=REQUEST_ID_1)\ + .AndReturn([tracker]) + views.STACKDB.save(tracker) + self.mox.ReplayAll() + views.update_kpi(timing, raw) + self.assertEqual(tracker.request_id, REQUEST_ID_1) + self.assertEqual(tracker.lifecycle, lifecycle) + self.assertEqual(tracker.last_timing, timing) + self.assertEqual(tracker.start, start) + self.assertEqual(tracker.duration, end-start) + self.mox.VerifyAll() def test_aggregate_lifecycle_no_instance(self): raw = self.mox.CreateMockAnything() raw.instance = None - - views.aggregate_lifecycle(raw) - self.mox.ReplayAll() + views.aggregate_lifecycle(raw) self.mox.VerifyAll() def test_aggregate_lifecycle_start(self): @@ -82,7 +146,7 @@ class StacktachLifecycleTestCase(unittest.TestCase): views.STACKDB.find_timings(name=event_name, lifecycle=lifecycle).AndReturn([timing]) self.mox.StubOutWithMock(views, "update_kpi") - views.update_kpi(lifecycle, timing, end_raw) + views.update_kpi(timing, end_raw) views.STACKDB.save(timing) self.mox.ReplayAll() @@ -98,7 +162,6 @@ class StacktachLifecycleTestCase(unittest.TestCase): self.assertEqual(timing.end_when, end_when) self.assertEqual(timing.diff, end_when-start_when) - self.mox.UnsetStubs() self.mox.VerifyAll() @@ -122,5 +185,4 @@ class StacktachLifecycleTestCase(unittest.TestCase): self.assertEqual(lifecycle.last_state, 'active') self.assertEqual(lifecycle.last_task_state, 'reboot') - self.mox.UnsetStubs() self.mox.VerifyAll() diff --git a/tests/unit/test_utils.py b/tests/unit/utils.py similarity index 51% rename from tests/unit/test_utils.py rename to tests/unit/utils.py index 82fa2e3..742285e 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/utils.py @@ -1,3 +1,7 @@ +import datetime +import os +import sys +import unittest INSTANCE_ID_1 = 'testinstanceid1' INSTANCE_ID_2 = 'testinstanceid2' @@ -9,6 +13,27 @@ REQUEST_ID_1 = 'testrequestid1' REQUEST_ID_2 = 'testrequestid2' REQUEST_ID_3 = 'testrequestid3' +def setup_sys_path(): + sys.path = [os.path.abspath(os.path.dirname('stacktach'))] + sys.path + +def setup_environment(): + os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' + os.environ['STACKTACH_DB_ENGINE'] = 'django.db.backends.sqlite3' + when = str(datetime.datetime.utcnow()) + os.environ['STACKTACH_DB_NAME'] = '/tmp/stacktach.%s.sqlite' % when + os.environ['STACKTACH_DB_HOST'] = '' + os.environ['STACKTACH_DB_USERNAME'] = '' + os.environ['STACKTACH_DB_PASSWORD'] = '' + install_dir = os.path.abspath(os.path.dirname('stacktach')) + os.environ['STACKTACH_INSTALL_DIR'] = install_dir + +setup_sys_path() +setup_environment() +from stacktach import datetime_to_decimal as dt + +def decimal_utcnow(): + return dt.dt_to_decimal(datetime.datetime.utcnow()) + def create_raw(mox, when, event, instance=INSTANCE_ID_1, request_id=REQUEST_ID_1, state='active', old_task='', host='compute', json=''): @@ -19,7 +44,7 @@ def create_raw(mox, when, event, instance=INSTANCE_ID_1, raw.when = when raw.state = state raw.old_task = old_task - raw.request_id = request_id, + raw.request_id = request_id raw.json = json return raw @@ -41,4 +66,14 @@ def create_timing(mox, name, lifecycle, start_raw=None, start_when=None, timing.end_raw = end_raw timing.end_when = end_when timing.diff = diff - return timing \ No newline at end of file + return timing + +def create_tracker(mox, request_id, lifecycle, start, last_timing=None, + duration=str(0.0)): + tracker = mox.CreateMockAnything() + tracker.request_id=request_id + tracker.lifecycle=lifecycle + tracker.start=start + tracker.last_timing=last_timing + tracker.duration=duration + return tracker \ No newline at end of file diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 630adc5..0000000 --- a/tox.ini +++ /dev/null @@ -1,28 +0,0 @@ -[tox] -envlist = py26,py27,pep8 - -[testenv] -setenv = VIRTUAL_ENV={envdir} -# NOSE_WITH_OPENSTACK=1 -# NOSE_OPENSTACK_COLOR=1 -# NOSE_OPENSTACK_RED=0.05 -# NOSE_OPENSTACK_YELLOW=0.025 -# NOSE_OPENSTACK_SHOW_ELAPSED=1 -# NOSE_OPENSTACK_STDOUT=1 -#deps = -r{toxinidir}/tools/pip-requires -# -r{toxinidir}/tools/test-requires -#commands = nosetests {posargs} - -[tox:jenkins] -downloadcache = ~/cache/pip - -[testenv:pep8] -deps = pep8==1.3.3 -commands = - pep8 --ignore=E125,E126,E711,E712 --repeat --show-source --exclude=.venv,.tox,dist,doc,openstack . - -[testenv:cover] -setenv = NOSE_WITH_COVERAGE=1 - -[testenv:venv] -commands = {posargs}