[svn] commit: r2453 - in /branches/trac191: ./ src/bin/stats/ src/bin/stats/tests/

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Jul 9 09:16:16 UTC 2010


Author: naokikambe
Date: Fri Jul  9 09:16:16 2010
New Revision: 2453

Log:
- add stub script, which behaves as a sender to Stats module and which can talk with the stats module in order to testing and verification of stats module, so not to be started by boss process
- adopt Listener pattern and Observer pattern model in stats.py
- add some changes which stats module can receive statistics information from other module via cfgmgr, stats module can send dynamic valuable like datetime and counter
- add definition statistics items and more commands which stats module and other sender modules use via bindctl or cfgmgr
- add some changes to test script for more strictly testing
- add minor changes like mismatch from coding guidelines
- add some change to unittest_fakesession.py in order to be more like real session.py
- delete some dead code

Added:
    branches/trac191/src/bin/stats/run_b10-stats_stub.sh.in
    branches/trac191/src/bin/stats/stats_stub.py.in
    branches/trac191/src/bin/stats/tests/b10-stats_stub_test.py
Modified:
    branches/trac191/configure.ac
    branches/trac191/src/bin/stats/Makefile.am
    branches/trac191/src/bin/stats/stats.py.in
    branches/trac191/src/bin/stats/stats.spec.pre.in
    branches/trac191/src/bin/stats/tests/Makefile.am
    branches/trac191/src/bin/stats/tests/b10-stats_test.py
    branches/trac191/src/bin/stats/tests/stats_test.in
    branches/trac191/src/bin/stats/tests/unittest_fakesession.py

Modified: branches/trac191/configure.ac
==============================================================================
--- branches/trac191/configure.ac (original)
+++ branches/trac191/configure.ac Fri Jul  9 09:16:16 2010
@@ -439,8 +439,10 @@
            src/bin/xfrout/tests/xfrout_test
            src/bin/xfrout/run_b10-xfrout.sh
 	   src/bin/stats/stats.py
+	   src/bin/stats/stats_stub.py
 	   src/bin/stats/stats.spec.pre
            src/bin/stats/run_b10-stats.sh
+           src/bin/stats/run_b10-stats_stub.sh
 	   src/bin/stats/tests/stats_test
            src/bin/bind10/bind10.py
            src/bin/bind10/tests/bind10_test
@@ -470,6 +472,7 @@
            chmod +x src/bin/xfrout/run_b10-xfrout.sh
 	   chmod +x src/bin/stats/tests/stats_test
 	   chmod +x src/bin/stats/run_b10-stats.sh
+	   chmod +x src/bin/stats/run_b10-stats_stub.sh
            chmod +x src/bin/bind10/run_bind10.sh
            chmod +x src/bin/cmdctl/tests/cmdctl_test
            chmod +x src/bin/xfrin/tests/xfrin_test

Modified: branches/trac191/src/bin/stats/Makefile.am
==============================================================================
--- branches/trac191/src/bin/stats/Makefile.am (original)
+++ branches/trac191/src/bin/stats/Makefile.am Fri Jul  9 09:16:16 2010
@@ -3,11 +3,12 @@
 pkglibexecdir = $(libexecdir)/@PACKAGE@
 
 pkglibexec_SCRIPTS = b10-stats
+noinst_SCRIPTS = b10-stats_stub
 
 b10_statsdir = $(DESTDIR)$(pkgdatadir)
 b10_stats_DATA = stats.spec
 
-CLEANFILES = b10-stats b10-stats.pyc stats stats.pyc stats.spec
+CLEANFILES = stats.spec b10-stats stats.pyc stats.pyo b10-stats_stub stats_stub.pyc stats_stub.pyo
 
 man_MANS = b10-stats.8
 EXTRA_DIST = $(man_MANS) b10-stats.xml
@@ -28,3 +29,8 @@
 	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
 	       -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" stats.py >$@
 	chmod a+x $@
+
+b10-stats_stub: stats_stub.py
+	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
+	       -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" stats_stub.py >$@
+	chmod a+x $@

Modified: branches/trac191/src/bin/stats/stats.py.in
==============================================================================
--- branches/trac191/src/bin/stats/stats.py.in (original)
+++ branches/trac191/src/bin/stats/stats.py.in Fri Jul  9 09:16:16 2010
@@ -15,16 +15,18 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+# $Id$
+__version__ = "$Revision$"
+
 import sys; sys.path.append ('@@PYTHONPATH@@')
-
 import os
