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