Пример #1
0
    def test_fiber_safety_timeout(self):
        # Test correctness of the lock in case of timeouts.
        lock = self.Lock()
        order = []

        def run_test(ix):
            lock.acquire()
            order.append(ix)
            lock.release()

        fibers = []
        for i in range(self.nfibers):
            fibers.append(gruvi.spawn(run_test, i))
        # There's 5 elements in lock._waiter now. Kill the first one, and
        # schedule a cancel for the second one. Both conditions should be
        # handled appropriately and no deadlocks should happen.
        lock.acquire()
        gruvi.sleep(0)  # make sure all fibers are waiting on lock.acquire()
        fibers[0].cancel()
        gruvi.sleep(0)  # first one will be gone
        self.assertFalse(fibers[0].is_alive())
        fibers[1].cancel()  # a Cancelled is now scheduled for number two
        self.assertTrue(fibers[1].is_alive())
        lock.release()
        for fib in fibers:
            fib.join()
        # All fibers should have gotten the lock except 1 and 2.
        self.assertEqual(order, list(range(2, len(fibers))))
Пример #2
0
 def test_send_message_incremental(self):
     # Send a message byte by byte. The protocol should be able process it.
     transport = MockTransport()
     protocol = DbusProtocol(True, self.store_messages, 'foo')
     transport.start(protocol)
     authexchange = b'\0AUTH ANONYMOUS\r\nBEGIN\r\n'
     for i in range(len(authexchange)):
         protocol.data_received(authexchange[i:i+1])
     auth = protocol._authenticator
     self.assertTrue(auth.authenticationSucceeded())
     message = txdbus.MethodCallMessage('/org/freedesktop/DBus', 'Hello',
                     interface='org.freedesktop.DBus', destination='org.freedesktop.DBus')
     for i in range(len(message.rawMessage)):
         protocol.data_received(message.rawMessage[i:i+1])
     gruvi.sleep(0)
     self.assertIsNone(protocol._error)
     self.assertFalse(transport.closed)
     self.assertEqual(len(self.messages), 0)
     message = txdbus.MethodCallMessage('/my/path', 'Method')
     for i in range(len(message.rawMessage)):
         protocol.data_received(message.rawMessage[i:i+1])
     gruvi.sleep(0)
     self.assertIsNone(protocol._error)
     self.assertFalse(transport.closed)
     self.assertEqual(len(self.messages), 1)
     self.assertEqual(self.messages[0].path, '/my/path')
     self.assertEqual(self.messages[0].member, 'Method')
     self.assertEqual(self.protocols, [protocol])
Пример #3
0
 def test_ssl_no_handshake_on_connect(self):
     # Ensure that when create_connection(ssl=True) returns, that the SSL
     # handshake has completed.
     context = self.get_ssl_context()
     server = create_server(StreamProtocol, ('localhost', 0), ssl=context)
     addr = server.addresses[0]
     ssl_args = {'do_handshake_on_connect': False}
     ctrans, cproto = create_connection(StreamProtocol,
                                        addr,
                                        ssl=context,
                                        ssl_args=ssl_args)
     # The SSL handshake has not been established at this point.
     sslobj = ctrans.get_extra_info('ssl')
     self.assertIsNone(sslobj)
     # Now initiate the SSL handshake and allow it some time to complete
     ctrans.do_handshake()
     gruvi.sleep(0.1)
     # There should be a channel binding now.
     sslobj = ctrans.get_extra_info('ssl')
     self.assertIsNotNone(sslobj)
     sslcb = sslobj.get_channel_binding('tls-unique')
     self.assertGreater(len(sslcb), 0)
     strans, sproto = list(server.connections)[0]
     cproto.stream.write(b'foo\n')
     self.assertEqual(sproto.stream.readline(), b'foo\n')
     server.close()
     self.assertEqual(len(list(server.connections)), 0)
     self.assertEqual(cproto.stream.readline(), b'')
     ctrans.close()
Пример #4
0
    def test_timeout(self):
        # Ensure that the timeout argument to acquire() works.
        hub = get_hub()
        lock = gruvi.RLock()
        sync = gruvi.Lock()

        def lock_rlock():
            lock.acquire()
            sync.acquire()
            lock.release()

        # This needs a new fiber, as the same fiber *can* lock the same RLock twice.
        sync.acquire()
        fiber = gruvi.spawn(lock_rlock)
        gruvi.sleep(0)
        self.assertTrue(lock.locked())
        t0 = hub.loop.now()
        self.assertFalse(lock.acquire(timeout=0.01))
        t1 = hub.loop.now()
        # Internally the event loop uses timestamps with a 1ms granularity. So
        # allow for that.
        self.assertGreaterEqual(t1 - t0, 10)
        sync.release()
        fiber.join()
        self.assertFalse(lock._callbacks)
