Browse Source

working on ccsession tests
updated command callback fingerprint; the function a module provides should now
take 2 arguments; the first is a string with the name of the command, the second
an ElementPtr containing argument(s)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@999 e5f2f494-b856-4b98-b285-d166d9295462

Jelte Jansen 15 years ago
parent
commit
718c75b966

+ 5 - 5
src/bin/auth/main.cc

@@ -63,15 +63,15 @@ my_config_handler(isc::data::ElementPtr config)
 }
 }
 
 
 isc::data::ElementPtr
 isc::data::ElementPtr
-my_command_handler(isc::data::ElementPtr command) {
+my_command_handler(const std::string& command, const isc::data::ElementPtr args) {
     isc::data::ElementPtr answer = isc::config::createAnswer(0);
     isc::data::ElementPtr answer = isc::config::createAnswer(0);
 
 
-    cout << "[XX] Handle command: " << endl << command->str() << endl;
-    if (command->get(0)->stringValue() == "print_message") 
+    cout << "[XX] Handle command: " << endl << command << endl;
+    if (command == "print_message") 
     {
     {
-        cout << command->get(1)->get("message") << endl;
+        cout << args << endl;
         /* let's add that message to our answer as well */
         /* let's add that message to our answer as well */
-        answer->get("result")->add(command->get(1));
+        answer->get("result")->add(args);
     }
     }
     return answer;
     return answer;
 }
 }

+ 6 - 7
src/bin/bind10/bind10.py.in

@@ -119,24 +119,23 @@ class BoB:
         return answer
         return answer
         # TODO
         # TODO
 
 
-    def command_handler(self, command):
-        # a command is of the form [ "command", { "arg1": arg1, "arg2": arg2 } ]
+    def command_handler(self, command, args):
         if self.verbose:
         if self.verbose:
             print("[XX] Boss got command:")
             print("[XX] Boss got command:")
             print(command)
             print(command)
         answer = [ 1, "Command not implemented" ]
         answer = [ 1, "Command not implemented" ]
-        if type(command) != list or len(command) == 0:
+        if type(command) != str:
             answer = isc.config.ccsession.create_answer(1, "bad command")
             answer = isc.config.ccsession.create_answer(1, "bad command")
         else:
         else:
-            cmd = command[0]
+            cmd = command
             if cmd == "shutdown":
             if cmd == "shutdown":
                 print("[XX] got shutdown command")
                 print("[XX] got shutdown command")
                 self.runnable = False
                 self.runnable = False
                 answer = isc.config.ccsession.create_answer(0)
                 answer = isc.config.ccsession.create_answer(0)
             elif cmd == "print_message":
             elif cmd == "print_message":
-                if len(command) > 1 and type(command[1]) == dict and "message" in command[1]:
-                    print(command[1]["message"])
-                answer = isc.config.ccsession.create_answer(0)
+                if args:
+                    print(args)
+                answer = isc.config.ccsession.create_answer(0, args)
             elif cmd == "print_settings":
             elif cmd == "print_settings":
                 print("Full Config:")
                 print("Full Config:")
                 full_config = self.ccs.get_full_config()
                 full_config = self.ccs.get_full_config()

+ 8 - 8
src/lib/config/cpp/ccsession.cc

