1 /*
2  * spillbuf-test.c : test the spill buffer code
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23 
24 #include "svn_types.h"
25 
26 #include "private/svn_subr_private.h"
27 
28 #include "../svn_test.h"
29 
30 
31 static const char basic_data[] = "abcdefghijklmnopqrstuvwxyz"
32                                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
33                                  "0123456789";
34 
35 
36 /* Validate that BUF is STARTING_SIZE in length. Then read some data from
37    the buffer, which should match EXPECTED. The EXPECTED value must be
38    NUL-terminated, but the NUL is not part of the expected/verified value.  */
39 #define CHECK_READ(b, s, e, p) SVN_ERR(check_read(b, s, e, p))
40 static svn_error_t *
check_read(svn_spillbuf_t * buf,svn_filesize_t starting_size,const char * expected,apr_pool_t * scratch_pool)41 check_read(svn_spillbuf_t *buf,
42            svn_filesize_t starting_size,
43            const char *expected,
44            apr_pool_t *scratch_pool)
45 {
46   apr_size_t expected_len = strlen(expected);
47   const char *readptr;
48   apr_size_t readlen;
49 
50   SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == starting_size);
51   SVN_ERR(svn_spillbuf__read(&readptr, &readlen, buf, scratch_pool));
52   SVN_TEST_ASSERT(readptr != NULL
53                   && readlen == expected_len
54                   && memcmp(readptr, expected, expected_len) == 0);
55   return SVN_NO_ERROR;
56 }
57 
58 
59 static svn_error_t *
test_spillbuf__basic(apr_pool_t * pool,apr_size_t len,svn_spillbuf_t * buf)60 test_spillbuf__basic(apr_pool_t *pool, apr_size_t len, svn_spillbuf_t *buf)
61 {
62   int i;
63   const char *readptr;
64   apr_size_t readlen;
65 
66   /* It starts empty.  */
67   SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 0);
68 
69   /* Place enough data into the buffer to cause a spill to disk.  */
70   for (i = 20; i--; )
71     SVN_ERR(svn_spillbuf__write(buf, basic_data, len, pool));
72 
73   /* And now has content.  */
74   SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) > 0);
75 
76   /* Verify that we can read 20 copies of basic_data from the buffer.  */
77   for (i = 20; i--; )
78     CHECK_READ(buf, (i + 1) * len, basic_data, pool);
79 
80   /* And after precisely 20 reads, it should be empty.  */
81   SVN_ERR(svn_spillbuf__read(&readptr, &readlen, buf, pool));
82   SVN_TEST_ASSERT(readptr == NULL);
83   SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 0);
84 
85   return SVN_NO_ERROR;
86 }
87 
88 static svn_error_t *
test_spillbuf_basic(apr_pool_t * pool)89 test_spillbuf_basic(apr_pool_t *pool)
90 {
91   apr_size_t len = strlen(basic_data);  /* Don't include basic_data's NUL  */
92   svn_spillbuf_t *buf = svn_spillbuf__create(len, 10 * len, pool);
93   return test_spillbuf__basic(pool, len, buf);
94 }
95 
96 static svn_error_t *
test_spillbuf_basic_spill_all(apr_pool_t * pool)97 test_spillbuf_basic_spill_all(apr_pool_t *pool)
98 {
99   apr_size_t len = strlen(basic_data);  /* Don't include basic_data's NUL  */
100   svn_spillbuf_t *buf =
101     svn_spillbuf__create_extended(len, 10 * len, TRUE, TRUE, NULL, pool);
102   return test_spillbuf__basic(pool, len, buf);
103 }
104 
105 static svn_error_t *
read_callback(svn_boolean_t * stop,void * baton,const char * data,apr_size_t len,apr_pool_t * scratch_pool)106 read_callback(svn_boolean_t *stop,
107               void *baton,
108               const char *data,
109               apr_size_t len,
110               apr_pool_t *scratch_pool)
111 {
112   int *counter = baton;
113 
114   SVN_TEST_ASSERT(len == sizeof(basic_data));
115   SVN_TEST_ASSERT(memcmp(data, basic_data, len) == 0);
116 
117   *stop = (++*counter == 10);
118 
119   return SVN_NO_ERROR;
120 }
121 
122 
123 static svn_error_t *
test_spillbuf__callback(apr_pool_t * pool,svn_spillbuf_t * buf)124 test_spillbuf__callback(apr_pool_t *pool, svn_spillbuf_t *buf)
125 {
126   int i;
127   int counter;
128   svn_boolean_t exhausted;
129 
130   /* Place enough data into the buffer to cause a spill to disk.  */
131   for (i = 20; i--; )
132     SVN_ERR(svn_spillbuf__write(buf, basic_data, sizeof(basic_data), pool));
133 
134   counter = 0;
135   SVN_ERR(svn_spillbuf__process(&exhausted, buf, read_callback, &counter,
136                                 pool));
137   SVN_TEST_ASSERT(!exhausted);
138 
139   SVN_ERR(svn_spillbuf__process(&exhausted, buf, read_callback, &counter,
140                                 pool));
141   SVN_TEST_ASSERT(exhausted);
142 
143   return SVN_NO_ERROR;
144 }
145 
146 static svn_error_t *
test_spillbuf_callback(apr_pool_t * pool)147 test_spillbuf_callback(apr_pool_t *pool)
148 {
149   svn_spillbuf_t *buf = svn_spillbuf__create(
150                           sizeof(basic_data) /* blocksize */,
151                           10 * sizeof(basic_data) /* maxsize */,
152                           pool);
153   return test_spillbuf__callback(pool, buf);
154 }
155 
156 static svn_error_t *
test_spillbuf_callback_spill_all(apr_pool_t * pool)157 test_spillbuf_callback_spill_all(apr_pool_t *pool)
158 {
159   svn_spillbuf_t *buf = svn_spillbuf__create_extended(
160                           sizeof(basic_data) /* blocksize */,
161                           10 * sizeof(basic_data) /* maxsize */,
162                           TRUE /* delte on close */,
163                           TRUE /* spill all data */,
164                           NULL, pool);
165   return test_spillbuf__callback(pool, buf);
166 }
167 
168 static svn_error_t *
test_spillbuf__file(apr_pool_t * pool,apr_size_t altsize,svn_spillbuf_t * buf)169 test_spillbuf__file(apr_pool_t *pool, apr_size_t altsize, svn_spillbuf_t *buf)
170 {
171   int i;
172   const char *readptr;
173   apr_size_t readlen;
174   apr_size_t cur_index;
175 
176   /* Place enough data into the buffer to cause a spill to disk. Note that
177      we are writing data that is *smaller* than the blocksize.  */
178   for (i = 7; i--; )
179     SVN_ERR(svn_spillbuf__write(buf, basic_data, sizeof(basic_data), pool));
180 
181   /* The first two reads will be in-memory blocks (the third write causes
182      the spill to disk). The spillbuf will pack the content into BLOCKSIZE
183      blocks. The second/last memory block will (thus) be a bit smaller.  */
184   SVN_ERR(svn_spillbuf__read(&readptr, &readlen, buf, pool));
185   SVN_TEST_ASSERT(readptr != NULL);
186   SVN_TEST_ASSERT(readlen == altsize);
187   SVN_ERR(svn_spillbuf__read(&readptr, &readlen, buf, pool));
188   SVN_TEST_ASSERT(readptr != NULL);
189   /* The second write put sizeof(basic_data) into the buffer. A small
190      portion was stored at the end of the memblock holding the first write.
191      Thus, the size of this read will be the written data, minus that
192      slice written to the first block.  */
193   SVN_TEST_ASSERT(readlen
194                   == sizeof(basic_data) - (altsize - sizeof(basic_data)));
195 
196   /* Current index into basic_data[] that we compare against.  */
197   cur_index = 0;
198 
199   while (TRUE)
200     {
201       /* This will read more bytes (from the spill file into a temporary
202          in-memory block) than the blocks of data that we wrote. This makes
203          it trickier to verify that the right data is being returned.  */
204       SVN_ERR(svn_spillbuf__read(&readptr, &readlen, buf, pool));
205       if (readptr == NULL)
206         break;
207 
208       while (TRUE)
209         {
210           apr_size_t amt;
211 
212           /* Compute the slice of basic_data that we will compare against,
213              given the readlen and cur_index.  */
214           if (cur_index + readlen >= sizeof(basic_data))
215             amt = sizeof(basic_data) - cur_index;
216           else
217             amt = readlen;
218           SVN_TEST_ASSERT(memcmp(readptr, &basic_data[cur_index], amt) == 0);
219           if ((cur_index += amt) == sizeof(basic_data))
220             cur_index = 0;
221           if ((readlen -= amt) == 0)
222             break;
223           readptr += amt;
224         }
225     }
226 
227   SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 0);
228 
229   return SVN_NO_ERROR;
230 }
231 
232 static svn_error_t *
test_spillbuf_file(apr_pool_t * pool)233 test_spillbuf_file(apr_pool_t *pool)
234 {
235   apr_size_t altsize = sizeof(basic_data) + 2;
236   svn_spillbuf_t *buf = svn_spillbuf__create(
237                           altsize /* blocksize */,
238                           2 * sizeof(basic_data) /* maxsize */,
239                           pool);
240   return test_spillbuf__file(pool, altsize, buf);
241 }
242 
243 static svn_error_t *
test_spillbuf_file_spill_all(apr_pool_t * pool)244 test_spillbuf_file_spill_all(apr_pool_t *pool)
245 {
246   apr_size_t altsize = sizeof(basic_data) + 2;
247   svn_spillbuf_t *buf = svn_spillbuf__create_extended(
248                           altsize /* blocksize */,
249                           2 * sizeof(basic_data)  /* maxsize */,
250                           TRUE /* delte on close */,
251                           TRUE /* spill all data */,
252                           NULL, pool);
253   return test_spillbuf__file(pool, altsize, buf);
254 }
255 
256 static svn_error_t *
test_spillbuf__interleaving(apr_pool_t * pool,svn_spillbuf_t * buf)257 test_spillbuf__interleaving(apr_pool_t *pool, svn_spillbuf_t* buf)
258 {
259   SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
260   SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
261   /* now: two blocks: 8 and 4 bytes  */
262 
263   CHECK_READ(buf, 12, "abcdefgh", pool);
264   /* now: one block: 4 bytes  */
265 
266   SVN_ERR(svn_spillbuf__write(buf, "mnopqr", 6, pool));
267   /* now: two blocks: 8 and 2 bytes  */
268 
269   CHECK_READ(buf, 10, "ijklmnop", pool);
270   /* now: one block: 2 bytes  */
271 
272   SVN_ERR(svn_spillbuf__write(buf, "stuvwx", 6, pool));
273   SVN_ERR(svn_spillbuf__write(buf, "ABCDEF", 6, pool));
274   SVN_ERR(svn_spillbuf__write(buf, "GHIJKL", 6, pool));
275   /* now: two blocks: 8 and 6 bytes, and 6 bytes spilled to a file  */
276 
277   CHECK_READ(buf, 20, "qrstuvwx", pool);
278   CHECK_READ(buf, 12, "ABCDEF", pool);
279   CHECK_READ(buf, 6, "GHIJKL", pool);
280 
281   SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 0);
282 
283   return SVN_NO_ERROR;
284 }
285 
286 static svn_error_t *
test_spillbuf_interleaving(apr_pool_t * pool)287 test_spillbuf_interleaving(apr_pool_t *pool)
288 {
289   svn_spillbuf_t *buf = svn_spillbuf__create(8 /* blocksize */,
290                                              15 /* maxsize */,
291                                              pool);
292   return test_spillbuf__interleaving(pool, buf);
293 }
294 
295 static svn_error_t *
test_spillbuf_interleaving_spill_all(apr_pool_t * pool)296 test_spillbuf_interleaving_spill_all(apr_pool_t *pool)
297 {
298   svn_spillbuf_t *buf = svn_spillbuf__create_extended(
299                           8 /* blocksize */,
300                           15 /* maxsize */,
301                           TRUE /* delte on close */,
302                           TRUE /* spill all data */,
303                           NULL, pool);
304   return test_spillbuf__interleaving(pool, buf);
305 }
306 
307 static svn_error_t *
test_spillbuf_reader(apr_pool_t * pool)308 test_spillbuf_reader(apr_pool_t *pool)
309 {
310   svn_spillbuf_reader_t *sbr = svn_spillbuf__reader_create(4 /* blocksize */,
311                                                            100 /* maxsize */,
312                                                            pool);
313   apr_size_t amt;
314   char buf[10];
315 
316   SVN_ERR(svn_spillbuf__reader_write(sbr, "abcdef", 6, pool));
317 
318   /* Get a buffer from the underlying reader, and grab a couple bytes.  */
319   SVN_ERR(svn_spillbuf__reader_read(&amt, sbr, buf, 2, pool));
320   SVN_TEST_ASSERT(amt == 2 && memcmp(buf, "ab", 2) == 0);
321 
322   /* Trigger the internal "save" feature of the SBR.  */
323   SVN_ERR(svn_spillbuf__reader_write(sbr, "ghijkl", 6, pool));
324 
325   /* Read from the save buffer, and from the internal blocks.  */
326   SVN_ERR(svn_spillbuf__reader_read(&amt, sbr, buf, 10, pool));
327   SVN_TEST_ASSERT(amt == 10 && memcmp(buf, "cdefghijkl", 10) == 0);
328 
329   /* Should be done.  */
330   SVN_ERR(svn_spillbuf__reader_read(&amt, sbr, buf, 10, pool));
331   SVN_TEST_ASSERT(amt == 0);
332 
333   return SVN_NO_ERROR;
334 }
335 
336 static svn_error_t *
test_spillbuf_stream(apr_pool_t * pool)337 test_spillbuf_stream(apr_pool_t *pool)
338 {
339   svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
340                                              100 /* maxsize */,
341                                              pool);
342   svn_stream_t *stream = svn_stream__from_spillbuf(buf, pool);
343   char readbuf[256];
344   apr_size_t readlen;
345   apr_size_t writelen;
346 
347   writelen = 6;
348   SVN_ERR(svn_stream_write(stream, "abcdef", &writelen));
349   SVN_ERR(svn_stream_write(stream, "ghijkl", &writelen));
350   /* now: two blocks: 8 and 4 bytes  */
351 
352   readlen = 8;
353   SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
354   SVN_TEST_ASSERT(readlen == 8
355                   && memcmp(readbuf, "abcdefgh", 8) == 0);
356   /* now: one block: 4 bytes  */
357 
358   SVN_ERR(svn_stream_write(stream, "mnopqr", &writelen));
359   /* now: two blocks: 8 and 2 bytes  */
360 
361   SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
362   SVN_TEST_ASSERT(readlen == 8
363                   && memcmp(readbuf, "ijklmnop", 8) == 0);
364   /* now: one block: 2 bytes  */
365 
366   SVN_ERR(svn_stream_write(stream, "stuvwx", &writelen));
367   SVN_ERR(svn_stream_write(stream, "ABCDEF", &writelen));
368   SVN_ERR(svn_stream_write(stream, "GHIJKL", &writelen));
369   /* now: two blocks: 8 and 6 bytes, and 6 bytes spilled to a file  */
370 
371   SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
372   SVN_TEST_ASSERT(readlen == 8
373                   && memcmp(readbuf, "qrstuvwx", 8) == 0);
374   readlen = 6;
375   SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
376   SVN_TEST_ASSERT(readlen == 6
377                   && memcmp(readbuf, "ABCDEF", 6) == 0);
378   SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
379   SVN_TEST_ASSERT(readlen == 6
380                   && memcmp(readbuf, "GHIJKL", 6) == 0);
381 
382   return SVN_NO_ERROR;
383 }
384 
385 static svn_error_t *
test_spillbuf__rwfile(apr_pool_t * pool,svn_spillbuf_t * buf)386 test_spillbuf__rwfile(apr_pool_t *pool, svn_spillbuf_t *buf)
387 {
388   SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
389   SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
390   SVN_ERR(svn_spillbuf__write(buf, "mnopqr", 6, pool));
391   /* now: two blocks: 4 and 2 bytes, and 12 bytes in spill file.  */
392 
393   CHECK_READ(buf, 18, "abcd", pool);
394   /* now: one block: 2 bytes, and 12 bytes in spill file.  */
395 
396   CHECK_READ(buf, 14, "ef", pool);
397   /* now: no blocks, and 12 bytes in spill file.  */
398 
399   CHECK_READ(buf, 12, "ghij", pool);
400   /* now: no blocks, and 8 bytes in spill file.  */
401 
402   /* Write more data. It should be appended to the spill file.  */
403   SVN_ERR(svn_spillbuf__write(buf, "stuvwx", 6, pool));
404   /* now: no blocks, and 14 bytes in spill file.  */
405 
406   CHECK_READ(buf, 14, "klmn", pool);
407   /* now: no blocks, and 10 bytes in spill file.  */
408 
409   CHECK_READ(buf, 10, "opqr", pool);
410   /* now: no blocks, and 6 bytes in spill file.  */
411 
412   CHECK_READ(buf, 6, "stuv", pool);
413   /* now: no blocks, and 2 bytes in spill file.  */
414 
415   CHECK_READ(buf, 2, "wx", pool);
416   /* now: no blocks, and no spill file.  */
417 
418   return SVN_NO_ERROR;
419 }
420 
421 static svn_error_t *
test_spillbuf_rwfile(apr_pool_t * pool)422 test_spillbuf_rwfile(apr_pool_t *pool)
423 {
424   svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
425                                              10 /* maxsize */,
426                                              pool);
427   return test_spillbuf__rwfile(pool, buf);
428 }
429 
430 static svn_error_t *
test_spillbuf_rwfile_spill_all(apr_pool_t * pool)431 test_spillbuf_rwfile_spill_all(apr_pool_t *pool)
432 {
433   svn_spillbuf_t *buf = svn_spillbuf__create_extended(
434                           4 /* blocksize */,
435                           10 /* maxsize */,
436                           TRUE /* delte on close */,
437                           TRUE /* spill all data */,
438                           NULL, pool);
439   return test_spillbuf__rwfile(pool, buf);
440 }
441 
442 static svn_error_t *
test_spillbuf__eof(apr_pool_t * pool,svn_spillbuf_t * buf)443 test_spillbuf__eof(apr_pool_t *pool, svn_spillbuf_t *buf)
444 {
445   SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
446   SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
447   /* now: two blocks: 4 and 2 bytes, and 6 bytes in spill file.  */
448 
449   CHECK_READ(buf, 12, "abcd", pool);
450   CHECK_READ(buf, 8, "ef", pool);
451   CHECK_READ(buf, 6, "ghij", pool);
452   CHECK_READ(buf, 2, "kl", pool);
453   /* The spill file should have been emptied and forgotten.  */
454 
455   /* Assuming the spill file has been forgotten, this should result in
456      precisely the same behavior. Specifically: the initial write should
457      create two blocks, and the second write should be spilled. If there
458      *was* a spill file, then this written data would go into the file.  */
459   SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
460   SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
461   CHECK_READ(buf, 12, "abcd", pool);
462   CHECK_READ(buf, 8, "ef", pool);
463   CHECK_READ(buf, 6, "ghij", pool);
464   CHECK_READ(buf, 2, "kl", pool);
465   /* The spill file should have been emptied and forgotten.  */
466 
467   /* Now, let's do a sequence where we arrange to hit EOF precisely on
468      a block-sized read. Note: the second write must be more than 4 bytes,
469      or it will not cause a spill. We use 8 to get the right boundary.  */
470   SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
471   SVN_ERR(svn_spillbuf__write(buf, "ghijklmn", 8, pool));
472   CHECK_READ(buf, 14, "abcd", pool);
473   CHECK_READ(buf, 10, "ef", pool);
474   CHECK_READ(buf, 8, "ghij", pool);
475   CHECK_READ(buf, 4, "klmn", pool);
476   /* We discard the spill file when we know it has no data, rather than
477      upon hitting EOF (upon a read attempt). Thus, the spill file should
478      be gone.  */
479 
480   /* Verify the forgotten spill file.  */
481   SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
482   SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
483   CHECK_READ(buf, 12, "abcd", pool);
484   CHECK_READ(buf, 8, "ef", pool);
485   CHECK_READ(buf, 6, "ghij", pool);
486   /* Two unread bytes remaining in the spill file.  */
487   SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 2);
488 
489   return SVN_NO_ERROR;
490 }
491 
492 static svn_error_t *
test_spillbuf_eof(apr_pool_t * pool)493 test_spillbuf_eof(apr_pool_t *pool)
494 {
495   svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
496                                              10 /* maxsize */,
497                                              pool);
498   return test_spillbuf__eof(pool, buf);
499 }
500 
501 static svn_error_t *
test_spillbuf_eof_spill_all(apr_pool_t * pool)502 test_spillbuf_eof_spill_all(apr_pool_t *pool)
503 {
504   svn_spillbuf_t *buf = svn_spillbuf__create_extended(
505                           4 /* blocksize */,
506                           10 /* maxsize */,
507                           TRUE /* delte on close */,
508                           TRUE /* spill all data */,
509                           NULL, pool);
510   return test_spillbuf__eof(pool, buf);
511 }
512 
513 static svn_error_t *
test_spillbuf__file_attrs(apr_pool_t * pool,svn_boolean_t spill_all,svn_spillbuf_t * buf)514 test_spillbuf__file_attrs(apr_pool_t *pool, svn_boolean_t spill_all,
515                           svn_spillbuf_t *buf)
516 {
517   svn_filesize_t filesize;
518 
519   SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
520   SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
521   SVN_ERR(svn_spillbuf__write(buf, "mnopqr", 6, pool));
522 
523   /* Check that the spillbuf size is what we expect it to be */
524   SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 18);
525 
526   /* Check file existence */
527   SVN_TEST_ASSERT(svn_spillbuf__get_filename(buf) != NULL);
528   SVN_TEST_ASSERT(svn_spillbuf__get_file(buf) != NULL);
529 
530   /* The size of the file must match expectations */
531   SVN_ERR(svn_io_file_size_get(&filesize, svn_spillbuf__get_file(buf), pool));
532   if (spill_all)
533     SVN_TEST_ASSERT(filesize == svn_spillbuf__get_size(buf));
534   else
535     SVN_TEST_ASSERT(filesize == (svn_spillbuf__get_size(buf)
536                                  - svn_spillbuf__get_memory_size(buf)));
537   return SVN_NO_ERROR;
538 }
539 
540 static svn_error_t *
test_spillbuf_file_attrs(apr_pool_t * pool)541 test_spillbuf_file_attrs(apr_pool_t *pool)
542 {
543   svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
544                                              10 /* maxsize */,
545                                              pool);
546   return test_spillbuf__file_attrs(pool, FALSE, buf);
547 }
548 
549 static svn_error_t *
test_spillbuf_file_attrs_spill_all(apr_pool_t * pool)550 test_spillbuf_file_attrs_spill_all(apr_pool_t *pool)
551 {
552   svn_spillbuf_t *buf = svn_spillbuf__create_extended(
553                           4 /* blocksize */,
554                           10 /* maxsize */,
555                           TRUE /* delte on close */,
556                           TRUE /* spill all data */,
557                           NULL, pool);
558   return test_spillbuf__file_attrs(pool, TRUE, buf);
559 }
560 
561 /* The test table.  */
562 
563 static int max_threads = 1;
564 
565 static struct svn_test_descriptor_t test_funcs[] =
566   {
567     SVN_TEST_NULL,
568     SVN_TEST_PASS2(test_spillbuf_basic, "basic spill buffer test"),
569     SVN_TEST_PASS2(test_spillbuf_basic_spill_all,
570                    "basic spill buffer test (spill-all-data)"),
571     SVN_TEST_PASS2(test_spillbuf_callback, "spill buffer read callback"),
572     SVN_TEST_PASS2(test_spillbuf_callback_spill_all,
573                    "spill buffer read callback (spill-all-data)"),
574     SVN_TEST_PASS2(test_spillbuf_file, "spill buffer file test"),
575     SVN_TEST_PASS2(test_spillbuf_file_spill_all,
576                    "spill buffer file test (spill-all-data)"),
577     SVN_TEST_PASS2(test_spillbuf_interleaving,
578                    "interleaving reads and writes"),
579     SVN_TEST_PASS2(test_spillbuf_interleaving_spill_all,
580                    "interleaving reads and writes (spill-all-data)"),
581     SVN_TEST_PASS2(test_spillbuf_reader, "spill buffer reader test"),
582     SVN_TEST_PASS2(test_spillbuf_stream, "spill buffer stream test"),
583     SVN_TEST_PASS2(test_spillbuf_rwfile, "read/write spill file"),
584     SVN_TEST_PASS2(test_spillbuf_rwfile_spill_all,
585                    "read/write spill file (spill-all-data)"),
586     SVN_TEST_PASS2(test_spillbuf_eof, "validate reaching EOF of spill file"),
587     SVN_TEST_PASS2(test_spillbuf_eof_spill_all,
588                    "validate reaching EOF (spill-all-data)"),
589     SVN_TEST_PASS2(test_spillbuf_file_attrs, "check spill file properties"),
590     SVN_TEST_PASS2(test_spillbuf_file_attrs_spill_all,
591                    "check spill file properties (spill-all-data)"),
592     SVN_TEST_NULL
593   };
594 
595 SVN_TEST_MAIN
596