Make IpcDaemonTestCase demonstrate an EbuildIpcDaemon based
authorZac Medico <zmedico@gentoo.org>
Fri, 13 Aug 2010 05:08:56 +0000 (22:08 -0700)
committerZac Medico <zmedico@gentoo.org>
Fri, 13 Aug 2010 05:08:56 +0000 (22:08 -0700)
replacement for EBUILD_EXIT_STATUS_FILE.

bin/ebuild-ipc.py
pym/_emerge/EbuildIpcDaemon.py
pym/portage/tests/ebuild/test_ipc_daemon.py

index 2edd6655955ec2c0d7e83885ba08e809db311b32..761e07a2ac4a8ad5f49c63545311c9a65219735d 100755 (executable)
@@ -51,18 +51,17 @@ class EbuildIpc(object):
                output_file.flush()
 
                events = select.select([input_file], [], [])
-               if input_file in events[0]:
-                       reply = pickle.load(input_file)
-               else:
-                       reply = None
-
+               reply = pickle.load(input_file)
                output_file.close()
                input_file.close()
 
-               if reply == 'OK':
-                       rval = os.EX_OK
-               else:
-                       rval = 1
+               (out, err, rval) = reply
+
+               if out:
+                       portage.util.writemsg_stdout(out, noiselevel=-1)
+
+               if err:
+                       portage.util.writemsg(out, noiselevel=-1)
 
                return rval
 
index 48f58224b861310a8e2a3ad88f429b9fd4749243..2f4d8933cda5ca638f75dc1617c3359acd7916c6 100644 (file)
@@ -24,7 +24,7 @@ class EbuildIpcDaemon(FifoIpcDaemon):
        left orphan processes running in the backgraound (as in bug 278895).
        """
 
-       __slots__ = ()
+       __slots__ = ('commands',)
 
        def _input_handler(self, fd, event):
 
@@ -38,15 +38,15 @@ class EbuildIpcDaemon(FifoIpcDaemon):
 
                        if buf:
                                obj = pickle.loads(buf.tostring())
-                               if isinstance(obj, list) and \
-                                       obj and \
-                                       obj[0] == 'exit':
-                                       output_fd = os.open(self.output_fifo, os.O_WRONLY|os.O_NONBLOCK)
-                                       output_file = os.fdopen(output_fd, 'wb')
-                                       pickle.dump('OK', output_file)
-                                       output_file.close()
-                                       self._unregister()
-                                       self.wait()
+                               cmd_key = obj[0]
+                               cmd_handler = self.commands[cmd_key]
+                               cmd_handler(obj, self._send_reply)
 
                self._unregister_if_appropriate(event)
                return self._registered
+
+       def _send_reply(self, reply):
+               output_fd = os.open(self.output_fifo, os.O_WRONLY|os.O_NONBLOCK)
+               output_file = os.fdopen(output_fd, 'wb')
+               pickle.dump(reply, output_file)
+               output_file.close()
index 488bd3999050eafc3067e4986f132a55e58b9231..bd27a38d14b944632cfbeee1363930a1db237601 100644 (file)
@@ -12,6 +12,28 @@ from _emerge.SpawnProcess import SpawnProcess
 from _emerge.EbuildIpcDaemon import EbuildIpcDaemon
 from _emerge.TaskScheduler import TaskScheduler
 
+class ExitCommand(object):
+
+       def __init__(self):
+               self.callback = None
+               self.exitcode = None
+
+       def __call__(self, argv, send_reply):
+               duplicate = False
+               if self.exitcode is not None:
+                       # Ignore all but the first call, since if die is called
+                       # then we certainly want to honor that exitcode, even
+                       # the ebuild process manages to send a second exit
+                       # command.
+                       duplicate = True
+               else:
+                       self.exitcode = int(argv[1])
+
+               # (stdout, stderr, returncode)
+               send_reply(('', '', 0))
+               if not duplicate and self.callback is not None:
+                       self.callback()
+
 class IpcDaemonTestCase(TestCase):
 
        def testIpcDaemon(self):
@@ -25,16 +47,25 @@ class IpcDaemonTestCase(TestCase):
                        output_fifo = os.path.join(tmpdir, '.ipc_out')
                        os.mkfifo(input_fifo)
                        os.mkfifo(output_fifo)
-                       task_scheduler = TaskScheduler(max_jobs=2)
-                       daemon = EbuildIpcDaemon(input_fifo=input_fifo,
-                               output_fifo=output_fifo,
-                               scheduler=task_scheduler.sched_iface)
-                       proc = SpawnProcess(
-                               args=[BASH_BINARY, "-c", '"$PORTAGE_BIN_PATH"/ebuild-ipc exit 0'],
-                               env=env, scheduler=task_scheduler.sched_iface)
-                       task_scheduler.add(daemon)
-                       task_scheduler.add(proc)
-                       task_scheduler.run()
-                       self.assertEqual(proc.returncode, os.EX_OK)
+                       for exitcode in (0, 1, 2):
+                               task_scheduler = TaskScheduler(max_jobs=2)
+                               exit_command = ExitCommand()
+                               commands = {'exit' : exit_command}
+                               daemon = EbuildIpcDaemon(commands=commands,
+                                       input_fifo=input_fifo,
+                                       output_fifo=output_fifo,
+                                       scheduler=task_scheduler.sched_iface)
+                               proc = SpawnProcess(
+                                       args=[BASH_BINARY, "-c",
+                                       '"$PORTAGE_BIN_PATH"/ebuild-ipc exit %d' % exitcode],
+                                       env=env, scheduler=task_scheduler.sched_iface)
+                               def exit_command_callback():
+                                       daemon.cancel()
+                                       proc.cancel()
+                               exit_command.callback = exit_command_callback
+                               task_scheduler.add(daemon)
+                               task_scheduler.add(proc)
+                               task_scheduler.run()
+                               self.assertEqual(exit_command.exitcode, exitcode)
                finally:
                        shutil.rmtree(tmpdir)