+import signal
+import select
+import time
 from optparse import OptionParser, OptionValueError
-import signal
-import time
-import isc
-import isc.cc
-from isc.config.ccsession import ModuleCCSession, create_answer, COMMAND_SHUTDOWN
-from isc.cc import SessionError
+from collections import defaultdict
+from isc.config.ccsession import ModuleCCSession, create_answer
+from isc.cc import Session, SessionError
 
 # If B10_FROM_SOURCE is set in the environment, we use data files
 # from a directory relative to that, otherwise we use the ones
@@ -36,175 +38,348 @@
     DATAROOTDIR = "@datarootdir@"
     SPECFILE_LOCATION = "@datadir@/@PACKAGE@/stats.spec".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
 
-class Stats:
-    """
-    Stats module
-    """
-    def __init__(self, cc_session=None, verbose=False):
-        """
-        creates & initialize a stats module
-        """
-        self._boottime=self.get_datetime()
+class Singleton(type):
+    """
+    A abstract class of singleton pattern
+    """
+    def __init__(self, *args):
+        type.__init__(self, *args)
+        self._instances = {}
+
+    def __call__(self, *args):
+        if not args in self._instances:
+            self._instances[args] = type.__call__(self, *args)
+        return self._instances[args]
+
+class Callback():
+    """
+    A Callback handler class
+    """
+    def __init__(self, name, callback=None, *args, **kwargs):
+        self.name=name
+        self.callback=callback
+        self.args=args
+        self.kwargs=kwargs
+
+    def __call__(self, *args, **kwargs):
+        if args:
+            self.args=args
+        if kwargs:
+            self.kwargs=kwargs
+        if self.callback:
+            return self.callback(*self.args, **self.kwargs)
+
+class Subject():
+    """
+    A abstract subject class of observer pattern
+    """
+    def __init__(self, verbose=False):
         self.verbose=verbose
-        if self.verbose:
-            sys.stdout.write("[b10-stats] initialize a stats module\n")
-
-        if cc_session:
-            ccss = ModuleCCSession(SPECFILE_LOCATION,
-                                   self.config_handler,
-                                   self.command_handler,
-                                   cc_session)
+        self._listeners = []
+
+    def attach(self, listener):
+        if not listener in self._listeners:
+            self._listeners.append(listener)
+
+    def detach(self, listener):
+        try:
+            self._listeners.remove(listener)
+        except ValueError:
+            pass
+
+    def notify(self, event, modifier=None):
+        for listener in self._listeners:
+            if modifier != listener:
+                listener.update(event)
+
+class Listener():
+    """
+    A abstract listener class of observer pattern
+    """
+    def __init__(self, subject):
+        self.subject = subject
+        self.subject.attach(self)
+        self.events = {}
+
+    def update(self, name):
+        if name in self.events:
+            callback = self.events[name]
+            return callback()
+
+    def add_event(self, event):
+        self.events[event.name]=event
+
+class SessionSubject(Subject):
+    """
+    A concrete subject class which creates CC session object
+    """
+    __metaclass__ = Singleton
+    def __init__(self, session=None, verbose=False):
+        Subject.__init__(self)
+        self.verbose = verbose
+        if session is None:
+            self.session = Session()
         else:
-            ccss = ModuleCCSession(SPECFILE_LOCATION,
-                                   self.config_handler,
-                                   self.command_handler)
-
-        self.ccss=ccss
-        self._session=ccss._session
+            self.session = session
         self.running = False
 
-    def get_boottime(self):
-        """
-        datetime when stats module starts
-        """
-        return self._boottime
-
-    def get_lname(self):
-        """
-        Return local_name of CCSession
-        """
-        return self._session.lname
-
-    def get_statsspec(self):
-        """
-        Return dictionary of stat_spec
-        """
-        spec=self.ccss.get_module_spec().get_full_spec()
-        return spec['stats_spec']
+    def start(self):
+        self.running = True
+        self.notify('start')
+
+    def stop(self):
+        self.running = False
+        self.notify('stop')
+
+    def check(self):
+        self.notify('check')
+
+class CCSessionListener(Listener):
+    """
+    A concrete listener class which creates SessionSubject object and
+    ModuleCCSession object
+    """
+    def __init__(self, subject, verbose=False):
+        Listener.__init__(self, subject)
+        self.verbose = verbose
+        self.subject = subject
+        self.session = subject.session
+
+        # create ModuleCCSession object
+        self.cc_session = ModuleCCSession(SPECFILE_LOCATION,
+                                          self.config_handler,
+                                          self.command_handler,
+                                          self.session)
+
+        # initialize internal data
+        self.stats_spec = self.get_full_spec()['stats_spec']
+        self.stats_data = self.initialize_data(self.stats_spec)
+
+        # add event handler invoked via SessionSubject object
+        self.add_event(Callback('start', self.start))
+        self.add_event(Callback('stop', self.stop))
+        self.add_event(Callback('check', self.check))
+
+        # add event handler related command_handler of ModuleCCSession
+        # invoked via bindctl
+        for c in self.get_full_spec()['commands']:
+               cmd = c["command_name"]
+               try:
+                   self.add_event(Callback('command_'+cmd, eval("self.command_"+cmd)))
+               except NameError:
+                   pass
 
     def config_handler(self, new_config):
         """
         handle a configure from the cc channel
         """
