testlfs.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "fspr_file_io.h"
  17. #include "fspr_file_info.h"
  18. #include "fspr_errno.h"
  19. #include "fspr_general.h"
  20. #include "fspr_poll.h"
  21. #include "fspr_strings.h"
  22. #include "fspr_lib.h"
  23. #include "fspr_mmap.h"
  24. #include "testutil.h"
  25. /* Only enable these tests by default on platforms which support sparse
  26. * files... just Unixes? */
  27. #if defined(WIN32) || defined(OS2) || defined(NETWARE)
  28. static void test_nolfs(abts_case *tc, void *data)
  29. {
  30. ABTS_NOT_IMPL(tc, "Large Files tests require Sparse file support");
  31. }
  32. #elif APR_HAS_LARGE_FILES
  33. #define USE_LFS_TESTS
  34. /* Tests which create an 8Gb sparse file and then check it can be used
  35. * as normal. */
  36. static fspr_off_t eightGb = APR_INT64_C(2) << 32;
  37. static int madefile = 0;
  38. #define PRECOND if (!madefile) { ABTS_NOT_IMPL(tc, "Large file tests not enabled"); return; }
  39. #define TESTDIR "lfstests"
  40. #define TESTFILE "large.bin"
  41. #define TESTFN "lfstests/large.bin"
  42. static void test_open(abts_case *tc, void *data)
  43. {
  44. fspr_file_t *f;
  45. fspr_status_t rv;
  46. rv = fspr_dir_make(TESTDIR, APR_OS_DEFAULT, p);
  47. if (rv && !APR_STATUS_IS_EEXIST(rv)) {
  48. APR_ASSERT_SUCCESS(tc, "make test directory", rv);
  49. }
  50. APR_ASSERT_SUCCESS(tc, "open file",
  51. fspr_file_open(&f, TESTFN,
  52. APR_CREATE | APR_WRITE | APR_TRUNCATE,
  53. APR_OS_DEFAULT, p));
  54. rv = fspr_file_trunc(f, eightGb);
  55. APR_ASSERT_SUCCESS(tc, "close large file", fspr_file_close(f));
  56. /* 8Gb may pass rlimits or filesystem limits */
  57. if (APR_STATUS_IS_EINVAL(rv)
  58. #ifdef EFBIG
  59. || rv == EFBIG
  60. #endif
  61. ) {
  62. ABTS_NOT_IMPL(tc, "Creation of large file (limited by rlimit or fs?)");
  63. }
  64. else {
  65. APR_ASSERT_SUCCESS(tc, "truncate file to 8gb", rv);
  66. }
  67. madefile = rv == APR_SUCCESS;
  68. }
  69. static void test_reopen(abts_case *tc, void *data)
  70. {
  71. fspr_file_t *fh;
  72. fspr_finfo_t finfo;
  73. PRECOND;
  74. APR_ASSERT_SUCCESS(tc, "re-open 8Gb file",
  75. fspr_file_open(&fh, TESTFN, APR_READ, APR_OS_DEFAULT, p));
  76. APR_ASSERT_SUCCESS(tc, "file_info_get failed",
  77. fspr_file_info_get(&finfo, APR_FINFO_NORM, fh));
  78. ABTS_ASSERT(tc, "file_info_get gave incorrect size",
  79. finfo.size == eightGb);
  80. APR_ASSERT_SUCCESS(tc, "re-close large file", fspr_file_close(fh));
  81. }
  82. static void test_stat(abts_case *tc, void *data)
  83. {
  84. fspr_finfo_t finfo;
  85. PRECOND;
  86. APR_ASSERT_SUCCESS(tc, "stat large file",
  87. fspr_stat(&finfo, TESTFN, APR_FINFO_NORM, p));
  88. ABTS_ASSERT(tc, "stat gave incorrect size", finfo.size == eightGb);
  89. }
  90. static void test_readdir(abts_case *tc, void *data)
  91. {
  92. fspr_dir_t *dh;
  93. fspr_status_t rv;
  94. PRECOND;
  95. APR_ASSERT_SUCCESS(tc, "open test directory",
  96. fspr_dir_open(&dh, TESTDIR, p));
  97. do {
  98. fspr_finfo_t finfo;
  99. rv = fspr_dir_read(&finfo, APR_FINFO_NORM, dh);
  100. if (rv == APR_SUCCESS && strcmp(finfo.name, TESTFILE) == 0) {
  101. ABTS_ASSERT(tc, "fspr_dir_read gave incorrect size for large file",
  102. finfo.size == eightGb);
  103. }
  104. } while (rv == APR_SUCCESS);
  105. if (!APR_STATUS_IS_ENOENT(rv)) {
  106. APR_ASSERT_SUCCESS(tc, "fspr_dir_read failed", rv);
  107. }
  108. APR_ASSERT_SUCCESS(tc, "close test directory",
  109. fspr_dir_close(dh));
  110. }
  111. #define TESTSTR "Hello, world."
  112. static void test_append(abts_case *tc, void *data)
  113. {
  114. fspr_file_t *fh;
  115. fspr_finfo_t finfo;
  116. PRECOND;
  117. APR_ASSERT_SUCCESS(tc, "open 8Gb file for append",
  118. fspr_file_open(&fh, TESTFN, APR_WRITE | APR_APPEND,
  119. APR_OS_DEFAULT, p));
  120. APR_ASSERT_SUCCESS(tc, "append to 8Gb file",
  121. fspr_file_write_full(fh, TESTSTR, strlen(TESTSTR), NULL));
  122. APR_ASSERT_SUCCESS(tc, "file_info_get failed",
  123. fspr_file_info_get(&finfo, APR_FINFO_NORM, fh));
  124. ABTS_ASSERT(tc, "file_info_get gave incorrect size",
  125. finfo.size == eightGb + strlen(TESTSTR));
  126. APR_ASSERT_SUCCESS(tc, "close 8Gb file", fspr_file_close(fh));
  127. }
  128. static void test_seek(abts_case *tc, void *data)
  129. {
  130. fspr_file_t *fh;
  131. fspr_off_t pos;
  132. PRECOND;
  133. APR_ASSERT_SUCCESS(tc, "open 8Gb file for writing",
  134. fspr_file_open(&fh, TESTFN, APR_WRITE,
  135. APR_OS_DEFAULT, p));
  136. pos = 0;
  137. APR_ASSERT_SUCCESS(tc, "relative seek to end",
  138. fspr_file_seek(fh, APR_END, &pos));
  139. ABTS_ASSERT(tc, "seek to END gave 8Gb", pos == eightGb);
  140. pos = eightGb;
  141. APR_ASSERT_SUCCESS(tc, "seek to 8Gb", fspr_file_seek(fh, APR_SET, &pos));
  142. ABTS_ASSERT(tc, "seek gave 8Gb offset", pos == eightGb);
  143. pos = 0;
  144. APR_ASSERT_SUCCESS(tc, "relative seek to 0", fspr_file_seek(fh, APR_CUR, &pos));
  145. ABTS_ASSERT(tc, "relative seek gave 8Gb offset", pos == eightGb);
  146. fspr_file_close(fh);
  147. }
  148. static void test_write(abts_case *tc, void *data)
  149. {
  150. fspr_file_t *fh;
  151. fspr_off_t pos = eightGb - 4;
  152. PRECOND;
  153. APR_ASSERT_SUCCESS(tc, "re-open 8Gb file",
  154. fspr_file_open(&fh, TESTFN, APR_WRITE, APR_OS_DEFAULT, p));
  155. APR_ASSERT_SUCCESS(tc, "seek to 8Gb - 4",
  156. fspr_file_seek(fh, APR_SET, &pos));
  157. ABTS_ASSERT(tc, "seek gave 8Gb-4 offset", pos == eightGb - 4);
  158. APR_ASSERT_SUCCESS(tc, "write magic string to 8Gb-4",
  159. fspr_file_write_full(fh, "FISH", 4, NULL));
  160. APR_ASSERT_SUCCESS(tc, "close 8Gb file", fspr_file_close(fh));
  161. }
  162. #if APR_HAS_MMAP
  163. static void test_mmap(abts_case *tc, void *data)
  164. {
  165. fspr_mmap_t *map;
  166. fspr_file_t *fh;
  167. fspr_size_t len = 16384; /* hopefully a multiple of the page size */
  168. fspr_off_t off = eightGb - len;
  169. void *ptr;
  170. PRECOND;
  171. APR_ASSERT_SUCCESS(tc, "open 8gb file for mmap",
  172. fspr_file_open(&fh, TESTFN, APR_READ, APR_OS_DEFAULT, p));
  173. APR_ASSERT_SUCCESS(tc, "mmap 8Gb file",
  174. fspr_mmap_create(&map, fh, off, len, APR_MMAP_READ, p));
  175. APR_ASSERT_SUCCESS(tc, "close file", fspr_file_close(fh));
  176. ABTS_ASSERT(tc, "mapped a 16K block", map->size == len);
  177. APR_ASSERT_SUCCESS(tc, "get pointer into mmaped region",
  178. fspr_mmap_offset(&ptr, map, len - 4));
  179. ABTS_ASSERT(tc, "pointer was not NULL", ptr != NULL);
  180. ABTS_ASSERT(tc, "found the magic string", memcmp(ptr, "FISH", 4) == 0);
  181. APR_ASSERT_SUCCESS(tc, "delete mmap handle", fspr_mmap_delete(map));
  182. }
  183. #endif /* APR_HAS_MMAP */
  184. static void test_format(abts_case *tc, void *data)
  185. {
  186. fspr_off_t off;
  187. PRECOND;
  188. off = fspr_atoi64(fspr_off_t_toa(p, eightGb));
  189. ABTS_ASSERT(tc, "fspr_atoi64 parsed fspr_off_t_toa result incorrectly",
  190. off == eightGb);
  191. }
  192. #else
  193. static void test_nolfs(abts_case *tc, void *data)
  194. {
  195. ABTS_NOT_IMPL(tc, "Large Files not supported");
  196. }
  197. #endif
  198. abts_suite *testlfs(abts_suite *suite)
  199. {
  200. suite = ADD_SUITE(suite)
  201. #ifdef USE_LFS_TESTS
  202. abts_run_test(suite, test_open, NULL);
  203. abts_run_test(suite, test_reopen, NULL);
  204. abts_run_test(suite, test_stat, NULL);
  205. abts_run_test(suite, test_readdir, NULL);
  206. abts_run_test(suite, test_seek, NULL);
  207. abts_run_test(suite, test_append, NULL);
  208. abts_run_test(suite, test_write, NULL);
  209. #if APR_HAS_MMAP
  210. abts_run_test(suite, test_mmap, NULL);
  211. #endif
  212. abts_run_test(suite, test_format, NULL);
  213. #else
  214. abts_run_test(suite, test_nolfs, NULL);
  215. #endif
  216. return suite;
  217. }