PageRenderTime 41ms CodeModel.GetById 9ms app.highlight 26ms RepoModel.GetById 2ms app.codeStats 0ms

/test_apiary/apiarytests.py

https://bitbucket.org/lindenlab/apiary/
Python | 252 lines | 187 code | 40 blank | 25 comment | 19 complexity | 7493dcc5be4a1995e99b6e00b58d595b MD5 | raw file
  1#
  2# $LicenseInfo:firstyear=2010&license=mit$
  3# 
  4# Copyright (c) 2010, Linden Research, Inc.
  5# 
  6# Permission is hereby granted, free of charge, to any person obtaining a copy
  7# of this software and associated documentation files (the "Software"), to deal
  8# in the Software without restriction, including without limitation the rights
  9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10# copies of the Software, and to permit persons to whom the Software is
 11# furnished to do so, subject to the following conditions:
 12# 
 13# The above copyright notice and this permission notice shall be included in
 14# all copies or substantial portions of the Software.
 15# 
 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22# THE SOFTWARE.
 23# $/LicenseInfo$
 24#
 25
 26import sys
 27import time
 28import threading
 29import unittest
 30
 31import apiary
 32from apiary.base import Messages
 33#import apiary.tools.debug ; apiary.tools.debug.enable_debug()
 34
 35import amqplib.client_0_8 as amqp
 36
 37
 38class SimpleWorkerBee(apiary.WorkerBee):
 39    def __init__(self, options, arguments):
 40        apiary.WorkerBee.__init__(self, options, arguments)
 41        self._result = ''
 42    
 43    def start(self):
 44        self._result = '('
 45    
 46    def event(self, data):
 47        self._result += data
 48    
 49    def end(self):
 50        self._result += ')'
 51        return self._result
 52        
 53
 54class SimpleQueenBee(apiary.QueenBee):
 55    def __init__(self, options, arguments):
 56        apiary.QueenBee.__init__(self, options, arguments)
 57        self.results = []
 58        self._events = []
 59        self._startfn = self.start
 60        self._eventfn = self.event
 61        self._endfn = self.end
 62    
 63    def addstart(self, seq):
 64        self._events.append([self._startfn, seq])
 65    
 66    def addevent(self, seq, data):
 67        self._events.append([self._eventfn, seq, data])
 68    
 69    def addend(self, seq):
 70        self._events.append([self._endfn, seq])
 71    
 72    def addstringseq(self, seq, data):
 73        self.addstart(seq)
 74        for c in data:
 75            self.addevent(seq, c)
 76        self.addend(seq)
 77    
 78    def addsleep(self, t=0.25):
 79        self._events.append([time.sleep, t])
 80        
 81    def next(self):
 82        if not self._events:
 83            return False
 84        e = self._events.pop(0)
 85        e[0](*e[1:])
 86        return True
 87    
 88    def result(self, seq, data):
 89        self.results.append(data)
 90
 91
 92class apiaryTestCase(unittest.TestCase):
 93    def setUp(self):
 94        args = ['--protocol', 'mysql']
 95        self.options = apiary.parse_args(args)[0]
 96        self._transport = None
 97        self._open = False
 98        self._threads = []
 99        apiary.clean(self.options)
