test-lib.sh 8.78 KB
Newer Older
1 2 3 4 5 6 7 8
# Test framework for go-ipfs
#
# Copyright (c) 2014 Christian Couder
# MIT Licensed; see the LICENSE file in this repository.
#
# We are using sharness (https://github.com/mlafeldt/sharness)
# which was extracted from the Git test framework.

9 10 11
# use the ipfs tool to test against

# add current directory to path, for ipfs tool.
12
if test "$MAKE_SKIP_PATH" != "1"; then
13 14 15 16 17 18 19 20 21 22 23
	BIN=$(cd .. && echo `pwd`/bin)
	BIN2=$(cd ../.. && echo `pwd`/cmd/ipfs)
	PATH=${BIN2}:${BIN}:${PATH}

	# assert the `ipfs` we're using is the right one.
	if test `which ipfs` != ${BIN2}/ipfs; then
		echo >&2 "Cannot find the tests' local ipfs tool."
		echo >&2 "Please check test and ipfs tool installation."
		exit 1
	fi
fi
24

25 26 27 28
# set sharness verbosity. we set the env var directly as
# it's too late to pass in --verbose, and --verbose is harder
# to pass through in some cases.
test "$TEST_VERBOSE" = 1 && verbose=t
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
29 30 31 32
# source the common hashes first.
. lib/test-lib-hashes.sh


33
SHARNESS_LIB="lib/sharness/sharness.sh"
34

35 36 37 38 39 40 41 42
. "$SHARNESS_LIB" || {
	echo >&2 "Cannot source: $SHARNESS_LIB"
	echo >&2 "Please check Sharness installation."
	exit 1
}

# Please put go-ipfs specific shell functions below

43 44
TEST_OS="$(uname -s | tr '[a-z]' '[A-Z]')"

45
# grab + output options
46
test "$TEST_NO_FUSE" != 1 && test_set_prereq FUSE
47
test "$TEST_EXPENSIVE" = 1 && test_set_prereq EXPENSIVE
48
test "$TEST_NO_DOCKER" != 1 && type docker >/dev/null 2>&1 && test_set_prereq DOCKER
49
test "$TEST_NO_PLUGIN" != 1 && test "$TEST_OS" = "LINUX" && test_set_prereq PLUGIN
50 51 52

# Set a prereq as error messages are often different on Windows/Cygwin
expr "$TEST_OS" : "CYGWIN_NT" >/dev/null || test_set_prereq STD_ERR_MSG
53

54 55 56
if test "$TEST_VERBOSE" = 1; then
	echo '# TEST_VERBOSE='"$TEST_VERBOSE"
	echo '# TEST_NO_FUSE='"$TEST_NO_FUSE"
57
	echo '# TEST_NO_PLUGIN='"$TEST_NO_PLUGIN"
58
	echo '# TEST_EXPENSIVE='"$TEST_EXPENSIVE"
59
	echo '# TEST_OS='"$TEST_OS"
60 61
fi

62 63 64
# source our generic test lib
. ../../ipfs-test-lib.sh

65 66 67
# source iptb lib
. ../lib/iptb-lib.sh

68
test_cmp_repeat_10_sec() {
Christian Couder's avatar
Christian Couder committed
69
	for i in $(test_seq 1 100)
70
	do
71
		test_cmp "$1" "$2" >/dev/null && return
72
		go-sleep 100ms
73 74 75 76
	done
	test_cmp "$1" "$2"
}

77
test_run_repeat_60_sec() {
78
	for i in $(test_seq 1 600)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
79
	do
80 81
		(test_eval_ "$1") && return
		go-sleep 100ms
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
82 83 84 85
	done
	return 1 # failed
}

86
test_wait_output_n_lines_60_sec() {
87
	for i in $(test_seq 1 600)
88
	do
89 90
		test $(cat "$1" | wc -l | tr -d " ") -ge $2 && return
		go-sleep 100ms
91
	done
92
	actual=$(cat "$1" | wc -l | tr -d " ")
93
	test_fsh "expected $2 lines of output. got $actual"
94 95
}

96
test_wait_open_tcp_port_10_sec() {
97 98
	for i in $(test_seq 1 100)
	do
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
99 100 101 102 103
		# this is not a perfect check, but it's portable.
		# cant count on ss. not installed everywhere.
		# cant count on netstat using : or . as port delim. differ across platforms.
		echo $(netstat -aln | egrep "^tcp.*LISTEN" | egrep "[.:]$1" | wc -l) -gt 0
		if [ $(netstat -aln | egrep "^tcp.*LISTEN" | egrep "[.:]$1" | wc -l) -gt 0 ]; then
104 105
			return 0
		fi
106
		go-sleep 100ms
107 108 109 110
	done
	return 1
}

111 112 113 114 115 116

