github.com/whyrusleeping/gx@v0.14.3/tests/lib/test-lib.sh (about) 1 # Test framework for go-ipfs 2 # 3 # Copyright (c) 2014 Christian Couder 4 # MIT Licensed; see the LICENSE file in this repository. 5 # 6 # We are using sharness (https://github.com/mlafeldt/sharness) 7 # which was extracted from the Git test framework. 8 9 # set sharness verbosity. we set the env var directly as 10 # it's too late to pass in --verbose, and --verbose is harder 11 # to pass through in some cases. 12 test "$TEST_VERBOSE" = 1 && verbose=t 13 14 cwd=$(pwd) 15 SHARNESS_LIB="lib/sharness/sharness.sh" 16 17 . "$SHARNESS_LIB" || { 18 echo >&2 "Cannot source: $SHARNESS_LIB" 19 echo >&2 "Please check Sharness installation." 20 exit 1 21 } 22 23 # add current directory to path, for ipfs tool. 24 # after loading sharness, so that ./bin takes precedence over ./. 25 PATH="$cwd"/bin:${PATH} 26 export PATH 27 28 # assert the `ipfs` we're using is the right one. 29 if test `which ipfs` != "$cwd/bin/ipfs"; then 30 echo >&2 "Found ipfs executable but it's not $cwd/bin/ipfs" 31 echo >&2 "Check PATH: $PATH" 32 exit 1 33 fi 34 35 # Please put go-ipfs specific shell functions below 36 37 # grab + output options 38 test "$TEST_NO_FUSE" != 1 && test_set_prereq FUSE 39 test "$TEST_EXPENSIVE" = 1 && test_set_prereq EXPENSIVE 40 41 if test "$TEST_VERBOSE" = 1; then 42 echo '# TEST_VERBOSE='"$TEST_VERBOSE" 43 echo '# TEST_NO_FUSE='"$TEST_NO_FUSE" 44 echo '# TEST_EXPENSIVE='"$TEST_EXPENSIVE" 45 fi 46 47 test_cmp_repeat_10_sec() { 48 for i in $(test_seq 1 100) 49 do 50 test_cmp "$1" "$2" >/dev/null && return 51 go-sleep 100ms 52 done 53 test_cmp "$1" "$2" 54 } 55 56 test_fsh() { 57 echo "> $@" 58 eval "$@" 59 echo "" 60 false 61 } 62 63 test_run_repeat_60_sec() { 64 for i in $(test_seq 1 600) 65 do 66 (test_eval_ "$1") && return 67 go-sleep 100ms 68 done 69 return 1 # failed 70 } 71 72 test_wait_output_n_lines_60_sec() { 73 for i in $(test_seq 1 600) 74 do 75 test $(cat "$1" | wc -l | tr -d " ") -ge $2 && return 76 go-sleep 100ms 77 done 78 actual=$(cat "$1" | wc -l | tr -d " ") 79 test_fsh "expected $2 lines of output. got $actual" 80 } 81 82 test_wait_open_tcp_port_10_sec() { 83 for i in $(test_seq 1 100) 84 do 85 # this is not a perfect check, but it's portable. 86 # cant count on ss. not installed everywhere. 87 # cant count on netstat using : or . as port delim. differ across platforms. 88 echo $(netstat -aln | egrep "^tcp.*LISTEN" | egrep "[.:]$1" | wc -l) -gt 0 89 if [ $(netstat -aln | egrep "^tcp.*LISTEN" | egrep "[.:]$1" | wc -l) -gt 0 ]; then 90 return 0 91 fi 92 go-sleep 100ms 93 done 94 return 1 95 } 96 97 98 # test_config_set helps us make sure _we really did set_ a config value. 99 # it sets it and then tests it. This became elaborate because ipfs config 100 # was setting really weird things and am not sure why. 101 test_config_set() { 102 103 # grab flags (like --bool in "ipfs config --bool") 104 test_cfg_flags="" # unset in case. 105 test "$#" = 3 && { test_cfg_flags=$1; shift; } 106 107 test_cfg_key=$1 108 test_cfg_val=$2 109 110 # when verbose, tell the user what config values are being set 111 test_cfg_cmd="ipfs config $test_cfg_flags \"$test_cfg_key\" \"$test_cfg_val\"" 112 test "$TEST_VERBOSE" = 1 && echo "$test_cfg_cmd" 113 114 # ok try setting the config key/val pair. 115 ipfs config $test_cfg_flags "$test_cfg_key" "$test_cfg_val" 116 echo "$test_cfg_val" >cfg_set_expected 117 ipfs config "$test_cfg_key" >cfg_set_actual 118 test_cmp cfg_set_expected cfg_set_actual 119 } 120 121 test_init_ipfs() { 122 123 # we have a problem where initializing daemons with the same api port 124 # often fails-- it hangs indefinitely. The proper solution is to make 125 # ipfs pick an unused port for the api on startup, and then use that. 126 # Unfortunately, ipfs doesnt yet know how to do this-- the api port 127 # must be specified. Until ipfs learns how to do this, we must use 128 # specific port numbers, which may still fail but less frequently 129 # if we at least use different ones. 130 131 # Using RANDOM like this is clearly wrong-- it samples with replacement 132 # and it doesnt even check the port is unused. this is a trivial stop gap 133 # until the proper solution is implemented. 134 RANDOM=$$ 135 PORT_API=$((RANDOM % 3000 + 5100)) 136 ADDR_API="/ip4/127.0.0.1/tcp/$PORT_API" 137 138 PORT_GWAY=$((RANDOM % 3000 + 8100)) 139 ADDR_GWAY="/ip4/127.0.0.1/tcp/$PORT_GWAY" 140 141 PORT_SWARM=$((RANDOM % 3000 + 12000)) 142 ADDR_SWARM="[ 143 \"/ip4/0.0.0.0/tcp/$PORT_SWARM\" 144 ]" 145 146 147 # we set the Addresses.API config variable. 148 # the cli client knows to use it, so only need to set. 149 # todo: in the future, use env? 150 151 test_expect_success "ipfs init succeeds" ' 152 export IPFS_PATH="$(pwd)/.ipfs" && 153 ipfs init -b=1024 > /dev/null 154 ' 155 156 test_expect_success "prepare config -- mounting and bootstrap rm" ' 157 mkdir mountdir ipfs ipns && 158 test_config_set Mounts.IPFS "$(pwd)/ipfs" && 159 test_config_set Mounts.IPNS "$(pwd)/ipns" && 160 test_config_set Addresses.API "$ADDR_API" && 161 test_config_set Addresses.Gateway "$ADDR_GWAY" && 162 test_config_set --json Addresses.Swarm "$ADDR_SWARM" && 163 ipfs bootstrap rm --all || 164 test_fsh cat "\"$IPFS_PATH/config\"" 165 ' 166 167 } 168 169 test_config_ipfs_gateway_readonly() { 170 ADDR_GWAY=$1 171 test_expect_success "prepare config -- gateway address" ' 172 test "$ADDR_GWAY" != "" && 173 test_config_set "Addresses.Gateway" "$ADDR_GWAY" 174 ' 175 176 # tell the user what's going on if they messed up the call. 177 if test "$#" = 0; then 178 echo "# Error: must call with an address, for example:" 179 echo '# test_config_ipfs_gateway_readonly "/ip4/0.0.0.0/tcp/5002"' 180 echo '#' 181 fi 182 } 183 184 test_config_ipfs_gateway_writable() { 185 186 test_config_ipfs_gateway_readonly $1 187 188 test_expect_success "prepare config -- gateway writable" ' 189 test_config_set --bool Gateway.Writable true || 190 test_fsh cat "\"$IPFS_PATH/config\"" 191 ' 192 } 193 194 test_launch_ipfs_daemon() { 195 196 args="$@" 197 198 test_expect_success "'ipfs daemon' succeeds" ' 199 ipfs daemon $args >actual_daemon 2>daemon_err & 200 ' 201 202 # we say the daemon is ready when the API server is ready. 203 test_expect_success "'ipfs daemon' is ready" ' 204 IPFS_PID=$! && 205 pollEndpoint -ep=/version -host=$ADDR_API -v -tout=1s -tries=60 2>poll_apierr > poll_apiout || 206 test_fsh cat actual_daemon || test_fsh cat daemon_err || test_fsh cat poll_apierr || test_fsh cat poll_apiout 207 ' 208 209 if test "$ADDR_GWAY" != ""; then 210 test_expect_success "'ipfs daemon' output includes Gateway address" ' 211 pollEndpoint -ep=/version -host=$ADDR_GWAY -v -tout=1s -tries=60 2>poll_gwerr > poll_gwout || 212 test_fsh cat daemon_err || test_fsh cat poll_gwerr || test_fsh cat poll_gwout 213 ' 214 fi 215 } 216 217 test_mount_ipfs() { 218 219 # make sure stuff is unmounted first. 220 test_expect_success FUSE "'ipfs mount' succeeds" ' 221 umount "$(pwd)/ipfs" || true && 222 umount "$(pwd)/ipns" || true && 223 ipfs mount >actual 224 ' 225 226 test_expect_success FUSE "'ipfs mount' output looks good" ' 227 echo "IPFS mounted at: $(pwd)/ipfs" >expected && 228 echo "IPNS mounted at: $(pwd)/ipns" >>expected && 229 test_cmp expected actual 230 ' 231 232 } 233 234 test_launch_ipfs_daemon_and_mount() { 235 236 test_init_ipfs 237 test_launch_ipfs_daemon 238 test_mount_ipfs 239 240 } 241 242 test_kill_repeat_10_sec() { 243 # try to shut down once + wait for graceful exit 244 kill $1 245 for i in $(test_seq 1 100) 246 do 247 go-sleep 100ms 248 ! kill -0 $1 2>/dev/null && return 249 done 250 251 # if not, try once more, which will skip graceful exit 252 kill $1 253 go-sleep 1s 254 ! kill -0 $1 2>/dev/null && return 255 256 # ok, no hope. kill it to prevent it messing with other tests 257 kill -9 $1 2>/dev/null 258 return 1 259 } 260 261 test_kill_ipfs_daemon() { 262 263 test_expect_success "'ipfs daemon' is still running" ' 264 kill -0 $IPFS_PID 265 ' 266 267 test_expect_success "'ipfs daemon' can be killed" ' 268 test_kill_repeat_10_sec $IPFS_PID 269 ' 270 } 271 272 test_curl_resp_http_code() { 273 curl -I "$1" >curl_output || { 274 echo "curl error with url: '$1'" 275 echo "curl output was:" 276 cat curl_output 277 return 1 278 } 279 shift && 280 RESP=$(head -1 curl_output) && 281 while test "$#" -gt 0 282 do 283 expr "$RESP" : "$1" >/dev/null && return 284 shift 285 done 286 echo "curl response didn't match!" 287 echo "curl response was: '$RESP'" 288 echo "curl output was:" 289 cat curl_output 290 return 1 291 } 292 293 test_must_be_empty() { 294 if test -s "$1" 295 then 296 echo "'$1' is not empty, it contains:" 297 cat "$1" 298 return 1 299 fi 300 } 301 302 test_should_contain() { 303 test "$#" = 2 || error "bug in the test script: not 2 parameters to test_should_contain" 304 if ! grep -q "$1" "$2" 305 then 306 echo "'$2' does not contain '$1', it contains:" 307 cat "$2" 308 return 1 309 fi 310 } 311 312 test_str_contains() { 313 find=$1 314 shift 315 echo "$@" | grep "$find" >/dev/null 316 } 317 318 disk_usage() { 319 # normalize du across systems 320 case $(uname -s) in 321 Linux) 322 DU="du -sb" 323 ;; 324 FreeBSD) 325 DU="du -s -A -B 1" 326 ;; 327 Darwin | DragonFly) 328 DU="du" 329 ;; 330 esac 331 $DU "$1" | awk "{print \$1}" 332 } 333 334 # output a file's permission in human readable format 335 generic_stat() { 336 # normalize stat across systems 337 case $(uname -s) in 338 Linux) 339 _STAT="stat -c %A" 340 ;; 341 FreeBSD | Darwin | DragonFly) 342 _STAT="stat -f %Sp" 343 ;; 344 esac 345 $_STAT "$1" 346 } 347 348 test_check_peerid() { 349 peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && 350 test "$peeridlen" = "46" || { 351 echo "Bad peerid '$1' with len '$peeridlen'" 352 return 1 353 } 354 } 355 356 357 make_package() { 358 dir=$1 359 lang=$2 360 mkdir -p $dir 361 test_expect_success "gx init succeeds" ' 362 (cd $dir && gx init --lang="$lang") 363 ' 364 } 365 366 publish_package() { 367 pkgdir=$1 368 (cd $pkgdir && gx publish) | awk '{ print $6 }' 369 } 370 371 pkg_run() { 372 dir=$1 373 shift 374 (cd $dir && $@) 375 }