Пример #5
0
 def test_send_message(self):
     # After the "Hello" message, it should be possible to send other
     # messages.
     transport = MockTransport()
     protocol = DbusProtocol(True, self.store_messages, 'foo')
     transport.start(protocol)
     protocol.data_received(b'\0AUTH ANONYMOUS\r\nBEGIN\r\n')
     auth = protocol._authenticator
     self.assertTrue(auth.authenticationSucceeded())
     message = txdbus.MethodCallMessage('/org/freedesktop/DBus', 'Hello',
                     interface='org.freedesktop.DBus', destination='org.freedesktop.DBus')
     protocol.data_received(message.rawMessage)
     gruvi.sleep(0)
     self.assertIsNone(protocol._error)
     self.assertFalse(transport.closed)
     self.assertTrue(protocol._name_acquired)
     self.assertEqual(len(self.messages), 0)
     message = txdbus.MethodCallMessage('/my/path', 'Method')
     protocol.data_received(message.rawMessage)
     gruvi.sleep(0)
     self.assertIsNone(protocol._error)
     self.assertFalse(transport.closed)
     self.assertEqual(len(self.messages), 1)
     self.assertEqual(self.messages[0].path, '/my/path')
     self.assertEqual(self.messages[0].member, 'Method')
     self.assertEqual(self.protocols, [protocol])
Пример #6
0
 def test_thread_safety(self):
     cond = gruvi.Condition()
     ready = []
     result = []
     def run_test():
         with cond:
             ready.append(gruvi.current_fiber())
             timeout = random.choice((None, 0.1))
             result.append(cond.wait(timeout=timeout))
     def run_thread():
         fibers = []
         for i in range(self.nfibers):
             fibers.append(gruvi.spawn(run_test))
         for fib in fibers:
             fib.join()
     threads = []
     for i in range(self.nthreads):
         thread = threading.Thread(target=run_thread)
         thread.start()
         threads.append(thread)
     gruvi.sleep(0.2)
     while len(ready) != self.nthreads*self.nfibers:
         gruvi.sleep(0.1)
     with cond:
         cond.notify_all()
     for thread in threads:
         thread.join()
     timeouts = result.count(False)
     notified = result.count(True)
     self.assertEqual(timeouts + notified, self.nthreads*self.nfibers)
     self.assertGreater(timeouts, 0)
     self.assertGreater(notified, 0)
     self.assertIsNone(cond._callbacks)
Пример #7
0
 def test_thread_safety(self):
     event = gruvi.Event()
     result = []
     def run_test():
         timeout = random.choice((None, 0.1))
         result.append(event.wait(timeout=timeout))
     def run_thread():
         fibers = []
         for i in range(self.nfibers):
             fibers.append(gruvi.spawn(run_test))
         for fib in fibers:
             fib.join()
     threads = []
     for i in range(self.nthreads):
         thread = threading.Thread(target=run_thread)
         thread.start()
         threads.append(thread)
     gruvi.sleep(0.5)
     event.set()
     for thread in threads:
         thread.join()
     timeouts = result.count(False)
     notified = result.count(True)
     self.assertEqual(timeouts + notified, self.nthreads*self.nfibers)
     self.assertGreater(timeouts, 0)
     self.assertGreater(notified, 0)
     self.assertIsNone(event._callbacks)
Пример #8
0
 def test_ssl_no_handshake_on_connect(self):
     # Ensure that when create_connection(ssl=True) returns, that the SSL
     # handshake has completed.
     context = self.get_ssl_context()
     server = create_server(StreamProtocol, ('localhost', 0), ssl=context)
     addr = server.addresses[0]
     ssl_args = {'do_handshake_on_connect': False}
     ctrans, cproto = create_connection(StreamProtocol, addr, ssl=context, ssl_args=ssl_args)
     # The SSL handshake has not been established at this point.
     sslobj = ctrans.get_extra_info('ssl')
     self.assertIsNone(sslobj)
     # Now initiate the SSL handshake and allow it some time to complete
     ctrans.do_handshake()
     gruvi.sleep(0.1)
     # There should be a channel binding now.
     sslobj = ctrans.get_extra_info('ssl')
     self.assertIsNotNone(sslobj)
     sslcb = sslobj.get_channel_binding('tls-unique')
     self.assertGreater(len(sslcb), 0)
     strans, sproto = list(server.connections)[0]
     cproto.stream.write(b'foo\n')
     self.assertEqual(sproto.stream.readline(), b'foo\n')
     server.close()
     self.assertEqual(len(list(server.connections)), 0)
     self.assertEqual(cproto.stream.readline(), b'')
     ctrans.close()
Пример #9
0
 def test_fiber_safety_timeout(self):
     # Test correctness of the lock in case of timeouts.
     lock = self.Lock()
     order = []
     def run_test(ix):
         lock.acquire()
         order.append(ix)
         lock.release()
     fibers = []
     for i in range(self.nfibers):
         fibers.append(gruvi.spawn(run_test, i))
     # There's 5 elements in lock._waiter now. Kill the first one, and
     # schedule a cancel for the second one. Both conditions should be
     # handled appropriately and no deadlocks should happen.
     lock.acquire()
     gruvi.sleep(0)  # make sure all fibers are waiting on lock.acquire()
     fibers[0].cancel()
     gruvi.sleep(0)  # first one will be gone
     self.assertFalse(fibers[0].is_alive())
     fibers[1].cancel()  # a Cancelled is now scheduled for number two
     self.assertTrue(fibers[1].is_alive())
     lock.release()
     for fib in fibers:
         fib.join()
     # All fibers should have gotten the lock except 1 and 2.
     self.assertEqual(order, list(range(2, len(fibers))))