@@ -164,7 +164,7 @@ ModuleCCSession::read_module_specification(const std::string& filename) {
 
 
 ModuleCCSession::ModuleCCSession(std::string spec_file_name,
 ModuleCCSession::ModuleCCSession(std::string spec_file_name,
                                isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
                                isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-                               isc::data::ElementPtr(*command_handler)(isc::data::ElementPtr command)
+                               isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)
                               ) throw (isc::cc::SessionError):
                               ) throw (isc::cc::SessionError):
     session_(isc::cc::Session())
     session_(isc::cc::Session())
 {
 {
@@ -249,16 +249,16 @@ ModuleCCSession::check_command()
         if (!data->getType() == Element::map || data->contains("result")) {
         if (!data->getType() == Element::map || data->contains("result")) {
             return 0;
             return 0;
         }
         }
+        ElementPtr arg;
+        std::string cmd_str = parseCommand(arg, data);
         ElementPtr answer;
         ElementPtr answer;
-        if (data->contains("config_update")) {
-            ElementPtr new_config = data->get("config_update");
-            answer = handleConfigUpdate(new_config);
-        }
-        if (data->contains("command")) {
+        if (cmd_str == "config_update") {
+            answer = handleConfigUpdate(arg);
+        } else {
             if (command_handler_) {
             if (command_handler_) {
-                answer = command_handler_(data->get("command"));
+                answer = command_handler_(cmd_str, arg);
             } else {
             } else {
-                answer = Element::createFromString("{ \"result\": [0] }");
+                answer = createAnswer(1, "Command given but no command handler for module");
             }
             }
         }
         }
         session_.reply(routing, answer);
         session_.reply(routing, answer);

+ 3 - 3
src/lib/config/cpp/ccsession.h

@@ -54,7 +54,7 @@ public:
      */
      */
     ModuleCCSession(std::string spec_file_name,
     ModuleCCSession(std::string spec_file_name,
                     isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config) = NULL,
                     isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(isc::data::ElementPtr command) = NULL
+                    isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args) = NULL
                     ) throw (isc::cc::SessionError);
                     ) throw (isc::cc::SessionError);
     int getSocket();
     int getSocket();
 
 
@@ -87,7 +87,7 @@ public:
      *
      *
      * This protocol is very likely to change.
      * This protocol is very likely to change.
      */
      */
-    void set_command_handler(isc::data::ElementPtr(*command_handler)(isc::data::ElementPtr command)) { command_handler_ = command_handler; };
+    void set_command_handler(isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)) { command_handler_ = command_handler; };
 
 
     const ElementPtr getConfig() { return config_; }
     const ElementPtr getConfig() { return config_; }
 private:
 private:
@@ -100,7 +100,7 @@ private:
     ElementPtr handleConfigUpdate(ElementPtr new_config);
     ElementPtr handleConfigUpdate(ElementPtr new_config);
 
 
     isc::data::ElementPtr(*config_handler_)(isc::data::ElementPtr new_config);
     isc::data::ElementPtr(*config_handler_)(isc::data::ElementPtr new_config);
-    isc::data::ElementPtr(*command_handler_)(isc::data::ElementPtr command);
+    isc::data::ElementPtr(*command_handler_)(const std::string& command, const isc::data::ElementPtr args);
 };
 };
 
 
 ElementPtr createAnswer(const int rcode);
 ElementPtr createAnswer(const int rcode);

+ 31 - 18
src/lib/config/python/isc/config/ccsession.py

@@ -58,6 +58,8 @@ def parse_answer(msg):
         raise ModuleCCSessionError("wrong rcode type in answer message")
         raise ModuleCCSessionError("wrong rcode type in answer message")
     else:
     else:
         if len(msg['result']) > 1:
         if len(msg['result']) > 1:
+            if (msg['result'][0] != 0 and type(msg['result'][1]) != str):
+                raise ModuleCCSessionError("rcode in answer message is non-zero, value is not a string")
             return msg['result'][0], msg['result'][1]
             return msg['result'][0], msg['result'][1]
         else:
         else:
             return msg['result'][0], None
             return msg['result'][0], None
@@ -78,6 +80,7 @@ def create_answer(rcode, arg = None):
 
 
 # 'fixed' commands
 # 'fixed' commands
 """Fixed names for command and configuration messages"""
 """Fixed names for command and configuration messages"""
+COMMAND_CONFIG_UPDATE = "config_update"
 COMMAND_COMMANDS_UPDATE = "commands_update"
 COMMAND_COMMANDS_UPDATE = "commands_update"
 COMMAND_SPECIFICATION_UPDATE = "specification_update"
 COMMAND_SPECIFICATION_UPDATE = "specification_update"
 
 
@@ -94,9 +97,9 @@ def parse_command(msg):
     if type(msg) == dict and len(msg.items()) == 1:
     if type(msg) == dict and len(msg.items()) == 1:
         cmd, value = msg.popitem()
         cmd, value = msg.popitem()
         if cmd == "command" and type(value) == list:
         if cmd == "command" and type(value) == list:
