test-lib.sh 12.6 KB
Newer Older
1 2 3 4 5
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano
#

6 7 8
# Keep the original TERM for say_color
ORIGINAL_TERM=$TERM

9 10
# For repeatability, reset the environment to known value.
LANG=C
11
LC_ALL=C
12
PAGER=cat
13
TZ=UTC
14 15
TERM=dumb
export LANG LC_ALL PAGER TERM TZ
16 17
EDITOR=:
VISUAL=:
18
unset GIT_EDITOR
19 20 21 22 23
unset AUTHOR_DATE
unset AUTHOR_EMAIL
unset AUTHOR_NAME
unset COMMIT_AUTHOR_EMAIL
unset COMMIT_AUTHOR_NAME
24
unset EMAIL
25 26
unset GIT_ALTERNATE_OBJECT_DIRECTORIES
unset GIT_AUTHOR_DATE
27 28
GIT_AUTHOR_EMAIL=author@example.com
GIT_AUTHOR_NAME='A U Thor'
29
unset GIT_COMMITTER_DATE
30 31
GIT_COMMITTER_EMAIL=committer@example.com
GIT_COMMITTER_NAME='C O Mitter'
32 33
unset GIT_DIFF_OPTS
unset GIT_DIR
34
unset GIT_WORK_TREE
35 36 37
unset GIT_EXTERNAL_DIFF
unset GIT_INDEX_FILE
unset GIT_OBJECT_DIRECTORY
38
unset GIT_CEILING_DIRECTORIES
39 40
unset SHA1_FILE_DIRECTORIES
unset SHA1_FILE_DIRECTORY
41 42
GIT_MERGE_VERBOSITY=5
export GIT_MERGE_VERBOSITY
43 44
export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
45
export EDITOR VISUAL
46
GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u}
47

48 49 50 51
# Protect ourselves from common misconfiguration to export
# CDPATH into the environment
unset CDPATH

52
case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
53 54 55 56 57 58 59 60
	1|2|true)
		echo "* warning: Some tests will not work if GIT_TRACE" \
			"is set as to trace on STDERR ! *"
		echo "* warning: Please set GIT_TRACE to something" \
			"other than 1, 2 or true ! *"
		;;
esac

61 62 63 64 65 66
# Each test should start with something like this, after copyright notices:
#
# test_description='Description of this test...
# This test checks if command xyzzy does the right thing...
# '
# . ./test-lib.sh
67 68 69 70 71 72 73 74
[ "x$ORIGINAL_TERM" != "xdumb" ] && (
		TERM=$ORIGINAL_TERM &&
		export TERM &&
		[ -t 1 ] &&
		tput bold >/dev/null 2>&1 &&
		tput setaf 1 >/dev/null 2>&1 &&
		tput sgr0 >/dev/null 2>&1
	) &&
75
	color=t
76 77 78 79 80 81

while test "$#" -ne 0
do
	case "$1" in
	-d|--d|--de|--deb|--debu|--debug)
		debug=t; shift ;;
J
Junio C Hamano 已提交
82 83
	-i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
		immediate=t; shift ;;
84 85
	-l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
		export GIT_TEST_LONG=t; shift ;;
86
	-h|--h|--he|--hel|--help)
87
		help=t; shift ;;
88 89
	-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
		verbose=t; shift ;;
90 91
	-q|--q|--qu|--qui|--quie|--quiet)
		quiet=t; shift ;;
92
	--no-color)
93
		color=; shift ;;
94
	--no-python)
J
Junio C Hamano 已提交
95 96
		# noop now...
		shift ;;
97 98 99 100 101
	*)
		break ;;
	esac
done

102 103
if test -n "$color"; then
	say_color () {
104 105 106
		(
		TERM=$ORIGINAL_TERM
		export TERM
107 108 109 110 111
		case "$1" in
			error) tput bold; tput setaf 1;; # bold red
			skip)  tput bold; tput setaf 2;; # bold green
			pass)  tput setaf 2;;            # green
			info)  tput setaf 3;;            # brown
112
			*) test -n "$quiet" && return;;
113 114
		esac
		shift
S
Shawn O. Pearce 已提交
115
		printf "* %s" "$*"
116
		tput sgr0
117
		echo
118
		)
119 120 121
	}
else
	say_color() {
122
		test -z "$1" && test -n "$quiet" && return
123 124 125 126 127 128 129
		shift
		echo "* $*"
	}
fi

error () {
	say_color error "error: $*"
130
	trap - EXIT
131 132 133 134 135 136 137
	exit 1
}

say () {
	say_color info "$*"
}

138 139 140 141 142 143 144 145 146
test "${test_description}" != "" ||
error "Test script did not set test_description."

