testbuckets.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
  2. * applicable.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * 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 "abts.h"
  17. #include "testutil.h"
  18. #include "apr_buckets.h"
  19. #include "apr_strings.h"
  20. static void test_create(abts_case *tc, void *data)
  21. {
  22. apr_bucket_alloc_t *ba;
  23. apr_bucket_brigade *bb;
  24. ba = apr_bucket_alloc_create(p);
  25. bb = apr_brigade_create(p, ba);
  26. ABTS_ASSERT(tc, "new brigade not NULL", bb != NULL);
  27. ABTS_ASSERT(tc, "new brigade is empty", APR_BRIGADE_EMPTY(bb));
  28. apr_brigade_destroy(bb);
  29. apr_bucket_alloc_destroy(ba);
  30. }
  31. static void test_simple(abts_case *tc, void *data)
  32. {
  33. apr_bucket_alloc_t *ba;
  34. apr_bucket_brigade *bb;
  35. apr_bucket *fb, *tb;
  36. ba = apr_bucket_alloc_create(p);
  37. bb = apr_brigade_create(p, ba);
  38. fb = APR_BRIGADE_FIRST(bb);
  39. ABTS_ASSERT(tc, "first bucket of empty brigade is sentinel",
  40. fb == APR_BRIGADE_SENTINEL(bb));
  41. fb = apr_bucket_flush_create(ba);
  42. APR_BRIGADE_INSERT_HEAD(bb, fb);
  43. ABTS_ASSERT(tc, "first bucket of brigade is flush",
  44. APR_BRIGADE_FIRST(bb) == fb);
  45. ABTS_ASSERT(tc, "bucket after flush is sentinel",
  46. APR_BUCKET_NEXT(fb) == APR_BRIGADE_SENTINEL(bb));
  47. tb = apr_bucket_transient_create("aaa", 3, ba);
  48. APR_BUCKET_INSERT_BEFORE(fb, tb);
  49. ABTS_ASSERT(tc, "bucket before flush now transient",
  50. APR_BUCKET_PREV(fb) == tb);
  51. ABTS_ASSERT(tc, "bucket after transient is flush",
  52. APR_BUCKET_NEXT(tb) == fb);
  53. ABTS_ASSERT(tc, "bucket before transient is sentinel",
  54. APR_BUCKET_PREV(tb) == APR_BRIGADE_SENTINEL(bb));
  55. apr_brigade_cleanup(bb);
  56. ABTS_ASSERT(tc, "cleaned up brigade was empty", APR_BRIGADE_EMPTY(bb));
  57. apr_brigade_destroy(bb);
  58. apr_bucket_alloc_destroy(ba);
  59. }
  60. static apr_bucket_brigade *make_simple_brigade(apr_bucket_alloc_t *ba,
  61. const char *first,
  62. const char *second)
  63. {
  64. apr_bucket_brigade *bb = apr_brigade_create(p, ba);
  65. apr_bucket *e;
  66. e = apr_bucket_transient_create(first, strlen(first), ba);
  67. APR_BRIGADE_INSERT_TAIL(bb, e);
  68. e = apr_bucket_transient_create(second, strlen(second), ba);
  69. APR_BRIGADE_INSERT_TAIL(bb, e);
  70. return bb;
  71. }
  72. /* tests that 'bb' flattens to string 'expect'. */
  73. static void flatten_match(abts_case *tc, const char *ctx,
  74. apr_bucket_brigade *bb,
  75. const char *expect)
  76. {
  77. apr_size_t elen = strlen(expect);
  78. char *buf = malloc(elen);
  79. apr_size_t len = elen;
  80. char msg[200];
  81. sprintf(msg, "%s: flatten brigade", ctx);
  82. apr_assert_success(tc, msg, apr_brigade_flatten(bb, buf, &len));
  83. sprintf(msg, "%s: length match (%ld not %ld)", ctx,
  84. (long)len, (long)elen);
  85. ABTS_ASSERT(tc, msg, len == elen);
  86. sprintf(msg, "%s: result match", msg);
  87. ABTS_STR_NEQUAL(tc, expect, buf, len);
  88. free(buf);
  89. }
  90. static void test_flatten(abts_case *tc, void *data)
  91. {
  92. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  93. apr_bucket_brigade *bb;
  94. bb = make_simple_brigade(ba, "hello, ", "world");
  95. flatten_match(tc, "flatten brigade", bb, "hello, world");
  96. apr_brigade_destroy(bb);
  97. apr_bucket_alloc_destroy(ba);
  98. }
  99. static int count_buckets(apr_bucket_brigade *bb)
  100. {
  101. apr_bucket *e;
  102. int count = 0;
  103. for (e = APR_BRIGADE_FIRST(bb);
  104. e != APR_BRIGADE_SENTINEL(bb);
  105. e = APR_BUCKET_NEXT(e)) {
  106. count++;
  107. }
  108. return count;
  109. }
  110. static void test_split(abts_case *tc, void *data)
  111. {
  112. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  113. apr_bucket_brigade *bb, *bb2;
  114. apr_bucket *e;
  115. bb = make_simple_brigade(ba, "hello, ", "world");
  116. /* split at the "world" bucket */
  117. e = APR_BRIGADE_LAST(bb);
  118. bb2 = apr_brigade_split(bb, e);
  119. ABTS_ASSERT(tc, "split brigade contains one bucket",
  120. count_buckets(bb2) == 1);
  121. ABTS_ASSERT(tc, "original brigade contains one bucket",
  122. count_buckets(bb) == 1);
  123. flatten_match(tc, "match original brigade", bb, "hello, ");
  124. flatten_match(tc, "match split brigade", bb2, "world");
  125. apr_brigade_destroy(bb2);
  126. apr_brigade_destroy(bb);
  127. apr_bucket_alloc_destroy(ba);
  128. }
  129. #define COUNT 3000
  130. #define THESTR "hello"
  131. static void test_bwrite(abts_case *tc, void *data)
  132. {
  133. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  134. apr_bucket_brigade *bb = apr_brigade_create(p, ba);
  135. apr_off_t length;
  136. int n;
  137. for (n = 0; n < COUNT; n++) {
  138. apr_assert_success(tc, "brigade_write",
  139. apr_brigade_write(bb, NULL, NULL,
  140. THESTR, sizeof THESTR));
  141. }
  142. apr_assert_success(tc, "determine brigade length",
  143. apr_brigade_length(bb, 1, &length));
  144. ABTS_ASSERT(tc, "brigade has correct length",
  145. length == (COUNT * sizeof THESTR));
  146. apr_brigade_destroy(bb);
  147. apr_bucket_alloc_destroy(ba);
  148. }
  149. static void test_splitline(abts_case *tc, void *data)
  150. {
  151. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  152. apr_bucket_brigade *bin, *bout;
  153. bin = make_simple_brigade(ba, "blah blah blah-",
  154. "end of line.\nfoo foo foo");
  155. bout = apr_brigade_create(p, ba);
  156. apr_assert_success(tc, "split line",
  157. apr_brigade_split_line(bout, bin,
  158. APR_BLOCK_READ, 100));
  159. flatten_match(tc, "split line", bout, "blah blah blah-end of line.\n");
  160. flatten_match(tc, "remainder", bin, "foo foo foo");
  161. apr_brigade_destroy(bout);
  162. apr_brigade_destroy(bin);
  163. apr_bucket_alloc_destroy(ba);
  164. }
  165. /* Test that bucket E has content EDATA of length ELEN. */
  166. static void test_bucket_content(abts_case *tc,
  167. apr_bucket *e,
  168. const char *edata,
  169. apr_size_t elen)
  170. {
  171. const char *adata;
  172. apr_size_t alen;
  173. apr_assert_success(tc, "read from bucket",
  174. apr_bucket_read(e, &adata, &alen,
  175. APR_BLOCK_READ));
  176. ABTS_ASSERT(tc, "read expected length", alen == elen);
  177. ABTS_STR_NEQUAL(tc, edata, adata, elen);
  178. }
  179. static void test_splits(abts_case *tc, void *ctx)
  180. {
  181. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  182. apr_bucket_brigade *bb;
  183. apr_bucket *e;
  184. char *str = "alphabeta";
  185. int n;
  186. bb = apr_brigade_create(p, ba);
  187. APR_BRIGADE_INSERT_TAIL(bb,
  188. apr_bucket_immortal_create(str, 9, ba));
  189. APR_BRIGADE_INSERT_TAIL(bb,
  190. apr_bucket_transient_create(str, 9, ba));
  191. APR_BRIGADE_INSERT_TAIL(bb,
  192. apr_bucket_heap_create(strdup(str), 9, free, ba));
  193. APR_BRIGADE_INSERT_TAIL(bb,
  194. apr_bucket_pool_create(apr_pstrdup(p, str), 9, p,
  195. ba));
  196. ABTS_ASSERT(tc, "four buckets inserted", count_buckets(bb) == 4);
  197. /* now split each of the buckets after byte 5 */
  198. for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
  199. ABTS_ASSERT(tc, "reached end of brigade",
  200. e != APR_BRIGADE_SENTINEL(bb));
  201. ABTS_ASSERT(tc, "split bucket OK",
  202. apr_bucket_split(e, 5) == APR_SUCCESS);
  203. e = APR_BUCKET_NEXT(e);
  204. ABTS_ASSERT(tc, "split OK", e != APR_BRIGADE_SENTINEL(bb));
  205. e = APR_BUCKET_NEXT(e);
  206. }
  207. ABTS_ASSERT(tc, "four buckets split into eight",
  208. count_buckets(bb) == 8);
  209. for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
  210. const char *data;
  211. apr_size_t len;
  212. apr_assert_success(tc, "read alpha from bucket",
  213. apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
  214. ABTS_ASSERT(tc, "read 5 bytes", len == 5);
  215. ABTS_STR_NEQUAL(tc, "alpha", data, 5);
  216. e = APR_BUCKET_NEXT(e);
  217. apr_assert_success(tc, "read beta from bucket",
  218. apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
  219. ABTS_ASSERT(tc, "read 4 bytes", len == 4);
  220. ABTS_STR_NEQUAL(tc, "beta", data, 5);
  221. e = APR_BUCKET_NEXT(e);
  222. }
  223. /* now delete the "alpha" buckets */
  224. for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
  225. apr_bucket *f;
  226. ABTS_ASSERT(tc, "reached end of brigade",
  227. e != APR_BRIGADE_SENTINEL(bb));
  228. f = APR_BUCKET_NEXT(e);
  229. apr_bucket_delete(e);
  230. e = APR_BUCKET_NEXT(f);
  231. }
  232. ABTS_ASSERT(tc, "eight buckets reduced to four",
  233. count_buckets(bb) == 4);
  234. flatten_match(tc, "flatten beta brigade", bb,
  235. "beta" "beta" "beta" "beta");
  236. apr_brigade_destroy(bb);
  237. apr_bucket_alloc_destroy(ba);
  238. }
  239. #define TIF_FNAME "testfile.txt"
  240. static void test_insertfile(abts_case *tc, void *ctx)
  241. {
  242. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  243. apr_bucket_brigade *bb;
  244. const apr_off_t bignum = (APR_INT64_C(2) << 32) + 424242;
  245. apr_off_t count;
  246. apr_file_t *f;
  247. apr_bucket *e;
  248. ABTS_ASSERT(tc, "open test file",
  249. apr_file_open(&f, TIF_FNAME,
  250. APR_WRITE|APR_TRUNCATE|APR_CREATE,
  251. APR_OS_DEFAULT, p) == APR_SUCCESS);
  252. if (apr_file_trunc(f, bignum)) {
  253. apr_file_close(f);
  254. apr_file_remove(TIF_FNAME, p);
  255. ABTS_NOT_IMPL(tc, "Skipped: could not create large file");
  256. return;
  257. }
  258. bb = apr_brigade_create(p, ba);
  259. e = apr_brigade_insert_file(bb, f, 0, bignum, p);
  260. ABTS_ASSERT(tc, "inserted file was not at end of brigade",
  261. e == APR_BRIGADE_LAST(bb));
  262. /* check that the total size of inserted buckets is equal to the
  263. * total size of the file. */
  264. count = 0;
  265. for (e = APR_BRIGADE_FIRST(bb);
  266. e != APR_BRIGADE_SENTINEL(bb);
  267. e = APR_BUCKET_NEXT(e)) {
  268. ABTS_ASSERT(tc, "bucket size sane", e->length != (apr_size_t)-1);
  269. count += e->length;
  270. }
  271. ABTS_ASSERT(tc, "total size of buckets incorrect", count == bignum);
  272. apr_brigade_destroy(bb);
  273. /* Truncate the file to zero size before close() so that we don't
  274. * actually write out the large file if we are on a non-sparse file
  275. * system - like Mac OS X's HFS. Otherwise, pity the poor user who
  276. * has to wait for the 8GB file to be written to disk.
  277. */
  278. apr_file_trunc(f, 0);
  279. apr_file_close(f);
  280. apr_bucket_alloc_destroy(ba);
  281. apr_file_remove(TIF_FNAME, p);
  282. }
  283. /* Make a test file named FNAME, and write CONTENTS to it. */
  284. static apr_file_t *make_test_file(abts_case *tc, const char *fname,
  285. const char *contents)
  286. {
  287. apr_file_t *f;
  288. ABTS_ASSERT(tc, "create test file",
  289. apr_file_open(&f, fname,
  290. APR_READ|APR_WRITE|APR_TRUNCATE|APR_CREATE,
  291. APR_OS_DEFAULT, p) == APR_SUCCESS);
  292. ABTS_ASSERT(tc, "write test file contents",
  293. apr_file_puts(contents, f) == APR_SUCCESS);
  294. return f;
  295. }
  296. static void test_manyfile(abts_case *tc, void *data)
  297. {
  298. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  299. apr_bucket_brigade *bb = apr_brigade_create(p, ba);
  300. apr_file_t *f;
  301. f = make_test_file(tc, "manyfile.bin",
  302. "world" "hello" "brave" " ,\n");
  303. apr_brigade_insert_file(bb, f, 5, 5, p);
  304. apr_brigade_insert_file(bb, f, 16, 1, p);
  305. apr_brigade_insert_file(bb, f, 15, 1, p);
  306. apr_brigade_insert_file(bb, f, 10, 5, p);
  307. apr_brigade_insert_file(bb, f, 15, 1, p);
  308. apr_brigade_insert_file(bb, f, 0, 5, p);
  309. apr_brigade_insert_file(bb, f, 17, 1, p);
  310. /* can you tell what it is yet? */
  311. flatten_match(tc, "file seek test", bb,
  312. "hello, brave world\n");
  313. apr_file_close(f);
  314. apr_brigade_destroy(bb);
  315. apr_bucket_alloc_destroy(ba);
  316. }
  317. /* Regression test for PR 34708, where a file bucket will keep
  318. * duplicating itself on being read() when EOF is reached
  319. * prematurely. */
  320. static void test_truncfile(abts_case *tc, void *data)
  321. {
  322. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  323. apr_bucket_brigade *bb = apr_brigade_create(p, ba);
  324. apr_file_t *f = make_test_file(tc, "testfile.txt", "hello");
  325. apr_bucket *e;
  326. const char *buf;
  327. apr_size_t len;
  328. apr_brigade_insert_file(bb, f, 0, 5, p);
  329. apr_file_trunc(f, 0);
  330. e = APR_BRIGADE_FIRST(bb);
  331. ABTS_ASSERT(tc, "single bucket in brigade",
  332. APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
  333. apr_bucket_file_enable_mmap(e, 0);
  334. ABTS_ASSERT(tc, "read gave APR_EOF",
  335. apr_bucket_read(e, &buf, &len, APR_BLOCK_READ) == APR_EOF);
  336. ABTS_ASSERT(tc, "read length 0", len == 0);
  337. ABTS_ASSERT(tc, "still a single bucket in brigade",
  338. APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
  339. apr_file_close(f);
  340. apr_brigade_destroy(bb);
  341. apr_bucket_alloc_destroy(ba);
  342. }
  343. static const char hello[] = "hello, world";
  344. static void test_partition(abts_case *tc, void *data)
  345. {
  346. apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
  347. apr_bucket_brigade *bb = apr_brigade_create(p, ba);
  348. apr_bucket *e;
  349. e = apr_bucket_immortal_create(hello, strlen(hello), ba);
  350. APR_BRIGADE_INSERT_HEAD(bb, e);
  351. apr_assert_success(tc, "partition brigade",
  352. apr_brigade_partition(bb, 5, &e));
  353. test_bucket_content(tc, APR_BRIGADE_FIRST(bb),
  354. "hello", 5);
  355. test_bucket_content(tc, APR_BRIGADE_LAST(bb),
  356. ", world", 7);
  357. ABTS_ASSERT(tc, "partition returns APR_INCOMPLETE",
  358. apr_brigade_partition(bb, 8192, &e));
  359. ABTS_ASSERT(tc, "APR_INCOMPLETE partition returned sentinel",
  360. e == APR_BRIGADE_SENTINEL(bb));
  361. apr_brigade_destroy(bb);
  362. apr_bucket_alloc_destroy(ba);
  363. }
  364. abts_suite *testbuckets(abts_suite *suite)
  365. {
  366. suite = ADD_SUITE(suite);
  367. abts_run_test(suite, test_create, NULL);
  368. abts_run_test(suite, test_simple, NULL);
  369. abts_run_test(suite, test_flatten, NULL);
  370. abts_run_test(suite, test_split, NULL);
  371. abts_run_test(suite, test_bwrite, NULL);
  372. abts_run_test(suite, test_splitline, NULL);
  373. abts_run_test(suite, test_splits, NULL);
  374. abts_run_test(suite, test_insertfile, NULL);
  375. abts_run_test(suite, test_manyfile, NULL);
  376. abts_run_test(suite, test_truncfile, NULL);
  377. abts_run_test(suite, test_partition, NULL);
  378. return suite;
  379. }