[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [stem/master] Unit testing for stem.util.conf



commit 59764266b9dbce91accd6a55a371f24516b257a7
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date:   Mon Jan 23 09:25:46 2012 -0800

    Unit testing for stem.util.conf
    
    I needed unit tests for the new listener functions so wrote long overdue tests
    for everything within the utilitity too. Caught a couple bugs in the process.
---
 run_tests.py               |    2 +
 stem/util/conf.py          |   12 ++-
 test/unit/util/__init__.py |    2 +-
 test/unit/util/conf.py     |  232 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 245 insertions(+), 3 deletions(-)

diff --git a/run_tests.py b/run_tests.py
index c7dd91e..acb229b 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -17,6 +17,7 @@ import test.unit.connection.authentication
 import test.unit.connection.protocolinfo
 import test.unit.socket.control_line
 import test.unit.socket.control_message
+import test.unit.util.conf
 import test.unit.util.enum
 import test.unit.util.system
 import test.unit.version
@@ -71,6 +72,7 @@ DEFAULT_RUN_TARGET = TARGETS.RUN_OPEN
 
 UNIT_TESTS = (
   test.unit.util.enum.TestEnum,
+  test.unit.util.conf.TestConf,
   test.unit.util.system.TestSystem,
   test.unit.version.TestVersion,
   test.unit.socket.control_message.TestControlMessage,
diff --git a/stem/util/conf.py b/stem/util/conf.py
index 68a332a..8a1fcfc 100644
--- a/stem/util/conf.py
+++ b/stem/util/conf.py
@@ -19,6 +19,7 @@ Config - Custom configuration.
   |- clear - empties our loaded configuration contents
   |- update - replaces mappings in a dictionary with the config's values
   |- add_listener - notifies the given listener when an update occures
+  |- clear_listeners - removes any attached listeners
   |- sync - keeps a dictionary synchronized with our config
   |- keys - provides keys in the loaded configuration
   |- set - sets the given key/value pair
@@ -272,10 +273,17 @@ class Config():
     
     if backfill:
       for key in self.keys():
-        listener(key)
+        listener(self, key)
     
     self._contents_lock.release()
   
+  def clear_listeners(self):
+    """
+    Removes any attached listeners.
+    """
+    
+    self._listeners = []
+  
   def sync(self, config_dict, interceptor = None):
     """
     Synchronizes a dictionary with our current configuration (like the 'update'
@@ -314,7 +322,7 @@ class Config():
       set of configuration keys we've loaded but have never been requested
     """
     
-    return set(self.get_keys()).difference(self._requested_keys)
+    return set(self.keys()).difference(self._requested_keys)
   
   def set(self, key, value, overwrite = True):
     """
diff --git a/test/unit/util/__init__.py b/test/unit/util/__init__.py
index 57015c1..7c8d12b 100644
--- a/test/unit/util/__init__.py
+++ b/test/unit/util/__init__.py
@@ -2,5 +2,5 @@
 Unit tests for stem.util.* contents.
 """
 
-__all__ = ["enum", "system"]
+__all__ = ["conf", "enum", "system"]
 
diff --git a/test/unit/util/conf.py b/test/unit/util/conf.py
new file mode 100644
index 0000000..3e59a7c
--- /dev/null
+++ b/test/unit/util/conf.py
@@ -0,0 +1,232 @@
+"""
+Unit tests for the stem.util.conf class and functions.
+"""
+
+import unittest
+import stem.util.conf
+
+class TestConf(unittest.TestCase):
+  """
+  Tests the stem.util.conf contents.
+  """
+  
+  def tearDown(self):
+    # clears the config contents
+    test_config = stem.util.conf.get_config("unit_testing")
+    test_config.clear()
+    test_config.clear_listeners()
+  
+  def test_clear(self):
+    """
+    Tests the clear method.
+    """
+    
+    test_config = stem.util.conf.get_config("unit_testing")
+    self.assertEquals([], test_config.keys())
+    
+    # tests clearing when we're already empty
+    test_config.clear()
+    self.assertEquals([], test_config.keys())
+    
+    # tests clearing when we have contents
+    test_config.set("hello", "world")
+    self.assertEquals(["hello"], test_config.keys())
+    
+    test_config.clear()
+    self.assertEquals([], test_config.keys())
+  
+  def test_update(self):
+    """
+    Tests the update method.
+    """
+    
+    my_config = {
+      "bool_value": False,
+      "int_value": 5,
+      "str_value": "hello",
+      "list_value": [],
+      "map_value": {},
+    }
+    
+    test_config = stem.util.conf.get_config("unit_testing")
+    test_config.set("bool_value", "true")
+    test_config.set("int_value", "11")
+    test_config.set("str_value", "world")
+    test_config.set("list_value", "a", False)
+    test_config.set("list_value", "b", False)
+    test_config.set("list_value", "c", False)
+    test_config.set("map_value", "foo => bar")
+    
+    test_config.update(my_config)
+    self.assertEquals(True, my_config["bool_value"])
+    self.assertEquals(11, my_config["int_value"])
+    self.assertEquals("world", my_config["str_value"])
+    self.assertEquals(["a", "b", "c"], my_config["list_value"])
+    self.assertEquals({"foo": "bar"}, my_config["map_value"])
+  
+  def test_update_type_mismatch(self):
+    """
+    Tests the update method when the config file has missing entries or the
+    wrong types.
+    """
+    
+    my_config = {
+      "bool_value": False,
+      "int_value": 5,
+      "str_value": "hello",
+      "list_value": [],
+      "map_value": {},
+    }
+    
+    test_config = stem.util.conf.get_config("unit_testing")
+    test_config.set("bool_value", "hello world")
+    test_config.set("int_value", "11a")
+    test_config.set("map_value", "foo bar")
+    
+    test_config.update(my_config)
+    self.assertEquals(False, my_config["bool_value"])
+    self.assertEquals(5, my_config["int_value"])
+    self.assertEquals("hello", my_config["str_value"])
+    self.assertEquals([], my_config["list_value"])
+    self.assertEquals({}, my_config["map_value"])
+  
+  def test_listeners(self):
+    """
+    Tests the add_listener and clear_listeners methods.
+    """
+    
+    listener_received_keys = []
+    
+    def test_listener(config, key):
+      self.assertEquals(config, stem.util.conf.get_config("unit_testing"))
+      listener_received_keys.append(key)
+    
+    test_config = stem.util.conf.get_config("unit_testing")
+    test_config.add_listener(test_listener)
+    
+    self.assertEquals([], listener_received_keys)
+    test_config.set("hello", "world")
+    self.assertEquals(["hello"], listener_received_keys)
+    
+    test_config.clear_listeners()
+    
+    test_config.set("foo", "bar")
+    self.assertEquals(["hello"], listener_received_keys)
+  
+  def test_sync(self):
+    """
+    Tests the sync method.
+    """
+    
+    my_config = {
+      "bool_value": False,
+      "int_value": 5,
+      "str_value": "hello",
+      "list_value": [],
+    }
+    
+    test_config = stem.util.conf.get_config("unit_testing")
+    
+    # checks that sync causes existing contents to be applied
+    test_config.set("bool_value", "true")
+    test_config.sync(my_config)
+    self.assertEquals(True, my_config["bool_value"])
+    
+    # check a basic update
+    test_config.set("str_value", "me")
+    self.assertEquals("me", my_config["str_value"])
+    
+    # update with a type mismatch, should keep the old value
+    test_config.set("int_value", "7a")
+    self.assertEquals(5, my_config["int_value"])
+    
+    # changes for a collection
+    test_config.set("list_value", "a", False)
+    self.assertEquals(["a"], my_config["list_value"])
+    
+    test_config.set("list_value", "b", False)
+    self.assertEquals(["a", "b"], my_config["list_value"])
+    
+    test_config.set("list_value", "c", False)
+    self.assertEquals(["a", "b", "c"], my_config["list_value"])
+  
+  def test_unused_keys(self):
+    """
+    Tests the unused_keys method.
+    """
+    
+    test_config = stem.util.conf.get_config("unit_testing")
+    test_config.set("hello", "world")
+    test_config.set("foo", "bar")
+    test_config.set("pw", "12345")
+    
+    test_config.get("hello")
+    test_config.get_value("foo")
+    
+    self.assertEquals(set(["pw"]), test_config.unused_keys())
+    
+    test_config.get("pw")
+    self.assertEquals(set(), test_config.unused_keys())
+  
+  def test_get(self):
+    """
+    Tests the get and get_value methods.
+    """
+    
+    test_config = stem.util.conf.get_config("unit_testing")
+    test_config.set("bool_value", "true")
+    test_config.set("int_value", "11")
+    test_config.set("float_value", "11.1")
+    test_config.set("str_value", "world")
+    test_config.set("list_value", "a", False)
+    test_config.set("list_value", "b", False)
+    test_config.set("list_value", "c", False)
+    test_config.set("map_value", "foo => bar")
+    
+    # check that we get the default for type mismatch or missing values
+    
+    self.assertEquals(5, test_config.get("foo", 5))
+    self.assertEquals(5, test_config.get("bool_value", 5))
+    
+    # checks that we get a string when no default is supplied
+    
+    self.assertEquals("11", test_config.get("int_value"))
+    
+    # exercise type casting for each of the supported types
+    
+    self.assertEquals(True, test_config.get("bool_value", False))
+    self.assertEquals(11, test_config.get("int_value", 0))
+    self.assertEquals(11.1, test_config.get("float_value", 0.0))
+    self.assertEquals("world", test_config.get("str_value", ""))
+    self.assertEquals(["a", "b", "c"], test_config.get("list_value", []))
+    self.assertEquals(("a", "b", "c"), test_config.get("list_value", ()))
+    self.assertEquals({"foo": "bar"}, test_config.get("map_value", {}))
+    
+    # the get_value is similar, though only provides back a string or list
+    
+    self.assertEquals("c", test_config.get_value("list_value"))
+    self.assertEquals(["a", "b", "c"], test_config.get_value("list_value", multiple = True))
+    
+    self.assertEquals(None, test_config.get_value("foo"))
+    self.assertEquals("hello", test_config.get_value("foo", "hello"))
+  
+  def test_csv(self):
+    """
+    Tests the get_str_csv and get_int_csv methods.
+    """
+    
+    test_config = stem.util.conf.get_config("unit_testing")
+    test_config.set("str_csv_value", "hello, world")
+    test_config.set("int_csv_value", "1, 2, 3")
+    test_config.set("not_a_csv_value", "blarg I say!")
+    
+    self.assertEquals(["hello", "world"], test_config.get_str_csv("str_csv_value"))
+    self.assertEquals(["1", "2", "3"], test_config.get_str_csv("int_csv_value"))
+    self.assertEquals(["blarg I say!"], test_config.get_str_csv("not_a_csv_value"))
+    self.assertEquals(None, test_config.get_str_csv("not_a_csv_value", count = 5))
+    
+    self.assertEquals(None, test_config.get_int_csv("str_csv_value"))
+    self.assertEquals([1, 2, 3], test_config.get_int_csv("int_csv_value"))
+    self.assertEquals(None, test_config.get_int_csv("int_csv_value", min_value = 4))
+    self.assertEquals(None, test_config.get_int_csv("not_a_csv_value"))
+

_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits