def test_bind_client_ipv6(self): """IPv6 client binding""" q1 = QoS("100M", "My first QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth1': i1 }) r.bind("2001:db8::1", "eth1", "qos1") r.bind("2001:db8::2", "eth1", "qos1") self.assertEqual(r.clients["2001:db8::1"], ('eth1', 'qos1')) self.assertEqual(r.clients["2001:db8::2"], ('eth1', 'qos1'))
def test_equality(self): """Test equality of two routers""" q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}) i2 = Interface("WAN", "My third interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth1': i1, 'eth2': i2}) self.assertEqual(r, Router("eth0", interfaces={ 'eth1': Interface("LAN", "My second interface", {'qos1': QoS("100M", "My first QoS"), 'qos2': q2}), 'eth2': Interface("WAN", "My third interface", {'qos1': q1}) })) self.assertNotEqual(r, Router("eth0", interfaces={ 'eth1': Interface("LAN", "My second interface", {'qos1': QoS("100M", "My first QoS"), 'qos2': q2}), 'eth3': Interface("WAN", "My third interface", {'qos1': q1}) })) self.assertNotEqual(r, Router("eth0", interfaces={ 'eth1': Interface("LAN", "My second interface", {'qos3': QoS("3G", "My first QoS"), 'qos2': q2}), 'eth2': Interface("WAN", "My third interface", {'qos1': q1}) })) self.assertNotEqual(r, Router("eth0")) self.assertNotEqual(r, "eth0") # With equality, clients are not considered r.bind("192.168.15.3", "eth2", "qos1") self.assertEqual(r, Router("eth0", interfaces={ 'eth1': Interface("LAN", "My second interface", {'qos1': QoS("100M", "My first QoS"), 'qos2': q2}), 'eth2': Interface("WAN", "My third interface", {'qos1': q1}) }))
def test_pickle(self): """Pickling""" q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}) i2 = Interface("WAN", "My third interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth1': i1, 'eth2': i2}) self.assertEqual(r, pickle.loads(pickle.dumps(r))) self.assertEqual(r.clients, pickle.loads(pickle.dumps(r)).clients) r.bind("192.168.15.2", "eth2", "qos1") self.assertEqual(r, pickle.loads(pickle.dumps(r))) self.assertEqual(r.clients, pickle.loads(pickle.dumps(r)).clients)
def setUp(self): r = Router.load({'clients': 'eth0'}) # Start the service self.service = Service({}, r) time.sleep(0.2) # Safety # Configure app configure(app)
def realSetup(self): self.router = Router.load(self.config) # Start the service in a separate process self.service = Service( dict(helper=dict(save=os.path.join(self.temp, "save.pickle"))), self.router) time.sleep(0.2) # Safety
def setUp(self): r = Router.load(yaml.load(""" clients: eth0 interfaces: eth1: name: LAN description: "My first interface" qos: - qos1 - qos2 eth2: name: WAN description: "My second interface" password: 1234 qos: - qos1 qos: qos1: name: 100M description: "My first QoS" bandwidth: 100mbps netem: delay 100ms 10ms distribution experimental qos2: name: 10M description: "My second QoS" bandwidth: 10mbps netem: delay 200ms 10ms """)) self.service = Service({}, r) # helper configure(app, dict(web=dict(expire=2))) self.app = app.test_client() # web time.sleep(0.1)
def run(cls, args=sys.argv[1:], binder=None): """Start the helper service. This method should be used to instantiate :class:`Service`. The configuration file must be provided as an argument. :param args: list of command line arguments :type args: list of strings :param binder: binder to register to the router """ from optparse import OptionParser usage = "usage: %prog [options] config.yaml" parser = OptionParser(usage=usage) parser.add_option("-l", "--log", type="string", dest="log", help="log to file", metavar="FILE") parser.add_option("-s", "--syslog", action="store_true", dest="syslog", help="log to syslog") parser.add_option("-d", "--debug", action="count", dest="debug", help="enable debugging") (options, args) = parser.parse_args(args) if len(args) != 1: parser.error("incorrect number of arguments") # Logger configuration l = logging.root if options.debug == 1: l.setLevel(logging.INFO) if options.debug > 1: l.setLevel(logging.DEBUG) if options.log: fh = logging.FileHandler(options.log) fh.setFormatter(logging.Formatter("%(asctime)s %(name)s[%(process)d] " "%(levelname)s: %(message)s")) l.addHandler(fh) if options.syslog: sh = logging.handlers.SysLogHandler(address="/dev/log", facility="daemon") sh.setFormatter(logging.Formatter("kitero[%(process)d]: " "%(levelname)s %(message)s")) l.addHandler(sh) if not options.syslog and not options.log: # Log to stderr eh = logging.StreamHandler() eh.setFormatter(logging.Formatter("%(asctime)s %(name)s[%(process)d] " "%(levelname)s: %(message)s")) l.addHandler(eh) # Reading configuration file logger.info("read configuration file %r" % args[0]) try: config = yaml.safe_load(file(args[0])) config = kitero.config.merge(config) # Create the router router = Router.load(config["router"]) # Add the regular binder to it if binder is not None: router.register(binder) # Start service s = cls(config, router) s.wait() except Exception as e: logger.exception("unhandled error received") sys.exit(1) sys.exit(0)
def test_load_with_missing(self): """Load router with missing information""" doc = """ interfaces: eth1: description: "My first interface" """ with self.assertRaises(ValueError): r = Router.load(yaml.load(doc))
def test_load_minimal(self): """Load router with minimal information""" doc = """ clients: eth0 """ r = Router.load(yaml.load(doc)) self.assertEqual(r.interfaces, {}) self.assertEqual(r.incoming, ["eth0"]) self.assertEqual(r.clients, {})
def test_load(self): """Load router from YAML representation""" doc = """ clients: eth0 interfaces: eth1: name: LAN description: "My first interface" qos: - qos1 - qos2 eth2: name: WAN description: "My second interface" qos: - qos1 - qos3 password: 1234 qos: qos1: name: "100M" description: "My first QoS" bandwidth: 100mbps netem: delay 100ms 10ms distribution experimental qos2: name: "10M" description: "My second QoS" bandwidth: 10mbps netem: delay 200ms 10ms qos3: name: "1M" description: "My third QoS" bandwidth: 1mbps netem: delay 500ms 30ms """ r = Router.load(yaml.load(doc)) self.assertEqual(r.incoming, ["eth0"]) self.assertEqual(r.clients, {}) self.assertEqual(r.interfaces["eth1"], Interface("LAN", "My first interface", qos={'qos1': QoS("100M", "My first QoS", {"bandwidth": "100mbps", "netem": "delay 100ms 10ms distribution experimental"}), 'qos2': QoS("10M", "My second QoS", {"bandwidth": "10mbps", "netem": "delay 200ms 10ms"})})) self.assertEqual(r.interfaces["eth2"], Interface("WAN", "My second interface", qos={'qos1': QoS("100M", "My first QoS", {"bandwidth": "100mbps", "netem": "delay 100ms 10ms distribution experimental"}), 'qos3': QoS("1M", "My third QoS", {"bandwidth": "1mbps", "netem": "delay 500ms 30ms"})})) self.assertEqual(len(r.interfaces), 2) self.assertEqual(r.interfaces["eth2"].check_password("1234"), True)
def test_router(self): """Create a complete router""" q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}) i2 = Interface("WAN", "My third interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth1': i1, 'eth2': i2}) self.assertEqual(r.incoming, ["eth0"]) self.assertEqual(r.clients, {}) self.assertEqual(r.interfaces, {'eth1': i1, 'eth2': i2})
def test_unbind_client(self): """Unbind a client""""" q1 = QoS("100M", "My first QoS") i1 = Interface("WAN", "My third interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth2': i1}) r.bind("192.168.15.2", "eth2", "qos1") r.bind("192.168.15.3", "eth2", "qos1") r.unbind("192.168.15.2") with self.assertRaises(KeyError): r.clients["192.168.15.2"] self.assertEqual(len(r.clients), 1) r.unbind("192.168.15.2") self.assertEqual(len(r.clients), 1)
def test_load_unknown_qos(self): """Load router from YAML with unknown QoS""" doc = """ clients: eth0 interfaces: eth1: name: LAN description: "My first interface" qos: - qos3 """ with self.assertRaises(KeyError): r = Router.load(yaml.load(doc))
def test_load_almost_minimal(self): """Load router with almost minimal information""" doc = """ clients: eth0 interfaces: eth1: name: LAN description: "My first interface" """ r = Router.load(yaml.load(doc)) self.assertEqual(r.interfaces, {'eth1': Interface("LAN", "My first interface")}) self.assertEqual(r.incoming, ["eth0"]) self.assertEqual(r.clients, {})
def test_several_incoming(self): """Load router with several incoming interfaces""" doc = """ clients: - eth0 - eth2 interfaces: eth1: name: LAN description: "My first interface" """ r = Router.load(yaml.load(doc)) self.assertEqual(r.incoming, ["eth0", "eth2"])
def test_bind_with_password(self): """Bind a password protected interface""" q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}, password="******") i2 = Interface("WAN", "My third interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth1': i1, 'eth2': i2}) r.bind("192.168.15.2", "eth1", "qos2", password="******") r.bind("192.168.15.3", "eth2", "qos1") r.bind("192.168.15.4", "eth1", "qos2", password=1234) r.bind("192.168.15.5", "eth2", "qos1", password=4574) self.assertEqual(r.clients["192.168.15.2"], ('eth1', 'qos2')) self.assertEqual(r.clients["192.168.15.3"], ('eth2', 'qos1')) self.assertEqual(r.clients["192.168.15.4"], ('eth1', 'qos2')) self.assertEqual(r.clients["192.168.15.5"], ('eth2', 'qos1'))
def test_bind_inexistant(self): """Client binding to inexistant interface or QoS""" q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}) i2 = Interface("WAN", "My third interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth1': i1, 'eth2': i2}) with self.assertRaises(KeyError): r.bind("192.168.15.2", "eth3", "qos2") with self.assertRaises(KeyError): r.bind("192.168.15.2", "eth2", "qos2")
def test_double_bind_client(self): """Try to bind a client twice""" q1 = QoS("100M", "My first QoS") i1 = Interface("LAN", "My third interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth2': i1}) r.bind("192.168.15.2", "eth2", "qos1") r.bind("192.168.15.3", "eth2", "qos1") with self.assertRaises(ValueError): r.bind("192.168.15.3", "eth2", "qos1") self.assertEqual(r.clients["192.168.15.2"], ('eth2', 'qos1')) self.assertEqual(r.clients["192.168.15.3"], ('eth2', 'qos1'))
def test_bind_client(self): """Client binding""" q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}) i2 = Interface("WAN", "My third interface", {'qos1': q1}) r = Router("eth0", interfaces={'eth1': i1, 'eth2': i2}) r.bind("192.168.15.2", "eth1", "qos2") r.bind("192.168.15.3", "eth2", "qos1") r.bind("192.168.15.4", "eth1", "qos2") self.assertEqual(r.clients["192.168.15.2"], ('eth1', 'qos2')) self.assertEqual(r.clients["192.168.15.3"], ('eth2', 'qos1')) self.assertEqual(r.clients["192.168.15.4"], ('eth1', 'qos2'))
def test_bind_incorrect_password(self): """Bind with an incorrect password""" q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}, password="******") r = Router("eth0", interfaces={'eth1': i1}) with self.assertRaises(AssertionError): r.bind("192.168.15.2", "eth1", "qos2") with self.assertRaises(AssertionError): r.bind("192.168.15.2", "eth1", "qos2", "4512") with self.assertRaises(KeyError): r.clients["192.168.15.2"]
def setUp(self): r = Router.load( yaml.load(""" clients: eth0 interfaces: eth1: name: LAN description: "My first interface" qos: - qos1 - qos2 eth2: name: WAN description: "My second interface" qos: - qos1 - qos3 qos: qos1: name: 100M description: "My first QoS" bandwidth: 100mbps netem: delay 100ms 10ms distribution experimental qos2: name: 10M description: "My second QoS" bandwidth: 10mbps netem: delay 200ms 10ms qos3: name: 1M description: "My third QoS" bandwidth: 1mbps netem: delay 500ms 30ms """)) # Start the service in a separate process self.service = Service({}, r) time.sleep(0.2) # Safety
def setUp(self): r = Router.load(yaml.load(""" clients: eth0 interfaces: eth1: name: LAN description: "My first interface" qos: - qos1 - qos2 eth2: name: WAN description: "My second interface" qos: - qos1 - qos3 qos: qos1: name: 100M description: "My first QoS" bandwidth: 100mbps netem: delay 100ms 10ms distribution experimental qos2: name: 10M description: "My second QoS" bandwidth: 10mbps netem: delay 200ms 10ms qos3: name: 1M description: "My third QoS" bandwidth: 1mbps netem: delay 500ms 30ms """)) # Start the service in a separate process self.service = Service({}, r) time.sleep(0.2) # Safety
def setUp(self): self.binder = self.BINDER() doc = """ clients: eth0 interfaces: eth1: name: LAN description: "My first interface" qos: - qos1 - qos2 eth2: name: WAN description: "My second interface" qos: - qos1 - qos3 - qos4 qos: qos1: name: "100M" description: "My first QoS" bandwidth: down: 100mbps buffer 10Mbit latency 1s up: 50mbps buffer 10Mbit latency 1s netem: delay 100ms 10ms distribution experimental qos2: name: "10M" description: "My second QoS" bandwidth: 10mbps buffer 10Mbit latency 1s netem: delay 200ms 10ms qos3: name: "1M" description: "My third QoS" netem: down: delay 500ms 30ms up: delay 10ms 2ms loss 0.01% qos4: name: "unlimited" description: "My fourth QoS" """ self.router = Router.load(yaml.load(doc)) self.router.register(self.binder) # Provide fake binaries for `ip`, `iptables`, `tc` self.temp = tempfile.mkdtemp() biny = os.path.join(self.temp, "bin") os.mkdir(biny) self.oldpath = os.environ['PATH'] os.environ['PATH'] = "%s:%s" % (biny, os.environ['PATH']) f = file(os.path.join(biny, "fake"), "w") f.write("""#!/bin/sh echo $(basename $0) "$@" >> "%s" case "$(basename $0) $@" in "iptables -t mangle -v -S kitero-ACCOUNTING") cat <<EOF -N kitero-ACCOUNTING -A kitero-ACCOUNTING -o eth2 -m connmark --mark 0x40000000/0xffe00000 -m comment --comment "up-eth2-172.29.7.14" -c 39219 2079628 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x40000000/0xffe00000 -m comment --comment "down-eth2-172.29.7.14" -c 72867 108647983 -A kitero-ACCOUNTING -o eth2 -m connmark --mark 0x41000000/0xffe00000 -m comment --comment "up-eth2-172.29.7.15" -c 247 20796 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x41000000/0xffe00000 -m comment --comment "down-eth2-172.29.7.15" -c 867 2015775 -A kitero-ACCOUNTING -o eth1 -m connmark --mark 0x20000000/0xffe00000 -m comment --comment "up-eth1-172.29.7.19" -c 8888 99999 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x20000000/0xffe00000 -m comment --comment "down-eth1-172.29.7.19" -c 8888 11111 EOF ;; "ip6tables -t mangle -v -S kitero-ACCOUNTING") cat <<EOF -N kitero-ACCOUNTING -A kitero-ACCOUNTING -o eth2 -m connmark --mark 0x40000000/0xffe00000 -m comment --comment "up-eth2-2001:db8::1" -c 3219 209628 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x40000000/0xffe00000 -m comment --comment "down-eth2-2001:db8::1" -c 7287 18647983 -A kitero-ACCOUNTING -o eth1 -m connmark --mark 0x20000000/0xffe00000 -m comment --comment "up-eth1-2001:db8::2" -c 8885 97999 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x20000000/0xffe00000 -m comment --comment "down-eth1-2001:db8::2" -c 8885 12111 EOF ;; esac exit 0 """ % os.path.join(self.temp, "output.txt")) f.close() os.chmod(os.path.join(biny, "fake"), stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) for ex in ['iptables', 'ip6tables', 'tc', 'ip']: os.symlink("fake", os.path.join(biny, ex))
def setUp(self): self.binder = self.BINDER() doc = """ clients: eth0 interfaces: eth1: name: LAN description: "My first interface" qos: - qos1 - qos2 eth2: name: WAN description: "My second interface" qos: - qos1 - qos3 - qos4 qos: qos1: name: "100M" description: "My first QoS" bandwidth: down: 100mbps buffer 10Mbit latency 1s up: 50mbps buffer 10Mbit latency 1s netem: delay 100ms 10ms distribution experimental qos2: name: "10M" description: "My second QoS" bandwidth: 10mbps buffer 10Mbit latency 1s netem: delay 200ms 10ms qos3: name: "1M" description: "My third QoS" netem: down: delay 500ms 30ms up: delay 10ms 2ms loss 0.01% qos4: name: "unlimited" description: "My fourth QoS" """ self.router = Router.load(yaml.load(doc)) self.router.register(self.binder) # Provide fake binaries for `ip`, `iptables`, `tc` self.temp = tempfile.mkdtemp() biny = os.path.join(self.temp, "bin") os.mkdir(biny) self.oldpath = os.environ['PATH'] os.environ['PATH'] = "%s:%s" % (biny, os.environ['PATH']) f = file(os.path.join(biny, "fake"), "w") f.write("""#!/bin/sh echo $(basename $0) "$@" >> "%s" case "$(basename $0) $@" in "iptables -t mangle -v -S kitero-ACCOUNTING") cat <<EOF -N kitero-ACCOUNTING -A kitero-ACCOUNTING -o eth2 -m connmark --mark 0x40000000/0xffe00000 -m comment --comment "up-eth2-172.29.7.14" -c 39219 2079628 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x40000000/0xffe00000 -m comment --comment "down-eth2-172.29.7.14" -c 72867 108647983 -A kitero-ACCOUNTING -o eth2 -m connmark --mark 0x41000000/0xffe00000 -m comment --comment "up-eth2-172.29.7.15" -c 247 20796 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x41000000/0xffe00000 -m comment --comment "down-eth2-172.29.7.15" -c 867 2015775 -A kitero-ACCOUNTING -o eth1 -m connmark --mark 0x20000000/0xffe00000 -m comment --comment "up-eth1-172.29.7.19" -c 8888 99999 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x20000000/0xffe00000 -m comment --comment "down-eth1-172.29.7.19" -c 8888 11111 EOF ;; "ip6tables -t mangle -v -S kitero-ACCOUNTING") cat <<EOF -N kitero-ACCOUNTING -A kitero-ACCOUNTING -o eth2 -m connmark --mark 0x40000000/0xffe00000 -m comment --comment "up-eth2-2001:db8::1" -c 3219 209628 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x40000000/0xffe00000 -m comment --comment "down-eth2-2001:db8::1" -c 7287 18647983 -A kitero-ACCOUNTING -o eth1 -m connmark --mark 0x20000000/0xffe00000 -m comment --comment "up-eth1-2001:db8::2" -c 8885 97999 -A kitero-ACCOUNTING -o eth0 -m connmark --mark 0x20000000/0xffe00000 -m comment --comment "down-eth1-2001:db8::2" -c 8885 12111 EOF ;; esac exit 0 """ % os.path.join(self.temp, "output.txt")) f.close() os.chmod( os.path.join(biny, "fake"), stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) for ex in ['iptables', 'ip6tables', 'tc', 'ip']: os.symlink("fake", os.path.join(biny, ex))
def test_bind_once(self): """The binder should be bound to only one router""" self.binder.notify("unknown", self.router) self.binder.notify("unknwon", self.router) with self.assertRaises(ValueError): self.binder.notify("unknwon", Router("eth0"))
def test_empty_router(self): """Create an empty router""" r = Router("eth0") self.assertEqual(r.incoming, ["eth0"]) self.assertEqual(r.interfaces, {}) self.assertEqual(r.clients, {})
def run(cls, args=sys.argv[1:], binder=None): """Start the helper service. This method should be used to instantiate :class:`Service`. The configuration file must be provided as an argument. :param args: list of command line arguments :type args: list of strings :param binder: binder to register to the router """ from optparse import OptionParser usage = "usage: %prog [options] config.yaml" parser = OptionParser(usage=usage) parser.add_option("-l", "--log", type="string", dest="log", help="log to file", metavar="FILE") parser.add_option("-s", "--syslog", action="store_true", dest="syslog", help="log to syslog") parser.add_option("-d", "--debug", action="count", dest="debug", help="enable debugging") (options, args) = parser.parse_args(args) if len(args) != 1: parser.error("incorrect number of arguments") # Logger configuration l = logging.root if options.debug == 1: l.setLevel(logging.INFO) if options.debug > 1: l.setLevel(logging.DEBUG) if options.log: fh = logging.FileHandler(options.log) fh.setFormatter( logging.Formatter('%(asctime)s %(name)s[%(process)d] ' '%(levelname)s: %(message)s')) l.addHandler(fh) if options.syslog: sh = logging.handlers.SysLogHandler(address='/dev/log', facility="daemon") sh.setFormatter( logging.Formatter('kitero[%(process)d]: ' '%(levelname)s %(message)s')) l.addHandler(sh) if not options.syslog and not options.log: # Log to stderr eh = logging.StreamHandler() eh.setFormatter( logging.Formatter('%(asctime)s %(name)s[%(process)d] ' '%(levelname)s: %(message)s')) l.addHandler(eh) # Reading configuration file logger.info("read configuration file %r" % args[0]) try: config = yaml.safe_load(file(args[0])) config = kitero.config.merge(config) # Create the router router = Router.load(config['router']) # Add the regular binder to it if binder is not None: router.register(binder) # Start service s = cls(config, router) s.wait() except Exception as e: logger.exception("unhandled error received") sys.exit(1) sys.exit(0)
def test_multiple_incoming(self): """Create an empty router with several incoming interfaces""" r = Router(["eth0", "eth2"]) self.assertEqual(r.incoming, ["eth0", "eth2"]) self.assertEqual(r.interfaces, {}) self.assertEqual(r.clients, {})
def test_router_with_shared_interface(self): """Try to create router with duplicate interfaces""" i1 = Interface("LAN", "My second interface") i2 = Interface("WAN", "My third interface") with self.assertRaises(ValueError): r = Router("eth0", interfaces={'eth0': i1, 'eth1': i2})
def realSetup(self): self.router = Router.load(self.config) # Start the service in a separate process self.service = Service(dict(helper=dict(save=os.path.join(self.temp, "save.pickle"))), self.router) time.sleep(0.2) # Safety
class TestRouterObserver(unittest.TestCase): def setUp(self): q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}) i2 = Interface("WAN", "My third interface", {'qos1': q1}) self.router = Router("eth0", interfaces={'eth1': i1, 'eth2': i2}) def test_register_observer(self): """Register an observer and receive events""" last = {} class Observer(object): zope.interface.implements(IBinder) def notify(self, event, source, **kwargs): last['event'] = event last['source'] = source last['args'] = kwargs self.router.register(Observer()) self.router.bind("192.168.15.2", "eth2", "qos1") self.assertEqual(last['event'], 'bind') self.assertEqual(last['source'], self.router) self.assertEqual(last['args']['client'], '192.168.15.2') self.assertEqual(last['args']['interface'], 'eth2') self.assertEqual(last['args']['qos'], 'qos1') self.router.bind("192.168.15.3", "eth2", "qos1") self.assertEqual(last['event'], 'bind') self.assertEqual(last['source'], self.router) self.assertEqual(last['args']['client'], '192.168.15.3') self.assertEqual(last['args']['interface'], 'eth2') self.assertEqual(last['args']['qos'], 'qos1') self.router.unbind("192.168.15.3") self.assertEqual(last['event'], 'unbind') self.assertEqual(last['source'], self.router) self.assertEqual(last['args']['client'], '192.168.15.3') def test_register_not_observer(self): """Register something which is not an observer""" last = {} class Observer(object): def notify(self, event, source, **kwargs): """Will not be called""" with self.assertRaises(ValueError): self.router.register(Observer()) def test_register_several_observers(self): """Register several observers""" events = {} class Observer(object): zope.interface.implements(IBinder) def notify(self, event, source, **kwargs): events[self] = event obs1 = Observer() obs2 = Observer() obs3 = Observer() self.router.register(obs1) self.router.register(obs2) self.router.register(obs3) self.router.bind("192.168.15.2", "eth2", "qos1") self.assertEqual(events, {obs1: 'bind', obs2: 'bind', obs3: 'bind'}) def test_observer_pickling(self): """Check if observers are notified on unpickling""" temp = tempfile.mkdtemp() try: testfile = os.path.join(temp, "testfile.txt") self.router.register(PickableObserver(testfile)) self.router.bind("192.168.15.2", "eth2", "qos1") self.assertEqual(file(testfile).read(), "bind\n") r = pickle.loads(pickle.dumps(self.router)) self.assertEqual(self.router, r) self.assertEqual(self.router.clients, r.clients) self.assertEqual(file(testfile).read(), "bind\nbind\n") finally: shutil.rmtree(temp) def test_stats(self): """Register an observer that also implements IStatsProvider""" class Observer(object): zope.interface.implements(IBinder, IStatsProvider) def notify(self, event, source, **kwargs): """Do nothing""" def stats(self): return {'eth1': {'up': 47, 'down': 255}, 'eth2': {'clients': 2, 'details': {'172.14.15.16': {'up': 1, 'down': 2}}}} self.assertEqual(self.router.stats, {'eth1': {'clients': 0, 'details': {}}, 'eth2': {'clients': 0, 'details': {}}}) self.router.register(Observer()) self.assertEqual(self.router.stats, {'eth1': {'clients': 0, 'up': 47, 'down': 255, 'details': {}}, 'eth2': {'clients': 0, 'details': {}}})
def setUp(self): q1 = QoS("100M", "My first QoS") q2 = QoS("10M", "My second QoS") i1 = Interface("LAN", "My second interface", {'qos1': q1, 'qos2': q2}) i2 = Interface("WAN", "My third interface", {'qos1': q1}) self.router = Router("eth0", interfaces={'eth1': i1, 'eth2': i2})