autotest.sh 11.7 KB
Newer Older
Olivier Paroz's avatar
Olivier Paroz committed
1
#!/usr/bin/env bash
Thomas Mueller's avatar
Thomas Mueller committed
2
#
Thomas Mueller's avatar
Thomas Mueller committed
3
# ownCloud
Thomas Mueller's avatar
Thomas Mueller committed
4
#
5
6
7
# @author Vincent Petry
# @author Morris Jobke
# @author Robin McCorkell
Thomas Mueller's avatar
Thomas Mueller committed
8
# @author Thomas Müller
9
10
11
# @author Andreas Fischer
# @author Joas Schilling
# @author Lukas Reschke
12
# @author Jörn Friedrich Dreyer
13
# @copyright 2012-2015 Thomas Müller thomas.mueller@tmit.eu
Thomas Mueller's avatar
Thomas Mueller committed
14
15
#

16
17
#$EXECUTOR_NUMBER is set by Jenkins and allows us to run autotest in parallel
DATABASENAME=oc_autotest$EXECUTOR_NUMBER
18
DATABASEUSER=oc_autotest$EXECUTOR_NUMBER
19
DATABASEHOST=localhost
20
ADMINLOGIN=admin$EXECUTOR_NUMBER
Thomas Mueller's avatar
Thomas Mueller committed
21
22
BASEDIR=$PWD

23
PRIMARY_STORAGE_CONFIGS="local swift"
24
DBCONFIGS="sqlite mysql mariadb pgsql oci mysqlmb4"
25
26
27
28
29
30
31
32

# $PHP_EXE is run through 'which' and as such e.g. 'php' or 'hhvm' is usually
# sufficient. Due to the behaviour of 'which', $PHP_EXE may also be a path
# (absolute or not) to an executable, e.g. ./code/projects/php-src/sapi/cli/php.
if [ -z "$PHP_EXE" ]; then
	PHP_EXE=php
fi
PHP=$(which "$PHP_EXE")
33
34
35
36

if test -z "$PHPUNIT"; then
	PHPUNIT=$(which phpunit)
fi
37

38
39
set -e

40
41
42
_XDEBUG_CONFIG=$XDEBUG_CONFIG
unset XDEBUG_CONFIG

43
44
45
46
47
48
49
50
51
function print_syntax {
	echo -e "Syntax: ./autotest.sh [dbconfigname] [testfile]\n" >&2
	echo -e "\t\"dbconfigname\" can be one of: $DBCONFIGS" >&2
	echo -e "\t\"testfile\" is the name of a test file, for example lib/template.php" >&2
	echo -e "\nExample: ./autotest.sh sqlite lib/template.php" >&2
	echo "will run the test suite from \"tests/lib/template.php\"" >&2
	echo -e "\nIf no arguments are specified, all tests will be run with all database configs" >&2
}

52
53
54
55
56
57
58
if [ -x "$PHP" ]; then
	echo "Using PHP executable $PHP"
else
	echo "Could not find PHP executable $PHP_EXE" >&2
	exit 3
fi

59
if ! [ -x "$PHPUNIT" ]; then
Jürgen Weigert's avatar
Jürgen Weigert committed
60
	echo "phpunit executable not found, please install phpunit version >= 4.4" >&2
61
62
63
	exit 3
fi

64
65
# PHPUnit might also be installed via a facade binary script
if [[ "$PHPUNIT" =~ \.phar$ ]]; then
66
  PHPUNIT=( "$PHP" "$PHPUNIT" )
67
else
68
  PHPUNIT=( "$PHPUNIT" )
69
70
71
fi

PHPUNIT_VERSION=$($PHPUNIT --version | cut -d" " -f2)
72
73
PHPUNIT_MAJOR_VERSION=$(echo "$PHPUNIT_VERSION" | cut -d"." -f1)
PHPUNIT_MINOR_VERSION=$(echo "$PHPUNIT_VERSION" | cut -d"." -f2)
74

75
76
if ! [ "$PHPUNIT_MAJOR_VERSION" -gt 4 -o \( "$PHPUNIT_MAJOR_VERSION" -eq 4 -a "$PHPUNIT_MINOR_VERSION" -ge 4 \) ]; then
	echo "phpunit version >= 4.4 required. Version found: $PHPUNIT_VERSION" >&2
77
78
79
	exit 4
fi

80
if ! [ \( -w config -a ! -f config/config.php \) -o \( -f config/config.php -a -w config/config.php \) ]; then
81
82
83
84
	echo "Please enable write permissions on config and config/config.php" >&2
	exit 1
fi

85
if [ "$1" ]; then
86
87
	FOUND=0
	for DBCONFIG in $DBCONFIGS; do
88
		if [ "$1" = "$DBCONFIG" ]; then
89
90
91
92
93
94
95
96
97
98
			FOUND=1
			break
		fi
	done
	if [ $FOUND = 0 ]; then
		echo -e "Unknown database config name \"$1\"\n" >&2
		print_syntax
		exit 2
	fi
fi
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
if [ "$PRIMARY_STORAGE_CONFIG" ]; then
	FOUND=0
	for PSC in $PRIMARY_STORAGE_CONFIGS; do
		if [ "$PRIMARY_STORAGE_CONFIG" = "$PSC" ]; then
			FOUND=1
			break
		fi
	done
	if [ $FOUND = 0 ]; then
		echo -e "Unknown primary storage config name \"$PRIMARY_STORAGE_CONFIG\"\n" >&2
		print_syntax
		exit 2
	fi
else
	PRIMARY_STORAGE_CONFIG="local"
fi
115

116
# check for the presence of @since in all OCP methods
117
$PHP build/OCPSinceChecker.php
118

119
120
# Back up existing (dev) config if one exists and backup not already there
if [ -f config/config.php ] && [ ! -f config/config-autotest-backup.php ]; then
121
122
123
	mv config/config.php config/config-autotest-backup.php
fi

124
function cleanup_config {
125

126
127
	if [ ! -z "$DOCKER_CONTAINER_ID" ]; then
		echo "Kill the docker $DOCKER_CONTAINER_ID"
128
		docker stop "$DOCKER_CONTAINER_ID"
129
		docker rm -f "$DOCKER_CONTAINER_ID"
130
131
	fi

132
	cd "$BASEDIR"
133
134
135
136
	if [ "$PRIMARY_STORAGE_CONFIG" == "swift" ] ; then
		echo "Kill the swift docker"
		tests/objectstore/stop-swift-ceph.sh
	fi
137
138
139
140
	# Restore existing config
	if [ -f config/config-autotest-backup.php ]; then
		mv config/config-autotest-backup.php config/config.php
	fi
141
142
143
144
	# Remove autotest config
	if [ -f config/autoconfig.php ]; then
		rm config/autoconfig.php
	fi
145
146
147
148
	# Remove autotest swift storage config
	if [ -f config/autotest-storage-swift.config.php ]; then
		rm config/autotest-storage-swift.config.php
	fi
149
150
	# Remove mysqlmb4.config.php
	rm -f config/mysqlmb4.config.php
151
152
}

153
154
# restore config on exit
trap cleanup_config EXIT
155

156
157
158
159
160
161
162
# use tmpfs for datadir - should speedup unit test execution
if [ -d /dev/shm ]; then
  DATADIR=/dev/shm/data-autotest$EXECUTOR_NUMBER
else
  DATADIR=$BASEDIR/data-autotest
fi

163
164
echo "Using database $DATABASENAME"

