summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/basic/cdc.t8
-rw-r--r--tests/basic/pgfid-feat.t36
-rw-r--r--tests/bugs/bug-1058663.c111
-rw-r--r--tests/bugs/bug-1058663.t29
-rw-r--r--tests/bugs/bug-1058797.t45
-rwxr-xr-xtests/encryption/crypt.t87
-rw-r--r--tests/encryption/frag.c328
7 files changed, 639 insertions, 5 deletions
diff --git a/tests/basic/cdc.t b/tests/basic/cdc.t
index 69f39f7d1..70d2171a8 100755
--- a/tests/basic/cdc.t
+++ b/tests/basic/cdc.t
@@ -21,18 +21,16 @@ EXPECT 'off' volinfo_field $V0 'performance.io-cache'
TEST $CLI volume set $V0 performance.quick-read off
EXPECT 'off' volinfo_field $V0 'performance.quick-read'
-TEST $CLI volume set $V0 strict-write-ordering on
+TEST $CLI volume set $V0 performance.strict-write-ordering on
EXPECT 'on' volinfo_field $V0 'performance.strict-write-ordering'
## Turn on cdc xlator by setting network.compression to on
TEST $CLI volume set $V0 network.compression on
EXPECT 'on' volinfo_field $V0 'network.compression'
-EXPECT 'server' volinfo_field $V0 'network.compression.mode'
## Make sure that user cannot change network.compression.mode
## This would break the cdc xlator if allowed!
-TEST $CLI volume set $V0 network.compression.mode client
-EXPECT 'server' volinfo_field $V0 'network.compression.mode'
+TEST ! $CLI volume set $V0 network.compression.mode client
## Turn on network.compression.debug option
## This will dump compressed data onto disk as gzip file
@@ -44,6 +42,7 @@ EXPECT 'on' volinfo_field $V0 'network.compression.debug'
TEST $CLI volume start $V0;
EXPECT 'Started' volinfo_field $V0 'Status';
+sleep 2
## Mount FUSE with caching disabled
TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0;
@@ -121,7 +120,6 @@ TEST umount $M0
## Reset the network.compression options
TEST $CLI volume reset $V0 network.compression.debug
TEST $CLI volume reset $V0 network.compression.min-size
-TEST $CLI volume reset $V0 network.compression.mode
TEST $CLI volume reset $V0 network.compression
## Stop the volume
diff --git a/tests/basic/pgfid-feat.t b/tests/basic/pgfid-feat.t
new file mode 100644
index 000000000..8784cc7bf
--- /dev/null
+++ b/tests/basic/pgfid-feat.t
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+. $(dirname $0)/../volume.rc
+
+cleanup;
+
+function get_ancestry_path() {
+ local path=$1
+ local ancestry=$(getfattr --absolute-names -e text -n glusterfs.ancestry.path "$M0/$path" | grep "^glusterfs.ancestry.path" | cut -d"=" -f2 | tr -d \");
+ echo $ancestry;
+}
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume info;
+
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2,3,4};
+TEST $CLI volume start $V0;
+TEST glusterfs -s $H0 --volfile-id $V0 $M0;
+
+TEST $CLI volume set $V0 build-pgfid on;
+
+TEST mkdir $M0/a;
+TEST touch $M0/a/b;
+
+getfattr -e text -n glusterfs.ancestry.path "$M0/a/b" | grep "^glusterfs.ancestry.path" | cut -d"=" -f2 | tr -d \";
+EXPECT "/a/b" get_ancestry_path "/a/b";
+
+TEST $CLI volume set $V0 build-pgfid off;
+TEST ! getfattr -e text -n "glusterfs.ancestry.path" $M0/a/b;
+
+TEST $CLI volume stop $V0;
+TEST $CLI volume delete $V0;
+
+cleanup;
diff --git a/tests/bugs/bug-1058663.c b/tests/bugs/bug-1058663.c
new file mode 100644
index 000000000..631afecce
--- /dev/null
+++ b/tests/bugs/bug-1058663.c
@@ -0,0 +1,111 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#define FILE_SIZE 1048576
+
+/* number of tests to run */
+#define RUN_LOOP 1000
+
+/* number of SIGBUS before exiting */
+#define MAX_SIGBUS 1
+static int expect_sigbus = 0;
+static int sigbus_received = 0;
+
+/* test for truncate()/seek()/write()/mmap()
+ * There should ne no SIGBUS triggered.
+ */
+void seek_write(char *filename)
+{
+ int fd;
+ uint8_t* map;
+ int i;
+
+ fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+ lseek(fd, FILE_SIZE - 1, SEEK_SET);
+ write(fd, "\xff", 1);
+
+ map = mmap(NULL, FILE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
+ for (i = 0; i < (FILE_SIZE - 1); i++) {
+ if (map[i] != 0) /* should never be true */
+ abort();
+ }
+ munmap(map, FILE_SIZE);
+
+ close(fd);
+}
+
+int read_after_eof(char *filename)
+{
+ int ret = 0;
+ int fd;
+ char* data;
+ uint8_t* map;
+
+ fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+ lseek(fd, FILE_SIZE - 1, SEEK_SET);
+ write(fd, "\xff", 1);
+
+ /* trigger verify that reading after EOF fails */
+ ret = read(fd, data, FILE_SIZE / 2);
+ if (ret != 0)
+ return 1;
+
+ /* map an area of 1 byte after FILE_SIZE */
+ map = mmap(NULL, 1, PROT_READ, MAP_PRIVATE, fd, FILE_SIZE);
+ /* map[0] is an access after EOF, it should trigger SIGBUS */
+ if (map[0] != 0)
+ /* it is expected that we exit before we get here */
+ if (!sigbus_received)
+ return 1;
+ munmap(map, FILE_SIZE);
+
+ close(fd);
+
+ return ret;
+}
+
+/* signal handler for SIGBUS */
+void catch_sigbus(int signum)
+{
+ switch (signum) {
+ case SIGBUS:
+ sigbus_received++;
+ if (!expect_sigbus)
+ exit(EXIT_FAILURE);
+ if (sigbus_received >= MAX_SIGBUS)
+ exit(EXIT_SUCCESS);
+ break;
+ default:
+ printf("Unexpected signal received: %d\n", signum);
+ }
+}
+
+int main(int argc, char** argv)
+{
+ int i = 0;
+
+ if (argc == 1) {
+ printf("Usage: %s <filename>\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ signal(SIGBUS, catch_sigbus);
+
+ /* the next test should not trigger SIGBUS */
+ expect_sigbus = 0;
+ for (i = 0; i < RUN_LOOP; i++) {
+ seek_write(argv[1]);
+ }
+
+ /* the next test should trigger SIGBUS */
+ expect_sigbus = 1;
+ if (read_after_eof(argv[1]))
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/bugs/bug-1058663.t b/tests/bugs/bug-1058663.t
new file mode 100644
index 000000000..5ca348e77
--- /dev/null
+++ b/tests/bugs/bug-1058663.t
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+. $(dirname $0)/../volume.rc
+
+cleanup;
+
+## Start and create a volume
+TEST glusterd;
+TEST pidof glusterd;
+TEST $CLI volume info;
+
+TEST $CLI volume create $V0 $H0:$B0/$V0;
+TEST $CLI volume start $V0;
+
+TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0
+
+# compile the test program and run it
+gcc $(dirname $0)/bug-1058663.c -o $(dirname $0)/bug-1058663;
+TEST $(dirname $0)/bug-1058663 $M0/bug-1058663.bin;
+rm -f $(dirname $0)/M0/bug-1058663.bin;
+
+TEST umount $M0;
+
+TEST $CLI volume stop $V0;
+TEST $CLI volume delete $V0;
+
+cleanup;
+
diff --git a/tests/bugs/bug-1058797.t b/tests/bugs/bug-1058797.t
new file mode 100644
index 000000000..2b80794cf
--- /dev/null
+++ b/tests/bugs/bug-1058797.t
@@ -0,0 +1,45 @@
+#!/bin/bash
+#Test that the setuid bit is healed correctly.
+
+. $(dirname $0)/../include.rc
+. $(dirname $0)/../volume.rc
+
+cleanup;
+#Basic checks
+TEST glusterd
+
+#Create a 1x2 replica volume
+TEST $CLI volume create $V0 replica 2 $H0:$B0/brick{0,1};
+TEST $CLI volume start $V0
+TEST $CLI volume set $V0 cluster.self-heal-daemon off
+
+# FUSE mount;create a file
+TEST glusterfs -s $H0 --volfile-id $V0 $M0
+TEST touch $M0/file
+
+#Kill brick1 and set S_ISUID and S_ISGID bits from mount point
+kill_brick $V0 $H0 $B0/brick1
+TEST chmod +x,+s $M0/file
+
+#Get file permissions from backend brick0 and verify that S_ISUID is indeed set
+file_permissions1=`ls -l $B0/brick0/file | awk '{print $1}'| cut -d. -f1 | cut -d- -f2,3,4,5,6`
+setuid_bit1=`echo $file_permissions1 | cut -b3`
+EXPECT "s" echo $setuid_bit1
+
+#Restart volume and do lookup from mount to trigger heal
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN 20 "1" afr_child_up_status $V0 1
+TEST ls -l $M0/file
+
+#Get file permissions from healed brick1 and verify that S_ISUID is indeed set
+file_permissions2=`ls -l $B0/brick1/file | awk '{print $1}' | cut -d. -f1 | cut -d- -f2,3,4,5,6`
+setuid_bit2=`echo $file_permissions2 | cut -b3`
+EXPECT "s" echo $setuid_bit2
+
+#Also compare the entire permission string,just to be sure
+EXPECT $file_permissions1 echo $file_permissions2
+TEST umount $M0
+TEST $CLI volume stop $V0
+TEST $CLI volume delete $V0;
+
+cleanup;
diff --git a/tests/encryption/crypt.t b/tests/encryption/crypt.t
new file mode 100755
index 000000000..aa46bd429
--- /dev/null
+++ b/tests/encryption/crypt.t
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+. $(dirname $0)/../volume.rc
+
+cleanup;
+
+TEST glusterd
+TEST pidof glusterd
+
+## Create a volume with one brick
+TEST $CLI volume create $V0 $H0:$B0/${V0}1;
+EXPECT "$V0" volinfo_field $V0 'Volume Name';
+EXPECT 'Created' volinfo_field $V0 'Status';
+EXPECT '1' brick_count $V0
+
+## Turn off performance translators
+
+TEST $CLI volume set $V0 performance.quick-read off
+EXPECT 'off' volinfo_field $V0 'performance.quick-read'
+TEST $CLI volume set $V0 performance.write-behind off
+EXPECT 'off' volinfo_field $V0 'performance.write-behind'
+TEST $CLI volume set $V0 performance.open-behind off
+EXPECT 'off' volinfo_field $V0 'performance.open-behind'
+
+## Turn on crypt xlator by setting features.encryption to on
+TEST $CLI volume set $V0 encryption on
+EXPECT 'on' volinfo_field $V0 'features.encryption'
+
+## Specify location of master key
+TEST $CLI volume set $V0 encryption.master-key /tmp/$V0-master-key
+
+## Create a file with master key
+
+echo "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" > /tmp/$V0-master-key
+
+## Start the volume
+TEST $CLI volume start $V0;
+EXPECT 'Started' volinfo_field $V0 'Status';
+
+## Mount the volume
+TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0;
+
+## Testing writev, readv, ftruncate:
+## Create fragmented files and compare them with the reference files
+
+build_tester $(dirname $0)/frag.c
+TEST $(dirname $0)/frag $M0/testfile /tmp/$V0-goodfile 262144 500
+
+## Testing link, unlink, symlink, rename
+
+TEST ln $M0/testfile $M0/testfile-link
+TEST mv $M0/testfile $M0/testfile-renamed
+TEST ln -s $M0/testfile-link $M0/testfile-symlink
+TEST rm -f $M0/testfile-renamed
+
+## Remount the volume
+TEST umount $M0
+TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0;
+
+TEST diff -u $M0/testfile-symlink /tmp/$V0-goodfile
+EXPECT ''
+
+TEST rm -f $M0/testfile-symlink
+TEST rm -f $M0/testfile-link
+
+## Cleanup files
+
+TEST rm -f /tmp/$V0-master-key
+TEST rm -f /tmp/$V0-goodfile
+
+TEST umount $M0
+
+## Reset crypt options
+TEST $CLI volume reset $V0 encryption.block-size
+TEST $CLI volume reset $V0 encryption.data-key-size
+
+## Stop the volume
+TEST $CLI volume stop $V0;
+EXPECT 'Stopped' volinfo_field $V0 'Status';
+
+## Delete the volume
+TEST $CLI volume delete $V0;
+TEST ! $CLI volume info $V0;
+
+TEST rm -rf $(dirname $0)/frag
+cleanup;
diff --git a/tests/encryption/frag.c b/tests/encryption/frag.c
new file mode 100644
index 000000000..86da037c6
--- /dev/null
+++ b/tests/encryption/frag.c
@@ -0,0 +1,328 @@
+/*
+ Copyright (c) 2008-2013 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define MAX_NUM_OPS (1 << 20)
+#define MAX_FILE_SIZE (1 << 30)
+
+typedef enum {
+ READ_OP,
+ WRITE_OP,
+ TRUNC_OP,
+ LAST_OP
+} frag_op;
+
+struct frag_ctx {
+ int test_fd;
+ int good_fd;
+ char *test_buf;
+ char *good_buf;
+ char *content;
+ int max_file_size;
+};
+
+typedef int (*frag_op_t)(struct frag_ctx *ctx, off_t offset, size_t count);
+
+static int doread(int fd, off_t offset, size_t count,
+ char *buf, int max_file_size)
+{
+ int ret = 0;
+ int was_read = 0;
+
+ if (lseek(fd, offset, SEEK_SET) == -1) {
+ perror("lseek failed");
+ return -1;
+ }
+ while (count) {
+ ret = read(fd, buf + offset + was_read, count);
+ if (ret < 0)
+ return -1;
+ if (ret == 0)
+ break;
+ if (ret > count) {
+ fprintf(stderr, "READ: read more than asked\n");
+ return -1;
+ }
+ count -= ret;
+ was_read += ret;
+ }
+ return ret;
+}
+
+static int dowrite(int fd, off_t offset, size_t count, char *buf)
+{
+ int ret;
+
+ ret = lseek(fd, offset, SEEK_SET);
+ if (ret == -1)
+ return ret;
+ return write(fd, buf, count);
+}
+
+static int dotrunc(int fd, off_t offset)
+{
+ int ret;
+
+ ret = ftruncate(fd, offset);
+ if (ret == -1)
+ perror("truncate failed");
+ return ret;
+}
+
+static int prepare_file(char *filename, int *fd, char **buf, int max_file_size)
+{
+ int ret;
+
+ *buf = malloc(max_file_size);
+ if (*buf == NULL) {
+ perror("malloc failed");
+ return -1;
+ }
+ *fd = open(filename, O_CREAT | O_RDWR, S_IRWXU);
+ if (*fd == -1) {
+ perror("open failed");
+ free(*buf);
+ *buf = NULL;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * @offset, @count: random values from [0, max_file_size - 1]
+ */
+static int frag_write(struct frag_ctx *ctx, off_t offset, size_t count)
+{
+ int ret;
+ struct stat test_stbuf;
+ struct stat good_stbuf;
+
+ if (offset + count > ctx->max_file_size)
+ offset = offset / 2;
+ if (offset + count > ctx->max_file_size)
+ count = count / 2;
+
+ if (fstat(ctx->test_fd, &test_stbuf)) {
+ fprintf(stderr, "WRITE: fstat of test file failed\n");
+ return -1;
+ }
+ if (offset > test_stbuf.st_size)
+ printf("writing hole\n");
+
+ ret = dowrite(ctx->test_fd, offset, count, ctx->content);
+ if (ret < 0 || ret != count){
+ fprintf(stderr, "WRITE: failed to write test file\n");
+ return -1;
+ }
+ ret = dowrite(ctx->good_fd, offset, count, ctx->content);
+ if (ret < 0 || ret != count) {
+ fprintf(stderr, "WRITE: failed to write test file\n");
+ return -1;
+ }
+ if (fstat(ctx->test_fd, &test_stbuf)) {
+ fprintf(stderr, "WRITE: fstat of test file failed\n");
+ return -1;
+ }
+ if (fstat(ctx->good_fd, &good_stbuf)) {
+ fprintf(stderr, "WRITE: fstat of good file failed\n");
+ return -1;
+ }
+ if (test_stbuf.st_size != good_stbuf.st_size) {
+ fprintf(stderr,
+ "READ: Bad file size %d (expected %d)\n",
+ (int)test_stbuf.st_size,
+ (int)good_stbuf.st_size);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * @offset, @count: random values from [0, max_file_size - 1]
+ */
+static int frag_read(struct frag_ctx *ctx, off_t offset, size_t count)
+{
+ ssize_t test_ret;
+ ssize_t good_ret;
+
+ test_ret = doread(ctx->test_fd,
+ offset, count, ctx->test_buf, ctx->max_file_size);
+ if (test_ret < 0) {
+ fprintf(stderr, "READ: failed to read test file\n");
+ return -1;
+ }
+ good_ret = doread(ctx->good_fd,
+ offset, count, ctx->good_buf, ctx->max_file_size);
+ if (good_ret < 0) {
+ fprintf(stderr, "READ: failed to read good file\n");
+ return -1;
+ }
+ if (test_ret != good_ret) {
+ fprintf(stderr,
+ "READ: Bad return value %d (expected %d\n)",
+ test_ret, good_ret);
+ return -1;
+ }
+ if (memcmp(ctx->test_buf + offset, ctx->good_buf + offset, good_ret)) {
+ fprintf(stderr, "READ: bad data\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * @offset: random value from [0, max_file_size - 1]
+ */
+static int frag_truncate(struct frag_ctx *ctx,
+ off_t offset, __attribute__((unused))size_t count)
+{
+ int ret;
+ struct stat test_stbuf;
+ struct stat good_stbuf;
+
+ if (fstat(ctx->test_fd, &test_stbuf)) {
+ fprintf(stderr, "TRUNCATE: fstat of test file failed\n");
+ return -1;
+ }
+ if (offset > test_stbuf.st_size)
+ printf("expanding truncate to %d\n", offset);
+ else if (offset < test_stbuf.st_size)
+ printf("shrinking truncate to %d\n", offset);
+ else
+ printf("trivial truncate\n");
+
+ ret = dotrunc(ctx->test_fd, offset);
+ if (ret == -1) {
+ fprintf(stderr, "TRUNCATE: failed for test file\n");
+ return -1;
+ }
+ ret = dotrunc(ctx->good_fd, offset);
+ if (ret == -1) {
+ fprintf(stderr, "TRUNCATE: failed for good file\n");
+ return -1;
+ }
+ if (fstat(ctx->test_fd, &test_stbuf)) {
+ fprintf(stderr, "TRUNCATE: fstat of test file failed\n");
+ return -1;
+ }
+ if (fstat(ctx->good_fd, &good_stbuf)) {
+ fprintf(stderr, "TRUNCATE: fstat of good file failed\n");
+ return -1;
+ }
+ if (test_stbuf.st_size != good_stbuf.st_size) {
+ fprintf(stderr,
+ "TRUNCATE: bad test file size %d (expected %d)\n",
+ test_stbuf.st_size,
+ good_stbuf.st_size);
+ return -1;
+ }
+ return 0;
+}
+
+frag_op_t frag_ops[LAST_OP] = {
+ [READ_OP] = frag_read,
+ [WRITE_OP] = frag_write,
+ [TRUNC_OP] = frag_truncate
+};
+
+static void put_ctx(struct frag_ctx *ctx)
+{
+ if (ctx->test_buf)
+ free(ctx->test_buf);
+ if (ctx->good_buf)
+ free(ctx->good_buf);
+ if (ctx->content)
+ free(ctx->content);
+}
+
+main (int argc, char *argv[])
+{
+ int i;
+ int ret = 0;
+ struct frag_ctx ctx;
+ char *test_filename = NULL;
+ char *good_filename = NULL;
+ int num_ops;
+ int max_file_size;
+
+ memset(&ctx, 0, sizeof(ctx));
+ if (argc != 5) {
+ fprintf(stderr,
+ "usage: %s <test-file-name> <good-file-name> <max-file-size> <number-of-operations>\n",
+ argv[0]);
+ ret = -1;
+ goto exit;
+ }
+ test_filename = argv[1];
+ good_filename = argv[2];
+ max_file_size = atoi(argv[3]);
+ if (max_file_size > MAX_FILE_SIZE)
+ max_file_size = MAX_FILE_SIZE;
+ num_ops = atoi(argv[4]);
+ if (num_ops > MAX_NUM_OPS)
+ num_ops = MAX_NUM_OPS;
+
+ ret = prepare_file(test_filename,
+ &ctx.test_fd, &ctx.test_buf, max_file_size);
+ if (ret)
+ goto exit;
+ ret = prepare_file(good_filename,
+ &ctx.good_fd, &ctx.good_buf, max_file_size);
+ if (ret) {
+ if (close(ctx.test_fd) == -1)
+ perror("close test_buf failed");
+ goto exit;
+ }
+ ctx.content = malloc(max_file_size);
+ if (!ctx.content) {
+ perror("malloc failed");
+ goto close;
+ }
+ ctx.max_file_size = max_file_size;
+ for (i = 0; i < max_file_size; i++)
+ ctx.content[i] = random() % 256;
+
+ for (i = 0; i < num_ops; i++) {
+ ret = frag_ops[random() % LAST_OP](&ctx,
+ random() % max_file_size, /* offset */
+ random() % max_file_size /* count */);
+ if (ret)
+ break;
+ }
+ close:
+ if (close(ctx.test_fd) == -1)
+ perror("close test_fd failed");
+ if (close(ctx.good_fd) == -1)
+ perror("close good_fd failed");
+ exit:
+ put_ctx(&ctx);
+ if (ret)
+ exit(1);
+ exit(0);
+}
+
+/*
+ Local variables:
+ c-indentation-style: "K&R"
+ mode-name: "LC"
+ c-basic-offset: 8
+ tab-width: 8
+ fill-column: 80
+ scroll-step: 1
+ End:
+*/