示例#1
0
    def test_exceptionpreservation(self):
        # events for controlling execution order
        gt1event = eventlet.Event()
        gt2event = eventlet.Event()

        def test_gt1():
            try:
                raise KeyError()
            except KeyError:
                gt1event.send('exception')
                gt2event.wait()
                assert sys.exc_info()[0] is KeyError
                gt1event.send('test passed')

        def test_gt2():
            gt1event.wait()
            gt1event.reset()
            assert sys.exc_info()[0] is None
            try:
                raise ValueError()
            except ValueError:
                gt2event.send('exception')
                gt1event.wait()
                assert sys.exc_info()[0] is ValueError

        g1 = eventlet.spawn(test_gt1)
        g2 = eventlet.spawn(test_gt2)
        try:
            g1.wait()
            g2.wait()
        finally:
            g1.kill()
            g2.kill()
示例#2
0
    def test_change_subscription(self):
        # FIXME: Extensive testing showed this particular test is the root cause
        # of sporadic failures on Travis.
        pub, sub, port = self.create_bound_pair(zmq.PUB, zmq.SUB)
        sub.setsockopt(zmq.SUBSCRIBE, b'test')
        eventlet.sleep(0)
        sub_ready = eventlet.Event()
        sub_last = eventlet.Event()
        sub_done = eventlet.Event()

        def rx():
            while sub.recv() != b'test BEGIN':
                eventlet.sleep(0)
            sub_ready.send()
            count = 0
            while True:
                msg = sub.recv()
                if msg == b'test BEGIN':
                    # BEGIN may come many times
                    continue
                if msg == b'test LAST':
                    sub.setsockopt(zmq.SUBSCRIBE, b'done')
                    sub.setsockopt(zmq.UNSUBSCRIBE, b'test')
                    eventlet.sleep(0)
                    # In real application you should either sync
                    # or tolerate loss of messages.
                    sub_last.send()
                if msg == b'done DONE':
                    break
                count += 1
            sub_done.send(count)

        def tx():
            # Sync receiver ready to avoid loss of first packets
            while not sub_ready.ready():
                pub.send(b'test BEGIN')
                eventlet.sleep(0.005)
            for i in range(1, 101):
                msg = 'test {0}'.format(i).encode()
                if i != 50:
                    pub.send(msg)
                else:
                    pub.send(b'test LAST')
                    sub_last.wait()
                # XXX: putting a real delay of 1ms here fixes sporadic failures on Travis
                # just yield eventlet.sleep(0) doesn't cut it
                eventlet.sleep(0.001)
            pub.send(b'done DONE')

        eventlet.spawn(rx)
        eventlet.spawn(tx)
        rx_count = sub_done.wait()
        self.assertEqual(rx_count, 50)
示例#3
0
    def test_waiters_get_woken(self):
        # verify that when there's someone waiting on an empty pool
        # and someone puts an immediately-closed connection back in
        # the pool that the waiter gets woken
        self.pool.put(self.connection)
        self.pool.clear()
        self.pool = self.create_pool(max_size=1, max_age=0)

        self.connection = self.pool.get()
        self.assertEqual(self.pool.free(), 0)
        self.assertEqual(self.pool.waiting(), 0)
        e = eventlet.Event()

        def retrieve(pool, ev):
            c = pool.get()
            ev.send(c)

        eventlet.spawn(retrieve, self.pool, e)
        eventlet.sleep(0)  # these two sleeps should advance the retrieve
        eventlet.sleep(0)  # coroutine until it's waiting in get()
        self.assertEqual(self.pool.free(), 0)
        self.assertEqual(self.pool.waiting(), 1)
        self.pool.put(self.connection)
        timer = eventlet.Timeout(1)
        conn = e.wait()
        timer.cancel()
        self.assertEqual(self.pool.free(), 0)
        self.assertEqual(self.pool.waiting(), 0)
        self.pool.put(conn)
示例#4
0
    def test_waiting(self):
        pool = eventlet.GreenPool(1)
        done = eventlet.Event()

        def consume():
            done.wait()

        def waiter(pool):
            gt = pool.spawn(consume)
            gt.wait()

        waiters = []
        self.assertEqual(pool.running(), 0)
        waiters.append(eventlet.spawn(waiter, pool))
        eventlet.sleep(0)
        self.assertEqual(pool.waiting(), 0)
        waiters.append(eventlet.spawn(waiter, pool))
        eventlet.sleep(0)
        self.assertEqual(pool.waiting(), 1)
        waiters.append(eventlet.spawn(waiter, pool))
        eventlet.sleep(0)
        self.assertEqual(pool.waiting(), 2)
        self.assertEqual(pool.running(), 1)
        done.send(None)
        for w in waiters:
            w.wait()
        self.assertEqual(pool.waiting(), 0)
        self.assertEqual(pool.running(), 0)
