Add python-eventlet 0.16.1
[packages/trusty/python-eventlet.git] / eventlet / tests / pools_test.py
1 from unittest import TestCase, main
2
3 import eventlet
4 from eventlet import Queue
5 from eventlet import pools
6 from eventlet.support import six
7
8
9 class IntPool(pools.Pool):
10     def create(self):
11         self.current_integer = getattr(self, 'current_integer', 0) + 1
12         return self.current_integer
13
14
15 class TestIntPool(TestCase):
16     def setUp(self):
17         self.pool = IntPool(min_size=0, max_size=4)
18
19     def test_integers(self):
20         # Do not actually use this pattern in your code. The pool will be
21         # exhausted, and unrestoreable.
22         # If you do a get, you should ALWAYS do a put, probably like this:
23         # try:
24         #     thing = self.pool.get()
25         # do stuff
26         # finally:
27         #     self.pool.put(thing)
28
29         # with self.pool.some_api_name() as thing:
30         # do stuff
31         self.assertEqual(self.pool.get(), 1)
32         self.assertEqual(self.pool.get(), 2)
33         self.assertEqual(self.pool.get(), 3)
34         self.assertEqual(self.pool.get(), 4)
35
36     def test_free(self):
37         self.assertEqual(self.pool.free(), 4)
38         gotten = self.pool.get()
39         self.assertEqual(self.pool.free(), 3)
40         self.pool.put(gotten)
41         self.assertEqual(self.pool.free(), 4)
42
43     def test_exhaustion(self):
44         waiter = Queue(0)
45
46         def consumer():
47             gotten = None
48             try:
49                 gotten = self.pool.get()
50             finally:
51                 waiter.put(gotten)
52
53         eventlet.spawn(consumer)
54
55         one, two, three, four = (
56             self.pool.get(), self.pool.get(), self.pool.get(), self.pool.get())
57         self.assertEqual(self.pool.free(), 0)
58
59         # Let consumer run; nothing will be in the pool, so he will wait
60         eventlet.sleep(0)
61
62         # Wake consumer
63         self.pool.put(one)
64
65         # wait for the consumer
66         self.assertEqual(waiter.get(), one)
67
68     def test_blocks_on_pool(self):
69         waiter = Queue(0)
70
71         def greedy():
72             self.pool.get()
73             self.pool.get()
74             self.pool.get()
75             self.pool.get()
76             # No one should be waiting yet.
77             self.assertEqual(self.pool.waiting(), 0)
78             # The call to the next get will unschedule this routine.
79             self.pool.get()
80             # So this put should never be called.
81             waiter.put('Failed!')
82
83         killable = eventlet.spawn(greedy)
84
85         # no one should be waiting yet.
86         self.assertEqual(self.pool.waiting(), 0)
87
88         # Wait for greedy
89         eventlet.sleep(0)
90
91         # Greedy should be blocking on the last get
92         self.assertEqual(self.pool.waiting(), 1)
93
94         # Send will never be called, so balance should be 0.
95         self.assertFalse(not waiter.full())
96
97         eventlet.kill(killable)
98
99     def test_ordering(self):
100         # normal case is that items come back out in the
101         # same order they are put
102         one, two = self.pool.get(), self.pool.get()
103         self.pool.put(one)
104         self.pool.put(two)
105         self.assertEqual(self.pool.get(), one)
106         self.assertEqual(self.pool.get(), two)
107
108     def test_putting_to_queue(self):
109         timer = eventlet.Timeout(0.1)
110         try:
111             size = 2
112             self.pool = IntPool(min_size=0, max_size=size)
113             queue = Queue()
114             results = []
115
116             def just_put(pool_item, index):
117                 self.pool.put(pool_item)
118                 queue.put(index)
119             for index in six.moves.range(size + 1):
120                 pool_item = self.pool.get()
121                 eventlet.spawn(just_put, pool_item, index)
122
123             for _ in six.moves.range(size + 1):
124                 x = queue.get()
125                 results.append(x)
126             self.assertEqual(sorted(results), list(six.moves.range(size + 1)))
127         finally:
128             timer.cancel()
129
130     def test_resize(self):
131         pool = IntPool(max_size=2)
132         a = pool.get()
133         b = pool.get()
134         self.assertEqual(pool.free(), 0)
135
136         # verify that the pool discards excess items put into it
137         pool.resize(1)
138         pool.put(a)
139         pool.put(b)
140         self.assertEqual(pool.free(), 1)
141
142         # resize larger and assert that there are more free items
143         pool.resize(2)
144         self.assertEqual(pool.free(), 2)
145
146     def test_create_contention(self):
147         creates = [0]
148
149         def sleep_create():
150             creates[0] += 1
151             eventlet.sleep()
152             return "slept"
153
154         p = pools.Pool(max_size=4, create=sleep_create)
155
156         def do_get():
157             x = p.get()
158             self.assertEqual(x, "slept")
159             p.put(x)
160
161         gp = eventlet.GreenPool()
162         for i in six.moves.range(100):
163             gp.spawn_n(do_get)
164         gp.waitall()
165         self.assertEqual(creates[0], 4)
166
167
168 class TestAbstract(TestCase):
169     mode = 'static'
170
171     def test_abstract(self):
172         # Going for 100% coverage here
173         # A Pool cannot be used without overriding create()
174         pool = pools.Pool()
175         self.assertRaises(NotImplementedError, pool.get)
176
177
178 class TestIntPool2(TestCase):
179     mode = 'static'
180
181     def setUp(self):
182         self.pool = IntPool(min_size=3, max_size=3)
183
184     def test_something(self):
185         self.assertEqual(len(self.pool.free_items), 3)
186         # Cover the clause in get where we get from the free list instead of creating
187         # an item on get
188         gotten = self.pool.get()
189         self.assertEqual(gotten, 1)
190
191
192 class TestOrderAsStack(TestCase):
193     mode = 'static'
194
195     def setUp(self):
196         self.pool = IntPool(max_size=3, order_as_stack=True)
197
198     def test_ordering(self):
199         # items come out in the reverse order they are put
200         one, two = self.pool.get(), self.pool.get()
201         self.pool.put(one)
202         self.pool.put(two)
203         self.assertEqual(self.pool.get(), two)
204         self.assertEqual(self.pool.get(), one)
205
206
207 class RaisePool(pools.Pool):
208     def create(self):
209         raise RuntimeError()
210
211
212 class TestCreateRaises(TestCase):
213     mode = 'static'
214
215     def setUp(self):
216         self.pool = RaisePool(max_size=3)
217
218     def test_it(self):
219         self.assertEqual(self.pool.free(), 3)
220         self.assertRaises(RuntimeError, self.pool.get)
221         self.assertEqual(self.pool.free(), 3)
222
223
224 ALWAYS = RuntimeError('I always fail')
225 SOMETIMES = RuntimeError('I fail half the time')
226
227
228 class TestTookTooLong(Exception):
229     pass
230
231 if __name__ == '__main__':
232     main()