Current section

Files

Jump to
aion_flow src aion@testing@mock.erl
Raw

src/aion@testing@mock.erl

-module(aion@testing@mock).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aion/testing/mock.gleam").
-export([activity/3]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Typed activity mock registry for `aion/testing`.\n"
"\n"
" Tests register mocks against an `Activity(i, o)` value so the handler is\n"
" statically checked against the same input and output types that\n"
" `workflow.run` will use. The test-only FFI double stores a type-erased\n"
" wrapper in process-scoped state and intercepts activity dispatch by name.\n"
).
-file("src/aion/testing/mock.gleam", 42).
-spec activity_error_to_raw(aion@error:activity_error()) -> binary().
activity_error_to_raw(Activity_error) ->
case Activity_error of
{retryable, Message, _} ->
<<"retryable:"/utf8, Message/binary>>;
{terminal, Message@1, _} ->
<<"terminal:"/utf8, Message@1/binary>>;
{activity_decode_failed, Decode_error} ->
<<"terminal:activity decode failed: "/utf8,
(erlang:element(2, Decode_error))/binary>>;
{activity_timed_out, {timed_out, Message@2}} ->
<<"timeout:"/utf8, Message@2/binary>>;
{activity_cancelled, {cancelled, Reason}} ->
<<"cancelled:"/utf8, Reason/binary>>;
{activity_non_deterministic, {non_determinism_violation, Message@3}} ->
<<"non_determinism:"/utf8, Message@3/binary>>;
{activity_engine_failure, Message@4} ->
Message@4
end.
-file("src/aion/testing/mock.gleam", 16).
?DOC(
" Register a typed activity mock for the current process.\n"
"\n"
" A handler whose input or output type does not match the supplied activity will\n"
" fail at `gleam build`, before the workflow test can run.\n"
).
-spec activity(
EJW,
aion@activity:activity(EJX, EJY),
fun((EJX) -> {ok, EJY} | {error, aion@error:activity_error()})
) -> {ok, EJW} | {error, aion@error:engine_error()}.
activity(Env, Activity_value, Handler) ->
Input_codec = aion@activity:input_codec(Activity_value),
Output_codec = aion@activity:output_codec(Activity_value),
Name = aion@activity:name(Activity_value),
Raw_handler = fun(Raw_input) ->
case (erlang:element(3, Input_codec))(Raw_input) of
{ok, Typed_input} ->
case Handler(Typed_input) of
{ok, Typed_output} ->
{ok, (erlang:element(2, Output_codec))(Typed_output)};
{error, Activity_error} ->
{error, activity_error_to_raw(Activity_error)}
end;
{error, Decode_error} ->
{error,
<<"terminal:mock input decode failed: "/utf8,
(erlang:element(2, Decode_error))/binary>>}
end
end,
case aion_flow_ffi:testing_register_activity_mock(Name, Raw_handler) of
{ok, _} ->
{ok, Env};
{error, Raw_error} ->
{error, {engine_failure, Raw_error}}
end.