summaryrefslogtreecommitdiffstats
path: root/media/tools/constrained_network_server/cns_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'media/tools/constrained_network_server/cns_test.py')
-rwxr-xr-xmedia/tools/constrained_network_server/cns_test.py162
1 files changed, 162 insertions, 0 deletions
diff --git a/media/tools/constrained_network_server/cns_test.py b/media/tools/constrained_network_server/cns_test.py
new file mode 100755
index 0000000..fad79bc
--- /dev/null
+++ b/media/tools/constrained_network_server/cns_test.py
@@ -0,0 +1,162 @@
+#!/usr/bin/python
+
+# Copyright (c) 2011 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 Constrained Network Server."""
+import os
+import signal
+import subprocess
+import tempfile
+import time
+import unittest
+import urllib2
+
+import cns
+
+
+class PortAllocatorTest(unittest.TestCase):
+ """Unit tests for the Port Allocator class."""
+
+ # Expiration time for ports. In mock time.
+ _EXPIRY_TIME = 6
+
+ def setUp(self):
+ # Mock out time.time() to accelerate port expiration testing.
+ self._old_time = time.time
+ self._current_time = 0
+ time.time = lambda: self._current_time
+
+ # TODO(dalecurtis): Mock out actual calls to shadi's port setup.
+ self._pa = cns.PortAllocator(cns._DEFAULT_CNS_PORT_RANGE, self._EXPIRY_TIME)
+
+ def tearDown(self):
+ self._pa.Cleanup(all_ports=True)
+ # Ensure ports are cleaned properly.
+ self.assertEquals(self._pa._ports, {})
+ time.time = self._old_time
+
+ def testPortAllocator(self):
+ # Ensure Get() succeeds and returns the correct port.
+ self.assertEquals(self._pa.Get('test'), cns._DEFAULT_CNS_PORT_RANGE[0])
+
+ # Call again with the same key and make sure we get the same port.
+ self.assertEquals(self._pa.Get('test'), cns._DEFAULT_CNS_PORT_RANGE[0])
+
+ # Call with a different key and make sure we get a different port.
+ self.assertEquals(self._pa.Get('test2'), cns._DEFAULT_CNS_PORT_RANGE[0] + 1)
+
+ # Update fake time so that ports should expire.
+ self._current_time += self._EXPIRY_TIME + 1
+
+ # Test to make sure cache is checked before expiring ports.
+ self.assertEquals(self._pa.Get('test2'), cns._DEFAULT_CNS_PORT_RANGE[0] + 1)
+
+ # Update fake time so that ports should expire.
+ self._current_time += self._EXPIRY_TIME + 1
+
+ # Request a new port, old ports should be expired, so we should get the
+ # first port in the range. Make sure this is the only allocated port.
+ self.assertEquals(self._pa.Get('test3'), cns._DEFAULT_CNS_PORT_RANGE[0])
+ self.assertEquals(self._pa._ports.keys(), [cns._DEFAULT_CNS_PORT_RANGE[0]])
+
+ def testPortAllocatorExpiresOnlyCorrectPorts(self):
+ # Ensure Get() succeeds and returns the correct port.
+ self.assertEquals(self._pa.Get('test'), cns._DEFAULT_CNS_PORT_RANGE[0])
+
+ # Stagger port allocation and so we can ensure only ports older than the
+ # expiry time are actually expired.
+ self._current_time += self._EXPIRY_TIME / 2 + 1
+
+ # Call with a different key and make sure we get a different port.
+ self.assertEquals(self._pa.Get('test2'), cns._DEFAULT_CNS_PORT_RANGE[0] + 1)
+
+ # After this sleep the port with key 'test' should expire on the next Get().
+ self._current_time += self._EXPIRY_TIME / 2 + 1
+
+ # Call with a different key and make sure we get the first port.
+ self.assertEquals(self._pa.Get('test3'), cns._DEFAULT_CNS_PORT_RANGE[0])
+ self.assertEquals(set(self._pa._ports.keys()), set([
+ cns._DEFAULT_CNS_PORT_RANGE[0], cns._DEFAULT_CNS_PORT_RANGE[0] + 1]))
+
+
+class ConstrainedNetworkServerTest(unittest.TestCase):
+ """End to end tests for ConstrainedNetworkServer system."""
+
+ # Amount of time to wait for the CNS to start up.
+ _SERVER_START_SLEEP_SECS = 1
+
+ # Sample data used to verify file serving.
+ _TEST_DATA = 'The quick brown fox jumps over the lazy dog'
+
+ # Server information.
+ _SERVER_URL = ('http://127.0.0.1:%d/ServeConstrained?' %
+ cns._DEFAULT_SERVING_PORT)
+
+ # Setting for latency testing.
+ _LATENCY_TEST_SECS = 5
+
+ def _StartServer(self):
+ """Starts the CNS, returns pid."""
+ cmd = ['python', 'cns.py']
+ process = subprocess.Popen(cmd, stderr=subprocess.PIPE)
+
+ # Wait for server to startup.
+ line = True
+ while line:
+ line = process.stderr.readline()
+ if 'STARTED' in line:
+ return process.pid
+
+ self.fail('Failed to start CNS.')
+
+ def setUp(self):
+ # Start the CNS.
+ self._server_pid = self._StartServer()
+
+ # Create temp file for serving. Run after server start so if a failure
+ # during setUp() occurs we don't leave junk files around.
+ f, self._file = tempfile.mkstemp(dir=os.getcwd())
+ os.write(f, self._TEST_DATA)
+ os.close(f)
+
+ # Strip cwd off so we have a proper relative path.
+ self._relative_fn = self._file[len(os.getcwd()) + 1:]
+
+ def tearDown(self):
+ os.unlink(self._file)
+ os.kill(self._server_pid, signal.SIGKILL)
+
+ def testServerServesFiles(self):
+ now = time.time()
+
+ f = urllib2.urlopen('%sf=%s' % (self._SERVER_URL, self._relative_fn))
+
+ # Verify file data is served correctly.
+ self.assertEqual(self._TEST_DATA, f.read())
+
+ # For completeness ensure an unconstrained call takes less time than our
+ # artificial constraints checked in the tests below.
+ self.assertTrue(time.time() - now < self._LATENCY_TEST_SECS)
+
+ def testServerLatencyConstraint(self):
+ now = time.time()
+
+ base_url = '%sf=%s' % (self._SERVER_URL, self._relative_fn)
+ url = '%s&latency=%d' % (base_url, self._LATENCY_TEST_SECS * 1000)
+ f = urllib2.urlopen(url)
+
+ # Verify file data is served correctly.
+ self.assertEqual(self._TEST_DATA, f.read())
+
+ # Verify the request took longer than the requested latency.
+ self.assertTrue(time.time() - now > self._LATENCY_TEST_SECS)
+
+ # Verify the server properly redirected the URL.
+ self.assertEquals(f.geturl(), base_url.replace(
+ str(cns._DEFAULT_SERVING_PORT), str(cns._DEFAULT_CNS_PORT_RANGE[0])))
+
+
+if __name__ == '__main__':
+ unittest.main()