test_libos.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #!/usr/bin/env python3
  2. import mmap
  3. import os
  4. import sys
  5. import unittest
  6. import subprocess
  7. from regression import (
  8. HAS_SGX,
  9. RegressionTestCase,
  10. SandboxTestCase,
  11. expectedFailureIf,
  12. )
  13. class TC_00_Bootstrap(RegressionTestCase):
  14. def test_100_basic_bootstrapping(self):
  15. stdout, stderr = self.run_binary(['bootstrap'])
  16. # Basic Bootstrapping
  17. self.assertIn('User Program Started', stdout)
  18. # One Argument Given
  19. self.assertIn('# of Arguments: 1', stdout)
  20. self.assertIn('argv[0] = file:bootstrap', stdout)
  21. def test_101_basic_bootstrapping_five_arguments(self):
  22. # Five Arguments Given
  23. stdout, stderr = self.run_binary(['bootstrap', 'a', 'b', 'c', 'd'])
  24. self.assertIn('# of Arguments: 5', stdout)
  25. self.assertIn('argv[0] = file:bootstrap', stdout)
  26. self.assertIn('argv[1] = a', stdout)
  27. self.assertIn('argv[2] = b', stdout)
  28. self.assertIn('argv[3] = c', stdout)
  29. self.assertIn('argv[4] = d', stdout)
  30. def test_110_basic_bootstrapping_cxx(self):
  31. stdout, stderr = self.run_binary(['bootstrap-c++'])
  32. # Basic Bootstrapping (C++)
  33. self.assertIn('User Program Started', stdout)
  34. def test_200_exec(self):
  35. stdout, stderr = self.run_binary(['exec'])
  36. # 2 page child binary
  37. self.assertIn(
  38. '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  39. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  40. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  41. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  42. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  43. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  44. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  45. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  46. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  47. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  48. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  49. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  50. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  51. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  52. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
  53. '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ',
  54. stdout)
  55. def test_201_fork_and_exec(self):
  56. stdout, stderr = self.run_binary(['fork_and_exec'])
  57. # fork and exec 2 page child binary
  58. self.assertIn('child exited with status: 0', stdout)
  59. self.assertIn('test completed successfully', stdout)
  60. def test_202_vfork_and_exec(self):
  61. stdout, stderr = self.run_binary(['vfork_and_exec'])
  62. # vfork and exec 2 page child binary
  63. self.assertIn('child exited with status: 0', stdout)
  64. self.assertIn('test completed successfully', stdout)
  65. def test_210_exec_invalid_args(self):
  66. stdout, stderr = self.run_binary(['exec_invalid_args'])
  67. # Execve with invalid pointers in arguments
  68. self.assertIn(
  69. 'execve(invalid-path) correctly returned error', stdout)
  70. self.assertIn(
  71. 'execve(invalid-argv-ptr) correctly returned error', stdout)
  72. self.assertIn(
  73. 'execve(invalid-envp-ptr) correctly returned error', stdout)
  74. self.assertIn(
  75. 'execve(invalid-argv) correctly returned error', stdout)
  76. self.assertIn(
  77. 'execve(invalid-envp) correctly returned error', stdout)
  78. def test_300_shared_object(self):
  79. stdout, stderr = self.run_binary(['shared_object'])
  80. # Shared Object
  81. self.assertIn('Hello world', stdout)
  82. def test_400_exit(self):
  83. with self.expect_returncode(113):
  84. self.run_binary(['exit'])
  85. def test_500_init_fail(self):
  86. try:
  87. self.run_binary(['init_fail'])
  88. self.fail('expected to return nonzero (and != 42)')
  89. except subprocess.CalledProcessError as e:
  90. self.assertNotEqual(e.returncode, 42, 'expected returncode != 42')
  91. @unittest.skipUnless(HAS_SGX,
  92. 'This test is only meaningful on SGX PAL because only SGX catches raw '
  93. 'syscalls and redirects to Graphene\'s LibOS. If we will add seccomp to '
  94. 'Linux PAL, then we should allow this test on Linux PAL as well.')
  95. class TC_01_OpenMP(RegressionTestCase):
  96. def test_000_simple_for_loop(self):
  97. stdout, stderr = self.run_binary(['openmp'])
  98. # OpenMP simple for loop
  99. self.assertIn('first: 0, last: 9', stdout)
  100. class TC_30_Syscall(RegressionTestCase):
  101. def test_000_getcwd(self):
  102. stdout, stderr = self.run_binary(['getcwd'])
  103. # Getcwd syscall
  104. self.assertIn('[bss_cwd_buf] getcwd succeeded: /', stdout)
  105. self.assertIn('[mmapped_cwd_buf] getcwd succeeded: /', stdout)
  106. def test_010_stat_invalid_args(self):
  107. stdout, stderr = self.run_binary(['stat_invalid_args'])
  108. # Stat with invalid arguments
  109. self.assertIn('stat(invalid-path-ptr) correctly returned error', stdout)
  110. self.assertIn('stat(invalid-buf-ptr) correctly returned error', stdout)
  111. self.assertIn('lstat(invalid-path-ptr) correctly returned error', stdout)
  112. self.assertIn('lstat(invalid-buf-ptr) correctly returned error', stdout)
  113. def test_011_fstat_cwd(self):
  114. stdout, stderr = self.run_binary(['fstat_cwd'])
  115. # fstat on a directory
  116. self.assertIn('fstat returned the fd type as S_IFDIR', stdout)
  117. def test_020_getdents(self):
  118. # This doesn't catch extraneous entries, but should be fine
  119. # until the LTP test can be run (need symlink support)
  120. stdout, stderr = self.run_binary(['getdents'])
  121. self.assertIn('getdents: setup ok', stdout)
  122. # Directory listing (32-bit)
  123. self.assertIn('getdents32: . [0x4]', stdout)
  124. self.assertIn('getdents32: .. [0x4]', stdout)
  125. self.assertIn('getdents32: file1 [0x8]', stdout)
  126. self.assertIn('getdents32: file2 [0x8]', stdout)
  127. self.assertIn('getdents32: dir3 [0x4]', stdout)
  128. # Directory listing (64-bit)
  129. self.assertIn('getdents64: . [0x4]', stdout)
  130. self.assertIn('getdents64: .. [0x4]', stdout)
  131. self.assertIn('getdents64: file1 [0x8]', stdout)
  132. self.assertIn('getdents64: file2 [0x8]', stdout)
  133. self.assertIn('getdents64: dir3 [0x4]', stdout)
  134. def test_030_fopen(self):
  135. stdout, stderr = self.run_binary(['fopen_cornercases'])
  136. # fopen corner cases
  137. self.assertIn('Successfully read from file: Hello World', stdout)
  138. def test_040_futex_wake(self):
  139. stdout, stderr = self.run_binary(['futex'])
  140. # Futex Wake Test
  141. self.assertIn('Woke all kiddos', stdout)
  142. def test_041_futex_timeout(self):
  143. stdout, stderr = self.run_binary(['futex-timeout'])
  144. # Futex Timeout Test
  145. self.assertIn('futex correctly timed out', stdout)
  146. def test_050_mmap(self):
  147. stdout, stderr = self.run_binary(['mmap-file'], timeout=60)
  148. # Private mmap beyond file range
  149. self.assertIn('mmap test 6 passed', stdout)
  150. self.assertIn('mmap test 7 passed', stdout)
  151. # Private mmap beyond file range (after fork)
  152. self.assertIn('mmap test 1 passed', stdout)
  153. self.assertIn('mmap test 2 passed', stdout)
  154. self.assertIn('mmap test 3 passed', stdout)
  155. self.assertIn('mmap test 4 passed', stdout)
  156. @unittest.skipIf(HAS_SGX,
  157. 'On SGX, SIGBUS isn\'t always implemented correctly, for lack '
  158. 'of memory protection. For now, some of these cases won\'t work.')
  159. def test_051_mmap_sgx(self):
  160. stdout, stderr = self.run_binary(['mmap-file'], timeout=60)
  161. # SIGBUS test
  162. self.assertIn('mmap test 5 passed', stdout)
  163. self.assertIn('mmap test 8 passed', stdout)
  164. def test_52_large_mmap(self):
  165. stdout, stderr = self.run_binary(['large-mmap'], timeout=240)
  166. # Ftruncate
  167. self.assertIn('large-mmap: ftruncate OK', stdout)
  168. # Large mmap
  169. self.assertIn('large-mmap: mmap 1 completed OK', stdout)
  170. self.assertIn('large-mmap: mmap 2 completed OK', stdout)
  171. @unittest.skip('sigaltstack isn\'t correctly implemented')
  172. def test_060_sigaltstack(self):
  173. stdout, stderr = self.run_binary(['sigaltstack'])
  174. # Sigaltstack Test
  175. self.assertIn('OK on sigaltstack in main thread before alarm', stdout)
  176. self.assertIn('&act == 0x', stdout)
  177. self.assertIn('sig 14 count 1 goes off with sp=0x', stdout)
  178. self.assertIn('OK on signal stack', stdout)
  179. self.assertIn('OK on sigaltstack in handler', stdout)
  180. self.assertIn('sig 14 count 2 goes off with sp=0x', stdout)
  181. self.assertIn('OK on signal stack', stdout)
  182. self.assertIn('OK on sigaltstack in handler', stdout)
  183. self.assertIn('sig 14 count 3 goes off with sp=0x', stdout)
  184. self.assertIn('OK on signal stack', stdout)
  185. self.assertIn('OK on sigaltstack in handler', stdout)
  186. self.assertIn('OK on sigaltstack in main thread', stdout)
  187. self.assertIn('done exiting', stdout)
  188. @unittest.skipUnless(HAS_SGX,
  189. 'This test is only meaningful on SGX PAL because only SGX catches raw '
  190. 'syscalls and redirects to Graphene\'s LibOS. If we will add seccomp to '
  191. 'Linux PAL, then we should allow this test on Linux PAL as well.')
  192. class TC_31_SyscallSGX(RegressionTestCase):
  193. def test_000_syscall_redirect(self):
  194. stdout, stderr = self.run_binary(['syscall'])
  195. # Syscall Instruction Redirection
  196. self.assertIn('Hello world', stdout)
  197. class TC_40_FileSystem(RegressionTestCase):
  198. def test_000_base(self):
  199. stdout, stderr = self.run_binary(['proc'])
  200. # Base /proc files present
  201. self.assertIn('/proc/1/..', stdout)
  202. self.assertIn('/proc/1/cwd', stdout)
  203. self.assertIn('/proc/1/exe', stdout)
  204. self.assertIn('/proc/1/root', stdout)
  205. self.assertIn('/proc/1/fd', stdout)
  206. self.assertIn('/proc/1/maps', stdout)
  207. self.assertIn('/proc/.', stdout)
  208. self.assertIn('/proc/1', stdout)
  209. self.assertIn('/proc/self', stdout)
  210. self.assertIn('/proc/meminfo', stdout)
  211. self.assertIn('/proc/cpuinfo', stdout)
  212. def test_010_path(self):
  213. stdout, stderr = self.run_binary(['proc-path'])
  214. # Base /proc path present
  215. self.assertIn('proc path test success', stdout)
  216. def test_020_cpuinfo(self):
  217. stdout, stderr = self.run_binary(['proc_cpuinfo'], timeout=50)
  218. # proc/cpuinfo Linux-based formatting
  219. self.assertIn('cpuinfo test passed', stdout)
  220. class TC_80_Socket(RegressionTestCase):
  221. def test_000_getsockopt(self):
  222. stdout, stderr = self.run_binary(['getsockopt'])
  223. self.assertIn('getsockopt: Got socket type OK', stdout)
  224. def test_010_epoll_wait_timeout(self):
  225. stdout, stderr = self.run_binary(['epoll_wait_timeout', '8000'],
  226. timeout=50)
  227. # epoll_wait timeout
  228. self.assertIn('epoll_wait test passed', stdout)
  229. def test_100_socket_unix(self):
  230. stdout, stderr = self.run_binary(['unix'])
  231. self.assertIn('Data: This is packet 0', stdout)
  232. self.assertIn('Data: This is packet 1', stdout)
  233. self.assertIn('Data: This is packet 2', stdout)
  234. self.assertIn('Data: This is packet 3', stdout)
  235. self.assertIn('Data: This is packet 4', stdout)
  236. self.assertIn('Data: This is packet 5', stdout)
  237. self.assertIn('Data: This is packet 6', stdout)
  238. self.assertIn('Data: This is packet 7', stdout)
  239. self.assertIn('Data: This is packet 8', stdout)
  240. self.assertIn('Data: This is packet 9', stdout)
  241. def test_200_socket_udp(self):
  242. stdout, stderr = self.run_binary(['udp'], timeout=50)
  243. self.assertIn('Data: This is packet 0', stdout)
  244. self.assertIn('Data: This is packet 1', stdout)
  245. self.assertIn('Data: This is packet 2', stdout)
  246. self.assertIn('Data: This is packet 3', stdout)
  247. self.assertIn('Data: This is packet 4', stdout)
  248. self.assertIn('Data: This is packet 5', stdout)
  249. self.assertIn('Data: This is packet 6', stdout)
  250. self.assertIn('Data: This is packet 7', stdout)
  251. self.assertIn('Data: This is packet 8', stdout)
  252. self.assertIn('Data: This is packet 9', stdout)