stdlib: Implement common assert commands (#8515)

Implement common assert commands with tests.
Fixes #8419.

---------

Co-authored-by: Mate Farkas <Mate.Farkas@oneidentity.com>
This commit is contained in:
Máté FARKAS 2023-03-20 14:57:28 +01:00 committed by GitHub
parent ecc153cbef
commit 7d963776a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 266 additions and 99 deletions

View File

@ -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)
# }

View File

@ -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 § }
# }

View File

@ -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

View File

@ -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 [] {

View File

@ -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"]
}
}