-            if len(value) == 1:
+            if len(value) == 1 and type(value[0]) == str:
                 return value[0], None
                 return value[0], None
-            elif len(value) > 1:
+            elif len(value) > 1 and type(value[0]) == str:
                 return value[0], value[1]
                 return value[0], value[1]
     return None, None
     return None, None
 
 
@@ -105,6 +108,8 @@ def create_command(command_name, params = None):
        specified in the module's specification, and an optional params
        specified in the module's specification, and an optional params
        object"""
        object"""
     # TODO: validate_command with spec
     # TODO: validate_command with spec
+    if type(command_name) != str:
+        raise ModuleCCSessionError("command in create_command() not a string")
     cmd = [ command_name ]
     cmd = [ command_name ]
     if params:
     if params:
         cmd.append(params)
         cmd.append(params)
@@ -121,7 +126,7 @@ class ModuleCCSession(ConfigData):
        callbacks are called when 'check_command' is called on the
        callbacks are called when 'check_command' is called on the
        ModuleCCSession"""
        ModuleCCSession"""
        
        
-    def __init__(self, spec_file_name, config_handler, command_handler):
+    def __init__(self, spec_file_name, config_handler, command_handler, cc_session = None):
         """Initialize a ModuleCCSession. This does *NOT* send the
         """Initialize a ModuleCCSession. This does *NOT* send the
            specification and request the configuration yet. Use start()
            specification and request the configuration yet. Use start()
            for that once the ModuleCCSession has been initialized.
            for that once the ModuleCCSession has been initialized.
@@ -137,7 +142,10 @@ class ModuleCCSession(ConfigData):
         self.set_config_handler(config_handler)
         self.set_config_handler(config_handler)
         self.set_command_handler(command_handler)
         self.set_command_handler(command_handler)
 
 
-        self._session = Session()
+        if not cc_session:
+            self._session = Session()
+        else:
+            self._session = cc_session
         self._session.group_subscribe(self._module_name, "*")
         self._session.group_subscribe(self._module_name, "*")
 
 
     def start(self):
     def start(self):
@@ -172,17 +180,18 @@ class ModuleCCSession(ConfigData):
         if msg:
         if msg:
             answer = None
             answer = None
             try:
             try:
-                if "config_update" in msg:
-                    new_config = msg["config_update"]
+                cmd, arg = isc.config.ccsession.parse_command(msg)
+                if cmd == COMMAND_CONFIG_UPDATE:
+                    new_config = arg
                     errors = []
                     errors = []
                     if not self._config_handler:
                     if not self._config_handler:
                         answer = create_answer(2, self._module_name + " has no config handler")
                         answer = create_answer(2, self._module_name + " has no config handler")
                     elif not self.get_module_spec().validate_config(False, new_config, errors):
                     elif not self.get_module_spec().validate_config(False, new_config, errors):
                         answer = create_answer(1, " ".join(errors))
                         answer = create_answer(1, " ".join(errors))
                     else:
                     else:
-                        answer = self._config_handler(msg["config_update"])
-                if "command" in msg and self._command_handler:
-                    answer = self._command_handler(msg["command"])
+                        answer = self._config_handler(new_config)
+                else:
+                    answer = self._command_handler(cmd, arg)
             except Exception as exc:
             except Exception as exc:
                 answer = create_answer(1, str(exc))
                 answer = create_answer(1, str(exc))
             if answer:
             if answer:
@@ -208,18 +217,22 @@ class ModuleCCSession(ConfigData):
         answer, env = self._session.group_recvmsg(False)
         answer, env = self._session.group_recvmsg(False)
         
         
     def __request_config(self):
     def __request_config(self):
-        """Asks the configuration manager for the current configuration, and call the config handler if set"""
+        """Asks the configuration manager for the current configuration, and call the config handler if set.
+           Raises a ModuleCCSessionError if there is no answer from the configuration manager"""
         self._session.group_sendmsg({ "command": [ "get_config", { "module_name": self._module_name } ] }, "ConfigManager")
         self._session.group_sendmsg({ "command": [ "get_config", { "module_name": self._module_name } ] }, "ConfigManager")
         answer, env = self._session.group_recvmsg(False)
         answer, env = self._session.group_recvmsg(False)
