1
from __future__ import generators
2
import unittest, pickle, sys
3
sys.path.insert(0, "../src")
6
class Iterators(unittest.TestCase):
7
one_to_100 = lambda s: iter(range(1, 101))
8
evens = lambda s: iter(range(2, 101, 2))
9
odds = lambda s: iter(range(1, 100, 2))
10
empty = lambda s: iter([])
12
def __init__(self, *args):
13
apply (unittest.TestCase.__init__, (self,) + args)
14
self.falseerror = self.falseerror_maker()
15
self.trueerror = self.trueerror_maker()
16
self.emptygen = self.emptygen_maker()
17
self.typeerror = self.typeerror_maker()
18
self.nameerror = self.nameerror_maker()
20
def falseerror_maker(self):
26
def trueerror_maker(self):
32
def nameerror_maker(self):
36
def typeerror_maker(self):
41
def alwayserror(self, x):
44
def emptygen_maker(self):
48
class IterEqualTestCase(Iterators):
49
"""Tests for iter_equal function"""
51
"""Empty iterators should be equal"""
52
assert Iter.equal(self.empty(), iter([]))
55
"""See if normal iterators are equal"""
56
assert Iter.equal(iter((1,2,3)), iter((1,2,3)))
57
assert Iter.equal(self.odds(), iter(range(1, 100, 2)))
58
assert Iter.equal(iter((1,2,3)), iter(range(1, 4)))
60
def testNormalInequality(self):
61
"""See if normal unequals work"""
62
assert not Iter.equal(iter((1,2,3)), iter((1,2,4)))
63
assert not Iter.equal(self.odds(), iter(["hello", "there"]))
65
def testGenerators(self):
66
"""equals works for generators"""
73
assert Iter.equal(f(), g())
76
"""Differently sized iterators"""
77
assert not Iter.equal(iter((1,2,3)), iter((1,2)))
78
assert not Iter.equal(iter((1,2)), iter((1,2,3)))
81
class FilterTestCase(Iterators):
82
"""Tests for lazy_filter function"""
84
"""empty iterators -> empty iterators"""
85
assert Iter.empty(Iter.filter(self.alwayserror,
87
"Filtering an empty iterator should result in empty iterator"
90
"""Test numbers 1 - 100 #1"""
91
assert Iter.equal(Iter.filter(lambda x: x % 2 == 0,
94
assert Iter.equal(Iter.filter(lambda x: x % 2,
99
"""Should raise appropriate error"""
100
i = Iter.filter(lambda x: x, self.falseerror_maker())
101
self.assertRaises(Exception, i.next)
104
class MapTestCase(Iterators):
105
"""Test mapping of iterators"""
106
def testNumbers(self):
107
"""1 to 100 * 2 = 2 to 200"""
108
assert Iter.equal(Iter.map(lambda x: 2*x, self.one_to_100()),
109
iter(range(2, 201, 2)))
111
def testShortcut(self):
112
"""Map should go in order"""
116
i = Iter.map(f, self.trueerror_maker())
118
self.assertRaises(NameError, i.next)
121
"""Map of an empty iterator is empty"""
122
assert Iter.empty(Iter.map(lambda x: x, iter([])))
125
class CatTestCase(Iterators):
126
"""Test concatenation of iterators"""
128
"""Empty + empty = empty"""
129
assert Iter.empty(Iter.cat(iter([]), iter([])))
131
def testNumbers(self):
132
"""1 to 50 + 51 to 100 = 1 to 100"""
133
assert Iter.equal(Iter.cat(iter(range(1, 51)), iter(range(51, 101))),
136
def testShortcut(self):
137
"""Process iterators in order"""
138
i = Iter.cat(self.typeerror_maker(), self.nameerror_maker())
141
self.assertRaises(TypeError, i.next)
144
class AndOrTestCase(Iterators):
145
"""Test And and Or"""
147
"""And() -> true, Or() -> false"""
148
assert Iter.And(self.empty())
149
assert not Iter.Or(self.empty())
151
def testAndShortcut(self):
152
"""And should return if any false"""
153
assert Iter.And(self.falseerror_maker()) is None
155
def testOrShortcut(self):
156
"""Or should return if any true"""
157
assert Iter.Or(self.trueerror_maker()) == 1
159
def testNormalAnd(self):
160
"""And should go through true iterators, picking last"""
161
assert Iter.And(iter([1,2,3,4])) == 4
162
self.assertRaises(Exception, Iter.And, self.trueerror_maker())
164
def testNormalOr(self):
165
"""Or goes through false iterators, picking last"""
166
assert Iter.Or(iter([0, None, []])) == []
167
self.assertRaises(Exception, Iter.Or, self.falseerror_maker())
170
class FoldingTest(Iterators):
171
"""Test folding operations"""
172
def f(self, x, y): return x + y
175
"""Folds of empty iterators should produce defaults"""
176
assert Iter.foldl(self.f, 23, self.empty()) == 23
177
assert Iter.foldr(self.f, 32, self.empty()) == 32
179
def testAddition(self):
180
"""Use folds to sum lists"""
181
assert Iter.foldl(self.f, 0, self.one_to_100()) == 5050
182
assert Iter.foldr(self.f, 0, self.one_to_100()) == 5050
184
def testLargeAddition(self):
185
"""Folds on 10000 element iterators"""
186
assert Iter.foldl(self.f, 0, iter(range(1, 10001))) == 50005000
187
self.assertRaises(RuntimeError,
188
Iter.foldr, self.f, 0, iter(range(1, 10001)))
191
"""Use folds to calculate length of lists"""
192
assert Iter.foldl(lambda x, y: x+1, 0, self.evens()) == 50
193
assert Iter.foldr(lambda x, y: y+1, 0, self.odds()) == 50
195
class MultiplexTest(Iterators):
196
def testSingle(self):
197
"""Test multiplex single stream"""
198
i_orig = self.one_to_100()
199
i2_orig = self.one_to_100()
200
i = Iter.multiplex(i_orig, 1)[0]
201
assert Iter.equal(i, i2_orig)
203
def testTrible(self):
204
"""Test splitting iterator into three"""
206
def ff(x): counter[0] += 1
207
i_orig = self.one_to_100()
208
i2_orig = self.one_to_100()
209
i1, i2, i3 = Iter.multiplex(i_orig, 3, ff)
210
assert Iter.equal(i1, i2)
211
assert Iter.equal(i3, i2_orig)
212
assert counter[0] == 100, counter
214
def testDouble(self):
215
"""Test splitting into two..."""
216
i1, i2 = Iter.multiplex(self.one_to_100(), 2)
217
assert Iter.equal(i1, self.one_to_100())
218
assert Iter.equal(i2, self.one_to_100())
221
class ITRBadder(ITRBranch):
222
def start_process(self, index):
225
def end_process(self):
227
summand = self.base_index[-1]
228
#print "Adding ", summand
229
self.total += summand
231
def branch_process(self, subinstance):
232
#print "Adding subinstance ", subinstance.total
233
self.total += subinstance.total
235
class ITRBadder2(ITRBranch):
236
def start_process(self, index):
239
def end_process(self):
240
#print "Adding ", self.base_index
241
self.total += reduce(lambda x,y: x+y, self.base_index, 0)
243
def can_fast_process(self, index):
244
if len(index) == 3: return 1
247
def fast_process(self, index):
248
self.total += index[0] + index[1] + index[2]
250
def branch_process(self, subinstance):
251
#print "Adding branch ", subinstance.total
252
self.total += subinstance.total
254
class TreeReducerTest(unittest.TestCase):
256
self.i1 = [(), (1,), (2,), (3,)]
257
self.i2 = [(0,), (0,1), (0,1,0), (0,1,1), (0,2), (0,2,1), (0,3)]
259
self.i1a = [(), (1,)]
260
self.i1b = [(2,), (3,)]
261
self.i2a = [(0,), (0,1), (0,1,0)]
262
self.i2b = [(0,1,1), (0,2)]
263
self.i2c = [(0,2,1), (0,3)]
265
def testTreeReducer(self):
266
"""testing IterTreeReducer"""
267
itm = IterTreeReducer(ITRBadder, [])
268
for index in self.i1:
270
assert val, (val, index)
272
assert itm.root_branch.total == 6, itm.root_branch.total
274
itm2 = IterTreeReducer(ITRBadder2, [])
275
for index in self.i2:
277
if index == (): assert not val
280
assert itm2.root_branch.total == 12, itm2.root_branch.total
282
def testTreeReducerState(self):
283
"""Test saving and recreation of an IterTreeReducer"""
284
itm1a = IterTreeReducer(ITRBadder, [])
285
for index in self.i1a:
288
itm1b = pickle.loads(pickle.dumps(itm1a))
289
for index in self.i1b:
293
assert itm1b.root_branch.total == 6, itm1b.root_branch.total
295
itm2a = IterTreeReducer(ITRBadder2, [])
296
for index in self.i2a:
298
if index == (): assert not val
300
itm2b = pickle.loads(pickle.dumps(itm2a))
301
for index in self.i2b:
303
if index == (): assert not val
305
itm2c = pickle.loads(pickle.dumps(itm2b))
306
for index in self.i2c:
308
if index == (): assert not val
311
assert itm2c.root_branch.total == 12, itm2c.root_branch.total
314
if __name__ == "__main__": unittest.main()