diff --git a/tests/acceptance/ld_preload.rb b/tests/acceptance/ld_preload.rb new file mode 100644 index 0000000..9cc5a14 --- /dev/null +++ b/tests/acceptance/ld_preload.rb @@ -0,0 +1,36 @@ +require 'tempfile' + +# LdPreload is a little wrapper for using LD_PRELOAD when testing flexnbd +module LdPreload + # This takes an object name, sets up a temporary log file, whose name is + # recorded in the environment as OUTPUT_obj_name, where obj_name is the + # name of the preload module to build and load. + def with_ld_preload(obj_name) + @ld_preload_logs ||= {} + flunk 'Can only load a preload module once!' if @ld_preload_logs[obj_name] + + system("make -C ld_preloads/ #{obj_name}.o > /dev/null") || + flunk("Failed to build object #{obj_name}") + orig_env = ENV['LD_PRELOAD'] + ENV['LD_PRELOAD'] = [orig_env, File.expand_path("./ld_preloads/#{obj_name}.o")].compact.join(' ') + + # Open the log, and stick it in a hash + @ld_preload_logs[obj_name] = Tempfile.new(obj_name) + ENV['OUTPUT_' + obj_name] = @ld_preload_logs[obj_name].path + + yield + ensure + if @ld_preload_logs[obj_name] + @ld_preload_logs[obj_name].close + @ld_preload_logs.delete(obj_name) + end + ENV['LD_PRELOAD'] = orig_env + end + + def read_ld_preload_log(obj_name) + lines = [] + lines << @ld_preload_logs[obj_name].readline.chomp until + @ld_preload_logs[obj_name].eof? + lines + end +end diff --git a/tests/acceptance/ld_preloads/msync_catcher.c b/tests/acceptance/ld_preloads/msync_logger.c similarity index 94% rename from tests/acceptance/ld_preloads/msync_catcher.c rename to tests/acceptance/ld_preloads/msync_logger.c index 18ef284..73543cd 100644 --- a/tests/acceptance/ld_preloads/msync_catcher.c +++ b/tests/acceptance/ld_preloads/msync_logger.c @@ -22,7 +22,7 @@ int msync(void *addr, size_t length, int flags) { retval = real_msync(addr, length, flags); - fn = getenv("MSYNC_CATCHER_OUTPUT"); + fn = getenv("OUTPUT_msync_logger"); if ( fn != NULL ) { fd = fopen(fn,"a"); fprintf(fd,"msync:%d:%i:%i:%i\n", addr, length, flags, retval); diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index 2299584..8a451ce 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -1,9 +1,11 @@ require 'test/unit' require 'environment' require 'flexnbd/fake_source' -require 'tempfile' +require 'ld_preload' class TestServeMode < Test::Unit::TestCase + include LdPreload + def setup super @b = "\xFF".b @@ -12,7 +14,6 @@ class TestServeMode < Test::Unit::TestCase def teardown @env.cleanup - teardown_msync_catcher super end @@ -39,33 +40,10 @@ class TestServeMode < Test::Unit::TestCase end end - def setup_msync_catcher - `make -C ld_preloads/ msync_catcher.o` - omit 'LD_PRELOAD library not found' unless - File.exist?('ld_preloads/msync_catcher.o') - - @msync_catcher = Tempfile.new('msync') - ENV['MSYNC_CATCHER_OUTPUT'] = @msync_catcher.path - - @ld_preload_orig = ENV['LD_PRELOAD'] - ENV['LD_PRELOAD'] = 'ld_preloads/msync_catcher.o' - 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 + def parse_msync_logs + read_ld_preload_log('msync_logger').map do |l| + l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i } end - op - end - - def teardown_msync_catcher - @msync_catcher.close if @msync_catcher - - ENV.delete 'MSYNC_CATCHER_OUTPUT' - ENV['LD_PRELOAD'] = @ld_preload_orig end def test_bad_request_magic_receives_error_response @@ -160,39 +138,42 @@ 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] + with_ld_preload('msync_logger') do + 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_logs + 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 - 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| - # Write somewhere in the third page - pos = page_size * 3 + 100 - client.write_with_fua(pos, "\x00" * 33) - rsp = client.read_response - assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal 0, rsp[:error] + with_ld_preload('msync_logger') do + page_size = Integer(`getconf PAGESIZE`) + + @env.blocksize = page_size * 10 + connect_to_server do |client| + # Write somewhere in the third page + pos = page_size * 3 + 100 + client.write_with_fua(pos, "\x00" * 33) + rsp = client.read_response + assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 0, rsp[:error] + end + op = parse_msync_logs + + 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 - - 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 def test_odd_size_discs_are_truncated_to_nearest_512