aboutsummaryrefslogtreecommitdiff
path: root/aoc2023/build/packages/adglent/src/showtime_ffi.erl
diff options
context:
space:
mode:
authorJ.J <thechairman@thechairman.info>2024-05-30 21:50:02 -0400
committerJ.J <thechairman@thechairman.info>2024-05-30 21:50:02 -0400
commit612fd986ab1e00b6d34dc1937136250e08e89325 (patch)
treea3c93952040c6afdf348b5831619a45db7ba0a2e /aoc2023/build/packages/adglent/src/showtime_ffi.erl
parent231c2b688d1e6cf0846d46e883da30e042a9c6cf (diff)
downloadgleam_aoc-612fd986ab1e00b6d34dc1937136250e08e89325.tar.gz
gleam_aoc-612fd986ab1e00b6d34dc1937136250e08e89325.zip
cleanup
Diffstat (limited to 'aoc2023/build/packages/adglent/src/showtime_ffi.erl')
-rw-r--r--aoc2023/build/packages/adglent/src/showtime_ffi.erl187
1 files changed, 187 insertions, 0 deletions
diff --git a/aoc2023/build/packages/adglent/src/showtime_ffi.erl b/aoc2023/build/packages/adglent/src/showtime_ffi.erl
new file mode 100644
index 0000000..3259623
--- /dev/null
+++ b/aoc2023/build/packages/adglent/src/showtime_ffi.erl
@@ -0,0 +1,187 @@
+-module(showtime_ffi).
+
+-export([run_test/4, functions/0, capture_output/1, gleam_error/1]).
+
+gleam_error(Value) ->
+ erlang:error(#{
+ gleam_error => let_assert,
+ message => <<"Assertion pattern match failed"/utf8>>,
+ value => Value,
+ module => <<"this/is/not/used"/utf8>>,
+ function => <<"gleam_error"/utf8>>,
+ % Not used
+ line => 0
+ }).
+
+start_output_capture(Capture) ->
+ OldGroupLeader = group_leader(),
+ CapturePid = spawn(showtime_ffi, capture_output, [{[], {OldGroupLeader, Capture}}]),
+ group_leader(CapturePid, self()),
+ {CapturePid, OldGroupLeader}.
+
+stop_output_capture({CapturePid, OldGroupLeader}) ->
+ group_leader(OldGroupLeader, self()),
+ CapturePid ! {capture_done, self()},
+ receive
+ Buffer ->
+ Buffer
+ end.
+
+capture_output({Buffer, {OldGroupLeader, Capture}}) ->
+ receive
+ {io_request, From, ReplyAs, {put_chars, unicode, BitString}} ->
+ case Capture of
+ yes ->
+ From ! {io_reply, ReplyAs, ok},
+ capture_output({[BitString | Buffer], {OldGroupLeader, Capture}});
+ mixed ->
+ OldGroupLeader ! {io_request, From, ReplyAs, {put_chars, unicode, BitString}},
+ capture_output({[BitString | Buffer], {OldGroupLeader, Capture}});
+ no ->
+ OldGroupLeader ! {io_request, From, ReplyAs, {put_chars, unicode, BitString}},
+ capture_output({Buffer, {OldGroupLeader, Capture}})
+ end;
+ {capture_done, SenderPid} ->
+ SenderPid ! Buffer;
+ OtherMessage ->
+ OldGroupLeader ! OtherMessage,
+ capture_output({Buffer, {OldGroupLeader, Capture}})
+ end.
+
+run_test(Module, Function, IgnoreTags, Capture) ->
+ OutputCapture = start_output_capture(Capture),
+ try
+ Result = apply(Module, Function, []),
+ {ResultType, FinalResult} =
+ case Result of
+ {test, {meta, _Description, Tags}, TestFun} ->
+ case
+ lists:any(
+ fun(Tag) ->
+ lists:any(fun(IgnoreTag) -> IgnoreTag == Tag end, IgnoreTags)
+ end,
+ Tags
+ )
+ of
+ true ->
+ {ignored, ignore};
+ false ->
+ {test_function_return, TestFun()}
+ end;
+ DirectResult ->
+ {test_function_return, DirectResult}
+ end,
+ OutputCaptureBuffer = stop_output_capture(OutputCapture),
+ case ResultType of
+ ignored -> {ok, {ResultType, FinalResult}};
+ _ -> {ok, {ResultType, FinalResult, OutputCaptureBuffer}}
+ end
+ catch
+ Class:Reason:Stacktrace ->
+ GleamReason =
+ case Reason of
+ {Assertion, ReasonList} ->
+ ErlangReasonList =
+ lists:map(
+ fun(ReasonDetail) ->
+ case ReasonDetail of
+ {line, LineNo} ->
+ {reason_line, LineNo};
+ {expression, List} ->
+ {expression, list_to_binary(List)};
+ {module, ModuleAtom} ->
+ {module, atom_to_binary(ModuleAtom)};
+ {pattern, Pattern} ->
+ {pattern, list_to_binary(Pattern)};
+ Other ->
+ Other
+ end
+ end,
+ ReasonList
+ ),
+ GleamAssertionType =
+ case Assertion of
+ assertEqual ->
+ assert_equal;
+ assertNotEqual ->
+ assert_not_equal;
+ assertMatch ->
+ assert_match;
+ OtherAssertionType ->
+ OtherAssertionType
+ end,
+ {GleamAssertionType, ErlangReasonList};
+ #{
+ function := GleamFunction,
+ gleam_error := GleamError,
+ line := Line,
+ message := Message,
+ module := GleamModule,
+ value := Value
+ } ->
+ case Value of
+ {error, {OkValue, _, _, _}} when OkValue == not_eq; OkValue == eq ->
+ {gleam_error,
+ {GleamError, GleamModule, GleamFunction, Line, Message, Value}};
+ {error, {OkValue, _, _}} when OkValue == is_ok; OkValue == is_error ->
+ {gleam_error,
+ {GleamError, GleamModule, GleamFunction, Line, Message, Value}};
+ {error, {OkValue, _}} when OkValue == fail ->
+ {gleam_error,
+ {GleamError, GleamModule, GleamFunction, Line, Message, Value}};
+ _ ->
+ {gleam_assert, Value, Line}
+ end;
+ OtherReason ->
+ {generic_exception, OtherReason}
+ end,
+ GleamClass =
+ case Class of
+ error ->
+ erlang_error;
+ Other ->
+ Other
+ end,
+ GleamTraceList =
+ lists:map(
+ fun(Trace) ->
+ case Trace of
+ {ModuleName, FunctionName, Arity, ExtraInfoList} ->
+ {trace_module, atom_to_binary(ModuleName),
+ atom_to_binary(FunctionName), map_arity(Arity),
+ map_extra_info_list(ExtraInfoList)};
+ {FunctionName, Arity, ExtraInfoList} ->
+ {trace, atom_to_binary(FunctionName), map_arity(Arity),
+ map_extra_info_list(ExtraInfoList)}
+ end
+ end,
+ Stacktrace
+ ),
+ OutputCaptureBufferCatch = stop_output_capture(OutputCapture),
+ {error,
+ {erlang_exception, GleamClass, GleamReason, {trace_list, GleamTraceList},
+ OutputCaptureBufferCatch}}
+ end.
+
+map_extra_info_list(ExtraInfoList) ->
+ lists:map(
+ fun(ExtraInfo) ->
+ case ExtraInfo of
+ {file, FileNameList} -> {file, list_to_binary(FileNameList)};
+ Other -> Other
+ end
+ end,
+ ExtraInfoList
+ ).
+
+map_arity(Arity) ->
+ if
+ is_list(Arity) ->
+ {arg_list, Arity};
+ is_integer(Arity) ->
+ {num, Arity}
+ end.
+
+functions() ->
+ Funs = module_info(exports),
+ Funs.