示例#5
0
    def test_send_1k_req_rep(self):
        req, rep, port = self.create_bound_pair(zmq.REQ, zmq.REP)
        eventlet.sleep()
        done = eventlet.Event()

        def tx():
            tx_i = 0
            req.send(str(tx_i).encode())
            while req.recv() != b'done':
                tx_i += 1
                req.send(str(tx_i).encode())
            done.send(0)

        def rx():
            while True:
                rx_i = rep.recv()
                if rx_i == b"1000":
                    rep.send(b'done')
                    break
                rep.send(b'i')

        eventlet.spawn(tx)
        eventlet.spawn(rx)
        final_i = done.wait()
        self.assertEqual(final_i, 0)
示例#6
0
    def test_reset(self):
        evt = eventlet.Event()

        # calling reset before send should throw
        self.assertRaises(AssertionError, evt.reset)

        value = 'some stuff'

        def send_to_event():
            evt.send(value)

        eventlet.spawn_n(send_to_event)
        self.assertEqual(evt.wait(), value)

        # now try it again, and we should get the same exact value,
        # and we shouldn't be allowed to resend without resetting
        value2 = 'second stuff'
        self.assertRaises(AssertionError, evt.send, value2)
        self.assertEqual(evt.wait(), value)

        # reset and everything should be happy
        evt.reset()

        def send_to_event2():
            evt.send(value2)

        eventlet.spawn_n(send_to_event2)
        self.assertEqual(evt.wait(), value2)
示例#7
0
    def spawn(self, function, *args, **kwargs):
        """Run the *function* with its arguments in its own green thread.
        Returns the :class:`GreenThread <eventlet.GreenThread>`
        object that is running the function, which can be used to retrieve the
        results.

        If the pool is currently at capacity, ``spawn`` will block until one of
        the running greenthreads completes its task and frees up a slot.

        This function is reentrant; *function* can call ``spawn`` on the same
        pool without risk of deadlocking the whole thing.
        """
        # if reentering an empty pool, don't try to wait on a coroutine freeing
        # itself -- instead, just execute in the current coroutine
        current = eventlet.getcurrent()
        if self.sem.locked() and current in self.coroutines_running:
            # a bit hacky to use the GT without switching to it
            gt = eventlet.greenthread.GreenThread(current)
            gt.main(function, args, kwargs)
            return gt
        else:
            self.sem.acquire()
            gt = eventlet.spawn(function, *args, **kwargs)
            if not self.coroutines_running:
                self.no_coros_running = eventlet.Event()
            self.coroutines_running.add(gt)
            gt.link(self._spawn_done)
        return gt
示例#8
0
    def assert_pool_has_free(self, pool, num_free):
        self.assertEqual(pool.free(), num_free)

        def wait_long_time(e):
            e.wait()

        timer = eventlet.Timeout(1)
        try:
            evt = eventlet.Event()
            for x in six.moves.range(num_free):
                pool.spawn(wait_long_time, evt)
                # if the pool has fewer free than we expect,
                # then we'll hit the timeout error
        finally:
            timer.cancel()

        # if the runtime error is not raised it means the pool had
        # some unexpected free items
        timer = eventlet.Timeout(0, RuntimeError)
        try:
            self.assertRaises(RuntimeError, pool.spawn, wait_long_time, evt)
        finally:
            timer.cancel()

        # clean up by causing all the wait_long_time functions to return
        evt.send(None)
        eventlet.sleep(0)
        eventlet.sleep(0)
示例#9
0
    def test_send_during_recv(self):
        sender, receiver, port = self.create_bound_pair(zmq.XREQ, zmq.XREQ)
        eventlet.sleep()

        num_recvs = 30
        done_evts = [eventlet.Event() for _ in range(num_recvs)]

        def slow_rx(done, msg):
            self.assertEqual(sender.recv(), msg)
            done.send(0)

        def tx():
            tx_i = 0
            while tx_i <= 1000:
                sender.send(str(tx_i).encode())
                tx_i += 1

        def rx():
            while True:
                rx_i = receiver.recv()
                if rx_i == b"1000":
                    for i in range(num_recvs):
                        receiver.send(('done%d' % i).encode())
                    eventlet.sleep()
                    return

        for i in range(num_recvs):
            eventlet.spawn(slow_rx, done_evts[i], ("done%d" % i).encode())

        eventlet.spawn(tx)
        eventlet.spawn(rx)
        for evt in done_evts:
            self.assertEqual(evt.wait(), 0)
