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"&& 38if test_have_prereq CYGWIN && ! p4 -V|grep-q CYGWIN 39then 40 path=$(cygpath --windows "$path") 41else 42 path=$(test-tool path-utils real_path "$path") 43fi&& 44echo"$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 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 () { 79iftest -f"$pidfile" 80then 81kill -9$(cat "$pidfile")2>/dev/null &&exit255 82fi 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 () { 93mkdir-p"$db""$cli""$git"&& 94rm-f"$pidfile"&& 95( 96cd"$db"&& 97{ 98 p4d -q -p$P4DPORT"$@"& 99echo $! >"$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)) 112while true 113do 114iftest$(time_in_seconds)-gt$timeout 115then 116kill -9$pid 117exit1 118fi 119sleep1 120done& 121 watchdog_pid=$! 122 123 ready= 124whiletest$i-gt0 125do 126# succeed when p4 client commands start to work 127if p4 info >/dev/null 2>&1 128then 129 ready=true 130break 131fi 132# fail if p4d died 133kill -0$pid2>/dev/null ||break 134echo waiting for p4d to start 135sleep1 136 i=$(( $i - 1 )) 137done 138 139iftest -z"$ready" 140then 141# p4d failed to start 142return1 143fi 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 151return0 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 163p4_add_job () { 164 p4 job -f -i<<-EOF 165 Job:$1 166 Status: open 167 User: dummy 168 Description: 169 EOF 170} 171 172retry_until_success () { 173 timeout=$(($(time_in_seconds)+$RETRY_TIMEOUT)) 174until"$@"2>/dev/null ||test$(time_in_seconds)-gt$timeout 175do 176sleep1 177done 178} 179 180retry_until_fail () { 181 timeout=$(($(time_in_seconds)+$RETRY_TIMEOUT)) 182until!"$@"2>/dev/null ||test$(time_in_seconds)-gt$timeout 183do 184sleep1 185done 186} 187 188kill_p4d () { 189 pid=$(cat "$pidfile") 190 retry_until_fail kill$pid 191 retry_until_fail kill -9$pid 192# complain if it would not die 193 test_must_fail kill$pid>/dev/null 2>&1&& 194rm-rf"$db""$cli""$pidfile"&& 195 retry_until_fail kill -9$watchdog_pid 196} 197 198cleanup_git () { 199 retry_until_success rm-r"$git" 200 test_must_fail test -d"$git"&& 201 retry_until_success mkdir"$git" 202} 203 204marshal_dump () { 205 what=$1&& 206 line=${2:-1}&& 207cat>"$TRASH_DIRECTORY/marshal-dump.py"<<-EOF && 208 import marshal 209 import sys 210 instream = getattr(sys.stdin, 'buffer', sys.stdin) 211 for i in range($line): 212 d = marshal.load(instream) 213 print(d[b'$what'].decode('utf-8')) 214 EOF 215"$PYTHON_PATH""$TRASH_DIRECTORY/marshal-dump.py" 216} 217 218# 219# Construct a client with this list of View lines 220# 221client_view () { 222( 223cat<<-EOF && 224 Client:$P4CLIENT 225 Description:$P4CLIENT 226 Root:$cli 227 AltRoots:$(native_path "$cli") 228 LineEnd: unix 229 View: 230 EOF 231printf"\t%s\n""$@" 232) | p4 client -i 233} 234 235is_cli_file_writeable () { 236# cygwin version of p4 does not set read-only attr, 237# will be marked 444 but -w is true 238file="$1"&& 239if test_have_prereq CYGWIN && p4 -V|grep-q CYGWIN 240then 241 stat=$(stat --format=%a "$file")&& 242test$stat=644 243else 244test -w"$file" 245fi 246}