Thomas Mueller's avatar
Thomas Mueller committed
165
function execute_tests {
166
	DB=$1
167
	echo "Setup environment for $DB testing on $PRIMARY_STORAGE_CONFIG storage ..."
Thomas Mueller's avatar
Thomas Mueller committed
168
	# back to root folder
169
	cd "$BASEDIR"
Thomas Mueller's avatar
Thomas Mueller committed
170
171

	# revert changes to tests/data
172
	git checkout tests/data
Thomas Mueller's avatar
Thomas Mueller committed
173

Thomas Mueller's avatar
Thomas Mueller committed
174
	# reset data directory
175
176
	rm -rf "$DATADIR"
	mkdir "$DATADIR"
177

178
179
180
181
	if [ "$PRIMARY_STORAGE_CONFIG" == "swift" ] ; then
		tests/objectstore/start-swift-ceph.sh
		cp tests/objectstore/swift.config.php config/autotest-storage-swift.config.php
	fi
182
	cp tests/preseed-config.php config/config.php
Thomas Mueller's avatar
Thomas Mueller committed
183

184
185
	_DB=$DB

Thomas Mueller's avatar
Thomas Mueller committed
186
	# drop database
187
	if [ "$DB" == "mysql" ] ; then
188
189
190
191
192
193
194
195
196
197
198
199
		if [ ! -z "$USEDOCKER" ] ; then
			echo "Fire up the mysql docker"
			DOCKER_CONTAINER_ID=$(docker run \
				-v $BASEDIR/tests/docker/mariadb:/etc/mysql/conf.d \
				-e MYSQL_ROOT_PASSWORD=owncloud \
				-e MYSQL_USER="$DATABASEUSER" \
				-e MYSQL_PASSWORD=owncloud \
				-e MYSQL_DATABASE="$DATABASENAME" \
				-d mysql)
			DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")

			echo "Waiting for MySQL initialisation ..."
200
201
			if ! apps/files_external/tests/env/wait-for-connection $DATABASEHOST 3306 600; then
				echo "[ERROR] Waited 600 seconds, no response" >&2
202
203
204
205
206
207
208
209
210
211
212
213
214
				exit 1
			fi

			echo "MySQL is up."

		else
			if [ "mysql" != "$(mysql --version | grep -o mysql)" ] ; then
				echo "Your mysql binary is not provided by mysql"
				echo "To use the docker container set the USEDOCKER environment variable"
				exit -1
			fi
			mysql -u "$DATABASEUSER" -powncloud -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true
		fi
Thomas Mueller's avatar
Thomas Mueller committed
215
	fi
216
217
218
219
220
221
222
223
224
225
226
227
228
229
	if [ "$DB" == "mysqlmb4" ] ; then
		echo "Fire up the mysql docker"
		DOCKER_CONTAINER_ID=$(docker run \
			-v $BASEDIR/tests/docker/mysqlmb4:/etc/mysql/conf.d \
			-e MYSQL_ROOT_PASSWORD=owncloud \
			-e MYSQL_USER="$DATABASEUSER" \
			-e MYSQL_PASSWORD=owncloud \
			-e MYSQL_DATABASE="$DATABASENAME" \
			-d mysql:5.7)

		DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")

		echo "Waiting for MySQL(utf8mb4) initialisation ..."

230
231
		if ! apps/files_external/tests/env/wait-for-connection $DATABASEHOST 3306 600; then
			echo "[ERROR] Waited 600 seconds, no response" >&2
232
233
234
235
236
237
238
239
240
			exit 1
		fi
		sleep 1

		echo "MySQL(utf8mb4)  is up."
		_DB="mysql"

		cp tests/docker/mysqlmb4.config.php config
	fi
241
242
243
244
	if [ "$DB" == "mariadb" ] ; then
		if [ ! -z "$USEDOCKER" ] ; then
			echo "Fire up the mariadb docker"
			DOCKER_CONTAINER_ID=$(docker run \
Thomas Müller's avatar
Thomas Müller committed
245
				-v $BASEDIR/tests/docker/mariadb:/etc/mysql/conf.d \
246
247
248
249
				-e MYSQL_ROOT_PASSWORD=owncloud \
				-e MYSQL_USER="$DATABASEUSER" \
				-e MYSQL_PASSWORD=owncloud \
				-e MYSQL_DATABASE="$DATABASENAME" \
Thomas Müller's avatar
Thomas Müller committed
250
				-d mariadb)
251
			DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
252
253

			echo "Waiting for MariaDB initialisation ..."
254
255
			if ! apps/files_external/tests/env/wait-for-connection $DATABASEHOST 3306 600; then
				echo "[ERROR] Waited 600 seconds, no response" >&2
256
257
				exit 1
			fi
258
259
260
261
262
263

			echo "MariaDB is up."

		else
			if [ "MariaDB" != "$(mysql --version | grep -o MariaDB)" ] ; then
				echo "Your mysql binary is not provided by MariaDB"
Phil Davis's avatar
Phil Davis committed
264
				echo "To use the docker container set the USEDOCKER environment variable"
265
266
267
268
269
270
271
272
273
				exit -1
			fi
			mysql -u "$DATABASEUSER" -powncloud -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true
		fi

		#Reset _DB to mysql since that is what we use internally
		_DB="mysql"
	fi
	if [ "$DB" == "pgsql" ] ; then
274
275
276
		if [ ! -z "$USEDOCKER" ] ; then
			echo "Fire up the postgres docker"
			DOCKER_CONTAINER_ID=$(docker run -e POSTGRES_USER="$DATABASEUSER" -e POSTGRES_PASSWORD=owncloud -d postgres)
277
			DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
278
279
280
281
282
283
284
285
286
287

			echo "Waiting for Postgres initialisation ..."

			# grep exits on the first match and then the script continues
			docker logs -f "$DOCKER_CONTAINER_ID" 2>&1 | grep -q "database system is ready to accept connections"

			echo "Postgres is up."
		else
			dropdb -U "$DATABASEUSER" "$DATABASENAME" || true
		fi
288
	fi
289
	if [ "$DB" == "oci" ] ; then
290
		echo "Fire up the oracle docker"
291
		DOCKER_CONTAINER_ID=$(docker run -d deepdiver/docker-oracle-xe-11g)
292
		DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
293

294
295
		echo "Waiting for Oracle initialization ... "

296
297
298
		# Try to connect to the OCI host via sqlplus to ensure that the connection is already running
      		for i in {1..48}
                do
299
                        if sqlplus "autotest/owncloud@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=$DATABASEHOST)(Port=1521))(CONNECT_DATA=(SID=XE)))" < /dev/null | grep 'Connected to'; then
300
301
302
303
                                break;
                        fi
                        sleep 5
                done
304

305
		DATABASEUSER=autotest
306
		DATABASENAME='XE'
307
	fi
Thomas Mueller's avatar
Thomas Mueller committed
308
309

	# trigger installation
310
	echo "Installing ...."
311
	"$PHP" ./occ maintenance:install -vvv --database="$_DB" --database-name="$DATABASENAME" --database-host="$DATABASEHOST" --database-user="$DATABASEUSER" --database-pass=owncloud --database-table-prefix=oc_ --admin-user="$ADMINLOGIN" --admin-pass=admin --data-dir="$DATADIR"
Thomas Mueller's avatar
Thomas Mueller committed
312
313

	#test execution
314
	echo "Testing with $DB ..."
Thomas Mueller's avatar
Thomas Mueller committed
315
	cd tests
316
317
	rm -rf "coverage-html-$DB"
	mkdir "coverage-html-$DB"
318
	"$PHP" -f enable_all.php | grep -i -C9999 error && echo "Error during setup" && exit 101
319
320
321
	if [[ "$_XDEBUG_CONFIG" ]]; then
		export XDEBUG_CONFIG=$_XDEBUG_CONFIG
	fi
322
323
324
325
326
327
328
329
330
	GROUP=''
	if [ "$TEST_SELECTION" == "DB" ]; then
		GROUP='--group DB'
	fi
	if [ "$TEST_SELECTION" == "NODB" ]; then
		GROUP='--exclude-group DB'
	fi

	COVER=''
331
	if [ -z "$NOCOVERAGE" ]; then
332
		COVER="--coverage-clover autotest-clover-$DB.xml --coverage-html coverage-html-$DB"
333
334
335
	else
		echo "No coverage"
	fi
336
337
338
	echo "${PHPUNIT[@]}" --configuration phpunit-autotest.xml $GROUP $COVER --log-junit "autotest-results-$DB.xml" "$2" "$3"
	"${PHPUNIT[@]}" --configuration phpunit-autotest.xml $GROUP $COVER --log-junit "autotest-results-$DB.xml" "$2" "$3"
		RESULT=$?
339

340
	if [ "$PRIMARY_STORAGE_CONFIG" == "swift" ] ; then
341
		cd ..
342
		echo "Kill the swift docker"
343
		tests/objectstore/stop-swift-ceph.sh
344
345
	fi

346
347
	if [ ! -z "$DOCKER_CONTAINER_ID" ] ; then
		echo "Kill the docker $DOCKER_CONTAINER_ID"
348
		docker stop $DOCKER_CONTAINER_ID
349
350
351
		docker rm -f $DOCKER_CONTAINER_ID
		unset DOCKER_CONTAINER_ID
	fi
Thomas Mueller's avatar
Thomas Mueller committed
352
353
354
355
}