-        answer = create_answer(0)
-        return answer
+        # do nothing
+        return create_answer(0)
 
     def command_handler(self, command, args):
         """
         handle commands from the cc channel
         """
-        self.command=command
-        self.args=args
-        if command == COMMAND_SHUTDOWN:
-            ans=self.command_shutdown()
-        elif command == "status":
-            ans=self.command_status()
-        elif command == "show":
-            ans=self.command_show()
-        elif command == "statsspec":
-            ans=self.command_statsspec()
+        cmd = None
+        # add 'command_' suffix in order to prevent executing internal
+        # command via bindctl
+        name = 'command_'+command
+        
+        if name in self.events:
+            event=self.events[name]
+            return event(args)
         else:
-            ans=self.command_unknown()
-        return ans
+            return self.command_unknown(command, args)
 
     def start(self):
         """
-        start the stats module
-        """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] starting the stats module\n")
-        self.boot_time=self.get_datetime()
-        self.ccss.start()
-        self.running = True
-        while (self.running):
-            self.ccss.check_command()
-        self.ccss.close()
-        return True
+        start the cc chanel
+        """
+        return self.cc_session.start()
 
     def stop(self):
         """
-        stop the stats module
-        """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] stopping the stats module\n")
-        self.running = False
-
-    def command_shutdown(self):
+        stop the cc chanel
+        """
+        return self.cc_session.close()
+
+    def check(self):
+        """
+        check the cc chanel
+        """
+        return self.cc_session.check_command()
+
+    def command_shutdown(self, args):
         """
         handle shutdown command
         """
         if self.verbose:
-            sys.stdout.write("[b10-stats] got 'shutdown' command\n")
-        self.stop()
-        return create_answer(0)
-
-    def command_status(self):
+            sys.stdout.write("[b10-stats] 'shutdown' command received\n")
+        self.subject.running = False
+        return create_answer(0)
+
+    def command_set(self, args):
+        """
+        handle set command
+        """
+        if self.verbose:
+            sys.stdout.write("[b10-stats] 'set' command received, args: "+str(args)+"\n")
+
+        data = self.stats_data
+        # Data type of the top level must be dictionary type
+        for k in args.keys():
+            data[k] = args[k]
+        self.stats_data = data
+        return create_answer(0)
+
+    def command_add(self, args):
+        """
+        handle add command
+        """
+        if self.verbose:
+            sys.stdout.write("[b10-stats] 'add' command received, args: "+str(args)+"\n")
+
+        # A internal private function adding for each element, which
+        # is called recursively
+        def __add_data(data, args):
+            # print(type(data), type(args))
+
+            if type(data) == type([]):
+                max = max(len(data), len(args))
+                for i in max:
+                    if i in data and i in args:
+                        data[i] = __add_data(data[i], args[i])
+                    elif i in args:
+                        data.extend(args[i:])
+                        break
+            elif type(data) == type({}):
+                for k in args.keys():
+                    if k in data:
+                        data[k] = __add_data(data[k], args[k])
+                    else:
+                        data[k] = args[k]
+            else:
+                data = data + args
+            return data
+
+        # call a internal function
+        self.stats_data = __add_data(self.stats_data, args)
+        return create_answer(0)
+
+    def command_del(self, args):
+        """
+        handle add command
+        """
+        if self.verbose:
+            sys.stdout.write("[b10-stats] 'del' command received, args: "+str(args)+"\n")
+
+        # just remove one item
+        self.stats_data.pop(args)
+        return create_answer(0)
+
+    def command_spec(self, args):
+        """
+        handle show stats spec command
+        """
+        if self.verbose:
+            sys.stdout.write("[b10-stats] 'spec' command received\n")
+        return create_answer(0,dict(self.stats_spec))
+
+    def command_show(self, args):
+        """
+        handle show command
+        """
+        if self.verbose:
+            sys.stdout.write("[b10-stats] 'show' command received\n")
+
+        # overwrite information about stats module
+        self.stats_data['report_time'] = get_datetime()
+        self.stats_data['stats.timestamp'] = get_timestamp()
+        self.stats_data['stats.lname'] = self.session.lname
+
+        return create_answer(0, dict(self.stats_data))
+
+    def command_reset(self, args):
+        """
+        handle reset command
+        """
+        if self.verbose:
+            sys.stdout.write("[b10-stats] 'reset' command received\n")
+        # re-initialize data
+        self.stats_spec = self.get_full_spec()['stats_spec']
+        self.stats_data = self.initialize_data(self.stats_spec)
+        return create_answer(0)
+
+    def command_status(self, args):
         """
         handle status command
         """
         if self.verbose:
