From 2010fb2bc620e6f66ed769b140d92e1d94da1439 Mon Sep 17 00:00:00 2001 From: Edward Shishkin Date: Fri, 13 Dec 2013 21:17:44 +0100 Subject: Added test case for crypt translator Change-Id: I7a28a1285c19c3279c2f71e9d9914cf14c761858 BUG: 1030058 Signed-off-by: Edward Shishkin Reviewed-on: http://review.gluster.org/6504 Tested-by: Gluster Build System Reviewed-by: Anand Avati --- tests/encryption/crypt.t | 87 +++++++++++++ tests/encryption/frag.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 415 insertions(+) create mode 100755 tests/encryption/crypt.t create mode 100644 tests/encryption/frag.c 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. + 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 +#include +#include +#include +#include +#include +#include +#include + +#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 \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: +*/ -- cgit