-        rcode, value = parse_answer(answer)
-        if rcode == 0:
-            if value != None and self.get_module_spec().validate_config(False, value):
-                self.set_local_config(value);
-                if self._config_handler:
-                    self._config_handler(value)
+        if answer:
+            rcode, value = parse_answer(answer)
+            if rcode == 0:
+                if value != None and self.get_module_spec().validate_config(False, value):
+                    self.set_local_config(value);
+                    if self._config_handler:
+                        self._config_handler(value)
+            else:
+                # log error
+                print("Error requesting configuration: " + value)
         else:
         else:
-            # log error
-            print("Error requesting configuration: " + value)
+            raise ModuleCCSessionError("No answer from configuration manager")
 
 
 class UIModuleCCSession(MultiConfigData):
 class UIModuleCCSession(MultiConfigData):
     """This class is used in a configuration user interface. It contains
     """This class is used in a configuration user interface. It contains

+ 169 - 0
src/lib/config/python/isc/config/ccsession_test.py

@@ -0,0 +1,169 @@
+# Copyright (C) 2010  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#
+# Tests for the ConfigData and MultiConfigData classes
+#
+
+import unittest
+import os
+from isc.config.ccsession import *
+from unittest_fakesession import FakeModuleCCSession
+
+class TestHelperFunctions(unittest.TestCase):
+    def test_parse_answer(self):
+        self.assertRaises(ModuleCCSessionError, parse_answer, 1)
+        self.assertRaises(ModuleCCSessionError, parse_answer, { 'just a dict': 1 })
+        self.assertRaises(ModuleCCSessionError, parse_answer, { 'result': 1 })
+        self.assertRaises(ModuleCCSessionError, parse_answer, { 'result': [] })
+        self.assertRaises(ModuleCCSessionError, parse_answer, { 'result': [ 'not_an_rcode' ] })
+        self.assertRaises(ModuleCCSessionError, parse_answer, { 'result': [ 1, 2 ] })
+        
+        rcode, val = parse_answer({ 'result': [ 0 ] })
+        self.assertEqual(0, rcode)
+        self.assertEqual(None, val)
+        rcode, val = parse_answer({ 'result': [ 0, "something" ] })
+        self.assertEqual(0, rcode)
+        self.assertEqual("something", val)
+        rcode, val = parse_answer({ 'result': [ 1, "some error" ] })
+        self.assertEqual(1, rcode)
+        self.assertEqual("some error", val)
+
+    def test_create_answer(self):
+        self.assertRaises(ModuleCCSessionError, create_answer, 'not_an_int')
+        self.assertRaises(ModuleCCSessionError, create_answer, 1, 2)
+        self.assertRaises(ModuleCCSessionError, create_answer, 1)
+        self.assertEqual({ 'result': [ 0 ] }, create_answer(0))
+        self.assertEqual({ 'result': [ 1, 'something bad' ] }, create_answer(1, 'something bad'))
+        self.assertEqual({ 'result': [ 0, 'something good' ] }, create_answer(0, 'something good'))
+        self.assertEqual({ 'result': [ 0, ['some', 'list' ] ] }, create_answer(0, ['some', 'list']))
+        self.assertEqual({ 'result': [ 0, {'some': 'map' } ] }, create_answer(0, {'some': 'map'}))
+
+    def test_parse_command(self):
+        cmd, arg = parse_command(1)
+        self.assertEqual(None, cmd)
+        self.assertEqual(None, arg)
+
+        cmd, arg = parse_command({})
+        self.assertEqual(None, cmd)
+        self.assertEqual(None, arg)
+
+        cmd, arg = parse_command({ 'not a command': 1})
+        self.assertEqual(None, cmd)
+        self.assertEqual(None, arg)
+
+        cmd, arg = parse_command({ 'command': 1})
+        self.assertEqual(None, cmd)
+        self.assertEqual(None, arg)
+
+        cmd, arg = parse_command({ 'command': []})
+        self.assertEqual(None, cmd)
+        self.assertEqual(None, arg)
+
+        cmd, arg = parse_command({ 'command': [ 1 ]})
+        self.assertEqual(None, cmd)
+        self.assertEqual(None, arg)
+
+        cmd, arg = parse_command({ 'command': [ 'command' ]})
+        self.assertEqual('command', cmd)
+        self.assertEqual(None, arg)
+
+        cmd, arg = parse_command({ 'command': [ 'command', 1 ]})
+        self.assertEqual('command', cmd)
+        self.assertEqual(1, arg)
+
+        cmd, arg = parse_command({ 'command': [ 'command', ['some', 'argument', 'list'] ]})
+        self.assertEqual('command', cmd)
+        self.assertEqual(['some', 'argument', 'list'], arg)
+
+    def test_create_command(self):
+        self.assertRaises(ModuleCCSessionError, create_command, 1)
+        self.assertEqual({'command': [ 'my_command' ]}, create_command('my_command'))
+        self.assertEqual({'command': [ 'my_command', 1 ]}, create_command('my_command', 1))
+        self.assertEqual({'command': [ 'my_command', [ 'some', 'list' ] ]}, create_command('my_command', [ 'some', 'list' ]))
+        self.assertEqual({'command': [ 'my_command', { 'some': 'map' } ]}, create_command('my_command', { 'some': 'map' }))
+
+class TestModuleCCSession(unittest.TestCase):
+    def setUp(self):
+        if 'CONFIG_TESTDATA_PATH' in os.environ:
+            self.data_path = os.environ['CONFIG_TESTDATA_PATH']
+        else:
+            self.data_path = "../../../testdata"
+
+    def spec_file(self, file):
+        return self.data_path + os.sep + file
+        
+    def create_session(self, spec_file_name, config_handler = None, command_handler = None, cc_session = None):
+        return ModuleCCSession(self.spec_file(spec_file_name), config_handler, command_handler, cc_session)
+
+    def test_init(self):
+        fake_session = FakeModuleCCSession()
+        mccs = self.create_session("spec1.spec", None, None, fake_session)
+        self.assertEqual(isc.config.module_spec_from_file(self.spec_file("spec1.spec"))._module_spec, mccs.specification._module_spec)
+        self.assertEqual(None, mccs._config_handler)
+        self.assertEqual(None, mccs._command_handler)
+
+    def test_start1(self):
+        fake_session = FakeModuleCCSession()
+        mccs = self.create_session("spec1.spec", None, None, fake_session)
+        self.assertEqual(len(fake_session.message_queue), 0)
+        self.assertRaises(ModuleCCSessionError, mccs.start)
+        self.assertEqual(len(fake_session.message_queue), 2)
+        self.assertEqual({'command': ['module_spec', {'module_name': 'Spec1'}]},
+                         fake_session.get_message('ConfigManager', None))
+        self.assertEqual({'command': ['get_config', {'module_name': 'Spec1'}]},
+                         fake_session.get_message('ConfigManager', None))
+
+        self.assertEqual(len(fake_session.message_queue), 0)
+        fake_session.group_sendmsg({'result': [ 0 ]}, "Spec1")
+        fake_session.group_sendmsg({'result': [ 0 ]}, "Spec1")
+        mccs.start()
+        self.assertEqual(len(fake_session.message_queue), 2)
+
+        self.assertEqual({'command': ['module_spec', {'module_name': 'Spec1'}]},
+                         fake_session.get_message('ConfigManager', None))
+        self.assertEqual({'command': ['get_config', {'module_name': 'Spec1'}]},
+                         fake_session.get_message('ConfigManager', None))
+
+    def test_get_socket(self):
+        fake_session = FakeModuleCCSession()
+        mccs = self.create_session("spec1.spec", None, None, fake_session)
+        self.assertNotEqual(None, mccs.get_socket())
+
+    def test_get_session(self):
+        fake_session = FakeModuleCCSession()
+        mccs = self.create_session("spec1.spec", None, None, fake_session)
+        self.assertEqual(fake_session, mccs.get_session())
+
+    def test_close(self):
+        fake_session = FakeModuleCCSession()
+        mccs = self.create_session("spec1.spec", None, None, fake_session)
+        mccs.close()
+        self.assertEqual("closed", fake_session._socket)
+
+    def test_check_command(self):
+        fake_session = FakeModuleCCSession()
+        mccs = self.create_session("spec1.spec", None, None, fake_session)
+
+        mccs.check_command()
+        self.assertEqual(len(fake_session.message_queue), 0)
+
+        fake_session.group_sendmsg({'result': [ 0 ]}, "Spec1")
+        mccs.check_command()
+        self.assertEqual(len(fake_session.message_queue), 0)
+        
+if __name__ == '__main__':
+    unittest.main()
+