Пример #10
0
    def test_thread_safety(self):
        # A Queue should be thread safe. This meanst that all entries that are
        # put in the queue must be returned, that no entry must be returned
        # twice and that the order must be respected. Also no deadlock must
        # ever occur.
        # To test, fire up a bunch of threads which each fire up a bunch of
        # fibers, and have the fibers do some random sleeps. Then let it run
        # and test the result.
        result = []
        reference = []
        lock = gruvi.Lock()

        def put_queue(tid, fid, count):
            for i in range(count):
                with lock:
                    gruvi.sleep(random.randint(0, 2) / 1000)
                    queue.put((tid, fid, count))
                    reference.append((tid, fid, count))

        def get_queue(count):
            for i in range(count):
                with lock:
                    result.append(queue.get())

        def thread_put(tid, nfibers, count):
            fibers = []
            for i in range(nfibers):
                fibers.append(gruvi.spawn(put_queue, tid, i, count))
            for fib in fibers:
                fib.join()
            gruvi.get_hub().close()

        def thread_get(nfibers, count):
            fibers = []
            for i in range(nfibers):
                fibers.append(gruvi.spawn(get_queue, count))
            for fib in fibers:
                fib.join()
            gruvi.get_hub().close()

        queue = gruvi.Queue()
        threads = []
        # 5 procuders and 5 consumers, each with 20 fibers
        for i in range(5):
            thread = threading.Thread(target=thread_put, args=(i, 20, 5))
            thread.start()
            threads.append(thread)
        for i in range(5):
            thread = threading.Thread(target=thread_get, args=(20, 5))
            thread.start()
            threads.append(thread)
        for thread in threads:
            thread.join()
        gruvi.sleep(0)  # run callbacks
        self.assertEqual(len(result), 500)
        self.assertEqual(result, reference)
        # Within a (tid,fid) pair, the counts must be monotonic
        partial_sort = sorted(result, key=lambda el: (el[0], el[1]))
        full_sort = sorted(result, key=lambda el: (el[0], el[1], el[2]))
        self.assertEqual(partial_sort, full_sort)
Пример #11
0
 def thread_sleep():
     hub = gruvi.get_hub()
     gruvi.sleep(0)
     refs.append(weakref.ref(hub))
     refs.append(weakref.ref(hub.loop))
     hub.close()
     hub.switch()
Пример #12
0
 def thread_sleep():
     hub = gruvi.get_hub()
     gruvi.sleep(0)
     refs.append(weakref.ref(hub))
     refs.append(weakref.ref(hub.loop))
     hub.close()
     hub.switch()
Пример #13
0
 def pair_step2(self, uuid, kxid, pin, certinfo):
     """Perform step 2 in pairing exchange.
     
     If successfull, this returns the peer certificate. On error, a
     SyncApiError is raised.
     """
     if self.client is None:
         raise RuntimeError('Not connected')
     url = '/api/vaults/%s/pair' % uuid
     # XXX: wait until SSL is up
     gruvi.sleep(0.1)
     headers = self._get_hmac_cb_auth(kxid, pin)
     response = self._make_request('POST', url, headers, certinfo)
     if response is None:
         raise SyncApiError('Could not make syncapi request')
     status = response.status
     if status != 200:
         self._log.error('expecting HTTP status 200 (got: {})', status)
         raise SyncApiError('HTTP status {0}'.format(response.status))
     if not self._check_hmac_cb_auth(response, pin):
         raise SyncApiError('Illegal syncapi response')
     peercert = response.entity
     if peercert is None or not isinstance(peercert, dict):
         raise SyncApiError('Illegal syncapi response')
     return peercert
Пример #14
0
 def test_read_write_flow_control(self):
     # Test the read and write flow control of a stream transport.
     transport = MockTransport()
     protocol = StreamProtocol()
     transport.start(protocol)
     protocol.stream.buffer.set_buffer_limits(100)
     transport.set_write_buffer_limits(50)
     def reader():
         while True:
             buf = protocol.stream.read(20)
             if not buf:
                 break
             protocol.stream.write(buf)
     fib = gruvi.spawn(reader)
     buf = b'x' * 20
     interrupted = 0
     for i in range(100):
         protocol.data_received(buf)
         if transport._reading:
             continue
         interrupted += 1
         self.assertGreater(protocol.stream.buffer.get_buffer_size(), 0)
         # Switch to the reader() fiber which will fill up the transport
         # write buffer.
         gruvi.sleep(0)
         # The transport write buffer should be full but the protocol read
         # buffer should still contain something.
         self.assertGreater(protocol.stream.buffer.get_buffer_size(), 0)
         self.assertFalse(transport._can_write.is_set())
         # Drain write buffer and resume writing
         transport.drain()
     self.assertGreater(interrupted, 30)
     fib.cancel()
     gruvi.sleep(0)
Пример #15
0
    def test_thread_safety(self):
        event = gruvi.Event()
        result = []

        def run_test():
            timeout = random.choice((None, 0.1))
            result.append(event.wait(timeout=timeout))

        def run_thread():
            fibers = []
            for i in range(self.nfibers):
                fibers.append(gruvi.spawn(run_test))
            for fib in fibers:
                fib.join()

        threads = []
        for i in range(self.nthreads):
            thread = threading.Thread(target=run_thread)
            thread.start()
            threads.append(thread)
        gruvi.sleep(0.5)
        event.set()
        for thread in threads:
            thread.join()
        timeouts = result.count(False)
        notified = result.count(True)
        self.assertEqual(timeouts + notified, self.nthreads * self.nfibers)
        self.assertGreater(timeouts, 0)
        self.assertGreater(notified, 0)
        self.assertFalse(event._callbacks)
