From 79181b3153369dfaaacc6da3d54e1fe484afcf4d Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Wed, 7 Feb 2018 21:45:20 +0000 Subject: [PATCH] Added LD_PRELOAD library to monitor msync calls in testing --- Makefile | 4 +- tests/acceptance/ld_preloads/Makefile | 13 ++++++ tests/acceptance/ld_preloads/msync_catcher.c | 33 +++++++++++++++ tests/acceptance/test_serve_mode.rb | 44 ++++++++++++++++---- 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 tests/acceptance/ld_preloads/Makefile create mode 100644 tests/acceptance/ld_preloads/msync_catcher.c diff --git a/Makefile b/Makefile index b6b101f..f7d1e63 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,8 @@ check: $(OBJS) $(CHECK_BINS) r=true ; for bin in $(CHECK_BINS); do $$bin || r=false; done ; $$r acceptance: build - cd tests/acceptance && RUBYOPT='-I.' ruby nbd_scenarios -v + $(MAKE) -C tests/acceptance/ld_preloads all + cd tests/acceptance && LD_PRELOADS=$$(echo ld_preloads/*.o) RUBYOPT='-I.' ruby nbd_scenarios -v test: check acceptance @@ -108,6 +109,7 @@ install: clean: rm -rf build/* + $(RM) $(LD_PRELOAD_OBJ) .PHONY: clean objs check_objs all server proxy check_bins check doc build test acceptance diff --git a/tests/acceptance/ld_preloads/Makefile b/tests/acceptance/ld_preloads/Makefile new file mode 100644 index 0000000..1c5f9ad --- /dev/null +++ b/tests/acceptance/ld_preloads/Makefile @@ -0,0 +1,13 @@ + +SRC := $(wildcard *.c) +OBJS := $(SRC:%.c=%.o) + +all: $(OBJS) + +clean: + $(RM) $(OBJS) + +%.o: %.c + gcc -shared -fPIC -ldl -o $@ $< + +.PHONY: all clean diff --git a/tests/acceptance/ld_preloads/msync_catcher.c b/tests/acceptance/ld_preloads/msync_catcher.c new file mode 100644 index 0000000..18ef284 --- /dev/null +++ b/tests/acceptance/ld_preloads/msync_catcher.c @@ -0,0 +1,33 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +typedef int (*real_msync_t)(void *addr, size_t length, int flags); + +int real_msync(void *addr, size_t length, int flags) { + return ((real_msync_t)dlsym(RTLD_NEXT, "msync"))(addr, length, flags); +} + +/* + * Noddy LD_PRELOAD wrapper to catch msync calls, and log them to a file. + */ + +int msync(void *addr, size_t length, int flags) { + FILE *fd; + char *fn; + int retval; + + retval = real_msync(addr, length, flags); + + fn = getenv("MSYNC_CATCHER_OUTPUT"); + if ( fn != NULL ) { + fd = fopen(fn,"a"); + fprintf(fd,"msync:%d:%i:%i:%i\n", addr, length, flags, retval); + fclose(fd); + } + + return retval; +} diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index e67da83..cdf3e58 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -1,6 +1,7 @@ require 'test/unit' require 'environment' require 'flexnbd/fake_source' +require 'tempfile' class TestServeMode < Test::Unit::TestCase def setup @@ -11,6 +12,7 @@ class TestServeMode < Test::Unit::TestCase def teardown @env.cleanup + teardown_msync_catcher super end @@ -37,6 +39,26 @@ class TestServeMode < Test::Unit::TestCase end end + def setup_msync_catcher + @msync_catcher = Tempfile.new('msync') + ENV['MSYNC_CATCHER_OUTPUT'] = @msync_catcher.path + end + + def parse_msync_output + op = [] + until @msync_catcher.eof? + op << @msync_catcher.readline.chomp.split(':').map do |e| + e =~ /^\d+$/ ? e.to_i : e + end + end + op + end + + def teardown_msync_catcher + @msync_catcher.close if @msync_catcher + ENV.delete 'MSYNC_CATCHER_OUTPUT' + end + def test_bad_request_magic_receives_error_response connect_to_server do |client| # replace REQUEST_MAGIC with all 0s to make it look bad @@ -109,15 +131,21 @@ class TestServeMode < Test::Unit::TestCase end def test_flush_is_accepted + setup_msync_catcher connect_to_server do |client| client.flush rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] end + op = parse_msync_output + assert_equal 1, op.count, 'Only one msync expected' + assert_equal @env.blocksize, op.first[2], 'msync length wrong' + assert_equal 6, op.first[3], 'msync called with incorrect flags' end def test_write_with_fua_is_accepted + setup_msync_catcher page_size = Integer(`getconf PAGESIZE`) @env.blocksize = page_size * 10 connect_to_server do |client| @@ -127,13 +155,15 @@ class TestServeMode < Test::Unit::TestCase rsp = client.read_response assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal 0, rsp[:error] - # TODO: test offset and length - # Should be rounded to the third page - # assert_equal(msync_offset, page_size *3) - - # Should be 100 + 33, as we've started writing 100 bytes into a page, for - # 33 bytes - # assert_equal(msync_length, 133) end + + op = parse_msync_output + assert_equal 1, op.count, 'Only one msync expected' + + # Should be 100 + 33, as we've started writing 100 bytes into a page, for + # 33 bytes + assert_equal 133, op.first[2], 'msync length wrong' + assert_equal 6, op.first[3], 'msync called with incorrect flags' end + end