+ 6 - 3
src/lib/config/python/isc/config/cfgmgr.py

@@ -241,13 +241,15 @@ class ConfigManager:
             conf_part = data.find_no_exc(self.config.data, module_name)
             conf_part = data.find_no_exc(self.config.data, module_name)
             if conf_part:
             if conf_part:
                 data.merge(conf_part, cmd[1])
                 data.merge(conf_part, cmd[1])
-                self.cc.group_sendmsg({ "config_update": conf_part }, module_name)
+                update_cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, conf_part)
+                self.cc.group_sendmsg(update_cmd, module_name)
                 answer, env = self.cc.group_recvmsg(False)
                 answer, env = self.cc.group_recvmsg(False)
             else:
             else:
                 conf_part = data.set(self.config.data, module_name, {})
                 conf_part = data.set(self.config.data, module_name, {})
                 data.merge(conf_part[module_name], cmd[1])
                 data.merge(conf_part[module_name], cmd[1])
                 # send out changed info
                 # send out changed info
-                self.cc.group_sendmsg({ "config_update": conf_part[module_name] }, module_name)
+                update_cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, conf_part[module_name])
+                self.cc.group_sendmsg(update_cmd, module_name)
                 # replace 'our' answer with that of the module
                 # replace 'our' answer with that of the module
                 answer, env = self.cc.group_recvmsg(False)
                 answer, env = self.cc.group_recvmsg(False)
             if answer:
             if answer:
