#!/usr/bin/env python # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Tests for traffic control library.""" import unittest import traffic_control class TrafficControlUnitTests(unittest.TestCase): """Unit tests for traffic control.""" # Stores commands called by the traffic control _Exec function. commands = [] def _ExecMock(self, command, **kwargs): """Mocks traffic_control._Exec and adds the command to commands list.""" cmd_list = [str(x) for x in command] self.commands.append(' '.join(cmd_list)) return '' def setUp(self): """Resets the commands list and set the _Exec mock function.""" self.commands = [] self._old_Exec = traffic_control._Exec traffic_control._Exec = self._ExecMock def tearDown(self): """Resets the _Exec mock function to the original.""" traffic_control._Exec = self._old_Exec def testCreateConstrainedPort(self): config = { 'interface': 'fakeeth', 'port': 12345, 'server_port': 8888, 'bandwidth': 256, 'latency': 100, 'loss': 2 } traffic_control.CreateConstrainedPort(config) expected = [ 'sudo tc qdisc add dev fakeeth root handle 1: htb', 'sudo tc class add dev fakeeth parent 1: classid 1:3039 htb rate ' '256kbit ceil 256kbit', 'sudo tc qdisc add dev fakeeth parent 1:3039 handle 3039:0 netem loss ' '2% delay 100ms', 'sudo tc filter add dev fakeeth protocol ip parent 1: prio 1 u32 match ' 'ip sport 12345 0xffff flowid 1:3039', 'sudo iptables -t nat -A PREROUTING -i fakeeth -p tcp --dport 12345 -j ' 'REDIRECT --to-port 8888', 'sudo iptables -t nat -A OUTPUT -p tcp --dport 12345 -j REDIRECT ' '--to-port 8888' ] self.assertEqual(expected, self.commands) def testCreateConstrainedPortDefaults(self): config = { 'interface': 'fakeeth', 'port': 12345, 'server_port': 8888, 'latency': None } traffic_control.CreateConstrainedPort(config) expected = [ 'sudo tc qdisc add dev fakeeth root handle 1: htb', 'sudo tc class add dev fakeeth parent 1: classid 1:3039 htb rate ' '%dkbit ceil %dkbit' % (traffic_control._DEFAULT_MAX_BANDWIDTH_KBIT, traffic_control._DEFAULT_MAX_BANDWIDTH_KBIT), 'sudo tc qdisc add dev fakeeth parent 1:3039 handle 3039:0 netem', 'sudo tc filter add dev fakeeth protocol ip parent 1: prio 1 u32 ' 'match ip sport 12345 0xffff flowid 1:3039', 'sudo iptables -t nat -A PREROUTING -i fakeeth -p tcp --dport 12345 -j ' 'REDIRECT --to-port 8888', 'sudo iptables -t nat -A OUTPUT -p tcp --dport 12345 -j REDIRECT ' '--to-port 8888' ] self.assertEqual(expected, self.commands) def testDeleteConstrainedPort(self): config = { 'interface': 'fakeeth', 'port': 12345, 'server_port': 8888, 'bandwidth': 256, } _old_GetFilterHandleId = traffic_control._GetFilterHandleId traffic_control._GetFilterHandleId = lambda interface, port: '800::800' try: traffic_control.DeleteConstrainedPort(config) expected = [ 'sudo tc filter del dev fakeeth protocol ip parent 1:0 handle ' '800::800 prio 1 u32', 'sudo tc class del dev fakeeth parent 1: classid 1:3039 htb rate ' '256kbit ceil 256kbit', 'sudo iptables -t nat -D PREROUTING -i fakeeth -p tcp --dport 12345 ' '-j REDIRECT --to-port 8888', 'sudo iptables -t nat -D OUTPUT -p tcp --dport 12345 -j REDIRECT ' '--to-port 8888'] self.assertEqual(expected, self.commands) finally: traffic_control._GetFilterHandleId = _old_GetFilterHandleId def testTearDown(self): config = {'interface': 'fakeeth'} traffic_control.TearDown(config) expected = [ 'sudo tc qdisc del dev fakeeth root', 'sudo iptables -t nat -F' ] self.assertEqual(expected, self.commands) def testGetFilterHandleID(self): # Check seach for handle ID command. self.assertRaises(traffic_control.TrafficControlError, traffic_control._GetFilterHandleId, 'fakeeth', 1) self.assertEquals(self.commands, ['sudo tc filter list dev fakeeth parent ' '1:']) # Check with handle ID available. traffic_control._Exec = (lambda command, msg: 'filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht ' '800 bkt 0 flowid 1:1\nmatch 08ae0000/ffff0000 at 20') output = traffic_control._GetFilterHandleId('fakeeth', 1) self.assertEqual(output, '800::800') # Check with handle ID not available. traffic_control._Exec = (lambda command, msg: 'filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht ' '800 bkt 0 flowid 1:11\nmatch 08ae0000/ffff0000 at 20') self.assertRaises(traffic_control.TrafficControlError, traffic_control._GetFilterHandleId, 'fakeeth', 1) traffic_control._Exec = lambda command, msg: 'NO ID IN HERE' self.assertRaises(traffic_control.TrafficControlError, traffic_control._GetFilterHandleId, 'fakeeth', 1) if __name__ == '__main__': unittest.main()