From 4e15382dea359375f3fa8907b60d13791ae39e83 Mon Sep 17 00:00:00 2001 From: William Yang Date: Thu, 24 Oct 2024 16:42:34 +0200 Subject: [PATCH] test(proper): cover the case when the stream owner is dead after accepted --- c_src/quicer_tp.c | 1 - test/example_client_connection.erl | 1 + test/prop_stateful_client_conn.erl | 28 ++++++++++++++++++++++++++++ test/prop_stateful_server_conn.erl | 20 ++++++++++++++------ tools/run/bin/lib.sh | 2 +- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/c_src/quicer_tp.c b/c_src/quicer_tp.c index bc087491..0824031d 100644 --- a/c_src/quicer_tp.c +++ b/c_src/quicer_tp.c @@ -84,5 +84,4 @@ tp_snk(ErlNifEnv *env, enif_make_tuple2(env, ATOM_IN_ENV(TRACE), snk_event)); enif_send(NULL, pid, env, report); enif_free_env(env); - } diff --git a/test/example_client_connection.erl b/test/example_client_connection.erl index 7cb93ff4..01bf2bc9 100644 --- a/test/example_client_connection.erl +++ b/test/example_client_connection.erl @@ -164,6 +164,7 @@ handle_info({quic, Sig, Stream, _} = Msg, #{streams := Streams} = S) when _ = quicer:async_shutdown_stream(Stream), {ok, S#{streams := lists:keydelete(Stream, 2, Streams)}}; {OwnerPid, Stream} when is_pid(OwnerPid) -> + %%% you should not hit here in testing, if so, fire one issue report {error, {fixme, bug_handoff_fail}}; false -> %% garbage signals from already dead stream (such like crashed owner) diff --git a/test/prop_stateful_client_conn.erl b/test/prop_stateful_client_conn.erl index ce28d503..27d7ccda 100644 --- a/test/prop_stateful_client_conn.erl +++ b/test/prop_stateful_client_conn.erl @@ -28,6 +28,10 @@ postcondition/3 ]). +%% Helpers +-export([ + spawn_stream_acceptor/3 +]). %%%%%%%%%%%%%%%%%% %%% PROPERTIES %%% %%%%%%%%%%%%%%%%%% @@ -72,6 +76,10 @@ command(#{handle := Handle}) -> {100, {call, quicer, getopt, [Handle, ?LET({Opt, _}, conn_opt(), Opt)]}}, {100, {call, quicer, async_accept_stream, [Handle, ?LET(Opts, quicer_acceptor_opts(), Opts)]}}, + {100, + {call, ?MODULE, spawn_stream_acceptor, [ + Handle, ?LET(Opts, quicer_acceptor_opts(), Opts), range(0, 200) + ]}}, {100, {call, quicer, peername, [Handle]}}, {50, {call, quicer, peercert, [Handle]}}, {10, {call, quicer, negotiated_protocol, [Handle]}}, @@ -205,6 +213,8 @@ postcondition(#{handle := _H, state := closed}, {call, quicer, get_connections, true; postcondition(#{state := closed}, {call, _Mod, _Fun, _Args}, {error, closed}) -> true; +postcondition(_State, {call, ?MODULE, spawn_stream_acceptor, _Args}, ok) -> + true; postcondition(_State, {call, _Mod, _Fun, _Args} = _Call, _Res) -> false. @@ -278,3 +288,21 @@ default_conn_opts() -> {certfile, "./msquic/submodules/openssl/test/certs/servercert.pem"}, {keyfile, "./msquic/submodules/openssl/test/certs/serverkey.pem"} ]. + +%% Test helpers +spawn_stream_acceptor(ConnHandle, Opts, DieAfter) -> + spawn( + fun() -> + do_accept_stream(ConnHandle, Opts, DieAfter) + end + ), + ok. + +do_accept_stream(Conn, Opts, DieAfter) -> + {ok, Conn} = quicer:async_accept_stream(Conn, Opts), + receive + {quicer, new_stream, _Stream, _Flags} -> + timer:sleep(DieAfter) + after DieAfter -> + ok + end. diff --git a/test/prop_stateful_server_conn.erl b/test/prop_stateful_server_conn.erl index 777ad853..a5952ecc 100644 --- a/test/prop_stateful_server_conn.erl +++ b/test/prop_stateful_server_conn.erl @@ -139,7 +139,9 @@ postcondition(#{state := accepted}, {call, quicer, handshake, _Args}, {ok, _}) - true; postcondition(#{state := accepted}, {call, quicer, handshake, _Args}, {error, invalid_state}) -> true; -postcondition(#{state := accepted}, {call, quicer, handshake, _Args}, {error, timeout}) -> +postcondition(#{state := closed}, {call, quicer, handshake, _}, {error, timeout}) -> + true; +postcondition(#{state := _}, {call, quicer, handshake, _Args}, {error, timeout}) -> %% @FIXME true; postcondition( @@ -209,21 +211,23 @@ postcondition(_State, {call, quicer, close_connection, _Args}, ok) -> true; postcondition(_State, {call, quicer, shutdown_connection, _Args}, ok) -> true; -postcondition(accepted, {call, quicer, close_connection, _Args}, {error, timeout}) -> +postcondition(#{state := accepted}, {call, quicer, close_connection, _Args}, {error, timeout}) -> + true; +postcondition(#{state := accepted}, {call, quicer, shutdown_connection, _Args}, {error, timeout}) -> true; -postcondition(accepted, {call, quicer, shutdown_connection, _Args}, {error, timeout}) -> +postcondition(#{state := accepted}, {call, quicer, close_connection, _Args}, {error, closed}) -> true; -postcondition(accepted, {call, quicer, close_connection, _Args}, {error, closed}) -> +postcondition(#{state := closed}, {call, quicer, close_connection, _Args}, {error, timeout}) -> true; postcondition(_, {call, quicer, shutdown_connection, [_, _, Tout]}, {error, timeout}) when Tout < 200 -> true; -postcondition(_, {call, quicer, close_connection, [_, _, Tout]}, {error, timeout}) when +postcondition(_, {call, quicer, close_connection, [_, Tout]}, {error, timeout}) when Tout < 200 -> true; -postcondition(accepted, {call, quicer, shutdown_connection, _Args}, {error, closed}) -> +postcondition(#{state := accepted}, {call, quicer, shutdown_connection, _Args}, {error, closed}) -> true; postcondition( #{me := Me, owner := Owner, state := State}, @@ -243,6 +247,10 @@ postcondition( S =:= accepted orelse S =:= closed -> true; +postcondition( + #{state := accepted}, {call, quicer, async_csend, [_]}, {error, stm_send_error, aborted} +) -> + true; postcondition(#{state := accepted}, {call, quicer, async_csend, [_]}, {error, timeout}) -> %% @FIXME https://github.com/emqx/quic/issues/265 true; diff --git a/tools/run/bin/lib.sh b/tools/run/bin/lib.sh index a0b4aaca..da77c152 100644 --- a/tools/run/bin/lib.sh +++ b/tools/run/bin/lib.sh @@ -29,7 +29,7 @@ do_run() { done ;; proper) - escript "$REBAR3" as test proper + escript "$REBAR3" as test proper --noshrink ;; *) escript "$REBAR3" $@