Пример #16
0
 def fiber1():
     local.foo = 10
     interleaved.append(1)
     gruvi.sleep(0)
     self.assertEqual(local.foo, 10)
     local.foo = 30
     interleaved.append(1)
     gruvi.sleep(0)
     self.assertEqual(local.foo, 30)
Пример #17
0
 def fiber2():
     self.assertFalse(hasattr(local, 'foo'))
     local.foo = 20
     interleaved.append(2)
     gruvi.sleep(0)
     self.assertEqual(local.foo, 20)
     local.foo = 40
     interleaved.append(2)
     gruvi.sleep(0)
     self.assertEqual(local.foo, 40)
Пример #18
0
 def test_cancel(self):
     # Ensure that it's possible to cancel() a fiber.
     def sleeper():
         gruvi.sleep(1000)
     fiber = gruvi.spawn(sleeper)
     gruvi.sleep(0)
     self.assertTrue(fiber.alive)
     fiber.cancel()
     gruvi.sleep(0)
     self.assertFalse(fiber.alive)
Пример #19
0
 def test_thread_safety(self):
     # A Queue should be thread safe. This meanst that all entries that are
     # put in the queue must be returned, that no entry must be returned
     # twice and that the order must be respected. Also no deadlock must
     # ever occur.
     # To test, fire up a bunch of threads which each fire up a bunch of
     # fibers, and have the fibers do some random sleeps. Then let it run
     # and test the result.
     result = []
     reference = []
     lock = gruvi.Lock()
     def put_queue(tid, fid, count):
         for i in range(count):
             with lock:
                 gruvi.sleep(random.randint(0, 10)/10000)
                 queue.put((tid, fid, count))
                 reference.append((tid, fid, count))
     def get_queue(count):
         for i in range(count):
             with lock:
                 result.append(queue.get())
     def thread_put(tid, nfibers, count):
         fibers = []
         for i in range(nfibers):
             fibers.append(gruvi.spawn(put_queue, tid, i, count))
         for fib in fibers:
             fib.join()
         gruvi.get_hub().close()
     def thread_get(nfibers, count):
         fibers = []
         for i in range(nfibers):
             fibers.append(gruvi.spawn(get_queue, count))
         for fib in fibers:
             fib.join()
         gruvi.get_hub().close()
     queue = gruvi.Queue()
     threads = []
     # 5 procuders and 5 consumers, each with 20 fibers
     for i in range(5):
         thread = threading.Thread(target=thread_put, args=(i, 20, 5))
         thread.start()
         threads.append(thread)
     for i in range(5):
         thread = threading.Thread(target=thread_get, args=(20, 5))
         thread.start()
         threads.append(thread)
     for thread in threads:
         thread.join()
     gruvi.sleep(0)  # run callbacks
     self.assertEqual(len(result), 500)
     self.assertEqual(result, reference)
     # Within a (tid,fid) pair, the counts must be monotonic
     partial_sort = sorted(result, key=lambda el: (el[0], el[1]))
     full_sort = sorted(result, key=lambda el: (el[0], el[1], el[2]))
     self.assertEqual(partial_sort, full_sort)
Пример #20
0
    def test_cancel(self):
        # Ensure that it's possible to cancel() a fiber.
        def sleeper():
            gruvi.sleep(1000)

        fiber = gruvi.spawn(sleeper)
        gruvi.sleep(0)
        self.assertTrue(fiber.alive)
        fiber.cancel()
        gruvi.sleep(0)
        self.assertFalse(fiber.alive)
Пример #21
0
 def test_duplicate(self):
     futures = [Future()] * 5
     result = []
     def waiter():
         result.append(gruvi.wait(futures))
     fib = Fiber(waiter)
     fib.start()
     gruvi.sleep(0)
     self.assertEqual(result, [])
     futures[0].set_result(None)
     gruvi.sleep(0)
     self.assertEqual(result, [(futures, [])])
Пример #22
0
 def test_sleep(self):
     # Test that sleep() works
     hub = gruvi.get_hub()
     # use hub.now() as there's slight rounding errors with time.time()
     t0 = hub.loop.now()
     gruvi.sleep(0.01)
     t1 = hub.loop.now()
     self.assertGreaterEqual(t1 - t0, 10)
     t0 = hub.loop.now()
     gruvi.sleep(0.1)
     t1 = hub.loop.now()
     self.assertGreaterEqual(t1 - t0, 100)
Пример #23
0
 def test_wait(self):
     event = gruvi.Event()
     done = []
     def waiter():
         done.append(False)
         done.append(event.wait())
     gruvi.spawn(waiter)
     gruvi.sleep(0)
     self.assertEqual(done, [False])
     event.set()
     gruvi.sleep(0)
     self.assertEqual(done, [False, True])
