From b6a86b76e1fa37649a5386104b77a8c597475d91 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 8 Mar 2024 15:09:19 +0100 Subject: [PATCH 1/9] ci(fix): download latest pre-release of the linux-clang-{version} artifact --- .github/workflows/ci.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 103cb57..e086f9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,10 @@ on: pull_request: branches: [ master ] +env: + ARTIFACT_NAME: "linux-clang-15.zip" + CLANG_VERSION: 15 + jobs: build: runs-on: ubuntu-latest @@ -17,26 +21,26 @@ jobs: - uses: robinraju/release-downloader@v1.5 with: latest: true + preRelease: true repository: ArkScript-lang/Ark - fileName: "linux-clang-11.zip" + fileName: ${{ env.ARTIFACT_NAME }} - name: Set up files shell: bash run: | - unzip linux-clang-11.zip + unzip $ARTIFACT_NAME chmod u+x arkscript *.so lib/*.arkm cp lib/*.arkm ./ - name: Update LLVM compilers shell: bash run: | - version=11 - sudo apt-get install -y clang-${version} lld-${version} libc++-${version}-dev libc++abi-${version}-dev clang-tools-${version} + sudo apt-get install -y clang-${CLANG_VERSION} lld-${CLANG_VERSION} \ + libc++-${CLANG_VERSION}-dev libc++abi-${CLANG_VERSION}-dev \ + clang-tools-${CLANG_VERSION} - name: Tests shell: bash run: | ./arkscript --version - for f in tests/*.ark; do - ./arkscript $f -L ./ - done + ./arkscript tests/all.ark -L ./ From 0ef68c57f0a75482b2709e16697ef30a8a863c20 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 8 Mar 2024 15:10:28 +0100 Subject: [PATCH 2/9] ci(fix): bump release-downloader to 1.9 to use the preRelease setting --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e086f9a..72221c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: - name: Checkout std uses: actions/checkout@v2 - - uses: robinraju/release-downloader@v1.5 + - uses: robinraju/release-downloader@v1.9 with: latest: true preRelease: true From 2af2a11d91e95b8f5deda58a4c59dee348cf22d5 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Mon, 20 Nov 2023 14:01:15 +0100 Subject: [PATCH 3/9] chore!: update code to use the new syntax --- Events.ark | 2 +- List.ark | 10 +++++----- Macros.ark | 20 ++++++++++---------- tests/all.ark | 10 ++++++++++ tests/events-tests.ark | 4 ++-- tests/exceptions-tests.ark | 4 ++-- tests/functional-tests.ark | 4 ++-- tests/lazy-tests.ark | 4 ++-- tests/list-tests.ark | 6 +++--- tests/macros-tests.ark | 4 ++-- tests/math-tests.ark | 4 ++-- tests/range-tests.ark | 6 +++--- tests/string-tests.ark | 4 ++-- tests/switch-tests.ark | 18 +++++++++--------- tests/tests-tools.ark | 16 ++++++++-------- 15 files changed, 63 insertions(+), 53 deletions(-) create mode 100644 tests/all.ark diff --git a/Events.ark b/Events.ark index acb7ed3..bf1f2ae 100644 --- a/Events.ark +++ b/Events.ark @@ -1,4 +1,4 @@ -(import "List.ark") +(import std.List) # @brief Allows to register events listeners and emit events # =begin diff --git a/List.ark b/List.ark index 023d45d..5596211 100644 --- a/List.ark +++ b/List.ark @@ -3,7 +3,7 @@ # @param _func the function to call on each element # @details The original list is left unmodified. # =begin -# (import "List.ark") +# (import std.List) # (let collection [1 2 5 12]) # (list:forEach collection (fun (element) { # (print element) @@ -21,7 +21,7 @@ # @param _L the list to iterate over # @details The original list is left unmodified. # =begin -# (import "List.ark") +# (import std.List) # (let collection [1 2 5 12]) # (let p (list:product collection)) # => 120 # =end @@ -38,7 +38,7 @@ # @param _L the list to iterate over # @details The original list is left unmodified. # =begin -# (import "List.ark") +# (import std.List) # (let collection [1 2 5 12]) # (let p (list:sum collection)) # => 20 # =end @@ -51,7 +51,7 @@ (set _index (+ 1 _index))}) _output })) -(import "Math.ark") # needed for math:min, math:max +(import std.Math :min :max) # @brief Drop the first n elements of a list # @param _L the list to work on @@ -101,7 +101,7 @@ # @param _f the predicate # @details The original list is left unmodified. # =begin -# (import "Math.ark") +# (import std.Math) # (print (list:filter [1 2 3 4 5 6 7 8 9] math:even)) # [2 4 6 8] # =end # @author https://github.com/rstefanic diff --git a/Macros.ark b/Macros.ark index a34c0ac..d342478 100644 --- a/Macros.ark +++ b/Macros.ark @@ -1,15 +1,15 @@ -!{-> (arg fn1 ...fn) { - !{if (> (len fn) 0) +($ -> (arg fn1 ...fn) { + ($if (> (len fn) 0) (-> (fn1 arg) ...fn) - (fn1 arg)}}} + (fn1 arg))}) # internal, do not use -!{__suffix-dup (sym x) { - !{if (> x 1) - (__suffix-dup sym (- x 1))} - (symcat sym x)}} +($ __suffix-dup (sym x) { + ($if (> x 1) + (__suffix-dup sym (- x 1))) + (symcat sym x)}) -!{partial (func ...defargs) { - !{bloc (__suffix-dup a (- (argcount func) (len defargs)))} +($ partial (func ...defargs) { + ($ bloc (__suffix-dup a (- (argcount func) (len defargs)))) (fun (bloc) (func ...defargs bloc)) - !{undef bloc}}} + ($undef bloc)}) \ No newline at end of file diff --git a/tests/all.ark b/tests/all.ark new file mode 100644 index 0000000..b37678b --- /dev/null +++ b/tests/all.ark @@ -0,0 +1,10 @@ +(import events-tests) +(import exceptions-tests) +(import functional-tests) +(import lazy-tests) +(import list-tests) +(import macros-tests) +(import math-tests) +(import range-tests) +(import string-tests) +(import switch-tests) \ No newline at end of file diff --git a/tests/events-tests.ark b/tests/events-tests.ark index e759c50..65d0563 100644 --- a/tests/events-tests.ark +++ b/tests/events-tests.ark @@ -1,6 +1,6 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "Events.ark") +(import std.Events) (let events-tests (fun () { (mut tests 0) diff --git a/tests/exceptions-tests.ark b/tests/exceptions-tests.ark index 1f8a490..7dbaa0e 100644 --- a/tests/exceptions-tests.ark +++ b/tests/exceptions-tests.ark @@ -1,6 +1,6 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "Exceptions.ark") +(import std.Exceptions) (let exceptions-tests (fun () { (mut tests 0) diff --git a/tests/functional-tests.ark b/tests/functional-tests.ark index ac48359..46f1de3 100644 --- a/tests/functional-tests.ark +++ b/tests/functional-tests.ark @@ -1,6 +1,6 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "Functional.ark") +(import std.Functional) (let functional-tests (fun () { (mut tests 0) diff --git a/tests/lazy-tests.ark b/tests/lazy-tests.ark index dd4a154..7858df2 100644 --- a/tests/lazy-tests.ark +++ b/tests/lazy-tests.ark @@ -1,6 +1,6 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "Lazy.ark") +(import std.Lazy) (let lazy-tests (fun () { (mut tests 0) diff --git a/tests/list-tests.ark b/tests/list-tests.ark index 846c89d..466fb3d 100644 --- a/tests/list-tests.ark +++ b/tests/list-tests.ark @@ -1,7 +1,7 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "List.ark") -(import "Math.ark") # for math:even +(import std.List) +(import std.Math :even) (let list-tests (fun () { (mut tests 0) diff --git a/tests/macros-tests.ark b/tests/macros-tests.ark index 7873e02..7dfa0fe 100644 --- a/tests/macros-tests.ark +++ b/tests/macros-tests.ark @@ -1,6 +1,6 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "Macros.ark") +(import std.Macros) (let macros-tests (fun () { (mut tests 0) diff --git a/tests/math-tests.ark b/tests/math-tests.ark index 22b1d11..ee1365d 100644 --- a/tests/math-tests.ark +++ b/tests/math-tests.ark @@ -1,6 +1,6 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "Math.ark") +(import std.Math) (let math-tests (fun () { (mut tests 0) diff --git a/tests/range-tests.ark b/tests/range-tests.ark index 034d030..c70dd97 100644 --- a/tests/range-tests.ark +++ b/tests/range-tests.ark @@ -1,7 +1,7 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "Range.ark") -(import "Math.ark") # for math:even +(import std.Range) +(import std.Math :even) (let range-tests (fun () { (mut tests 0) diff --git a/tests/string-tests.ark b/tests/string-tests.ark index 18a8fae..af5495b 100644 --- a/tests/string-tests.ark +++ b/tests/string-tests.ark @@ -1,6 +1,6 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "String.ark") +(import std.String) (let string-tests (fun () { (mut tests 0) diff --git a/tests/switch-tests.ark b/tests/switch-tests.ark index ce8afc9..52b1df3 100644 --- a/tests/switch-tests.ark +++ b/tests/switch-tests.ark @@ -1,19 +1,19 @@ -(import "tests-tools.ark") +(import tests-tools) -(import "Switch.ark") +(import std.Switch) (let switch-tests (fun () { (mut tests 0) (let start-time (time)) (switch 12 [ - [0 '(assert-val false "switch 12" tests)] - [-1 '(assert-val false "switch 12" tests)] - [nil '(assert-val false "switch 12" tests)] - ["12" '(assert-val false "switch 12" tests)] - [[12] '(assert-val false "switch 12" tests)] - [12 '(set tests (assert-val true "switch 12" tests))] - [true '(assert-val false "switch 12" tests)]]) + [0 (fun () (assert-val false "switch 12" tests))] + [-1 (fun () (assert-val false "switch 12" tests))] + [nil (fun () (assert-val false "switch 12" tests))] + ["12" (fun () (assert-val false "switch 12" tests))] + [[12] (fun () (assert-val false "switch 12" tests))] + [12 (fun () (set tests (assert-val true "switch 12" tests)))] + [true (fun () (assert-val false "switch 12" tests))]]) # FIXME: this is crashing the GCC8 and GCC11 builds # (switch 0 [ diff --git a/tests/tests-tools.ark b/tests/tests-tools.ark index eccc3f6..c825b1e 100644 --- a/tests/tests-tools.ark +++ b/tests/tests-tools.ark @@ -1,31 +1,31 @@ -(import "console.arkm") +(import console) (let assert-eq (fun (val1 val2 message tests) { - (assert (= val1 val2) (str:format "%% (%%) - %% SHOULD BE EQUAL TO %%" message tests val1 val2)) + (assert (= val1 val2) (str:format "{} ({}) - {} SHOULD BE EQUAL TO {}" message tests val1 val2)) (+ 1 tests)})) (let assert-neq (fun (val1 val2 message tests) { - (assert (!= val1 val2) (str:format "%% (%%) - %% SHOULD BE NOT EQUAL TO %%" message tests val1 val2)) + (assert (!= val1 val2) (str:format "{} ({}) - {} SHOULD BE NOT EQUAL TO {}" message tests val1 val2)) (+ 1 tests)})) (let assert-gt (fun (val1 val2 message tests) { - (assert (> val1 val2) (str:format "%% (%%) - %% SHOULD BE GREATER THAN %%" message tests val1 val2)) + (assert (> val1 val2) (str:format "{} ({}) - {} SHOULD BE GREATER THAN {}" message tests val1 val2)) (+ 1 tests)})) (let assert-ge (fun (val1 val2 message tests) { - (assert (>= val1 val2) (str:format "%% (%%) - %% SHOULD BE GREATER OR EQUAL TO %%" message tests val1 val2)) + (assert (>= val1 val2) (str:format "{} ({}) - {} SHOULD BE GREATER OR EQUAL TO {}" message tests val1 val2)) (+ 1 tests)})) (let assert-lt (fun (val1 val2 message tests) { - (assert (< val1 val2) (str:format "%% (%%) - %% SHOULD BE LESSER THAN %%" message tests val1 val2)) + (assert (< val1 val2) (str:format "{} ({}) - {} SHOULD BE LESSER THAN {}" message tests val1 val2)) (+ 1 tests)})) (let assert-le (fun (val1 val2 message tests) { - (assert (<= val1 val2) (str:format "%% (%%) - %% SHOULD BE LESSER OR EQUAL TO %%" message tests val1 val2)) + (assert (<= val1 val2) (str:format "{} ({}) - {} SHOULD BE LESSER OR EQUAL TO {}" message tests val1 val2)) (+ 1 tests)})) (let assert-val (fun (val0 message tests) { - (assert val0 (str:format "%% (%%) - %% SHOULD BE TRUTHY" message tests val0)) + (assert val0 (str:format "{} ({}) - {} SHOULD BE TRUTHY" message tests val0)) (+ 1 tests)})) (let recap (fun (test-name tests time_) { From 2ed0a837f9c5cd51e497ee2a1daf219d21272c99 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 1 Mar 2024 17:29:40 +0100 Subject: [PATCH 4/9] fix: str:replace can now accept a replacement containing the pattern --- String.ark | 8 ++++++-- tests/string-tests.ark | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/String.ark b/String.ark index 5d5b0a1..ade4a5b 100644 --- a/String.ark +++ b/String.ark @@ -135,11 +135,15 @@ (let _pattern_sz (len _pattern)) (while (!= -1 _idx) { + (mut _next_segment (str:slice _out (+ _idx _pattern_sz) (- (len _out) (+ _idx _pattern_sz)))) (set _out (+ (str:slice _out 0 _idx) _new - (str:slice _out (+ _idx _pattern_sz) (- (len _out) (+ _idx _pattern_sz))))) - (set _idx (str:find _out _pattern))}) + _next_segment)) + (set _idx (str:find _next_segment _pattern)) + (if (!= -1 _idx) + (set _idx (+ _idx _pattern_sz))) + }) _out })) # @brief Join a list of elements with a given string delimiter diff --git a/tests/string-tests.ark b/tests/string-tests.ark index af5495b..563cb2d 100644 --- a/tests/string-tests.ark +++ b/tests/string-tests.ark @@ -29,6 +29,7 @@ (set tests (assert-eq "hello world" (str:replace "hello world" "coucou" "not") "string replace" tests)) (set tests (assert-eq "not world" (str:replace "hello world" "hello" "not") "string replace" tests)) (set tests (assert-eq "not not " (str:replace "hello hello " "hello" "not") "string replace" tests)) + (set tests (assert-eq "hello worldABC" (str:replace "hello worldABC" "ABC" "worldABC") "string replace" tests)) (set tests (assert-eq "hello;3.14;true;world" (str:join ["hello" 3.14 true "world"] ";") "string join" tests)) (set tests (assert-eq "hello" (str:join ["hello"] ";") "string join" tests)) @@ -38,4 +39,4 @@ tests })) -(let passed-string (string-tests)) \ No newline at end of file +(let passed-string (string-tests)) From e3fdc80f31985fe79eb23e4790811660f35203f1 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Sat, 2 Mar 2024 18:49:59 +0100 Subject: [PATCH 5/9] feat: creating a new testing library, now part of the library instead of the tests part --- String.ark | 6 +- Testing.ark | 58 +++++++++++++++++ tests/events-tests.ark | 36 ++++------- tests/exceptions-tests.ark | 30 +++------ tests/functional-tests.ark | 28 +++------ tests/lazy-tests.ark | 27 +++----- tests/list-tests.ark | 110 +++++++++++++++----------------- tests/macros-tests.ark | 50 ++++++--------- tests/math-tests.ark | 124 +++++++++++++++++-------------------- tests/range-tests.ark | 32 ++++------ tests/string-tests.ark | 72 ++++++++++----------- tests/switch-tests.ark | 34 +++------- tests/tests-tools.ark | 50 --------------- 13 files changed, 278 insertions(+), 379 deletions(-) create mode 100644 Testing.ark delete mode 100644 tests/tests-tools.ark diff --git a/String.ark b/String.ark index ade4a5b..c9d2fd0 100644 --- a/String.ark +++ b/String.ark @@ -135,15 +135,15 @@ (let _pattern_sz (len _pattern)) (while (!= -1 _idx) { + (mut _first_segment (str:slice _out 0 _idx)) (mut _next_segment (str:slice _out (+ _idx _pattern_sz) (- (len _out) (+ _idx _pattern_sz)))) (set _out (+ - (str:slice _out 0 _idx) + _first_segment _new _next_segment)) (set _idx (str:find _next_segment _pattern)) (if (!= -1 _idx) - (set _idx (+ _idx _pattern_sz))) - }) + (set _idx (+ _idx (len _first_segment) (len _new))))}) _out })) # @brief Join a list of elements with a given string delimiter diff --git a/Testing.ark b/Testing.ark new file mode 100644 index 0000000..ff04c96 --- /dev/null +++ b/Testing.ark @@ -0,0 +1,58 @@ +(let _runner (fun (_name _callable) { + (mut _passed 0) + (mut _failed 0) + (mut _failures []) + + (let _start_time (time)) + # run test + (_callable) + (let _end_time (time)) + + # no newline, yet + (puts _name) + (if (> _passed 0) + (puts (str:format " - {} ✅" _passed))) + (if (> _failed 0) + (puts (str:format ", {} ❌" _failed))) + + (puts (str:format " in {:2.3f}ms\n" (* 1000 (- _end_time _start_time)))) + + (mut _i 0) + (let _failures_count (len _failures)) + (while (< _i _failures_count) { + (print "\t" (@ _failures _i)) + (set _i (+ 1 _i))}) + + [_passed _failed]})) + +(let _report_error (fun (_lhs _rhs _lhs_repr _rhs_repr) { + (set _failed (+ 1 _failed)) + (append! _failures (str:format "{} was not equal to {}" _lhs_repr _rhs_repr)) + (let _rhs_start (+ (len _lhs_repr) (len " was not equal to "))) + (let _lhs_align (len _lhs_repr)) + (let _rhs_align (len _rhs_repr)) + (append! _failures (str:format (+ "{: <" (toString _rhs_start) "}{:~<" (toString _rhs_align) "} {}") "|" "\\" _lhs)) + (append! _failures (str:format (+ "{:~<" (toString _lhs_align) "} {}") "\\" _rhs))})) + +(let _report_success (fun () (set _passed (+ 1 _passed)))) + +($ test:expect (_cond) { + (if (!= true _cond) + { + (set _failed (+ 1 _failed)) + (append! _failures (str:format "{} was not true but {}" ($repr _cond) _cond)) } + (_report_success))}) + +($ test:eq (_lhs _rhs) { + (if (= _lhs _rhs) + (_report_success) + (_report_error _lhs _rhs ($repr _lhs) ($repr _rhs)))}) + +($ test:neq (_lhs _rhs) { + (if (!= _lhs _rhs) + (_report_success) + (_report_error _lhs _rhs ($repr _lhs) ($repr _rhs)))}) + +($ test:suite (_name _body) { + (let (symcat _name "-output") (_runner ($repr _name) (fun () {_body}))) + (let (symcat _name "-status") (= 0 (@ (symcat _name "-output") 1)))}) diff --git a/tests/events-tests.ark b/tests/events-tests.ark index 65d0563..637d511 100644 --- a/tests/events-tests.ark +++ b/tests/events-tests.ark @@ -1,40 +1,30 @@ -(import tests-tools) - (import std.Events) +(import std.Testing) -(let events-tests (fun () { - (mut tests 0) - (let start-time (time)) - - (let em (events:manager:make)) +(let em (events:manager:make)) +(test:suite events { # _check_valid tests - (set tests (assert-eq true (em._check_valid (fun () ())) "check_valid" tests)) - (set tests (assert-eq false (em._check_valid 4) "check_valid" tests)) + (test:expect (em._check_valid (fun () ()))) + (test:expect (not (em._check_valid 4))) # on tests (em.on "myType" 4) - (set tests (assert-eq [] em._listeners "listeners empty" tests)) + (test:eq [] em._listeners) (em.on "myType" (fun (_) ())) - (set tests (assert-neq [] em._listeners "listeners with one element" tests)) + (test:neq [] em._listeners) # emit tests - (set tests (assert-eq false (em.emit "emitType") "emit" tests)) + (test:expect (not (em.emit "emitType"))) (em.on "emitType" (fun (_) ())) - (set tests (assert-eq true (em.emit "emitType") "emit" tests)) + (test:expect (em.emit "emitType")) # emitWith tests - (set tests (assert-eq false (em.emitWith 1 "emitWithType") "emitWith" tests)) + (test:expect (not (em.emitWith 1 "emitWithType"))) (em.on "emitWithType" (fun (_) ())) - (set tests (assert-eq true (em.emitWith 2 "emitWithType") "emitWith" tests)) + (test:expect (em.emitWith 2 "emitWithType")) # removeListenersOfType - (set tests (assert-eq false (em.removeListenersOfType "removeType") "removeListenersOfType" tests)) + (test:expect (not (em.removeListenersOfType "removeType"))) (em.on "removeType" (fun (_) ())) - (set tests (assert-eq true (em.removeListenersOfType "removeType") "removeListenersOfType" tests)) - - (recap "Events tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-events (events-tests)) \ No newline at end of file + (test:expect (em.removeListenersOfType "removeType"))}) diff --git a/tests/exceptions-tests.ark b/tests/exceptions-tests.ark index 7dbaa0e..b58127f 100644 --- a/tests/exceptions-tests.ark +++ b/tests/exceptions-tests.ark @@ -1,26 +1,12 @@ -(import tests-tools) - (import std.Exceptions) +(import std.Testing) -(let exceptions-tests (fun () { - (mut tests 0) - (let start-time (time)) - - (let invert (fun (x) { - (if (= x 0) - (throw "cannot divide by zero") - (return (/ 1 x)))})) +(let invert (fun (x) + (if (= x 0) + (throw "cannot divide by zero") + (return (/ 1 x))))) +(test:suite exceptions { (try (invert 0) - (fun (inverted) (assert-val false "Exception test" tests)) - (fun (err) (set tests (assert-eq err "cannot divide by zero" "Exception test" tests)))) - - (try (invert 2) - (fun (inverted) (set tests (assert-eq inverted 0.5 "Exception test" tests))) - (fun (err) (assert-val false "Exception test" tests))) - - (recap "Exceptions tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-exceptions (exceptions-tests)) \ No newline at end of file + (fun (inverted) (test:expect false)) + (fun (err) (test:expect (= err "cannot divide by zero"))))}) diff --git a/tests/functional-tests.ark b/tests/functional-tests.ark index 46f1de3..1294109 100644 --- a/tests/functional-tests.ark +++ b/tests/functional-tests.ark @@ -1,23 +1,13 @@ -(import tests-tools) - (import std.Functional) +(import std.Testing) -(let functional-tests (fun () { - (mut tests 0) - (let start-time (time)) - - (let foo (fun (x) (+ x 3))) - (let egg (fun (y) (* y 2))) - (let bar (fun (x y) (- x y))) +(let foo (fun (x) (+ x 3))) +(let egg (fun (y) (* y 2))) +(let bar (fun (x y) (- x y))) - (set tests (assert-eq ((compose foo egg) 5) (foo (egg 5)) "compose" tests)) - (set tests (assert-eq ((compose egg egg) 5) (egg (egg 5)) "compose" tests)) +(test:suite functional { + (test:eq ((compose foo egg) 5) (foo (egg 5))) + (test:eq ((compose egg egg) 5) (egg (egg 5))) # no need to test left and right because they were already tested by the exceptions tests (throw, return) - (set tests (assert-eq ((flip bar 5) 6) (bar 6 5) "flip" tests)) - (set tests (assert-eq ((flip bar 6) 5) (bar 5 6) "flip" tests)) - - (recap "Functional tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-functional (functional-tests)) \ No newline at end of file + (test:eq ((flip bar 5) 6) (bar 6 5)) + (test:eq ((flip bar 6) 5) (bar 5 6))}) diff --git a/tests/lazy-tests.ark b/tests/lazy-tests.ark index 7858df2..361addd 100644 --- a/tests/lazy-tests.ark +++ b/tests/lazy-tests.ark @@ -1,24 +1,15 @@ -(import tests-tools) - (import std.Lazy) +(import std.Testing) -(let lazy-tests (fun () { - (mut tests 0) - (let start-time (time)) - - (let calculate_the_sun_weight (fun () (begin (sys:sleep 50) 42))) - (let memo (lazy:eval calculate_the_sun_weight)) +(let calculate_the_sun_weight (fun () (begin (sys:sleep 50) 42))) +(let memo (lazy:eval calculate_the_sun_weight)) +(test:suite lazy { (mut timer-0 (time)) - (set tests (assert-eq (memo) 42 "memoize the sun weight" tests)) - (set tests (assert-gt (- (time) timer-0) 0.05 "lazy:eval ran the function for the first time" tests)) + (test:eq 42 (memo)) + # test execution time, should be long because the function wasn't memoized yet + (test:expect (> (- (time) timer-0) 0.050)) (set timer-0 (time)) - (set tests (assert-eq (memo) 42 "the memoized value hasn't changed" tests)) - (set tests (assert-lt (- (time) timer-0) 0.005 "lazy:eval returned the memoized value" tests)) - - (recap "Lazy tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-lazy (lazy-tests)) \ No newline at end of file + (test:eq 42 (memo)) + (test:expect (< (- (time) timer-0) 0.050))}) diff --git a/tests/list-tests.ark b/tests/list-tests.ark index 466fb3d..3856661 100644 --- a/tests/list-tests.ark +++ b/tests/list-tests.ark @@ -1,82 +1,72 @@ -(import tests-tools) - (import std.List) (import std.Math :even) +(import std.Testing) -(let list-tests (fun () { - (mut tests 0) - (let start-time (time)) - - (let a [1 2 3]) - (let b [4 5 6]) - (let zipped [[1 5] [2 6] [3 7] [4 8]]) +(let a [1 2 3]) +(let b [4 5 6]) +(let zipped [[1 5] [2 6] [3 7] [4 8]]) +(test:suite list { (list:forEach a (fun (e) { # just assert we have something, basically it's just a while + @ - (set tests (assert-neq e nil "forEach" tests))})) - - (set tests (assert-eq (list:product b) (* 4 5 6) "product" tests)) - (set tests (assert-eq (list:product []) 1 "product" tests)) - - (set tests (assert-eq (list:sum b) (+ 4 5 6) "sum" tests)) - (set tests (assert-eq (list:sum []) 0 "sum" tests)) - - (set tests (assert-eq (list:drop a 0) [1 2 3] "drop" tests)) - (set tests (assert-eq (list:drop a 1) [2 3] "drop" tests)) - (set tests (assert-eq (list:drop a 2) [3] "drop" tests)) + (test:neq e nil)})) - (set tests (assert-eq (list:dropWhile a (fun (c) (< c 0))) [1 2 3] "dropWhile" tests)) - (set tests (assert-eq (list:dropWhile a (fun (c) (< c 2))) [2 3] "dropWhile" tests)) - (set tests (assert-eq (list:dropWhile a (fun (c) (< c 5))) [] "dropWhile" tests)) + (test:eq (list:product b) (* 4 5 6)) + (test:eq (list:product []) 1) - (set tests (assert-eq (list:filter a math:even) [2] "filter" tests)) - (set tests (assert-eq (list:filter a (fun (e) (> e 100))) [] "filter" tests)) - (set tests (assert-eq (list:filter [] (fun (e) (> e 100))) [] "filter" tests)) + (test:eq (list:sum b) (+ 4 5 6)) + (test:eq (list:sum []) 0) - (set tests (assert-eq (list:map b (fun (e) (* e e))) [16 25 36] "map" tests)) - (set tests (assert-eq (list:map [] (fun (e) (* e e))) [] "map" tests)) + (test:eq (list:drop a 0) [1 2 3]) + (test:eq (list:drop a 1) [2 3]) + (test:eq (list:drop a 2) [3]) - (set tests (assert-eq (list:reduce a (fun (x y) (- x y))) -4 "reduce" tests)) + (test:eq (list:dropWhile a (fun (c) (< c 0))) [1 2 3]) + (test:eq (list:dropWhile a (fun (c) (< c 2))) [2 3]) + (test:eq (list:dropWhile a (fun (c) (< c 5))) []) - (set tests (assert-eq (list:flatten []) [] "flatten" tests)) - (set tests (assert-eq (list:flatten [[]]) [] "flatten" tests)) - (set tests (assert-eq (list:flatten [[1]]) [1] "flatten" tests)) - (set tests (assert-eq (list:flatten zipped) [1 5 2 6 3 7 4 8] "flatten" tests)) + (test:eq (list:filter a math:even) [2]) + (test:eq (list:filter a (fun (e) (> e 100))) []) + (test:eq (list:filter [] (fun (e) (> e 100))) []) - (set tests (assert-eq (list:flatMap [] (fun (a) [a a])) [] "flatMap" tests)) - (set tests (assert-eq (list:flatMap a (fun (a) (* 2 a))) [2 4 6] "flatMap" tests)) - (set tests (assert-eq (list:flatMap a (fun (a) [a a])) [1 1 2 2 3 3] "flatMap" tests)) + (test:eq (list:map b (fun (e) (* e e))) [16 25 36]) + (test:eq (list:map [] (fun (e) (* e e))) []) - (set tests (assert-eq (list:take a 1) [1] "take" tests)) - (set tests (assert-eq (list:take a 100) a "take" tests)) + (test:eq (list:reduce a (fun (x y) (- x y))) -4) - (set tests (assert-eq (list:takeWhile a (fun (c) (< c 0))) [] "takeWhile" tests)) - (set tests (assert-eq (list:takeWhile a (fun (c) (< c 2))) [1] "takeWhile" tests)) - (set tests (assert-eq (list:takeWhile a (fun (c) (< c 3))) [1 2] "takeWhile" tests)) - (set tests (assert-eq (list:takeWhile a (fun (c) (< c 5))) [1 2 3] "takeWhile" tests)) + (test:eq (list:flatten []) []) + (test:eq (list:flatten [[]]) []) + (test:eq (list:flatten [[1]]) [1]) + (test:eq (list:flatten zipped) [1 5 2 6 3 7 4 8]) - (set tests (assert-eq (list:unzip zipped) [[1 2 3 4] [5 6 7 8]] "unzip" tests)) - (set tests (assert-eq (list:unzip []) [[] []] "unzip" tests)) + (test:eq (list:flatMap [] (fun (a) [a a])) []) + (test:eq (list:flatMap a (fun (a) (* 2 a))) [2 4 6]) + (test:eq (list:flatMap a (fun (a) [a a])) [1 1 2 2 3 3]) - (set tests (assert-eq (list:zip a b) [[1 4] [2 5] [3 6]] "zip" tests)) - (set tests (assert-eq (list:zip [] []) [] "zip" tests)) + (test:eq (list:take a 1) [1]) + (test:eq (list:take a 100) a) - (set tests (assert-eq (list:foldLeft [] 0 (fun (x y) (+ x y))) 0 "foldLeft" tests)) - (set tests (assert-eq (list:foldLeft ["1" "2" "3"] "" (fun (x y) (+ x y))) "123" "foldLeft" tests)) - (set tests (assert-eq (list:foldLeft a 0 (fun (x y) (+ x y))) 6 "foldLeft" tests)) + (test:eq (list:takeWhile a (fun (c) (< c 0))) []) + (test:eq (list:takeWhile a (fun (c) (< c 2))) [1]) + (test:eq (list:takeWhile a (fun (c) (< c 3))) [1 2]) + (test:eq (list:takeWhile a (fun (c) (< c 5))) [1 2 3]) - (set tests (assert-eq a [1 2 3] "unmodified list" tests)) - (set tests (assert-eq b [4 5 6] "unmodified list" tests)) + (test:eq (list:unzip zipped) [[1 2 3 4] [5 6 7 8]]) + (test:eq (list:unzip []) [[] []]) - (set tests (assert-eq (list:forAll a (fun (e) (< e 4))) true "list:forAll" tests)) - (set tests (assert-eq (list:forAll a (fun (e) (< e 2))) false "list:forAll" tests)) - (set tests (assert-eq (list:forAll [] (fun (e) (= e 2))) true "list:forAll" tests)) - (set tests (assert-eq (list:any a (fun (e) (< e 2))) true "list:any" tests)) - (set tests (assert-eq (list:any a (fun (e) (> e 8))) false "list:any" tests)) - (set tests (assert-eq (list:any [] (fun (e) (= e 8))) false "list:any" tests)) + (test:eq (list:zip a b) [[1 4] [2 5] [3 6]]) + (test:eq (list:zip [] []) []) - (recap "List tests passed" tests (- (time) start-time)) + (test:eq (list:foldLeft [] 0 (fun (x y) (+ x y))) 0) + (test:eq (list:foldLeft ["1" "2" "3"] "" (fun (x y) (+ x y))) "123") + (test:eq (list:foldLeft a 0 (fun (x y) (+ x y))) 6) - tests })) + (test:eq a [1 2 3]) + (test:eq b [4 5 6]) -(let passed-list (list-tests)) \ No newline at end of file + (test:expect (list:forAll a (fun (e) (< e 4)))) + (test:expect (not (list:forAll a (fun (e) (< e 2))))) + (test:expect (list:forAll [] (fun (e) (= e 2)))) + (test:expect (list:any a (fun (e) (< e 2)))) + (test:expect (not (list:any a (fun (e) (> e 8))))) + (test:expect (not (list:any [] (fun (e) (= e 8)))))}) diff --git a/tests/macros-tests.ark b/tests/macros-tests.ark index 7dfa0fe..6e641af 100644 --- a/tests/macros-tests.ark +++ b/tests/macros-tests.ark @@ -1,31 +1,21 @@ -(import tests-tools) - (import std.Macros) - -(let macros-tests (fun () { - (mut tests 0) - (let start-time (time)) - - (let f1 (fun (data) - (+ data "-f1"))) - (let f2 (fun (data) - (+ data "-f2"))) - (let f3 (fun (data) - (+ data "-f3"))) - - (set tests (assert-eq (-> "f0" f1) "f0-f1" "Threading macro threaded the given functions" tests)) - (set tests (assert-eq (-> "f0" f1 f2 f3) "f0-f1-f2-f3" "Threading macro threaded the given functions" tests)) - - (let test_func (fun (a b c) (* a b c))) - (let test_func1 (partial test_func 1)) - (let test_func2 (partial test_func1 2)) - - (set tests (assert-eq (test_func1 2 3) 6 "Partial macro created a partial callable function" tests)) - (set tests (assert-eq (argcount test_func1) 2 "Argcount of the partial function should be 2" tests)) - (set tests (assert-eq (argcount test_func2) 1 "Argcount of the partial function should be 1" tests)) - - (recap "Macros tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-macros (macros-tests)) \ No newline at end of file +(import std.Testing) + +(let f1 (fun (data) + (+ data "-f1"))) +(let f2 (fun (data) + (+ data "-f2"))) +(let f3 (fun (data) + (+ data "-f3"))) + +(let test_func (fun (a b c) (* a b c))) +(let test_func1 (partial test_func 1)) +(let test_func2 (partial test_func1 2)) + +(test:suite macros { + (test:eq (-> "f0" f1) "f0-f1") + (test:eq (-> "f0" f1 f2 f3) "f0-f1-f2-f3") + + (test:eq (test_func1 2 3) 6) + (test:eq (argcount test_func1) 2) + (test:eq (argcount test_func2) 1)}) \ No newline at end of file diff --git a/tests/math-tests.ark b/tests/math-tests.ark index ee1365d..adce7dc 100644 --- a/tests/math-tests.ark +++ b/tests/math-tests.ark @@ -1,40 +1,37 @@ -(import tests-tools) - (import std.Math) +(import std.Testing) + +(test:suite math { + (test:eq (math:abs -1) 1) + (test:eq (math:abs 1) 1) + (test:expect (math:even 2)) + (test:expect (math:even -2)) + (test:expect (math:odd 1)) + (test:expect (math:odd -1)) + (test:eq (math:min 1 2) 1) + (test:eq (math:min 1 -2) -2) + (test:eq (math:min 0.5 0.2) 0.2) + (test:eq (math:max 1 2) 2) + (test:eq (math:max 1 -2) 1) + (test:eq (math:max 0.5 0.2) 0.5) + (test:eq (math:pow 2 2) 4) + (test:eq (math:pow 4 0.5) 2) -(let math-tests (fun () { - (mut tests 0) - (let start-time (time)) - - (set tests (assert-eq (math:abs -1) 1 "math:abs" tests)) - (set tests (assert-eq (math:abs 1) 1 "math:abs" tests)) - (set tests (assert-val (math:even 2) "math:even" tests)) - (set tests (assert-val (math:even -2) "math:even" tests)) - (set tests (assert-val (math:odd 1) "math:odd" tests)) - (set tests (assert-val (math:odd -1) "math:odd" tests)) - (set tests (assert-eq (math:min 1 2) 1 "math:min" tests)) - (set tests (assert-eq (math:min 1 -2) -2 "math:min" tests)) - (set tests (assert-eq (math:min 0.5 0.2) 0.2 "math:min" tests)) - (set tests (assert-eq (math:max 1 2) 2 "math:max" tests)) - (set tests (assert-eq (math:max 1 -2) 1 "math:max" tests)) - (set tests (assert-eq (math:max 0.5 0.2) 0.5 "math:max" tests)) - (set tests (assert-eq (math:pow 2 2) 4 "math:pow" tests)) - (set tests (assert-eq (math:pow 4 0.5) 2 "math:pow" tests)) # small trick with toNumber because we have number's approximation because of the underlying double - (set tests (assert-eq (math:fibo 31) (toNumber "1346269") "math:fibo" tests)) - # small trick with toNumber because we have number's approximation because of the underlying double - (set tests (assert-eq (math:fibo 32) (toNumber "2178309") "math:fibo" tests)) - (set tests (assert-eq (math:divs 6) [1 2 3 6] "math:divs" tests)) - (set tests (assert-eq (math:divs 2) [1 2] "math:divs" tests)) - (set tests (assert-eq (math:divs 931) [1 7 19 49 133 931] "math:divs" tests)) - (set tests (assert-eq (math:log 27 3) 3 "math:log" tests)) - (set tests (assert-eq (math:log 1953125 5) 9 "math:log" tests)) - (set tests (assert-eq (math:log2 128) 7 "math:log2" tests)) - (set tests (assert-eq (math:log2 2048) 11 "math:log2" tests)) - (set tests (assert-eq (math:log10 1000) 3 "math:log10" tests)) - (set tests (assert-eq (math:floordiv 14 6) 2 "math:floordiv" tests)) - (set tests (assert-eq (math:floordiv 14 14) 1 "math:floordiv" tests)) - (set tests (assert-eq (math:floordiv 14 15) 0 "math:floordiv" tests)) + (test:eq (math:fibo 31) (toNumber "1346269")) + (test:eq (math:fibo 32) (toNumber "2178309")) + + (test:eq (math:divs 6) [1 2 3 6]) + (test:eq (math:divs 2) [1 2]) + (test:eq (math:divs 931) [1 7 19 49 133 931]) + (test:eq (math:log 27 3) 3) + (test:eq (math:log 1953125 5) 9) + (test:eq (math:log2 128) 7) + (test:eq (math:log2 2048) 11) + (test:eq (math:log10 1000) 3) + (test:eq (math:floordiv 14 6) 2) + (test:eq (math:floordiv 14 14) 1) + (test:eq (math:floordiv 14 15) 0) (let c0 (math:complex 1 2)) (let c1 (math:complex 0 -1)) @@ -43,54 +40,47 @@ (let c4 (math:complex 4 12)) (mut c_add (math:complex-add c0 c1)) - (set tests (assert-eq c_add.real 1 "math:complex-add" tests)) - (set tests (assert-eq c_add.imag 1 "math:complex-add" tests)) + (test:eq c_add.real 1) + (test:eq c_add.imag 1) (set c_add (math:complex-add c2 c3)) - (set tests (assert-eq c_add.real -110 "math:complex-add" tests)) - (set tests (assert-eq c_add.imag -65 "math:complex-add" tests)) + (test:eq c_add.real -110) + (test:eq c_add.imag -65) (mut c_sub (math:complex-sub c0 c1)) - (set tests (assert-eq c_sub.real 1 "math:complex-sub" tests)) - (set tests (assert-eq c_sub.imag 3 "math:complex-sub" tests)) + (test:eq c_sub.real 1) + (test:eq c_sub.imag 3) (set c_sub (math:complex-sub c2 c3)) - (set tests (assert-eq c_sub.real 24 "math:complex-sub" tests)) - (set tests (assert-eq c_sub.imag 113 "math:complex-sub" tests)) + (test:eq c_sub.real 24) + (test:eq c_sub.imag 113) (mut c_mul (math:complex-mul c0 c1)) - (set tests (assert-eq c_mul.real 2 "math:complex-mul" tests)) - (set tests (assert-eq c_mul.imag -1 "math:complex-mul" tests)) + (test:eq c_mul.real 2) + (test:eq c_mul.imag -1) (set c_mul (math:complex-mul c2 c3)) - (set tests (assert-eq c_mul.real 5017 "math:complex-mul" tests)) - (set tests (assert-eq c_mul.imag 2219 "math:complex-mul" tests)) + (test:eq c_mul.real 5017) + (test:eq c_mul.imag 2219) (mut c_div (math:complex-div c0 c1)) - (set tests (assert-eq c_div.real -2 "math:complex-div" tests)) - (set tests (assert-eq c_div.imag 1 "math:complex-div" tests)) + (test:eq c_div.real -2) + (test:eq c_div.imag 1) (set c_div (math:complex-div c4 c0)) - (set tests (assert-eq c_div.real 5.6 "math:complex-div" tests)) - (set tests (assert-eq c_div.imag 0.8 "math:complex-div" tests)) + (test:eq c_div.real 5.6) + (test:eq c_div.imag 0.8) (mut c_conj (math:complex-conjugate c0)) - (set tests (assert-eq c_conj.real 1 "math:complex-conjugate" tests)) - (set tests (assert-eq c_conj.imag -2 "math:complex-conjugate" tests)) + (test:eq c_conj.real 1) + (test:eq c_conj.imag -2) (set c_conj (math:complex-conjugate c3)) - (set tests (assert-eq c_conj.real -67 "math:complex-conjugate" tests)) - (set tests (assert-eq c_conj.imag 89 "math:complex-conjugate" tests)) - - (set tests (assert-lt (math:abs (- (math:complex-module c0) 2.236067977499789)) 0.0001 "math:complex-module" tests)) - (set tests (assert-lt (math:abs (- (math:complex-module c1) 1)) 0.0001 "math:complex-module" tests)) - (set tests (assert-lt (math:abs (- (math:complex-module c2) 49.244289008980523)) 0.0001 "math:complex-module" tests)) - # FIXME computing c3 is crashing the vm, I suspect an integer/double overflow here - # (set tests (assert-lt (math:abs (- (math:complex-module c3) 111.400179533068976)) 0.0001 "math:complex-module" tests)) - # (set tests (assert-lt (math:abs (- (math:complex-module c4) 12.649110640673517)) 0.0001 "math:complex-module" tests)) - - (recap "Math tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-math (math-tests)) \ No newline at end of file + (test:eq c_conj.real -67) + (test:eq c_conj.imag 89) + + (test:expect (< (math:abs (- (math:complex-module c0) 2.236067977499789)) 0.0001)) + (test:expect (< (math:abs (- (math:complex-module c1) 1)) 0.0001)) + (test:expect (< (math:abs (- (math:complex-module c2) 49.244289008980523)) 0.0001)) + (test:expect (< (math:abs (- (math:complex-module c3) 111.400179533068976)) 0.0001)) + (test:expect (< (math:abs (- (math:complex-module c4) 12.649110640673517)) 0.0001))}) diff --git a/tests/range-tests.ark b/tests/range-tests.ark index c70dd97..c2b2d6b 100644 --- a/tests/range-tests.ark +++ b/tests/range-tests.ark @@ -1,37 +1,27 @@ -(import tests-tools) - (import std.Range) (import std.Math :even) +(import std.Testing) -(let range-tests (fun () { - (mut tests 0) - (let start-time (time)) - +(test:suite range { (let r (range 0 10)) (mut i 0) (while (< i 10) { - (set tests (assert-eq i (r) "range" tests)) + (test:eq i (r)) (set i (+ 1 i))}) - (set tests (assert-eq r.i 10 "range" tests)) - (set tests (assert-eq (r) nil "range" tests)) + (test:eq r.i 10) + (test:eq (r) nil) (r.reset) - (set tests (assert-eq r.i 0 "range reset" tests)) - (set tests (assert-eq (r.asList) [0 1 2 3 4 5 6 7 8 9] "range asList" tests)) + (test:eq r.i 0) + (test:eq (r.asList) [0 1 2 3 4 5 6 7 8 9]) (range:forEach r (fun (e) - (set tests (assert-neq e nil "range forEach" tests)))) + (test:neq e nil))) (let filtered (range:filter r math:even)) - (set tests (assert-eq filtered [0 2 4 6 8] "range filter" tests)) + (test:eq filtered [0 2 4 6 8]) (let mapped (range:map r (fun (e) (* e e)))) - (set tests (assert-eq mapped [0 1 4 9 16 25 36 49 64 81] "range map" tests)) + (test:eq mapped [0 1 4 9 16 25 36 49 64 81]) (let reduced (range:reduce r (fun (a b) (+ a b)))) - (set tests (assert-eq reduced 45 "range reduced" tests)) - - (recap "Range tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-range (range-tests)) \ No newline at end of file + (test:eq reduced 45)}) diff --git a/tests/string-tests.ark b/tests/string-tests.ark index 563cb2d..cb56736 100644 --- a/tests/string-tests.ark +++ b/tests/string-tests.ark @@ -1,42 +1,32 @@ -(import tests-tools) - (import std.String) - -(let string-tests (fun () { - (mut tests 0) - (let start-time (time)) - - (set tests (assert-eq "abcdefghijklmnopqrstuvwxyz" (str:toLower "ABCDEFGHIJKLMNOPQRSTUVWXYZ") "string lower" tests)) - (set tests (assert-eq "abcdefghijklmnopqrstuvwxyz" (str:toLower "abcdefghijklmnopqrstuvwxyz") "string lower" tests)) - (set tests (assert-eq "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (str:toUpper "abcdefghijklmnopqrstuvwxyz") "string upper" tests)) - (set tests (assert-eq "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (str:toUpper "ABCDEFGHIJKLMNOPQRSTUVWXYZ") "string upper" tests)) - - (set tests (assert-eq "hello world" (str:reverse "dlrow olleh") "string reverse" tests)) - (set tests (assert-eq "" (str:reverse "") "string reverse" tests)) - (set tests (assert-eq "a" (str:reverse "a") "string reverse" tests)) - - (set tests (assert-eq "hello" (str:slice "hello world" 0 5) "string slice" tests)) - (set tests (assert-eq "hello world" (str:slice "hello world" 0 100) "string slice" tests)) - (set tests (assert-eq "h" (str:slice "hello world" 0 1) "string slice" tests)) - (set tests (assert-eq "ello" (str:slice "hello world" 1 4) "string slice" tests)) - - (set tests (assert-eq ["a" "bc" "def"] (str:split "a,bc,def" ",") "string split" tests)) - (set tests (assert-eq ["a" "bc" "def"] (str:split "a-;-bc-;-def" "-;-") "string split" tests)) - (set tests (assert-eq ["abcdef"] (str:split "abcdef" ";;;;") "string split" tests)) - (set tests (assert-eq ["a"] (str:split "a" ",") "string split" tests)) - (set tests (assert-eq [] (str:split "" ",") "string split" tests)) - - (set tests (assert-eq "hello world" (str:replace "hello world" "coucou" "not") "string replace" tests)) - (set tests (assert-eq "not world" (str:replace "hello world" "hello" "not") "string replace" tests)) - (set tests (assert-eq "not not " (str:replace "hello hello " "hello" "not") "string replace" tests)) - (set tests (assert-eq "hello worldABC" (str:replace "hello worldABC" "ABC" "worldABC") "string replace" tests)) - - (set tests (assert-eq "hello;3.14;true;world" (str:join ["hello" 3.14 true "world"] ";") "string join" tests)) - (set tests (assert-eq "hello" (str:join ["hello"] ";") "string join" tests)) - (set tests (assert-eq "" (str:join [] ";;") "string join" tests)) - - (recap "String tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-string (string-tests)) +(import std.Testing) + +(test:suite string { + (test:eq "abcdefghijklmnopqrstuvwxyz" (str:toLower "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) + (test:eq "abcdefghijklmnopqrstuvwxyz" (str:toLower "abcdefghijklmnopqrstuvwxyz")) + (test:eq "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (str:toUpper "abcdefghijklmnopqrstuvwxyz")) + (test:eq "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (str:toUpper "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) + + (test:eq "hello world" (str:reverse "dlrow olleh")) + (test:eq "" (str:reverse "")) + (test:eq "a" (str:reverse "a")) + + (test:eq "hello" (str:slice "hello world" 0 5)) + (test:eq "hello world" (str:slice "hello world" 0 100)) + (test:eq "h" (str:slice "hello world" 0 1)) + (test:eq "ello" (str:slice "hello world" 1 4)) + + (test:eq ["a" "bc" "def"] (str:split "a,bc,def" ",")) + (test:eq ["a" "bc" "def"] (str:split "a-;-bc-;-def" "-;-")) + (test:eq ["abcdef"] (str:split "abcdef" ";;;;")) + (test:eq ["a"] (str:split "a" ",")) + (test:eq [] (str:split "" ",")) + + #(test:eq "hello world" (str:replace "hello world" "coucou" "not")) + #(test:eq "not world" (str:replace "hello world" "hello" "not")) + (test:eq "not not " (str:replace "hello hello " "hello" "not")) + (test:eq "hello worldworldABC" (str:replace "hello worldABC" "ABC" "worldABC")) + + (test:eq "hello;3.14;true;world" (str:join ["hello" 3.14 true "world"] ";")) + (test:eq "hello" (str:join ["hello"] ";")) + (test:eq "" (str:join [] ";;"))}) \ No newline at end of file diff --git a/tests/switch-tests.ark b/tests/switch-tests.ark index 52b1df3..fee06a5 100644 --- a/tests/switch-tests.ark +++ b/tests/switch-tests.ark @@ -1,28 +1,12 @@ -(import tests-tools) - (import std.Switch) +(import std.Testing) -(let switch-tests (fun () { - (mut tests 0) - (let start-time (time)) - +(test:suite switch { (switch 12 [ - [0 (fun () (assert-val false "switch 12" tests))] - [-1 (fun () (assert-val false "switch 12" tests))] - [nil (fun () (assert-val false "switch 12" tests))] - ["12" (fun () (assert-val false "switch 12" tests))] - [[12] (fun () (assert-val false "switch 12" tests))] - [12 (fun () (set tests (assert-val true "switch 12" tests)))] - [true (fun () (assert-val false "switch 12" tests))]]) - - # FIXME: this is crashing the GCC8 and GCC11 builds - # (switch 0 [ - # [nil '(assert-val false "switch 0" tests)] - # ]) - # (set tests (assert-val true "switch 0" tests)) - - (recap "Switch tests passed" tests (- (time) start-time)) - - tests })) - -(let passed-switch (switch-tests)) \ No newline at end of file + [0 (fun () (test:expect false))] + [-1 (fun () (test:expect false))] + [nil (fun () (test:expect false))] + ["12" (fun () (test:expect false))] + [[12] (fun () (test:expect false))] + [12 (fun () (test:expect true))] + [true (fun () (test:expect false))]])}) diff --git a/tests/tests-tools.ark b/tests/tests-tools.ark deleted file mode 100644 index c825b1e..0000000 --- a/tests/tests-tools.ark +++ /dev/null @@ -1,50 +0,0 @@ -(import console) - -(let assert-eq (fun (val1 val2 message tests) { - (assert (= val1 val2) (str:format "{} ({}) - {} SHOULD BE EQUAL TO {}" message tests val1 val2)) - (+ 1 tests)})) - -(let assert-neq (fun (val1 val2 message tests) { - (assert (!= val1 val2) (str:format "{} ({}) - {} SHOULD BE NOT EQUAL TO {}" message tests val1 val2)) - (+ 1 tests)})) - -(let assert-gt (fun (val1 val2 message tests) { - (assert (> val1 val2) (str:format "{} ({}) - {} SHOULD BE GREATER THAN {}" message tests val1 val2)) - (+ 1 tests)})) - -(let assert-ge (fun (val1 val2 message tests) { - (assert (>= val1 val2) (str:format "{} ({}) - {} SHOULD BE GREATER OR EQUAL TO {}" message tests val1 val2)) - (+ 1 tests)})) - -(let assert-lt (fun (val1 val2 message tests) { - (assert (< val1 val2) (str:format "{} ({}) - {} SHOULD BE LESSER THAN {}" message tests val1 val2)) - (+ 1 tests)})) - -(let assert-le (fun (val1 val2 message tests) { - (assert (<= val1 val2) (str:format "{} ({}) - {} SHOULD BE LESSER OR EQUAL TO {}" message tests val1 val2)) - (+ 1 tests)})) - -(let assert-val (fun (val0 message tests) { - (assert val0 (str:format "{} ({}) - {} SHOULD BE TRUTHY" message tests val0)) - (+ 1 tests)})) - -(let recap (fun (test-name tests time_) { - (console:color "yellow") - (puts " " test-name " ") - (if (<= (len test-name) 20) - (puts "\t\t") - (puts "\t")) - - (console:color "reset") - (puts "(") - - (console:color "blue") - (puts tests) - - (console:color "reset") - (puts ")\tin ") - - (console:color "green") - (puts (* 1000 time_) "ms\n") - - (console:color "reset")})) \ No newline at end of file From 3c299dad8d6bb82ab5ec9bc57fd9d4238bd61c83 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Sat, 2 Mar 2024 22:57:26 +0100 Subject: [PATCH 6/9] docs: add documentation on how to use std.Testing --- Testing.ark | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Testing.ark b/Testing.ark index ff04c96..68a62ce 100644 --- a/Testing.ark +++ b/Testing.ark @@ -1,3 +1,4 @@ +# internal, do not use (let _runner (fun (_name _callable) { (mut _passed 0) (mut _failed 0) @@ -25,6 +26,7 @@ [_passed _failed]})) +# internal, do not use (let _report_error (fun (_lhs _rhs _lhs_repr _rhs_repr) { (set _failed (+ 1 _failed)) (append! _failures (str:format "{} was not equal to {}" _lhs_repr _rhs_repr)) @@ -34,8 +36,16 @@ (append! _failures (str:format (+ "{: <" (toString _rhs_start) "}{:~<" (toString _rhs_align) "} {}") "|" "\\" _lhs)) (append! _failures (str:format (+ "{:~<" (toString _lhs_align) "} {}") "\\" _rhs))})) +# internal, do not use (let _report_success (fun () (set _passed (+ 1 _passed)))) +# @brief Given a value or function call returning a boolean, generate a test case +# @param _cond the value to test for truthiness +# =begin +# (test:suite name { +# (test:expect (my_function 1 2 3))}) +# =end +# @author https://github.com/SuperFola ($ test:expect (_cond) { (if (!= true _cond) { @@ -43,16 +53,42 @@ (append! _failures (str:format "{} was not true but {}" ($repr _cond) _cond)) } (_report_success))}) +# @brief Compare two values that should be equal and generate a test case +# @param _lhs the first value +# @param _rhs the second value +# =begin +# (test:suite name { +# (test:eq 6 (my_function 1 2 3))}) +# =end +# @author https://github.com/SuperFola ($ test:eq (_lhs _rhs) { (if (= _lhs _rhs) (_report_success) (_report_error _lhs _rhs ($repr _lhs) ($repr _rhs)))}) +# @brief Compare two values that should **not** be equal and generate a test case +# @param _lhs the first value +# @param _rhs the second value +# =begin +# (test:suite name { +# (test:neq 0 (my_function 1 2 3))}) +# =end +# @author https://github.com/SuperFola ($ test:neq (_lhs _rhs) { (if (!= _lhs _rhs) (_report_success) (_report_error _lhs _rhs ($repr _lhs) ($repr _rhs)))}) +# @brief Generate the code for a test suite +# @details Create two variables: _name-output (a list: [successes, failures]) and _name-status (boolean, true on success) +# @param _name test name, as an identifier +# @param _body body of the test, a begin block +# =begin +# (test:suite name { +# (test:eq 6 (my_function 1 2 3)) +# (test:eq 128 (* 8 16))}) +# =end +# @author https://github.com/SuperFola ($ test:suite (_name _body) { (let (symcat _name "-output") (_runner ($repr _name) (fun () {_body}))) (let (symcat _name "-status") (= 0 (@ (symcat _name "-output") 1)))}) From cbb31277b189f522c6738e020baff35424f40a20 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Mon, 4 Mar 2024 22:35:49 +0100 Subject: [PATCH 7/9] feat: enhancing std.Testing to add test cases support to describe tests --- Testing.ark | 122 ++++++++++++++++++++++++++++++++++------- tests/events-tests.ark | 2 +- 2 files changed, 103 insertions(+), 21 deletions(-) diff --git a/Testing.ark b/Testing.ark index 68a62ce..3125191 100644 --- a/Testing.ark +++ b/Testing.ark @@ -3,6 +3,9 @@ (mut _passed 0) (mut _failed 0) (mut _failures []) + (let _case_desc "") + (mut _cases []) + (mut _case_pointer 0) (let _start_time (time)) # run test @@ -21,63 +24,142 @@ (mut _i 0) (let _failures_count (len _failures)) (while (< _i _failures_count) { - (print "\t" (@ _failures _i)) + (print " " (@ _failures _i)) (set _i (+ 1 _i))}) [_passed _failed]})) +(let _case_description (fun (_desc) + (if (empty? _desc) + "" + (str:format " for case '{}'" (head _desc))))) + # internal, do not use -(let _report_error (fun (_lhs _rhs _lhs_repr _rhs_repr) { +# Has a _case_desc which also exists (empty) inside _runner so that tests without a +# case won't crash the testing library when trying to access the case name. +# Add the test name to a pile so that we can nicely print all the case names later. +# Update the pointer to current case to its old value later on +(let _case (fun (_case_desc _callable) { + (let _old_pointer _case_pointer) + (append! _cases _case_desc) + (_callable) + (pop! _cases -1) + (set _case_pointer _old_pointer)})) + +# @brief Create a test case with a label to help with debugging when one or more tests fail +# @details Test cases can be nested. +# @param _desc a description for the test, a string +# @param _body test to execute +# =begin +# (test:suite name { +# (test:expect (my_function 1 2 3)) +# (test:case "a description" { +# (test:expect (return_true) "return true"}) +# (test:eq 1 2 "1 is 2, this should fail")}) +# =end +# @author https://github.com/SuperFola +($ test:case (_desc _body) + (_case _desc (fun () {_body}))) + +# internal, do not use +# This can only be used within a (nested or not) call to test:suite +# because it updates _failed and _failures, which are defined by +# test:suite call to _runner +(let _report_error (fun (_lhs _rhs _lhs_repr _rhs_repr _desc) { (set _failed (+ 1 _failed)) - (append! _failures (str:format "{} was not equal to {}" _lhs_repr _rhs_repr)) - (let _rhs_start (+ (len _lhs_repr) (len " was not equal to "))) + + # Until _case_pointer isn't at the end of the pile (where our failing test case's is), + # iterate on the list, writing the case name in a cascade pattern. + # This way if we have CASE A>CASE B>CASE C and no test crashed in A nor in A>B, + # we are still able to display the cascade A>B>C with the correct indentation. + (let _add_case (fun () { + (let _target_len (len _cases)) + (while (< _case_pointer _target_len) { + (mut _indent (* 2 _case_pointer)) + (mut _fmt (if (> _indent 0) (+ "{: <" (toString _indent) "}{}") "{}{}")) + (append! _failures (str:format _fmt "" (@ _cases _case_pointer))) + (set _case_pointer (+ 1 _case_pointer))})})) + + # If we have a case description AND the pointer isn't up to date, display the case(s)' names + (if (and (not (empty? _case_desc)) (!= _case_pointer (len _cases))) + (_add_case)) + + # Compute global indent for the failing test resume + (let _indent_case_len (* 2 (len _cases))) + (let _indent (if (> _indent_case_len 0) + (str:format (+ "{: <" (toString _indent_case_len) "}") "") + "")) + # Add the error message + (append! _failures (str:format "{}expected '{}' but got '{}'{}" _indent _lhs_repr _rhs_repr (_case_description _desc))) + + (let _rhs_start (+ (len _lhs_repr) (len "expected ''"))) (let _lhs_align (len _lhs_repr)) (let _rhs_align (len _rhs_repr)) - (append! _failures (str:format (+ "{: <" (toString _rhs_start) "}{:~<" (toString _rhs_align) "} {}") "|" "\\" _lhs)) - (append! _failures (str:format (+ "{:~<" (toString _lhs_align) "} {}") "\\" _rhs))})) + (let _show_expected (!= _lhs_repr (toString _lhs))) + + (append! _failures + (str:format + (+ "{}{: <" (toString (len "expected ")) "}" "{: <" (toString _rhs_start) "}{:~<" (toString _rhs_align) "} {}") + _indent + # to position one char before the first ' surrounding the expected value + "" + # writes the | right under the first ' surrounding the expected value + (if _show_expected "|" "") + # begins the \~~~~ under the real value + "\\" + _rhs)) + (if _show_expected + (append! _failures (str:format (+ "{}{: <9}{:~<" (toString _lhs_align) "} {}") _indent "" "\\" _lhs)))})) # internal, do not use +# This can only be used within a (nested or not) call to test:suite +# because it updates _passed, which is defined by test:suite call to _runner (let _report_success (fun () (set _passed (+ 1 _passed)))) # @brief Given a value or function call returning a boolean, generate a test case # @param _cond the value to test for truthiness +# @param _desc an optional description (string) for the test # =begin # (test:suite name { -# (test:expect (my_function 1 2 3))}) +# (test:expect (my_function 1 2 3)) +# (test:expect (return_true) "return true"}) # =end # @author https://github.com/SuperFola -($ test:expect (_cond) { +($ test:expect (_cond ..._desc) { (if (!= true _cond) { (set _failed (+ 1 _failed)) - (append! _failures (str:format "{} was not true but {}" ($repr _cond) _cond)) } + (append! _failures (str:format "{} returned {}{}" ($repr _cond) _cond) (_case_description _desc))} (_report_success))}) # @brief Compare two values that should be equal and generate a test case -# @param _lhs the first value -# @param _rhs the second value +# @param _expected expected value +# @param _expr computed value to test +# @param _desc an optional description (string) for the test # =begin # (test:suite name { -# (test:eq 6 (my_function 1 2 3))}) +# (test:eq 6 (my_function 1 2 3)) +# (test:eq 5 (foo) "foo should return 5")}) # =end # @author https://github.com/SuperFola -($ test:eq (_lhs _rhs) { - (if (= _lhs _rhs) +($ test:eq (_expected _expr ..._desc) { + (if (= _expected _expr) (_report_success) - (_report_error _lhs _rhs ($repr _lhs) ($repr _rhs)))}) + (_report_error _expected _expr ($repr _expected) ($repr _expr) _desc))}) # @brief Compare two values that should **not** be equal and generate a test case -# @param _lhs the first value -# @param _rhs the second value +# @param _unexpected the value we don't want +# @param _value tested value +# @param _desc an optional description (string) for the test # =begin # (test:suite name { # (test:neq 0 (my_function 1 2 3))}) # =end # @author https://github.com/SuperFola -($ test:neq (_lhs _rhs) { - (if (!= _lhs _rhs) +($ test:neq (_unexpected _value ..._desc) { + (if (!= _unexpected _value) (_report_success) - (_report_error _lhs _rhs ($repr _lhs) ($repr _rhs)))}) + (_report_error _unexpected _value ($repr _unexpected) ($repr _value) _desc))}) # @brief Generate the code for a test suite # @details Create two variables: _name-output (a list: [successes, failures]) and _name-status (boolean, true on success) diff --git a/tests/events-tests.ark b/tests/events-tests.ark index 637d511..284ebc0 100644 --- a/tests/events-tests.ark +++ b/tests/events-tests.ark @@ -5,7 +5,7 @@ (test:suite events { # _check_valid tests - (test:expect (em._check_valid (fun () ()))) + (test:expect (em._check_valid (fun () ())) "a function is valid") (test:expect (not (em._check_valid 4))) # on tests From 15e7534bd3b018324c75f66e1303cd0e2cb2fc69 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Mon, 4 Mar 2024 22:45:19 +0100 Subject: [PATCH 8/9] feat: do not show the computed real value if it's equal to its representation --- Testing.ark | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/Testing.ark b/Testing.ark index 3125191..8ff906b 100644 --- a/Testing.ark +++ b/Testing.ark @@ -96,20 +96,27 @@ (let _lhs_align (len _lhs_repr)) (let _rhs_align (len _rhs_repr)) (let _show_expected (!= _lhs_repr (toString _lhs))) - - (append! _failures - (str:format - (+ "{}{: <" (toString (len "expected ")) "}" "{: <" (toString _rhs_start) "}{:~<" (toString _rhs_align) "} {}") - _indent - # to position one char before the first ' surrounding the expected value - "" - # writes the | right under the first ' surrounding the expected value - (if _show_expected "|" "") - # begins the \~~~~ under the real value - "\\" - _rhs)) + (let _show_real (!= _rhs_repr (toString _rhs))) + + (if _show_real + (append! _failures + (str:format + (+ "{}{: <" (toString (len "expected ")) "}" "{: <" (toString _rhs_start) "}{:~<" (toString _rhs_align) "} {}") + _indent + # to position one char before the first ' surrounding the expected value + "" + # writes the | right under the first ' surrounding the expected value + (if _show_expected "|" "") + # begins the \~~~~ under the real value + (if _show_real "\\" "") + (if _show_real _rhs "")))) (if _show_expected - (append! _failures (str:format (+ "{}{: <9}{:~<" (toString _lhs_align) "} {}") _indent "" "\\" _lhs)))})) + (append! _failures + (str:format + (+ "{}{: <" (toString (len "expected ")) "}\\ {}") + _indent + "" + _lhs)))})) # internal, do not use # This can only be used within a (nested or not) call to test:suite From c3520e804c82b3501ad259e72e3de1dafcc73d4d Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Mon, 4 Mar 2024 22:54:07 +0100 Subject: [PATCH 9/9] feat: display all successful cases too when display_cases_success is true --- Testing.ark | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Testing.ark b/Testing.ark index 8ff906b..c12d754 100644 --- a/Testing.ark +++ b/Testing.ark @@ -6,6 +6,7 @@ (let _case_desc "") (mut _cases []) (mut _case_pointer 0) + (mut display_cases_success false) (let _start_time (time)) # run test @@ -29,10 +30,10 @@ [_passed _failed]})) -(let _case_description (fun (_desc) +(let _test_desc (fun (_desc) (if (empty? _desc) "" - (str:format " for case '{}'" (head _desc))))) + (str:format " for test '{}'" (head _desc))))) # internal, do not use # Has a _case_desc which also exists (empty) inside _runner so that tests without a @@ -61,6 +62,19 @@ ($ test:case (_desc _body) (_case _desc (fun () {_body}))) +# internal, do not use +# Until _case_pointer isn't at the end of the pile (where our failing test case's is), +# iterate on the list, writing the case name in a cascade pattern. +# This way if we have CASE A>CASE B>CASE C and no test crashed in A nor in A>B, +# we are still able to display the cascade A>B>C with the correct indentation. +(let _add_case (fun () { + (let _target_len (len _cases)) + (while (< _case_pointer _target_len) { + (mut _indent (* 2 _case_pointer)) + (mut _fmt (if (> _indent 0) (+ "{: <" (toString _indent) "}{}") "{}{}")) + (append! _failures (str:format _fmt "" (@ _cases _case_pointer))) + (set _case_pointer (+ 1 _case_pointer))})})) + # internal, do not use # This can only be used within a (nested or not) call to test:suite # because it updates _failed and _failures, which are defined by @@ -68,18 +82,6 @@ (let _report_error (fun (_lhs _rhs _lhs_repr _rhs_repr _desc) { (set _failed (+ 1 _failed)) - # Until _case_pointer isn't at the end of the pile (where our failing test case's is), - # iterate on the list, writing the case name in a cascade pattern. - # This way if we have CASE A>CASE B>CASE C and no test crashed in A nor in A>B, - # we are still able to display the cascade A>B>C with the correct indentation. - (let _add_case (fun () { - (let _target_len (len _cases)) - (while (< _case_pointer _target_len) { - (mut _indent (* 2 _case_pointer)) - (mut _fmt (if (> _indent 0) (+ "{: <" (toString _indent) "}{}") "{}{}")) - (append! _failures (str:format _fmt "" (@ _cases _case_pointer))) - (set _case_pointer (+ 1 _case_pointer))})})) - # If we have a case description AND the pointer isn't up to date, display the case(s)' names (if (and (not (empty? _case_desc)) (!= _case_pointer (len _cases))) (_add_case)) @@ -90,7 +92,7 @@ (str:format (+ "{: <" (toString _indent_case_len) "}") "") "")) # Add the error message - (append! _failures (str:format "{}expected '{}' but got '{}'{}" _indent _lhs_repr _rhs_repr (_case_description _desc))) + (append! _failures (str:format "{}expected '{}' but got '{}'{}" _indent _lhs_repr _rhs_repr (_test_desc _desc))) (let _rhs_start (+ (len _lhs_repr) (len "expected ''"))) (let _lhs_align (len _lhs_repr)) @@ -121,7 +123,11 @@ # internal, do not use # This can only be used within a (nested or not) call to test:suite # because it updates _passed, which is defined by test:suite call to _runner -(let _report_success (fun () (set _passed (+ 1 _passed)))) +(let _report_success (fun () { + (set _passed (+ 1 _passed)) + (if display_cases_success + (_add_case)) +})) # @brief Given a value or function call returning a boolean, generate a test case # @param _cond the value to test for truthiness @@ -136,7 +142,7 @@ (if (!= true _cond) { (set _failed (+ 1 _failed)) - (append! _failures (str:format "{} returned {}{}" ($repr _cond) _cond) (_case_description _desc))} + (append! _failures (str:format "{} returned {}{}" ($repr _cond) _cond) (_test_desc _desc))} (_report_success))}) # @brief Compare two values that should be equal and generate a test case @@ -174,6 +180,7 @@ # @param _body body of the test, a begin block # =begin # (test:suite name { +# (set display_cases_success true) # default: false, when true, display all the cases names on success and failures # (test:eq 6 (my_function 1 2 3)) # (test:eq 128 (* 8 16))}) # =end