Ejemplo n.º 1
0
 def test_write(self):
     data = io.BytesIO()
     stream = messaging.JsonIOStream(data, data, "data")
     for message in self.MESSAGES:
         stream.write_json(message)
     data = data.getvalue()
     assert data == self.SERIALIZED_MESSAGES
Ejemplo n.º 2
0
 def test_read(self):
     data = io.BytesIO(self.SERIALIZED_MESSAGES)
     stream = messaging.JsonIOStream(data, data, "data")
     for expected_message in self.MESSAGES:
         message = stream.read_json()
         assert message == expected_message
     with pytest.raises(messaging.NoMoreMessages) as exc_info:
         stream.read_json()
     assert exc_info.value.stream is stream
Ejemplo n.º 3
0
def start():
    global _stream, _process, _worker_log_filename
    if _stream is not None:
        return

    args = [sys.executable, worker.__file__, str(os.getpid())]
    log.info(
        "Spawning {0} for tests-{1}:\n\n{2}",
        _name,
        os.getpid(),
        "\n".join(repr(s) for s in args),
    )

    _process = psutil.Popen(args,
                            bufsize=0,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE)

    _stream = messaging.JsonIOStream(_process.stdout, _process.stdin, _name)

    event, _worker_log_filename = _stream.read_json()
    assert event == "watchdog"

    atexit.register(stop)
Ejemplo n.º 4
0
    def test_fuzz(self):
        # Set up two channels over the same stream that send messages to each other
        # asynchronously, and record everything that they send and receive.
        # All records should match at the end.

        class Fuzzer(object):
            def __init__(self, name):
                self.name = name
                self.lock = threading.Lock()
                self.sent = []
                self.received = []
                self.responses_sent = []
                self.responses_received = []
                self.done = False

            def start(self, channel):
                self._worker = threading.Thread(
                    name=self.name,
                    target=lambda: self._send_requests_and_events(channel),
                )
                self._worker.daemon = True
                self._worker.start()

            def wait(self):
                self._worker.join()

            def done_event(self, event):
                with self.lock:
                    self.done = True

            def fizz_event(self, event):
                assert event.event == "fizz"
                with self.lock:
                    self.received.append(("event", "fizz", event.body))

            def buzz_event(self, event):
                assert event.event == "buzz"
                with self.lock:
                    self.received.append(("event", "buzz", event.body))

            def event(self, event):
                with self.lock:
                    self.received.append(("event", event.event, event.body))

            def make_and_log_response(self, request):
                x = random.randint(-100, 100)
                if x < 0:
                    exc_type = (messaging.InvalidMessageError if x %
                                2 else messaging.MessageHandlingError)
                    x = exc_type(str(x), request)
                with self.lock:
                    self.responses_sent.append((request.seq, x))
                return x

            def fizz_request(self, request):
                assert request.command == "fizz"
                with self.lock:
                    self.received.append(
                        ("request", "fizz", request.arguments))
                return self.make_and_log_response(request)

            def buzz_request(self, request):
                assert request.command == "buzz"
                with self.lock:
                    self.received.append(
                        ("request", "buzz", request.arguments))
                return self.make_and_log_response(request)

            def request(self, request):
                with self.lock:
                    self.received.append(
                        ("request", request.command, request.arguments))
                return self.make_and_log_response(request)

            def _got_response(self, response):
                with self.lock:
                    self.responses_received.append(
                        (response.request.seq, response.body))

            def _send_requests_and_events(self, channel):
                types = [
                    random.choice(("event", "request")) for _ in range(0, 100)
                ]

                for typ in types:
                    name = random.choice(("fizz", "buzz", "fizzbuzz"))
                    body = random.randint(0, 100)

                    with self.lock:
                        self.sent.append((typ, name, body))

                    if typ == "event":
                        channel.send_event(name, body)
                    elif typ == "request":
                        req = channel.send_request(name, body)
                        req.on_response(self._got_response)

                channel.send_event("done")

                # Spin until we receive "done", and also get responses to all requests.
                requests_sent = types.count("request")
                log.info("{0} waiting for {1} responses...", self.name,
                         requests_sent)
                while True:
                    with self.lock:
                        if self.done:
                            if requests_sent == len(self.responses_received):
                                break
                    time.sleep(0.1)

        fuzzer1 = Fuzzer("fuzzer1")
        fuzzer2 = Fuzzer("fuzzer2")

        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.bind(("localhost", 0))
        _, port = server_socket.getsockname()
        server_socket.listen(0)

        socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socket1_thread = threading.Thread(
            target=lambda: socket1.connect(("localhost", port)))
        socket1_thread.start()
        socket2, _ = server_socket.accept()
        socket1_thread.join()

        try:
            io1 = socket1.makefile("rwb", 0)
            io2 = socket2.makefile("rwb", 0)

            stream1 = messaging.JsonIOStream(io1, io1, "socket1")
            channel1 = messaging.JsonMessageChannel(stream1, fuzzer1)
            channel1.start()
            fuzzer1.start(channel1)

            stream2 = messaging.JsonIOStream(io2, io2, "socket2")
            channel2 = messaging.JsonMessageChannel(stream2, fuzzer2)
            channel2.start()
            fuzzer2.start(channel2)

            fuzzer1.wait()
            fuzzer2.wait()

        finally:
            socket1.close()
            socket2.close()

        assert fuzzer1.sent == fuzzer2.received
        assert fuzzer2.sent == fuzzer1.received
        assert fuzzer1.responses_sent == fuzzer2.responses_received
        assert fuzzer2.responses_sent == fuzzer1.responses_received