示例#10
0
    def test_exponential_backoff_subscribe_error(
        self,
        entrypoint,
        config,
        mock_pubsub,
        mock_sleep,
        backoff_factor,
        sleep_durations,
    ):
        config['REDIS'] = {'pubsub_backoff_factor': backoff_factor}
        entrypoint.setup()
        event = eventlet.Event()
        mock_pubsub.psubscribe.side_effect = [
            ConnectionError('Error1'),
            Exception('Error2'),
            ConnectionError('Error3'),
            TimeoutError('Error4'),
            None,
            None,  # Subscribes successfully
        ]
        mock_pubsub.listen.side_effect = event.wait

        with eventlet.Timeout(TIMEOUT):
            entrypoint.start()
            sleep(TIME_SLEEP)
            entrypoint.stop()

        assert mock_sleep.call_args_list == [
            call(duration) for duration in sleep_durations
        ]
示例#11
0
    def test_recv_during_send(self):
        sender, receiver, port = self.create_bound_pair(zmq.XREQ, zmq.XREQ)
        eventlet.sleep()

        done = eventlet.Event()

        try:
            SNDHWM = zmq.SNDHWM
        except AttributeError:
            # ZeroMQ <3.0
            SNDHWM = zmq.HWM

        sender.setsockopt(SNDHWM, 10)
        sender.setsockopt(zmq.SNDBUF, 10)

        receiver.setsockopt(zmq.RCVBUF, 10)

        def tx():
            tx_i = 0
            while tx_i <= 1000:
                sender.send(str(tx_i).encode())
                tx_i += 1
            done.send(0)

        eventlet.spawn(tx)
        final_i = done.wait()
        self.assertEqual(final_i, 0)
示例#12
0
    def test_default_backoff_factor_listen_error(self, entrypoint, config,
                                                 mock_pubsub, mock_sleep):
        config['REDIS'].pop('pubsub_backoff_factor', None)
        entrypoint.setup()
        event = eventlet.Event()
        mock_pubsub.listen.side_effect = [
            ConnectionError('Error1'),
            Exception('Error2'),
            ConnectionError('Error3'),
            TimeoutError('Error4'),
            redis_listen(
                {
                    'type': 'pmessage',
                    'pattern': '__keyspace@*__:*',
                    'channel': '__keyspace@0__:foo',
                    'data': 'expire',
                },
                ConnectionError('Error5'),
            ),
            redis_listen(event.wait),
        ]

        with eventlet.Timeout(TIMEOUT):
            entrypoint.start()
            sleep(TIME_SLEEP)
            entrypoint.stop()

        assert mock_sleep.call_args_list == [
            call(2),
            call(4),
            call(8),
            call(16),
            call(2),
        ]
示例#13
0
    def test_error_subscribing(self, mock_redis_client, entrypoint):
        mock_pubsub_1 = MagicMock()
        mock_pubsub_2 = MagicMock()
        mock_redis_client.pubsub.side_effect = [mock_pubsub_1, mock_pubsub_2]
        mock_pubsub_1.psubscribe.side_effect = [None, ConnectionError('Boom!')]
        event = eventlet.Event()
        mock_pubsub_2.psubscribe.return_value = None
        mock_pubsub_2.listen.side_effect = event.wait
        entrypoint.setup()

        with eventlet.Timeout(TIMEOUT):
            entrypoint.start()
            sleep(TIME_SLEEP)
            entrypoint.stop()

        assert mock_redis_client.pubsub.call_args_list == [call(), call()]
        assert mock_pubsub_1.psubscribe.call_args_list == [
            call('__keyevent@0__:*'),
            call('__keyspace@0__:*'),
        ]
        assert not mock_pubsub_1.listen.called
        assert mock_pubsub_2.psubscribe.call_args_list == [
            call('__keyevent@0__:*'),
            call('__keyspace@0__:*'),
        ]
        assert mock_pubsub_2.listen.call_args_list == [call()]
示例#14
0
    def test_resize(self):
        pool = eventlet.GreenPool(2)
        evt = eventlet.Event()

        def wait_long_time(e):
            e.wait()

        pool.spawn(wait_long_time, evt)
        pool.spawn(wait_long_time, evt)
        self.assertEqual(pool.free(), 0)
        self.assertEqual(pool.running(), 2)
        self.assert_pool_has_free(pool, 0)

        # verify that the pool discards excess items put into it
        pool.resize(1)

        # cause the wait_long_time functions to return, which will
        # trigger puts to the pool
        evt.send(None)
        eventlet.sleep(0)
        eventlet.sleep(0)

        self.assertEqual(pool.free(), 1)
        self.assertEqual(pool.running(), 0)
        self.assert_pool_has_free(pool, 1)

        # resize larger and assert that there are more free items
        pool.resize(2)
        self.assertEqual(pool.free(), 2)
        self.assertEqual(pool.running(), 0)
        self.assert_pool_has_free(pool, 2)