-            sys.stdout.write("[b10-stats] got 'status' command\n")
-        ret="I'm alive."
-        return create_answer(0,ret)
-
-    def command_show(self):
-        """
-        handle show command
-        """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] got 'show' command\n")
-        ret={}
-        for sspec in self.get_statsspec():
-            name=sspec['name']
-            if name == 'report_time':
-                ret[name]=self.get_datetime()
-            elif name == 'stats.boot_time':
-                ret[name]=self.get_boottime()
-            elif name == 'stats.timestamp':
-                ret[name]=self.get_timestamp()
-            elif name == 'stats.lname':
-                ret[name]=self.get_lname()
-            else:
-                sys.stderr.write("[b10-stats] an errer while reading specfile")
-                return create_answer(1, "an errer while reading specfile")
-        return create_answer(0,ret)
-
-    def command_statsspec(self):
-        """
-        handle stats_spec command
-        """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] got 'statsspec' command\n")
-        return create_answer(0,self.get_statsspec())
-
-    def command_unknown(self):
+            sys.stdout.write("[b10-stats] 'status' command received\n")
+        return create_answer(0, "I'm alive.")
+
+    def command_unknown(self, command, args):
         """
         handle an unknown command
         """
         if self.verbose:
-            sys.stdout.write("[b10-stats] got unknown command\n")
-        return create_answer(1, "Unknown command: '"+str(self.command)+"'")
-
-    def get_timestamp(self):
-        """
-        get current timestamp
-        """
-        return time.time()
-
-    def get_datetime(self):
-        """
-        get current datetime
-        """
-        return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
+            sys.stdout.write("[b10-stats] Unknown command received: '"
+                             + str(command) + "'\n")
+        return create_answer(1, "Unknown command: '"+str(command)+"'")
+
+    def initialize_data(self, spec):
+        """
+        initialize stats data
+        """
+        t = spec.get('type')
+        if t == 'null':
+            return None
+        elif t == 'boolean':
+            return bool(spec.get('default', False))
+        elif t == 'string':
+            return str(spec.get('default', ''))
+        elif t in set(['number', 'integer']):
+            return int(spec.get('default', 0))
+        elif t in set(['float', 'double']):
+            return float(spec.get('default', 0.0))
+        elif t == 'array':
+            return [ self.initialize_data(x) for x in spec['items'] ]
+        elif t == 'object':
+            d = spec['properties']
+            return dict([ (k, self.initialize_data(d[k])) for k in d.keys() ])
+        else:
+            return spec.get('default')
+
+    def get_full_spec(self):
+        """
+        get full spec from cc_session
+        """
+        return self.cc_session.get_module_spec().get_full_spec()
+
+def get_timestamp():
+    """
+    get current timestamp
+    """
+    return time.time()
+
+def get_datetime():
+    """
+    get current datetime
+    """
+    return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
 
 def main():
     try:
-        parser = OptionParser()
+        parser=OptionParser()
         parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                       help="display more about what is going on")
         (options, args) = parser.parse_args()
-        stats=Stats(verbose=options.verbose)
-        stats.start()
+        subject = SessionSubject(verbose=options.verbose)
+        listener = CCSessionListener(subject, verbose=options.verbose)
+        subject.start()
+        while subject.running:
+            subject.check()
+        subject.stop()
     except OptionValueError:
         sys.stderr.write("[b10-stats] Error parsing options\n")
     except SessionError as se:
