From 7d963776a0a6b9c0bc030dfff7e675466f1ff8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20FARKAS?= Date: Mon, 20 Mar 2023 14:57:28 +0100 Subject: [PATCH] stdlib: Implement common assert commands (#8515) Implement common assert commands with tests. Fixes #8419. --------- Co-authored-by: Mate Farkas --- crates/nu-utils/standard_library/std.nu | 231 ++++++++++++++---- .../nu-utils/standard_library/test_asserts.nu | 64 +++++ crates/nu-utils/standard_library/test_dirs.nu | 27 +- .../nu-utils/standard_library/test_logger.nu | 6 +- crates/nu-utils/standard_library/test_std.nu | 37 +-- 5 files changed, 266 insertions(+), 99 deletions(-) create mode 100644 crates/nu-utils/standard_library/test_asserts.nu diff --git a/crates/nu-utils/standard_library/std.nu b/crates/nu-utils/standard_library/std.nu index cd0907c3f2..0b21cf39fa 100644 --- a/crates/nu-utils/standard_library/std.nu +++ b/crates/nu-utils/standard_library/std.nu @@ -1,18 +1,11 @@ # std.nu, `used` to load all standard library components -# ---------------- builtin std functions -------------------- - -def _assertion-error [start, end, label, message?: string] { - error make { - msg: ($message | default "Assertion failed."), - label: { - text: $label, - start: $start, - end: $end - } - } -} - +# Universal assert command +# +# If the condition is not true, it generates an error. +# +# # Example +# # ```nushell # >_ assert (3 == 3) # >_ assert (42 == 3) @@ -26,51 +19,183 @@ def _assertion-error [start, end, label, message?: string] { # 13 │ # ╰──── # ``` -export def assert [cond: bool, message?: string] { - if $cond { return } - let span = (metadata $cond).span - _assertion-error $span.start $span.end "It is not true." $message -} - -# ```nushell -# ❯ assert eq 3 3 -# ❯ assert eq 3 1 -# Error: -# × Assertion failed. -# ╭─[entry #14:1:1] -# 1 │ assert eq 3 1 -# · ─┬─ -# · ╰── They are not equal: 3 != 1 -# ╰──── -# # +# The --error-label flag can be used if you want to create a custom assert command: # ``` -export def "assert eq" [left: any, right: any, message?: string] { - let left_start = (metadata $left).span.start - let right_end = (metadata $right).span.end - - if ($left != $right) { - _assertion-error $left_start $right_end $"They are not equal: ($left) != ($right)" $message +# def "assert even" [number: int] { +# assert ($number mod 2 == 0) --error-label { +# start: (metadata $number).span.start, +# end: (metadata $number).span.end, +# text: $"($number) is not an even number", +# } +# } +# ``` +export def assert [ + condition: bool, # Condition, which should be true + message?: string, # Optional error message + --error-label: record # Label for `error make` if you want to create a custom assert +] { + if $condition { return } + let span = (metadata $condition).span + error make { + msg: ($message | default "Assertion failed."), + label: ($error_label | default { + text: "It is not true.", + start: (metadata $condition).span.start, + end: (metadata $condition).span.end + }) } } -# ```nushell -# ❯ assert ne 1 3 -# ❯ assert ne 42 42 -# Error: -# × Assertion failed. -# ╭─[entry #23:1:1] -# 1 │ assert ne 42 42 -# · ──┬── -# · ╰── They both are 42 -# ╰──── -# ``` -export def "assert ne" [left: any, right: any, message?: string] { - let left_start = (metadata $left).span.start - let right_end = (metadata $right).span.end +# Assert that executing the code generates an error +# +# For more documentation see the assert command +# +# # Examples +# +# > assert error {|| missing_command} # passes +# > assert error {|| 12} # fails +export def "assert error" [ + code: closure, + message?: string +] { + let error_raised = (try { do $code; false } catch { true }) + assert ($error_raised) $message --error-label { + start: (metadata $code).span.start + end: (metadata $code).span.end + text: $"There were no error during code execution: (view source $code)" + } +} - if ($left == $right) { - _assertion-error $left_start $right_end $"They both are ($left)" $message +# Assert $left == $right +# +# For more documentation see the assert command +# +# # Examples +# +# > assert equal 1 1 # passes +# > assert equal (0.1 + 0.2) 0.3 +# > assert equal 1 2 # fails +export def "assert equal" [left: any, right: any, message?: string] { + assert ($left == $right) $message --error-label { + start: (metadata $left).span.start + end: (metadata $right).span.end + text: $"They are not equal. Left = ($left). Right = ($right)." + } +} + +# Assert $left != $right +# +# For more documentation see the assert command +# +# # Examples +# +# > assert not equal 1 2 # passes +# > assert not equal 1 "apple" # passes +# > assert not equal 7 7 # fails +export def "assert not equal" [left: any, right: any, message?: string] { + assert ($left != $right) $message --error-label { + start: (metadata $left).span.start + end: (metadata $right).span.end + text: $"They both are ($left)." + } +} + +# Assert $left <= $right +# +# For more documentation see the assert command +# +# # Examples +# +# > assert less or equal 1 2 # passes +# > assert less or equal 1 1 # passes +# > assert less or equal 1 0 # fails +export def "assert less or equal" [left: any, right: any, message?: string] { + assert ($left <= $right) $message --error-label { + start: (metadata $left).span.start + end: (metadata $right).span.end + text: $"Left: ($left), Right: ($right)" + } +} + +# Assert $left < $right +# +# For more documentation see the assert command +# +# # Examples +# +# > assert less 1 2 # passes +# > assert less 1 1 # fails +export def "assert less" [left: any, right: any, message?: string] { + assert ($left < $right) $message --error-label { + start: (metadata $left).span.start + end: (metadata $right).span.end + text: $"Left: ($left), Right: ($right)" + } +} + +# Assert $left > $right +# +# For more documentation see the assert command +# +# # Examples +# +# > assert greater 2 1 # passes +# > assert greater 2 2 # fails +export def "assert greater" [left: any, right: any, message?: string] { + assert ($left > $right) $message --error-label { + start: (metadata $left).span.start + end: (metadata $right).span.end + text: $"Left: ($left), Right: ($right)" + } +} + +# Assert $left >= $right +# +# For more documentation see the assert command +# +# # Examples +# +# > assert greater or equal 2 1 # passes +# > assert greater or equal 2 2 # passes +# > assert greater or equal 1 2 # fails +export def "assert greater or equal" [left: any, right: any, message?: string] { + assert ($left >= $right) $message --error-label { + start: (metadata $left).span.start + end: (metadata $right).span.end + text: $"Left: ($left), Right: ($right)" + } +} + +# Assert length of $left is $right +# +# For more documentation see the assert command +# +# # Examples +# +# > assert length [0, 0] 2 # passes +# > assert length [0] 3 # fails +export def "assert length" [left: list, right: int, message?: string] { + assert (($left | length) == $right) $message --error-label { + start: (metadata $left).span.start + end: (metadata $right).span.end + text: $"Length of ($left) is ($left | length), not ($right)" + } +} + +# Assert that ($left | str contains $right) +# +# For more documentation see the assert command +# +# # Examples +# +# > assert str contains "arst" "rs" # passes +# > assert str contains "arst" "k" # fails +export def "assert str contains" [left: string, right: string, message?: string] { + assert ($left | str contains $right) $message --error-label { + start: (metadata $left).span.start + end: (metadata $right).span.end + text: $"'($left)' does not contain '($right)'." } } @@ -125,7 +250,7 @@ export def match [ # std path add "bar" "baz" # std path add "fooo" --append # -# assert eq $env.PATH ["bar" "baz" "foo" "fooo"] +# assert equal $env.PATH ["bar" "baz" "foo" "fooo"] # # print (std path add "returned" --ret) # } diff --git a/crates/nu-utils/standard_library/test_asserts.nu b/crates/nu-utils/standard_library/test_asserts.nu new file mode 100644 index 0000000000..ddb21049fe --- /dev/null +++ b/crates/nu-utils/standard_library/test_asserts.nu @@ -0,0 +1,64 @@ +use std.nu * + +export def test_assert [] { + assert true + assert (1 + 2 == 3) + assert error { assert false } + assert error { assert (1 + 2 == 4) } +} + +export def test_assert_equal [] { + assert equal (1 + 2) 3 + assert equal (0.1 + 0.2 | into string | into decimal) 0.3 # 0.30000000000000004 == 0.3 + assert error { assert equal 1 "foo" } + assert error { assert equal (1 + 2) 4) } +} + +export def test_assert_not_equal [] { + assert not equal (1 + 2) 4 + assert not equal 1 "foo" + assert not equal (1 + 2) 3) + assert error { assert not equal 1 1 } +} + +export def test_assert_error [] { + let failing_code = {|| missing_code_to_run} + assert error $failing_code + + let good_code = {|| } + let assert_error_raised = (try { do assert $good_code; false } catch { true }) + assert $assert_error_raised "The assert error should raise an error if there is no error in the executed code." +} + +export def test_assert_less [] { + assert less 1 2 + assert error { assert less 1 1 } +} + +export def test_assert_less_or_equal [] { + assert less or equal 1 2 + assert less or equal 1 1 + assert error { assert less or equal 1 0 } +} + +export def test_assert_greater [] { + assert greater 2 1 + assert error { assert greater 2 2 } +} + +export def test_assert_greater_or_equal [] { + assert greater or equal 1 1 + assert greater or equal 2 1 + assert error { assert greater or equal 0 1 } +} + +export def test_assert_length [] { + assert length [0, 0, 0] 3 + assert error { assert length [0, 0] 3 } +} + +# export def test_assert_§ [] { +# assert § +# assert error { assert § } +# } + diff --git a/crates/nu-utils/standard_library/test_dirs.nu b/crates/nu-utils/standard_library/test_dirs.nu index 88faa2567a..54b1420f4d 100644 --- a/crates/nu-utils/standard_library/test_dirs.nu +++ b/crates/nu-utils/standard_library/test_dirs.nu @@ -1,4 +1,5 @@ -use std.nu assert +use std.nu "assert length" +use std.nu "assert equal" def clean [path: path] { cd $path @@ -21,31 +22,31 @@ export def test_dirs_command [] { use std.nu "dirs drop" use std.nu "dirs show" - assert (1 == ($env.DIRS_LIST | length)) "list is just pwd after initialization" - assert ($base_path == $env.DIRS_LIST.0) "list is just pwd after initialization" + assert length $env.DIRS_LIST 1 "list is just pwd after initialization" + assert equal $base_path $env.DIRS_LIST.0 "list is just pwd after initialization" dirs next - assert ($base_path == $env.DIRS_LIST.0) "next wraps at end of list" + assert equal $base_path $env.DIRS_LIST.0 "next wraps at end of list" dirs prev - assert ($base_path == $env.DIRS_LIST.0) "prev wraps at top of list" + assert equal $base_path $env.DIRS_LIST.0 "prev wraps at top of list" dirs add $path_b $path_a - assert ($path_b == $env.PWD) "add changes PWD to first added dir" - assert (3 == ($env.DIRS_LIST | length)) "add in fact adds to list" - assert ($path_a == $env.DIRS_LIST.2) "add in fact adds to list" + assert equal $path_b $env.PWD "add changes PWD to first added dir" + assert length $env.DIRS_LIST 3 "add in fact adds to list" + assert equal $path_a $env.DIRS_LIST.2 "add in fact adds to list" dirs next 2 - assert ($base_path == $env.PWD) "next wraps at end of list" + assert equal $base_path $env.PWD "next wraps at end of list" dirs prev 1 - assert ($path_a == $env.PWD) "prev wraps at start of list" + assert equal $path_a $env.PWD "prev wraps at start of list" dirs drop - assert (2 == ($env.DIRS_LIST | length)) "drop removes from list" - assert ($base_path == $env.PWD) "drop changes PWD to next in list (after dropped element)" + assert length $env.DIRS_LIST 2 "drop removes from list" + assert equal $base_path $env.PWD "drop changes PWD to next in list (after dropped element)" - assert ((dirs show) == [[active path]; [true $base_path] [false $path_b]]) "show table contains expected information" + assert equal (dirs show) [[active path]; [true $base_path] [false $path_b]] "show table contains expected information" } catch { |error| clean $base_path diff --git a/crates/nu-utils/standard_library/test_logger.nu b/crates/nu-utils/standard_library/test_logger.nu index 65bffca081..fad163b7da 100644 --- a/crates/nu-utils/standard_library/test_logger.nu +++ b/crates/nu-utils/standard_library/test_logger.nu @@ -8,13 +8,13 @@ def run [system_level, message_level] { } def "assert no message" [system_level, message_level] { let output = (run $system_level $message_level) - assert eq $output "" + assert equal "" $output } def "assert message" [system_level, message_level, message_level_str] { let output = (run $system_level $message_level) - assert ($output | str contains $message_level_str) - assert ($output | str contains "test message") + assert str contains $output $message_level_str + assert str contains $output "test message" } export def test_critical [] { diff --git a/crates/nu-utils/standard_library/test_std.nu b/crates/nu-utils/standard_library/test_std.nu index 1c5c2d4e38..6a49b796d1 100644 --- a/crates/nu-utils/standard_library/test_std.nu +++ b/crates/nu-utils/standard_library/test_std.nu @@ -1,28 +1,5 @@ use std.nu -export def test_assert [] { - def test_failing [code: closure] { - let code_did_run = (try { do $code; true } catch { false }) - - if $code_did_run { - error make {msg: (view source $code)} - } - } - - std assert true - std assert (1 + 2 == 3) - test_failing { std assert false } - test_failing { std assert (1 + 2 == 4) } - - std assert eq (1 + 2) 3 - test_failing { std assert eq 1 "foo" } - test_failing { std assert eq (1 + 2) 4) } - - std assert ne (1 + 2) 4 - std assert ne 1 "foo" - std assert ne (1 + 2) 3) -} - export def test_match [] { use std.nu assert @@ -41,24 +18,24 @@ export def test_match [] { } export def test_path_add [] { - use std.nu "assert eq" + use std.nu "assert equal" with-env [PATH []] { - assert eq $env.PATH [] + assert equal $env.PATH [] std path add "/foo/" - assert eq $env.PATH ["/foo/"] + assert equal $env.PATH ["/foo/"] std path add "/bar/" "/baz/" - assert eq $env.PATH ["/bar/", "/baz/", "/foo/"] + assert equal $env.PATH ["/bar/", "/baz/", "/foo/"] let-env PATH = [] std path add "foo" std path add "bar" "baz" --append - assert eq $env.PATH ["foo", "bar", "baz"] + assert equal $env.PATH ["foo", "bar", "baz"] - assert eq (std path add "fooooo" --ret) ["fooooo", "foo", "bar", "baz"] - assert eq $env.PATH ["fooooo", "foo", "bar", "baz"] + assert equal (std path add "fooooo" --ret) ["fooooo", "foo", "bar", "baz"] + assert equal $env.PATH ["fooooo", "foo", "bar", "baz"] } }