tests: pre-commit regression tests

Framework for writing test cases to be submitted with patches.

This framework and the test cases get exercised by Jenkins in
the pre-commit regression test. Jenkins is configured to give
a +1 verified vote only if the regression test passes without
failures (which includes test cases added/changed by the patch
being tested)

Every patch should include a test case (either extensions/changes
to existing test cases or add new ones, as appropriate). The test
case should be part of the same commit so that both code and
test case get reviewed together.

Test cases added are cumulative. Every new patch gets
tested against its own test case and every test case previously
added.

A lot of new commits in the near future will be pure test cases
(with no code change) which will get added in "catch up" mode.

The tool used for implementing test cases is 'prove', and the
framework itself is modeled similar to the POSIX compliance
filesystem test suite.

Under the top level directory, a new directory named 'tests/'
is added. This contains top level classifier directories and
framework files/scripts.

Functionality tests should be created under a classifier directory
below 'tests/'. For e.g:

  tests/basic/mount.t
  tests/performance/write-behind.t

Bugs which get fixed should include a test case script named
by the bug id, so that we are guaranteed any new change will
not bring the issue back. For e.g:

  tests/bugs/bug-123456.t

Triggering of regression tests in Jenkins is manual at this point
as we do not want the entire test suite to run against every
revision of a patch while it is still in the review/resubmit cycle.

Signed-off-by: Anand Avati <avati@redhat.com>

Change-Id: I8078244619135ccaba38e068925f8ca85141055a
BUG: 764966
Signed-off-by: Anand Avati <avati@redhat.com>
Reviewed-on: http://review.gluster.org/4101
Tested-by: Gluster Build System <jenkins@build.gluster.com>
This commit is contained in:
Anand Avati 2012-10-17 15:51:18 -07:00
parent 56d1f81949
commit bb41c8ab88
7 changed files with 234 additions and 83 deletions

3
run-tests.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
prove -r $(dirname $0)/tests;

View File

@ -1,83 +0,0 @@
#!/bin/bash
set -e;
M=/mnt;
P=/build;
H=$(hostname);
T=600;
V=patchy;
function cleanup()
{
killall -15 glusterfs glusterfsd glusterd glusterd 2>&1 || true;
killall -9 glusterfs glusterfsd glusterd glusterd 2>&1 || true;
umount -l $M 2>&1 || true;
rm -rf /var/lib/glusterd /etc/glusterd $P/export;
}
function start_fs()
{
mkdir -p $P/export;
chmod 0755 $P/export;
glusterd;
gluster --mode=script volume create $V replica 2 $H:$P/export/export{1,2,3,4};
gluster volume start $V;
glusterfs -s $H --volfile-id $V $M;
# mount -t glusterfs $H:/$V $M;
}
function run_tests()
{
cd $M;
(sleep 1; dbench -s -t 60 10 >/dev/null) &
(sleep 1; /opt/qa/tools/posix_compliance.sh) &
wait %2
wait %3
rm -rf clients;
cd -;
}
function watchdog ()
{
# insurance against hangs during the test
sleep $1;
echo "Kicking in watchdog after $1 secs";
cleanup;
}
function finish ()
{
cleanup;
kill %1;
}
function main ()
{
cleanup;
watchdog $T &
trap finish EXIT;
set -x;
start_fs;
run_tests;
}
main "$@";

20
tests/README Normal file
View File

