plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
plum-std/Testing.plum
| 2ec05c8 | 1 | module std |
| 2ec05c8 | 2 | |
| b7071c9 | 3 | import std/Option |
| b7071c9 | 4 | import std/Result |
| b7071c9 | 5 | import std/List |
| 73b5e55 | 6 | import std/Bool |
| ca5fd6f | 7 | import std/Number |
| 29313cb | 8 | import std/Str |
| 2ec05c8 | 9 | |
| 2ec05c8 | 10 | # Small jest/rspec-style assertion helpers for use inside `test` blocks, e.g. |
| 2ec05c8 | 11 | # |
| 2ec05c8 | 12 | # test "add works" |
| a9a0147 | 13 | # assert expectEq(add(1, 2), 3) |
| a9a0147 | 14 | # assert expectTrue(isEven(4)) |
| 2ec05c8 | 15 | # |
| a9a0147 | 16 | # These are plain functions returning `Bool` (`assert` only takes a bare |
| a9a0147 | 17 | # boolean expression — see `plum-core/parser.rs`'s `assert` rule), not a new |
| a9a0147 | 18 | # grammar form. They exist purely to make the condition read like an |
| 2ec05c8 | 19 | # assertion instead of a raw comparison. |
| 2ec05c8 | 20 | # |
| 2ec05c8 | 21 | # `expectArray`/`expectSome`/`expectOk`/`expectErr` below take a container |
| 2ec05c8 | 22 | # type (`List[T]`/`Option[T]`/`Result[T, E]`) whose OWN generic param is |
| 2ec05c8 | 23 | # nested inside the param type — this used to hit a real monomorphizer bug |
| 2ec05c8 | 24 | # (misclassified as a "bare generic class reference" fn, then lost its type |
| 2ec05c8 | 25 | # argument when the specialized signature was registered, mismatching the |
| 2ec05c8 | 26 | # caller's concrete arg type; fixed in `plum-checker/src/monomorphize.rs`'s |
| 2ec05c8 | 27 | # `fnGenericParams`/`resolveFnInstantiation`, see the |
| 2ec05c8 | 28 | # `plum_generic_method_self_nesting_landmine`-adjacent compiler-bugs memory). |
| 2ec05c8 | 29 | # The underlying type's own method (`result.isOk()`, `listA.equals(listB)`) |
| 2ec05c8 | 30 | # still works too and reads just as well — use whichever fits the call site. |
| 2ec05c8 | 31 | # |
| 2ec05c8 | 32 | # CAVEAT on `expectEq`/`expectNotEq`/`expectObject`/`List.equals`: Plum's |
| 2ec05c8 | 33 | # `==`/`!=` have no operator-overloading mechanism. For Int/Str/Bool/Float |
| 2ec05c8 | 34 | # they do real value comparison (Str is content-compared, not |
| 2ec05c8 | 35 | # reference-compared). For class/enum instances there is no such override, |
| 2ec05c8 | 36 | # so `==` compiles to reference identity — `expectEq` on two |
| 2ec05c8 | 37 | # separately-constructed-but-equal structs will wrongly report `false`. For |
| 2ec05c8 | 38 | # those types, prefer the type's own `equals(self, other)` method (e.g. |
| a9a0147 | 39 | # `Uuid.equals`, `Time.equals`) directly in `assert` instead. |
| 2ec05c8 | 40 | |
| 2ec05c8 | 41 | fun expectTrue(cond: Bool) -> Bool = |
| 2ec05c8 | 42 | cond |
| 2ec05c8 | 43 | |
| 2ec05c8 | 44 | fun expectFalse(cond: Bool) -> Bool = |
| 2ec05c8 | 45 | !cond |
| 2ec05c8 | 46 | |
| 2ec05c8 | 47 | fun expectEq(a: T, b: T) -> Bool = |
| 2ec05c8 | 48 | a == b |
| 2ec05c8 | 49 | |
| 2ec05c8 | 50 | fun expectNotEq(a: T, b: T) -> Bool = |
| 2ec05c8 | 51 | a != b |
| 2ec05c8 | 52 | |
| 2ec05c8 | 53 | # See the module-level CAVEAT above — this is `expectEq` under a name that |
| 2ec05c8 | 54 | # reads better at a class/struct call site; it does NOT do structural |
| 2ec05c8 | 55 | # (field-by-field) comparison. |
| 2ec05c8 | 56 | fun expectObject(a: T, b: T) -> Bool = |
| 2ec05c8 | 57 | a == b |
| 2ec05c8 | 58 | |
| 2ec05c8 | 59 | # Elementwise `List[T]` comparison — see the module-level CAVEAT above for |
| 2ec05c8 | 60 | # what `List.equals`'s own `==` means when `T` is a class/enum. |
| 2ec05c8 | 61 | fun expectArray(a: List[T], b: List[T]) -> Bool = |
| 2ec05c8 | 62 | a.equals(b) |
| 2ec05c8 | 63 | |
| 2ec05c8 | 64 | fun expectSome(o: Option[T]) -> Bool = |
| 2ec05c8 | 65 | o.isSome() |
| 2ec05c8 | 66 | |
| 2ec05c8 | 67 | fun expectNone(o: Option[T]) -> Bool = |
| 2ec05c8 | 68 | o.isNone() |
| 2ec05c8 | 69 | |
| 2ec05c8 | 70 | fun expectOk(r: Result[T, E]) -> Bool = |
| 2ec05c8 | 71 | r.isOk() |
| 2ec05c8 | 72 | |
| 2ec05c8 | 73 | fun expectErr(r: Result[T, E]) -> Bool = |
| 2ec05c8 | 74 | r.isErr() |
| 2ec05c8 | 75 | |
| 2ec05c8 | 76 | fun makeOkForTestingTest() -> Result[Int, Str] = |
| 2ec05c8 | 77 | return Ok(5) |
| 2ec05c8 | 78 | |
| 2ec05c8 | 79 | fun makeErrForTestingTest() -> Result[Int, Str] = |
| 2ec05c8 | 80 | return Err("bad") |
| 2ec05c8 | 81 | |
| 2ec05c8 | 82 | fun makeNoneForTestingTest() -> Option[Int] = |
| 2ec05c8 | 83 | return None |
| 2ec05c8 | 84 | |
| 2ec05c8 | 85 | test "expectTrue and expectFalse" |
| a9a0147 | 86 | assert expectTrue(1 == 1) |
| a9a0147 | 87 | assert expectFalse(1 == 2) |
| 2ec05c8 | 88 | |
| 2ec05c8 | 89 | test "expectEq and expectNotEq" |
| a9a0147 | 90 | assert expectEq(2 + 2, 4) |
| a9a0147 | 91 | assert expectEq("ab" + "c", "abc") |
| a9a0147 | 92 | assert expectNotEq(2 + 2, 5) |
| 2ec05c8 | 93 | |
| 2ec05c8 | 94 | test "list equality via the List.equals method" |
| 4a2384c | 95 | a := List(1, 2, 3) |
| 4a2384c | 96 | b := List(1, 2, 3) |
| 4a2384c | 97 | c := List(1, 2) |
| a9a0147 | 98 | assert a.equals(b) |
| a9a0147 | 99 | assert expectFalse(a.equals(c)) |
| 2ec05c8 | 100 | |
| 2ec05c8 | 101 | test "Option/Result checks via their own isSome/isNone/isOk/isErr methods" |
| a9a0147 | 102 | assert Some(1).isSome() |
| a9a0147 | 103 | assert makeNoneForTestingTest().isNone() |
| a9a0147 | 104 | assert makeOkForTestingTest().isOk() |
| a9a0147 | 105 | assert makeErrForTestingTest().isErr() |
| 2ec05c8 | 106 | |
| 2ec05c8 | 107 | test "expectArray compares two List[T]s elementwise" |
| 4a2384c | 108 | a := List(1, 2, 3) |
| 4a2384c | 109 | b := List(1, 2, 3) |
| 4a2384c | 110 | c := List(1, 2) |
| a9a0147 | 111 | assert expectArray(a, b) |
| a9a0147 | 112 | assert expectFalse(expectArray(a, c)) |
| 4a2384c | 113 | d := List("x", "y") |
| 4a2384c | 114 | e := List("x", "y") |
| a9a0147 | 115 | assert expectArray(d, e) |
| 2ec05c8 | 116 | |
| 2ec05c8 | 117 | test "expectSome/expectNone/expectOk/expectErr check the right variant" |
| a9a0147 | 118 | assert expectSome(Some(1)) |
| a9a0147 | 119 | assert expectFalse(expectSome(makeNoneForTestingTest())) |
| a9a0147 | 120 | assert expectNone(makeNoneForTestingTest()) |
| a9a0147 | 121 | assert expectOk(makeOkForTestingTest()) |
| a9a0147 | 122 | assert expectFalse(expectOk(makeErrForTestingTest())) |
| a9a0147 | 123 | assert expectErr(makeErrForTestingTest()) |
| a9a0147 | 124 | assert expectFalse(expectErr(makeOkForTestingTest())) |