|
11 | 11 | import signal |
12 | 12 | import sys |
13 | 13 |
|
14 | | -from iptest import IronPythonTestCase, is_cli, run_test |
| 14 | +from iptest import IronPythonTestCase, is_windows, is_posix, is_osx, is_linux, run_test |
15 | 15 |
|
16 | | -SUPPORTED_SIGNALS = [ signal.SIGBREAK, |
17 | | - signal.SIGABRT, |
18 | | - signal.SIGINT, |
19 | | - signal.SIGTERM, |
20 | | - signal.SIGFPE, |
21 | | - signal.SIGILL, |
22 | | - signal.SIGSEGV, |
23 | | - ] |
| 16 | +if is_linux: |
| 17 | + SIG_codes = {'SIGABRT': 6, 'SIGALRM': 14, 'SIGBUS': 7, 'SIGCHLD': 17, 'SIGCLD': 17, 'SIGCONT': 18, 'SIGFPE': 8, 'SIGHUP': 1, 'SIGILL': 4, 'SIGINT': 2, 'SIGIO': 29, 'SIGIOT': 6, 'SIGKILL': 9, 'SIGPIPE': 13, 'SIGPOLL': 29, 'SIGPROF': 27, 'SIGPWR': 30, 'SIGQUIT': 3, 'SIGRTMAX': 64, 'SIGRTMIN': 34, 'SIGSEGV': 11, 'SIGSTKFLT': 16, 'SIGSTOP': 19, 'SIGSYS': 31, 'SIGTERM': 15, 'SIGTRAP': 5, 'SIGTSTP': 20, 'SIGTTIN': 21, 'SIGTTOU': 22, 'SIGURG': 23, 'SIGUSR1': 10, 'SIGUSR2': 12, 'SIGVTALRM': 26, 'SIGWINCH': 28, 'SIGXCPU': 24, 'SIGXFSZ': 25} |
| 18 | +elif is_osx: |
| 19 | + SIG_codes = {'SIGABRT': 6, 'SIGALRM': 14, 'SIGBUS': 10, 'SIGCHLD': 20, 'SIGCONT': 19, 'SIGEMT': 7, 'SIGFPE': 8, 'SIGHUP': 1, 'SIGILL': 4, 'SIGINFO': 29, 'SIGINT': 2, 'SIGIO': 23, 'SIGIOT': 6, 'SIGKILL': 9, 'SIGPIPE': 13, 'SIGPROF': 27, 'SIGQUIT': 3, 'SIGSEGV': 11, 'SIGSTOP': 17, 'SIGSYS': 12, 'SIGTERM': 15, 'SIGTRAP': 5, 'SIGTSTP': 18, 'SIGTTIN': 21, 'SIGTTOU': 22, 'SIGURG': 16, 'SIGUSR1': 30, 'SIGUSR2': 31, 'SIGVTALRM': 26, 'SIGWINCH': 28, 'SIGXCPU': 24, 'SIGXFSZ': 25} |
| 20 | +elif is_windows: |
| 21 | + SIG_codes = {'SIGABRT': 22, 'SIGBREAK': 21, 'SIGFPE': 8, 'SIGILL': 4, 'SIGINT': 2, 'SIGSEGV': 11, 'SIGTERM': 15} |
| 22 | + |
| 23 | +SUPPORTED_SIGNALS = set(SIG_codes.values()) |
24 | 24 |
|
25 | 25 | class SignalTest(IronPythonTestCase): |
26 | 26 |
|
27 | 27 | def test_000_run_me_first(self): |
28 | | - for x in [x for x in SUPPORTED_SIGNALS if x!=signal.SIGINT]: |
29 | | - self.assertEqual(signal.getsignal(x), 0) |
30 | | - self.assertEqual(signal.getsignal(signal.SIGINT), signal.default_int_handler) |
31 | | - |
32 | | - for x in range(1, 23): |
| 28 | + WEIRD_CASES = { signal.SIGINT: signal.default_int_handler } |
| 29 | + if is_posix: |
| 30 | + WEIRD_CASES[signal.SIGKILL] = None |
| 31 | + WEIRD_CASES[signal.SIGSTOP] = None |
| 32 | + WEIRD_CASES[signal.SIGPIPE] = signal.SIG_IGN |
| 33 | + WEIRD_CASES[signal.SIGXFSZ] = signal.SIG_IGN |
| 34 | + |
| 35 | + for x in [x for x in SUPPORTED_SIGNALS]: |
| 36 | + with self.subTest(sig=x): |
| 37 | + self.assertEqual(signal.getsignal(x), WEIRD_CASES.get(x, signal.SIG_DFL)) |
| 38 | + |
| 39 | + for x in range(1, signal.NSIG): |
33 | 40 | if x in SUPPORTED_SIGNALS: continue |
34 | 41 | self.assertEqual(signal.getsignal(x), None) |
35 | 42 |
|
| 43 | + |
36 | 44 | def test_signal_getsignal_negative(self): |
37 | | - for x in [-2, -1, 0, 23, 24, 25]: |
| 45 | + for x in [-2, -1, 0, signal.NSIG, signal.NSIG + 1, signal.NSIG + 2]: |
38 | 46 | self.assertRaisesMessage(ValueError, "signal number out of range", |
39 | 47 | signal.getsignal, x) |
40 | 48 | for x in [None, "abc", "14"]: |
41 | 49 | self.assertRaises(TypeError, signal.getsignal, x) |
42 | 50 |
|
| 51 | + |
43 | 52 | def test_module_constants(self): |
44 | | - self.assertEqual(signal.NSIG, 23) |
45 | | - self.assertEqual(signal.SIGABRT, 22) |
46 | | - self.assertEqual(signal.SIGBREAK, 21) |
47 | | - self.assertEqual(signal.SIGFPE, 8) |
48 | | - self.assertEqual(signal.SIGILL, 4) |
49 | | - self.assertEqual(signal.SIGINT, 2) |
50 | | - self.assertEqual(signal.SIGSEGV, 11) |
51 | | - self.assertEqual(signal.SIGTERM, 15) |
52 | | - self.assertEqual(signal.SIG_DFL, 0) |
53 | | - self.assertEqual(signal.SIG_IGN, 1) |
| 53 | + if is_linux: |
| 54 | + self.assertEqual(signal.NSIG, 65) |
| 55 | + elif is_osx: |
| 56 | + self.assertEqual(signal.NSIG, 32) |
| 57 | + elif is_windows: |
| 58 | + self.assertEqual(signal.NSIG, 23) |
| 59 | + |
| 60 | + # when run with CPython, this verifies that SIG_codes are correct and matching CPython |
| 61 | + for sig in SIG_codes: |
| 62 | + self.assertEqual(getattr(signal, sig), SIG_codes[sig]) |
| 63 | + |
54 | 64 |
|
55 | 65 | def test_doc(self): |
| 66 | + signal_module = signal |
56 | 67 | if sys.version_info >= (3,5): |
57 | | - self.assertIsNone(signal.__doc__) |
58 | | - else: |
59 | | - self.assertTrue("get the signal action for a given signal" in signal.__doc__) |
| 68 | + import _signal |
| 69 | + signal_module = _signal |
| 70 | + self.assertTrue("get the signal action for a given signal" in signal_module.__doc__) |
60 | 71 | self.assertTrue("The default handler for SIGINT installed by Python" in signal.default_int_handler.__doc__) |
61 | 72 | self.assertTrue("Return the current action for the given signal" in signal.getsignal.__doc__) |
62 | 73 | self.assertTrue("Set the action for the given signal" in signal.signal.__doc__) |
63 | 74 |
|
| 75 | + |
64 | 76 | def test_signal_signal_neg(self): |
65 | 77 | def a(b, c): |
66 | 78 | pass |
67 | 79 |
|
68 | | - WEIRD_WORKING_CASES = [6] if is_cli else [] |
69 | | - NO_SUCH_DIR = [21] |
70 | | - |
71 | | - for x in range(1, 23): |
| 80 | + for x in range(1, signal.NSIG): |
72 | 81 | if x in SUPPORTED_SIGNALS: continue |
73 | | - if x in WEIRD_WORKING_CASES: continue |
74 | | - self.assertRaises(RuntimeError if is_cli else ValueError, |
| 82 | + self.assertRaises(ValueError, |
75 | 83 | signal.signal, x, a) |
76 | 84 |
|
77 | | - for x in [-2, -1, 0, 23, 24, 25]: |
78 | | - self.assertRaisesMessage(ValueError, "signal number out of range" if is_cli else "invalid signal value", |
| 85 | + for x in [-2, -1, 0, signal.NSIG, signal.NSIG + 1, signal.NSIG + 2]: |
| 86 | + self.assertRaisesMessage(ValueError, "signal number out of range", |
79 | 87 | signal.signal, x, a) |
80 | 88 |
|
81 | 89 | def bad_sig0(): pass |
82 | 90 | def bad_sig1(a): pass |
83 | 91 | def bad_sig3(a,b,c): pass |
84 | 92 |
|
85 | | - for y in SUPPORTED_SIGNALS + WEIRD_WORKING_CASES: |
| 93 | + for y in SUPPORTED_SIGNALS: |
86 | 94 | bad_handlers = [-2, -1, 2, 3, 4, 10, 22, 23, 24, None] |
87 | 95 | for x in bad_handlers: |
88 | 96 | self.assertRaisesMessage(TypeError, "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object", |
89 | 97 | signal.signal, y, x) |
90 | 98 |
|
| 99 | + |
91 | 100 | def test_signal_signal(self): |
92 | | - WORKING_CASES = SUPPORTED_SIGNALS |
93 | | - if is_cli: |
94 | | - WORKING_CASES += [6] |
95 | | - WEIRD_CASES = { |
96 | | - 6: None, |
97 | | - 2: signal.default_int_handler} |
98 | | - for x in WORKING_CASES: |
99 | | - #Ideal handler signature |
100 | | - def a(signum, frame): |
101 | | - return x |
102 | | - |
103 | | - ret_val = signal.signal(x, a) |
104 | | - if x not in WEIRD_CASES.keys(): |
105 | | - self.assertEqual(ret_val, signal.SIG_DFL) |
106 | | - else: |
107 | | - self.assertEqual(ret_val, WEIRD_CASES[x]) |
108 | | - self.assertEqual(a, signal.getsignal(x)) |
109 | | - |
110 | | - #Strange handler signatures |
| 101 | + WEIRD_CASES = { signal.SIGINT: signal.default_int_handler} |
| 102 | + if is_posix: |
| 103 | + WEIRD_CASES[signal.SIGKILL] = None |
| 104 | + WEIRD_CASES[signal.SIGSTOP] = None |
| 105 | + WEIRD_CASES[signal.SIGPIPE] = signal.SIG_IGN |
| 106 | + WEIRD_CASES[signal.SIGXFSZ] = signal.SIG_IGN |
| 107 | + |
| 108 | + for x in SUPPORTED_SIGNALS: |
| 109 | + with self.subTest(sig=x): |
| 110 | + |
| 111 | + # correctness of expected handler tested by assertion in test_000_run_me_first |
| 112 | + expected_val = WEIRD_CASES.get(x, signal.SIG_DFL) |
| 113 | + |
| 114 | + if expected_val is None: |
| 115 | + # signals that cannot be handled |
| 116 | + with self.assertRaises(OSError) as cm: |
| 117 | + signal.signal(x, signal.SIG_DFL) |
| 118 | + |
| 119 | + self.assertEqual(cm.exception.errno, 22) |
| 120 | + self.assertEqual(cm.exception.strerror, "Invalid argument") |
| 121 | + else: |
| 122 | + # Ideal handler signature |
| 123 | + def a(signum, frame): |
| 124 | + return x |
| 125 | + |
| 126 | + ret_val = signal.signal(x, a) |
| 127 | + self.assertEqual(ret_val, expected_val) |
| 128 | + self.assertEqual(a, signal.getsignal(x)) |
| 129 | + self.assertEqual(a, signal.signal(x, expected_val)) # restores old handler |
| 130 | + |
| 131 | + # Strange handler signatures |
111 | 132 | class KNew(object): |
112 | 133 | def __call__(self, *args, **kwargs): |
113 | 134 | pass |
114 | 135 |
|
115 | 136 | a = KNew() |
116 | | - ret_val = signal.signal(signal.SIGBREAK, a) |
117 | | - self.assertEqual(a, signal.getsignal(signal.SIGBREAK)) |
| 137 | + ret_val = signal.signal(signal.SIGINT, a) |
| 138 | + self.assertEqual(a, signal.getsignal(signal.SIGINT)) |
| 139 | + |
118 | 140 |
|
119 | 141 | run_test(__name__) |
0 commit comments