|
@@ -477,28 +477,51 @@ class MyModuleCCSession(isc.config.ConfigData):
|
|
self.stopped = True # just record it's called to inspect it later
|
|
self.stopped = True # just record it's called to inspect it later
|
|
|
|
|
|
class SimpleStats(stats.Stats):
|
|
class SimpleStats(stats.Stats):
|
|
|
|
+ """A faked Stats class for unit tests.
|
|
|
|
+
|
|
|
|
+ This class inherits most of the real Stats class, but replace the
|
|
|
|
+ ModuleCCSession with a fake one so we can avoid network I/O in tests,
|
|
|
|
+ and can also inspect or tweak messages via the session more easily.
|
|
|
|
+ This class also maintains some faked module information and statistics
|
|
|
|
+ data that can be retrieved from the implementation of the Stats class.
|
|
|
|
+
|
|
|
|
+ """
|
|
def __init__(self):
|
|
def __init__(self):
|
|
- self.__seq = 4200 # for faked group_sendmsg, arbitrary choice.
|
|
|
|
- self._answers = [] # if set, use them as faked response to recvmsg
|
|
|
|
|
|
+ # First, setup some internal attributes. All of them are essentially
|
|
|
|
+ # private (so prefixed with double '_'), but some are defined as if
|
|
|
|
+ # "protected" (with a single '_') for the convenient of tests that
|
|
|
|
+ # may want to inspect or tweak them.
|
|
|
|
+
|
|
|
|
+ # initial seq num for faked group_sendmsg, arbitrary choice.
|
|
|
|
+ self.__seq = 4200
|
|
|
|
+ # if set, use them as faked response to group_recvmsg (see below).
|
|
|
|
+ # it's a list of tuples, each of which is of (answer, envelope).
|
|
|
|
+ self._answers = []
|
|
|
|
+ # the default answer from faked recvmsg if _answers is empty
|
|
self.__default_answer = isc.config.ccsession.create_answer(
|
|
self.__default_answer = isc.config.ccsession.create_answer(
|
|
0, {'Init':
|
|
0, {'Init':
|
|
json.loads(MockInit.spec_str)['module_spec']['statistics'],
|
|
json.loads(MockInit.spec_str)['module_spec']['statistics'],
|
|
'Auth':
|
|
'Auth':
|
|
json.loads(MockAuth.spec_str)['module_spec']['statistics']
|
|
json.loads(MockAuth.spec_str)['module_spec']['statistics']
|
|
})
|
|
})
|
|
|
|
+ # setup faked auth statistics
|
|
self.__init_auth_stat()
|
|
self.__init_auth_stat()
|
|
|
|
+ # statistics data for faked Init module
|
|
self._init_sdata = {
|
|
self._init_sdata = {
|
|
'boot_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', CONST_BASETIME)
|
|
'boot_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', CONST_BASETIME)
|
|
}
|
|
}
|
|
|
|
|
|
- # Since we replace _init_statistics_data, this doesn't cause
|
|
|
|
- # any network I/O
|
|
|
|
|
|
+ # Incorporate other setups of the real Stats module. We use the faked
|
|
|
|
+ # ModuleCCSession to avoid blocking network operation. Note also that
|
|
|
|
+ # we replace _init_statistics_data() (see below), so we don't
|
|
|
|
+ # initialize statistics data yet.
|
|
stats.Stats.__init__(self, MyModuleCCSession)
|
|
stats.Stats.__init__(self, MyModuleCCSession)
|
|
|
|
|
|
- # replace some (faked) ModuleCCSession methods so we can avoid
|
|
|
|
- # network I/O, then call _init_statistics_data. This will
|
|
|
|
- # get the Stats module info from the file directly and some
|
|
|
|
- # amount information about the Init and Auth modules (hardcoded below).
|
|
|
|
|
|
+ # replace some (faked) ModuleCCSession methods so we can inspect/fake
|
|
|
|
+ # the data exchanged via the CC session, then call
|
|
|
|
+ # _init_statistics_data. This will get the Stats module info from
|
|
|
|
+ # the file directly and some amount information about the Init and
|
|
|
|
+ # Auth modules (hardcoded below).
|
|
self.cc_session.group_sendmsg = self.__check_group_sendmsg
|
|
self.cc_session.group_sendmsg = self.__check_group_sendmsg
|
|
self.cc_session.group_recvmsg = self.__check_group_recvmsg
|
|
self.cc_session.group_recvmsg = self.__check_group_recvmsg
|
|
stats.Stats._init_statistics_data(self)
|
|
stats.Stats._init_statistics_data(self)
|
|
@@ -528,20 +551,31 @@ class SimpleStats(stats.Stats):
|
|
}
|
|
}
|
|
|
|
|
|
def _init_statistics_data(self):
|
|
def _init_statistics_data(self):
|
|
|
|
+ # Inherited from real Stats class, just for deferring the
|
|
|
|
+ # initialization until we are ready.
|
|
pass
|
|
pass
|
|
|
|
|
|
- def get_datetime(self):
|
|
|
|
- return 42
|
|
|
|
-
|
|
|
|
def __check_group_sendmsg(self, command, destination):
|
|
def __check_group_sendmsg(self, command, destination):
|
|
|
|
+ """Faked ModuleCCSession.group_sendmsg for tests.
|
|
|
|
+
|
|
|
|
+ Skipping actual network communication, and just returning an internally
|
|
|
|
+ generated sequence number.
|
|
|
|
+
|
|
|
|
+ """
|
|
self.__seq += 1
|
|
self.__seq += 1
|
|
return self.__seq
|
|
return self.__seq
|
|
|
|
|
|
def __check_group_recvmsg(self, nonblocking, seq):
|
|
def __check_group_recvmsg(self, nonblocking, seq):
|
|
- # if faked anser is given, use it; otherwise use the default.
|
|
|
|
- # we don't actually check the sequence.
|
|
|
|
|
|
+ """Faked ModuleCCSession.group_recvmsg for tests.
|
|
|
|
+
|
|
|
|
+ Skipping actual network communication, and returning an internally
|
|
|
|
+ prepared answer. sequence number. If faked anser is given in
|
|
|
|
+ _answers, use it; otherwise use the default. we don't actually check
|
|
|
|
+ the sequence.
|
|
|
|
+
|
|
|
|
+ """
|
|
if len(self._answers) == 0:
|
|
if len(self._answers) == 0:
|
|
- return self.__default_answer, None
|
|
|
|
|
|
+ return self.__default_answer, {'from': 'no-matter'}
|
|
return self._answers.pop(0)
|
|
return self._answers.pop(0)
|
|
|
|
|
|
class MyStats(stats.Stats):
|
|
class MyStats(stats.Stats):
|