if test "$help" = "t"
then
	echo "$test_description"
	exit 0
fi

147
exec 5>&1
148 149 150 151 152 153 154 155 156
if test "$verbose" = "t"
then
	exec 4>&2 3>&1
else
	exec 4>/dev/null 3>/dev/null
fi

test_failure=0
test_count=0
J
Junio C Hamano 已提交
157 158
test_fixed=0
test_broken=0
159
test_success=0
160

161 162 163 164 165
die () {
	echo >&5 "FATAL: Unexpected exit with code $?"
	exit 1
}

166
trap 'die' EXIT
167

168 169 170 171 172 173 174 175
# The semantics of the editor variables are that of invoking
# sh -c "$EDITOR \"$@\"" files ...
#
# If our trash directory contains shell metacharacters, they will be
# interpreted if we just set $EDITOR directly, so do a little dance with
# environment variables to work around this.
#
# In particular, quoting isn't enough, as the path may contain the same quote
176
# that we're using.
177 178 179 180 181 182 183
test_set_editor () {
	FAKE_EDITOR="$1"
	export FAKE_EDITOR
	VISUAL='"$FAKE_EDITOR"'
	export VISUAL
}

184 185 186
test_tick () {
	if test -z "${test_tick+set}"
	then
J
Junio C Hamano 已提交
187
		test_tick=1112911993
188 189 190
	else
		test_tick=$(($test_tick + 60))
	fi
J
Junio C Hamano 已提交
191 192
	GIT_COMMITTER_DATE="$test_tick -0700"
	GIT_AUTHOR_DATE="$test_tick -0700"
193 194
	export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
}
195

196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
# Call test_commit with the arguments "<message> [<file> [<contents>]]"
#
# This will commit a file with the given contents and the given commit
# message.  It will also add a tag with <message> as name.
#
# Both <file> and <contents> default to <message>.

test_commit () {
	file=${2:-$(echo "$1" | tr 'A-Z' 'a-z')}
	echo "${3-$1}" > "$file" &&
	git add "$file" &&
	test_tick &&
	git commit -m "$1" &&
	git tag "$1"
}

# Call test_merge with the arguments "<message> <commit>", where <commit>
# can be a tag pointing to the commit-to-merge.

test_merge () {
	test_tick &&
	git merge -m "$1" "$2" &&
	git tag "$1"
}

J
Junio C Hamano 已提交
221 222 223 224
# You are not expected to call test_ok_ and test_failure_ directly, use
# the text_expect_* functions instead.

test_ok_ () {
225
	test_count=$(expr "$test_count" + 1)
226
	test_success=$(expr "$test_success" + 1)
227
	say_color "" "  ok $test_count: $@"
228 229
}

J
Junio C Hamano 已提交
230
test_failure_ () {
231 232
	test_count=$(expr "$test_count" + 1)
	test_failure=$(expr "$test_failure" + 1);
233
	say_color error "FAIL $test_count: $1"
234 235
	shift
	echo "$@" | sed -e 's/^/	/'
236
	test "$immediate" = "" || { trap - EXIT; exit 1; }
J
Junio C Hamano 已提交
237 238
}

J
Junio C Hamano 已提交
239 240 241 242 243 244 245 246 247 248 249
test_known_broken_ok_ () {
	test_count=$(expr "$test_count" + 1)
	test_fixed=$(($test_fixed+1))
	say_color "" "  FIXED $test_count: $@"
}

test_known_broken_failure_ () {
	test_count=$(expr "$test_count" + 1)
	test_broken=$(($test_broken+1))
	say_color skip "  still broken $test_count: $@"
}
J
Junio C Hamano 已提交
250 251

test_debug () {
252
	test "$debug" = "" || eval "$1"
253 254
}

255 256 257 258 259 260
test_run_ () {
	eval >&3 2>&4 "$1"
	eval_ret="$?"
	return 0
}

261 262 263 264 265 266 267 268 269 270 271 272 273
test_skip () {
	this_test=$(expr "./$0" : '.*/\(t[0-9]*\)-[^/]*$')
	this_test="$this_test.$(expr "$test_count" + 1)"
	to_skip=
	for skp in $GIT_SKIP_TESTS
	do
		case "$this_test" in
		$skp)
			to_skip=t
		esac
	done
	case "$to_skip" in
	t)
274
		say_color skip >&3 "skipping test: $@"
275
		test_count=$(expr "$test_count" + 1)
276
		say_color skip "skip $test_count: $1"
277 278 279 280 281 282 283 284
		: true
		;;
	*)
		false
		;;
	esac
}

