On Tue, May 15, 2018 at 7:25 AM, Waldek Kozaczuk <[email protected]> wrote:
> Nadav, > > Thanks for applying this patch. > > It would be nice to add './script/build check fs=rofs' to one of the > Jenkins job. What do you think? > I'll leave this to Avi's consideration, he's in charge of the Jenkins scripts. One question, though - are we should that it's fine to change the "fs=" without a "make clean"? E.g., would ./script/build check ./script/build check fs=rofs ./script/build check Really build a ZFS build, then a ROFS build, then again a ZFS build, even though the only thing changed is the command line? If this doesn't work, then Jenkins won't work properly (I believe it doesn't bother with a "make clean" every time). > > Waldek > > On Sunday, May 13, 2018 at 5:44:29 PM UTC-4, Bot Droid wrote: >> >> From: Waldemar Kozaczuk <[email protected]> >> Committer: Nadav Har'El <[email protected]> >> Branch: master >> >> Enhanced tests to allows testing rofs/ramfs image >> >> This patch adds new unit tests and modifies existing ones to make >> it possible to test images with read-only filesystem mounted >> at root and ramfs mounted at /tmp. >> >> Following changes are part of this patch: >> >> - modified tests module makefile to divide all tests >> into three groups - zfs specific, rofs/ramfs specific and >> remaining ones applicable to any filesystem; some of the tests >> are filtered out temporarily of rofs/ramfs image due to >> bugs/shortcomings >> of ramfs filesystem which are described in more detail in makefile >> itself >> >> - added new test tst-concurrent-read.cc to verify concurrent reads; the >> test >> can be compiled to test either read/write (zfs) or read-only >> filesystem >> (rofs) >> >> - enhanced tst-chdir.cc, tst-readdir.cc and tst-symlink.cc tests >> by adding READ_ONLY_FS macro parameter to test both read/write (zfs) >> and read-only file system (rofs); these 3 tests and >> tst-concurrent-read.cc >> are part of rofs/ramfs image compiled in both read/write and read-only >> mode (for example tst-chdir.so and tst-chdir-rofs.so) >> >> - modified tst-fallocate.cc and tst-fs-link.cc to use /tmp directory >> instead of /usr >> >> In order to build rofs test image and execute following command >> can be used: >> >> ./script/build check fs=rofs >> >> By default test image is built with zfs filesystem mounted. >> >> Signed-off-by: Waldemar Kozaczuk <[email protected]> >> Message-Id: <[email protected]> >> >> --- >> diff --git a/modules/tests/Makefile b/modules/tests/Makefile >> --- a/modules/tests/Makefile >> +++ b/modules/tests/Makefile >> @@ -4,6 +4,7 @@ module: usr.manifest build_all_tests >> src := $(OSV_BASE) >> out := $(OSV_BUILD_PATH) >> arch := $(ARCH) >> +fs_type := $(fs_type) >> # TODO: consider setting $(out) not to OSV_BUILD_PATH but to >> ./build/$ARCH. >> # TODO: need to set up CXX, etc., for cross compilation, as in the main >> # Makefile... >> @@ -50,23 +51,49 @@ $(out)/%.o: $(src)/%.cc >> $(out)/%.o: $(src)/%.c >> $(makedir) >> $(call quiet, $(CC) $(CFLAGS) -c -o $@ $< , CC $*.c) >> +$(out)/tests/rofs/%.o: $(src)/tests/%.cc >> + $(makedir) >> + $(call quiet, $(CXX) $(CXXFLAGS) -DREAD_ONLY_FS -c -o $@ $<, CXX >> $*.cc) >> +$(out)/tests/rofs/%.o: $(src)/tests/%.c >> + $(makedir) >> + $(call quiet, $(CC) $(CFLAGS) -DREAD_ONLY_FS -c -o $@ $< , CC >> $*.c) >> $(out)/%.so: $(out)/%.o >> $(call quiet, $(CXX) $(CXXFLAGS) -shared -o $@ $< $(LIBS), LD >> $*.so) >> >> +# The rofs test image mounts /tmp as ramfs and 4 tests that exercise >> file >> system >> +# fail due to some unresolved bugs or other shortcomings of the ramfs >> implementation >> +# and are temporarily removed from the rofs-only-tests list. The tests >> tst-readdir.so >> +# and tst-rename.so would fail until the issue #68 is fixed. Similarly >> +# tst-fs-link.so do not pass due to lack of hard links support in the >> ramfs >> +# implementation. Lastly tst-fallocate.so also does not work with ramfs >> >> due to >> +# the shortcomings in ramfs implementation of statfs that does not >> report >> free/used >> +# blocks adequately. >> +# >> +# These 4 tests are compiled from the same source files but passed in >> READ_ONLY_FS >> +# to switch relevant logic in those tests to exercise scenarios >> applicable >> +# to read-only filesystem >> +rofs-only-tests := rofs/tst-chdir.so rofs/tst-symlink.so >> rofs/tst-readdir.so \ >> + rofs/tst-concurrent-read.so >> + >> +zfs-only-tests := tst-readdir.so tst-fallocate.so tst-fs-link.so \ >> + tst-concurrent-read.so >> + >> +specific-fs-tests := $($(fs_type)-only-tests) >> + >> tests := tst-pthread.so misc-ramdisk.so tst-vblk.so tst-bsd-evh.so \ >> misc-bsd-callout.so tst-bsd-kthread.so tst-bsd-taskqueue.so \ >> tst-fpu.so tst-preempt.so tst-tracepoint.so tst-hub.so \ >> misc-console.so misc-leak.so misc-readbench.so >> misc-mmap-anon-perf.so \ >> tst-mmap-file.so misc-mmap-big-file.so tst-mmap.so tst-huge.so >> \ >> tst-elf-permissions.so misc-mutex.so misc-sockets.so >> tst-condvar.so \ >> tst-queue-mpsc.so tst-af-local.so tst-pipe.so tst-yield.so \ >> - misc-ctxsw.so tst-readdir.so tst-read.so tst-symlink.so >> tst-openat.so \ >> + misc-ctxsw.so tst-read.so tst-symlink.so tst-openat.so \ >> tst-eventfd.so tst-remove.so misc-wake.so tst-epoll.so >> misc-lfring.so \ >> misc-fsx.so tst-sleep.so tst-resolve.so tst-except.so \ >> misc-tcp-sendonly.so tst-tcp-nbwrite.so misc-tcp-hash-srv.so \ >> misc-loadbalance.so misc-scheduler.so tst-console.so tst-app.so >> \ >> misc-setpriority.so misc-timeslice.so misc-tls.so misc-gtod.so >> \ >> - tst-dns-resolver.so tst-fs-link.so tst-kill.so tst-truncate.so \ >> + tst-dns-resolver.so tst-kill.so tst-truncate.so \ >> misc-panic.so tst-utimes.so tst-utimensat.so tst-futimesat.so \ >> misc-tcp.so tst-strerror_r.so misc-random.so misc-urandom.so \ >> tst-commands.so tst-threadcomplete.so tst-timerfd.so \ >> @@ -75,7 +102,7 @@ tests := tst-pthread.so misc-ramdisk.so tst-vblk.so >> tst-bsd-evh.so \ >> tst-concurrent-init.so tst-ring-spsc-wraparound.so tst-shm.so \ >> tst-align.so tst-cxxlocale.so misc-tcp-close-without-reading.so >> \ >> tst-sigwait.so tst-sampler.so misc-malloc.so misc-memcpy.so \ >> - misc-free-perf.so tst-fallocate.so misc-printf.so >> tst-hostname.so \ >> + misc-free-perf.so misc-printf.so tst-hostname.so \ >> tst-sendfile.so misc-lock-perf.so tst-uio.so tst-printf.so \ >> tst-pthread-affinity.so tst-pthread-tsd.so tst-thread-local.so >> \ >> tst-zfs-mount.so tst-regex.so tst-tcp-siocoutq.so \ >> @@ -111,7 +138,7 @@ $(out)/tests/tst-tls.so: \ >> $(makedir) >> $(call quiet, cd $(out); $(CXX) $(CXXFLAGS) -shared -o $@ $< >> tests/libtls.so, CXX tst-tls.so) >> >> -boost-tests := tst-rename.so tst-vfs.so tst-libc-locking.so >> misc-fs-stress.so \ >> +boost-tests := tst-vfs.so tst-libc-locking.so misc-fs-stress.so \ >> misc-bdev-write.so misc-bdev-wlatency.so misc-bdev-rw.so \ >> tst-promise.so tst-dlfcn.so tst-stat.so tst-wait-for.so \ >> tst-bsd-tcp1.so tst-bsd-tcp1-zsnd.so tst-bsd-tcp1-zrcv.so \ >> @@ -120,6 +147,12 @@ boost-tests := tst-rename.so tst-vfs.so >> tst-libc-locking.so misc-fs-stress.so \ >> tst-rcu-hashtable.so tst-unordered-ring-mpsc.so \ >> tst-seek.so >> >> +rofs-only-boost-tests := >> + >> +zfs-only-boost-tests := tst-rename.so >> + >> +boost-tests += $($(fs_type)-only-boost-tests) >> + >> BOOSTLIBS=$(src)/external/$(ARCH)/misc.bin/usr/lib64 >> $(boost-tests:%=$(out)/tests/%): LIBS += \ >> $(BOOSTLIBS)/libboost_unit_test_framework.so \ >> @@ -157,15 +190,20 @@ $(solaris-tests:%=$(out)/tests/%): COMMON+= \ >> -I $(src)/bsd/sys -I $(src)/bsd -I $(src)/bsd/$(ARCH) >> >> all_tests := $(tests:%=tests/%) >> +all_tests += $(specific-fs-tests:%=tests/%) >> >> build_all_tests: $(all_tests:%=$(out)/%) >> -.PHONY: build_all_tests >> +.PHONY: build_all_tests clean >> >> # Automatically generate usr.manifest which includes all tests. >> -usr.manifest: $(lastword $(MAKEFILE_LIST)) usr.manifest.skel >> +usr.manifest: $(lastword $(MAKEFILE_LIST)) usr.manifest.skel FORCE >> @echo " generating modules/tests/usr.manifest" >> @cat [email protected] > $@ >> - @echo $(all_tests) | tr ' ' '\n' | awk '{print "/" $$0 ": ./" >> $$0}' >> $@ >> + @echo $(all_tests) | tr ' ' '\n' | grep -v >> "tests/rofs/tst-.*.so" | >> awk '{print "/" $$0 ": ./" $$0}' >> $@ >> + @echo $(all_tests) | tr ' ' '\n' | grep "tests/rofs/tst-.*.so" | >> >> sed 's/\.so//' | awk 'BEGIN { FS = "/" } ; { print "/tests/" >> $$3 "-rofs.so: ./tests/" $$2 "/" $$3 ".so"}' >> $@ >> + ./create_static.sh $(out) $(fs_type) >> +.PHONY: FORCE >> +FORCE: >> >> clean: >> -rm -f usr.manifest >> diff --git a/modules/tests/create_static.sh >> b/modules/tests/create_static.sh >> --- a/modules/tests/create_static.sh >> +++ b/modules/tests/create_static.sh >> @@ -0,0 +1,36 @@ >> +#!/bin/bash >> + >> +THIS_PATH=$(readlink -f $0) >> +THIS_DIRECTORY=$(dirname ${THIS_PATH}) >> +OUT=$1 >> +FS=${2-zfs} >> + >> +#Clean the directory >> +rm -rf ${OUT}/tests/static >> + >> +if [ ${FS} = "rofs" ] >> +then >> + mkdir -p ${OUT}/tests/static/rofs/tst-readdir-empty >> + mkdir -p ${OUT}/tests/static/rofs/tst-readdir >> + touch ${OUT}/tests/static/rofs/tst-readdir/aaa >> + >> + mkdir -p ${OUT}/tests/static/rofs/tst-chdir >> + touch ${OUT}/tests/static/rofs/tst-chdir/f >> + >> + mkdir -p ${OUT}/tests/static/rofs/tst-symlink >> + touch ${OUT}/tests/static/rofs/tst-symlink/f1 >> + cd ${OUT}/tests/static/rofs/tst-symlink && ln -s f1 f2_AAA >> + >> + echo '/rofs/tst-readdir-empty: >> ./tests/static/rofs/tst-readdir-empty' >> >> >> ${THIS_DIRECTORY}/usr.manifest >> + echo '/rofs/tst-chdir/f: ./tests/static/rofs/tst-chdir/f' >> >> ${THIS_DIRECTORY}/usr.manifest >> + echo '/rofs/tst-readdir/aaa: ./tests/static/rofs/tst-readdir/aaa' >> >> >> ${THIS_DIRECTORY}/usr.manifest >> + echo '/rofs/tst-symlink/f1: ./tests/static/rofs/tst-symlink/f1' >> >> >> ${THIS_DIRECTORY}/usr.manifest >> + echo '/rofs/tst-symlink/f2_AAA: ->/rofs/tst-symlink/f1' >> >> ${THIS_DIRECTORY}/usr.manifest >> + >> + #This file is around 700K so it is a good test sample for the >> concurrent >> test >> + echo '/rofs/mmap-file-test1: ./core/spinlock.o' >> >> ${THIS_DIRECTORY}/usr.manifest >> + echo '/rofs/mmap-file-test2: ./core/spinlock.o' >> >> ${THIS_DIRECTORY}/usr.manifest >> +else >> + echo '/tmp/mmap-file-test1: ./core/spinlock.o' >> >> ${THIS_DIRECTORY}/usr.manifest >> + echo '/tmp/mmap-file-test2: ./core/spinlock.o' >> >> ${THIS_DIRECTORY}/usr.manifest >> +fi >> diff --git a/scripts/build b/scripts/build >> --- a/scripts/build >> +++ b/scripts/build >> @@ -153,7 +153,7 @@ if [ "$export" == "selected" ] >> then >> no_required_arg="--no-required" >> fi >> -jdkbase=$jdkbase ARCH=$arch mode=$mode OSV_BASE=$SRC >> OSV_BUILD_PATH=$OSV_BUILD_PATH scripts/module.py $j_arg build -c $modules >> >> $usrskel_arg $no_required_arg >> +fs_type=$fs_type jdkbase=$jdkbase ARCH=$arch mode=$mode OSV_BASE=$SRC >> OSV_BUILD_PATH=$OSV_BUILD_PATH scripts/module.py $j_arg build -c $modules >> >> $usrskel_arg $no_required_arg >> >> bootfs_manifest=$manifest make "${args[@]}" | tee -a build.out >> # check exit status of make >> diff --git a/tests/tst-chdir.cc b/tests/tst-chdir.cc >> --- a/tests/tst-chdir.cc >> +++ b/tests/tst-chdir.cc >> @@ -15,6 +15,12 @@ >> >> #include <iostream> >> >> +#if defined(READ_ONLY_FS) >> +#define SUBDIR "rofs" >> +#else >> +#define SUBDIR "tmp" >> +#endif >> + >> int tests = 0, fails = 0; >> >> #define expect(actual, expected) do_expect(actual, expected, #actual, >> #expected, __FILE__, __LINE__) >> @@ -37,36 +43,50 @@ bool do_expect(T actual, T expected, const char >> *actuals, const char *expecteds, >> >> int main(int argc, char **argv) >> { >> +#if defined(READ_ONLY_FS) >> + expect_errno(mkdir("/rofs/tst-chdir-non-existent", 0777), EROFS); >> +#else >> expect(mkdir("/tmp/tst-chdir", 0777), 0); >> - >> +#endif >> /********* test chdir() **************/ >> // chdir to non-existant subdirectory returns ENOENT: >> - expect_errno(chdir("/tmp/tst-chdir/x"), ENOENT); >> + expect_errno(chdir("/" SUBDIR "/tst-chdir/x"), ENOENT); >> // chdir to path with non-existant middle component returns >> ENOTDIR: >> - expect_errno(chdir("/tmp/tst-chdir/x/y"), ENOENT); >> + expect_errno(chdir("/" SUBDIR " /tst-chdir/x/y"), ENOENT); >> // chdir to a non-directory file, or if a non-directory is part of >> the >> // path, fails with ENOTDIR: >> +#if defined(READ_ONLY_FS) >> + expect_errno(mknod("/rofs/tst-chdir/f-nonexistent", 0777|S_IFREG, >> 0), >> EROFS); >> +#else >> expect(mknod("/tmp/tst-chdir/f", 0777|S_IFREG, 0), 0); >> - expect_errno(chdir("/tmp/tst-chdir/f"), ENOTDIR); >> - expect_errno(chdir("/tmp/tst-chdir/f/g"), ENOTDIR); >> +#endif >> + expect_errno(chdir("/" SUBDIR "/tst-chdir/f"), ENOTDIR); >> + expect_errno(chdir("/" SUBDIR "/tst-chdir/f/g"), ENOTDIR); >> +#if defined(READ_ONLY_FS) >> + expect_errno(unlink("/rofs/tst-chdir/f"), EROFS); >> +#else >> expect(unlink("/tmp/tst-chdir/f"), 0); >> +#endif >> // chdir to existing directory succeeds: >> expect(chdir("/"), 0); >> - expect(chdir("/tmp"), 0); >> - expect(chdir("/tmp/tst-chdir"), 0); >> - expect(chdir("/tmp/tst-chdir/"), 0); >> + expect(chdir("/" SUBDIR), 0); >> + expect(chdir("/" SUBDIR "/tst-chdir"), 0); >> + expect(chdir("/" SUBDIR "/tst-chdir/"), 0); >> expect(chdir("/"), 0); >> // chdir actually "works" (changes the return value of getcwd) >> char buf[1024]; >> - expect(chdir("/tmp/tst-chdir"), 0); >> + expect(chdir("/" SUBDIR "/tst-chdir"), 0); >> getcwd(buf, sizeof(buf)); >> - expect(strcmp(buf, "/tmp/tst-chdir"), 0); >> + expect(strcmp(buf, "/" SUBDIR "/tst-chdir"), 0); >> expect(chdir("/"), 0); >> >> - >> +#if defined(READ_ONLY_FS) >> + expect_errno(rmdir("/rofs/tst-chdir"), ENOTEMPTY); >> +#else >> // Finally remove the temporary directory (assumes the above left >> // nothing in it) >> expect(rmdir("/tmp/tst-chdir"), 0); >> +#endif >> >> std::cout << "SUMMARY: " << tests << " tests, " << fails << " >> failures\n"; >> return fails == 0 ? 0 : 1; >> diff --git a/tests/tst-concurrent-read.cc b/tests/tst-concurrent-read.cc >> --- a/tests/tst-concurrent-read.cc >> +++ b/tests/tst-concurrent-read.cc >> @@ -0,0 +1,104 @@ >> +#include <stdio.h> >> +#include <string.h> >> +#include <sys/mman.h> >> +#include <sys/stat.h> >> +#include <fcntl.h> >> +#include <unistd.h> >> +#include <stdlib.h> >> +#include <time.h> >> + >> +#include <iostream> >> +#include <thread> >> +#include <vector> >> +#include <atomic> >> + >> +#if defined(READ_ONLY_FS) >> +#define SUBDIR "rofs" >> +#else >> +#define SUBDIR "tmp" >> +#endif >> + >> +int tests = 0, fails = 0; >> + >> +using namespace std; >> + >> +#define expect(actual, expected) do_expect(actual, expected, #actual, >> #expected, __FILE__, __LINE__) >> +template<typename T> >> +bool do_expect(T actual, T expected, const char *actuals, const char >> *expecteds, const char *file, int line) >> +{ >> + ++tests; >> + if (actual != expected) { >> + fails++; >> + cout << "FAIL: " << file << ":" << line << ": For " << actuals >> << >> + ", expected " << expecteds << ", saw " << actual >> << ".\n"; >> + return false; >> + } >> + return true; >> +} >> + >> +int main() >> +{ >> + srand (time(NULL)); >> + // >> + // First read first file using mmap >> + string file_1("/" SUBDIR "/mmap-file-test1"); >> + int fd1 = open(file_1.c_str(), O_RDONLY, 0666); >> + expect(fd1 >= 0, true ); >> + >> + struct stat sb; >> + if (fstat (fd1, &sb) == -1) { >> + perror ("fstat"); >> + return 1; >> + } >> + >> + if (!S_ISREG (sb.st_mode)) { >> + cerr << file_1 << " is not a file\n"; >> + return 1; >> + } >> + >> + off_t length = sb.st_size; >> + void *address = mmap(0, length, PROT_READ, MAP_PRIVATE, fd1, 0); >> + if (address == MAP_FAILED) { >> + return 1; >> + } >> + >> + string file_2("/" SUBDIR "/mmap-file-test2"); >> + int fd2 = open(file_2.c_str(), O_RDONLY, 0666); >> + expect(fd2 >= 0, true ); >> + >> + vector<thread> readers; >> + >> + int thread_count = 10, reads_count = 100; >> + atomic<long> identical_count(0); >> + for(int i = 0; i < thread_count; i++) { >> + >> readers.emplace_back(thread([i,reads_count,fd2,length,address,&identical_count]{ >> >> + unsigned char buffer[4096]; >> + for(int step = 0; step < reads_count; step++) { >> + off_t offset = rand() % length; >> + size_t amount = min(length - offset, 4096l); >> + >> + int ret = pread(fd2, buffer, amount, offset); >> + expect(ret > 0, true); >> + if( ret > 0 ) { >> + auto is_identical = memcmp(buffer, >> static_cast<unsigned char*>(address) + offset, amount) == 0 ? 1 : 0; >> + identical_count += is_identical; >> + } >> + else { >> + cout << "[" << i << "] FAILED to read " << amount << >> " >> bytes at " << offset << "\n"; >> + } >> + } >> + })); >> + } >> + >> + for(auto &t : readers) { >> + t.join(); >> + } >> + >> + cout << "Identical count " << identical_count.load() << endl; >> + >> + munmap(address,length); >> + close(fd1); >> + close(fd2); >> + >> + expect(identical_count.load(),(long)(thread_count * reads_count)); >> +} >> diff --git a/tests/tst-fallocate.cc b/tests/tst-fallocate.cc >> --- a/tests/tst-fallocate.cc >> +++ b/tests/tst-fallocate.cc >> @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) >> struct stat st; >> struct statfs fs; >> >> - strcpy(path, "/usr/tst-fallocateXXXXXX"); >> + strcpy(path, "/tmp/tst-fallocateXXXXXX"); >> mktemp(path); >> >> // Create a temporary file that's used in testing. >> diff --git a/tests/tst-fs-link.cc b/tests/tst-fs-link.cc >> --- a/tests/tst-fs-link.cc >> +++ b/tests/tst-fs-link.cc >> @@ -32,8 +32,8 @@ extern "C" int namei(char *, struct dentry **); >> static int check_vnode_duplicity(void) >> { >> int err = 0; >> - char oldpath[64] = "/usr/tst-fs-linkXXXXXX"; >> - char newpath[64] = "/usr/tst-fs-linkXXXXXX"; >> + char oldpath[64] = "/tmp/tst-fs-linkXXXXXX"; >> + char newpath[64] = "/tmp/tst-fs-linkXXXXXX"; >> struct dentry *olddp, *newdp; >> >> mktemp(oldpath); >> @@ -91,10 +91,10 @@ int main(int argc, char *argv[]) >> newpath = argv[2]; >> } else { >> >> - strcpy(oldp, "/usr/tst-fs-linkXXXXXX"); >> + strcpy(oldp, "/tmp/tst-fs-linkXXXXXX"); >> mktemp(oldp); >> >> - strcpy(newp, "/usr/tst-fs-linkXXXXXX"); >> + strcpy(newp, "/tmp/tst-fs-linkXXXXXX"); >> mktemp(newp); >> >> oldpath = oldp; >> diff --git a/tests/tst-readdir.cc b/tests/tst-readdir.cc >> --- a/tests/tst-readdir.cc >> +++ b/tests/tst-readdir.cc >> @@ -13,22 +13,32 @@ >> >> #include <osv/debug.hh> >> >> +#if defined(READ_ONLY_FS) >> +#define SUBDIR "rofs" >> +#else >> +#define SUBDIR "tmp" >> +#endif >> + >> int tests = 0, fails = 0; >> >> static void report(bool ok, const char* msg) >> { >> ++tests; >> fails += !ok; >> - debug("%s: %s\n", (ok ? "PASS" : "FAIL"), msg); >> + printf("%s: %s\n", (ok ? "PASS" : "FAIL"), msg); >> } >> >> int main(int argc, char **argv) >> { >> debug("Testing readdir() and related functions\n"); >> - report(mkdir("/tmp/tst-readdir", 0777) == 0, "mkdir"); >> +#if defined(READ_ONLY_FS) >> + report(mkdir("/rofs/tst-readdir-empty2", 0777) == -1 && errno == >> EROFS, "mkdir"); >> +#else >> + report(mkdir("/tmp/tst-readdir-empty", 0777) == 0, "mkdir empty"); >> +#endif >> >> // test readdir() on empty directory >> - DIR *dir = opendir("/tmp/tst-readdir"); >> + DIR *dir = opendir("/" SUBDIR "/tst-readdir-empty"); >> report(dir != NULL, "opendir"); >> struct dirent *ent; >> ent = readdir(dir); >> @@ -43,11 +53,15 @@ int main(int argc, char **argv) >> report(iret == 0, "closedir"); >> >> // test readdir() on directory with one file >> - int fd; >> - fd=creat("/tmp/tst-readdir/aaa", 0777); >> +#if defined(READ_ONLY_FS) >> + report(creat("/rofs/tst-readdir/non-existent", 0777) < 0 && errno >> == >> EROFS, "creat"); >> +#else >> + report(mkdir("/tmp/tst-readdir", 0777) == 0, "mkdir empty"); >> + int fd=creat("/tmp/tst-readdir/aaa", 0777); >> report(fd>=0, "creat"); >> close(fd); >> - dir = opendir("/tmp/tst-readdir"); >> +#endif >> + dir = opendir("/" SUBDIR "/tst-readdir"); >> report(dir != NULL, "opendir"); >> ent = readdir(dir); >> report(ent != NULL, "readdir"); >> @@ -64,7 +78,7 @@ int main(int argc, char **argv) >> report(iret == 0, "closedir"); >> >> // test readdir_r() on directory with one file >> - dir = opendir("/tmp/tst-readdir"); >> + dir = opendir("/" SUBDIR "/tst-readdir"); >> report(dir != NULL, "opendir"); >> ent = (struct dirent *)malloc(4096); >> struct dirent *r; >> @@ -80,7 +94,7 @@ int main(int argc, char **argv) >> free(ent); >> >> // test rewinddir(), still on a directory with one file >> - dir = opendir("/tmp/tst-readdir"); >> + dir = opendir("/" SUBDIR "/tst-readdir"); >> report(dir != NULL, "opendir"); >> ent = (struct dirent *)malloc(4096); >> report(readdir_r(dir, ent, &r)==0 && r!=NULL, "readdir_r"); >> @@ -106,7 +120,7 @@ int main(int argc, char **argv) >> free(ent); >> >> // test telldir(), seekdir() >> - dir = opendir("/tmp/tst-readdir"); >> + dir = opendir("/" SUBDIR "/tst-readdir"); >> report(dir != NULL, "opendir"); >> ent = (struct dirent *)malloc(4096); >> report(readdir_r(dir, ent, &r)==0 && r!=NULL, "readdir_r"); >> @@ -128,6 +142,11 @@ int main(int argc, char **argv) >> report(iret == 0, "closedir"); >> free(ent); >> >> +#if defined(READ_ONLY_FS) >> + report(unlink("/rofs/tst-readdir/aaa")==-1 && errno == EROFS, >> "unlink >> aaa"); >> + report(rmdir("/rofs/tst-readdir")==-1 && errno == ENOTEMPTY, >> "rmdir"); >> + report(mknod("/rofs/tst-readdir/b", 0777|S_IFREG, 0) == -1 && errno >> == >> EROFS, "mknod"); >> +#else >> // clean up the temporary directory we created with one file. >> report(unlink("/tmp/tst-readdir/aaa")==0, "unlink aaa"); >> report(rmdir("/tmp/tst-readdir")==0, "rmdir"); >> @@ -192,9 +211,10 @@ int main(int argc, char **argv) >> report(unlink("/tmp/tst-readdir/c")==0, "unlink"); >> report(unlink("/tmp/tst-readdir/d")==0, "unlink"); >> report(rmdir("/tmp/tst-readdir")==0, "rmdir"); >> + report(rmdir("/tmp/tst-readdir-empty")==0, "rmdir empty"); >> +#endif >> >> - >> - debug("SUMMARY: %d tests, %d failures\n", tests, fails); >> + printf("SUMMARY: %d tests, %d failures\n", tests, fails); >> return fails == 0 ? 0 : 1; >> } >> >> diff --git a/tests/tst-symlink.cc b/tests/tst-symlink.cc >> --- a/tests/tst-symlink.cc >> +++ b/tests/tst-symlink.cc >> @@ -13,37 +13,47 @@ >> #include <unistd.h> >> #include <limits.h> >> #include <stdlib.h> >> +#include <iostream> >> >> #define debug printf >> >> -#define TESTDIR "/tmp" >> +#if defined(READ_ONLY_FS) >> +#define TESTDIR "/rofs/tst-symlink" >> +#else >> +#define TESTDIR "/tmp/tst-symlink" >> +#endif >> >> #define N1 "f1" >> #define N2 "f2_AAA" >> #define N3 "f3" >> #define N4 "f4" >> #define N5 "f5" >> +#define N6 "f6" >> #define D1 "d1" >> #define D2 "d2_AAA" >> #define D3 "d3" >> #define D4 "d4" >> >> int tests = 0, fails = 0; >> >> -static void report(bool ok, const char *msg) >> +static void report(bool ok, const char* msg) >> { >> ++tests; >> fails += !ok; >> - debug("%s: %s\n", (ok ? "PASS" : "FAIL"), msg); >> - if (fails) >> + printf("%s: %s\n", (ok ? "PASS" : "FAIL"), msg); >> + if (fails) { >> + printf("Errno: %d\n", errno); >> exit(0); >> + } >> } >> >> +#if !defined(READ_ONLY_FS) >> static void fill_buf(char *b, unsigned int no) >> { >> memset(b, 'A', no - 1); >> b[no - 1] = 0; >> } >> +#endif >> >> static bool search_dir(const char *dir, const char *name) >> { >> @@ -67,54 +77,79 @@ int main(int argc, char **argv) >> { >> struct stat buf; >> int rc; >> - int error; >> - time_t t1; >> char path[PATH_MAX]; >> int fd; >> - int fd1; >> - char b1[4097]; >> - char b2[4097]; >> - char path1[PATH_MAX]; >> >> debug("Testing symlink() and related functions.\n"); >> >> report(sizeof(path) >= 4096, "sizeof(PATH_MAX)"); >> >> +#if defined(READ_ONLY_FS) >> + report(-1 == mkdir("/rofs/tst-symlink1", 0777) && errno == >> EROFS, "mkdir"); >> +#else >> + report(0 == mkdir(TESTDIR, 0777), "mkdir"); >> +#endif >> + >> report(chdir(TESTDIR) == 0, "chdir"); >> >> /* >> * test to check >> - * access to symlink >> - * file type >> + * access to symlink >> + * file type >> */ >> + >> +#if defined(READ_ONLY_FS) >> + fd = open(N1, O_RDONLY); >> +#else >> fd = creat(N1, 0777); >> +#endif >> report(fd >= 0, "creat"); >> report(search_dir(TESTDIR, N1) == true, "search dir"); >> >> report(lstat(N1, &buf) == 0, "lstat"); >> report(S_ISREG(buf.st_mode) == 1, "file mode"); >> >> +#if defined(READ_ONLY_FS) >> + report(symlink(N1, N6) == -1 && errno == EROFS, "symlink"); >> + report(search_dir(TESTDIR, N2) == true, "search dir"); >> +#else >> report(symlink(N1, N2) == 0, "symlink"); >> report(search_dir(TESTDIR, N2) == true, "search dir"); >> +#endif >> >> +#if defined(READ_ONLY_FS) >> + report(access(N1, R_OK) == 0, "access1"); >> + report(access(N1, R_OK | W_OK) == -1 && errno == EROFS, "access2"); >> + report(access(N2, R_OK) == 0, "access3"); >> + report(access(N2, R_OK | W_OK) == -1 && errno == EROFS, "access4"); >> +#else >> report(access(N1, R_OK | W_OK) == 0, "access"); >> report(access(N2, R_OK | W_OK) == 0, "access"); >> +#endif >> >> rc = readlink(N2, path, sizeof(path)); >> report(rc >= 0, "readlink"); >> path[rc] = 0; >> +#if defined(READ_ONLY_FS) >> + report(strcmp(path, TESTDIR "/" N1) == 0, "readlink path"); >> +#else >> report(strcmp(path, N1) == 0, "readlink path"); >> - >> +#endif >> report(lstat(N2, &buf) == 0, "lstat"); >> report(S_ISLNK(buf.st_mode) == 1, "file mode"); >> >> close(fd); >> +#if defined(READ_ONLY_FS) >> + report(unlink(N1) == -1 && errno == EROFS, "unlink"); >> +#else >> report(unlink(N1) == 0, "unlink"); >> +#endif >> report(lstat(N2, &buf) == 0, "lstat"); >> report(S_ISLNK(buf.st_mode) == 1, "file mode"); >> >> +#if !defined(READ_ONLY_FS) >> rc = stat(N2, &buf); >> - error = errno; >> + int error = errno; >> report(rc < 0, "stat"); >> report(error == ENOENT, "ENOENT expected"); >> >> @@ -130,7 +165,10 @@ int main(int argc, char **argv) >> report(fd >= 0, "creat"); >> report(symlink(N1, N2) == 0, "symlink"); >> >> - fd1 = open(N2, O_RDONLY); >> + char b1[4097]; >> + char b2[4097]; >> + >> + int fd1 = open(N2, O_RDONLY); >> report(fd1 >= 0, "symlink open"); >> >> fill_buf(b1, sizeof(b1)); >> @@ -143,11 +181,14 @@ int main(int argc, char **argv) >> report(rc == sizeof(b2), "symlink read"); >> >> report(memcmp(b1, b2, sizeof(b1)) == 0, "data verification"); >> +#endif >> >> #ifdef NOT_YET >> rc = ftruncate(fd1, 0); >> report(rc != 0 && errno == EINVAL, "symlink fd truncate"); >> #endif >> + >> +#if !defined(READ_ONLY_FS) >> report(ftruncate(fd, 0) == 0, "file fd truncate"); >> report(fstat(fd, &buf) == 0, "fstat file"); >> report(buf.st_size == 0, "file size after truncate"); >> @@ -192,7 +233,7 @@ int main(int argc, char **argv) >> report(fd >= 0, "creat"); >> report(mkdir(D1, 0777) == 0, "mkdir"); >> report(stat(D1, &buf) == 0, "stat"); >> - t1 = buf.st_ctime; >> + time_t t1 = buf.st_ctime; >> sleep(1); >> >> snprintf(path, sizeof(path), "%s/%s", D1, N2); >> @@ -221,6 +262,7 @@ int main(int argc, char **argv) >> report(symlink(N1, path) == 0, "symlink"); >> report(unlink(path) == 0, "unlink"); >> >> + printf("-->Smok\n"); >> fill_buf(path, 257); >> rc = symlink(N1, path); >> error = errno; >> @@ -300,6 +342,7 @@ int main(int argc, char **argv) >> report(fd >= 0, "create file"); >> close(fd); >> >> + char path1[PATH_MAX]; >> report(symlink(D1, D2) == 0, "symlink to directory"); /* /tmp/d2 -> >> >> /tmp/d1 */ >> snprintf(path1, sizeof(path1), "%s/%s", D1, N2); >> report(rename(path, path1) == 0, "rename(f1,f2)"); >> @@ -344,7 +387,14 @@ int main(int argc, char **argv) >> report(unlink(path) == 0, "unlink(d4/f5)"); >> report(unlink(D3) == 0, "unlink(d3)"); >> report(rmdir(D4) == 0, "rmdir"); >> +#endif >> + >> +#if defined(READ_ONLY_FS) >> + report(-1 == rmdir(TESTDIR) && errno == ENOTEMPTY, "rmdir"); >> +#else >> + report(0 == rmdir(TESTDIR), "rmdir"); >> +#endif >> >> - debug("SUMMARY: %d tests, %d failures\n", tests, fails); >> + std::cout << "SUMMARY: " << tests << " tests, " << fails << " >> failures\n"; >> return (fails == 0 ? 0 : 1); >> } >> diff --git a/tests/tst-uio.cc b/tests/tst-uio.cc >> --- a/tests/tst-uio.cc >> +++ b/tests/tst-uio.cc >> @@ -73,9 +73,9 @@ int main() >> // keeps track of how much it copied. Unbelievably, we had such a >> bug >> // in OSv and didn't notice it for over a year. >> #ifdef __OSV__ >> - const char* fn = "/tests/tst-rename.so"; // A file roughly 200KB >> in >> size. >> + const char* fn = "/tests/tst-regex.so"; // A file roughly 200KB in >> >> size. >> #else >> - const char* fn = "build/release/tests/tst-rename.so"; >> + const char* fn = "build/release/tests/tst-regex.so"; >> #endif >> int fd; >> expect_success(fd, open(fn, O_RDONLY)); >> diff --git a/tests/tst-zfs-mount.cc b/tests/tst-zfs-mount.cc >> --- a/tests/tst-zfs-mount.cc >> +++ b/tests/tst-zfs-mount.cc >> @@ -162,7 +162,7 @@ int main(int argc, char **argv) >> report(fd > 0, "create /tmp/foo"); >> >> report(write(fd, &foo, sizeof(foo)) == sizeof(foo), "write >> sizeof(foo) >> bytes to fd"); >> - //report(pwrite(fd, &foo, sizeof(foo), LONG_MAX) == -1 && errno == >> EFBIG, "check for maximum allowed offset"); >> + report(pwrite(fd, &foo, sizeof(foo), LONG_MAX) == -1 && errno == >> EFBIG, "check for maximum allowed offset"); >> report(fsync(fd) == 0, "fsync fd"); >> report(fstat(fd, &s) == 0, "fstat fd"); >> >> -- > You received this message because you are subscribed to the Google Groups > "OSv Development" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