# test_config_set helps us make sure _we really did set_ a config value.
# it sets it and then tests it. This became elaborate because ipfs config
# was setting really weird things and am not sure why.
test_config_set() {

Etienne Laurin's avatar
Etienne Laurin committed
117
	# grab flags (like --bool in "ipfs config --bool")
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	test_cfg_flags="" # unset in case.
	test "$#" = 3 && { test_cfg_flags=$1; shift; }

	test_cfg_key=$1
	test_cfg_val=$2

	# when verbose, tell the user what config values are being set
	test_cfg_cmd="ipfs config $test_cfg_flags \"$test_cfg_key\" \"$test_cfg_val\""
	test "$TEST_VERBOSE" = 1 && echo "$test_cfg_cmd"

	# ok try setting the config key/val pair.
	ipfs config $test_cfg_flags "$test_cfg_key" "$test_cfg_val"
	echo "$test_cfg_val" >cfg_set_expected
	ipfs config "$test_cfg_key" >cfg_set_actual
	test_cmp cfg_set_expected cfg_set_actual
}

135
test_init_ipfs() {
136

137

138 139 140 141
	# we set the Addresses.API config variable.
	# the cli client knows to use it, so only need to set.
	# todo: in the future, use env?

142
	test_expect_success "ipfs init succeeds" '
143
		export IPFS_PATH="$(pwd)/.ipfs" &&
Steven Allen's avatar
Steven Allen committed
144
		ipfs init --profile=test -b=1024 > /dev/null
145 146
	'

Steven Allen's avatar
Steven Allen committed
147
	test_expect_success "prepare config -- mounting" '
148
		mkdir mountdir ipfs ipns &&
149
		test_config_set Mounts.IPFS "$(pwd)/ipfs" &&
Steven Allen's avatar
Steven Allen committed
150
		test_config_set Mounts.IPNS "$(pwd)/ipns" ||
151
		test_fsh cat "\"$IPFS_PATH/config\""
152 153
	'

154 155
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
156 157
test_config_ipfs_gateway_writable() {
	test_expect_success "prepare config -- gateway writable" '
Etienne Laurin's avatar
Etienne Laurin committed
158
		test_config_set --bool Gateway.Writable true ||
159
		test_fsh cat "\"$IPFS_PATH/config\""
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
160 161 162
	'
}

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
test_wait_for_file() {
	loops=$1
	delay=$2
	file=$3
	fwaitc=0
	while ! test -f "$file"
	do
		if test $fwaitc -ge $loops
		then
			echo "Error: timed out waiting for file: $file"
			return 1
		fi

		go-sleep $delay
		fwaitc=`expr $fwaitc + 1`
	done
}

Jeromy's avatar
Jeromy committed
181 182
test_set_address_vars() {
	daemon_output="$1"
183 184 185 186 187 188

	test_expect_success "set up address variables" '
		API_MADDR=$(cat "$IPFS_PATH/api") &&
		API_ADDR=$(convert_tcp_maddr $API_MADDR) &&
		API_PORT=$(port_from_maddr $API_MADDR) &&

Jeromy's avatar
Jeromy committed
189
		GWAY_MADDR=$(sed -n "s/^Gateway (.*) server listening on //p" "$daemon_output") &&
190 191 192 193
		GWAY_ADDR=$(convert_tcp_maddr $GWAY_MADDR) &&
		GWAY_PORT=$(port_from_maddr $GWAY_MADDR)
	'

194
	if ipfs swarm addrs local >/dev/null 2>&1; then
195
		test_expect_success "set swarm address vars" '
196
		ipfs swarm addrs local > addrs_out &&
197 198 199 200
			SWARM_MADDR=$(grep "127.0.0.1" addrs_out) &&
			SWARM_PORT=$(port_from_maddr $SWARM_MADDR)
		'
	fi
Jeromy's avatar
Jeromy committed
201 202 203 204 205 206
}

test_launch_ipfs_daemon() {

	args="$@"

207
	test "$TEST_ULIMIT_PRESET" != 1 && ulimit -n 2048
Jeromy's avatar
Jeromy committed
208

Jeromy's avatar
Jeromy committed
209 210 211 212 213 214 215 216 217 218
	test_expect_success "'ipfs daemon' succeeds" '
		ipfs daemon $args >actual_daemon 2>daemon_err &
	'

	# wait for api file to show up
	test_expect_success "api file shows up" '
		test_wait_for_file 20 100ms "$IPFS_PATH/api"
	'

	test_set_address_vars actual_daemon
219

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
220 221
	# we say the daemon is ready when the API server is ready.
	test_expect_success "'ipfs daemon' is ready" '
222
		IPFS_PID=$! &&
223
		pollEndpoint -ep=/version -host=$API_MADDR -v -tout=1s -tries=60 2>poll_apierr > poll_apiout ||
Henry's avatar
Henry committed
224
		test_fsh cat actual_daemon || test_fsh cat daemon_err || test_fsh cat poll_apierr || test_fsh cat poll_apiout
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
225
	'
226 227
}

228
do_umount() {
229
	if [ "$(uname -s)" = "Linux" ]; then
230
	fusermount -u "$1"
231
	else
232
	umount "$1"
233
	fi
234 235
}

236
test_mount_ipfs() {
237

238
	# make sure stuff is unmounted first.
239
	test_expect_success FUSE "'ipfs mount' succeeds" '
240 241
		do_umount "$(pwd)/ipfs" || true &&
		do_umount "$(pwd)/ipns" || true &&
242 243 244 245 246 247 248 249
		ipfs mount >actual
	'

	test_expect_success FUSE "'ipfs mount' output looks good" '
		echo "IPFS mounted at: $(pwd)/ipfs" >expected &&
		echo "IPNS mounted at: $(pwd)/ipns" >>expected &&
		test_cmp expected actual
	'
250 251 252 253 254 255 256 257 258

}

test_launch_ipfs_daemon_and_mount() {

	test_init_ipfs
	test_launch_ipfs_daemon
	test_mount_ipfs

259 260 261
}

test_kill_repeat_10_sec() {
262 263
	# try to shut down once + wait for graceful exit
	kill $1
Christian Couder's avatar
Christian Couder committed
264
	for i in $(test_seq 1 100)
265
	do
266
		go-sleep 100ms
267 268
		! kill -0 $1 2>/dev/null && return
	done
269 270 271

	# if not, try once more, which will skip graceful exit
	kill $1
272
	go-sleep 1s
273 274 275 276 277
	! kill -0 $1 2>/dev/null && return

	# ok, no hope. kill it to prevent it messing with other tests
	kill -9 $1 2>/dev/null
	return 1
278 279
}

280
test_kill_ipfs_daemon() {
281

282
	test_expect_success "'ipfs daemon' is still running" '
283 284 285
		kill -0 $IPFS_PID
	'

286
	test_expect_success "'ipfs daemon' can be killed" '
287
		test_kill_repeat_10_sec $IPFS_PID
288 289
	'
}
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310

test_curl_resp_http_code() {
	curl -I "$1" >curl_output || {
		echo "curl error with url: '$1'"
		echo "curl output was:"
		cat curl_output
		return 1
	}
	shift &&
	RESP=$(head -1 curl_output) &&
	while test "$#" -gt 0
	do
		expr "$RESP" : "$1" >/dev/null && return
		shift
	done
	echo "curl response didn't match!"
	echo "curl response was: '$RESP'"
	echo "curl output was:"
	cat curl_output
	return 1
}
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

test_must_be_empty() {
	if test -s "$1"
	then
		echo "'$1' is not empty, it contains:"
		cat "$1"
		return 1
	fi
}

test_should_contain() {
	test "$#" = 2 || error "bug in the test script: not 2 parameters to test_should_contain"
	if ! grep -q "$1" "$2"
	then
		echo "'$2' does not contain '$1', it contains:"
		cat "$2"
		return 1
	fi
}
Jeromy's avatar
Jeromy committed
330 331 332 333

test_str_contains() {
	find=$1
	shift
334
	echo "$@" | egrep "\b$find\b" >/dev/null
Jeromy's avatar
Jeromy committed
335
}
rht's avatar
rht committed
336 337

disk_usage() {
338 339 340 341
	# normalize du across systems
	case $(uname -s) in
		Linux)
			DU="du -sb"
342
			M=1
343 344 345
			;;
		FreeBSD)
			DU="du -s -A -B 1"
346
			M=512
347 348 349
			;;
		Darwin | DragonFly | *)
			DU="du -s"
350
			M=512
351 352
			;;
	esac
353
	expr $($DU "$1" | awk "{print \$1}") "*" "$M"
rht's avatar
rht committed
354
}
355 356 357

# output a file's permission in human readable format
generic_stat() {
358 359 360 361 362 363 364 365 366 367
	# normalize stat across systems
	case $(uname -s) in
		Linux)
			_STAT="stat -c %A"
			;;
		FreeBSD | Darwin | DragonFly)
			_STAT="stat -f %Sp"
			;;
	esac
	$_STAT "$1" || echo "failed" # Avoid returning nothing.
368
}
369 370

test_check_peerid() {
371 372 373 374 375
	peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") &&
	test "$peeridlen" = "46" || {
		echo "Bad peerid '$1' with len '$peeridlen'"
		return 1
	}
376
}
377 378 379 380 381 382 383 384

convert_tcp_maddr() {
	echo $1 | awk -F'/' '{ printf "%s:%s", $3, $5 }'
}

port_from_maddr() {
	echo $1 | awk -F'/' '{ print $NF }'
}