285
test_expect_failure () {
286
	test "$#" = 2 ||
287
	error "bug in the test script: not 2 parameters to test-expect-failure"
288
	if ! test_skip "$@"
289
	then
J
Junio C Hamano 已提交
290
		say >&3 "checking known breakage: $2"
291
		test_run_ "$2"
J
Junio C Hamano 已提交
292
		if [ "$?" = 0 -a "$eval_ret" = 0 ]
293
		then
J
Junio C Hamano 已提交
294
			test_known_broken_ok_ "$1"
295
		else
J
Junio C Hamano 已提交
296
		    test_known_broken_failure_ "$1"
297
		fi
298
	fi
299
	echo >&3 ""
300 301 302
}

test_expect_success () {
303
	test "$#" = 2 ||
304
	error "bug in the test script: not 2 parameters to test-expect-success"
305
	if ! test_skip "$@"
306
	then
307 308 309 310 311 312 313 314
		say >&3 "expecting success: $2"
		test_run_ "$2"
		if [ "$?" = 0 -a "$eval_ret" = 0 ]
		then
			test_ok_ "$1"
		else
			test_failure_ "$@"
		fi
315
	fi
316
	echo >&3 ""
317 318
}

319 320 321
test_expect_code () {
	test "$#" = 3 ||
	error "bug in the test script: not 3 parameters to test-expect-code"
322
	if ! test_skip "$@"
323
	then
324 325 326 327 328 329 330 331
		say >&3 "expecting exit code $1: $3"
		test_run_ "$3"
		if [ "$?" = 0 -a "$eval_ret" = "$1" ]
		then
			test_ok_ "$2"
		else
			test_failure_ "$@"
		fi
332
	fi
333
	echo >&3 ""
334 335
}

336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
# test_external runs external test scripts that provide continuous
# test output about their progress, and succeeds/fails on
# zero/non-zero exit code.  It outputs the test output on stdout even
# in non-verbose mode, and announces the external script with "* run
# <n>: ..." before running it.  When providing relative paths, keep in
# mind that all scripts run in "trash directory".
# Usage: test_external description command arguments...
# Example: test_external 'Perl API' perl ../path/to/test.pl
test_external () {
	test "$#" -eq 3 ||
	error >&5 "bug in the test script: not 3 parameters to test_external"
	descr="$1"
	shift
	if ! test_skip "$descr" "$@"
	then
		# Announce the script to reduce confusion about the
		# test output that follows.
		say_color "" " run $(expr "$test_count" + 1): $descr ($*)"
		# Run command; redirect its stderr to &4 as in
		# test_run_, but keep its stdout on our stdout even in
		# non-verbose mode.
		"$@" 2>&4
		if [ "$?" = 0 ]
		then
			test_ok_ "$descr"
		else
			test_failure_ "$descr" "$@"
		fi
	fi
}

# Like test_external, but in addition tests that the command generated
# no output on stderr.
test_external_without_stderr () {
	# The temporary file has no (and must have no) security
	# implications.
	tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi
	stderr="$tmp/git-external-stderr.$$.tmp"
	test_external "$@" 4> "$stderr"
	[ -f "$stderr" ] || error "Internal error: $stderr disappeared."
	descr="no stderr: $1"
	shift
	say >&3 "expecting no stderr from previous command"
	if [ ! -s "$stderr" ]; then
		rm "$stderr"
		test_ok_ "$descr"
	else
		if [ "$verbose" = t ]; then
			output=`echo; echo Stderr is:; cat "$stderr"`
		else
			output=
		fi
		# rm first in case test_failure exits.
		rm "$stderr"
		test_failure_ "$descr" "$@" "$output"
	fi
}

J
Junio C Hamano 已提交
394 395 396 397 398 399 400 401 402 403 404 405 406 407
# This is not among top-level (test_expect_success | test_expect_failure)
# but is a prefix that can be used in the test script, like:
#
#	test_expect_success 'complain and die' '
#           do something &&
#           do something else &&
#	    test_must_fail git checkout ../outerspace
#	'
#
# Writing this as "! git checkout ../outerspace" is wrong, because
# the failure could be due to a segv.  We want a controlled failure.

test_must_fail () {
	"$@"
408
	test $? -gt 0 -a $? -le 129 -o $? -gt 192
J
Junio C Hamano 已提交
409 410
}

411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
# test_cmp is a helper function to compare actual and expected output.
# You can use it like:
#
#	test_expect_success 'foo works' '
#		echo expected >expected &&
#		foo >actual &&
#		test_cmp expected actual
#	'
#
# This could be written as either "cmp" or "diff -u", but:
# - cmp's output is not nearly as easy to read as diff -u
# - not all diff versions understand "-u"

test_cmp() {
	$GIT_TEST_CMP "$@"
}