#
# start test execution
356
#
357
358
if [ -z "$1" ]
  then
359
360
	# run all known database configs
	for DBCONFIG in $DBCONFIGS; do
361
		execute_tests "$DBCONFIG"
362
	done
363
else
364
	FILENAME="$2"
365
	if [ ! -z "$2" ] && [ ! -f "tests/$FILENAME" ]; then
366
367
368
		FILENAME="../$FILENAME"
	fi
	execute_tests "$1" "$FILENAME" "$3"
369
fi
Thomas Mueller's avatar
Thomas Mueller committed
370
371

#
372
# NOTES on mysql:
373
#  - CREATE DATABASE oc_autotest;
Thomas Mueller's avatar
Thomas Mueller committed
374
#  - CREATE USER 'oc_autotest'@'localhost' IDENTIFIED BY 'owncloud';
375
376
377
378
379
380
#  - grant all on oc_autotest.* to 'oc_autotest'@'localhost';
#
#  - for parallel executor support with EXECUTOR_NUMBER=0:
#  - CREATE DATABASE oc_autotest0;
#  - CREATE USER 'oc_autotest0'@'localhost' IDENTIFIED BY 'owncloud';
#  - grant all on oc_autotest0.* to 'oc_autotest0'@'localhost';
381
#
382
383
# NOTES on pgsql:
#  - su - postgres
Thomas Müller's avatar
Thomas Müller committed
384
#  - createuser -P oc_autotest (enter password and enable superuser)
385
386
387
#  - to enable dropdb I decided to add following line to pg_hba.conf (this is not the safest way but I don't care for the testing machine):
# local	all	all	trust
#
Thomas Müller's avatar
Thomas Müller committed
388
389
390
#  - for parallel executor support with EXECUTOR_NUMBER=0:
#  - createuser -P oc_autotest0 (enter password and enable superuser)
#
391
392
393
394
395
# NOTES on oci:
#  - it's a pure nightmare to install Oracle on a Linux-System
#  - DON'T TRY THIS AT HOME!
#  - if you really need it: we feel sorry for you
#