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()