From c0643834b9ee30204b049b716ae22c25ba86f49f Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Tue, 17 Feb 2009 16:17:03 +0000 Subject: mesh.py and simplemeshtest.py should be in lib/gibber/tests --- lib/gibber/tests/mesh.py | 235 +++++++++++++++++++++++++++++++++++++ lib/gibber/tests/simplemeshtest.py | 101 ++++++++++++++++ tests/Makefile.am | 2 - tests/mesh.py | 235 ------------------------------------- tests/simplemeshtest.py | 101 ---------------- 5 files changed, 336 insertions(+), 338 deletions(-) create mode 100644 lib/gibber/tests/mesh.py create mode 100644 lib/gibber/tests/simplemeshtest.py delete mode 100644 tests/mesh.py delete mode 100644 tests/simplemeshtest.py diff --git a/lib/gibber/tests/mesh.py b/lib/gibber/tests/mesh.py new file mode 100644 index 00000000..e0a7fef8 --- /dev/null +++ b/lib/gibber/tests/mesh.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python + +from twisted.internet import reactor, protocol +from base64 import b64encode, b64decode +from struct import unpack +import random + +packettypes = { 0: "Whois request", + 1: "Whois reply", + 2: "Repair request", + 3: "Session", + 0xf: "Data", + 0x10: "No data", + 0x11: "Failure", + 0x12: "Attempt join", + 0x13: "Join", + 0x14: "Bye" +} + +WHOIS_REQUEST = 0x0 +WHOIS_REPLY = 0x1 +REPAIR_REQUEST = 0x2 +SESSION = 0x3 +DATA = 0xf +NO_DATA = 0x10 +FAILURE = 0x11 +ATTEMPT_JOIN = 0x12 +JOIN = 0x13 +BYE = 0x14 + +def packet_sender(data): + return unpack ("!I", data[8:12])[0] + +def packet_type(data): + return unpack("B", data[7])[0] + +def dump_depends(data): + sender = packet_sender(data) + num_senders = unpack("B", data[16])[0] + print "sender: %x (%d)" % (sender, num_senders) + for x in xrange (0, num_senders): + (sender, depend) = unpack("!II", data[17 + x:17 + x + 8]) + print "%x:\t%x" % (sender, depend) + + +class BaseMeshNode(protocol.ProcessProtocol): + delimiter = '\n' + __buffer = '' + + def __init__(self, name): + self.name = name + self.process = reactor.spawnProcess(self, + "./test-r-multicast-transport-io", + ("test-r-multicast-transport-io", name), + None) + self.peers = [] + self.packets = {} + + def sendPacket(self, data): + "Should be overridden" + print "Should send: " + data + + def __sendPacket(self, data): + binary = b64decode(data) + type = packet_type(binary) + self.packets[type] = self.packets.get(type, 0) + 1 + return self.sendPacket(binary) + + def stats(self): + print "-------" + self.name + "-------" + for (a,b) in self.packets.iteritems(): + print packettypes[a] + ":\t" + str(b) + + def gotOutput(self, sender, data): + "Should be overridden" + print "Output: " + data + + def node_connected(self): + "Should be overridden" + print "Connected!!" + + def node_disconnected(self): + "Should be overridden" + print "Disconnected!!" + + def __connected(self, data): + self.node_connected() + + def __disconnected(self, data): + self.node_disconnected() + + def __gotOutput(self, data): + (sender, rawdata) = data.split(":", 1) + self.gotOutput(sender, b64decode(rawdata)) + + + def newNode(self, data): + if not data in self.peers: + self.peers.append(data) + + def __newNodes(self, data): + for x in data.split(): + self.newNode(x) + + def leftNode(self, node): + self.peers.remove(node) + + def __leftNodes(self, data): + for x in data.split(): + self.leftNode (x) + + def recvPacket(self, data): + self.process.write("RECV:" + b64encode(data) + "\n") + + def pushInput(self, data): + self.process.write("INPUT:" + b64encode(data) + "\n") + + def fail(self, name): + self.process.write("FAIL:" + name + "\n") + + def disconnect(self): + self.process.write("DISCONNECT\n") + + def lineReceived(self, line): + commands = { "SEND" : self.__sendPacket, + "OUTPUT" : self.__gotOutput, + "CONNECTED" : self.__connected, + "DISCONNECTED" : self.__disconnected, + "NEWNODES" : self.__newNodes, + "LOSTNODES" : self.__leftNodes + } + + parts = line.rstrip().split(":", 1) + if len(parts) == 2: + command = parts[0] + rawdata = parts[1] + if command in commands: + commands[command](rawdata) + return + self.unknownOutput(line) + + def unknownOutput(self, line): + print self.name + " (U) " + line.rstrip() + + def outReceived(self, data): + lines = (self.__buffer + data).split(self.delimiter) + self.__buffer = lines.pop(-1) + for line in lines: + self.lineReceived(line) + + def errReceived(self, data): + print self.name + " Error: " + data.rstrip() + + def processEnded(self, reason): + if self.process.status != 0: + print "process ended: " + str(reason) + +class MeshNode(BaseMeshNode): + def __init__(self, name, mesh): + BaseMeshNode.__init__(self, name) + self.mesh = mesh + + def sendPacket(self, data): + self.mesh.sendPacket(self, data) + + def gotOutput(self, sender, data): + self.mesh.gotOutput(self, sender, data) + + def node_connected(self): + self.mesh.connected(self) + +class Link: + def __init__(self, target, bandwidth, latency, dropchance): + self.target = target + self.bandwidth = bandwidth + self.latency = latency + self.dropchance = dropchance + + def send(self, data): + if random.random() > self.dropchance: + self.target.recvPacket(data) + +class Mesh: + def __init__ (self): + self.nodes = [] + self.connections = {} + + def connect(self, node): + print node.name + " got connected" + + def gotOutput(self, node, sender, data): + print "Got " + data + " from " + node.name + " send by " + sender + + def connect(self, node0, node1, bandwidth, latency, dropchance): + self.connections.setdefault(node0, []).append( + Link(node1, bandwidth, latency, dropchance)) + + def connect_duplex(self, node0, node1, bandwidth, latency, dropchance): + self.connect(node0, node1, bandwidth, latency, dropchance) + self.connect(node1, node0, bandwidth, latency, dropchance) + + def connect_full(self, bandwidth, latency, dropchance): + self.connections = {} + for x in self.nodes: + for y in self.nodes: + if x != y: + self.connect(x, y, bandwidth, latency, dropchance) + + def sendPacket(self, node, data): + conn = self.connections.get(node, []) + for link in conn: + link.send(data) + + def addNode(self, name): + node = MeshNode(name, self) + self.nodes.append(node) + return node + + def addMeshNode(self, node): + self.nodes.append(node) + return node + + def removeMeshNode (self, node): + self.nodes.remove(node) + del self.connections[node] + for (n, links) in self.connections.iteritems(): + for link in links: + if link.target == node: + self.connections[n].remove(link) + + + def connected (self, node): + "To be overwritten" + pass + diff --git a/lib/gibber/tests/simplemeshtest.py b/lib/gibber/tests/simplemeshtest.py new file mode 100644 index 00000000..575eeb94 --- /dev/null +++ b/lib/gibber/tests/simplemeshtest.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +from twisted.internet import reactor +from mesh import Mesh, MeshNode +import sys + +NUMNODES = 5 +NUMPACKETS = 10 +DELAY = 0.1 + + +nodes = [] +# We're optimists +success = True + +class TestMeshNode(MeshNode): + nodes = 1 + + def __init__ (self, name, mesh): + MeshNode.__init__(self, name, mesh) + + def node_connected(self): + MeshNode.node_connected(self) + print "Connected" + + def newNode (self, data): + MeshNode.newNode (self, data) + print "node0 - Added " + data + self.nodes += 1 + if self.nodes == NUMNODES: + print "Everybody joined" + for x in xrange(0, NUMPACKETS): + reactor.callLater(0.1 * x, (lambda y: self.pushInput(str(y) + "\n")), x) + + def leftNode (self, data): + MeshNode.leftNode (self, data) + print data.rstrip() + " left" + reactor.stop() + +class TestMesh(Mesh): + expected = {} + done = 0 + + def gotOutput(self, node, sender, data): + global success + + if self.expected.get(node) == None: + self.expected[node] = 0 + + if (self.expected.get(node, int(data)) != int(data)): + print "Got " + data.rstrip() + " instead of " + \ + str(self.expected[node]) + " from " + node.name + + success = False + reactor.crash() + + if not sender in node.peers: + print "Sender " + sender + " not in node peers" + success = False + reactor.crash() + + self.expected[node] = int(data) + 1 + + if self.expected[node] == 10: + self.done += 1 + + if self.done == NUMNODES - 1: + for x in self.nodes: + x.stats() + self.nodes[-1].disconnect() + +m = TestMesh() + + +n = TestMeshNode("node0", m) +nodes.append(n) +m.addMeshNode(n) + +for x in xrange(1, NUMNODES): + nodes.append(m.addNode("node" + str(x))) + +# Connect all nodes to all others. 1024 bytes/s bandwidth, 50ms delay and 0% +# packet loss.. (bandwidth and delay aren't implemented just yet) +m.connect_full(1024, 50, 0.30) + +def timeout(): + global success + print "TIMEOUT!" + success = False + reactor.crash() + +reactor.callLater(60, timeout) + +reactor.run() + + +if not success: + print "FAILED" + sys.exit(-1) + +print "SUCCESS" diff --git a/tests/Makefile.am b/tests/Makefile.am index 405e3b7a..3856abed 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -10,8 +10,6 @@ $(top_builddir)/lib/gibber/libgibber.la: .PHONY: $(top_builddir)/lib/gibber/libgibber.la -EXTRA_DIST = simplemeshtest.py mesh.py $(check_SCRIPTS) - noinst_PROGRAMS = \ telepathy-salut-debug diff --git a/tests/mesh.py b/tests/mesh.py deleted file mode 100644 index e0a7fef8..00000000 --- a/tests/mesh.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python - -from twisted.internet import reactor, protocol -from base64 import b64encode, b64decode -from struct import unpack -import random - -packettypes = { 0: "Whois request", - 1: "Whois reply", - 2: "Repair request", - 3: "Session", - 0xf: "Data", - 0x10: "No data", - 0x11: "Failure", - 0x12: "Attempt join", - 0x13: "Join", - 0x14: "Bye" -} - -WHOIS_REQUEST = 0x0 -WHOIS_REPLY = 0x1 -REPAIR_REQUEST = 0x2 -SESSION = 0x3 -DATA = 0xf -NO_DATA = 0x10 -FAILURE = 0x11 -ATTEMPT_JOIN = 0x12 -JOIN = 0x13 -BYE = 0x14 - -def packet_sender(data): - return unpack ("!I", data[8:12])[0] - -def packet_type(data): - return unpack("B", data[7])[0] - -def dump_depends(data): - sender = packet_sender(data) - num_senders = unpack("B", data[16])[0] - print "sender: %x (%d)" % (sender, num_senders) - for x in xrange (0, num_senders): - (sender, depend) = unpack("!II", data[17 + x:17 + x + 8]) - print "%x:\t%x" % (sender, depend) - - -class BaseMeshNode(protocol.ProcessProtocol): - delimiter = '\n' - __buffer = '' - - def __init__(self, name): - self.name = name - self.process = reactor.spawnProcess(self, - "./test-r-multicast-transport-io", - ("test-r-multicast-transport-io", name), - None) - self.peers = [] - self.packets = {} - - def sendPacket(self, data): - "Should be overridden" - print "Should send: " + data - - def __sendPacket(self, data): - binary = b64decode(data) - type = packet_type(binary) - self.packets[type] = self.packets.get(type, 0) + 1 - return self.sendPacket(binary) - - def stats(self): - print "-------" + self.name + "-------" - for (a,b) in self.packets.iteritems(): - print packettypes[a] + ":\t" + str(b) - - def gotOutput(self, sender, data): - "Should be overridden" - print "Output: " + data - - def node_connected(self): - "Should be overridden" - print "Connected!!" - - def node_disconnected(self): - "Should be overridden" - print "Disconnected!!" - - def __connected(self, data): - self.node_connected() - - def __disconnected(self, data): - self.node_disconnected() - - def __gotOutput(self, data): - (sender, rawdata) = data.split(":", 1) - self.gotOutput(sender, b64decode(rawdata)) - - - def newNode(self, data): - if not data in self.peers: - self.peers.append(data) - - def __newNodes(self, data): - for x in data.split(): - self.newNode(x) - - def leftNode(self, node): - self.peers.remove(node) - - def __leftNodes(self, data): - for x in data.split(): - self.leftNode (x) - - def recvPacket(self, data): - self.process.write("RECV:" + b64encode(data) + "\n") - - def pushInput(self, data): - self.process.write("INPUT:" + b64encode(data) + "\n") - - def fail(self, name): - self.process.write("FAIL:" + name + "\n") - - def disconnect(self): - self.process.write("DISCONNECT\n") - - def lineReceived(self, line): - commands = { "SEND" : self.__sendPacket, - "OUTPUT" : self.__gotOutput, - "CONNECTED" : self.__connected, - "DISCONNECTED" : self.__disconnected, - "NEWNODES" : self.__newNodes, - "LOSTNODES" : self.__leftNodes - } - - parts = line.rstrip().split(":", 1) - if len(parts) == 2: - command = parts[0] - rawdata = parts[1] - if command in commands: - commands[command](rawdata) - return - self.unknownOutput(line) - - def unknownOutput(self, line): - print self.name + " (U) " + line.rstrip() - - def outReceived(self, data): - lines = (self.__buffer + data).split(self.delimiter) - self.__buffer = lines.pop(-1) - for line in lines: - self.lineReceived(line) - - def errReceived(self, data): - print self.name + " Error: " + data.rstrip() - - def processEnded(self, reason): - if self.process.status != 0: - print "process ended: " + str(reason) - -class MeshNode(BaseMeshNode): - def __init__(self, name, mesh): - BaseMeshNode.__init__(self, name) - self.mesh = mesh - - def sendPacket(self, data): - self.mesh.sendPacket(self, data) - - def gotOutput(self, sender, data): - self.mesh.gotOutput(self, sender, data) - - def node_connected(self): - self.mesh.connected(self) - -class Link: - def __init__(self, target, bandwidth, latency, dropchance): - self.target = target - self.bandwidth = bandwidth - self.latency = latency - self.dropchance = dropchance - - def send(self, data): - if random.random() > self.dropchance: - self.target.recvPacket(data) - -class Mesh: - def __init__ (self): - self.nodes = [] - self.connections = {} - - def connect(self, node): - print node.name + " got connected" - - def gotOutput(self, node, sender, data): - print "Got " + data + " from " + node.name + " send by " + sender - - def connect(self, node0, node1, bandwidth, latency, dropchance): - self.connections.setdefault(node0, []).append( - Link(node1, bandwidth, latency, dropchance)) - - def connect_duplex(self, node0, node1, bandwidth, latency, dropchance): - self.connect(node0, node1, bandwidth, latency, dropchance) - self.connect(node1, node0, bandwidth, latency, dropchance) - - def connect_full(self, bandwidth, latency, dropchance): - self.connections = {} - for x in self.nodes: - for y in self.nodes: - if x != y: - self.connect(x, y, bandwidth, latency, dropchance) - - def sendPacket(self, node, data): - conn = self.connections.get(node, []) - for link in conn: - link.send(data) - - def addNode(self, name): - node = MeshNode(name, self) - self.nodes.append(node) - return node - - def addMeshNode(self, node): - self.nodes.append(node) - return node - - def removeMeshNode (self, node): - self.nodes.remove(node) - del self.connections[node] - for (n, links) in self.connections.iteritems(): - for link in links: - if link.target == node: - self.connections[n].remove(link) - - - def connected (self, node): - "To be overwritten" - pass - diff --git a/tests/simplemeshtest.py b/tests/simplemeshtest.py deleted file mode 100644 index 575eeb94..00000000 --- a/tests/simplemeshtest.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python - -from twisted.internet import reactor -from mesh import Mesh, MeshNode -import sys - -NUMNODES = 5 -NUMPACKETS = 10 -DELAY = 0.1 - - -nodes = [] -# We're optimists -success = True - -class TestMeshNode(MeshNode): - nodes = 1 - - def __init__ (self, name, mesh): - MeshNode.__init__(self, name, mesh) - - def node_connected(self): - MeshNode.node_connected(self) - print "Connected" - - def newNode (self, data): - MeshNode.newNode (self, data) - print "node0 - Added " + data - self.nodes += 1 - if self.nodes == NUMNODES: - print "Everybody joined" - for x in xrange(0, NUMPACKETS): - reactor.callLater(0.1 * x, (lambda y: self.pushInput(str(y) + "\n")), x) - - def leftNode (self, data): - MeshNode.leftNode (self, data) - print data.rstrip() + " left" - reactor.stop() - -class TestMesh(Mesh): - expected = {} - done = 0 - - def gotOutput(self, node, sender, data): - global success - - if self.expected.get(node) == None: - self.expected[node] = 0 - - if (self.expected.get(node, int(data)) != int(data)): - print "Got " + data.rstrip() + " instead of " + \ - str(self.expected[node]) + " from " + node.name - - success = False - reactor.crash() - - if not sender in node.peers: - print "Sender " + sender + " not in node peers" - success = False - reactor.crash() - - self.expected[node] = int(data) + 1 - - if self.expected[node] == 10: - self.done += 1 - - if self.done == NUMNODES - 1: - for x in self.nodes: - x.stats() - self.nodes[-1].disconnect() - -m = TestMesh() - - -n = TestMeshNode("node0", m) -nodes.append(n) -m.addMeshNode(n) - -for x in xrange(1, NUMNODES): - nodes.append(m.addNode("node" + str(x))) - -# Connect all nodes to all others. 1024 bytes/s bandwidth, 50ms delay and 0% -# packet loss.. (bandwidth and delay aren't implemented just yet) -m.connect_full(1024, 50, 0.30) - -def timeout(): - global success - print "TIMEOUT!" - success = False - reactor.crash() - -reactor.callLater(60, timeout) - -reactor.run() - - -if not success: - print "FAILED" - sys.exit(-1) - -print "SUCCESS" -- cgit v1.2.3