b5cb5075c20a82bd10a88fc10083145ee99e2f1d
   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-tool 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        (cd / && "$PYTHON_PATH" -c 'import time; print(int(time.time()))')
  54}
  55
  56test_set_port P4DPORT
  57
  58P4PORT=localhost:$P4DPORT
  59P4CLIENT=client
  60P4USER=author
  61P4EDITOR=true
  62unset P4CHARSET
  63export P4PORT P4CLIENT P4USER P4EDITOR P4CHARSET
  64
  65db="$TRASH_DIRECTORY/db"
  66cli="$TRASH_DIRECTORY/cli"
  67git="$TRASH_DIRECTORY/git"
  68pidfile="$TRASH_DIRECTORY/p4d.pid"
  69
  70stop_p4d_and_watchdog () {
  71        kill -9 $p4d_pid $watchdog_pid
  72}
  73
  74# git p4 submit generates a temp file, which will
  75# not get cleaned up if the submission fails.  Don't
  76# clutter up /tmp on the test machine.
  77TMPDIR="$TRASH_DIRECTORY"
  78export TMPDIR
  79
  80registered_stop_p4d_atexit_handler=
  81start_p4d () {
  82        # One of the test scripts stops and then re-starts p4d.
  83        # Don't register and then run the same atexit handlers several times.
  84        if test -z "$registered_stop_p4d_atexit_handler"
  85        then
  86                test_atexit 'stop_p4d_and_watchdog'
  87                registered_stop_p4d_atexit_handler=AlreadyDone
  88        fi
  89
  90        mkdir -p "$db" "$cli" "$git" &&
  91        rm -f "$pidfile" &&
  92        (
  93                cd "$db" &&
  94                {
  95                        p4d -q -p $P4DPORT "$@" &
  96                        echo $! >"$pidfile"
  97                }
  98        ) &&
  99        p4d_pid=$(cat "$pidfile")
 100
 101        # This gives p4d a long time to start up, as it can be
 102        # quite slow depending on the machine.  Set this environment
 103        # variable to something smaller to fail faster in, say,
 104        # an automated test setup.  If the p4d process dies, that
 105        # will be caught with the "kill -0" check below.
 106        i=${P4D_START_PATIENCE:-300}
 107
 108        timeout=$(($(time_in_seconds) + $P4D_TIMEOUT))
 109        while true
 110        do
 111                if test $(time_in_seconds) -gt $timeout
 112                then
 113                        kill -9 $p4d_pid
 114                        exit 1
 115                fi
 116                sleep 1
 117        done &
 118        watchdog_pid=$!
 119
 120        ready=
 121        while test $i -gt 0
 122        do
 123                # succeed when p4 client commands start to work
 124                if p4 info >/dev/null 2>&1
 125                then
 126                        ready=true
 127                        break
 128                fi
 129                # fail if p4d died
 130                kill -0 $p4d_pid 2>/dev/null || break
 131                echo waiting for p4d to start
 132                sleep 1
 133                i=$(( $i - 1 ))
 134        done
 135
 136        if test -z "$ready"
 137        then
 138                # p4d failed to start
 139                return 1
 140        fi
 141
 142        # build a p4 user so author@example.com has an entry
 143        p4_add_user author
 144
 145        # build a client
 146        client_view "//depot/... //client/..." &&
 147
 148        return 0
 149}
 150
 151p4_add_user () {
 152        name=$1 &&
 153        p4 user -f -i <<-EOF
 154        User: $name
 155        Email: $name@example.com
 156        FullName: Dr. $name
 157        EOF
 158}
 159
 160p4_add_job () {
 161        p4 job -f -i <<-EOF
 162        Job: $1
 163        Status: open
 164        User: dummy
 165        Description:
 166        EOF
 167}
 168
 169retry_until_success () {
 170        timeout=$(($(time_in_seconds) + $RETRY_TIMEOUT))
 171        until "$@" 2>/dev/null || test $(time_in_seconds) -gt $timeout
 172        do
 173                sleep 1
 174        done
 175}
 176
 177stop_and_cleanup_p4d () {
 178        kill -9 $p4d_pid $watchdog_pid
 179        wait $p4d_pid
 180        rm -rf "$db" "$cli" "$pidfile"
 181}
 182
 183cleanup_git () {
 184        retry_until_success rm -r "$git"
 185        test_must_fail test -d "$git" &&
 186        retry_until_success mkdir "$git"
 187}
 188
 189marshal_dump () {
 190        what=$1 &&
 191        line=${2:-1} &&
 192        cat >"$TRASH_DIRECTORY/marshal-dump.py" <<-EOF &&
 193        import marshal
 194        import sys
 195        instream = getattr(sys.stdin, 'buffer', sys.stdin)
 196        for i in range($line):
 197            d = marshal.load(instream)
 198        print(d[b'$what'].decode('utf-8'))
 199        EOF
 200        "$PYTHON_PATH" "$TRASH_DIRECTORY/marshal-dump.py"
 201}
 202
 203#
 204# Construct a client with this list of View lines
 205#
 206client_view () {
 207        (
 208                cat <<-EOF &&
 209                Client: $P4CLIENT
 210                Description: $P4CLIENT
 211                Root: $cli
 212                AltRoots: $(native_path "$cli")
 213                LineEnd: unix
 214                View:
 215                EOF
 216                printf "\t%s\n" "$@"
 217        ) | p4 client -i
 218}
 219
 220is_cli_file_writeable () {
 221        # cygwin version of p4 does not set read-only attr,
 222        # will be marked 444 but -w is true
 223        file="$1" &&
 224        if test_have_prereq CYGWIN && p4 -V | grep -q CYGWIN
 225        then
 226                stat=$(stat --format=%a "$file") &&
 227                test $stat = 644
 228        else
 229                test -w "$file"
 230        fi
 231}