示例#15
0
    def test_send_1k_pub_sub(self):
        pub, sub_all, port = self.create_bound_pair(zmq.PUB, zmq.SUB)
        sub1 = self.context.socket(zmq.SUB)
        sub2 = self.context.socket(zmq.SUB)
        self.sockets.extend([sub1, sub2])
        addr = 'tcp://127.0.0.1:%s' % port
        sub1.connect(addr)
        sub2.connect(addr)
        sub_all.setsockopt(zmq.SUBSCRIBE, b'')
        sub1.setsockopt(zmq.SUBSCRIBE, b'sub1')
        sub2.setsockopt(zmq.SUBSCRIBE, b'sub2')

        sub_all_done = eventlet.Event()
        sub1_done = eventlet.Event()
        sub2_done = eventlet.Event()

        eventlet.sleep(0.2)

        def rx(sock, done_evt, msg_count=10000):
            count = 0
            while count < msg_count:
                msg = sock.recv()
                eventlet.sleep()
                if b'LAST' in msg:
                    break
                count += 1

            done_evt.send(count)

        def tx(sock):
            for i in range(1, 1001):
                msg = ("sub%s %s" % ([2, 1][i % 2], i)).encode()
                sock.send(msg)
                eventlet.sleep()
            sock.send(b'sub1 LAST')
            sock.send(b'sub2 LAST')

        eventlet.spawn(rx, sub_all, sub_all_done)
        eventlet.spawn(rx, sub1, sub1_done)
        eventlet.spawn(rx, sub2, sub2_done)
        eventlet.spawn(tx, pub)
        sub1_count = sub1_done.wait()
        sub2_count = sub2_done.wait()
        sub_all_count = sub_all_done.wait()
        self.assertEqual(sub1_count, 500)
        self.assertEqual(sub2_count, 500)
        self.assertEqual(sub_all_count, 1000)
示例#16
0
 def test_double_exception(self):
     evt = eventlet.Event()
     # send an exception through the event
     evt.send(exc=RuntimeError('from test_double_exception'))
     self.assertRaises(RuntimeError, evt.wait)
     evt.reset()
     # shouldn't see the RuntimeError again
     eventlet.Timeout(0.001)
     self.assertRaises(eventlet.Timeout, evt.wait)
示例#17
0
    def do_flush(self):
        if not self.payload_buffer:
            return

        buffer_switch_event = eventlet.Event()
        eventlet.spawn_n(self._gt_flush, buffer_switch_event)
        buffer_switch_event.wait()
        self.payload_buffer = []
        self.total_buffer_size = 0
示例#18
0
    def test_close_during_recv(self):
        sender, receiver, port = self.create_bound_pair(zmq.XREQ, zmq.XREQ)
        eventlet.sleep()
        done1 = eventlet.Event()
        done2 = eventlet.Event()

        def rx(e):
            self.assertRaisesErrno(RECV_ON_CLOSED_SOCKET_ERRNOS, receiver.recv)
            e.send()

        eventlet.spawn(rx, done1)
        eventlet.spawn(rx, done2)

        eventlet.sleep()
        receiver.close()

        done1.wait()
        done2.wait()
示例#19
0
    def test_waiting_for_event(self):
        evt = eventlet.Event()
        value = 'some stuff'

        def send_to_event():
            evt.send(value)

        eventlet.spawn_n(send_to_event)
        self.assertEqual(evt.wait(), value)
示例#20
0
def test_wait_timeout_exceed():
    evt = eventlet.Event()
    delay = 0.1
    eventlet.spawn_after(delay * 2, evt.send, True)
    t1 = eventlet.hubs.get_hub().clock()
    with eventlet.Timeout(delay, False):
        result = evt.wait(timeout=delay)
        td = eventlet.hubs.get_hub().clock() - t1
        assert not result
        assert td >= delay
示例#21
0
    def test_does_not_use_notification_events_config_if_not_provided(
            self, create_service, config, mock_redis_client, mock_pubsub):
        event = eventlet.Event()
        mock_pubsub.listen.side_effect = event.wait
        config['REDIS'].pop('notification_events')

        create_service(uri_config_key=URI_CONFIG_KEY,
                       events='*',
                       keys='*',
                       dbs='*')
        assert mock_redis_client.config_set.call_args_list == []
