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