test_fs.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #!/usr/bin/env python3
  2. import filecmp
  3. import os
  4. import shutil
  5. import sys
  6. import unittest
  7. from regression import (
  8. HAS_SGX,
  9. RegressionTestCase,
  10. expectedFailureIf,
  11. )
  12. # Generic FS tests that mimic probable usage patterns in applications.
  13. class TC_00_FileSystem(RegressionTestCase):
  14. @classmethod
  15. def setUpClass(c):
  16. c.FILE_SIZES = [0, 1, 2, 15, 16, 17, 255, 256, 257, 1023, 1024, 1025, 65535, 65536, 65537, 1048575, 1048576, 1048577]
  17. c.TEST_DIR = 'tmp'
  18. c.INDEXES = range(len(c.FILE_SIZES))
  19. c.INPUT_DIR = os.path.join(c.TEST_DIR, 'input')
  20. c.INPUT_FILES = [os.path.join(c.INPUT_DIR, str(x)) for x in c.FILE_SIZES]
  21. c.OUTPUT_DIR = os.path.join(c.TEST_DIR, 'output')
  22. c.OUTPUT_FILES = [os.path.join(c.OUTPUT_DIR, str(x)) for x in c.FILE_SIZES]
  23. # create directory structure and test files
  24. os.mkdir(c.TEST_DIR)
  25. os.mkdir(c.INPUT_DIR)
  26. for i in c.INDEXES:
  27. with open(c.INPUT_FILES[i], 'wb') as file:
  28. file.write(os.urandom(c.FILE_SIZES[i]))
  29. @classmethod
  30. def tearDownClass(c):
  31. shutil.rmtree(c.TEST_DIR)
  32. def setUp(self):
  33. # clean output for each test
  34. shutil.rmtree(self.OUTPUT_DIR, ignore_errors=True)
  35. os.mkdir(self.OUTPUT_DIR)
  36. # copy input file to output dir (for tests that alter the file so input remains untouched)
  37. def copy_input(self, input, output):
  38. shutil.copy(input, output)
  39. def verify_open_close(self, stdout, stderr, input_path, output_path):
  40. self.assertNotIn('ERROR: ', stderr)
  41. self.assertIn('open(' + input_path + ') input OK', stdout)
  42. self.assertIn('close(' + input_path + ') input OK', stdout)
  43. self.assertIn('open(' + input_path + ') input 1 OK', stdout)
  44. self.assertIn('open(' + input_path + ') input 2 OK', stdout)
  45. self.assertIn('close(' + input_path + ') input 1 OK', stdout)
  46. self.assertIn('close(' + input_path + ') input 2 OK', stdout)
  47. self.assertIn('fopen(' + input_path + ') input OK', stdout)
  48. self.assertIn('fclose(' + input_path + ') input OK', stdout)
  49. self.assertIn('fopen(' + input_path + ') input 1 OK', stdout)
  50. self.assertIn('fopen(' + input_path + ') input 2 OK', stdout)
  51. self.assertIn('fclose(' + input_path + ') input 1 OK', stdout)
  52. self.assertIn('fclose(' + input_path + ') input 2 OK', stdout)
  53. self.assertIn('open(' + output_path + ') output OK', stdout)
  54. self.assertIn('close(' + output_path + ') output OK', stdout)
  55. self.assertTrue(os.path.isfile(output_path))
  56. self.assertIn('open(' + output_path + ') output 1 OK', stdout)
  57. self.assertIn('open(' + output_path + ') output 2 OK', stdout)
  58. self.assertIn('close(' + output_path + ') output 1 OK', stdout)
  59. self.assertIn('close(' + output_path + ') output 2 OK', stdout)
  60. self.assertIn('fopen(' + output_path + ') output OK', stdout)
  61. self.assertIn('fclose(' + output_path + ') output OK', stdout)
  62. self.assertIn('fopen(' + output_path + ') output 1 OK', stdout)
  63. self.assertIn('fopen(' + output_path + ') output 2 OK', stdout)
  64. self.assertIn('fclose(' + output_path + ') output 1 OK', stdout)
  65. self.assertIn('fclose(' + output_path + ') output 2 OK', stdout)
  66. def test_100_open_close(self):
  67. input_path = self.INPUT_FILES[-1] # existing file
  68. output_path = os.path.join(self.OUTPUT_DIR, 'test_100') # new file to be created
  69. stdout, stderr = self.run_binary(['open_close', input_path, output_path])
  70. self.verify_open_close(stdout, stderr, input_path, output_path)
  71. def test_110_read_write(self):
  72. file_path = os.path.join(self.OUTPUT_DIR, 'test_110') # new file to be created
  73. stdout, stderr = self.run_binary(['read_write', file_path])
  74. self.assertNotIn('ERROR: ', stderr)
  75. self.assertTrue(os.path.isfile(file_path))
  76. self.assertIn('open(' + file_path + ') RW OK', stdout)
  77. self.assertIn('write(' + file_path + ') RW OK', stdout)
  78. self.assertIn('seek(' + file_path + ') RW OK', stdout)
  79. self.assertIn('read(' + file_path + ') RW OK', stdout)
  80. self.assertIn('compare(' + file_path + ') RW OK', stdout)
  81. self.assertIn('close(' + file_path + ') RW OK', stdout)
  82. def verify_seek_tell(self, stdout, stderr, input_path, output_path_1, output_path_2, size):
  83. self.assertNotIn('ERROR: ', stderr)
  84. self.assertIn('open(' + input_path + ') input OK', stdout)
  85. self.assertIn('seek(' + input_path + ') input start OK', stdout)
  86. self.assertIn('seek(' + input_path + ') input end OK', stdout)
  87. self.assertIn('tell(' + input_path + ') input end OK: ' + str(size), stdout)
  88. self.assertIn('seek(' + input_path + ') input rewind OK', stdout)
  89. self.assertIn('tell(' + input_path + ') input start OK: 0', stdout)
  90. self.assertIn('close(' + input_path + ') input OK', stdout)
  91. self.assertIn('fopen(' + input_path + ') input OK', stdout)
  92. self.assertIn('fseek(' + input_path + ') input start OK', stdout)
  93. self.assertIn('fseek(' + input_path + ') input end OK', stdout)
  94. self.assertIn('ftell(' + input_path + ') input end OK: ' + str(size), stdout)
  95. self.assertIn('fseek(' + input_path + ') input rewind OK', stdout)
  96. self.assertIn('ftell(' + input_path + ') input start OK: 0', stdout)
  97. self.assertIn('fclose(' + input_path + ') input OK', stdout)
  98. self.assertIn('open(' + output_path_1 + ') output OK', stdout)
  99. self.assertIn('seek(' + output_path_1 + ') output start OK', stdout)
  100. self.assertIn('seek(' + output_path_1 + ') output end OK', stdout)
  101. self.assertIn('tell(' + output_path_1 + ') output end OK: ' + str(size), stdout)
  102. self.assertIn('seek(' + output_path_1 + ') output end 2 OK', stdout)
  103. self.assertIn('seek(' + output_path_1 + ') output end 3 OK', stdout)
  104. self.assertIn('tell(' + output_path_1 + ') output end 2 OK: ' + str(size + 4098), stdout)
  105. self.assertIn('close(' + output_path_1 + ') output OK', stdout)
  106. self.assertIn('fopen(' + output_path_2 + ') output OK', stdout)
  107. self.assertIn('fseek(' + output_path_2 + ') output start OK', stdout)
  108. self.assertIn('fseek(' + output_path_2 + ') output end OK', stdout)
  109. self.assertIn('ftell(' + output_path_2 + ') output end OK: ' + str(size), stdout)
  110. self.assertIn('fseek(' + output_path_2 + ') output end 2 OK', stdout)
  111. self.assertIn('fseek(' + output_path_2 + ') output end 3 OK', stdout)
  112. self.assertIn('ftell(' + output_path_2 + ') output end 2 OK: ' + str(size + 4098), stdout)
  113. self.assertIn('fclose(' + output_path_2 + ') output OK', stdout)
  114. def test_115_seek_tell(self):
  115. input_path = self.INPUT_FILES[-1] # existing file
  116. output_path_1 = os.path.join(self.OUTPUT_DIR, 'test_115a') # writable files
  117. output_path_2 = os.path.join(self.OUTPUT_DIR, 'test_115b')
  118. self.copy_input(input_path, output_path_1)
  119. self.copy_input(input_path, output_path_2)
  120. stdout, stderr = self.run_binary(['seek_tell', input_path, output_path_1, output_path_2])
  121. self.verify_seek_tell(stdout, stderr, input_path, output_path_1, output_path_2, self.FILE_SIZES[-1])
  122. def test_120_file_delete(self):
  123. file_path = 'test_120'
  124. file_in = self.INPUT_FILES[-1] # existing file to be copied
  125. file_out_1 = os.path.join(self.OUTPUT_DIR, file_path + 'a')
  126. file_out_2 = os.path.join(self.OUTPUT_DIR, file_path + 'b')
  127. file_out_3 = os.path.join(self.OUTPUT_DIR, file_path + 'c')
  128. file_out_4 = os.path.join(self.OUTPUT_DIR, file_path + 'd')
  129. file_out_5 = os.path.join(self.OUTPUT_DIR, file_path + 'e')
  130. # 3 existing files, 2 new files
  131. self.copy_input(file_in, file_out_1)
  132. self.copy_input(file_in, file_out_2)
  133. self.copy_input(file_in, file_out_3)
  134. stdout, stderr = self.run_binary(['delete', file_out_1, file_out_2, file_out_3, file_out_4, file_out_5])
  135. # verify
  136. self.assertNotIn('ERROR: ', stderr)
  137. self.assertFalse(os.path.isfile(file_out_1))
  138. self.assertFalse(os.path.isfile(file_out_2))
  139. self.assertFalse(os.path.isfile(file_out_3))
  140. self.assertFalse(os.path.isfile(file_out_4))
  141. self.assertFalse(os.path.isfile(file_out_5))
  142. self.assertIn('unlink(' + file_out_1 + ') OK', stdout)
  143. self.assertIn('open(' + file_out_2 + ') input 1 OK', stdout)
  144. self.assertIn('close(' + file_out_2 + ') input 1 OK', stdout)
  145. self.assertIn('unlink(' + file_out_2 + ') input 1 OK', stdout)
  146. self.assertIn('open(' + file_out_3 + ') input 2 OK', stdout)
  147. self.assertIn('unlink(' + file_out_3 + ') input 2 OK', stdout)
  148. self.assertIn('close(' + file_out_3 + ') input 2 OK', stdout)
  149. self.assertIn('open(' + file_out_4 + ') output 1 OK', stdout)
  150. self.assertIn('close(' + file_out_4 + ') output 1 OK', stdout)
  151. self.assertIn('unlink(' + file_out_4 + ') output 1 OK', stdout)
  152. self.assertIn('open(' + file_out_5 + ') output 2 OK', stdout)
  153. self.assertIn('unlink(' + file_out_5 + ') output 2 OK', stdout)
  154. self.assertIn('close(' + file_out_5 + ') output 2 OK', stdout)
  155. def verify_stat(self, stdout, stderr, input_path, output_path, size):
  156. self.assertNotIn('ERROR: ', stderr)
  157. self.assertIn('stat(' + input_path + ') input 1 OK', stdout)
  158. self.assertIn('open(' + input_path + ') input 2 OK', stdout)
  159. self.assertIn('stat(' + input_path + ') input 2 OK: ' + size, stdout)
  160. self.assertIn('fstat(' + input_path + ') input 2 OK: ' + size, stdout)
  161. self.assertIn('close(' + input_path + ') input 2 OK', stdout)
  162. self.assertIn('stat(' + output_path + ') output 1 OK', stdout)
  163. self.assertIn('open(' + output_path + ') output 2 OK', stdout)
  164. self.assertIn('stat(' + output_path + ') output 2 OK: ' + size, stdout)
  165. self.assertIn('fstat(' + output_path + ') output 2 OK: ' + size, stdout)
  166. self.assertIn('close(' + output_path + ') output 2 OK', stdout)
  167. def test_130_file_stat(self):
  168. # running for every file separately so the process doesn't need to enumerate directory
  169. # (different code path, enumeration also performs stat)
  170. for i in self.INDEXES:
  171. input_path = self.INPUT_FILES[i] # existing file
  172. output_path = self.OUTPUT_FILES[i] # file that will be opened in write mode
  173. size = str(self.FILE_SIZES[i])
  174. self.copy_input(input_path, output_path)
  175. stdout, stderr = self.run_binary(['stat', input_path, output_path])
  176. self.verify_stat(stdout, stderr, input_path, output_path, size)
  177. def verify_size(self, file, size):
  178. self.assertEqual(os.stat(file).st_size, size)
  179. def do_truncate_test(self, size_in, size_out):
  180. # prepare paths/files
  181. i = self.FILE_SIZES.index(size_in)
  182. input = self.INPUT_FILES[i] # source file to be truncated
  183. out_1 = self.OUTPUT_FILES[i] + 'a'
  184. out_2 = self.OUTPUT_FILES[i] + 'b'
  185. self.copy_input(input, out_1)
  186. self.copy_input(input, out_2)
  187. # run test
  188. stdout, stderr = self.run_binary(['truncate', out_1, out_2, str(size_out)])
  189. self.assertNotIn('ERROR: ', stderr)
  190. self.assertIn('truncate(' + out_1 + ') to ' + str(size_out) + ' OK', stdout)
  191. self.assertIn('open(' + out_2 + ') output OK', stdout)
  192. self.assertIn('ftruncate(' + out_2 + ') to ' + str(size_out) + ' OK', stdout)
  193. self.assertIn('close(' + out_2 + ') output OK', stdout)
  194. self.verify_size(out_1, size_out)
  195. self.verify_size(out_2, size_out)
  196. def test_140_file_truncate(self):
  197. self.do_truncate_test(0, 1)
  198. self.do_truncate_test(0, 16)
  199. self.do_truncate_test(0, 65537)
  200. self.do_truncate_test(1, 0)
  201. self.do_truncate_test(1, 17)
  202. self.do_truncate_test(16, 0)
  203. self.do_truncate_test(16, 1048576)
  204. self.do_truncate_test(255, 15)
  205. self.do_truncate_test(255, 256)
  206. self.do_truncate_test(65537, 65535)
  207. self.do_truncate_test(65537, 65536)
  208. def verify_copy_content(self, input, output):
  209. self.assertTrue(filecmp.cmp(input, output, shallow=False))
  210. def verify_copy(self, stdout, stderr, input_dir, exec):
  211. self.assertNotIn('ERROR: ', stderr)
  212. self.assertIn('opendir(' + input_dir + ') OK', stdout)
  213. self.assertIn('readdir(.) OK', stdout)
  214. if input_dir[0] != '/':
  215. self.assertIn('readdir(..) OK', stdout)
  216. for i in self.INDEXES:
  217. size = str(self.FILE_SIZES[i])
  218. self.assertIn('readdir(' + size + ') OK', stdout)
  219. self.assertIn('open(' + size + ') input OK', stdout)
  220. self.assertIn('fstat(' + size + ') input OK', stdout)
  221. self.assertIn('open(' + size + ') output OK', stdout)
  222. self.assertIn('fstat(' + size + ') output 1 OK', stdout)
  223. if exec == 'copy_whole':
  224. self.assertIn('read_fd(' + size + ') input OK', stdout)
  225. self.assertIn('write_fd(' + size + ') output OK', stdout)
  226. if size != '0':
  227. if 'copy_mmap' in exec:
  228. self.assertIn('mmap_fd(' + size + ') input OK', stdout)
  229. self.assertIn('mmap_fd(' + size + ') output OK', stdout)
  230. self.assertIn('munmap_fd(' + size + ') input OK', stdout)
  231. self.assertIn('munmap_fd(' + size + ') output OK', stdout)
  232. if exec == 'copy_mmap_rev':
  233. self.assertIn('ftruncate(' + size + ') output OK', stdout)
  234. self.assertIn('fstat(' + size + ') output 2 OK', stdout)
  235. self.assertIn('close(' + size + ') input OK', stdout)
  236. self.assertIn('close(' + size + ') output OK', stdout)
  237. # compare
  238. for i in self.INDEXES:
  239. self.verify_copy_content(self.INPUT_FILES[i], self.OUTPUT_FILES[i])
  240. def do_copy_test(self, exec, timeout):
  241. stdout, stderr = self.run_binary([exec, self.INPUT_DIR, self.OUTPUT_DIR], timeout=timeout)
  242. self.verify_copy(stdout, stderr, self.INPUT_DIR, exec)
  243. def test_200_copy_dir_whole(self):
  244. self.do_copy_test('copy_whole', 30)
  245. def test_201_copy_dir_seq(self):
  246. self.do_copy_test('copy_seq', 60)
  247. def test_202_copy_dir_rev(self):
  248. self.do_copy_test('copy_rev', 60)
  249. @expectedFailureIf(HAS_SGX)
  250. def test_203_copy_dir_mmap_whole(self):
  251. self.do_copy_test('copy_mmap_whole', 30)
  252. @expectedFailureIf(HAS_SGX)
  253. def test_204_copy_dir_mmap_seq(self):
  254. self.do_copy_test('copy_mmap_seq', 60)
  255. @expectedFailureIf(HAS_SGX)
  256. def test_205_copy_dir_mmap_rev(self):
  257. self.do_copy_test('copy_mmap_rev', 60)
  258. def test_210_copy_dir_mounted(self):
  259. exec = 'copy_whole'
  260. stdout, stderr = self.run_binary([exec, '/mounted/input', '/mounted/output'], timeout=30)
  261. self.verify_copy(stdout, stderr, '/mounted/input', exec)