Пример #24
0
 def test_sleep(self):
     # Test that sleep() works
     hub = gruvi.get_hub()
     # use hub.now() as there's slight rounding errors with time.time()
     t0 = hub.loop.now()
     gruvi.sleep(0.01)
     t1 = hub.loop.now()
     self.assertGreaterEqual(t1-t0, 10)
     t0 = hub.loop.now()
     gruvi.sleep(0.1)
     t1 = hub.loop.now()
     self.assertGreaterEqual(t1-t0, 100)
Пример #25
0
 def test_returncode(self):
     # Ensure that the returncode attribute gets set when the child exits.
     proc = Process()
     proc.spawn(['sleep', '0.2'])
     tries = 0
     while True:
         if proc.returncode is not None:
             break
         tries += 1
         gruvi.sleep(0.02)
     self.assertEqual(proc.returncode, 0)
     self.assertGreater(tries, 5)
     proc.close()
Пример #26
0
 def get_request(self):
     # Get a parsed request.
     # The sleep here will run the dispatcher.
     gruvi.sleep(0)
     self.assertGreaterEqual(len(self.environs), 1)
     env = self.environs.pop(0)
     self.assertIsInstance(env, dict)
     message = env.get('test.message')
     self.assertIsInstance(message, HttpMessage)
     self.assertEqual(message.message_type, _lib.HTTP_REQUEST)
     body = env.get('test.body')
     self.assertIsInstance(body, six.binary_type)
     return env
Пример #27
0
 def get_request(self):
     # Get a parsed request.
     # The sleep here will run the dispatcher.
     gruvi.sleep(0)
     self.assertGreaterEqual(len(self.environs), 1)
     env = self.environs.pop(0)
     self.assertIsInstance(env, dict)
     message = env.get('test.message')
     self.assertIsInstance(message, HttpMessage)
     self.assertEqual(message.message_type, _lib.HTTP_REQUEST)
     body = env.get('test.body')
     self.assertIsInstance(body, six.binary_type)
     return env
Пример #28
0
 def test_cleanup(self):
     # After we close() a Hub, it should be garbage collectable, including
     # its event loop.
     hub = gruvi.Hub()
     gruvi.sleep(0)
     ref1 = weakref.ref(hub)
     ref2 = weakref.ref(hub.loop)
     hub.close()
     hub.switch()
     del hub
     gc.collect()
     self.assertIsNone(ref1())
     self.assertIsNone(ref2())
Пример #29
0
 def test_returncode(self):
     # Ensure that the returncode attribute gets set when the child exits.
     proc = Process()
     proc.spawn(['sleep', '0.2'])
     tries = 0
     while True:
         if proc.returncode is not None:
             break
         tries += 1
         gruvi.sleep(0.02)
     self.assertEqual(proc.returncode, 0)
     self.assertGreater(tries, 5)
     proc.close()
Пример #30
0
 def perf_spawn_throughput(self):
     # Measure the number of fibers we can spawn per second.
     t0 = t1 = time.time()
     count = [0]
     def dummy_fiber():
         count[0] += 1
     while t1 - t0 < 0.2:
         fiber = Fiber(dummy_fiber)
         fiber.start()
         gruvi.sleep(0)
         t1 = time.time()
     speed = count[0] / (t1 - t0)
     self.add_result(speed)
Пример #31
0
 def test_cleanup(self):
     # After we close() a Hub, it should be garbage collectable, including
     # its event loop.
     hub = gruvi.Hub()
     gruvi.sleep(0)
     ref1 = weakref.ref(hub)
     ref2 = weakref.ref(hub.loop)
     hub.close()
     hub.switch()
     del hub
     gc.collect()
     self.assertIsNone(ref1())
     self.assertIsNone(ref2())
Пример #32
0
 def lock_unlock(self, lock, count):
     failed = 0
     timeouts = 0
     for i in range(count):
         # the granularity of libuv's timers is 1ms.
         gruvi.sleep(random.randint(0, 2) / 1000)
         timeout = random.choice((None, 0.001))
         while not lock.acquire(timeout=timeout):
             timeouts += 1
         gruvi.sleep(random.randint(0, 2) / 1000)
         if lock._locked != 1 or lock._owner is not gruvi.current_fiber():
             failed += 1
         lock.release()
     return failed
Пример #33
0
 def test_pipe(self):
     # Ensure that create_connection() and create_server() can be used to
     # connect to each other over a pipe.
     addr = self.pipename()
     server = create_server(StreamProtocol, addr)
     ctrans, cproto = create_connection(StreamProtocol, addr)
     gruvi.sleep(0.1)  # allow Server to accept()
     strans, sproto = list(server.connections)[0]
     cproto.stream.write(b'foo\n')
     self.assertEqual(sproto.stream.readline(), b'foo\n')
     server.close()
     self.assertEqual(len(list(server.connections)), 0)
     self.assertEqual(cproto.stream.readline(), b'')
     ctrans.close()
Пример #34
0
 def lock_unlock(self, lock, count):
     failed = 0
     timeouts = 0
     for i in range(count):
         # the granularity of libuv's timers is 1ms.
         gruvi.sleep(random.randint(0, 14)/10000)
         timeout = random.choice((None, None, None, 0.001))
         while not lock.acquire(timeout=timeout):
             timeouts += 1
         gruvi.sleep(random.randint(0, 14)/10000)
         if lock._locked != 1 or lock._owner is not gruvi.current_fiber():
             failed += 1
         lock.release()
     return failed
