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}