1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano 4# 5 6# if --tee was passed, write the output not only to the terminal, but 7# additionally to the file test-results/$BASENAME.out, too. 8case"$GIT_TEST_TEE_STARTED, $* "in 9done,*) 10# do not redirect again 11;; 12*' --tee '*|*' --va'*) 13mkdir-p test-results 14 BASE=test-results/$(basename"$0" .sh) 15(GIT_TEST_TEE_STARTED=done${SHELL-sh}"$0""$@"2>&1; 16echo $? >$BASE.exit) |tee$BASE.out 17test"$(cat$BASE.exit)"=0 18exit 19;; 20esac 21 22# Keep the original TERM for say_color 23ORIGINAL_TERM=$TERM 24 25# For repeatability, reset the environment to known value. 26LANG=C 27LC_ALL=C 28PAGER=cat 29TZ=UTC 30TERM=dumb 31export LANG LC_ALL PAGER TERM TZ 32EDITOR=: 33unset VISUAL 34unset GIT_EDITOR 35unset AUTHOR_DATE 36unset AUTHOR_EMAIL 37unset AUTHOR_NAME 38unset COMMIT_AUTHOR_EMAIL 39unset COMMIT_AUTHOR_NAME 40unset EMAIL 41unset GIT_ALTERNATE_OBJECT_DIRECTORIES 42unset GIT_AUTHOR_DATE 43GIT_AUTHOR_EMAIL=author@example.com 44GIT_AUTHOR_NAME='A U Thor' 45unset GIT_COMMITTER_DATE 46GIT_COMMITTER_EMAIL=committer@example.com 47GIT_COMMITTER_NAME='C O Mitter' 48unset GIT_DIFF_OPTS 49unset GIT_DIR 50unset GIT_WORK_TREE 51unset GIT_EXTERNAL_DIFF 52unset GIT_INDEX_FILE 53unset GIT_OBJECT_DIRECTORY 54unset GIT_CEILING_DIRECTORIES 55unset SHA1_FILE_DIRECTORIES 56unset SHA1_FILE_DIRECTORY 57GIT_MERGE_VERBOSITY=5 58export GIT_MERGE_VERBOSITY 59export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME 60export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME 61export EDITOR 62GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u} 63 64# Protect ourselves from common misconfiguration to export 65# CDPATH into the environment 66unset CDPATH 67 68case $(echo$GIT_TRACE|tr"[A-Z]""[a-z]")in 691|2|true) 70echo"* warning: Some tests will not work if GIT_TRACE" \ 71"is set as to trace on STDERR ! *" 72echo"* warning: Please set GIT_TRACE to something" \ 73"other than 1, 2 or true ! *" 74;; 75esac 76 77# Convenience 78# 79# A regexp to match 5 and 40 hexdigits 80_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' 81_x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05" 82 83# Each test should start with something like this, after copyright notices: 84# 85# test_description='Description of this test... 86# This test checks if command xyzzy does the right thing... 87# ' 88# . ./test-lib.sh 89["x$ORIGINAL_TERM"!="xdumb"] && ( 90 TERM=$ORIGINAL_TERM&& 91export TERM && 92[-t1] && 93tput bold >/dev/null 2>&1&& 94tput setaf 1>/dev/null 2>&1&& 95tput sgr0 >/dev/null 2>&1 96) && 97 color=t 98 99whiletest"$#"-ne0 100do 101case"$1"in 102-d|--d|--de|--deb|--debu|--debug) 103 debug=t;shift;; 104-i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate) 105 immediate=t;shift;; 106-l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests) 107 GIT_TEST_LONG=t;export GIT_TEST_LONG;shift;; 108-h|--h|--he|--hel|--help) 109help=t;shift;; 110-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) 111 verbose=t;shift;; 112-q|--q|--qu|--qui|--quie|--quiet) 113 quiet=t;shift;; 114--with-dashes) 115 with_dashes=t;shift;; 116--no-color) 117 color=;shift;; 118--no-python) 119# noop now... 120shift;; 121--va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind) 122 valgrind=t; verbose=t;shift;; 123--tee) 124shift;;# was handled already 125--root=*) 126 root=$(expr"z$1":'z[^=]*=\(.*\)') 127shift;; 128*) 129echo"error: unknown test option '$1'">&2;exit1;; 130esac 131done 132 133iftest -n"$color";then 134 say_color () { 135( 136 TERM=$ORIGINAL_TERM 137export TERM 138case"$1"in 139 error)tput bold;tput setaf 1;;# bold red 140 skip)tput bold;tput setaf 2;;# bold green 141 pass)tput setaf 2;;# green 142 info)tput setaf 3;;# brown 143*)test -n"$quiet"&&return;; 144esac 145shift 146printf"* %s""$*" 147tput sgr0 148echo 149) 150} 151else 152 say_color() { 153test -z"$1"&&test -n"$quiet"&&return 154shift 155echo"* $*" 156} 157fi 158 159error () { 160 say_color error "error: $*" 161 GIT_EXIT_OK=t 162exit1 163} 164 165say () { 166 say_color info "$*" 167} 168 169test"${test_description}"!=""|| 170error "Test script did not set test_description." 171 172iftest"$help"="t" 173then 174echo"$test_description" 175exit0 176fi 177 178exec5>&1 179iftest"$verbose"="t" 180then 181exec4>&2 3>&1 182else 183exec4>/dev/null 3>/dev/null 184fi 185 186test_failure=0 187test_count=0 188test_fixed=0 189test_broken=0 190test_success=0 191 192die () { 193 code=$? 194iftest -n"$GIT_EXIT_OK" 195then 196exit$code 197else 198echo>&5"FATAL: Unexpected exit with code$code" 199exit1 200fi 201} 202 203GIT_EXIT_OK= 204trap'die' EXIT 205 206# The semantics of the editor variables are that of invoking 207# sh -c "$EDITOR \"$@\"" files ... 208# 209# If our trash directory contains shell metacharacters, they will be 210# interpreted if we just set $EDITOR directly, so do a little dance with 211# environment variables to work around this. 212# 213# In particular, quoting isn't enough, as the path may contain the same quote 214# that we're using. 215test_set_editor () { 216 FAKE_EDITOR="$1" 217export FAKE_EDITOR 218 EDITOR='"$FAKE_EDITOR"' 219export EDITOR 220} 221 222test_decode_color () { 223sed-e's/.\[1m/<WHITE>/g' \ 224-e's/.\[31m/<RED>/g' \ 225-e's/.\[32m/<GREEN>/g' \ 226-e's/.\[33m/<YELLOW>/g' \ 227-e's/.\[34m/<BLUE>/g' \ 228-e's/.\[35m/<MAGENTA>/g' \ 229-e's/.\[36m/<CYAN>/g' \ 230-e's/.\[m/<RESET>/g' 231} 232 233q_to_nul () { 234 perl -pe'y/Q/\000/' 235} 236 237q_to_cr () { 238tr Q '\015' 239} 240 241append_cr () { 242sed-e's/$/Q/'|tr Q '\015' 243} 244 245remove_cr () { 246tr'\015' Q |sed-e's/Q$//' 247} 248 249test_tick () { 250iftest -z"${test_tick+set}" 251then 252 test_tick=1112911993 253else 254 test_tick=$(($test_tick+60)) 255fi 256 GIT_COMMITTER_DATE="$test_tick-0700" 257 GIT_AUTHOR_DATE="$test_tick-0700" 258export GIT_COMMITTER_DATE GIT_AUTHOR_DATE 259} 260 261# Call test_commit with the arguments "<message> [<file> [<contents>]]" 262# 263# This will commit a file with the given contents and the given commit 264# message. It will also add a tag with <message> as name. 265# 266# Both <file> and <contents> default to <message>. 267 268test_commit () { 269file=${2:-"$1.t"} 270echo"${3-$1}">"$file"&& 271 git add "$file"&& 272 test_tick && 273 git commit -m"$1"&& 274 git tag "$1" 275} 276 277# Call test_merge with the arguments "<message> <commit>", where <commit> 278# can be a tag pointing to the commit-to-merge. 279 280test_merge () { 281 test_tick && 282 git merge -m"$1""$2"&& 283 git tag "$1" 284} 285 286# This function helps systems where core.filemode=false is set. 287# Use it instead of plain 'chmod +x' to set or unset the executable bit 288# of a file in the working directory and add it to the index. 289 290test_chmod () { 291chmod"$@"&& 292 git update-index --add"--chmod=$@" 293} 294 295# Use test_set_prereq to tell that a particular prerequisite is available. 296# The prerequisite can later be checked for in two ways: 297# 298# - Explicitly using test_have_prereq. 299# 300# - Implicitly by specifying the prerequisite tag in the calls to 301# test_expect_{success,failure,code}. 302# 303# The single parameter is the prerequisite tag (a simple word, in all 304# capital letters by convention). 305 306test_set_prereq () { 307 satisfied="$satisfied$1" 308} 309satisfied=" " 310 311test_have_prereq () { 312case$satisfiedin 313*"$1"*) 314:yes, have it ;; 315*) 316! : nope ;; 317esac 318} 319 320# You are not expected to call test_ok_ and test_failure_ directly, use 321# the text_expect_* functions instead. 322 323test_ok_ () { 324 test_success=$(($test_success+1)) 325 say_color """ ok$test_count: $@" 326} 327 328test_failure_ () { 329 test_failure=$(($test_failure+1)) 330 say_color error "FAIL$test_count:$1" 331shift 332echo"$@"|sed-e's/^/ /' 333test"$immediate"=""|| { GIT_EXIT_OK=t;exit1; } 334} 335 336test_known_broken_ok_ () { 337 test_fixed=$(($test_fixed+1)) 338 say_color """ FIXED$test_count: $@" 339} 340 341test_known_broken_failure_ () { 342 test_broken=$(($test_broken+1)) 343 say_color skip " still broken$test_count: $@" 344} 345 346test_debug () { 347test"$debug"=""||eval"$1" 348} 349 350test_run_ () { 351eval>&3 2>&4"$1" 352 eval_ret="$?" 353return0 354} 355 356test_skip () { 357 test_count=$(($test_count+1)) 358 to_skip= 359for skp in$GIT_SKIP_TESTS 360do 361case$this_test.$test_countin 362$skp) 363 to_skip=t 364esac 365done 366iftest -z"$to_skip"&&test -n"$prereq"&& 367! test_have_prereq "$prereq" 368then 369 to_skip=t 370fi 371case"$to_skip"in 372 t) 373 say_color skip >&3"skipping test: $@" 374 say_color skip "skip$test_count:$1" 375: true 376;; 377*) 378 false 379;; 380esac 381} 382 383test_expect_failure () { 384test"$#"=3&& { prereq=$1;shift; } || prereq= 385test"$#"=2|| 386 error "bug in the test script: not 2 or 3 parameters to test-expect-failure" 387if! test_skip "$@" 388then 389 say >&3"checking known breakage:$2" 390 test_run_ "$2" 391if["$?"=0-a"$eval_ret"=0] 392then 393 test_known_broken_ok_ "$1" 394else 395 test_known_broken_failure_ "$1" 396fi 397fi 398echo>&3"" 399} 400 401test_expect_success () { 402test"$#"=3&& { prereq=$1;shift; } || prereq= 403test"$#"=2|| 404 error "bug in the test script: not 2 or 3 parameters to test-expect-success" 405if! test_skip "$@" 406then 407 say >&3"expecting success:$2" 408 test_run_ "$2" 409if["$?"=0-a"$eval_ret"=0] 410then 411 test_ok_ "$1" 412else 413 test_failure_ "$@" 414fi 415fi 416echo>&3"" 417} 418 419test_expect_code () { 420test"$#"=4&& { prereq=$1;shift; } || prereq= 421test"$#"=3|| 422 error "bug in the test script: not 3 or 4 parameters to test-expect-code" 423if! test_skip "$@" 424then 425 say >&3"expecting exit code$1:$3" 426 test_run_ "$3" 427if["$?"=0-a"$eval_ret"="$1"] 428then 429 test_ok_ "$2" 430else 431 test_failure_ "$@" 432fi 433fi 434echo>&3"" 435} 436 437# test_external runs external test scripts that provide continuous 438# test output about their progress, and succeeds/fails on 439# zero/non-zero exit code. It outputs the test output on stdout even 440# in non-verbose mode, and announces the external script with "* run 441# <n>: ..." before running it. When providing relative paths, keep in 442# mind that all scripts run in "trash directory". 443# Usage: test_external description command arguments... 444# Example: test_external 'Perl API' perl ../path/to/test.pl 445test_external () { 446test"$#"=4&& { prereq=$1;shift; } || prereq= 447test"$#"=3|| 448 error >&5"bug in the test script: not 3 or 4 parameters to test_external" 449 descr="$1" 450shift 451if! test_skip "$descr""$@" 452then 453# Announce the script to reduce confusion about the 454# test output that follows. 455 say_color """ run$test_count:$descr($*)" 456# Run command; redirect its stderr to &4 as in 457# test_run_, but keep its stdout on our stdout even in 458# non-verbose mode. 459"$@"2>&4 460if["$?"=0] 461then 462 test_ok_ "$descr" 463else 464 test_failure_ "$descr""$@" 465fi 466fi 467} 468 469# Like test_external, but in addition tests that the command generated 470# no output on stderr. 471test_external_without_stderr () { 472# The temporary file has no (and must have no) security 473# implications. 474 tmp="$TMPDIR";if[-z"$tmp"];then tmp=/tmp;fi 475 stderr="$tmp/git-external-stderr.$$.tmp" 476 test_external "$@"4>"$stderr" 477[-f"$stderr"] || error "Internal error:$stderrdisappeared." 478 descr="no stderr:$1" 479shift 480 say >&3"expecting no stderr from previous command" 481if[ !-s"$stderr"];then 482rm"$stderr" 483 test_ok_ "$descr" 484else 485if["$verbose"= t ];then 486 output=`echo; echo Stderr is:; cat "$stderr"` 487else 488 output= 489fi 490# rm first in case test_failure exits. 491rm"$stderr" 492 test_failure_ "$descr""$@""$output" 493fi 494} 495 496# This is not among top-level (test_expect_success | test_expect_failure) 497# but is a prefix that can be used in the test script, like: 498# 499# test_expect_success 'complain and die' ' 500# do something && 501# do something else && 502# test_must_fail git checkout ../outerspace 503# ' 504# 505# Writing this as "! git checkout ../outerspace" is wrong, because 506# the failure could be due to a segv. We want a controlled failure. 507 508test_must_fail () { 509"$@" 510test $? -gt0-a $? -le129-o $? -gt192 511} 512 513# test_cmp is a helper function to compare actual and expected output. 514# You can use it like: 515# 516# test_expect_success 'foo works' ' 517# echo expected >expected && 518# foo >actual && 519# test_cmp expected actual 520# ' 521# 522# This could be written as either "cmp" or "diff -u", but: 523# - cmp's output is not nearly as easy to read as diff -u 524# - not all diff versions understand "-u" 525 526test_cmp() { 527$GIT_TEST_CMP"$@" 528} 529 530# Most tests can use the created repository, but some may need to create more. 531# Usage: test_create_repo <directory> 532test_create_repo () { 533test"$#"=1|| 534 error "bug in the test script: not 1 parameter to test-create-repo" 535 owd=`pwd` 536 repo="$1" 537mkdir-p"$repo" 538cd"$repo"|| error "Cannot setup test environment" 539"$GIT_EXEC_PATH/git-init""--template=$TEST_DIRECTORY/../templates/blt/">&3 2>&4|| 540 error "cannot run git init -- have you built things yet?" 541mv .git/hooks .git/hooks-disabled 542cd"$owd" 543} 544 545test_done () { 546 GIT_EXIT_OK=t 547 test_results_dir="$TEST_DIRECTORY/test-results" 548mkdir-p"$test_results_dir" 549 test_results_path="$test_results_dir/${0%.sh}-$$" 550 551echo"total$test_count">>$test_results_path 552echo"success$test_success">>$test_results_path 553echo"fixed$test_fixed">>$test_results_path 554echo"broken$test_broken">>$test_results_path 555echo"failed$test_failure">>$test_results_path 556echo"">>$test_results_path 557 558iftest"$test_fixed"!=0 559then 560 say_color pass "fixed$test_fixedknown breakage(s)" 561fi 562iftest"$test_broken"!=0 563then 564 say_color error "still have$test_brokenknown breakage(s)" 565 msg="remaining $(($test_count-$test_broken)) test(s)" 566else 567 msg="$test_counttest(s)" 568fi 569case"$test_failure"in 5700) 571 say_color pass "passed all$msg" 572 573test -d"$remove_trash"&& 574cd"$(dirname "$remove_trash")"&& 575rm-rf"$(basename "$remove_trash")" 576 577exit0;; 578 579*) 580 say_color error "failed$test_failureamong$msg" 581exit1;; 582 583esac 584} 585 586# Test the binaries we have just built. The tests are kept in 587# t/ subdirectory and are run in 'trash directory' subdirectory. 588TEST_DIRECTORY=$(pwd) 589iftest -n"$valgrind" 590then 591 make_symlink () { 592test -h"$2"&& 593test"$1"="$(readlink "$2")"|| { 594# be super paranoid 595ifmkdir"$2".lock 596then 597rm-f"$2"&& 598ln-s"$1""$2"&& 599rm-r"$2".lock 600else 601whiletest -d"$2".lock 602do 603 say "Waiting for lock on$2." 604sleep1 605done 606fi 607} 608} 609 610 make_valgrind_symlink () { 611# handle only executables 612test -x"$1"||return 613 614 base=$(basename"$1") 615 symlink_target=$TEST_DIRECTORY/../$base 616# do not override scripts 617iftest -x"$symlink_target"&& 618test!-d"$symlink_target"&& 619test"#!"!="$(head -c 2 < "$symlink_target")" 620then 621 symlink_target=../valgrind.sh 622fi 623case"$base"in 624*.sh|*.perl) 625 symlink_target=../unprocessed-script 626esac 627# create the link, or replace it if it is out of date 628 make_symlink "$symlink_target""$GIT_VALGRIND/bin/$base"||exit 629} 630 631# override all git executables in TEST_DIRECTORY/.. 632 GIT_VALGRIND=$TEST_DIRECTORY/valgrind 633mkdir-p"$GIT_VALGRIND"/bin 634forfilein$TEST_DIRECTORY/../git*$TEST_DIRECTORY/../test-* 635do 636 make_valgrind_symlink $file 637done 638 OLDIFS=$IFS 639 IFS=: 640for path in$PATH 641do 642ls"$path"/git-*2> /dev/null | 643whilereadfile 644do 645 make_valgrind_symlink "$file" 646done 647done 648 IFS=$OLDIFS 649 PATH=$GIT_VALGRIND/bin:$PATH 650 GIT_EXEC_PATH=$GIT_VALGRIND/bin 651export GIT_VALGRIND 652eliftest -n"$GIT_TEST_INSTALLED";then 653 GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path) || 654 error "Cannot run git from$GIT_TEST_INSTALLED." 655 PATH=$GIT_TEST_INSTALLED:$TEST_DIRECTORY/..:$PATH 656 GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH} 657else# normal case, use ../bin-wrappers only unless $with_dashes: 658 git_bin_dir="$TEST_DIRECTORY/../bin-wrappers" 659if!test -x"$git_bin_dir/git";then 660iftest -z"$with_dashes";then 661 say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH" 662fi 663 with_dashes=t 664fi 665 PATH="$git_bin_dir:$PATH" 666 GIT_EXEC_PATH=$TEST_DIRECTORY/.. 667iftest -n"$with_dashes";then 668 PATH="$TEST_DIRECTORY/..:$PATH" 669fi 670fi 671GIT_TEMPLATE_DIR=$(pwd)/../templates/blt 672unset GIT_CONFIG 673GIT_CONFIG_NOSYSTEM=1 674GIT_CONFIG_NOGLOBAL=1 675export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL 676 677. ../GIT-BUILD-OPTIONS 678 679GITPERLLIB=$(pwd)/../perl/blib/lib:$(pwd)/../perl/blib/arch/auto/Git 680export GITPERLLIB 681test -d ../templates/blt || { 682 error "You haven't built things yet, have you?" 683} 684 685iftest -z"$GIT_TEST_INSTALLED"&&test -z"$NO_PYTHON" 686then 687 GITPYTHONLIB="$(pwd)/../git_remote_helpers/build/lib" 688export GITPYTHONLIB 689test -d ../git_remote_helpers/build || { 690 error "You haven't built git_remote_helpers yet, have you?" 691} 692fi 693 694if!test -x ../test-chmtime;then 695echo>&2'You need to build test-chmtime:' 696echo>&2'Run "make test-chmtime" in the source (toplevel) directory' 697exit1 698fi 699 700# Test repository 701test="trash directory.$(basename "$0" .sh)" 702test -n"$root"&&test="$root/$test" 703case"$test"in 704/*) TRASH_DIRECTORY="$test";; 705*) TRASH_DIRECTORY="$TEST_DIRECTORY/$test";; 706esac 707test!-z"$debug"|| remove_trash=$TRASH_DIRECTORY 708rm-fr"$test"|| { 709 GIT_EXIT_OK=t 710echo>&5"FATAL: Cannot prepare test area" 711exit1 712} 713 714test_create_repo "$test" 715# Use -P to resolve symlinks in our working directory so that the cwd 716# in subprocesses like git equals our $PWD (for pathname comparisons). 717cd -P"$test"||exit1 718 719this_test=${0##*/} 720this_test=${this_test%%-*} 721for skp in$GIT_SKIP_TESTS 722do 723 to_skip= 724for skp in$GIT_SKIP_TESTS 725do 726case"$this_test"in 727$skp) 728 to_skip=t 729esac 730done 731case"$to_skip"in 732 t) 733 say_color skip >&3"skipping test$this_testaltogether" 734 say_color skip "skip all tests in$this_test" 735 test_done 736esac 737done 738 739# Provide an implementation of the 'yes' utility 740yes() { 741iftest$#=0 742then 743 y=y 744else 745 y="$*" 746fi 747 748whileecho"$y" 749do 750: 751done 752} 753 754# Fix some commands on Windows 755case $(uname -s)in 756*MINGW*) 757# Windows has its own (incompatible) sort and find 758sort() { 759/usr/bin/sort"$@" 760} 761find() { 762/usr/bin/find"$@" 763} 764sum() { 765md5sum"$@" 766} 767# git sees Windows-style pwd 768pwd() { 769builtin pwd -W 770} 771# no POSIX permissions 772# backslashes in pathspec are converted to '/' 773# exec does not inherit the PID 774;; 775*) 776 test_set_prereq POSIXPERM 777 test_set_prereq BSLASHPSPEC 778 test_set_prereq EXECKEEPSPID 779;; 780esac 781 782test -z"$NO_PERL"&& test_set_prereq PERL 783test -z"$NO_PYTHON"&& test_set_prereq PYTHON 784 785# test whether the filesystem supports symbolic links 786ln-s x y 2>/dev/null &&test -h y 2>/dev/null && test_set_prereq SYMLINKS 787rm-f y