"""Test the pre-kill hook on Darwin.""" from __future__ import print_function # system imports from multiprocessing import Process, Queue import platform import re from unittest import main, TestCase # third party from six import StringIO def do_child_process(child_work_queue, parent_work_queue, verbose): import os pid = os.getpid() if verbose: print("child: pid {} started, sending to parent".format(pid)) parent_work_queue.put(pid) if verbose: print("child: waiting for shut-down request from parent") child_work_queue.get() if verbose: print("child: received shut-down request. Child exiting.") class DarwinPreKillTestCase(TestCase): def __init__(self, methodName): super(DarwinPreKillTestCase, self).__init__(methodName) self.process = None self.child_work_queue = None self.verbose = False def tearDown(self): if self.verbose: print("parent: sending shut-down request to child") if self.process: self.child_work_queue.put("hello, child") self.process.join() if self.verbose: print("parent: child is fully shut down") def test_sample(self): # Ensure we're Darwin. if platform.system() != 'Darwin': self.skipTest("requires a Darwin-based OS") # Start the child process. self.child_work_queue = Queue() parent_work_queue = Queue() self.process = Process(target=do_child_process, args=(self.child_work_queue, parent_work_queue, self.verbose)) if self.verbose: print("parent: starting child") self.process.start() # Wait for the child to report its pid. Then we know we're running. if self.verbose: print("parent: waiting for child to start") child_pid = parent_work_queue.get() # Sample the child process. from darwin import do_pre_kill context_dict = { "archs": [platform.machine()], "platform_name": None, "platform_url": None, "platform_working_dir": None } if self.verbose: print("parent: running pre-kill action on child") output_io = StringIO() do_pre_kill(child_pid, context_dict, output_io) output = output_io.getvalue() if self.verbose: print("parent: do_pre_kill() wrote the following output:", output) self.assertIsNotNone(output) # We should have a line with: # Process: .* [{pid}] process_re = re.compile(r"Process:[^[]+\[([^]]+)\]") match = process_re.search(output) self.assertIsNotNone(match, "should have found process id for " "sampled process") self.assertEqual(1, len(match.groups())) self.assertEqual(child_pid, int(match.group(1))) # We should see a Call graph: section. callgraph_re = re.compile(r"Call graph:") match = callgraph_re.search(output) self.assertIsNotNone(match, "should have found the Call graph section" "in sample output") # We should see a Binary Images: section. binary_images_re = re.compile(r"Binary Images:") match = binary_images_re.search(output) self.assertIsNotNone(match, "should have found the Binary Images " "section in sample output") if __name__ == "__main__": main()