@@ -263,7 +265,8 @@ class ConfigManager:
             err_list = []
             err_list = []
             for module in self.config.data:
             for module in self.config.data:
                 if module != "version":
                 if module != "version":
-                    self.cc.group_sendmsg({ "config_update": self.config.data[module] }, module)
+                    update_cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, self.config.data[module])
+                    self.cc.group_sendmsg(update_cmd, module)
                     answer, env = self.cc.group_recvmsg(False)
                     answer, env = self.cc.group_recvmsg(False)
                     if answer == None:
                     if answer == None:
                         got_error = True
                         got_error = True

+ 7 - 51
src/lib/config/python/isc/config/cfgmgr_test.py

@@ -20,6 +20,7 @@
 import unittest
 import unittest
 import os
 import os
 from isc.config.cfgmgr import *
 from isc.config.cfgmgr import *
+from unittest_fakesession import FakeModuleCCSession
 
 
 class TestConfigManagerData(unittest.TestCase):
 class TestConfigManagerData(unittest.TestCase):
     def setUp(self):
     def setUp(self):
@@ -71,51 +72,6 @@ class TestConfigManagerData(unittest.TestCase):
         cfd2.data['test'] = { 'a': [ 1, 2, 3]}
         cfd2.data['test'] = { 'a': [ 1, 2, 3]}
         self.assertNotEqual(cfd1, cfd2)
         self.assertNotEqual(cfd1, cfd2)
         
         
-#
-# We can probably use a more general version of this
-#
-class FakeModuleCCSession:
-    def __init__(self):
-        self.subscriptions = {}
-        # each entry is of the form [ channel, instance, message ]
-        self.message_queue = []
-
-    def group_subscribe(self, group_name, instance_name = None):
-        if not group_name in self.subscriptions:
-            self.subscriptions[group_name] = []
-        if instance_name:
-            self.subscriptions[group_name].append(instance_name)
-            
-
-    def has_subscription(self, group_name, instance_name = None):
-        if group_name in self.subscriptions:
-            if instance_name:
-                return instance_name in self.subscriptions[group_name]
-            else:
-                return True
-        else:
-            return False
-
-    def group_sendmsg(self, msg, channel, target = None):
-        self.message_queue.append([ channel, target, msg ])
-
-    def group_reply(self, env, msg):
-        pass
-
-    def group_recvmsg(self, blocking):
-        for qm in self.message_queue:
-            if qm[0] in self.subscriptions and (qm[1] == None or qm[1] in self.subscriptions[qm[0]]):
-                self.message_queue.remove(qm)
-                return qm[2], {}
-        return None, None
-
-    def get_message(self, channel, target = None):
-        for qm in self.message_queue:
-            if qm[0] == channel and qm[1] == target:
-                self.message_queue.remove(qm)
-                return qm[2]
-        return None
-        
 
 
 class TestConfigManager(unittest.TestCase):
 class TestConfigManager(unittest.TestCase):
 
 
