t / lib-git-p4.shon commit t1430: clean up broken refs/tags/shadow (45669a7)
   1#
   2# Library code for git p4 tests
   3#
   4
   5# p4 tests never use the top-level repo; always build/clone into
   6# a subdirectory called "$git"
   7TEST_NO_CREATE_REPO=NoThanks
   8
   9# Some operations require multiple attempts to be successful. Define
  10# here the maximal retry timeout in seconds.
  11RETRY_TIMEOUT=60
  12
  13# Sometimes p4d seems to hang. Terminate the p4d process automatically after
  14# the defined timeout in seconds.
  15P4D_TIMEOUT=300
  16
  17. ./test-lib.sh
  18
  19if ! test_have_prereq PYTHON
  20then
  21        skip_all='skipping git p4 tests; python not available'
  22        test_done
  23fi
  24( p4 -h && p4d -h ) >/dev/null 2>&1 || {
  25        skip_all='skipping git p4 tests; no p4 or p4d'
  26        test_done
  27}
  28
  29# On cygwin, the NT version of Perforce can be used.  When giving
  30# it paths, either on the command-line or in client specifications,
  31# be sure to use the native windows form.
  32#
  33# Older versions of perforce were available compiled natively for
  34# cygwin.  Those do not accept native windows paths, so make sure
  35# not to convert for them.
  36native_path() {
  37        path="$1" &&
  38        if test_have_prereq CYGWIN && ! p4 -V | grep -q CYGWIN
  39        then
  40                path=$(cygpath --windows "$path")
  41        else
  42                path=$(test-path-utils real_path "$path")
  43        fi &&
  44        echo "$path"
  45}
  46
  47# On Solaris the 'date +%s' function is not supported and therefore we
  48# need this replacement.
  49# Attention: This function is not safe again against time offset updates
  50# at runtime (e.g. via NTP). The 'clock_gettime(CLOCK_MONOTONIC)'
  51# function could fix that but it is not in Python until 3.3.
  52time_in_seconds() {
  53        python -c 'import time; print int(time.time())'
  54}
  55
  56# Try to pick a unique port: guess a large number, then hope
  57# no more than one of each test is running.
  58#
  59# This does not handle the case where somebody else is running the
  60# same tests and has chosen the same ports.
  61testid=${this_test#t}
  62git_p4_test_start=9800
  63P4DPORT=$((10669 + ($testid - $git_p4_test_start)))
  64
  65P4PORT=localhost:$P4DPORT
  66P4CLIENT=client
  67P4USER=author
  68P4EDITOR=true
  69unset P4CHARSET
  70export P4PORT P4CLIENT P4USER P4EDITOR P4CHARSET
  71
  72db="$TRASH_DIRECTORY/db"
  73cli="$TRASH_DIRECTORY/cli"
  74git="$TRASH_DIRECTORY/git"
  75pidfile="$TRASH_DIRECTORY/p4d.pid"
  76
  77# Sometimes "prove" seems to hang on exit because p4d is still running
  78cleanup() {
  79        if test -f "$pidfile"
  80        then
  81                kill -9 $(cat "$pidfile") 2>/dev/null && exit 255
  82        fi
  83}
  84trap cleanup EXIT
  85
  86# git p4 submit generates a temp file, which will
  87# not get cleaned up if the submission fails.  Don't
  88# clutter up /tmp on the test machine.
  89TMPDIR="$TRASH_DIRECTORY"
  90export TMPDIR
  91
  92start_p4d() {
  93        mkdir -p "$db" "$cli" "$git" &&
  94        rm -f "$pidfile" &&
  95        (
  96                cd "$db" &&
  97                {
  98                        p4d -q -p $P4DPORT "$@" &
  99                        echo $! >"$pidfile"
 100                }
 101        ) &&
 102
 103        # This gives p4d a long time to start up, as it can be
 104        # quite slow depending on the machine.  Set this environment
 105        # variable to something smaller to fail faster in, say,
 106        # an automated test setup.  If the p4d process dies, that
 107        # will be caught with the "kill -0" check below.
 108        i=${P4D_START_PATIENCE:-300}
 109        pid=$(cat "$pidfile")
 110
 111        timeout=$(($(time_in_seconds) + $P4D_TIMEOUT))
 112        while true
 113        do
 114                if test $(time_in_seconds) -gt $timeout
 115                then
 116                        kill -9 $pid
 117                        exit 1
 118                fi
 119                sleep 1
 120        done &
 121        watchdog_pid=$!
 122
 123        ready=
 124        while test $i -gt 0
 125        do
 126                # succeed when p4 client commands start to work
 127                if p4 info >/dev/null 2>&1
 128                then
 129                        ready=true
 130                        break
 131                fi
 132                # fail if p4d died
 133                kill -0 $pid 2>/dev/null || break
 134                echo waiting for p4d to start
 135                sleep 1
 136                i=$(( $i - 1 ))
 137        done
 138
 139        if test -z "$ready"
 140        then
 141                # p4d failed to start
 142                return 1
 143        fi
 144
 145        # build a p4 user so author@example.com has an entry
 146        p4_add_user author
 147
 148        # build a client
 149        client_view "//depot/... //client/..." &&
 150
 151        return 0
 152}
 153
 154p4_add_user() {
 155        name=$1 &&
 156        p4 user -f -i <<-EOF
 157        User: $name
 158        Email: $name@example.com
 159        FullName: Dr. $name
 160        EOF
 161}
 162
 163retry_until_success() {
 164        timeout=$(($(time_in_seconds) + $RETRY_TIMEOUT))
 165        until "$@" 2>/dev/null || test $(time_in_seconds) -gt $timeout
 166        do
 167                sleep 1
 168        done
 169}
 170
 171retry_until_fail() {
 172        timeout=$(($(time_in_seconds) + $RETRY_TIMEOUT))
 173        until ! "$@" 2>/dev/null || test $(time_in_seconds) -gt $timeout
 174        do
 175                sleep 1
 176        done
 177}
 178
 179kill_p4d() {
 180        pid=$(cat "$pidfile")
 181        retry_until_fail kill $pid
 182        retry_until_fail kill -9 $pid
 183        # complain if it would not die
 184        test_must_fail kill $pid >/dev/null 2>&1 &&
 185        rm -rf "$db" "$cli" "$pidfile" &&
 186        retry_until_fail kill -9 $watchdog_pid
 187}
 188
 189cleanup_git() {
 190        retry_until_success rm -r "$git"
 191        test_must_fail test -d "$git" &&
 192        retry_until_success mkdir "$git"
 193}
 194
 195marshal_dump() {
 196        what=$1 &&
 197        line=${2:-1} &&
 198        cat >"$TRASH_DIRECTORY/marshal-dump.py" <<-EOF &&
 199        import marshal
 200        import sys
 201        for i in range($line):
 202            d = marshal.load(sys.stdin)
 203        print d['$what']
 204        EOF
 205        "$PYTHON_PATH" "$TRASH_DIRECTORY/marshal-dump.py"
 206}
 207
 208#
 209# Construct a client with this list of View lines
 210#
 211client_view() {
 212        (
 213                cat <<-EOF &&
 214                Client: $P4CLIENT
 215                Description: $P4CLIENT
 216                Root: $cli
 217                AltRoots: $(native_path "$cli")
 218                LineEnd: unix
 219                View:
 220                EOF
 221                printf "\t%s\n" "$@"
 222        ) | p4 client -i
 223}
 224
 225is_cli_file_writeable() {
 226        # cygwin version of p4 does not set read-only attr,
 227        # will be marked 444 but -w is true
 228        file="$1" &&
 229        if test_have_prereq CYGWIN && p4 -V | grep -q CYGWIN
 230        then
 231                stat=$(stat --format=%a "$file") &&
 232                test $stat = 644
 233        else
 234                test -w "$file"
 235        fi
 236}