Пример #35
0
 def test_notify_multiple(self):
     # Ensure that multiple fibers can be notified, and that the order in
     # which they are notified is respected.
     cond = gruvi.Condition()
     waiting = [0]
     done = []
     def wait_cond(i):
         with cond:
             waiting[0] += 1
             cond.wait()
             waiting[0] -= 1
             done.append(i)
     fibers = []
     for i in range(10):
         fibers.append(gruvi.spawn(wait_cond, i))
     gruvi.sleep(0)
     self.assertEqual(waiting[0], 10)
     with cond:
         cond.notify(1)
     gruvi.sleep(0)
     self.assertEqual(waiting[0], 9)
     with cond:
         cond.notify(3)
     gruvi.sleep(0)
     self.assertEqual(waiting[0], 6)
     with cond:
         cond.notify_all()
     gruvi.sleep(0)
     self.assertEqual(waiting[0], 0)
     self.assertEqual(done, list(range(10)))
Пример #36
0
    def test_wait(self):
        event = gruvi.Event()
        done = []

        def waiter():
            done.append(False)
            done.append(event.wait())

        gruvi.spawn(waiter)
        gruvi.sleep(0)
        self.assertEqual(done, [False])
        event.set()
        gruvi.sleep(0)
        self.assertEqual(done, [False, True])
Пример #37
0
    def test_duplicate(self):
        futures = [Future()] * 5
        result = []

        def waiter():
            result.append(gruvi.wait(futures))

        fib = Fiber(waiter)
        fib.start()
        gruvi.sleep(0)
        self.assertEqual(result, [])
        futures[0].set_result(None)
        gruvi.sleep(0)
        self.assertEqual(result, [(futures, [])])
Пример #38
0
 def test_pipe(self):
     # Ensure that create_connection() and create_server() can be used to
     # connect to each other over a pipe.
     addr = self.pipename()
     server = create_server(StreamProtocol, addr)
     ctrans, cproto = create_connection(StreamProtocol, addr)
     gruvi.sleep(0.1)  # allow Server to accept()
     strans, sproto = list(server.connections)[0]
     cproto.stream.write(b'foo\n')
     self.assertEqual(sproto.stream.readline(), b'foo\n')
     server.close()
     self.assertEqual(len(list(server.connections)), 0)
     self.assertEqual(cproto.stream.readline(), b'')
     ctrans.close()
Пример #39
0
    def test_notify_multiple(self):
        # Ensure that multiple fibers can be notified, and that the order in
        # which they are notified is respected.
        cond = gruvi.Condition()
        waiting = [0]
        done = []

        def wait_cond(i):
            with cond:
                waiting[0] += 1
                cond.wait()
                waiting[0] -= 1
                done.append(i)

        fibers = []
        for i in range(10):
            fibers.append(gruvi.spawn(wait_cond, i))
        gruvi.sleep(0)
        self.assertEqual(waiting[0], 10)
        with cond:
            cond.notify(1)
        gruvi.sleep(0)
        self.assertEqual(waiting[0], 9)
        with cond:
            cond.notify(3)
        gruvi.sleep(0)
        self.assertEqual(waiting[0], 6)
        with cond:
            cond.notify_all()
        gruvi.sleep(0)
        self.assertEqual(waiting[0], 0)
        self.assertEqual(done, list(range(10)))
Пример #40
0
    def perf_spawn_throughput(self):
        # Measure the number of fibers we can spawn per second.
        t0 = t1 = time.time()
        count = [0]

        def dummy_fiber():
            count[0] += 1

        while t1 - t0 < 0.2:
            fiber = Fiber(dummy_fiber)
            fiber.start()
            gruvi.sleep(0)
            t1 = time.time()
        speed = count[0] / (t1 - t0)
        self.add_result(speed)
Пример #41
0
 def test_basic(self):
     # Ensure that a basic wait/notify works.
     cond = gruvi.Condition()
     waiting = [0]
     def wait_cond():
         with cond:
             waiting[0] += 1
             cond.wait()
             waiting[0] -= 1
     gruvi.spawn(wait_cond)
     gruvi.sleep(0)
     self.assertEqual(waiting[0], 1)
     with cond:
         cond.notify()
     gruvi.sleep(0)
     self.assertEqual(waiting[0], 0)
Пример #42
0
 def test_flow_control(self):
     # Write more bytes than the protocol buffers. Flow control should kick
     # in and alternate scheduling of the producer and the consumer.
     proto = self.protocol
     proto.read_buffer_size = 100
     message = b'{ "id": 1, "method": "foo"}'
     for i in range(1000):
         proto.data_received(message)
         if not proto._reading:
             gruvi.sleep(0)  # run dispatcher
         self.assertTrue(proto._reading)
     mm = self.get_messages()
     self.assertEqual(len(mm), 1000)
     message = json.loads(message.decode('utf8'))
     for m in mm:
         self.assertEqual(m, message)
Пример #43
0
 def test_flow_control(self):
     # Write more bytes than the protocol buffers. Flow control should kick
     # in and alternate scheduling of the producer and the consumer.
     proto = self.protocol
     proto.read_buffer_size = 100
     message = b'{ "id": 1, "method": "foo"}'
     for i in range(1000):
         proto.data_received(message)
         if not proto._reading:
             gruvi.sleep(0)  # run dispatcher
         self.assertTrue(proto._reading)
     mm = self.get_messages()
     self.assertEqual(len(mm), 1000)
     message = json.loads(message.decode('utf8'))
     for m in mm:
         self.assertEqual(m, message)
