1
/* fs-pack-test.c --- tests for the filesystem
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
12
* http://www.apache.org/licenses/LICENSE-2.0
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
20
* ====================================================================
25
#include <apr_pools.h>
27
#include "../svn_test.h"
28
#include "../../libsvn_fs_fs/fs.h"
30
#include "svn_pools.h"
31
#include "svn_props.h"
33
#include "private/svn_string_private.h"
35
#include "../svn_test_fs.h"
39
/*** Helper Functions ***/
42
ignore_fs_warnings(void *baton, svn_error_t *err)
45
SVN_DBG(("Ignoring FS warning %s\n",
46
svn_error_symbolic_name(err ? err->apr_err : 0)));
51
/* Write the format number and maximum number of files per directory
52
to a new format file in PATH, overwriting a previously existing
53
file. Use POOL for temporary allocation.
55
(This implementation is largely stolen from libsvn_fs_fs/fs_fs.c.) */
57
write_format(const char *path,
59
int max_files_per_dir,
64
path = svn_dirent_join(path, "format", pool);
66
if (format >= SVN_FS_FS__MIN_LAYOUT_FORMAT_OPTION_FORMAT)
68
if (max_files_per_dir)
69
contents = apr_psprintf(pool,
71
"layout sharded %d\n",
72
format, max_files_per_dir);
74
contents = apr_psprintf(pool,
81
contents = apr_psprintf(pool, "%d\n", format);
87
SVN_ERR(svn_io_write_unique(&path_tmp,
88
svn_dirent_dirname(path, pool),
89
contents, strlen(contents),
90
svn_io_file_del_none, pool));
92
/* rename the temp file as the real destination */
93
SVN_ERR(svn_io_file_rename(path_tmp, path, pool));
96
/* And set the perms to make it read only */
97
return svn_io_set_file_read_only(path, FALSE, pool);
100
/* Return the expected contents of "iota" in revision REV. */
102
get_rev_contents(svn_revnum_t rev, apr_pool_t *pool)
104
/* Toss in a bunch of magic numbers for spice. */
105
apr_int64_t num = ((rev * 1234353 + 4358) * 4583 + ((rev % 4) << 1)) / 42;
106
return apr_psprintf(pool, "%" APR_INT64_T_FMT "\n", num);
109
struct pack_notify_baton
111
apr_int64_t expected_shard;
112
svn_fs_pack_notify_action_t expected_action;
116
pack_notify(void *baton,
118
svn_fs_pack_notify_action_t action,
121
struct pack_notify_baton *pnb = baton;
123
SVN_TEST_ASSERT(shard == pnb->expected_shard);
124
SVN_TEST_ASSERT(action == pnb->expected_action);
126
/* Update expectations. */
129
case svn_fs_pack_notify_start:
130
pnb->expected_action = svn_fs_pack_notify_end;
133
case svn_fs_pack_notify_end:
134
pnb->expected_action = svn_fs_pack_notify_start;
135
pnb->expected_shard++;
139
return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
140
"Unknown notification action when packing");
146
/* Create a packed filesystem in DIR. Set the shard size to
147
SHARD_SIZE and create NUM_REVS number of revisions (in addition to
148
r0). Use POOL for allocations. After this function successfully
149
completes, the filesystem's youngest revision number will be the
152
create_packed_filesystem(const char *dir,
153
const svn_test_opts_t *opts,
160
svn_fs_root_t *txn_root;
161
const char *conflict;
162
svn_revnum_t after_rev;
163
apr_pool_t *subpool = svn_pool_create(pool);
164
struct pack_notify_baton pnb;
165
apr_pool_t *iterpool;
168
/* Create a filesystem, then close it */
169
SVN_ERR(svn_test__create_fs(&fs, dir, opts, subpool));
170
svn_pool_destroy(subpool);
172
subpool = svn_pool_create(pool);
174
/* Rewrite the format file */
175
SVN_ERR(svn_io_read_version_file(&version,
176
svn_dirent_join(dir, "format", subpool),
178
SVN_ERR(write_format(dir, version, shard_size, subpool));
180
/* Reopen the filesystem */
181
SVN_ERR(svn_fs_open(&fs, dir, NULL, subpool));
183
/* Revision 1: the Greek tree */
184
SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
185
SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
186
SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
187
SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));
188
SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
190
/* Revisions 2 thru NUM_REVS-1: content tweaks to "iota". */
191
iterpool = svn_pool_create(subpool);
192
while (after_rev < num_revs)
194
svn_pool_clear(iterpool);
195
SVN_ERR(svn_fs_begin_txn(&txn, fs, after_rev, iterpool));
196
SVN_ERR(svn_fs_txn_root(&txn_root, txn, iterpool));
197
SVN_ERR(svn_test__set_file_contents(txn_root, "iota",
198
get_rev_contents(after_rev + 1,
201
SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, iterpool));
202
SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
204
svn_pool_destroy(iterpool);
205
svn_pool_destroy(subpool);
207
/* Now pack the FS */
208
pnb.expected_shard = 0;
209
pnb.expected_action = svn_fs_pack_notify_start;
210
return svn_fs_pack(dir, pack_notify, &pnb, NULL, NULL, pool);
213
/* Create a packed FSFS filesystem for revprop tests at REPO_NAME with
214
* MAX_REV revisions and the given SHARD_SIZE and OPTS. Return it in *FS.
215
* Use POOL for allocations.
218
prepare_revprop_repo(svn_fs_t **fs,
219
const char *repo_name,
222
const svn_test_opts_t *opts,
226
svn_fs_root_t *txn_root;
227
const char *conflict;
228
svn_revnum_t after_rev;
231
/* Create the packed FS and open it. */
232
SVN_ERR(create_packed_filesystem(repo_name, opts, max_rev, shard_size, pool));
233
SVN_ERR(svn_fs_open(fs, repo_name, NULL, pool));
235
subpool = svn_pool_create(pool);
236
/* Do a commit to trigger packing. */
237
SVN_ERR(svn_fs_begin_txn(&txn, *fs, max_rev, subpool));
238
SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
239
SVN_ERR(svn_test__set_file_contents(txn_root, "iota", "new-iota", subpool));
240
SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));
241
SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
242
svn_pool_destroy(subpool);
244
/* Pack the repository. */
245
SVN_ERR(svn_fs_pack(repo_name, NULL, NULL, NULL, NULL, pool));
250
/* For revision REV, return a short log message allocated in POOL.
252
static svn_string_t *
253
default_log(svn_revnum_t rev, apr_pool_t *pool)
255
return svn_string_createf(pool, "Default message for rev %ld", rev);
258
/* For revision REV, return a long log message allocated in POOL.
260
static svn_string_t *
261
large_log(svn_revnum_t rev, apr_size_t length, apr_pool_t *pool)
263
svn_stringbuf_t *temp = svn_stringbuf_create_ensure(100000, pool);
264
int i, count = (int)(length - 50) / 6;
266
svn_stringbuf_appendcstr(temp, "A ");
267
for (i = 0; i < count; ++i)
268
svn_stringbuf_appendcstr(temp, "very, ");
270
svn_stringbuf_appendcstr(temp,
271
apr_psprintf(pool, "very long message for rev %ld, indeed", rev));
273
return svn_stringbuf__morph_into_string(temp);
276
/* For revision REV, return a long log message allocated in POOL.
278
static svn_string_t *
279
huge_log(svn_revnum_t rev, apr_pool_t *pool)
281
return large_log(rev, 90000, pool);
287
/* ------------------------------------------------------------------------ */
288
#define REPO_NAME "test-repo-fsfs-pack"
292
pack_filesystem(const svn_test_opts_t *opts,
296
svn_node_kind_t kind;
302
/* Bail (with success) on known-untestable scenarios */
303
if ((strcmp(opts->fs_type, "fsfs") != 0)
304
|| (opts->server_minor_version && (opts->server_minor_version < 6)))
307
SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE,
310
/* Check to see that the pack files exist, and that the rev directories
312
for (i = 0; i < (MAX_REV + 1) / SHARD_SIZE; i++)
314
path = svn_dirent_join_many(pool, REPO_NAME, "revs",
315
apr_psprintf(pool, "%d.pack", i / SHARD_SIZE),
318
/* These files should exist. */
319
SVN_ERR(svn_io_check_path(path, &kind, pool));
320
if (kind != svn_node_file)
321
return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
322
"Expected pack file '%s' not found", path);
324
path = svn_dirent_join_many(pool, REPO_NAME, "revs",
325
apr_psprintf(pool, "%d.pack", i / SHARD_SIZE),
327
SVN_ERR(svn_io_check_path(path, &kind, pool));
328
if (kind != svn_node_file)
329
return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
330
"Expected manifest file '%s' not found",
333
/* This directory should not exist. */
334
path = svn_dirent_join_many(pool, REPO_NAME, "revs",
335
apr_psprintf(pool, "%d", i / SHARD_SIZE),
337
SVN_ERR(svn_io_check_path(path, &kind, pool));
338
if (kind != svn_node_none)
339
return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
340
"Unexpected directory '%s' found", path);
343
/* Ensure the min-unpacked-rev jives with the above operations. */
344
SVN_ERR(svn_io_file_open(&file,
345
svn_dirent_join(REPO_NAME, PATH_MIN_UNPACKED_REV,
347
APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
349
SVN_ERR(svn_io_read_length_line(file, buf, &len, pool));
350
SVN_ERR(svn_io_file_close(file, pool));
351
if (SVN_STR_TO_REV(buf) != (MAX_REV / SHARD_SIZE) * SHARD_SIZE)
352
return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
353
"Bad '%s' contents", PATH_MIN_UNPACKED_REV);
355
/* Finally, make sure the final revision directory does exist. */
356
path = svn_dirent_join_many(pool, REPO_NAME, "revs",
357
apr_psprintf(pool, "%d", (i / SHARD_SIZE) + 1),
359
SVN_ERR(svn_io_check_path(path, &kind, pool));
360
if (kind != svn_node_none)
361
return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
362
"Expected directory '%s' not found", path);
371
/* ------------------------------------------------------------------------ */
372
#define REPO_NAME "test-repo-fsfs-pack-even"
376
pack_even_filesystem(const svn_test_opts_t *opts,
379
svn_node_kind_t kind;
382
/* Bail (with success) on known-untestable scenarios */
383
if ((strcmp(opts->fs_type, "fsfs") != 0)
384
|| (opts->server_minor_version && (opts->server_minor_version < 6)))
387
SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE,
390
path = svn_dirent_join_many(pool, REPO_NAME, "revs", "2.pack", NULL);
391
SVN_ERR(svn_io_check_path(path, &kind, pool));
392
if (kind != svn_node_dir)
393
return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
394
"Packing did not complete as expected");
402
/* ------------------------------------------------------------------------ */
403
#define REPO_NAME "test-repo-read-packed-fs"
407
read_packed_fs(const svn_test_opts_t *opts,
411
svn_stream_t *rstream;
412
svn_stringbuf_t *rstring;
415
/* Bail (with success) on known-untestable scenarios */
416
if ((strcmp(opts->fs_type, "fsfs") != 0)
417
|| (opts->server_minor_version && (opts->server_minor_version < 6)))
420
SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE, pool));
421
SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, pool));
423
for (i = 1; i < (MAX_REV + 1); i++)
425
svn_fs_root_t *rev_root;
428
SVN_ERR(svn_fs_revision_root(&rev_root, fs, i, pool));
429
SVN_ERR(svn_fs_file_contents(&rstream, rev_root, "iota", pool));
430
SVN_ERR(svn_test__stream_to_string(&rstring, rstream, pool));
433
sb = svn_stringbuf_create("This is the file 'iota'.\n", pool);
435
sb = svn_stringbuf_create(get_rev_contents(i, pool), pool);
437
if (! svn_stringbuf_compare(rstring, sb))
438
return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
439
"Bad data in revision %ld.", i);
448
/* ------------------------------------------------------------------------ */
449
#define REPO_NAME "test-repo-commit-packed-fs"
453
commit_packed_fs(const svn_test_opts_t *opts,
458
svn_fs_root_t *txn_root;
459
const char *conflict;
460
svn_revnum_t after_rev;
462
/* Bail (with success) on known-untestable scenarios */
463
if ((strcmp(opts->fs_type, "fsfs") != 0)
464
|| (opts->server_minor_version && (opts->server_minor_version < 6)))
467
/* Create the packed FS and open it. */
468
SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, 5, pool));
469
SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, pool));
471
/* Now do a commit. */
472
SVN_ERR(svn_fs_begin_txn(&txn, fs, MAX_REV, pool));
473
SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
474
SVN_ERR(svn_test__set_file_contents(txn_root, "iota",
475
"How much better is it to get wisdom than gold! and to get "
476
"understanding rather to be chosen than silver!", pool));
477
SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, pool));
478
SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
486
/* ------------------------------------------------------------------------ */
487
#define REPO_NAME "test-repo-get-set-revprop-packed-fs"
491
get_set_revprop_packed_fs(const svn_test_opts_t *opts,
495
svn_string_t *prop_value;
497
/* Bail (with success) on known-untestable scenarios */
498
if ((strcmp(opts->fs_type, "fsfs") != 0)
499
|| (opts->server_minor_version && (opts->server_minor_version < 7)))
502
/* Create the packed FS and open it. */
503
SVN_ERR(prepare_revprop_repo(&fs, REPO_NAME, MAX_REV, SHARD_SIZE, opts,
506
/* Try to get revprop for revision 0
507
* (non-packed due to special handling). */
508
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, 0, SVN_PROP_REVISION_AUTHOR,
511
/* Try to change revprop for revision 0
512
* (non-packed due to special handling). */
513
SVN_ERR(svn_fs_change_rev_prop(fs, 0, SVN_PROP_REVISION_AUTHOR,
514
svn_string_create("tweaked-author", pool),
518
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, 0, SVN_PROP_REVISION_AUTHOR,
520
SVN_TEST_STRING_ASSERT(prop_value->data, "tweaked-author");
522
/* Try to get packed revprop for revision 5. */
523
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, 5, SVN_PROP_REVISION_AUTHOR,
526
/* Try to change packed revprop for revision 5. */
527
SVN_ERR(svn_fs_change_rev_prop(fs, 5, SVN_PROP_REVISION_AUTHOR,
528
svn_string_create("tweaked-author2", pool),
532
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, 5, SVN_PROP_REVISION_AUTHOR,
534
SVN_TEST_STRING_ASSERT(prop_value->data, "tweaked-author2");
542
/* ------------------------------------------------------------------------ */
543
#define REPO_NAME "test-repo-get-set-large-revprop-packed-fs"
547
get_set_large_revprop_packed_fs(const svn_test_opts_t *opts,
551
svn_string_t *prop_value;
554
/* Bail (with success) on known-untestable scenarios */
555
if ((strcmp(opts->fs_type, "fsfs") != 0)
556
|| (opts->server_minor_version && (opts->server_minor_version < 7)))
559
/* Create the packed FS and open it. */
560
SVN_ERR(prepare_revprop_repo(&fs, REPO_NAME, MAX_REV, SHARD_SIZE, opts,
563
/* Set commit messages to different, large values that fill the pack
564
* files but do not exceed the pack size limit. */
565
for (rev = 0; rev <= MAX_REV; ++rev)
566
SVN_ERR(svn_fs_change_rev_prop(fs, rev, SVN_PROP_REVISION_LOG,
567
large_log(rev, 15000, pool),
571
for (rev = 0; rev <= MAX_REV; ++rev)
573
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, rev,
574
SVN_PROP_REVISION_LOG, pool));
575
SVN_TEST_STRING_ASSERT(prop_value->data,
576
large_log(rev, 15000, pool)->data);
579
/* Put a larger revprop into the last, some middle and the first revision
580
* of a pack. This should cause the packs to split in the middle. */
581
SVN_ERR(svn_fs_change_rev_prop(fs, 3, SVN_PROP_REVISION_LOG,
582
/* rev 0 is not packed */
583
large_log(3, 37000, pool),
585
SVN_ERR(svn_fs_change_rev_prop(fs, 5, SVN_PROP_REVISION_LOG,
586
large_log(5, 25000, pool),
588
SVN_ERR(svn_fs_change_rev_prop(fs, 8, SVN_PROP_REVISION_LOG,
589
large_log(8, 25000, pool),
593
for (rev = 0; rev <= MAX_REV; ++rev)
595
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, rev,
596
SVN_PROP_REVISION_LOG, pool));
599
SVN_TEST_STRING_ASSERT(prop_value->data,
600
large_log(rev, 37000, pool)->data);
601
else if (rev == 5 || rev == 8)
602
SVN_TEST_STRING_ASSERT(prop_value->data,
603
large_log(rev, 25000, pool)->data);
605
SVN_TEST_STRING_ASSERT(prop_value->data,
606
large_log(rev, 15000, pool)->data);
615
/* ------------------------------------------------------------------------ */
616
#define REPO_NAME "test-repo-get-set-huge-revprop-packed-fs"
620
get_set_huge_revprop_packed_fs(const svn_test_opts_t *opts,
624
svn_string_t *prop_value;
627
/* Bail (with success) on known-untestable scenarios */
628
if ((strcmp(opts->fs_type, "fsfs") != 0)
629
|| (opts->server_minor_version && (opts->server_minor_version < 7)))
632
/* Create the packed FS and open it. */
633
SVN_ERR(prepare_revprop_repo(&fs, REPO_NAME, MAX_REV, SHARD_SIZE, opts,
636
/* Set commit messages to different values */
637
for (rev = 0; rev <= MAX_REV; ++rev)
638
SVN_ERR(svn_fs_change_rev_prop(fs, rev, SVN_PROP_REVISION_LOG,
639
default_log(rev, pool),
643
for (rev = 0; rev <= MAX_REV; ++rev)
645
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, rev,
646
SVN_PROP_REVISION_LOG, pool));
647
SVN_TEST_STRING_ASSERT(prop_value->data, default_log(rev, pool)->data);
650
/* Put a huge revprop into the last, some middle and the first revision
651
* of a pack. They will cause the pack files to split accordingly. */
652
SVN_ERR(svn_fs_change_rev_prop(fs, 3, SVN_PROP_REVISION_LOG,
655
SVN_ERR(svn_fs_change_rev_prop(fs, 5, SVN_PROP_REVISION_LOG,
658
SVN_ERR(svn_fs_change_rev_prop(fs, 8, SVN_PROP_REVISION_LOG,
663
for (rev = 0; rev <= MAX_REV; ++rev)
665
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, rev,
666
SVN_PROP_REVISION_LOG, pool));
668
if (rev == 3 || rev == 5 || rev == 8)
669
SVN_TEST_STRING_ASSERT(prop_value->data,
670
huge_log(rev, pool)->data);
672
SVN_TEST_STRING_ASSERT(prop_value->data,
673
default_log(rev, pool)->data);
682
/* ------------------------------------------------------------------------ */
683
/* Regression test for issue #3571 (fsfs 'svnadmin recover' expects
684
youngest revprop to be outside revprops.db). */
685
#define REPO_NAME "test-repo-recover-fully-packed"
689
recover_fully_packed(const svn_test_opts_t *opts,
695
svn_fs_root_t *txn_root;
696
const char *conflict;
697
svn_revnum_t after_rev;
700
/* Bail (with success) on known-untestable scenarios */
701
if ((strcmp(opts->fs_type, "fsfs") != 0)
702
|| (opts->server_minor_version && (opts->server_minor_version < 7)))
705
/* Create a packed FS for which every revision will live in a pack
706
digest file, and then recover it. */
707
SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE, pool));
708
SVN_ERR(svn_fs_recover(REPO_NAME, NULL, NULL, pool));
710
/* Add another revision, re-pack, re-recover. */
711
subpool = svn_pool_create(pool);
712
SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, subpool));
713
SVN_ERR(svn_fs_begin_txn(&txn, fs, MAX_REV, subpool));
714
SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
715
SVN_ERR(svn_test__set_file_contents(txn_root, "A/mu", "new-mu", subpool));
716
SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));
717
SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
718
svn_pool_destroy(subpool);
719
SVN_ERR(svn_fs_pack(REPO_NAME, NULL, NULL, NULL, NULL, pool));
720
SVN_ERR(svn_fs_recover(REPO_NAME, NULL, NULL, pool));
722
/* Now, delete the youngest revprop file, and recover again. This
723
time we want to see an error! */
724
SVN_ERR(svn_io_remove_file2(
725
svn_dirent_join_many(pool, REPO_NAME, PATH_REVPROPS_DIR,
726
apr_psprintf(pool, "%ld/%ld",
727
after_rev / SHARD_SIZE,
731
err = svn_fs_recover(REPO_NAME, NULL, NULL, pool);
733
return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
734
"Expected SVN_ERR_FS_CORRUPT error; got none");
735
if (err->apr_err != SVN_ERR_FS_CORRUPT)
736
return svn_error_create(SVN_ERR_TEST_FAILED, err,
737
"Expected SVN_ERR_FS_CORRUPT error; got:");
738
svn_error_clear(err);
745
/* ------------------------------------------------------------------------ */
746
/* Regression test for issue #4320 (fsfs file-hinting fails when reading a rep
747
from the transaction that is commiting rev = SHARD_SIZE). */
748
#define REPO_NAME "test-repo-file-hint-at-shard-boundary"
750
#define MAX_REV (SHARD_SIZE - 1)
752
file_hint_at_shard_boundary(const svn_test_opts_t *opts,
758
svn_fs_root_t *txn_root;
759
const char *file_contents;
760
svn_stringbuf_t *retrieved_contents;
761
svn_error_t *err = SVN_NO_ERROR;
763
/* Bail (with success) on known-untestable scenarios */
764
if ((strcmp(opts->fs_type, "fsfs") != 0)
765
|| (opts->server_minor_version && (opts->server_minor_version < 8)))
768
/* Create a packed FS and MAX_REV revisions */
769
SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE, pool));
771
/* Reopen the filesystem */
772
subpool = svn_pool_create(pool);
773
SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, subpool));
775
/* Revision = SHARD_SIZE */
776
file_contents = get_rev_contents(SHARD_SIZE, subpool);
777
SVN_ERR(svn_fs_begin_txn(&txn, fs, MAX_REV, subpool));
778
SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
779
SVN_ERR(svn_test__set_file_contents(txn_root, "iota", file_contents,
782
/* Retrieve the file. */
783
SVN_ERR(svn_test__get_file_contents(txn_root, "iota", &retrieved_contents,
785
if (strcmp(retrieved_contents->data, file_contents))
787
err = svn_error_create(SVN_ERR_TEST_FAILED, err,
788
"Retrieved incorrect contents from iota.");
791
/* Close the repo. */
792
svn_pool_destroy(subpool);
800
/* ------------------------------------------------------------------------ */
801
#define REPO_NAME "get_set_multiple_huge_revprops_packed_fs"
805
get_set_multiple_huge_revprops_packed_fs(const svn_test_opts_t *opts,
809
svn_string_t *prop_value;
812
/* Bail (with success) on known-untestable scenarios */
813
if ((strcmp(opts->fs_type, "fsfs") != 0)
814
|| (opts->server_minor_version && (opts->server_minor_version < 7)))
817
/* Create the packed FS and open it. */
818
SVN_ERR(prepare_revprop_repo(&fs, REPO_NAME, MAX_REV, SHARD_SIZE, opts,
821
/* Set commit messages to different values */
822
for (rev = 0; rev <= MAX_REV; ++rev)
823
SVN_ERR(svn_fs_change_rev_prop(fs, rev, SVN_PROP_REVISION_LOG,
824
default_log(rev, pool),
828
for (rev = 0; rev <= MAX_REV; ++rev)
830
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, rev,
831
SVN_PROP_REVISION_LOG, pool));
832
SVN_TEST_STRING_ASSERT(prop_value->data, default_log(rev, pool)->data);
835
/* Put a huge revprop into revision 1 and 2. */
836
SVN_ERR(svn_fs_change_rev_prop(fs, 1, SVN_PROP_REVISION_LOG,
839
SVN_ERR(svn_fs_change_rev_prop(fs, 2, SVN_PROP_REVISION_LOG,
842
SVN_ERR(svn_fs_change_rev_prop(fs, 5, SVN_PROP_REVISION_LOG,
845
SVN_ERR(svn_fs_change_rev_prop(fs, 6, SVN_PROP_REVISION_LOG,
850
for (rev = 0; rev <= MAX_REV; ++rev)
852
SVN_ERR(svn_fs_revision_prop(&prop_value, fs, rev,
853
SVN_PROP_REVISION_LOG, pool));
855
if (rev == 1 || rev == 2 || rev == 5 || rev == 6)
856
SVN_TEST_STRING_ASSERT(prop_value->data,
857
huge_log(rev, pool)->data);
859
SVN_TEST_STRING_ASSERT(prop_value->data,
860
default_log(rev, pool)->data);
869
/* ------------------------------------------------------------------------ */
871
#define REPO_NAME "revprop_caching_on_off"
873
revprop_caching_on_off(const svn_test_opts_t *opts,
878
apr_hash_t *fs_config;
880
const svn_string_t *another_value_for_avoiding_warnings_from_a_broken_api;
881
const svn_string_t *new_value = svn_string_create("new", pool);
883
if (strcmp(opts->fs_type, "fsfs") != 0)
884
return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, NULL);
886
/* Open two filesystem objects, enable revision property caching
888
SVN_ERR(svn_test__create_fs(&fs1, REPO_NAME, opts, pool));
890
fs_config = apr_hash_make(pool);
891
apr_hash_set(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
892
APR_HASH_KEY_STRING, "1");
894
SVN_ERR(svn_fs_open(&fs2, svn_fs_path(fs1, pool), fs_config, pool));
896
/* With inefficient named atomics, the filesystem will output a warning
897
and disable the revprop caching, but we still would like to test
898
these cases. Ignore the warning(s). */
899
svn_fs_set_warning_func(fs2, ignore_fs_warnings, NULL);
901
SVN_ERR(svn_fs_revision_prop(&value, fs2, 0, "svn:date", pool));
902
another_value_for_avoiding_warnings_from_a_broken_api = value;
903
SVN_ERR(svn_fs_change_rev_prop2(
905
&another_value_for_avoiding_warnings_from_a_broken_api,
908
/* Expect the change to be visible through both objects.*/
909
SVN_ERR(svn_fs_revision_prop(&value, fs1, 0, "svn:date", pool));
910
SVN_TEST_STRING_ASSERT(value->data, "new");
912
SVN_ERR(svn_fs_revision_prop(&value, fs2, 0, "svn:date", pool));
913
SVN_TEST_STRING_ASSERT(value->data, "new");
920
/* ------------------------------------------------------------------------ */
922
/* The test table. */
924
struct svn_test_descriptor_t test_funcs[] =
927
SVN_TEST_OPTS_PASS(pack_filesystem,
928
"pack a FSFS filesystem"),
929
SVN_TEST_OPTS_PASS(pack_even_filesystem,
930
"pack FSFS where revs % shard = 0"),
931
SVN_TEST_OPTS_PASS(read_packed_fs,
932
"read from a packed FSFS filesystem"),
933
SVN_TEST_OPTS_PASS(commit_packed_fs,
934
"commit to a packed FSFS filesystem"),
935
SVN_TEST_OPTS_PASS(get_set_revprop_packed_fs,
936
"get/set revprop while packing FSFS filesystem"),
937
SVN_TEST_OPTS_PASS(get_set_large_revprop_packed_fs,
938
"get/set large packed revprops in FSFS"),
939
SVN_TEST_OPTS_PASS(get_set_huge_revprop_packed_fs,
940
"get/set huge packed revprops in FSFS"),
941
SVN_TEST_OPTS_PASS(recover_fully_packed,
942
"recover a fully packed filesystem"),
943
SVN_TEST_OPTS_PASS(file_hint_at_shard_boundary,
944
"test file hint at shard boundary"),
945
SVN_TEST_OPTS_PASS(get_set_multiple_huge_revprops_packed_fs,
946
"set multiple huge revprops in packed FSFS"),
947
SVN_TEST_OPTS_PASS(revprop_caching_on_off,
948
"change revprops with enabled and disabled caching"),