github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/tini/test/run_inner_tests.py (about)

     1  #!/usr/bin/env python
     2  #coding:utf-8
     3  import os
     4  import sys
     5  import signal
     6  import subprocess
     7  import time
     8  import psutil
     9  import bitmap
    10  import re
    11  
    12  
    13  SIGNUM_TO_SIGNAME = dict((v, k) for k,v in signal.__dict__.items() if re.match("^SIG[A-Z]+$", k))
    14  
    15  
    16  def busy_wait(condition_callable, timeout):
    17      checks = 100
    18      increment = float(timeout) / checks
    19  
    20      for _ in xrange(checks):
    21          if condition_callable():
    22              return
    23          time.sleep(increment)
    24  
    25      assert False, "Condition was never met"
    26  
    27  
    28  def main():
    29      src = os.environ["SOURCE_DIR"]
    30      build = os.environ["BUILD_DIR"]
    31  
    32      args_disabled = os.environ.get("MINIMAL")
    33  
    34      proxy = os.path.join(src, "test", "subreaper-proxy.py")
    35      tini = os.path.join(build, "tini")
    36  
    37      subreaper_support = bool(int(os.environ["FORCE_SUBREAPER"]))
    38  
    39      tests = [([proxy, tini], {}),]
    40  
    41      if subreaper_support:
    42          if not args_disabled:
    43              tests.append(([tini, "-s"], {}))
    44          tests.append(([tini], {"TINI_SUBREAPER": ""}))
    45  
    46      for target, env in tests:
    47          # Run the reaping test
    48          print "Running reaping test ({0} with env {1})".format(" ".join(target), env)
    49          p = subprocess.Popen(target + [os.path.join(src, "test", "reaping", "stage_1.py")],
    50                               env=dict(os.environ, **env),
    51                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    52  
    53          out, err = p.communicate()
    54  
    55          if subreaper_support:
    56              # If subreaper support sin't available, Tini won't looku p its subreaper bit
    57              # and will output the error message here.
    58              assert "zombie reaping won't work" not in err, "Warning message was output!"
    59          ret = p.wait()
    60          assert ret == 0, "Reaping test failed!\nOUT: %s\nERR: %s" % (out, err)
    61  
    62  
    63          # Run the signals test
    64          for signum in [signal.SIGINT, signal.SIGTERM]:
    65              print "running signal test for: {0} ({1} with env {2})".format(SIGNUM_TO_SIGNAME[signum], " ".join(target), env)
    66              p = subprocess.Popen(target + [os.path.join(src, "test", "signals", "test.py")], env=dict(os.environ, **env))
    67              p.send_signal(signum)
    68              ret = p.wait()
    69              assert ret == -signum, "Signals test failed (ret was {0}, expected {1})".format(ret, -signum)
    70  
    71  
    72      # Run the process group test
    73      # This test has Tini spawn a process that ignores SIGUSR1 and spawns a child that doesn't (and waits on the child)
    74      # We send SIGUSR1 to Tini, and expect the grand-child to terminate, then the child, and then Tini.
    75      if not args_disabled:
    76          print "Running process group test"
    77          p = subprocess.Popen([tini, '-g', os.path.join(src, "test", "pgroup", "stage_1.py")], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    78  
    79          busy_wait(lambda: len(psutil.Process(p.pid).children(recursive=True)) == 2, 10)
    80          p.send_signal(signal.SIGUSR1)
    81          busy_wait(lambda: p.poll() is not None, 10)
    82  
    83      # Run failing test. Force verbosity to 1 so we see the subreaper warning
    84      # regardless of whether MINIMAL is set.
    85      print "Running zombie reaping failure test (Tini should warn)"
    86      p = subprocess.Popen(
    87          [tini, os.path.join(src, "test", "reaping", "stage_1.py")],
    88          stdout=subprocess.PIPE, stderr=subprocess.PIPE,
    89          env={'TINI_VERBOSITY': '1'}
    90      )
    91      out, err = p.communicate()
    92      assert "zombie reaping won't work" in err, "No warning message was output!"
    93      ret = p.wait()
    94      assert ret == 1, "Reaping test succeeded (it should have failed)!"
    95  
    96  
    97      # Test that the signals are properly in place here.
    98      print "running signal configuration test"
    99  
   100      p = subprocess.Popen([os.path.join(build, "sigconf-test"), tini, "cat", "/proc/self/status"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
   101      out, err = p.communicate()
   102  
   103      # Extract the signal properties, and add a zero at the end.
   104      props = [line.split(":") for line in out.splitlines()]
   105      props = [(k.strip(), v.strip()) for (k, v) in props]
   106      props = [(k, bitmap.BitMap.fromstring(bin(int(v, 16))[2:].zfill(32))) for (k, v) in props if k in ["SigBlk", "SigIgn", "SigCgt"]]
   107      props = dict(props)
   108  
   109      # Print actual handling configuration
   110      for k, bmp in props.items():
   111          print "{0}: {1}".format(k, ", ".join(["{0} ({1})".format(SIGNUM_TO_SIGNAME[n+1], n+1) for n in bmp.nonzero()]))
   112  
   113      for signal_set_name, signals_to_test_for in [
   114          ("SigIgn", [signal.SIGTTOU, signal.SIGSEGV, signal.SIGINT,]),
   115          ("SigBlk", [signal.SIGTTIN, signal.SIGILL,  signal.SIGTERM,]),
   116      ]:
   117          for signum in signals_to_test_for:
   118              # Use signum - 1 because the bitmap is 0-indexed but represents signals strting at 1
   119              assert (signum - 1) in props[signal_set_name].nonzero(), "{0} ({1}) is missing in {2}!".format(SIGNUM_TO_SIGNAME[signum], signum, signal_set_name)
   120  
   121      print "---------------------------"
   122      print "All done, tests as expected"
   123      print "---------------------------"
   124  
   125  
   126  if __name__ == "__main__":
   127      main()