100        
101    def tearDown(self):
102        self.close()
103        self.join_workers()
104        # if connect() fails, don't try to clean up
105        try:
106            self.connect()
107        except apiary.ConnectionError:
108            pass
109        else:
110            apiary.clean(self.options)
111        
112    def connect(self):
113        if self._transport is None:
114            self._transport = apiary.Transport(self.options)
115            self.send = self._transport.send
116        self._transport.connect()
117        self._open = True
118                
119    def close(self):
120        if self._open:
121            self._transport.close()
122            self._open = False
123    
124    def start_workers(self, cls=SimpleWorkerBee, n=1):
125        threads = [threading.Thread(target=apiary.run_worker, args=(cls, self.options, [])) for i in range(n)]
126        [t.start() for t in threads]
127        f = sys._getframe(1)
128        name = "Worker-%s:%d-" % (f.f_code.co_name, f.f_lineno)
129        for i in xrange(0,len(threads)):
130            threads[i].setName(name + str(i+1))
131        self._threads += threads
132        
133    def join_workers(self):
134        for t in self._threads:
135            t.join(5.0)
136            if t.isAlive():
137                raise Exception("thread %s never died" % t.getName())
138        self._threads = []
139
140
141class TestWorkerBee(apiaryTestCase):
142    def testNoWork(self):
143        self.start_workers(SimpleWorkerBee, 1)
144        
145        time.sleep(0.1)
146        self.connect()
147        self._transport.queue('worker-job')
148        self._transport.send('worker-job', Messages.StopWorker)
149
150        self.join_workers()
151        self.close()
152        
153
154class TestBasics(apiaryTestCase):
155
156    def testEmptyQueenBee(self):
157        c = SimpleQueenBee(self.options, [])
158        c.main()
159        
160    def testOneSeq(self):
161        c = SimpleQueenBee(self.options, [])
162        c.addstringseq('aaa', ['1234.5	abc'])
163
164        self.start_workers(SimpleWorkerBee, 1)
165
166        c.main()
167        
168        r = ','.join(c.results)
169        self.assert_('(1234.5	abc)' in r)
170        
171        self.join_workers()
172
173    def testTwoSeq(self):
174        c = SimpleQueenBee(self.options, [])
175        c.addstringseq('aaa', ['1234.5	abc'])
176        c.addstringseq('xxx', ['4321.0	xyz'])
177        
178        self.start_workers(SimpleWorkerBee, 1)
179        
180        c.main()
181        r = ','.join(c.results)
182        self.assert_('(1234.5	abc)' in r)
183        self.assert_('(4321.0	xyz)' in r)
184        
185        self.join_workers()
186
187        
188    def testTwoSeq2(self):
189        c = SimpleQueenBee(self.options, [])
190        c.addstringseq('aaa', ['1234.5	abc'])
191        c.addstringseq('xxx', ['4321.0	xyz'])
192        
193        self.start_workers(SimpleWorkerBee, 2)
194        
195        c.main()
196        r = ','.join(c.results)
197        self.assert_('(1234.5	abc)' in r)
198        self.assert_('(4321.0	xyz)' in r)
199
200        self.join_workers()
201
202    def testTwoSeq2Interleaved(self):
203        c = SimpleQueenBee(self.options, [])
204        c.addstart('aaa')
205        c.addstart('xxx')
206        c.addsleep()
207        c.addevent('aaa', '1234.5	a')
208        c.addevent('xxx', '4321.0	x')
209        c.addsleep()
210        c.addevent('xxx', '4321.1	y')
211        c.addevent('aaa', '1234.6	b')
212        c.addsleep()
213        c.addevent('aaa', '1234.7	c')
214        c.addevent('xxx', '4321.2	z')
215        c.addsleep()
216        c.addend('aaa')
217        c.addend('xxx')
218        
219        self.start_workers(SimpleWorkerBee, 2)
220        
221        c.main()
222        r = ','.join(c.results)
223        self.assert_('(1234.5	a1234.6	b1234.7	c)' in r)
224        self.assert_('(4321.0	x4321.1	y4321.2	z)' in r)
225        
226        self.join_workers()
227
228
229class TestErrors(apiaryTestCase):
230    def do_nothing(self):
231        pass
232
233    def testConnectionError(self):
234        self.options.amqp_host = "localhost:1"
235        self._transport = apiary.Transport(self.options)
236        self.assertRaises(apiary.ConnectionError, self.connect)
237 
238    def testExclusiveQueueUse(self):
239        self._transport = apiary.Transport(self.options)
240        self._transport.connect()
241        self._transport.usequeue('minder-end')
242        self._transport.consume('minder-end', 'm0', self.do_nothing)
243        self._transport2 = apiary.Transport(self.options)
244        self._transport2.connect()
245        self._transport2.usequeue('minder-end')
246        self.assertRaises(amqp.AMQPChannelException, self._transport2.consume, 'minder-end', 'm0', self.do_nothing)
247        self._transport.close()
248        self._transport2.close()
249
250
251if __name__ == '__main__':
252    unittest.main()