From 6d5241e222c05ae39b9955dbbf6d453adf1ef01b Mon Sep 17 00:00:00 2001 From: Hayleigh Thompson Date: Sat, 17 Aug 2024 11:53:40 +0100 Subject: [PATCH] :fire: Remove old vendored gleeunit code. --- test/eunit_progress.erl | 592 ------------------------ test/gleam_community_maths_test_ffi.erl | 40 -- test/gleam_community_maths_test_ffi.mjs | 103 ----- 3 files changed, 735 deletions(-) delete mode 100644 test/eunit_progress.erl delete mode 100644 test/gleam_community_maths_test_ffi.erl delete mode 100755 test/gleam_community_maths_test_ffi.mjs diff --git a/test/eunit_progress.erl b/test/eunit_progress.erl deleted file mode 100644 index faef6b5..0000000 --- a/test/eunit_progress.erl +++ /dev/null @@ -1,592 +0,0 @@ -%% eunit_formatters https://github.com/seancribbs/eunit_formatters -%% Changes made to the original code: -%% - Embedded binomial_heap.erl file contents into current file. -%% - ignore warnings for heap implementation to keep complete implementation. -%% - removed "namespaced_dicts" dependant preprocessor directive, -%% as it does not apply for our project, we just assume OTP version >= 17. -%% This is because the previous verison uses rebar, and we won't do that. - -%% Copyright 2014 Sean Cribbs -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. - - -%% @doc A listener/reporter for eunit that prints '.' for each -%% success, 'F' for each failure, and 'E' for each error. It can also -%% optionally summarize the failures at the end. --compile({nowarn_unused_function, [insert/2, to_list/1, to_list/2, size/1]}). --module(eunit_progress). --behaviour(eunit_listener). --define(NOTEST, true). --include_lib("eunit/include/eunit.hrl"). - --define(RED, "\e[0;31m"). --define(GREEN, "\e[0;32m"). --define(YELLOW, "\e[0;33m"). --define(WHITE, "\e[0;37m"). --define(CYAN, "\e[0;36m"). --define(RESET, "\e[0m"). - --record(node,{ - rank = 0 :: non_neg_integer(), - key :: term(), - value :: term(), - children = new() :: binomial_heap() - }). - --export_type([binomial_heap/0, heap_node/0]). --type binomial_heap() :: [ heap_node() ]. --type heap_node() :: #node{}. - -%% eunit_listener callbacks --export([ - init/1, - handle_begin/3, - handle_end/3, - handle_cancel/3, - terminate/2, - start/0, - start/1 - ]). - -%% -- binomial_heap.erl content start -- - --record(state, { - status = dict:new() :: euf_dict(), - failures = [] :: [[pos_integer()]], - skips = [] :: [[pos_integer()]], - timings = new() :: binomial_heap(), - colored = true :: boolean(), - profile = false :: boolean() - }). - --type euf_dict() :: dict:dict(). - --spec new() -> binomial_heap(). -new() -> - []. - -% Inserts a new pair into the heap (or creates a new heap) --spec insert(term(), term()) -> binomial_heap(). -insert(Key,Value) -> - insert(Key,Value,[]). - --spec insert(term(), term(), binomial_heap()) -> binomial_heap(). -insert(Key,Value,Forest) -> - insTree(#node{key=Key,value=Value},Forest). - -% Merges two heaps --spec merge(binomial_heap(), binomial_heap()) -> binomial_heap(). -merge(TS1,[]) when is_list(TS1) -> TS1; -merge([],TS2) when is_list(TS2) -> TS2; -merge([#node{rank=R1}=T1|TS1]=F1,[#node{rank=R2}=T2|TS2]=F2) -> - if - R1 < R2 -> - [T1 | merge(TS1,F2)]; - R2 < R1 -> - [T2 | merge(F1, TS2)]; - true -> - insTree(link(T1,T2),merge(TS1,TS2)) - end. - -% Deletes the top entry from the heap and returns it --spec delete(binomial_heap()) -> {{term(), term()}, binomial_heap()}. -delete(TS) -> - {#node{key=Key,value=Value,children=TS1},TS2} = getMin(TS), - {{Key,Value},merge(lists:reverse(TS1),TS2)}. - -% Turns the heap into list in heap order --spec to_list(binomial_heap()) -> [{term(), term()}]. -to_list([]) -> []; -to_list(List) when is_list(List) -> - to_list([],List). -to_list(Acc, []) -> - lists:reverse(Acc); -to_list(Acc,Forest) -> - {Next, Trees} = delete(Forest), - to_list([Next|Acc], Trees). - -% Take N elements from the top of the heap --spec take(non_neg_integer(), binomial_heap()) -> [{term(), term()}]. -take(N,Trees) when is_integer(N), is_list(Trees) -> - take(N,Trees,[]). -take(0,_Trees,Acc) -> - lists:reverse(Acc); -take(_N,[],Acc)-> - lists:reverse(Acc); -take(N,Trees,Acc) -> - {Top,T2} = delete(Trees), - take(N-1,T2,[Top|Acc]). - -% Get an estimate of the size based on the binomial property --spec size(binomial_heap()) -> non_neg_integer(). -size(Forest) -> - erlang:trunc(lists:sum([math:pow(2,R) || #node{rank=R} <- Forest])). - -%% Private API --spec link(heap_node(), heap_node()) -> heap_node(). -link(#node{rank=R,key=X1,children=C1}=T1,#node{key=X2,children=C2}=T2) -> - case X1 < X2 of - true -> - T1#node{rank=R+1,children=[T2|C1]}; - _ -> - T2#node{rank=R+1,children=[T1|C2]} - end. - -insTree(Tree, []) -> - [Tree]; -insTree(#node{rank=R1}=T1, [#node{rank=R2}=T2|Rest] = TS) -> - case R1 < R2 of - true -> - [T1|TS]; - _ -> - insTree(link(T1,T2),Rest) - end. - -getMin([T]) -> - {T,[]}; -getMin([#node{key=K} = T|TS]) -> - {#node{key=K1} = T1,TS1} = getMin(TS), - case K < K1 of - true -> {T,TS}; - _ -> {T1,[T|TS1]} - end. - -%% -- binomial_heap.erl content end -- - -%% Startup -start() -> - start([]). - -start(Options) -> - eunit_listener:start(?MODULE, Options). - -%%------------------------------------------ -%% eunit_listener callbacks -%%------------------------------------------ -init(Options) -> - #state{colored=proplists:get_bool(colored, Options), - profile=proplists:get_bool(profile, Options)}. - -handle_begin(group, Data, St) -> - GID = proplists:get_value(id, Data), - Dict = St#state.status, - St#state{status=dict:store(GID, orddict:from_list([{type, group}|Data]), Dict)}; -handle_begin(test, Data, St) -> - TID = proplists:get_value(id, Data), - Dict = St#state.status, - St#state{status=dict:store(TID, orddict:from_list([{type, test}|Data]), Dict)}. - -handle_end(group, Data, St) -> - St#state{status=merge_on_end(Data, St#state.status)}; -handle_end(test, Data, St) -> - NewStatus = merge_on_end(Data, St#state.status), - St1 = print_progress(Data, St), - St2 = record_timing(Data, St1), - St2#state{status=NewStatus}. - -handle_cancel(_, Data, #state{status=Status, skips=Skips}=St) -> - Status1 = merge_on_end(Data, Status), - ID = proplists:get_value(id, Data), - St#state{status=Status1, skips=[ID|Skips]}. - -terminate({ok, Data}, St) -> - print_failures(St), - print_pending(St), - print_profile(St), - print_timing(St), - print_results(Data, St); -terminate({error, Reason}, St) -> - io:nl(), io:nl(), - print_colored(io_lib:format("Eunit failed: ~25p~n", [Reason]), ?RED, St), - sync_end(error). - -sync_end(Result) -> - receive - {stop, Reference, ReplyTo} -> - ReplyTo ! {result, Reference, Result}, - ok - end. - -%%------------------------------------------ -%% Print and collect information during run -%%------------------------------------------ -print_progress(Data, St) -> - TID = proplists:get_value(id, Data), - case proplists:get_value(status, Data) of - ok -> - print_progress_success(St), - St; - {skipped, _Reason} -> - print_progress_skipped(St), - St#state{skips=[TID|St#state.skips]}; - {error, Exception} -> - print_progress_failed(Exception, St), - St#state{failures=[TID|St#state.failures]} - end. - -record_timing(Data, State=#state{timings=T, profile=true}) -> - TID = proplists:get_value(id, Data), - case lists:keyfind(time, 1, Data) of - {time, Int} -> - %% It's a min-heap, so we insert negative numbers instead - %% of the actuals and normalize when we report on them. - T1 = insert(-Int, TID, T), - State#state{timings=T1}; - false -> - State - end; -record_timing(_Data, State) -> - State. - -print_progress_success(St) -> - print_colored(".", ?GREEN, St). - -print_progress_skipped(St) -> - print_colored("*", ?YELLOW, St). - -print_progress_failed(_Exc, St) -> - print_colored("F", ?RED, St). - -merge_on_end(Data, Dict) -> - ID = proplists:get_value(id, Data), - dict:update(ID, - fun(Old) -> - orddict:merge(fun merge_data/3, Old, orddict:from_list(Data)) - end, Dict). - -merge_data(_K, undefined, X) -> X; -merge_data(_K, X, undefined) -> X; -merge_data(_K, _, X) -> X. - -%%------------------------------------------ -%% Print information at end of run -%%------------------------------------------ -print_failures(#state{failures=[]}) -> - ok; -print_failures(#state{failures=Fails}=State) -> - io:nl(), - io:fwrite("Failures:~n",[]), - lists:foldr(print_failure_fun(State), 1, Fails), - ok. - -print_failure_fun(#state{status=Status}=State) -> - fun(Key, Count) -> - TestData = dict:fetch(Key, Status), - TestId = format_test_identifier(TestData), - io:fwrite("~n ~p) ~ts~n", [Count, TestId]), - print_failure_reason(proplists:get_value(status, TestData), - proplists:get_value(output, TestData), - State), - io:nl(), - Count + 1 - end. - -print_failure_reason({skipped, Reason}, _Output, State) -> - print_colored(io_lib:format(" ~ts~n", [format_pending_reason(Reason)]), - ?RED, State); -print_failure_reason({error, {_Class, Term, Stack}}, Output, State) when - is_tuple(Term), tuple_size(Term) == 2, is_list(element(2, Term)) -> - print_assertion_failure(Term, Stack, Output, State), - print_failure_output(5, Output, State); -print_failure_reason({error, {error, Error, Stack}}, Output, State) when is_list(Stack) -> - print_colored(indent(5, "Failure: ~p~n", [Error]), ?RED, State), - print_stack(Stack, State), - print_failure_output(5, Output, State); -print_failure_reason({error, Reason}, Output, State) -> - print_colored(indent(5, "Failure: ~p~n", [Reason]), ?RED, State), - print_failure_output(5, Output, State). - -print_stack(Stack, State) -> - print_colored(indent(5, "Stacktrace:~n", []), ?CYAN, State), - print_stackframes(Stack, State). -print_stackframes([{eunit_test, _, _, _} | Stack], State) -> - print_stackframes(Stack, State); -print_stackframes([{eunit_proc, _, _, _} | Stack], State) -> - print_stackframes(Stack, State); -print_stackframes([{Module, Function, _Arity, _Location} | Stack], State) -> - print_colored(indent(7, "~p.~p~n", [Module, Function]), ?CYAN, State), - print_stackframes(Stack, State); -print_stackframes([], _State) -> - ok. - - -print_failure_output(_, <<>>, _) -> ok; -print_failure_output(_, undefined, _) -> ok; -print_failure_output(Indent, Output, State) -> - print_colored(indent(Indent, "Output: ~ts", [Output]), ?CYAN, State). - -print_assertion_failure({Type, Props}, Stack, Output, State) -> - FailureDesc = format_assertion_failure(Type, Props, 5), - {M,F,A,Loc} = lists:last(Stack), - LocationText = io_lib:format(" %% ~ts:~p:in `~ts`", [proplists:get_value(file, Loc), - proplists:get_value(line, Loc), - format_function_name(M,F,A)]), - print_colored(FailureDesc, ?RED, State), - io:nl(), - print_colored(LocationText, ?CYAN, State), - io:nl(), - print_failure_output(5, Output, State), - io:nl(). - -print_pending(#state{skips=[]}) -> - ok; -print_pending(#state{status=Status, skips=Skips}=State) -> - io:nl(), - io:fwrite("Pending:~n", []), - lists:foreach(fun(ID) -> - Info = dict:fetch(ID, Status), - case proplists:get_value(reason, Info) of - undefined -> - ok; - Reason -> - print_pending_reason(Reason, Info, State) - end - end, lists:reverse(Skips)), - io:nl(). - -print_pending_reason(Reason0, Data, State) -> - Text = case proplists:get_value(type, Data) of - group -> - io_lib:format(" ~ts~n", [proplists:get_value(desc, Data)]); - test -> - io_lib:format(" ~ts~n", [format_test_identifier(Data)]) - end, - Reason = io_lib:format(" %% ~ts~n", [format_pending_reason(Reason0)]), - print_colored(Text, ?YELLOW, State), - print_colored(Reason, ?CYAN, State). - -print_profile(#state{timings=T, status=Status, profile=true}=State) -> - TopN = take(10, T), - TopNTime = abs(lists:sum([ Time || {Time, _} <- TopN ])), - TLG = dict:fetch([], Status), - TotalTime = proplists:get_value(time, TLG), - if TotalTime =/= undefined andalso TotalTime > 0 andalso TopN =/= [] -> - TopNPct = (TopNTime / TotalTime) * 100, - io:nl(), io:nl(), - io:fwrite("Top ~p slowest tests (~ts, ~.1f% of total time):", [length(TopN), format_time(TopNTime), TopNPct]), - lists:foreach(print_timing_fun(State), TopN), - io:nl(); - true -> ok - end; -print_profile(#state{profile=false}) -> - ok. - -print_timing(#state{status=Status}) -> - TLG = dict:fetch([], Status), - Time = proplists:get_value(time, TLG), - io:nl(), - io:fwrite("Finished in ~ts~n", [format_time(Time)]), - ok. - -print_results(Data, State) -> - Pass = proplists:get_value(pass, Data, 0), - Fail = proplists:get_value(fail, Data, 0), - Skip = proplists:get_value(skip, Data, 0), - Cancel = proplists:get_value(cancel, Data, 0), - Total = Pass + Fail + Skip + Cancel, - {Color, Result} = if Fail > 0 -> {?RED, error}; - Skip > 0; Cancel > 0 -> {?YELLOW, error}; - Pass =:= 0 -> {?YELLOW, ok}; - true -> {?GREEN, ok} - end, - print_results(Color, Total, Fail, Skip, Cancel, State), - sync_end(Result). - -print_results(Color, 0, _, _, _, State) -> - print_colored(Color, "0 tests\n", State); -print_results(Color, Total, Fail, Skip, Cancel, State) -> - SkipText = format_optional_result(Skip, "skipped"), - CancelText = format_optional_result(Cancel, "cancelled"), - Text = io_lib:format("~p tests, ~p failures~ts~ts~n", [Total, Fail, SkipText, CancelText]), - print_colored(Text, Color, State). - -print_timing_fun(#state{status=Status}=State) -> - fun({Time, Key}) -> - TestData = dict:fetch(Key, Status), - TestId = format_test_identifier(TestData), - io:nl(), - io:fwrite(" ~ts~n", [TestId]), - print_colored([" "|format_time(abs(Time))], ?CYAN, State) - end. - -%%------------------------------------------ -%% Print to the console with the given color -%% if enabled. -%%------------------------------------------ -print_colored(Text, Color, #state{colored=true}) -> - io:fwrite("~s~ts~s", [Color, Text, ?RESET]); -print_colored(Text, _Color, #state{colored=false}) -> - io:fwrite("~ts", [Text]). - -%%------------------------------------------ -%% Generic data formatters -%%------------------------------------------ -format_function_name(M, F, A) -> - io_lib:format("~ts:~ts/~p", [M, F, A]). - -format_optional_result(0, _) -> - []; -format_optional_result(Count, Text) -> - io_lib:format(", ~p ~ts", [Count, Text]). - -format_test_identifier(Data) -> - {Mod, Fun, Arity} = proplists:get_value(source, Data), - Line = case proplists:get_value(line, Data) of - 0 -> ""; - L -> io_lib:format(":~p", [L]) - end, - Desc = case proplists:get_value(desc, Data) of - undefined -> ""; - DescText -> io_lib:format(": ~ts", [DescText]) - end, - io_lib:format("~ts~ts~ts", [format_function_name(Mod, Fun, Arity), Line, Desc]). - -format_time(undefined) -> - "? seconds"; -format_time(Time) -> - io_lib:format("~.3f seconds", [Time / 1000]). - -format_pending_reason({module_not_found, M}) -> - io_lib:format("Module '~ts' missing", [M]); -format_pending_reason({no_such_function, {M,F,A}}) -> - io_lib:format("Function ~ts undefined", [format_function_name(M,F,A)]); -format_pending_reason({exit, Reason}) -> - io_lib:format("Related process exited with reason: ~p", [Reason]); -format_pending_reason(Reason) -> - io_lib:format("Unknown error: ~p", [Reason]). - -%% @doc Formats all the known eunit assertions, you're on your own if -%% you make an assertion yourself. -format_assertion_failure(Type, Props, I) when Type =:= assertion_failed - ; Type =:= assert -> - Keys = proplists:get_keys(Props), - HasEUnitProps = ([expression, value] -- Keys) =:= [], - HasHamcrestProps = ([expected, actual, matcher] -- Keys) =:= [], - if - HasEUnitProps -> - [indent(I, "Failure: ?assert(~ts)~n", [proplists:get_value(expression, Props)]), - indent(I, " expected: true~n", []), - case proplists:get_value(value, Props) of - false -> - indent(I, " got: false", []); - {not_a_boolean, V} -> - indent(I, " got: ~p", [V]) - end]; - HasHamcrestProps -> - [indent(I, "Failure: ?assertThat(~p)~n", [proplists:get_value(matcher, Props)]), - indent(I, " expected: ~p~n", [proplists:get_value(expected, Props)]), - indent(I, " got: ~p", [proplists:get_value(actual, Props)])]; - true -> - [indent(I, "Failure: unknown assert: ~p", [Props])] - end; - -format_assertion_failure(Type, Props, I) when Type =:= assertMatch_failed - ; Type =:= assertMatch -> - Expr = proplists:get_value(expression, Props), - Pattern = proplists:get_value(pattern, Props), - Value = proplists:get_value(value, Props), - [indent(I, "Failure: ?assertMatch(~ts, ~ts)~n", [Pattern, Expr]), - indent(I, " expected: = ~ts~n", [Pattern]), - indent(I, " got: ~p", [Value])]; - -format_assertion_failure(Type, Props, I) when Type =:= assertNotMatch_failed - ; Type =:= assertNotMatch -> - Expr = proplists:get_value(expression, Props), - Pattern = proplists:get_value(pattern, Props), - Value = proplists:get_value(value, Props), - [indent(I, "Failure: ?assertNotMatch(~ts, ~ts)~n", [Pattern, Expr]), - indent(I, " expected not: = ~ts~n", [Pattern]), - indent(I, " got: ~p", [Value])]; - -format_assertion_failure(Type, Props, I) when Type =:= assertEqual_failed - ; Type =:= assertEqual -> - Expr = proplists:get_value(expression, Props), - Expected = proplists:get_value(expected, Props), - Value = proplists:get_value(value, Props), - [indent(I, "Failure: ?assertEqual(~w, ~ts)~n", [Expected, - Expr]), - indent(I, " expected: ~p~n", [Expected]), - indent(I, " got: ~p", [Value])]; - -format_assertion_failure(Type, Props, I) when Type =:= assertNotEqual_failed - ; Type =:= assertNotEqual -> - Expr = proplists:get_value(expression, Props), - Value = proplists:get_value(value, Props), - [indent(I, "Failure: ?assertNotEqual(~p, ~ts)~n", - [Value, Expr]), - indent(I, " expected not: == ~p~n", [Value]), - indent(I, " got: ~p", [Value])]; - -format_assertion_failure(Type, Props, I) when Type =:= assertException_failed - ; Type =:= assertException -> - Expr = proplists:get_value(expression, Props), - Pattern = proplists:get_value(pattern, Props), - {Class, Term} = extract_exception_pattern(Pattern), % I hate that we have to do this, why not just give DATA - [indent(I, "Failure: ?assertException(~ts, ~ts, ~ts)~n", [Class, Term, Expr]), - case proplists:is_defined(unexpected_success, Props) of - true -> - [indent(I, " expected: exception ~ts but nothing was raised~n", [Pattern]), - indent(I, " got: value ~p", [proplists:get_value(unexpected_success, Props)])]; - false -> - Ex = proplists:get_value(unexpected_exception, Props), - [indent(I, " expected: exception ~ts~n", [Pattern]), - indent(I, " got: exception ~p", [Ex])] - end]; - -format_assertion_failure(Type, Props, I) when Type =:= assertNotException_failed - ; Type =:= assertNotException -> - Expr = proplists:get_value(expression, Props), - Pattern = proplists:get_value(pattern, Props), - {Class, Term} = extract_exception_pattern(Pattern), % I hate that we have to do this, why not just give DAT - Ex = proplists:get_value(unexpected_exception, Props), - [indent(I, "Failure: ?assertNotException(~ts, ~ts, ~ts)~n", [Class, Term, Expr]), - indent(I, " expected not: exception ~ts~n", [Pattern]), - indent(I, " got: exception ~p", [Ex])]; - -format_assertion_failure(Type, Props, I) when Type =:= command_failed - ; Type =:= command -> - Cmd = proplists:get_value(command, Props), - Expected = proplists:get_value(expected_status, Props), - Status = proplists:get_value(status, Props), - [indent(I, "Failure: ?cmdStatus(~p, ~p)~n", [Expected, Cmd]), - indent(I, " expected: status ~p~n", [Expected]), - indent(I, " got: status ~p", [Status])]; - -format_assertion_failure(Type, Props, I) when Type =:= assertCmd_failed - ; Type =:= assertCmd -> - Cmd = proplists:get_value(command, Props), - Expected = proplists:get_value(expected_status, Props), - Status = proplists:get_value(status, Props), - [indent(I, "Failure: ?assertCmdStatus(~p, ~p)~n", [Expected, Cmd]), - indent(I, " expected: status ~p~n", [Expected]), - indent(I, " got: status ~p", [Status])]; - -format_assertion_failure(Type, Props, I) when Type =:= assertCmdOutput_failed - ; Type =:= assertCmdOutput -> - Cmd = proplists:get_value(command, Props), - Expected = proplists:get_value(expected_output, Props), - Output = proplists:get_value(output, Props), - [indent(I, "Failure: ?assertCmdOutput(~p, ~p)~n", [Expected, Cmd]), - indent(I, " expected: ~p~n", [Expected]), - indent(I, " got: ~p", [Output])]; - -format_assertion_failure(Type, Props, I) -> - indent(I, "~p", [{Type, Props}]). - -indent(I, Fmt, Args) -> - io_lib:format("~" ++ integer_to_list(I) ++ "s" ++ Fmt, [" "|Args]). - -extract_exception_pattern(Str) -> - ["{", Class, Term|_] = re:split(Str, "[, ]{1,2}", [unicode,{return,list}]), - {Class, Term}. \ No newline at end of file diff --git a/test/gleam_community_maths_test_ffi.erl b/test/gleam_community_maths_test_ffi.erl deleted file mode 100644 index f727223..0000000 --- a/test/gleam_community_maths_test_ffi.erl +++ /dev/null @@ -1,40 +0,0 @@ --module(gleam_community_maths_test_ffi). - --export([ - main/0, should_equal/2, should_not_equal/2, should_be_ok/1, - should_be_error/1 -]). - --include_lib("eunit/include/eunit.hrl"). - -main() -> - Options = [ - no_tty, {report, {eunit_progress, [colored]}} - ], - Files = filelib:wildcard("test/**/*.{erl,gleam}"), - Modules = lists:map(fun filepath_to_module/1, Files), - case eunit:test(Modules, Options) of - ok -> erlang:halt(0); - _ -> erlang:halt(1) - end. - -filepath_to_module(Path0) -> - Path1 = string:replace(Path0, "test/", ""), - Path2 = string:replace(Path1, ".erl", ""), - Path3 = string:replace(Path2, ".gleam", ""), - Path4 = string:replace(Path3, "/", "@", all), - Path5 = list_to_binary(Path4), - binary_to_atom(Path5). - -should_equal(Actual, Expected) -> - ?assertEqual(Expected, Actual), - nil. -should_not_equal(Actual, Expected) -> - ?assertNotEqual(Expected, Actual), - nil. -should_be_ok(A) -> - ?assertMatch({ok, _}, A), - nil. -should_be_error(A) -> - ?assertMatch({error, _}, A), - nil. diff --git a/test/gleam_community_maths_test_ffi.mjs b/test/gleam_community_maths_test_ffi.mjs deleted file mode 100755 index 48295b4..0000000 --- a/test/gleam_community_maths_test_ffi.mjs +++ /dev/null @@ -1,103 +0,0 @@ -// This file is a verbatim copy of gleeunit 0.10.0's - -async function* gleamFiles(directory) { - for (let entry of await read_dir(directory)) { - let path = join_path(directory, entry); - if (path.endsWith(".gleam")) { - yield path; - } else { - try { - yield* gleamFiles(path); - } catch (error) { - // Could not read directory, assume it's a file - } - } - } -} - -async function readRootPackageName() { - let toml = await read_file("gleam.toml", "utf-8"); - for (let line of toml.split("\n")) { - let matches = line.match(/\s*name\s*=\s*"([a-z][a-z0-9_]*)"/); // Match regexp in compiler-cli/src/new.rs in validate_name() - if (matches) return matches[1]; - } - throw new Error("Could not determine package name from gleam.toml"); -} - -export async function main() { - let passes = 0; - let failures = 0; - - let packageName = await readRootPackageName(); - let dist = `../${packageName}/`; - - for await (let path of await gleamFiles("test")) { - let js_path = path.slice("test/".length).replace(".gleam", ".mjs"); - let module = await import(join_path(dist, js_path)); - for (let fnName of Object.keys(module)) { - if (!fnName.endsWith("_test")) continue; - try { - await module[fnName](); - write(`\u001b[32m.\u001b[0m`); - passes++; - } catch (error) { - let moduleName = "\n" + js_path.slice(0, -4); - let line = error.line ? `:${error.line}` : ""; - write(`\n❌ ${moduleName}.${fnName}${line}: ${error}\n`); - failures++; - } - } - } - - console.log(` -${passes + failures} tests, ${failures} failures`); - exit(failures ? 1 : 0); -} - -export function crash(message) { - throw new Error(message); -} - -function write(message) { - if (globalThis.Deno) { - Deno.stdout.writeSync(new TextEncoder().encode(message)); - } else { - process.stdout.write(message); - } -} - -function exit(code) { - if (globalThis.Deno) { - Deno.exit(code); - } else { - process.exit(code); - } -} - -async function read_dir(path) { - if (globalThis.Deno) { - let items = []; - for await (let item of Deno.readDir(path, { withFileTypes: true })) { - items.push(item.name); - } - return items; - } else { - let { readdir } = await import("fs/promises"); - return readdir(path); - } -} - -function join_path(a, b) { - if (a.endsWith("/")) return a + b; - return a + "/" + b; -} - -async function read_file(path) { - if (globalThis.Deno) { - return Deno.readTextFile(path); - } else { - let { readFile } = await import("fs/promises"); - let contents = await readFile(path); - return contents.toString(); - } -} \ No newline at end of file