Skip to content

Commit f9e8f64

Browse files
committed
Make test_signal passing with CPython/macOS
1 parent 5ecae46 commit f9e8f64

File tree

1 file changed

+80
-58
lines changed

1 file changed

+80
-58
lines changed

tests/suite/modules/system_related/test_signal.py

Lines changed: 80 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,109 +11,131 @@
1111
import signal
1212
import sys
1313

14-
from iptest import IronPythonTestCase, is_cli, run_test
14+
from iptest import IronPythonTestCase, is_windows, is_posix, is_osx, is_linux, run_test
1515

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

2525
class SignalTest(IronPythonTestCase):
2626

2727
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):
3340
if x in SUPPORTED_SIGNALS: continue
3441
self.assertEqual(signal.getsignal(x), None)
3542

43+
3644
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]:
3846
self.assertRaisesMessage(ValueError, "signal number out of range",
3947
signal.getsignal, x)
4048
for x in [None, "abc", "14"]:
4149
self.assertRaises(TypeError, signal.getsignal, x)
4250

51+
4352
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+
5464

5565
def test_doc(self):
66+
signal_module = signal
5667
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__)
6071
self.assertTrue("The default handler for SIGINT installed by Python" in signal.default_int_handler.__doc__)
6172
self.assertTrue("Return the current action for the given signal" in signal.getsignal.__doc__)
6273
self.assertTrue("Set the action for the given signal" in signal.signal.__doc__)
6374

75+
6476
def test_signal_signal_neg(self):
6577
def a(b, c):
6678
pass
6779

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):
7281
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,
7583
signal.signal, x, a)
7684

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",
7987
signal.signal, x, a)
8088

8189
def bad_sig0(): pass
8290
def bad_sig1(a): pass
8391
def bad_sig3(a,b,c): pass
8492

85-
for y in SUPPORTED_SIGNALS + WEIRD_WORKING_CASES:
93+
for y in SUPPORTED_SIGNALS:
8694
bad_handlers = [-2, -1, 2, 3, 4, 10, 22, 23, 24, None]
8795
for x in bad_handlers:
8896
self.assertRaisesMessage(TypeError, "signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object",
8997
signal.signal, y, x)
9098

99+
91100
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
111132
class KNew(object):
112133
def __call__(self, *args, **kwargs):
113134
pass
114135

115136
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+
118140

119141
run_test(__name__)

0 commit comments

Comments
 (0)