From 9cf029a190b007c10e36c6c43bdb0acbd07b367e Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Tue, 20 Jan 2015 18:09:38 +0000 Subject: distbuild: Add a test to ensure JsonMachine is robust This is important to avoid distbuild processes crashing (or worse) if they are sent unexpected input. --- distbuild/jm_tests.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ without-test-modules | 1 - 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 distbuild/jm_tests.py diff --git a/distbuild/jm_tests.py b/distbuild/jm_tests.py new file mode 100644 index 00000000..87bf1b51 --- /dev/null +++ b/distbuild/jm_tests.py @@ -0,0 +1,75 @@ +# coding=utf8 +# mainloop/jm_tests.py -- testcases for JSON-parsing state machine abstraction +# +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.. + + +import contextlib +import logging +import socket +import unittest + +import distbuild + + +class JsonMachineTests(unittest.TestCase): + def setUp(self): + self.loop = distbuild.MainLoop() + + @contextlib.contextmanager + def listening_json_machine(self, port): + '''Return a writable socket connected to an example JSON machine. + + This example uses the code path that listens for incoming build jobs + from remote machines running `morph distbuild`. + + ''' + listener = distbuild.ListenServer( + 'localhost', port, distbuild.InitiatorConnection, [None, None]) + self.loop.add_state_machine(listener) + + listen_socket = socket.socket() + try: + listen_socket.connect(('localhost', port)) + self.loop._run_once() + yield listen_socket + finally: + logging.info('Shutting down test connection handler') + listen_socket.shutdown(socket.SHUT_RDWR) + listener.close() + self.loop.run() + + def test_invalid_input(self): + '''Distbuild processes must be robust against invalid input. + + Anyone can write to the port that listens for connections from the + `morph distbuild` command. It should not be possible to break the + distbuild controller by sending it unexpected input. + + ''' + def send_and_process(string): + sock.sendall(string + '\n') + self.loop._run_once() + + invalid_inputs = [ + 'fooin', + '{ "foo": "bar" }', + bytearray([1, 185, 5, 53]), + ] + + with self.listening_json_machine(7979) as sock: + for message in invalid_inputs: + send_and_process(message) diff --git a/without-test-modules b/without-test-modules index 530deb4f..584e603b 100644 --- a/without-test-modules +++ b/without-test-modules @@ -40,7 +40,6 @@ distbuild/helper_router.py distbuild/idgen.py distbuild/initiator.py distbuild/initiator_connection.py -distbuild/jm.py distbuild/json_router.py distbuild/mainloop.py distbuild/protocol.py -- cgit v1.2.1