git-sync/test_git.sh

990 lines
28 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright 2023 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
function fail() {
echo "FAIL:" "$@" >&3
return 42
}
function pass() {
echo "PASS"
}
function assert_file_exists() {
if ! [[ -f "$1" ]]; then
fail "$1 does not exist"
fi
}
function assert_file_absent() {
if [[ -f "$1" ]]; then
fail "$1 exists but should not"
fi
}
function assert_eq() {
if [[ "$1" == "$2" ]]; then
return
fi
fail "'$1' does not equal '$2'"
}
function assert_substr() {
if [[ "$1" == *"$2"* ]]; then
return
fi
fail "'$1' does not contain '$2'"
}
# DIR is the directory in which all this test's state lives.
RUNID="${RANDOM}${RANDOM}"
DIR="/tmp/git-sync-git.$RUNID"
mkdir "$DIR"
# WORKDIR is where test cases run
WORKDIR="$DIR/work"
function clean_workdir() {
rm -rf "$WORKDIR"
mkdir -p "$WORKDIR"
}
#
# After all the test functions are defined, we can iterate over them and run
# them all automatically. See the end of this file.
#
##############################################
# Test `git init` on an existing repo
##############################################
function git::reinit_existing_repo() {
git init -b main
date > file
git add file
git commit -qam 'commit_1'
TREE1="$(git ls-tree HEAD | cut -d' ' -f3 | cut -f1)"
git init
TREE2="$(git ls-tree HEAD | cut -d' ' -f3 | cut -f1)"
assert_eq "$TREE1" "$TREE2"
}
##############################################
# Test `git fetch` of a branch
##############################################
function git::fetch_upstream_branch() {
mkdir upstream
pushd upstream >/dev/null
git init -b main
# A commit on branch 1
git checkout -b upstream_branch_1
date > file_1
git add file_1
git commit -qam 'commit_1'
SHA1="$(git rev-parse HEAD)"
# A commit on branch 2
git checkout -b upstream_branch_2
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA2="$(git rev-parse HEAD)"
popd >/dev/null
mkdir clone
cd clone
git init -b clone_branch
assert_substr "$(git cat-file -t "$SHA1" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA2" 2>&1 || true)" "could not get object info"
git fetch "file://$WORKDIR/upstream" upstream_branch_1
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_substr "$(git cat-file -t "$SHA2" 2>&1 || true)" "could not get object info"
git checkout "$SHA1"
assert_file_exists file_1
assert_file_absent file_2
git fetch "file://$WORKDIR/upstream" upstream_branch_2
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
git checkout "$SHA2"
assert_file_exists file_1
assert_file_exists file_2
}
##############################################
# Test `git fetch` of a tag
##############################################
function git::fetch_upstream_tag() {
mkdir upstream
pushd upstream >/dev/null
git init -b main
# A tag on branch 1 (not at HEAD)
git checkout -b upstream_branch_1
date > file_1
git add file_1
git commit -qam 'commit_1'
SHA1="$(git rev-parse HEAD)"
git tag upstream_tag_1
# Another tag on branch 1 (at HEAD)
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA2="$(git rev-parse HEAD)"
git tag upstream_tag_2
# A tag on branch 2 (not at HEAD)
git checkout -b upstream_branch_2
date > file_3
git add file_3
git commit -qam 'commit_3'
SHA3="$(git rev-parse HEAD)"
git tag upstream_tag_3
# Another tag on branch 2 (at HEAD)
date > file_4
git add file_4
git commit -qam 'commit_4'
SHA4="$(git rev-parse HEAD)"
git tag upstream_tag_4
popd >/dev/null
mkdir clone
pushd clone >/dev/null
git init -b clone_branch
assert_substr "$(git cat-file -t "$SHA1" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA2" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git fetch "file://$WORKDIR/upstream" upstream_tag_1
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_substr "$(git cat-file -t "$SHA2" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA1"
assert_file_exists file_1
assert_file_absent file_2
assert_file_absent file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" upstream_tag_2
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA2"
assert_file_exists file_1
assert_file_exists file_2
assert_file_absent file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" upstream_tag_3
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_eq "$(git cat-file -t "$SHA3")" "commit"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA3"
assert_file_exists file_1
assert_file_exists file_2
assert_file_exists file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" upstream_tag_4
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_eq "$(git cat-file -t "$SHA3")" "commit"
assert_eq "$(git cat-file -t "$SHA4")" "commit"
git checkout "$SHA4"
assert_file_exists file_1
assert_file_exists file_2
assert_file_exists file_3
assert_file_exists file_4
}
##############################################
# Test `git fetch` of an annotated tag
##############################################
function git::fetch_upstream_tag_annotated() {
mkdir upstream
pushd upstream >/dev/null
git init -b main
# A tag on branch 1 (not at HEAD)
git checkout -b upstream_branch_1
date > file_1
git add file_1
git commit -qam 'commit_1'
SHA1="$(git rev-parse HEAD)"
git tag -am "anntag_1" upstream_anntag_1
# Another tag on branch 1 (at HEAD)
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA2="$(git rev-parse HEAD)"
git tag -am "anntag_2" upstream_anntag_2
# A tag on branch 2 (not at HEAD)
git checkout -b upstream_branch_2
date > file_3
git add file_3
git commit -qam 'commit_3'
SHA3="$(git rev-parse HEAD)"
git tag -am "anntag_3" upstream_anntag_3
# Another tag on branch 2 (at HEAD)
date > file_4
git add file_4
git commit -qam 'commit_4'
SHA4="$(git rev-parse HEAD)"
git tag -am "anntag_4" upstream_anntag_4
popd >/dev/null
mkdir clone
pushd clone >/dev/null
git init -b clone_branch
assert_substr "$(git cat-file -t "$SHA1" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA2" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git fetch "file://$WORKDIR/upstream" upstream_anntag_1
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_substr "$(git cat-file -t "$SHA2" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA1"
assert_file_exists file_1
assert_file_absent file_2
assert_file_absent file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" upstream_anntag_2
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA2"
assert_file_exists file_1
assert_file_exists file_2
assert_file_absent file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" upstream_anntag_3
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_eq "$(git cat-file -t "$SHA3")" "commit"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA3"
assert_file_exists file_1
assert_file_exists file_2
assert_file_exists file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" upstream_anntag_4
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_eq "$(git cat-file -t "$SHA3")" "commit"
assert_eq "$(git cat-file -t "$SHA4")" "commit"
git checkout "$SHA4"
assert_file_exists file_1
assert_file_exists file_2
assert_file_exists file_3
assert_file_exists file_4
}
##############################################
# Test `git fetch` of a SHA
##############################################
function git::fetch_upstream_sha() {
mkdir upstream
pushd upstream >/dev/null
git init -b main
# A commit on branch 1 (not at HEAD)
git checkout -b upstream_branch_1
date > file_1
git add file_1
git commit -qam 'commit_1'
SHA1="$(git rev-parse HEAD)"
# Another commit on branch 1 (at HEAD)
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA2="$(git rev-parse HEAD)"
# A commit on branch 2 (not at HEAD)
git checkout -b upstream_branch_2
date > file_3
git add file_3
git commit -qam 'commit_3'
SHA3="$(git rev-parse HEAD)"
# Another commit on branch 2 (at HEAD)
date > file_4
git add file_4
git commit -qam 'commit_4'
SHA4="$(git rev-parse HEAD)"
popd >/dev/null
mkdir clone
pushd clone >/dev/null
git init -b clone_branch
assert_substr "$(git cat-file -t "$SHA1" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA2" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git fetch "file://$WORKDIR/upstream" "$SHA1"
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_substr "$(git cat-file -t "$SHA2" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA1"
assert_file_exists file_1
assert_file_absent file_2
assert_file_absent file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" "$SHA2"
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_substr "$(git cat-file -t "$SHA3" 2>&1 || true)" "could not get object info"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA2"
assert_file_exists file_1
assert_file_exists file_2
assert_file_absent file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" "$SHA3"
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_eq "$(git cat-file -t "$SHA3")" "commit"
assert_substr "$(git cat-file -t "$SHA4" 2>&1 || true)" "could not get object info"
git checkout "$SHA3"
assert_file_exists file_1
assert_file_exists file_2
assert_file_exists file_3
assert_file_absent file_4
git fetch "file://$WORKDIR/upstream" "$SHA4"
assert_eq "$(git cat-file -t "$SHA1")" "commit"
assert_eq "$(git cat-file -t "$SHA2")" "commit"
assert_eq "$(git cat-file -t "$SHA3")" "commit"
assert_eq "$(git cat-file -t "$SHA4")" "commit"
git checkout "$SHA4"
assert_file_exists file_1
assert_file_exists file_2
assert_file_exists file_3
assert_file_exists file_4
}
##############################################
# Test git shallow fetch from a branch
##############################################
function git::shallow_fetch_branch() {
mkdir upstream
pushd upstream >/dev/null
git init -b upstream_branch
# Some commits
date > file_1
git add file_1
git commit -qam 'commit_1'
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA="$(git rev-parse HEAD)"
popd >/dev/null
mkdir clone
cd clone
git init -b clone_branch
git fetch "file://$WORKDIR/upstream" upstream_branch
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
git fetch "file://$WORKDIR/upstream" upstream_branch --depth 1
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "true"
git fetch "file://$WORKDIR/upstream" upstream_branch --unshallow
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
}
##############################################
# Test git shallow fetch from a tag
##############################################
function git::shallow_fetch_tag() {
mkdir upstream
pushd upstream >/dev/null
git init -b upstream_branch
# Some commits
date > file_1
git add file_1
git commit -qam 'commit_1'
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA="$(git rev-parse HEAD)"
git tag upstream_tag
popd >/dev/null
mkdir clone
cd clone
git init -b clone_branch
git fetch "file://$WORKDIR/upstream" upstream_tag
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
git fetch "file://$WORKDIR/upstream" upstream_tag --depth 1
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "true"
git fetch "file://$WORKDIR/upstream" upstream_tag --unshallow
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
}
##############################################
# Test git shallow fetch from an annotated tag
##############################################
function git::shallow_fetch_tag_annotated() {
mkdir upstream
pushd upstream >/dev/null
git init -b upstream_branch
# Some commits
date > file_1
git add file_1
git commit -qam 'commit_1'
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA="$(git rev-parse HEAD)"
git tag -am "upstream_anntag" upstream_anntag
popd >/dev/null
mkdir clone
cd clone
git init -b clone_branch
git fetch "file://$WORKDIR/upstream" upstream_anntag
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
git fetch "file://$WORKDIR/upstream" upstream_anntag --depth 1
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "true"
git fetch "file://$WORKDIR/upstream" upstream_anntag --unshallow
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
}
##############################################
# Test git shallow fetch from a SHA
##############################################
function git::shallow_fetch_sha() {
mkdir upstream
pushd upstream >/dev/null
git init -b upstream_branch
# Some commits
date > file_1
git add file_1
git commit -qam 'commit_1'
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA="$(git rev-parse HEAD)"
popd >/dev/null
mkdir clone
cd clone
git init -b clone_branch
git fetch "file://$WORKDIR/upstream" "$SHA"
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
git fetch "file://$WORKDIR/upstream" "$SHA" --depth 1
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "true"
git fetch "file://$WORKDIR/upstream" "$SHA" --unshallow
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
}
##############################################
# Test git fetch with depth too large
##############################################
function git::fetch_too_large_depth() {
mkdir upstream
pushd upstream >/dev/null
git init -b upstream_branch
# Some commits
date > file_1
git add file_1
git commit -qam 'commit_1'
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA="$(git rev-parse HEAD)"
popd >/dev/null
mkdir clone
cd clone
git init -b clone_branch
git fetch "file://$WORKDIR/upstream" upstream_branch --depth 1000
git checkout "$SHA"
assert_file_exists file_1
assert_file_exists file_2
assert_eq "$(git rev-parse --is-shallow-repository)" "false"
}
##############################################
# Test git rev-parse with a branch
##############################################
function git::rev_parse_branch() {
mkdir repo
pushd repo >/dev/null
git init -b main
# A commit on branch 1
git checkout -b branch_1
date > file_1
git add file_1
git commit -qam 'commit_1'
SHA1="$(git rev-parse HEAD)"
# A commit on branch 2
git checkout -b branch_2
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA2="$(git rev-parse HEAD)"
assert_eq "$(git rev-parse branch_1)" "$SHA1"
assert_eq "$(git rev-parse 'branch_1^{commit}')" "$SHA1"
assert_eq "$(git rev-parse branch_2)" "$SHA2"
assert_eq "$(git rev-parse 'branch_2^{commit}')" "$SHA2"
}
##############################################
# Test git rev-parse with a tag
##############################################
function git::rev_parse_tag() {
mkdir repo
pushd repo >/dev/null
git init -b main
# A tag on branch 1 (not at HEAD)
git checkout -b branch_1
date > file_1
git add file_1
git commit -qam 'commit_1'
SHA1="$(git rev-parse HEAD)"
git tag tag_1
# Another tag on branch 1 (at HEAD)
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA2="$(git rev-parse HEAD)"
git tag tag_2
# A tag on branch 2 (not at HEAD)
git checkout -b branch_2
date > file_3
git add file_3
git commit -qam 'commit_3'
SHA3="$(git rev-parse HEAD)"
git tag tag_3
# Another tag on branch 2 (at HEAD)
date > file_4
git add file_4
git commit -qam 'commit_4'
SHA4="$(git rev-parse HEAD)"
git tag tag_4
assert_eq "$(git rev-parse tag_1)" "$SHA1"
assert_eq "$(git rev-parse 'tag_1^{commit}')" "$SHA1"
assert_eq "$(git rev-parse tag_2)" "$SHA2"
assert_eq "$(git rev-parse 'tag_2^{commit}')" "$SHA2"
assert_eq "$(git rev-parse tag_3)" "$SHA3"
assert_eq "$(git rev-parse 'tag_3^{commit}')" "$SHA3"
assert_eq "$(git rev-parse tag_4)" "$SHA4"
assert_eq "$(git rev-parse 'tag_4^{commit}')" "$SHA4"
}
##############################################
# Test git rev-parse with an annotated tag
##############################################
function git::rev_parse_tag_annotated() {
mkdir repo
pushd repo >/dev/null
git init -b main
# A tag on branch 1 (not at HEAD)
git checkout -b branch_1
date > file_1
git add file_1
git commit -qam 'commit_1'
SHA1="$(git rev-parse HEAD)"
git tag -am "anntag_1" anntag_1
# Another tag on branch 1 (at HEAD)
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA2="$(git rev-parse HEAD)"
git tag -am "anntag_2" anntag_2
# A tag on branch 2 (not at HEAD)
git checkout -b branch_2
date > file_3
git add file_3
git commit -qam 'commit_3'
SHA3="$(git rev-parse HEAD)"
git tag -am "anntag_3" anntag_3
# Another tag on branch 2 (at HEAD)
date > file_4
git add file_4
git commit -qam 'commit_4'
SHA4="$(git rev-parse HEAD)"
git tag -am "anntag_4" anntag_4
# Annotated tags have their own SHA, which can be found with rev-parse, but
# it doesn't make sense to test rev-parse against itself.
assert_eq "$(git rev-parse 'anntag_1^{commit}')" "$SHA1"
assert_eq "$(git rev-parse 'anntag_2^{commit}')" "$SHA2"
assert_eq "$(git rev-parse 'anntag_3^{commit}')" "$SHA3"
assert_eq "$(git rev-parse 'anntag_4^{commit}')" "$SHA4"
}
##############################################
# Test git rev-parse with a SHA
##############################################
function git::rev_parse_sha() {
mkdir repo
pushd repo >/dev/null
git init -b main
# A commit on branch 1 (not at HEAD)
git checkout -b branch_1
date > file_1
git add file_1
git commit -qam 'commit_1'
SHA1="$(git rev-parse HEAD)"
SHORT1="${SHA1%????????}"
# Another commit on branch 1 (at HEAD)
date > file_2
git add file_2
git commit -qam 'commit_2'
SHA2="$(git rev-parse HEAD)"
SHORT2="${SHA2%????????}"
# A commit on branch 2 (not at HEAD)
git checkout -b branch_2
date > file_3
git add file_3
git commit -qam 'commit_3'
SHA3="$(git rev-parse HEAD)"
SHORT3="${SHA3%????????}"
# Another commit on branch 2 (at HEAD)
date > file_4
git add file_4
git commit -qam 'commit_4'
SHA4="$(git rev-parse HEAD)"
SHORT4="${SHA4%????????}"
assert_eq "$(git rev-parse "$SHA1")" "$SHA1"
assert_eq "$(git rev-parse "$SHA1^{commit}")" "$SHA1"
assert_eq "$(git rev-parse "$SHORT1")" "$SHA1"
assert_eq "$(git rev-parse "$SHA2")" "$SHA2"
assert_eq "$(git rev-parse "$SHA2^{commit}")" "$SHA2"
assert_eq "$(git rev-parse "$SHORT2")" "$SHA2"
assert_eq "$(git rev-parse "$SHA3")" "$SHA3"
assert_eq "$(git rev-parse "$SHA3^{commit}")" "$SHA3"
assert_eq "$(git rev-parse "$SHORT3")" "$SHA3"
assert_eq "$(git rev-parse "$SHA4")" "$SHA4"
assert_eq "$(git rev-parse "$SHA4^{commit}")" "$SHA4"
assert_eq "$(git rev-parse "$SHORT4")" "$SHA4"
}
##############################################
# Test git rev-parse with a non-existent ref
##############################################
function git::rev_parse_non_existent_name() {
mkdir repo
pushd repo >/dev/null
git init -b main
assert_substr "$(git rev-parse does-not-exist 2>&1 || true)" "unknown revision"
}
##############################################
# Test git rev-parse with a non-existent sha
##############################################
function git::rev_parse_non_existent_sha() {
mkdir repo
pushd repo >/dev/null
git init -b main
# As long as it tastes like a SHA, rev-parse is happy, but there is no
# commit for it.
assert_eq "$(git rev-parse 0123456789abcdef0123456789abcdef01234567)" "0123456789abcdef0123456789abcdef01234567"
assert_substr "$(git rev-parse '0123456789abcdef0123456789abcdef01234567^{commit}' 2>&1 || true)" "unknown revision"
# Less-than-full SHAs do not work.
assert_substr "$(git rev-parse 0123456789abcdef 2>&1 || true)" "unknown revision"
assert_substr "$(git rev-parse '0123456789abcdef^{commit}' 2>&1 || true)" "unknown revision"
}
#
# main
#
function list_tests() {
(
shopt -s extdebug
declare -F \
| cut -f3 -d' ' \
| grep "^git::" \
| while read -r X; do declare -F "$X"; done \
| sort -n -k2 \
| cut -f1 -d' ' \
| sed 's/^git:://'
)
}
# Figure out which, if any, tests to run.
mapfile -t all_tests < <(list_tests)
tests_to_run=()
function print_tests() {
echo "available tests:"
for t in "${all_tests[@]}"; do
echo " $t"
done
}
# Validate and accumulate tests to run if args are specified.
for arg; do
# Use -? to list known tests.
if [[ "${arg}" == "-?" ]]; then
print_tests
exit 0
fi
if [[ "${arg}" =~ ^- ]]; then
echo "ERROR: unknown flag '${arg}'"
exit 1
fi
# Make sure each non-flag arg matches at least one test.
nmatches=0
for t in "${all_tests[@]}"; do
if [[ "${t}" =~ ${arg} ]]; then
nmatches=$((nmatches+1))
# Don't run tests twice, just keep the first match.
if [[ " ${tests_to_run[*]} " == *" ${t} "* ]]; then
continue
fi
tests_to_run+=("${t}")
continue
fi
done
if [[ ${nmatches} == 0 ]]; then
echo "ERROR: no tests match pattern '${arg}'"
echo
print_tests
exit 1
fi
tests_to_run+=("${matches[@]}")
done
set -- "${tests_to_run[@]}"
# If no tests were specified, run them all.
if [[ "$#" == 0 ]]; then
set -- "${all_tests[@]}"
fi
function finish() {
r=$?
trap "" INT EXIT ERR
if [[ $r != 0 ]]; then
echo
echo "the directory $DIR was not removed as it contains"\
"log files useful for debugging"
fi
exit $r
}
trap finish INT EXIT ERR
echo
echo "test root is $DIR"
echo
# Run a test function and return its error code. This is needed because POSIX
# dictates that `errexit` does not apply inside a function called in an `if`
# context. But if we don't call it with `if`, then it terminates the whole
# test run as soon as one test fails. So this jumps through hoops to let the
# individual test functions run outside of `if` and return a code in a
# variable.
#
# Args:
# $1: the name of a variable to populate with the return code
# $2+: the test function to run and optional args
function run_test() {
retvar=$1
shift
declare -g "$retvar"
local restore_opts
restore_opts=$(set +o)
set +o errexit
set +o nounset
set +o pipefail
(
set -o errexit
set -o nounset
set -o pipefail
"$@"
)
eval "$retvar=$?"
eval "$restore_opts"
}
# Override local configs for predictability in this test.
export GIT_CONFIG_GLOBAL=/dev/null
export GIT_CONFIG_SYSTEM=/dev/null
# TODO: add a flag to run all the tests inside the git-sync container image
# Iterate over the chosen tests and run them.
FAILS=()
FINAL_RET=0
RUNS="${RUNS:-1}"
for t; do
TEST_RET=0
RUN=0
while (( "${RUN}" < "${RUNS}" )); do
clean_workdir
pushd "$WORKDIR" >/dev/null
sfx=""
if (( "${RUNS}" > 1 )); then
sfx=" ($((RUN+1))/${RUNS})"
fi
echo -n "testcase ${t}${sfx}: "
# Set &3 for our own output, let testcases use &2 and &1.
exec 3>&1
# See comments on run_test for details.
RUN_RET=0
LOG="${DIR}/log.$t"
run_test RUN_RET "git::${t}" >"${LOG}.${RUN}" 2>&1
if [[ "$RUN_RET" == 0 ]]; then
pass
else
TEST_RET=1
if [[ "$RUN_RET" != 42 ]]; then
echo "FAIL: unknown error"
fi
fi
RUN=$((RUN+1))
popd >/dev/null
done
if [[ "$TEST_RET" != 0 ]]; then
FINAL_RET=1
FAILS+=("$t (log: ${LOG}.*)")
fi
done
if [[ "$FINAL_RET" != 0 ]]; then
echo
echo "the following tests failed:"
for f in "${FAILS[@]}"; do
echo " $f"
done
exit 1
fi
# Finally...
echo
if [[ "${CLEANUP:-}" == 0 ]]; then
echo "leaving logs in $DIR"
else
rm -rf "$DIR"
fi