@@ -257,7 +213,7 @@ class TestConfigManager(unittest.TestCase):
                                 my_ok_answer)
                                 my_ok_answer)
         # The cfgmgr should have eaten the ok message, and sent out an update again
         # The cfgmgr should have eaten the ok message, and sent out an update again
         self.assertEqual(len(self.fake_session.message_queue), 1)
         self.assertEqual(len(self.fake_session.message_queue), 1)
-        self.assertEqual({'config_update': {'test': 123}},
+        self.assertEqual({'command': [ 'config_update', {'test': 123}]},
                          self.fake_session.get_message(self.name, None))
                          self.fake_session.get_message(self.name, None))
         # and the queue should now be empty again
         # and the queue should now be empty again
         self.assertEqual(len(self.fake_session.message_queue), 0)
         self.assertEqual(len(self.fake_session.message_queue), 0)
@@ -267,7 +223,7 @@ class TestConfigManager(unittest.TestCase):
         self._handle_msg_helper({ "command": [ "set_config", [self.name, { "test": 124 }] ] },
         self._handle_msg_helper({ "command": [ "set_config", [self.name, { "test": 124 }] ] },
                                 my_ok_answer)
                                 my_ok_answer)
         self.assertEqual(len(self.fake_session.message_queue), 1)
         self.assertEqual(len(self.fake_session.message_queue), 1)
-        self.assertEqual({'config_update': {'test': 124}},
+        self.assertEqual({'command': [ 'config_update', {'test': 124}]},
                          self.fake_session.get_message(self.name, None))
                          self.fake_session.get_message(self.name, None))
         self.assertEqual(len(self.fake_session.message_queue), 0)
         self.assertEqual(len(self.fake_session.message_queue), 0)
 
 
@@ -277,7 +233,7 @@ class TestConfigManager(unittest.TestCase):
         self._handle_msg_helper({ "command": [ "set_config", [ { self.name: { "test": 125 } }] ] },
         self._handle_msg_helper({ "command": [ "set_config", [ { self.name: { "test": 125 } }] ] },
                                 my_ok_answer )
                                 my_ok_answer )
         self.assertEqual(len(self.fake_session.message_queue), 1)
         self.assertEqual(len(self.fake_session.message_queue), 1)
-        self.assertEqual({'config_update': {'test': 125}},
+        self.assertEqual({'command': [ 'config_update', {'test': 125}]},
                          self.fake_session.get_message(self.name, None))
                          self.fake_session.get_message(self.name, None))
         self.assertEqual(len(self.fake_session.message_queue), 0)
         self.assertEqual(len(self.fake_session.message_queue), 0)
 
 
@@ -286,7 +242,7 @@ class TestConfigManager(unittest.TestCase):
                           self.cm.handle_msg,
                           self.cm.handle_msg,
                           { "command": [ "set_config", [ { self.name: { "test": 125 } }] ] } )
                           { "command": [ "set_config", [ { self.name: { "test": 125 } }] ] } )
         self.assertEqual(len(self.fake_session.message_queue), 1)
         self.assertEqual(len(self.fake_session.message_queue), 1)
-        self.assertEqual({'config_update': {'test': 125}},
+        self.assertEqual({'command': [ 'config_update', {'test': 125}]},
                          self.fake_session.get_message(self.name, None))
                          self.fake_session.get_message(self.name, None))
         self.assertEqual(len(self.fake_session.message_queue), 0)
         self.assertEqual(len(self.fake_session.message_queue), 0)
 
 
