diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/odirect_read.c | 59 | ||||
-rw-r--r-- | tests/odirect_write.c | 78 | ||||
-rwxr-xr-x | tests/test_bindfs.rb | 22 |
4 files changed, 162 insertions, 1 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 0a52108..742899b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,10 +4,12 @@ UNAME_S := $(shell uname -s) AM_CPPFLAGS = ${my_CPPFLAGS} AM_CFLAGS = ${my_CFLAGS} -noinst_PROGRAMS = readdir_inode utimens_nofollow fcntl_locker test_dir_rewind +noinst_PROGRAMS = readdir_inode utimens_nofollow fcntl_locker odirect_read odirect_write test_dir_rewind readdir_inode_SOURCES = readdir_inode.c utimens_nofollow_SOURCES = utimens_nofollow.c fcntl_locker_SOURCES = fcntl_locker.c +odirect_read_SOURCES = odirect_read.c +odirect_write_SOURCES = odirect_write.c test_dir_rewind_SOURCES = test_dir_rewind.c TESTS = test_bindfs.rb diff --git a/tests/odirect_read.c b/tests/odirect_read.c new file mode 100644 index 0000000..8fc746b --- /dev/null +++ b/tests/odirect_read.c @@ -0,0 +1,59 @@ +#ifdef __linux__ + +#include <stdio.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef O_DIRECT +#define O_DIRECT 00040000 /* direct disk access hint */ +#endif + +int main(int argc, char** argv) { + if (argc != 2) { + fprintf(stderr, "Expected 1 argument: the file to read.\n"); + return 1; + } + + int fd = open(argv[1], O_RDONLY | O_DIRECT); + if (fd == -1) { + perror("failed to open file"); + return 1; + } + + const size_t buf_size = 4096; + unsigned char* buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); + if (buf == MAP_FAILED) { + perror("mmap failed"); + return 1; + } + + while (1) { + ssize_t amt_read = read(fd, buf, buf_size); + if (amt_read == 0) { + break; + } + if (amt_read == -1) { + perror("failed to read file"); + return 1; + } + fwrite(buf, 1, amt_read, stdout); + fflush(stdout); + } + + return 0; +} + +#else // __linux__ + +#include <stdio.h> + +int main() { + fprintf(stderr, "Not supported on this platform.\n"); + return 1; +} + +#endif // __linux__ diff --git a/tests/odirect_write.c b/tests/odirect_write.c new file mode 100644 index 0000000..1376a51 --- /dev/null +++ b/tests/odirect_write.c @@ -0,0 +1,78 @@ +#ifdef __linux__ + +#include <stdio.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef O_DIRECT +#define O_DIRECT 00040000 /* direct disk access hint */ +#endif + +int main(int argc, char** argv) { + if (argc != 2) { + fprintf(stderr, "Expected 1 argument: the file to read.\n"); + return 1; + } + + int fd = open(argv[1], O_WRONLY | O_CREAT | O_DIRECT, 0644); + if (fd == -1) { + perror("failed to open file"); + return 1; + } + + const size_t buf_size = 4096; + unsigned char* buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); + if (buf == MAP_FAILED) { + perror("mmap failed"); + return 1; + } + + size_t total_size = 0; + while (1) { + if (feof(stdin)) { + break; + } + + memset(buf, 0, buf_size); + size_t amt_read = fread(buf, 1, buf_size, stdin); + if (ferror(stdin)) { + perror("failed to read stdin"); + return 1; + } + if (amt_read == 0) { + continue; + } + + total_size += amt_read; + + ssize_t res = write(fd, buf, buf_size); + if (res == -1) { + perror("failed to write"); + return 1; + } + if (res != buf_size) { + // Too lazy to write a loop here unless it turns out to be necessary. + fprintf(stderr, "Failed to write exactly %ld bytes", amt_read); + } + } + + munmap(buf, buf_size); + + return 0; +} + +#else // __linux__ + +#include <stdio.h> + +int main() { + fprintf(stderr, "Not supported on this platform.\n"); + return 1; +} + +#endif // __linux__ diff --git a/tests/test_bindfs.rb b/tests/test_bindfs.rb index c5d41f6..9e5d381 100755 --- a/tests/test_bindfs.rb +++ b/tests/test_bindfs.rb @@ -775,6 +775,28 @@ if `uname`.strip == 'Linux' && end end +# Pull Request #74 +if `uname`.strip == 'Linux' + def odirect_data + ('abc' * 10000)[0...8192] + end + + testenv("", :title => "O_DIRECT reads") do + File.write("src/f", odirect_data) + read_data = `#{$tests_dir}/odirect_read mnt/f` + assert { $?.success? } + assert { read_data == odirect_data } + end + + testenv("", :title => "O_DIRECT writes") do + IO.popen("#{$tests_dir}/odirect_write mnt/f", "w") do |pipe| + pipe.write(odirect_data) + end + assert { $?.success? } + assert { File.read("src/f") == odirect_data } + end +end + if `uname`.strip != 'FreeBSD' # -o dev is not supported on FreeBSD root_testenv("-odev") do system("mknod mnt/zero c 1 5") |