diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/javascript.scm | 23 | ||||
| -rw-r--r-- | tests/propnet.scm | 41 | ||||
| -rw-r--r-- | tests/reader.scm | 324 | ||||
| -rw-r--r-- | tests/store.scm | 80 | ||||
| -rw-r--r-- | tests/work/command-line-tool.scm | 12 | ||||
| -rw-r--r-- | tests/workflow.scm | 31 |
6 files changed, 336 insertions, 175 deletions
diff --git a/tests/javascript.scm b/tests/javascript.scm index 75936c0..58d2639 100644 --- a/tests/javascript.scm +++ b/tests/javascript.scm @@ -1,5 +1,5 @@ ;;; ravanan --- High-reproducibility CWL runner powered by Guix -;;; Copyright © 2024 Arun Isaac <arunisaac@systemreboot.net> +;;; Copyright © 2024–2025 Arun Isaac <arunisaac@systemreboot.net> ;;; ;;; This file is part of ravanan. ;;; @@ -119,7 +119,12 @@ (evaluate-parameter-reference "foo$(inputs.vector)$(inputs.object)"))) (test-equal "evaluate parameter reference with node (without context)" - '(evaluate-javascript (*approximate*) "(inputs.n + 1)" "") + '(evaluate-javascript (*approximate*) + "(inputs.n + 1)" + (string-append "" + "inputs = " (scm->json-string inputs) ";" + "self = " (scm->json-string self) ";" + "runtime = " (scm->json-string runtime) ";")) (gexp->sexp-rec (evaluate-parameter-reference "$(inputs.n + 1)"))) @@ -129,7 +134,12 @@ (if (string? token) token (scm->json-string (canonicalize-json token)))) (list (json-ref runtime "cores") "foo" - (evaluate-javascript (*approximate*) "(inputs.threads*2)" "") + (evaluate-javascript (*approximate*) + "(inputs.threads*2)" + (string-append "" + "inputs = " (scm->json-string inputs) ";" + "self = " (scm->json-string self) ";" + "runtime = " (scm->json-string runtime) ";")) (json-ref inputs "output_filename"))) "") (gexp->sexp-rec @@ -142,7 +152,12 @@ (list "foo" (json-ref inputs "vector") (json-ref inputs "object") - (evaluate-javascript (*approximate*) "(inputs.object.foo*20)" ""))) + (evaluate-javascript (*approximate*) + "(inputs.object.foo*20)" + (string-append "" + "inputs = " (scm->json-string inputs) ";" + "self = " (scm->json-string self) ";" + "runtime = " (scm->json-string runtime) ";")))) "") (gexp->sexp-rec (evaluate-parameter-reference "foo$(inputs.vector)$(inputs.object)$(inputs.object.foo*20)"))) diff --git a/tests/propnet.scm b/tests/propnet.scm index 182eb30..1f48d61 100644 --- a/tests/propnet.scm +++ b/tests/propnet.scm @@ -1,5 +1,5 @@ ;;; ravanan --- High-reproducibility CWL runner powered by Guix -;;; Copyright © 2024 Arun Isaac <arunisaac@systemreboot.net> +;;; Copyright © 2024–2025 Arun Isaac <arunisaac@systemreboot.net> ;;; ;;; This file is part of ravanan. ;;; @@ -23,19 +23,30 @@ (test-equal "Trigger propagator with no inputs" '((out . #t)) - (run-propnet (propnet (list (propagator "const" - (const '((out . #t))) - '() - '() - '((out . out)))) - (@@ (ravanan workflow) value=?) - (@@ (ravanan workflow) merge-values) - (scheduler (lambda (proc _) - proc) - (const 'completed) - 0 - (lambda (proc) - (proc)))) - '())) + (run-with-state + (let loop ((mstate (schedule-propnet + (propnet (list (propagator "const" + (const '((out . #t))) + '() + '() + '((out . out)))) + (@@ (ravanan workflow) value=?) + (@@ (ravanan workflow) merge-values) + (scheduler (lambda (proc inputs scheduler) + (state-return proc)) + (lambda (state) + (state-return (state+status state + 'completed))) + (lambda (proc) + (state-return (proc))))) + '()))) + ;; Poll. + (state-let* ((state mstate) + (state+status (poll-propnet state))) + (if (eq? (state+status-status state+status) + 'pending) + (loop (state-return (state+status-state state+status))) + ;; Capture outputs. + (capture-propnet-output (state+status-state state+status))))))) (test-end "propnet") diff --git a/tests/reader.scm b/tests/reader.scm index f3bcdd2..d55e396 100644 --- a/tests/reader.scm +++ b/tests/reader.scm @@ -16,169 +16,185 @@ ;;; You should have received a copy of the GNU General Public License ;;; along with ravanan. If not, see <https://www.gnu.org/licenses/>. -(use-modules (srfi srfi-1) +(use-modules (srfi srfi-26) (srfi srfi-64) (ice-9 filesystem) (ice-9 match) (web uri) (ravanan reader) (ravanan work command-line-tool) - (ravanan work utils)) - -(define normalize-formal-input - (@@ (ravanan reader) normalize-formal-input)) - -(define normalize-formal-output - (@@ (ravanan reader) normalize-formal-output)) - -(define normalize-input - (@@ (ravanan reader) normalize-input)) - -(define (json=? tree1 tree2) - (cond - ;; Arrays - ((vector? tree1) - (lset= json=? - (vector->list tree1) - (vector->list tree2))) - ;; Dictionaries - ((list? tree1) - (lset= (match-lambda* - (((key1 . value1) (key2 . value2)) - (and (string=? key1 key2) - (json=? value1 value2)))) - tree1 - tree2)) - ;; Atoms - (else - (equal? tree1 tree2)))) + (ravanan work types) + (ravanan work utils) + (ravanan work vectors)) (test-begin "reader") -(test-equal "Coerce number to number" +(test-equal "Coerce to boolean (true)" + #t + (coerce-type "true" 'boolean)) + +(test-equal "Coerce to boolean (false)" + #f + (coerce-type "false" 'boolean)) + +(test-equal "Coerce to int" + 37 + (coerce-type "37" 'int)) + +(test-equal "Coerce to float" + 37.1 + (coerce-type "37.1" 'float)) + +(test-equal "Coerce to double" + 37.1 + (coerce-type "37.1" 'double)) + +(test-equal "Coerce to string" + "37" + (coerce-type "37" 'string)) + +(test-equal "Coerce to File" + '(("class" . "File") + ("location" . "foo")) + (coerce-type '(("class" . "File") + ("location" . "foo")) + 'File)) + +(test-equal "Coerce to array" + #(1 2 3) + (coerce-type #("1" "2" "3") + (cwl-array-type 'int))) + +(test-equal "Coerce to union type (int first)" + 37 + (coerce-type "37" + (cwl-union-type 'int 'string))) + +(test-equal "Coerce to union type (string first)" + "37" + (coerce-type "37" + (cwl-union-type 'string 'int))) + +(test-equal "Coerce int to int" 37 - (coerce-type 37 'number)) - -(test-assert "Normalize File type formal input" - (json=? '(("type" . "File") - ("id" . "foo") - ("secondaryFiles" . #((("pattern" . ".bai") - ("required" . #t))))) - (normalize-formal-input - '(("type" . "File") - ("id" . "foo") - ("secondaryFiles" . #(".bai")))))) - -(test-assert "Normalize File array type formal input" - (json=? '(("type" - ("type" . "array") - ("items" . "File")) - ("id" . "foo") - ("secondaryFiles" . #((("pattern" . ".bai") - ("required" . #t))))) - (normalize-formal-input - '(("type" - ("type" . "array") - ("items" . "File")) - ("id" . "foo") - ("secondaryFiles" . #(".bai")))))) - -(test-assert "Normalize array of File arrays type formal input" - (json=? '(("type" - ("type" . "array") - ("items" . (("type" . "array") - ("items" . "File")))) - ("id" . "foo") - ("secondaryFiles" . #((("pattern" . ".bai") - ("required" . #t))))) - (normalize-formal-input - '(("type" - ("type" . "array") - ("items" . (("type" . "array") - ("items" . "File")))) - ("id" . "foo") - ("secondaryFiles" . #(".bai")))))) - -(test-assert "Normalize File type formal output" - (json=? '(("type" . "File") - ("id" . "foo") - ("secondaryFiles" . #((("pattern" . ".bai") - ("required" . #f))))) - (normalize-formal-output - '(("type" . "File") - ("id" . "foo") - ("secondaryFiles" . #(".bai")))))) - -(test-assert "Normalize File array type formal output" - (json=? '(("type" - ("type" . "array") - ("items" . "File")) - ("id" . "foo") - ("secondaryFiles" . #((("pattern" . ".bai") - ("required" . #f))))) - (normalize-formal-output - '(("type" - ("type" . "array") - ("items" . "File")) - ("id" . "foo") - ("secondaryFiles" . #(".bai")))))) - -(test-assert "Normalize array of File arrays type formal output" - (json=? '(("type" - ("type" . "array") - ("items" . (("type" . "array") - ("items" . "File")))) - ("id" . "foo") - ("secondaryFiles" . #((("pattern" . ".bai") - ("required" . #f))))) - (normalize-formal-output - '(("type" - ("type" . "array") - ("items" . (("type" . "array") - ("items" . "File")))) - ("id" . "foo") - ("secondaryFiles" . #(".bai")))))) - -(test-assert "Normalize inputs with only location" - (call-with-temporary-directory - (lambda (dir) - (json=? (let ((path (expand-file-name "foo" dir))) - `(("class" . "File") - ("location" . ,(uri->string (build-uri 'file #:path path))) - ("path" . ,path) - ("basename" . "foo") - ("nameroot" . "foo") - ("nameext" . "") - ("size" . 0) - ("checksum" . "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709"))) - (call-with-current-directory dir - (lambda () - ;; Create an actual file called "foo" so that canonicalize-path - ;; works. - (call-with-output-file "foo" - (const #t)) - (normalize-input '(("class" . "File") - ("location" . "foo"))))))))) - -(test-assert "Normalize inputs with only path" - (call-with-temporary-directory - (lambda (dir) - (json=? (let ((path (expand-file-name "foo" dir))) - `(("class" . "File") - ("location" . ,(uri->string (build-uri 'file #:path path))) - ("path" . ,path) - ("basename" . "foo") - ("nameroot" . "foo") - ("nameext" . "") - ("size" . 0) - ("checksum" . "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709"))) - (call-with-current-directory dir - (lambda () - ;; Create an actual file called "foo" so that canonicalize-path - ;; works. - (call-with-output-file "foo" - (const #t)) - (normalize-input '(("class" . "File") - ("path" . "foo"))))))))) + (coerce-type 37 'int)) + +(test-equal "Normalize inputs with only location" + (canonicalize-json + (let ((path (canonicalize-path "test-data/foo"))) + `(("class" . "File") + ("location" . ,(uri->string (build-uri 'file + #:host "" + #:path path + #:validate? #f))) + ("path" . ,path) + ("basename" . "foo") + ("nameroot" . "foo") + ("nameext" . "") + ("size" . 0) + ("checksum" . "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709")))) + (call-with-values + (cut read-workflow+inputs + "test-data/workflow-with-a-file-input.cwl" + "test-data/input-file-with-location-only.yaml") + (lambda (workflow inputs) + (canonicalize-json (assoc-ref inputs "foo"))))) + +(test-equal "Normalize inputs with only path" + (canonicalize-json + (let ((path (canonicalize-path "test-data/foo"))) + `(("class" . "File") + ("location" . ,(uri->string (build-uri 'file + #:host "" + #:path path + #:validate? #f))) + ("path" . ,path) + ("basename" . "foo") + ("nameroot" . "foo") + ("nameext" . "") + ("size" . 0) + ("checksum" . "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709")))) + (call-with-values + (cut read-workflow+inputs + "test-data/workflow-with-a-file-input.cwl" + "test-data/input-file-with-path-only.yaml") + (lambda (workflow inputs) + (canonicalize-json (assoc-ref inputs "foo"))))) + +(test-equal "Read YAML inputs file with type ambiguities" + '(("number" . 13) + ("flag" . #t) + ("reverseflag" . #f) + ("foo" . "bar") + ("arr" . #(1 2 3))) + (call-with-values + (cut read-workflow+inputs + "test-data/workflow-for-inputs-with-type-ambiguities.cwl" + "test-data/inputs-with-type-ambiguities.yaml") + (lambda (workflow inputs) + inputs))) + +(test-equal "Resolve type ambiguities in workflow default inputs" + '(("number" . 13) + ("flag" . #t) + ("reverseflag" . #f) + ("foo" . "bar") + ("arr" . #(1 2 3))) + (call-with-values + (cut read-workflow+inputs + "test-data/workflow-with-default-inputs.cwl" + "test-data/empty.yaml") + (lambda (workflow inputs) + (vector-map->list (lambda (input) + (cons (assoc-ref input "id") + (assoc-ref input "default"))) + (assoc-ref workflow "inputs"))))) + +(test-equal "Normalize File type formals" + (list (vector-map canonicalize-json + #((("id" . "infoo") + ("type" . "File") + ("secondaryFiles" . #((("pattern" . ".bai") + ("required" . #t))))) + (("id" . "inbar") + ("type" + ("type" . "array") + ("items" . "File")) + ("secondaryFiles" . #((("pattern" . ".bai") + ("required" . #t))))) + (("id" . "infoobar") + ("type" + ("type" . "array") + ("items" . (("type" . "array") + ("items" . "File")))) + ("secondaryFiles" . #((("pattern" . ".bai") + ("required" . #t))))))) + (vector-map canonicalize-json + #((("id" . "outfoo") + ("type" . "File") + ("secondaryFiles" . #((("pattern" . ".bai") + ("required" . #f))))) + (("id" . "outbar") + ("type" + ("type" . "array") + ("items" . "File")) + ("secondaryFiles" . #((("pattern" . ".bai") + ("required" . #f))))) + (("id" . "outfoobar") + ("type" + ("type" . "array") + ("items" . (("type" . "array") + ("items" . "File")))) + ("secondaryFiles" . #((("pattern" . ".bai") + ("required" . #f)))))))) + (call-with-values + (cut read-workflow+inputs + "test-data/workflow-with-various-file-type-formals.cwl" + "test-data/empty.yaml") + (lambda (workflow inputs) + (list (vector-map canonicalize-json + (assoc-ref workflow "inputs")) + (vector-map canonicalize-json + (assoc-ref workflow "outputs")))))) (test-end "reader") diff --git a/tests/store.scm b/tests/store.scm new file mode 100644 index 0000000..f209583 --- /dev/null +++ b/tests/store.scm @@ -0,0 +1,80 @@ +;;; ravanan --- High-reproducibility CWL runner powered by Guix +;;; Copyright © 2025 Arun Isaac <arunisaac@systemreboot.net> +;;; +;;; This file is part of ravanan. +;;; +;;; ravanan is free software: you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation, either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; ravanan is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with ravanan. If not, see <https://www.gnu.org/licenses/>. + +(use-modules (srfi srfi-64) + (ravanan store)) + +(test-begin "store") + +(test-equal "step-store-files-directory must be insensitive to order of inputs" + (step-store-files-directory "/gnu/store/hl96c0xd19ngvl8rf4cyw452rpgqsi1b-foo" + '(("foo" . 1) + ("foobar" . 3) + ("bar" . (("aal" . 1) + ("vel" . 2)))) + "store") + (step-store-files-directory "/gnu/store/hl96c0xd19ngvl8rf4cyw452rpgqsi1b-foo" + '(("foo" . 1) + ("bar" . (("vel" . 2) + ("aal" . 1))) + ("foobar" . 3)) + "store")) + +(test-equal "step-store-data-file must be insensitive to order of inputs" + (step-store-data-file "/gnu/store/hl96c0xd19ngvl8rf4cyw452rpgqsi1b-foo" + '(("foo" . 1) + ("foobar" . 3) + ("bar" . (("aal" . 1) + ("vel" . 2)))) + "store") + (step-store-data-file "/gnu/store/hl96c0xd19ngvl8rf4cyw452rpgqsi1b-foo" + '(("foo" . 1) + ("bar" . (("vel" . 2) + ("aal" . 1))) + ("foobar" . 3)) + "store")) + +(test-equal "step-store-stdout-file must be insensitive to order of inputs" + (step-store-stdout-file "/gnu/store/hl96c0xd19ngvl8rf4cyw452rpgqsi1b-foo" + '(("foo" . 1) + ("foobar" . 3) + ("bar" . (("aal" . 1) + ("vel" . 2)))) + "store") + (step-store-stdout-file "/gnu/store/hl96c0xd19ngvl8rf4cyw452rpgqsi1b-foo" + '(("foo" . 1) + ("bar" . (("vel" . 2) + ("aal" . 1))) + ("foobar" . 3)) + "store")) + +(test-equal "step-store-stderr-file must be insensitive to order of inputs" + (step-store-stderr-file "/gnu/store/hl96c0xd19ngvl8rf4cyw452rpgqsi1b-foo" + '(("foo" . 1) + ("foobar" . 3) + ("bar" . (("aal" . 1) + ("vel" . 2)))) + "store") + (step-store-stderr-file "/gnu/store/hl96c0xd19ngvl8rf4cyw452rpgqsi1b-foo" + '(("foo" . 1) + ("bar" . (("vel" . 2) + ("aal" . 1))) + ("foobar" . 3)) + "store")) + +(test-end "store") diff --git a/tests/work/command-line-tool.scm b/tests/work/command-line-tool.scm index 3d11b53..93b97d4 100644 --- a/tests/work/command-line-tool.scm +++ b/tests/work/command-line-tool.scm @@ -1,5 +1,5 @@ ;;; ravanan --- High-reproducibility CWL runner powered by Guix -;;; Copyright © 2024 Arun Isaac <arunisaac@systemreboot.net> +;;; Copyright © 2024, 2025 Arun Isaac <arunisaac@systemreboot.net> ;;; ;;; This file is part of ravanan. ;;; @@ -24,6 +24,14 @@ (test-equal "match null object to array type" #f - (match-type 'null (array-type 'File))) + (match-type 'null (cwl-array-type 'File))) + +(test-equal "match int to float" + 'float + (match-type 1 'float)) + +(test-equal "match float to float" + 'float + (match-type 1.3 'float)) (test-end "work.command-line-tool") diff --git a/tests/workflow.scm b/tests/workflow.scm new file mode 100644 index 0000000..06b2609 --- /dev/null +++ b/tests/workflow.scm @@ -0,0 +1,31 @@ +;;; ravanan --- High-reproducibility CWL runner powered by Guix +;;; Copyright © 2025 Arun Isaac <arunisaac@systemreboot.net> +;;; +;;; This file is part of ravanan. +;;; +;;; ravanan is free software: you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation, either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; ravanan is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with ravanan. If not, see <https://www.gnu.org/licenses/>. + +(use-modules (srfi srfi-64)) + +(define optional-input? + (@@ (ravanan workflow) optional-input?)) + +(test-begin "workflow") + +(test-assert "Inputs that have a boolean #f default are also optional" + (optional-input? `(("id" . "foo") + ("type" . "boolean") + ("default" . #f)))) + +(test-end "workflow") |