@ -0,0 +1,20 @@
How to use use
==============
- Build and install the version of glusterfs with your changes. Make
sure the installed version is accessible from $PATH.
- (optional) Set environment variables to specify location of
export directories and mount points. Unless you have special
requirements, the defaults should just work. The variables
themselves can be found at the top of tests/include.rc. All
of them can be overriden with environment variables.
- Execute run-tests.sh in the top level directory as root.
- If some test cases fail, you can execute the failed test case script
directly bypassing run-tests.sh. At this time it might be
useful to set the envrionment variable DEBUG=1 before running
the individual test script directly by hand.
- BE WARNED THAT THE TEST CASES DELETE /var/lib/glusterd/* !!!

62
tests/basic/mount.t Executable file
View File

@ -0,0 +1,62 @@
#!/bin/bash
. $(dirname $0)/../include.rc
cleanup;
## Start and create a volume
TEST glusterd
TEST pidof glusterd
TEST $CLI volume info;
TEST $CLI volume create $V0 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8};
function volinfo_field()
{
local vol=$1;
local field=$2;
$CLI volume info $vol | grep "^$field: " | sed 's/.*: //';
}
## Verify volume is is created
EXPECT "$V0" volinfo_field $V0 'Volume Name';
EXPECT 'Created' volinfo_field $V0 'Status';
## Start volume and verify
TEST $CLI volume start $V0;
EXPECT 'Started' volinfo_field $V0 'Status';
## Make volume tightly consistent for metdata
TEST $CLI volume set $V0 performance.stat-prefetch off;
## Mount FUSE with caching disabled
TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0;
## Wait for volume to register with rpc.mountd
sleep 5;
## Mount NFS
TEST mount -t nfs -o vers=3,nolock,soft,intr $H0:/$V0 $N0;
## Test for consistent views between NFS and FUSE mounts
TEST ! stat $M0/newfile;
TEST touch $M0/newfile;
TEST stat $N0/newfile;
TEST rm $N0/newfile;
TEST ! stat $M0/newfile;
## Finish up
TEST $CLI volume stop $V0;
EXPECT 'Stopped' volinfo_field $V0 'Status';
TEST $CLI volume delete $V0;
TEST ! $CLI volume info $V0;
cleanup;

47
tests/basic/volume.t Executable file
View File

@ -0,0 +1,47 @@
#!/bin/bash
. $(dirname $0)/../include.rc
cleanup;
TEST glusterd
TEST pidof glusterd
TEST $CLI volume info;
TEST $CLI volume create $V0 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8};
function volinfo_field()
{
local vol=$1;
local field=$2;
$CLI volume info $vol | grep "^$field: " | sed 's/.*: //';
}
function brick_count()
{
local vol=$1;
$CLI volume info $vol | egrep "^Brick[0-9]+: " | wc -l;
}
EXPECT "$V0" volinfo_field $V0 'Volume Name';
EXPECT 'Created' volinfo_field $V0 'Status';
EXPECT '8' brick_count $V0
TEST $CLI volume start $V0;
EXPECT 'Started' volinfo_field $V0 'Status';
TEST $CLI volume add-brick $V0 $H0:$B0/${V0}{9,10,11,12};
EXPECT '12' brick_count $V0
TEST $CLI volume stop $V0;
EXPECT 'Stopped' volinfo_field $V0 'Status';
TEST $CLI volume delete $V0;
TEST ! $CLI volume info $V0;
cleanup;

9
tests/bugs/bug-000000.t Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
. $(dirname $0)/../include.rc
cleanup;
TEST glusterd
cleanup;

93
tests/include.rc Normal file
View File

@ -0,0 +1,93 @@
M0=${M0:=/mnt/glusterfs/0}; # 0th mount point for FUSE
M1=${M1:=/mnt/glusterfs/1}; # 1st mount point for FUSE
N0=${N0:=/mnt/nfs/0}; # 0th mount point for NFS
N1=${N1:=/mnt/nfs/1}; # 1st mount point for NFS
V0=${V0:=patchy}; # volume name to use in tests
B0=${B0:=/d/backends}; # top level of brick directories
H0=${H0:=`hostname --fqdn`}; # hostname
DEBUG=${DEBUG:=0} # turn on debugging?
CLI="gluster --mode=script";
mkdir -p $B0;
mkdir -p $M0 $M1;
mkdir -p $N0 $N1;
testcnt=`egrep '^[ \t]*(EXPECT|TEST)' $0 | wc -l`;
echo 1..$testcnt
t=1
function dbg()
{
[ "x$DEBUG" = "x0" ] || echo "$*" >&2;
}
function test_header()
{
dbg "=========================";
dbg "TEST $t (line $TESTLINE): $*";
}
function test_footer()
{
RET=$?
if [ $RET -eq 0 ]; then
echo "ok $t";
else
echo "not ok $t";
fi
dbg "RESULT $t: $RET";
t=`expr $t + 1`;
}
function _EXPECT()
{
TESTLINE=$1;
shift;
test_header "$@";
e="$1";
shift;
"$@" | tail -1 | egrep '^'${e}'$' >/dev/null 2>&1;
test_footer;
}
function _TEST()
{
TESTLINE=$1;
shift;
test_header "$@";
eval "$@" >/dev/null 2>&1
test_footer;
}
function cleanup()
{
killall -15 glusterfs glusterfsd glusterd 2>/dev/null || true;
killall -9 glusterfs glusterfsd glusterd 2>/dev/null || true;
rm -rf /var/lib/glusterd/* $B0/* /etc/glusterd/*;
umount -l $M0 2>/dev/null || true;
umount -l $M1 2>/dev/null || true;
umount -l $N0 2>/dev/null || true;
umount -l $N1 2>/dev/null || true;
}
alias EXPECT='_EXPECT $LINENO'
alias TEST='_TEST $LINENO'
shopt -s expand_aliases