Пример #44
0
 def perf_switch_throughput(self):
     # Measure the number of switches we can do per second.
     t0 = t1 = time.time()
     count = [0]
     def switch_parent():
         while True:
             gruvi.sleep(0)
     fiber = Fiber(switch_parent)
     fiber.start()
     while t1 - t0 < 0.2:
         gruvi.sleep(0)
         count[0] += 1
         t1 = time.time()
     speed = count[0] / (t1 - t0)
     self.add_result(speed)
     fiber.cancel()
     gruvi.sleep(0)
Пример #45
0
 def test_send_random(self):
     server = JsonRpcServer(echo_app)
     server.listen(('127.0.0.1', 0))
     addr = server.addresses[0]
     client = JsonRpcClient()
     client.connect(addr)
     exc = None
     try:
         while True:
             chunk = os.urandom(1024)
             client.transport.write(chunk)
             gruvi.sleep(0)
     except Exception as e:
         exc = e
     self.assertIsInstance(exc, TransportError)
     server.close()
     client.close()
Пример #46
0
 def test_send_random(self):
     server = JsonRpcServer(echo_app)
     server.listen(('127.0.0.1', 0))
     addr = server.addresses[0]
     client = JsonRpcClient()
     client.connect(addr)
     exc = None
     try:
         while True:
             chunk = os.urandom(1024)
             client.transport.write(chunk)
             gruvi.sleep(0)
     except Exception as e:
         exc = e
     self.assertIsInstance(exc, TransportError)
     server.close()
     client.close()
Пример #47
0
 def test_non_blocking(self):
     # Ensure that the blocking argument to acquire() works.
     lock = gruvi.RLock()
     sync = gruvi.Lock()
     def lock_rlock():
         lock.acquire()
         sync.acquire()
         lock.release()
     # This needs a new fiber, as the same fiber *can* lock the same RLock twice.
     sync.acquire()
     fiber = gruvi.spawn(lock_rlock)
     gruvi.sleep(0)
     self.assertTrue(lock.locked())
     self.assertFalse(lock.acquire(blocking=False))
     sync.release()
     fiber.join()
     self.assertFalse(lock._callbacks)
Пример #48
0
 def sync(self, uuid, model):
     """Synchronize vault `uuid` with the remote peer."""
     if self.client is None:
         raise RuntimeError('Not connected')
     vault = model.get_vault(uuid)
     if vault is None:
         raise SyncApiError('Vault not found')
     vector = model.get_vector(uuid)
     vector = dump_vector(vector)
     url = '/api/vaults/%s/items?vector=%s' % (vault['id'], vector)
     gruvi.sleep(0.1)  # XXX: wait for ssl handshake
     headers = self._get_ed25519_cb_auth(uuid, model)
     response = self._make_request('GET', url, headers)
     if not response:
         raise SyncApiError('Could not make HTTP request')
     status = response.status
     if status != 200:
         self._log.error('expecting HTTP status 200 (got: {})', status)
         raise SyncApiError('Illegal syncapi response')
     if not self._check_ed25519_cb_auth(uuid, response, model):
         raise SyncApiError('Illegal syncapi response')
     initems = response.entity
     if initems is None or not isinstance(initems, list):
         raise SyncApiError('Illegal syncapi response')
     nitems = model.import_items(uuid, initems)
     self._log.debug('imported {} items into model', nitems)
     vector = response.get_header('X-Vector', '')
     try:
         vector = parse_vector(vector)
     except ValueError as e:
         self._log.error('illegal X-Vector header: {} ({})', vector, str(e))
         raise SyncApiError('Invalid response')
     outitems = model.get_items(uuid, vector)
     url = '/api/vaults/%s/items' % uuid
     response = self._make_request('POST', url, headers, outitems)
     if not response:
         raise SyncApiError('Illegal syncapi response')
     if status != 200:
         self._log.error('expecting HTTP status 200 (got: {})', status)
         raise SyncApiError('Illegal syncapi response')
     if not self._check_ed25519_cb_auth(uuid, response, model):
         raise SyncApiError('Illegal syncapi response')
     self._log.debug('succesfully retrieved {} items from peer', len(initems))
     self._log.debug('succesfully pushed {} items to peer', len(outitems))
     return len(initems) + len(outitems)
Пример #49
0
 def test_send_garbage(self):
     # Send random garbage and ensure the connection gets dropped.
     server = DbusServer(echo_app)
     addr = 'unix:path=' + self.pipename()
     server.listen(addr)
     client = DbusClient()
     client.connect(addr)
     exc = None
     try:
         while True:
             chunk = os.urandom(100)
             client.transport.write(chunk)
             gruvi.sleep(0)
     except Exception as e:
         exc = e
     self.assertIsInstance(exc, TransportError)
     server.close()
     client.close()
