| 1 |
"""OLAP Test fixture for Storage Managers.""" |
|---|
| 2 |
|
|---|
| 3 |
import datetime |
|---|
| 4 |
dt = datetime.datetime |
|---|
| 5 |
td = datetime.timedelta |
|---|
| 6 |
import os |
|---|
| 7 |
thisdir = os.path.dirname(__file__) |
|---|
| 8 |
logname = os.path.join(thisdir, "olaptest.log") |
|---|
| 9 |
|
|---|
| 10 |
import sys |
|---|
| 11 |
import traceback |
|---|
| 12 |
import unittest |
|---|
| 13 |
|
|---|
| 14 |
import dejavu |
|---|
| 15 |
from dejavu import Unit, UnitProperty |
|---|
| 16 |
from dejavu.test import tools |
|---|
| 17 |
from dejavu import views |
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
class Clinic(Unit): |
|---|
| 21 |
Name = UnitProperty() |
|---|
| 22 |
Type = UnitProperty() |
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
class Argument(Unit): |
|---|
| 26 |
Topic = UnitProperty() |
|---|
| 27 |
Start = UnitProperty(dt) |
|---|
| 28 |
Duration = UnitProperty(datetime.timedelta) |
|---|
| 29 |
ClinicID = UnitProperty(int, index=True) |
|---|
| 30 |
|
|---|
| 31 |
Argument.many_to_one('ClinicID', Clinic, 'ID') |
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
class Participant(Unit): |
|---|
| 35 |
DirectoryID = UnitProperty(int, index=True) |
|---|
| 36 |
ArgumentID = UnitProperty(int, index=True) |
|---|
| 37 |
|
|---|
| 38 |
Participant.many_to_one('ArgumentID', Argument, 'ID') |
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 |
class Directory(Unit): |
|---|
| 42 |
Name = UnitProperty() |
|---|
| 43 |
Birth = UnitProperty(datetime.date) |
|---|
| 44 |
Gender = UnitProperty() |
|---|
| 45 |
|
|---|
| 46 |
Directory.one_to_many('ID', Participant, 'DirectoryID') |
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
class OLAPTests(unittest.TestCase): |
|---|
| 50 |
|
|---|
| 51 |
def test_1_populate(self): |
|---|
| 52 |
box = store.new_sandbox() |
|---|
| 53 |
|
|---|
| 54 |
c = Clinic(Name = 'The Argument Clinic') |
|---|
| 55 |
box.memorize(c) |
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 |
brown = Directory(Name='Sam Brown', Birth=datetime.date(1973, 3, 4), |
|---|
| 59 |
Gender='Male') |
|---|
| 60 |
green = Directory(Name='David Green', Birth=datetime.date(1988, 11, 21), |
|---|
| 61 |
Gender='Male') |
|---|
| 62 |
white = Directory(Name='Alice White', Birth=datetime.date(1964, 9, 8), |
|---|
| 63 |
Gender='Female') |
|---|
| 64 |
for person in (brown, green, white): |
|---|
| 65 |
box.memorize(person) |
|---|
| 66 |
|
|---|
| 67 |
|
|---|
| 68 |
sixtynine = dt(1969, 1, 1) |
|---|
| 69 |
for s in range(5): |
|---|
| 70 |
for d in range(12): |
|---|
| 71 |
arg = Argument(Topic = "What is an Argument?", |
|---|
| 72 |
Start = sixtynine + td(s * 13.54 + d * 30), |
|---|
| 73 |
Duration = td(minutes=d * 5), |
|---|
| 74 |
ClinicID = c.ID, |
|---|
| 75 |
) |
|---|
| 76 |
box.memorize(arg) |
|---|
| 77 |
box.memorize(Participant(DirectoryID=brown.ID, ArgumentID=arg.ID)) |
|---|
| 78 |
if d % 2: |
|---|
| 79 |
box.memorize(Participant(DirectoryID=green.ID, ArgumentID=arg.ID)) |
|---|
| 80 |
else: |
|---|
| 81 |
box.memorize(Participant(DirectoryID=white.ID, ArgumentID=arg.ID)) |
|---|
| 82 |
box.flush_all() |
|---|
| 83 |
|
|---|
| 84 |
def test_2_simple_views(self): |
|---|
| 85 |
|
|---|
| 86 |
sixtynine = dt(1969, 1, 1) |
|---|
| 87 |
expected = [] |
|---|
| 88 |
for s in range(5): |
|---|
| 89 |
for d in range(12): |
|---|
| 90 |
expected.append((sixtynine + td(s * 13.54 + d * 30), |
|---|
| 91 |
td(minutes=d * 5)) |
|---|
| 92 |
) |
|---|
| 93 |
expected.sort() |
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 |
times = views.View((Argument, ['Start', 'Duration'], |
|---|
| 97 |
lambda a: a.Topic == 'What is an Argument?')) |
|---|
| 98 |
|
|---|
| 99 |
|
|---|
| 100 |
clsname = 'WhatIsAnArgumentTimes' |
|---|
| 101 |
snap = times.results(clsname, store) |
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
snapclass = snap.unitclass(store) |
|---|
| 105 |
self.assertEqual(snapclass.__name__, clsname) |
|---|
| 106 |
|
|---|
| 107 |
|
|---|
| 108 |
actual = store.view((snapclass, ['Start', 'Duration'])) |
|---|
| 109 |
actual.sort() |
|---|
| 110 |
|
|---|
| 111 |
|
|---|
| 112 |
|
|---|
| 113 |
self.assertEqual(actual, expected) |
|---|
| 114 |
|
|---|
| 115 |
def test_3_multidim_views(self): |
|---|
| 116 |
box = store.new_sandbox() |
|---|
| 117 |
brownid = box.unit(Directory, Name='Sam Brown').ID |
|---|
| 118 |
box.flush_all() |
|---|
| 119 |
|
|---|
| 120 |
brownargs = views.View((Clinic << Argument << Participant, |
|---|
| 121 |
[['ID', 'Name'], None, None], |
|---|
| 122 |
lambda c, a, p: p.DirectoryID == brownid)) |
|---|
| 123 |
clsname = 'BrownClinics' |
|---|
| 124 |
snap = brownargs.results(clsname, store) |
|---|
| 125 |
snapclass = snap.unitclass(store) |
|---|
| 126 |
self.assertEqual(snapclass.__name__, clsname) |
|---|
| 127 |
actual = store.view((snapclass, ['Name'])) |
|---|
| 128 |
actual.sort() |
|---|
| 129 |
self.assertEqual(actual, [(u'The Argument Clinic',)] * 60) |
|---|
| 130 |
|
|---|
| 131 |
def test_4_aggregate_views(self): |
|---|
| 132 |
firstargs = views.View((Argument << Participant << Directory, |
|---|
| 133 |
lambda a, p, d: [d.Name, min(a.Start)])) |
|---|
| 134 |
clsname = 'FirstArgument' |
|---|
| 135 |
snap = firstargs.results(clsname, store) |
|---|
| 136 |
snapclass = snap.unitclass(store) |
|---|
| 137 |
self.assertEqual(snapclass.__name__, clsname) |
|---|
| 138 |
actual = store.view((snapclass, )) |
|---|
| 139 |
actual.sort() |
|---|
| 140 |
self.assertEqual(actual, [(u'Alice White', dt(1969, 1, 1)), |
|---|
| 141 |
(u'David Green', dt(1969, 1, 31)), |
|---|
| 142 |
(u'Sam Brown', dt(1969, 1, 1)), |
|---|
| 143 |
]) |
|---|
| 144 |
|
|---|
| 145 |
|
|---|
| 146 |
store = dejavu.VerticalPartitioner() |
|---|
| 147 |
|
|---|
| 148 |
def _djvlog(message): |
|---|
| 149 |
"""Dejavu logger (writes to error.log).""" |
|---|
| 150 |
if isinstance(message, unicode): |
|---|
| 151 |
message = message.encode('utf8') |
|---|
| 152 |
s = "%s %s" % (dt.now().isoformat(), message) |
|---|
| 153 |
f = open(logname, 'ab') |
|---|
| 154 |
f.write(s + '\n') |
|---|
| 155 |
f.close() |
|---|
| 156 |
|
|---|
| 157 |
def init(): |
|---|
| 158 |
global store |
|---|
| 159 |
store = dejavu.VerticalPartitioner() |
|---|
| 160 |
store.log = _djvlog |
|---|
| 161 |
store.logflags = (dejavu.logflags.ERROR + dejavu.logflags.SQL + |
|---|
| 162 |
dejavu.logflags.IO) |
|---|
| 163 |
|
|---|
| 164 |
def setup(SM_class, opts): |
|---|
| 165 |
"""Set up storage for Clinic classes.""" |
|---|
| 166 |
sm = store.add_store('test_clinic', SM_class, opts) |
|---|
| 167 |
v = getattr(sm, "version", None) |
|---|
| 168 |
if v: |
|---|
| 169 |
print v() |
|---|
| 170 |
sm.create_database() |
|---|
| 171 |
|
|---|
| 172 |
store.register_all(globals()) |
|---|
| 173 |
views.register_classes(store) |
|---|
| 174 |
store.map_all('repair') |
|---|
| 175 |
|
|---|
| 176 |
def teardown(): |
|---|
| 177 |
"""Tear down storage for Clinic classes.""" |
|---|
| 178 |
for store in store.stores.values(): |
|---|
| 179 |
try: |
|---|
| 180 |
store.drop_database() |
|---|
| 181 |
except (AttributeError, NotImplementedError): |
|---|
| 182 |
pass |
|---|
| 183 |
store.stores = {} |
|---|
| 184 |
store.shutdown() |
|---|
| 185 |
|
|---|
| 186 |
def run(SM_class, opts): |
|---|
| 187 |
"""Run the clinic fixture.""" |
|---|
| 188 |
try: |
|---|
| 189 |
try: |
|---|
| 190 |
setup(SM_class, opts) |
|---|
| 191 |
loader = unittest.TestLoader().loadTestsFromTestCase |
|---|
| 192 |
|
|---|
| 193 |
|
|---|
| 194 |
case = loader(OLAPTests) |
|---|
| 195 |
startTime = dt.now() |
|---|
| 196 |
tools.djvTestRunner.run(case) |
|---|
| 197 |
print "Ran clinic case in:", dt.now() - startTime |
|---|
| 198 |
except: |
|---|
| 199 |
traceback.print_exc() |
|---|
| 200 |
finally: |
|---|
| 201 |
teardown() |
|---|