From 2d1e473a9bf8cb231451204b190e005f13264888 Mon Sep 17 00:00:00 2001 From: Nick Daly Date: Thu, 22 Mar 2012 07:19:58 -0500 Subject: [PATCH] Added a few notes about why this is difficult to test. - Reorganized file a little. - Test requests are now from and to real clients. --- ugly_hacks/santiago/test_santiago.py | 173 ++++++++++++++++++--------- 1 file changed, 115 insertions(+), 58 deletions(-) diff --git a/ugly_hacks/santiago/test_santiago.py b/ugly_hacks/santiago/test_santiago.py index fda4d08ba..cc3b46194 100644 --- a/ugly_hacks/santiago/test_santiago.py +++ b/ugly_hacks/santiago/test_santiago.py @@ -1,3 +1,6 @@ +#! /usr/bin/python -*- mode: autofill; fill-column: 80 -*- + + """Making Santiago dance, in 4 parts: - Validating the initial request (playing B). @@ -11,8 +14,33 @@ - Validating the direct response (playing A). - Validating the indirect response (playing C, B, and A). +FIXME: Can't use the current CPy setup. It never returns, so I can't test +against it. + +If I produce a listener that just echoes the parameters, I can validate the response: + + import httplib, urllib + + params = urllib.urlencode({'@number': 12524, '@type': 'issue', '@action': 'show'}) + headers = {"Content-type": "application/x-www-form-urlencoded", + "Accept": "text/plain"} + conn = httplib.HTTPConnection("bugs.python.org") + print params, headers, conn + + conn.request("POST", "", params, headers) + response = conn.getresponse() + print response.status, response.reason + + data = response.read() + print data + + conn.close() + + """ + +import cherrypy import unittest from protocols.http import SantiagoHttpSender, SantiagoHttpListener import santiago @@ -43,6 +71,29 @@ class SantiagoTest(unittest.TestCase): self.santiago_a = Santiago(listeners_a, senders_a, hosting_a, consuming_a) self.santiago_b = Santiago(listeners_b, senders_b, hosting_b, consuming_b) + def serveOnPort(self, port): + """Start listening for connections on a named port. + + Used in testing as a mock listener for responses from a Santiago server. + + """ + class RequestReceiver(object): + """A very basic listener. + + It merely records the calling arguments. + + """ + @cherrypy.expose + def index(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs + + self.socket_port = port + + self.receiver = RequestReceiver() + + cherrypy.quickstart(self.receiver) + if sys.version_info < (2, 7): """Add a poor man's forward compatibility.""" @@ -53,6 +104,44 @@ class SantiagoTest(unittest.TestCase): if not a in b: raise self.ContainsError("%s not in %s" % (a, b)) +class TestClientInitialRequest(SantiagoTest): + """Does the client send a correctly formed request? + + In these tests, we're sending requests to a mock listener which merely + records that the requests were well-formed. + + """ + def setUp(self): + super(SantiagoTest, self).setUp() + + self.serveOnPort(8000) + + def test_request(self): + """Verify that A queues a properly formatted initial request.""" + + self.santiago_a.request(from_="a", to="b", + client="a", host="b", + service="wiki", reply_to="localhost:9001") + + self.assertEqual(self.santiago_a.outgoing_messages, + [{ "from": "a", "to": "b", + "client": "a", "host": "b", + "service": "wiki", "reply-to": "localhost:9001"}]) + + def test_request(self): + """Verify that A sends out a properly formatted initial request.""" + + self.santiago_a.request(from_="a", to="b", + client="a", host="b", + service="wiki", reply_to="localhost:9001") + + self.santiago_a.process() + + self.assertEqual(self.receiver.kwargs, + [{ "from": "a", "to": "b", + "client": "a", "host": "b", + "service": "wiki", "reply-to": "localhost:9001"}]) + class TestServerInitialRequest(SantiagoTest): """Test how the Santiago server replies to initial service requests. @@ -68,6 +157,11 @@ class TestServerInitialRequest(SantiagoTest): untrusted client, B ignores it. """ + def setUp(self): + super(SantiagoTest, self).setUp() + + self.serveOnPort(9000) + def test_acknowledgement(self): """If B receives an authorized request, then it replies with a location. @@ -77,7 +171,7 @@ class TestServerInitialRequest(SantiagoTest): In this case, B will answer with the wiki's location. """ - self.santiago_b.receive(from_=None, to=None, + self.santiago_b.receive(from_="a", to="b", client="a", host="b", service="wiki", reply_to=None) @@ -90,13 +184,13 @@ class TestServerInitialRequest(SantiagoTest): "locations": ["192.168.0.13"], "reply-to": "localhost:8000"}]) - def test_reject_bad_service(self) + def test_reject_bad_service(self): """Does B reject requests for unsupported services? In this case, B should reply with an empty list of locations. """ - self.santiago_b.receive(from_=None, to=None, + self.santiago_b.receive(from_="a", to="b", client="a", host="b", service="wiki", reply_to=None) @@ -119,7 +213,7 @@ class TestServerInitialRequest(SantiagoTest): In this case, B will never answer the request. """ - self.santiago_b.receive(from_=None, to=None, + self.santiago_b.receive(from_="a", to="b", client="z", host="b", service="wiki", reply_to=None) @@ -132,7 +226,11 @@ class TestServerInitialRequest(SantiagoTest): untrusted key connection attempt. """ - self.fail() + self.santiago_b.receive(from_="a", to="b", + client="z", host="b", + service="wiki", reply_to=None) + + self.assertEqual(self.santiago_b.outgoing_messages, []) def test_reject_bad_source_good_client(self): """B is silent when an untrusted key proxies anything for a trusted key. @@ -141,7 +239,11 @@ class TestServerInitialRequest(SantiagoTest): untrusted key connection attempt. """ - self.fail() + self.santiago_b.receive(from_="z", to="b", + client="a", host="b", + service="wiki", reply_to=None) + + self.assertEqual(self.santiago_b.outgoing_messages, []) def test_reject_bad_source_bad_client(self): """B is silent when untrusted keys proxy anything for untrusted keys. @@ -150,7 +252,11 @@ class TestServerInitialRequest(SantiagoTest): connection attempt. """ - self.fail() + self.santiago_b.receive(from_="y", to="b", + client="z", host="b", + service="wiki", reply_to=None) + + self.assertEqual(self.santiago_b.outgoing_messages, []) def test_learn_santaigo(self): """Does B learn new Santiago locations from trusted requests? @@ -158,7 +264,7 @@ class TestServerInitialRequest(SantiagoTest): If A sends B a request with a new Santiago location, B should learn it. """ - self.santiago_b.receive(from_=None, to=None, + self.santiago_b.receive(from_="a", to="b", client="a", host="b", service="wiki", reply_to="localhost:9001") @@ -168,62 +274,13 @@ class TestServerInitialRequest(SantiagoTest): def test_handle_requests_once(self): """Verify that we reply to each request only once.""" - self.santiago_b.receive(from_=None, to=None, + self.santiago_b.receive(from_="a", to="b", client="a", host="b", service="wiki", reply_to=None) self.santiago_b.process() self.assertEqual(self.santiago_b.outgoing_messages, []) -class TestClientInitialRequest(SantiagoTest): - """Does the client send a correctly formed request? - - In these tests, we're sending requests to a mock listener which merely - records that the requests were well-formed. - - """ - def setUp(self): - super(SantiagoTest, self).setUp() - - import cherrypy - class RequestReceiver(object): - - def index(self, *args, **kwargs): - self.args = *args - self.kwargs = **kwargs - - index.exposed = True - self.socket_port = 8000 - - self.receiver = RequestReceiver() - cherrypy.quickstart(self.receiver) - - def test_request(self): - """Verify that A queues a properly formatted initial request.""" - - self.santiago_a.request(from_="a", to="b", - client="a", host="b", - service="wiki", reply_to="localhost:9001") - - self.assertEqual(self.santiago_a.outgoing_messages, - [{ "from": "a", "to": "b", - "client": "a", "host": "b", - "service": "wiki", "reply-to": "localhost:9001"})] - - def test_request(self): - """Verify that A sends out a properly formatted initial request.""" - - self.santiago_a.request(from_="a", to="b", - client="a", host="b", - service="wiki", reply_to="localhost:9001") - - self.santiago_a.process() - - self.assertEqual(self.receiver.kwargs, - [{ "from": "a", "to": "b", - "client": "a", "host": "b", - "service": "wiki", "reply-to": "localhost:9001"})] - class TestServerInitialResponse(SantiagoTest): pass