Пример #50
0
 def test_partial(self):
     # Ensure that the "count" argument of wait() can be used to wait for a
     # subset of the futures to complete.
     futures = [Future() for i in range(10)]
     result = []
     def waiter():
         result.append(gruvi.wait(futures, count=5))
     fib = Fiber(waiter)
     fib.start()
     gruvi.sleep(0)
     for i in range(4):
         futures[i].set_result(None)
     self.assertTrue(fib.alive)
     self.assertEqual(result, [])
     futures[4].set_result(None)
     gruvi.sleep(0)
     self.assertFalse(fib.alive)
     self.assertEqual(result, [(futures[:5], futures[5:])])
Пример #51
0
    def test_basic(self):
        # Ensure that a basic wait/notify works.
        cond = gruvi.Condition()
        waiting = [0]

        def wait_cond():
            with cond:
                waiting[0] += 1
                cond.wait()
                waiting[0] -= 1

        gruvi.spawn(wait_cond)
        gruvi.sleep(0)
        self.assertEqual(waiting[0], 1)
        with cond:
            cond.notify()
        gruvi.sleep(0)
        self.assertEqual(waiting[0], 0)
Пример #52
0
 def test_read_write_flow_control(self):
     # Send a lot of messages filling up the protocol read buffer.
     transport = MockTransport()
     protocol = DbusProtocol(True, self.store_and_echo_messages)
     transport.start(protocol)
     protocol.data_received(b'\0AUTH ANONYMOUS\r\nBEGIN\r\n')
     auth = protocol._authenticator
     self.assertTrue(auth.authenticationSucceeded())
     message = txdbus.MethodCallMessage('/org/freedesktop/DBus', 'Hello',
                     interface='org.freedesktop.DBus', destination='org.freedesktop.DBus')
     protocol.data_received(message.rawMessage)
     gruvi.sleep(0)
     self.assertTrue(protocol._name_acquired)
     interrupted = 0
     message = txdbus.SignalMessage('/my/path', 'Signal', 'my.iface',
                                    signature='s', body=['x'*100])
     msglen = len(message.rawMessage)
     protocol.set_read_buffer_limits(10*msglen)
     transport.buffer.seek(0)
     transport.buffer.truncate()
     transport.set_write_buffer_limits(7*msglen)
     for i in range(100):
         # Fill up protocol read buffer
         message = txdbus.SignalMessage('/my/path', 'Signal', 'my.iface',
                                        signature='s', body=['x'*100])
         protocol.data_received(message.rawMessage)
         if protocol._reading:
             continue
         interrupted += 1
         self.assertGreater(protocol._queue.qsize(), 0)
         # Run the dispatcher to fill up the transport write buffer
         gruvi.sleep(0)
         # Now the write buffer is full and the read buffer still contains
         # some entries because it is larger.
         self.assertTrue(protocol._reading)
         self.assertGreater(protocol._queue.qsize(), 0)
         self.assertFalse(protocol._may_write.is_set())
         # Drain write buffer and resume writing
         transport.buffer.seek(0)
         transport.buffer.truncate()
         protocol.resume_writing()
     # Should be interrupted > 10 times. The write buffer is the limiting factor
     # not the read buffer.
     self.assertGreater(interrupted, 10)
Пример #53
0
    def perf_switch_throughput(self):
        # Measure the number of switches we can do per second.
        t0 = t1 = time.time()
        count = [0]

        def switch_parent():
            while True:
                gruvi.sleep(0)

        fiber = Fiber(switch_parent)
        fiber.start()
        while t1 - t0 < 0.2:
            gruvi.sleep(0)
            count[0] += 1
            t1 = time.time()
        speed = count[0] / (t1 - t0)
        self.add_result(speed)
        fiber.cancel()
        gruvi.sleep(0)
Пример #54
0
    def test_non_blocking(self):
        # Ensure that the blocking argument to acquire() works.
        lock = gruvi.RLock()
        sync = gruvi.Lock()

        def lock_rlock():
            lock.acquire()
            sync.acquire()
            lock.release()

        # This needs a new fiber, as the same fiber *can* lock the same RLock twice.
        sync.acquire()
        fiber = gruvi.spawn(lock_rlock)
        gruvi.sleep(0)
        self.assertTrue(lock.locked())
        self.assertFalse(lock.acquire(blocking=False))
        sync.release()
        fiber.join()
        self.assertFalse(lock._callbacks)
Пример #55
0
    def test_lock_order(self):
        # Locks are fair and are granted in order.
        lock = self.Lock()
        order = []

        def run_test(ix):
            lock.acquire()
            order.append(ix)
            lock.release()

        fibers = []
        for i in range(self.nfibers):
            fibers.append(gruvi.spawn(run_test, i))
        lock.acquire()
        gruvi.sleep(0)
        self.assertEqual(order, [])
        lock.release()
        for fib in fibers:
            fib.join()
        self.assertEqual(order, list(range(len(fibers))))
Пример #56
0
    def test_partial(self):
        # Ensure that the "count" argument of wait() can be used to wait for a
        # subset of the futures to complete.
        futures = [Future() for i in range(10)]
        result = []

        def waiter():
            result.append(gruvi.wait(futures, count=5))

        fib = Fiber(waiter)
        fib.start()
        gruvi.sleep(0)
        for i in range(4):
            futures[i].set_result(None)
        self.assertTrue(fib.alive)
        self.assertEqual(result, [])
        futures[4].set_result(None)
        gruvi.sleep(0)
        self.assertFalse(fib.alive)
        self.assertEqual(result, [(futures[:5], futures[5:])])