428
# Most tests can use the created repository, but some may need to create more.
429 430 431 432 433 434
# Usage: test_create_repo <directory>
test_create_repo () {
	test "$#" = 1 ||
	error "bug in the test script: not 1 parameter to test-create-repo"
	owd=`pwd`
	repo="$1"
435
	mkdir -p "$repo"
436
	cd "$repo" || error "Cannot setup test environment"
437
	"$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >&3 2>&4 ||
438
	error "cannot run git init -- have you built things yet?"
439 440 441
	mv .git/hooks .git/hooks-disabled
	cd "$owd"
}
J
Junio C Hamano 已提交
442

443
test_done () {
444
	trap - EXIT
445 446 447 448 449 450 451 452 453 454
	test_results_dir="$TEST_DIRECTORY/test-results"
	mkdir -p "$test_results_dir"
	test_results_path="$test_results_dir/${0%-*}-$$"

	echo "total $test_count" >> $test_results_path
	echo "success $test_success" >> $test_results_path
	echo "fixed $test_fixed" >> $test_results_path
	echo "broken $test_broken" >> $test_results_path
	echo "failed $test_failure" >> $test_results_path
	echo "" >> $test_results_path
J
Junio C Hamano 已提交
455 456 457 458 459 460 461 462

	if test "$test_fixed" != 0
	then
		say_color pass "fixed $test_fixed known breakage(s)"
	fi
	if test "$test_broken" != 0
	then
		say_color error "still have $test_broken known breakage(s)"
463 464 465
		msg="remaining $(($test_count-$test_broken)) test(s)"
	else
		msg="$test_count test(s)"
J
Junio C Hamano 已提交
466
	fi
467
	case "$test_failure" in
468
	0)
469
		# We could:
470
		# cd .. && rm -fr 'trash directory'
471 472 473 474 475 476
		# but that means we forbid any tests that use their own
		# subdirectory from calling test_done without coming back
		# to where they started from.
		# The Makefile provided will clean this test area so
		# we will leave things as they are.

477
		say_color pass "passed all $msg"
J
Johannes Schindelin 已提交
478 479 480 481 482

		test -d "$remove_trash" &&
		cd "$(dirname "$remove_trash")" &&
		rm -rf "$(basename "$remove_trash")"

483 484 485
		exit 0 ;;

	*)
486
		say_color error "failed $test_failure among $msg"
487 488 489 490 491 492
		exit 1 ;;

	esac
}

# Test the binaries we have just built.  The tests are kept in
493
# t/ subdirectory and are run in 'trash directory' subdirectory.
494 495
TEST_DIRECTORY=$(pwd)
PATH=$TEST_DIRECTORY/..:$PATH
J
Johannes Schindelin 已提交
496
GIT_EXEC_PATH=$(pwd)/..
J
Johannes Schindelin 已提交
497
GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
J
Jeff King 已提交
498 499 500 501
unset GIT_CONFIG
GIT_CONFIG_NOSYSTEM=1
GIT_CONFIG_NOGLOBAL=1
export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
502

503 504
GITPERLLIB=$(pwd)/../perl/blib/lib:$(pwd)/../perl/blib/arch/auto/Git
export GITPERLLIB
505 506 507
test -d ../templates/blt || {
	error "You haven't built things yet, have you?"
}
508

E
Eric Wong 已提交
509 510 511 512 513 514
if ! test -x ../test-chmtime; then
	echo >&2 'You need to build test-chmtime:'
	echo >&2 'Run "make test-chmtime" in the source (toplevel) directory'
	exit 1
fi

515 516
. ../GIT-BUILD-OPTIONS

517
# Test repository
J
Johannes Schindelin 已提交
518
test="trash directory.$(basename "$0" .sh)"
519
test ! -z "$debug" || remove_trash="$TEST_DIRECTORY/$test"
520
rm -fr "$test" || {
521
	trap - EXIT
522 523 524 525
	echo >&5 "FATAL: Cannot prepare test area"
	exit 1
}

526
test_create_repo "$test"
527 528 529
# Use -P to resolve symlinks in our working directory so that the cwd
# in subprocesses like git equals our $PWD (for pathname comparisons).
cd -P "$test" || exit 1
530 531 532 533 534 535 536 537 538 539 540 541 542 543

this_test=$(expr "./$0" : '.*/\(t[0-9]*\)-[^/]*$')
for skp in $GIT_SKIP_TESTS
do
	to_skip=
	for skp in $GIT_SKIP_TESTS
	do
		case "$this_test" in
		$skp)
			to_skip=t
		esac
	done
	case "$to_skip" in
	t)
544 545
		say_color skip >&3 "skipping test $this_test altogether"
		say_color skip "skip all tests in $this_test"
546 547 548
		test_done
	esac
done