@@ -295,7 +251,7 @@ class TestConfigManager(unittest.TestCase):
         self._handle_msg_helper({ "command": [ "set_config", [ { self.name: { "test": 125 } }] ] },
         self._handle_msg_helper({ "command": [ "set_config", [ { self.name: { "test": 125 } }] ] },
                                 my_bad_answer )
                                 my_bad_answer )
         self.assertEqual(len(self.fake_session.message_queue), 1)
         self.assertEqual(len(self.fake_session.message_queue), 1)
-        self.assertEqual({'config_update': {'test': 125}},
+        self.assertEqual({'command': [ 'config_update', {'test': 125}]},
                          self.fake_session.get_message(self.name, None))
                          self.fake_session.get_message(self.name, None))
         self.assertEqual(len(self.fake_session.message_queue), 0)
         self.assertEqual(len(self.fake_session.message_queue), 0)
 
 
@@ -304,7 +260,7 @@ class TestConfigManager(unittest.TestCase):
         self._handle_msg_helper({ "command": [ "set_config", [ self.name, { "test": 125 }] ] },
         self._handle_msg_helper({ "command": [ "set_config", [ self.name, { "test": 125 }] ] },
                                 my_bad_answer )
                                 my_bad_answer )
         self.assertEqual(len(self.fake_session.message_queue), 1)
         self.assertEqual(len(self.fake_session.message_queue), 1)
-        self.assertEqual({'config_update': {'test': 125}},
+        self.assertEqual({'command': [ 'config_update', {'test': 125}]},
                          self.fake_session.get_message(self.name, None))
                          self.fake_session.get_message(self.name, None))
         self.assertEqual(len(self.fake_session.message_queue), 0)
         self.assertEqual(len(self.fake_session.message_queue), 0)
 
 

+ 2 - 0
src/lib/config/python/isc/config/config_test.in

@@ -16,4 +16,6 @@ ${PYTHON_EXEC} -O ${CONFIG_PATH}/config_data_test.py $*
 
 
 ${PYTHON_EXEC} -O ${CONFIG_PATH}/module_spec_test.py $*
 ${PYTHON_EXEC} -O ${CONFIG_PATH}/module_spec_test.py $*
 
 
+${PYTHON_EXEC} -O ${CONFIG_PATH}/ccsession_test.py $*
+
 ${PYTHON_EXEC} -O ${CONFIG_PATH}/cfgmgr_test.py $*
 ${PYTHON_EXEC} -O ${CONFIG_PATH}/cfgmgr_test.py $*

+ 52 - 0
src/lib/config/python/isc/config/unittest_fakesession.py

@@ -0,0 +1,52 @@
+
+
+#
+# We can probably use a more general version of this
+#
+class FakeModuleCCSession:
+    def __init__(self):
+        self.subscriptions = {}
+        # each entry is of the form [ channel, instance, message ]
+        self.message_queue = []
+        self._socket = "ok we just need something not-None here atm"
+
+    def group_subscribe(self, group_name, instance_name = None):
+        if not group_name in self.subscriptions:
+            self.subscriptions[group_name] = []
+        if instance_name:
+            self.subscriptions[group_name].append(instance_name)
+            
+
+    def has_subscription(self, group_name, instance_name = None):
+        if group_name in self.subscriptions:
+            if instance_name:
+                return instance_name in self.subscriptions[group_name]
+            else:
+                return True
+        else:
+            return False
+
+    def group_sendmsg(self, msg, channel, target = None):
+        self.message_queue.append([ channel, target, msg ])
+
+    def group_reply(self, env, msg):
+        pass
+
+    def group_recvmsg(self, blocking):
+        for qm in self.message_queue:
+            if qm[0] in self.subscriptions and (qm[1] == None or qm[1] in self.subscriptions[qm[0]]):
+                self.message_queue.remove(qm)
+                return qm[2], {}
+        return None, None
+
+    def get_message(self, channel, target = None):
+        for qm in self.message_queue:
+            if qm[0] == channel and qm[1] == target:
+                self.message_queue.remove(qm)
+                return qm[2]
+        return None
+
+    def close(self):
+        # need to pass along somehow that this function has been called,
+        self._socket = "closed"
+        pass