OILS / pyext / posix_test.py View on Github | oilshell.org

184 lines, 103 significant
1#!/usr/bin/env python2
2"""
3posix_test.py: Tests for our posix_ module subset.
4
5NOTE: There are more tests in Python-2.7.13/Lib/test/test_posix.py.
6
7Notes on stripping posixmodule.c:
8
9I left in:
10
11 - putenv, unsetenv: Isn't it simpler to use these than os.environ? I'm not
12 sure how it works.
13 - tcgetpgrp, tcsetpgrp, setsid, getsid: is this for job control?
14
15 - times: This is a builtin! It's like 'time' for the shell prosecs itself.
16 - symlink - useful for writing tools?
17 - waitpid - because we're using wait
18
19 - set*uid, etc. - for container tools?
20 - kill, killpg - would the kill builtin need these?
21 - getppid - I think for $PPID
22
23 - mkdir, rmdir() -- might be useful for tools
24
25Other notes:
26
27 - The shell uses dup2 but not dup?
28"""
29from __future__ import print_function
30
31import signal
32import subprocess
33import unittest
34
35import posix_ # module under test
36from mycpp.mylib import log
37
38
39# Taken from build/oil-defs/.../posix_methods.def
40
41FUNCS = [
42 "access",
43 "chdir",
44 "getcwd",
45 "listdir",
46 "lstat",
47 "readlink",
48 "stat",
49 "umask",
50 "uname",
51 "_exit",
52 "execv",
53 "execve",
54 "fork",
55 "geteuid",
56 "getpid",
57 "getuid",
58 "wait",
59 "open",
60 "close",
61 "dup2",
62 "read",
63 "write",
64 "fdopen",
65 "isatty",
66 "pipe",
67 "strerror",
68 "WIFSIGNALED",
69 "WIFEXITED",
70 "WEXITSTATUS",
71 "WTERMSIG",
72
73 # Additional names found by grepping
74 'X_OK',
75 'R_OK',
76 'W_OK',
77
78 'O_APPEND',
79 'O_CREAT',
80 'O_RDONLY',
81 'O_RDWR',
82 'O_TRUNC',
83 'O_WRONLY',
84]
85
86class PosixTest(unittest.TestCase):
87
88 def testFoo(self):
89 print(posix_.getcwd())
90 # Testing this because I removed a lot of #ifdef
91 entries = posix_.listdir('.')
92 self.assert_('doc' in entries)
93
94 def testFunctionsExist(self):
95 for name in FUNCS:
96 func = getattr(posix_, name)
97 print(func)
98
99 def testEmptyReadAndWrite(self):
100 # Regression for bug where this would hang
101 posix_.read(0, 0)
102 posix_.write(1, '')
103
104 def testRead(self):
105 if posix_.environ.get('EINTR_TEST'):
106 # Now we can do kill -TERM PID can get EINTR.
107 # Or Ctrl-C for KeyboardInterrupt
108
109 signal.signal(signal.SIGTERM, _Handler)
110 log('Hanging on read in pid %d', posix_.getpid())
111 posix_.read(0, 1)
112
113 def testWait(self):
114 if posix_.environ.get('EINTR_TEST'):
115 # Now we can do kill -TERM PID can get EINTR.
116 signal.signal(signal.SIGTERM, _Handler)
117
118 p = subprocess.Popen(['sleep', '5'])
119 log('started sleep pid %d', p.pid)
120
121 log('Hanging on wait in pid %d', posix_.getpid())
122 posix_.wait()
123
124 def testWaitpid(self):
125 if posix_.environ.get('EINTR_TEST'):
126 # Now we can do kill -TERM PID can get EINTR.
127 signal.signal(signal.SIGTERM, _Handler)
128
129 p = subprocess.Popen(['sleep', '5'])
130 log('started sleep pid %d', p.pid)
131
132 log('Hanging on waitpid in pid %d', posix_.getpid())
133 posix_.waitpid(-1, 0)
134
135 def testWrite(self):
136 if posix_.environ.get('EINTR_TEST'):
137
138 signal.signal(signal.SIGTERM, _Handler)
139 r, w = posix_.pipe()
140 log('Hanging on write in pid %d', posix_.getpid())
141
142 # 1 byte bigger than pipe size
143 n = posix_.write(w, 'x'*65537)
144 log('1: Wrote %d bytes', n)
145
146 # write returns early when a signal interrupts it, and we read at least
147 # one byte! We do NOT get EINTR>
148
149 # On the second try, it didn't write anything, and we get EINTR!
150
151 log('Second try (pid %d)', posix_.getpid())
152 n = posix_.write(w, 'x'*65537)
153 log('2: Wrote %d bytes', n)
154
155 def testPrint(self):
156 # Conclusion: print CAN raise IOError with EINTR.
157
158 if posix_.environ.get('EINTR_TEST'):
159
160 signal.signal(signal.SIGTERM, _Handler)
161 r, w = posix_.pipe()
162 log('Hanging on write in pid %d', posix_.getpid())
163 f = posix_.fdopen(w, 'w')
164
165 # 1 byte bigger than pipe size
166 print('x'*65537, file=f)
167 log('1: done')
168
169 # write returns early when a signal interrupts it, and we read at least
170 # one byte! We do NOT get EINTR>
171
172 # On the second try, it didn't write anything, and we get EINTR!
173
174 log('Second try (pid %d)', posix_.getpid())
175 print('x'*65537, file=f)
176 log('2: done')
177
178
179def _Handler(x, y):
180 log('Got signal %s %s', x, y)
181
182
183if __name__ == '__main__':
184 unittest.main()