mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-28 08:03:36 +00:00
Started to add real unit tests!
We can now verify that Santiago 'queues' and sends requested messages.
This commit is contained in:
parent
f2dd818d3d
commit
e2ef78abbd
@ -40,7 +40,7 @@ class SantiagoHttpListener(santiago.SantiagoListener):
|
||||
<html><head><title>Use it right.</title></head><body>
|
||||
|
||||
<p>Nice try, now try again with a request like:</p>
|
||||
<p>http://localhost:8080/santiago/(requester)/(server)/(service)</p>
|
||||
<p>http://localhost:8080/serve/(requester)/(server)/(service)</p>
|
||||
|
||||
<dl>
|
||||
<dt>requster</dt><dd>james, ian</dd>
|
||||
@ -49,17 +49,17 @@ class SantiagoHttpListener(santiago.SantiagoListener):
|
||||
</dl>
|
||||
|
||||
<p>This'll get you good results:</p>
|
||||
<code><a href="http://localhost:8080/santiago/james/nick/wiki">
|
||||
http://localhost:8080/santiago/james/nick/wiki</a></code>
|
||||
<code><a href="http://localhost:8080/serve/james/wiki/nick">
|
||||
http://localhost:8080/serve/james/wiki/nick</a></code>
|
||||
|
||||
<p>See the <code>serving_to</code>, <code>serving_what</code>, and
|
||||
<code>me</code> variables.</p>
|
||||
|
||||
</body></html>"""
|
||||
|
||||
def __init__(self, instance, port=8080):
|
||||
super(SantiagoHttpListener, self).__init__(instance)
|
||||
self.socket_port = port
|
||||
def __init__(self, instance, location="localhost:8080"):
|
||||
super(SantiagoHttpListener, self).__init__(instance, location)
|
||||
self.socket_port = location.rpartition(":")[2]
|
||||
|
||||
@cherrypy.expose
|
||||
@cherrypy.tools.json_out()
|
||||
|
||||
@ -66,7 +66,7 @@ class Santiago(object):
|
||||
Each Santiago keeps track of the services it hosts, and other servers'
|
||||
Santiago services. A Santiago has no idea of and is not responsible for
|
||||
anybody else's services.
|
||||
|
||||
|
||||
"""
|
||||
self.instance = instance
|
||||
self.hosting = self.load_dict("hosting")
|
||||
@ -95,7 +95,7 @@ class Santiago(object):
|
||||
|
||||
def am_i(self, server):
|
||||
"""Hello? Is it me you're looking for?"""
|
||||
|
||||
|
||||
return self.instance == server
|
||||
|
||||
# Server-related tags
|
||||
@ -106,7 +106,7 @@ class Santiago(object):
|
||||
|
||||
post::
|
||||
|
||||
location in cfg.santiago.hosting[service]
|
||||
location in self.hosting[service]
|
||||
|
||||
"""
|
||||
self.hosting[service].append(location)
|
||||
@ -116,7 +116,7 @@ class Santiago(object):
|
||||
|
||||
post::
|
||||
|
||||
service in cfg.santiago.keys[key]
|
||||
service in self.keys[key]
|
||||
|
||||
"""
|
||||
self.keys[key].append(service)
|
||||
@ -129,7 +129,7 @@ class Santiago(object):
|
||||
|
||||
post::
|
||||
|
||||
forall(locations, lambda x: x in cfg.santiago.servers[service][key])
|
||||
forall(locations, lambda x: x in self.servers[service][key])
|
||||
|
||||
"""
|
||||
self.servers[service][key] += locations
|
||||
@ -139,7 +139,7 @@ class Santiago(object):
|
||||
|
||||
def add_listener(self, listener):
|
||||
"""Registers a protocol-specific listener."""
|
||||
|
||||
|
||||
self.listeners.append(listener)
|
||||
|
||||
def add_sender(self, sender):
|
||||
@ -149,18 +149,19 @@ class Santiago(object):
|
||||
|
||||
# processing related tags
|
||||
# -----------------------
|
||||
|
||||
def serve(self, key, service, server, hops, santiagi):
|
||||
|
||||
def serve(self, key, service, server, hops, santiagi, listener):
|
||||
"""Provide a requested service to a client."""
|
||||
|
||||
if santiagi is not None:
|
||||
self.learn_service("santiago", key, santiagi)
|
||||
|
||||
if not self.am_i(server):
|
||||
return self.proxy(key, service, server, hops=hops)
|
||||
self.proxy(key, service, server, hops=hops)
|
||||
|
||||
if service in self.keys[key]:
|
||||
return self.hosting[service]
|
||||
# TODO pick the senders more intelligently.
|
||||
self.senders[0].ack(key, self.hosting[service], listener)
|
||||
|
||||
def proxy(self, key, service, server, hops=3):
|
||||
"""Passes a Santiago request off to another known host.
|
||||
@ -183,11 +184,12 @@ class Santiago(object):
|
||||
class SantiagoListener(object):
|
||||
"""Listens for requests on the santiago port."""
|
||||
|
||||
def __init__(self, santiago):
|
||||
def __init__(self, santiago, location):
|
||||
self.santiago = santiago
|
||||
self.location = location
|
||||
|
||||
def serve(self, key, service, server, hops, santiagi):
|
||||
return self.santiago.serve(key, service, server, hops, santiagi)
|
||||
return self.santiago.serve(key, service, server, hops, santiagi, self.location)
|
||||
|
||||
|
||||
class SantiagoSender(object):
|
||||
@ -195,6 +197,14 @@ class SantiagoSender(object):
|
||||
|
||||
def __init__(self, santiago):
|
||||
self.santiago = santiago
|
||||
self.messages = list()
|
||||
|
||||
def send(self):
|
||||
"""Sends all messages on the queue."""
|
||||
|
||||
answer = self.messages
|
||||
self.messages = list()
|
||||
return answer
|
||||
|
||||
def request(self, destination, resource):
|
||||
"""Sends a request for a resource to a known Santiago.
|
||||
@ -216,7 +226,7 @@ class SantiagoSender(object):
|
||||
# TODO my request is signed with my GPG key, recipient encrypted.
|
||||
|
||||
"""
|
||||
pass # TODO: do.
|
||||
pass # TODO: queue a request message.
|
||||
|
||||
def nak(self):
|
||||
"""Denies a requested resource to a Santiago.
|
||||
@ -227,7 +237,7 @@ class SantiagoSender(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def ack(self):
|
||||
def ack(self, key, location, listener=None):
|
||||
"""A successful reply to a Santiago request.
|
||||
|
||||
The response must include:
|
||||
@ -239,7 +249,10 @@ class SantiagoSender(object):
|
||||
- The Santiago listener that received and accepted the request.
|
||||
|
||||
"""
|
||||
pass
|
||||
self.messages.append({
|
||||
"to": key,
|
||||
"location": location,
|
||||
"reply-to": listener,})
|
||||
|
||||
def end(self):
|
||||
"""Sent by the original requester, when it receives the server's
|
||||
@ -252,7 +265,7 @@ class SantiagoSender(object):
|
||||
|
||||
def proxy(self, key, service, server, hops):
|
||||
"""Sends the request to another server."""
|
||||
|
||||
|
||||
# TODO pull this off, another day.
|
||||
return ("%(key)s is requesting the %(service)s from %(server)s. " +
|
||||
self.santiago.instance + " is not %(server)s. " +
|
||||
|
||||
@ -14,30 +14,117 @@
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from protocols.http import SantiagoHttpSender, SantiagoHttpListener
|
||||
import santiago
|
||||
# TODO import some http client and validate my responses!
|
||||
import sys
|
||||
|
||||
class TestInitialRequest(unittest.TestCase):
|
||||
|
||||
class SantiagoTest(unittest.TestCase):
|
||||
"""The base class for tests."""
|
||||
|
||||
def setUp(self):
|
||||
self.santiago = santiago.Santiago("0x1")
|
||||
|
||||
if sys.version_info < (2, 7):
|
||||
"""Add a poor man's forward compatibility."""
|
||||
|
||||
class ContainsError(AssertionError):
|
||||
pass
|
||||
|
||||
def assertIn(self, a, b):
|
||||
if not a in b:
|
||||
raise self.ContainsError("%s not in %s" % (a, b))
|
||||
|
||||
class TestDataModel(SantiagoTest):
|
||||
"""Test adding and removing services and data."""
|
||||
|
||||
def test_add_listener(self):
|
||||
"""Verify that we can add a listener."""
|
||||
|
||||
http_listener = SantiagoHttpListener(self.santiago, "localhost:8080")
|
||||
self.santiago.add_listener(http_listener)
|
||||
|
||||
self.assertIn(http_listener, self.santiago.listeners)
|
||||
|
||||
def test_add_sender(self):
|
||||
"""Verify that we can add a sender."""
|
||||
|
||||
http_sender = SantiagoHttpSender(self.santiago)
|
||||
self.santiago.add_sender(http_sender)
|
||||
|
||||
self.assertIn(http_sender, self.santiago.senders)
|
||||
|
||||
def test_provide_at_location(self):
|
||||
"""Verify that we can provide a service somewhere."""
|
||||
|
||||
service, location = ("something", "there")
|
||||
self.santiago.provide_at_location(service, location)
|
||||
|
||||
self.assertIn(location, self.santiago.hosting[service])
|
||||
|
||||
def test_provide_for_key(self):
|
||||
"""Verify we can provide a specific service to someone."""
|
||||
|
||||
service, key = ("something", "0x1")
|
||||
self.santiago.provide_for_key(service, key)
|
||||
|
||||
self.assertIn(service, self.santiago.keys[key])
|
||||
|
||||
|
||||
class TestServing(SantiagoTest):
|
||||
"""TODO: tests for:
|
||||
|
||||
(normal serving + proxying) * (learning santiagi + not learning)
|
||||
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TestServing, self).setUp()
|
||||
|
||||
self.santiago.provide_at_location("wiki", "192.168.0.13")
|
||||
self.santiago.provide_for_key("wiki", "0x2")
|
||||
|
||||
self.listener = santiago.SantiagoListener(self.santiago, "localhost:8080")
|
||||
self.sender = santiago.SantiagoSender(self.santiago)
|
||||
self.santiago.add_listener(self.listener)
|
||||
self.santiago.add_sender(self.sender)
|
||||
|
||||
def test_successful_serve(self):
|
||||
"""Make sure we get an expected, successful serving message back."""
|
||||
|
||||
self.listener.serve("0x2", "wiki", "0x1", 0, None)
|
||||
expected = [
|
||||
{ "to": "0x2",
|
||||
"location": ["192.168.0.13"],
|
||||
"reply-to": self.listener.location, }, ]
|
||||
|
||||
self.assertEqual(self.sender.send(), expected)
|
||||
|
||||
|
||||
class TestConsuming(SantiagoTest):
|
||||
"""TODO: tests for:
|
||||
|
||||
(learning services)
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
class TestInitialRequest(SantiagoTest):
|
||||
"""Testing the initial request.
|
||||
|
||||
Does Santiago produce well-formed output when creating a service request?
|
||||
|
||||
"""
|
||||
def setup(self):
|
||||
requester = santiago.SantiagoSender("initial_requester")
|
||||
destination = santiago.SantiagoListener("initial_destination",8081)
|
||||
|
||||
def test_valid_request(self):
|
||||
"""When requested, does Santiago send out an appropriate message?"""
|
||||
|
||||
# TODO finish these and otehr tests
|
||||
requester.request(destination="james", service="wiki")
|
||||
|
||||
class TestInitialResponse(unittest.TestCase):
|
||||
pass
|
||||
|
||||
class TestForwardedRequest(unittest.TestCase):
|
||||
class TestInitialResponse(SantiagoTest):
|
||||
pass
|
||||
|
||||
class TestForwardedResponse(unittest.TestCase):
|
||||
class TestForwardedRequest(SantiagoTest):
|
||||
pass
|
||||
|
||||
class TestForwardedResponse(SantiagoTest):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user