summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/.gitattributes2
-rw-r--r--t/Makefile16
-rw-r--r--t/README34
-rw-r--r--t/chainlint-cat.pl29
-rwxr-xr-xt/chainlint.pl33
-rw-r--r--t/chainlint/arithmetic-expansion.expect18
-rw-r--r--t/chainlint/arithmetic-expansion.test2
-rw-r--r--t/chainlint/bash-array.expect20
-rw-r--r--t/chainlint/bash-array.test2
-rw-r--r--t/chainlint/blank-line-before-esac.expect36
-rw-r--r--t/chainlint/blank-line-before-esac.test2
-rw-r--r--t/chainlint/blank-line.expect16
-rw-r--r--t/chainlint/blank-line.test2
-rw-r--r--t/chainlint/block-comment.expect16
-rw-r--r--t/chainlint/block-comment.test2
-rw-r--r--t/chainlint/block.expect46
-rw-r--r--t/chainlint/block.test2
-rw-r--r--t/chainlint/broken-chain.expect12
-rw-r--r--t/chainlint/broken-chain.test2
-rw-r--r--t/chainlint/case-comment.expect22
-rw-r--r--t/chainlint/case-comment.test2
-rw-r--r--t/chainlint/case.expect38
-rw-r--r--t/chainlint/case.test2
-rw-r--r--t/chainlint/chain-break-background.expect18
-rw-r--r--t/chainlint/chain-break-background.test2
-rw-r--r--t/chainlint/chain-break-continue.expect24
-rw-r--r--t/chainlint/chain-break-continue.test2
-rw-r--r--t/chainlint/chain-break-false.expect18
-rw-r--r--t/chainlint/chain-break-false.test2
-rw-r--r--t/chainlint/chain-break-return-exit.expect38
-rw-r--r--t/chainlint/chain-break-return-exit.test2
-rw-r--r--t/chainlint/chain-break-status.expect18
-rw-r--r--t/chainlint/chain-break-status.test2
-rw-r--r--t/chainlint/chained-block.expect18
-rw-r--r--t/chainlint/chained-block.test2
-rw-r--r--t/chainlint/chained-subshell.expect20
-rw-r--r--t/chainlint/chained-subshell.test2
-rw-r--r--t/chainlint/close-nested-and-parent-together.expect6
-rw-r--r--t/chainlint/close-nested-and-parent-together.test2
-rw-r--r--t/chainlint/close-subshell.expect52
-rw-r--r--t/chainlint/close-subshell.test2
-rw-r--r--t/chainlint/command-substitution-subsubshell.expect4
-rw-r--r--t/chainlint/command-substitution-subsubshell.test2
-rw-r--r--t/chainlint/command-substitution.expect18
-rw-r--r--t/chainlint/command-substitution.test2
-rw-r--r--t/chainlint/comment.expect16
-rw-r--r--t/chainlint/comment.test2
-rw-r--r--t/chainlint/complex-if-in-cuddled-loop.expect18
-rw-r--r--t/chainlint/complex-if-in-cuddled-loop.test2
-rw-r--r--t/chainlint/cuddled-if-then-else.expect12
-rw-r--r--t/chainlint/cuddled-if-then-else.test2
-rw-r--r--t/chainlint/cuddled-loop.expect8
-rw-r--r--t/chainlint/cuddled-loop.test2
-rw-r--r--t/chainlint/cuddled.expect34
-rw-r--r--t/chainlint/cuddled.test2
-rw-r--r--t/chainlint/double-here-doc.expect24
-rw-r--r--t/chainlint/double-here-doc.test2
-rw-r--r--t/chainlint/dqstring-line-splice.expect10
-rw-r--r--t/chainlint/dqstring-line-splice.test2
-rw-r--r--t/chainlint/dqstring-no-interpolate.expect24
-rw-r--r--t/chainlint/dqstring-no-interpolate.test2
-rw-r--r--t/chainlint/empty-here-doc.expect8
-rw-r--r--t/chainlint/empty-here-doc.test2
-rw-r--r--t/chainlint/exclamation.expect8
-rw-r--r--t/chainlint/exclamation.test2
-rw-r--r--t/chainlint/exit-loop.expect48
-rw-r--r--t/chainlint/exit-loop.test2
-rw-r--r--t/chainlint/exit-subshell.expect10
-rw-r--r--t/chainlint/exit-subshell.test2
-rw-r--r--t/chainlint/for-loop-abbreviated.expect10
-rw-r--r--t/chainlint/for-loop-abbreviated.test2
-rw-r--r--t/chainlint/for-loop.expect28
-rw-r--r--t/chainlint/for-loop.test2
-rw-r--r--t/chainlint/function.expect22
-rw-r--r--t/chainlint/function.test2
-rw-r--r--t/chainlint/here-doc-body-indent.expect2
-rw-r--r--t/chainlint/here-doc-body-indent.test4
-rw-r--r--t/chainlint/here-doc-body-pathological.expect7
-rw-r--r--t/chainlint/here-doc-body-pathological.test9
-rw-r--r--t/chainlint/here-doc-body.expect7
-rw-r--r--t/chainlint/here-doc-body.test9
-rw-r--r--t/chainlint/here-doc-close-subshell.expect8
-rw-r--r--t/chainlint/here-doc-close-subshell.test2
-rw-r--r--t/chainlint/here-doc-double.expect2
-rw-r--r--t/chainlint/here-doc-double.test10
-rw-r--r--t/chainlint/here-doc-indent-operator.expect22
-rw-r--r--t/chainlint/here-doc-indent-operator.test2
-rw-r--r--t/chainlint/here-doc-multi-line-command-subst.expect16
-rw-r--r--t/chainlint/here-doc-multi-line-command-subst.test2
-rw-r--r--t/chainlint/here-doc-multi-line-string.expect14
-rw-r--r--t/chainlint/here-doc-multi-line-string.test2
-rw-r--r--t/chainlint/here-doc.expect50
-rw-r--r--t/chainlint/here-doc.test2
-rw-r--r--t/chainlint/if-condition-split.expect14
-rw-r--r--t/chainlint/if-condition-split.test2
-rw-r--r--t/chainlint/if-in-loop.expect24
-rw-r--r--t/chainlint/if-in-loop.test2
-rw-r--r--t/chainlint/if-then-else.expect44
-rw-r--r--t/chainlint/if-then-else.test2
-rw-r--r--t/chainlint/incomplete-line.expect20
-rw-r--r--t/chainlint/incomplete-line.test2
-rw-r--r--t/chainlint/inline-comment.expect16
-rw-r--r--t/chainlint/inline-comment.test2
-rw-r--r--t/chainlint/loop-detect-failure.expect30
-rw-r--r--t/chainlint/loop-detect-failure.test2
-rw-r--r--t/chainlint/loop-detect-status.expect36
-rw-r--r--t/chainlint/loop-detect-status.test2
-rw-r--r--t/chainlint/loop-in-if.expect24
-rw-r--r--t/chainlint/loop-in-if.test2
-rw-r--r--t/chainlint/loop-upstream-pipe.expect20
-rw-r--r--t/chainlint/loop-upstream-pipe.test2
-rw-r--r--t/chainlint/multi-line-nested-command-substitution.expect36
-rw-r--r--t/chainlint/multi-line-nested-command-substitution.test2
-rw-r--r--t/chainlint/multi-line-string.expect28
-rw-r--r--t/chainlint/multi-line-string.test2
-rw-r--r--t/chainlint/negated-one-liner.expect10
-rw-r--r--t/chainlint/negated-one-liner.test2
-rw-r--r--t/chainlint/nested-cuddled-subshell.expect50
-rw-r--r--t/chainlint/nested-cuddled-subshell.test2
-rw-r--r--t/chainlint/nested-here-doc.expect60
-rw-r--r--t/chainlint/nested-here-doc.test2
-rw-r--r--t/chainlint/nested-loop-detect-failure.expect62
-rw-r--r--t/chainlint/nested-loop-detect-failure.test2
-rw-r--r--t/chainlint/nested-subshell-comment.expect22
-rw-r--r--t/chainlint/nested-subshell-comment.test2
-rw-r--r--t/chainlint/nested-subshell.expect26
-rw-r--r--t/chainlint/nested-subshell.test2
-rw-r--r--t/chainlint/not-heredoc.expect28
-rw-r--r--t/chainlint/not-heredoc.test2
-rw-r--r--t/chainlint/one-liner-for-loop.expect18
-rw-r--r--t/chainlint/one-liner-for-loop.test2
-rw-r--r--t/chainlint/one-liner.expect18
-rw-r--r--t/chainlint/one-liner.test2
-rw-r--r--t/chainlint/p4-filespec.expect8
-rw-r--r--t/chainlint/p4-filespec.test2
-rw-r--r--t/chainlint/pipe.expect20
-rw-r--r--t/chainlint/pipe.test2
-rw-r--r--t/chainlint/return-loop.expect10
-rw-r--r--t/chainlint/return-loop.test2
-rw-r--r--t/chainlint/semicolon.expect38
-rw-r--r--t/chainlint/semicolon.test2
-rw-r--r--t/chainlint/sqstring-in-sqstring.expect8
-rw-r--r--t/chainlint/sqstring-in-sqstring.test2
-rw-r--r--t/chainlint/subshell-here-doc.expect60
-rw-r--r--t/chainlint/subshell-here-doc.test2
-rw-r--r--t/chainlint/subshell-one-liner.expect38
-rw-r--r--t/chainlint/subshell-one-liner.test2
-rw-r--r--t/chainlint/t7900-subtree.expect44
-rw-r--r--t/chainlint/t7900-subtree.test2
-rw-r--r--t/chainlint/token-pasting.expect54
-rw-r--r--t/chainlint/token-pasting.test2
-rw-r--r--t/chainlint/unclosed-here-doc-indent.expect8
-rw-r--r--t/chainlint/unclosed-here-doc-indent.test2
-rw-r--r--t/chainlint/unclosed-here-doc.expect14
-rw-r--r--t/chainlint/unclosed-here-doc.test2
-rw-r--r--t/chainlint/while-loop.expect28
-rw-r--r--t/chainlint/while-loop.test2
-rwxr-xr-xt/check-non-portable-shell.pl4
-rw-r--r--t/helper/test-bloom.c9
-rw-r--r--t/helper/test-json-writer.c2
-rw-r--r--t/helper/test-oidmap.c125
-rw-r--r--t/helper/test-parse-options.c1
-rw-r--r--t/helper/test-read-graph.c65
-rw-r--r--t/helper/test-reftable.c4
-rw-r--r--t/helper/test-repository.c4
-rw-r--r--t/helper/test-tool.c1
-rw-r--r--t/helper/test-tool.h1
-rw-r--r--t/helper/test-trace2.c1
-rw-r--r--t/lib-bundle-uri-protocol.sh4
-rw-r--r--t/socks4-proxy.pl48
-rwxr-xr-xt/t0006-date.sh51
-rwxr-xr-xt/t0007-git-var.sh2
-rwxr-xr-xt/t0016-oidmap.sh112
-rwxr-xr-xt/t0018-advice.sh1
-rwxr-xr-xt/t0021-conversion.sh1
-rwxr-xr-xt/t0033-safe-directory.sh178
-rwxr-xr-xt/t0095-bloom.sh8
-rwxr-xr-xt/t0301-credential-cache.sh2
-rwxr-xr-xt/t0302-credential-store.sh2
-rwxr-xr-xt/t0303-credential-external.sh1
-rwxr-xr-xt/t0600-reffiles-backend.sh38
-rwxr-xr-xt/t0612-reftable-jgit-compatibility.sh1
-rwxr-xr-xt/t0613-reftable-write-options.sh1
-rwxr-xr-xt/t1004-read-tree-m-u-wf.sh1
-rwxr-xr-xt/t1015-read-index-unmerged.sh2
-rwxr-xr-xt/t1021-rerere-in-workdir.sh1
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh16
-rwxr-xr-xt/t1300-config.sh9
-rwxr-xr-xt/t1404-update-ref-errors.sh196
-rwxr-xr-xt/t1410-reflog.sh8
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh2
-rwxr-xr-xt/t1511-rev-parse-caret.sh1
-rwxr-xr-xt/t1512-rev-parse-disambiguation.sh1
-rwxr-xr-xt/t2030-unresolve-info.sh1
-rwxr-xr-xt/t2080-parallel-checkout-basics.sh1
-rwxr-xr-xt/t2082-parallel-checkout-attributes.sh1
-rwxr-xr-xt/t2107-update-index-basic.sh1
-rwxr-xr-xt/t2400-worktree-add.sh1
-rwxr-xr-xt/t2500-untracked-overwriting.sh1
-rwxr-xr-xt/t2501-cwd-empty.sh1
-rwxr-xr-xt/t3201-branch-contains.sh1
-rwxr-xr-xt/t3202-show-branch.sh1
-rwxr-xr-xt/t3206-range-diff.sh53
-rwxr-xr-xt/t3301-notes.sh11
-rwxr-xr-xt/t3306-notes-prune.sh1
-rwxr-xr-xt/t3308-notes-merge.sh1
-rwxr-xr-xt/t3309-notes-merge-auto-resolve.sh1
-rwxr-xr-xt/t3400-rebase.sh1
-rwxr-xr-xt/t3401-rebase-and-am-rename.sh1
-rwxr-xr-xt/t3403-rebase-skip.sh1
-rwxr-xr-xt/t3406-rebase-message.sh1
-rwxr-xr-xt/t3407-rebase-abort.sh1
-rwxr-xr-xt/t3417-rebase-whitespace-fix.sh1
-rwxr-xr-xt/t3418-rebase-continue.sh1
-rwxr-xr-xt/t3420-rebase-autostash.sh1
-rwxr-xr-xt/t3421-rebase-topology-linear.sh2
-rwxr-xr-xt/t3424-rebase-empty.sh1
-rwxr-xr-xt/t3428-rebase-signoff.sh1
-rwxr-xr-xt/t3430-rebase-merges.sh4
-rwxr-xr-xt/t3434-rebase-i18n.sh1
-rwxr-xr-xt/t3500-cherry.sh1
-rwxr-xr-xt/t3504-cherry-pick-rerere.sh1
-rwxr-xr-xt/t3505-cherry-pick-empty.sh1
-rwxr-xr-xt/t3508-cherry-pick-many-commits.sh1
-rwxr-xr-xt/t3509-cherry-pick-merge-df.sh1
-rwxr-xr-xt/t3650-replay-basics.sh1
-rwxr-xr-xt/t3701-add-interactive.sh67
-rwxr-xr-xt/t3903-stash.sh1
-rwxr-xr-xt/t3904-stash-patch.sh2
-rwxr-xr-xt/t3905-stash-include-untracked.sh1
-rwxr-xr-xt/t3907-stash-show-config.sh1
-rwxr-xr-xt/t4034-diff-words.sh2
-rwxr-xr-xt/t4061-diff-indent.sh1
-rwxr-xr-xt/t4129-apply-samemode.sh62
-rwxr-xr-xt/t4131-apply-fake-ancestor.sh1
-rwxr-xr-xt/t4151-am-abort.sh1
-rwxr-xr-xt/t4153-am-resume-override-opts.sh3
-rwxr-xr-xt/t4200-rerere.sh1
-rwxr-xr-xt/t4201-shortlog.sh1
-rwxr-xr-xt/t4203-mailmap.sh1
-rwxr-xr-xt/t4204-patch-id.sh40
-rwxr-xr-xt/t4208-log-magic-pathspec.sh1
-rwxr-xr-xt/t4216-log-bloom.sh325
-rwxr-xr-xt/t4253-am-keep-cr-dos.sh1
-rwxr-xr-xt/t4255-am-submodule.sh1
-rwxr-xr-xt/t5150-request-pull.sh1
-rwxr-xr-xt/t5300-pack-object.sh4
-rwxr-xr-xt/t5305-include-tag.sh1
-rwxr-xr-xt/t5318-commit-graph.sh2
-rwxr-xr-xt/t5319-multi-pack-index.sh55
-rwxr-xr-xt/t5407-post-rewrite-hook.sh1
-rwxr-xr-xt/t5512-ls-remote.sh14
-rwxr-xr-xt/t5514-fetch-multiple.sh1
-rwxr-xr-xt/t5516-fetch-push.sh10
-rwxr-xr-xt/t5520-pull.sh1
-rwxr-xr-xt/t5528-push-default.sh1
-rwxr-xr-xt/t5529-push-errors.sh17
-rwxr-xr-xt/t5535-fetch-push-symref.sh1
-rwxr-xr-xt/t5543-atomic-push.sh1
-rwxr-xr-xt/t5551-http-fetch-smart.sh1
-rwxr-xr-xt/t5553-set-upstream.sh8
-rwxr-xr-xt/t5558-clone-bundle-uri.sh187
-rwxr-xr-xt/t5563-simple-http-auth.sh116
-rwxr-xr-xt/t5564-http-proxy.sh55
-rwxr-xr-xt/t5570-git-daemon.sh1
-rwxr-xr-xt/t5605-clone-local.sh1
-rwxr-xr-xt/t5607-clone-bundle.sh36
-rwxr-xr-xt/t5612-clone-refspec.sh1
-rwxr-xr-xt/t6000-rev-list-misc.sh1
-rwxr-xr-xt/t6001-rev-list-graft.sh1
-rwxr-xr-xt/t6007-rev-list-cherry-pick-file.sh1
-rwxr-xr-xt/t6010-merge-base.sh1
-rwxr-xr-xt/t6013-rev-list-reverse-parents.sh1
-rwxr-xr-xt/t6017-rev-list-stdin.sh1
-rwxr-xr-xt/t6020-bundle-misc.sh1
-rwxr-xr-xt/t6115-rev-list-du.sh2
-rwxr-xr-xt/t6120-describe.sh37
-rwxr-xr-xt/t6130-pathspec-noglob.sh2
-rwxr-xr-xt/t6133-pathspec-rev-dwim.sh2
-rwxr-xr-xt/t6402-merge-rename.sh1
-rwxr-xr-xt/t6406-merge-attr.sh42
-rwxr-xr-xt/t6421-merge-partial-clone.sh15
-rwxr-xr-xt/t6427-diff3-conflict-markers.sh1
-rwxr-xr-xt/t6430-merge-recursive.sh1
-rwxr-xr-xt/t6432-merge-recursive-space-options.sh1
-rwxr-xr-xt/t6434-merge-recursive-rename-options.sh1
-rwxr-xr-xt/t6436-merge-overwrite.sh1
-rwxr-xr-xt/t7006-pager.sh18
-rwxr-xr-xt/t7010-setup.sh1
-rwxr-xr-xt/t7012-skip-worktree-writing.sh1
-rwxr-xr-xt/t7064-wtstatus-pv2.sh1
-rwxr-xr-xt/t7201-co.sh14
-rwxr-xr-xt/t7400-submodule-basic.sh1
-rwxr-xr-xt/t7501-commit-basic-functionality.sh1
-rwxr-xr-xt/t7505-prepare-commit-msg-hook.sh1
-rwxr-xr-xt/t7512-status-help.sh1
-rwxr-xr-xt/t7600-merge.sh1
-rwxr-xr-xt/t7606-merge-custom.sh1
-rwxr-xr-xt/t7611-merge-abort.sh1
-rwxr-xr-xt/t7615-diff-algo-with-mergy-operations.sh60
-rw-r--r--t/t7615/base.c17
-rw-r--r--t/t7615/ours.c17
-rw-r--r--t/t7615/theirs.c17
-rwxr-xr-xt/t7704-repack-cruft.sh2
-rwxr-xr-xt/t7810-grep.sh1
-rwxr-xr-xt/t8002-blame.sh1
-rwxr-xr-xt/t8003-blame-corner-cases.sh1
-rwxr-xr-xt/t8004-blame-with-conflicts.sh1
-rwxr-xr-xt/t8006-blame-textconv.sh2
-rwxr-xr-xt/t8008-blame-formats.sh2
-rwxr-xr-xt/t8009-blame-vs-topicbranches.sh2
-rwxr-xr-xt/t8011-blame-split-file.sh2
-rwxr-xr-xt/t8012-blame-colors.sh1
-rwxr-xr-xt/t8013-blame-ignore-revs.sh2
-rwxr-xr-xt/t8014-blame-ignore-fuzzy.sh2
-rwxr-xr-xt/t9001-send-email.sh43
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh1
-rwxr-xr-xt/t9502-gitweb-standalone-parse-output.sh1
-rwxr-xr-xt/t9800-git-p4-basic.sh17
-rwxr-xr-xt/t9801-git-p4-branch.sh1
-rwxr-xr-xt/t9802-git-p4-filetype.sh19
-rwxr-xr-xt/t9803-git-p4-shell-metachars.sh1
-rwxr-xr-xt/t9804-git-p4-label.sh1
-rwxr-xr-xt/t9805-git-p4-skip-submit-edit.sh1
-rwxr-xr-xt/t9806-git-p4-options.sh1
-rwxr-xr-xt/t9808-git-p4-chdir.sh1
-rwxr-xr-xt/t9809-git-p4-client-view.sh1
-rwxr-xr-xt/t9810-git-p4-rcs.sh1
-rwxr-xr-xt/t9811-git-p4-label-import.sh1
-rwxr-xr-xt/t9812-git-p4-wildcards.sh1
-rwxr-xr-xt/t9813-git-p4-preserve-users.sh1
-rwxr-xr-xt/t9814-git-p4-rename.sh1
-rwxr-xr-xt/t9815-git-p4-submit-fail.sh1
-rwxr-xr-xt/t9816-git-p4-locked.sh1
-rwxr-xr-xt/t9817-git-p4-exclude.sh1
-rwxr-xr-xt/t9818-git-p4-block.sh1
-rwxr-xr-xt/t9819-git-p4-case-folding.sh1
-rwxr-xr-xt/t9820-git-p4-editor-handling.sh1
-rwxr-xr-xt/t9821-git-p4-path-variations.sh1
-rwxr-xr-xt/t9822-git-p4-path-encoding.sh1
-rwxr-xr-xt/t9823-git-p4-mock-lfs.sh1
-rwxr-xr-xt/t9825-git-p4-handle-utf16-without-bom.sh23
-rwxr-xr-xt/t9826-git-p4-keep-empty-commits.sh1
-rwxr-xr-xt/t9827-git-p4-change-filetype.sh1
-rwxr-xr-xt/t9828-git-p4-map-user.sh1
-rwxr-xr-xt/t9829-git-p4-jobs.sh1
-rwxr-xr-xt/t9830-git-p4-symlink-dir.sh1
-rwxr-xr-xt/t9831-git-p4-triggers.sh1
-rwxr-xr-xt/t9832-unshelve.sh1
-rwxr-xr-xt/t9833-errors.sh1
-rwxr-xr-xt/t9834-git-p4-file-dir-bug.sh1
-rwxr-xr-xt/t9835-git-p4-metadata-encoding-python2.sh1
-rwxr-xr-xt/t9836-git-p4-metadata-encoding-python3.sh1
-rwxr-xr-xt/t9902-completion.sh1
-rwxr-xr-xt/t9903-bash-prompt.sh1
-rw-r--r--t/test-lib-functions.sh32
-rw-r--r--t/test-lib.sh40
-rw-r--r--t/unit-tests/t-example-decorate.c24
-rw-r--r--t/unit-tests/t-oidmap.c181
-rw-r--r--t/unit-tests/t-reftable-merged.c463
-rw-r--r--t/unit-tests/t-reftable-pq.c152
-rw-r--r--t/unit-tests/t-reftable-record.c551
-rw-r--r--t/unit-tests/t-reftable-tree.c84
-rw-r--r--t/unit-tests/t-strvec.c47
-rw-r--r--t/unit-tests/test-lib.h5
365 files changed, 4639 insertions, 1467 deletions
diff --git a/t/.gitattributes b/t/.gitattributes
index b9cea1795d..7664c6e027 100644
--- a/t/.gitattributes
+++ b/t/.gitattributes
@@ -1,5 +1,5 @@
t[0-9][0-9][0-9][0-9]/* -whitespace
-/chainlint/*.expect eol=lf
+/chainlint/*.expect eol=lf -whitespace
/t0110/url-* binary
/t3206/* eol=lf
/t3900/*.txt eol=lf
diff --git a/t/Makefile b/t/Makefile
index b2eb9f770b..4c30e7c06f 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -108,20 +108,8 @@ clean-chainlint:
check-chainlint:
@mkdir -p '$(CHAINLINTTMP_SQ)' && \
- for i in $(CHAINLINTTESTS); do \
- echo "test_expect_success '$$i' '" && \
- sed -e '/^# LINT: /d' chainlint/$$i.test && \
- echo "'"; \
- done >'$(CHAINLINTTMP_SQ)'/tests && \
- { \
- echo "# chainlint: $(CHAINLINTTMP_SQ)/tests" && \
- for i in $(CHAINLINTTESTS); do \
- echo "# chainlint: $$i" && \
- cat chainlint/$$i.expect; \
- done \
- } >'$(CHAINLINTTMP_SQ)'/expect && \
- $(CHAINLINT) --emit-all '$(CHAINLINTTMP_SQ)'/tests | \
- sed -e 's/^[1-9][0-9]* //' >'$(CHAINLINTTMP_SQ)'/actual && \
+ '$(PERL_PATH_SQ)' chainlint-cat.pl '$(CHAINLINTTMP_SQ)' $(CHAINLINTTESTS) && \
+ { $(CHAINLINT) --emit-all '$(CHAINLINTTMP_SQ)'/tests >'$(CHAINLINTTMP_SQ)'/actual || true; } && \
diff -u '$(CHAINLINTTMP_SQ)'/expect '$(CHAINLINTTMP_SQ)'/actual
test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \
diff --git a/t/README b/t/README
index d9e0e07506..724ee58195 100644
--- a/t/README
+++ b/t/README
@@ -382,33 +382,9 @@ mapping between "TEST_PASSES_SANITIZE_LEAK=true" and those tests that
pass under "SANITIZE=leak". This is especially useful when testing a
series that fixes various memory leaks with "git rebase -x".
-GIT_TEST_SANITIZE_LEAK_LOG=true will log memory leaks to
-"test-results/$TEST_NAME.leak/trace.*" files. The logs include a
-"dedup_token" (see +"ASAN_OPTIONS=help=1 ./git") and other options to
-make logs +machine-readable.
-
-With GIT_TEST_SANITIZE_LEAK_LOG=true we'll look at the leak logs
-before exiting and exit on failure if the logs showed that we had a
-memory leak, even if the test itself would have otherwise passed. This
-allows us to catch e.g. missing &&-chaining. This is especially useful
-when combined with "GIT_TEST_PASSING_SANITIZE_LEAK", see below.
-
GIT_TEST_PASSING_SANITIZE_LEAK=check when combined with "--immediate"
will run to completion faster, and result in the same failing
-tests. The only practical reason to run
-GIT_TEST_PASSING_SANITIZE_LEAK=check without "--immediate" is to
-combine it with "GIT_TEST_SANITIZE_LEAK_LOG=true". If we stop at the
-first failing test case our leak logs won't show subsequent leaks we
-might have run into.
-
-GIT_TEST_PASSING_SANITIZE_LEAK=(true|check) will not catch all memory
-leaks unless combined with GIT_TEST_SANITIZE_LEAK_LOG=true. Some tests
-run "git" (or "test-tool" etc.) without properly checking the exit
-code, or git will invoke itself and fail to ferry the abort() exit
-code to the original caller. When the two modes are combined we'll
-look at the "test-results/$TEST_NAME.leak/trace.*" files at the end of
-the test run to see if had memory leaks which the test itself didn't
-catch.
+tests.
GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version'
default to n.
@@ -906,6 +882,14 @@ see test-lib-functions.sh for the full list and their options.
'git-write-tree should be able to write an empty tree.' \
'tree=$(git-write-tree)'
+ If <script> is `-` (a single dash), then the script to run is read
+ from stdin. This lets you more easily use single quotes within the
+ script by using a here-doc. For example:
+
+ test_expect_success 'output contains expected string' - <<\EOT
+ grep "this string has 'quotes' in it" output
+ EOT
+
If you supply three parameters the first will be taken to be a
prerequisite; see the test_set_prereq and test_have_prereq
documentation below:
diff --git a/t/chainlint-cat.pl b/t/chainlint-cat.pl
new file mode 100644
index 0000000000..388f6e1e41
--- /dev/null
+++ b/t/chainlint-cat.pl
@@ -0,0 +1,29 @@
+#!/usr/bin/env perl
+
+my $outdir = shift;
+open(my $tests, '>', "$outdir/tests")
+ or die "unable to open $outdir/tests: $!";
+open(my $expect, '>', "$outdir/expect")
+ or die "unable to open $outdir/expect: $!";
+
+print $expect "# chainlint: $outdir/tests\n";
+
+my $offset = 0;
+for my $script (@ARGV) {
+ print $expect "# chainlint: $script\n";
+
+ open(my $expect_in, '<', "chainlint/$script.expect")
+ or die "unable to open chainlint/$script.expect: $!";
+ while (<$expect_in>) {
+ s/^\d+/$& + $offset/e;
+ print $expect $_;
+ }
+
+ open(my $test_in, '<', "chainlint/$script.test")
+ or die "unable to open chainlint/$script.test: $!";
+ while (<$test_in>) {
+ /^# LINT: / and next;
+ print $tests $_;
+ $offset++;
+ }
+}
diff --git a/t/chainlint.pl b/t/chainlint.pl
index 1bbd985b78..5361f23b1d 100755
--- a/t/chainlint.pl
+++ b/t/chainlint.pl
@@ -174,6 +174,10 @@ sub swallow_heredocs {
$$b =~ /(?:\G|\n)$indent\Q$$tag[0]\E(?:\n|\z)/gc;
if (pos($$b) > $start) {
my $body = substr($$b, $start, pos($$b) - $start);
+ $self->{parser}->{heredocs}->{$$tag[0]} = {
+ content => substr($body, 0, length($body) - length($&)),
+ start_line => $self->{lineno},
+ };
$self->{lineno} += () = $body =~ /\n/sg;
next;
}
@@ -232,7 +236,8 @@ sub new {
my $self = bless {
buff => [],
stop => [],
- output => []
+ output => [],
+ heredocs => {},
} => $class;
$self->{lexer} = Lexer->new($self, $s);
return $self;
@@ -616,14 +621,21 @@ sub unwrap {
sub check_test {
my $self = shift @_;
- my ($title, $body) = map(unwrap, @_);
+ my $title = unwrap(shift @_);
+ my $body = shift @_;
+ my $lineno = $body->[3];
+ $body = unwrap($body);
+ if ($body eq '-') {
+ my $herebody = shift @_;
+ $body = $herebody->{content};
+ $lineno = $herebody->{start_line};
+ }
$self->{ntests}++;
my $parser = TestParser->new(\$body);
my @tokens = $parser->parse();
my $problems = $parser->{problems};
return unless $emit_all || @$problems;
my $c = main::fd_colors(1);
- my $lineno = $_[1]->[3];
my $start = 0;
my $checked = '';
for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) {
@@ -649,8 +661,13 @@ sub parse_cmd {
return @tokens unless @tokens && $tokens[0]->[0] =~ /^test_expect_(?:success|failure)$/;
my $n = $#tokens;
$n-- while $n >= 0 && $tokens[$n]->[0] =~ /^(?:[;&\n|]|&&|\|\|)$/;
- $self->check_test($tokens[1], $tokens[2]) if $n == 2; # title body
- $self->check_test($tokens[2], $tokens[3]) if $n > 2; # prereq title body
+ my $herebody;
+ if ($n >= 2 && $tokens[$n-1]->[0] eq '-' && $tokens[$n]->[0] =~ /^<<-?(.+)$/) {
+ $herebody = $self->{heredocs}->{$1};
+ $n--;
+ }
+ $self->check_test($tokens[1], $tokens[2], $herebody) if $n == 2; # title body
+ $self->check_test($tokens[2], $tokens[3], $herebody) if $n > 2; # prereq title body
return @tokens;
}
@@ -762,7 +779,7 @@ sub check_script {
while (my $path = $next_script->()) {
$nscripts++;
my $fh;
- unless (open($fh, "<", $path)) {
+ unless (open($fh, "<:unix:crlf", $path)) {
$emit->("?!ERR?! $path: $!\n");
next;
}
@@ -806,8 +823,10 @@ unless (@scripts) {
show_stats($start_time, \@stats) if $show_stats;
exit;
}
+$jobs = @scripts if @scripts < $jobs;
-unless ($Config{useithreads} && eval {
+unless ($jobs > 1 &&
+ $Config{useithreads} && eval {
require threads; threads->import();
require Thread::Queue; Thread::Queue->import();
1;
diff --git a/t/chainlint/arithmetic-expansion.expect b/t/chainlint/arithmetic-expansion.expect
index 46ee1046af..338ecd5861 100644
--- a/t/chainlint/arithmetic-expansion.expect
+++ b/t/chainlint/arithmetic-expansion.expect
@@ -1,9 +1,9 @@
-(
- foo &&
- bar=$((42 + 1)) &&
- baz
-) &&
-(
- bar=$((42 + 1)) ?!AMP?!
- baz
-)
+2 (
+3 foo &&
+4 bar=$((42 + 1)) &&
+5 baz
+6 ) &&
+7 (
+8 bar=$((42 + 1)) ?!AMP?!
+9 baz
+10 )
diff --git a/t/chainlint/arithmetic-expansion.test b/t/chainlint/arithmetic-expansion.test
index 16206960d8..7b4c5c9a41 100644
--- a/t/chainlint/arithmetic-expansion.test
+++ b/t/chainlint/arithmetic-expansion.test
@@ -1,3 +1,4 @@
+test_expect_success 'arithmetic-expansion' '
(
foo &&
# LINT: closing ")" of $((...)) not misinterpreted as subshell-closing ")"
@@ -9,3 +10,4 @@
bar=$((42 + 1))
baz
)
+'
diff --git a/t/chainlint/bash-array.expect b/t/chainlint/bash-array.expect
index 4c34eaee45..435dc8bdc8 100644
--- a/t/chainlint/bash-array.expect
+++ b/t/chainlint/bash-array.expect
@@ -1,10 +1,10 @@
-(
- foo &&
- bar=(gumbo stumbo wumbo) &&
- baz
-) &&
-(
- foo &&
- bar=${#bar[@]} &&
- baz
-)
+2 (
+3 foo &&
+4 bar=(gumbo stumbo wumbo) &&
+5 baz
+6 ) &&
+7 (
+8 foo &&
+9 bar=${#bar[@]} &&
+10 baz
+11 )
diff --git a/t/chainlint/bash-array.test b/t/chainlint/bash-array.test
index 92bbb777b8..4ca977d299 100644
--- a/t/chainlint/bash-array.test
+++ b/t/chainlint/bash-array.test
@@ -1,3 +1,4 @@
+test_expect_success 'bash-array' '
(
foo &&
# LINT: ")" in Bash array assignment not misinterpreted as subshell-closing ")"
@@ -10,3 +11,4 @@
bar=${#bar[@]} &&
baz
)
+'
diff --git a/t/chainlint/blank-line-before-esac.expect b/t/chainlint/blank-line-before-esac.expect
index 056e03003d..b88ba919eb 100644
--- a/t/chainlint/blank-line-before-esac.expect
+++ b/t/chainlint/blank-line-before-esac.expect
@@ -1,18 +1,18 @@
-test_done () {
- case "$test_failure" in
- 0)
- test_at_end_hook_
-
- exit 0 ;;
-
- *)
- if test $test_external_has_tap -eq 0
- then
- say_color error "# failed $test_failure among $msg"
- say "1..$test_count"
- fi
-
- exit 1 ;;
-
- esac
-}
+2 test_done () {
+3 case "$test_failure" in
+4 0)
+5 test_at_end_hook_
+6
+7 exit 0 ;;
+8
+9 *)
+10 if test $test_external_has_tap -eq 0
+11 then
+12 say_color error "# failed $test_failure among $msg"
+13 say "1..$test_count"
+14 fi
+15
+16 exit 1 ;;
+17
+18 esac
+19 }
diff --git a/t/chainlint/blank-line-before-esac.test b/t/chainlint/blank-line-before-esac.test
index cecccad19f..51f02ea0c5 100644
--- a/t/chainlint/blank-line-before-esac.test
+++ b/t/chainlint/blank-line-before-esac.test
@@ -1,3 +1,4 @@
+test_expect_success 'blank-line-before-esac' '
# LINT: blank line before "esac"
test_done () {
case "$test_failure" in
@@ -17,3 +18,4 @@ test_done () {
esac
}
+'
diff --git a/t/chainlint/blank-line.expect b/t/chainlint/blank-line.expect
index b47827d749..6ae39dd174 100644
--- a/t/chainlint/blank-line.expect
+++ b/t/chainlint/blank-line.expect
@@ -1,8 +1,8 @@
-(
-
- nothing &&
-
- something
-
-
-)
+2 (
+3
+4 nothing &&
+5
+6 something
+7
+8
+9 )
diff --git a/t/chainlint/blank-line.test b/t/chainlint/blank-line.test
index 0fdf15b3e1..6f29a491de 100644
--- a/t/chainlint/blank-line.test
+++ b/t/chainlint/blank-line.test
@@ -1,3 +1,4 @@
+test_expect_success 'blank-line' '
(
nothing &&
@@ -8,3 +9,4 @@
)
+'
diff --git a/t/chainlint/block-comment.expect b/t/chainlint/block-comment.expect
index df2beea888..7926936c18 100644
--- a/t/chainlint/block-comment.expect
+++ b/t/chainlint/block-comment.expect
@@ -1,8 +1,8 @@
-(
- {
- # show a
- echo a &&
- # show b
- echo b
- }
-)
+2 (
+3 {
+4 # show a
+5 echo a &&
+6 # show b
+7 echo b
+8 }
+9 )
diff --git a/t/chainlint/block-comment.test b/t/chainlint/block-comment.test
index df2beea888..934ef4113a 100644
--- a/t/chainlint/block-comment.test
+++ b/t/chainlint/block-comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'block-comment' '
(
{
# show a
@@ -6,3 +7,4 @@
echo b
}
)
+'
diff --git a/t/chainlint/block.expect b/t/chainlint/block.expect
index 1c87326364..b62e3d58c3 100644
--- a/t/chainlint/block.expect
+++ b/t/chainlint/block.expect
@@ -1,23 +1,23 @@
-(
- foo &&
- {
- echo a ?!AMP?!
- echo b
- } &&
- bar &&
- {
- echo c
- } ?!AMP?!
- baz
-) &&
-
-{
- echo a; ?!AMP?! echo b
-} &&
-{ echo a; ?!AMP?! echo b; } &&
-
-{
- echo "${var}9" &&
- echo "done"
-} &&
-finis
+2 (
+3 foo &&
+4 {
+5 echo a ?!AMP?!
+6 echo b
+7 } &&
+8 bar &&
+9 {
+10 echo c
+11 } ?!AMP?!
+12 baz
+13 ) &&
+14
+15 {
+16 echo a; ?!AMP?! echo b
+17 } &&
+18 { echo a; ?!AMP?! echo b; } &&
+19
+20 {
+21 echo "${var}9" &&
+22 echo "done"
+23 } &&
+24 finis
diff --git a/t/chainlint/block.test b/t/chainlint/block.test
index 4ab69a4afc..a1b6b4dd32 100644
--- a/t/chainlint/block.test
+++ b/t/chainlint/block.test
@@ -1,3 +1,4 @@
+test_expect_success 'block' '
(
# LINT: missing "&&" after first "echo"
foo &&
@@ -25,3 +26,4 @@
echo "done"
} &&
finis
+'
diff --git a/t/chainlint/broken-chain.expect b/t/chainlint/broken-chain.expect
index cfb58fb6b9..9a1838736f 100644
--- a/t/chainlint/broken-chain.expect
+++ b/t/chainlint/broken-chain.expect
@@ -1,6 +1,6 @@
-(
- foo &&
- bar ?!AMP?!
- baz &&
- wop
-)
+2 (
+3 foo &&
+4 bar ?!AMP?!
+5 baz &&
+6 wop
+7 )
diff --git a/t/chainlint/broken-chain.test b/t/chainlint/broken-chain.test
index 2a44aa73b7..1966499ef9 100644
--- a/t/chainlint/broken-chain.test
+++ b/t/chainlint/broken-chain.test
@@ -1,3 +1,4 @@
+test_expect_success 'broken-chain' '
(
foo &&
# LINT: missing "&&" from "bar"
@@ -6,3 +7,4 @@
# LINT: final statement before closing ")" legitimately lacks "&&"
wop
)
+'
diff --git a/t/chainlint/case-comment.expect b/t/chainlint/case-comment.expect
index 641c157b98..2442dd5f25 100644
--- a/t/chainlint/case-comment.expect
+++ b/t/chainlint/case-comment.expect
@@ -1,11 +1,11 @@
-(
- case "$x" in
- # found foo
- x) foo ;;
- # found other
- *)
- # treat it as bar
- bar
- ;;
- esac
-)
+2 (
+3 case "$x" in
+4 # found foo
+5 x) foo ;;
+6 # found other
+7 *)
+8 # treat it as bar
+9 bar
+10 ;;
+11 esac
+12 )
diff --git a/t/chainlint/case-comment.test b/t/chainlint/case-comment.test
index 641c157b98..3f31ae9010 100644
--- a/t/chainlint/case-comment.test
+++ b/t/chainlint/case-comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'case-comment' '
(
case "$x" in
# found foo
@@ -9,3 +10,4 @@
;;
esac
)
+'
diff --git a/t/chainlint/case.expect b/t/chainlint/case.expect
index 31f280d8ce..c04c61ff36 100644
--- a/t/chainlint/case.expect
+++ b/t/chainlint/case.expect
@@ -1,19 +1,19 @@
-(
- case "$x" in
- x) foo ;;
- *) bar ;;
- esac &&
- foobar
-) &&
-(
- case "$x" in
- x) foo ;;
- *) bar ;;
- esac ?!AMP?!
- foobar
-) &&
-(
- case "$x" in 1) true;; esac &&
- case "$y" in 2) false;; esac ?!AMP?!
- foobar
-)
+2 (
+3 case "$x" in
+4 x) foo ;;
+5 *) bar ;;
+6 esac &&
+7 foobar
+8 ) &&
+9 (
+10 case "$x" in
+11 x) foo ;;
+12 *) bar ;;
+13 esac ?!AMP?!
+14 foobar
+15 ) &&
+16 (
+17 case "$x" in 1) true;; esac &&
+18 case "$y" in 2) false;; esac ?!AMP?!
+19 foobar
+20 )
diff --git a/t/chainlint/case.test b/t/chainlint/case.test
index 4cb086bf87..bea21fee4f 100644
--- a/t/chainlint/case.test
+++ b/t/chainlint/case.test
@@ -1,3 +1,4 @@
+test_expect_success 'case' '
(
# LINT: "...)" arms in "case" not misinterpreted as subshell-closing ")"
case "$x" in
@@ -21,3 +22,4 @@
case "$y" in 2) false;; esac
foobar
)
+'
diff --git a/t/chainlint/chain-break-background.expect b/t/chainlint/chain-break-background.expect
index 20d0bb5333..d06deadae7 100644
--- a/t/chainlint/chain-break-background.expect
+++ b/t/chainlint/chain-break-background.expect
@@ -1,9 +1,9 @@
-JGIT_DAEMON_PID= &&
-git init --bare empty.git &&
->empty.git/git-daemon-export-ok &&
-mkfifo jgit_daemon_output &&
-{
- jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
- JGIT_DAEMON_PID=$!
-} &&
-test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+2 JGIT_DAEMON_PID= &&
+3 git init --bare empty.git &&
+4 >empty.git/git-daemon-export-ok &&
+5 mkfifo jgit_daemon_output &&
+6 {
+7 jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
+8 JGIT_DAEMON_PID=$!
+9 } &&
+10 test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
diff --git a/t/chainlint/chain-break-background.test b/t/chainlint/chain-break-background.test
index e10f656b05..c68e1b04d5 100644
--- a/t/chainlint/chain-break-background.test
+++ b/t/chainlint/chain-break-background.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-background' '
JGIT_DAEMON_PID= &&
git init --bare empty.git &&
>empty.git/git-daemon-export-ok &&
@@ -8,3 +9,4 @@ mkfifo jgit_daemon_output &&
JGIT_DAEMON_PID=$!
} &&
test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+'
diff --git a/t/chainlint/chain-break-continue.expect b/t/chainlint/chain-break-continue.expect
index 47a3457710..4bb60aae25 100644
--- a/t/chainlint/chain-break-continue.expect
+++ b/t/chainlint/chain-break-continue.expect
@@ -1,12 +1,12 @@
-git ls-tree --name-only -r refs/notes/many_notes |
-while read path
-do
- test "$path" = "foobar/non-note.txt" && continue
- test "$path" = "deadbeef" && continue
- test "$path" = "de/adbeef" && continue
-
- if test $(expr length "$path") -ne $hexsz
- then
- return 1
- fi
-done
+2 git ls-tree --name-only -r refs/notes/many_notes |
+3 while read path
+4 do
+5 test "$path" = "foobar/non-note.txt" && continue
+6 test "$path" = "deadbeef" && continue
+7 test "$path" = "de/adbeef" && continue
+8
+9 if test $(expr length "$path") -ne $hexsz
+10 then
+11 return 1
+12 fi
+13 done
diff --git a/t/chainlint/chain-break-continue.test b/t/chainlint/chain-break-continue.test
index f0af71d8bd..de8119b204 100644
--- a/t/chainlint/chain-break-continue.test
+++ b/t/chainlint/chain-break-continue.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-continue' '
git ls-tree --name-only -r refs/notes/many_notes |
while read path
do
@@ -11,3 +12,4 @@ do
return 1
fi
done
+'
diff --git a/t/chainlint/chain-break-false.expect b/t/chainlint/chain-break-false.expect
index 989766fb85..4f815f8e14 100644
--- a/t/chainlint/chain-break-false.expect
+++ b/t/chainlint/chain-break-false.expect
@@ -1,9 +1,9 @@
-if condition not satisified
-then
- echo it did not work...
- echo failed!
- false
-else
- echo it went okay ?!AMP?!
- congratulate user
-fi
+2 if condition not satisified
+3 then
+4 echo it did not work...
+5 echo failed!
+6 false
+7 else
+8 echo it went okay ?!AMP?!
+9 congratulate user
+10 fi
diff --git a/t/chainlint/chain-break-false.test b/t/chainlint/chain-break-false.test
index a5aaff8c8a..f78ad911fc 100644
--- a/t/chainlint/chain-break-false.test
+++ b/t/chainlint/chain-break-false.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-false' '
# LINT: broken &&-chain okay if explicit "false" signals failure
if condition not satisified
then
@@ -8,3 +9,4 @@ else
echo it went okay
congratulate user
fi
+'
diff --git a/t/chainlint/chain-break-return-exit.expect b/t/chainlint/chain-break-return-exit.expect
index 4cd18e2edf..ba0ec51aa0 100644
--- a/t/chainlint/chain-break-return-exit.expect
+++ b/t/chainlint/chain-break-return-exit.expect
@@ -1,19 +1,19 @@
-case "$(git ls-files)" in
-one) echo pass one ;;
-*) echo bad one; return 1 ;;
-esac &&
-(
- case "$(git ls-files)" in
- two) echo pass two ;;
- *) echo bad two; exit 1 ;;
- esac
-) &&
-case "$(git ls-files)" in
-dir/two"$LF"one) echo pass both ;;
-*) echo bad; return 1 ;;
-esac &&
-
-for i in 1 2 3 4 ; do
- git checkout main -b $i || return $?
- test_commit $i $i $i tag$i || return $?
-done
+2 case "$(git ls-files)" in
+3 one) echo pass one ;;
+4 *) echo bad one; return 1 ;;
+5 esac &&
+6 (
+7 case "$(git ls-files)" in
+8 two) echo pass two ;;
+9 *) echo bad two; exit 1 ;;
+10 esac
+11 ) &&
+12 case "$(git ls-files)" in
+13 dir/two"$LF"one) echo pass both ;;
+14 *) echo bad; return 1 ;;
+15 esac &&
+16
+17 for i in 1 2 3 4 ; do
+18 git checkout main -b $i || return $?
+19 test_commit $i $i $i tag$i || return $?
+20 done
diff --git a/t/chainlint/chain-break-return-exit.test b/t/chainlint/chain-break-return-exit.test
index 46542edf88..b6f519bb4d 100644
--- a/t/chainlint/chain-break-return-exit.test
+++ b/t/chainlint/chain-break-return-exit.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-return-exit' '
case "$(git ls-files)" in
one) echo pass one ;;
# LINT: broken &&-chain okay if explicit "return 1" signals failuire
@@ -21,3 +22,4 @@ for i in 1 2 3 4 ; do
git checkout main -b $i || return $?
test_commit $i $i $i tag$i || return $?
done
+'
diff --git a/t/chainlint/chain-break-status.expect b/t/chainlint/chain-break-status.expect
index e6b3b2193e..23c0caa7d8 100644
--- a/t/chainlint/chain-break-status.expect
+++ b/t/chainlint/chain-break-status.expect
@@ -1,9 +1,9 @@
-OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&
-test_match_signal 13 "$OUT" &&
-
-{ test-tool sigchain >actual; ret=$?; } &&
-{
- test_match_signal 15 "$ret" ||
- test "$ret" = 3
-} &&
-test_cmp expect actual
+2 OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&
+3 test_match_signal 13 "$OUT" &&
+4
+5 { test-tool sigchain >actual; ret=$?; } &&
+6 {
+7 test_match_signal 15 "$ret" ||
+8 test "$ret" = 3
+9 } &&
+10 test_cmp expect actual
diff --git a/t/chainlint/chain-break-status.test b/t/chainlint/chain-break-status.test
index a6602a7b99..d9fee190d9 100644
--- a/t/chainlint/chain-break-status.test
+++ b/t/chainlint/chain-break-status.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-status' '
# LINT: broken &&-chain okay if next command handles "$?" explicitly
OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&
test_match_signal 13 "$OUT" &&
@@ -9,3 +10,4 @@ test_match_signal 13 "$OUT" &&
test "$ret" = 3
} &&
test_cmp expect actual
+'
diff --git a/t/chainlint/chained-block.expect b/t/chainlint/chained-block.expect
index 574cdceb07..a546b714a6 100644
--- a/t/chainlint/chained-block.expect
+++ b/t/chainlint/chained-block.expect
@@ -1,9 +1,9 @@
-echo nobody home && {
- test the doohicky ?!AMP?!
- right now
-} &&
-
-GIT_EXTERNAL_DIFF=echo git diff | {
- read path oldfile oldhex oldmode newfile newhex newmode &&
- test "z$oh" = "z$oldhex"
-}
+2 echo nobody home && {
+3 test the doohicky ?!AMP?!
+4 right now
+5 } &&
+6
+7 GIT_EXTERNAL_DIFF=echo git diff | {
+8 read path oldfile oldhex oldmode newfile newhex newmode &&
+9 test "z$oh" = "z$oldhex"
+10 }
diff --git a/t/chainlint/chained-block.test b/t/chainlint/chained-block.test
index 86f81ece63..71ef1d0b7f 100644
--- a/t/chainlint/chained-block.test
+++ b/t/chainlint/chained-block.test
@@ -1,3 +1,4 @@
+test_expect_success 'chained-block' '
# LINT: start of block chained to preceding command
echo nobody home && {
test the doohicky
@@ -9,3 +10,4 @@ GIT_EXTERNAL_DIFF=echo git diff | {
read path oldfile oldhex oldmode newfile newhex newmode &&
test "z$oh" = "z$oldhex"
}
+'
diff --git a/t/chainlint/chained-subshell.expect b/t/chainlint/chained-subshell.expect
index 83810ea7ec..f78b268291 100644
--- a/t/chainlint/chained-subshell.expect
+++ b/t/chainlint/chained-subshell.expect
@@ -1,10 +1,10 @@
-mkdir sub && (
- cd sub &&
- foo the bar ?!AMP?!
- nuff said
-) &&
-
-cut "-d " -f actual | (read s1 s2 s3 &&
-test -f $s1 ?!AMP?!
-test $(cat $s2) = tree2path1 &&
-test $(cat $s3) = tree3path1)
+2 mkdir sub && (
+3 cd sub &&
+4 foo the bar ?!AMP?!
+5 nuff said
+6 ) &&
+7
+8 cut "-d " -f actual | (read s1 s2 s3 &&
+9 test -f $s1 ?!AMP?!
+10 test $(cat $s2) = tree2path1 &&
+11 test $(cat $s3) = tree3path1)
diff --git a/t/chainlint/chained-subshell.test b/t/chainlint/chained-subshell.test
index 4ff6ddd8cb..1f11f65398 100644
--- a/t/chainlint/chained-subshell.test
+++ b/t/chainlint/chained-subshell.test
@@ -1,3 +1,4 @@
+test_expect_success 'chained-subshell' '
# LINT: start of subshell chained to preceding command
mkdir sub && (
cd sub &&
@@ -11,3 +12,4 @@ test -f $s1
test $(cat $s2) = tree2path1 &&
# LINT: closing subshell ")" correctly detected on same line as "$(...)"
test $(cat $s3) = tree3path1)
+'
diff --git a/t/chainlint/close-nested-and-parent-together.expect b/t/chainlint/close-nested-and-parent-together.expect
index 72d482f76d..4167e54a59 100644
--- a/t/chainlint/close-nested-and-parent-together.expect
+++ b/t/chainlint/close-nested-and-parent-together.expect
@@ -1,3 +1,3 @@
-(cd foo &&
- (bar &&
- baz))
+2 (cd foo &&
+3 (bar &&
+4 baz))
diff --git a/t/chainlint/close-nested-and-parent-together.test b/t/chainlint/close-nested-and-parent-together.test
index 72d482f76d..56b28b186b 100644
--- a/t/chainlint/close-nested-and-parent-together.test
+++ b/t/chainlint/close-nested-and-parent-together.test
@@ -1,3 +1,5 @@
+test_expect_success 'close-nested-and-parent-together' '
(cd foo &&
(bar &&
baz))
+'
diff --git a/t/chainlint/close-subshell.expect b/t/chainlint/close-subshell.expect
index 2192a2870a..a272cfe72e 100644
--- a/t/chainlint/close-subshell.expect
+++ b/t/chainlint/close-subshell.expect
@@ -1,26 +1,26 @@
-(
- foo
-) &&
-(
- bar
-) >out &&
-(
- baz
-) 2>err &&
-(
- boo
-) <input &&
-(
- bip
-) | wuzzle &&
-(
- bop
-) | fazz \
- fozz &&
-(
- bup
-) |
-fuzzle &&
-(
- yop
-)
+2 (
+3 foo
+4 ) &&
+5 (
+6 bar
+7 ) >out &&
+8 (
+9 baz
+10 ) 2>err &&
+11 (
+12 boo
+13 ) <input &&
+14 (
+15 bip
+16 ) | wuzzle &&
+17 (
+18 bop
+19 ) | fazz \
+20 fozz &&
+21 (
+22 bup
+23 ) |
+24 fuzzle &&
+25 (
+26 yop
+27 )
diff --git a/t/chainlint/close-subshell.test b/t/chainlint/close-subshell.test
index 508ca447fd..b99f80569d 100644
--- a/t/chainlint/close-subshell.test
+++ b/t/chainlint/close-subshell.test
@@ -1,3 +1,4 @@
+test_expect_success 'close-subshell' '
# LINT: closing ")" with various decorations ("&&", ">", "|", etc.)
(
foo
@@ -25,3 +26,4 @@ fuzzle &&
(
yop
)
+'
diff --git a/t/chainlint/command-substitution-subsubshell.expect b/t/chainlint/command-substitution-subsubshell.expect
index ec42f2c30c..f2a9312dc8 100644
--- a/t/chainlint/command-substitution-subsubshell.expect
+++ b/t/chainlint/command-substitution-subsubshell.expect
@@ -1,2 +1,2 @@
-OUT=$( ((large_git 1>&3) | :) 3>&1 ) &&
-test_match_signal 13 "$OUT"
+2 OUT=$( ((large_git 1>&3) | :) 3>&1 ) &&
+3 test_match_signal 13 "$OUT"
diff --git a/t/chainlint/command-substitution-subsubshell.test b/t/chainlint/command-substitution-subsubshell.test
index 321de2951c..4ea772d60a 100644
--- a/t/chainlint/command-substitution-subsubshell.test
+++ b/t/chainlint/command-substitution-subsubshell.test
@@ -1,3 +1,5 @@
+test_expect_success 'command-substitution-subsubshell' '
# LINT: subshell nested in subshell nested in command substitution
OUT=$( ((large_git 1>&3) | :) 3>&1 ) &&
test_match_signal 13 "$OUT"
+'
diff --git a/t/chainlint/command-substitution.expect b/t/chainlint/command-substitution.expect
index c72e4df9e7..5e31b36db6 100644
--- a/t/chainlint/command-substitution.expect
+++ b/t/chainlint/command-substitution.expect
@@ -1,9 +1,9 @@
-(
- foo &&
- bar=$(gobble) &&
- baz
-) &&
-(
- bar=$(gobble blocks) ?!AMP?!
- baz
-)
+2 (
+3 foo &&
+4 bar=$(gobble) &&
+5 baz
+6 ) &&
+7 (
+8 bar=$(gobble blocks) ?!AMP?!
+9 baz
+10 )
diff --git a/t/chainlint/command-substitution.test b/t/chainlint/command-substitution.test
index 3bbb002a4c..494d671e80 100644
--- a/t/chainlint/command-substitution.test
+++ b/t/chainlint/command-substitution.test
@@ -1,3 +1,4 @@
+test_expect_success 'command-substitution' '
(
foo &&
# LINT: closing ")" of $(...) not misinterpreted as subshell-closing ")"
@@ -9,3 +10,4 @@
bar=$(gobble blocks)
baz
)
+'
diff --git a/t/chainlint/comment.expect b/t/chainlint/comment.expect
index a68f1f9d7c..584098d6ba 100644
--- a/t/chainlint/comment.expect
+++ b/t/chainlint/comment.expect
@@ -1,8 +1,8 @@
-(
- # comment 1
- nothing &&
- # comment 2
- something
- # comment 3
- # comment 4
-)
+2 (
+3 # comment 1
+4 nothing &&
+5 # comment 2
+6 something
+7 # comment 3
+8 # comment 4
+9 )
diff --git a/t/chainlint/comment.test b/t/chainlint/comment.test
index 113c0c466f..c488beac0d 100644
--- a/t/chainlint/comment.test
+++ b/t/chainlint/comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'comment' '
(
# LINT: swallow comment lines
# comment 1
@@ -9,3 +10,4 @@
# comment 3
# comment 4
)
+'
diff --git a/t/chainlint/complex-if-in-cuddled-loop.expect b/t/chainlint/complex-if-in-cuddled-loop.expect
index dac2d0fd1d..3a740103db 100644
--- a/t/chainlint/complex-if-in-cuddled-loop.expect
+++ b/t/chainlint/complex-if-in-cuddled-loop.expect
@@ -1,9 +1,9 @@
-(for i in a b c; do
- if test "$(echo $(waffle bat))" = "eleventeen" &&
- test "$x" = "$y"; then
- :
- else
- echo >file
- fi ?!LOOP?!
- done) &&
-test ! -f file
+2 (for i in a b c; do
+3 if test "$(echo $(waffle bat))" = "eleventeen" &&
+4 test "$x" = "$y"; then
+5 :
+6 else
+7 echo >file
+8 fi ?!LOOP?!
+9 done) &&
+10 test ! -f file
diff --git a/t/chainlint/complex-if-in-cuddled-loop.test b/t/chainlint/complex-if-in-cuddled-loop.test
index 5efeda58b2..f98ae4c42d 100644
--- a/t/chainlint/complex-if-in-cuddled-loop.test
+++ b/t/chainlint/complex-if-in-cuddled-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'complex-if-in-cuddled-loop' '
# LINT: "for" loop cuddled with "(" and ")" and nested "if" with complex
# LINT: multi-line condition; indented with spaces, not tabs
(for i in a b c; do
@@ -9,3 +10,4 @@
fi
done) &&
test ! -f file
+'
diff --git a/t/chainlint/cuddled-if-then-else.expect b/t/chainlint/cuddled-if-then-else.expect
index 1d8ed58c49..72da8794cb 100644
--- a/t/chainlint/cuddled-if-then-else.expect
+++ b/t/chainlint/cuddled-if-then-else.expect
@@ -1,6 +1,6 @@
-(if test -z ""; then
- echo empty
- else
- echo bizzy
- fi) &&
-echo foobar
+2 (if test -z ""; then
+3 echo empty
+4 else
+5 echo bizzy
+6 fi) &&
+7 echo foobar
diff --git a/t/chainlint/cuddled-if-then-else.test b/t/chainlint/cuddled-if-then-else.test
index 7c53f4efe3..b1b42e1aac 100644
--- a/t/chainlint/cuddled-if-then-else.test
+++ b/t/chainlint/cuddled-if-then-else.test
@@ -1,3 +1,4 @@
+test_expect_success 'cuddled-if-then-else' '
# LINT: "if" cuddled with "(" and ")"; indented with spaces, not tabs
(if test -z ""; then
echo empty
@@ -5,3 +6,4 @@
echo bizzy
fi) &&
echo foobar
+'
diff --git a/t/chainlint/cuddled-loop.expect b/t/chainlint/cuddled-loop.expect
index 9cf260708e..c38585c756 100644
--- a/t/chainlint/cuddled-loop.expect
+++ b/t/chainlint/cuddled-loop.expect
@@ -1,4 +1,4 @@
-( while read x
- do foobar bop || exit 1
- done <file ) &&
-outside subshell
+2 ( while read x
+3 do foobar bop || exit 1
+4 done <file ) &&
+5 outside subshell
diff --git a/t/chainlint/cuddled-loop.test b/t/chainlint/cuddled-loop.test
index 3c2a62f751..6fccb6ac22 100644
--- a/t/chainlint/cuddled-loop.test
+++ b/t/chainlint/cuddled-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'cuddled-loop' '
# LINT: "while" loop cuddled with "(" and ")", with embedded (allowed)
# LINT: "|| exit {n}" to exit loop early, and using redirection "<" to feed
# LINT: loop; indented with spaces, not tabs
@@ -5,3 +6,4 @@
do foobar bop || exit 1
done <file ) &&
outside subshell
+'
diff --git a/t/chainlint/cuddled.expect b/t/chainlint/cuddled.expect
index c3e0be4047..b06d638311 100644
--- a/t/chainlint/cuddled.expect
+++ b/t/chainlint/cuddled.expect
@@ -1,17 +1,17 @@
-(cd foo &&
- bar
-) &&
-
-(cd foo ?!AMP?!
- bar
-) &&
-
-(
- cd foo &&
- bar) &&
-
-(cd foo &&
- bar) &&
-
-(cd foo ?!AMP?!
- bar)
+2 (cd foo &&
+3 bar
+4 ) &&
+5
+6 (cd foo ?!AMP?!
+7 bar
+8 ) &&
+9
+10 (
+11 cd foo &&
+12 bar) &&
+13
+14 (cd foo &&
+15 bar) &&
+16
+17 (cd foo ?!AMP?!
+18 bar)
diff --git a/t/chainlint/cuddled.test b/t/chainlint/cuddled.test
index 257b5b5eed..5a6ef7a4a6 100644
--- a/t/chainlint/cuddled.test
+++ b/t/chainlint/cuddled.test
@@ -1,3 +1,4 @@
+test_expect_success 'cuddled' '
# LINT: first subshell statement cuddled with opening "("
(cd foo &&
bar
@@ -20,3 +21,4 @@
# LINT: same with missing "&&"
(cd foo
bar)
+'
diff --git a/t/chainlint/double-here-doc.expect b/t/chainlint/double-here-doc.expect
index cd584a4357..48c04ecd58 100644
--- a/t/chainlint/double-here-doc.expect
+++ b/t/chainlint/double-here-doc.expect
@@ -1,12 +1,12 @@
-run_sub_test_lib_test_err run-inv-range-start \
- "--run invalid range start" \
- --run="a-5" <<-\EOF &&
-test_expect_success "passing test #1" "true"
-test_done
-EOF
-check_sub_test_lib_test_err run-inv-range-start \
- <<-\EOF_OUT 3<<-EOF_ERR
-> FATAL: Unexpected exit with code 1
-EOF_OUT
-> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
-EOF_ERR
+2 run_sub_test_lib_test_err run-inv-range-start \
+3 "--run invalid range start" \
+4 --run="a-5" <<-\EOF &&
+5 test_expect_success "passing test #1" "true"
+6 test_done
+7 EOF
+8 check_sub_test_lib_test_err run-inv-range-start \
+9 <<-\EOF_OUT 3<<-EOF_ERR
+10 > FATAL: Unexpected exit with code 1
+11 EOF_OUT
+12 > error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
+13 EOF_ERR
diff --git a/t/chainlint/double-here-doc.test b/t/chainlint/double-here-doc.test
index cd584a4357..1b69b7a651 100644
--- a/t/chainlint/double-here-doc.test
+++ b/t/chainlint/double-here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'double-here-doc' '
run_sub_test_lib_test_err run-inv-range-start \
"--run invalid range start" \
--run="a-5" <<-\EOF &&
@@ -10,3 +11,4 @@ check_sub_test_lib_test_err run-inv-range-start \
EOF_OUT
> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
EOF_ERR
+'
diff --git a/t/chainlint/dqstring-line-splice.expect b/t/chainlint/dqstring-line-splice.expect
index 37eab80738..2ca1c92cd6 100644
--- a/t/chainlint/dqstring-line-splice.expect
+++ b/t/chainlint/dqstring-line-splice.expect
@@ -1,5 +1,5 @@
-
-echo 'fatal: reword option of --fixup is mutually exclusive with' '--patch/--interactive/--all/--include/--only' >expect &&
-test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
-test_cmp expect actual
-
+2
+3 echo 'fatal: reword option of --fixup is mutually exclusive with' '--patch/--interactive/--all/--include/--only' >expect &&
+4 test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
+5 test_cmp expect actual
+6
diff --git a/t/chainlint/dqstring-line-splice.test b/t/chainlint/dqstring-line-splice.test
index b40714439f..f6aa637be8 100644
--- a/t/chainlint/dqstring-line-splice.test
+++ b/t/chainlint/dqstring-line-splice.test
@@ -1,3 +1,4 @@
+test_expect_success 'dqstring-line-splice' '
# LINT: line-splice within DQ-string
'"
echo 'fatal: reword option of --fixup is mutually exclusive with'\
@@ -5,3 +6,4 @@ echo 'fatal: reword option of --fixup is mutually exclusive with'\
test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
test_cmp expect actual
"'
+'
diff --git a/t/chainlint/dqstring-no-interpolate.expect b/t/chainlint/dqstring-no-interpolate.expect
index 087eda15e4..c9f75849c5 100644
--- a/t/chainlint/dqstring-no-interpolate.expect
+++ b/t/chainlint/dqstring-no-interpolate.expect
@@ -1,12 +1,12 @@
-grep "^ ! [rejected][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out &&
-
-grep "^\.git$" output.txt &&
-
-
-(
- cd client$version &&
- GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. $(cat ../input)
-) >output &&
- cut -d ' ' -f 2 <output | sort >actual &&
- test_cmp expect actual
-
+2 grep "^ ! [rejected][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out &&
+3
+4 grep "^\.git$" output.txt &&
+5
+6
+7 (
+8 cd client$version &&
+9 GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. $(cat ../input)
+10 ) >output &&
+11 cut -d ' ' -f 2 <output | sort >actual &&
+12 test_cmp expect actual
+13
diff --git a/t/chainlint/dqstring-no-interpolate.test b/t/chainlint/dqstring-no-interpolate.test
index d2f4219cbb..7ae079b558 100644
--- a/t/chainlint/dqstring-no-interpolate.test
+++ b/t/chainlint/dqstring-no-interpolate.test
@@ -1,3 +1,4 @@
+test_expect_success 'dqstring-no-interpolate' '
# LINT: regex dollar-sign eol anchor in double-quoted string not special
grep "^ ! \[rejected\][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out &&
@@ -13,3 +14,4 @@ grep "^\\.git\$" output.txt &&
cut -d ' ' -f 2 <output | sort >actual &&
test_cmp expect actual
"'
+'
diff --git a/t/chainlint/empty-here-doc.expect b/t/chainlint/empty-here-doc.expect
index 8507721192..54b33f823a 100644
--- a/t/chainlint/empty-here-doc.expect
+++ b/t/chainlint/empty-here-doc.expect
@@ -1,4 +1,4 @@
-git ls-tree $tree path >current &&
-cat >expected <<\EOF &&
-EOF
-test_output
+2 git ls-tree $tree path >current &&
+3 cat >expected <<\EOF &&
+4 EOF
+5 test_output
diff --git a/t/chainlint/empty-here-doc.test b/t/chainlint/empty-here-doc.test
index 24fc165de3..8b7ab6eb5f 100644
--- a/t/chainlint/empty-here-doc.test
+++ b/t/chainlint/empty-here-doc.test
@@ -1,5 +1,7 @@
+test_expect_success 'empty-here-doc' '
git ls-tree $tree path >current &&
# LINT: empty here-doc
cat >expected <<\EOF &&
EOF
test_output
+'
diff --git a/t/chainlint/exclamation.expect b/t/chainlint/exclamation.expect
index 765a35bb4c..078744b61b 100644
--- a/t/chainlint/exclamation.expect
+++ b/t/chainlint/exclamation.expect
@@ -1,4 +1,4 @@
-if ! condition; then echo nope; else yep; fi &&
-test_prerequisite !MINGW &&
-mail uucp!address &&
-echo !whatever!
+2 if ! condition; then echo nope; else yep; fi &&
+3 test_prerequisite !MINGW &&
+4 mail uucp!address &&
+5 echo !whatever!
diff --git a/t/chainlint/exclamation.test b/t/chainlint/exclamation.test
index 323595b5bd..796de21b7c 100644
--- a/t/chainlint/exclamation.test
+++ b/t/chainlint/exclamation.test
@@ -1,3 +1,4 @@
+test_expect_success 'exclamation' '
# LINT: "! word" is two tokens
if ! condition; then echo nope; else yep; fi &&
# LINT: "!word" is single token, not two tokens "!" and "word"
@@ -6,3 +7,4 @@ test_prerequisite !MINGW &&
mail uucp!address &&
# LINT: "!word!" is single token, not three tokens "!", "word", and "!"
echo !whatever!
+'
diff --git a/t/chainlint/exit-loop.expect b/t/chainlint/exit-loop.expect
index f76aa60466..407278094c 100644
--- a/t/chainlint/exit-loop.expect
+++ b/t/chainlint/exit-loop.expect
@@ -1,24 +1,24 @@
-(
- for i in a b c
- do
- foo || exit 1
- bar &&
- baz
- done
-) &&
-(
- while true
- do
- foo || exit 1
- bar &&
- baz
- done
-) &&
-(
- i=0 &&
- while test $i -lt 10
- do
- echo $i || exit
- i=$(($i + 1))
- done
-)
+2 (
+3 for i in a b c
+4 do
+5 foo || exit 1
+6 bar &&
+7 baz
+8 done
+9 ) &&
+10 (
+11 while true
+12 do
+13 foo || exit 1
+14 bar &&
+15 baz
+16 done
+17 ) &&
+18 (
+19 i=0 &&
+20 while test $i -lt 10
+21 do
+22 echo $i || exit
+23 i=$(($i + 1))
+24 done
+25 )
diff --git a/t/chainlint/exit-loop.test b/t/chainlint/exit-loop.test
index 2f038207e1..7e8b68b465 100644
--- a/t/chainlint/exit-loop.test
+++ b/t/chainlint/exit-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'exit-loop' '
(
for i in a b c
do
@@ -25,3 +26,4 @@
i=$(($i + 1))
done
)
+'
diff --git a/t/chainlint/exit-subshell.expect b/t/chainlint/exit-subshell.expect
index da80339f78..793db12453 100644
--- a/t/chainlint/exit-subshell.expect
+++ b/t/chainlint/exit-subshell.expect
@@ -1,5 +1,5 @@
-(
- foo || exit 1
- bar &&
- baz
-)
+2 (
+3 foo || exit 1
+4 bar &&
+5 baz
+6 )
diff --git a/t/chainlint/exit-subshell.test b/t/chainlint/exit-subshell.test
index 4e6ab69b88..05dff55cd7 100644
--- a/t/chainlint/exit-subshell.test
+++ b/t/chainlint/exit-subshell.test
@@ -1,6 +1,8 @@
+test_expect_success 'exit-subshell' '
(
# LINT: "|| exit {n}" valid subshell escape without hurting &&-chain
foo || exit 1
bar &&
baz
)
+'
diff --git a/t/chainlint/for-loop-abbreviated.expect b/t/chainlint/for-loop-abbreviated.expect
index 02c0d15cca..5574831976 100644
--- a/t/chainlint/for-loop-abbreviated.expect
+++ b/t/chainlint/for-loop-abbreviated.expect
@@ -1,5 +1,5 @@
-for it
-do
- path=$(expr "$it" : ([^:]*)) &&
- git update-index --add "$path" || exit
-done
+2 for it
+3 do
+4 path=$(expr "$it" : ([^:]*)) &&
+5 git update-index --add "$path" || exit
+6 done
diff --git a/t/chainlint/for-loop-abbreviated.test b/t/chainlint/for-loop-abbreviated.test
index 1084eccb89..1dd14f2a44 100644
--- a/t/chainlint/for-loop-abbreviated.test
+++ b/t/chainlint/for-loop-abbreviated.test
@@ -1,6 +1,8 @@
+test_expect_success 'for-loop-abbreviated' '
# LINT: for-loop lacking optional "in [word...]" before "do"
for it
do
path=$(expr "$it" : '\([^:]*\)') &&
git update-index --add "$path" || exit
done
+'
diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect
index d2237f1e38..908aeedf96 100644
--- a/t/chainlint/for-loop.expect
+++ b/t/chainlint/for-loop.expect
@@ -1,14 +1,14 @@
-(
- for i in a b c
- do
- echo $i ?!AMP?!
- cat <<-\EOF ?!LOOP?!
- bar
- EOF
- done ?!AMP?!
-
- for i in a b c; do
- echo $i &&
- cat $i ?!LOOP?!
- done
-)
+2 (
+3 for i in a b c
+4 do
+5 echo $i ?!AMP?!
+6 cat <<-\EOF ?!LOOP?!
+7 bar
+8 EOF
+9 done ?!AMP?!
+10
+11 for i in a b c; do
+12 echo $i &&
+13 cat $i ?!LOOP?!
+14 done
+15 )
diff --git a/t/chainlint/for-loop.test b/t/chainlint/for-loop.test
index 6cb3428158..6f2489eb19 100644
--- a/t/chainlint/for-loop.test
+++ b/t/chainlint/for-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'for-loop' '
(
# LINT: "for", "do", "done" do not need "&&"
for i in a b c
@@ -17,3 +18,4 @@
cat $i
done
)
+'
diff --git a/t/chainlint/function.expect b/t/chainlint/function.expect
index dd7c997a3c..c226246b25 100644
--- a/t/chainlint/function.expect
+++ b/t/chainlint/function.expect
@@ -1,11 +1,11 @@
-sha1_file() {
- echo "$*" | sed "s#..#.git/objects/&/#"
-} &&
-
-remove_object() {
- file=$(sha1_file "$*") &&
- test -e "$file" ?!AMP?!
- rm -f "$file"
-} ?!AMP?!
-
-sha1_file arg && remove_object arg
+2 sha1_file() {
+3 echo "$*" | sed "s#..#.git/objects/&/#"
+4 } &&
+5
+6 remove_object() {
+7 file=$(sha1_file "$*") &&
+8 test -e "$file" ?!AMP?!
+9 rm -f "$file"
+10 } ?!AMP?!
+11
+12 sha1_file arg && remove_object arg
diff --git a/t/chainlint/function.test b/t/chainlint/function.test
index 5ee59562c9..763fcf3f87 100644
--- a/t/chainlint/function.test
+++ b/t/chainlint/function.test
@@ -1,3 +1,4 @@
+test_expect_success 'function' '
# LINT: "()" in function definition not mistaken for subshell
sha1_file() {
echo "$*" | sed "s#..#.git/objects/&/#"
@@ -11,3 +12,4 @@ remove_object() {
}
sha1_file arg && remove_object arg
+'
diff --git a/t/chainlint/here-doc-body-indent.expect b/t/chainlint/here-doc-body-indent.expect
new file mode 100644
index 0000000000..4323acc93d
--- /dev/null
+++ b/t/chainlint/here-doc-body-indent.expect
@@ -0,0 +1,2 @@
+2 echo "we should find this" ?!AMP?!
+3 echo "even though our heredoc has its indent stripped"
diff --git a/t/chainlint/here-doc-body-indent.test b/t/chainlint/here-doc-body-indent.test
new file mode 100644
index 0000000000..39ff970ef3
--- /dev/null
+++ b/t/chainlint/here-doc-body-indent.test
@@ -0,0 +1,4 @@
+test_expect_success 'here-doc-body-indent' - <<-\EOT
+ echo "we should find this"
+ echo "even though our heredoc has its indent stripped"
+EOT
diff --git a/t/chainlint/here-doc-body-pathological.expect b/t/chainlint/here-doc-body-pathological.expect
new file mode 100644
index 0000000000..a93a1fa3aa
--- /dev/null
+++ b/t/chainlint/here-doc-body-pathological.expect
@@ -0,0 +1,7 @@
+2 echo "outer here-doc does not allow indented end-tag" ?!AMP?!
+3 cat >file <<-\EOF &&
+4 but this inner here-doc
+5 does allow indented EOF
+6 EOF
+7 echo "missing chain after" ?!AMP?!
+8 echo "but this line is OK because it's the end"
diff --git a/t/chainlint/here-doc-body-pathological.test b/t/chainlint/here-doc-body-pathological.test
new file mode 100644
index 0000000000..7d2daa44f9
--- /dev/null
+++ b/t/chainlint/here-doc-body-pathological.test
@@ -0,0 +1,9 @@
+test_expect_success 'here-doc-body-pathological' - <<\EOF
+ echo "outer here-doc does not allow indented end-tag"
+ cat >file <<-\EOF &&
+ but this inner here-doc
+ does allow indented EOF
+ EOF
+ echo "missing chain after"
+ echo "but this line is OK because it's the end"
+EOF
diff --git a/t/chainlint/here-doc-body.expect b/t/chainlint/here-doc-body.expect
new file mode 100644
index 0000000000..ddf1c412af
--- /dev/null
+++ b/t/chainlint/here-doc-body.expect
@@ -0,0 +1,7 @@
+2 echo "missing chain before" ?!AMP?!
+3 cat >file <<-\EOF &&
+4 inside inner here-doc
+5 these are not shell commands
+6 EOF
+7 echo "missing chain after" ?!AMP?!
+8 echo "but this line is OK because it's the end"
diff --git a/t/chainlint/here-doc-body.test b/t/chainlint/here-doc-body.test
new file mode 100644
index 0000000000..989ac2f4e1
--- /dev/null
+++ b/t/chainlint/here-doc-body.test
@@ -0,0 +1,9 @@
+test_expect_success 'here-doc-body' - <<\EOT
+ echo "missing chain before"
+ cat >file <<-\EOF &&
+ inside inner here-doc
+ these are not shell commands
+ EOF
+ echo "missing chain after"
+ echo "but this line is OK because it's the end"
+EOT
diff --git a/t/chainlint/here-doc-close-subshell.expect b/t/chainlint/here-doc-close-subshell.expect
index 7d9c2b5607..965813f463 100644
--- a/t/chainlint/here-doc-close-subshell.expect
+++ b/t/chainlint/here-doc-close-subshell.expect
@@ -1,4 +1,4 @@
-(
- cat <<-\INPUT)
- fizz
- INPUT
+2 (
+3 cat <<-\INPUT)
+4 fizz
+5 INPUT
diff --git a/t/chainlint/here-doc-close-subshell.test b/t/chainlint/here-doc-close-subshell.test
index b857ff5467..2458f3323b 100644
--- a/t/chainlint/here-doc-close-subshell.test
+++ b/t/chainlint/here-doc-close-subshell.test
@@ -1,5 +1,7 @@
+test_expect_success 'here-doc-close-subshell' '
(
# LINT: line contains here-doc and closes nested subshell
cat <<-\INPUT)
fizz
INPUT
+'
diff --git a/t/chainlint/here-doc-double.expect b/t/chainlint/here-doc-double.expect
new file mode 100644
index 0000000000..20dba4b452
--- /dev/null
+++ b/t/chainlint/here-doc-double.expect
@@ -0,0 +1,2 @@
+8 echo "actual test commands" ?!AMP?!
+9 echo "that should be checked"
diff --git a/t/chainlint/here-doc-double.test b/t/chainlint/here-doc-double.test
new file mode 100644
index 0000000000..777389f0d9
--- /dev/null
+++ b/t/chainlint/here-doc-double.test
@@ -0,0 +1,10 @@
+# This is obviously a ridiculous thing to do, but we should be able
+# to handle two here-docs on the same line, and attribute them
+# correctly.
+test_expect_success "$(cat <<END_OF_PREREQS)" 'here-doc-double' - <<\EOT
+SOME
+PREREQS
+END_OF_PREREQS
+ echo "actual test commands"
+ echo "that should be checked"
+EOT
diff --git a/t/chainlint/here-doc-indent-operator.expect b/t/chainlint/here-doc-indent-operator.expect
index f92a7ce999..277a11202d 100644
--- a/t/chainlint/here-doc-indent-operator.expect
+++ b/t/chainlint/here-doc-indent-operator.expect
@@ -1,11 +1,11 @@
-cat >expect <<- EOF &&
-header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
-num_commits: $1
-chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data
-EOF
-
-cat >expect << -EOF ?!AMP?!
-this is not indented
--EOF
-
-cleanup
+2 cat >expect <<- EOF &&
+3 header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
+4 num_commits: $1
+5 chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data
+6 EOF
+7
+8 cat >expect << -EOF ?!AMP?!
+9 this is not indented
+10 -EOF
+11
+12 cleanup
diff --git a/t/chainlint/here-doc-indent-operator.test b/t/chainlint/here-doc-indent-operator.test
index c8a6f18eb4..a2656f47c1 100644
--- a/t/chainlint/here-doc-indent-operator.test
+++ b/t/chainlint/here-doc-indent-operator.test
@@ -1,3 +1,4 @@
+test_expect_success 'here-doc-indent-operator' '
# LINT: whitespace between operator "<<-" and tag legal
cat >expect <<- EOF &&
header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
@@ -11,3 +12,4 @@ this is not indented
-EOF
cleanup
+'
diff --git a/t/chainlint/here-doc-multi-line-command-subst.expect b/t/chainlint/here-doc-multi-line-command-subst.expect
index b7364c82c8..41b55f6437 100644
--- a/t/chainlint/here-doc-multi-line-command-subst.expect
+++ b/t/chainlint/here-doc-multi-line-command-subst.expect
@@ -1,8 +1,8 @@
-(
- x=$(bobble <<-\END &&
- fossil
- vegetable
- END
- wiffle) ?!AMP?!
- echo $x
-)
+2 (
+3 x=$(bobble <<-\END &&
+4 fossil
+5 vegetable
+6 END
+7 wiffle) ?!AMP?!
+8 echo $x
+9 )
diff --git a/t/chainlint/here-doc-multi-line-command-subst.test b/t/chainlint/here-doc-multi-line-command-subst.test
index 899bc5de8b..8710a8c483 100644
--- a/t/chainlint/here-doc-multi-line-command-subst.test
+++ b/t/chainlint/here-doc-multi-line-command-subst.test
@@ -1,3 +1,4 @@
+test_expect_success 'here-doc-multi-line-command-subst' '
(
# LINT: line contains here-doc and opens multi-line $(...)
x=$(bobble <<-\END &&
@@ -7,3 +8,4 @@
wiffle)
echo $x
)
+'
diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect
index 6c13bdcbfb..c71828589e 100644
--- a/t/chainlint/here-doc-multi-line-string.expect
+++ b/t/chainlint/here-doc-multi-line-string.expect
@@ -1,7 +1,7 @@
-(
- cat <<-\TXT && echo "multi-line
- string" ?!AMP?!
- fizzle
- TXT
- bap
-)
+2 (
+3 cat <<-\TXT && echo "multi-line
+4 string" ?!AMP?!
+5 fizzle
+6 TXT
+7 bap
+8 )
diff --git a/t/chainlint/here-doc-multi-line-string.test b/t/chainlint/here-doc-multi-line-string.test
index a53edbcc8d..2f496002fd 100644
--- a/t/chainlint/here-doc-multi-line-string.test
+++ b/t/chainlint/here-doc-multi-line-string.test
@@ -1,3 +1,4 @@
+test_expect_success 'here-doc-multi-line-string' '
(
# LINT: line contains here-doc and opens multi-line string
cat <<-\TXT && echo "multi-line
@@ -6,3 +7,4 @@
TXT
bap
)
+'
diff --git a/t/chainlint/here-doc.expect b/t/chainlint/here-doc.expect
index 91b961242a..2c382dd8eb 100644
--- a/t/chainlint/here-doc.expect
+++ b/t/chainlint/here-doc.expect
@@ -1,25 +1,25 @@
-boodle wobba \
- gorgo snoot \
- wafta snurb <<EOF &&
-quoth the raven,
-nevermore...
-EOF
-
-cat <<-Arbitrary_Tag_42 >foo &&
-snoz
-boz
-woz
-Arbitrary_Tag_42
-
-cat <<"zump" >boo &&
-snoz
-boz
-woz
-zump
-
-horticulture <<\EOF
-gomez
-morticia
-wednesday
-pugsly
-EOF
+2 boodle wobba \
+3 gorgo snoot \
+4 wafta snurb <<EOF &&
+5 quoth the raven,
+6 nevermore...
+7 EOF
+8
+9 cat <<-Arbitrary_Tag_42 >foo &&
+10 snoz
+11 boz
+12 woz
+13 Arbitrary_Tag_42
+14
+15 cat <<"zump" >boo &&
+16 snoz
+17 boz
+18 woz
+19 zump
+20
+21 horticulture <<\EOF
+22 gomez
+23 morticia
+24 wednesday
+25 pugsly
+26 EOF
diff --git a/t/chainlint/here-doc.test b/t/chainlint/here-doc.test
index 3f5f92cad3..c91b695319 100644
--- a/t/chainlint/here-doc.test
+++ b/t/chainlint/here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'here-doc' '
# LINT: stitch together incomplete \-ending lines
# LINT: swallow here-doc to avoid false positives in content
boodle wobba \
@@ -28,3 +29,4 @@ morticia
wednesday
pugsly
EOF
+'
diff --git a/t/chainlint/if-condition-split.expect b/t/chainlint/if-condition-split.expect
index ee745ef8d7..9daf3d294a 100644
--- a/t/chainlint/if-condition-split.expect
+++ b/t/chainlint/if-condition-split.expect
@@ -1,7 +1,7 @@
-if bob &&
- marcia ||
- kevin
-then
- echo "nomads" ?!AMP?!
- echo "for sure"
-fi
+2 if bob &&
+3 marcia ||
+4 kevin
+5 then
+6 echo "nomads" ?!AMP?!
+7 echo "for sure"
+8 fi
diff --git a/t/chainlint/if-condition-split.test b/t/chainlint/if-condition-split.test
index 240daa9fd5..9a3b3ed04a 100644
--- a/t/chainlint/if-condition-split.test
+++ b/t/chainlint/if-condition-split.test
@@ -1,3 +1,4 @@
+test_expect_success 'if-condition-split' '
# LINT: "if" condition split across multiple lines at "&&" or "||"
if bob &&
marcia ||
@@ -6,3 +7,4 @@ then
echo "nomads"
echo "for sure"
fi
+'
diff --git a/t/chainlint/if-in-loop.expect b/t/chainlint/if-in-loop.expect
index d6514ae749..ff8c60dbdb 100644
--- a/t/chainlint/if-in-loop.expect
+++ b/t/chainlint/if-in-loop.expect
@@ -1,12 +1,12 @@
-(
- for i in a b c
- do
- if false
- then
- echo "err"
- exit 1
- fi ?!AMP?!
- foo
- done ?!AMP?!
- bar
-)
+2 (
+3 for i in a b c
+4 do
+5 if false
+6 then
+7 echo "err"
+8 exit 1
+9 fi ?!AMP?!
+10 foo
+11 done ?!AMP?!
+12 bar
+13 )
diff --git a/t/chainlint/if-in-loop.test b/t/chainlint/if-in-loop.test
index 90c23976fe..5be9d1cfa5 100644
--- a/t/chainlint/if-in-loop.test
+++ b/t/chainlint/if-in-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'if-in-loop' '
(
for i in a b c
do
@@ -13,3 +14,4 @@
done
bar
)
+'
diff --git a/t/chainlint/if-then-else.expect b/t/chainlint/if-then-else.expect
index cbaaf857d4..965d7e41a2 100644
--- a/t/chainlint/if-then-else.expect
+++ b/t/chainlint/if-then-else.expect
@@ -1,22 +1,22 @@
-(
- if test -n ""
- then
- echo very ?!AMP?!
- echo empty
- elif test -z ""
- then
- echo foo
- else
- echo foo &&
- cat <<-\EOF
- bar
- EOF
- fi ?!AMP?!
- echo poodle
-) &&
-(
- if test -n ""; then
- echo very &&
- echo empty
- fi
-)
+2 (
+3 if test -n ""
+4 then
+5 echo very ?!AMP?!
+6 echo empty
+7 elif test -z ""
+8 then
+9 echo foo
+10 else
+11 echo foo &&
+12 cat <<-\EOF
+13 bar
+14 EOF
+15 fi ?!AMP?!
+16 echo poodle
+17 ) &&
+18 (
+19 if test -n ""; then
+20 echo very &&
+21 echo empty
+22 fi
+23 )
diff --git a/t/chainlint/if-then-else.test b/t/chainlint/if-then-else.test
index 2055336c2b..6582a7f440 100644
--- a/t/chainlint/if-then-else.test
+++ b/t/chainlint/if-then-else.test
@@ -1,3 +1,4 @@
+test_expect_success 'if-then-else' '
(
# LINT: "if", "then", "elif", "else", "fi" do not need "&&"
if test -n ""
@@ -27,3 +28,4 @@
echo empty
fi
)
+'
diff --git a/t/chainlint/incomplete-line.expect b/t/chainlint/incomplete-line.expect
index 134d3a14f5..b15e00b901 100644
--- a/t/chainlint/incomplete-line.expect
+++ b/t/chainlint/incomplete-line.expect
@@ -1,10 +1,10 @@
-line 1 \
-line 2 \
-line 3 \
-line 4 &&
-(
- line 5 \
- line 6 \
- line 7 \
- line 8
-)
+2 line 1 \
+3 line 2 \
+4 line 3 \
+5 line 4 &&
+6 (
+7 line 5 \
+8 line 6 \
+9 line 7 \
+10 line 8
+11 )
diff --git a/t/chainlint/incomplete-line.test b/t/chainlint/incomplete-line.test
index d856658083..74a93021eb 100644
--- a/t/chainlint/incomplete-line.test
+++ b/t/chainlint/incomplete-line.test
@@ -1,3 +1,4 @@
+test_expect_success 'incomplete-line' '
# LINT: stitch together all incomplete \-ending lines
line 1 \
line 2 \
@@ -10,3 +11,4 @@ line 4 &&
line 7 \
line 8
)
+'
diff --git a/t/chainlint/inline-comment.expect b/t/chainlint/inline-comment.expect
index 6bad218530..0285c0b22c 100644
--- a/t/chainlint/inline-comment.expect
+++ b/t/chainlint/inline-comment.expect
@@ -1,8 +1,8 @@
-(
- foobar && # comment 1
- barfoo ?!AMP?! # wrong position for &&
- flibble "not a # comment"
-) &&
-
-(cd foo &&
- flibble "not a # comment")
+2 (
+3 foobar && # comment 1
+4 barfoo ?!AMP?! # wrong position for &&
+5 flibble "not a # comment"
+6 ) &&
+7
+8 (cd foo &&
+9 flibble "not a # comment")
diff --git a/t/chainlint/inline-comment.test b/t/chainlint/inline-comment.test
index 8f26856e77..4fbbf1058a 100644
--- a/t/chainlint/inline-comment.test
+++ b/t/chainlint/inline-comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'inline-comment' '
(
# LINT: swallow inline comment (leaving command intact)
foobar && # comment 1
@@ -10,3 +11,4 @@
# LINT: "#" in string in cuddled subshell not misinterpreted as comment
(cd foo &&
flibble "not a # comment")
+'
diff --git a/t/chainlint/loop-detect-failure.expect b/t/chainlint/loop-detect-failure.expect
index a66025c39d..40c06f0d53 100644
--- a/t/chainlint/loop-detect-failure.expect
+++ b/t/chainlint/loop-detect-failure.expect
@@ -1,15 +1,15 @@
-git init r1 &&
-for n in 1 2 3 4 5
-do
- echo "This is file: $n" > r1/file.$n &&
- git -C r1 add file.$n &&
- git -C r1 commit -m "$n" || return 1
-done &&
-
-git init r2 &&
-for n in 1000 10000
-do
- printf "%"$n"s" X > r2/large.$n &&
- git -C r2 add large.$n &&
- git -C r2 commit -m "$n" ?!LOOP?!
-done
+2 git init r1 &&
+3 for n in 1 2 3 4 5
+4 do
+5 echo "This is file: $n" > r1/file.$n &&
+6 git -C r1 add file.$n &&
+7 git -C r1 commit -m "$n" || return 1
+8 done &&
+9
+10 git init r2 &&
+11 for n in 1000 10000
+12 do
+13 printf "%"$n"s" X > r2/large.$n &&
+14 git -C r2 add large.$n &&
+15 git -C r2 commit -m "$n" ?!LOOP?!
+16 done
diff --git a/t/chainlint/loop-detect-failure.test b/t/chainlint/loop-detect-failure.test
index b9791cc802..44673aa394 100644
--- a/t/chainlint/loop-detect-failure.test
+++ b/t/chainlint/loop-detect-failure.test
@@ -1,3 +1,4 @@
+test_expect_success 'loop-detect-failure' '
git init r1 &&
# LINT: loop handles failure explicitly with "|| return 1"
for n in 1 2 3 4 5
@@ -15,3 +16,4 @@ do
git -C r2 add large.$n &&
git -C r2 commit -m "$n"
done
+'
diff --git a/t/chainlint/loop-detect-status.expect b/t/chainlint/loop-detect-status.expect
index 7ce3a34806..0f180b08de 100644
--- a/t/chainlint/loop-detect-status.expect
+++ b/t/chainlint/loop-detect-status.expect
@@ -1,18 +1,18 @@
-(while test $i -le $blobcount
- do
- printf "Generating blob $i/$blobcount\r" >&2 &&
- printf "blob\nmark :$i\ndata $blobsize\n" &&
- #test-tool genrandom $i $blobsize &&
- printf "%-${blobsize}s" $i &&
- echo "M 100644 :$i $i" >> commit &&
- i=$(($i+1)) ||
- echo $? > exit-status
- done &&
- echo "commit refs/heads/main" &&
- echo "author A U Thor <author@email.com> 123456789 +0000" &&
- echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
- echo "data 5" &&
- echo ">2gb" &&
- cat commit) |
-git fast-import --big-file-threshold=2 &&
-test ! -f exit-status
+2 (while test $i -le $blobcount
+3 do
+4 printf "Generating blob $i/$blobcount\r" >&2 &&
+5 printf "blob\nmark :$i\ndata $blobsize\n" &&
+6 #test-tool genrandom $i $blobsize &&
+7 printf "%-${blobsize}s" $i &&
+8 echo "M 100644 :$i $i" >> commit &&
+9 i=$(($i+1)) ||
+10 echo $? > exit-status
+11 done &&
+12 echo "commit refs/heads/main" &&
+13 echo "author A U Thor <author@email.com> 123456789 +0000" &&
+14 echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
+15 echo "data 5" &&
+16 echo ">2gb" &&
+17 cat commit) |
+18 git fast-import --big-file-threshold=2 &&
+19 test ! -f exit-status
diff --git a/t/chainlint/loop-detect-status.test b/t/chainlint/loop-detect-status.test
index 1c6c23cfc9..8b639be073 100644
--- a/t/chainlint/loop-detect-status.test
+++ b/t/chainlint/loop-detect-status.test
@@ -1,3 +1,4 @@
+test_expect_success 'loop-detect-status' '
# LINT: "$?" handled explicitly within loop body
(while test $i -le $blobcount
do
@@ -17,3 +18,4 @@
cat commit) |
git fast-import --big-file-threshold=2 &&
test ! -f exit-status
+'
diff --git a/t/chainlint/loop-in-if.expect b/t/chainlint/loop-in-if.expect
index 6c5d6e5b24..4e8c67c914 100644
--- a/t/chainlint/loop-in-if.expect
+++ b/t/chainlint/loop-in-if.expect
@@ -1,12 +1,12 @@
-(
- if true
- then
- while true
- do
- echo "pop" ?!AMP?!
- echo "glup" ?!LOOP?!
- done ?!AMP?!
- foo
- fi ?!AMP?!
- bar
-)
+2 (
+3 if true
+4 then
+5 while true
+6 do
+7 echo "pop" ?!AMP?!
+8 echo "glup" ?!LOOP?!
+9 done ?!AMP?!
+10 foo
+11 fi ?!AMP?!
+12 bar
+13 )
diff --git a/t/chainlint/loop-in-if.test b/t/chainlint/loop-in-if.test
index dfcc3f98fb..b0d0d393cf 100644
--- a/t/chainlint/loop-in-if.test
+++ b/t/chainlint/loop-in-if.test
@@ -1,3 +1,4 @@
+test_expect_success 'loop-in-if' '
(
if true
then
@@ -13,3 +14,4 @@
fi
bar
)
+'
diff --git a/t/chainlint/loop-upstream-pipe.expect b/t/chainlint/loop-upstream-pipe.expect
index 0b82ecc4b9..bef82479ca 100644
--- a/t/chainlint/loop-upstream-pipe.expect
+++ b/t/chainlint/loop-upstream-pipe.expect
@@ -1,10 +1,10 @@
-(
- git rev-list --objects --no-object-names base..loose |
- while read oid
- do
- path="$objdir/$(test_oid_to_path "$oid")" &&
- printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" ||
- echo "object list generation failed for $oid"
- done |
- sort -k1
-) >expect &&
+2 (
+3 git rev-list --objects --no-object-names base..loose |
+4 while read oid
+5 do
+6 path="$objdir/$(test_oid_to_path "$oid")" &&
+7 printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" ||
+8 echo "object list generation failed for $oid"
+9 done |
+10 sort -k1
+11 ) >expect &&
diff --git a/t/chainlint/loop-upstream-pipe.test b/t/chainlint/loop-upstream-pipe.test
index efb77da897..8415a4db27 100644
--- a/t/chainlint/loop-upstream-pipe.test
+++ b/t/chainlint/loop-upstream-pipe.test
@@ -1,3 +1,4 @@
+test_expect_success 'loop-upstream-pipe' '
(
git rev-list --objects --no-object-names base..loose |
while read oid
@@ -9,3 +10,4 @@
done |
sort -k1
) >expect &&
+'
diff --git a/t/chainlint/multi-line-nested-command-substitution.expect b/t/chainlint/multi-line-nested-command-substitution.expect
index 300058341b..ad27e43e05 100644
--- a/t/chainlint/multi-line-nested-command-substitution.expect
+++ b/t/chainlint/multi-line-nested-command-substitution.expect
@@ -1,18 +1,18 @@
-(
- foo &&
- x=$(
- echo bar |
- cat
- ) &&
- echo ok
-) |
-sort &&
-(
- bar &&
- x=$(echo bar |
- cat
- ) &&
- y=$(echo baz |
- fip) &&
- echo fail
-)
+2 (
+3 foo &&
+4 x=$(
+5 echo bar |
+6 cat
+7 ) &&
+8 echo ok
+9 ) |
+10 sort &&
+11 (
+12 bar &&
+13 x=$(echo bar |
+14 cat
+15 ) &&
+16 y=$(echo baz |
+17 fip) &&
+18 echo fail
+19 )
diff --git a/t/chainlint/multi-line-nested-command-substitution.test b/t/chainlint/multi-line-nested-command-substitution.test
index 300058341b..e811c63f2b 100644
--- a/t/chainlint/multi-line-nested-command-substitution.test
+++ b/t/chainlint/multi-line-nested-command-substitution.test
@@ -1,3 +1,4 @@
+test_expect_success 'multi-line-nested-command-substitution' '
(
foo &&
x=$(
@@ -16,3 +17,4 @@ sort &&
fip) &&
echo fail
)
+'
diff --git a/t/chainlint/multi-line-string.expect b/t/chainlint/multi-line-string.expect
index 27ff95218e..62c54e3a5e 100644
--- a/t/chainlint/multi-line-string.expect
+++ b/t/chainlint/multi-line-string.expect
@@ -1,14 +1,14 @@
-(
- x="line 1
- line 2
- line 3" &&
- y="line 1
- line2" ?!AMP?!
- foobar
-) &&
-(
- echo "xyz" "abc
- def
- ghi" &&
- barfoo
-)
+2 (
+3 x="line 1
+4 line 2
+5 line 3" &&
+6 y="line 1
+7 line2" ?!AMP?!
+8 foobar
+9 ) &&
+10 (
+11 echo "xyz" "abc
+12 def
+13 ghi" &&
+14 barfoo
+15 )
diff --git a/t/chainlint/multi-line-string.test b/t/chainlint/multi-line-string.test
index 4a0af2107d..7b5048d2ea 100644
--- a/t/chainlint/multi-line-string.test
+++ b/t/chainlint/multi-line-string.test
@@ -1,3 +1,4 @@
+test_expect_success 'multi-line-string' '
(
x="line 1
line 2
@@ -13,3 +14,4 @@
ghi" &&
barfoo
)
+'
diff --git a/t/chainlint/negated-one-liner.expect b/t/chainlint/negated-one-liner.expect
index ad4c2d949e..a6ce52a1da 100644
--- a/t/chainlint/negated-one-liner.expect
+++ b/t/chainlint/negated-one-liner.expect
@@ -1,5 +1,5 @@
-! (foo && bar) &&
-! (foo && bar) >baz &&
-
-! (foo; ?!AMP?! bar) &&
-! (foo; ?!AMP?! bar) >baz
+2 ! (foo && bar) &&
+3 ! (foo && bar) >baz &&
+4
+5 ! (foo; ?!AMP?! bar) &&
+6 ! (foo; ?!AMP?! bar) >baz
diff --git a/t/chainlint/negated-one-liner.test b/t/chainlint/negated-one-liner.test
index c9598e9153..30f4cc5a9b 100644
--- a/t/chainlint/negated-one-liner.test
+++ b/t/chainlint/negated-one-liner.test
@@ -1,3 +1,4 @@
+test_expect_success 'negated-one-liner' '
# LINT: top-level one-liner subshell
! (foo && bar) &&
! (foo && bar) >baz &&
@@ -5,3 +6,4 @@
# LINT: top-level one-liner subshell missing internal "&&"
! (foo; bar) &&
! (foo; bar) >baz
+'
diff --git a/t/chainlint/nested-cuddled-subshell.expect b/t/chainlint/nested-cuddled-subshell.expect
index 3836049cc4..0191c9c294 100644
--- a/t/chainlint/nested-cuddled-subshell.expect
+++ b/t/chainlint/nested-cuddled-subshell.expect
@@ -1,25 +1,25 @@
-(
- (cd foo &&
- bar
- ) &&
-
- (cd foo &&
- bar
- ) ?!AMP?!
-
- (
- cd foo &&
- bar) &&
-
- (
- cd foo &&
- bar) ?!AMP?!
-
- (cd foo &&
- bar) &&
-
- (cd foo &&
- bar) ?!AMP?!
-
- foobar
-)
+2 (
+3 (cd foo &&
+4 bar
+5 ) &&
+6
+7 (cd foo &&
+8 bar
+9 ) ?!AMP?!
+10
+11 (
+12 cd foo &&
+13 bar) &&
+14
+15 (
+16 cd foo &&
+17 bar) ?!AMP?!
+18
+19 (cd foo &&
+20 bar) &&
+21
+22 (cd foo &&
+23 bar) ?!AMP?!
+24
+25 foobar
+26 )
diff --git a/t/chainlint/nested-cuddled-subshell.test b/t/chainlint/nested-cuddled-subshell.test
index 8fd656c7b5..31e92d3be4 100644
--- a/t/chainlint/nested-cuddled-subshell.test
+++ b/t/chainlint/nested-cuddled-subshell.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-cuddled-subshell' '
(
# LINT: opening "(" cuddled with first nested subshell statement
(cd foo &&
@@ -29,3 +30,4 @@
foobar
)
+'
diff --git a/t/chainlint/nested-here-doc.expect b/t/chainlint/nested-here-doc.expect
index 29b3832a98..70d9b68dc9 100644
--- a/t/chainlint/nested-here-doc.expect
+++ b/t/chainlint/nested-here-doc.expect
@@ -1,30 +1,30 @@
-cat <<ARBITRARY >foop &&
-naddle
-fub <<EOF
- nozzle
- noodle
-EOF
-formp
-ARBITRARY
-
-(
- cat <<-\INPUT_END &&
- fish are mice
- but geese go slow
- data <<EOF
- perl is lerp
- and nothing else
- EOF
- toink
- INPUT_END
-
- cat <<-\EOT ?!AMP?!
- text goes here
- data <<EOF
- data goes here
- EOF
- more test here
- EOT
-
- foobar
-)
+2 cat <<ARBITRARY >foop &&
+3 naddle
+4 fub <<EOF
+5 nozzle
+6 noodle
+7 EOF
+8 formp
+9 ARBITRARY
+10
+11 (
+12 cat <<-\INPUT_END &&
+13 fish are mice
+14 but geese go slow
+15 data <<EOF
+16 perl is lerp
+17 and nothing else
+18 EOF
+19 toink
+20 INPUT_END
+21
+22 cat <<-\EOT ?!AMP?!
+23 text goes here
+24 data <<EOF
+25 data goes here
+26 EOF
+27 more test here
+28 EOT
+29
+30 foobar
+31 )
diff --git a/t/chainlint/nested-here-doc.test b/t/chainlint/nested-here-doc.test
index f35404bf0f..9505c47a34 100644
--- a/t/chainlint/nested-here-doc.test
+++ b/t/chainlint/nested-here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-here-doc' '
# LINT: inner "EOF" not misintrepreted as closing ARBITRARY here-doc
cat <<ARBITRARY >foop &&
naddle
@@ -31,3 +32,4 @@ ARBITRARY
foobar
)
+'
diff --git a/t/chainlint/nested-loop-detect-failure.expect b/t/chainlint/nested-loop-detect-failure.expect
index 3461df40e5..c13c4d2f90 100644
--- a/t/chainlint/nested-loop-detect-failure.expect
+++ b/t/chainlint/nested-loop-detect-failure.expect
@@ -1,31 +1,31 @@
-for i in 0 1 2 3 4 5 6 7 8 9;
-do
- for j in 0 1 2 3 4 5 6 7 8 9;
- do
- echo "$i$j" >"path$i$j" ?!LOOP?!
- done ?!LOOP?!
-done &&
-
-for i in 0 1 2 3 4 5 6 7 8 9;
-do
- for j in 0 1 2 3 4 5 6 7 8 9;
- do
- echo "$i$j" >"path$i$j" || return 1
- done
-done &&
-
-for i in 0 1 2 3 4 5 6 7 8 9;
-do
- for j in 0 1 2 3 4 5 6 7 8 9;
- do
- echo "$i$j" >"path$i$j" ?!LOOP?!
- done || return 1
-done &&
-
-for i in 0 1 2 3 4 5 6 7 8 9;
-do
- for j in 0 1 2 3 4 5 6 7 8 9;
- do
- echo "$i$j" >"path$i$j" || return 1
- done || return 1
-done
+2 for i in 0 1 2 3 4 5 6 7 8 9;
+3 do
+4 for j in 0 1 2 3 4 5 6 7 8 9;
+5 do
+6 echo "$i$j" >"path$i$j" ?!LOOP?!
+7 done ?!LOOP?!
+8 done &&
+9
+10 for i in 0 1 2 3 4 5 6 7 8 9;
+11 do
+12 for j in 0 1 2 3 4 5 6 7 8 9;
+13 do
+14 echo "$i$j" >"path$i$j" || return 1
+15 done
+16 done &&
+17
+18 for i in 0 1 2 3 4 5 6 7 8 9;
+19 do
+20 for j in 0 1 2 3 4 5 6 7 8 9;
+21 do
+22 echo "$i$j" >"path$i$j" ?!LOOP?!
+23 done || return 1
+24 done &&
+25
+26 for i in 0 1 2 3 4 5 6 7 8 9;
+27 do
+28 for j in 0 1 2 3 4 5 6 7 8 9;
+29 do
+30 echo "$i$j" >"path$i$j" || return 1
+31 done || return 1
+32 done
diff --git a/t/chainlint/nested-loop-detect-failure.test b/t/chainlint/nested-loop-detect-failure.test
index e6f0c1acfb..3d4b657412 100644
--- a/t/chainlint/nested-loop-detect-failure.test
+++ b/t/chainlint/nested-loop-detect-failure.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-loop-detect-failure' '
# LINT: neither loop handles failure explicitly with "|| return 1"
for i in 0 1 2 3 4 5 6 7 8 9;
do
@@ -33,3 +34,4 @@ do
echo "$i$j" >"path$i$j" || return 1
done || return 1
done
+'
diff --git a/t/chainlint/nested-subshell-comment.expect b/t/chainlint/nested-subshell-comment.expect
index 9138cf386d..f89a8d03a8 100644
--- a/t/chainlint/nested-subshell-comment.expect
+++ b/t/chainlint/nested-subshell-comment.expect
@@ -1,11 +1,11 @@
-(
- foo &&
- (
- bar &&
- # bottles wobble while fiddles gobble
- # minor numbers of cows (or do they?)
- baz &&
- snaff
- ) ?!AMP?!
- fuzzy
-)
+2 (
+3 foo &&
+4 (
+5 bar &&
+6 # bottles wobble while fiddles gobble
+7 # minor numbers of cows (or do they?)
+8 baz &&
+9 snaff
+10 ) ?!AMP?!
+11 fuzzy
+12 )
diff --git a/t/chainlint/nested-subshell-comment.test b/t/chainlint/nested-subshell-comment.test
index 0215cdb192..b430580ce0 100644
--- a/t/chainlint/nested-subshell-comment.test
+++ b/t/chainlint/nested-subshell-comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-subshell-comment' '
(
foo &&
(
@@ -11,3 +12,4 @@
)
fuzzy
)
+'
diff --git a/t/chainlint/nested-subshell.expect b/t/chainlint/nested-subshell.expect
index 73ff28546a..811e8a7912 100644
--- a/t/chainlint/nested-subshell.expect
+++ b/t/chainlint/nested-subshell.expect
@@ -1,13 +1,13 @@
-(
- cd foo &&
- (
- echo a &&
- echo b
- ) >file &&
-
- cd foo &&
- (
- echo a ?!AMP?!
- echo b
- ) >file
-)
+2 (
+3 cd foo &&
+4 (
+5 echo a &&
+6 echo b
+7 ) >file &&
+8
+9 cd foo &&
+10 (
+11 echo a ?!AMP?!
+12 echo b
+13 ) >file
+14 )
diff --git a/t/chainlint/nested-subshell.test b/t/chainlint/nested-subshell.test
index 440ee9992d..c31da34b73 100644
--- a/t/chainlint/nested-subshell.test
+++ b/t/chainlint/nested-subshell.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-subshell' '
(
cd foo &&
(
@@ -11,3 +12,4 @@
echo b
) >file
)
+'
diff --git a/t/chainlint/not-heredoc.expect b/t/chainlint/not-heredoc.expect
index 2e9bb135fe..611b7b75cb 100644
--- a/t/chainlint/not-heredoc.expect
+++ b/t/chainlint/not-heredoc.expect
@@ -1,14 +1,14 @@
-echo "<<<<<<< ours" &&
-echo ourside &&
-echo "=======" &&
-echo theirside &&
-echo ">>>>>>> theirs" &&
-
-(
- echo "<<<<<<< ours" &&
- echo ourside &&
- echo "=======" &&
- echo theirside &&
- echo ">>>>>>> theirs" ?!AMP?!
- poodle
-) >merged
+2 echo "<<<<<<< ours" &&
+3 echo ourside &&
+4 echo "=======" &&
+5 echo theirside &&
+6 echo ">>>>>>> theirs" &&
+7
+8 (
+9 echo "<<<<<<< ours" &&
+10 echo ourside &&
+11 echo "=======" &&
+12 echo theirside &&
+13 echo ">>>>>>> theirs" ?!AMP?!
+14 poodle
+15 ) >merged
diff --git a/t/chainlint/not-heredoc.test b/t/chainlint/not-heredoc.test
index 9aa57346cd..09711e45e0 100644
--- a/t/chainlint/not-heredoc.test
+++ b/t/chainlint/not-heredoc.test
@@ -1,3 +1,4 @@
+test_expect_success 'not-heredoc' '
# LINT: "<< ours" inside string is not here-doc
echo "<<<<<<< ours" &&
echo ourside &&
@@ -14,3 +15,4 @@ echo ">>>>>>> theirs" &&
echo ">>>>>>> theirs"
poodle
) >merged
+'
diff --git a/t/chainlint/one-liner-for-loop.expect b/t/chainlint/one-liner-for-loop.expect
index 51a3dc7c54..49dcf065ef 100644
--- a/t/chainlint/one-liner-for-loop.expect
+++ b/t/chainlint/one-liner-for-loop.expect
@@ -1,9 +1,9 @@
-git init dir-rename-and-content &&
-(
- cd dir-rename-and-content &&
- test_write_lines 1 2 3 4 5 >foo &&
- mkdir olddir &&
- for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?!
- git add foo olddir &&
- git commit -m "original" &&
-)
+2 git init dir-rename-and-content &&
+3 (
+4 cd dir-rename-and-content &&
+5 test_write_lines 1 2 3 4 5 >foo &&
+6 mkdir olddir &&
+7 for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?!
+8 git add foo olddir &&
+9 git commit -m "original" &&
+10 )
diff --git a/t/chainlint/one-liner-for-loop.test b/t/chainlint/one-liner-for-loop.test
index 4bd8c066c7..00afd7ef76 100644
--- a/t/chainlint/one-liner-for-loop.test
+++ b/t/chainlint/one-liner-for-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'one-liner-for-loop' '
git init dir-rename-and-content &&
(
cd dir-rename-and-content &&
@@ -8,3 +9,4 @@ git init dir-rename-and-content &&
git add foo olddir &&
git commit -m "original" &&
)
+'
diff --git a/t/chainlint/one-liner.expect b/t/chainlint/one-liner.expect
index 57a7a444c1..9861811283 100644
--- a/t/chainlint/one-liner.expect
+++ b/t/chainlint/one-liner.expect
@@ -1,9 +1,9 @@
-(foo && bar) &&
-(foo && bar) |
-(foo && bar) >baz &&
-
-(foo; ?!AMP?! bar) &&
-(foo; ?!AMP?! bar) |
-(foo; ?!AMP?! bar) >baz &&
-
-(foo "bar; baz")
+2 (foo && bar) &&
+3 (foo && bar) |
+4 (foo && bar) >baz &&
+5
+6 (foo; ?!AMP?! bar) &&
+7 (foo; ?!AMP?! bar) |
+8 (foo; ?!AMP?! bar) >baz &&
+9
+10 (foo "bar; baz")
diff --git a/t/chainlint/one-liner.test b/t/chainlint/one-liner.test
index be9858fa29..6e42ee1b5e 100644
--- a/t/chainlint/one-liner.test
+++ b/t/chainlint/one-liner.test
@@ -1,3 +1,4 @@
+test_expect_success 'one-liner' '
# LINT: top-level one-liner subshell
(foo && bar) &&
(foo && bar) |
@@ -10,3 +11,4 @@
# LINT: ";" in string not misinterpreted as broken &&-chain
(foo "bar; baz")
+'
diff --git a/t/chainlint/p4-filespec.expect b/t/chainlint/p4-filespec.expect
index 1290fd1ff2..cff3e4e3d1 100644
--- a/t/chainlint/p4-filespec.expect
+++ b/t/chainlint/p4-filespec.expect
@@ -1,4 +1,4 @@
-(
- p4 print -1 //depot/fiddle#42 >file &&
- foobar
-)
+2 (
+3 p4 print -1 //depot/fiddle#42 >file &&
+4 foobar
+5 )
diff --git a/t/chainlint/p4-filespec.test b/t/chainlint/p4-filespec.test
index 4fd2d6e2b8..8ba6b911dc 100644
--- a/t/chainlint/p4-filespec.test
+++ b/t/chainlint/p4-filespec.test
@@ -1,5 +1,7 @@
+test_expect_success 'p4-filespec' '
(
# LINT: Perforce revspec in filespec not misinterpreted as in-line comment
p4 print -1 //depot/fiddle#42 >file &&
foobar
)
+'
diff --git a/t/chainlint/pipe.expect b/t/chainlint/pipe.expect
index 811971b1a3..1bbe5a2ce1 100644
--- a/t/chainlint/pipe.expect
+++ b/t/chainlint/pipe.expect
@@ -1,10 +1,10 @@
-(
- foo |
- bar |
- baz &&
-
- fish |
- cow ?!AMP?!
-
- sunder
-)
+2 (
+3 foo |
+4 bar |
+5 baz &&
+6
+7 fish |
+8 cow ?!AMP?!
+9
+10 sunder
+11 )
diff --git a/t/chainlint/pipe.test b/t/chainlint/pipe.test
index dd82534c66..1af81c243b 100644
--- a/t/chainlint/pipe.test
+++ b/t/chainlint/pipe.test
@@ -1,3 +1,4 @@
+test_expect_success 'pipe' '
(
# LINT: no "&&" needed on line ending with "|"
foo |
@@ -10,3 +11,4 @@
sunder
)
+'
diff --git a/t/chainlint/return-loop.expect b/t/chainlint/return-loop.expect
index cfc0549bef..da8f9abea3 100644
--- a/t/chainlint/return-loop.expect
+++ b/t/chainlint/return-loop.expect
@@ -1,5 +1,5 @@
-while test $i -lt $((num - 5))
-do
- git notes add -m "notes for commit$i" HEAD~$i || return 1
- i=$((i + 1))
-done
+2 while test $i -lt $((num - 5))
+3 do
+4 git notes add -m "notes for commit$i" HEAD~$i || return 1
+5 i=$((i + 1))
+6 done
diff --git a/t/chainlint/return-loop.test b/t/chainlint/return-loop.test
index f90b171300..ea76c3593a 100644
--- a/t/chainlint/return-loop.test
+++ b/t/chainlint/return-loop.test
@@ -1,6 +1,8 @@
+test_expect_success 'return-loop' '
while test $i -lt $((num - 5))
do
# LINT: "|| return {n}" valid loop escape outside subshell; no "&&" needed
git notes add -m "notes for commit$i" HEAD~$i || return 1
i=$((i + 1))
done
+'
diff --git a/t/chainlint/semicolon.expect b/t/chainlint/semicolon.expect
index 3aa2259f36..866438310c 100644
--- a/t/chainlint/semicolon.expect
+++ b/t/chainlint/semicolon.expect
@@ -1,19 +1,19 @@
-(
- cat foo ; ?!AMP?! echo bar ?!AMP?!
- cat foo ; ?!AMP?! echo bar
-) &&
-(
- cat foo ; ?!AMP?! echo bar &&
- cat foo ; ?!AMP?! echo bar
-) &&
-(
- echo "foo; bar" &&
- cat foo; ?!AMP?! echo bar
-) &&
-(
- foo;
-) &&
-(cd foo &&
- for i in a b c; do
- echo; ?!LOOP?!
- done)
+2 (
+3 cat foo ; ?!AMP?! echo bar ?!AMP?!
+4 cat foo ; ?!AMP?! echo bar
+5 ) &&
+6 (
+7 cat foo ; ?!AMP?! echo bar &&
+8 cat foo ; ?!AMP?! echo bar
+9 ) &&
+10 (
+11 echo "foo; bar" &&
+12 cat foo; ?!AMP?! echo bar
+13 ) &&
+14 (
+15 foo;
+16 ) &&
+17 (cd foo &&
+18 for i in a b c; do
+19 echo; ?!LOOP?!
+20 done)
diff --git a/t/chainlint/semicolon.test b/t/chainlint/semicolon.test
index 67e1192c50..fc0ba1b539 100644
--- a/t/chainlint/semicolon.test
+++ b/t/chainlint/semicolon.test
@@ -1,3 +1,4 @@
+test_expect_success 'semicolon' '
(
# LINT: missing internal "&&" and ending "&&"
cat foo ; echo bar
@@ -23,3 +24,4 @@
# LINT: semicolon unnecessary but legitimate
echo;
done)
+'
diff --git a/t/chainlint/sqstring-in-sqstring.expect b/t/chainlint/sqstring-in-sqstring.expect
index cf0b591cf7..ba5d3c3a6d 100644
--- a/t/chainlint/sqstring-in-sqstring.expect
+++ b/t/chainlint/sqstring-in-sqstring.expect
@@ -1,4 +1,4 @@
-perl -e '
- defined($_ = -s $_) or die for @ARGV;
- exit 1 if $ARGV[0] <= $ARGV[1];
-' test-2-$packname_2.pack test-3-$packname_3.pack
+2 perl -e '
+3 defined($_ = -s $_) or die for @ARGV;
+4 exit 1 if $ARGV[0] <= $ARGV[1];
+5 ' test-2-$packname_2.pack test-3-$packname_3.pack
diff --git a/t/chainlint/sqstring-in-sqstring.test b/t/chainlint/sqstring-in-sqstring.test
index 77a425e0c7..24169724a5 100644
--- a/t/chainlint/sqstring-in-sqstring.test
+++ b/t/chainlint/sqstring-in-sqstring.test
@@ -1,5 +1,7 @@
+test_expect_success 'sqstring-in-sqstring' '
# LINT: SQ-string Perl code fragment within SQ-string
perl -e '\''
defined($_ = -s $_) or die for @ARGV;
exit 1 if $ARGV[0] <= $ARGV[1];
'\'' test-2-$packname_2.pack test-3-$packname_3.pack
+'
diff --git a/t/chainlint/subshell-here-doc.expect b/t/chainlint/subshell-here-doc.expect
index 75d6f607e2..5647500c82 100644
--- a/t/chainlint/subshell-here-doc.expect
+++ b/t/chainlint/subshell-here-doc.expect
@@ -1,30 +1,30 @@
-(
- echo wobba \
- gorgo snoot \
- wafta snurb <<-EOF &&
- quoth the raven,
- nevermore...
- EOF
-
- cat <<EOF >bip ?!AMP?!
- fish fly high
-EOF
-
- echo <<-\EOF >bop
- gomez
- morticia
- wednesday
- pugsly
- EOF
-) &&
-(
- cat <<-\ARBITRARY >bup &&
- glink
- FIZZ
- ARBITRARY
- cat <<-"ARBITRARY3" >bup3 &&
- glink
- FIZZ
- ARBITRARY3
- meep
-)
+2 (
+3 echo wobba \
+4 gorgo snoot \
+5 wafta snurb <<-EOF &&
+6 quoth the raven,
+7 nevermore...
+8 EOF
+9
+10 cat <<EOF >bip ?!AMP?!
+11 fish fly high
+12 EOF
+13
+14 echo <<-\EOF >bop
+15 gomez
+16 morticia
+17 wednesday
+18 pugsly
+19 EOF
+20 ) &&
+21 (
+22 cat <<-\ARBITRARY >bup &&
+23 glink
+24 FIZZ
+25 ARBITRARY
+26 cat <<-"ARBITRARY3" >bup3 &&
+27 glink
+28 FIZZ
+29 ARBITRARY3
+30 meep
+31 )
diff --git a/t/chainlint/subshell-here-doc.test b/t/chainlint/subshell-here-doc.test
index d40eb65583..4a38f47f01 100644
--- a/t/chainlint/subshell-here-doc.test
+++ b/t/chainlint/subshell-here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'subshell-here-doc' '
(
# LINT: stitch together incomplete \-ending lines
# LINT: swallow here-doc to avoid false positives in content
@@ -33,3 +34,4 @@ EOF
ARBITRARY3
meep
)
+'
diff --git a/t/chainlint/subshell-one-liner.expect b/t/chainlint/subshell-one-liner.expect
index 8f694990e8..214316c6a0 100644
--- a/t/chainlint/subshell-one-liner.expect
+++ b/t/chainlint/subshell-one-liner.expect
@@ -1,19 +1,19 @@
-(
- (foo && bar) &&
- (foo && bar) |
- (foo && bar) >baz &&
-
- (foo; ?!AMP?! bar) &&
- (foo; ?!AMP?! bar) |
- (foo; ?!AMP?! bar) >baz &&
-
- (foo || exit 1) &&
- (foo || exit 1) |
- (foo || exit 1) >baz &&
-
- (foo && bar) ?!AMP?!
-
- (foo && bar; ?!AMP?! baz) ?!AMP?!
-
- foobar
-)
+2 (
+3 (foo && bar) &&
+4 (foo && bar) |
+5 (foo && bar) >baz &&
+6
+7 (foo; ?!AMP?! bar) &&
+8 (foo; ?!AMP?! bar) |
+9 (foo; ?!AMP?! bar) >baz &&
+10
+11 (foo || exit 1) &&
+12 (foo || exit 1) |
+13 (foo || exit 1) >baz &&
+14
+15 (foo && bar) ?!AMP?!
+16
+17 (foo && bar; ?!AMP?! baz) ?!AMP?!
+18
+19 foobar
+20 )
diff --git a/t/chainlint/subshell-one-liner.test b/t/chainlint/subshell-one-liner.test
index 37fa643c20..dac536afcc 100644
--- a/t/chainlint/subshell-one-liner.test
+++ b/t/chainlint/subshell-one-liner.test
@@ -1,3 +1,4 @@
+test_expect_success 'subshell-one-liner' '
(
# LINT: nested one-liner subshell
(foo && bar) &&
@@ -22,3 +23,4 @@
foobar
)
+'
diff --git a/t/chainlint/t7900-subtree.expect b/t/chainlint/t7900-subtree.expect
index 02f3129232..9e60338bcf 100644
--- a/t/chainlint/t7900-subtree.expect
+++ b/t/chainlint/t7900-subtree.expect
@@ -1,22 +1,22 @@
-(
- chks="sub1
-sub2
-sub3
-sub4" &&
- chks_sub=$(cat <<TXT | sed "s,^,sub dir/,"
-$chks
-TXT
-) &&
- chkms="main-sub1
-main-sub2
-main-sub3
-main-sub4" &&
- chkms_sub=$(cat <<TXT | sed "s,^,sub dir/,"
-$chkms
-TXT
-) &&
-
- subfiles=$(git ls-files) &&
- check_equal "$subfiles" "$chkms
-$chks"
-)
+2 (
+3 chks="sub1
+4 sub2
+5 sub3
+6 sub4" &&
+7 chks_sub=$(cat <<TXT | sed "s,^,sub dir/,"
+8 $chks
+9 TXT
+10 ) &&
+11 chkms="main-sub1
+12 main-sub2
+13 main-sub3
+14 main-sub4" &&
+15 chkms_sub=$(cat <<TXT | sed "s,^,sub dir/,"
+16 $chkms
+17 TXT
+18 ) &&
+19
+20 subfiles=$(git ls-files) &&
+21 check_equal "$subfiles" "$chkms
+22 $chks"
+23 )
diff --git a/t/chainlint/t7900-subtree.test b/t/chainlint/t7900-subtree.test
index 02f3129232..1f4f03300f 100644
--- a/t/chainlint/t7900-subtree.test
+++ b/t/chainlint/t7900-subtree.test
@@ -1,3 +1,4 @@
+test_expect_success 't7900-subtree' '
(
chks="sub1
sub2
@@ -20,3 +21,4 @@ TXT
check_equal "$subfiles" "$chkms
$chks"
)
+'
diff --git a/t/chainlint/token-pasting.expect b/t/chainlint/token-pasting.expect
index 6a387917a7..64f3235d26 100644
--- a/t/chainlint/token-pasting.expect
+++ b/t/chainlint/token-pasting.expect
@@ -1,27 +1,27 @@
-git config filter.rot13.smudge ./rot13.sh &&
-git config filter.rot13.clean ./rot13.sh &&
-
-{
- echo "*.t filter=rot13" ?!AMP?!
- echo "*.i ident"
-} >.gitattributes &&
-
-{
- echo a b c d e f g h i j k l m ?!AMP?!
- echo n o p q r s t u v w x y z ?!AMP?!
- echo '$Id$'
-} >test &&
-cat test >test.t &&
-cat test >test.o &&
-cat test >test.i &&
-git add test test.t test.i &&
-rm -f test test.t test.i &&
-git checkout -- test test.t test.i &&
-
-echo "content-test2" >test2.o &&
-echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!AMP?!
-
-downstream_url_for_sed=$(
- printf "%sn" "$downstream_url" |
- sed -e 's/\/\\/g' -e 's/[[/.*^$]/\&/g'
-)
+2 git config filter.rot13.smudge ./rot13.sh &&
+3 git config filter.rot13.clean ./rot13.sh &&
+4
+5 {
+6 echo "*.t filter=rot13" ?!AMP?!
+7 echo "*.i ident"
+8 } >.gitattributes &&
+9
+10 {
+11 echo a b c d e f g h i j k l m ?!AMP?!
+12 echo n o p q r s t u v w x y z ?!AMP?!
+13 echo '$Id$'
+14 } >test &&
+15 cat test >test.t &&
+16 cat test >test.o &&
+17 cat test >test.i &&
+18 git add test test.t test.i &&
+19 rm -f test test.t test.i &&
+20 git checkout -- test test.t test.i &&
+21
+22 echo "content-test2" >test2.o &&
+23 echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!AMP?!
+24
+25 downstream_url_for_sed=$(
+26 printf "%sn" "$downstream_url" |
+27 sed -e 's/\/\\/g' -e 's/[[/.*^$]/\&/g'
+28 )
diff --git a/t/chainlint/token-pasting.test b/t/chainlint/token-pasting.test
index b4610ce815..590914b733 100644
--- a/t/chainlint/token-pasting.test
+++ b/t/chainlint/token-pasting.test
@@ -1,3 +1,4 @@
+test_expect_success 'token-pasting' '
# LINT: single token; composite of multiple strings
git config filter.rot13.smudge ./rot13.sh &&
git config filter.rot13.clean ./rot13.sh &&
@@ -30,3 +31,4 @@ downstream_url_for_sed=$(
# LINT: exit/enter string context; "&" inside string not command terminator
sed -e '\''s/\\/\\\\/g'\'' -e '\''s/[[/.*^$]/\\&/g'\''
)
+'
diff --git a/t/chainlint/unclosed-here-doc-indent.expect b/t/chainlint/unclosed-here-doc-indent.expect
index 7c30a1a024..f78e23cb63 100644
--- a/t/chainlint/unclosed-here-doc-indent.expect
+++ b/t/chainlint/unclosed-here-doc-indent.expect
@@ -1,4 +1,4 @@
-command_which_is_run &&
-cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! &&
-we forget to end the here-doc
-command_which_is_gobbled
+2 command_which_is_run &&
+3 cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! &&
+4 we forget to end the here-doc
+5 command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc-indent.test b/t/chainlint/unclosed-here-doc-indent.test
index 5c841a9dfd..7ac9d0f7d7 100644
--- a/t/chainlint/unclosed-here-doc-indent.test
+++ b/t/chainlint/unclosed-here-doc-indent.test
@@ -1,4 +1,6 @@
+test_expect_success 'unclosed-here-doc-indent' '
command_which_is_run &&
cat >expect <<-\EOF &&
we forget to end the here-doc
command_which_is_gobbled
+'
diff --git a/t/chainlint/unclosed-here-doc.expect b/t/chainlint/unclosed-here-doc.expect
index d65e50f78d..51304672cf 100644
--- a/t/chainlint/unclosed-here-doc.expect
+++ b/t/chainlint/unclosed-here-doc.expect
@@ -1,7 +1,7 @@
-command_which_is_run &&
-cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! &&
- we try to end the here-doc below,
- but the indentation throws us off
- since the operator is not "<<-".
- EOF
-command_which_is_gobbled
+2 command_which_is_run &&
+3 cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! &&
+4 we try to end the here-doc below,
+5 but the indentation throws us off
+6 since the operator is not "<<-".
+7 EOF
+8 command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc.test b/t/chainlint/unclosed-here-doc.test
index 69d3786c34..68e78f06f3 100644
--- a/t/chainlint/unclosed-here-doc.test
+++ b/t/chainlint/unclosed-here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'unclosed-here-doc' '
command_which_is_run &&
cat >expect <<\EOF &&
we try to end the here-doc below,
@@ -5,3 +6,4 @@ cat >expect <<\EOF &&
since the operator is not "<<-".
EOF
command_which_is_gobbled
+'
diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect
index 06c1567f48..5ffabd5a93 100644
--- a/t/chainlint/while-loop.expect
+++ b/t/chainlint/while-loop.expect
@@ -1,14 +1,14 @@
-(
- while true
- do
- echo foo ?!AMP?!
- cat <<-\EOF ?!LOOP?!
- bar
- EOF
- done ?!AMP?!
-
- while true; do
- echo foo &&
- cat bar ?!LOOP?!
- done
-)
+2 (
+3 while true
+4 do
+5 echo foo ?!AMP?!
+6 cat <<-\EOF ?!LOOP?!
+7 bar
+8 EOF
+9 done ?!AMP?!
+10
+11 while true; do
+12 echo foo &&
+13 cat bar ?!LOOP?!
+14 done
+15 )
diff --git a/t/chainlint/while-loop.test b/t/chainlint/while-loop.test
index d09fb016e4..33a201906a 100644
--- a/t/chainlint/while-loop.test
+++ b/t/chainlint/while-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'while-loop' '
(
# LINT: "while", "do", "done" do not need "&&"
while true
@@ -17,3 +18,4 @@
cat bar
done
)
+'
diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl
index b2b28c2ced..6ee7700eb4 100755
--- a/t/check-non-portable-shell.pl
+++ b/t/check-non-portable-shell.pl
@@ -49,8 +49,8 @@ while (<>) {
/\bexport\s+[A-Za-z0-9_]*=/ and err '"export FOO=bar" is not portable (use FOO=bar && export FOO)';
/\blocal\s+[A-Za-z0-9_]*=\$([A-Za-z0-9_{]|[(][^(])/ and
err q(quote "$val" in 'local var=$val');
- /^\s*([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and exists($func{$4}) and
- err '"FOO=bar shell_func" assignment extends beyond "shell_func"';
+ /\b([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and !/test_env.+=/ and exists($func{$4}) and
+ err '"FOO=bar shell_func" is not portable (use test_env FOO=bar shell_func)';
$line = '';
# this resets our $. for each file
close ARGV if eof;
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index f7f9b62002..97541daf71 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -51,6 +51,7 @@ static void get_bloom_filter_for_commit(const struct object_id *commit_oid)
static const char *bloom_usage = "\n"
" test-tool bloom get_murmur3 <string>\n"
+" test-tool bloom get_murmur3_seven_highbit\n"
" test-tool bloom generate_filter <string> [<string>...]\n"
" test-tool bloom get_filter_for_commit <commit-hex>\n";
@@ -65,7 +66,13 @@ int cmd__bloom(int argc, const char **argv)
uint32_t hashed;
if (argc < 3)
usage(bloom_usage);
- hashed = murmur3_seeded(0, argv[2], strlen(argv[2]));
+ hashed = murmur3_seeded_v2(0, argv[2], strlen(argv[2]));
+ printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
+ }
+
+ if (!strcmp(argv[1], "get_murmur3_seven_highbit")) {
+ uint32_t hashed;
+ hashed = murmur3_seeded_v2(0, "\x99\xaa\xbb\xcc\xdd\xee\xff", 7);
printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
}
diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c
index ed52eb76bf..a288069b04 100644
--- a/t/helper/test-json-writer.c
+++ b/t/helper/test-json-writer.c
@@ -415,6 +415,7 @@ static void get_i(struct line *line, intmax_t *s_in)
get_s(line, &s);
+ errno = 0;
*s_in = strtol(s, &endptr, 10);
if (*endptr || errno == ERANGE)
die("line[%d]: invalid integer value", line->nr);
@@ -427,6 +428,7 @@ static void get_d(struct line *line, double *s_in)
get_s(line, &s);
+ errno = 0;
*s_in = strtod(s, &endptr);
if (*endptr || errno == ERANGE)
die("line[%d]: invalid float value", line->nr);
diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c
deleted file mode 100644
index c03cfa5ecf..0000000000
--- a/t/helper/test-oidmap.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#define USE_THE_REPOSITORY_VARIABLE
-
-#include "test-tool.h"
-#include "hex.h"
-#include "object-name.h"
-#include "oidmap.h"
-#include "repository.h"
-#include "setup.h"
-#include "strbuf.h"
-#include "string-list.h"
-
-/* key is an oid and value is a name (could be a refname for example) */
-struct test_entry {
- struct oidmap_entry entry;
- char name[FLEX_ARRAY];
-};
-
-#define DELIM " \t\r\n"
-
-/*
- * Read stdin line by line and print result of commands to stdout:
- *
- * hash oidkey -> sha1hash(oidkey)
- * put oidkey namevalue -> NULL / old namevalue
- * get oidkey -> NULL / namevalue
- * remove oidkey -> NULL / old namevalue
- * iterate -> oidkey1 namevalue1\noidkey2 namevalue2\n...
- *
- */
-int cmd__oidmap(int argc UNUSED, const char **argv UNUSED)
-{
- struct string_list parts = STRING_LIST_INIT_NODUP;
- struct strbuf line = STRBUF_INIT;
- struct oidmap map = OIDMAP_INIT;
-
- setup_git_directory();
-
- /* init oidmap */
- oidmap_init(&map, 0);
-
- /* process commands from stdin */
- while (strbuf_getline(&line, stdin) != EOF) {
- char *cmd, *p1, *p2;
- struct test_entry *entry;
- struct object_id oid;
-
- /* break line into command and up to two parameters */
- string_list_setlen(&parts, 0);
- string_list_split_in_place(&parts, line.buf, DELIM, 2);
- string_list_remove_empty_items(&parts, 0);
-
- /* ignore empty lines */
- if (!parts.nr)
- continue;
- if (!*parts.items[0].string || *parts.items[0].string == '#')
- continue;
-
- cmd = parts.items[0].string;
- p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
- p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
-
- if (!strcmp("put", cmd) && p1 && p2) {
-
- if (repo_get_oid(the_repository, p1, &oid)) {
- printf("Unknown oid: %s\n", p1);
- continue;
- }
-
- /* create entry with oid_key = p1, name_value = p2 */
- FLEX_ALLOC_STR(entry, name, p2);
- oidcpy(&entry->entry.oid, &oid);
-
- /* add / replace entry */
- entry = oidmap_put(&map, entry);
-
- /* print and free replaced entry, if any */
- puts(entry ? entry->name : "NULL");
- free(entry);
-
- } else if (!strcmp("get", cmd) && p1) {
-
- if (repo_get_oid(the_repository, p1, &oid)) {
- printf("Unknown oid: %s\n", p1);
- continue;
- }
-
- /* lookup entry in oidmap */
- entry = oidmap_get(&map, &oid);
-
- /* print result */
- puts(entry ? entry->name : "NULL");
-
- } else if (!strcmp("remove", cmd) && p1) {
-
- if (repo_get_oid(the_repository, p1, &oid)) {
- printf("Unknown oid: %s\n", p1);
- continue;
- }
-
- /* remove entry from oidmap */
- entry = oidmap_remove(&map, &oid);
-
- /* print result and free entry*/
- puts(entry ? entry->name : "NULL");
- free(entry);
-
- } else if (!strcmp("iterate", cmd)) {
-
- struct oidmap_iter iter;
- oidmap_iter_init(&map, &iter);
- while ((entry = oidmap_iter_next(&iter)))
- printf("%s %s\n", oid_to_hex(&entry->entry.oid), entry->name);
-
- } else {
-
- printf("Unknown command %s\n", cmd);
-
- }
- }
-
- string_list_clear(&parts, 0);
- strbuf_release(&line);
- oidmap_free(&map, 1);
- return 0;
-}
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index ded8116cc5..5250913d99 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -207,6 +207,7 @@ int cmd__parse_options(int argc, const char **argv)
expect.strdup_strings = 1;
string_list_clear(&expect, 0);
string_list_clear(&list, 0);
+ free(file);
return ret;
}
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index d9e980d04c..9018c9f541 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -7,20 +7,8 @@
#include "bloom.h"
#include "setup.h"
-int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
+static void dump_graph_info(struct commit_graph *graph)
{
- struct commit_graph *graph = NULL;
- struct object_directory *odb;
-
- setup_git_directory();
- odb = the_repository->objects->odb;
-
- prepare_repo_settings(the_repository);
-
- graph = read_commit_graph_one(the_repository, odb);
- if (!graph)
- return 1;
-
printf("header: %08x %d %d %d %d\n",
ntohl(*(uint32_t*)graph->data),
*(unsigned char*)(graph->data + 4),
@@ -59,8 +47,57 @@ int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
if (graph->topo_levels)
printf(" topo_levels");
printf("\n");
+}
+
+static void dump_graph_bloom_filters(struct commit_graph *graph)
+{
+ uint32_t i;
+
+ for (i = 0; i < graph->num_commits + graph->num_commits_in_base; i++) {
+ struct bloom_filter filter = { 0 };
+ size_t j;
+
+ if (load_bloom_filter_from_graph(graph, &filter, i) < 0) {
+ fprintf(stderr, "missing Bloom filter for graph "
+ "position %"PRIu32"\n", i);
+ continue;
+ }
+
+ for (j = 0; j < filter.len; j++)
+ printf("%02x", filter.data[j]);
+ if (filter.len)
+ printf("\n");
+ }
+}
+
+int cmd__read_graph(int argc, const char **argv)
+{
+ struct commit_graph *graph = NULL;
+ struct object_directory *odb;
+ int ret = 0;
+
+ setup_git_directory();
+ odb = the_repository->objects->odb;
+
+ prepare_repo_settings(the_repository);
+
+ graph = read_commit_graph_one(the_repository, odb);
+ if (!graph) {
+ ret = 1;
+ goto done;
+ }
+
+ if (argc <= 1)
+ dump_graph_info(graph);
+ else if (!strcmp(argv[1], "bloom-filters"))
+ dump_graph_bloom_filters(graph);
+ else {
+ fprintf(stderr, "unknown sub-command: '%s'\n", argv[1]);
+ ret = 1;
+ }
+done:
UNLEAK(graph);
- return 0;
+ return ret;
}
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 9160bc5da6..623cf3f0f5 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -5,12 +5,8 @@
int cmd__reftable(int argc, const char **argv)
{
/* test from simple to complex. */
- record_test_main(argc, argv);
block_test_main(argc, argv);
- tree_test_main(argc, argv);
- pq_test_main(argc, argv);
readwrite_test_main(argc, argv);
- merged_test_main(argc, argv);
stack_test_main(argc, argv);
return 0;
}
diff --git a/t/helper/test-repository.c b/t/helper/test-repository.c
index c6a074df3d..63c37de33d 100644
--- a/t/helper/test-repository.c
+++ b/t/helper/test-repository.c
@@ -19,7 +19,7 @@ static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
setup_git_env(gitdir);
- memset(the_repository, 0, sizeof(*the_repository));
+ repo_clear(the_repository);
if (repo_init(&r, gitdir, worktree))
die("Couldn't init repo");
@@ -49,7 +49,7 @@ static void test_get_commit_tree_in_graph(const char *gitdir,
setup_git_env(gitdir);
- memset(the_repository, 0, sizeof(*the_repository));
+ repo_clear(the_repository);
if (repo_init(&r, gitdir, worktree))
die("Couldn't init repo");
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 93436a82ae..da3e69128a 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -44,7 +44,6 @@ static struct test_cmd cmds[] = {
{ "mergesort", cmd__mergesort },
{ "mktemp", cmd__mktemp },
{ "oid-array", cmd__oid_array },
- { "oidmap", cmd__oidmap },
{ "online-cpus", cmd__online_cpus },
{ "pack-mtimes", cmd__pack_mtimes },
{ "parse-options", cmd__parse_options },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index d9033d14e1..642a34578c 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -37,7 +37,6 @@ int cmd__lazy_init_name_hash(int argc, const char **argv);
int cmd__match_trees(int argc, const char **argv);
int cmd__mergesort(int argc, const char **argv);
int cmd__mktemp(int argc, const char **argv);
-int cmd__oidmap(int argc, const char **argv);
int cmd__online_cpus(int argc, const char **argv);
int cmd__pack_mtimes(int argc, const char **argv);
int cmd__parse_options(int argc, const char **argv);
diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c
index cd955ec63e..c588c273ce 100644
--- a/t/helper/test-trace2.c
+++ b/t/helper/test-trace2.c
@@ -26,6 +26,7 @@ static int get_i(int *p_value, const char *data)
if (!data || !*data)
return MyError;
+ errno = 0;
*p_value = strtol(data, &endptr, 10);
if (*endptr || errno == ERANGE)
return MyError;
diff --git a/t/lib-bundle-uri-protocol.sh b/t/lib-bundle-uri-protocol.sh
index a4a1af8d02..de09b6b02e 100644
--- a/t/lib-bundle-uri-protocol.sh
+++ b/t/lib-bundle-uri-protocol.sh
@@ -18,7 +18,7 @@ git)
start_git_daemon --export-all --enable=receive-pack
BUNDLE_URI_PARENT="$GIT_DAEMON_DOCUMENT_ROOT_PATH/parent"
BUNDLE_URI_REPO_URI="$GIT_DAEMON_URL/parent"
- BUNDLE_URI_BUNDLE_URI="https://example.com/fake.bdl"
+ BUNDLE_URI_BUNDLE_URI="$BUNDLE_URI_REPO_URI/fake.bdl"
test_set_prereq BUNDLE_URI_GIT
;;
http)
@@ -26,7 +26,7 @@ http)
start_httpd
BUNDLE_URI_PARENT="$HTTPD_DOCUMENT_ROOT_PATH/http_parent"
BUNDLE_URI_REPO_URI="$HTTPD_URL/smart/http_parent"
- BUNDLE_URI_BUNDLE_URI="https://example.com/fake.bdl"
+ BUNDLE_URI_BUNDLE_URI="$BUNDLE_URI_REPO_URL/fake.bdl"
test_set_prereq BUNDLE_URI_HTTP
;;
*)
diff --git a/t/socks4-proxy.pl b/t/socks4-proxy.pl
new file mode 100644
index 0000000000..4c3a35c008
--- /dev/null
+++ b/t/socks4-proxy.pl
@@ -0,0 +1,48 @@
+use strict;
+use IO::Select;
+use IO::Socket::UNIX;
+use IO::Socket::INET;
+
+my $path = shift;
+
+unlink($path);
+my $server = IO::Socket::UNIX->new(Listen => 1, Local => $path)
+ or die "unable to listen on $path: $!";
+
+$| = 1;
+print "ready\n";
+
+while (my $client = $server->accept()) {
+ sysread $client, my $buf, 8;
+ my ($version, $cmd, $port, $ip) = unpack 'CCnN', $buf;
+ next unless $version == 4; # socks4
+ next unless $cmd == 1; # TCP stream connection
+
+ # skip NUL-terminated id
+ while (sysread $client, my $char, 1) {
+ last unless ord($char);
+ }
+
+ # version(0), reply(5a == granted), port (ignored), ip (ignored)
+ syswrite $client, "\x00\x5a\x00\x00\x00\x00\x00\x00";
+
+ my $remote = IO::Socket::INET->new(PeerHost => $ip, PeerPort => $port)
+ or die "unable to connect to $ip/$port: $!";
+
+ my $io = IO::Select->new($client, $remote);
+ while ($io->count) {
+ for my $fh ($io->can_read(0)) {
+ for my $pair ([$client, $remote], [$remote, $client]) {
+ my ($from, $to) = @$pair;
+ next unless $fh == $from;
+
+ my $r = sysread $from, my $buf, 1024;
+ if (!defined $r || $r <= 0) {
+ $io->remove($from);
+ next;
+ }
+ syswrite $to, $buf;
+ }
+ }
+ }
+}
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 3031256d14..fd373e1b39 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -8,6 +8,11 @@ TEST_PASSES_SANITIZE_LEAK=true
# arbitrary reference time: 2009-08-30 19:20:00
GIT_TEST_DATE_NOW=1251660000; export GIT_TEST_DATE_NOW
+if test_have_prereq TIME_IS_64BIT,TIME_T_IS_64BIT
+then
+ test_set_prereq HAVE_64BIT_TIME
+fi
+
check_relative() {
t=$(($GIT_TEST_DATE_NOW - $1))
echo "$t -> $2" >expect
@@ -80,14 +85,15 @@ check_show raw "$TIME" '1466000000 -0200'
# arbitrary time absurdly far in the future
FUTURE="5758122296 -0400"
-check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT,TIME_T_IS_64BIT
-check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" TIME_IS_64BIT,TIME_T_IS_64BIT
+check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" HAVE_64BIT_TIME
+check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" HAVE_64BIT_TIME
-check_parse() {
+REQUIRE_64BIT_TIME=
+check_parse () {
echo "$1 -> $2" >expect
- test_expect_${4:-success} "parse date ($1${3:+ TZ=$3})" "
- TZ=${3:-$TZ} test-tool date parse '$1' >actual &&
- test_cmp expect actual
+ test_expect_success $REQUIRE_64BIT_TIME "parse date ($1${3:+ TZ=$3}) -> $2" "
+ TZ=${3:-$TZ} test-tool date parse '$1' >actual &&
+ test_cmp expect actual
"
}
@@ -117,6 +123,39 @@ check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
check_parse 'Thu, 7 Apr 2005 15:14:13 -0700' '2005-04-07 15:14:13 -0700'
+check_parse '1970-01-01 00:00:00' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 +00' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 Z' '1970-01-01 00:00:00 +0000'
+check_parse '1970-01-01 00:00:00 -01' '1970-01-01 00:00:00 -0100'
+check_parse '1970-01-01 00:00:00 +01' bad
+check_parse '1970-01-01 00:00:00 +11' bad
+check_parse '1970-01-01 00:59:59 +01' bad
+check_parse '1970-01-01 01:00:00 +01' '1970-01-01 01:00:00 +0100'
+check_parse '1970-01-01 01:00:00 +11' bad
+check_parse '1970-01-02 00:00:00 +11' '1970-01-02 00:00:00 +1100'
+check_parse '1969-12-31 23:59:59' bad
+check_parse '1969-12-31 23:59:59 +00' bad
+check_parse '1969-12-31 23:59:59 Z' bad
+check_parse '1969-12-31 23:59:59 +11' bad
+check_parse '1969-12-31 23:59:59 -11' bad
+
+REQUIRE_64BIT_TIME=HAVE_64BIT_TIME
+check_parse '2099-12-31 23:59:59' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 +00' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 Z' '2099-12-31 23:59:59 +0000'
+check_parse '2099-12-31 23:59:59 +01' '2099-12-31 23:59:59 +0100'
+check_parse '2099-12-31 23:59:59 -01' bad
+check_parse '2099-12-31 23:59:59 -11' bad
+check_parse '2099-12-31 23:00:00 -01' bad
+check_parse '2099-12-31 22:59:59 -01' '2099-12-31 22:59:59 -0100'
+check_parse '2100-00-00 00:00:00' bad
+check_parse '2099-12-30 00:00:00 -11' '2099-12-30 00:00:00 -1100'
+check_parse '2100-00-00 00:00:00 +00' bad
+check_parse '2100-00-00 00:00:00 Z' bad
+check_parse '2100-00-00 00:00:00 -11' bad
+check_parse '2100-00-00 00:00:00 +11' bad
+REQUIRE_64BIT_TIME=
+
check_approxidate() {
echo "$1 -> $2 +0000" >expect
test_expect_${3:-success} "parse approxidate ($1)" "
diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh
index ff4fd9348c..9fc5882387 100755
--- a/t/t0007-git-var.sh
+++ b/t/t0007-git-var.sh
@@ -157,7 +157,7 @@ test_expect_success POSIXPERM 'GIT_SHELL_PATH points to a valid executable' '
test_expect_success MINGW 'GIT_SHELL_PATH points to a suitable shell' '
shellpath=$(git var GIT_SHELL_PATH) &&
case "$shellpath" in
- *sh) ;;
+ [A-Z]:/*/sh.exe) test -f "$shellpath";;
*) return 1;;
esac
'
diff --git a/t/t0016-oidmap.sh b/t/t0016-oidmap.sh
deleted file mode 100755
index 0faef1f4f1..0000000000
--- a/t/t0016-oidmap.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/bin/sh
-
-test_description='test oidmap'
-
-TEST_PASSES_SANITIZE_LEAK=true
-. ./test-lib.sh
-
-# This purposefully is very similar to t0011-hashmap.sh
-
-test_oidmap () {
- echo "$1" | test-tool oidmap $3 >actual &&
- echo "$2" >expect &&
- test_cmp expect actual
-}
-
-
-test_expect_success 'setup' '
-
- test_commit one &&
- test_commit two &&
- test_commit three &&
- test_commit four
-
-'
-
-test_expect_success 'put' '
-
-test_oidmap "put one 1
-put two 2
-put invalidOid 4
-put three 3" "NULL
-NULL
-Unknown oid: invalidOid
-NULL"
-
-'
-
-test_expect_success 'replace' '
-
-test_oidmap "put one 1
-put two 2
-put three 3
-put invalidOid 4
-put two deux
-put one un" "NULL
-NULL
-NULL
-Unknown oid: invalidOid
-2
-1"
-
-'
-
-test_expect_success 'get' '
-
-test_oidmap "put one 1
-put two 2
-put three 3
-get two
-get four
-get invalidOid
-get one" "NULL
-NULL
-NULL
-2
-NULL
-Unknown oid: invalidOid
-1"
-
-'
-
-test_expect_success 'remove' '
-
-test_oidmap "put one 1
-put two 2
-put three 3
-remove one
-remove two
-remove invalidOid
-remove four" "NULL
-NULL
-NULL
-1
-2
-Unknown oid: invalidOid
-NULL"
-
-'
-
-test_expect_success 'iterate' '
- test-tool oidmap >actual.raw <<-\EOF &&
- put one 1
- put two 2
- put three 3
- iterate
- EOF
-
- # sort "expect" too so we do not rely on the order of particular oids
- sort >expect <<-EOF &&
- NULL
- NULL
- NULL
- $(git rev-parse one) 1
- $(git rev-parse two) 2
- $(git rev-parse three) 3
- EOF
-
- sort <actual.raw >actual &&
- test_cmp expect actual
-'
-
-test_done
diff --git a/t/t0018-advice.sh b/t/t0018-advice.sh
index 29306b367c..fac52322a7 100755
--- a/t/t0018-advice.sh
+++ b/t/t0018-advice.sh
@@ -96,7 +96,6 @@ test_expect_success 'advice should be printed when GIT_ADVICE is set to true' '
>README &&
GIT_ADVICE=true git status
) >actual &&
- cat actual > /tmp/actual &&
test_cmp expect actual
'
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index 0b4997022b..eeb2714d9d 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -5,6 +5,7 @@ test_description='blob conversion via gitattributes'
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/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/t0095-bloom.sh b/t/t0095-bloom.sh
index b567383eb8..c8d84ab606 100755
--- a/t/t0095-bloom.sh
+++ b/t/t0095-bloom.sh
@@ -29,6 +29,14 @@ test_expect_success 'compute unseeded murmur3 hash for test string 2' '
test_cmp expect actual
'
+test_expect_success 'compute unseeded murmur3 hash for test string 3' '
+ cat >expect <<-\EOF &&
+ Murmur3 Hash with seed=0:0xa183ccfd
+ EOF
+ test-tool bloom get_murmur3_seven_highbit >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'compute bloom key for empty string' '
cat >expect <<-\EOF &&
Hashes:0x5615800c|0x5b966560|0x61174ab4|0x66983008|0x6c19155c|0x7199fab0|0x771ae004|
diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh
index c10e35905e..5d5b64205f 100755
--- a/t/t0301-credential-cache.sh
+++ b/t/t0301-credential-cache.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='credential-cache tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-credential.sh
diff --git a/t/t0302-credential-store.sh b/t/t0302-credential-store.sh
index 716bf1af9f..f83db659e2 100755
--- a/t/t0302-credential-store.sh
+++ b/t/t0302-credential-store.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='credential-store tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-credential.sh
diff --git a/t/t0303-credential-external.sh b/t/t0303-credential-external.sh
index 72ae405c3e..8aadbe86c4 100755
--- a/t/t0303-credential-external.sh
+++ b/t/t0303-credential-external.sh
@@ -29,6 +29,7 @@ you can set GIT_TEST_CREDENTIAL_HELPER_SETUP to a sequence of shell
commands.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-credential.sh
diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh
index b2a771ff2b..20df336cc3 100755
--- a/t/t0600-reffiles-backend.sh
+++ b/t/t0600-reffiles-backend.sh
@@ -91,82 +91,82 @@ test_expect_success 'empty directory should not fool 1-arg delete' '
git update-ref --stdin
'
-test_expect_success 'non-empty directory blocks create' '
+test_expect_success 'non-empty directory blocks create' - <<\EOT
prefix=refs/ne-create &&
mkdir -p .git/$prefix/foo/bar &&
: >.git/$prefix/foo/bar/baz.lock &&
test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/foo': there is a non-empty directory '.git/$prefix/foo' blocking reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/foo $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/foo $D $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'broken reference blocks create' '
+test_expect_success 'broken reference blocks create' - <<\EOT
prefix=refs/broken-create &&
mkdir -p .git/$prefix &&
echo "gobbledigook" >.git/$prefix/foo &&
test_when_finished "rm -f .git/$prefix/foo" &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
+ fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo': reference broken
EOF
printf "%s\n" "update $prefix/foo $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
+ fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo': reference broken
EOF
printf "%s\n" "update $prefix/foo $D $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'non-empty directory blocks indirect create' '
+test_expect_success 'non-empty directory blocks indirect create' - <<\EOT
prefix=refs/ne-indirect-create &&
git symbolic-ref $prefix/symref $prefix/foo &&
mkdir -p .git/$prefix/foo/bar &&
: >.git/$prefix/foo/bar/baz.lock &&
test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/symref': there is a non-empty directory '.git/$prefix/foo' blocking reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/symref $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/symref $D $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'broken reference blocks indirect create' '
+test_expect_success 'broken reference blocks indirect create' - <<\EOT
prefix=refs/broken-indirect-create &&
git symbolic-ref $prefix/symref $prefix/foo &&
echo "gobbledigook" >.git/$prefix/foo &&
test_when_finished "rm -f .git/$prefix/foo" &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
+ fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo': reference broken
EOF
printf "%s\n" "update $prefix/symref $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
+ fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo': reference broken
EOF
printf "%s\n" "update $prefix/symref $D $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
test_expect_success 'no bogus intermediate values during delete' '
prefix=refs/slow-transaction &&
@@ -224,7 +224,7 @@ test_expect_success 'no bogus intermediate values during delete' '
test_must_fail git rev-parse --verify --quiet $prefix/foo
'
-test_expect_success 'delete fails cleanly if packed-refs file is locked' '
+test_expect_success 'delete fails cleanly if packed-refs file is locked' - <<\EOT
prefix=refs/locked-packed-refs &&
# Set up a reference with differing loose and packed versions:
git update-ref $prefix/foo $C &&
@@ -236,9 +236,9 @@ test_expect_success 'delete fails cleanly if packed-refs file is locked' '
test_when_finished "rm -f .git/packed-refs.lock" &&
test_must_fail git update-ref -d $prefix/foo >out 2>err &&
git for-each-ref $prefix >actual &&
- test_grep "Unable to create $SQ.*packed-refs.lock$SQ: " err &&
+ test_grep "Unable to create '.*packed-refs.lock': " err &&
test_cmp unchanged actual
-'
+EOT
test_expect_success 'delete fails cleanly if packed-refs.new write fails' '
# Setup and expectations are similar to the test above.
diff --git a/t/t0612-reftable-jgit-compatibility.sh b/t/t0612-reftable-jgit-compatibility.sh
index d0d7e80b49..84922153ab 100755
--- a/t/t0612-reftable-jgit-compatibility.sh
+++ b/t/t0612-reftable-jgit-compatibility.sh
@@ -11,6 +11,7 @@ export GIT_TEST_DEFAULT_REF_FORMAT
GIT_TEST_SPLIT_INDEX=0
export GIT_TEST_SPLIT_INDEX
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
if ! test_have_prereq JGIT
diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh
index e2708e11d5..b1c6c97524 100755
--- a/t/t0613-reftable-write-options.sh
+++ b/t/t0613-reftable-write-options.sh
@@ -16,6 +16,7 @@ export GIT_TEST_DEFAULT_HASH
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'default write options' '
diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh
index 11bf10424f..2b9720b0fe 100755
--- a/t/t1004-read-tree-m-u-wf.sh
+++ b/t/t1004-read-tree-m-u-wf.sh
@@ -5,6 +5,7 @@ test_description='read-tree -m -u checks working tree files'
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-read-tree.sh
diff --git a/t/t1015-read-index-unmerged.sh b/t/t1015-read-index-unmerged.sh
index 55d22da32c..da737a32a2 100755
--- a/t/t1015-read-index-unmerged.sh
+++ b/t/t1015-read-index-unmerged.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='Test various callers of read_index_unmerged'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup modify/delete + directory/file conflict' '
diff --git a/t/t1021-rerere-in-workdir.sh b/t/t1021-rerere-in-workdir.sh
index 0b892894eb..69bf9476cb 100755
--- a/t/t1021-rerere-in-workdir.sh
+++ b/t/t1021-rerere-in-workdir.sh
@@ -4,6 +4,7 @@ test_description='rerere run in a workdir'
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 SYMLINKS setup '
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 2f1ae5fd3b..a2c0e1b4dc 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -159,7 +159,10 @@ init_repos () {
git -C sparse-checkout sparse-checkout set deep &&
git -C sparse-index sparse-checkout init --cone --sparse-index &&
test_cmp_config -C sparse-index true index.sparse &&
- git -C sparse-index sparse-checkout set deep
+ git -C sparse-index sparse-checkout set deep &&
+
+ # Disable this message to keep stderr the same.
+ git -C sparse-index config advice.sparseIndexExpanded false
}
init_repos_as_submodules () {
@@ -2331,4 +2334,15 @@ test_expect_success 'sparse-index is not expanded: check-attr' '
ensure_not_expanded check-attr -a --cached -- folder1/a
'
+test_expect_success 'advice.sparseIndexExpanded' '
+ init_repos &&
+
+ git -C sparse-index config --unset advice.sparseIndexExpanded &&
+ git -C sparse-index sparse-checkout set deep/deeper1 &&
+ mkdir -p sparse-index/deep/deeper2/deepest &&
+ touch sparse-index/deep/deeper2/deepest/bogus &&
+ git -C sparse-index status 2>err &&
+ grep "The sparse index is expanding to a full index" err
+'
+
test_done
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 9de2d95f06..f13277c8f3 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -2704,6 +2704,15 @@ test_expect_success '--get and --get-all with --fixed-value' '
test_must_fail git config --file=config --get-regexp --fixed-value fixed+ non-existent
'
+test_expect_success '--fixed-value with value-less configuration' '
+ test_when_finished rm -f config &&
+ cat >config <<-\EOF &&
+ [section]
+ key
+ EOF
+ git config --file=config --fixed-value section.key value pattern
+'
+
test_expect_success 'includeIf.hasconfig:remote.*.url' '
git init hasremoteurlTest &&
test_when_finished "rm -rf hasremoteurlTest" &&
diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh
index 67ebd81a4c..df90112618 100755
--- a/t/t1404-update-ref-errors.sh
+++ b/t/t1404-update-ref-errors.sh
@@ -100,13 +100,13 @@ df_test() {
printf "%s\n" "delete $delname" "create $addname $D"
fi >commands &&
test_must_fail git update-ref --stdin <commands 2>output.err &&
- grep -E "fatal:( cannot lock ref $SQ$addname$SQ:)? $SQ$delref$SQ exists; cannot create $SQ$addref$SQ" output.err &&
+ grep -E "fatal:( cannot lock ref '$addname':)? '$delref' exists; cannot create '$addref'" output.err &&
printf "%s\n" "$C $delref" >expected-refs &&
git for-each-ref --format="%(objectname) %(refname)" $prefix/r >actual-refs &&
test_cmp expected-refs actual-refs
}
-test_expect_success 'setup' '
+test_expect_success 'setup' - <<\EOT
git commit --allow-empty -m Initial &&
C=$(git rev-parse HEAD) &&
@@ -114,283 +114,283 @@ test_expect_success 'setup' '
D=$(git rev-parse HEAD) &&
git commit --allow-empty -m Third &&
E=$(git rev-parse HEAD)
-'
+EOT
-test_expect_success 'existing loose ref is a simple prefix of new' '
+test_expect_success 'existing loose ref is a simple prefix of new' - <<\EOT
prefix=refs/1l &&
test_update_rejected "a c e" false "b c/x d" \
- "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x$SQ"
+ "'$prefix/c' exists; cannot create '$prefix/c/x'"
-'
+EOT
-test_expect_success 'existing packed ref is a simple prefix of new' '
+test_expect_success 'existing packed ref is a simple prefix of new' - <<\EOT
prefix=refs/1p &&
test_update_rejected "a c e" true "b c/x d" \
- "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x$SQ"
+ "'$prefix/c' exists; cannot create '$prefix/c/x'"
-'
+EOT
-test_expect_success 'existing loose ref is a deeper prefix of new' '
+test_expect_success 'existing loose ref is a deeper prefix of new' - <<\EOT
prefix=refs/2l &&
test_update_rejected "a c e" false "b c/x/y d" \
- "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x/y$SQ"
+ "'$prefix/c' exists; cannot create '$prefix/c/x/y'"
-'
+EOT
-test_expect_success 'existing packed ref is a deeper prefix of new' '
+test_expect_success 'existing packed ref is a deeper prefix of new' - <<\EOT
prefix=refs/2p &&
test_update_rejected "a c e" true "b c/x/y d" \
- "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x/y$SQ"
+ "'$prefix/c' exists; cannot create '$prefix/c/x/y'"
-'
+EOT
-test_expect_success 'new ref is a simple prefix of existing loose' '
+test_expect_success 'new ref is a simple prefix of existing loose' - <<\EOT
prefix=refs/3l &&
test_update_rejected "a c/x e" false "b c d" \
- "$SQ$prefix/c/x$SQ exists; cannot create $SQ$prefix/c$SQ"
+ "'$prefix/c/x' exists; cannot create '$prefix/c'"
-'
+EOT
-test_expect_success 'new ref is a simple prefix of existing packed' '
+test_expect_success 'new ref is a simple prefix of existing packed' - <<\EOT
prefix=refs/3p &&
test_update_rejected "a c/x e" true "b c d" \
- "$SQ$prefix/c/x$SQ exists; cannot create $SQ$prefix/c$SQ"
+ "'$prefix/c/x' exists; cannot create '$prefix/c'"
-'
+EOT
-test_expect_success 'new ref is a deeper prefix of existing loose' '
+test_expect_success 'new ref is a deeper prefix of existing loose' - <<\EOT
prefix=refs/4l &&
test_update_rejected "a c/x/y e" false "b c d" \
- "$SQ$prefix/c/x/y$SQ exists; cannot create $SQ$prefix/c$SQ"
+ "'$prefix/c/x/y' exists; cannot create '$prefix/c'"
-'
+EOT
-test_expect_success 'new ref is a deeper prefix of existing packed' '
+test_expect_success 'new ref is a deeper prefix of existing packed' - <<\EOT
prefix=refs/4p &&
test_update_rejected "a c/x/y e" true "b c d" \
- "$SQ$prefix/c/x/y$SQ exists; cannot create $SQ$prefix/c$SQ"
+ "'$prefix/c/x/y' exists; cannot create '$prefix/c'"
-'
+EOT
-test_expect_success 'one new ref is a simple prefix of another' '
+test_expect_success 'one new ref is a simple prefix of another' - <<\EOT
prefix=refs/5 &&
test_update_rejected "a e" false "b c c/x d" \
- "cannot process $SQ$prefix/c$SQ and $SQ$prefix/c/x$SQ at the same time"
+ "cannot process '$prefix/c' and '$prefix/c/x' at the same time"
-'
+EOT
-test_expect_success 'D/F conflict prevents add long + delete short' '
+test_expect_success 'D/F conflict prevents add long + delete short' - <<\EOT
df_test refs/df-al-ds --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents add short + delete long' '
+test_expect_success 'D/F conflict prevents add short + delete long' - <<\EOT
df_test refs/df-as-dl --add-del foo foo/bar
-'
+EOT
-test_expect_success 'D/F conflict prevents delete long + add short' '
+test_expect_success 'D/F conflict prevents delete long + add short' - <<\EOT
df_test refs/df-dl-as --del-add foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents delete short + add long' '
+test_expect_success 'D/F conflict prevents delete short + add long' - <<\EOT
df_test refs/df-ds-al --del-add foo foo/bar
-'
+EOT
-test_expect_success 'D/F conflict prevents add long + delete short packed' '
+test_expect_success 'D/F conflict prevents add long + delete short packed' - <<\EOT
df_test refs/df-al-dsp --pack --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents add short + delete long packed' '
+test_expect_success 'D/F conflict prevents add short + delete long packed' - <<\EOT
df_test refs/df-as-dlp --pack --add-del foo foo/bar
-'
+EOT
-test_expect_success 'D/F conflict prevents delete long packed + add short' '
+test_expect_success 'D/F conflict prevents delete long packed + add short' - <<\EOT
df_test refs/df-dlp-as --pack --del-add foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents delete short packed + add long' '
+test_expect_success 'D/F conflict prevents delete short packed + add long' - <<\EOT
df_test refs/df-dsp-al --pack --del-add foo foo/bar
-'
+EOT
# Try some combinations involving symbolic refs...
-test_expect_success 'D/F conflict prevents indirect add long + delete short' '
+test_expect_success 'D/F conflict prevents indirect add long + delete short' - <<\EOT
df_test refs/df-ial-ds --sym-add --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' '
+test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' - <<\EOT
df_test refs/df-ial-ids --sym-add --sym-del --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' '
+test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' - <<\EOT
df_test refs/df-ias-idl --sym-add --sym-del --add-del foo foo/bar
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' '
+test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' - <<\EOT
df_test refs/df-idl-ias --sym-add --sym-del --del-add foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect add long + delete short packed' '
+test_expect_success 'D/F conflict prevents indirect add long + delete short packed' - <<\EOT
df_test refs/df-ial-dsp --sym-add --pack --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' '
+test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' - <<\EOT
df_test refs/df-ial-idsp --sym-add --sym-del --pack --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents add long + indirect delete short packed' '
+test_expect_success 'D/F conflict prevents add long + indirect delete short packed' - <<\EOT
df_test refs/df-al-idsp --sym-del --pack --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' '
+test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' - <<\EOT
df_test refs/df-idlp-ias --sym-add --sym-del --pack --del-add foo/bar foo
-'
+EOT
# Test various errors when reading the old values of references...
-test_expect_success 'missing old value blocks update' '
+test_expect_success 'missing old value blocks update' - <<\EOT
prefix=refs/missing-update &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/foo $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks update' '
+test_expect_success 'incorrect old value blocks update' - <<\EOT
prefix=refs/incorrect-update &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/foo': is at $C but expected $D
EOF
printf "%s\n" "update $prefix/foo $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'existing old value blocks create' '
+test_expect_success 'existing old value blocks create' - <<\EOT
prefix=refs/existing-create &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: reference already exists
+ fatal: cannot lock ref '$prefix/foo': reference already exists
EOF
printf "%s\n" "create $prefix/foo $E" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks delete' '
+test_expect_success 'incorrect old value blocks delete' - <<\EOT
prefix=refs/incorrect-delete &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/foo': is at $C but expected $D
EOF
printf "%s\n" "delete $prefix/foo $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'missing old value blocks indirect update' '
+test_expect_success 'missing old value blocks indirect update' - <<\EOT
prefix=refs/missing-indirect-update &&
git symbolic-ref $prefix/symref $prefix/foo &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/symref $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks indirect update' '
+test_expect_success 'incorrect old value blocks indirect update' - <<\EOT
prefix=refs/incorrect-indirect-update &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
EOF
printf "%s\n" "update $prefix/symref $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'existing old value blocks indirect create' '
+test_expect_success 'existing old value blocks indirect create' - <<\EOT
prefix=refs/existing-indirect-create &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: reference already exists
+ fatal: cannot lock ref '$prefix/symref': reference already exists
EOF
printf "%s\n" "create $prefix/symref $E" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks indirect delete' '
+test_expect_success 'incorrect old value blocks indirect delete' - <<\EOT
prefix=refs/incorrect-indirect-delete &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
EOF
printf "%s\n" "delete $prefix/symref $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'missing old value blocks indirect no-deref update' '
+test_expect_success 'missing old value blocks indirect no-deref update' - <<\EOT
prefix=refs/missing-noderef-update &&
git symbolic-ref $prefix/symref $prefix/foo &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: reference is missing but expected $D
+ fatal: cannot lock ref '$prefix/symref': reference is missing but expected $D
EOF
printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks indirect no-deref update' '
+test_expect_success 'incorrect old value blocks indirect no-deref update' - <<\EOT
prefix=refs/incorrect-noderef-update &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
EOF
printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'existing old value blocks indirect no-deref create' '
+test_expect_success 'existing old value blocks indirect no-deref create' - <<\EOT
prefix=refs/existing-noderef-create &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: reference already exists
+ fatal: cannot lock ref '$prefix/symref': reference already exists
EOF
printf "%s\n" "option no-deref" "create $prefix/symref $E" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks indirect no-deref delete' '
+test_expect_success 'incorrect old value blocks indirect no-deref delete' - <<\EOT
prefix=refs/incorrect-noderef-delete &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
EOF
printf "%s\n" "option no-deref" "delete $prefix/symref $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
test_done
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 5bf883f1e3..246a3f46ab 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -146,6 +146,14 @@ test_expect_success rewind '
test_line_count = 5 output
'
+test_expect_success 'reflog expire should not barf on an annotated tag' '
+ test_when_finished "git tag -d v0.tag || :" &&
+ git -c core.logAllRefUpdates=always \
+ tag -a -m "tag name" v0.tag main &&
+ git reflog expire --dry-run refs/tags/v0.tag 2>err &&
+ test_grep ! "error: [Oo]bject .* not a commit" err
+'
+
test_expect_success 'corrupt and check' '
corrupt $F &&
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index b754b9fd74..5eaa6428c4 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test git rev-parse --parseopt'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_invalid_long_option () {
diff --git a/t/t1511-rev-parse-caret.sh b/t/t1511-rev-parse-caret.sh
index 6ecfed86bc..e7e78a4028 100755
--- a/t/t1511-rev-parse-caret.sh
+++ b/t/t1511-rev-parse-caret.sh
@@ -5,6 +5,7 @@ test_description='tests for ref^{stuff}'
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/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh
index 70f1e0a998..f9d68ce74e 100755
--- a/t/t1512-rev-parse-disambiguation.sh
+++ b/t/t1512-rev-parse-disambiguation.sh
@@ -23,6 +23,7 @@ one tagged as v1.0.0. They all have one regular file each.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_cmp_failed_rev_parse () {
diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh
index be3fcdde07..b3f6bc97b5 100755
--- a/t/t2030-unresolve-info.sh
+++ b/t/t2030-unresolve-info.sh
@@ -5,6 +5,7 @@ test_description='undoing resolution'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_resolve_undo () {
diff --git a/t/t2080-parallel-checkout-basics.sh b/t/t2080-parallel-checkout-basics.sh
index 5ffe1a41e2..59e5570cb2 100755
--- a/t/t2080-parallel-checkout-basics.sh
+++ b/t/t2080-parallel-checkout-basics.sh
@@ -8,6 +8,7 @@ working tree.
'
TEST_NO_CREATE_REPO=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-parallel-checkout.sh"
diff --git a/t/t2082-parallel-checkout-attributes.sh b/t/t2082-parallel-checkout-attributes.sh
index f3511cd43a..aec55496eb 100755
--- a/t/t2082-parallel-checkout-attributes.sh
+++ b/t/t2082-parallel-checkout-attributes.sh
@@ -10,6 +10,7 @@ properly (without access to the index or attribute stack).
'
TEST_NO_CREATE_REPO=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-parallel-checkout.sh"
. "$TEST_DIRECTORY/lib-encoding.sh"
diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh
index cc72ead79f..f0eab13f96 100755
--- a/t/t2107-update-index-basic.sh
+++ b/t/t2107-update-index-basic.sh
@@ -5,6 +5,7 @@ test_description='basic update-index tests
Tests for command-line parsing and basic operation.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'update-index --nonsense fails' '
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index ba320dc417..cfc4aeb179 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -6,6 +6,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
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t2500-untracked-overwriting.sh b/t/t2500-untracked-overwriting.sh
index 5c0bf4d21f..714feb83be 100755
--- a/t/t2500-untracked-overwriting.sh
+++ b/t/t2500-untracked-overwriting.sh
@@ -2,6 +2,7 @@
test_description='Test handling of overwriting untracked files'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_setup_reset () {
diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh
index f6d8d7d03d..8af4e8cfe3 100755
--- a/t/t2501-cwd-empty.sh
+++ b/t/t2501-cwd-empty.sh
@@ -2,6 +2,7 @@
test_description='Test handling of the current working directory becoming empty'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh
index 800fc33165..6e587d27d7 100755
--- a/t/t3201-branch-contains.sh
+++ b/t/t3201-branch-contains.sh
@@ -2,6 +2,7 @@
test_description='branch --contains <commit>, --no-contains <commit> --merged, and --no-merged'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh
index a1139f79e2..3b6dad0c46 100755
--- a/t/t3202-show-branch.sh
+++ b/t/t3202-show-branch.sh
@@ -2,6 +2,7 @@
test_description='test show-branch'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'error descriptions on empty repository' '
diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index a767c3520e..86010931ab 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -5,6 +5,7 @@ test_description='range-diff tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Note that because of the range-diff's heuristics, test_commit does more
@@ -533,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-* &&
@@ -560,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-*
@@ -606,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 &&
@@ -630,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 &&
@@ -645,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 &&
@@ -678,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 &&
@@ -691,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-* &&
@@ -708,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-* &&
@@ -739,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-* &&
@@ -767,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-* &&
@@ -796,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/t3301-notes.sh b/t/t3301-notes.sh
index cf23c06c09..99137fb235 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -5,6 +5,7 @@
test_description='Test commit notes'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
write_script fake_editor <<\EOF
@@ -1556,4 +1557,14 @@ test_expect_success 'empty notes are displayed by git log' '
test_cmp expect actual
'
+test_expect_success 'empty notes do not invoke the editor' '
+ test_commit 18th &&
+ GIT_EDITOR="false" git notes add -C "$empty_blob" --allow-empty &&
+ git notes remove HEAD &&
+ GIT_EDITOR="false" git notes add -m "" --allow-empty &&
+ git notes remove HEAD &&
+ GIT_EDITOR="false" git notes add -F /dev/null --allow-empty &&
+ git notes remove HEAD
+'
+
test_done
diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh
index 8f4102ff9e..b6e9f643e3 100755
--- a/t/t3306-notes-prune.sh
+++ b/t/t3306-notes-prune.sh
@@ -2,6 +2,7 @@
test_description='Test git notes prune'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup: create a few commits with notes' '
diff --git a/t/t3308-notes-merge.sh b/t/t3308-notes-merge.sh
index 202702be1a..e1d05ff6bc 100755
--- a/t/t3308-notes-merge.sh
+++ b/t/t3308-notes-merge.sh
@@ -5,6 +5,7 @@
test_description='Test merging of notes trees'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh
index 9bd5dbf341..f55277f499 100755
--- a/t/t3309-notes-merge-auto-resolve.sh
+++ b/t/t3309-notes-merge-auto-resolve.sh
@@ -5,6 +5,7 @@
test_description='Test notes merging with auto-resolving strategies'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Set up a notes merge scenario with all kinds of potential conflicts
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index e1c8c5f701..ae34bfad60 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -11,6 +11,7 @@ among other things.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GIT_AUTHOR_NAME=author@name
diff --git a/t/t3401-rebase-and-am-rename.sh b/t/t3401-rebase-and-am-rename.sh
index f18bae9450..328c1d3a3f 100755
--- a/t/t3401-rebase-and-am-rename.sh
+++ b/t/t3401-rebase-and-am-rename.sh
@@ -2,6 +2,7 @@
test_description='git rebase + directory rename tests'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh
index a1911c4a9d..4f1d6e8ea6 100755
--- a/t/t3403-rebase-skip.sh
+++ b/t/t3403-rebase-skip.sh
@@ -8,6 +8,7 @@ test_description='git rebase --merge --skip 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-rebase.sh
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index a1d7fa7f7c..82108b67e6 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -5,6 +5,7 @@ test_description='messages from rebase operation'
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/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh
index 9f49c4228b..2c3f38d45a 100755
--- a/t/t3407-rebase-abort.sh
+++ b/t/t3407-rebase-abort.sh
@@ -5,6 +5,7 @@ test_description='git rebase --abort tests'
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/t3417-rebase-whitespace-fix.sh b/t/t3417-rebase-whitespace-fix.sh
index 96f2cf22fa..22ee3a2045 100755
--- a/t/t3417-rebase-whitespace-fix.sh
+++ b/t/t3417-rebase-whitespace-fix.sh
@@ -5,6 +5,7 @@ test_description='git rebase --whitespace=fix
This test runs git rebase --whitespace=fix and make sure that it works.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# prepare initial revision of "file" with a blank line at the end
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index 127216f722..c0d29c2154 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -5,6 +5,7 @@ test_description='git rebase --continue 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-rebase.sh
diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh
index 1a820f1481..63e400b89f 100755
--- a/t/t3420-rebase-autostash.sh
+++ b/t/t3420-rebase-autostash.sh
@@ -7,6 +7,7 @@ test_description='git rebase --autostash tests'
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/t3421-rebase-topology-linear.sh b/t/t3421-rebase-topology-linear.sh
index 62d86d557d..737af80bb3 100755
--- a/t/t3421-rebase-topology-linear.sh
+++ b/t/t3421-rebase-topology-linear.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='basic rebase topology tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3424-rebase-empty.sh b/t/t3424-rebase-empty.sh
index 1ee6b00fd5..515c949ae3 100755
--- a/t/t3424-rebase-empty.sh
+++ b/t/t3424-rebase-empty.sh
@@ -2,6 +2,7 @@
test_description='git rebase of commits that start or become empty'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup test repository' '
diff --git a/t/t3428-rebase-signoff.sh b/t/t3428-rebase-signoff.sh
index 6f57aed9fa..365436ebfc 100755
--- a/t/t3428-rebase-signoff.sh
+++ b/t/t3428-rebase-signoff.sh
@@ -5,6 +5,7 @@ test_description='git rebase --signoff
This test runs git rebase --signoff and make sure that it works.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
index 59b5d6b6f2..2aa8593f77 100755
--- a/t/t3430-rebase-merges.sh
+++ b/t/t3430-rebase-merges.sh
@@ -21,6 +21,7 @@ Initial setup:
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-log-graph.sh
@@ -391,8 +392,7 @@ test_expect_success 'refuse to merge ancestors of HEAD' '
test_expect_success 'root commits' '
git checkout --orphan unrelated &&
- (GIT_AUTHOR_NAME="Parsnip" GIT_AUTHOR_EMAIL="root@example.com" \
- test_commit second-root) &&
+ test_commit --author "Parsnip <root@example.com>" second-root &&
test_commit third-root &&
cat >script-from-scratch <<-\EOF &&
pick third-root
diff --git a/t/t3434-rebase-i18n.sh b/t/t3434-rebase-i18n.sh
index a4e482d2cd..26a48d6b10 100755
--- a/t/t3434-rebase-i18n.sh
+++ b/t/t3434-rebase-i18n.sh
@@ -17,6 +17,7 @@ Initial setup:
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
compare_msg () {
diff --git a/t/t3500-cherry.sh b/t/t3500-cherry.sh
index 78c3eac54b..61ca87512d 100755
--- a/t/t3500-cherry.sh
+++ b/t/t3500-cherry.sh
@@ -11,6 +11,7 @@ checks that git cherry only returns the second patch in the local branch
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GIT_AUTHOR_EMAIL=bogus_email_address
diff --git a/t/t3504-cherry-pick-rerere.sh b/t/t3504-cherry-pick-rerere.sh
index 4581ae98b8..597c98e9c5 100755
--- a/t/t3504-cherry-pick-rerere.sh
+++ b/t/t3504-cherry-pick-rerere.sh
@@ -5,6 +5,7 @@ test_description='cherry-pick should rerere for conflicts'
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/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh
index 9748443530..ead3fb4680 100755
--- a/t/t3505-cherry-pick-empty.sh
+++ b/t/t3505-cherry-pick-empty.sh
@@ -5,6 +5,7 @@ test_description='test cherry-picking an empty commit'
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/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh
index 2d53ce754c..afa7727a4a 100755
--- a/t/t3508-cherry-pick-many-commits.sh
+++ b/t/t3508-cherry-pick-many-commits.sh
@@ -5,6 +5,7 @@ test_description='test cherry-picking many commits'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_head_differs_from() {
diff --git a/t/t3509-cherry-pick-merge-df.sh b/t/t3509-cherry-pick-merge-df.sh
index f4159246e1..171cc6d76b 100755
--- a/t/t3509-cherry-pick-merge-df.sh
+++ b/t/t3509-cherry-pick-merge-df.sh
@@ -4,6 +4,7 @@ test_description='Test cherry-pick with directory/file conflicts'
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 'Initialize repository' '
diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh
index 389670262e..12bd3db4cb 100755
--- a/t/t3650-replay-basics.sh
+++ b/t/t3650-replay-basics.sh
@@ -5,6 +5,7 @@ test_description='basic git replay tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GIT_AUTHOR_NAME=author@name
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 5d78868ac1..718438ffc7 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -575,6 +575,54 @@ test_expect_success 'navigate to hunk via regex / pattern' '
test_cmp expect actual.trimmed
'
+test_expect_success 'print again the hunk' '
+ test_when_finished "git reset" &&
+ tr _ " " >expect <<-EOF &&
+ +15
+ 20
+ (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? @@ -1,2 +1,3 @@
+ 10
+ +15
+ 20
+ (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
+ EOF
+ test_write_lines s y g 1 p | git add -p >actual &&
+ tail -n 7 <actual >actual.trimmed &&
+ test_cmp expect actual.trimmed
+'
+
+test_expect_success TTY 'print again the hunk (PAGER)' '
+ test_when_finished "git reset" &&
+ cat >expect <<-EOF &&
+ <GREEN>+<RESET><GREEN>15<RESET>
+ 20<RESET>
+ <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>PAGER <CYAN>@@ -1,2 +1,3 @@<RESET>
+ PAGER 10<RESET>
+ PAGER <GREEN>+<RESET><GREEN>15<RESET>
+ PAGER 20<RESET>
+ <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>
+ EOF
+ test_write_lines s y g 1 P |
+ (
+ GIT_PAGER="sed s/^/PAGER\ /" &&
+ export GIT_PAGER &&
+ test_terminal git add -p >actual
+ ) &&
+ tail -n 7 <actual | test_decode_color >actual.trimmed &&
+ test_cmp expect actual.trimmed
+'
+
+test_expect_success TTY 'P handles SIGPIPE when writing to pager' '
+ test_when_finished "rm -f huge_file; git reset" &&
+ printf "\n%2500000s" Y >huge_file &&
+ git add -N huge_file &&
+ test_write_lines P q | (
+ GIT_PAGER="head -n 1" &&
+ export GIT_PAGER &&
+ test_terminal git add -p
+ )
+'
+
test_expect_success 'split hunk "add -p (edit)"' '
# Split, say Edit and do nothing. Then:
#
@@ -1164,4 +1212,23 @@ test_expect_success 'reset -p with unmerged files' '
test_must_be_empty staged
'
+test_expect_success 'hunk splitting works with diff.suppressBlankEmpty' '
+ test_config diff.suppressBlankEmpty true &&
+ write_script fake-editor.sh <<-\EOF &&
+ tr F G <"$1" >"$1.tmp" &&
+ mv "$1.tmp" "$1"
+ EOF
+
+ test_write_lines a b "" c d "" e f "" >file &&
+ git add file &&
+ test_write_lines A b "" c D "" e F "" >file &&
+ (
+ test_set_editor "$(pwd)/fake-editor.sh" &&
+ test_write_lines s n y e q | git add -p file
+ ) &&
+ git cat-file blob :file >actual &&
+ test_write_lines a b "" c D "" e G "" >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index a7f71f8126..e4c0937f61 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -8,6 +8,7 @@ test_description='Test git stash'
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-unique-files.sh
diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh
index 368fc2a6cc..aa5019fd6c 100755
--- a/t/t3904-stash-patch.sh
+++ b/t/t3904-stash-patch.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='stash -p'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-patch-mode.sh
test_expect_success 'setup' '
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index 1289ae3e07..a1733f45c3 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -5,6 +5,7 @@
test_description='Test git stash --include-untracked'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'stash save --include-untracked some dirty working directory' '
diff --git a/t/t3907-stash-show-config.sh b/t/t3907-stash-show-config.sh
index 10914bba7b..7a2eb98b86 100755
--- a/t/t3907-stash-show-config.sh
+++ b/t/t3907-stash-show-config.sh
@@ -2,6 +2,7 @@
test_description='Test git stash show configuration.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh
index 74586f3813..4dcd7e9925 100755
--- a/t/t4034-diff-words.sh
+++ b/t/t4034-diff-words.sh
@@ -70,7 +70,7 @@ test_language_driver () {
word_diff --color-words
'
test_expect_success "diff driver '$lang' in Islandic" '
- LANG=is_IS.UTF-8 LANGUAGE=is LC_ALL="$is_IS_locale" \
+ test_env LANG=is_IS.UTF-8 LANGUAGE=is LC_ALL="$is_IS_locale" \
word_diff --color-words
'
}
diff --git a/t/t4061-diff-indent.sh b/t/t4061-diff-indent.sh
index 7750b87ca1..2942e5d9b9 100755
--- a/t/t4061-diff-indent.sh
+++ b/t/t4061-diff-indent.sh
@@ -6,6 +6,7 @@ test_description='Test diff indent heuristic.
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
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
index 4eb8444029..d9a1084b5e 100755
--- a/t/t4129-apply-samemode.sh
+++ b/t/t4129-apply-samemode.sh
@@ -130,4 +130,66 @@ test_expect_success 'git apply respects core.fileMode' '
test_grep ! "has type 100644, expected 100755" err
'
+test_expect_success POSIXPERM 'patch mode for new file is canonicalized' '
+ cat >patch <<-\EOF &&
+ diff --git a/non-canon b/non-canon
+ new file mode 100660
+ --- /dev/null
+ +++ b/non-canon
+ +content
+ EOF
+ test_when_finished "git reset --hard" &&
+ (
+ umask 0 &&
+ git apply --index patch 2>err
+ ) &&
+ test_must_be_empty err &&
+ git ls-files -s -- non-canon >staged &&
+ test_grep "^100644" staged &&
+ ls -l non-canon >worktree &&
+ test_grep "^-rw-rw-rw" worktree
+'
+
+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 &&
+
+ cat >patch <<-\EOF &&
+ diff --git a/non-canon b/non-canon
+ deleted file mode 100660
+ --- a/non-canon
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -content
+ EOF
+ git apply --index patch 2>err &&
+ test_must_be_empty err &&
+ git ls-files -- non-canon >staged &&
+ test_must_be_empty staged &&
+ test_path_is_missing non-canon
+'
+
+test_expect_success POSIXPERM 'patch mode for mode change is canonicalized' '
+ test_when_finished "git reset --hard" &&
+ echo content >non-canon &&
+ git add non-canon &&
+
+ cat >patch <<-\EOF &&
+ diff --git a/non-canon b/non-canon
+ old mode 100660
+ new mode 100770
+ EOF
+ (
+ umask 0 &&
+ git apply --index patch 2>err
+ ) &&
+ test_must_be_empty err &&
+ git ls-files -s -- non-canon >staged &&
+ test_grep "^100755" staged &&
+ ls -l non-canon >worktree &&
+ test_grep "^-rwxrwxrwx" worktree
+'
+
test_done
diff --git a/t/t4131-apply-fake-ancestor.sh b/t/t4131-apply-fake-ancestor.sh
index b1361ce546..40c92115a6 100755
--- a/t/t4131-apply-fake-ancestor.sh
+++ b/t/t4131-apply-fake-ancestor.sh
@@ -5,6 +5,7 @@
test_description='git apply --build-fake-ancestor handling.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh
index edb38da701..1825a89d6a 100755
--- a/t/t4151-am-abort.sh
+++ b/t/t4151-am-abort.sh
@@ -2,6 +2,7 @@
test_description='am --abort'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh
index a32cec42aa..dd6ad8f7a8 100755
--- a/t/t4153-am-resume-override-opts.sh
+++ b/t/t4153-am-resume-override-opts.sh
@@ -2,6 +2,7 @@
test_description='git-am command-line options override saved options'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
format_patch () {
@@ -98,7 +99,7 @@ test_expect_success '--reject overrides --no-reject' '
test_path_is_dir .git/rebase-apply &&
test_path_is_missing file.rej &&
- test_must_fail git am --retry --reject </dev/zero &&
+ test_must_fail git am --retry --reject &&
test_path_is_dir .git/rebase-apply &&
test_path_is_file file.rej
'
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index b0a3e84984..213b36fb96 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -25,6 +25,7 @@ test_description='git rerere
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/t4201-shortlog.sh b/t/t4201-shortlog.sh
index f698d0c9ad..c20c885724 100755
--- a/t/t4201-shortlog.sh
+++ b/t/t4201-shortlog.sh
@@ -9,6 +9,7 @@ test_description='git shortlog
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/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 8a88dd7900..79e5f42760 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -5,6 +5,7 @@ test_description='.mailmap configurations'
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 commits and contacts file' '
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index 605faea0c7..dc8ddb10af 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -114,6 +114,46 @@ test_expect_success 'patch-id supports git-format-patch output' '
test "$2" = $(git rev-parse HEAD)
'
+test_expect_success 'patch-id computes the same for various formats' '
+ # This test happens to consider "git log -p -1" output
+ # the canonical input format, so use it as the norm.
+ git log -1 -p same >log-p.output &&
+ git patch-id <log-p.output >expect &&
+
+ # format-patch begins with "From <commit object name>"
+ git format-patch -1 --stdout same >format-patch.output &&
+ git patch-id <format-patch.output >actual &&
+ test_cmp actual expect &&
+
+ # "diff-tree --stdin -p" begins with "<commit object name>"
+ same=$(git rev-parse same) &&
+ echo $same | git diff-tree --stdin -p >diff-tree.output &&
+ git patch-id <diff-tree.output >actual &&
+ test_cmp actual expect &&
+
+ # "diff-tree --stdin -v -p" begins with "commit <commit object name>"
+ echo $same | git diff-tree --stdin -p -v >diff-tree-v.output &&
+ git patch-id <diff-tree-v.output >actual &&
+ test_cmp actual expect
+'
+
+hash=$(git rev-parse same:)
+for cruft in "$hash" "commit $hash is bad" "From $hash status"
+do
+ test_expect_success "patch-id with <$cruft> in log message" '
+ git format-patch -1 --stdout same >patch-0 &&
+ git patch-id <patch-0 >expect &&
+
+ {
+ sed -e "/^$/q" patch-0 &&
+ printf "random message\n%s\n\n" "$cruft" &&
+ sed -e "1,/^$/d" patch-0
+ } >patch-cruft &&
+ git patch-id <patch-cruft >actual &&
+ test_cmp actual expect
+ '
+done
+
test_expect_success 'whitespace is irrelevant in footer' '
get_patch_id main &&
git checkout same &&
diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh
index 806b2809d4..2a46eb6bed 100755
--- a/t/t4208-log-magic-pathspec.sh
+++ b/t/t4208-log-magic-pathspec.sh
@@ -5,6 +5,7 @@ test_description='magic pathspec tests using git-log'
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/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 2ba0324a69..3f163dc396 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -82,7 +82,23 @@ test_bloom_filters_used () {
test_bloom_filters_not_used () {
log_args=$1
setup "$log_args" &&
- ! grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf" &&
+
+ if grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf"
+ then
+ # if the Bloom filter system is initialized, ensure that no
+ # filters were used
+ data="statistics:{"
+ # unusable filters (e.g., those computed with a
+ # different value of commitGraph.changedPathsVersion)
+ # are counted in the filter_not_present bucket, so any
+ # value is OK there.
+ data="$data\"filter_not_present\":[0-9][0-9]*,"
+ data="$data\"maybe\":0,"
+ data="$data\"definitely_not\":0,"
+ data="$data\"false_positive\":0}"
+
+ grep -q "$data" "$TRASH_DIRECTORY/trace.perf"
+ fi &&
test_cmp log_wo_bloom log_w_bloom
}
@@ -163,7 +179,7 @@ test_expect_success 'setup - add commit-graph to the chain with Bloom filters' '
test_bloom_filters_used_when_some_filters_are_missing () {
log_args=$1
- bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":9"
+ bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":10"
setup "$log_args" &&
grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
test_cmp log_wo_bloom log_w_bloom
@@ -206,6 +222,10 @@ test_filter_trunc_large () {
grep "\"key\":\"filter-trunc-large\",\"value\":\"$1\"" $2
}
+test_filter_upgraded () {
+ grep "\"key\":\"filter-upgraded\",\"value\":\"$1\"" $2
+}
+
test_expect_success 'correctly report changes over limit' '
git init limits &&
(
@@ -405,8 +425,307 @@ test_expect_success 'Bloom generation backfills empty commits' '
)
'
+graph=.git/objects/info/commit-graph
+graphdir=.git/objects/info/commit-graphs
+chain=$graphdir/commit-graph-chain
+
+test_expect_success 'setup for mixed Bloom setting tests' '
+ repo=mixed-bloom-settings &&
+
+ git init $repo &&
+ for i in one two three
+ do
+ test_commit -C $repo $i file || return 1
+ done
+'
+
+test_expect_success 'ensure Bloom filters with incompatible settings are ignored' '
+ # Compute Bloom filters with "unusual" settings.
+ git -C $repo rev-parse one >in &&
+ GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=3 git -C $repo commit-graph write \
+ --stdin-commits --changed-paths --split <in &&
+ layer=$(head -n 1 $repo/$chain) &&
+
+ # A commit-graph layer without Bloom filters "hides" the layers
+ # below ...
+ git -C $repo rev-parse two >in &&
+ git -C $repo commit-graph write --stdin-commits --no-changed-paths \
+ --split=no-merge <in &&
+
+ # Another commit-graph layer that has Bloom filters, but with
+ # standard settings, and is thus incompatible with the base
+ # layer written above.
+ git -C $repo rev-parse HEAD >in &&
+ git -C $repo commit-graph write --stdin-commits --changed-paths \
+ --split=no-merge <in &&
+
+ test_line_count = 3 $repo/$chain &&
+
+ # Ensure that incompatible Bloom filters are ignored.
+ git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- file \
+ >expect 2>err &&
+ git -C $repo log --oneline --no-decorate -- file >actual 2>err &&
+ test_cmp expect actual &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err
+'
+
+test_expect_success 'merge graph layers with incompatible Bloom settings' '
+ # Ensure that incompatible Bloom filters are ignored when
+ # merging existing layers.
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C $repo commit-graph write --reachable --changed-paths 2>err &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err &&
+ grep "{\"hash_version\":1,\"num_hashes\":7,\"bits_per_entry\":10,\"max_changed_paths\":512" trace2.txt &&
+
+ test_path_is_file $repo/$graph &&
+ test_dir_is_empty $repo/$graphdir &&
+
+ git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- \
+ file >expect &&
+ trace_out="$(pwd)/trace.perf" &&
+ GIT_TRACE2_PERF="$trace_out" \
+ git -C $repo log --oneline --no-decorate -- file >actual 2>err &&
+
+ test_cmp expect actual &&
+ grep "statistics:{\"filter_not_present\":0," trace.perf &&
+ test_must_be_empty err
+'
+
+# chosen to be the same under all Unicode normalization forms
+CENT=$(printf "\302\242")
+
+test_expect_success 'ensure Bloom filter with incompatible versions are ignored' '
+ rm "$repo/$graph" &&
+
+ git -C $repo log --oneline --no-decorate -- $CENT >expect &&
+
+ # Compute v1 Bloom filters for commits at the bottom.
+ git -C $repo rev-parse HEAD^ >in &&
+ git -C $repo commit-graph write --stdin-commits --changed-paths \
+ --split <in &&
+
+ # Compute v2 Bloomfilters for the rest of the commits at the top.
+ git -C $repo rev-parse HEAD >in &&
+ git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write \
+ --stdin-commits --changed-paths --split=no-merge <in &&
+
+ test_line_count = 2 $repo/$chain &&
+
+ git -C $repo log --oneline --no-decorate -- $CENT >actual 2>err &&
+ test_cmp expect actual &&
+
+ layer="$(head -n 1 $repo/$chain)" &&
+ cat >expect.err <<-EOF &&
+ warning: disabling Bloom filters for commit-graph layer $SQ$layer$SQ due to incompatible settings
+ EOF
+ test_cmp expect.err err &&
+
+ # Merge the two layers with incompatible bloom filter versions,
+ # ensuring that the v2 filters are used.
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write --reachable --changed-paths 2>err &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err &&
+ grep "{\"hash_version\":2,\"num_hashes\":7,\"bits_per_entry\":10,\"max_changed_paths\":512" trace2.txt
+'
+
+get_first_changed_path_filter () {
+ test-tool read-graph bloom-filters >filters.dat &&
+ head -n 1 filters.dat
+}
+
+test_expect_success 'set up repo with high bit path, version 1 changed-path' '
+ git init highbit1 &&
+ test_commit -C highbit1 c1 "$CENT" &&
+ git -C highbit1 commit-graph write --reachable --changed-paths
+'
+
+test_expect_success 'setup check value of version 1 changed-path' '
+ (
+ cd highbit1 &&
+ echo "52a9" >expect &&
+ get_first_changed_path_filter >actual
+ )
+'
+
+# expect will not match actual if char is unsigned by default. Write the test
+# in this way, so that a user running this test script can still see if the two
+# files match. (It will appear as an ordinary success if they match, and a skip
+# if not.)
+if test_cmp highbit1/expect highbit1/actual
+then
+ test_set_prereq SIGNED_CHAR_BY_DEFAULT
+fi
+test_expect_success SIGNED_CHAR_BY_DEFAULT 'check value of version 1 changed-path' '
+ # Only the prereq matters for this test.
+ true
+'
+
+test_expect_success 'setup make another commit' '
+ # "git log" does not use Bloom filters for root commits - see how, in
+ # revision.c, rev_compare_tree() (the only code path that eventually calls
+ # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit
+ # has one parent. Therefore, make another commit so that we perform the tests on
+ # a non-root commit.
+ test_commit -C highbit1 anotherc1 "another$CENT"
+'
+
+test_expect_success 'version 1 changed-path used when version 1 requested' '
+ (
+ cd highbit1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 1 changed-path not used when version 2 requested' '
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion 2 &&
+ test_bloom_filters_not_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 1 changed-path used when autodetect requested' '
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'when writing another commit graph, preserve existing version 1 of changed-path' '
+ test_commit -C highbit1 c1double "$CENT$CENT" &&
+ git -C highbit1 commit-graph write --reachable --changed-paths &&
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ echo "options: bloom(1,10,7) read_generation_data" >expect &&
+ test-tool read-graph >full &&
+ grep options full >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'set up repo with high bit path, version 2 changed-path' '
+ git init highbit2 &&
+ git -C highbit2 config --add commitGraph.changedPathsVersion 2 &&
+ test_commit -C highbit2 c2 "$CENT" &&
+ git -C highbit2 commit-graph write --reachable --changed-paths
+'
+
+test_expect_success 'check value of version 2 changed-path' '
+ (
+ cd highbit2 &&
+ echo "c01f" >expect &&
+ get_first_changed_path_filter >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'setup make another commit' '
+ # "git log" does not use Bloom filters for root commits - see how, in
+ # revision.c, rev_compare_tree() (the only code path that eventually calls
+ # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit
+ # has one parent. Therefore, make another commit so that we perform the tests on
+ # a non-root commit.
+ test_commit -C highbit2 anotherc2 "another$CENT"
+'
+
+test_expect_success 'version 2 changed-path used when version 2 requested' '
+ (
+ cd highbit2 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 2 changed-path not used when version 1 requested' '
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion 1 &&
+ test_bloom_filters_not_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 2 changed-path used when autodetect requested' '
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'when writing another commit graph, preserve existing version 2 of changed-path' '
+ test_commit -C highbit2 c2double "$CENT$CENT" &&
+ git -C highbit2 commit-graph write --reachable --changed-paths &&
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ echo "options: bloom(2,10,7) read_generation_data" >expect &&
+ test-tool read-graph >full &&
+ grep options full >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'when writing commit graph, do not reuse changed-path of another version' '
+ git init doublewrite &&
+ test_commit -C doublewrite c "$CENT" &&
+
+ git -C doublewrite config --add commitGraph.changedPathsVersion 1 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ for v in -2 3
+ do
+ git -C doublewrite config --add commitGraph.changedPathsVersion $v &&
+ git -C doublewrite commit-graph write --reachable --changed-paths 2>err &&
+ cat >expect <<-EOF &&
+ warning: attempting to write a commit-graph, but ${SQ}commitGraph.changedPathsVersion${SQ} ($v) is not supported
+ EOF
+ test_cmp expect err || return 1
+ done &&
+
+ git -C doublewrite config --add commitGraph.changedPathsVersion 2 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ (
+ cd doublewrite &&
+ echo "c01f" >expect &&
+ get_first_changed_path_filter >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'when writing commit graph, reuse changed-path of another version where possible' '
+ git init upgrade &&
+
+ test_commit -C upgrade base no-high-bits &&
+
+ git -C upgrade config --add commitGraph.changedPathsVersion 1 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C upgrade commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ git -C upgrade config --add commitGraph.changedPathsVersion 2 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C upgrade commit-graph write --reachable --changed-paths &&
+ test_filter_computed 0 trace2.txt &&
+ test_filter_upgraded 1 trace2.txt
+'
+
corrupt_graph () {
- graph=.git/objects/info/commit-graph &&
test_when_finished "rm -rf $graph" &&
git commit-graph write --reachable --changed-paths &&
corrupt_chunk_file $graph "$@"
diff --git a/t/t4253-am-keep-cr-dos.sh b/t/t4253-am-keep-cr-dos.sh
index 0ee69d2a0c..2bcdd9f34f 100755
--- a/t/t4253-am-keep-cr-dos.sh
+++ b/t/t4253-am-keep-cr-dos.sh
@@ -9,6 +9,7 @@ test_description='git-am mbox with dos line ending.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Three patches which will be added as files with dos line ending.
diff --git a/t/t4255-am-submodule.sh b/t/t4255-am-submodule.sh
index a7ba08f728..04f3ccfc41 100755
--- a/t/t4255-am-submodule.sh
+++ b/t/t4255-am-submodule.sh
@@ -2,6 +2,7 @@
test_description='git am handling submodules'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-submodule-update.sh
diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh
index cb67bac1c4..86bee33160 100755
--- a/t/t5150-request-pull.sh
+++ b/t/t5150-request-pull.sh
@@ -5,6 +5,7 @@ test_description='Test workflows involving pull request.'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
if ! test_have_prereq PERL
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index 61e2be2903..4ad023c846 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -3,9 +3,9 @@
# Copyright (c) 2005 Junio C Hamano
#
-test_description='git pack-object
+test_description='git pack-object'
-'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index 44bd9ef45f..dc8fe55c82 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -4,6 +4,7 @@ test_description='git pack-object --include-tag'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
TRASH=$(pwd)
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index a2b4442660..2916c07e3c 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='commit graph'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-chunk.sh
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index 10d2a6bf92..ace5ac3b61 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -1027,6 +1027,61 @@ test_expect_success 'repack --batch-size=<large> repacks everything' '
)
'
+test_expect_success 'repack/expire loop' '
+ git init repack-expire &&
+ test_when_finished "rm -fr repack-expire" &&
+ (
+ cd repack-expire &&
+
+ test_commit_bulk 5 &&
+
+ # Create three overlapping pack-files
+ git rev-list --objects HEAD~3 >in-1 &&
+ git rev-list --objects HEAD~4..HEAD~2 >in-2 &&
+ git rev-list --objects HEAD~3..HEAD >in-3 &&
+
+ # Create disconnected blobs
+ obj1=$(git hash-object -w in-1) &&
+ obj2=$(git hash-object -w in-2) &&
+ obj3=$(git hash-object -w in-3) &&
+
+ echo $obj2 >>in-2 &&
+ echo $obj3 >>in-3 &&
+
+ for i in $(test_seq 3)
+ do
+ git pack-objects .git/objects/pack/test-$i <in-$i \
+ || return 1
+ done &&
+
+ rm -fr .git/objects/pack/pack-* &&
+ git multi-pack-index write &&
+
+ for i in $(test_seq 3)
+ do
+ for file in $(ls .git/objects/pack/test-$i*)
+ do
+ test-tool chmtime =+$((3600*$i-25000)) $file || return 1
+ done || return 1
+ done &&
+
+ pack1=$(ls .git/objects/pack/test-1-*.pack) &&
+ pack2=$(ls .git/objects/pack/test-2-*.pack) &&
+ pack3=$(ls .git/objects/pack/test-3-*.pack) &&
+
+ # Prevent test-1 from being rewritten.
+ touch "${pack1%.pack}.keep" &&
+
+ # This repack-expire loop should repack all non-kept packs
+ # into a new pack and then delete the old packs.
+ git multi-pack-index repack &&
+ git multi-pack-index expire &&
+
+ test_path_is_missing $pack3 &&
+ test_path_is_missing $pack2
+ )
+'
+
test_expect_success 'load reverse index when missing .idx, .pack' '
git init repo &&
test_when_finished "rm -fr repo" &&
diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh
index ad7f8c6f00..e99e728236 100755
--- a/t/t5407-post-rewrite-hook.sh
+++ b/t/t5407-post-rewrite-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-rewrite hook.'
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/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 42e77eb5a9..d64b40e408 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -5,6 +5,7 @@ test_description='git ls-remote'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
generate_references () {
@@ -402,4 +403,17 @@ test_expect_success 'v0 clients can handle multiple symrefs' '
test_cmp expect actual
'
+test_expect_success 'helper with refspec capability fails gracefully' '
+ mkdir test-bin &&
+ write_script test-bin/git-remote-foo <<-EOF &&
+ echo import
+ echo refspec ${SQ}*:*${SQ}
+ EOF
+ (
+ PATH="$PWD/test-bin:$PATH" &&
+ export PATH &&
+ test_must_fail nongit git ls-remote foo::bar
+ )
+'
+
test_done
diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh
index 25772c85c5..579872c258 100755
--- a/t/t5514-fetch-multiple.sh
+++ b/t/t5514-fetch-multiple.sh
@@ -5,6 +5,7 @@ test_description='fetch --all works correctly'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
setup_repository () {
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 2e7c0e1648..9d693eb57f 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -230,6 +230,16 @@ test_expect_success 'push with negotiation proceeds anyway even if negotiation f
test_grep "push negotiation failed" err
'
+test_expect_success 'push deletion with negotiation' '
+ mk_empty testrepo &&
+ git push testrepo $the_first_commit:refs/heads/master &&
+ git -c push.negotiate=1 push testrepo \
+ :master $the_first_commit:refs/heads/next 2>errors-2 &&
+ test_grep ! "negotiate-only needs one or " errors-2 &&
+ git -c push.negotiate=1 push testrepo :next 2>errors-1 &&
+ test_grep ! "negotiate-only needs one or " errors-1
+'
+
test_expect_success 'push with negotiation does not attempt to fetch submodules' '
mk_empty submodule_upstream &&
test_commit -C submodule_upstream submodule_commit &&
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 47534f1062..1098cbd0a1 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -5,6 +5,7 @@ test_description='pulling into void'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
modify () {
diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh
index 14f7eced9a..bc2bada34c 100755
--- a/t/t5528-push-default.sh
+++ b/t/t5528-push-default.sh
@@ -4,6 +4,7 @@ test_description='check various push.default settings'
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 bare remotes' '
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
index 0247137cb3..17d7257892 100755
--- a/t/t5529-push-errors.sh
+++ b/t/t5529-push-errors.sh
@@ -2,6 +2,9 @@
test_description='detect some push errors early (before contacting remote)'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
@@ -38,6 +41,20 @@ test_expect_success 'detect missing sha1 expressions early' '
test_cmp expect rp-ran
'
+# We use an existing local_ref, since it follows a different flow in
+# 'builtin/push.c:set_refspecs()' and we want to test that regression.
+test_expect_success 'detect empty remote with existing local ref' '
+ test_must_fail git push "" main 2> stderr &&
+ grep "fatal: bad repository ${SQ}${SQ}" stderr
+'
+
+# While similar to the previous test, here we want to ensure that
+# even targeted refspecs are handled.
+test_expect_success 'detect empty remote with targeted refspec' '
+ test_must_fail git push "" HEAD:refs/heads/main 2> stderr &&
+ grep "fatal: bad repository ${SQ}${SQ}" stderr
+'
+
test_expect_success 'detect ambiguous refs early' '
git branch foo &&
git tag foo &&
diff --git a/t/t5535-fetch-push-symref.sh b/t/t5535-fetch-push-symref.sh
index e8f6d233ff..7122af7fdb 100755
--- a/t/t5535-fetch-push-symref.sh
+++ b/t/t5535-fetch-push-symref.sh
@@ -2,6 +2,7 @@
test_description='avoiding conflicting update through symref aliasing'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh
index 04b47ad84a..479d103469 100755
--- a/t/t5543-atomic-push.sh
+++ b/t/t5543-atomic-push.sh
@@ -5,6 +5,7 @@ test_description='pushing to a repository using the atomic push option'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
mk_repo_pair () {
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index a623a1058c..7b5ab0eae1 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -643,7 +643,6 @@ test_expect_success 'clone empty SHA-256 repository with protocol v0' '
test_expect_success 'passing hostname resolution information works' '
BOGUS_HOST=gitbogusexamplehost.invalid &&
BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&
- test_must_fail git ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null &&
git -c "http.curloptResolve=$BOGUS_HOST:$LIB_HTTPD_PORT:127.0.0.1" ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null
'
diff --git a/t/t5553-set-upstream.sh b/t/t5553-set-upstream.sh
index 48050162c2..70e3376d31 100755
--- a/t/t5553-set-upstream.sh
+++ b/t/t5553-set-upstream.sh
@@ -73,10 +73,10 @@ test_expect_success 'fetch --set-upstream main:other does not set the branch oth
check_config_missing other2
'
-test_expect_success 'fetch --set-upstream http://nosuchdomain.example.com fails with invalid url' '
+test_expect_success 'fetch --set-upstream ./does-not-exist fails with invalid url' '
# main explicitly not cleared, we check that it is not touched from previous value
clear_config other other2 &&
- test_must_fail git fetch --set-upstream http://nosuchdomain.example.com &&
+ test_must_fail git fetch --set-upstream ./does-not-exist &&
check_config main upstream refs/heads/other &&
check_config_missing other &&
check_config_missing other2
@@ -143,10 +143,10 @@ test_expect_success 'pull --set-upstream upstream tag does not set the tag' '
check_config_missing three
'
-test_expect_success 'pull --set-upstream http://nosuchdomain.example.com fails with invalid url' '
+test_expect_success 'pull --set-upstream ./does-not-exist fails with invalid url' '
# main explicitly not cleared, we check that it is not touched from previous value
clear_config other other2 three &&
- test_must_fail git pull --set-upstream http://nosuchdomain.example.com &&
+ test_must_fail git pull --set-upstream ./does-not-exist &&
check_config main upstream refs/heads/other &&
check_config_missing other &&
check_config_missing other2 &&
diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh
index 1ca5f745e7..cd05321e17 100755
--- a/t/t5558-clone-bundle-uri.sh
+++ b/t/t5558-clone-bundle-uri.sh
@@ -3,6 +3,7 @@
test_description='test fetching bundles with --bundle-uri'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-bundle.sh
test_expect_success 'fail to clone from non-existent file' '
test_when_finished rm -rf test &&
@@ -19,10 +20,39 @@ test_expect_success 'fail to clone from non-bundle file' '
test_expect_success 'create bundle' '
git init clone-from &&
- git -C clone-from checkout -b topic &&
- test_commit -C clone-from A &&
- test_commit -C clone-from B &&
- git -C clone-from bundle create B.bundle topic
+ (
+ cd clone-from &&
+ git checkout -b topic &&
+
+ test_commit A &&
+ git bundle create A.bundle topic &&
+
+ test_commit B &&
+ git bundle create B.bundle topic &&
+
+ # Create a bundle with reference pointing to non-existent object.
+ commit_a=$(git rev-parse A) &&
+ commit_b=$(git rev-parse B) &&
+ sed -e "/^$/q" -e "s/$commit_a /$commit_b /" \
+ <A.bundle >bad-header.bundle &&
+ convert_bundle_to_pack \
+ <A.bundle >>bad-header.bundle &&
+
+ tree_b=$(git rev-parse B^{tree}) &&
+ cat >data <<-EOF &&
+ tree $tree_b
+ parent $commit_b
+ author A U Thor
+ committer A U Thor
+
+ commit: this is a commit with bad emails
+
+ EOF
+ bad_commit=$(git hash-object --literally -t commit -w --stdin <data) &&
+ git branch bad $bad_commit &&
+ git bundle create bad-object.bundle bad &&
+ git update-ref -d refs/heads/bad
+ )
'
test_expect_success 'clone with path bundle' '
@@ -33,6 +63,33 @@ test_expect_success 'clone with path bundle' '
test_cmp expect actual
'
+test_expect_success 'clone with bundle that has bad header' '
+ # Write bundle ref fails, but clone can still proceed.
+ git clone --bundle-uri="clone-from/bad-header.bundle" \
+ clone-from clone-bad-header 2>err &&
+ commit_b=$(git -C clone-from rev-parse B) &&
+ test_grep "trying to write ref '\''refs/bundles/topic'\'' with nonexistent object $commit_b" err &&
+ git -C clone-bad-header for-each-ref --format="%(refname)" >refs &&
+ test_grep ! "refs/bundles/" refs
+'
+
+test_expect_success 'clone with bundle that has bad object' '
+ # Unbundle succeeds if no fsckObjects configured.
+ git clone --bundle-uri="clone-from/bad-object.bundle" \
+ clone-from clone-bad-object-no-fsck &&
+ git -C clone-bad-object-no-fsck for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ test_write_lines refs/bundles/bad >expect &&
+ test_cmp expect actual &&
+
+ # Unbundle fails with fsckObjects set true, but clone can still proceed.
+ git -c fetch.fsckObjects=true clone --bundle-uri="clone-from/bad-object.bundle" \
+ clone-from clone-bad-object-fsck 2>err &&
+ test_grep "missingEmail" err &&
+ git -C clone-bad-object-fsck for-each-ref --format="%(refname)" >refs &&
+ test_grep ! "refs/bundles/" refs
+'
+
test_expect_success 'clone with path bundle and non-default hash' '
test_when_finished "rm -rf clone-path-non-default-hash" &&
GIT_DEFAULT_HASH=sha256 git clone --bundle-uri="clone-from/B.bundle" \
@@ -259,6 +316,128 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' '
! grep "refs/bundles/" refs
'
+test_expect_success 'negotiation: bundle with part of wanted commits' '
+ test_when_finished "rm -f trace*.txt" &&
+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
+ git clone --no-local --bundle-uri="clone-from/A.bundle" \
+ clone-from nego-bundle-part &&
+ git -C nego-bundle-part for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ test_write_lines refs/bundles/topic >expect &&
+ test_cmp expect actual &&
+ # Ensure that refs/bundles/topic are sent as "have".
+ tip=$(git -C clone-from rev-parse A) &&
+ test_grep "clone> have $tip" trace-packet.txt
+'
+
+test_expect_success 'negotiation: bundle with all wanted commits' '
+ test_when_finished "rm -f trace*.txt" &&
+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
+ git clone --no-local --single-branch --branch=topic --no-tags \
+ --bundle-uri="clone-from/B.bundle" \
+ clone-from nego-bundle-all &&
+ git -C nego-bundle-all for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ test_write_lines refs/bundles/topic >expect &&
+ test_cmp expect actual &&
+ # We already have all needed commits so no "want" needed.
+ test_grep ! "clone> want " trace-packet.txt
+'
+
+test_expect_success 'negotiation: bundle list (no heuristic)' '
+ test_when_finished "rm -f trace*.txt" &&
+ cat >bundle-list <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+
+ [bundle "bundle-1"]
+ uri = file://$(pwd)/clone-from/bundle-1.bundle
+
+ [bundle "bundle-2"]
+ uri = file://$(pwd)/clone-from/bundle-2.bundle
+ EOF
+
+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
+ git clone --no-local --bundle-uri="file://$(pwd)/bundle-list" \
+ clone-from nego-bundle-list-no-heuristic &&
+
+ git -C nego-bundle-list-no-heuristic for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ EOF
+ test_cmp expect actual &&
+ tip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) &&
+ test_grep "clone> have $tip" trace-packet.txt
+'
+
+test_expect_success 'negotiation: bundle list (creationToken)' '
+ test_when_finished "rm -f trace*.txt" &&
+ cat >bundle-list <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = file://$(pwd)/clone-from/bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = file://$(pwd)/clone-from/bundle-2.bundle
+ creationToken = 2
+ EOF
+
+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
+ git clone --no-local --bundle-uri="file://$(pwd)/bundle-list" \
+ clone-from nego-bundle-list-heuristic &&
+
+ git -C nego-bundle-list-heuristic for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ EOF
+ test_cmp expect actual &&
+ tip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) &&
+ test_grep "clone> have $tip" trace-packet.txt
+'
+
+test_expect_success 'negotiation: bundle list with all wanted commits' '
+ test_when_finished "rm -f trace*.txt" &&
+ cat >bundle-list <<-EOF &&
+ [bundle]
+ version = 1
+ mode = all
+ heuristic = creationToken
+
+ [bundle "bundle-1"]
+ uri = file://$(pwd)/clone-from/bundle-1.bundle
+ creationToken = 1
+
+ [bundle "bundle-2"]
+ uri = file://$(pwd)/clone-from/bundle-2.bundle
+ creationToken = 2
+ EOF
+
+ GIT_TRACE_PACKET="$(pwd)/trace-packet.txt" \
+ git clone --no-local --single-branch --branch=left --no-tags \
+ --bundle-uri="file://$(pwd)/bundle-list" \
+ clone-from nego-bundle-list-all &&
+
+ git -C nego-bundle-list-all for-each-ref --format="%(refname)" >refs &&
+ grep "refs/bundles/" refs >actual &&
+ cat >expect <<-\EOF &&
+ refs/bundles/base
+ refs/bundles/left
+ EOF
+ test_cmp expect actual &&
+ # We already have all needed commits so no "want" needed.
+ test_grep ! "clone> want " trace-packet.txt
+'
+
#########################################################################
# HTTP tests begin here
diff --git a/t/t5563-simple-http-auth.sh b/t/t5563-simple-http-auth.sh
index 4af796de67..ba03f6a09f 100755
--- a/t/t5563-simple-http-auth.sh
+++ b/t/t5563-simple-http-auth.sh
@@ -178,6 +178,122 @@ test_expect_success 'access using basic auth invalid credentials' '
EOF
'
+test_expect_success 'access using basic proactive auth' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default status=403
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ test_config_global http.proactiveAuth basic &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=Basic
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using auto proactive auth with basic default' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default status=403
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ test_config_global http.proactiveAuth auto &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using auto proactive auth with authtype from credential helper' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ capability[]=authtype
+ authtype=Bearer
+ credential=YS1naXQtdG9rZW4=
+ EOF
+
+ # Basic base64(a-git-token)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Bearer YS1naXQtdG9rZW4=
+ EOF
+
+ CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default status=403
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ test_config_global http.proactiveAuth auto &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ EOF
+
+ expect_credential_query store <<-EOF
+ capability[]=authtype
+ authtype=Bearer
+ credential=YS1naXQtdG9rZW4=
+ protocol=http
+ host=$HTTPD_DEST
+ EOF
+'
+
test_expect_success 'access using basic auth with extra challenges' '
test_when_finished "per_test_cleanup" &&
diff --git a/t/t5564-http-proxy.sh b/t/t5564-http-proxy.sh
index bb35b87071..4aef99bc28 100755
--- a/t/t5564-http-proxy.sh
+++ b/t/t5564-http-proxy.sh
@@ -39,4 +39,59 @@ test_expect_success 'clone can prompt for proxy password' '
expect_askpass pass proxuser
'
+start_socks() {
+ mkfifo socks_output &&
+ {
+ "$PERL_PATH" "$TEST_DIRECTORY/socks4-proxy.pl" "$1" >socks_output &
+ echo $! > "$TRASH_DIRECTORY/socks.pid"
+ } &&
+ read line <socks_output &&
+ test "$line" = ready
+}
+
+# The %30 tests that the correct amount of percent-encoding is applied to the
+# proxy string passed to curl.
+test_lazy_prereq SOCKS_PROXY '
+ test_have_prereq PERL &&
+ start_socks "$TRASH_DIRECTORY/%30.sock"
+'
+
+test_atexit '
+ test ! -e "$TRASH_DIRECTORY/socks.pid" ||
+ kill "$(cat "$TRASH_DIRECTORY/socks.pid")"
+'
+
+# The below tests morally ought to be gated on a prerequisite that Git is
+# linked with a libcurl that supports Unix socket paths for proxies (7.84 or
+# later), but this is not easy to test right now. Instead, we || the tests with
+# this function.
+old_libcurl_error() {
+ grep -Fx "fatal: libcurl 7.84 or later is required to support paths in proxy URLs" "$1"
+}
+
+test_expect_success SOCKS_PROXY 'clone via Unix socket' '
+ test_when_finished "rm -rf clone" &&
+ test_config_global http.proxy "socks4://localhost$PWD/%2530.sock" && {
+ {
+ GIT_TRACE_CURL=$PWD/trace git clone "$HTTPD_URL/smart/repo.git" clone 2>err &&
+ grep -i "SOCKS4 request granted" trace
+ } ||
+ old_libcurl_error err
+ }
+'
+
+test_expect_success 'Unix socket requires socks*:' - <<\EOT
+ ! git clone -c http.proxy=localhost/path https://example.com/repo.git 2>err && {
+ grep -Fx "fatal: Invalid proxy URL 'localhost/path': only SOCKS proxies support paths" err ||
+ old_libcurl_error err
+ }
+EOT
+
+test_expect_success 'Unix socket requires localhost' - <<\EOT
+ ! git clone -c http.proxy=socks4://127.0.0.1/path https://example.com/repo.git 2>err && {
+ grep -Fx "fatal: Invalid proxy URL 'socks4://127.0.0.1/path': host must be localhost if a path is present" err ||
+ old_libcurl_error err
+ }
+EOT
+
test_done
diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh
index f9a9bf9503..c5f08b6799 100755
--- a/t/t5570-git-daemon.sh
+++ b/t/t5570-git-daemon.sh
@@ -4,6 +4,7 @@ test_description='test fetching over git protocol'
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-git-daemon.sh
diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh
index 339d8c786f..d9a320abd2 100755
--- a/t/t5605-clone-local.sh
+++ b/t/t5605-clone-local.sh
@@ -4,6 +4,7 @@ test_description='test local clone'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
repo_is_hardlinked() {
diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh
index 0d1e92d996..7ceaa8194d 100755
--- a/t/t5607-clone-bundle.sh
+++ b/t/t5607-clone-bundle.sh
@@ -4,6 +4,7 @@ test_description='some bundle related tests'
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' '
@@ -138,6 +139,41 @@ test_expect_success 'fetch SHA-1 from bundle' '
git fetch --no-tags foo/tip.bundle "$(cat hash)"
'
+test_expect_success 'clone bundle with different fsckObjects configurations' '
+ test_create_repo bundle-fsck &&
+ (
+ cd bundle-fsck &&
+ test_commit A &&
+ commit_a=$(git rev-parse A) &&
+ tree_a=$(git rev-parse A^{tree}) &&
+ cat >data <<-EOF &&
+ tree $tree_a
+ parent $commit_a
+ author A U Thor
+ committer A U Thor
+
+ commit: this is a commit with bad emails
+
+ EOF
+ bad_commit=$(git hash-object --literally -t commit -w --stdin <data) &&
+ git branch bad $bad_commit &&
+ git bundle create bad.bundle bad
+ ) &&
+
+ git clone bundle-fsck/bad.bundle bundle-no-fsck &&
+
+ git -c fetch.fsckObjects=false -c transfer.fsckObjects=true \
+ clone bundle-fsck/bad.bundle bundle-fetch-no-fsck &&
+
+ test_must_fail git -c fetch.fsckObjects=true \
+ clone bundle-fsck/bad.bundle bundle-fetch-fsck 2>err &&
+ test_grep "missingEmail" err &&
+
+ test_must_fail git -c transfer.fsckObjects=true \
+ clone bundle-fsck/bad.bundle bundle-transfer-fsck 2>err &&
+ test_grep "missingEmail" err
+'
+
test_expect_success 'git bundle uses expected default format' '
git bundle create bundle HEAD^.. &&
cat >expect <<-EOF &&
diff --git a/t/t5612-clone-refspec.sh b/t/t5612-clone-refspec.sh
index 3126cfd7e9..72762de977 100755
--- a/t/t5612-clone-refspec.sh
+++ b/t/t5612-clone-refspec.sh
@@ -4,6 +4,7 @@ test_description='test refspec written by clone-command'
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/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index 6289a2e8b0..f6d17ee902 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -5,6 +5,7 @@ test_description='miscellaneous rev-list tests'
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/t6001-rev-list-graft.sh b/t/t6001-rev-list-graft.sh
index 73a2465aa0..3553bbbfe7 100755
--- a/t/t6001-rev-list-graft.sh
+++ b/t/t6001-rev-list-graft.sh
@@ -5,6 +5,7 @@ test_description='Revision traversal vs grafts and path limiter'
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/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh
index 6f3e543977..2d337d7287 100755
--- a/t/t6007-rev-list-cherry-pick-file.sh
+++ b/t/t6007-rev-list-cherry-pick-file.sh
@@ -5,6 +5,7 @@ test_description='test git rev-list --cherry-pick -- file'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# A---B---D---F
diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh
index 44c726ea39..f96ea82e78 100755
--- a/t/t6010-merge-base.sh
+++ b/t/t6010-merge-base.sh
@@ -6,6 +6,7 @@
test_description='Merge base and parent list computation.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
M=1130000000
diff --git a/t/t6013-rev-list-reverse-parents.sh b/t/t6013-rev-list-reverse-parents.sh
index 39793cbbd6..4128269c1d 100755
--- a/t/t6013-rev-list-reverse-parents.sh
+++ b/t/t6013-rev-list-reverse-parents.sh
@@ -5,6 +5,7 @@ test_description='--reverse combines with --parents'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t6017-rev-list-stdin.sh b/t/t6017-rev-list-stdin.sh
index 4821b90e74..a0a40fe55c 100755
--- a/t/t6017-rev-list-stdin.sh
+++ b/t/t6017-rev-list-stdin.sh
@@ -8,6 +8,7 @@ test_description='log family learns --stdin'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check () {
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
index 3e6bcbf30c..fe75a06572 100755
--- a/t/t6020-bundle-misc.sh
+++ b/t/t6020-bundle-misc.sh
@@ -8,6 +8,7 @@ test_description='Test git-bundle'
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-bundle.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t6115-rev-list-du.sh b/t/t6115-rev-list-du.sh
index c0cfda62fa..21c4a211b1 100755
--- a/t/t6115-rev-list-du.sh
+++ b/t/t6115-rev-list-du.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='basic tests of rev-list --disk-usage'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# we want a mix of reachable and unreachable, as well as
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index e78315d23d..05ed2510d9 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -14,6 +14,7 @@ test_description='test describe'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_describe () {
@@ -671,4 +672,40 @@ test_expect_success 'setup misleading taggerdates' '
check_describe newer-tag-older-commit~1 --contains unique-file~2
+test_expect_success 'describe --dirty with a file with changed stat' '
+ test_when_finished "rm -fr stat-dirty" &&
+ git init stat-dirty &&
+ (
+ cd stat-dirty &&
+
+ echo A >file &&
+ git add file &&
+ git commit -m A &&
+ git tag A -a -m A &&
+ echo "A" >expect &&
+
+ test-tool chmtime -10 file &&
+ git describe --dirty >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'describe --broken --dirty with a file with changed stat' '
+ test_when_finished "rm -fr stat-dirty" &&
+ git init stat-dirty &&
+ (
+ cd stat-dirty &&
+
+ echo A >file &&
+ git add file &&
+ git commit -m A &&
+ git tag A -a -m A &&
+ echo "A" >expect &&
+
+ test-tool chmtime -10 file &&
+ git describe --dirty --broken >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh
index ba7902c9cd..82de25d549 100755
--- a/t/t6130-pathspec-noglob.sh
+++ b/t/t6130-pathspec-noglob.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test globbing (and noglob) of pathspec limiting'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create commits with glob characters' '
diff --git a/t/t6133-pathspec-rev-dwim.sh b/t/t6133-pathspec-rev-dwim.sh
index a290ffca0d..6dd4bbbf9f 100755
--- a/t/t6133-pathspec-rev-dwim.sh
+++ b/t/t6133-pathspec-rev-dwim.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test dwim of revs versus pathspecs in revision parser'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t6402-merge-rename.sh b/t/t6402-merge-rename.sh
index 2738b50c2a..729aac9842 100755
--- a/t/t6402-merge-rename.sh
+++ b/t/t6402-merge-rename.sh
@@ -4,6 +4,7 @@ test_description='Merge-recursive merging renames'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
modify () {
diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh
index 156a1efacf..9bf9524934 100755
--- a/t/t6406-merge-attr.sh
+++ b/t/t6406-merge-attr.sh
@@ -185,7 +185,7 @@ test_expect_success !WINDOWS 'custom merge driver that is killed with a signal'
>./please-abort &&
echo "* merge=custom" >.gitattributes &&
- test_must_fail git merge main 2>err &&
+ test_expect_code 2 git merge main 2>err &&
grep "^error: failed to execute internal merge" err &&
git ls-files -u >output &&
git diff --name-only HEAD >>output &&
@@ -261,4 +261,44 @@ test_expect_success 'binary files with union attribute' '
grep -i "warning.*cannot merge.*HEAD vs. bin-main" output
'
+test_expect_success !WINDOWS 'custom merge driver that is killed with a signal on recursive merge' '
+ test_when_finished "rm -f output please-abort" &&
+ test_when_finished "git checkout side" &&
+
+ git reset --hard anchor &&
+
+ git checkout -b base-a main^ &&
+ echo base-a >text &&
+ git commit -m base-a text &&
+
+ git checkout -b base-b main^ &&
+ echo base-b >text &&
+ git commit -m base-b text &&
+
+ git checkout -b recursive-a base-a &&
+ test_must_fail git merge base-b &&
+ echo recursive-a >text &&
+ git add text &&
+ git commit -m recursive-a &&
+
+ git checkout -b recursive-b base-b &&
+ test_must_fail git merge base-a &&
+ echo recursive-b >text &&
+ git add text &&
+ git commit -m recursive-b &&
+
+ git config --replace-all \
+ merge.custom.driver "./custom-merge %O %A %B 0 %P %S %X %Y" &&
+ git config --replace-all \
+ merge.custom.name "custom merge driver for testing" &&
+
+ >./please-abort &&
+ echo "* merge=custom" >.gitattributes &&
+ test_expect_code 2 git merge recursive-a 2>err &&
+ grep "error: failed to execute internal merge" err &&
+ git ls-files -u >output &&
+ git diff --name-only HEAD >>output &&
+ test_must_be_empty output
+'
+
test_done
diff --git a/t/t6421-merge-partial-clone.sh b/t/t6421-merge-partial-clone.sh
index 711b709e75..b99f29ef9b 100755
--- a/t/t6421-merge-partial-clone.sh
+++ b/t/t6421-merge-partial-clone.sh
@@ -230,8 +230,9 @@ test_expect_merge_algorithm failure success 'Objects downloaded for single relev
grep fetch_count trace.output | cut -d "|" -f 9 | tr -d " ." >actual &&
test_cmp expect actual &&
- # Check the number of fetch commands exec-ed
- grep d0.*fetch.negotiationAlgorithm trace.output >fetches &&
+ # Check the number of fetch commands exec-ed by filtering trace to
+ # child_start events by the top-level program (2nd field == d0)
+ grep " d0 .* child_start .*fetch.negotiationAlgorithm" trace.output >fetches &&
test_line_count = 2 fetches &&
git rev-list --objects --all --missing=print |
@@ -318,8 +319,9 @@ test_expect_merge_algorithm failure success 'Objects downloaded when a directory
grep fetch_count trace.output | cut -d "|" -f 9 | tr -d " ." >actual &&
test_cmp expect actual &&
- # Check the number of fetch commands exec-ed
- grep d0.*fetch.negotiationAlgorithm trace.output >fetches &&
+ # Check the number of fetch commands exec-ed by filtering trace to
+ # child_start events by the top-level program (2nd field == d0)
+ grep " d0 .* child_start .*fetch.negotiationAlgorithm" trace.output >fetches &&
test_line_count = 1 fetches &&
git rev-list --objects --all --missing=print |
@@ -422,8 +424,9 @@ test_expect_merge_algorithm failure success 'Objects downloaded with lots of ren
grep fetch_count trace.output | cut -d "|" -f 9 | tr -d " ." >actual &&
test_cmp expect actual &&
- # Check the number of fetch commands exec-ed
- grep d0.*fetch.negotiationAlgorithm trace.output >fetches &&
+ # Check the number of fetch commands exec-ed by filtering trace to
+ # child_start events by the top-level program (2nd field == d0)
+ grep " d0 .* child_start .*fetch.negotiationAlgorithm" trace.output >fetches &&
test_line_count = 4 fetches &&
git rev-list --objects --all --missing=print |
diff --git a/t/t6427-diff3-conflict-markers.sh b/t/t6427-diff3-conflict-markers.sh
index dd5fe6a402..a13271b349 100755
--- a/t/t6427-diff3-conflict-markers.sh
+++ b/t/t6427-diff3-conflict-markers.sh
@@ -5,6 +5,7 @@ test_description='recursive merge diff3 style conflict markers'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Setup:
diff --git a/t/t6430-merge-recursive.sh b/t/t6430-merge-recursive.sh
index ca15e6dd6d..555f00f78a 100755
--- a/t/t6430-merge-recursive.sh
+++ b/t/t6430-merge-recursive.sh
@@ -5,6 +5,7 @@ test_description='merge-recursive backend test'
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-merge.sh
diff --git a/t/t6432-merge-recursive-space-options.sh b/t/t6432-merge-recursive-space-options.sh
index db4b77e63d..c93538b0c3 100755
--- a/t/t6432-merge-recursive-space-options.sh
+++ b/t/t6432-merge-recursive-space-options.sh
@@ -14,6 +14,7 @@ test_description='merge-recursive space options
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b
diff --git a/t/t6434-merge-recursive-rename-options.sh b/t/t6434-merge-recursive-rename-options.sh
index a11707835b..df1d0c156c 100755
--- a/t/t6434-merge-recursive-rename-options.sh
+++ b/t/t6434-merge-recursive-rename-options.sh
@@ -29,6 +29,7 @@ mentions this in a different context).
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
get_expected_stages () {
diff --git a/t/t6436-merge-overwrite.sh b/t/t6436-merge-overwrite.sh
index 4f4376421e..ccc620477d 100755
--- a/t/t6436-merge-overwrite.sh
+++ b/t/t6436-merge-overwrite.sh
@@ -7,6 +7,7 @@ Do not overwrite changes.'
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/t7006-pager.sh b/t/t7006-pager.sh
index e56ca5b0fa..a0296d6ca4 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -2,6 +2,7 @@
test_description='Test automatic use of a pager.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-pager.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
@@ -725,18 +726,11 @@ test_expect_success TTY 'git discards pager non-zero exit without SIGPIPE' '
test_path_is_file pager-used
'
-test_expect_success TTY 'git skips paging nonexisting command' '
- test_when_finished "rm trace.normal" &&
+test_expect_success TTY 'git errors when asked to execute nonexisting pager' '
+ test_when_finished "rm -f err" &&
test_config core.pager "does-not-exist" &&
- GIT_TRACE2="$(pwd)/trace.normal" &&
- export GIT_TRACE2 &&
- test_when_finished "unset GIT_TRACE2" &&
-
- test_terminal git log &&
-
- grep child_exit trace.normal >child-exits &&
- test_line_count = 1 child-exits &&
- grep " code:-1 " child-exits
+ test_must_fail test_terminal git log 2>err &&
+ test_grep "unable to execute pager" err
'
test_expect_success TTY 'git returns SIGPIPE on propagated signals from pager' '
@@ -762,7 +756,7 @@ test_expect_success TTY 'git returns SIGPIPE on propagated signals from pager' '
test_expect_success TTY 'non-existent pager doesnt cause crash' '
test_config pager.show invalid-pager &&
- test_terminal git show
+ test_must_fail test_terminal git show
'
test_done
diff --git a/t/t7010-setup.sh b/t/t7010-setup.sh
index 520f96d09f..d9add2162e 100755
--- a/t/t7010-setup.sh
+++ b/t/t7010-setup.sh
@@ -2,6 +2,7 @@
test_description='setup taking and sanitizing funny paths'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh
index cd5c20fe51..d984200c17 100755
--- a/t/t7012-skip-worktree-writing.sh
+++ b/t/t7012-skip-worktree-writing.sh
@@ -5,6 +5,7 @@
test_description='test worktree writing operations when skip-worktree is used'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh
index 11884d2fc3..06c1301222 100755
--- a/t/t7064-wtstatus-pv2.sh
+++ b/t/t7064-wtstatus-pv2.sh
@@ -4,6 +4,7 @@ test_description='git status --porcelain=v2
This test exercises porcelain V2 output for git status.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 42352dc0db..2d984eb4c6 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -23,6 +23,7 @@ Test switching across them.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_tick
@@ -497,6 +498,19 @@ test_expect_success 'checkout unmerged stage' '
test ztheirside = "z$(cat file)"
'
+test_expect_success 'checkout --ours is incompatible with switching' '
+ test_must_fail git checkout --ours 2>error &&
+ test_grep "needs the paths to check out" error &&
+
+ test_must_fail git checkout --ours HEAD 2>error &&
+ test_grep "cannot be used with switching" error &&
+
+ test_must_fail git checkout --ours main 2>error &&
+ test_grep "cannot be used with switching" error &&
+
+ git checkout --ours file
+'
+
test_expect_success 'checkout path with --merge from tree-ish is a no-no' '
setup_conflicting_index &&
test_must_fail git checkout -m HEAD -- file
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 981488885f..098d8833b6 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -12,6 +12,7 @@ subcommands of git submodule.
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 - enable local submodules' '
diff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh
index cc12f99f11..52f5e28154 100755
--- a/t/t7501-commit-basic-functionality.sh
+++ b/t/t7501-commit-basic-functionality.sh
@@ -9,6 +9,7 @@ test_description='git commit'
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"
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index 2128142a61..b88383df9e 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -5,6 +5,7 @@ test_description='prepare-commit-msg hook'
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 'set up commits for rebasing' '
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 802f8f704c..cdd5f2c697 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -10,6 +10,7 @@ test_description='git status advice'
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
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index ef54cff4fa..65fd3d8552 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -29,6 +29,7 @@ Testing basic merge operations/option parsing.
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/t7606-merge-custom.sh b/t/t7606-merge-custom.sh
index 81fb7c474c..135cb23085 100755
--- a/t/t7606-merge-custom.sh
+++ b/t/t7606-merge-custom.sh
@@ -14,6 +14,7 @@ Testing a custom strategy.
* (tag: c0) c0
"
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'set up custom strategy' '
diff --git a/t/t7611-merge-abort.sh b/t/t7611-merge-abort.sh
index d6975ca48d..992a8f9874 100755
--- a/t/t7611-merge-abort.sh
+++ b/t/t7611-merge-abort.sh
@@ -25,6 +25,7 @@ Next, test git merge --abort with the following variables:
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/t7615-diff-algo-with-mergy-operations.sh b/t/t7615-diff-algo-with-mergy-operations.sh
new file mode 100755
index 0000000000..9a83be518c
--- /dev/null
+++ b/t/t7615-diff-algo-with-mergy-operations.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='git merge and other operations that rely on merge
+
+Testing the influence of the diff algorithm on the merge output.'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ cp "$TEST_DIRECTORY"/t7615/base.c file.c &&
+ git add file.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ cp "$TEST_DIRECTORY"/t7615/ours.c file.c &&
+ git add file.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ cp "$TEST_DIRECTORY"/t7615/theirs.c file.c &&
+ git add file.c &&
+ git commit -m c2 &&
+ git tag c2
+'
+
+GIT_TEST_MERGE_ALGORITHM=recursive
+
+test_expect_success 'merge c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' '
+ git reset --hard c1 &&
+ test_must_fail git merge -s recursive c2
+'
+
+test_expect_success 'merge c2 to c1 with recursive merge strategy succeeds with -Xdiff-algorithm=histogram' '
+ git reset --hard c1 &&
+ git merge --strategy recursive -Xdiff-algorithm=histogram c2
+'
+
+test_expect_success 'merge c2 to c1 with recursive merge strategy succeeds with diff.algorithm = histogram' '
+ git reset --hard c1 &&
+ git config diff.algorithm histogram &&
+ git merge --strategy recursive c2
+'
+
+test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' '
+ git reset --hard c1 &&
+ test_must_fail git cherry-pick -s recursive c2
+'
+
+test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy succeeds with -Xdiff-algorithm=histogram' '
+ git reset --hard c1 &&
+ git cherry-pick --strategy recursive -Xdiff-algorithm=histogram c2
+'
+
+test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy succeeds with diff.algorithm = histogram' '
+ git reset --hard c1 &&
+ git config diff.algorithm histogram &&
+ git cherry-pick --strategy recursive c2
+'
+
+test_done
diff --git a/t/t7615/base.c b/t/t7615/base.c
new file mode 100644
index 0000000000..c64abc5936
--- /dev/null
+++ b/t/t7615/base.c
@@ -0,0 +1,17 @@
+int f(int x, int y)
+{
+ if (x == 0)
+ {
+ return y;
+ }
+ return x;
+}
+
+int g(size_t u)
+{
+ while (u < 30)
+ {
+ u++;
+ }
+ return u;
+}
diff --git a/t/t7615/ours.c b/t/t7615/ours.c
new file mode 100644
index 0000000000..44d8251397
--- /dev/null
+++ b/t/t7615/ours.c
@@ -0,0 +1,17 @@
+int g(size_t u)
+{
+ while (u < 30)
+ {
+ u++;
+ }
+ return u;
+}
+
+int h(int x, int y, int z)
+{
+ if (z == 0)
+ {
+ return x;
+ }
+ return y;
+}
diff --git a/t/t7615/theirs.c b/t/t7615/theirs.c
new file mode 100644
index 0000000000..85f02146fe
--- /dev/null
+++ b/t/t7615/theirs.c
@@ -0,0 +1,17 @@
+int f(int x, int y)
+{
+ if (x == 0)
+ {
+ return y;
+ }
+ return x;
+}
+
+int g(size_t u)
+{
+ while (u > 34)
+ {
+ u--;
+ }
+ return u;
+}
diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh
index 71e1ef3a10..959e6e2648 100755
--- a/t/t7704-repack-cruft.sh
+++ b/t/t7704-repack-cruft.sh
@@ -330,7 +330,7 @@ test_expect_success '--max-cruft-size with pruning' '
# repack (and prune) with a --max-cruft-size to ensure
# that we appropriately split the resulting set of packs
git repack -d --cruft --max-cruft-size=1M \
- --cruft-expiration=10.seconds.ago &&
+ --cruft-expiration=1000.seconds.ago &&
ls $packdir/pack-*.mtimes | sort >cruft.after &&
for cruft in $(cat cruft.after)
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 875dcfd98f..af2cf2f78a 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -31,6 +31,7 @@ int main(int argc, const char **argv)
return 0;
/* char ?? */
}
+
EOF
test_expect_success setup '
diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
index 0147de304b..3596634039 100755
--- a/t/t8002-blame.sh
+++ b/t/t8002-blame.sh
@@ -5,6 +5,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
PROG='git blame -c'
diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh
index 731265541a..6288352f57 100755
--- a/t/t8003-blame-corner-cases.sh
+++ b/t/t8003-blame-corner-cases.sh
@@ -4,6 +4,7 @@ test_description='git blame corner cases'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pick_fc='s/^[0-9a-f^]* *\([^ ]*\) *(\([^ ]*\) .*/\1-\2/'
diff --git a/t/t8004-blame-with-conflicts.sh b/t/t8004-blame-with-conflicts.sh
index 35414a5336..2c2a0b33f9 100755
--- a/t/t8004-blame-with-conflicts.sh
+++ b/t/t8004-blame-with-conflicts.sh
@@ -6,6 +6,7 @@ test_description='git blame on conflicted files'
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 first case' '
diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh
index 7683515155..42f8be25a3 100755
--- a/t/t8006-blame-textconv.sh
+++ b/t/t8006-blame-textconv.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git blame textconv support'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
find_blame() {
diff --git a/t/t8008-blame-formats.sh b/t/t8008-blame-formats.sh
index ae4b579d24..fb5d225a67 100755
--- a/t/t8008-blame-formats.sh
+++ b/t/t8008-blame-formats.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='blame output in various formats on a simple case'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t8009-blame-vs-topicbranches.sh b/t/t8009-blame-vs-topicbranches.sh
index 72596e38b2..30331713b9 100755
--- a/t/t8009-blame-vs-topicbranches.sh
+++ b/t/t8009-blame-vs-topicbranches.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='blaming trough history with topic branches'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Creates the history shown below. '*'s mark the first parent in the merges.
diff --git a/t/t8011-blame-split-file.sh b/t/t8011-blame-split-file.sh
index bdda0c03fe..da1801f4d2 100755
--- a/t/t8011-blame-split-file.sh
+++ b/t/t8011-blame-split-file.sh
@@ -10,6 +10,8 @@ Note that we need to use "blame -C" to find the commit for all lines. We will
not bother testing that the non-C case fails to find it. That is how blame
behaves now, but it is not a property we want to make sure is retained.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# help avoid typing and reading long strings of similar lines
diff --git a/t/t8012-blame-colors.sh b/t/t8012-blame-colors.sh
index c3a5f6d01f..9a79c109f2 100755
--- a/t/t8012-blame-colors.sh
+++ b/t/t8012-blame-colors.sh
@@ -5,6 +5,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
PROG='git blame -c'
diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh
index dbfbd86e83..d33788d867 100755
--- a/t/t8013-blame-ignore-revs.sh
+++ b/t/t8013-blame-ignore-revs.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='ignore revisions when blaming'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Creates:
diff --git a/t/t8014-blame-ignore-fuzzy.sh b/t/t8014-blame-ignore-fuzzy.sh
index 0bd0341301..933222cea1 100755
--- a/t/t8014-blame-ignore-fuzzy.sh
+++ b/t/t8014-blame-ignore-fuzzy.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git blame ignore fuzzy heuristic'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
pick_author='s/^[0-9a-f^]* *(\([^ ]*\) .*/\1/'
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 58699f8e4e..64a4ab3736 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -1299,6 +1299,49 @@ test_expect_success $PREREQ 'utf8 sender is not duplicated' '
test_line_count = 1 msgfrom
'
+test_expect_success $PREREQ 'setup expect for cc list' "
+cat >expected-cc <<\EOF
+!recipient@example.com!
+!author@example.com!
+!one@example.com!
+!os@example.com!
+!odd_?=mail@example.com!
+!doug@example.com!
+!codev@example.com!
+!thor.au@example.com!
+EOF
+"
+
+test_expect_success $PREREQ 'cc list is sanitized' '
+ clean_fake_sendmail &&
+ test_commit weird_cc_body &&
+ test_when_finished "git reset --hard HEAD^" &&
+ git commit --amend -F - <<-EOF &&
+ Test Cc: sanitization.
+
+ Cc: Person, One <one@example.com>
+ Cc: Ronnie O${SQ}Sullivan <os@example.com>
+ Reviewed-by: Füñný Nâmé <odd_?=mail@example.com>
+ Reported-by: bugger on Jira
+ Reported-by: Douglas Reporter <doug@example.com> [from Jira profile]
+ BugID: 12345
+ Co-developed-by: "C. O. Developer" <codev@example.com>
+ Signed-off-by: A. U. Thor <thor.au@example.com>
+ EOF
+ git send-email -1 --to=recipient@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" >actual-show-all-headers &&
+ test_cmp expected-cc commandline1 &&
+ test_grep "^(body) Adding cc: \"Person, One\" <one@example.com>" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: Ronnie O${SQ}Sullivan <os@example.com>" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: =?UTF-8?q?F=C3=BC=C3=B1n=C3=BD=20N=C3=A2m=C3=A9?="\
+" <odd_?=mail@example.com>" actual-show-all-headers &&
+ test_grep "^(body) Ignoring Reported-by .* bugger on Jira" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: Douglas Reporter <doug@example.com>" actual-show-all-headers &&
+ test_grep ! "12345" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: \"C. O. Developer\" <codev@example.com>" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: \"A. U. Thor\" <thor.au@example.com>" actual-show-all-headers
+'
+
test_expect_success $PREREQ 'sendemail.composeencoding works' '
clean_fake_sendmail &&
git config sendemail.composeencoding iso-8859-1 &&
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 7679780fb8..ccfa415384 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -13,6 +13,7 @@ or warnings to log.'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-gitweb.sh
# ----------------------------------------------------------------------
diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh
index 81d5625557..b41ea19331 100755
--- a/t/t9502-gitweb-standalone-parse-output.sh
+++ b/t/t9502-gitweb-standalone-parse-output.sh
@@ -13,6 +13,7 @@ in the HTTP header or the actual script output.'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-gitweb.sh
# ----------------------------------------------------------------------
diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh
index 53af8e34ac..3e6dfce248 100755
--- a/t/t9800-git-p4-basic.sh
+++ b/t/t9800-git-p4-basic.sh
@@ -5,6 +5,7 @@ test_description='git p4 tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
@@ -297,8 +298,20 @@ test_expect_success 'exit when p4 fails to produce marshaled output' '
# p4 changes, files, or describe; just in p4 print. If P4CLIENT is unset, the
# message will include "Librarian checkout".
test_expect_success 'exit gracefully for p4 server errors' '
- test_when_finished "mv \"$db\"/depot/file1,v,hidden \"$db\"/depot/file1,v" &&
- mv "$db"/depot/file1,v "$db"/depot/file1,v,hidden &&
+ # Note that newer Perforce versions started to store files
+ # compressed in directories. The case statement handles both
+ # old and new layout.
+ case "$(echo "$db"/depot/file1*)" in
+ *,v)
+ test_when_finished "mv \"$db\"/depot/file1,v,hidden \"$db\"/depot/file1,v" &&
+ mv "$db"/depot/file1,v "$db"/depot/file1,v,hidden;;
+ *,d)
+ path="$(echo "$db"/depot/file1,d/*.gz)" &&
+ test_when_finished "mv \"$path\",hidden \"$path\"" &&
+ mv "$path" "$path",hidden;;
+ *)
+ BUG "unhandled p4d layout";;
+ esac &&
test_when_finished cleanup_git &&
test_expect_code 1 git p4 clone --dest="$git" //depot@1 >out 2>err &&
test_grep "Error from p4 print" err
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index c598011635..cdbfacc727 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -5,6 +5,7 @@ test_description='git p4 tests for p4 branches'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh
index bb236cd2b5..1bc48305b0 100755
--- a/t/t9802-git-p4-filetype.sh
+++ b/t/t9802-git-p4-filetype.sh
@@ -2,6 +2,7 @@
test_description='git p4 filetype tests'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
@@ -300,10 +301,22 @@ test_expect_success SYMLINKS 'empty symlink target' '
# text
# @@
#
+ # Note that newer Perforce versions started to store files
+ # compressed in directories. The case statement handles both
+ # old and new layout.
cd "$db/depot" &&
- sed "/@target1/{; s/target1/@/; n; d; }" \
- empty-symlink,v >empty-symlink,v.tmp &&
- mv empty-symlink,v.tmp empty-symlink,v
+ case "$(echo empty-symlink*)" in
+ empty-symlink,v)
+ sed "/@target1/{; s/target1/@/; n; d; }" \
+ empty-symlink,v >empty-symlink,v.tmp &&
+ mv empty-symlink,v.tmp empty-symlink,v;;
+ empty-symlink,d)
+ path="empty-symlink,d/$(ls empty-symlink,d/ | tail -n1)" &&
+ rm "$path" &&
+ gzip </dev/null >"$path";;
+ *)
+ BUG "unhandled p4d layout";;
+ esac
) &&
(
# Make sure symlink really is empty. Asking
diff --git a/t/t9803-git-p4-shell-metachars.sh b/t/t9803-git-p4-shell-metachars.sh
index 2913277013..ab7fe16266 100755
--- a/t/t9803-git-p4-shell-metachars.sh
+++ b/t/t9803-git-p4-shell-metachars.sh
@@ -2,6 +2,7 @@
test_description='git p4 transparency to shell metachars in filenames'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9804-git-p4-label.sh b/t/t9804-git-p4-label.sh
index 3236457106..c8963fd398 100755
--- a/t/t9804-git-p4-label.sh
+++ b/t/t9804-git-p4-label.sh
@@ -2,6 +2,7 @@
test_description='git p4 label tests'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9805-git-p4-skip-submit-edit.sh b/t/t9805-git-p4-skip-submit-edit.sh
index 90ef647db7..72dce3d2b4 100755
--- a/t/t9805-git-p4-skip-submit-edit.sh
+++ b/t/t9805-git-p4-skip-submit-edit.sh
@@ -2,6 +2,7 @@
test_description='git p4 skipSubmitEdit config variables'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9806-git-p4-options.sh b/t/t9806-git-p4-options.sh
index c26d297433..e4ce44ebf3 100755
--- a/t/t9806-git-p4-options.sh
+++ b/t/t9806-git-p4-options.sh
@@ -5,6 +5,7 @@ test_description='git p4 options'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9808-git-p4-chdir.sh b/t/t9808-git-p4-chdir.sh
index 58a9b3b71e..342f7f3d4a 100755
--- a/t/t9808-git-p4-chdir.sh
+++ b/t/t9808-git-p4-chdir.sh
@@ -2,6 +2,7 @@
test_description='git p4 relative chdir'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9809-git-p4-client-view.sh b/t/t9809-git-p4-client-view.sh
index 9c9710d8c7..f33fdea889 100755
--- a/t/t9809-git-p4-client-view.sh
+++ b/t/t9809-git-p4-client-view.sh
@@ -2,6 +2,7 @@
test_description='git p4 client view'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9810-git-p4-rcs.sh b/t/t9810-git-p4-rcs.sh
index 5fe83315ec..15e32c9f35 100755
--- a/t/t9810-git-p4-rcs.sh
+++ b/t/t9810-git-p4-rcs.sh
@@ -2,6 +2,7 @@
test_description='git p4 rcs keywords'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
CP1252="\223\224"
diff --git a/t/t9811-git-p4-label-import.sh b/t/t9811-git-p4-label-import.sh
index 5ac5383fb7..52a4b0af81 100755
--- a/t/t9811-git-p4-label-import.sh
+++ b/t/t9811-git-p4-label-import.sh
@@ -5,6 +5,7 @@ test_description='git p4 label tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9812-git-p4-wildcards.sh b/t/t9812-git-p4-wildcards.sh
index 254a7c2446..46aa5fd56c 100755
--- a/t/t9812-git-p4-wildcards.sh
+++ b/t/t9812-git-p4-wildcards.sh
@@ -2,6 +2,7 @@
test_description='git p4 wildcards'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9813-git-p4-preserve-users.sh b/t/t9813-git-p4-preserve-users.sh
index fd018c87a8..0efea28da2 100755
--- a/t/t9813-git-p4-preserve-users.sh
+++ b/t/t9813-git-p4-preserve-users.sh
@@ -2,6 +2,7 @@
test_description='git p4 preserve users'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9814-git-p4-rename.sh b/t/t9814-git-p4-rename.sh
index 2a9838f37f..00df6ebd3b 100755
--- a/t/t9814-git-p4-rename.sh
+++ b/t/t9814-git-p4-rename.sh
@@ -2,6 +2,7 @@
test_description='git p4 rename'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9815-git-p4-submit-fail.sh b/t/t9815-git-p4-submit-fail.sh
index c766fd159f..92ef9d8c24 100755
--- a/t/t9815-git-p4-submit-fail.sh
+++ b/t/t9815-git-p4-submit-fail.sh
@@ -2,6 +2,7 @@
test_description='git p4 submit failure handling'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9816-git-p4-locked.sh b/t/t9816-git-p4-locked.sh
index 5e904ac80d..e687fbc25f 100755
--- a/t/t9816-git-p4-locked.sh
+++ b/t/t9816-git-p4-locked.sh
@@ -2,6 +2,7 @@
test_description='git p4 locked file behavior'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9817-git-p4-exclude.sh b/t/t9817-git-p4-exclude.sh
index ec3d937c6a..3deb334fed 100755
--- a/t/t9817-git-p4-exclude.sh
+++ b/t/t9817-git-p4-exclude.sh
@@ -2,6 +2,7 @@
test_description='git p4 tests for excluded paths during clone and sync'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9818-git-p4-block.sh b/t/t9818-git-p4-block.sh
index de591d875c..091bb72bdb 100755
--- a/t/t9818-git-p4-block.sh
+++ b/t/t9818-git-p4-block.sh
@@ -2,6 +2,7 @@
test_description='git p4 fetching changes in multiple blocks'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9819-git-p4-case-folding.sh b/t/t9819-git-p4-case-folding.sh
index b4d93f0c17..985be20357 100755
--- a/t/t9819-git-p4-case-folding.sh
+++ b/t/t9819-git-p4-case-folding.sh
@@ -2,6 +2,7 @@
test_description='interaction with P4 case-folding'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
if test_have_prereq CASE_INSENSITIVE_FS
diff --git a/t/t9820-git-p4-editor-handling.sh b/t/t9820-git-p4-editor-handling.sh
index fa1bba1dd9..48e4dfb95c 100755
--- a/t/t9820-git-p4-editor-handling.sh
+++ b/t/t9820-git-p4-editor-handling.sh
@@ -2,6 +2,7 @@
test_description='git p4 handling of EDITOR'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9821-git-p4-path-variations.sh b/t/t9821-git-p4-path-variations.sh
index ef80f1690b..49691c53da 100755
--- a/t/t9821-git-p4-path-variations.sh
+++ b/t/t9821-git-p4-path-variations.sh
@@ -2,6 +2,7 @@
test_description='Clone repositories with path case variations'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d with case folding enabled' '
diff --git a/t/t9822-git-p4-path-encoding.sh b/t/t9822-git-p4-path-encoding.sh
index 572d395498..e62ed49f51 100755
--- a/t/t9822-git-p4-path-encoding.sh
+++ b/t/t9822-git-p4-path-encoding.sh
@@ -2,6 +2,7 @@
test_description='Clone repositories with non ASCII paths'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
UTF8_ESCAPED="a-\303\244_o-\303\266_u-\303\274.txt"
diff --git a/t/t9823-git-p4-mock-lfs.sh b/t/t9823-git-p4-mock-lfs.sh
index 88b76dc4d6..98a40d8af3 100755
--- a/t/t9823-git-p4-mock-lfs.sh
+++ b/t/t9823-git-p4-mock-lfs.sh
@@ -2,6 +2,7 @@
test_description='Clone repositories and store files in Mock LFS'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_file_is_not_in_mock_lfs () {
diff --git a/t/t9825-git-p4-handle-utf16-without-bom.sh b/t/t9825-git-p4-handle-utf16-without-bom.sh
index f049ff8229..d0b86537dd 100755
--- a/t/t9825-git-p4-handle-utf16-without-bom.sh
+++ b/t/t9825-git-p4-handle-utf16-without-bom.sh
@@ -2,6 +2,7 @@
test_description='git p4 handling of UTF-16 files without BOM'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
UTF16="\227\000\227\000"
@@ -22,9 +23,25 @@ test_expect_success 'init depot with UTF-16 encoded file and artificially remove
cd db &&
p4d -jc &&
# P4D automatically adds a BOM. Remove it here to make the file invalid.
- sed -e "\$d" depot/file1,v >depot/file1,v.new &&
- mv depot/file1,v.new depot/file1,v &&
- printf "@$UTF16@" >>depot/file1,v &&
+ #
+ # Note that newer Perforce versions started to store files
+ # compressed in directories. The case statement handles both
+ # old and new layout.
+ case "$(echo depot/file1*)" in
+ depot/file1,v)
+ sed -e "\$d" depot/file1,v >depot/file1,v.new &&
+ mv depot/file1,v.new depot/file1,v &&
+ printf "@$UTF16@" >>depot/file1,v;;
+ depot/file1,d)
+ path="$(echo depot/file1,d/*.gz)" &&
+ gunzip -c "$path" >"$path.unzipped" &&
+ sed -e "\$d" "$path.unzipped" >"$path.new" &&
+ printf "$UTF16" >>"$path.new" &&
+ gzip -c "$path.new" >"$path" &&
+ rm "$path.unzipped" "$path.new";;
+ *)
+ BUG "unhandled p4d layout";;
+ esac &&
p4d -jrF checkpoint.1
)
'
diff --git a/t/t9826-git-p4-keep-empty-commits.sh b/t/t9826-git-p4-keep-empty-commits.sh
index fd64afe064..54083f842e 100755
--- a/t/t9826-git-p4-keep-empty-commits.sh
+++ b/t/t9826-git-p4-keep-empty-commits.sh
@@ -2,6 +2,7 @@
test_description='Clone repositories and keep empty commits'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9827-git-p4-change-filetype.sh b/t/t9827-git-p4-change-filetype.sh
index d3670bd7a2..3476ea2fd3 100755
--- a/t/t9827-git-p4-change-filetype.sh
+++ b/t/t9827-git-p4-change-filetype.sh
@@ -2,6 +2,7 @@
test_description='git p4 support for file type change'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9828-git-p4-map-user.sh b/t/t9828-git-p4-map-user.sh
index ca6c2942bd..7c8f9e3930 100755
--- a/t/t9828-git-p4-map-user.sh
+++ b/t/t9828-git-p4-map-user.sh
@@ -2,6 +2,7 @@
test_description='Clone repositories and map users'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9829-git-p4-jobs.sh b/t/t9829-git-p4-jobs.sh
index 88cfb1fcd3..3fc0948d9c 100755
--- a/t/t9829-git-p4-jobs.sh
+++ b/t/t9829-git-p4-jobs.sh
@@ -2,6 +2,7 @@
test_description='git p4 retrieve job info'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9830-git-p4-symlink-dir.sh b/t/t9830-git-p4-symlink-dir.sh
index 3fb6960c18..02561a7f0e 100755
--- a/t/t9830-git-p4-symlink-dir.sh
+++ b/t/t9830-git-p4-symlink-dir.sh
@@ -2,6 +2,7 @@
test_description='git p4 symlinked directories'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9831-git-p4-triggers.sh b/t/t9831-git-p4-triggers.sh
index ff6c0352e6..f287f41e37 100755
--- a/t/t9831-git-p4-triggers.sh
+++ b/t/t9831-git-p4-triggers.sh
@@ -2,6 +2,7 @@
test_description='git p4 with server triggers'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9832-unshelve.sh b/t/t9832-unshelve.sh
index 6b3cb0414a..a266775408 100755
--- a/t/t9832-unshelve.sh
+++ b/t/t9832-unshelve.sh
@@ -6,6 +6,7 @@ last_shelved_change () {
test_description='git p4 unshelve'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9833-errors.sh b/t/t9833-errors.sh
index e22369ccdf..da1d30c142 100755
--- a/t/t9833-errors.sh
+++ b/t/t9833-errors.sh
@@ -2,6 +2,7 @@
test_description='git p4 errors'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9834-git-p4-file-dir-bug.sh b/t/t9834-git-p4-file-dir-bug.sh
index dac67e89d7..565870fc74 100755
--- a/t/t9834-git-p4-file-dir-bug.sh
+++ b/t/t9834-git-p4-file-dir-bug.sh
@@ -6,6 +6,7 @@ This test creates files and directories with the same name in perforce and
checks that git-p4 recovers from the error at the same time as the perforce
repository.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
test_expect_success 'start p4d' '
diff --git a/t/t9835-git-p4-metadata-encoding-python2.sh b/t/t9835-git-p4-metadata-encoding-python2.sh
index 036bf79c66..ad20ffdede 100755
--- a/t/t9835-git-p4-metadata-encoding-python2.sh
+++ b/t/t9835-git-p4-metadata-encoding-python2.sh
@@ -6,6 +6,7 @@ This test checks that the import process handles inconsistent text
encoding in p4 metadata (author names, commit messages, etc) without
failing, and produces maximally sane output in git.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
python_target_version='2'
diff --git a/t/t9836-git-p4-metadata-encoding-python3.sh b/t/t9836-git-p4-metadata-encoding-python3.sh
index 63350dc4b5..71ae763399 100755
--- a/t/t9836-git-p4-metadata-encoding-python3.sh
+++ b/t/t9836-git-p4-metadata-encoding-python3.sh
@@ -6,6 +6,7 @@ This test checks that the import process handles inconsistent text
encoding in p4 metadata (author names, commit messages, etc) without
failing, and produces maximally sane output in git.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-git-p4.sh
python_target_version='3'
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 932d5ad759..cc6aa9f0cd 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -16,6 +16,7 @@ test_untraceable=UnfortunatelyYes
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-bash.sh
complete ()
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index d667dda654..95e9955bca 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -8,6 +8,7 @@ test_description='test git-specific bash prompt functions'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-bash.sh
. "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh"
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 1ea9f31225..fde9bf54fc 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -872,6 +872,24 @@ test_verify_prereq () {
BUG "'$test_prereq' does not look like a prereq"
}
+# assign the variable named by "$1" with the contents of "$2";
+# if "$2" is "-", then read stdin into "$1" instead
+test_body_or_stdin () {
+ if test "$2" != "-"
+ then
+ eval "$1=\$2"
+ return
+ fi
+
+ # start with a newline, to match hanging newline from open-quote style
+ eval "$1=\$LF"
+ local test_line
+ while IFS= read -r test_line
+ do
+ eval "$1=\${$1}\${test_line}\${LF}"
+ done
+}
+
test_expect_failure () {
test_start_ "$@"
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
@@ -881,9 +899,11 @@ test_expect_failure () {
export test_prereq
if ! test_skip "$@"
then
+ local test_body
+ test_body_or_stdin test_body "$2"
test -n "$test_skip_test_preamble" ||
- say >&3 "checking known breakage of $TEST_NUMBER.$test_count '$1': $2"
- if test_run_ "$2" expecting_failure
+ say >&3 "checking known breakage of $TEST_NUMBER.$test_count '$1': $test_body"
+ if test_run_ "$test_body" expecting_failure
then
test_known_broken_ok_ "$1"
else
@@ -902,13 +922,15 @@ test_expect_success () {
export test_prereq
if ! test_skip "$@"
then
+ local test_body
+ test_body_or_stdin test_body "$2"
test -n "$test_skip_test_preamble" ||
- say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $2"
- if test_run_ "$2"
+ say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $test_body"
+ if test_run_ "$test_body"
then
test_ok_ "$1"
else
- test_failure_ "$@"
+ test_failure_ "$1" "$test_body"
fi
fi
test_finish_
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 79d3e0e7d9..54247604cb 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1269,9 +1269,12 @@ check_test_results_san_file_ () {
then
say "As TEST_PASSES_SANITIZE_LEAK=true isn't set the above leak is 'ok' with GIT_TEST_PASSING_SANITIZE_LEAK=check" &&
invert_exit_code=t
- else
- say "With GIT_TEST_SANITIZE_LEAK_LOG=true our logs revealed a memory leak, exit non-zero!" &&
+ elif test "$test_failure" = 0
+ then
+ say "Our logs revealed a memory leak, exit non-zero!" &&
invert_exit_code=t
+ else
+ say "Our logs revealed a memory leak..."
fi
}
@@ -1575,33 +1578,28 @@ then
test_done
fi
- if test_bool_env GIT_TEST_SANITIZE_LEAK_LOG false
+ if ! mkdir -p "$TEST_RESULTS_SAN_DIR"
then
- if ! mkdir -p "$TEST_RESULTS_SAN_DIR"
- then
- BAIL_OUT "cannot create $TEST_RESULTS_SAN_DIR"
- fi &&
- TEST_RESULTS_SAN_FILE="$TEST_RESULTS_SAN_DIR/$TEST_RESULTS_SAN_FILE_PFX"
+ BAIL_OUT "cannot create $TEST_RESULTS_SAN_DIR"
+ fi &&
+ TEST_RESULTS_SAN_FILE="$TEST_RESULTS_SAN_DIR/$TEST_RESULTS_SAN_FILE_PFX"
- # In case "test-results" is left over from a previous
- # run: Only report if new leaks show up.
- TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP=$(nr_san_dir_leaks_)
+ # In case "test-results" is left over from a previous
+ # run: Only report if new leaks show up.
+ TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP=$(nr_san_dir_leaks_)
- # Don't litter *.leak dirs if there was nothing to report
- test_atexit "rmdir \"$TEST_RESULTS_SAN_DIR\" 2>/dev/null || :"
+ # Don't litter *.leak dirs if there was nothing to report
+ test_atexit "rmdir \"$TEST_RESULTS_SAN_DIR\" 2>/dev/null || :"
+
+ prepend_var LSAN_OPTIONS : dedup_token_length=9999
+ prepend_var LSAN_OPTIONS : log_exe_name=1
+ prepend_var LSAN_OPTIONS : log_path=\"$TEST_RESULTS_SAN_FILE\"
+ export LSAN_OPTIONS
- prepend_var LSAN_OPTIONS : dedup_token_length=9999
- prepend_var LSAN_OPTIONS : log_exe_name=1
- prepend_var LSAN_OPTIONS : log_path=\"$TEST_RESULTS_SAN_FILE\"
- export LSAN_OPTIONS
- fi
elif test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check" ||
test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
then
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_PASSING_SANITIZE_LEAK=true"
-elif test_bool_env GIT_TEST_SANITIZE_LEAK_LOG false
-then
- BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_SANITIZE_LEAK_LOG=true"
fi
if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 &&
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-oidmap.c b/t/unit-tests/t-oidmap.c
new file mode 100644
index 0000000000..b22e52d08b
--- /dev/null
+++ b/t/unit-tests/t-oidmap.c
@@ -0,0 +1,181 @@
+#include "test-lib.h"
+#include "lib-oid.h"
+#include "oidmap.h"
+#include "hash.h"
+#include "hex.h"
+
+/*
+ * Elements we will put in oidmap structs are made of a key: the entry.oid
+ * field, which is of type struct object_id, and a value: the name field (could
+ * be a refname for example).
+ */
+struct test_entry {
+ struct oidmap_entry entry;
+ char name[FLEX_ARRAY];
+};
+
+static const char *const key_val[][2] = { { "11", "one" },
+ { "22", "two" },
+ { "33", "three" } };
+
+static void setup(void (*f)(struct oidmap *map))
+{
+ struct oidmap map = OIDMAP_INIT;
+ int ret = 0;
+
+ for (size_t i = 0; i < ARRAY_SIZE(key_val); i++){
+ struct test_entry *entry;
+
+ FLEX_ALLOC_STR(entry, name, key_val[i][1]);
+ if ((ret = get_oid_arbitrary_hex(key_val[i][0], &entry->entry.oid))) {
+ free(entry);
+ break;
+ }
+ entry = oidmap_put(&map, entry);
+ if (!check(entry == NULL))
+ free(entry);
+ }
+
+ if (!ret)
+ f(&map);
+ oidmap_free(&map, 1);
+}
+
+static void t_replace(struct oidmap *map)
+{
+ struct test_entry *entry, *prev;
+
+ FLEX_ALLOC_STR(entry, name, "un");
+ if (get_oid_arbitrary_hex("11", &entry->entry.oid))
+ return;
+ prev = oidmap_put(map, entry);
+ if (!check(prev != NULL))
+ return;
+ check_str(prev->name, "one");
+ free(prev);
+
+ FLEX_ALLOC_STR(entry, name, "deux");
+ if (get_oid_arbitrary_hex("22", &entry->entry.oid))
+ return;
+ prev = oidmap_put(map, entry);
+ if (!check(prev != NULL))
+ return;
+ check_str(prev->name, "two");
+ free(prev);
+}
+
+static void t_get(struct oidmap *map)
+{
+ struct test_entry *entry;
+ struct object_id oid;
+
+ if (get_oid_arbitrary_hex("22", &oid))
+ return;
+ entry = oidmap_get(map, &oid);
+ if (!check(entry != NULL))
+ return;
+ check_str(entry->name, "two");
+
+ if (get_oid_arbitrary_hex("44", &oid))
+ return;
+ check(oidmap_get(map, &oid) == NULL);
+
+ if (get_oid_arbitrary_hex("11", &oid))
+ return;
+ entry = oidmap_get(map, &oid);
+ if (!check(entry != NULL))
+ return;
+ check_str(entry->name, "one");
+}
+
+static void t_remove(struct oidmap *map)
+{
+ struct test_entry *entry;
+ struct object_id oid;
+
+ if (get_oid_arbitrary_hex("11", &oid))
+ return;
+ entry = oidmap_remove(map, &oid);
+ if (!check(entry != NULL))
+ return;
+ check_str(entry->name, "one");
+ check(oidmap_get(map, &oid) == NULL);
+ free(entry);
+
+ if (get_oid_arbitrary_hex("22", &oid))
+ return;
+ entry = oidmap_remove(map, &oid);
+ if (!check(entry != NULL))
+ return;
+ check_str(entry->name, "two");
+ check(oidmap_get(map, &oid) == NULL);
+ free(entry);
+
+ if (get_oid_arbitrary_hex("44", &oid))
+ return;
+ check(oidmap_remove(map, &oid) == NULL);
+}
+
+static int key_val_contains(struct test_entry *entry, char seen[])
+{
+ for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) {
+ struct object_id oid;
+
+ if (get_oid_arbitrary_hex(key_val[i][0], &oid))
+ return -1;
+
+ if (oideq(&entry->entry.oid, &oid)) {
+ if (seen[i])
+ return 2;
+ seen[i] = 1;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void t_iterate(struct oidmap *map)
+{
+ struct oidmap_iter iter;
+ struct test_entry *entry;
+ char seen[ARRAY_SIZE(key_val)] = { 0 };
+ int count = 0;
+
+ oidmap_iter_init(map, &iter);
+ while ((entry = oidmap_iter_next(&iter))) {
+ int ret;
+ if (!check_int((ret = key_val_contains(entry, seen)), ==, 0)) {
+ switch (ret) {
+ case -1:
+ break; /* error message handled by get_oid_arbitrary_hex() */
+ case 1:
+ test_msg("obtained entry was not given in the input\n"
+ " name: %s\n oid: %s\n",
+ entry->name, oid_to_hex(&entry->entry.oid));
+ break;
+ case 2:
+ test_msg("duplicate entry detected\n"
+ " name: %s\n oid: %s\n",
+ entry->name, oid_to_hex(&entry->entry.oid));
+ break;
+ default:
+ test_msg("BUG: invalid return value (%d) from key_val_contains()",
+ ret);
+ break;
+ }
+ } else {
+ count++;
+ }
+ }
+ check_int(count, ==, ARRAY_SIZE(key_val));
+ check_int(hashmap_get_size(&map->map), ==, ARRAY_SIZE(key_val));
+}
+
+int cmd_main(int argc UNUSED, const char **argv UNUSED)
+{
+ TEST(setup(t_replace), "replace works");
+ TEST(setup(t_get), "get works");
+ TEST(setup(t_remove), "remove works");
+ TEST(setup(t_iterate), "iterate works");
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c
new file mode 100644
index 0000000000..b6263ee8b5
--- /dev/null
+++ b/t/unit-tests/t-reftable-merged.c
@@ -0,0 +1,463 @@
+/*
+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/blocksource.h"
+#include "reftable/constants.h"
+#include "reftable/merged.h"
+#include "reftable/reader.h"
+#include "reftable/reftable-error.h"
+#include "reftable/reftable-generic.h"
+#include "reftable/reftable-merged.h"
+#include "reftable/reftable-writer.h"
+
+static ssize_t strbuf_add_void(void *b, const void *data, const size_t sz)
+{
+ strbuf_add(b, data, sz);
+ return sz;
+}
+
+static int noop_flush(void *arg)
+{
+ return 0;
+}
+
+static void write_test_table(struct strbuf *buf,
+ struct reftable_ref_record refs[], const size_t n)
+{
+ uint64_t min = 0xffffffff;
+ uint64_t max = 0;
+ size_t i;
+ int err;
+
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ };
+ struct reftable_writer *w = NULL;
+ for (i = 0; i < n; i++) {
+ uint64_t ui = refs[i].update_index;
+ if (ui > max)
+ max = ui;
+ if (ui < min)
+ min = ui;
+ }
+
+ w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
+ reftable_writer_set_limits(w, min, max);
+
+ for (i = 0; i < n; i++) {
+ uint64_t before = refs[i].update_index;
+ int n = reftable_writer_add_ref(w, &refs[i]);
+ check_int(n, ==, 0);
+ check_int(before, ==, refs[i].update_index);
+ }
+
+ err = reftable_writer_close(w);
+ check(!err);
+
+ reftable_writer_free(w);
+}
+
+static void write_test_log_table(struct strbuf *buf, struct reftable_log_record logs[],
+ const size_t n, const uint64_t update_index)
+{
+ int err;
+
+ struct reftable_write_options opts = {
+ .block_size = 256,
+ .exact_log_message = 1,
+ };
+ struct reftable_writer *w = NULL;
+ w = reftable_new_writer(&strbuf_add_void, &noop_flush, buf, &opts);
+ reftable_writer_set_limits(w, update_index, update_index);
+
+ for (size_t i = 0; i < n; i++) {
+ int err = reftable_writer_add_log(w, &logs[i]);
+ check(!err);
+ }
+
+ err = reftable_writer_close(w);
+ check(!err);
+
+ reftable_writer_free(w);
+}
+
+static struct reftable_merged_table *
+merged_table_from_records(struct reftable_ref_record **refs,
+ struct reftable_block_source **source,
+ struct reftable_reader ***readers, const size_t *sizes,
+ struct strbuf *buf, const size_t n)
+{
+ struct reftable_merged_table *mt = NULL;
+ struct reftable_table *tabs;
+ int err;
+
+ REFTABLE_CALLOC_ARRAY(tabs, n);
+ REFTABLE_CALLOC_ARRAY(*readers, n);
+ REFTABLE_CALLOC_ARRAY(*source, n);
+
+ for (size_t i = 0; i < n; i++) {
+ write_test_table(&buf[i], refs[i], sizes[i]);
+ block_source_from_strbuf(&(*source)[i], &buf[i]);
+
+ err = reftable_new_reader(&(*readers)[i], &(*source)[i],
+ "name");
+ check(!err);
+ reftable_table_from_reader(&tabs[i], (*readers)[i]);
+ }
+
+ err = reftable_new_merged_table(&mt, tabs, n, GIT_SHA1_FORMAT_ID);
+ check(!err);
+ return mt;
+}
+
+static void readers_destroy(struct reftable_reader **readers, const size_t n)
+{
+ for (size_t i = 0; i < n; i++)
+ reftable_reader_free(readers[i]);
+ reftable_free(readers);
+}
+
+static void t_merged_single_record(void)
+{
+ struct reftable_ref_record r1[] = { {
+ .refname = (char *) "b",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 1, 2, 3, 0 },
+ } };
+ struct reftable_ref_record r2[] = { {
+ .refname = (char *) "a",
+ .update_index = 2,
+ .value_type = REFTABLE_REF_DELETION,
+ } };
+ struct reftable_ref_record r3[] = { {
+ .refname = (char *) "c",
+ .update_index = 3,
+ .value_type = REFTABLE_REF_DELETION,
+ } };
+
+ struct reftable_ref_record *refs[] = { r1, r2, r3 };
+ size_t sizes[] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };
+ struct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };
+ struct reftable_block_source *bs = NULL;
+ struct reftable_reader **readers = NULL;
+ struct reftable_merged_table *mt =
+ merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3);
+ struct reftable_ref_record ref = { 0 };
+ struct reftable_iterator it = { 0 };
+ int err;
+
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ err = reftable_iterator_seek_ref(&it, "a");
+ check(!err);
+
+ err = reftable_iterator_next_ref(&it, &ref);
+ check(!err);
+ check(reftable_ref_record_equal(&r2[0], &ref, GIT_SHA1_RAWSZ));
+ reftable_ref_record_release(&ref);
+ reftable_iterator_destroy(&it);
+ readers_destroy(readers, 3);
+ reftable_merged_table_free(mt);
+ for (size_t i = 0; i < ARRAY_SIZE(bufs); i++)
+ strbuf_release(&bufs[i]);
+ reftable_free(bs);
+}
+
+static void t_merged_refs(void)
+{
+ struct reftable_ref_record r1[] = {
+ {
+ .refname = (char *) "a",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 1 },
+ },
+ {
+ .refname = (char *) "b",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 1 },
+ },
+ {
+ .refname = (char *) "c",
+ .update_index = 1,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 1 },
+ }
+ };
+ struct reftable_ref_record r2[] = { {
+ .refname = (char *) "a",
+ .update_index = 2,
+ .value_type = REFTABLE_REF_DELETION,
+ } };
+ struct reftable_ref_record r3[] = {
+ {
+ .refname = (char *) "c",
+ .update_index = 3,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 2 },
+ },
+ {
+ .refname = (char *) "d",
+ .update_index = 3,
+ .value_type = REFTABLE_REF_VAL1,
+ .value.val1 = { 1 },
+ },
+ };
+
+ struct reftable_ref_record *want[] = {
+ &r2[0],
+ &r1[1],
+ &r3[0],
+ &r3[1],
+ };
+
+ struct reftable_ref_record *refs[] = { r1, r2, r3 };
+ size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };
+ struct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };
+ struct reftable_block_source *bs = NULL;
+ struct reftable_reader **readers = NULL;
+ struct reftable_merged_table *mt =
+ merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3);
+ struct reftable_iterator it = { 0 };
+ int err;
+ struct reftable_ref_record *out = NULL;
+ size_t len = 0;
+ size_t cap = 0;
+ size_t i;
+
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ err = reftable_iterator_seek_ref(&it, "a");
+ check(!err);
+ check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID);
+ check_int(reftable_merged_table_min_update_index(mt), ==, 1);
+ check_int(reftable_merged_table_max_update_index(mt), ==, 3);
+
+ while (len < 100) { /* cap loops/recursion. */
+ struct reftable_ref_record ref = { 0 };
+ int err = reftable_iterator_next_ref(&it, &ref);
+ if (err > 0)
+ break;
+
+ REFTABLE_ALLOC_GROW(out, len + 1, cap);
+ out[len++] = ref;
+ }
+ reftable_iterator_destroy(&it);
+
+ check_int(ARRAY_SIZE(want), ==, len);
+ for (i = 0; i < len; i++)
+ check(reftable_ref_record_equal(want[i], &out[i],
+ GIT_SHA1_RAWSZ));
+ for (i = 0; i < len; i++)
+ reftable_ref_record_release(&out[i]);
+ reftable_free(out);
+
+ for (i = 0; i < 3; i++)
+ strbuf_release(&bufs[i]);
+ readers_destroy(readers, 3);
+ reftable_merged_table_free(mt);
+ reftable_free(bs);
+}
+
+static struct reftable_merged_table *
+merged_table_from_log_records(struct reftable_log_record **logs,
+ struct reftable_block_source **source,
+ struct reftable_reader ***readers, const size_t *sizes,
+ struct strbuf *buf, const size_t n)
+{
+ struct reftable_merged_table *mt = NULL;
+ struct reftable_table *tabs;
+ int err;
+
+ REFTABLE_CALLOC_ARRAY(tabs, n);
+ REFTABLE_CALLOC_ARRAY(*readers, n);
+ REFTABLE_CALLOC_ARRAY(*source, n);
+
+ for (size_t i = 0; i < n; i++) {
+ write_test_log_table(&buf[i], logs[i], sizes[i], i + 1);
+ block_source_from_strbuf(&(*source)[i], &buf[i]);
+
+ err = reftable_new_reader(&(*readers)[i], &(*source)[i],
+ "name");
+ check(!err);
+ reftable_table_from_reader(&tabs[i], (*readers)[i]);
+ }
+
+ err = reftable_new_merged_table(&mt, tabs, n, GIT_SHA1_FORMAT_ID);
+ check(!err);
+ return mt;
+}
+
+static void t_merged_logs(void)
+{
+ struct reftable_log_record r1[] = {
+ {
+ .refname = (char *) "a",
+ .update_index = 2,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value.update = {
+ .old_hash = { 2 },
+ /* deletion */
+ .name = (char *) "jane doe",
+ .email = (char *) "jane@invalid",
+ .message = (char *) "message2",
+ }
+ },
+ {
+ .refname = (char *) "a",
+ .update_index = 1,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value.update = {
+ .old_hash = { 1 },
+ .new_hash = { 2 },
+ .name = (char *) "jane doe",
+ .email = (char *) "jane@invalid",
+ .message = (char *) "message1",
+ }
+ },
+ };
+ struct reftable_log_record r2[] = {
+ {
+ .refname = (char *) "a",
+ .update_index = 3,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value.update = {
+ .new_hash = { 3 },
+ .name = (char *) "jane doe",
+ .email = (char *) "jane@invalid",
+ .message = (char *) "message3",
+ }
+ },
+ };
+ struct reftable_log_record r3[] = {
+ {
+ .refname = (char *) "a",
+ .update_index = 2,
+ .value_type = REFTABLE_LOG_DELETION,
+ },
+ };
+ struct reftable_log_record *want[] = {
+ &r2[0],
+ &r3[0],
+ &r1[1],
+ };
+
+ struct reftable_log_record *logs[] = { r1, r2, r3 };
+ size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) };
+ struct strbuf bufs[3] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT };
+ struct reftable_block_source *bs = NULL;
+ struct reftable_reader **readers = NULL;
+ struct reftable_merged_table *mt = merged_table_from_log_records(
+ logs, &bs, &readers, sizes, bufs, 3);
+ struct reftable_iterator it = { 0 };
+ int err;
+ struct reftable_log_record *out = NULL;
+ size_t len = 0;
+ size_t cap = 0;
+ size_t i;
+
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ err = reftable_iterator_seek_log(&it, "a");
+ check(!err);
+ check_int(reftable_merged_table_hash_id(mt), ==, GIT_SHA1_FORMAT_ID);
+ check_int(reftable_merged_table_min_update_index(mt), ==, 1);
+ check_int(reftable_merged_table_max_update_index(mt), ==, 3);
+
+ while (len < 100) { /* cap loops/recursion. */
+ struct reftable_log_record log = { 0 };
+ int err = reftable_iterator_next_log(&it, &log);
+ if (err > 0)
+ break;
+
+ REFTABLE_ALLOC_GROW(out, len + 1, cap);
+ out[len++] = log;
+ }
+ reftable_iterator_destroy(&it);
+
+ check_int(ARRAY_SIZE(want), ==, len);
+ for (i = 0; i < len; i++)
+ check(reftable_log_record_equal(want[i], &out[i],
+ GIT_SHA1_RAWSZ));
+
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ err = reftable_iterator_seek_log_at(&it, "a", 2);
+ check(!err);
+ reftable_log_record_release(&out[0]);
+ err = reftable_iterator_next_log(&it, &out[0]);
+ check(!err);
+ check(reftable_log_record_equal(&out[0], &r3[0], GIT_SHA1_RAWSZ));
+ reftable_iterator_destroy(&it);
+
+ for (i = 0; i < len; i++)
+ reftable_log_record_release(&out[i]);
+ reftable_free(out);
+
+ for (i = 0; i < 3; i++)
+ strbuf_release(&bufs[i]);
+ readers_destroy(readers, 3);
+ reftable_merged_table_free(mt);
+ reftable_free(bs);
+}
+
+static void t_default_write_opts(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 rec = {
+ .refname = (char *) "master",
+ .update_index = 1,
+ };
+ int err;
+ struct reftable_block_source source = { 0 };
+ struct reftable_table *tab = reftable_calloc(1, sizeof(*tab));
+ uint32_t hash_id;
+ struct reftable_reader *rd = NULL;
+ struct reftable_merged_table *merged = NULL;
+
+ reftable_writer_set_limits(w, 1, 1);
+
+ err = reftable_writer_add_ref(w, &rec);
+ check(!err);
+
+ err = reftable_writer_close(w);
+ check(!err);
+ reftable_writer_free(w);
+
+ block_source_from_strbuf(&source, &buf);
+
+ err = reftable_new_reader(&rd, &source, "filename");
+ check(!err);
+
+ hash_id = reftable_reader_hash_id(rd);
+ check_int(hash_id, ==, GIT_SHA1_FORMAT_ID);
+
+ reftable_table_from_reader(&tab[0], rd);
+ err = reftable_new_merged_table(&merged, tab, 1, GIT_SHA256_FORMAT_ID);
+ check_int(err, ==, REFTABLE_FORMAT_ERROR);
+ err = reftable_new_merged_table(&merged, tab, 1, GIT_SHA1_FORMAT_ID);
+ check(!err);
+
+ reftable_reader_free(rd);
+ reftable_merged_table_free(merged);
+ strbuf_release(&buf);
+}
+
+
+int cmd_main(int argc, const char *argv[])
+{
+ TEST(t_default_write_opts(), "merged table with default write opts");
+ TEST(t_merged_logs(), "merged table with multiple log updates for same ref");
+ TEST(t_merged_refs(), "merged table with multiple updates to same ref");
+ TEST(t_merged_single_record(), "ref ocurring in only one record can be fetched");
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c
new file mode 100644
index 0000000000..039bd0f1f9
--- /dev/null
+++ b/t/unit-tests/t-reftable-pq.c
@@ -0,0 +1,152 @@
+/*
+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/constants.h"
+#include "reftable/pq.h"
+
+static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq)
+{
+ for (size_t i = 1; i < pq->len; i++) {
+ size_t parent = (i - 1) / 2;
+ check(pq_less(&pq->heap[parent], &pq->heap[i]));
+ }
+}
+
+static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b)
+{
+ return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index);
+}
+
+static void t_pq_record(void)
+{
+ struct merged_iter_pqueue pq = { 0 };
+ struct reftable_record recs[54];
+ size_t N = ARRAY_SIZE(recs) - 1, i;
+ char *last = NULL;
+
+ for (i = 0; i < N; i++) {
+ reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
+ }
+
+ i = 1;
+ do {
+ struct pq_entry e = {
+ .rec = &recs[i],
+ };
+
+ merged_iter_pqueue_add(&pq, &e);
+ merged_iter_pqueue_check(&pq);
+ i = (i * 7) % N;
+ } while (i != 1);
+
+ while (!merged_iter_pqueue_is_empty(pq)) {
+ struct pq_entry top = merged_iter_pqueue_top(pq);
+ struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ merged_iter_pqueue_check(&pq);
+
+ check(pq_entry_equal(&top, &e));
+ check(reftable_record_type(e.rec) == BLOCK_TYPE_REF);
+ if (last)
+ check_int(strcmp(last, e.rec->u.ref.refname), <, 0);
+ last = e.rec->u.ref.refname;
+ }
+
+ for (i = 0; i < N; i++)
+ reftable_record_release(&recs[i]);
+ merged_iter_pqueue_release(&pq);
+}
+
+static void t_pq_index(void)
+{
+ struct merged_iter_pqueue pq = { 0 };
+ struct reftable_record recs[13];
+ char *last = NULL;
+ size_t N = ARRAY_SIZE(recs), i;
+
+ for (i = 0; i < N; i++) {
+ reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ recs[i].u.ref.refname = (char *) "refs/heads/master";
+ }
+
+ i = 1;
+ do {
+ struct pq_entry e = {
+ .rec = &recs[i],
+ .index = i,
+ };
+
+ merged_iter_pqueue_add(&pq, &e);
+ merged_iter_pqueue_check(&pq);
+ i = (i * 7) % N;
+ } while (i != 1);
+
+ for (i = N - 1; i > 0; i--) {
+ struct pq_entry top = merged_iter_pqueue_top(pq);
+ struct pq_entry e = merged_iter_pqueue_remove(&pq);
+ merged_iter_pqueue_check(&pq);
+
+ check(pq_entry_equal(&top, &e));
+ check(reftable_record_type(e.rec) == BLOCK_TYPE_REF);
+ check_int(e.index, ==, i);
+ if (last)
+ check_str(last, e.rec->u.ref.refname);
+ last = e.rec->u.ref.refname;
+ }
+
+ merged_iter_pqueue_release(&pq);
+}
+
+static void t_merged_iter_pqueue_top(void)
+{
+ struct merged_iter_pqueue pq = { 0 };
+ struct reftable_record recs[13];
+ size_t N = ARRAY_SIZE(recs), i;
+
+ for (i = 0; i < N; i++) {
+ reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ recs[i].u.ref.refname = (char *) "refs/heads/master";
+ }
+
+ i = 1;
+ do {
+ struct pq_entry e = {
+ .rec = &recs[i],
+ .index = i,
+ };
+
+ merged_iter_pqueue_add(&pq, &e);
+ merged_iter_pqueue_check(&pq);
+ i = (i * 7) % N;
+ } while (i != 1);
+
+ for (i = N - 1; i > 0; i--) {
+ struct pq_entry top = merged_iter_pqueue_top(pq);
+ struct pq_entry e = merged_iter_pqueue_remove(&pq);
+
+ merged_iter_pqueue_check(&pq);
+ check(pq_entry_equal(&top, &e));
+ check(reftable_record_equal(top.rec, &recs[i], GIT_SHA1_RAWSZ));
+ for (size_t j = 0; i < pq.len; j++) {
+ check(pq_less(&top, &pq.heap[j]));
+ check_int(top.index, >, j);
+ }
+ }
+
+ merged_iter_pqueue_release(&pq);
+}
+
+int cmd_main(int argc, const char *argv[])
+{
+ TEST(t_pq_record(), "pq works with record-based comparison");
+ TEST(t_pq_index(), "pq works with index-based comparison");
+ TEST(t_merged_iter_pqueue_top(), "merged_iter_pqueue_top works");
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
new file mode 100644
index 0000000000..cb649ee419
--- /dev/null
+++ b/t/unit-tests/t-reftable-record.c
@@ -0,0 +1,551 @@
+/*
+ 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/constants.h"
+#include "reftable/record.h"
+
+static void t_copy(struct reftable_record *rec)
+{
+ struct reftable_record copy;
+ uint8_t typ;
+
+ typ = reftable_record_type(rec);
+ reftable_record_init(&copy, typ);
+ reftable_record_copy_from(&copy, rec, GIT_SHA1_RAWSZ);
+ /* do it twice to catch memory leaks */
+ reftable_record_copy_from(&copy, rec, GIT_SHA1_RAWSZ);
+ check(reftable_record_equal(rec, &copy, GIT_SHA1_RAWSZ));
+
+ reftable_record_release(&copy);
+}
+
+static void t_varint_roundtrip(void)
+{
+ uint64_t inputs[] = { 0,
+ 1,
+ 27,
+ 127,
+ 128,
+ 257,
+ 4096,
+ ((uint64_t)1 << 63),
+ ((uint64_t)1 << 63) + ((uint64_t)1 << 63) - 1 };
+
+ for (size_t i = 0; i < ARRAY_SIZE(inputs); i++) {
+ uint8_t dest[10];
+
+ struct string_view out = {
+ .buf = dest,
+ .len = sizeof(dest),
+ };
+ uint64_t in = inputs[i];
+ int n = put_var_int(&out, in);
+ uint64_t got = 0;
+
+ check_int(n, >, 0);
+ out.len = n;
+ n = get_var_int(&got, &out);
+ check_int(n, >, 0);
+
+ check_int(got, ==, in);
+ }
+}
+
+static void set_hash(uint8_t *h, int j)
+{
+ for (int i = 0; i < hash_size(GIT_SHA1_FORMAT_ID); i++)
+ h[i] = (j >> i) & 0xff;
+}
+
+static void t_reftable_ref_record_comparison(void)
+{
+ struct reftable_record in[3] = {
+ {
+ .type = BLOCK_TYPE_REF,
+ .u.ref.refname = (char *) "refs/heads/master",
+ .u.ref.value_type = REFTABLE_REF_VAL1,
+ },
+ {
+ .type = BLOCK_TYPE_REF,
+ .u.ref.refname = (char *) "refs/heads/master",
+ .u.ref.value_type = REFTABLE_REF_DELETION,
+ },
+ {
+ .type = BLOCK_TYPE_REF,
+ .u.ref.refname = (char *) "HEAD",
+ .u.ref.value_type = REFTABLE_REF_SYMREF,
+ .u.ref.value.symref = (char *) "refs/heads/master",
+ },
+ };
+
+ check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+
+ check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ));
+ check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+
+ in[1].u.ref.value_type = in[0].u.ref.value_type;
+ check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+}
+
+static void t_reftable_ref_record_compare_name(void)
+{
+ struct reftable_ref_record recs[3] = {
+ {
+ .refname = (char *) "refs/heads/a"
+ },
+ {
+ .refname = (char *) "refs/heads/b"
+ },
+ {
+ .refname = (char *) "refs/heads/a"
+ },
+ };
+
+ check_int(reftable_ref_record_compare_name(&recs[0], &recs[1]), <, 0);
+ check_int(reftable_ref_record_compare_name(&recs[1], &recs[0]), >, 0);
+ check_int(reftable_ref_record_compare_name(&recs[0], &recs[2]), ==, 0);
+}
+
+static void t_reftable_ref_record_roundtrip(void)
+{
+ struct strbuf scratch = STRBUF_INIT;
+
+ for (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) {
+ struct reftable_record in = {
+ .type = BLOCK_TYPE_REF,
+ .u.ref.value_type = i,
+ };
+ struct reftable_record out = { .type = BLOCK_TYPE_REF };
+ struct strbuf key = STRBUF_INIT;
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ int n, m;
+
+ in.u.ref.value_type = i;
+ switch (i) {
+ case REFTABLE_REF_DELETION:
+ break;
+ case REFTABLE_REF_VAL1:
+ set_hash(in.u.ref.value.val1, 1);
+ break;
+ case REFTABLE_REF_VAL2:
+ set_hash(in.u.ref.value.val2.value, 1);
+ set_hash(in.u.ref.value.val2.target_value, 2);
+ break;
+ case REFTABLE_REF_SYMREF:
+ in.u.ref.value.symref = xstrdup("target");
+ break;
+ }
+ in.u.ref.refname = xstrdup("refs/heads/master");
+
+ t_copy(&in);
+
+ check_int(reftable_record_val_type(&in), ==, i);
+ check_int(reftable_record_is_deletion(&in), ==, i == REFTABLE_REF_DELETION);
+
+ reftable_record_key(&in, &key);
+ n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
+ check_int(n, >, 0);
+
+ /* decode into a non-zero reftable_record to test for leaks. */
+ m = reftable_record_decode(&out, key, i, dest, GIT_SHA1_RAWSZ, &scratch);
+ check_int(n, ==, m);
+
+ check(reftable_ref_record_equal(&in.u.ref, &out.u.ref,
+ GIT_SHA1_RAWSZ));
+ reftable_record_release(&in);
+
+ strbuf_release(&key);
+ reftable_record_release(&out);
+ }
+
+ strbuf_release(&scratch);
+}
+
+static void t_reftable_log_record_comparison(void)
+{
+ struct reftable_record in[3] = {
+ {
+ .type = BLOCK_TYPE_LOG,
+ .u.log.refname = (char *) "refs/heads/master",
+ .u.log.update_index = 42,
+ },
+ {
+ .type = BLOCK_TYPE_LOG,
+ .u.log.refname = (char *) "refs/heads/master",
+ .u.log.update_index = 22,
+ },
+ {
+ .type = BLOCK_TYPE_LOG,
+ .u.log.refname = (char *) "refs/heads/main",
+ .u.log.update_index = 22,
+ },
+ };
+
+ check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ));
+ check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ /* comparison should be reversed for equal keys, because
+ * comparison is now performed on the basis of update indices */
+ check_int(reftable_record_cmp(&in[0], &in[1]), <, 0);
+
+ in[1].u.log.update_index = in[0].u.log.update_index;
+ check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+}
+
+static void t_reftable_log_record_compare_key(void)
+{
+ struct reftable_log_record logs[3] = {
+ {
+ .refname = (char *) "refs/heads/a",
+ .update_index = 1,
+ },
+ {
+ .refname = (char *) "refs/heads/b",
+ .update_index = 2,
+ },
+ {
+ .refname = (char *) "refs/heads/a",
+ .update_index = 3,
+ },
+ };
+
+ check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0);
+ check_int(reftable_log_record_compare_key(&logs[1], &logs[0]), >, 0);
+
+ logs[1].update_index = logs[0].update_index;
+ check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0);
+
+ check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), >, 0);
+ check_int(reftable_log_record_compare_key(&logs[2], &logs[0]), <, 0);
+ logs[2].update_index = logs[0].update_index;
+ check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), ==, 0);
+}
+
+static void t_reftable_log_record_roundtrip(void)
+{
+ struct reftable_log_record in[] = {
+ {
+ .refname = xstrdup("refs/heads/master"),
+ .update_index = 42,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value = {
+ .update = {
+ .name = xstrdup("han-wen"),
+ .email = xstrdup("hanwen@google.com"),
+ .message = xstrdup("test"),
+ .time = 1577123507,
+ .tz_offset = 100,
+ },
+ }
+ },
+ {
+ .refname = xstrdup("refs/heads/master"),
+ .update_index = 22,
+ .value_type = REFTABLE_LOG_DELETION,
+ },
+ {
+ .refname = xstrdup("branch"),
+ .update_index = 33,
+ .value_type = REFTABLE_LOG_UPDATE,
+ }
+ };
+ struct strbuf scratch = STRBUF_INIT;
+ set_hash(in[0].value.update.new_hash, 1);
+ set_hash(in[0].value.update.old_hash, 2);
+ set_hash(in[2].value.update.new_hash, 3);
+ set_hash(in[2].value.update.old_hash, 4);
+
+ check(!reftable_log_record_is_deletion(&in[0]));
+ check(reftable_log_record_is_deletion(&in[1]));
+ check(!reftable_log_record_is_deletion(&in[2]));
+
+ for (size_t i = 0; i < ARRAY_SIZE(in); i++) {
+ struct reftable_record rec = { .type = BLOCK_TYPE_LOG };
+ struct strbuf key = STRBUF_INIT;
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ /* populate out, to check for leaks. */
+ struct reftable_record out = {
+ .type = BLOCK_TYPE_LOG,
+ .u.log = {
+ .refname = xstrdup("old name"),
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value = {
+ .update = {
+ .name = xstrdup("old name"),
+ .email = xstrdup("old@email"),
+ .message = xstrdup("old message"),
+ },
+ },
+ },
+ };
+ int n, m, valtype;
+
+ rec.u.log = in[i];
+
+ t_copy(&rec);
+
+ reftable_record_key(&rec, &key);
+
+ n = reftable_record_encode(&rec, dest, GIT_SHA1_RAWSZ);
+ check_int(n, >=, 0);
+ valtype = reftable_record_val_type(&rec);
+ m = reftable_record_decode(&out, key, valtype, dest,
+ GIT_SHA1_RAWSZ, &scratch);
+ check_int(n, ==, m);
+
+ check(reftable_log_record_equal(&in[i], &out.u.log,
+ GIT_SHA1_RAWSZ));
+ reftable_log_record_release(&in[i]);
+ strbuf_release(&key);
+ reftable_record_release(&out);
+ }
+
+ strbuf_release(&scratch);
+}
+
+static void t_key_roundtrip(void)
+{
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ struct strbuf last_key = STRBUF_INIT;
+ struct strbuf key = STRBUF_INIT;
+ struct strbuf roundtrip = STRBUF_INIT;
+ int restart;
+ uint8_t extra;
+ int n, m;
+ uint8_t rt_extra;
+
+ strbuf_addstr(&last_key, "refs/heads/master");
+ strbuf_addstr(&key, "refs/tags/bla");
+ extra = 6;
+ n = reftable_encode_key(&restart, dest, last_key, key, extra);
+ check(!restart);
+ check_int(n, >, 0);
+
+ strbuf_addstr(&roundtrip, "refs/heads/master");
+ m = reftable_decode_key(&roundtrip, &rt_extra, dest);
+ check_int(n, ==, m);
+ check(!strbuf_cmp(&key, &roundtrip));
+ check_int(rt_extra, ==, extra);
+
+ strbuf_release(&last_key);
+ strbuf_release(&key);
+ strbuf_release(&roundtrip);
+}
+
+static void t_reftable_obj_record_comparison(void)
+{
+
+ uint8_t id_bytes[] = { 0, 1, 2, 3, 4, 5, 6 };
+ uint64_t offsets[] = { 0, 16, 32, 48, 64, 80, 96, 112};
+ struct reftable_record in[3] = {
+ {
+ .type = BLOCK_TYPE_OBJ,
+ .u.obj.hash_prefix = id_bytes,
+ .u.obj.hash_prefix_len = 7,
+ .u.obj.offsets = offsets,
+ .u.obj.offset_len = 8,
+ },
+ {
+ .type = BLOCK_TYPE_OBJ,
+ .u.obj.hash_prefix = id_bytes,
+ .u.obj.hash_prefix_len = 7,
+ .u.obj.offsets = offsets,
+ .u.obj.offset_len = 5,
+ },
+ {
+ .type = BLOCK_TYPE_OBJ,
+ .u.obj.hash_prefix = id_bytes,
+ .u.obj.hash_prefix_len = 5,
+ },
+ };
+
+ check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+
+ check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ));
+ check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+
+ in[1].u.obj.offset_len = in[0].u.obj.offset_len;
+ check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+}
+
+static void t_reftable_obj_record_roundtrip(void)
+{
+ uint8_t testHash1[GIT_SHA1_RAWSZ] = { 1, 2, 3, 4, 0 };
+ uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 };
+ struct reftable_obj_record recs[3] = {
+ {
+ .hash_prefix = testHash1,
+ .hash_prefix_len = 5,
+ .offsets = till9,
+ .offset_len = 3,
+ },
+ {
+ .hash_prefix = testHash1,
+ .hash_prefix_len = 5,
+ .offsets = till9,
+ .offset_len = 9,
+ },
+ {
+ .hash_prefix = testHash1,
+ .hash_prefix_len = 5,
+ },
+ };
+ struct strbuf scratch = STRBUF_INIT;
+
+ for (size_t i = 0; i < ARRAY_SIZE(recs); i++) {
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ struct reftable_record in = {
+ .type = BLOCK_TYPE_OBJ,
+ .u = {
+ .obj = recs[i],
+ },
+ };
+ struct strbuf key = STRBUF_INIT;
+ struct reftable_record out = { .type = BLOCK_TYPE_OBJ };
+ int n, m;
+ uint8_t extra;
+
+ check(!reftable_record_is_deletion(&in));
+ t_copy(&in);
+ reftable_record_key(&in, &key);
+ n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
+ check_int(n, >, 0);
+ extra = reftable_record_val_type(&in);
+ m = reftable_record_decode(&out, key, extra, dest,
+ GIT_SHA1_RAWSZ, &scratch);
+ check_int(n, ==, m);
+
+ check(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));
+ strbuf_release(&key);
+ reftable_record_release(&out);
+ }
+
+ strbuf_release(&scratch);
+}
+
+static void t_reftable_index_record_comparison(void)
+{
+ struct reftable_record in[3] = {
+ {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx.offset = 22,
+ .u.idx.last_key = STRBUF_INIT,
+ },
+ {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx.offset = 32,
+ .u.idx.last_key = STRBUF_INIT,
+ },
+ {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx.offset = 32,
+ .u.idx.last_key = STRBUF_INIT,
+ },
+ };
+ strbuf_addstr(&in[0].u.idx.last_key, "refs/heads/master");
+ strbuf_addstr(&in[1].u.idx.last_key, "refs/heads/master");
+ strbuf_addstr(&in[2].u.idx.last_key, "refs/heads/branch");
+
+ check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+
+ check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ));
+ check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+
+ in[1].u.idx.offset = in[0].u.idx.offset;
+ check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+
+ for (size_t i = 0; i < ARRAY_SIZE(in); i++)
+ reftable_record_release(&in[i]);
+}
+
+static void t_reftable_index_record_roundtrip(void)
+{
+ struct reftable_record in = {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx = {
+ .offset = 42,
+ .last_key = STRBUF_INIT,
+ },
+ };
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ struct strbuf scratch = STRBUF_INIT;
+ struct strbuf key = STRBUF_INIT;
+ struct reftable_record out = {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx = { .last_key = STRBUF_INIT },
+ };
+ int n, m;
+ uint8_t extra;
+
+ strbuf_addstr(&in.u.idx.last_key, "refs/heads/master");
+ reftable_record_key(&in, &key);
+ t_copy(&in);
+
+ check(!reftable_record_is_deletion(&in));
+ check(!strbuf_cmp(&key, &in.u.idx.last_key));
+ n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
+ check_int(n, >, 0);
+
+ extra = reftable_record_val_type(&in);
+ m = reftable_record_decode(&out, key, extra, dest, GIT_SHA1_RAWSZ,
+ &scratch);
+ check_int(m, ==, n);
+
+ check(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));
+
+ reftable_record_release(&out);
+ strbuf_release(&key);
+ strbuf_release(&scratch);
+ strbuf_release(&in.u.idx.last_key);
+}
+
+int cmd_main(int argc, const char *argv[])
+{
+ TEST(t_reftable_ref_record_comparison(), "comparison operations work on ref record");
+ TEST(t_reftable_log_record_comparison(), "comparison operations work on log record");
+ TEST(t_reftable_index_record_comparison(), "comparison operations work on index record");
+ TEST(t_reftable_obj_record_comparison(), "comparison operations work on obj record");
+ TEST(t_reftable_ref_record_compare_name(), "reftable_ref_record_compare_name works");
+ TEST(t_reftable_log_record_compare_key(), "reftable_log_record_compare_key works");
+ TEST(t_reftable_log_record_roundtrip(), "record operations work on log record");
+ TEST(t_reftable_ref_record_roundtrip(), "record operations work on ref record");
+ TEST(t_varint_roundtrip(), "put_var_int and get_var_int work");
+ TEST(t_key_roundtrip(), "reftable_encode_key and reftable_decode_key work");
+ TEST(t_reftable_obj_record_roundtrip(), "record operations work on obj record");
+ TEST(t_reftable_index_record_roundtrip(), "record operations work on index record");
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/t-reftable-tree.c
new file mode 100644
index 0000000000..e7d774d774
--- /dev/null
+++ b/t/unit-tests/t-reftable-tree.c
@@ -0,0 +1,84 @@
+/*
+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/tree.h"
+
+static int t_compare(const void *a, const void *b)
+{
+ return (char *)a - (char *)b;
+}
+
+struct curry {
+ void **arr;
+ size_t len;
+};
+
+static void store(void *arg, void *key)
+{
+ struct curry *c = arg;
+ c->arr[c->len++] = key;
+}
+
+static void t_tree_search(void)
+{
+ struct tree_node *root = NULL;
+ void *values[11] = { 0 };
+ struct tree_node *nodes[11] = { 0 };
+ size_t i = 1;
+
+ /*
+ * Pseudo-randomly insert the pointers for elements between
+ * values[1] and values[10] (inclusive) in the tree.
+ */
+ do {
+ nodes[i] = tree_search(&values[i], &root, &t_compare, 1);
+ i = (i * 7) % 11;
+ } while (i != 1);
+
+ for (i = 1; i < ARRAY_SIZE(nodes); i++) {
+ check_pointer_eq(&values[i], nodes[i]->key);
+ check_pointer_eq(nodes[i], tree_search(&values[i], &root, &t_compare, 0));
+ }
+
+ check(!tree_search(values, &root, t_compare, 0));
+ tree_free(root);
+}
+
+static void t_infix_walk(void)
+{
+ struct tree_node *root = NULL;
+ void *values[11] = { 0 };
+ void *out[11] = { 0 };
+ struct curry c = {
+ .arr = (void **) &out,
+ };
+ size_t i = 1;
+ size_t count = 0;
+
+ do {
+ tree_search(&values[i], &root, t_compare, 1);
+ i = (i * 7) % 11;
+ count++;
+ } while (i != 1);
+
+ infix_walk(root, &store, &c);
+ for (i = 1; i < ARRAY_SIZE(values); i++)
+ check_pointer_eq(&values[i], out[i - 1]);
+ check(!out[i - 1]);
+ check_int(c.len, ==, count);
+ tree_free(root);
+}
+
+int cmd_main(int argc, const char *argv[])
+{
+ TEST(t_tree_search(), "tree_search works");
+ TEST(t_infix_walk(), "infix_walk works");
+
+ return test_done();
+}
diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
index d4615ab06d..fa1a041469 100644
--- a/t/unit-tests/t-strvec.c
+++ b/t/unit-tests/t-strvec.c
@@ -3,38 +3,21 @@
#include "strvec.h"
#define check_strvec(vec, ...) \
- check_strvec_loc(TEST_LOCATION(), vec, __VA_ARGS__)
-LAST_ARG_MUST_BE_NULL
-static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
-{
- va_list ap;
- size_t nr = 0;
-
- va_start(ap, vec);
- while (1) {
- const char *str = va_arg(ap, const char *);
- if (!str)
- break;
-
- if (!check_uint(vec->nr, >, nr) ||
- !check_uint(vec->alloc, >, nr) ||
- !check_str(vec->v[nr], str)) {
- struct strbuf msg = STRBUF_INIT;
- strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
- test_assert(loc, msg.buf, 0);
- strbuf_release(&msg);
- va_end(ap);
- return;
- }
-
- nr++;
- }
- va_end(ap);
-
- check_uint(vec->nr, ==, nr);
- check_uint(vec->alloc, >=, nr);
- check_pointer_eq(vec->v[nr], NULL);
-}
+ do { \
+ const char *expect[] = { __VA_ARGS__ }; \
+ if (check_uint(ARRAY_SIZE(expect), >, 0) && \
+ check_pointer_eq(expect[ARRAY_SIZE(expect) - 1], NULL) && \
+ check_uint((vec)->nr, ==, ARRAY_SIZE(expect) - 1) && \
+ check_uint((vec)->nr, <=, (vec)->alloc)) { \
+ for (size_t i = 0; i < ARRAY_SIZE(expect); i++) { \
+ if (!check_str((vec)->v[i], expect[i])) { \
+ test_msg(" i: %"PRIuMAX, \
+ (uintmax_t)i); \
+ break; \
+ } \
+ } \
+ } \
+ } while (0)
static void t_static_init(void)
{
diff --git a/t/unit-tests/test-lib.h b/t/unit-tests/test-lib.h
index 2de6d715d5..c59f646fd9 100644
--- a/t/unit-tests/test-lib.h
+++ b/t/unit-tests/test-lib.h
@@ -76,8 +76,9 @@ int test_assert(const char *location, const char *check, int ok);
int check_bool_loc(const char *loc, const char *check, int ok);
/*
- * Compare two integers. Prints a message with the two values if the
- * comparison fails. NB this is not thread safe.
+ * Compare the equality of two pointers of same type. Prints a message
+ * with the two values if the equality fails. NB this is not thread
+ * safe.
*/
#define check_pointer_eq(a, b) \
(test__tmp[0].p = (a), test__tmp[1].p = (b), \