@@ -212,7 +387,9 @@
               + "is the command channel daemon running?\n")
     except KeyboardInterrupt as kie:
         sys.stderr.write("[b10-stats] Interrupted, exiting\n")
+    finally:
+        if subject:
+            subject.stop()
 
 if __name__ == "__main__":
     main()
-

Modified: branches/trac191/src/bin/stats/stats.spec.pre.in
==============================================================================
--- branches/trac191/src/bin/stats/stats.spec.pre.in (original)
+++ branches/trac191/src/bin/stats/stats.spec.pre.in Fri Jul  9 09:16:16 2010
@@ -22,44 +22,74 @@
         "command_args": []
       },
       {
-        "command_name": "shutdown",
-        "command_description": "Shut down stats module",
+        "command_name": "set",
+        "command_description": "Set statistics data",
         "command_args": []
       },
       {
-        "command_name": "statsspec",
-        "command_description": "Show contents of stats_spec in specfile",
+        "command_name": "add",
+        "command_description": "Add statistics data",
+        "command_args": []
+      },
+      {
+        "command_name": "del",
+        "command_description": "Delete statistics data",
+        "command_args": []
+      },
+      {
+        "command_name": "reset",
+        "command_description": "Reset statistics data",
+        "command_args": []
+      },
+      {
+        "command_name": "shutdown",
+        "command_description": "Shutdown stats module",
+        "command_args": []
+      },
+      {
+        "command_name": "spec",
+        "command_description": "Show stats_spec module",
         "command_args": []
       }
     ],
-    "stats_spec": [
-      {
-        "name": "report_time",
-        "title": "Report time",
-        "description": "A date time when stats module reports",
-        "type": "string",
-        "format": "date-time"
-      },
-      {
-        "name": "stats.boot_time",
-        "title": "stats.BootTime",
-        "description": "A date time when b10-stats process starts",
-        "type": "string",
-        "format": "date-time"
-      },
-      {
-        "name": "stats.timestamp",
-        "title": "stats.Timestamp",
-        "description": "Current timestamp since epoch time (1970-01-01T00:00:00Z)",
-        "type": "float",
-        "format": "second"
-      },
-      {
-        "name": "stats.lname",
-        "title": "stats.LocalName",
-        "description": "A localname of stats module given via CC protocol",
-        "type": "string"
+    "stats_spec": {
+      "description": "A specification of statistics",
+      "type": "object",
+      "properties": {
+        "report_time": {
+          "title": "Report time",
+          "description": "A date time when stats module reports",
+          "type": "string",
+          "format": "date-time"
+        },
+        "bind10.boot_time": {
+          "title": "stats.BootTime",
+          "description": "A date time when b10-stats process starts",
+          "type": "string",
+          "format": "date-time"
+        },
+        "stats.timestamp": {
+          "title": "stats.Timestamp",
+          "description": "Current timestamp since epoch time (1970-01-01T00:00:00Z)",
+          "type": "float",
+          "format": "second"
+        },
+        "stats.lname": {
+          "title": "stats.LocalName",
+          "description": "A localname of stats module given via CC protocol",
+          "type": "string"
+        },
+        "auth.queries.tcp": {
+          "title": "auth.queries.tcp",
+          "description": "A number of incremental query counts per a process which Auth servers receives in TCP since last sending",
+          "type": "number"
+        },
+        "auth.queries.udp": {
+          "title": "auth.queries.udp",
+          "description": "A number of incremental query counts per a process which Auth servers receives in UDP since last sending",
+          "type": "number"
+        }
       }
-    ]
+    }
   }
 }

Modified: branches/trac191/src/bin/stats/tests/Makefile.am
==============================================================================
--- branches/trac191/src/bin/stats/tests/Makefile.am (original)
+++ branches/trac191/src/bin/stats/tests/Makefile.am Fri Jul  9 09:16:16 2010
@@ -1,4 +1,4 @@
-PYTESTS = b10-stats_test.py
+PYTESTS = b10-stats_test.py b10-stats_stub_test.py
 EXTRA_DIST = $(PYTESTS)
 CLEANFILES = unittest_fakesession.pyc
 
