1 /* strings-reps-test.c --- test `strings' and `representations' interfaces
2 *
3 * ====================================================================
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 * ====================================================================
21 */
22
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <stdio.h>
27
28 #include <apr.h>
29
30 #include "svn_error.h"
31 #include "private/svn_skel.h"
32
33 #include "../svn_test.h"
34 #include "../svn_test_fs.h"
35 #include "../../libsvn_fs/fs-loader.h"
36 #include "../../libsvn_fs_base/fs.h"
37 #include "../../libsvn_fs_base/util/fs_skels.h"
38 #include "../../libsvn_fs_base/bdb/strings-table.h"
39 #include "../../libsvn_fs_base/bdb/reps-table.h"
40
41
42
43 /*-----------------------------------------------------------------*/
44 /* Helper functions and batons for reps-table testing. */
45 struct rep_args
46 {
47 const char *key;
48 svn_fs_t *fs;
49 svn_skel_t *skel;
50 };
51
52
53 static svn_error_t *
txn_body_write_new_rep(void * baton,trail_t * trail)54 txn_body_write_new_rep(void *baton, trail_t *trail)
55 {
56 struct rep_args *b = (struct rep_args *) baton;
57 representation_t *rep;
58 SVN_ERR(svn_fs_base__parse_representation_skel(&rep, b->skel,
59 trail->pool));
60 return svn_fs_bdb__write_new_rep(&(b->key), b->fs, rep, trail, trail->pool);
61 }
62
63
64 static svn_error_t *
txn_body_write_rep(void * baton,trail_t * trail)65 txn_body_write_rep(void *baton, trail_t *trail)
66 {
67 struct rep_args *b = (struct rep_args *) baton;
68 representation_t *rep;
69 SVN_ERR(svn_fs_base__parse_representation_skel(&rep, b->skel,
70 trail->pool));
71 return svn_fs_bdb__write_rep(b->fs, b->key, rep, trail, trail->pool);
72 }
73
74
75 static svn_error_t *
txn_body_read_rep(void * baton,trail_t * trail)76 txn_body_read_rep(void *baton, trail_t *trail)
77 {
78 struct rep_args *b = (struct rep_args *) baton;
79 representation_t *rep;
80 base_fs_data_t *bfd = b->fs->fsap_data;
81 SVN_ERR(svn_fs_bdb__read_rep(&rep, b->fs, b->key, trail, trail->pool));
82 return svn_fs_base__unparse_representation_skel(&(b->skel), rep,
83 bfd->format, trail->pool);
84 }
85
86
87 static svn_error_t *
txn_body_delete_rep(void * baton,trail_t * trail)88 txn_body_delete_rep(void *baton, trail_t *trail)
89 {
90 struct rep_args *b = (struct rep_args *) baton;
91 return svn_fs_bdb__delete_rep(b->fs, b->key, trail, trail->pool);
92 }
93
94
95
96 /* Representation Table Test functions. */
97
98 static svn_error_t *
write_new_rep(const svn_test_opts_t * opts,apr_pool_t * pool)99 write_new_rep(const svn_test_opts_t *opts,
100 apr_pool_t *pool)
101 {
102 struct rep_args args;
103 const char *rep = "((fulltext 0 ) a83t2Z0q)";
104 svn_fs_t *fs;
105
106 /* Create a new fs and repos */
107 SVN_ERR(svn_test__create_bdb_fs
108 (&fs, "test-repo-write-new-rep", opts,
109 pool));
110
111 /* Set up transaction baton */
112 args.fs = fs;
113 args.skel = svn_skel__parse(rep, strlen(rep), pool);
114 args.key = NULL;
115
116 /* Write new rep to reps table. */
117 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_write_new_rep, &args,
118 FALSE, pool));
119
120 if (args.key == NULL)
121 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
122 "error writing new representation");
123
124 return SVN_NO_ERROR;
125 }
126
127
128 static svn_error_t *
write_rep(const svn_test_opts_t * opts,apr_pool_t * pool)129 write_rep(const svn_test_opts_t *opts,
130 apr_pool_t *pool)
131 {
132 struct rep_args new_args;
133 struct rep_args args;
134 const char *new_rep = "((fulltext 0 ) a83t2Z0q)";
135 const char *rep = "((fulltext 0 ) kfogel31337)";
136 svn_fs_t *fs;
137
138 /* Create a new fs and repos */
139 SVN_ERR(svn_test__create_bdb_fs
140 (&fs, "test-repo-write-rep", opts,
141 pool));
142
143 /* Set up transaction baton */
144 new_args.fs = fs;
145 new_args.skel = svn_skel__parse(new_rep, strlen(new_rep), pool);
146 new_args.key = NULL;
147
148 /* Write new rep to reps table. */
149 SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_new_rep,
150 &new_args, FALSE, pool));
151
152 /* Make sure we got a valid key. */
153 if (new_args.key == NULL)
154 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
155 "error writing new representation");
156
157 /* Set up transaction baton for re-writing reps. */
158 args.fs = new_args.fs;
159 args.skel = svn_skel__parse(rep, strlen(rep), pool);
160 args.key = new_args.key;
161
162 /* Overwrite first rep in reps table. */
163 SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_rep, &args,
164 FALSE, pool));
165
166 return SVN_NO_ERROR;
167 }
168
169
170 static svn_error_t *
read_rep(const svn_test_opts_t * opts,apr_pool_t * pool)171 read_rep(const svn_test_opts_t *opts,
172 apr_pool_t *pool)
173 {
174 struct rep_args new_args;
175 struct rep_args args;
176 struct rep_args read_args;
177 svn_stringbuf_t *skel_data;
178 svn_fs_t *fs;
179
180 const char *rep = "((fulltext 0 ) kfogel31337)";
181 const char *new_rep_before = "((fulltext 0 ) a83t2Z0)";
182
183 /* This test also tests the introduction of checksums into skels that
184 didn't have them. */
185
186 /* Get writeable strings. */
187 char *rep_after = apr_pstrdup
188 (pool, "((fulltext 0 (md5 16 XXXXXXXXXXXXXXXX)) kfogel31337");
189 char *new_rep_after = apr_pstrdup
190 (pool, "((fulltext 0 (md5 16 XXXXXXXXXXXXXXXX)) a83t2Z0");
191 size_t rep_after_len = strlen(rep_after);
192 size_t new_rep_after_len = strlen(new_rep_after);
193
194 /* Replace the fake fake checksums with the real fake checksums.
195 And someday, when checksums are actually calculated, we can
196 replace the real fake checksums with real real checksums. */
197 {
198 char *p;
199
200 for (p = rep_after; *p; p++)
201 if (*p == 'X')
202 *p = '\0';
203
204 for (p = new_rep_after; *p; p++)
205 if (*p == 'X')
206 *p = '\0';
207 }
208
209 /* Create a new fs and repos */
210 SVN_ERR(svn_test__create_bdb_fs
211 (&fs, "test-repo-read-rep", opts,
212 pool));
213
214 /* Set up transaction baton */
215 new_args.fs = fs;
216 new_args.skel = svn_skel__parse(new_rep_before, strlen(new_rep_before),
217 pool);
218 new_args.key = NULL;
219
220 /* Write new rep to reps table. */
221 SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_new_rep,
222 &new_args, FALSE, pool));
223
224 /* Make sure we got a valid key. */
225 if (new_args.key == NULL)
226 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
227 "error writing new representation");
228
229 /* Read the new rep back from the reps table. */
230 read_args.fs = new_args.fs;
231 read_args.skel = NULL;
232 read_args.key = new_args.key;
233 SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_read_rep, &read_args,
234 FALSE, pool));
235
236 /* Make sure the skel matches. */
237 if (! read_args.skel)
238 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
239 "error reading new representation");
240
241 skel_data = svn_skel__unparse(read_args.skel, pool);
242 if (memcmp(skel_data->data, new_rep_after, new_rep_after_len) != 0)
243 return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
244 "representation corrupted (first check)");
245
246 /* Set up transaction baton for re-writing reps. */
247 args.fs = new_args.fs;
248 args.skel = svn_skel__parse(rep, strlen(rep), pool);
249 args.key = new_args.key;
250
251 /* Overwrite first rep in reps table. */
252 SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_rep, &args,
253 FALSE, pool));
254
255 /* Read the new rep back from the reps table (using the same FS and
256 key as the first read...let's make sure this thing didn't get
257 written to the wrong place). */
258 read_args.skel = NULL;
259 SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_read_rep, &read_args,
260 FALSE, pool));
261
262 /* Make sure the skel matches. */
263 if (! read_args.skel)
264 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
265 "error reading new representation");
266
267 skel_data = svn_skel__unparse(read_args.skel, pool);
268 if (memcmp(skel_data->data, rep_after, rep_after_len) != 0)
269 return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
270 "representation corrupted (second check)");
271
272 return SVN_NO_ERROR;
273 }
274
275
276 static svn_error_t *
delete_rep(const svn_test_opts_t * opts,apr_pool_t * pool)277 delete_rep(const svn_test_opts_t *opts,
278 apr_pool_t *pool)
279 {
280 struct rep_args new_args;
281 struct rep_args delete_args;
282 struct rep_args read_args;
283 const char *new_rep = "((fulltext 0 ) a83t2Z0q)";
284 svn_fs_t *fs;
285 svn_error_t *err;
286
287 /* Create a new fs and repos */
288 SVN_ERR(svn_test__create_bdb_fs
289 (&fs, "test-repo-delete-rep", opts,
290 pool));
291
292 /* Set up transaction baton */
293 new_args.fs = fs;
294 new_args.skel = svn_skel__parse(new_rep, strlen(new_rep), pool);
295 new_args.key = NULL;
296
297 /* Write new rep to reps table. */
298 SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_write_new_rep,
299 &new_args, FALSE, pool));
300
301 /* Make sure we got a valid key. */
302 if (new_args.key == NULL)
303 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
304 "error writing new representation");
305
306 /* Delete the rep we just wrote. */
307 delete_args.fs = new_args.fs;
308 delete_args.key = new_args.key;
309 SVN_ERR(svn_fs_base__retry_txn(new_args.fs, txn_body_delete_rep,
310 &delete_args, FALSE, pool));
311
312 /* Try to read the new rep back from the reps table. */
313 read_args.fs = new_args.fs;
314 read_args.skel = NULL;
315 read_args.key = new_args.key;
316 err = svn_fs_base__retry_txn(new_args.fs, txn_body_read_rep, &read_args,
317 FALSE, pool);
318
319 /* We better have an error... */
320 if ((! err) && (read_args.skel))
321 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
322 "error deleting representation");
323 svn_error_clear(err);
324
325 return SVN_NO_ERROR;
326 }
327
328
329 /* ------------------------------------------------------------------- */
330 /* Helper functions and batons for strings-table testing. */
331
332 static svn_error_t *
verify_expected_record(svn_fs_t * fs,const char * key,const char * expected_text,apr_size_t expected_len,trail_t * trail)333 verify_expected_record(svn_fs_t *fs,
334 const char *key,
335 const char *expected_text,
336 apr_size_t expected_len,
337 trail_t *trail)
338 {
339 apr_size_t size;
340 char buf[100];
341 svn_stringbuf_t *text;
342 svn_filesize_t offset = 0;
343 svn_filesize_t string_size;
344
345 /* Check the string size. */
346 SVN_ERR(svn_fs_bdb__string_size(&string_size, fs, key,
347 trail, trail->pool));
348 if (string_size > SVN_MAX_OBJECT_SIZE)
349 return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
350 "record size is too large "
351 "(got %" SVN_FILESIZE_T_FMT ", "
352 "limit is %" APR_SIZE_T_FMT ")",
353 string_size, SVN_MAX_OBJECT_SIZE);
354 size = (apr_size_t) string_size;
355 if (size != expected_len)
356 return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
357 "record has unexpected size "
358 "(got %" APR_SIZE_T_FMT ", "
359 "expected %" APR_SIZE_T_FMT ")",
360 size, expected_len);
361
362 /* Read the string back in 100-byte chunks. */
363 text = svn_stringbuf_create_empty(trail->pool);
364 while (1)
365 {
366 size = sizeof(buf);
367 SVN_ERR(svn_fs_bdb__string_read(fs, key, buf, offset, &size,
368 trail, trail->pool));
369 if (size == 0)
370 break;
371 svn_stringbuf_appendbytes(text, buf, size);
372 offset += size;
373 }
374
375 /* Check the size and contents of the read data. */
376 if (text->len != expected_len)
377 return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
378 "record read returned unexpected size "
379 "(got %" APR_SIZE_T_FMT ", "
380 "expected %" APR_SIZE_T_FMT ")",
381 size, expected_len);
382 if (memcmp(expected_text, text->data, expected_len))
383 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
384 "record read returned unexpected data");
385
386 return SVN_NO_ERROR;
387 }
388
389
390 struct string_args
391 {
392 svn_fs_t *fs;
393 const char *key;
394 const char *text;
395 apr_size_t len;
396 };
397
398
399 static svn_error_t *
txn_body_verify_string(void * baton,trail_t * trail)400 txn_body_verify_string(void *baton, trail_t *trail)
401 {
402 struct string_args *b = (struct string_args *) baton;
403 return verify_expected_record(b->fs, b->key, b->text, b->len, trail);
404 }
405
406
407 static svn_error_t *
txn_body_string_append(void * baton,trail_t * trail)408 txn_body_string_append(void *baton, trail_t *trail)
409 {
410 struct string_args *b = (struct string_args *) baton;
411 return svn_fs_bdb__string_append(b->fs, &(b->key), b->len,
412 b->text, trail, trail->pool);
413 }
414
415
416 static svn_error_t *
txn_body_string_clear(void * baton,trail_t * trail)417 txn_body_string_clear(void *baton, trail_t *trail)
418 {
419 struct string_args *b = (struct string_args *) baton;
420 return svn_fs_bdb__string_clear(b->fs, b->key, trail, trail->pool);
421 }
422
423
424 static svn_error_t *
txn_body_string_delete(void * baton,trail_t * trail)425 txn_body_string_delete(void *baton, trail_t *trail)
426 {
427 struct string_args *b = (struct string_args *) baton;
428 return svn_fs_bdb__string_delete(b->fs, b->key, trail, trail->pool);
429 }
430
431
432 static svn_error_t *
txn_body_string_size(void * baton,trail_t * trail)433 txn_body_string_size(void *baton, trail_t *trail)
434 {
435 struct string_args *b = (struct string_args *) baton;
436 svn_filesize_t string_size;
437 SVN_ERR(svn_fs_bdb__string_size(&string_size, b->fs, b->key,
438 trail, trail->pool));
439 if (string_size > SVN_MAX_OBJECT_SIZE)
440 return svn_error_createf
441 (SVN_ERR_FS_GENERAL, NULL,
442 "txn_body_string_size: string size is too large "
443 "(got %" SVN_FILESIZE_T_FMT ", limit is %" APR_SIZE_T_FMT ")",
444 string_size, SVN_MAX_OBJECT_SIZE);
445 b->len = (apr_size_t) string_size;
446 return SVN_NO_ERROR;
447 }
448
449
450 static svn_error_t *
txn_body_string_append_fail(void * baton,trail_t * trail)451 txn_body_string_append_fail(void *baton, trail_t *trail)
452 {
453 struct string_args *b = (struct string_args *) baton;
454 SVN_ERR(svn_fs_bdb__string_append(b->fs, &(b->key), b->len,
455 b->text, trail, trail->pool));
456 return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
457 "la dee dah, la dee day...");
458 }
459
460 static svn_error_t *
txn_body_string_copy(void * baton,trail_t * trail)461 txn_body_string_copy(void *baton, trail_t *trail)
462 {
463 struct string_args *b = (struct string_args *) baton;
464 return svn_fs_bdb__string_copy(b->fs, &(b->key), b->key,
465 trail, trail->pool);
466 }
467
468
469 static const char *bigstring1 =
470 " Alice opened the door and found that it led into a small\n"
471 "passage, not much larger than a rat-hole: she knelt down and\n"
472 "looked along the passage into the loveliest garden you ever saw.\n"
473 "How she longed to get out of that dark hall, and wander about\n"
474 "among those beds of bright flowers and those cool fountains, but\n"
475 "she could not even get her head though the doorway; 'and even if\n"
476 "my head would go through,' thought poor Alice, 'it would be of\n"
477 "very little use without my shoulders. Oh, how I wish\n"
478 "I could shut up like a telescope! I think I could, if I only\n"
479 "know how to begin.' For, you see, so many out-of-the-way things\n"
480 "had happened lately, that Alice had begun to think that very few\n"
481 "things indeed were really impossible.";
482
483 static const char *bigstring2 =
484 " There seemed to be no use in waiting by the little door, so she\n"
485 "went back to the table, half hoping she might find another key on\n"
486 "it, or at any rate a book of rules for shutting people up like\n"
487 "telescopes: this time she found a little bottle on it, ('which\n"
488 "certainly was not here before,' said Alice,) and round the neck\n"
489 "of the bottle was a paper label, with the words 'DRINK ME'\n"
490 "beautifully printed on it in large letters.";
491
492 static const char *bigstring3 =
493 " It was all very well to say 'Drink me,' but the wise little\n"
494 "Alice was not going to do THAT in a hurry. 'No, I'll look\n"
495 "first,' she said, 'and see whether it's marked \"poison\" or not';\n"
496 "for she had read several nice little histories about children who\n"
497 "had got burnt, and eaten up by wild beasts and other unpleasant\n"
498 "things, all because they WOULD not remember the simple rules\n"
499 "their friends had taught them: such as, that a red-hot poker\n"
500 "will burn you if you hold it too long; and that if you cut your\n"
501 "finger VERY deeply with a knife, it usually bleeds; and she had\n"
502 "never forgotten that, if you drink much from a bottle marked\n"
503 "'poison,' it is almost certain to disagree with you, sooner or\n"
504 "later.";
505
506
507 static svn_error_t *
test_strings(const svn_test_opts_t * opts,apr_pool_t * pool)508 test_strings(const svn_test_opts_t *opts,
509 apr_pool_t *pool)
510 {
511 struct string_args args;
512 svn_fs_t *fs;
513 svn_stringbuf_t *string;
514
515 /* Create a new fs and repos */
516 SVN_ERR(svn_test__create_bdb_fs
517 (&fs, "test-repo-test-strings", opts,
518 pool));
519
520 /* The plan (after each step below, verify the size and contents of
521 the string):
522
523 1. Write a new string (string1).
524 2. Append string2 to string.
525 3. Clear string.
526 4. Append string3 to string.
527 5. Delete string (verify by size requested failure).
528 6. Write a new string (string1), appending string2, string3, and
529 string4.
530 */
531
532 /* 1. Write a new string (string1). */
533 args.fs = fs;
534 args.key = NULL;
535 args.text = bigstring1;
536 args.len = strlen(bigstring1);
537 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
538 FALSE, pool));
539
540 /* Make sure a key was returned. */
541 if (! args.key)
542 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
543 "write of new string failed to return new key");
544
545 /* Verify record's size and contents. */
546 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
547 FALSE, pool));
548
549 /* Append a second string to our first one. */
550 args.text = bigstring2;
551 args.len = strlen(bigstring2);
552 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
553 FALSE, pool));
554
555 /* Verify record's size and contents. */
556 string = svn_stringbuf_create(bigstring1, pool);
557 svn_stringbuf_appendcstr(string, bigstring2);
558 args.text = string->data;
559 args.len = string->len;
560 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
561 FALSE, pool));
562
563 /* Clear the record */
564 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_clear, &args,
565 FALSE, pool));
566
567 /* Verify record's size and contents. */
568 args.text = "";
569 args.len = 0;
570 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
571 FALSE, pool));
572
573 /* Append a third string to our first one. */
574 args.text = bigstring3;
575 args.len = strlen(bigstring3);
576 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
577 FALSE, pool));
578
579 /* Verify record's size and contents. */
580 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
581 FALSE, pool));
582
583 /* Delete our record...she's served us well. */
584 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_delete, &args,
585 FALSE, pool));
586
587 /* Now, we expect a size request on this record to fail with
588 SVN_ERR_FS_NO_SUCH_STRING. */
589 {
590 svn_error_t *err = svn_fs_base__retry_txn(args.fs, txn_body_string_size,
591 &args, FALSE, pool);
592
593 if (! err)
594 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
595 "query unexpectedly successful");
596 if (err->apr_err != SVN_ERR_FS_NO_SUCH_STRING)
597 return svn_error_create(SVN_ERR_FS_GENERAL, err,
598 "query failed with unexpected error");
599 svn_error_clear(err);
600 }
601
602 return SVN_NO_ERROR;
603 }
604
605
606 static svn_error_t *
write_null_string(const svn_test_opts_t * opts,apr_pool_t * pool)607 write_null_string(const svn_test_opts_t *opts,
608 apr_pool_t *pool)
609 {
610 struct string_args args;
611 svn_fs_t *fs;
612
613 /* Create a new fs and repos */
614 SVN_ERR(svn_test__create_bdb_fs
615 (&fs, "test-repo-write-null-string", opts,
616 pool));
617
618 args.fs = fs;
619 args.key = NULL;
620 args.text = NULL;
621 args.len = 0;
622 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
623 FALSE, pool));
624
625 return SVN_NO_ERROR;
626 }
627
628
629 static svn_error_t *
abort_string(const svn_test_opts_t * opts,apr_pool_t * pool)630 abort_string(const svn_test_opts_t *opts,
631 apr_pool_t *pool)
632 {
633 struct string_args args, args2;
634 svn_fs_t *fs;
635
636 /* Create a new fs and repos */
637 SVN_ERR(svn_test__create_bdb_fs
638 (&fs, "test-repo-abort-string", opts,
639 pool));
640
641 /* The plan:
642
643 1. Write a new string (string1).
644 2. Overwrite string1 with string2, but then ABORT the transaction.
645 3. Read string to make sure it is still string1.
646 */
647
648 /* 1. Write a new string (string1). */
649 args.fs = fs;
650 args.key = NULL;
651 args.text = bigstring1;
652 args.len = strlen(bigstring1);
653 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
654 FALSE, pool));
655
656 /* Make sure a key was returned. */
657 if (! args.key)
658 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
659 "write of new string failed to return new key");
660
661 /* Verify record's size and contents. */
662 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
663 FALSE, pool));
664
665 /* Append a second string to our first one. */
666 args2.fs = fs;
667 args2.key = args.key;
668 args2.text = bigstring2;
669 args2.len = strlen(bigstring2);
670 {
671 svn_error_t *err;
672
673 /* This function is *supposed* to fail with SVN_ERR_TEST_FAILED */
674 err = svn_fs_base__retry_txn(args.fs, txn_body_string_append_fail,
675 &args2, FALSE, pool);
676 if ((! err) || (err->apr_err != SVN_ERR_TEST_FAILED))
677 return svn_error_create(SVN_ERR_TEST_FAILED, err,
678 "failed to intentionally abort a trail");
679 svn_error_clear(err);
680 }
681
682 /* Verify that record's size and contents are still that of string1 */
683 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
684 FALSE, pool));
685
686 return SVN_NO_ERROR;
687 }
688
689 static svn_error_t *
copy_string(const svn_test_opts_t * opts,apr_pool_t * pool)690 copy_string(const svn_test_opts_t *opts,
691 apr_pool_t *pool)
692 {
693 struct string_args args;
694 svn_fs_t *fs;
695 const char *old_key;
696
697 /* Create a new fs and repos */
698 SVN_ERR(svn_test__create_bdb_fs
699 (&fs, "test-repo-copy-string", opts,
700 pool));
701
702 /* Write a new string (string1). */
703 args.fs = fs;
704 args.key = NULL;
705 args.text = bigstring1;
706 args.len = strlen(bigstring1);
707 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
708 FALSE, pool));
709
710 /* Make sure a key was returned. */
711 if (! (old_key = args.key))
712 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
713 "write of new string failed to return new key");
714
715 /* Now copy that string into a new location. */
716 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_copy, &args,
717 FALSE, pool));
718
719 /* Make sure a different key was returned. */
720 if ((! args.key) || (! strcmp(old_key, args.key)))
721 return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
722 "copy of string failed to return new key");
723
724 /* Verify record's size and contents. */
725 SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
726 FALSE, pool));
727
728 return SVN_NO_ERROR;
729 }
730
731
732
733 /* The test table. */
734
735 static int max_threads = 3;
736
737 static struct svn_test_descriptor_t test_funcs[] =
738 {
739 SVN_TEST_NULL,
740 SVN_TEST_OPTS_PASS(write_new_rep,
741 "write a new rep, get a new key back"),
742 SVN_TEST_OPTS_PASS(write_rep,
743 "write a new rep, then overwrite it"),
744 SVN_TEST_OPTS_PASS(read_rep,
745 "write and overwrite a new rep; confirm with reads"),
746 SVN_TEST_OPTS_PASS(delete_rep,
747 "write, then delete, a new rep; confirm deletion"),
748 SVN_TEST_OPTS_PASS(test_strings,
749 "test many strings table functions together"),
750 SVN_TEST_OPTS_PASS(write_null_string,
751 "write a null string"),
752 SVN_TEST_OPTS_PASS(abort_string,
753 "write a string, then abort during an overwrite"),
754 SVN_TEST_OPTS_PASS(copy_string,
755 "create and copy a string"),
756 SVN_TEST_NULL
757 };
758
759 SVN_TEST_MAIN
760