-module(metamon@internal@runner). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/metamon/internal/runner.gleam"). -export([plain/3, equivariant/4, morph_name/1, run_assert_morph/4, run_forall_morph_n/6, run_forall_morphs/5, run_forall/4, run_forall_morph/5]). -export_type([morph_spec/2, step/1, outcome/0, evaluation/1]). -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(false). -opaque morph_spec(GLF, GLG) :: {plain_spec, binary(), metamon@transform:transform(GLF), metamon@relation:relation(GLG)} | {equivariant_spec, binary(), metamon@transform:transform(GLF), metamon@transform:transform(GLG), metamon@relation:relation(GLG)}. -type step(GLH) :: continue | {stop, binary()} | {gleam_phantom, GLH}. -type outcome() :: done | {halted, binary()}. -type evaluation(GLI) :: {evaluation, binary(), GLI, GLI, boolean()}. -file("src/metamon/internal/runner.gleam", 48). ?DOC(false). -spec plain( binary(), metamon@transform:transform(GLJ), metamon@relation:relation(GLL) ) -> morph_spec(GLJ, GLL). plain(Name, Transform, Relation) -> {plain_spec, Name, Transform, Relation}. -file("src/metamon/internal/runner.gleam", 58). ?DOC(false). -spec equivariant( binary(), metamon@transform:transform(GLP), metamon@transform:transform(GLR), metamon@relation:relation(GLR) ) -> morph_spec(GLP, GLR). equivariant(Name, Input_transform, Output_transform, Relation) -> {equivariant_spec, Name, Input_transform, Output_transform, Relation}. -file("src/metamon/internal/runner.gleam", 216). ?DOC(false). -spec render_for( metamon@config:config(), metamon@internal@report:failure_report() ) -> binary(). render_for(Cfg, Report) -> case metamon@config:output_format(Cfg) of text -> metamon@internal@report:render(Report); json -> metamon@internal@report:render_json(Report) end. -file("src/metamon/internal/runner.gleam", 259). ?DOC(false). -spec compute_n_outputs( list(metamon@transform:transform(GNH)), fun((GNH) -> GNK), GNH ) -> list(GNK). compute_n_outputs(Transforms, F, Input) -> Source_output = F(Input), Followups = gleam@list:map( Transforms, fun(T) -> F((erlang:element(3, T))(Input)) end ), [Source_output | Followups]. -file("src/metamon/internal/runner.gleam", 270). ?DOC(false). -spec morph_n_failure( metamon@config:config(), binary(), list(metamon@transform:transform(GNM)), metamon@relation:relation_n(GNP), integer(), GNM, metamon@internal@report:input_source(), list(GNP) ) -> binary(). morph_n_failure( Cfg, Test_name, Transforms, Rel, Run_index, Input, Source, Outputs ) -> Transform_names = begin _pipe = gleam@list:map(Transforms, fun(T) -> erlang:element(2, T) end), gleam@string:join(_pipe, <<", "/utf8>>) end, Outputs_rendered = begin _pipe@1 = gleam@list:index_map( Outputs, fun(Out, I) -> <<<<<<" ["/utf8, (erlang:integer_to_binary(I))/binary>>/binary, "] "/utf8>>/binary, (gleam@string:inspect(Out))/binary>> end ), gleam@string:join(_pipe@1, <<"\n"/utf8>>) end, erlang:list_to_binary( [<<"× n-ary metamorphic relation `"/utf8>>, erlang:element(2, Rel), <<"` failed\n test: "/utf8>>, Test_name, <<"\n config seed: "/utf8>>, erlang:integer_to_binary( metamon@generator@seed:state(metamon@config:seed(Cfg)) ), <<"\n runs: "/utf8>>, erlang:integer_to_binary(Run_index), <<" / "/utf8>>, erlang:integer_to_binary(metamon@config:runs(Cfg)), <<"\n source: "/utf8>>, case Source of {edge_source, I@1} -> <<<<"edge("/utf8, (erlang:integer_to_binary(I@1))/binary>>/binary, ")"/utf8>>; {random_source, S, Sz} -> <<<<<<<<"random(seed="/utf8, (erlang:integer_to_binary(S))/binary>>/binary, ", size="/utf8>>/binary, (erlang:integer_to_binary(Sz))/binary>>/binary, ")"/utf8>> end, <<"\n transforms: "/utf8>>, Transform_names, <<"\n source input:\n "/utf8>>, gleam@string:inspect(Input), <<"\n outputs (source first, then each follow-up):\n"/utf8>>, Outputs_rendered] ). -file("src/metamon/internal/runner.gleam", 398). ?DOC(false). -spec run_edges( list(GOB), integer(), fun((GOB, metamon@internal@report:input_source(), integer()) -> step(GOB)) ) -> outcome(). run_edges(Edges, Index, Body) -> case Edges of [] -> done; [First | Rest] -> case Body(First, {edge_source, Index}, Index) of continue -> run_edges(Rest, Index + 1, Body); {stop, Text} -> {halted, Text} end end. -file("src/metamon/internal/runner.gleam", 439). ?DOC(false). -spec scaled_size(integer(), integer(), integer()) -> integer(). scaled_size(Index, Total, Max_size) -> case Total =< 1 of true -> Max_size; false -> case (Total - 1) of 0 -> 0; Gleam@denominator -> Index * Max_size div Gleam@denominator end end. -file("src/metamon/internal/runner.gleam", 413). ?DOC(false). -spec run_random( metamon@config:config(), metamon@generator:generator(GOE), integer(), integer(), metamon@generator@seed:seed(), fun((GOE, metamon@internal@report:input_source(), integer()) -> step(GOE)) ) -> outcome(). run_random(Cfg, Gen, Start_index, Remaining, S, Body) -> case Remaining =< 0 of true -> done; false -> {Here, Rest_seed} = metamon@generator@seed:split(S), Size = scaled_size( Start_index, metamon@config:runs(Cfg), metamon@config:max_size(Cfg) ), Value = erlang:element( 2, metamon@generator:generate(Gen, Here, Size) ), case Body( Value, {random_source, metamon@generator@seed:state(Here), Size}, Start_index ) of continue -> run_random( Cfg, Gen, Start_index + 1, Remaining - 1, Rest_seed, Body ); {stop, Text} -> {halted, Text} end end. -file("src/metamon/internal/runner.gleam", 448). ?DOC(false). -spec forall_failure( metamon@config:config(), binary(), metamon@generator:generator(GOH), fun((GOH) -> boolean()), integer(), GOH, metamon@internal@report:input_source() ) -> binary(). forall_failure(Cfg, Test_name, _, _, Run_index, Input, Source) -> Report = {failure_report, <<"(plain property)"/utf8>>, Test_name, metamon@generator@seed:state(metamon@config:seed(Cfg)), Run_index, metamon@config:runs(Cfg), 0, false, none, <<""/utf8>>, gleam@string:inspect(Input), <<""/utf8>>, <<""/utf8>>, <<""/utf8>>, Source, false, metamon@annotate:current_annotations(), metamon@annotate:current_footnotes(), {some, metamon@coverage:snapshot()}}, render_for(Cfg, Report). -file("src/metamon/internal/runner.gleam", 485). ?DOC(false). -spec evaluate_spec(morph_spec(GOJ, GOK), fun((GOJ) -> GOK), GOJ) -> evaluation(GOK). evaluate_spec(Spec, F, Input) -> case Spec of {plain_spec, _, T, R} -> Fol_in = (erlang:element(3, T))(Input), Src_out = F(Input), Fol_out = F(Fol_in), {evaluation, gleam@string:inspect(Fol_in), Src_out, Fol_out, (erlang:element(3, R))(Src_out, Fol_out)}; {equivariant_spec, _, Ti, To, R@1} -> Fol_in@1 = (erlang:element(3, Ti))(Input), Raw_src_out = F(Input), Src_out@1 = (erlang:element(3, To))(Raw_src_out), Fol_out@1 = F(Fol_in@1), {evaluation, gleam@string:inspect(Fol_in@1), Src_out@1, Fol_out@1, (erlang:element(3, R@1))(Src_out@1, Fol_out@1)} end. -file("src/metamon/internal/runner.gleam", 517). ?DOC(false). -spec morph_mode_of(morph_spec(any(), any())) -> metamon@internal@report:morph_mode(). morph_mode_of(Spec) -> case Spec of {plain_spec, _, T, _} -> {plain, erlang:element(2, T)}; {equivariant_spec, _, Ti, To, _} -> {equivariant, erlang:element(2, Ti), erlang:element(2, To)} end. -file("src/metamon/internal/runner.gleam", 525). ?DOC(false). -spec relation_name_of(morph_spec(any(), any())) -> binary(). relation_name_of(Spec) -> case Spec of {plain_spec, _, _, R} -> erlang:element(2, R); {equivariant_spec, _, _, _, R@1} -> erlang:element(2, R@1) end. -file("src/metamon/internal/runner.gleam", 532). ?DOC(false). -spec spec_name(morph_spec(any(), any())) -> binary(). spec_name(Spec) -> case Spec of {plain_spec, Name, _, _} -> Name; {equivariant_spec, Name@1, _, _, _} -> Name@1 end. -file("src/metamon/internal/runner.gleam", 73). ?DOC(false). -spec morph_name(morph_spec(any(), any())) -> binary(). morph_name(Spec) -> spec_name(Spec). -file("src/metamon/internal/runner.gleam", 581). ?DOC(false). -spec morph_failure_static( binary(), morph_spec(GPG, GPH), GPG, evaluation(GPH), integer(), integer() ) -> metamon@internal@report:failure_report(). morph_failure_static( Test_name, Spec, Input, Evaluation, Run_index, Config_seed_value ) -> {failure_report, spec_name(Spec), Test_name, Config_seed_value, Run_index, 1, 0, false, {some, morph_mode_of(Spec)}, relation_name_of(Spec), gleam@string:inspect(Input), erlang:element(2, Evaluation), gleam@string:inspect(erlang:element(3, Evaluation)), gleam@string:inspect(erlang:element(4, Evaluation)), {edge_source, 0}, true, metamon@annotate:current_annotations(), metamon@annotate:current_footnotes(), none}. -file("src/metamon/internal/runner.gleam", 631). ?DOC(false). -spec shrink_loop( metamon@generator@tree:tree(GPQ), morph_spec(GPQ, GPS), fun((GPQ) -> GPS), GPQ, integer(), integer() ) -> {GPQ, integer(), boolean()}. shrink_loop(Current_tree, Spec, F, Best, Budget, Done) -> case Done >= Budget of true -> {Best, Done, true}; false -> case metamon@generator@tree:shrinks_find( erlang:element(3, Current_tree), fun(Child) -> Evaluation = evaluate_spec( Spec, F, erlang:element(2, Child) ), not erlang:element(5, Evaluation) end ) of {error, _} -> {Best, Done, false}; {ok, Child@1} -> shrink_loop( Child@1, Spec, F, erlang:element(2, Child@1), Budget, Done + 1 ) end end. -file("src/metamon/internal/runner.gleam", 613). ?DOC(false). -spec shrink_morph_input( metamon@config:config(), metamon@generator:generator(GPL), morph_spec(GPL, GPN), fun((GPL) -> GPN), GPL, metamon@internal@report:input_source() ) -> {GPL, integer(), boolean()}. shrink_morph_input(Cfg, Gen, Spec, F, Current, Source) -> case Source of {edge_source, _} -> {Current, 0, false}; {random_source, Seed_value, Size} -> Initial_tree = metamon@generator:generate( Gen, metamon@generator@seed:seed(Seed_value), Size ), shrink_loop( Initial_tree, Spec, F, Current, metamon@config:shrink_limit(Cfg), 0 ) end. -file("src/metamon/internal/runner.gleam", 539). ?DOC(false). -spec morph_failure( metamon@config:config(), binary(), metamon@generator:generator(GPA), morph_spec(GPA, GPC), fun((GPA) -> GPC), integer(), GPA, metamon@internal@report:input_source(), evaluation(GPC) ) -> binary(). morph_failure( Cfg, Test_name, Gen, Spec, F, Run_index, Input, Source, Evaluation ) -> {Shrunk_input, Shrinks_count, Capped} = shrink_morph_input( Cfg, Gen, Spec, F, Input, Source ), Final_eval = evaluate_spec(Spec, F, Shrunk_input), Report = {failure_report, spec_name(Spec), Test_name, metamon@generator@seed:state(metamon@config:seed(Cfg)), Run_index, metamon@config:runs(Cfg), Shrinks_count, Capped, {some, morph_mode_of(Spec)}, relation_name_of(Spec), gleam@string:inspect(Shrunk_input), erlang:element(2, Final_eval), gleam@string:inspect(erlang:element(3, Final_eval)), gleam@string:inspect(erlang:element(4, Final_eval)), Source, metamon@config:diff_enabled(Cfg), metamon@annotate:current_annotations(), metamon@annotate:current_footnotes(), {some, metamon@coverage:snapshot()}}, _ = Evaluation, render_for(Cfg, Report). -file("src/metamon/internal/runner.gleam", 656). ?DOC(false). -spec reset_state() -> nil. reset_state() -> metamon@annotate:reset(), metamon@coverage:reset(). -file("src/metamon/internal/runner.gleam", 693). ?DOC(false). -spec panic_with(binary()) -> nil. panic_with(Message) -> erlang:error(#{gleam_error => panic, message => Message, file => <>, module => <<"metamon/internal/runner"/utf8>>, function => <<"panic_with"/utf8>>, line => 694}). -file("src/metamon/internal/runner.gleam", 198). ?DOC(false). -spec run_assert_morph(binary(), morph_spec(GMX, GMY), fun((GMX) -> GMY), GMX) -> nil. run_assert_morph(Test_name, Spec, F, Input) -> reset_state(), Evaluation = evaluate_spec(Spec, F, Input), case erlang:element(5, Evaluation) of true -> nil; false -> Report = morph_failure_static( Test_name, Spec, Input, Evaluation, 0, 0 ), panic_with(render_for(metamon@config:default_config(), Report)) end. -file("src/metamon/internal/runner.gleam", 661). ?DOC(false). -spec finish_with_coverage_check( metamon@config:config(), binary(), gleam@option:option(binary()) ) -> nil. finish_with_coverage_check(_, Test_name, Morph_name) -> Snap = metamon@coverage:snapshot(), case metamon@coverage:first_shortfall(Snap) of none -> nil; {some, Req} -> Prefix = case Morph_name of none -> <<<<"× property `"/utf8, Test_name/binary>>/binary, "`"/utf8>>; {some, Name} -> <<<<<<<<"× metamorphic relation `"/utf8, Name/binary>>/binary, "` ("/utf8>>/binary, Test_name/binary>>/binary, ")"/utf8>> end, Message = <<<<<<<<<<<<<<<<<<<<<>/binary, (erlang:element(2, Req))/binary>>/binary, "` hit "/utf8>>/binary, (erlang:integer_to_binary( erlang:element(4, Req) ))/binary>>/binary, "/"/utf8>>/binary, (erlang:integer_to_binary( erlang:element(2, Snap) ))/binary>>/binary, " ("/utf8>>/binary, (gleam_stdlib:float_to_string( metamon@coverage:actual_pct( erlang:element(4, Req), erlang:element(2, Snap) ) ))/binary>>/binary, "%, target≥"/utf8>>/binary, (gleam_stdlib:float_to_string( metamon@coverage:target_pct_of( Req, erlang:element(2, Snap) ) ))/binary>>/binary, "%)"/utf8>>, panic_with(Message) end. -file("src/metamon/internal/runner.gleam", 697). ?DOC(false). -spec take_first(list(GPW), integer()) -> list(GPW). take_first(Items, N) -> case {N, Items} of {N@1, _} when N@1 =< 0 -> []; {_, []} -> []; {N@2, [First | Rest]} -> [First | take_first(Rest, N@2 - 1)] end. -file("src/metamon/internal/runner.gleam", 377). ?DOC(false). -spec iterate_inputs( metamon@config:config(), metamon@generator:generator(GNY), fun((GNY, metamon@internal@report:input_source(), integer()) -> step(GNY)) ) -> outcome(). iterate_inputs(Cfg, Gen, Body) -> Edges = begin _pipe = metamon@generator:edges_of(Gen), take_first(_pipe, metamon@config:max_edges(Cfg)) end, Edge_count = erlang:length(Edges), Run_total = metamon@config:runs(Cfg), case run_edges(Edges, 0, Body) of {halted, Text} -> {halted, Text}; done -> Remaining = Run_total - Edge_count, case Remaining =< 0 of true -> done; false -> run_random( Cfg, Gen, Edge_count, Remaining, metamon@config:seed(Cfg), Body ) end end. -file("src/metamon/internal/runner.gleam", 226). ?DOC(false). -spec run_forall_morph_n( metamon@config:config(), binary(), metamon@generator:generator(GNB), list(metamon@transform:transform(GNB)), metamon@relation:relation_n(GNF), fun((GNB) -> GNF) ) -> nil. run_forall_morph_n(Cfg, Test_name, Gen, Transforms, Rel, F) -> reset_state(), case iterate_inputs( Cfg, Gen, fun(Input, Source, Run_index) -> Outputs = compute_n_outputs(Transforms, F, Input), case (erlang:element(3, Rel))(Outputs) of true -> continue; false -> {stop, morph_n_failure( Cfg, Test_name, Transforms, Rel, Run_index, Input, Source, Outputs )} end end ) of done -> finish_with_coverage_check( Cfg, Test_name, {some, erlang:element(2, Rel)} ); {halted, Text} -> panic_with(Text) end. -file("src/metamon/internal/runner.gleam", 321). ?DOC(false). -spec run_forall_morphs( metamon@config:config(), binary(), metamon@generator:generator(GNS), list(morph_spec(GNS, GNU)), fun((GNS) -> GNU) ) -> nil. run_forall_morphs(Cfg, Test_name, Gen, Specs, F) -> Collected = gleam@list:fold( Specs, [], fun(Reports, Spec) -> reset_state(), Outcome = iterate_inputs( Cfg, Gen, fun(Input, Source, Run_index) -> Evaluation = evaluate_spec(Spec, F, Input), case erlang:element(5, Evaluation) of true -> continue; false -> {stop, morph_failure( Cfg, Test_name, Gen, Spec, F, Run_index, Input, Source, Evaluation )} end end ), case Outcome of done -> Reports; {halted, Text} -> [Text | Reports] end end ), case Collected of [] -> nil; Failures -> panic_with( <<"× one or more metamorphic relations failed\n\n"/utf8, (gleam@string:join( lists:reverse(Failures), <<"\n\n---\n\n"/utf8>> ))/binary>> ) end. -file("src/metamon/internal/runner.gleam", 707). ?DOC(false). -spec load_regression_for(metamon@config:config(), binary()) -> list(metamon@internal@regression:entry()). load_regression_for(Cfg, Mr_name) -> case metamon@config:regression_file(Cfg) of none -> []; {some, Path} -> case simplifile:read(Path) of {ok, Content} -> _pipe = metamon@internal@regression:parse(Content), gleam@list:filter( _pipe, fun(Entry) -> erlang:element(2, Entry) =:= Mr_name end ); {error, _} -> [] end end. -file("src/metamon/internal/runner.gleam", 830). ?DOC(false). -spec list_at(list(GQM), integer()) -> gleam@option:option(GQM). list_at(Items, Index) -> case {Items, Index} of {[], _} -> none; {[First | _], 0} -> {some, First}; {[_ | Rest], I} -> list_at(Rest, I - 1) end. -file("src/metamon/internal/runner.gleam", 808). ?DOC(false). -spec reproduce_entry_value( metamon@generator:generator(GQK), metamon@internal@regression:entry() ) -> GQK. reproduce_entry_value(Gen, Entry) -> case erlang:element(6, Entry) of {some, I} -> case list_at(metamon@generator:edges_of(Gen), I) of {some, Value} -> Value; none -> erlang:element( 2, metamon@generator:generate( Gen, metamon@generator@seed:seed( erlang:element(3, Entry) ), erlang:element(5, Entry) ) ) end; none -> erlang:element( 2, metamon@generator:generate( Gen, metamon@generator@seed:seed(erlang:element(3, Entry)), erlang:element(5, Entry) ) ) end. -file("src/metamon/internal/runner.gleam", 838). ?DOC(false). -spec replay_failure_message( binary(), metamon@internal@regression:entry(), any() ) -> binary(). replay_failure_message(Mr_name, Entry, Value) -> erlang:list_to_binary( [<<"× regression replay for `"/utf8>>, Mr_name, <<"` failed\n recorded: "/utf8>>, erlang:element(8, Entry), <<"\n config_seed: "/utf8>>, erlang:integer_to_binary(erlang:element(3, Entry)), <<"\n run_index: "/utf8>>, erlang:integer_to_binary(erlang:element(4, Entry)), <<"\n size: "/utf8>>, erlang:integer_to_binary(erlang:element(5, Entry)), <<"\n reproduced input:\n "/utf8>>, gleam@string:inspect(Value), case erlang:element(7, Entry) of {some, N} -> <<"\n note:\n "/utf8, N/binary>>; none -> <<""/utf8>> end] ). -file("src/metamon/internal/runner.gleam", 771). ?DOC(false). -spec replay_regression_for_forall( metamon@generator:generator(GQB), list(metamon@internal@regression:entry()), fun((GQB) -> boolean()) ) -> outcome(). replay_regression_for_forall(Gen, Entries, Property) -> case Entries of [] -> done; [Entry | Rest] -> Value = reproduce_entry_value(Gen, Entry), case Property(Value) of true -> replay_regression_for_forall(Gen, Rest, Property); false -> {halted, replay_failure_message( <<"(plain property)"/utf8>>, Entry, Value )} end end. -file("src/metamon/internal/runner.gleam", 789). ?DOC(false). -spec replay_regression_for_morph( metamon@generator:generator(GQE), morph_spec(GQE, GQG), fun((GQE) -> GQG), list(metamon@internal@regression:entry()) ) -> outcome(). replay_regression_for_morph(Gen, Spec, F, Entries) -> case Entries of [] -> done; [Entry | Rest] -> Value = reproduce_entry_value(Gen, Entry), Evaluation = evaluate_spec(Spec, F, Value), case erlang:element(5, Evaluation) of true -> replay_regression_for_morph(Gen, Spec, F, Rest); false -> {halted, replay_failure_message(spec_name(Spec), Entry, Value)} end end. -file("src/metamon/internal/runner.gleam", 722). ?DOC(false). -spec record_regression_for( metamon@config:config(), binary(), metamon@internal@report:input_source(), any() ) -> nil. record_regression_for(Cfg, Mr_name, Source, Input) -> case metamon@config:regression_file(Cfg) of none -> nil; {some, Path} -> Edge_index = case Source of {edge_source, I} -> {some, I}; {random_source, _, _} -> none end, {Seed_value, Size} = case Source of {edge_source, _} -> {metamon@generator@seed:state(metamon@config:seed(Cfg)), 0}; {random_source, S, Sz} -> {S, Sz} end, Run_index = case Source of {edge_source, I@1} -> I@1; {random_source, _, _} -> 0 end, Entry = {entry, Mr_name, Seed_value, Run_index, Size, Edge_index, {some, gleam@string:inspect(Input)}, erlang:integer_to_binary(metamon_ffi:now_microseconds())}, Existing = case simplifile:read(Path) of {ok, C} -> C; {error, _} -> <<""/utf8>> end, Separator = case Existing of <<""/utf8>> -> <<""/utf8>>; _ -> <<"\n"/utf8>> end, _ = simplifile:write( Path, <<<>/binary, (metamon@internal@regression:render(Entry))/binary>> ), nil end. -file("src/metamon/internal/runner.gleam", 108). ?DOC(false). -spec forall_step( metamon@config:config(), binary(), metamon@generator:generator(GME), fun((GME) -> boolean()), GME, metamon@internal@report:input_source(), integer() ) -> step(GME). forall_step(Cfg, Test_name, Gen, Property, Input, Source, Run_index) -> case Property(Input) of true -> continue; false -> record_regression_for( Cfg, <<"(plain property)"/utf8>>, Source, Input ), {stop, forall_failure( Cfg, Test_name, Gen, Property, Run_index, Input, Source )} end. -file("src/metamon/internal/runner.gleam", 92). ?DOC(false). -spec drive_forall( metamon@config:config(), binary(), metamon@generator:generator(GMC), fun((GMC) -> boolean()) ) -> nil. drive_forall(Cfg, Test_name, Gen, Property) -> Outcome = iterate_inputs( Cfg, Gen, fun(Input, Source, Run_index) -> forall_step(Cfg, Test_name, Gen, Property, Input, Source, Run_index) end ), case Outcome of done -> finish_with_coverage_check(Cfg, Test_name, none); {halted, Report_text} -> panic_with(Report_text) end. -file("src/metamon/internal/runner.gleam", 78). ?DOC(false). -spec run_forall( metamon@config:config(), binary(), metamon@generator:generator(GMA), fun((GMA) -> boolean()) ) -> nil. run_forall(Cfg, Test_name, Gen, Property) -> reset_state(), Regression_entries = load_regression_for(Cfg, <<"(plain property)"/utf8>>), case replay_regression_for_forall(Gen, Regression_entries, Property) of {halted, Text} -> panic_with(Text); done -> drive_forall(Cfg, Test_name, Gen, Property) end. -file("src/metamon/internal/runner.gleam", 167). ?DOC(false). -spec morph_step( metamon@config:config(), binary(), metamon@generator:generator(GMR), morph_spec(GMR, GMT), fun((GMR) -> GMT), GMR, metamon@internal@report:input_source(), integer() ) -> step(GMR). morph_step(Cfg, Test_name, Gen, Spec, F, Input, Source, Run_index) -> Evaluation = evaluate_spec(Spec, F, Input), case erlang:element(5, Evaluation) of true -> continue; false -> record_regression_for(Cfg, spec_name(Spec), Source, Input), {stop, morph_failure( Cfg, Test_name, Gen, Spec, F, Run_index, Input, Source, Evaluation )} end. -file("src/metamon/internal/runner.gleam", 150). ?DOC(false). -spec drive_morph( metamon@config:config(), binary(), metamon@generator:generator(GMM), morph_spec(GMM, GMO), fun((GMM) -> GMO) ) -> nil. drive_morph(Cfg, Test_name, Gen, Spec, F) -> Outcome = iterate_inputs( Cfg, Gen, fun(Input, Source, Run_index) -> morph_step(Cfg, Test_name, Gen, Spec, F, Input, Source, Run_index) end ), case Outcome of done -> finish_with_coverage_check(Cfg, Test_name, {some, spec_name(Spec)}); {halted, Report_text} -> panic_with(Report_text) end. -file("src/metamon/internal/runner.gleam", 135). ?DOC(false). -spec run_forall_morph( metamon@config:config(), binary(), metamon@generator:generator(GMH), morph_spec(GMH, GMJ), fun((GMH) -> GMJ) ) -> nil. run_forall_morph(Cfg, Test_name, Gen, Spec, F) -> reset_state(), Entries = load_regression_for(Cfg, spec_name(Spec)), case replay_regression_for_morph(Gen, Spec, F, Entries) of {halted, Text} -> panic_with(Text); done -> drive_morph(Cfg, Test_name, Gen, Spec, F) end.