from isc.config.ccsession import *
from isc.cc import SessionError, SessionTimeout
import isc.util.process
+import select
from isc.log_messages.ddns_messages import *
This loops waiting for events until self.shutdown() has been called.
'''
logger.info(DDNS_RUNNING)
+ cc_fileno = self._cc.get_socket().fileno()
+ listen_fileno = self._listen_socket.fileno()
while not self._shutdown:
# We do not catch any exceptions here right now, but this would
# be a good place to catch any exceptions that b10-ddns can
# recover from. We currently have no exception hierarchy to
# make such a distinction easily, but once we do, this would
# be the place to catch.
- self._cc.check_command(False)
+
+ # TODO: Catch select exceptions, like EINTR
+ (reads, writes, exceptions) = \
+ select.select([cc_fileno, listen_fileno], [], [])
+ for fileno in reads:
+ if fileno == cc_fileno:
+ self._cc.check_command(False)
+ elif fileno == listen_fileno:
+ self.accept()
+ else:
+ pass # TODO
self.shutdown_cleanup()
logger.info(DDNS_STOPPED)
import isc
import ddns
import isc.config
+import select
+
+class FakeSocket:
+ """
+ A fake socket. It only provides a file number.
+ """
+ def __init__(self, fileno):
+ self.__fileno = fileno
+ def fileno(self):
+ return self.__fileno
class MyCCSession(isc.config.ConfigData):
'''Fake session with minimal interface compliance'''
'''Called by DDNSServer initialization, but not used in tests'''
self._started = True
+ def get_socket(self):
+ """
+ Used to get the file number for select.
+ """
+ return FakeSocket(1)
+
class MyDDNSServer():
'''Fake DDNS server used to test the main() function'''
def __init__(self):
self.assertFalse(cc_session._started)
self.ddns_server = ddns.DDNSServer(cc_session)
self.assertTrue(cc_session._started)
+ self.__select_expected = None
+ self.__select_answer = None
+ self.__hook_called = False
def test_config_handler(self):
# Config handler does not do anything yet, but should at least
signal_handler(None, None)
self.assertTrue(self.ddns_server._shutdown)
+ def __select(self, reads, writes, exceptions, timeout=None):
+ """
+ A fake select. It checks it was called with the correct parameters and
+ returns a preset answer.
+ """
+ self.assertEqual(self.__select_expected, (reads, writes, exceptions,
+ timeout))
+ answer = self.__select_answer
+ self.__select_answer = None
+ self.ddns_server._shutdown = True
+ return answer
+
+ def __hook(self):
+ """
+ A hook that can be installed to any unary function and see if it was
+ really called.
+ """
+ self.__hook_called = True
+
+ def test_accept_called(self):
+ """
+ Test we call the accept function when a new connection comes.
+ """
+ self.ddns_server._listen_socket = FakeSocket(2)
+ ddns.select.select = self.__select
+ self.ddns_server.accept = self.__hook
+ self.__select_expected = ([1, 2], [], [], None)
+ self.__select_answer = ([2], [], [])
+ self.ddns_server.run()
+ self.assertTrue(self.ddns_server._shutdown)
+ # The answer got used
+ self.assertIsNone(self.__select_answer)
+ self.assertTrue(self.__hook_called)
+ ddns.select.select = select.select
+
class TestMain(unittest.TestCase):
def setUp(self):
self._server = MyDDNSServer()
self._server.set_exception(BaseException("error"))
self.assertRaises(BaseException, ddns.main, self._server)
self.assertTrue(self._server.exception_raised)
-
if __name__== "__main__":
isc.log.resetUnitTestRootLogger()