示例#22
0
    def test_stop_entrypoint(self, mock_pubsub, entrypoint, method):
        event = eventlet.Event()
        mock_pubsub.listen.side_effect = event.wait
        stop_method = getattr(entrypoint, method)
        entrypoint.setup()

        with eventlet.Timeout(TIMEOUT):
            entrypoint.start()
            sleep(TIME_SLEEP)
            stop_method()

        assert entrypoint._thread.dead is True
示例#23
0
 def __init__(self, size=1000):
     try:
         size = int(size)
     except ValueError as e:
         msg = 'GreenPool() expect size :: int, actual: {0} {1}'.format(type(size), str(e))
         raise TypeError(msg)
     if size < 0:
         msg = 'GreenPool() expect size >= 0, actual: {0}'.format(repr(size))
         raise ValueError(msg)
     self.size = size
     self.coroutines_running = set()
     self.sem = eventlet.Semaphore(size)
     self.no_coros_running = eventlet.Event()
示例#24
0
    def test_uses_notification_events_config_if_provided(
            self, create_service, config, mock_redis_client, mock_pubsub):
        event = eventlet.Event()
        mock_pubsub.listen.side_effect = event.wait
        config['REDIS']['notification_events'] = 'test_value'

        create_service(uri_config_key=URI_CONFIG_KEY,
                       events='*',
                       keys='*',
                       dbs='*')
        assert mock_redis_client.config_set.call_args_list == [
            call('notify-keyspace-events', 'test_value')
        ]
示例#25
0
    def test_killall_remaining_results(self):
        semaphore = eventlet.Event()

        def native_fun():
            time.sleep(.5)

        def gt_fun():
            semaphore.send(None)
            tpool.execute(native_fun)

        gt = eventlet.spawn(gt_fun)
        semaphore.wait()
        tpool.killall()
        gt.wait()
示例#26
0
    def _test_multiple_waiters(self, exception):
        evt = eventlet.Event()
        results = []

        def wait_on_event(i_am_done):
            evt.wait()
            results.append(True)
            i_am_done.send()
            if exception:
                raise Exception()

        waiters = []
        count = 5
        for i in range(count):
            waiters.append(eventlet.Event())
            eventlet.spawn_n(wait_on_event, waiters[-1])
        eventlet.sleep()  # allow spawns to start executing
        evt.send()

        for w in waiters:
            w.wait()

        self.assertEqual(len(results), count)
示例#27
0
    def test_block(self):
        e = zmq._BlockedThread()
        done = eventlet.Event()
        self.assertFalse(e)

        def block():
            e.block()
            done.send(1)

        eventlet.spawn(block)
        eventlet.sleep()

        self.assertFalse(done.has_result())
        e.wake()
        done.wait()
示例#28
0
    def test_recv_spawned_before_send_is_non_blocking(self):
        req, rep, port = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
        #       req.connect(ipc)
        #       rep.bind(ipc)
        eventlet.sleep()
        msg = dict(res=None)
        done = eventlet.Event()

        def rx():
            msg['res'] = rep.recv()
            done.send('done')

        eventlet.spawn(rx)
        req.send(b'test')
        done.wait()
        self.assertEqual(msg['res'], b'test')
示例#29
0
 def spawn_n(self, function, *args, **kwargs):
     """Create a greenthread to run the *function*, the same as
     :meth:`spawn`.  The difference is that :meth:`spawn_n` returns
     None; the results of *function* are not retrievable.
     """
     # if reentering an empty pool, don't try to wait on a coroutine freeing
     # itself -- instead, just execute in the current coroutine
     current = eventlet.getcurrent()
     if self.sem.locked() and current in self.coroutines_running:
         self._spawn_n_impl(function, args, kwargs, None)
     else:
         self.sem.acquire()
         g = eventlet.spawn_n(self._spawn_n_impl, function, args, kwargs,
                              True)
         if not self.coroutines_running:
             self.no_coros_running = eventlet.Event()
         self.coroutines_running.add(g)
示例#30
0
    def test_multiple_coros(self):
        evt = eventlet.Event()
        results = []

        def producer():
            results.append('prod')
            evt.send()

        def consumer():
            results.append('cons1')
            evt.wait()
            results.append('cons2')

        pool = eventlet.GreenPool(2)
        done = pool.spawn(consumer)
        pool.spawn_n(producer)
        done.wait()
        self.assertEqual(['cons1', 'prod', 'cons2'], results)