@@ -9,7 +9,6 @@
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_srcdir)/src/bin/stats \
-	CONFIG_TESTDATA_PATH=$(abs_top_srcdir)/src/lib/config/testdata \
 	B10_FROM_SOURCE=$(abs_top_srcdir) \
 	$(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \
 	done

Modified: branches/trac191/src/bin/stats/tests/b10-stats_test.py
==============================================================================
--- branches/trac191/src/bin/stats/tests/b10-stats_test.py (original)
+++ branches/trac191/src/bin/stats/tests/b10-stats_test.py Fri Jul  9 09:16:16 2010
@@ -13,7 +13,8 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: cfgmgr_test.py 1860 2010-05-19 17:02:32Z jelte $
+# $Id$
+__version__ = "$Revision$"
 
 #
 # Tests for the stats module
@@ -22,90 +23,214 @@
 import time
 import re
 import unittest
-import isc
 from isc.config.ccsession import ModuleCCSessionError
 from unittest_fakesession import FakeModuleCCSession
-from stats import Stats
+from stats import SessionSubject, CCSessionListener
 
 class TestStats(unittest.TestCase):
 
-    def test_stats(self):
-        """
-        Test for initialize, start, shutdown
+    def setUp(self):
+        self.session = FakeModuleCCSession()
+        self.subject = SessionSubject(session=self.session, verbose=False)
+        self.listener = CCSessionListener(self.subject, verbose=False)
+        self.stats_spec = self.listener.cc_session.get_module_spec().get_full_spec()['stats_spec']
+        self.stats_data = {
+                'report_time' : get_datetime(),
+                'bind10.boot_time' : '',
+                'stats.timestamp' : float(int(get_timestamp())),
+                'stats.lname' : self.session.lname,
+                'auth.queries.tcp': 0,
+                'auth.queries.udp': 0
+                }
+
+    def test_start(self):
+        """
+        Test for stats
         
         """
-        fake_session = FakeModuleCCSession()
-        stats = Stats(fake_session)
-        ccss=stats.ccss
-        self.assertEqual(len(fake_session.message_queue), 0)
-        self.assertRaises(ModuleCCSessionError, stats.start)
-        self.assertEqual(len(fake_session.message_queue), 2)
-        self.assertEqual({"command": ["module_spec", ccss.specification._module_spec]},
-                         fake_session.get_message("ConfigManager", None))
+        session = self.session
+        subject = self.subject
+        listener = self.listener
+
+        self.assertEqual(len(subject.session.message_queue), 0)
+        self.assertFalse(subject.running)
+        self.assertRaises(ModuleCCSessionError, subject.start)
+        self.assertTrue(subject.running)
+        self.assertEqual(len(subject.session.message_queue), 2)
+        self.assertEqual({"command": ["module_spec", listener.cc_session.specification._module_spec]},
+                         subject.session.get_message("ConfigManager", None))
         self.assertEqual({"command": ["get_config", {"module_name": "Stats"}]},
-                         fake_session.get_message("ConfigManager", None))
-        self.assertEqual(len(fake_session.message_queue), 0)
-        fake_session.group_sendmsg({'result': [ 0 ]}, "Stats")
-        fake_session.group_sendmsg({'result': [ 1, "just an error" ]}, "Stats")
-        self.assertEqual(len(fake_session.message_queue), 2)
-        fake_session.group_sendmsg({"command": [ "shutdown" ]}, "Stats")
-        self.assertEqual(len(fake_session.message_queue), 3)
-        self.assertFalse(stats.running)
-        stats.start()
-        self.assertFalse(stats.running)
-
-    def test_spec(self):
-        """
-        Test for spec file
+                         subject.session.get_message("ConfigManager", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+        session.group_sendmsg({'result': [ 0 ]}, "Stats")
+        session.group_sendmsg({'result': [ 1, "just an error" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 2)
+        self.assertTrue(subject.running)
+        subject.start()
+        self.assertTrue(subject.running)
+        self.assertEqual(len(subject.session.message_queue), 2)
+        self.assertEqual({"command": ["module_spec", listener.cc_session.specification._module_spec]},
+                         subject.session.get_message("ConfigManager", None))
+        self.assertEqual({"command": ["get_config", {"module_name": "Stats"}]},
+                         subject.session.get_message("ConfigManager", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+        subject.check()
+        self.assertTrue(subject.running)
+
+    def test_commands(self):
+        """
+        Test for stats commands
         
         """
-        fake_session = FakeModuleCCSession()
-        stats = Stats(fake_session)
-        names1=[ 'report_time',
-                 'stats.boot_time',
-                 'stats.timestamp',
-                 'stats.lname'      ]
-        names1.sort()
-        names2=[ sspec['name'] for sspec in stats.get_statsspec() ]
-        names2.sort()
-        self.assertTrue(names1==names2)
-
-    def test_commands(self):
-        """
-        Test for command handlig
-        
-        """
-        fake_session = FakeModuleCCSession()
-        stats = Stats(fake_session)
-        ccss=stats.ccss
-        self.assertRaises(ModuleCCSessionError, stats.start)
-        self.assertEqual({'result': [0]},
-                         stats.command_handler("shutdown", None))
-        self.assertEqual({'result': [0, "I'm alive."]},
-                         stats.command_handler("status", None))
-        self.assertEqual({'result': [0, ccss.specification._module_spec['stats_spec']]},
-                         stats.command_handler("statsspec", None))
-        self.assertEqual({'result': [1, "Unknown command: 'unknown'"]},
-                         stats.command_handler("unknown", None))
-        ret_stats=stats.command_handler("show", None)
-        self.assertTrue('result' in ret_stats)
-        self.assertTrue(ret_stats['result'])
-        rs=ret_stats['result']
-        self.assertEqual(len(ret_stats['result']), 2)
-        self.assertEqual(ret_stats['result'][0], 0)
-        self.assertTrue(ret_stats['result'][1])
-        rs=ret_stats['result'][1]
-        self.assertTrue('report_time'     in rs)
-        self.assertTrue('stats.boot_time' in rs)
-        self.assertTrue('stats.timestamp' in rs)
-        self.assertTrue('stats.lname'     in rs)
-        self.assertTrue(time.strptime(rs['report_time'], '%Y-%m-%dT%H:%M:%SZ'))
-        self.assertTrue(time.strptime(rs['stats.boot_time'], '%Y-%m-%dT%H:%M:%SZ'))
-        self.assertTrue(time.strptime(rs['report_time'], '%Y-%m-%dT%H:%M:%SZ'))
-        self.assertTrue(time.time() - rs['stats.timestamp'] >=0)
-        self.assertTrue(type(time.time() - rs['stats.timestamp'])==type(float(0.1)))
-        self.assertTrue(re.match('^[^@]+@[^@]+$', rs['stats.lname']))
-        self.assertEqual(ret_stats['result'][0], 0)
+        session = self.session
+        subject = self.subject
+        stats_spec = self.stats_spec.copy()
+        stats_data = self.stats_data.copy()
+
+        self.assertFalse(subject.running)
+        self.assertRaises(ModuleCCSessionError, subject.start)
+        self.assertTrue(subject.running)
+        for i in (0, 1):
+            subject.session.get_message("ConfigManager", None)
+
+        # test show command
+        session.group_sendmsg({"command": [ "show" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        result_data = subject.session.get_message("Stats", None)
+        result_data['result'][1]['stats.timestamp'] = float(int(result_data['result'][1]['stats.timestamp']))
+        self.assertEqual({ "result": [ 0, stats_data ]}, result_data)
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test set command
+        stats_data['atest'] = float(1.0)
+        session.group_sendmsg({"command":
+                                   [ "set",
+                                     {'atest' : stats_data['atest']}
+                                     ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        self.assertEqual(result_ok(),
+                         subject.session.get_message("Stats", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test show command
+        session.group_sendmsg({"command": [ "show" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        result_data = subject.session.get_message("Stats", None)
+        result_data['result'][1]['stats.timestamp'] = float(int(result_data['result'][1]['stats.timestamp']))
+        self.assertEqual(result_ok(0, stats_data), result_data)
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test add command
+        stats_data['atest'] = stats_data['atest'] + float(0.1)
+        session.group_sendmsg({"command": [ "add", {'atest': float(0.1) } ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        self.assertEqual(result_ok(),
+                         subject.session.get_message("Stats", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test show command
+        session.group_sendmsg({"command": [ "show" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        result_data = subject.session.get_message("Stats", None)
+        result_data['result'][1]['stats.timestamp'] = float(int(result_data['result'][1]['stats.timestamp']))
+        self.assertEqual({ "result": [ 0, stats_data ]}, result_data)
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test del command
+        stats_data.pop('atest')
+        session.group_sendmsg({"command": [ "del", 'atest' ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        self.assertEqual(result_ok(),
+                         subject.session.get_message("Stats", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test show command
+        session.group_sendmsg({"command": [ "show" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        result_data = subject.session.get_message("Stats", None)
+        result_data['result'][1]['stats.timestamp'] = float(int(result_data['result'][1]['stats.timestamp']))
+        self.assertEqual({ "result": [ 0, stats_data ]}, result_data)
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test reset command
+        stats_data = self.stats_data.copy()
+        session.group_sendmsg({"command": [ "reset" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        self.assertEqual(result_ok(),
+                         subject.session.get_message("Stats", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test show command
+        session.group_sendmsg({"command": [ "show" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        result_data = subject.session.get_message("Stats", None)
+        result_data['result'][1]['stats.timestamp'] = float(int(result_data['result'][1]['stats.timestamp']))
+        self.assertEqual({ "result": [ 0, stats_data ]}, result_data)
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test show spec command
+        session.group_sendmsg({"command": [ "spec" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        self.assertEqual(result_ok(0, stats_spec),
+                         subject.session.get_message("Stats", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test status command
+        session.group_sendmsg({"command": [ "status" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        self.assertEqual(result_ok(0, "I'm alive."),
+                         subject.session.get_message("Stats", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test unknown command
+        session.group_sendmsg({"command": [ "hoge" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        subject.check()
+        self.assertEqual(result_ok(1, "Unknown command: 'hoge'"),
+                         subject.session.get_message("Stats", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+        # test shutdown command
+        session.group_sendmsg({"command": [ "shutdown" ]}, "Stats")
+        self.assertEqual(len(subject.session.message_queue), 1)
+        self.assertTrue(subject.running)
+        subject.check()
+        self.assertFalse(subject.running)
+        self.assertEqual(result_ok(),
+                         subject.session.get_message("Stats", None))
+        self.assertEqual(len(subject.session.message_queue), 0)
+
+    def tearDown(self):
+        self.session.close()
+
+def result_ok(*args):
+    if args:
+        return { 'result': list(args) }
+    else:
+        return { 'result': [ 0 ] }
+
+def get_timestamp():
+    """
+    get current timestamp
+    """
+    return time.time()
+
+def get_datetime():
+    """
+    get current datetime
+    """
+    return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
 
 if __name__ == "__main__":
     unittest.main()

Modified: branches/trac191/src/bin/stats/tests/stats_test.in
==============================================================================
--- branches/trac191/src/bin/stats/tests/stats_test.in (original)
+++ branches/trac191/src/bin/stats/tests/stats_test.in Fri Jul  9 09:16:16 2010
@@ -23,9 +23,6 @@
 PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_srcdir@/src/bin/stats
 export PYTHONPATH
 
-CONFIG_TESTDATA_PATH=@abs_top_srcdir@/src/lib/config/testdata
-export CONFIG_TESTDATA_PATH
-
 B10_FROM_SOURCE=@abs_top_srcdir@
 export B10_FROM_SOURCE
 # TODO: We need to do this feature based (ie. no general from_source)
@@ -36,3 +33,5 @@
 
 cd ${BIND10_PATH}
 ${PYTHON_EXEC} -O ${STATS_PATH}/b10-stats_test.py $*
+
+${PYTHON_EXEC} -O ${STATS_PATH}/b10-stats_stub_test.py $*

Modified: branches/trac191/src/bin/stats/tests/unittest_fakesession.py
==============================================================================
--- branches/trac191/src/bin/stats/tests/unittest_fakesession.py (original)
+++ branches/trac191/src/bin/stats/tests/unittest_fakesession.py Fri Jul  9 09:16:16 2010
@@ -1,4 +1,8 @@
+# $Id$
+__version__ = "$Revision$"
 
+import os
+from isc.cc.session import SessionError
 
 #
 # We can probably use a more general version of this
@@ -8,7 +12,9 @@
         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"
+        # set socket dummy data
+        cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 0; done'
+        self._socket = os.popen(cmd, 'r')
         # set lname
         self.lname='123abc at xxxx'
 
@@ -29,13 +35,19 @@
             return False
 
     def group_sendmsg(self, msg, channel, target = None):
+        if self._socket.closed:
+            raise SessionError("Session has been closed.")
         self.message_queue.append([ channel, target, msg ])
 
     def group_reply(self, env, msg):
+        if self._socket.closed:
+            raise SessionError("Session has been closed.")
         if 'group' in env:
             self.message_queue.append([ env['group'], None, msg])
 
     def group_recvmsg(self, blocking, seq = None):
+        if self._socket.closed:
+            raise SessionError("Session has been closed.")
         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)
@@ -51,5 +63,6 @@
 
     def close(self):
         # need to pass along somehow that this function has been called,
-        self._socket = "closed"
-        pass
+        if not self._socket.closed:
+            buf = self._socket.readlines()
+        self._socket.close()




More information about the bind10-changes mailing list