aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/README6
-rw-r--r--t/helper/test-advise.c2
-rw-r--r--t/helper/test-config.c2
-rw-r--r--t/helper/test-example-tap.c35
-rw-r--r--t/helper/test-hashmap.c98
-rw-r--r--t/helper/test-read-midx.c24
-rw-r--r--t/helper/test-ref-store.c2
-rw-r--r--t/helper/test-reftable.c1
-rw-r--r--t/helper/test-userdiff.c2
-rw-r--r--t/lib-bitmap.sh6
-rw-r--r--t/lib-midx.sh28
-rwxr-xr-xt/t0011-hashmap.sh260
-rwxr-xr-xt/t0033-safe-directory.sh178
-rwxr-xr-xt/t0080-unit-test-output.sh60
-rwxr-xr-xt/t0210-trace2-normal.sh2
-rwxr-xr-xt/t0410-partial-clone.sh2
-rwxr-xr-xt/t0602-reffiles-fsck.sh92
-rwxr-xr-xt/t0610-reftable-basics.sh21
-rwxr-xr-xt/t1001-read-tree-m-2way.sh2
-rwxr-xr-xt/t1006-cat-file.sh1
-rwxr-xr-xt/t1050-large.sh1
-rwxr-xr-xt/t1450-fsck.sh1
-rwxr-xr-xt/t1601-index-bogus.sh2
-rwxr-xr-xt/t3206-range-diff.sh52
-rwxr-xr-xt/t3310-notes-merge-manual-resolve.sh1
-rwxr-xr-xt/t3311-notes-merge-fanout.sh1
-rwxr-xr-xt/t3404-rebase-interactive.sh1
-rwxr-xr-xt/t3435-rebase-gpg-sign.sh1
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh1
-rwxr-xr-xt/t3510-cherry-pick-sequence.sh1
-rwxr-xr-xt/t3705-add-sparse-checkout.sh1
-rwxr-xr-xt/t4013-diff-various.sh1
-rwxr-xr-xt/t4014-format-patch.sh1
-rwxr-xr-xt/t4018-diff-funcname.sh1
-rwxr-xr-xt/t4030-diff-textconv.sh2
-rwxr-xr-xt/t4042-diff-textconv-caching.sh2
-rwxr-xr-xt/t4048-diff-combined-binary.sh1
-rwxr-xr-xt/t4064-diff-oidfind.sh2
-rwxr-xr-xt/t4065-diff-anchored.sh1
-rwxr-xr-xt/t4068-diff-symmetric-merge-base.sh1
-rwxr-xr-xt/t4069-remerge-diff.sh36
-rwxr-xr-xt/t4108-apply-threeway.sh1
-rwxr-xr-xt/t4129-apply-samemode.sh2
-rwxr-xr-xt/t4209-log-pickaxe.sh2
-rwxr-xr-xt/t5310-pack-bitmaps.sh4
-rwxr-xr-xt/t5313-pack-bounds-checks.sh8
-rwxr-xr-xt/t5319-multi-pack-index.sh30
-rwxr-xr-xt/t5326-multi-pack-bitmaps.sh4
-rwxr-xr-xt/t5327-multi-pack-bitmaps-rev.sh6
-rwxr-xr-xt/t5332-multi-pack-reuse.sh2
-rwxr-xr-xt/t5334-incremental-multi-pack-index.sh46
-rwxr-xr-xt/t5509-fetch-push-namespaces.sh1
-rwxr-xr-xt/t5523-push-upstream.sh4
-rwxr-xr-xt/t5572-pull-submodule.sh1
-rwxr-xr-xt/t5802-connect-helper.sh2
-rwxr-xr-xt/t5814-proto-disable-ext.sh2
-rwxr-xr-xt/t5815-submodule-protos.sh2
-rwxr-xr-xt/t6020-bundle-misc.sh32
-rwxr-xr-xt/t6421-merge-partial-clone.sh1
-rwxr-xr-xt/t6428-merge-conflicts-sparse.sh1
-rwxr-xr-xt/t7004-tag.sh1144
-rwxr-xr-xt/t7008-filter-branch-null-sha1.sh1
-rwxr-xr-xt/t7030-verify-tag.sh1
-rwxr-xr-xt/t7418-submodule-sparse-gitmodules.sh1
-rwxr-xr-xt/t7424-submodule-mixed-ref-formats.sh144
-rwxr-xr-xt/t7700-repack.sh48
-rwxr-xr-xt/t7817-grep-sparse-checkout.sh1
-rwxr-xr-xt/t9300-fast-import.sh1
-rwxr-xr-xt/t9304-fast-import-marks.sh2
-rwxr-xr-xt/t9351-fast-export-anonymize.sh1
-rw-r--r--t/unit-tests/t-ctype.c4
-rw-r--r--t/unit-tests/t-example-decorate.c24
-rw-r--r--t/unit-tests/t-hashmap.c361
-rw-r--r--t/unit-tests/t-reftable-basics.c228
-rw-r--r--t/unit-tests/t-reftable-readwrite.c974
-rw-r--r--t/unit-tests/t-strvec.c416
-rw-r--r--t/unit-tests/test-lib.c36
-rw-r--r--t/unit-tests/test-lib.h20
78 files changed, 3034 insertions, 1459 deletions
diff --git a/t/README b/t/README
index 724ee58195..44c02d8129 100644
--- a/t/README
+++ b/t/README
@@ -445,9 +445,9 @@ GIT_TEST_MULTI_PACK_INDEX=<boolean>, when true, forces the multi-pack-
index to be written after every 'git repack' command, and overrides the
'core.multiPackIndex' setting to true.
-GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=<boolean>, when true, sets the
-'--bitmap' option on all invocations of 'git multi-pack-index write',
-and ignores pack-objects' '--write-bitmap-index'.
+GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=<boolean>, when true, sets
+the '--incremental' option on all invocations of 'git multi-pack-index
+write'.
GIT_TEST_SIDEBAND_ALL=<boolean>, when true, overrides the
'uploadpack.allowSidebandAll' setting to true, and when false, forces
diff --git a/t/helper/test-advise.c b/t/helper/test-advise.c
index 8a3fd0009a..6967c8e25c 100644
--- a/t/helper/test-advise.c
+++ b/t/helper/test-advise.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "advice.h"
#include "config.h"
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index ed444ca4c2..e193079ed5 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "config.h"
#include "setup.h"
diff --git a/t/helper/test-example-tap.c b/t/helper/test-example-tap.c
index d072ad559f..914af88e0a 100644
--- a/t/helper/test-example-tap.c
+++ b/t/helper/test-example-tap.c
@@ -72,6 +72,8 @@ static void t_empty(void)
int cmd__example_tap(int argc, const char **argv)
{
+ check(1);
+
test_res = TEST(check_res = check_int(1, ==, 1), "passing test");
TEST(t_res(1), "passing test and assertion return 1");
test_res = TEST(check_res = check_int(1, ==, 2), "failing test");
@@ -92,5 +94,38 @@ int cmd__example_tap(int argc, const char **argv)
test_res = TEST(t_empty(), "test with no checks");
TEST(check_int(test_res, ==, 0), "test with no checks returns 0");
+ if_test ("if_test passing test")
+ check_int(1, ==, 1);
+ if_test ("if_test failing test")
+ check_int(1, ==, 2);
+ if_test ("if_test passing TEST_TODO()")
+ TEST_TODO(check(0));
+ if_test ("if_test failing TEST_TODO()")
+ TEST_TODO(check(1));
+ if_test ("if_test test_skip()") {
+ check(0);
+ test_skip("missing prerequisite");
+ check(1);
+ }
+ if_test ("if_test test_skip() inside TEST_TODO()")
+ TEST_TODO((test_skip("missing prerequisite"), 1));
+ if_test ("if_test TEST_TODO() after failing check") {
+ check(0);
+ TEST_TODO(check(0));
+ }
+ if_test ("if_test failing check after TEST_TODO()") {
+ check(1);
+ TEST_TODO(check(0));
+ check(0);
+ }
+ if_test ("if_test messages from failing string and char comparison") {
+ check_str("\thello\\", "there\"\n");
+ check_str("NULL", NULL);
+ check_char('a', ==, '\n');
+ check_char('\\', ==, '\'');
+ }
+ if_test ("if_test test with no checks")
+ ; /* nothing */
+
return test_done();
}
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index 2912899558..195e6278be 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -12,11 +12,6 @@ struct test_entry
char key[FLEX_ARRAY];
};
-static const char *get_value(const struct test_entry *e)
-{
- return e->key + strlen(e->key) + 1;
-}
-
static int test_entry_cmp(const void *cmp_data,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
@@ -141,30 +136,16 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
/*
* Read stdin line by line and print result of commands to stdout:
*
- * hash key -> strhash(key) memhash(key) strihash(key) memihash(key)
- * put key value -> NULL / old value
- * get key -> NULL / value
- * remove key -> NULL / old value
- * iterate -> key1 value1\nkey2 value2\n...
- * size -> tablesize numentries
- *
* perfhashmap method rounds -> test hashmap.[ch] performance
*/
int cmd__hashmap(int argc, const char **argv)
{
struct string_list parts = STRING_LIST_INIT_NODUP;
struct strbuf line = STRBUF_INIT;
- int icase;
- struct hashmap map = HASHMAP_INIT(test_entry_cmp, &icase);
-
- /* init hash map */
- icase = argc > 1 && !strcmp("ignorecase", argv[1]);
/* process commands from stdin */
while (strbuf_getline(&line, stdin) != EOF) {
char *cmd, *p1, *p2;
- unsigned int hash = 0;
- struct test_entry *entry;
/* break line into command and up to two parameters */
string_list_setlen(&parts, 0);
@@ -180,84 +161,8 @@ int cmd__hashmap(int argc, const char **argv)
cmd = parts.items[0].string;
p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
- if (p1)
- hash = icase ? strihash(p1) : strhash(p1);
-
- if (!strcmp("add", cmd) && p1 && p2) {
-
- /* create entry with key = p1, value = p2 */
- entry = alloc_test_entry(hash, p1, p2);
-
- /* add to hashmap */
- hashmap_add(&map, &entry->ent);
-
- } else if (!strcmp("put", cmd) && p1 && p2) {
-
- /* create entry with key = p1, value = p2 */
- entry = alloc_test_entry(hash, p1, p2);
-
- /* add / replace entry */
- entry = hashmap_put_entry(&map, entry, ent);
-
- /* print and free replaced entry, if any */
- puts(entry ? get_value(entry) : "NULL");
- free(entry);
-
- } else if (!strcmp("get", cmd) && p1) {
- /* lookup entry in hashmap */
- entry = hashmap_get_entry_from_hash(&map, hash, p1,
- struct test_entry, ent);
-
- /* print result */
- if (!entry)
- puts("NULL");
- hashmap_for_each_entry_from(&map, entry, ent)
- puts(get_value(entry));
-
- } else if (!strcmp("remove", cmd) && p1) {
-
- /* setup static key */
- struct hashmap_entry key;
- struct hashmap_entry *rm;
- hashmap_entry_init(&key, hash);
-
- /* remove entry from hashmap */
- rm = hashmap_remove(&map, &key, p1);
- entry = rm ? container_of(rm, struct test_entry, ent)
- : NULL;
-
- /* print result and free entry*/
- puts(entry ? get_value(entry) : "NULL");
- free(entry);
-
- } else if (!strcmp("iterate", cmd)) {
- struct hashmap_iter iter;
-
- hashmap_for_each_entry(&map, &iter, entry,
- ent /* member name */)
- printf("%s %s\n", entry->key, get_value(entry));
-
- } else if (!strcmp("size", cmd)) {
-
- /* print table sizes */
- printf("%u %u\n", map.tablesize,
- hashmap_get_size(&map));
-
- } else if (!strcmp("intern", cmd) && p1) {
-
- /* test that strintern works */
- const char *i1 = strintern(p1);
- const char *i2 = strintern(p1);
- if (strcmp(i1, p1))
- printf("strintern(%s) returns %s\n", p1, i1);
- else if (i1 == p1)
- printf("strintern(%s) returns input pointer\n", p1);
- else if (i1 != i2)
- printf("strintern(%s) != strintern(%s)", i1, i2);
- else
- printf("%s\n", i1);
- } else if (!strcmp("perfhashmap", cmd) && p1 && p2) {
+ if (!strcmp("perfhashmap", cmd) && p1 && p2) {
perf_hashmap(atoi(p1), atoi(p2));
@@ -270,6 +175,5 @@ int cmd__hashmap(int argc, const char **argv)
string_list_clear(&parts, 0);
strbuf_release(&line);
- hashmap_clear_and_free(&map, struct test_entry, ent);
return 0;
}
diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c
index 83effc2b5f..69757e94fc 100644
--- a/t/helper/test-read-midx.c
+++ b/t/helper/test-read-midx.c
@@ -9,8 +9,10 @@
#include "packfile.h"
#include "setup.h"
#include "gettext.h"
+#include "pack-revindex.h"
-static int read_midx_file(const char *object_dir, int show_objects)
+static int read_midx_file(const char *object_dir, const char *checksum,
+ int show_objects)
{
uint32_t i;
struct multi_pack_index *m;
@@ -21,6 +23,13 @@ static int read_midx_file(const char *object_dir, int show_objects)
if (!m)
return 1;
+ if (checksum) {
+ while (m && strcmp(hash_to_hex(get_midx_checksum(m)), checksum))
+ m = m->base_midx;
+ if (!m)
+ return 1;
+ }
+
printf("header: %08x %d %d %d %d\n",
m->signature,
m->version,
@@ -54,7 +63,8 @@ static int read_midx_file(const char *object_dir, int show_objects)
struct pack_entry e;
for (i = 0; i < m->num_objects; i++) {
- nth_midxed_object_oid(&oid, m, i);
+ nth_midxed_object_oid(&oid, m,
+ i + m->num_objects_in_base);
fill_midx_entry(the_repository, &oid, &e, m);
printf("%s %"PRIu64"\t%s\n",
@@ -111,7 +121,7 @@ static int read_midx_bitmapped_packs(const char *object_dir)
if (!midx)
return 1;
- for (i = 0; i < midx->num_packs; i++) {
+ for (i = 0; i < midx->num_packs + midx->num_packs_in_base; i++) {
if (nth_bitmapped_pack(the_repository, midx, &pack, i) < 0)
return 1;
@@ -127,16 +137,16 @@ static int read_midx_bitmapped_packs(const char *object_dir)
int cmd__read_midx(int argc, const char **argv)
{
- if (!(argc == 2 || argc == 3))
- usage("read-midx [--show-objects|--checksum|--preferred-pack|--bitmap] <object-dir>");
+ if (!(argc == 2 || argc == 3 || argc == 4))
+ usage("read-midx [--show-objects|--checksum|--preferred-pack|--bitmap] <object-dir> <checksum>");
if (!strcmp(argv[1], "--show-objects"))
- return read_midx_file(argv[2], 1);
+ return read_midx_file(argv[2], argv[3], 1);
else if (!strcmp(argv[1], "--checksum"))
return read_midx_checksum(argv[2]);
else if (!strcmp(argv[1], "--preferred-pack"))
return read_midx_preferred_pack(argv[2]);
else if (!strcmp(argv[1], "--bitmap"))
return read_midx_bitmapped_packs(argv[2]);
- return read_midx_file(argv[1], 0);
+ return read_midx_file(argv[1], argv[2], 0);
}
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 637b8b294e..65346dee55 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -156,7 +156,7 @@ static int cmd_rename_ref(struct ref_store *refs, const char **argv)
return refs_rename_ref(refs, oldref, newref, logmsg);
}
-static int each_ref(const char *refname, const struct object_id *oid,
+static int each_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data UNUSED)
{
printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 623cf3f0f5..ded28ee5fb 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -6,7 +6,6 @@ int cmd__reftable(int argc, const char **argv)
{
/* test from simple to complex. */
block_test_main(argc, argv);
- readwrite_test_main(argc, argv);
stack_test_main(argc, argv);
return 0;
}
diff --git a/t/helper/test-userdiff.c b/t/helper/test-userdiff.c
index 0ce31ce59f..94c48ababb 100644
--- a/t/helper/test-userdiff.c
+++ b/t/helper/test-userdiff.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "test-tool.h"
#include "setup.h"
#include "userdiff.h"
diff --git a/t/lib-bitmap.sh b/t/lib-bitmap.sh
index f595937094..62aa6744a6 100644
--- a/t/lib-bitmap.sh
+++ b/t/lib-bitmap.sh
@@ -1,6 +1,8 @@
# Helpers for scripts testing bitmap functionality; see t5310 for
# example usage.
+. "$TEST_DIRECTORY"/lib-midx.sh
+
objdir=.git/objects
midx=$objdir/pack/multi-pack-index
@@ -264,10 +266,6 @@ have_delta () {
test_cmp expect actual
}
-midx_checksum () {
- test-tool read-midx --checksum "$1"
-}
-
# midx_pack_source <obj>
midx_pack_source () {
test-tool read-midx --show-objects .git/objects | grep "^$1 " | cut -f2
diff --git a/t/lib-midx.sh b/t/lib-midx.sh
index 1261994744..e38c609604 100644
--- a/t/lib-midx.sh
+++ b/t/lib-midx.sh
@@ -6,3 +6,31 @@ test_midx_consistent () {
test_cmp expect actual &&
git multi-pack-index --object-dir=$1 verify
}
+
+midx_checksum () {
+ test-tool read-midx --checksum "$1"
+}
+
+midx_git_two_modes () {
+ git -c core.multiPackIndex=false $1 >expect &&
+ git -c core.multiPackIndex=true $1 >actual &&
+ if [ "$2" = "sorted" ]
+ then
+ sort <expect >expect.sorted &&
+ mv expect.sorted expect &&
+ sort <actual >actual.sorted &&
+ mv actual.sorted actual
+ fi &&
+ test_cmp expect actual
+}
+
+compare_results_with_midx () {
+ MSG=$1
+ test_expect_success "check normal git operations: $MSG" '
+ midx_git_two_modes "rev-list --objects --all" &&
+ midx_git_two_modes "log --raw" &&
+ midx_git_two_modes "count-objects --verbose" &&
+ midx_git_two_modes "cat-file --batch-all-objects --batch-check" &&
+ midx_git_two_modes "cat-file --batch-all-objects --batch-check --unordered" sorted
+ '
+}
diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh
deleted file mode 100755
index 46e74ad107..0000000000
--- a/t/t0011-hashmap.sh
+++ /dev/null
@@ -1,260 +0,0 @@
-#!/bin/sh
-
-test_description='test hashmap and string hash functions'
-
-TEST_PASSES_SANITIZE_LEAK=true
-. ./test-lib.sh
-
-test_hashmap() {
- echo "$1" | test-tool hashmap $3 > actual &&
- echo "$2" > expect &&
- test_cmp expect actual
-}
-
-test_expect_success 'put' '
-
-test_hashmap "put key1 value1
-put key2 value2
-put fooBarFrotz value3
-put foobarfrotz value4
-size" "NULL
-NULL
-NULL
-NULL
-64 4"
-
-'
-
-test_expect_success 'put (case insensitive)' '
-
-test_hashmap "put key1 value1
-put key2 value2
-put fooBarFrotz value3
-size" "NULL
-NULL
-NULL
-64 3" ignorecase
-
-'
-
-test_expect_success 'replace' '
-
-test_hashmap "put key1 value1
-put key1 value2
-put fooBarFrotz value3
-put fooBarFrotz value4
-size" "NULL
-value1
-NULL
-value3
-64 2"
-
-'
-
-test_expect_success 'replace (case insensitive)' '
-
-test_hashmap "put key1 value1
-put Key1 value2
-put fooBarFrotz value3
-put foobarfrotz value4
-size" "NULL
-value1
-NULL
-value3
-64 2" ignorecase
-
-'
-
-test_expect_success 'get' '
-
-test_hashmap "put key1 value1
-put key2 value2
-put fooBarFrotz value3
-put foobarfrotz value4
-get key1
-get key2
-get fooBarFrotz
-get notInMap" "NULL
-NULL
-NULL
-NULL
-value1
-value2
-value3
-NULL"
-
-'
-
-test_expect_success 'get (case insensitive)' '
-
-test_hashmap "put key1 value1
-put key2 value2
-put fooBarFrotz value3
-get Key1
-get keY2
-get foobarfrotz
-get notInMap" "NULL
-NULL
-NULL
-value1
-value2
-value3
-NULL" ignorecase
-
-'
-
-test_expect_success 'add' '
-
-test_hashmap "add key1 value1
-add key1 value2
-add fooBarFrotz value3
-add fooBarFrotz value4
-get key1
-get fooBarFrotz
-get notInMap" "value2
-value1
-value4
-value3
-NULL"
-
-'
-
-test_expect_success 'add (case insensitive)' '
-
-test_hashmap "add key1 value1
-add Key1 value2
-add fooBarFrotz value3
-add foobarfrotz value4
-get key1
-get Foobarfrotz
-get notInMap" "value2
-value1
-value4
-value3
-NULL" ignorecase
-
-'
-
-test_expect_success 'remove' '
-
-test_hashmap "put key1 value1
-put key2 value2
-put fooBarFrotz value3
-remove key1
-remove key2
-remove notInMap
-size" "NULL
-NULL
-NULL
-value1
-value2
-NULL
-64 1"
-
-'
-
-test_expect_success 'remove (case insensitive)' '
-
-test_hashmap "put key1 value1
-put key2 value2
-put fooBarFrotz value3
-remove Key1
-remove keY2
-remove notInMap
-size" "NULL
-NULL
-NULL
-value1
-value2
-NULL
-64 1" ignorecase
-
-'
-
-test_expect_success 'iterate' '
- test-tool hashmap >actual.raw <<-\EOF &&
- put key1 value1
- put key2 value2
- put fooBarFrotz value3
- iterate
- EOF
-
- cat >expect <<-\EOF &&
- NULL
- NULL
- NULL
- fooBarFrotz value3
- key1 value1
- key2 value2
- EOF
-
- sort <actual.raw >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'iterate (case insensitive)' '
- test-tool hashmap ignorecase >actual.raw <<-\EOF &&
- put key1 value1
- put key2 value2
- put fooBarFrotz value3
- iterate
- EOF
-
- cat >expect <<-\EOF &&
- NULL
- NULL
- NULL
- fooBarFrotz value3
- key1 value1
- key2 value2
- EOF
-
- sort <actual.raw >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'grow / shrink' '
-
- rm -f in &&
- rm -f expect &&
- for n in $(test_seq 51)
- do
- echo put key$n value$n >> in &&
- echo NULL >> expect || return 1
- done &&
- echo size >> in &&
- echo 64 51 >> expect &&
- echo put key52 value52 >> in &&
- echo NULL >> expect &&
- echo size >> in &&
- echo 256 52 >> expect &&
- for n in $(test_seq 12)
- do
- echo remove key$n >> in &&
- echo value$n >> expect || return 1
- done &&
- echo size >> in &&
- echo 256 40 >> expect &&
- echo remove key40 >> in &&
- echo value40 >> expect &&
- echo size >> in &&
- echo 64 39 >> expect &&
- test-tool hashmap <in >out &&
- test_cmp expect out
-
-'
-
-test_expect_success 'string interning' '
-
-test_hashmap "intern value1
-intern Value1
-intern value2
-intern value2
-" "value1
-Value1
-value2
-value2"
-
-'
-
-test_done
diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh
index 5fe61f1291..e97a84764f 100755
--- a/t/t0033-safe-directory.sh
+++ b/t/t0033-safe-directory.sh
@@ -119,4 +119,182 @@ test_expect_success 'local clone of unowned repo accepted in safe directory' '
test_path_is_dir target
'
+test_expect_success SYMLINKS 'checked paths are normalized' '
+ test_when_finished "rm -rf repository; rm -f repo" &&
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global --unset-all safe.directory
+ ) &&
+ git init repository &&
+ ln -s repository repo &&
+ (
+ cd repository &&
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ test_commit sample
+ ) &&
+
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global safe.directory "$(pwd)/repository"
+ ) &&
+ git -C repository for-each-ref &&
+ git -C repository/ for-each-ref &&
+ git -C repo for-each-ref &&
+ git -C repo/ for-each-ref &&
+ test_must_fail git -C repository/.git for-each-ref &&
+ test_must_fail git -C repository/.git/ for-each-ref &&
+ test_must_fail git -C repo/.git for-each-ref &&
+ test_must_fail git -C repo/.git/ for-each-ref
+'
+
+test_expect_success SYMLINKS 'checked leading paths are normalized' '
+ test_when_finished "rm -rf repository; rm -f repo" &&
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global --unset-all safe.directory
+ ) &&
+ mkdir -p repository &&
+ git init repository/s &&
+ ln -s repository repo &&
+ (
+ cd repository/s &&
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ test_commit sample
+ ) &&
+
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global safe.directory "$(pwd)/repository/*"
+ ) &&
+ git -C repository/s for-each-ref &&
+ git -C repository/s/ for-each-ref &&
+ git -C repo/s for-each-ref &&
+ git -C repo/s/ for-each-ref &&
+ git -C repository/s/.git for-each-ref &&
+ git -C repository/s/.git/ for-each-ref &&
+ git -C repo/s/.git for-each-ref &&
+ git -C repo/s/.git/ for-each-ref
+'
+
+test_expect_success SYMLINKS 'configured paths are normalized' '
+ test_when_finished "rm -rf repository; rm -f repo" &&
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global --unset-all safe.directory
+ ) &&
+ git init repository &&
+ ln -s repository repo &&
+ (
+ cd repository &&
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ test_commit sample
+ ) &&
+
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global safe.directory "$(pwd)/repo"
+ ) &&
+ git -C repository for-each-ref &&
+ git -C repository/ for-each-ref &&
+ git -C repo for-each-ref &&
+ git -C repo/ for-each-ref &&
+ test_must_fail git -C repository/.git for-each-ref &&
+ test_must_fail git -C repository/.git/ for-each-ref &&
+ test_must_fail git -C repo/.git for-each-ref &&
+ test_must_fail git -C repo/.git/ for-each-ref
+'
+
+test_expect_success SYMLINKS 'configured leading paths are normalized' '
+ test_when_finished "rm -rf repository; rm -f repo" &&
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global --unset-all safe.directory
+ ) &&
+ mkdir -p repository &&
+ git init repository/s &&
+ ln -s repository repo &&
+ (
+ cd repository/s &&
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ test_commit sample
+ ) &&
+
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global safe.directory "$(pwd)/repo/*"
+ ) &&
+ git -C repository/s for-each-ref &&
+ git -C repository/s/ for-each-ref &&
+ git -C repository/s/.git for-each-ref &&
+ git -C repository/s/.git/ for-each-ref &&
+ git -C repo/s for-each-ref &&
+ git -C repo/s/ for-each-ref &&
+ git -C repo/s/.git for-each-ref &&
+ git -C repo/s/.git/ for-each-ref
+'
+
+test_expect_success 'safe.directory set to a dot' '
+ test_when_finished "rm -rf repository" &&
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global --unset-all safe.directory
+ ) &&
+ mkdir -p repository/subdir &&
+ git init repository &&
+ (
+ cd repository &&
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ test_commit sample
+ ) &&
+
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global safe.directory "."
+ ) &&
+ git -C repository for-each-ref &&
+ git -C repository/ for-each-ref &&
+ git -C repository/.git for-each-ref &&
+ git -C repository/.git/ for-each-ref &&
+
+ # What is allowed is repository/subdir but the repository
+ # path is repository.
+ test_must_fail git -C repository/subdir for-each-ref &&
+
+ # Likewise, repository .git/refs is allowed with "." but
+ # repository/.git that is accessed is not allowed.
+ test_must_fail git -C repository/.git/refs for-each-ref
+'
+
+test_expect_success 'safe.directory set to asterisk' '
+ test_when_finished "rm -rf repository" &&
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global --unset-all safe.directory
+ ) &&
+ mkdir -p repository/subdir &&
+ git init repository &&
+ (
+ cd repository &&
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ test_commit sample
+ ) &&
+
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ git config --global safe.directory "*"
+ ) &&
+ # these are trivial
+ git -C repository for-each-ref &&
+ git -C repository/ for-each-ref &&
+ git -C repository/.git for-each-ref &&
+ git -C repository/.git/ for-each-ref &&
+
+ # With "*", everything is allowed, and the repository is
+ # discovered, which is different behaviour from "." above.
+ git -C repository/subdir for-each-ref &&
+
+ # Likewise.
+ git -C repository/.git/refs for-each-ref
+'
+
test_done
diff --git a/t/t0080-unit-test-output.sh b/t/t0080-unit-test-output.sh
index 7bbb065d58..3c369c88e2 100755
--- a/t/t0080-unit-test-output.sh
+++ b/t/t0080-unit-test-output.sh
@@ -5,23 +5,24 @@ test_description='Test the output of the unit test framework'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-test_expect_success 'TAP output from unit tests' '
+test_expect_success 'TAP output from unit tests' - <<\EOT
cat >expect <<-EOF &&
+ # BUG: check outside of test at t/helper/test-example-tap.c:75
ok 1 - passing test
ok 2 - passing test and assertion return 1
- # check "1 == 2" failed at t/helper/test-example-tap.c:77
+ # check "1 == 2" failed at t/helper/test-example-tap.c:79
# left: 1
# right: 2
not ok 3 - failing test
ok 4 - failing test and assertion return 0
not ok 5 - passing TEST_TODO() # TODO
ok 6 - passing TEST_TODO() returns 1
- # todo check ${SQ}check(x)${SQ} succeeded at t/helper/test-example-tap.c:26
+ # todo check 'check(x)' succeeded at t/helper/test-example-tap.c:26
not ok 7 - failing TEST_TODO()
ok 8 - failing TEST_TODO() returns 0
# check "0" failed at t/helper/test-example-tap.c:31
# skipping test - missing prerequisite
- # skipping check ${SQ}1${SQ} at t/helper/test-example-tap.c:33
+ # skipping check '1' at t/helper/test-example-tap.c:33
ok 9 - test_skip() # SKIP
ok 10 - skipped test returns 1
# skipping test - missing prerequisite
@@ -39,21 +40,54 @@ test_expect_success 'TAP output from unit tests' '
# check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:63
# left: "NULL"
# right: NULL
- # check "${SQ}a${SQ} == ${SQ}\n${SQ}" failed at t/helper/test-example-tap.c:64
- # left: ${SQ}a${SQ}
- # right: ${SQ}\012${SQ}
- # check "${SQ}\\\\${SQ} == ${SQ}\\${SQ}${SQ}" failed at t/helper/test-example-tap.c:65
- # left: ${SQ}\\\\${SQ}
- # right: ${SQ}\\${SQ}${SQ}
+ # check "'a' == '\n'" failed at t/helper/test-example-tap.c:64
+ # left: 'a'
+ # right: '\012'
+ # check "'\\\\' == '\\''" failed at t/helper/test-example-tap.c:65
+ # left: '\\\\'
+ # right: '\\''
not ok 17 - messages from failing string and char comparison
- # BUG: test has no checks at t/helper/test-example-tap.c:92
+ # BUG: test has no checks at t/helper/test-example-tap.c:94
not ok 18 - test with no checks
ok 19 - test with no checks returns 0
- 1..19
+ ok 20 - if_test passing test
+ # check "1 == 2" failed at t/helper/test-example-tap.c:100
+ # left: 1
+ # right: 2
+ not ok 21 - if_test failing test
+ not ok 22 - if_test passing TEST_TODO() # TODO
+ # todo check 'check(1)' succeeded at t/helper/test-example-tap.c:104
+ not ok 23 - if_test failing TEST_TODO()
+ # check "0" failed at t/helper/test-example-tap.c:106
+ # skipping test - missing prerequisite
+ # skipping check '1' at t/helper/test-example-tap.c:108
+ ok 24 - if_test test_skip() # SKIP
+ # skipping test - missing prerequisite
+ ok 25 - if_test test_skip() inside TEST_TODO() # SKIP
+ # check "0" failed at t/helper/test-example-tap.c:113
+ not ok 26 - if_test TEST_TODO() after failing check
+ # check "0" failed at t/helper/test-example-tap.c:119
+ not ok 27 - if_test failing check after TEST_TODO()
+ # check "!strcmp("\thello\\\\", "there\"\n")" failed at t/helper/test-example-tap.c:122
+ # left: "\011hello\\\\"
+ # right: "there\"\012"
+ # check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:123
+ # left: "NULL"
+ # right: NULL
+ # check "'a' == '\n'" failed at t/helper/test-example-tap.c:124
+ # left: 'a'
+ # right: '\012'
+ # check "'\\\\' == '\\''" failed at t/helper/test-example-tap.c:125
+ # left: '\\\\'
+ # right: '\\''
+ not ok 28 - if_test messages from failing string and char comparison
+ # BUG: test has no checks at t/helper/test-example-tap.c:127
+ not ok 29 - if_test test with no checks
+ 1..29
EOF
! test-tool example-tap >actual &&
test_cmp expect actual
-'
+EOT
test_done
diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh
index c312657a12..b9adc94aab 100755
--- a/t/t0210-trace2-normal.sh
+++ b/t/t0210-trace2-normal.sh
@@ -2,7 +2,7 @@
test_description='test trace2 facility (normal target)'
-TEST_PASSES_SANITIZE_LEAK=false
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Turn off any inherited trace2 settings for this test.
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index 2c30c86e7b..34bdb3ab1f 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -5,8 +5,6 @@ test_description='partial clone'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
-# missing promisor objects cause repacks which write bitmaps to fail
-GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
# When enabled, some commands will write commit-graphs. This causes fsck
# to fail when delete_object() is called because fsck will attempt to
# verify the out-of-sync commit graph.
diff --git a/t/t0602-reffiles-fsck.sh b/t/t0602-reffiles-fsck.sh
new file mode 100755
index 0000000000..71a4d1a5ae
--- /dev/null
+++ b/t/t0602-reffiles-fsck.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+test_description='Test reffiles backend consistency check'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_DEFAULT_REF_FORMAT=files
+export GIT_TEST_DEFAULT_REF_FORMAT
+TEST_PASSES_SANITIZE_LEAK=true
+
+. ./test-lib.sh
+
+test_expect_success 'ref name should be checked' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ branch_dir_prefix=.git/refs/heads &&
+ tag_dir_prefix=.git/refs/tags &&
+ cd repo &&
+
+ git commit --allow-empty -m initial &&
+ git checkout -b branch-1 &&
+ git tag tag-1 &&
+ git commit --allow-empty -m second &&
+ git checkout -b branch-2 &&
+ git tag tag-2 &&
+ git tag multi_hierarchy/tag-2 &&
+
+ cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 &&
+ test_must_fail git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ error: refs/heads/.branch-1: badRefName: invalid refname format
+ EOF
+ rm $branch_dir_prefix/.branch-1 &&
+ test_cmp expect err &&
+
+ cp $branch_dir_prefix/branch-1 $branch_dir_prefix/@ &&
+ test_must_fail git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ error: refs/heads/@: badRefName: invalid refname format
+ EOF
+ rm $branch_dir_prefix/@ &&
+ test_cmp expect err &&
+
+ cp $tag_dir_prefix/multi_hierarchy/tag-2 $tag_dir_prefix/multi_hierarchy/@ &&
+ test_must_fail git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ error: refs/tags/multi_hierarchy/@: badRefName: invalid refname format
+ EOF
+ rm $tag_dir_prefix/multi_hierarchy/@ &&
+ test_cmp expect err &&
+
+ cp $tag_dir_prefix/tag-1 $tag_dir_prefix/tag-1.lock &&
+ git refs verify 2>err &&
+ rm $tag_dir_prefix/tag-1.lock &&
+ test_must_be_empty err &&
+
+ cp $tag_dir_prefix/tag-1 $tag_dir_prefix/.lock &&
+ test_must_fail git refs verify 2>err &&
+ cat >expect <<-EOF &&
+ error: refs/tags/.lock: badRefName: invalid refname format
+ EOF
+ rm $tag_dir_prefix/.lock &&
+ test_cmp expect err
+'
+
+test_expect_success 'ref name check should be adapted into fsck messages' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ branch_dir_prefix=.git/refs/heads &&
+ tag_dir_prefix=.git/refs/tags &&
+ cd repo &&
+ git commit --allow-empty -m initial &&
+ git checkout -b branch-1 &&
+ git tag tag-1 &&
+ git commit --allow-empty -m second &&
+ git checkout -b branch-2 &&
+ git tag tag-2 &&
+
+ cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 &&
+ git -c fsck.badRefName=warn refs verify 2>err &&
+ cat >expect <<-EOF &&
+ warning: refs/heads/.branch-1: badRefName: invalid refname format
+ EOF
+ rm $branch_dir_prefix/.branch-1 &&
+ test_cmp expect err &&
+
+ cp $branch_dir_prefix/branch-1 $branch_dir_prefix/@ &&
+ git -c fsck.badRefName=ignore refs verify 2>err &&
+ test_must_be_empty err
+'
+
+test_done
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index b06c46999d..37510c2b2a 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -478,19 +478,26 @@ test_expect_success "$command: auto compaction" '
test_oid blob17_2 | git hash-object -w --stdin &&
- # Lock all tables write some refs. Auto-compaction will be
- # unable to compact tables and thus fails gracefully, leaving
- # the stack in a sub-optimal state.
- ls .git/reftable/*.ref |
+ # Lock all tables, write some refs. Auto-compaction will be
+ # unable to compact tables and thus fails gracefully,
+ # compacting only those tables which are not locked.
+ ls .git/reftable/*.ref | sort |
while read table
do
- touch "$table.lock" || exit 1
+ touch "$table.lock" &&
+ basename "$table" >>tables.expect || exit 1
done &&
+ test_line_count = 2 .git/reftable/tables.list &&
git branch B &&
git branch C &&
- rm .git/reftable/*.lock &&
- test_line_count = 4 .git/reftable/tables.list &&
+ # The new tables are auto-compacted, but the locked tables are
+ # left intact.
+ test_line_count = 3 .git/reftable/tables.list &&
+ head -n 2 .git/reftable/tables.list >tables.head &&
+ test_cmp tables.expect tables.head &&
+
+ rm .git/reftable/*.lock &&
git $command --auto &&
test_line_count = 1 .git/reftable/tables.list
)
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 88c524f655..48a1550371 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -397,7 +397,7 @@ test_expect_success 'a/b vs a, plus c/d case setup.' '
test_expect_success 'a/b vs a, plus c/d case test.' '
read_tree_u_must_succeed -u -m "$treeH" "$treeM" &&
- git ls-files --stage | tee >treeMcheck.out &&
+ git ls-files --stage >treeMcheck.out &&
test_cmp treeM.out treeMcheck.out
'
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index ff9bf213aa..d36cd7c086 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -2,6 +2,7 @@
test_description='git cat-file'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_cmdmode_usage () {
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index c71932b024..ed638f6644 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -3,6 +3,7 @@
test_description='adding and checking out large blobs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'core.bigFileThreshold must be non-negative' '
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 8a456b1142..280cbf3e03 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -6,6 +6,7 @@ test_description='git fsck random collection of tests
* (main) A
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1601-index-bogus.sh b/t/t1601-index-bogus.sh
index 4171f1e141..5dcc101882 100755
--- a/t/t1601-index-bogus.sh
+++ b/t/t1601-index-bogus.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test handling of bogus index entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create tree with null sha1' '
diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index 973e20254b..86010931ab 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -534,9 +534,9 @@ test_expect_success 'dual-coloring' '
for prev in topic main..topic
do
test_expect_success "format-patch --range-diff=$prev" '
+ test_when_finished "rm -f 000?-*" &&
git format-patch --cover-letter --range-diff=$prev \
main..unmodified >actual &&
- test_when_finished "rm 000?-*" &&
test_line_count = 5 actual &&
test_grep "^Range-diff:$" 0000-* &&
grep "= 1: .* s/5/A" 0000-* &&
@@ -561,32 +561,32 @@ test_expect_success "explicit --no-cover-letter defeats implied --cover-letter"
'
test_expect_success 'format-patch --range-diff as commentary' '
+ test_when_finished "rm -f 0001-*" &&
git format-patch --range-diff=HEAD~1 HEAD~1 >actual &&
- test_when_finished "rm 0001-*" &&
test_line_count = 1 actual &&
test_grep "^Range-diff:$" 0001-* &&
grep "> 1: .* new message" 0001-*
'
test_expect_success 'format-patch --range-diff reroll-count with a non-integer' '
+ test_when_finished "rm -f v2.9-0001-*" &&
git format-patch --range-diff=HEAD~1 -v2.9 HEAD~1 >actual &&
- test_when_finished "rm v2.9-0001-*" &&
test_line_count = 1 actual &&
test_grep "^Range-diff:$" v2.9-0001-* &&
grep "> 1: .* new message" v2.9-0001-*
'
test_expect_success 'format-patch --range-diff reroll-count with a integer' '
+ test_when_finished "rm -f v2-0001-*" &&
git format-patch --range-diff=HEAD~1 -v2 HEAD~1 >actual &&
- test_when_finished "rm v2-0001-*" &&
test_line_count = 1 actual &&
test_grep "^Range-diff ..* v1:$" v2-0001-* &&
grep "> 1: .* new message" v2-0001-*
'
test_expect_success 'format-patch --range-diff with v0' '
+ test_when_finished "rm -f v0-0001-*" &&
git format-patch --range-diff=HEAD~1 -v0 HEAD~1 >actual &&
- test_when_finished "rm v0-0001-*" &&
test_line_count = 1 actual &&
test_grep "^Range-diff:$" v0-0001-* &&
grep "> 1: .* new message" v0-0001-*
@@ -607,9 +607,9 @@ test_expect_success 'basic with modified format.pretty without "commit "' '
'
test_expect_success 'range-diff compares notes by default' '
+ test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
git notes add -m "unmodified note" unmodified &&
- test_when_finished git notes remove topic unmodified &&
git range-diff --no-color main..topic main..unmodified \
>actual &&
sed s/Z/\ /g >expect <<-EOF &&
@@ -631,9 +631,9 @@ test_expect_success 'range-diff compares notes by default' '
'
test_expect_success 'range-diff with --no-notes' '
+ test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
git notes add -m "unmodified note" unmodified &&
- test_when_finished git notes remove topic unmodified &&
git range-diff --no-color --no-notes main..topic main..unmodified \
>actual &&
cat >expect <<-EOF &&
@@ -646,12 +646,12 @@ test_expect_success 'range-diff with --no-notes' '
'
test_expect_success 'range-diff with multiple --notes' '
+ test_when_finished "git notes --ref=note1 remove topic unmodified || :" &&
git notes --ref=note1 add -m "topic note1" topic &&
git notes --ref=note1 add -m "unmodified note1" unmodified &&
- test_when_finished git notes --ref=note1 remove topic unmodified &&
+ test_when_finished "git notes --ref=note2 remove topic unmodified || :" &&
git notes --ref=note2 add -m "topic note2" topic &&
git notes --ref=note2 add -m "unmodified note2" unmodified &&
- test_when_finished git notes --ref=note2 remove topic unmodified &&
git range-diff --no-color --notes=note1 --notes=note2 main..topic main..unmodified \
>actual &&
sed s/Z/\ /g >expect <<-EOF &&
@@ -679,12 +679,12 @@ test_expect_success 'range-diff with multiple --notes' '
# `range-diff` should act like `log` with regards to notes
test_expect_success 'range-diff with --notes=custom does not show default notes' '
+ test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
git notes add -m "unmodified note" unmodified &&
+ test_when_finished "git notes --ref=custom remove topic unmodified || :" &&
git notes --ref=custom add -m "topic note" topic &&
git notes --ref=custom add -m "unmodified note" unmodified &&
- test_when_finished git notes remove topic unmodified &&
- test_when_finished git notes --ref=custom remove topic unmodified &&
git range-diff --notes=custom main..topic main..unmodified \
>actual &&
! grep "## Notes ##" actual &&
@@ -692,12 +692,12 @@ test_expect_success 'range-diff with --notes=custom does not show default notes'
'
test_expect_success 'format-patch --range-diff does not compare notes by default' '
+ test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
git notes add -m "unmodified note" unmodified &&
- test_when_finished git notes remove topic unmodified &&
+ test_when_finished "rm -f 000?-*" &&
git format-patch --cover-letter --range-diff=$prev \
main..unmodified >actual &&
- test_when_finished "rm 000?-*" &&
test_line_count = 5 actual &&
test_grep "^Range-diff:$" 0000-* &&
grep "= 1: .* s/5/A" 0000-* &&
@@ -709,26 +709,26 @@ test_expect_success 'format-patch --range-diff does not compare notes by default
'
test_expect_success 'format-patch --notes=custom --range-diff only compares custom notes' '
+ test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
- git notes --ref=custom add -m "topic note (custom)" topic &&
git notes add -m "unmodified note" unmodified &&
+ test_when_finished "git notes --ref=custom remove topic unmodified || :" &&
+ git notes --ref=custom add -m "topic note (custom)" topic &&
git notes --ref=custom add -m "unmodified note (custom)" unmodified &&
- test_when_finished git notes remove topic unmodified &&
- test_when_finished git notes --ref=custom remove topic unmodified &&
+ test_when_finished "rm -f 000?-*" &&
git format-patch --notes=custom --cover-letter --range-diff=$prev \
main..unmodified >actual &&
- test_when_finished "rm 000?-*" &&
grep "## Notes (custom) ##" 0000-* &&
! grep "## Notes ##" 0000-*
'
test_expect_success 'format-patch --range-diff with --no-notes' '
+ test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
git notes add -m "unmodified note" unmodified &&
- test_when_finished git notes remove topic unmodified &&
+ test_when_finished "rm -f 000?-*" &&
git format-patch --no-notes --cover-letter --range-diff=$prev \
main..unmodified >actual &&
- test_when_finished "rm 000?-*" &&
test_line_count = 5 actual &&
test_grep "^Range-diff:$" 0000-* &&
grep "= 1: .* s/5/A" 0000-* &&
@@ -740,12 +740,12 @@ test_expect_success 'format-patch --range-diff with --no-notes' '
'
test_expect_success 'format-patch --range-diff with --notes' '
+ test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
git notes add -m "unmodified note" unmodified &&
- test_when_finished git notes remove topic unmodified &&
+ test_when_finished "rm -f 000?-*" &&
git format-patch --notes --cover-letter --range-diff=$prev \
main..unmodified >actual &&
- test_when_finished "rm 000?-*" &&
test_line_count = 5 actual &&
test_grep "^Range-diff:$" 0000-* &&
grep "= 1: .* s/5/A" 0000-* &&
@@ -768,13 +768,13 @@ test_expect_success 'format-patch --range-diff with --notes' '
'
test_expect_success 'format-patch --range-diff with format.notes config' '
+ test_when_finished "git notes remove topic unmodified || :" &&
git notes add -m "topic note" topic &&
git notes add -m "unmodified note" unmodified &&
- test_when_finished git notes remove topic unmodified &&
test_config format.notes true &&
+ test_when_finished "rm -f 000?-*" &&
git format-patch --cover-letter --range-diff=$prev \
main..unmodified >actual &&
- test_when_finished "rm 000?-*" &&
test_line_count = 5 actual &&
test_grep "^Range-diff:$" 0000-* &&
grep "= 1: .* s/5/A" 0000-* &&
@@ -797,15 +797,15 @@ test_expect_success 'format-patch --range-diff with format.notes config' '
'
test_expect_success 'format-patch --range-diff with multiple notes' '
+ test_when_finished "git notes --ref=note1 remove topic unmodified || :" &&
git notes --ref=note1 add -m "topic note1" topic &&
git notes --ref=note1 add -m "unmodified note1" unmodified &&
- test_when_finished git notes --ref=note1 remove topic unmodified &&
+ test_when_finished "git notes --ref=note2 remove topic unmodified || :" &&
git notes --ref=note2 add -m "topic note2" topic &&
git notes --ref=note2 add -m "unmodified note2" unmodified &&
- test_when_finished git notes --ref=note2 remove topic unmodified &&
+ test_when_finished "rm -f 000?-*" &&
git format-patch --notes=note1 --notes=note2 --cover-letter --range-diff=$prev \
main..unmodified >actual &&
- test_when_finished "rm 000?-*" &&
test_line_count = 5 actual &&
test_grep "^Range-diff:$" 0000-* &&
grep "= 1: .* s/5/A" 0000-* &&
diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh
index 597df5ebc0..04866b89be 100755
--- a/t/t3310-notes-merge-manual-resolve.sh
+++ b/t/t3310-notes-merge-manual-resolve.sh
@@ -5,6 +5,7 @@
test_description='Test notes merging with manual conflict resolution'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Set up a notes merge scenario with different kinds of conflicts
diff --git a/t/t3311-notes-merge-fanout.sh b/t/t3311-notes-merge-fanout.sh
index 5b675417e9..ce4144db0f 100755
--- a/t/t3311-notes-merge-fanout.sh
+++ b/t/t3311-notes-merge-fanout.sh
@@ -5,6 +5,7 @@
test_description='Test notes merging at various fanout levels'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
verify_notes () {
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index f92baad138..f171af3061 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -26,6 +26,7 @@ Initial setup:
touch file "conflict".
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3435-rebase-gpg-sign.sh b/t/t3435-rebase-gpg-sign.sh
index 6aa2aeb628..6e329fea7c 100755
--- a/t/t3435-rebase-gpg-sign.sh
+++ b/t/t3435-rebase-gpg-sign.sh
@@ -8,6 +8,7 @@ test_description='test rebase --[no-]gpg-sign'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-rebase.sh"
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index f3947b400a..10e9c91dbb 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -13,6 +13,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pristine_detach () {
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index 7eb52b12ed..93c725bac3 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -12,6 +12,7 @@ test_description='Test cherry-pick continuation features
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Repeat first match 10 times
diff --git a/t/t3705-add-sparse-checkout.sh b/t/t3705-add-sparse-checkout.sh
index 2bade9e804..6ae45a788d 100755
--- a/t/t3705-add-sparse-checkout.sh
+++ b/t/t3705-add-sparse-checkout.sh
@@ -2,6 +2,7 @@
test_description='git add in sparse checked out working trees'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
SPARSE_ENTRY_BLOB=""
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 3855d68dbc..87d248d034 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -8,6 +8,7 @@ test_description='Various diff formatting options'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 884f83fb8a..1c46e963e4 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -8,6 +8,7 @@ test_description='various format-patch tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index e026fac1f4..8128c30e7f 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -5,6 +5,7 @@
test_description='Test custom diff function name patterns'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh
index a39a626664..29f6d610c2 100755
--- a/t/t4030-diff-textconv.sh
+++ b/t/t4030-diff-textconv.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='diff.*.textconv tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
find_diff() {
diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh
index 8ebfa3c1be..a179205394 100755
--- a/t/t4042-diff-textconv-caching.sh
+++ b/t/t4042-diff-textconv-caching.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test textconv caching'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >helper <<'EOF'
diff --git a/t/t4048-diff-combined-binary.sh b/t/t4048-diff-combined-binary.sh
index 0260cf64f5..f399484bce 100755
--- a/t/t4048-diff-combined-binary.sh
+++ b/t/t4048-diff-combined-binary.sh
@@ -4,6 +4,7 @@ test_description='combined and merge diff handle binary files and textconv'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup binary merge conflict' '
diff --git a/t/t4064-diff-oidfind.sh b/t/t4064-diff-oidfind.sh
index 6d8c8986fc..846f285f77 100755
--- a/t/t4064-diff-oidfind.sh
+++ b/t/t4064-diff-oidfind.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test finding specific blobs in the revision walking'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup ' '
diff --git a/t/t4065-diff-anchored.sh b/t/t4065-diff-anchored.sh
index b3f510f040..647537c12e 100755
--- a/t/t4065-diff-anchored.sh
+++ b/t/t4065-diff-anchored.sh
@@ -2,6 +2,7 @@
test_description='anchored diff algorithm'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success '--anchored' '
diff --git a/t/t4068-diff-symmetric-merge-base.sh b/t/t4068-diff-symmetric-merge-base.sh
index eff63c16b0..4d6565e728 100755
--- a/t/t4068-diff-symmetric-merge-base.sh
+++ b/t/t4068-diff-symmetric-merge-base.sh
@@ -5,6 +5,7 @@ test_description='behavior of diff with symmetric-diff setups and --merge-base'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# build these situations:
diff --git a/t/t4069-remerge-diff.sh b/t/t4069-remerge-diff.sh
index 07323ebafe..df342850a0 100755
--- a/t/t4069-remerge-diff.sh
+++ b/t/t4069-remerge-diff.sh
@@ -2,6 +2,7 @@
test_description='remerge-diff handling'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This test is ort-specific
@@ -110,6 +111,41 @@ test_expect_success 'can filter out additional headers with pickaxe' '
test_must_be_empty actual
'
+test_expect_success 'remerge-diff also works for git-diff-tree' '
+ # With a clean merge
+ git diff-tree -r -p --remerge-diff --no-commit-id bc_resolution >actual &&
+ test_must_be_empty actual &&
+
+ # With both a resolved conflict and an unrelated change
+ cat <<-EOF >tmp &&
+ diff --git a/numbers b/numbers
+ remerge CONFLICT (content): Merge conflict in numbers
+ index a1fb731..6875544 100644
+ --- a/numbers
+ +++ b/numbers
+ @@ -1,13 +1,9 @@
+ 1
+ 2
+ -<<<<<<< b0ed5cb (change_a)
+ -three
+ -=======
+ -tres
+ ->>>>>>> 6cd3f82 (change_b)
+ +drei
+ 4
+ 5
+ 6
+ 7
+ -eight
+ +acht
+ 9
+ EOF
+ sed -e "s/[0-9a-f]\{7,\}/HASH/g" tmp >expect &&
+ git diff-tree -r -p --remerge-diff --no-commit-id ab_resolution >tmp &&
+ sed -e "s/[0-9a-f]\{7,\}/HASH/g" tmp >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'setup non-content conflicts' '
git switch --orphan base &&
diff --git a/t/t4108-apply-threeway.sh b/t/t4108-apply-threeway.sh
index c558282bc0..3211e1e65f 100755
--- a/t/t4108-apply-threeway.sh
+++ b/t/t4108-apply-threeway.sh
@@ -5,6 +5,7 @@ test_description='git apply --3way'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
print_sanitized_conflicted_diff () {
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
index d9a1084b5e..87ffd2b8e1 100755
--- a/t/t4129-apply-samemode.sh
+++ b/t/t4129-apply-samemode.sh
@@ -153,8 +153,8 @@ test_expect_success POSIXPERM 'patch mode for new file is canonicalized' '
test_expect_success POSIXPERM 'patch mode for deleted file is canonicalized' '
test_when_finished "git reset --hard" &&
echo content >non-canon &&
- git add non-canon &&
chmod 666 non-canon &&
+ git add non-canon &&
cat >patch <<-\EOF &&
diff --git a/non-canon b/non-canon
diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh
index 64e1623733..b42fdc54fc 100755
--- a/t/t4209-log-pickaxe.sh
+++ b/t/t4209-log-pickaxe.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='log --grep/--author/--regexp-ignore-case/-S/-G'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_log () {
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index d7fd71360e..a6de7c5764 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -5,10 +5,6 @@ test_description='exercise basic bitmap functionality'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-bitmap.sh
-# t5310 deals only with single-pack bitmaps, so don't write MIDX bitmaps in
-# their place.
-GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
-
# Likewise, allow individual tests to control whether or not they use
# the boundary-based traversal.
sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL
diff --git a/t/t5313-pack-bounds-checks.sh b/t/t5313-pack-bounds-checks.sh
index ceaa6700a2..86fc73f9fb 100755
--- a/t/t5313-pack-bounds-checks.sh
+++ b/t/t5313-pack-bounds-checks.sh
@@ -7,11 +7,11 @@ TEST_PASSES_SANITIZE_LEAK=true
clear_base () {
test_when_finished 'restore_base' &&
- rm -f $base
+ rm -r -f $base
}
restore_base () {
- cp base-backup/* .git/objects/pack/
+ cp -r base-backup/* .git/objects/pack/
}
do_pack () {
@@ -64,9 +64,9 @@ test_expect_success 'set up base packfile and variables' '
git commit -m base &&
git repack -ad &&
base=$(echo .git/objects/pack/*) &&
- chmod +w $base &&
+ chmod -R +w $base &&
mkdir base-backup &&
- cp $base base-backup/ &&
+ cp -r $base base-backup/ &&
object=$(git rev-parse HEAD:file)
'
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index ace5ac3b61..ce1b58c732 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -3,8 +3,11 @@
test_description='multi-pack-indexes'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-chunk.sh
+. "$TEST_DIRECTORY"/lib-midx.sh
GIT_TEST_MULTI_PACK_INDEX=0
+GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
objdir=.git/objects
HASH_LEN=$(test_oid rawsz)
@@ -107,30 +110,6 @@ test_expect_success 'write midx with one v1 pack' '
midx_read_expect 1 18 4 $objdir
'
-midx_git_two_modes () {
- git -c core.multiPackIndex=false $1 >expect &&
- git -c core.multiPackIndex=true $1 >actual &&
- if [ "$2" = "sorted" ]
- then
- sort <expect >expect.sorted &&
- mv expect.sorted expect &&
- sort <actual >actual.sorted &&
- mv actual.sorted actual
- fi &&
- test_cmp expect actual
-}
-
-compare_results_with_midx () {
- MSG=$1
- test_expect_success "check normal git operations: $MSG" '
- midx_git_two_modes "rev-list --objects --all" &&
- midx_git_two_modes "log --raw" &&
- midx_git_two_modes "count-objects --verbose" &&
- midx_git_two_modes "cat-file --batch-all-objects --batch-check" &&
- midx_git_two_modes "cat-file --batch-all-objects --batch-check --unordered" sorted
- '
-}
-
test_expect_success 'write midx with one v2 pack' '
git pack-objects --index-version=2,0x40 $objdir/pack/test <obj-list &&
git multi-pack-index --object-dir=$objdir write &&
@@ -600,8 +579,7 @@ test_expect_success 'repack preserves multi-pack-index when creating packs' '
compare_results_with_midx "after repack"
test_expect_success 'multi-pack-index and pack-bitmap' '
- GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \
- git -c repack.writeBitmaps=true repack -ad &&
+ git -c repack.writeBitmaps=true repack -ad &&
git multi-pack-index write &&
git rev-list --test-bitmap HEAD
'
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index 916da389b6..832b92619c 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -4,10 +4,10 @@ test_description='exercise basic multi-pack bitmap functionality'
. ./test-lib.sh
. "${TEST_DIRECTORY}/lib-bitmap.sh"
-# We'll be writing our own midx and bitmaps, so avoid getting confused by the
+# We'll be writing our own MIDX, so avoid getting confused by the
# automatic ones.
GIT_TEST_MULTI_PACK_INDEX=0
-GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
# This test exercise multi-pack bitmap functionality where the object order is
# stored and read from a special chunk within the MIDX, so use the default
diff --git a/t/t5327-multi-pack-bitmaps-rev.sh b/t/t5327-multi-pack-bitmaps-rev.sh
index e65e311cd7..9cac03a94b 100755
--- a/t/t5327-multi-pack-bitmaps-rev.sh
+++ b/t/t5327-multi-pack-bitmaps-rev.sh
@@ -5,10 +5,10 @@ test_description='exercise basic multi-pack bitmap functionality (.rev files)'
. ./test-lib.sh
. "${TEST_DIRECTORY}/lib-bitmap.sh"
-# We'll be writing our own midx and bitmaps, so avoid getting confused by the
-# automatic ones.
+# We'll be writing our own MIDX, so avoid getting confused by the automatic
+# ones.
GIT_TEST_MULTI_PACK_INDEX=0
-GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
# Unlike t5326, this test exercise multi-pack bitmap functionality where the
# object order is stored in a separate .rev file.
diff --git a/t/t5332-multi-pack-reuse.sh b/t/t5332-multi-pack-reuse.sh
index ed823f37bc..941e73d354 100755
--- a/t/t5332-multi-pack-reuse.sh
+++ b/t/t5332-multi-pack-reuse.sh
@@ -6,6 +6,8 @@ TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-bitmap.sh
+GIT_TEST_MULTI_PACK_INDEX=0
+GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
objdir=.git/objects
packdir=$objdir/pack
diff --git a/t/t5334-incremental-multi-pack-index.sh b/t/t5334-incremental-multi-pack-index.sh
new file mode 100755
index 0000000000..c3b08acc73
--- /dev/null
+++ b/t/t5334-incremental-multi-pack-index.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+test_description='incremental multi-pack-index'
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-midx.sh
+
+GIT_TEST_MULTI_PACK_INDEX=0
+export GIT_TEST_MULTI_PACK_INDEX
+
+objdir=.git/objects
+packdir=$objdir/pack
+midxdir=$packdir/multi-pack-index.d
+midx_chain=$midxdir/multi-pack-index-chain
+
+test_expect_success 'convert non-incremental MIDX to incremental' '
+ test_commit base &&
+ git repack -ad &&
+ git multi-pack-index write &&
+
+ test_path_is_file $packdir/multi-pack-index &&
+ old_hash="$(midx_checksum $objdir)" &&
+
+ test_commit other &&
+ git repack -d &&
+ git multi-pack-index write --incremental &&
+
+ test_path_is_missing $packdir/multi-pack-index &&
+ test_path_is_file $midx_chain &&
+ test_line_count = 2 $midx_chain &&
+ grep $old_hash $midx_chain
+'
+
+compare_results_with_midx 'incremental MIDX'
+
+test_expect_success 'convert incremental to non-incremental' '
+ test_commit squash &&
+ git repack -d &&
+ git multi-pack-index write &&
+
+ test_path_is_file $packdir/multi-pack-index &&
+ test_dir_is_empty $midxdir
+'
+
+compare_results_with_midx 'non-incremental MIDX conversion'
+
+test_done
diff --git a/t/t5509-fetch-push-namespaces.sh b/t/t5509-fetch-push-namespaces.sh
index 31553b48df..05090feaf9 100755
--- a/t/t5509-fetch-push-namespaces.sh
+++ b/t/t5509-fetch-push-namespaces.sh
@@ -4,6 +4,7 @@ test_description='fetch/push involving ref namespaces'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index 1f859ade16..4ad36a31e1 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -124,14 +124,14 @@ test_expect_success TTY 'push --no-progress suppresses progress' '
test_expect_success TTY 'quiet push' '
ensure_fresh_upstream &&
- test_terminal git push --quiet --no-progress upstream main 2>&1 | tee output &&
+ test_terminal git push --quiet --no-progress upstream main >output 2>&1 &&
test_must_be_empty output
'
test_expect_success TTY 'quiet push -u' '
ensure_fresh_upstream &&
- test_terminal git push --quiet -u --no-progress upstream main 2>&1 | tee output &&
+ test_terminal git push --quiet -u --no-progress upstream main >output 2>&1 &&
test_must_be_empty output
'
diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh
index 51744521f7..916e58c166 100755
--- a/t/t5572-pull-submodule.sh
+++ b/t/t5572-pull-submodule.sh
@@ -5,6 +5,7 @@ test_description='pull can handle submodules'
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh
diff --git a/t/t5802-connect-helper.sh b/t/t5802-connect-helper.sh
index c6c2661878..dd3e6235cd 100755
--- a/t/t5802-connect-helper.sh
+++ b/t/t5802-connect-helper.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='ext::cmd remote "connect" helper'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5814-proto-disable-ext.sh b/t/t5814-proto-disable-ext.sh
index 9d6f7dfa2c..6fe1a98b2a 100755
--- a/t/t5814-proto-disable-ext.sh
+++ b/t/t5814-proto-disable-ext.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test disabling of remote-helper paths in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-proto-disable.sh"
diff --git a/t/t5815-submodule-protos.sh b/t/t5815-submodule-protos.sh
index 4d5956cc18..fe899ee82d 100755
--- a/t/t5815-submodule-protos.sh
+++ b/t/t5815-submodule-protos.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test protocol filtering with submodules'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-proto-disable.sh
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
index fe75a06572..34b5cd62c2 100755
--- a/t/t6020-bundle-misc.sh
+++ b/t/t6020-bundle-misc.sh
@@ -652,4 +652,36 @@ test_expect_success 'send a bundle to standard output' '
test_cmp expect actual
'
+test_expect_success 'unbundle outside of a repository' '
+ git bundle create some.bundle HEAD &&
+ echo "fatal: Need a repository to unbundle." >expect &&
+ nongit test_must_fail git bundle unbundle "$(pwd)/some.bundle" 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success 'list-heads outside of a repository' '
+ git bundle create some.bundle HEAD &&
+ cat >expect <<-EOF &&
+ $(git rev-parse HEAD) HEAD
+ EOF
+ nongit git bundle list-heads "$(pwd)/some.bundle" >actual &&
+ test_cmp expect actual
+'
+
+for hash in sha1 sha256
+do
+ test_expect_success "list-heads with bundle using $hash" '
+ test_when_finished "rm -rf hash" &&
+ git init --object-format=$hash hash &&
+ test_commit -C hash initial &&
+ git -C hash bundle create hash.bundle HEAD &&
+
+ cat >expect <<-EOF &&
+ $(git -C hash rev-parse HEAD) HEAD
+ EOF
+ git bundle list-heads hash/hash.bundle >actual &&
+ test_cmp expect actual
+ '
+done
+
test_done
diff --git a/t/t6421-merge-partial-clone.sh b/t/t6421-merge-partial-clone.sh
index b99f29ef9b..30349a466e 100755
--- a/t/t6421-merge-partial-clone.sh
+++ b/t/t6421-merge-partial-clone.sh
@@ -26,6 +26,7 @@ test_description="limiting blob downloads when merging with partial clones"
# underscore notation is to differentiate different
# files that might be renamed into each other's paths.)
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-merge.sh
diff --git a/t/t6428-merge-conflicts-sparse.sh b/t/t6428-merge-conflicts-sparse.sh
index 9919c3fa7c..8a79bc2e92 100755
--- a/t/t6428-merge-conflicts-sparse.sh
+++ b/t/t6428-merge-conflicts-sparse.sh
@@ -22,6 +22,7 @@ test_description="merge cases"
# underscore notation is to differentiate different
# files that might be renamed into each other's paths.)
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-merge.sh
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index fa6336edf9..b1316e62f4 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -61,8 +61,9 @@ test_expect_success 'sort tags, ignore case' '
)
'
-test_expect_success 'looking for a tag in an empty tree should fail' \
- '! (tag_exists mytag)'
+test_expect_success 'looking for a tag in an empty tree should fail' '
+ ! (tag_exists mytag)
+'
test_expect_success 'creating a tag in an empty tree should fail' '
test_must_fail git tag mynotag &&
@@ -129,10 +130,10 @@ test_expect_success 'listing all tags if one exists should succeed' '
git tag
'
-cat >expect <<EOF
-mytag
-EOF
test_expect_success 'Multiple -l or --list options are equivalent to one -l option' '
+ cat >expect <<-\EOF &&
+ mytag
+ EOF
git tag -l -l >actual &&
test_cmp expect actual &&
git tag --list --list >actual &&
@@ -148,32 +149,33 @@ test_expect_success 'listing all tags if one exists should output that tag' '
# pattern matching:
-test_expect_success 'listing a tag using a matching pattern should succeed' \
- 'git tag -l mytag'
+test_expect_success 'listing a tag using a matching pattern should succeed' '
+ git tag -l mytag
+'
-test_expect_success 'listing a tag with --ignore-case' \
- 'test $(git tag -l --ignore-case MYTAG) = mytag'
+test_expect_success 'listing a tag with --ignore-case' '
+ test $(git tag -l --ignore-case MYTAG) = mytag
+'
-test_expect_success \
- 'listing a tag using a matching pattern should output that tag' \
- 'test $(git tag -l mytag) = mytag'
+test_expect_success 'listing a tag using a matching pattern should output that tag' '
+ test $(git tag -l mytag) = mytag
+'
-test_expect_success \
- 'listing tags using a non-matching pattern should succeed' \
- 'git tag -l xxx'
+test_expect_success 'listing tags using a non-matching pattern should succeed' '
+ git tag -l xxx
+'
-test_expect_success \
- 'listing tags using a non-matching pattern should output nothing' \
- 'test $(git tag -l xxx | wc -l) -eq 0'
+test_expect_success 'listing tags using a non-matching pattern should output nothing' '
+ test $(git tag -l xxx | wc -l) -eq 0
+'
# special cases for creating tags:
-test_expect_success \
- 'trying to create a tag with the name of one existing should fail' \
- 'test_must_fail git tag mytag'
+test_expect_success 'trying to create a tag with the name of one existing should fail' '
+ test_must_fail git tag mytag
+'
-test_expect_success \
- 'trying to create a tag with a non-valid name should fail' '
+test_expect_success 'trying to create a tag with a non-valid name should fail' '
test $(git tag -l | wc -l) -eq 1 &&
test_must_fail git tag "" &&
test_must_fail git tag .othertag &&
@@ -207,19 +209,19 @@ test_expect_success 'trying to delete an unknown tag should fail' '
test_must_fail git tag -d unknown-tag
'
-cat >expect <<EOF
-myhead
-mytag
-EOF
-test_expect_success \
- 'trying to delete tags without params should succeed and do nothing' '
- git tag -l > actual && test_cmp expect actual &&
+test_expect_success 'trying to delete tags without params should succeed and do nothing' '
+ cat >expect <<-\EOF &&
+ myhead
+ mytag
+ EOF
+ git tag -l >actual &&
+ test_cmp expect actual &&
git tag -d &&
- git tag -l > actual && test_cmp expect actual
+ git tag -l >actual &&
+ test_cmp expect actual
'
-test_expect_success \
- 'deleting two existing tags in one command should succeed' '
+test_expect_success 'deleting two existing tags in one command should succeed' '
tag_exists mytag &&
tag_exists myhead &&
git tag -d mytag myhead &&
@@ -227,15 +229,13 @@ test_expect_success \
! tag_exists myhead
'
-test_expect_success \
- 'creating a tag with the name of another deleted one should succeed' '
+test_expect_success 'creating a tag with the name of another deleted one should succeed' '
! tag_exists mytag &&
git tag mytag &&
tag_exists mytag
'
-test_expect_success \
- 'trying to delete two tags, existing and not, should fail in the 2nd' '
+test_expect_success 'trying to delete two tags, existing and not, should fail in the 2nd' '
tag_exists mytag &&
! tag_exists nonexistingtag &&
test_must_fail git tag -d mytag nonexistingtag &&
@@ -243,23 +243,24 @@ test_expect_success \
! tag_exists nonexistingtag
'
-test_expect_success 'trying to delete an already deleted tag should fail' \
- 'test_must_fail git tag -d mytag'
+test_expect_success 'trying to delete an already deleted tag should fail' '
+ test_must_fail git tag -d mytag
+'
# listing various tags with pattern matching:
-cat >expect <<EOF
-a1
-aa1
-cba
-t210
-t211
-v0.2.1
-v1.0
-v1.0.1
-v1.1.3
-EOF
test_expect_success 'listing all tags should print them ordered' '
+ cat >expect <<-\EOF &&
+ a1
+ aa1
+ cba
+ t210
+ t211
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ EOF
git tag v1.0.1 &&
git tag t211 &&
git tag aa1 &&
@@ -269,91 +270,89 @@ test_expect_success 'listing all tags should print them ordered' '
git tag a1 &&
git tag v1.0 &&
git tag t210 &&
- git tag -l > actual &&
+ git tag -l >actual &&
test_cmp expect actual &&
- git tag > actual &&
+ git tag >actual &&
test_cmp expect actual
'
-cat >expect <<EOF
-a1
-aa1
-cba
-EOF
-test_expect_success \
- 'listing tags with substring as pattern must print those matching' '
+test_expect_success 'listing tags with substring as pattern must print those matching' '
+ cat >expect <<-\EOF &&
+ a1
+ aa1
+ cba
+ EOF
rm *a* &&
- git tag -l "*a*" > current &&
+ git tag -l "*a*" >current &&
test_cmp expect current
'
-cat >expect <<EOF
-v0.2.1
-v1.0.1
-EOF
-test_expect_success \
- 'listing tags with a suffix as pattern must print those matching' '
- git tag -l "*.1" > actual &&
+test_expect_success 'listing tags with a suffix as pattern must print those matching' '
+ cat >expect <<-\EOF &&
+ v0.2.1
+ v1.0.1
+ EOF
+ git tag -l "*.1" >actual &&
test_cmp expect actual
'
-cat >expect <<EOF
-t210
-t211
-EOF
-test_expect_success \
- 'listing tags with a prefix as pattern must print those matching' '
- git tag -l "t21*" > actual &&
+test_expect_success 'listing tags with a prefix as pattern must print those matching' '
+ cat >expect <<-\EOF &&
+ t210
+ t211
+ EOF
+ git tag -l "t21*" >actual &&
test_cmp expect actual
'
-cat >expect <<EOF
-a1
-EOF
-test_expect_success \
- 'listing tags using a name as pattern must print that one matching' '
- git tag -l a1 > actual &&
+test_expect_success 'listing tags using a name as pattern must print that one matching' '
+ cat >expect <<-\EOF &&
+ a1
+ EOF
+ git tag -l a1 >actual &&
test_cmp expect actual
'
-cat >expect <<EOF
-v1.0
-EOF
-test_expect_success \
- 'listing tags using a name as pattern must print that one matching' '
- git tag -l v1.0 > actual &&
+test_expect_success 'listing tags using a name as pattern must print that one matching' '
+ cat >expect <<-\EOF &&
+ v1.0
+ EOF
+ git tag -l v1.0 >actual &&
test_cmp expect actual
'
-cat >expect <<EOF
-v1.0.1
-v1.1.3
-EOF
-test_expect_success \
- 'listing tags with ? in the pattern should print those matching' '
- git tag -l "v1.?.?" > actual &&
+test_expect_success 'listing tags with ? in the pattern should print those matching' '
+ cat >expect <<-\EOF &&
+ v1.0.1
+ v1.1.3
+ EOF
+ git tag -l "v1.?.?" >actual &&
test_cmp expect actual
'
-test_expect_success \
- 'listing tags using v.* should print nothing because none have v.' '
- git tag -l "v.*" > actual &&
+test_expect_success 'listing tags using v.* should print nothing because none have v.' '
+ git tag -l "v.*" >actual &&
test_must_be_empty actual
'
-cat >expect <<EOF
-v0.2.1
-v1.0
-v1.0.1
-v1.1.3
-EOF
-test_expect_success \
- 'listing tags using v* should print only those having v' '
- git tag -l "v*" > actual &&
+test_expect_success 'listing tags using v* should print only those having v' '
+ cat >expect <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ EOF
+ git tag -l "v*" >actual &&
test_cmp expect actual
'
test_expect_success 'tag -l can accept multiple patterns' '
+ cat >expect <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ EOF
git tag -l "v1*" "v0*" >actual &&
test_cmp expect actual
'
@@ -367,16 +366,22 @@ test_expect_success 'tag -l can accept multiple patterns' '
# out if we're going to break this long-documented form of taking
# multiple patterns.
test_expect_success 'tag -l <pattern> -l <pattern> works, as our buggy documentation previously suggested' '
+ cat >expect <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ EOF
git tag -l "v1*" -l "v0*" >actual &&
test_cmp expect actual
'
test_expect_success 'listing tags in column' '
COLUMNS=41 git tag -l --column=row >actual &&
- cat >expected <<\EOF &&
-a1 aa1 cba t210 t211
-v0.2.1 v1.0 v1.0.1 v1.1.3
-EOF
+ cat >expected <<-\EOF &&
+ a1 aa1 cba t210 t211
+ v0.2.1 v1.0 v1.0.1 v1.1.3
+ EOF
test_cmp expected actual
'
@@ -384,10 +389,10 @@ test_expect_success 'listing tags in column with column.*' '
test_config column.tag row &&
test_config column.ui dense &&
COLUMNS=40 git tag -l >actual &&
- cat >expected <<\EOF &&
-a1 aa1 cba t210 t211
-v0.2.1 v1.0 v1.0.1 v1.1.3
-EOF
+ cat >expected <<-\EOF &&
+ a1 aa1 cba t210 t211
+ v0.2.1 v1.0 v1.0.1 v1.1.3
+ EOF
test_cmp expected actual
'
@@ -398,39 +403,39 @@ test_expect_success 'listing tag with -n --column should fail' '
test_expect_success 'listing tags -n in column with column.ui ignored' '
test_config column.ui "row dense" &&
COLUMNS=40 git tag -l -n >actual &&
- cat >expected <<\EOF &&
-a1 Foo
-aa1 Foo
-cba Foo
-t210 Foo
-t211 Foo
-v0.2.1 Foo
-v1.0 Foo
-v1.0.1 Foo
-v1.1.3 Foo
-EOF
+ cat >expected <<-\EOF &&
+ a1 Foo
+ aa1 Foo
+ cba Foo
+ t210 Foo
+ t211 Foo
+ v0.2.1 Foo
+ v1.0 Foo
+ v1.0.1 Foo
+ v1.1.3 Foo
+ EOF
test_cmp expected actual
'
# creating and verifying lightweight tags:
-test_expect_success \
- 'a non-annotated tag created without parameters should point to HEAD' '
+test_expect_success 'a non-annotated tag created without parameters should point to HEAD' '
git tag non-annotated-tag &&
test $(git cat-file -t non-annotated-tag) = commit &&
test $(git rev-parse non-annotated-tag) = $(git rev-parse HEAD)
'
-test_expect_success 'trying to verify an unknown tag should fail' \
- 'test_must_fail git tag -v unknown-tag'
+test_expect_success 'trying to verify an unknown tag should fail' '
+ test_must_fail git tag -v unknown-tag
+'
-test_expect_success \
- 'trying to verify a non-annotated and non-signed tag should fail' \
- 'test_must_fail git tag -v non-annotated-tag'
+test_expect_success 'trying to verify a non-annotated and non-signed tag should fail' '
+ test_must_fail git tag -v non-annotated-tag
+'
-test_expect_success \
- 'trying to verify many non-annotated or unknown tags, should fail' \
- 'test_must_fail git tag -v unknown-tag1 non-annotated-tag unknown-tag2'
+test_expect_success 'trying to verify many non-annotated or unknown tags, should fail' '
+ test_must_fail git tag -v unknown-tag1 non-annotated-tag unknown-tag2
+'
# creating annotated tags:
@@ -449,83 +454,78 @@ tagger C O Mitter <committer@example.com> $4 -0700
EOF
}
-commit=$(git rev-parse HEAD)
-time=$test_tick
-
-get_tag_header annotated-tag $commit commit $time >expect
-echo "A message" >>expect
-test_expect_success \
- 'creating an annotated tag with -m message should succeed' '
+test_expect_success 'creating an annotated tag with -m message should succeed' '
+ commit=$(git rev-parse HEAD) &&
+ time=$test_tick &&
+ get_tag_header annotated-tag $commit commit $time >expect &&
+ echo "A message" >>expect &&
git tag -m "A message" annotated-tag &&
get_tag_msg annotated-tag >actual &&
test_cmp expect actual
'
-get_tag_header annotated-tag-edit $commit commit $time >expect
-echo "An edited message" >>expect
test_expect_success 'set up editor' '
write_script fakeeditor <<-\EOF
sed -e "s/A message/An edited message/g" <"$1" >"$1-"
mv "$1-" "$1"
EOF
'
-test_expect_success \
- 'creating an annotated tag with -m message --edit should succeed' '
+
+test_expect_success 'creating an annotated tag with -m message --edit should succeed' '
+ get_tag_header annotated-tag-edit $commit commit $time >expect &&
+ echo "An edited message" >>expect &&
GIT_EDITOR=./fakeeditor git tag -m "A message" --edit annotated-tag-edit &&
get_tag_msg annotated-tag-edit >actual &&
test_cmp expect actual
'
-cat >msgfile <<EOF
-Another message
-in a file.
-EOF
-get_tag_header file-annotated-tag $commit commit $time >expect
-cat msgfile >>expect
-test_expect_success \
- 'creating an annotated tag with -F messagefile should succeed' '
+test_expect_success 'creating an annotated tag with -F messagefile should succeed' '
+ cat >msgfile <<-\EOF &&
+ Another message
+ in a file.
+ EOF
+ get_tag_header file-annotated-tag $commit commit $time >expect &&
+ cat msgfile >>expect &&
git tag -F msgfile file-annotated-tag &&
get_tag_msg file-annotated-tag >actual &&
test_cmp expect actual
'
-get_tag_header file-annotated-tag-edit $commit commit $time >expect
-sed -e "s/Another message/Another edited message/g" msgfile >>expect
test_expect_success 'set up editor' '
write_script fakeeditor <<-\EOF
sed -e "s/Another message/Another edited message/g" <"$1" >"$1-"
mv "$1-" "$1"
EOF
'
-test_expect_success \
- 'creating an annotated tag with -F messagefile --edit should succeed' '
+
+test_expect_success 'creating an annotated tag with -F messagefile --edit should succeed' '
+ get_tag_header file-annotated-tag-edit $commit commit $time >expect &&
+ sed -e "s/Another message/Another edited message/g" msgfile >>expect &&
GIT_EDITOR=./fakeeditor git tag -F msgfile --edit file-annotated-tag-edit &&
get_tag_msg file-annotated-tag-edit >actual &&
test_cmp expect actual
'
-cat >inputmsg <<EOF
-A message from the
-standard input
-EOF
-get_tag_header stdin-annotated-tag $commit commit $time >expect
-cat inputmsg >>expect
test_expect_success 'creating an annotated tag with -F - should succeed' '
+ cat >inputmsg <<-\EOF &&
+ A message from the
+ standard input
+ EOF
+ get_tag_header stdin-annotated-tag $commit commit $time >expect &&
+ cat inputmsg >>expect &&
git tag -F - stdin-annotated-tag <inputmsg &&
get_tag_msg stdin-annotated-tag >actual &&
test_cmp expect actual
'
-test_expect_success \
- 'trying to create a tag with a non-existing -F file should fail' '
+test_expect_success 'trying to create a tag with a non-existing -F file should fail' '
! test -f nonexistingfile &&
! tag_exists notag &&
test_must_fail git tag -F nonexistingfile notag &&
! tag_exists notag
'
-test_expect_success \
- 'trying to create tags giving both -m or -F options should fail' '
+test_expect_success 'trying to create tags giving both -m or -F options should fail' '
echo "message file 1" >msgfile1 &&
! tag_exists msgtag &&
test_must_fail git tag -m "message 1" -F msgfile1 msgtag &&
@@ -539,67 +539,61 @@ test_expect_success \
# blank and empty messages:
-get_tag_header empty-annotated-tag $commit commit $time >expect
-test_expect_success \
- 'creating a tag with an empty -m message should succeed' '
+test_expect_success 'creating a tag with an empty -m message should succeed' '
+ get_tag_header empty-annotated-tag $commit commit $time >expect &&
git tag -m "" empty-annotated-tag &&
get_tag_msg empty-annotated-tag >actual &&
test_cmp expect actual
'
->emptyfile
-get_tag_header emptyfile-annotated-tag $commit commit $time >expect
-test_expect_success \
- 'creating a tag with an empty -F messagefile should succeed' '
+test_expect_success 'creating a tag with an empty -F messagefile should succeed' '
+ >emptyfile &&
+ get_tag_header emptyfile-annotated-tag $commit commit $time >expect &&
git tag -F emptyfile emptyfile-annotated-tag &&
get_tag_msg emptyfile-annotated-tag >actual &&
test_cmp expect actual
'
-printf '\n\n \n\t\nLeading blank lines\n' >blanksfile
-printf '\n\t \t \nRepeated blank lines\n' >>blanksfile
-printf '\n\n\nTrailing spaces \t \n' >>blanksfile
-printf '\nTrailing blank lines\n\n\t \n\n' >>blanksfile
-get_tag_header blanks-annotated-tag $commit commit $time >expect
-cat >>expect <<EOF
-Leading blank lines
+test_expect_success 'extra blanks in the message for an annotated tag should be removed' '
+ printf "\n\n \n\t\nLeading blank lines\n" >blanksfile &&
+ printf "\n\t \t \nRepeated blank lines\n" >>blanksfile &&
+ printf "\n\n\nTrailing spaces \t \n" >>blanksfile &&
+ printf "\nTrailing blank lines\n\n\t \n\n" >>blanksfile &&
+ get_tag_header blanks-annotated-tag $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ Leading blank lines
-Repeated blank lines
+ Repeated blank lines
-Trailing spaces
+ Trailing spaces
-Trailing blank lines
-EOF
-test_expect_success \
- 'extra blanks in the message for an annotated tag should be removed' '
+ Trailing blank lines
+ EOF
git tag -F blanksfile blanks-annotated-tag &&
get_tag_msg blanks-annotated-tag >actual &&
test_cmp expect actual
'
-get_tag_header blank-annotated-tag $commit commit $time >expect
-test_expect_success \
- 'creating a tag with blank -m message with spaces should succeed' '
+test_expect_success 'creating a tag with blank -m message with spaces should succeed' '
+ get_tag_header blank-annotated-tag $commit commit $time >expect &&
git tag -m " " blank-annotated-tag &&
get_tag_msg blank-annotated-tag >actual &&
test_cmp expect actual
'
-echo ' ' >blankfile
-echo '' >>blankfile
-echo ' ' >>blankfile
-get_tag_header blankfile-annotated-tag $commit commit $time >expect
-test_expect_success \
- 'creating a tag with blank -F messagefile with spaces should succeed' '
+test_expect_success 'creating a tag with blank -F messagefile with spaces should succeed' '
+ echo " " >blankfile &&
+ echo "" >>blankfile &&
+ echo " " >>blankfile &&
+ get_tag_header blankfile-annotated-tag $commit commit $time >expect &&
git tag -F blankfile blankfile-annotated-tag &&
get_tag_msg blankfile-annotated-tag >actual &&
test_cmp expect actual
'
-printf ' ' >blanknonlfile
-get_tag_header blanknonlfile-annotated-tag $commit commit $time >expect
-test_expect_success \
- 'creating a tag with -F file of spaces and no newline should succeed' '
+test_expect_success 'creating a tag with -F file of spaces and no newline should succeed' '
+ printf " " >blanknonlfile &&
+ get_tag_header blanknonlfile-annotated-tag $commit commit $time >expect &&
git tag -F blanknonlfile blanknonlfile-annotated-tag &&
get_tag_msg blanknonlfile-annotated-tag >actual &&
test_cmp expect actual
@@ -607,62 +601,58 @@ test_expect_success \
# messages with commented lines:
-cat >commentsfile <<EOF
-# A comment
+test_expect_success 'creating a tag using a -F messagefile with #comments should succeed' '
+ cat >commentsfile <<-\EOF &&
+ # A comment
-############
-The message.
-############
-One line.
+ ############
+ The message.
+ ############
+ One line.
-# commented lines
-# commented lines
+ # commented lines
+ # commented lines
-Another line.
-# comments
+ Another line.
+ # comments
-Last line.
-EOF
-get_tag_header comments-annotated-tag $commit commit $time >expect
-cat >>expect <<EOF
-The message.
-One line.
+ Last line.
+ EOF
+ get_tag_header comments-annotated-tag $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ The message.
+ One line.
-Another line.
+ Another line.
-Last line.
-EOF
-test_expect_success \
- 'creating a tag using a -F messagefile with #comments should succeed' '
+ Last line.
+ EOF
git tag -F commentsfile comments-annotated-tag &&
get_tag_msg comments-annotated-tag >actual &&
test_cmp expect actual
'
-get_tag_header comment-annotated-tag $commit commit $time >expect
-test_expect_success \
- 'creating a tag with a #comment in the -m message should succeed' '
+test_expect_success 'creating a tag with a #comment in the -m message should succeed' '
+ get_tag_header comment-annotated-tag $commit commit $time >expect &&
git tag -m "#comment" comment-annotated-tag &&
get_tag_msg comment-annotated-tag >actual &&
test_cmp expect actual
'
-echo '#comment' >commentfile
-echo '' >>commentfile
-echo '####' >>commentfile
-get_tag_header commentfile-annotated-tag $commit commit $time >expect
-test_expect_success \
- 'creating a tag with #comments in the -F messagefile should succeed' '
+test_expect_success 'creating a tag with #comments in the -F messagefile should succeed' '
+ echo "#comment" >commentfile &&
+ echo "" >>commentfile &&
+ echo "####" >>commentfile &&
+ get_tag_header commentfile-annotated-tag $commit commit $time >expect &&
git tag -F commentfile commentfile-annotated-tag &&
get_tag_msg commentfile-annotated-tag >actual &&
test_cmp expect actual
'
-printf '#comment' >commentnonlfile
-get_tag_header commentnonlfile-annotated-tag $commit commit $time >expect
-test_expect_success \
- 'creating a tag with a file of #comment and no newline should succeed' '
+test_expect_success 'creating a tag with a file of #comment and no newline should succeed' '
+ printf "#comment" >commentnonlfile &&
+ get_tag_header commentnonlfile-annotated-tag $commit commit $time >expect &&
git tag -F commentnonlfile commentnonlfile-annotated-tag &&
get_tag_msg commentnonlfile-annotated-tag >actual &&
test_cmp expect actual
@@ -779,8 +769,7 @@ test_expect_success 'bad editor causes panic when only --trailer is given' '
# listing messages for annotated non-signed tags:
-test_expect_success \
- 'listing the one-line message of a non-signed tag should succeed' '
+test_expect_success 'listing the one-line message of a non-signed tag should succeed' '
git tag -m "A msg" tag-one-line &&
echo "tag-one-line" >expect &&
@@ -819,8 +808,7 @@ test_expect_success 'The -n 100 invocation means -n --list 100, not -n100' '
test_cmp expect actual
'
-test_expect_success \
- 'listing the zero-lines message of a non-signed tag should succeed' '
+test_expect_success 'listing the zero-lines message of a non-signed tag should succeed' '
git tag -m "" tag-zero-lines &&
echo "tag-zero-lines" >expect &&
@@ -844,11 +832,10 @@ test_expect_success \
test_cmp expect actual
'
-echo 'tag line one' >annotagmsg
-echo 'tag line two' >>annotagmsg
-echo 'tag line three' >>annotagmsg
-test_expect_success \
- 'listing many message lines of a non-signed tag should succeed' '
+test_expect_success 'listing many message lines of a non-signed tag should succeed' '
+ echo "tag line one" >annotagmsg &&
+ echo "tag line two" >>annotagmsg &&
+ echo "tag line three" >>annotagmsg &&
git tag -F annotagmsg tag-lines &&
echo "tag-lines" >expect &&
@@ -936,40 +923,37 @@ test_expect_success 'git tag --format with ahead-behind' '
# trying to verify annotated non-signed tags:
-test_expect_success GPG \
- 'trying to verify an annotated non-signed tag should fail' '
+test_expect_success GPG 'trying to verify an annotated non-signed tag should fail' '
tag_exists annotated-tag &&
test_must_fail git tag -v annotated-tag
'
-test_expect_success GPG \
- 'trying to verify a file-annotated non-signed tag should fail' '
+test_expect_success GPG 'trying to verify a file-annotated non-signed tag should fail' '
tag_exists file-annotated-tag &&
test_must_fail git tag -v file-annotated-tag
'
-test_expect_success GPG \
- 'trying to verify two annotated non-signed tags should fail' '
+test_expect_success GPG 'trying to verify two annotated non-signed tags should fail' '
tag_exists annotated-tag file-annotated-tag &&
test_must_fail git tag -v annotated-tag file-annotated-tag
'
# creating and verifying signed tags:
-get_tag_header signed-tag $commit commit $time >expect
-echo 'A signed tag message' >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
test_expect_success GPG 'creating a signed tag with -m message should succeed' '
+ get_tag_header signed-tag $commit commit $time >expect &&
+ echo "A signed tag message" >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -m "A signed tag message" signed-tag &&
get_tag_msg signed-tag >actual &&
test_cmp expect actual
'
-get_tag_header u-signed-tag $commit commit $time >expect
-echo 'Another message' >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
test_expect_success GPG 'sign with a given key id' '
+ get_tag_header u-signed-tag $commit commit $time >expect &&
+ echo "Another message" >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -u committer@example.com -m "Another message" u-signed-tag &&
get_tag_msg u-signed-tag >actual &&
test_cmp expect actual
@@ -989,137 +973,128 @@ test_expect_success GPG 'sign with an unknown id (2)' '
'
-cat >fakeeditor <<'EOF'
-#!/bin/sh
-test -n "$1" && exec >"$1"
-echo A signed tag message
-echo from a fake editor.
-EOF
-chmod +x fakeeditor
-
-get_tag_header implied-sign $commit commit $time >expect
-./fakeeditor >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
test_expect_success GPG '-u implies signed tag' '
+ write_script fakeeditor <<-\EOF &&
+ test -n "$1" && exec >"$1"
+ echo A signed tag message
+ echo from a fake editor.
+ EOF
+
+ get_tag_header implied-sign $commit commit $time >expect &&
+ ./fakeeditor >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
GIT_EDITOR=./fakeeditor git tag -u CDDE430D implied-sign &&
get_tag_msg implied-sign >actual &&
test_cmp expect actual
'
-cat >sigmsgfile <<EOF
-Another signed tag
-message in a file.
-EOF
-get_tag_header file-signed-tag $commit commit $time >expect
-cat sigmsgfile >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with -F messagefile should succeed' '
+test_expect_success GPG 'creating a signed tag with -F messagefile should succeed' '
+ cat >sigmsgfile <<-\EOF &&
+ Another signed tag
+ message in a file.
+ EOF
+ get_tag_header file-signed-tag $commit commit $time >expect &&
+ cat sigmsgfile >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F sigmsgfile file-signed-tag &&
get_tag_msg file-signed-tag >actual &&
test_cmp expect actual
'
-cat >siginputmsg <<EOF
-A signed tag message from
-the standard input
-EOF
-get_tag_header stdin-signed-tag $commit commit $time >expect
-cat siginputmsg >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
test_expect_success GPG 'creating a signed tag with -F - should succeed' '
+ cat >siginputmsg <<-\EOF &&
+ A signed tag message from
+ the standard input
+ EOF
+ get_tag_header stdin-signed-tag $commit commit $time >expect &&
+ cat siginputmsg >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F - stdin-signed-tag <siginputmsg &&
get_tag_msg stdin-signed-tag >actual &&
test_cmp expect actual
'
-get_tag_header implied-annotate $commit commit $time >expect
-./fakeeditor >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
test_expect_success GPG '-s implies annotated tag' '
+ get_tag_header implied-annotate $commit commit $time >expect &&
+ ./fakeeditor >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
GIT_EDITOR=./fakeeditor git tag -s implied-annotate &&
get_tag_msg implied-annotate >actual &&
test_cmp expect actual
'
-get_tag_header forcesignannotated-implied-sign $commit commit $time >expect
-echo "A message" >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'git tag -s implied if configured with tag.forcesignannotated' \
- 'test_config tag.forcesignannotated true &&
+test_expect_success GPG 'git tag -s implied if configured with tag.forcesignannotated' '
+ get_tag_header forcesignannotated-implied-sign $commit commit $time >expect &&
+ echo "A message" >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
+ test_config tag.forcesignannotated true &&
git tag -m "A message" forcesignannotated-implied-sign &&
get_tag_msg forcesignannotated-implied-sign >actual &&
test_cmp expect actual
'
-test_expect_success GPG \
- 'lightweight with no message when configured with tag.forcesignannotated' \
- 'test_config tag.forcesignannotated true &&
+test_expect_success GPG 'lightweight with no message when configured with tag.forcesignannotated' '
+ test_config tag.forcesignannotated true &&
git tag forcesignannotated-lightweight &&
tag_exists forcesignannotated-lightweight &&
test_must_fail git tag -v forcesignannotated-no-message
'
-get_tag_header forcesignannotated-annotate $commit commit $time >expect
-echo "A message" >>expect
-test_expect_success GPG \
- 'git tag -a disable configured tag.forcesignannotated' \
- 'test_config tag.forcesignannotated true &&
+test_expect_success GPG 'git tag -a disable configured tag.forcesignannotated' '
+ get_tag_header forcesignannotated-annotate $commit commit $time >expect &&
+ echo "A message" >>expect &&
+ test_config tag.forcesignannotated true &&
git tag -a -m "A message" forcesignannotated-annotate &&
get_tag_msg forcesignannotated-annotate >actual &&
test_cmp expect actual &&
test_must_fail git tag -v forcesignannotated-annotate
'
-get_tag_header forcesignannotated-disabled $commit commit $time >expect
-echo "A message" >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'git tag --sign enable GPG sign' \
- 'test_config tag.forcesignannotated false &&
+test_expect_success GPG 'git tag --sign enable GPG sign' '
+ get_tag_header forcesignannotated-disabled $commit commit $time >expect &&
+ echo "A message" >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
+ test_config tag.forcesignannotated false &&
git tag --sign -m "A message" forcesignannotated-disabled &&
get_tag_msg forcesignannotated-disabled >actual &&
test_cmp expect actual
'
-get_tag_header gpgsign-enabled $commit commit $time >expect
-echo "A message" >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'git tag configured tag.gpgsign enables GPG sign' \
- 'test_config tag.gpgsign true &&
+test_expect_success GPG 'git tag configured tag.gpgsign enables GPG sign' '
+ get_tag_header gpgsign-enabled $commit commit $time >expect &&
+ echo "A message" >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
+ test_config tag.gpgsign true &&
git tag -m "A message" gpgsign-enabled &&
get_tag_msg gpgsign-enabled>actual &&
test_cmp expect actual
'
-get_tag_header no-sign $commit commit $time >expect
-echo "A message" >>expect
-test_expect_success GPG \
- 'git tag --no-sign configured tag.gpgsign skip GPG sign' \
- 'test_config tag.gpgsign true &&
+test_expect_success GPG 'git tag --no-sign configured tag.gpgsign skip GPG sign' '
+ get_tag_header no-sign $commit commit $time >expect &&
+ echo "A message" >>expect &&
+ test_config tag.gpgsign true &&
git tag -a --no-sign -m "A message" no-sign &&
get_tag_msg no-sign>actual &&
test_cmp expect actual
'
-test_expect_success GPG \
- 'trying to create a signed tag with non-existing -F file should fail' '
+test_expect_success GPG 'trying to create a signed tag with non-existing -F file should fail' '
! test -f nonexistingfile &&
! tag_exists nosigtag &&
test_must_fail git tag -s -F nonexistingfile nosigtag &&
! tag_exists nosigtag
'
-test_expect_success GPG 'verifying a signed tag should succeed' \
- 'git tag -v signed-tag'
+test_expect_success GPG 'verifying a signed tag should succeed' '
+ git tag -v signed-tag
+'
-test_expect_success GPG 'verifying two signed tags in one command should succeed' \
- 'git tag -v signed-tag file-signed-tag'
+test_expect_success GPG 'verifying two signed tags in one command should succeed' '
+ git tag -v signed-tag file-signed-tag
+'
-test_expect_success GPG \
- 'verifying many signed and non-signed tags should fail' '
+test_expect_success GPG 'verifying many signed and non-signed tags should fail' '
test_must_fail git tag -v signed-tag annotated-tag &&
test_must_fail git tag -v file-annotated-tag file-signed-tag &&
test_must_fail git tag -v annotated-tag \
@@ -1150,78 +1125,72 @@ test_expect_success GPG 'verifying a forged tag with --format should fail silent
# blank and empty messages for signed tags:
-get_tag_header empty-signed-tag $commit commit $time >expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with an empty -m message should succeed' '
+test_expect_success GPG 'creating a signed tag with an empty -m message should succeed' '
+ get_tag_header empty-signed-tag $commit commit $time >expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -m "" empty-signed-tag &&
get_tag_msg empty-signed-tag >actual &&
test_cmp expect actual &&
git tag -v empty-signed-tag
'
->sigemptyfile
-get_tag_header emptyfile-signed-tag $commit commit $time >expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with an empty -F messagefile should succeed' '
+test_expect_success GPG 'creating a signed tag with an empty -F messagefile should succeed' '
+ >sigemptyfile &&
+ get_tag_header emptyfile-signed-tag $commit commit $time >expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F sigemptyfile emptyfile-signed-tag &&
get_tag_msg emptyfile-signed-tag >actual &&
test_cmp expect actual &&
git tag -v emptyfile-signed-tag
'
-printf '\n\n \n\t\nLeading blank lines\n' > sigblanksfile
-printf '\n\t \t \nRepeated blank lines\n' >>sigblanksfile
-printf '\n\n\nTrailing spaces \t \n' >>sigblanksfile
-printf '\nTrailing blank lines\n\n\t \n\n' >>sigblanksfile
-get_tag_header blanks-signed-tag $commit commit $time >expect
-cat >>expect <<EOF
-Leading blank lines
+test_expect_success GPG 'extra blanks in the message for a signed tag should be removed' '
+ printf "\n\n \n\t\nLeading blank lines\n" >sigblanksfile &&
+ printf "\n\t \t \nRepeated blank lines\n" >>sigblanksfile &&
+ printf "\n\n\nTrailing spaces \t \n" >>sigblanksfile &&
+ printf "\nTrailing blank lines\n\n\t \n\n" >>sigblanksfile &&
+ get_tag_header blanks-signed-tag $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ Leading blank lines
-Repeated blank lines
+ Repeated blank lines
-Trailing spaces
+ Trailing spaces
-Trailing blank lines
-EOF
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'extra blanks in the message for a signed tag should be removed' '
+ Trailing blank lines
+ EOF
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F sigblanksfile blanks-signed-tag &&
get_tag_msg blanks-signed-tag >actual &&
test_cmp expect actual &&
git tag -v blanks-signed-tag
'
-get_tag_header blank-signed-tag $commit commit $time >expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with a blank -m message should succeed' '
+test_expect_success GPG 'creating a signed tag with a blank -m message should succeed' '
+ get_tag_header blank-signed-tag $commit commit $time >expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -m " " blank-signed-tag &&
get_tag_msg blank-signed-tag >actual &&
test_cmp expect actual &&
git tag -v blank-signed-tag
'
-echo ' ' >sigblankfile
-echo '' >>sigblankfile
-echo ' ' >>sigblankfile
-get_tag_header blankfile-signed-tag $commit commit $time >expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with blank -F file with spaces should succeed' '
+test_expect_success GPG 'creating a signed tag with blank -F file with spaces should succeed' '
+ echo " " >sigblankfile &&
+ echo "" >>sigblankfile &&
+ echo " " >>sigblankfile &&
+ get_tag_header blankfile-signed-tag $commit commit $time >expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F sigblankfile blankfile-signed-tag &&
get_tag_msg blankfile-signed-tag >actual &&
test_cmp expect actual &&
git tag -v blankfile-signed-tag
'
-printf ' ' >sigblanknonlfile
-get_tag_header blanknonlfile-signed-tag $commit commit $time >expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with spaces and no newline should succeed' '
+test_expect_success GPG 'creating a signed tag with spaces and no newline should succeed' '
+ printf " " >sigblanknonlfile &&
+ get_tag_header blanknonlfile-signed-tag $commit commit $time >expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F sigblanknonlfile blanknonlfile-signed-tag &&
get_tag_msg blanknonlfile-signed-tag >actual &&
test_cmp expect actual &&
@@ -1241,69 +1210,65 @@ test_expect_success GPG 'signed tag with embedded PGP message' '
# messages with commented lines for signed tags:
-cat >sigcommentsfile <<EOF
-# A comment
+test_expect_success GPG 'creating a signed tag with a -F file with #comments should succeed' '
+ cat >sigcommentsfile <<-\EOF &&
+ # A comment
-############
-The message.
-############
-One line.
+ ############
+ The message.
+ ############
+ One line.
-# commented lines
-# commented lines
+ # commented lines
+ # commented lines
-Another line.
-# comments
+ Another line.
+ # comments
-Last line.
-EOF
-get_tag_header comments-signed-tag $commit commit $time >expect
-cat >>expect <<EOF
-The message.
-One line.
+ Last line.
+ EOF
+ get_tag_header comments-signed-tag $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ The message.
+ One line.
-Another line.
+ Another line.
-Last line.
-EOF
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with a -F file with #comments should succeed' '
+ Last line.
+ EOF
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F sigcommentsfile comments-signed-tag &&
get_tag_msg comments-signed-tag >actual &&
test_cmp expect actual &&
git tag -v comments-signed-tag
'
-get_tag_header comment-signed-tag $commit commit $time >expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with #commented -m message should succeed' '
+test_expect_success GPG 'creating a signed tag with #commented -m message should succeed' '
+ get_tag_header comment-signed-tag $commit commit $time >expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -m "#comment" comment-signed-tag &&
get_tag_msg comment-signed-tag >actual &&
test_cmp expect actual &&
git tag -v comment-signed-tag
'
-echo '#comment' >sigcommentfile
-echo '' >>sigcommentfile
-echo '####' >>sigcommentfile
-get_tag_header commentfile-signed-tag $commit commit $time >expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with #commented -F messagefile should succeed' '
+test_expect_success GPG 'creating a signed tag with #commented -F messagefile should succeed' '
+ echo "#comment" >sigcommentfile &&
+ echo "" >>sigcommentfile &&
+ echo "####" >>sigcommentfile &&
+ get_tag_header commentfile-signed-tag $commit commit $time >expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F sigcommentfile commentfile-signed-tag &&
get_tag_msg commentfile-signed-tag >actual &&
test_cmp expect actual &&
git tag -v commentfile-signed-tag
'
-printf '#comment' >sigcommentnonlfile
-get_tag_header commentnonlfile-signed-tag $commit commit $time >expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag with a #comment and no newline should succeed' '
+test_expect_success GPG 'creating a signed tag with a #comment and no newline should succeed' '
+ printf "#comment" >sigcommentnonlfile &&
+ get_tag_header commentnonlfile-signed-tag $commit commit $time >expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -F sigcommentnonlfile commentnonlfile-signed-tag &&
get_tag_msg commentnonlfile-signed-tag >actual &&
test_cmp expect actual &&
@@ -1312,8 +1277,7 @@ test_expect_success GPG \
# listing messages for signed tags:
-test_expect_success GPG \
- 'listing the one-line message of a signed tag should succeed' '
+test_expect_success GPG 'listing the one-line message of a signed tag should succeed' '
git tag -s -m "A message line signed" stag-one-line &&
echo "stag-one-line" >expect &&
@@ -1337,8 +1301,7 @@ test_expect_success GPG \
test_cmp expect actual
'
-test_expect_success GPG \
- 'listing the zero-lines message of a signed tag should succeed' '
+test_expect_success GPG 'listing the zero-lines message of a signed tag should succeed' '
git tag -s -m "" stag-zero-lines &&
echo "stag-zero-lines" >expect &&
@@ -1362,11 +1325,10 @@ test_expect_success GPG \
test_cmp expect actual
'
-echo 'stag line one' >sigtagmsg
-echo 'stag line two' >>sigtagmsg
-echo 'stag line three' >>sigtagmsg
-test_expect_success GPG \
- 'listing many message lines of a signed tag should succeed' '
+test_expect_success GPG 'listing many message lines of a signed tag should succeed' '
+ echo "stag line one" >sigtagmsg &&
+ echo "stag line two" >>sigtagmsg &&
+ echo "stag line three" >>sigtagmsg &&
git tag -s -F sigtagmsg stag-lines &&
echo "stag-lines" >expect &&
@@ -1408,74 +1370,64 @@ test_expect_success GPG \
# tags pointing to objects different from commits:
-tree=$(git rev-parse HEAD^{tree})
-blob=$(git rev-parse HEAD:foo)
-tag=$(git rev-parse signed-tag 2>/dev/null)
-
-get_tag_header tree-signed-tag $tree tree $time >expect
-echo "A message for a tree" >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag pointing to a tree should succeed' '
+test_expect_success GPG 'creating a signed tag pointing to a tree should succeed' '
+ tree=$(git rev-parse HEAD^{tree}) &&
+ get_tag_header tree-signed-tag $tree tree $time >expect &&
+ echo "A message for a tree" >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} &&
get_tag_msg tree-signed-tag >actual &&
test_cmp expect actual
'
-get_tag_header blob-signed-tag $blob blob $time >expect
-echo "A message for a blob" >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag pointing to a blob should succeed' '
+test_expect_success GPG 'creating a signed tag pointing to a blob should succeed' '
+ blob=$(git rev-parse HEAD:foo) &&
+ get_tag_header blob-signed-tag $blob blob $time >expect &&
+ echo "A message for a blob" >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -m "A message for a blob" blob-signed-tag HEAD:foo &&
get_tag_msg blob-signed-tag >actual &&
test_cmp expect actual
'
-get_tag_header tag-signed-tag $tag tag $time >expect
-echo "A message for another tag" >>expect
-echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success GPG \
- 'creating a signed tag pointing to another tag should succeed' '
+test_expect_success GPG 'creating a signed tag pointing to another tag should succeed' '
+ tag=$(git rev-parse signed-tag 2>/dev/null) &&
+ get_tag_header tag-signed-tag $tag tag $time >expect &&
+ echo "A message for another tag" >>expect &&
+ echo "-----BEGIN PGP SIGNATURE-----" >>expect &&
git tag -s -m "A message for another tag" tag-signed-tag signed-tag &&
get_tag_msg tag-signed-tag >actual &&
test_cmp expect actual
'
# usage with rfc1991 signatures
-get_tag_header rfc1991-signed-tag $commit commit $time >expect
-echo "RFC1991 signed tag" >>expect
-echo '-----BEGIN PGP MESSAGE-----' >>expect
-test_expect_success GPG,RFC1991 \
- 'creating a signed tag with rfc1991' '
+
+test_expect_success GPG,RFC1991 'creating a signed tag with rfc1991' '
+ get_tag_header rfc1991-signed-tag $commit commit $time >expect &&
+ echo "RFC1991 signed tag" >>expect &&
+ echo "-----BEGIN PGP MESSAGE-----" >>expect &&
echo "rfc1991" >gpghome/gpg.conf &&
git tag -s -m "RFC1991 signed tag" rfc1991-signed-tag $commit &&
get_tag_msg rfc1991-signed-tag >actual &&
test_cmp expect actual
'
-cat >fakeeditor <<'EOF'
-#!/bin/sh
-cp "$1" actual
-EOF
-chmod +x fakeeditor
-
-test_expect_success GPG,RFC1991 \
- 'reediting a signed tag body omits signature' '
+test_expect_success GPG,RFC1991 'reediting a signed tag body omits signature' '
+ write_script fakeeditor <<-\EOF &&
+ cp "$1" actual
+ EOF
echo "rfc1991" >gpghome/gpg.conf &&
echo "RFC1991 signed tag" >expect &&
GIT_EDITOR=./fakeeditor git tag -f -s rfc1991-signed-tag $commit &&
test_cmp expect actual
'
-test_expect_success GPG,RFC1991 \
- 'verifying rfc1991 signature' '
+test_expect_success GPG,RFC1991 'verifying rfc1991 signature' '
echo "rfc1991" >gpghome/gpg.conf &&
git tag -v rfc1991-signed-tag
'
-test_expect_success GPG,RFC1991 \
- 'list tag with rfc1991 signature' '
+test_expect_success GPG,RFC1991 'list tag with rfc1991 signature' '
echo "rfc1991" >gpghome/gpg.conf &&
echo "rfc1991-signed-tag RFC1991 signed tag" >expect &&
git tag -l -n1 rfc1991-signed-tag >actual &&
@@ -1486,15 +1438,12 @@ test_expect_success GPG,RFC1991 \
test_cmp expect actual
'
-rm -f gpghome/gpg.conf
-
-test_expect_success GPG,RFC1991 \
- 'verifying rfc1991 signature without --rfc1991' '
+test_expect_success GPG,RFC1991 'verifying rfc1991 signature without --rfc1991' '
+ rm -f gpghome/gpg.conf &&
git tag -v rfc1991-signed-tag
'
-test_expect_success GPG,RFC1991 \
- 'list tag with rfc1991 signature without --rfc1991' '
+test_expect_success GPG,RFC1991 'list tag with rfc1991 signature without --rfc1991' '
echo "rfc1991-signed-tag RFC1991 signed tag" >expect &&
git tag -l -n1 rfc1991-signed-tag >actual &&
test_cmp expect actual &&
@@ -1504,24 +1453,23 @@ test_expect_success GPG,RFC1991 \
test_cmp expect actual
'
-test_expect_success GPG,RFC1991 \
- 'reediting a signed tag body omits signature' '
+test_expect_success GPG,RFC1991 'reediting a signed tag body omits signature' '
echo "RFC1991 signed tag" >expect &&
GIT_EDITOR=./fakeeditor git tag -f -s rfc1991-signed-tag $commit &&
test_cmp expect actual
'
# try to sign with bad user.signingkey
-test_expect_success GPG \
- 'git tag -s fails if gpg is misconfigured (bad key)' \
- 'test_config user.signingkey BobTheMouse &&
- test_must_fail git tag -s -m tail tag-gpg-failure'
+test_expect_success GPG 'git tag -s fails if gpg is misconfigured (bad key)' '
+ test_config user.signingkey BobTheMouse &&
+ test_must_fail git tag -s -m tail tag-gpg-failure
+'
# try to produce invalid signature
-test_expect_success GPG \
- 'git tag -s fails if gpg is misconfigured (bad signature format)' \
- 'test_config gpg.program echo &&
- test_must_fail git tag -s -m tail tag-gpg-failure'
+test_expect_success GPG 'git tag -s fails if gpg is misconfigured (bad signature format)' '
+ test_config gpg.program echo &&
+ test_must_fail git tag -s -m tail tag-gpg-failure
+'
# try to produce invalid signature
test_expect_success GPG 'git verifies tag is valid with double signature' '
@@ -1542,34 +1490,32 @@ test_expect_success GPG 'git verifies tag is valid with double signature' '
'
# try to sign with bad user.signingkey
-test_expect_success GPGSM \
- 'git tag -s fails if gpgsm is misconfigured (bad key)' \
- 'test_config user.signingkey BobTheMouse &&
- test_config gpg.format x509 &&
- test_must_fail git tag -s -m tail tag-gpg-failure'
+test_expect_success GPGSM 'git tag -s fails if gpgsm is misconfigured (bad key)' '
+ test_config user.signingkey BobTheMouse &&
+ test_config gpg.format x509 &&
+ test_must_fail git tag -s -m tail tag-gpg-failure
+'
# try to produce invalid signature
-test_expect_success GPGSM \
- 'git tag -s fails if gpgsm is misconfigured (bad signature format)' \
- 'test_config gpg.x509.program echo &&
- test_config gpg.format x509 &&
- test_must_fail git tag -s -m tail tag-gpg-failure'
+test_expect_success GPGSM 'git tag -s fails if gpgsm is misconfigured (bad signature format)' '
+ test_config gpg.x509.program echo &&
+ test_config gpg.format x509 &&
+ test_must_fail git tag -s -m tail tag-gpg-failure
+'
# try to verify without gpg:
-rm -rf gpghome
-test_expect_success GPG \
- 'verify signed tag fails when public key is not present' \
- 'test_must_fail git tag -v signed-tag'
+test_expect_success GPG 'verify signed tag fails when public key is not present' '
+ rm -rf gpghome &&
+ test_must_fail git tag -v signed-tag
+'
-test_expect_success \
- 'git tag -a fails if tag annotation is empty' '
+test_expect_success 'git tag -a fails if tag annotation is empty' '
! (GIT_EDITOR=cat git tag -a initial-comment)
'
-test_expect_success \
- 'message in editor has initial comment' '
- ! (GIT_EDITOR=cat git tag -a initial-comment > actual)
+test_expect_success 'message in editor has initial comment' '
+ ! (GIT_EDITOR=cat git tag -a initial-comment >actual)
'
test_expect_success 'message in editor has initial comment: first line' '
@@ -1579,17 +1525,15 @@ test_expect_success 'message in editor has initial comment: first line' '
test_cmp first.expect first.actual
'
-test_expect_success \
- 'message in editor has initial comment: remainder' '
+test_expect_success 'message in editor has initial comment: remainder' '
# remove commented lines from the remainder -- should be empty
sed -e 1d -e "/^#/d" <actual >rest.actual &&
test_must_be_empty rest.actual
'
-get_tag_header reuse $commit commit $time >expect
-echo "An annotation to be reused" >> expect
-test_expect_success \
- 'overwriting an annotated tag should use its previous body' '
+test_expect_success 'overwriting an annotated tag should use its previous body' '
+ get_tag_header reuse $commit commit $time >expect &&
+ echo "An annotation to be reused" >>expect &&
git tag -a -m "An annotation to be reused" reuse &&
GIT_EDITOR=true git tag -f -a reuse &&
get_tag_msg reuse >actual &&
@@ -1618,192 +1562,202 @@ test_expect_success 'filename for the message is relative to cwd' '
# create a few more commits to test --contains
-hash1=$(git rev-parse HEAD)
-
test_expect_success 'creating second commit and tag' '
+ hash1=$(git rev-parse HEAD) &&
echo foo-2.0 >foo &&
git add foo &&
git commit -m second &&
git tag v2.0
'
-hash2=$(git rev-parse HEAD)
-
test_expect_success 'creating third commit without tag' '
+ hash2=$(git rev-parse HEAD) &&
echo foo-dev >foo &&
git add foo &&
git commit -m third
'
-hash3=$(git rev-parse HEAD)
-
# simple linear checks of --continue
-cat > expected <<EOF
-v0.2.1
-v1.0
-v1.0.1
-v1.1.3
-v2.0
-EOF
-
-test_expect_success 'checking that first commit is in all tags (hash)' "
+test_expect_success 'checking that first commit is in all tags (hash)' '
+ hash3=$(git rev-parse HEAD) &&
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ v2.0
+ EOF
git tag -l --contains $hash1 v* >actual &&
test_cmp expected actual
-"
+'
# other ways of specifying the commit
-test_expect_success 'checking that first commit is in all tags (tag)' "
+test_expect_success 'checking that first commit is in all tags (tag)' '
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ v2.0
+ EOF
git tag -l --contains v1.0 v* >actual &&
test_cmp expected actual
-"
+'
-test_expect_success 'checking that first commit is in all tags (relative)' "
+test_expect_success 'checking that first commit is in all tags (relative)' '
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ v2.0
+ EOF
git tag -l --contains HEAD~2 v* >actual &&
test_cmp expected actual
-"
+'
# All the --contains tests above, but with --no-contains
-test_expect_success 'checking that first commit is not listed in any tag with --no-contains (hash)' "
+test_expect_success 'checking that first commit is not listed in any tag with --no-contains (hash)' '
git tag -l --no-contains $hash1 v* >actual &&
test_must_be_empty actual
-"
+'
-test_expect_success 'checking that first commit is in all tags (tag)' "
+test_expect_success 'checking that first commit is in all tags (tag)' '
git tag -l --no-contains v1.0 v* >actual &&
test_must_be_empty actual
-"
+'
-test_expect_success 'checking that first commit is in all tags (relative)' "
+test_expect_success 'checking that first commit is in all tags (relative)' '
git tag -l --no-contains HEAD~2 v* >actual &&
test_must_be_empty actual
-"
-
-cat > expected <<EOF
-v2.0
-EOF
+'
-test_expect_success 'checking that second commit only has one tag' "
+test_expect_success 'checking that second commit only has one tag' '
+ cat >expected <<-\EOF &&
+ v2.0
+ EOF
git tag -l --contains $hash2 v* >actual &&
test_cmp expected actual
-"
-
-cat > expected <<EOF
-v0.2.1
-v1.0
-v1.0.1
-v1.1.3
-EOF
+'
-test_expect_success 'inverse of the last test, with --no-contains' "
+test_expect_success 'inverse of the last test, with --no-contains' '
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ EOF
git tag -l --no-contains $hash2 v* >actual &&
test_cmp expected actual
-"
+'
-test_expect_success 'checking that third commit has no tags' "
+test_expect_success 'checking that third commit has no tags' '
git tag -l --contains $hash3 v* >actual &&
test_must_be_empty actual
-"
-
-cat > expected <<EOF
-v0.2.1
-v1.0
-v1.0.1
-v1.1.3
-v2.0
-EOF
+'
-test_expect_success 'conversely --no-contains on the third commit lists all tags' "
+test_expect_success 'conversely --no-contains on the third commit lists all tags' '
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ v2.0
+ EOF
git tag -l --no-contains $hash3 v* >actual &&
test_cmp expected actual
-"
+'
# how about a simple merge?
test_expect_success 'creating simple branch' '
git branch stable v2.0 &&
git checkout stable &&
- echo foo-3.0 > foo &&
+ echo foo-3.0 >foo &&
git commit foo -m fourth &&
git tag v3.0
'
-hash4=$(git rev-parse HEAD)
-
-cat > expected <<EOF
-v3.0
-EOF
-
-test_expect_success 'checking that branch head only has one tag' "
+test_expect_success 'checking that branch head only has one tag' '
+ hash4=$(git rev-parse HEAD) &&
+ cat >expected <<-\EOF &&
+ v3.0
+ EOF
git tag -l --contains $hash4 v* >actual &&
test_cmp expected actual
-"
-
-cat > expected <<EOF
-v0.2.1
-v1.0
-v1.0.1
-v1.1.3
-v2.0
-EOF
+'
-test_expect_success 'checking that branch head with --no-contains lists all but one tag' "
+test_expect_success 'checking that branch head with --no-contains lists all but one tag' '
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ v2.0
+ EOF
git tag -l --no-contains $hash4 v* >actual &&
test_cmp expected actual
-"
+'
test_expect_success 'merging original branch into this branch' '
git merge --strategy=ours main &&
git tag v4.0
'
-cat > expected <<EOF
-v4.0
-EOF
-
-test_expect_success 'checking that original branch head has one tag now' "
+test_expect_success 'checking that original branch head has one tag now' '
+ cat >expected <<-\EOF &&
+ v4.0
+ EOF
git tag -l --contains $hash3 v* >actual &&
test_cmp expected actual
-"
-
-cat > expected <<EOF
-v0.2.1
-v1.0
-v1.0.1
-v1.1.3
-v2.0
-v3.0
-EOF
+'
-test_expect_success 'checking that original branch head with --no-contains lists all but one tag now' "
+test_expect_success 'checking that original branch head with --no-contains lists all but one tag now' '
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ v2.0
+ v3.0
+ EOF
git tag -l --no-contains $hash3 v* >actual &&
test_cmp expected actual
-"
-
-cat > expected <<EOF
-v0.2.1
-v1.0
-v1.0.1
-v1.1.3
-v2.0
-v3.0
-v4.0
-EOF
+'
-test_expect_success 'checking that initial commit is in all tags' "
+test_expect_success 'checking that initial commit is in all tags' '
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ v2.0
+ v3.0
+ v4.0
+ EOF
git tag -l --contains $hash1 v* >actual &&
test_cmp expected actual
-"
+'
test_expect_success 'checking that --contains can be used in non-list mode' '
+ cat >expected <<-\EOF &&
+ v0.2.1
+ v1.0
+ v1.0.1
+ v1.1.3
+ v2.0
+ v3.0
+ v4.0
+ EOF
git tag --contains $hash1 v* >actual &&
test_cmp expected actual
'
-test_expect_success 'checking that initial commit is in all tags with --no-contains' "
+test_expect_success 'checking that initial commit is in all tags with --no-contains' '
git tag -l --no-contains $hash1 v* >actual &&
test_must_be_empty actual
-"
+'
# mixing modes and options:
@@ -1840,16 +1794,16 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' '
for option in --contains --with --no-contains --without --merged --no-merged --points-at
do
- test_expect_success "mixing incompatible modes with $option is forbidden" "
+ test_expect_success "mixing incompatible modes with $option is forbidden" '
test_must_fail git tag -d $option HEAD &&
test_must_fail git tag -d $option HEAD some-tag &&
test_must_fail git tag -v $option HEAD
- "
- test_expect_success "Doing 'git tag --list-like $option <commit> <pattern> is permitted" "
+ '
+ test_expect_success "Doing 'git tag --list-like $option <commit> <pattern> is permitted" '
git tag -n $option HEAD HEAD &&
git tag $option HEAD HEAD &&
git tag $option
- "
+ '
done
# check points-at
@@ -2225,7 +2179,7 @@ test_expect_success 'git tag -l with --format="%(rest)" must fail' '
test_must_fail git tag -l --format="%(rest)" "v1*"
'
-test_expect_success "set up color tests" '
+test_expect_success 'set up color tests' '
echo "<RED>v1.0<RESET>" >expect.color &&
echo "v1.0" >expect.bare &&
color_args="--format=%(color:red)%(refname:short) --list v1.0"
diff --git a/t/t7008-filter-branch-null-sha1.sh b/t/t7008-filter-branch-null-sha1.sh
index 93fbc92b8d..0ce8fd2c89 100755
--- a/t/t7008-filter-branch-null-sha1.sh
+++ b/t/t7008-filter-branch-null-sha1.sh
@@ -2,6 +2,7 @@
test_description='filter-branch removal of trees with null sha1'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup: base commits' '
diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh
index 6f526c37c2..effa826744 100755
--- a/t/t7030-verify-tag.sh
+++ b/t/t7030-verify-tag.sh
@@ -4,6 +4,7 @@ test_description='signed tag tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t7418-submodule-sparse-gitmodules.sh b/t/t7418-submodule-sparse-gitmodules.sh
index dde11ecce8..e1d9bf2ee3 100755
--- a/t/t7418-submodule-sparse-gitmodules.sh
+++ b/t/t7418-submodule-sparse-gitmodules.sh
@@ -15,6 +15,7 @@ also by committing .gitmodules and then just removing it from the filesystem.
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7424-submodule-mixed-ref-formats.sh b/t/t7424-submodule-mixed-ref-formats.sh
new file mode 100755
index 0000000000..b43ef2ba67
--- /dev/null
+++ b/t/t7424-submodule-mixed-ref-formats.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+test_description='submodules handle mixed ref storage formats'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_ref_format () {
+ echo "$2" >expect &&
+ git -C "$1" rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+}
+
+for OTHER_FORMAT in files reftable
+do
+ if test "$OTHER_FORMAT" = "$GIT_DEFAULT_REF_FORMAT"
+ then
+ continue
+ fi
+
+test_expect_success 'setup' '
+ git config set --global protocol.file.allow always &&
+ # Some tests migrate the ref storage format, which does not work with
+ # reflogs at the time of writing these tests.
+ git config set --global core.logAllRefUpdates false
+'
+
+test_expect_success 'add existing repository with different ref storage format' '
+ test_when_finished "rm -rf parent" &&
+
+ git init parent &&
+ (
+ cd parent &&
+ test_commit parent &&
+ git init --ref-format=$OTHER_FORMAT submodule &&
+ test_commit -C submodule submodule &&
+ git submodule add ./submodule
+ )
+'
+
+test_expect_success 'add submodules with different ref storage format' '
+ test_when_finished "rm -rf submodule upstream" &&
+
+ git init submodule &&
+ test_commit -C submodule submodule-initial &&
+ git init upstream &&
+ test_ref_format upstream "$GIT_DEFAULT_REF_FORMAT" &&
+ git -C upstream submodule add --ref-format="$OTHER_FORMAT" "file://$(pwd)/submodule" &&
+ test_ref_format upstream/submodule "$OTHER_FORMAT"
+'
+
+test_expect_success 'recursive clone propagates ref storage format' '
+ test_when_finished "rm -rf submodule upstream downstream" &&
+
+ git init submodule &&
+ test_commit -C submodule submodule-initial &&
+ git init upstream &&
+ git -C upstream submodule add "file://$(pwd)/submodule" &&
+ git -C upstream commit -am "add submodule" &&
+
+ # The upstream repository and its submodule should be using the default
+ # ref format.
+ test_ref_format upstream "$GIT_DEFAULT_REF_FORMAT" &&
+ test_ref_format upstream/submodule "$GIT_DEFAULT_REF_FORMAT" &&
+
+ # The cloned repositories should use the other ref format that we have
+ # specified via `--ref-format`. The option should propagate to cloned
+ # submodules.
+ git clone --ref-format=$OTHER_FORMAT --recurse-submodules \
+ upstream downstream &&
+ test_ref_format downstream "$OTHER_FORMAT" &&
+ test_ref_format downstream/submodule "$OTHER_FORMAT"
+'
+
+test_expect_success 'clone submodules with different ref storage format' '
+ test_when_finished "rm -rf submodule upstream downstream" &&
+
+ git init submodule &&
+ test_commit -C submodule submodule-initial &&
+ git init upstream &&
+ git -C upstream submodule add "file://$(pwd)/submodule" &&
+ git -C upstream commit -m "upstream submodule" &&
+
+ git clone --no-recurse-submodules "file://$(pwd)/upstream" downstream &&
+ test_ref_format downstream "$GIT_DEFAULT_REF_FORMAT" &&
+ git -C downstream submodule update --init --ref-format=$OTHER_FORMAT &&
+ test_ref_format downstream/submodule "$OTHER_FORMAT"
+'
+
+test_expect_success 'status with mixed submodule ref storages' '
+ test_when_finished "rm -rf submodule main" &&
+
+ git init submodule &&
+ test_commit -C submodule submodule-initial &&
+ git init main &&
+ git -C main submodule add "file://$(pwd)/submodule" &&
+ git -C main commit -m "add submodule" &&
+ git -C main/submodule refs migrate --ref-format=$OTHER_FORMAT &&
+
+ # The main repository should use the default ref format now, whereas
+ # the submodule should use the other format.
+ test_ref_format main "$GIT_DEFAULT_REF_FORMAT" &&
+ test_ref_format main/submodule "$OTHER_FORMAT" &&
+
+ cat >expect <<-EOF &&
+ $(git -C main/submodule rev-parse HEAD) submodule (submodule-initial)
+ EOF
+ git -C main submodule status >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'recursive pull with mixed formats' '
+ test_when_finished "rm -rf submodule upstream downstream" &&
+
+ # Set up the initial structure with an upstream repository that has a
+ # submodule, as well as a downstream clone of the upstream repository.
+ git init submodule &&
+ test_commit -C submodule submodule-initial &&
+ git init upstream &&
+ git -C upstream submodule add "file://$(pwd)/submodule" &&
+ git -C upstream commit -m "upstream submodule" &&
+
+ # Clone the upstream repository such that the main repo and its
+ # submodules have different formats.
+ git clone --no-recurse-submodules "file://$(pwd)/upstream" downstream &&
+ git -C downstream submodule update --init --ref-format=$OTHER_FORMAT &&
+ test_ref_format downstream "$GIT_DEFAULT_REF_FORMAT" &&
+ test_ref_format downstream/submodule "$OTHER_FORMAT" &&
+
+ # Update the upstream submodule as well as the owning repository such
+ # that we can do a recursive pull.
+ test_commit -C submodule submodule-update &&
+ git -C upstream/submodule pull &&
+ git -C upstream commit -am "update the submodule" &&
+
+ git -C downstream pull --recurse-submodules &&
+ git -C upstream/submodule rev-parse HEAD >expect &&
+ git -C downstream/submodule rev-parse HEAD >actual &&
+ test_cmp expect actual
+'
+
+done
+
+test_done
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 127efe99f8..be1188e736 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -7,6 +7,9 @@ test_description='git repack works correctly'
. "${TEST_DIRECTORY}/lib-midx.sh"
. "${TEST_DIRECTORY}/lib-terminal.sh"
+GIT_TEST_MULTI_PACK_INDEX=0
+GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
+
commit_and_pack () {
test_commit "$@" 1>&2 &&
incrpackid=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&
@@ -70,14 +73,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '
# build on $oid, $packid, and .keep state from previous
- GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 git repack -Adbl &&
+ git repack -Adbl &&
test_has_duplicate_object true
'
test_expect_success 'writing bitmaps via config can duplicate .keep objects' '
# build on $oid, $packid, and .keep state from previous
- GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \
- git -c repack.writebitmaps=true repack -Adl &&
+ git -c repack.writebitmaps=true repack -Adl &&
test_has_duplicate_object true
'
@@ -118,7 +120,7 @@ test_expect_success '--local disables writing bitmaps when connected to alternat
(
cd member &&
test_commit "object" &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adl --write-bitmap-index 2>err &&
+ git repack -Adl --write-bitmap-index 2>err &&
cat >expect <<-EOF &&
warning: disabling bitmap writing, as some objects are not being packed
EOF
@@ -284,8 +286,7 @@ test_expect_success 'repacking fails when missing .pack actually means missing o
test_expect_success 'bitmaps are created by default in bare repos' '
git clone --bare .git bare.git &&
rm -f bare.git/objects/pack/*.bitmap &&
- GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \
- git -C bare.git repack -ad &&
+ git -C bare.git repack -ad &&
bitmap=$(ls bare.git/objects/pack/*.bitmap) &&
test_path_is_file "$bitmap"
'
@@ -296,8 +297,7 @@ test_expect_success 'incremental repack does not complain' '
'
test_expect_success 'bitmaps can be disabled on bare repos' '
- GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \
- git -c repack.writeBitmaps=false -C bare.git repack -ad &&
+ git -c repack.writeBitmaps=false -C bare.git repack -ad &&
bitmap=$(ls bare.git/objects/pack/*.bitmap || :) &&
test -z "$bitmap"
'
@@ -308,8 +308,7 @@ test_expect_success 'no bitmaps created if .keep files present' '
keep=${pack%.pack}.keep &&
test_when_finished "rm -f \"\$keep\"" &&
>"$keep" &&
- GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \
- git -C bare.git repack -ad 2>stderr &&
+ git -C bare.git repack -ad 2>stderr &&
test_must_be_empty stderr &&
find bare.git/objects/pack/ -type f -name "*.bitmap" >actual &&
test_must_be_empty actual
@@ -320,8 +319,7 @@ test_expect_success 'auto-bitmaps do not complain if unavailable' '
blob=$(test-tool genrandom big $((1024*1024)) |
git -C bare.git hash-object -w --stdin) &&
git -C bare.git update-ref refs/tags/big $blob &&
- GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \
- git -C bare.git repack -ad 2>stderr &&
+ git -C bare.git repack -ad 2>stderr &&
test_must_be_empty stderr &&
find bare.git/objects/pack -type f -name "*.bitmap" >actual &&
test_must_be_empty actual
@@ -342,9 +340,7 @@ test_expect_success 'repacking with a filter works' '
'
test_expect_success '--filter fails with --write-bitmap-index' '
- test_must_fail \
- env GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \
- git -C bare.git repack -a -d --write-bitmap-index --filter=blob:none
+ test_must_fail git -C bare.git repack -a -d --write-bitmap-index --filter=blob:none
'
test_expect_success 'repacking with two filters works' '
@@ -540,11 +536,11 @@ test_expect_success 'setup for --write-midx tests' '
test_expect_success '--write-midx unchanged' '
(
cd midx &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack &&
+ git repack &&
test_path_is_missing $midx &&
test_path_is_missing $midx-*.bitmap &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack --write-midx &&
+ git repack --write-midx &&
test_path_is_file $midx &&
test_path_is_missing $midx-*.bitmap &&
@@ -557,7 +553,7 @@ test_expect_success '--write-midx with a new pack' '
cd midx &&
test_commit loose &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack --write-midx &&
+ git repack --write-midx &&
test_path_is_file $midx &&
test_path_is_missing $midx-*.bitmap &&
@@ -568,7 +564,7 @@ test_expect_success '--write-midx with a new pack' '
test_expect_success '--write-midx with -b' '
(
cd midx &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack -mb &&
+ git repack -mb &&
test_path_is_file $midx &&
test_path_is_file $midx-*.bitmap &&
@@ -581,7 +577,7 @@ test_expect_success '--write-midx with -d' '
cd midx &&
test_commit repack &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack -Ad --write-midx &&
+ git repack -Ad --write-midx &&
test_path_is_file $midx &&
test_path_is_missing $midx-*.bitmap &&
@@ -594,21 +590,21 @@ test_expect_success 'cleans up MIDX when appropriate' '
cd midx &&
test_commit repack-2 &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb --write-midx &&
+ git repack -Adb --write-midx &&
checksum=$(midx_checksum $objdir) &&
test_path_is_file $midx &&
test_path_is_file $midx-$checksum.bitmap &&
test_commit repack-3 &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb --write-midx &&
+ git repack -Adb --write-midx &&
test_path_is_file $midx &&
test_path_is_missing $midx-$checksum.bitmap &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
test_commit repack-4 &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adb &&
+ git repack -Adb &&
find $objdir/pack -type f -name "multi-pack-index*" >files &&
test_must_be_empty files
@@ -629,7 +625,6 @@ test_expect_success '--write-midx with preferred bitmap tips' '
git log --format="create refs/tags/%s/%s %H" HEAD >refs &&
git update-ref --stdin <refs &&
- GIT_TEST_MULTI_PACK_INDEX=0 \
git repack --write-midx --write-bitmap-index &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
@@ -721,13 +716,13 @@ test_expect_success '--write-midx removes stale pack-based bitmaps' '
(
cd repo &&
test_commit base &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack -Ab &&
+ git repack -Ab &&
pack_bitmap=$(ls $objdir/pack/pack-*.bitmap) &&
test_path_is_file "$pack_bitmap" &&
test_commit tip &&
- GIT_TEST_MULTI_PACK_INDEX=0 git repack -bm &&
+ git repack -bm &&
test_path_is_file $midx &&
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
@@ -750,7 +745,6 @@ test_expect_success '--write-midx with --pack-kept-objects' '
keep="$objdir/pack/pack-$one.keep" &&
touch "$keep" &&
- GIT_TEST_MULTI_PACK_INDEX=0 \
git repack --write-midx --write-bitmap-index --geometric=2 -d \
--pack-kept-objects &&
diff --git a/t/t7817-grep-sparse-checkout.sh b/t/t7817-grep-sparse-checkout.sh
index eb59564565..0ba7817fb7 100755
--- a/t/t7817-grep-sparse-checkout.sh
+++ b/t/t7817-grep-sparse-checkout.sh
@@ -33,6 +33,7 @@ should leave the following structure in the working tree:
But note that sub2 should have the SKIP_WORKTREE bit set.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 1e68426852..3b3c371740 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -7,6 +7,7 @@ test_description='test git fast-import utility'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash
diff --git a/t/t9304-fast-import-marks.sh b/t/t9304-fast-import-marks.sh
index 410a871c52..1f776a80f3 100755
--- a/t/t9304-fast-import-marks.sh
+++ b/t/t9304-fast-import-marks.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test exotic situations with marks'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup dump of basic history' '
diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
index 156a647484..c0d9d7be75 100755
--- a/t/t9351-fast-export-anonymize.sh
+++ b/t/t9351-fast-export-anonymize.sh
@@ -4,6 +4,7 @@ test_description='basic tests for fast-export --anonymize'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup simple repo' '
diff --git a/t/unit-tests/t-ctype.c b/t/unit-tests/t-ctype.c
index d6ac1fe678..e28a7f50f9 100644
--- a/t/unit-tests/t-ctype.c
+++ b/t/unit-tests/t-ctype.c
@@ -4,15 +4,13 @@
size_t len = ARRAY_SIZE(string) - 1 + \
BUILD_ASSERT_OR_ZERO(ARRAY_SIZE(string) > 0) + \
BUILD_ASSERT_OR_ZERO(sizeof(string[0]) == sizeof(char)); \
- int skip = test__run_begin(); \
- if (!skip) { \
+ if_test (#class " works") { \
for (int i = 0; i < 256; i++) { \
if (!check_int(class(i), ==, !!memchr(string, i, len)))\
test_msg(" i: 0x%02x", i); \
} \
check(!class(EOF)); \
} \
- test__run_end(!skip, TEST_LOCATION(), #class " works"); \
} while (0)
#define DIGIT "0123456789"
diff --git a/t/unit-tests/t-example-decorate.c b/t/unit-tests/t-example-decorate.c
index a4a75db735..8bf0709c41 100644
--- a/t/unit-tests/t-example-decorate.c
+++ b/t/unit-tests/t-example-decorate.c
@@ -15,36 +15,29 @@ static void t_add(struct test_vars *vars)
{
void *ret = add_decoration(&vars->n, vars->one, &vars->decoration_a);
- if (!check(ret == NULL))
- test_msg("when adding a brand-new object, NULL should be returned");
+ check(ret == NULL);
ret = add_decoration(&vars->n, vars->two, NULL);
- if (!check(ret == NULL))
- test_msg("when adding a brand-new object, NULL should be returned");
+ check(ret == NULL);
}
static void t_readd(struct test_vars *vars)
{
void *ret = add_decoration(&vars->n, vars->one, NULL);
- if (!check(ret == &vars->decoration_a))
- test_msg("when readding an already existing object, existing decoration should be returned");
+ check(ret == &vars->decoration_a);
ret = add_decoration(&vars->n, vars->two, &vars->decoration_b);
- if (!check(ret == NULL))
- test_msg("when readding an already existing object, existing decoration should be returned");
+ check(ret == NULL);
}
static void t_lookup(struct test_vars *vars)
{
void *ret = lookup_decoration(&vars->n, vars->one);
- if (!check(ret == NULL))
- test_msg("lookup should return added declaration");
+ check(ret == NULL);
ret = lookup_decoration(&vars->n, vars->two);
- if (!check(ret == &vars->decoration_b))
- test_msg("lookup should return added declaration");
+ check(ret == &vars->decoration_b);
ret = lookup_decoration(&vars->n, vars->three);
- if (!check(ret == NULL))
- test_msg("lookup for unknown object should return NULL");
+ check(ret == NULL);
}
static void t_loop(struct test_vars *vars)
@@ -55,8 +48,7 @@ static void t_loop(struct test_vars *vars)
if (vars->n.entries[i].base)
objects_noticed++;
}
- if (!check_int(objects_noticed, ==, 2))
- test_msg("should have 2 objects");
+ check_int(objects_noticed, ==, 2);
}
int cmd_main(int argc UNUSED, const char **argv UNUSED)
diff --git a/t/unit-tests/t-hashmap.c b/t/unit-tests/t-hashmap.c
new file mode 100644
index 0000000000..09a48c2c4e
--- /dev/null
+++ b/t/unit-tests/t-hashmap.c
@@ -0,0 +1,361 @@
+#include "test-lib.h"
+#include "hashmap.h"
+#include "strbuf.h"
+
+struct test_entry {
+ int padding; /* hashmap entry no longer needs to be the first member */
+ struct hashmap_entry ent;
+ /* key and value as two \0-terminated strings */
+ char key[FLEX_ARRAY];
+};
+
+static int test_entry_cmp(const void *cmp_data,
+ const struct hashmap_entry *eptr,
+ const struct hashmap_entry *entry_or_key,
+ const void *keydata)
+{
+ const unsigned int ignore_case = cmp_data ? *((int *)cmp_data) : 0;
+ const struct test_entry *e1, *e2;
+ const char *key = keydata;
+
+ e1 = container_of(eptr, const struct test_entry, ent);
+ e2 = container_of(entry_or_key, const struct test_entry, ent);
+
+ if (ignore_case)
+ return strcasecmp(e1->key, key ? key : e2->key);
+ else
+ return strcmp(e1->key, key ? key : e2->key);
+}
+
+static const char *get_value(const struct test_entry *e)
+{
+ return e->key + strlen(e->key) + 1;
+}
+
+static struct test_entry *alloc_test_entry(const char *key, const char *value,
+ unsigned int ignore_case)
+{
+ size_t klen = strlen(key);
+ size_t vlen = strlen(value);
+ unsigned int hash = ignore_case ? strihash(key) : strhash(key);
+ struct test_entry *entry = xmalloc(st_add4(sizeof(*entry), klen, vlen, 2));
+
+ hashmap_entry_init(&entry->ent, hash);
+ memcpy(entry->key, key, klen + 1);
+ memcpy(entry->key + klen + 1, value, vlen + 1);
+ return entry;
+}
+
+static struct test_entry *get_test_entry(struct hashmap *map, const char *key,
+ unsigned int ignore_case)
+{
+ return hashmap_get_entry_from_hash(
+ map, ignore_case ? strihash(key) : strhash(key), key,
+ struct test_entry, ent);
+}
+
+static int key_val_contains(const char *key_val[][2], char seen[], size_t n,
+ struct test_entry *entry)
+{
+ for (size_t i = 0; i < n; i++) {
+ if (!strcmp(entry->key, key_val[i][0]) &&
+ !strcmp(get_value(entry), key_val[i][1])) {
+ if (seen[i])
+ return 2;
+ seen[i] = 1;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void setup(void (*f)(struct hashmap *map, unsigned int ignore_case),
+ unsigned int ignore_case)
+{
+ struct hashmap map = HASHMAP_INIT(test_entry_cmp, &ignore_case);
+
+ f(&map, ignore_case);
+ hashmap_clear_and_free(&map, struct test_entry, ent);
+}
+
+static void t_replace(struct hashmap *map, unsigned int ignore_case)
+{
+ struct test_entry *entry;
+
+ entry = alloc_test_entry("key1", "value1", ignore_case);
+ check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL);
+
+ entry = alloc_test_entry(ignore_case ? "Key1" : "key1", "value2",
+ ignore_case);
+ entry = hashmap_put_entry(map, entry, ent);
+ if (check(entry != NULL))
+ check_str(get_value(entry), "value1");
+ free(entry);
+
+ entry = alloc_test_entry("fooBarFrotz", "value3", ignore_case);
+ check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL);
+
+ entry = alloc_test_entry(ignore_case ? "FOObarFrotz" : "fooBarFrotz",
+ "value4", ignore_case);
+ entry = hashmap_put_entry(map, entry, ent);
+ if (check(entry != NULL))
+ check_str(get_value(entry), "value3");
+ free(entry);
+}
+
+static void t_get(struct hashmap *map, unsigned int ignore_case)
+{
+ struct test_entry *entry;
+ const char *key_val[][2] = { { "key1", "value1" },
+ { "key2", "value2" },
+ { "fooBarFrotz", "value3" },
+ { ignore_case ? "key4" : "foobarfrotz",
+ "value4" } };
+ const char *query[][2] = {
+ { ignore_case ? "Key1" : "key1", "value1" },
+ { ignore_case ? "keY2" : "key2", "value2" },
+ { ignore_case ? "FOObarFrotz" : "fooBarFrotz", "value3" },
+ { ignore_case ? "FOObarFrotz" : "foobarfrotz",
+ ignore_case ? "value3" : "value4" }
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) {
+ entry = alloc_test_entry(key_val[i][0], key_val[i][1],
+ ignore_case);
+ check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL);
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(query); i++) {
+ entry = get_test_entry(map, query[i][0], ignore_case);
+ if (check(entry != NULL))
+ check_str(get_value(entry), query[i][1]);
+ else
+ test_msg("query key: %s", query[i][0]);
+ }
+
+ check_pointer_eq(get_test_entry(map, "notInMap", ignore_case), NULL);
+ check_int(map->tablesize, ==, 64);
+ check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val));
+}
+
+static void t_add(struct hashmap *map, unsigned int ignore_case)
+{
+ struct test_entry *entry;
+ const char *key_val[][2] = {
+ { "key1", "value1" },
+ { ignore_case ? "Key1" : "key1", "value2" },
+ { "fooBarFrotz", "value3" },
+ { ignore_case ? "FOObarFrotz" : "fooBarFrotz", "value4" }
+ };
+ const char *query_keys[] = { "key1", ignore_case ? "FOObarFrotz" :
+ "fooBarFrotz" };
+ char seen[ARRAY_SIZE(key_val)] = { 0 };
+
+ for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) {
+ entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case);
+ hashmap_add(map, &entry->ent);
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(query_keys); i++) {
+ int count = 0;
+ entry = hashmap_get_entry_from_hash(map,
+ ignore_case ? strihash(query_keys[i]) :
+ strhash(query_keys[i]),
+ query_keys[i], struct test_entry, ent);
+
+ hashmap_for_each_entry_from(map, entry, ent)
+ {
+ int ret;
+ if (!check_int((ret = key_val_contains(
+ key_val, seen,
+ ARRAY_SIZE(key_val), entry)),
+ ==, 0)) {
+ switch (ret) {
+ case 1:
+ test_msg("found entry was not given in the input\n"
+ " key: %s\n value: %s",
+ entry->key, get_value(entry));
+ break;
+ case 2:
+ test_msg("duplicate entry detected\n"
+ " key: %s\n value: %s",
+ entry->key, get_value(entry));
+ break;
+ }
+ } else {
+ count++;
+ }
+ }
+ check_int(count, ==, 2);
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(seen); i++) {
+ if (!check_int(seen[i], ==, 1))
+ test_msg("following key-val pair was not iterated over:\n"
+ " key: %s\n value: %s",
+ key_val[i][0], key_val[i][1]);
+ }
+
+ check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val));
+ check_pointer_eq(get_test_entry(map, "notInMap", ignore_case), NULL);
+}
+
+static void t_remove(struct hashmap *map, unsigned int ignore_case)
+{
+ struct test_entry *entry, *removed;
+ const char *key_val[][2] = { { "key1", "value1" },
+ { "key2", "value2" },
+ { "fooBarFrotz", "value3" } };
+ const char *remove[][2] = { { ignore_case ? "Key1" : "key1", "value1" },
+ { ignore_case ? "keY2" : "key2", "value2" } };
+
+ for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) {
+ entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case);
+ check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL);
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(remove); i++) {
+ entry = alloc_test_entry(remove[i][0], "", ignore_case);
+ removed = hashmap_remove_entry(map, entry, ent, remove[i][0]);
+ if (check(removed != NULL))
+ check_str(get_value(removed), remove[i][1]);
+ free(entry);
+ free(removed);
+ }
+
+ entry = alloc_test_entry("notInMap", "", ignore_case);
+ check_pointer_eq(hashmap_remove_entry(map, entry, ent, "notInMap"), NULL);
+ free(entry);
+
+ check_int(map->tablesize, ==, 64);
+ check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val) - ARRAY_SIZE(remove));
+}
+
+static void t_iterate(struct hashmap *map, unsigned int ignore_case)
+{
+ struct test_entry *entry;
+ struct hashmap_iter iter;
+ const char *key_val[][2] = { { "key1", "value1" },
+ { "key2", "value2" },
+ { "fooBarFrotz", "value3" } };
+ char seen[ARRAY_SIZE(key_val)] = { 0 };
+
+ for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) {
+ entry = alloc_test_entry(key_val[i][0], key_val[i][1], ignore_case);
+ check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL);
+ }
+
+ hashmap_for_each_entry(map, &iter, entry, ent /* member name */)
+ {
+ int ret;
+ if (!check_int((ret = key_val_contains(key_val, seen,
+ ARRAY_SIZE(key_val),
+ entry)), ==, 0)) {
+ switch (ret) {
+ case 1:
+ test_msg("found entry was not given in the input\n"
+ " key: %s\n value: %s",
+ entry->key, get_value(entry));
+ break;
+ case 2:
+ test_msg("duplicate entry detected\n"
+ " key: %s\n value: %s",
+ entry->key, get_value(entry));
+ break;
+ }
+ }
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(seen); i++) {
+ if (!check_int(seen[i], ==, 1))
+ test_msg("following key-val pair was not iterated over:\n"
+ " key: %s\n value: %s",
+ key_val[i][0], key_val[i][1]);
+ }
+
+ check_int(hashmap_get_size(map), ==, ARRAY_SIZE(key_val));
+}
+
+static void t_alloc(struct hashmap *map, unsigned int ignore_case)
+{
+ struct test_entry *entry, *removed;
+
+ for (int i = 1; i <= 51; i++) {
+ char *key = xstrfmt("key%d", i);
+ char *value = xstrfmt("value%d", i);
+ entry = alloc_test_entry(key, value, ignore_case);
+ check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL);
+ free(key);
+ free(value);
+ }
+ check_int(map->tablesize, ==, 64);
+ check_int(hashmap_get_size(map), ==, 51);
+
+ entry = alloc_test_entry("key52", "value52", ignore_case);
+ check_pointer_eq(hashmap_put_entry(map, entry, ent), NULL);
+ check_int(map->tablesize, ==, 256);
+ check_int(hashmap_get_size(map), ==, 52);
+
+ for (int i = 1; i <= 12; i++) {
+ char *key = xstrfmt("key%d", i);
+ char *value = xstrfmt("value%d", i);
+
+ entry = alloc_test_entry(key, "", ignore_case);
+ removed = hashmap_remove_entry(map, entry, ent, key);
+ if (check(removed != NULL))
+ check_str(value, get_value(removed));
+ free(key);
+ free(value);
+ free(entry);
+ free(removed);
+ }
+ check_int(map->tablesize, ==, 256);
+ check_int(hashmap_get_size(map), ==, 40);
+
+ entry = alloc_test_entry("key40", "", ignore_case);
+ removed = hashmap_remove_entry(map, entry, ent, "key40");
+ if (check(removed != NULL))
+ check_str("value40", get_value(removed));
+ check_int(map->tablesize, ==, 64);
+ check_int(hashmap_get_size(map), ==, 39);
+ free(entry);
+ free(removed);
+}
+
+static void t_intern(struct hashmap *map, unsigned int ignore_case)
+{
+ const char *values[] = { "value1", "Value1", "value2", "value2" };
+
+ for (size_t i = 0; i < ARRAY_SIZE(values); i++) {
+ const char *i1 = strintern(values[i]);
+ const char *i2 = strintern(values[i]);
+
+ if (!check(!strcmp(i1, values[i])))
+ test_msg("strintern(%s) returns %s\n", values[i], i1);
+ else if (!check(i1 != values[i]))
+ test_msg("strintern(%s) returns input pointer\n",
+ values[i]);
+ else if (!check_pointer_eq(i1, i2))
+ test_msg("address('%s') != address('%s'), so strintern('%s') != strintern('%s')",
+ i1, i2, values[i], values[i]);
+ else
+ check_str(i1, values[i]);
+ }
+}
+
+int cmd_main(int argc UNUSED, const char **argv UNUSED)
+{
+ TEST(setup(t_replace, 0), "replace works");
+ TEST(setup(t_replace, 1), "replace (case insensitive) works");
+ TEST(setup(t_get, 0), "get works");
+ TEST(setup(t_get, 1), "get (case insensitive) works");
+ TEST(setup(t_add, 0), "add works");
+ TEST(setup(t_add, 1), "add (case insensitive) works");
+ TEST(setup(t_remove, 0), "remove works");
+ TEST(setup(t_remove, 1), "remove (case insensitive) works");
+ TEST(setup(t_iterate, 0), "iterate works");
+ TEST(setup(t_iterate, 1), "iterate (case insensitive) works");
+ TEST(setup(t_alloc, 0), "grow / shrink works");
+ TEST(setup(t_intern, 0), "string interning works");
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c
index 4e80bdf16d..1dd60ab5f0 100644
--- a/t/unit-tests/t-reftable-basics.c
+++ b/t/unit-tests/t-reftable-basics.c
@@ -20,141 +20,125 @@ static int integer_needle_lesseq(size_t i, void *_args)
return args->needle <= args->haystack[i];
}
-static void test_binsearch(void)
+int cmd_main(int argc, const char *argv[])
{
- int haystack[] = { 2, 4, 6, 8, 10 };
- struct {
- int needle;
- size_t expected_idx;
- } testcases[] = {
- {-9000, 0},
- {-1, 0},
- {0, 0},
- {2, 0},
- {3, 1},
- {4, 1},
- {7, 3},
- {9, 4},
- {10, 4},
- {11, 5},
- {9000, 5},
- };
-
- for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) {
- struct integer_needle_lesseq_args args = {
- .haystack = haystack,
- .needle = testcases[i].needle,
+ if_test ("binary search with binsearch works") {
+ int haystack[] = { 2, 4, 6, 8, 10 };
+ struct {
+ int needle;
+ size_t expected_idx;
+ } testcases[] = {
+ {-9000, 0},
+ {-1, 0},
+ {0, 0},
+ {2, 0},
+ {3, 1},
+ {4, 1},
+ {7, 3},
+ {9, 4},
+ {10, 4},
+ {11, 5},
+ {9000, 5},
};
- size_t idx;
- idx = binsearch(ARRAY_SIZE(haystack), &integer_needle_lesseq, &args);
- check_int(idx, ==, testcases[i].expected_idx);
+ for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) {
+ struct integer_needle_lesseq_args args = {
+ .haystack = haystack,
+ .needle = testcases[i].needle,
+ };
+ size_t idx;
+
+ idx = binsearch(ARRAY_SIZE(haystack),
+ &integer_needle_lesseq, &args);
+ check_int(idx, ==, testcases[i].expected_idx);
+ }
}
-}
-static void test_names_length(void)
-{
- const char *a[] = { "a", "b", NULL };
- check_int(names_length(a), ==, 2);
-}
-
-static void test_names_equal(void)
-{
- const char *a[] = { "a", "b", "c", NULL };
- const char *b[] = { "a", "b", "d", NULL };
- const char *c[] = { "a", "b", NULL };
+ if_test ("names_length retuns size of a NULL-terminated string array") {
+ const char *a[] = { "a", "b", NULL };
+ check_int(names_length(a), ==, 2);
+ }
- check(names_equal(a, a));
- check(!names_equal(a, b));
- check(!names_equal(a, c));
-}
+ if_test ("names_equal compares NULL-terminated string arrays") {
+ const char *a[] = { "a", "b", "c", NULL };
+ const char *b[] = { "a", "b", "d", NULL };
+ const char *c[] = { "a", "b", NULL };
-static void test_parse_names_normal(void)
-{
- char in1[] = "line\n";
- char in2[] = "a\nb\nc";
- char **out = NULL;
- parse_names(in1, strlen(in1), &out);
- check_str(out[0], "line");
- check(!out[1]);
- free_names(out);
-
- parse_names(in2, strlen(in2), &out);
- check_str(out[0], "a");
- check_str(out[1], "b");
- check_str(out[2], "c");
- check(!out[3]);
- free_names(out);
-}
+ check(names_equal(a, a));
+ check(!names_equal(a, b));
+ check(!names_equal(a, c));
+ }
-static void test_parse_names_drop_empty(void)
-{
- char in[] = "a\n\nb\n";
- char **out = NULL;
- parse_names(in, strlen(in), &out);
- check_str(out[0], "a");
- /* simply '\n' should be dropped as empty string */
- check_str(out[1], "b");
- check(!out[2]);
- free_names(out);
-}
+ if_test ("parse_names works for basic input") {
+ char in1[] = "line\n";
+ char in2[] = "a\nb\nc";
+ char **out = NULL;
+ parse_names(in1, strlen(in1), &out);
+ check_str(out[0], "line");
+ check(!out[1]);
+ free_names(out);
+
+ parse_names(in2, strlen(in2), &out);
+ check_str(out[0], "a");
+ check_str(out[1], "b");
+ check_str(out[2], "c");
+ check(!out[3]);
+ free_names(out);
+ }
-static void test_common_prefix(void)
-{
- struct strbuf a = STRBUF_INIT;
- struct strbuf b = STRBUF_INIT;
- struct {
- const char *a, *b;
- int want;
- } cases[] = {
- {"abcdef", "abc", 3},
- { "abc", "ab", 2 },
- { "", "abc", 0 },
- { "abc", "abd", 2 },
- { "abc", "pqr", 0 },
- };
-
- for (size_t i = 0; i < ARRAY_SIZE(cases); i++) {
- strbuf_addstr(&a, cases[i].a);
- strbuf_addstr(&b, cases[i].b);
- check_int(common_prefix_size(&a, &b), ==, cases[i].want);
- strbuf_reset(&a);
- strbuf_reset(&b);
+ if_test ("parse_names drops empty string") {
+ char in[] = "a\n\nb\n";
+ char **out = NULL;
+ parse_names(in, strlen(in), &out);
+ check_str(out[0], "a");
+ /* simply '\n' should be dropped as empty string */
+ check_str(out[1], "b");
+ check(!out[2]);
+ free_names(out);
}
- strbuf_release(&a);
- strbuf_release(&b);
-}
-static void test_u24_roundtrip(void)
-{
- uint32_t in = 0x112233;
- uint8_t dest[3];
- uint32_t out;
- put_be24(dest, in);
- out = get_be24(dest);
- check_int(in, ==, out);
-}
+ if_test ("common_prefix_size works") {
+ struct strbuf a = STRBUF_INIT;
+ struct strbuf b = STRBUF_INIT;
+ struct {
+ const char *a, *b;
+ int want;
+ } cases[] = {
+ {"abcdef", "abc", 3},
+ { "abc", "ab", 2 },
+ { "", "abc", 0 },
+ { "abc", "abd", 2 },
+ { "abc", "pqr", 0 },
+ };
-static void test_u16_roundtrip(void)
-{
- uint32_t in = 0xfef1;
- uint8_t dest[3];
- uint32_t out;
- put_be16(dest, in);
- out = get_be16(dest);
- check_int(in, ==, out);
-}
+ for (size_t i = 0; i < ARRAY_SIZE(cases); i++) {
+ strbuf_addstr(&a, cases[i].a);
+ strbuf_addstr(&b, cases[i].b);
+ check_int(common_prefix_size(&a, &b), ==, cases[i].want);
+ strbuf_reset(&a);
+ strbuf_reset(&b);
+ }
+ strbuf_release(&a);
+ strbuf_release(&b);
+ }
-int cmd_main(int argc, const char *argv[])
-{
- TEST(test_common_prefix(), "common_prefix_size works");
- TEST(test_parse_names_normal(), "parse_names works for basic input");
- TEST(test_parse_names_drop_empty(), "parse_names drops empty string");
- TEST(test_binsearch(), "binary search with binsearch works");
- TEST(test_names_length(), "names_length retuns size of a NULL-terminated string array");
- TEST(test_names_equal(), "names_equal compares NULL-terminated string arrays");
- TEST(test_u24_roundtrip(), "put_be24 and get_be24 work");
- TEST(test_u16_roundtrip(), "put_be16 and get_be16 work");
+ if_test ("put_be24 and get_be24 work") {
+ uint32_t in = 0x112233;
+ uint8_t dest[3];
+ uint32_t out;
+ put_be24(dest, in);
+ out = get_be24(dest);
+ check_int(in, ==, out);
+ }
+
+ if_test ("put_be16 and get_be16 work") {
+ uint32_t in = 0xfef1;
+ uint8_t dest[3];
+ uint32_t out;
+ put_be16(dest, in);
+ out = get_be16(dest);
+ check_int(in, ==, out);
+ }
return test_done();
}
diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c
new file mode 100644
index 0000000000..2ce56a0523
--- /dev/null
+++ b/t/unit-tests/t-reftable-readwrite.c
@@ -0,0 +1,974 @@
+/*
+Copyright 2020 Google LLC
+
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file or at
+https://developers.google.com/open-source/licenses/bsd
+*/
+
+#include "test-lib.h"
+#include "reftable/basics.h"
+#include "reftable/blocksource.h"
+#include "reftable/reader.h"
+#include "reftable/reftable-error.h"
+#include "reftable/reftable-writer.h"
+
+static const int update_index = 5;
+
+static void set_test_hash(uint8_t *p, int i)
+{
+ memset(p, (uint8_t)i, hash_size(GIT_SHA1_FORMAT_ID));
+}
+
+static ssize_t strbuf_add_void(void *b, const void *data, size_t sz)
+{
+ strbuf_add(b, data, sz);
+ return sz;
+}
+
+static int noop_flush(void *arg)
+{
+ return 0;
+}
+
+static void t_buffer(void)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_block_source source = { 0 };
+ struct reftable_block out = { 0 };
+ int n;
+ uint8_t in[] = "hello";
+ strbuf_add(&buf, in, sizeof(in));
+ block_source_from_strbuf(&source, &buf);
+ check_int(block_source_size(&source), ==, 6);
+ n = block_source_read_block(&source, &out, 0, sizeof(in));
+ check_int(n, ==, sizeof(in));
+ check(!memcmp(in, out.data, n));
+ reftable_block_done(&out);
+
+ n = block_source_read_block(&source, &out, 1, 2);
+ check_int(n, ==, 2);
+ check(!memcmp(out.data, "el", 2));
+
+ reftable_block_done(&out);
+ block_source_close(&source);
+ strbuf_release(&buf);
+}
+
+static void write_table(char ***names, struct strbuf *buf, int N,
+ int block_size, uint32_t hash_id)
+{
+ struct reftable_write_options opts = {
+ .block_size = block_size,
+ .hash_id = hash_id,
+ };
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
+ struct reftable_ref_record ref = { 0 };
+ int i = 0, n;
+ struct reftable_log_record log = { 0 };
+ const struct reftable_stats *stats = NULL;
+
+ REFTABLE_CALLOC_ARRAY(*names, N + 1);
+
+ reftable_writer_set_limits(w, update_index, update_index);
+ for (i = 0; i < N; i++) {
+ char name[100];
+ int n;
+
+ snprintf(name, sizeof(name), "refs/heads/branch%02d", i);
+
+ ref.refname = name;
+ ref.update_index = update_index;
+ ref.value_type = REFTABLE_REF_VAL1;
+ set_test_hash(ref.value.val1, i);
+ (*names)[i] = xstrdup(name);
+
+ n = reftable_writer_add_ref(w, &ref);
+ check_int(n, ==, 0);
+ }
+
+ for (i = 0; i < N; i++) {
+ char name[100];
+ int n;
+
+ snprintf(name, sizeof(name), "refs/heads/branch%02d", i);
+
+ log.refname = name;
+ log.update_index = update_index;
+ log.value_type = REFTABLE_LOG_UPDATE;
+ set_test_hash(log.value.update.new_hash, i);
+ log.value.update.message = (char *) "message";
+
+ n = reftable_writer_add_log(w, &log);
+ check_int(n, ==, 0);
+ }
+
+ n = reftable_writer_close(w);
+ check_int(n, ==, 0);
+
+ stats = reftable_writer_stats(w);
+ for (i = 0; i < stats->ref_stats.blocks; i++) {
+ int off = i * opts.block_size;
+ if (!off)
+ off = header_size((hash_id == GIT_SHA256_FORMAT_ID) ? 2 : 1);
+ check_char(buf->buf[off], ==, 'r');
+ }
+
+ check_int(stats->log_stats.blocks, >, 0);
+ reftable_writer_free(w);
+}
+
+static void t_log_buffer_size(void)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_write_options opts = {
+ .block_size = 4096,
+ };
+ int err;
+ int i;
+ struct reftable_log_record
+ log = { .refname = (char *) "refs/heads/master",
+ .update_index = 0xa,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value = { .update = {
+ .name = (char *) "Han-Wen Nienhuys",
+ .email = (char *) "hanwen@google.com",
+ .tz_offset = 100,
+ .time = 0x5e430672,
+ .message = (char *) "commit: 9\n",
+ } } };
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+
+ /* This tests buffer extension for log compression. Must use a random
+ hash, to ensure that the compressed part is larger than the original.
+ */
+ for (i = 0; i < GIT_SHA1_RAWSZ; i++) {
+ log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256);
+ log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256);
+ }
+ reftable_writer_set_limits(w, update_index, update_index);
+ err = reftable_writer_add_log(w, &log);
+ check(!err);
+ err = reftable_writer_close(w);
+ check(!err);
+ reftable_writer_free(w);
+ strbuf_release(&buf);
+}
+
+static void t_log_overflow(void)
+{
+ struct strbuf buf = STRBUF_INIT;
+ char msg[256] = { 0 };
+ struct reftable_write_options opts = {
+ .block_size = ARRAY_SIZE(msg),
+ };
+ int err;
+ struct reftable_log_record log = {
+ .refname = (char *) "refs/heads/master",
+ .update_index = 0xa,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value = {
+ .update = {
+ .old_hash = { 1 },
+ .new_hash = { 2 },
+ .name = (char *) "Han-Wen Nienhuys",
+ .email = (char *) "hanwen@google.com",
+ .tz_offset = 100,
+ .time = 0x5e430672,
+ .message = msg,
+ },
+ },
+ };
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+
+ memset(msg, 'x', sizeof(msg) - 1);
+ reftable_writer_set_limits(w, update_index, update_index);
+ err = reftable_writer_add_log(w, &log);
+ check_int(err, ==, REFTABLE_ENTRY_TOO_BIG_ERROR);
+ reftable_writer_free(w);
+ strbuf_release(&buf);
+}
+
+static void t_log_write_read(void)
+{
+ int N = 2;
+ char **names = reftable_calloc(N + 1, sizeof(*names));
+ int err;
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ };
+ struct reftable_ref_record ref = { 0 };
+ int i = 0;
+ struct reftable_log_record log = { 0 };
+ int n;
+ struct reftable_iterator it = { 0 };
+ struct reftable_reader rd = { 0 };
+ struct reftable_block_source source = { 0 };
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ const struct reftable_stats *stats = NULL;
+ reftable_writer_set_limits(w, 0, N);
+ for (i = 0; i < N; i++) {
+ char name[256];
+ struct reftable_ref_record ref = { 0 };
+ snprintf(name, sizeof(name), "b%02d%0*d", i, 130, 7);
+ names[i] = xstrdup(name);
+ ref.refname = name;
+ ref.update_index = i;
+
+ err = reftable_writer_add_ref(w, &ref);
+ check(!err);
+ }
+ for (i = 0; i < N; i++) {
+ struct reftable_log_record log = { 0 };
+
+ log.refname = names[i];
+ log.update_index = i;
+ log.value_type = REFTABLE_LOG_UPDATE;
+ set_test_hash(log.value.update.old_hash, i);
+ set_test_hash(log.value.update.new_hash, i + 1);
+
+ err = reftable_writer_add_log(w, &log);
+ check(!err);
+ }
+
+ n = reftable_writer_close(w);
+ check_int(n, ==, 0);
+
+ stats = reftable_writer_stats(w);
+ check_int(stats->log_stats.blocks, >, 0);
+ reftable_writer_free(w);
+ w = NULL;
+
+ block_source_from_strbuf(&source, &buf);
+
+ err = init_reader(&rd, &source, "file.log");
+ check(!err);
+
+ reftable_reader_init_ref_iterator(&rd, &it);
+
+ err = reftable_iterator_seek_ref(&it, names[N - 1]);
+ check(!err);
+
+ err = reftable_iterator_next_ref(&it, &ref);
+ check(!err);
+
+ /* end of iteration. */
+ err = reftable_iterator_next_ref(&it, &ref);
+ check_int(err, >, 0);
+
+ reftable_iterator_destroy(&it);
+ reftable_ref_record_release(&ref);
+
+ reftable_reader_init_log_iterator(&rd, &it);
+
+ err = reftable_iterator_seek_log(&it, "");
+ check(!err);
+
+ for (i = 0; ; i++) {
+ int err = reftable_iterator_next_log(&it, &log);
+ if (err > 0)
+ break;
+ check(!err);
+ check_str(names[i], log.refname);
+ check_int(i, ==, log.update_index);
+ reftable_log_record_release(&log);
+ }
+
+ check_int(i, ==, N);
+ reftable_iterator_destroy(&it);
+
+ /* cleanup. */
+ strbuf_release(&buf);
+ free_names(names);
+ reader_close(&rd);
+}
+
+static void t_log_zlib_corruption(void)
+{
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ };
+ struct reftable_iterator it = { 0 };
+ struct reftable_reader rd = { 0 };
+ struct reftable_block_source source = { 0 };
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ const struct reftable_stats *stats = NULL;
+ char message[100] = { 0 };
+ int err, i, n;
+ struct reftable_log_record log = {
+ .refname = (char *) "refname",
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value = {
+ .update = {
+ .new_hash = { 1 },
+ .old_hash = { 2 },
+ .name = (char *) "My Name",
+ .email = (char *) "myname@invalid",
+ .message = message,
+ },
+ },
+ };
+
+ for (i = 0; i < sizeof(message) - 1; i++)
+ message[i] = (uint8_t)(git_rand() % 64 + ' ');
+
+ reftable_writer_set_limits(w, 1, 1);
+
+ err = reftable_writer_add_log(w, &log);
+ check(!err);
+
+ n = reftable_writer_close(w);
+ check_int(n, ==, 0);
+
+ stats = reftable_writer_stats(w);
+ check_int(stats->log_stats.blocks, >, 0);
+ reftable_writer_free(w);
+ w = NULL;
+
+ /* corrupt the data. */
+ buf.buf[50] ^= 0x99;
+
+ block_source_from_strbuf(&source, &buf);
+
+ err = init_reader(&rd, &source, "file.log");
+ check(!err);
+
+ reftable_reader_init_log_iterator(&rd, &it);
+ err = reftable_iterator_seek_log(&it, "refname");
+ check_int(err, ==, REFTABLE_ZLIB_ERROR);
+
+ reftable_iterator_destroy(&it);
+
+ /* cleanup. */
+ strbuf_release(&buf);
+ reader_close(&rd);
+}
+
+static void t_table_read_write_sequential(void)
+{
+ char **names;
+ struct strbuf buf = STRBUF_INIT;
+ int N = 50;
+ struct reftable_iterator it = { 0 };
+ struct reftable_block_source source = { 0 };
+ struct reftable_reader rd = { 0 };
+ int err = 0;
+ int j = 0;
+
+ write_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID);
+
+ block_source_from_strbuf(&source, &buf);
+
+ err = init_reader(&rd, &source, "file.ref");
+ check(!err);
+
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, "");
+ check(!err);
+
+ for (j = 0; ; j++) {
+ struct reftable_ref_record ref = { 0 };
+ int r = reftable_iterator_next_ref(&it, &ref);
+ check_int(r, >=, 0);
+ if (r > 0)
+ break;
+ check_str(names[j], ref.refname);
+ check_int(update_index, ==, ref.update_index);
+ reftable_ref_record_release(&ref);
+ }
+ check_int(j, ==, N);
+ reftable_iterator_destroy(&it);
+ strbuf_release(&buf);
+ free_names(names);
+
+ reader_close(&rd);
+}
+
+static void t_table_write_small_table(void)
+{
+ char **names;
+ struct strbuf buf = STRBUF_INIT;
+ int N = 1;
+ write_table(&names, &buf, N, 4096, GIT_SHA1_FORMAT_ID);
+ check_int(buf.len, <, 200);
+ strbuf_release(&buf);
+ free_names(names);
+}
+
+static void t_table_read_api(void)
+{
+ char **names;
+ struct strbuf buf = STRBUF_INIT;
+ int N = 50;
+ struct reftable_reader rd = { 0 };
+ struct reftable_block_source source = { 0 };
+ int err;
+ struct reftable_log_record log = { 0 };
+ struct reftable_iterator it = { 0 };
+
+ write_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID);
+
+ block_source_from_strbuf(&source, &buf);
+
+ err = init_reader(&rd, &source, "file.ref");
+ check(!err);
+
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, names[0]);
+ check(!err);
+
+ err = reftable_iterator_next_log(&it, &log);
+ check_int(err, ==, REFTABLE_API_ERROR);
+
+ strbuf_release(&buf);
+ free_names(names);
+ reftable_iterator_destroy(&it);
+ reader_close(&rd);
+ strbuf_release(&buf);
+}
+
+static void t_table_read_write_seek(int index, int hash_id)
+{
+ char **names;
+ struct strbuf buf = STRBUF_INIT;
+ int N = 50;
+ struct reftable_reader rd = { 0 };
+ struct reftable_block_source source = { 0 };
+ int err;
+ int i = 0;
+
+ struct reftable_iterator it = { 0 };
+ struct strbuf pastLast = STRBUF_INIT;
+ struct reftable_ref_record ref = { 0 };
+
+ write_table(&names, &buf, N, 256, hash_id);
+
+ block_source_from_strbuf(&source, &buf);
+
+ err = init_reader(&rd, &source, "file.ref");
+ check(!err);
+ check_int(hash_id, ==, reftable_reader_hash_id(&rd));
+
+ if (!index)
+ rd.ref_offsets.index_offset = 0;
+ else
+ check_int(rd.ref_offsets.index_offset, >, 0);
+
+ for (i = 1; i < N; i++) {
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, names[i]);
+ check(!err);
+ err = reftable_iterator_next_ref(&it, &ref);
+ check(!err);
+ check_str(names[i], ref.refname);
+ check_int(REFTABLE_REF_VAL1, ==, ref.value_type);
+ check_int(i, ==, ref.value.val1[0]);
+
+ reftable_ref_record_release(&ref);
+ reftable_iterator_destroy(&it);
+ }
+
+ strbuf_addstr(&pastLast, names[N - 1]);
+ strbuf_addstr(&pastLast, "/");
+
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, pastLast.buf);
+ if (err == 0) {
+ struct reftable_ref_record ref = { 0 };
+ int err = reftable_iterator_next_ref(&it, &ref);
+ check_int(err, >, 0);
+ } else {
+ check_int(err, >, 0);
+ }
+
+ strbuf_release(&pastLast);
+ reftable_iterator_destroy(&it);
+
+ strbuf_release(&buf);
+ free_names(names);
+ reader_close(&rd);
+}
+
+static void t_table_read_write_seek_linear(void)
+{
+ t_table_read_write_seek(0, GIT_SHA1_FORMAT_ID);
+}
+
+static void t_table_read_write_seek_linear_sha256(void)
+{
+ t_table_read_write_seek(0, GIT_SHA256_FORMAT_ID);
+}
+
+static void t_table_read_write_seek_index(void)
+{
+ t_table_read_write_seek(1, GIT_SHA1_FORMAT_ID);
+}
+
+static void t_table_refs_for(int indexed)
+{
+ int N = 50;
+ char **want_names = reftable_calloc(N + 1, sizeof(*want_names));
+ int want_names_len = 0;
+ uint8_t want_hash[GIT_SHA1_RAWSZ];
+
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ };
+ struct reftable_ref_record ref = { 0 };
+ int i = 0;
+ int n;
+ int err;
+ struct reftable_reader rd;
+ struct reftable_block_source source = { 0 };
+
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+
+ struct reftable_iterator it = { 0 };
+ int j;
+
+ set_test_hash(want_hash, 4);
+
+ for (i = 0; i < N; i++) {
+ uint8_t hash[GIT_SHA1_RAWSZ];
+ char fill[51] = { 0 };
+ char name[100];
+ struct reftable_ref_record ref = { 0 };
+
+ memset(hash, i, sizeof(hash));
+ memset(fill, 'x', 50);
+ /* Put the variable part in the start */
+ snprintf(name, sizeof(name), "br%02d%s", i, fill);
+ name[40] = 0;
+ ref.refname = name;
+
+ ref.value_type = REFTABLE_REF_VAL2;
+ set_test_hash(ref.value.val2.value, i / 4);
+ set_test_hash(ref.value.val2.target_value, 3 + i / 4);
+
+ /* 80 bytes / entry, so 3 entries per block. Yields 17
+ */
+ /* blocks. */
+ n = reftable_writer_add_ref(w, &ref);
+ check_int(n, ==, 0);
+
+ if (!memcmp(ref.value.val2.value, want_hash, GIT_SHA1_RAWSZ) ||
+ !memcmp(ref.value.val2.target_value, want_hash, GIT_SHA1_RAWSZ))
+ want_names[want_names_len++] = xstrdup(name);
+ }
+
+ n = reftable_writer_close(w);
+ check_int(n, ==, 0);
+
+ reftable_writer_free(w);
+ w = NULL;
+
+ block_source_from_strbuf(&source, &buf);
+
+ err = init_reader(&rd, &source, "file.ref");
+ check(!err);
+ if (!indexed)
+ rd.obj_offsets.is_present = 0;
+
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, "");
+ check(!err);
+ reftable_iterator_destroy(&it);
+
+ err = reftable_reader_refs_for(&rd, &it, want_hash);
+ check(!err);
+
+ for (j = 0; ; j++) {
+ int err = reftable_iterator_next_ref(&it, &ref);
+ check_int(err, >=, 0);
+ if (err > 0)
+ break;
+ check_int(j, <, want_names_len);
+ check_str(ref.refname, want_names[j]);
+ reftable_ref_record_release(&ref);
+ }
+ check_int(j, ==, want_names_len);
+
+ strbuf_release(&buf);
+ free_names(want_names);
+ reftable_iterator_destroy(&it);
+ reader_close(&rd);
+}
+
+static void t_table_refs_for_no_index(void)
+{
+ t_table_refs_for(0);
+}
+
+static void t_table_refs_for_obj_index(void)
+{
+ t_table_refs_for(1);
+}
+
+static void t_write_empty_table(void)
+{
+ struct reftable_write_options opts = { 0 };
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_block_source source = { 0 };
+ struct reftable_reader *rd = NULL;
+ struct reftable_ref_record rec = { 0 };
+ struct reftable_iterator it = { 0 };
+ int err;
+
+ reftable_writer_set_limits(w, 1, 1);
+
+ err = reftable_writer_close(w);
+ check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR);
+ reftable_writer_free(w);
+
+ check_int(buf.len, ==, header_size(1) + footer_size(1));
+
+ block_source_from_strbuf(&source, &buf);
+
+ err = reftable_new_reader(&rd, &source, "filename");
+ check(!err);
+
+ reftable_reader_init_ref_iterator(rd, &it);
+ err = reftable_iterator_seek_ref(&it, "");
+ check(!err);
+
+ err = reftable_iterator_next_ref(&it, &rec);
+ check_int(err, >, 0);
+
+ reftable_iterator_destroy(&it);
+ reftable_reader_free(rd);
+ strbuf_release(&buf);
+}
+
+static void t_write_object_id_min_length(void)
+{
+ struct reftable_write_options opts = {
+ .block_size = 75,
+ };
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_ref_record ref = {
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = {42},
+ };
+ int err;
+ int i;
+
+ reftable_writer_set_limits(w, 1, 1);
+
+ /* Write the same hash in many refs. If there is only 1 hash, the
+ * disambiguating prefix is length 0 */
+ for (i = 0; i < 256; i++) {
+ char name[256];
+ snprintf(name, sizeof(name), "ref%05d", i);
+ ref.refname = name;
+ err = reftable_writer_add_ref(w, &ref);
+ check(!err);
+ }
+
+ err = reftable_writer_close(w);
+ check(!err);
+ check_int(reftable_writer_stats(w)->object_id_len, ==, 2);
+ reftable_writer_free(w);
+ strbuf_release(&buf);
+}
+
+static void t_write_object_id_length(void)
+{
+ struct reftable_write_options opts = {
+ .block_size = 75,
+ };
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_ref_record ref = {
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = {42},
+ };
+ int err;
+ int i;
+
+ reftable_writer_set_limits(w, 1, 1);
+
+ /* Write the same hash in many refs. If there is only 1 hash, the
+ * disambiguating prefix is length 0 */
+ for (i = 0; i < 256; i++) {
+ char name[256];
+ snprintf(name, sizeof(name), "ref%05d", i);
+ ref.refname = name;
+ ref.value.val1[15] = i;
+ err = reftable_writer_add_ref(w, &ref);
+ check(!err);
+ }
+
+ err = reftable_writer_close(w);
+ check(!err);
+ check_int(reftable_writer_stats(w)->object_id_len, ==, 16);
+ reftable_writer_free(w);
+ strbuf_release(&buf);
+}
+
+static void t_write_empty_key(void)
+{
+ struct reftable_write_options opts = { 0 };
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_ref_record ref = {
+ .refname = (char *) "",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_DELETION,
+ };
+ int err;
+
+ reftable_writer_set_limits(w, 1, 1);
+ err = reftable_writer_add_ref(w, &ref);
+ check_int(err, ==, REFTABLE_API_ERROR);
+
+ err = reftable_writer_close(w);
+ check_int(err, ==, REFTABLE_EMPTY_TABLE_ERROR);
+ reftable_writer_free(w);
+ strbuf_release(&buf);
+}
+
+static void t_write_key_order(void)
+{
+ struct reftable_write_options opts = { 0 };
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_writer *w =
+ reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
+ struct reftable_ref_record refs[2] = {
+ {
+ .refname = (char *) "b",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_SYMREF,
+ .value = {
+ .symref = (char *) "target",
+ },
+ }, {
+ .refname = (char *) "a",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_SYMREF,
+ .value = {
+ .symref = (char *) "target",
+ },
+ }
+ };
+ int err;
+
+ reftable_writer_set_limits(w, 1, 1);
+ err = reftable_writer_add_ref(w, &refs[0]);
+ check(!err);
+ err = reftable_writer_add_ref(w, &refs[1]);
+ check_int(err, ==, REFTABLE_API_ERROR);
+
+ refs[0].update_index = 2;
+ err = reftable_writer_add_ref(w, &refs[0]);
+ check_int(err, ==, REFTABLE_API_ERROR);
+
+ reftable_writer_close(w);
+ reftable_writer_free(w);
+ strbuf_release(&buf);
+}
+
+static void t_write_multiple_indices(void)
+{
+ struct reftable_write_options opts = {
+ .block_size = 100,
+ };
+ struct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;
+ struct reftable_block_source source = { 0 };
+ struct reftable_iterator it = { 0 };
+ const struct reftable_stats *stats;
+ struct reftable_writer *writer;
+ struct reftable_reader *reader;
+ int err, i;
+
+ writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts);
+ reftable_writer_set_limits(writer, 1, 1);
+ for (i = 0; i < 100; i++) {
+ struct reftable_ref_record ref = {
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = {i},
+ };
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "refs/heads/%04d", i);
+ ref.refname = buf.buf,
+
+ err = reftable_writer_add_ref(writer, &ref);
+ check(!err);
+ }
+
+ for (i = 0; i < 100; i++) {
+ struct reftable_log_record log = {
+ .update_index = 1,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value.update = {
+ .old_hash = { i },
+ .new_hash = { i },
+ },
+ };
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "refs/heads/%04d", i);
+ log.refname = buf.buf,
+
+ err = reftable_writer_add_log(writer, &log);
+ check(!err);
+ }
+
+ reftable_writer_close(writer);
+
+ /*
+ * The written data should be sufficiently large to result in indices
+ * for each of the block types.
+ */
+ stats = reftable_writer_stats(writer);
+ check_int(stats->ref_stats.index_offset, >, 0);
+ check_int(stats->obj_stats.index_offset, >, 0);
+ check_int(stats->log_stats.index_offset, >, 0);
+
+ block_source_from_strbuf(&source, &writer_buf);
+ err = reftable_new_reader(&reader, &source, "filename");
+ check(!err);
+
+ /*
+ * Seeking the log uses the log index now. In case there is any
+ * confusion regarding indices we would notice here.
+ */
+ reftable_reader_init_log_iterator(reader, &it);
+ err = reftable_iterator_seek_log(&it, "");
+ check(!err);
+
+ reftable_iterator_destroy(&it);
+ reftable_writer_free(writer);
+ reftable_reader_free(reader);
+ strbuf_release(&writer_buf);
+ strbuf_release(&buf);
+}
+
+static void t_write_multi_level_index(void)
+{
+ struct reftable_write_options opts = {
+ .block_size = 100,
+ };
+ struct strbuf writer_buf = STRBUF_INIT, buf = STRBUF_INIT;
+ struct reftable_block_source source = { 0 };
+ struct reftable_iterator it = { 0 };
+ const struct reftable_stats *stats;
+ struct reftable_writer *writer;
+ struct reftable_reader *reader;
+ int err;
+
+ writer = reftable_new_writer(&strbuf_add_void, &noop_flush, &writer_buf, &opts);
+ reftable_writer_set_limits(writer, 1, 1);
+ for (size_t i = 0; i < 200; i++) {
+ struct reftable_ref_record ref = {
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = {i},
+ };
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "refs/heads/%03" PRIuMAX, (uintmax_t)i);
+ ref.refname = buf.buf,
+
+ err = reftable_writer_add_ref(writer, &ref);
+ check(!err);
+ }
+ reftable_writer_close(writer);
+
+ /*
+ * The written refs should be sufficiently large to result in a
+ * multi-level index.
+ */
+ stats = reftable_writer_stats(writer);
+ check_int(stats->ref_stats.max_index_level, ==, 2);
+
+ block_source_from_strbuf(&source, &writer_buf);
+ err = reftable_new_reader(&reader, &source, "filename");
+ check(!err);
+
+ /*
+ * Seeking the last ref should work as expected.
+ */
+ reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_iterator_seek_ref(&it, "refs/heads/199");
+ check(!err);
+
+ reftable_iterator_destroy(&it);
+ reftable_writer_free(writer);
+ reftable_reader_free(reader);
+ strbuf_release(&writer_buf);
+ strbuf_release(&buf);
+}
+
+static void t_corrupt_table_empty(void)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_block_source source = { 0 };
+ struct reftable_reader rd = { 0 };
+ int err;
+
+ block_source_from_strbuf(&source, &buf);
+ err = init_reader(&rd, &source, "file.log");
+ check_int(err, ==, REFTABLE_FORMAT_ERROR);
+}
+
+static void t_corrupt_table(void)
+{
+ uint8_t zeros[1024] = { 0 };
+ struct strbuf buf = STRBUF_INIT;
+ struct reftable_block_source source = { 0 };
+ struct reftable_reader rd = { 0 };
+ int err;
+ strbuf_add(&buf, zeros, sizeof(zeros));
+
+ block_source_from_strbuf(&source, &buf);
+ err = init_reader(&rd, &source, "file.log");
+ check_int(err, ==, REFTABLE_FORMAT_ERROR);
+ strbuf_release(&buf);
+}
+
+int cmd_main(int argc, const char *argv[])
+{
+ TEST(t_buffer(), "strbuf works as blocksource");
+ TEST(t_corrupt_table(), "read-write on corrupted table");
+ TEST(t_corrupt_table_empty(), "read-write on an empty table");
+ TEST(t_log_buffer_size(), "buffer extension for log compression");
+ TEST(t_log_overflow(), "log overflow returns expected error");
+ TEST(t_log_write_read(), "read-write on log records");
+ TEST(t_log_zlib_corruption(), "reading corrupted log record returns expected error");
+ TEST(t_table_read_api(), "read on a table");
+ TEST(t_table_read_write_seek_index(), "read-write on a table with index");
+ TEST(t_table_read_write_seek_linear(), "read-write on a table without index (SHA1)");
+ TEST(t_table_read_write_seek_linear_sha256(), "read-write on a table without index (SHA256)");
+ TEST(t_table_read_write_sequential(), "sequential read-write on a table");
+ TEST(t_table_refs_for_no_index(), "refs-only table with no index");
+ TEST(t_table_refs_for_obj_index(), "refs-only table with index");
+ TEST(t_table_write_small_table(), "write_table works");
+ TEST(t_write_empty_key(), "write on refs with empty keys");
+ TEST(t_write_empty_table(), "read-write on empty tables");
+ TEST(t_write_key_order(), "refs must be written in increasing order");
+ TEST(t_write_multi_level_index(), "table with multi-level index");
+ TEST(t_write_multiple_indices(), "table with indices for multiple block types");
+ TEST(t_write_object_id_length(), "prefix compression on writing refs");
+ TEST(t_write_object_id_min_length(), "prefix compression on writing refs");
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
index fa1a041469..c4bac8fc91 100644
--- a/t/unit-tests/t-strvec.c
+++ b/t/unit-tests/t-strvec.c
@@ -19,237 +19,193 @@
} \
} while (0)
-static void t_static_init(void)
-{
- struct strvec vec = STRVEC_INIT;
- check_pointer_eq(vec.v, empty_strvec);
- check_uint(vec.nr, ==, 0);
- check_uint(vec.alloc, ==, 0);
-}
-
-static void t_dynamic_init(void)
-{
- struct strvec vec;
- strvec_init(&vec);
- check_pointer_eq(vec.v, empty_strvec);
- check_uint(vec.nr, ==, 0);
- check_uint(vec.alloc, ==, 0);
-}
-
-static void t_clear(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_push(&vec, "foo");
- strvec_clear(&vec);
- check_pointer_eq(vec.v, empty_strvec);
- check_uint(vec.nr, ==, 0);
- check_uint(vec.alloc, ==, 0);
-}
-
-static void t_push(void)
-{
- struct strvec vec = STRVEC_INIT;
-
- strvec_push(&vec, "foo");
- check_strvec(&vec, "foo", NULL);
-
- strvec_push(&vec, "bar");
- check_strvec(&vec, "foo", "bar", NULL);
-
- strvec_clear(&vec);
-}
-
-static void t_pushf(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushf(&vec, "foo: %d", 1);
- check_strvec(&vec, "foo: 1", NULL);
- strvec_clear(&vec);
-}
-
-static void t_pushl(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- check_strvec(&vec, "foo", "bar", "baz", NULL);
- strvec_clear(&vec);
-}
-
-static void t_pushv(void)
-{
- const char *strings[] = {
- "foo", "bar", "baz", NULL,
- };
- struct strvec vec = STRVEC_INIT;
-
- strvec_pushv(&vec, strings);
- check_strvec(&vec, "foo", "bar", "baz", NULL);
-
- strvec_clear(&vec);
-}
-
-static void t_replace_at_head(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_replace(&vec, 0, "replaced");
- check_strvec(&vec, "replaced", "bar", "baz", NULL);
- strvec_clear(&vec);
-}
-
-static void t_replace_at_tail(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_replace(&vec, 2, "replaced");
- check_strvec(&vec, "foo", "bar", "replaced", NULL);
- strvec_clear(&vec);
-}
-
-static void t_replace_in_between(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_replace(&vec, 1, "replaced");
- check_strvec(&vec, "foo", "replaced", "baz", NULL);
- strvec_clear(&vec);
-}
-
-static void t_replace_with_substring(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", NULL);
- strvec_replace(&vec, 0, vec.v[0] + 1);
- check_strvec(&vec, "oo", NULL);
- strvec_clear(&vec);
-}
-
-static void t_remove_at_head(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_remove(&vec, 0);
- check_strvec(&vec, "bar", "baz", NULL);
- strvec_clear(&vec);
-}
-
-static void t_remove_at_tail(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_remove(&vec, 2);
- check_strvec(&vec, "foo", "bar", NULL);
- strvec_clear(&vec);
-}
-
-static void t_remove_in_between(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_remove(&vec, 1);
- check_strvec(&vec, "foo", "baz", NULL);
- strvec_clear(&vec);
-}
-
-static void t_pop_empty_array(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pop(&vec);
- check_strvec(&vec, NULL);
- strvec_clear(&vec);
-}
-
-static void t_pop_non_empty_array(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_pushl(&vec, "foo", "bar", "baz", NULL);
- strvec_pop(&vec);
- check_strvec(&vec, "foo", "bar", NULL);
- strvec_clear(&vec);
-}
-
-static void t_split_empty_string(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, "");
- check_strvec(&vec, NULL);
- strvec_clear(&vec);
-}
-
-static void t_split_single_item(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, "foo");
- check_strvec(&vec, "foo", NULL);
- strvec_clear(&vec);
-}
-
-static void t_split_multiple_items(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, "foo bar baz");
- check_strvec(&vec, "foo", "bar", "baz", NULL);
- strvec_clear(&vec);
-}
-
-static void t_split_whitespace_only(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, " \t\n");
- check_strvec(&vec, NULL);
- strvec_clear(&vec);
-}
-
-static void t_split_multiple_consecutive_whitespaces(void)
-{
- struct strvec vec = STRVEC_INIT;
- strvec_split(&vec, "foo\n\t bar");
- check_strvec(&vec, "foo", "bar", NULL);
- strvec_clear(&vec);
-}
-
-static void t_detach(void)
-{
- struct strvec vec = STRVEC_INIT;
- const char **detached;
-
- strvec_push(&vec, "foo");
-
- detached = strvec_detach(&vec);
- check_str(detached[0], "foo");
- check_pointer_eq(detached[1], NULL);
-
- check_pointer_eq(vec.v, empty_strvec);
- check_uint(vec.nr, ==, 0);
- check_uint(vec.alloc, ==, 0);
-
- free((char *) detached[0]);
- free(detached);
-}
-
int cmd_main(int argc, const char **argv)
{
- TEST(t_static_init(), "static initialization");
- TEST(t_dynamic_init(), "dynamic initialization");
- TEST(t_clear(), "clear");
- TEST(t_push(), "push");
- TEST(t_pushf(), "pushf");
- TEST(t_pushl(), "pushl");
- TEST(t_pushv(), "pushv");
- TEST(t_replace_at_head(), "replace at head");
- TEST(t_replace_in_between(), "replace in between");
- TEST(t_replace_at_tail(), "replace at tail");
- TEST(t_replace_with_substring(), "replace with substring");
- TEST(t_remove_at_head(), "remove at head");
- TEST(t_remove_in_between(), "remove in between");
- TEST(t_remove_at_tail(), "remove at tail");
- TEST(t_pop_empty_array(), "pop with empty array");
- TEST(t_pop_non_empty_array(), "pop with non-empty array");
- TEST(t_split_empty_string(), "split empty string");
- TEST(t_split_single_item(), "split single item");
- TEST(t_split_multiple_items(), "split multiple items");
- TEST(t_split_whitespace_only(), "split whitespace only");
- TEST(t_split_multiple_consecutive_whitespaces(), "split multiple consecutive whitespaces");
- TEST(t_detach(), "detach");
+ if_test ("static initialization") {
+ struct strvec vec = STRVEC_INIT;
+ check_pointer_eq(vec.v, empty_strvec);
+ check_uint(vec.nr, ==, 0);
+ check_uint(vec.alloc, ==, 0);
+ }
+
+ if_test ("dynamic initialization") {
+ struct strvec vec;
+ strvec_init(&vec);
+ check_pointer_eq(vec.v, empty_strvec);
+ check_uint(vec.nr, ==, 0);
+ check_uint(vec.alloc, ==, 0);
+ }
+
+ if_test ("clear") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_push(&vec, "foo");
+ strvec_clear(&vec);
+ check_pointer_eq(vec.v, empty_strvec);
+ check_uint(vec.nr, ==, 0);
+ check_uint(vec.alloc, ==, 0);
+ }
+
+ if_test ("push") {
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_push(&vec, "foo");
+ check_strvec(&vec, "foo", NULL);
+
+ strvec_push(&vec, "bar");
+ check_strvec(&vec, "foo", "bar", NULL);
+
+ strvec_clear(&vec);
+ }
+
+ if_test ("pushf") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushf(&vec, "foo: %d", 1);
+ check_strvec(&vec, "foo: 1", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("pushl") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ check_strvec(&vec, "foo", "bar", "baz", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("pushv") {
+ const char *strings[] = {
+ "foo", "bar", "baz", NULL,
+ };
+ struct strvec vec = STRVEC_INIT;
+
+ strvec_pushv(&vec, strings);
+ check_strvec(&vec, "foo", "bar", "baz", NULL);
+
+ strvec_clear(&vec);
+ }
+
+ if_test ("replace at head") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_replace(&vec, 0, "replaced");
+ check_strvec(&vec, "replaced", "bar", "baz", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("replace at tail") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_replace(&vec, 2, "replaced");
+ check_strvec(&vec, "foo", "bar", "replaced", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("replace in between") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_replace(&vec, 1, "replaced");
+ check_strvec(&vec, "foo", "replaced", "baz", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("replace with substring") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", NULL);
+ strvec_replace(&vec, 0, vec.v[0] + 1);
+ check_strvec(&vec, "oo", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("remove at head") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_remove(&vec, 0);
+ check_strvec(&vec, "bar", "baz", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("remove at tail") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_remove(&vec, 2);
+ check_strvec(&vec, "foo", "bar", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("remove in between") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_remove(&vec, 1);
+ check_strvec(&vec, "foo", "baz", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("pop with empty array") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pop(&vec);
+ check_strvec(&vec, NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("pop with non-empty array") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
+ strvec_pop(&vec);
+ check_strvec(&vec, "foo", "bar", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("split empty string") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_split(&vec, "");
+ check_strvec(&vec, NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("split single item") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_split(&vec, "foo");
+ check_strvec(&vec, "foo", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("split multiple items") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_split(&vec, "foo bar baz");
+ check_strvec(&vec, "foo", "bar", "baz", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("split whitespace only") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_split(&vec, " \t\n");
+ check_strvec(&vec, NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("split multiple consecutive whitespaces") {
+ struct strvec vec = STRVEC_INIT;
+ strvec_split(&vec, "foo\n\t bar");
+ check_strvec(&vec, "foo", "bar", NULL);
+ strvec_clear(&vec);
+ }
+
+ if_test ("detach") {
+ struct strvec vec = STRVEC_INIT;
+ const char **detached;
+
+ strvec_push(&vec, "foo");
+
+ detached = strvec_detach(&vec);
+ check_str(detached[0], "foo");
+ check_pointer_eq(detached[1], NULL);
+
+ check_pointer_eq(vec.v, empty_strvec);
+ check_uint(vec.nr, ==, 0);
+ check_uint(vec.alloc, ==, 0);
+
+ free((char *) detached[0]);
+ free(detached);
+ }
+
return test_done();
}
diff --git a/t/unit-tests/test-lib.c b/t/unit-tests/test-lib.c
index 3c513ce59a..fa1f95965c 100644
--- a/t/unit-tests/test-lib.c
+++ b/t/unit-tests/test-lib.c
@@ -16,6 +16,8 @@ static struct {
unsigned running :1;
unsigned skip_all :1;
unsigned todo :1;
+ char location[100];
+ char description[100];
} ctx = {
.lazy_plan = 1,
.result = RESULT_NONE,
@@ -125,6 +127,8 @@ void test_plan(int count)
int test_done(void)
{
+ if (ctx.running && ctx.location[0] && ctx.description[0])
+ test__run_end(1, ctx.location, "%s", ctx.description);
assert(!ctx.running);
if (ctx.lazy_plan)
@@ -167,13 +171,38 @@ void test_skip_all(const char *format, ...)
va_end(ap);
}
+void test__run_describe(const char *location, const char *format, ...)
+{
+ va_list ap;
+ int len;
+
+ assert(ctx.running);
+ assert(!ctx.location[0]);
+ assert(!ctx.description[0]);
+
+ xsnprintf(ctx.location, sizeof(ctx.location), "%s",
+ make_relative(location));
+
+ va_start(ap, format);
+ len = vsnprintf(ctx.description, sizeof(ctx.description), format, ap);
+ va_end(ap);
+ if (len < 0)
+ die("unable to format message: %s", format);
+ if (len >= sizeof(ctx.description))
+ BUG("ctx.description too small to format %s", format);
+}
+
int test__run_begin(void)
{
+ if (ctx.running && ctx.location[0] && ctx.description[0])
+ test__run_end(1, ctx.location, "%s", ctx.description);
assert(!ctx.running);
ctx.count++;
ctx.result = RESULT_NONE;
ctx.running = 1;
+ ctx.location[0] = '\0';
+ ctx.description[0] = '\0';
return ctx.skip_all;
}
@@ -264,7 +293,12 @@ static void test_todo(void)
int test_assert(const char *location, const char *check, int ok)
{
- assert(ctx.running);
+ if (!ctx.running) {
+ test_msg("BUG: check outside of test at %s",
+ make_relative(location));
+ ctx.failed = 1;
+ return 0;
+ }
if (ctx.result == RESULT_SKIP) {
test_msg("skipping check '%s' at %s", check,
diff --git a/t/unit-tests/test-lib.h b/t/unit-tests/test-lib.h
index c59f646fd9..e4b234697f 100644
--- a/t/unit-tests/test-lib.h
+++ b/t/unit-tests/test-lib.h
@@ -15,6 +15,23 @@
TEST_LOCATION(), __VA_ARGS__)
/*
+ * Run a test unless test_skip_all() has been called. Acts like a
+ * conditional; the test body is expected as a statement or block after
+ * the closing parenthesis. The description for each test should be
+ * unique. E.g.:
+ *
+ * if_test ("something else %d %d", arg1, arg2) {
+ * prepare();
+ * test_something_else(arg1, arg2);
+ * cleanup();
+ * }
+ */
+#define if_test(...) \
+ if (test__run_begin() ? \
+ (test__run_end(0, TEST_LOCATION(), __VA_ARGS__), 0) : \
+ (test__run_describe(TEST_LOCATION(), __VA_ARGS__), 1))
+
+/*
* Print a test plan, should be called before any tests. If the number
* of tests is not known in advance test_done() will automatically
* print a plan at the end of the test program.
@@ -154,6 +171,9 @@ union test__tmp {
extern union test__tmp test__tmp[2];
+__attribute__((format (printf, 2, 3)))
+void test__run_describe(const char *, const char *, ...);
+
int test__run_begin(void);
__attribute__((format (printf, 3, 4)))
int test__run_end(int, const char *, const char *, ...);