diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/fcntl_locker.c | 67 | ||||
-rwxr-xr-x | tests/test_bindfs.rb | 41 |
3 files changed, 110 insertions, 1 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index eca8563..66713e2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,9 +1,10 @@ UNAME_S := $(shell uname -s) -noinst_PROGRAMS = readdir_inode utimens_nofollow +noinst_PROGRAMS = readdir_inode utimens_nofollow fcntl_locker readdir_inode_SOURCES = readdir_inode.c utimens_nofollow_SOURCES = utimens_nofollow.c +fcntl_locker_SOURCES = fcntl_locker.c TESTS = test_bindfs.rb SUBDIRS = internals diff --git a/tests/fcntl_locker.c b/tests/fcntl_locker.c new file mode 100644 index 0000000..fa2e9dc --- /dev/null +++ b/tests/fcntl_locker.c @@ -0,0 +1,67 @@ +// Takes two files and exits with 0 if fcntl-locking one fcntl-locks the other. +// If the files don't fcntl-lock each other, returns 1. +// If any other error occurs, returns 2. + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +int main(int argc, const char* argv[]) { + if (argc != 3) { + fprintf(stderr, "expecting exactly two arguments\n"); + return 2; + } + + int fd1 = -1; + int fd2 = -1; + int result = 2; + + fd1 = open(argv[1], O_RDWR); + if (fd1 == -1) { + perror("failed to open the first file"); + goto exit; + } + fd2 = open(argv[2], O_RDWR); + if (fd2 == -1) { + perror("failed to open the second file"); + goto exit; + } + + struct flock lock; + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + if (fcntl(fd1, F_SETLK, &lock) == -1) { + perror("fcntl F_SETLK on the first file failed"); + goto exit; + } + + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + if (fcntl(fd2, F_SETLK, &lock) == -1) { + if (errno == EACCES || errno == EAGAIN) { + result = 0; + goto exit; + } else { + perror("fcntl F_SETLK on the second file failed"); + goto exit; + } + } else { + result = 1; + goto exit; + } + +exit: + close(fd1); + close(fd2); + return result; +} diff --git a/tests/test_bindfs.rb b/tests/test_bindfs.rb index 04c853d..c0ae5dd 100755 --- a/tests/test_bindfs.rb +++ b/tests/test_bindfs.rb @@ -616,6 +616,47 @@ testenv("", :title => "many files in a directory") do assert { Dir.entries('mnt/dir').sort == expected_entries.sort } end +testenv("--enable-lock-forwarding --multithreaded", :title => "lock forwarding") do + File.write('src/file', 'some contents for fcntl lockng') + # (this test passes with an empty file as well, but this way is clearer) + + # flock + File.open('mnt/file') do |f1| + File.open('src/file') do |f2| + assert { f1.flock(File::LOCK_EX | File::LOCK_NB) } + assert { !f2.flock(File::LOCK_EX | File::LOCK_NB) } + assert { f1.flock(File::LOCK_UN) } + + assert { f2.flock(File::LOCK_EX | File::LOCK_NB) } + assert { !f1.flock(File::LOCK_EX | File::LOCK_NB) } + end + assert { f1.flock(File::LOCK_EX | File::LOCK_NB) } + end + + # fcntl locking + system("#{$tests_dir}/fcntl_locker src/file mnt/file") + raise "fcntl lock sharing test failed" unless $?.success? +end + +testenv("--disable-lock-forwarding", :title => "no lock forwarding") do + File.write('src/file', 'some contents for fcntl lockng') + + # flock + File.open('mnt/file') do |f1| + File.open('src/file') do |f2| + assert { f1.flock(File::LOCK_EX | File::LOCK_NB) } + assert { f2.flock(File::LOCK_EX | File::LOCK_NB) } + end + File.open('mnt/file') do |f2| + assert { !f2.flock(File::LOCK_EX | File::LOCK_NB) } + end + end + + # fcntl locking + system("#{$tests_dir}/fcntl_locker src/file mnt/file") + raise "fcntl lock sharing test failed" unless $?.exitstatus == 1 +end + # Issue #37 root_testenv("--enable-ioctl", :title => "append-only ioctl") do touch('mnt/file') |