PageRenderTime 16ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/test_apiary/apiarytests.py

https://bitbucket.org/lindenlab/apiary/
Python | 252 lines | 187 code | 40 blank | 25 comment | 12 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. import sys
  26. import time
  27. import threading
  28. import unittest
  29. import apiary
  30. from apiary.base import Messages
  31. #import apiary.tools.debug ; apiary.tools.debug.enable_debug()
  32. import amqplib.client_0_8 as amqp
  33. class SimpleWorkerBee(apiary.WorkerBee):
  34. def __init__(self, options, arguments):
  35. apiary.WorkerBee.__init__(self, options, arguments)
  36. self._result = ''
  37. def start(self):
  38. self._result = '('
  39. def event(self, data):
  40. self._result += data
  41. def end(self):
  42. self._result += ')'
  43. return self._result
  44. class SimpleQueenBee(apiary.QueenBee):
  45. def __init__(self, options, arguments):
  46. apiary.QueenBee.__init__(self, options, arguments)
  47. self.results = []
  48. self._events = []
  49. self._startfn = self.start
  50. self._eventfn = self.event
  51. self._endfn = self.end
  52. def addstart(self, seq):
  53. self._events.append([self._startfn, seq])
  54. def addevent(self, seq, data):
  55. self._events.append([self._eventfn, seq, data])
  56. def addend(self, seq):
  57. self._events.append([self._endfn, seq])
  58. def addstringseq(self, seq, data):
  59. self.addstart(seq)
  60. for c in data:
  61. self.addevent(seq, c)
  62. self.addend(seq)
  63. def addsleep(self, t=0.25):
  64. self._events.append([time.sleep, t])
  65. def next(self):
  66. if not self._events:
  67. return False
  68. e = self._events.pop(0)
  69. e[0](*e[1:])
  70. return True
  71. def result(self, seq, data):
  72. self.results.append(data)
  73. class apiaryTestCase(unittest.TestCase):
  74. def setUp(self):
  75. args = ['--protocol', 'mysql']
  76. self.options = apiary.parse_args(args)[0]
  77. self._transport = None
  78. self._open = False
  79. self._threads = []
  80. apiary.clean(self.options)
  81. def tearDown(self):
  82. self.close()
  83. self.join_workers()
  84. # if connect() fails, don't try to clean up
  85. try:
  86. self.connect()
  87. except apiary.ConnectionError:
  88. pass
  89. else:
  90. apiary.clean(self.options)
  91. def connect(self):
  92. if self._transport is None:
  93. self._transport = apiary.Transport(self.options)
  94. self.send = self._transport.send
  95. self._transport.connect()
  96. self._open = True
  97. def close(self):
  98. if self._open:
  99. self._transport.close()
  100. self._open = False
  101. def start_workers(self, cls=SimpleWorkerBee, n=1):
  102. threads = [threading.Thread(target=apiary.run_worker, args=(cls, self.options, [])) for i in range(n)]
  103. [t.start() for t in threads]
  104. f = sys._getframe(1)
  105. name = "Worker-%s:%d-" % (f.f_code.co_name, f.f_lineno)
  106. for i in xrange(0,len(threads)):
  107. threads[i].setName(name + str(i+1))
  108. self._threads += threads
  109. def join_workers(self):
  110. for t in self._threads:
  111. t.join(5.0)
  112. if t.isAlive():
  113. raise Exception("thread %s never died" % t.getName())
  114. self._threads = []
  115. class TestWorkerBee(apiaryTestCase):
  116. def testNoWork(self):
  117. self.start_workers(SimpleWorkerBee, 1)
  118. time.sleep(0.1)
  119. self.connect()
  120. self._transport.queue('worker-job')
  121. self._transport.send('worker-job', Messages.StopWorker)
  122. self.join_workers()
  123. self.close()
  124. class TestBasics(apiaryTestCase):
  125. def testEmptyQueenBee(self):
  126. c = SimpleQueenBee(self.options, [])
  127. c.main()
  128. def testOneSeq(self):
  129. c = SimpleQueenBee(self.options, [])
  130. c.addstringseq('aaa', ['1234.5 abc'])
  131. self.start_workers(SimpleWorkerBee, 1)
  132. c.main()
  133. r = ','.join(c.results)
  134. self.assert_('(1234.5 abc)' in r)
  135. self.join_workers()
  136. def testTwoSeq(self):
  137. c = SimpleQueenBee(self.options, [])
  138. c.addstringseq('aaa', ['1234.5 abc'])
  139. c.addstringseq('xxx', ['4321.0 xyz'])
  140. self.start_workers(SimpleWorkerBee, 1)
  141. c.main()
  142. r = ','.join(c.results)
  143. self.assert_('(1234.5 abc)' in r)
  144. self.assert_('(4321.0 xyz)' in r)
  145. self.join_workers()
  146. def testTwoSeq2(self):
  147. c = SimpleQueenBee(self.options, [])
  148. c.addstringseq('aaa', ['1234.5 abc'])
  149. c.addstringseq('xxx', ['4321.0 xyz'])
  150. self.start_workers(SimpleWorkerBee, 2)
  151. c.main()
  152. r = ','.join(c.results)
  153. self.assert_('(1234.5 abc)' in r)
  154. self.assert_('(4321.0 xyz)' in r)
  155. self.join_workers()
  156. def testTwoSeq2Interleaved(self):
  157. c = SimpleQueenBee(self.options, [])
  158. c.addstart('aaa')
  159. c.addstart('xxx')
  160. c.addsleep()
  161. c.addevent('aaa', '1234.5 a')
  162. c.addevent('xxx', '4321.0 x')
  163. c.addsleep()
  164. c.addevent('xxx', '4321.1 y')
  165. c.addevent('aaa', '1234.6 b')
  166. c.addsleep()
  167. c.addevent('aaa', '1234.7 c')
  168. c.addevent('xxx', '4321.2 z')
  169. c.addsleep()
  170. c.addend('aaa')
  171. c.addend('xxx')
  172. self.start_workers(SimpleWorkerBee, 2)
  173. c.main()
  174. r = ','.join(c.results)
  175. self.assert_('(1234.5 a1234.6 b1234.7 c)' in r)
  176. self.assert_('(4321.0 x4321.1 y4321.2 z)' in r)
  177. self.join_workers()
  178. class TestErrors(apiaryTestCase):
  179. def do_nothing(self):
  180. pass
  181. def testConnectionError(self):
  182. self.options.amqp_host = "localhost:1"
  183. self._transport = apiary.Transport(self.options)
  184. self.assertRaises(apiary.ConnectionError, self.connect)
  185. def testExclusiveQueueUse(self):
  186. self._transport = apiary.Transport(self.options)
  187. self._transport.connect()
  188. self._transport.usequeue('minder-end')
  189. self._transport.consume('minder-end', 'm0', self.do_nothing)
  190. self._transport2 = apiary.Transport(self.options)
  191. self._transport2.connect()
  192. self._transport2.usequeue('minder-end')
  193. self.assertRaises(amqp.AMQPChannelException, self._transport2.consume, 'minder-end', 'm0', self.do_nothing)
  194. self._transport.close()
  195. self._transport2.close()
  196. if __name__ == '__main__':
  197. unittest.main()