class _TestError: def _main_loop(self): return time.time() + 100, [] def _very_long_callback(self): time.sleep(tc.TASK_INTERVAL*15) return time.time() + 100, [] def _on_datagram_received(self, datagram): return time.time() + 100, [] def _crashing_callback(self): raise Exception, 'Crash testing' def test_failed_join(self): self.lock = threading.RLock() self.reactor = ThreadedReactor(self._main_loop, tc.CLIENT_PORT, self._on_datagram_received, task_interval=tc.TASK_INTERVAL) self.reactor.s = _SocketMock(tc.TASK_INTERVAL) # self.reactor.start() self.reactor.call_asap(self._very_long_callback) time.sleep(tc.TASK_INTERVAL*2) assert_raises(Exception, self.reactor.stop)
class TestSend: def _main_loop(self): return time.time() + 100, [DATAGRAM1] def _callback(self, value): with self.lock: self.callback_values.append(value) return time.time() + 100, [DATAGRAM2] def _on_datagram_received(self, datagram): with self.lock: self.datagrams_received.append(datagram) return time.time() + 100, [DATAGRAM3] def _crashing_callback(self): raise Exception, "Crash testing" def setup(self): self.main_loop_call_counter = 0 self.callback_values = [] self.datagrams_received = [] self.lock = threading.RLock() self.reactor = ThreadedReactor( self._main_loop, tc.CLIENT_PORT, self._on_datagram_received, task_interval=tc.TASK_INTERVAL ) self.reactor.s = _SocketMock() self.s = self.reactor.s self.reactor.start() def test_main_loop_send_data(self): time.sleep(tc.TASK_INTERVAL) eq_(self.s.get_datagrams_sent(), [DATAGRAM1]) return def test_call_asap_send_data(self): time.sleep(tc.TASK_INTERVAL) eq_(self.s.get_datagrams_sent(), [DATAGRAM1]) self.reactor.call_asap(self._callback, 1) time.sleep(tc.TASK_INTERVAL * 2) eq_(self.s.get_datagrams_sent(), [DATAGRAM1, DATAGRAM2]) def test_on_datagram_received_send_data(self): time.sleep(tc.TASK_INTERVAL) eq_(self.s.get_datagrams_sent(), [DATAGRAM1]) self.s.put_datagram_received(Datagram(DATA1, tc.SERVER_ADDR)) time.sleep(tc.TASK_INTERVAL / 2) eq_(self.s.get_datagrams_sent(), [DATAGRAM1, DATAGRAM3]) def teardown(self): self.reactor.stop()
class TestMinitwisted: def _main_loop(self): print 'main loop call' self.main_loop_call_counter += 1 return time.time() + self.main_loop_delay, [] def _main_loop_return_datagrams(self): return time.time() + self.main_loop_delay, [DATAGRAM1] def _callback(self, value): self.callback_values.append(value) return [] def _very_long_callback(self, value): time.sleep(tc.TASK_INTERVAL*11) return [] def _on_datagram_received(self, datagram): print 'on_datagram', datagram, datagram.data, datagram.addr self.datagrams_received.append(datagram) return time.time() + 100, [] def _crashing_callback(self): raise CrashError, 'Crash testing' def setup(self): time.mock_mode() self.main_loop_call_counter = 0 self.callback_values = [] self.datagrams_received = [] self.main_loop_delay = MAIN_LOOP_DELAY self.reactor = ThreadedReactor(self._main_loop, tc.CLIENT_PORT, self._on_datagram_received, task_interval=tc.TASK_INTERVAL) self.reactor.s = _SocketMock() #self.reactor.start() >> instead of usint start(), we use run_one_step() def test_call_main_loop(self): eq_(self.main_loop_call_counter, 0) self.reactor.run_one_step() # main_loop is called right away eq_(self.main_loop_call_counter, 1) self.reactor.run_one_step() # no events eq_(self.main_loop_call_counter, 1) time.sleep(self.main_loop_delay) self.reactor.run_one_step() # main_loop is called again after eq_(self.main_loop_call_counter, 2) def test_call_asap(self): eq_(self.callback_values, []) self.reactor.call_asap(self._callback, 0) eq_(self.callback_values, []) # stil nothing self.reactor.run_one_step() eq_(self.callback_values, [0]) #callback triggered for i in xrange(1, 5): self.reactor.call_asap(self._callback, i) self.reactor.run_one_step() eq_(self.callback_values, range(i + 1)) def test_minitwisted_crashed(self): self.reactor.call_asap(self._crashing_callback) assert_raises(CrashError, self.reactor.run_one_step) def test_on_datagram_received_callback(self): eq_(self.datagrams_received, []) self.reactor.run_one_step() eq_(self.datagrams_received, []) datagram = Datagram(DATA1, tc.SERVER_ADDR) # This is equivalent to sending a datagram to reactor self.reactor.s.put_datagram_received(datagram) self.reactor.run_one_step() eq_(len(self.datagrams_received), 1) eq_(self.datagrams_received[0], datagram) def test_block_flood(self): from floodbarrier import MAX_PACKETS_PER_PERIOD as FLOOD_LIMIT for _ in xrange(FLOOD_LIMIT * 2): self.reactor.s.put_datagram_received(Datagram(DATA1, tc.SERVER_ADDR)) for i in xrange(FLOOD_LIMIT): eq_(len(self.datagrams_received), i) self.reactor.run_one_step() eq_(len(self.datagrams_received), FLOOD_LIMIT) for i in xrange(FLOOD_LIMIT): eq_(len(self.datagrams_received), FLOOD_LIMIT) logger.warning( "TESTING LOGS ** IGNORE EXPECTED WARNING **") self.reactor.run_one_step() eq_(len(self.datagrams_received), FLOOD_LIMIT) def test_network_and_callback(self): self.reactor.call_asap(self._callback, 1) eq_(self.main_loop_call_counter, 0) eq_(self.callback_values, []) time.sleep(.1) self.reactor.run_one_step() # call_asap and main_loop triggered eq_(self.callback_values, [1]) eq_(self.main_loop_call_counter, 1) self.reactor.s.put_datagram_received(DATAGRAM1) eq_(self.datagrams_received, []) self.reactor.run_one_step() eq_(self.datagrams_received, [DATAGRAM1]) self.reactor.call_asap(self._callback, 2) self.reactor.s.put_datagram_received(DATAGRAM3) self.reactor.run_one_step() # receive AND call_asap eq_(self.datagrams_received, [DATAGRAM1, DATAGRAM3]) eq_(self.callback_values, [1, 2]) def teardown(self): #self.reactor.stop() >> reactor is not really running time.normal_mode()
class TestSend: def _main_loop(self): return time.time() + MAIN_LOOP_DELAY, [DATAGRAM1] def _callback(self, value): self.callback_values.append(value) return [DATAGRAM2] def _on_datagram_received(self, datagram): self.datagrams_received.append(datagram) return time.time() + MAIN_LOOP_DELAY, [DATAGRAM3] def _crashing_callback(self): raise CrashError, 'Crash testing' def setup(self): self.main_loop_call_counter = 0 self.callback_values = [] self.datagrams_received = [] self.reactor = ThreadedReactor(self._main_loop, tc.CLIENT_PORT, self._on_datagram_received, task_interval=tc.TASK_INTERVAL) self.reactor.s = _SocketMock() def test_main_loop_send_data(self): eq_(self.reactor.s.get_datagrams_sent(), []) self.reactor.run_one_step() # main_loop sends DATAGRAM1 eq_(self.reactor.s.get_datagrams_sent(), [DATAGRAM1]) def test_call_asap_send_data(self): self.reactor.run_one_step() eq_(self.reactor.s.get_datagrams_sent(), [DATAGRAM1]) self.reactor.call_asap(self._callback, 1) self.reactor.run_one_step() eq_(self.reactor.s.get_datagrams_sent(), [DATAGRAM1, DATAGRAM2]) def test_on_datagram_received_send_data(self): self.reactor.run_one_step() eq_(self.reactor.s.get_datagrams_sent(), [DATAGRAM1]) self.reactor.s.put_datagram_received(Datagram(DATA1, tc.SERVER_ADDR)) self.reactor.run_one_step() eq_(self.reactor.s.get_datagrams_sent(), [DATAGRAM1, DATAGRAM3]) def test_capture(self): self.reactor.start_capture() ts1 = time.time() time.sleep(tc.TASK_INTERVAL/2) # out > DATAGRAM1 (main_loop) self.reactor.run_one_step() ts2 = time.time() incoming_datagram = Datagram(DATA1, tc.SERVER_ADDR) self.reactor.s.put_datagram_received(incoming_datagram) time.sleep(tc.TASK_INTERVAL/2) self.reactor.run_one_step() # in < incoming_datagram (socket) # out > DATAGRAM3 (on_datagram_received) captured_msgs = self.reactor.stop_and_get_capture() eq_(len(captured_msgs), 3) for msg in captured_msgs: print msg assert ts1 < captured_msgs[0][0] < ts2 eq_(captured_msgs[0][1], tc.SERVER_ADDR) eq_(captured_msgs[0][2], True) #outgoing eq_(captured_msgs[0][3], DATA1) assert captured_msgs[1][0] > ts2 eq_(captured_msgs[1][1], DATAGRAM1.addr) eq_(captured_msgs[1][2], False) #incoming eq_(captured_msgs[1][3], DATAGRAM1.data) assert captured_msgs[2][0] > captured_msgs[1][0] eq_(captured_msgs[2][1], DATAGRAM3.addr) eq_(captured_msgs[2][2], True) #outgoing eq_(captured_msgs[2][3], DATAGRAM3.data) def teardown(self): return
class TestMinitwisted: def _main_loop(self): with self.lock: self.main_loop_call_counter += 1 return time.time() + tc.TASK_INTERVAL * 10, [] def _main_loop_return_datagrams(self): return time.time() + tc.TASK_INTERVAL * 10, [DATAGRAM1] def _callback(self, value): with self.lock: self.callback_values.append(value) return time.time() + 100, [] def _very_long_callback(self, value): time.sleep(tc.TASK_INTERVAL * 11) def _on_datagram_received(self, datagram): print "on_datagram", datagram, datagram.data, datagram.addr with self.lock: self.datagrams_received.append(datagram) return time.time() + 100, [] def _crashing_callback(self): raise Exception, "Crash testing" def setup(self): self.main_loop_call_counter = 0 self.callback_values = [] self.datagrams_received = [] self.lock = threading.RLock() self.reactor = ThreadedReactor( self._main_loop, tc.CLIENT_PORT, self._on_datagram_received, task_interval=tc.TASK_INTERVAL ) self.reactor.s = _SocketMock() self.s = self.reactor.s self.reactor.start() def test_call_main_loop(self): time.sleep(tc.TASK_INTERVAL) # main_loop is called right away with self.lock: # FIXME: this assert fails sometimes!!!! eq_(self.main_loop_call_counter, 1) time.sleep(0.1 + tc.TASK_INTERVAL) with self.lock: # FIXME: this crashes when recompiling eq_(self.main_loop_call_counter, 2) def test_call_asap(self): with self.lock: eq_(self.callback_values, []) self.reactor.call_asap(self._callback, 0) time.sleep(tc.TASK_INTERVAL * 2) with self.lock: eq_(self.callback_values, [0]) for i in xrange(1, 5): self.reactor.call_asap(self._callback, i) time.sleep(tc.TASK_INTERVAL * 3) with self.lock: eq_(self.callback_values, range(i + 1)) def test_minitwisted_crashed(self): self.reactor.call_asap(self._crashing_callback) time.sleep(tc.TASK_INTERVAL * 3) # from now on, the minitwisted thread is dead ok_(not self.reactor.running) def test_on_datagram_received_callback(self): # This is equivalent to sending a datagram to reactor self.s.put_datagram_received(Datagram(DATA1, tc.SERVER_ADDR)) datagram = Datagram(DATA1, tc.SERVER_ADDR) print "--------------", datagram, datagram.data, datagram.addr time.sleep(tc.TASK_INTERVAL * 1) with self.lock: datagram = self.datagrams_received.pop(0) print "popped>>>>>>>>>>>>>>>", datagram eq_(datagram.data, DATA1) eq_(datagram.addr, tc.SERVER_ADDR) def test_block_flood(self): from floodbarrier import MAX_PACKETS_PER_PERIOD as FLOOD_LIMIT for _ in xrange(FLOOD_LIMIT): self.s.put_datagram_received(Datagram(DATA1, tc.SERVER_ADDR)) time.sleep(tc.TASK_INTERVAL * 5) with self.lock: eq_(len(self.datagrams_received), FLOOD_LIMIT) for _ in xrange(10): self.s.put_datagram_received(Datagram(DATA1, tc.SERVER_ADDR)) time.sleep(tc.TASK_INTERVAL * 3) with self.lock: eq_(len(self.datagrams_received), FLOOD_LIMIT) logger.warning("TESTING LOGS ** IGNORE EXPECTED WARNING **") def _test_network_and_delayed(self): # TODO self.client_r.call_later(0.2, self.callback_f, 0) self.client_r.call_asap(self.callback_f, 1) task2 = self.client_r.call_later(0.2, self.callback_f, 2) with self.lock: eq_(self.callback_order, []) time.sleep(0.1) with self.lock: logger.debug("callback_order: %s" % self.callback_order) assert self.callback_order == [1] self.callback_order = [] assert not self.datagrams_received self.server_r.sendto(DATA, tc.CLIENT_PORT) time.sleep(0.02) # wait for network interruption with self.lock: logger.debug("callback_order: %s" % self.callback_order) assert self.callback_order == [] logger.debug("callback_order: %s" % self.callback_order) datagram = self.datagrams_received.pop(0) eq_(datagram.data, DATA) eq_(datagram.addr, tc.SERVER_ADDR) task2.cancel() # inside critical region?? time.sleep(0.1) # wait for task 0 (task 2 should be cancelled) with self.lock: assert self.callback_order == [0] assert not self.datagrams_received def teardown(self): self.reactor.stop()