Skip to content

Commit 4d42b17

Browse files
committed
Update vendored gleeunit
1 parent efc4883 commit 4d42b17

12 files changed

+767
-715
lines changed

test/eunit_progress.erl

Lines changed: 0 additions & 609 deletions
This file was deleted.

test/gleam_stdlib_test.gleam

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
@external(erlang, "gleam_stdlib_test_ffi", "main")
2-
@external(javascript, "././gleeunit.mjs", "main")
3-
pub fn main() -> Nil
1+
import gleeunit
2+
3+
pub fn main() -> Nil {
4+
gleeunit.main()
5+
}

test/gleeunit.gleam

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import gleam/list
2+
import gleam/string
3+
4+
/// Find and run all test functions for the current project using Erlang's EUnit
5+
/// test framework, or a custom JavaScript test runner.
6+
///
7+
/// Any Erlang or Gleam function in the `test` directory with a name ending in
8+
/// `_test` is considered a test function and will be run.
9+
///
10+
/// A test that panics is considered a failure.
11+
///
12+
pub fn main() -> Nil {
13+
do_main()
14+
}
15+
16+
@external(javascript, "./gleeunit_ffi.mjs", "main")
17+
fn do_main() -> Nil {
18+
let options = [Verbose, NoTty, Report(#(GleeunitProgress, [Colored(True)]))]
19+
20+
let result =
21+
find_files(matching: "**/*.{erl,gleam}", in: "test")
22+
|> list.map(gleam_to_erlang_module_name)
23+
|> list.map(dangerously_convert_string_to_atom(_, Utf8))
24+
|> run_eunit(options)
25+
26+
let code = case result {
27+
Ok(_) -> 0
28+
Error(_) -> 1
29+
}
30+
halt(code)
31+
}
32+
33+
@external(erlang, "erlang", "halt")
34+
fn halt(a: Int) -> Nil
35+
36+
fn gleam_to_erlang_module_name(path: String) -> String {
37+
path
38+
|> string.replace(".gleam", "")
39+
|> string.replace(".erl", "")
40+
|> string.replace("/", "@")
41+
}
42+
43+
@external(erlang, "gleeunit_ffi", "find_files")
44+
fn find_files(matching matching: String, in in: String) -> List(String)
45+
46+
type Atom
47+
48+
type Encoding {
49+
Utf8
50+
}
51+
52+
@external(erlang, "erlang", "binary_to_atom")
53+
fn dangerously_convert_string_to_atom(a: String, b: Encoding) -> Atom
54+
55+
type ReportModuleName {
56+
GleeunitProgress
57+
}
58+
59+
type GleeunitProgressOption {
60+
Colored(Bool)
61+
}
62+
63+
type EunitOption {
64+
Verbose
65+
NoTty
66+
Report(#(ReportModuleName, List(GleeunitProgressOption)))
67+
}
68+
69+
@external(erlang, "gleeunit_ffi", "run_eunit")
70+
fn run_eunit(a: List(Atom), b: List(EunitOption)) -> Result(Nil, a)

test/gleeunit.mjs

Lines changed: 0 additions & 103 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import gleam/dynamic
2+
3+
pub type GleamPanic {
4+
GleamPanic(
5+
message: String,
6+
file: String,
7+
module: String,
8+
function: String,
9+
line: Int,
10+
kind: PanicKind,
11+
)
12+
}
13+
14+
pub type PanicKind {
15+
Todo
16+
Panic
17+
LetAssert(
18+
start: Int,
19+
end: Int,
20+
pattern_start: Int,
21+
pattern_end: Int,
22+
value: dynamic.Dynamic,
23+
)
24+
Assert(start: Int, end: Int, expression_start: Int, kind: AssertKind)
25+
}
26+
27+
pub type AssertKind {
28+
BinaryOperator(
29+
operator: String,
30+
left: AssertedExpression,
31+
right: AssertedExpression,
32+
)
33+
FunctionCall(arguments: List(AssertedExpression))
34+
OtherExpression(expression: AssertedExpression)
35+
}
36+
37+
pub type AssertedExpression {
38+
AssertedExpression(start: Int, end: Int, kind: ExpressionKind)
39+
}
40+
41+
pub type ExpressionKind {
42+
Literal(value: dynamic.Dynamic)
43+
Expression(value: dynamic.Dynamic)
44+
Unevaluated
45+
}
46+
47+
@external(erlang, "gleeunit_gleam_panic_ffi", "from_dynamic")
48+
@external(javascript, "./gleeunit_gleam_panic_ffi.mjs", "from_dynamic")
49+
pub fn from_dynamic(data: dynamic.Dynamic) -> Result(GleamPanic, Nil)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
-module(gleeunit_gleam_panic_ffi).
2+
-export([from_dynamic/1]).
3+
4+
from_dynamic(#{
5+
gleam_error := assert,
6+
start := Start,
7+
'end' := End,
8+
expression_start := EStart
9+
} = E) ->
10+
wrap(E, {assert, Start, End, EStart, assert_kind(E)});
11+
from_dynamic(#{
12+
gleam_error := let_assert,
13+
start := Start,
14+
'end' := End,
15+
pattern_start := PStart,
16+
pattern_end := PEnd,
17+
value := Value
18+
} = E) ->
19+
wrap(E, {let_assert, Start, End, PStart, PEnd, Value});
20+
from_dynamic(#{gleam_error := panic} = E) ->
21+
wrap(E, panic);
22+
from_dynamic(#{gleam_error := todo} = E) ->
23+
wrap(E, todo);
24+
from_dynamic(_) ->
25+
{error, nil}.
26+
27+
assert_kind(#{kind := binary_operator, left := L, right := R, operator := O}) ->
28+
{binary_operator, atom_to_binary(O), expression(L), expression(R)};
29+
assert_kind(#{kind := function_call, arguments := Arguments}) ->
30+
{function_call, lists:map(fun expression/1, Arguments)};
31+
assert_kind(#{kind := expression, expression := Expression}) ->
32+
{other_expression, expression(Expression)}.
33+
34+
expression(#{start := S, 'end' := E, kind := literal, value := Value}) ->
35+
{asserted_expression, S, E, {literal, Value}};
36+
expression(#{start := S, 'end' := E, kind := expression, value := Value}) ->
37+
{asserted_expression, S, E, {expression, Value}};
38+
expression(#{start := S, 'end' := E, kind := unevaluated}) ->
39+
{asserted_expression, S, E, unevaluated}.
40+
41+
wrap(#{
42+
gleam_error := _,
43+
file := File,
44+
message := Message,
45+
module := Module,
46+
function := Function,
47+
line := Line
48+
}, Kind) ->
49+
{ok, {gleam_panic, Message, File, Module, Function, Line, Kind}}.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { Ok, Error, Empty, NonEmpty } from "../../gleam.mjs";
2+
import {
3+
GleamPanic,
4+
Todo,
5+
Panic,
6+
LetAssert,
7+
Assert,
8+
BinaryOperator,
9+
FunctionCall,
10+
OtherExpression,
11+
AssertedExpression,
12+
Literal,
13+
Expression,
14+
Unevaluated,
15+
} from "./gleam_panic.mjs";
16+
17+
export function from_dynamic(error) {
18+
if (!(error instanceof globalThis.Error) || !error.gleam_error) {
19+
return new Error(undefined);
20+
}
21+
22+
if (error.gleam_error === "todo") {
23+
return wrap(error, new Todo());
24+
}
25+
26+
if (error.gleam_error === "panic") {
27+
return wrap(error, new Panic());
28+
}
29+
30+
if (error.gleam_error === "let_assert") {
31+
let kind = new LetAssert(
32+
error.start,
33+
error.end,
34+
error.pattern_start,
35+
error.pattern_end,
36+
error.value,
37+
);
38+
return wrap(error, kind);
39+
}
40+
41+
if (error.gleam_error === "assert") {
42+
let kind = new Assert(
43+
error.start,
44+
error.end,
45+
error.expression_start,
46+
assert_kind(error),
47+
);
48+
return wrap(error, kind);
49+
}
50+
51+
return new Error(undefined);
52+
}
53+
54+
function assert_kind(error) {
55+
if (error.kind == "binary_operator") {
56+
return new BinaryOperator(
57+
error.operator,
58+
expression(error.left),
59+
expression(error.right),
60+
);
61+
}
62+
63+
if (error.kind == "function_call") {
64+
let list = new Empty();
65+
let i = error.arguments.length;
66+
while (i--) {
67+
list = new NonEmpty(expression(error.arguments[i]), list);
68+
}
69+
return new FunctionCall(list);
70+
}
71+
72+
return new OtherExpression(expression(error.expression));
73+
}
74+
75+
function expression(data) {
76+
const expression = new AssertedExpression(data.start, data.end, undefined);
77+
if (data.kind == "literal") {
78+
expression.kind = new Literal(data.value);
79+
} else if (data.kind == "expression") {
80+
expression.kind = new Expression(data.value);
81+
} else {
82+
expression.kind = new Unevaluated();
83+
}
84+
return expression;
85+
}
86+
87+
function wrap(e, kind) {
88+
return new Ok(
89+
new GleamPanic(e.message, e.file, e.module, e.function, e.line, kind),
90+
);
91+
}

0 commit comments

Comments
 (0)