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