Add stop signals to client threads
This commit is contained in:
95
tests/check_client.c
Normal file
95
tests/check_client.c
Normal file
@@ -0,0 +1,95 @@
|
||||
#include <check.h>
|
||||
|
||||
#include "self_pipe.h"
|
||||
|
||||
#include "client.h"
|
||||
|
||||
|
||||
START_TEST( test_assigns_socket )
|
||||
{
|
||||
struct client * c;
|
||||
|
||||
c = client_create( NULL, 42 );
|
||||
|
||||
fail_unless( 42 == c->socket, "Socket wasn't assigned." );
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST( test_assigns_server )
|
||||
{
|
||||
struct client * c;
|
||||
/* can't predict the storage size so we can't allocate one on
|
||||
* the stack
|
||||
*/
|
||||
struct server * s = (struct server *)42;
|
||||
|
||||
c = client_create( (struct server *)s, 0 );
|
||||
|
||||
fail_unless( s == c->serve, "Serve wasn't assigned." );
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST( test_opens_stop_signal )
|
||||
{
|
||||
struct client *c = client_create( NULL, 0 );
|
||||
|
||||
client_signal_stop( c );
|
||||
|
||||
fail_unless( 1 == self_pipe_signal_clear( c->stop_signal ),
|
||||
"No signal was sent." );
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST( test_closes_stop_signal )
|
||||
{
|
||||
struct client *c = client_create( NULL, 0 );
|
||||
int read_fd = c->stop_signal->read_fd;
|
||||
int write_fd = c->stop_signal->write_fd;
|
||||
|
||||
client_destroy( c );
|
||||
|
||||
fail_unless( fd_is_closed( read_fd ), "Stop signal wasn't destroyed." );
|
||||
fail_unless( fd_is_closed( write_fd ), "Stop signal wasn't destroyed." );
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
Suite *client_suite()
|
||||
{
|
||||
Suite *s = suite_create("client");
|
||||
|
||||
TCase *tc_create = tcase_create("create");
|
||||
TCase *tc_signal = tcase_create("signal");
|
||||
TCase *tc_destroy = tcase_create("destroy");
|
||||
|
||||
tcase_add_test(tc_create, test_assigns_socket);
|
||||
tcase_add_test(tc_create, test_assigns_server);
|
||||
|
||||
tcase_add_test(tc_signal, test_opens_stop_signal);
|
||||
|
||||
tcase_add_test( tc_destroy, test_closes_stop_signal );
|
||||
|
||||
suite_add_tcase(s, tc_create);
|
||||
suite_add_tcase(s, tc_signal);
|
||||
suite_add_tcase(s, tc_destroy);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = client_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
@@ -1,4 +1,7 @@
|
||||
require 'socket'
|
||||
require 'thread'
|
||||
|
||||
Thread.abort_on_exception = true
|
||||
|
||||
# Noddy test class to exercise FlexNBD from the outside for testing.
|
||||
#
|
||||
@@ -7,27 +10,64 @@ class FlexNBD
|
||||
|
||||
def initialize(bin, ip, port)
|
||||
@bin = bin
|
||||
@debug = `#{@bin} serve --help` =~ /--debug/ ? "--debug" : ""
|
||||
@debug = `#{@bin} serve --help` =~ /--verbose/ ? "--verbose" : ""
|
||||
@valgrind = ENV['VALGRIND'] ? "valgrind " : ""
|
||||
@bin = "#{@valgrind}#{@bin}"
|
||||
raise "#{bin} not executable" unless File.executable?(bin)
|
||||
@ctrl = "/tmp/.flexnbd.ctrl.#{Time.now.to_i}.#{rand}"
|
||||
@ip = ip
|
||||
@port = port
|
||||
@kill = false
|
||||
end
|
||||
|
||||
def debug?
|
||||
!@debug.empty?
|
||||
end
|
||||
|
||||
def debug( msg )
|
||||
$stderr.puts msg if debug?
|
||||
end
|
||||
|
||||
|
||||
def serve_cmd( file, acl )
|
||||
"#{@bin} serve "\
|
||||
"--addr #{ip} "\
|
||||
"--port #{port} "\
|
||||
"--file #{file} "\
|
||||
"--sock #{ctrl} "\
|
||||
"#{@debug} "\
|
||||
"#{acl.join(' ')}"
|
||||
end
|
||||
|
||||
|
||||
def read_cmd( offset, length )
|
||||
"#{@bin} read "\
|
||||
"--addr #{ip} "\
|
||||
"--port #{port} "\
|
||||
"--from #{offset} "\
|
||||
"#{@debug} "\
|
||||
"--size #{length}"
|
||||
end
|
||||
|
||||
|
||||
def write_cmd( offset, data )
|
||||
"#{@bin} write "\
|
||||
"--addr #{ip} "\
|
||||
"--port #{port} "\
|
||||
"--from #{offset} "\
|
||||
"#{@debug} "\
|
||||
"--size #{data.length}"
|
||||
end
|
||||
|
||||
|
||||
def serve(file, *acl)
|
||||
File.unlink(ctrl) if File.exists?(ctrl)
|
||||
cmd ="#{@bin} serve "\
|
||||
"--addr #{ip} "\
|
||||
"--port #{port} "\
|
||||
"--file #{file} "\
|
||||
"--sock #{ctrl} "\
|
||||
"#{@debug} "\
|
||||
"#{acl.join(' ')}"
|
||||
@pid = fork do
|
||||
exec(cmd)
|
||||
end
|
||||
cmd =serve_cmd( file, acl )
|
||||
debug( cmd )
|
||||
|
||||
@pid = fork do exec(cmd) end
|
||||
start_wait_thread( @pid )
|
||||
|
||||
while !File.socket?(ctrl)
|
||||
pid, status = Process.wait2(@pid, Process::WNOHANG)
|
||||
raise "server did not start (#{cmd})" if pid
|
||||
@@ -36,30 +76,37 @@ class FlexNBD
|
||||
at_exit { kill }
|
||||
end
|
||||
|
||||
def start_wait_thread( pid )
|
||||
Thread.start do
|
||||
Process.waitpid2( pid )
|
||||
unless @kill
|
||||
$stderr.puts "flexnbd quit"
|
||||
fail "flexnbd quit early"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def kill
|
||||
@kill = true
|
||||
Process.kill("INT", @pid)
|
||||
Process.wait(@pid)
|
||||
end
|
||||
|
||||
def read(offset, length)
|
||||
IO.popen("#{@bin} read "\
|
||||
"--addr #{ip} "\
|
||||
"--port #{port} "\
|
||||
"--from #{offset} "\
|
||||
"#{@debug} "\
|
||||
"--size #{length}","r") do |fh|
|
||||
cmd = read_cmd( offset, length )
|
||||
debug( cmd )
|
||||
|
||||
IO.popen(cmd) do |fh|
|
||||
return fh.read
|
||||
end
|
||||
raise "read failed" unless $?.success?
|
||||
end
|
||||
|
||||
def write(offset, data)
|
||||
IO.popen("#{@bin} write "\
|
||||
"--addr #{ip} "\
|
||||
"--port #{port} "\
|
||||
"--from #{offset} "\
|
||||
"#{@debug} "\
|
||||
"--size #{data.length}","w") do |fh|
|
||||
cmd = write_cmd( offset, data )
|
||||
debug( cmd )
|
||||
|
||||
IO.popen(cmd, "w") do |fh|
|
||||
fh.write(data)
|
||||
end
|
||||
raise "write failed" unless $?.success?
|
||||
|
Reference in New Issue
Block a user