Better lifecycle unit tests

Also, refactoring some DB calls for easier testing.
This commit is contained in:
Andrew Melton 2013-01-23 17:59:00 -05:00
parent f1411de065
commit 57fea75478
8 changed files with 231 additions and 8 deletions

16
stacktach/db.py Normal file
View File

@ -0,0 +1,16 @@
import models
def create_lifecycle(**kwargs):
return models.Lifecycle(**kwargs)
def find_lifecycles(**kwargs):
return models.Lifecycle.objects.select_related().filter(**kwargs)
def create_timing(**kwargs):
return models.Timing(**kwargs)
def find_timings(**kwargs):
return models.Timing.objects.select_related().filter(**kwargs)
def save(obj):
obj.save()

View File

@ -603,6 +603,7 @@ class ViewsUsageTestCase(unittest.TestCase):
self.assertEqual(exists.deleted_at, deleted)
self.assertEqual(exists.instance_type_id, '1')
class ViewsUsageWorkflowTestCase(unittest.TestCase):
def setUp(self):
self.deployment = Deployment(name='TestDeployment')

View File

@ -5,6 +5,7 @@ from django import http
from django.shortcuts import render_to_response
from django import template
from stacktach import db as stackdb
from stacktach import models
from stacktach import datetime_to_decimal as dt
@ -13,6 +14,9 @@ import json
import pprint
STACKDB = stackdb
def _extract_states(payload):
return {
'state' : payload.get('state', ""),
@ -129,16 +133,15 @@ def aggregate_lifecycle(raw):
# While we hope only one lifecycle ever exists it's quite
# likely we get multiple due to the workers and threads.
lifecycle = None
lifecycles = models.Lifecycle.objects.select_related().\
filter(instance=raw.instance)
lifecycles = STACKDB.find_lifecycles(instance=raw.instance)
if len(lifecycles) > 0:
lifecycle = lifecycles[0]
if not lifecycle:
lifecycle = models.Lifecycle(instance=raw.instance)
lifecycle = STACKDB.create_lifecycle(instance=raw.instance)
lifecycle.last_raw = raw
lifecycle.last_state = raw.state
lifecycle.last_task_state = raw.old_task
lifecycle.save()
STACKDB.save(lifecycle)
event = raw.event
parts = event.split('.')
@ -160,8 +163,7 @@ def aggregate_lifecycle(raw):
# *shouldn't* happen).
start = step == 'start'
timing = None
timings = models.Timing.objects.select_related().\
filter(name=name, lifecycle=lifecycle)
timings = STACKDB.find_timings(name=name, lifecycle=lifecycle)
if not start:
for t in timings:
try:
@ -173,7 +175,7 @@ def aggregate_lifecycle(raw):
pass
if timing is None:
timing = models.Timing(name=name, lifecycle=lifecycle)
timing = STACKDB.create_timing(name=name, lifecycle=lifecycle)
if start:
timing.start_raw = raw
@ -197,7 +199,7 @@ def aggregate_lifecycle(raw):
timing.diff = timing.end_when - timing.start_when
# Looks like a valid pair ...
update_kpi(lifecycle, timing, raw)
timing.save()
STACKDB.save(timing)
INSTANCE_EVENT = {

6
tests/__init__.py Normal file
View File

@ -0,0 +1,6 @@
import os
import sys
print "!!!!!!! %s" %__package__
#sys.path = [os.path.abspath(os.path.dirname(__package__))] + sys.path

0
tests/unit/__init__.py Normal file
View File

View File

@ -0,0 +1,126 @@
import datetime
import os
import sys
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
from stacktach import views
import test_utils as utils
class StacktachLifecycleTestCase(unittest.TestCase):
def setUp(self):
self.mox = mox.Mox()
views.STACKDB = self.mox.CreateMockAnything()
def tearDown(self):
pass
def test_aggregate_lifecycle_no_instance(self):
raw = self.mox.CreateMockAnything()
raw.instance = None
views.aggregate_lifecycle(raw)
self.mox.ReplayAll()
self.mox.VerifyAll()
def test_aggregate_lifecycle_start(self):
event_name = 'compute.instance.create'
event = '%s.start' % event_name
when = datetime.datetime.utcnow()
raw = utils.create_raw(self.mox, when, event, state='building')
views.STACKDB.find_lifecycles(instance=INSTANCE_ID_1).AndReturn([])
lifecycle = self.mox.CreateMockAnything()
lifecycle.instance = INSTANCE_ID_1
views.STACKDB.create_lifecycle(instance=INSTANCE_ID_1).AndReturn(lifecycle)
views.STACKDB.save(lifecycle)
views.STACKDB.find_timings(name=event_name, lifecycle=lifecycle).AndReturn([])
timing = utils.create_timing(self.mox, event_name, lifecycle)
views.STACKDB.create_timing(lifecycle=lifecycle, name=event_name).AndReturn(timing)
views.STACKDB.save(timing)
self.mox.ReplayAll()
views.aggregate_lifecycle(raw)
self.assertEqual(lifecycle.last_raw, raw)
self.assertEqual(lifecycle.last_state, 'building')
self.assertEqual(lifecycle.last_task_state, '')
self.assertEqual(timing.name, event_name)
self.assertEqual(timing.lifecycle, lifecycle)
self.assertEqual(timing.start_raw, raw)
self.assertEqual(timing.start_when, when)
self.mox.VerifyAll()
def test_aggregate_lifecycle_end(self):
event_name = 'compute.instance.create'
start_event = '%s.end' % event_name
end_event = '%s.end' % event_name
start_when = datetime.datetime.utcnow()
end_when = datetime.datetime.utcnow()
start_raw = utils.create_raw(self.mox, start_when, start_event,
state='building')
end_raw = utils.create_raw(self.mox, end_when, end_event,
old_task='build')
lifecycle = utils.create_lifecycle(self.mox, INSTANCE_ID_1,
'active', '', start_raw)
views.STACKDB.find_lifecycles(instance=INSTANCE_ID_1).AndReturn([lifecycle])
views.STACKDB.save(lifecycle)
timing = utils.create_timing(self.mox, event_name, lifecycle,
start_raw=start_raw,
start_when=start_when)
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.STACKDB.save(timing)
self.mox.ReplayAll()
views.aggregate_lifecycle(end_raw)
self.assertEqual(lifecycle.last_raw, end_raw)
self.assertEqual(lifecycle.last_state, 'active')
self.assertEqual(lifecycle.last_task_state, 'build')
self.assertEqual(timing.name, event_name)
self.assertEqual(timing.lifecycle, lifecycle)
self.assertEqual(timing.start_raw, start_raw)
self.assertEqual(timing.start_when, start_when)
self.assertEqual(timing.end_raw, end_raw)
self.assertEqual(timing.end_when, end_when)
self.assertEqual(timing.diff, end_when-start_when)
self.mox.UnsetStubs()
self.mox.VerifyAll()
def test_aggregate_lifecycle_update(self):
event = 'compute.instance.update'
when = datetime.datetime.utcnow()
raw = utils.create_raw(self.mox, when, event, old_task='reboot')
views.STACKDB.find_lifecycles(instance=INSTANCE_ID_1).AndReturn([])
lifecycle = self.mox.CreateMockAnything()
lifecycle.instance = INSTANCE_ID_1
views.STACKDB.create_lifecycle(instance=INSTANCE_ID_1).AndReturn(lifecycle)
views.STACKDB.save(lifecycle)
self.mox.StubOutWithMock(views, "start_kpi_tracking")
views.start_kpi_tracking(lifecycle, raw)
self.mox.ReplayAll()
views.aggregate_lifecycle(raw)
self.assertEqual(lifecycle.last_raw, raw)
self.assertEqual(lifecycle.last_state, 'active')
self.assertEqual(lifecycle.last_task_state, 'reboot')
self.mox.UnsetStubs()
self.mox.VerifyAll()

44
tests/unit/test_utils.py Normal file
View File

@ -0,0 +1,44 @@
INSTANCE_ID_1 = 'testinstanceid1'
INSTANCE_ID_2 = 'testinstanceid2'
MESSAGE_ID_1 = 'testmessageid1'
MESSAGE_ID_2 = 'testmessageid2'
REQUEST_ID_1 = 'testrequestid1'
REQUEST_ID_2 = 'testrequestid2'
REQUEST_ID_3 = 'testrequestid3'
def create_raw(mox, when, event, instance=INSTANCE_ID_1,
request_id=REQUEST_ID_1, state='active', old_task='',
host='compute', json=''):
raw = mox.CreateMockAnything()
raw.host = host
raw.instance = instance
raw.event = event
raw.when = when
raw.state = state
raw.old_task = old_task
raw.request_id = request_id,
raw.json = json
return raw
def create_lifecycle(mox, instance, last_state, last_task_state, last_raw):
lifecycle = mox.CreateMockAnything()
lifecycle.instance = instance
lifecycle.last_state = last_state
lifecycle.last_task_state = last_task_state
lifecycle.last_raw = last_raw
return lifecycle
def create_timing(mox, name, lifecycle, start_raw=None, start_when=None,
end_raw=None, end_when=None, diff=None):
timing = mox.CreateMockAnything()
timing.name = name
timing.lifecycle = lifecycle
timing.start_raw = start_raw
timing.start_when = start_when
timing.end_raw = end_raw
timing.end_when = end_when
timing.diff = diff
return timing

28
tox.ini Normal file
View File

@ -0,0 +1,28 @@
[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}