diff --git a/.gitignore b/.gitignore index 6f259ea..8f322f0 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,3 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts - -# testing files -test* diff --git a/docs/0.6.0-alpha/getting_started/testing.md b/docs/0.6.0-alpha/getting_started/testing.md new file mode 100644 index 0000000..6ff2dbd --- /dev/null +++ b/docs/0.6.0-alpha/getting_started/testing.md @@ -0,0 +1,44 @@ + +Test blocks are dedicated scopes for writing tests. They are executed only when running the `amber test` command and are ignored during normal compilation. Test blocks can be optionally named using a string literal. This improves readability and allows for targetted execution. + +## Syntax +```ab +import { assert } from "std/test" + +// Unique named test block +test "can multiply numbers" { + let result = 10 * 2 + assert(result == 20) +} + +// Unnamed test block (only one allowed per file) +test { + let name = "Amber" + assert(name + " Lang" == "Amber Lang") +} +``` + +# CLI Test Filtering + +The `amber test` command is designed to verify the correctness of your code by executing test blocks. By default, it recursively finds and runs all tests in the current directory. You can narrow down which tests to run by providing filter arguments. + +## Filtering Tests + +You can run a specific subset of tests by providing a filter argument. This argument performs a substring match against both the **filename** and the **test name**. + +```bash +# Run all tests located in the current directory containing "variable" in their name or filename +amber test . "variable" +``` + +## Targeting Specific Files + +Instead of running tests from the current directory, you can specify a particular file or directory to scan. + +```bash +# Run all tests inside main.ab +amber test main.ab + +# Run all tests in main.ab that contain "zip" in their name +amber test main.ab "zip" +``` diff --git a/docs/0.6.0-alpha/getting_started/usage.md b/docs/0.6.0-alpha/getting_started/usage.md index 7dda1ac..346ee25 100644 --- a/docs/0.6.0-alpha/getting_started/usage.md +++ b/docs/0.6.0-alpha/getting_started/usage.md @@ -4,7 +4,7 @@ The Amber CLI can be used as a runtime or as a compiler. The Amber CLI syntax uses subcommands, like the Git CLI: -*This output is generated from the 0.5.1-alpha version.* +*This output is generated from the 0.5.2-alpha version.* ``` Usage: amber [OPTIONS] [INPUT] [ARGS]... [COMMAND] @@ -15,6 +15,7 @@ Commands: build Compile Amber script to Bash docs Generate Amber script documentation completion Generate Bash completion script + test Run Amber tests help Print this message or the help of the given subcommand(s) Arguments: @@ -97,6 +98,16 @@ Furthermore, Amber adds a _shebang_ at the top of the compiled script. This enab $ ./output.sh ``` +## Testing + +Amber comes with a built-in test runner. You can define named test blocks in your code and execute them using the `amber test` command. + +```sh +$ amber test +``` + +For more details on writing and filtering tests, please refer to the [Testing guide](https://docs.amber-lang.com/getting_started/testing). + ## Syntax Highlighting [VS Code](https://code.visualstudio.com) as well as [Zed](https://zed.dev) now have built-in LSP integration. diff --git a/docs/0.6.0-alpha/getting_started/whats_new.md b/docs/0.6.0-alpha/getting_started/whats_new.md index c09f0f8..ad5c38b 100644 --- a/docs/0.6.0-alpha/getting_started/whats_new.md +++ b/docs/0.6.0-alpha/getting_started/whats_new.md @@ -1,291 +1,33 @@ -Featuring a new compiler backend that improves readability, reliability, and performance of bash output, new `Int` data type and more. +> WARNING: Brief description of new changes TBD when releasing -# Amber LSP +# Testing suite +Amber now features a built-in testing suite. It allows you to write dedicated `test` blocks that are only executed when running the `amber test` command. -Amber now offers code autocompletion, intelligent suggestions, real-time error checking, and more. It’s available in both [VS Code](https://marketplace.visualstudio.com/items?itemName=amber-lsp-publisher.amber-lsp), [Zed](https://zed.dev/extensions/amber) and [Helix](https://github.com/helix-editor/helix) through our language extension. Prebuilt binaries for all supported platforms can be found in the [LSP release page](https://github.com/amber-lang/amber-lsp/releases). Thank you [@KrosFire](https://github.com/KrosFire) for developing the LSP. +We also introduced a new `std/test` library. More on that in the [Standard library improvements](#standard-library-improvements) section. -![Amber LSP Feature]{"width": "100%"}(/images/lsp-example-light.webp)(/images/lsp-example-dark.webp) - -# Support for a wide range of Bash versions - -Amber now compiles to a bash that is compatible with Bash versions all the way back from `3.2` to latest (currently `5.3`). - -To achieve this, we integrated all the different bash versions and a macos runner into our continuous integration (CI) pipeline. Thank you [@lens0021](https://github.com/lens0021). - -# More readable bash output - -The generated Bash output has been significantly improved for readability. The main block is now unindented, removing unnecessary leading spaces. Additionally, the `__` prefix has been removed from non-ALL-CAPS variable and function names, enhancing developer flexibility. ALL-CAPS identifiers retain the `__` prefix to prevent collisions. - -![Bash output comparison]{"width": "100%"}(/images/bash-output-comparison-light.webp)(/images/bash-output-comparison-dark.webp) - -# Integer type - -New integer `Int` data type that is now the only supported type for: - -- **Array subscript** - `i` in `arr[i]` can only be of type `Int` -- **Range** - `a` and `b` in `a..b` range operator can only be `Int` -- **Iterator** - `i` in `for i, item in items` is `Int` instead of `Num`. - -The standard library has been updated to consistently use `Int` for contexts like indexes, lengths, and incremental numbers. - -# Comparison - -Comparison operator now supports lexical comparison of `Text` data type. - -```ab -echo "file.txt" < "file_new.txt" -``` - -It also works for lexical comparison of array types `[Text]` and `[Int]`. - -```ab -let left = ["apple", "banana", "cherry"] -let right = ["apple", "bananas", "dates"] - -echo left > right // True -``` - - -# Optimizer - -Optimizer removes redundant and unused variables in the bash output. It can significantly reduce the shell code size. Let's take this example: - -```ab -let my_array = [1, 2, 3] -echo my_array -``` - -Now this simple code example would compile to the following result: - -```sh -__array_0=(1 2 3) -my_array="${__array_0[@]}" -echo "${my_array[@]}" -``` - -Why does this code introduce a seemingly redundant variable? Because Bash can’t use array literals directly in expressions, so we must reference a variable. That's why we create an intermediate one. Here is the code after optimization: - -```sh -my_array=(1 2 3) -echo "${my_array[@]}" -``` - -For now, this optimizer works for simple expressions, but it will be improved as we continue to develop Amber. - -# Reversed range support - -Previously, the range function required `start < end`. Now it supports any numeric order. - -```ab -echo 0..3 // [0, 1, 2] -echo 6..3 // [6, 5, 4] - -echo 0..=3 // [0, 1, 2, 3] -echo 6..=3 // [6, 5, 4, 3] -``` - -# While Loop - -New `while` loop for executing a block of code as long as a condition is true. - -```ab -let i = 0 -while i < 5 { - i += 1 - echo i -} -``` - -# Conditional Blocks: `succeeded`, `exited` and `failed` - -Amber now provides enhanced control flow for failable operations with the introduction of `succeeded` and `exited` blocks and parameter support for `failed` blocks. These features offer more explicit and cleaner ways to handle both success and failure paths for commands and failable functions. - -## `succeeded` Block - -The `succeeded` block executes when a command or failable function completes successfully (exit code = 0). It complements the existing `failed` block functionality. - -You cannot use both `succeeded` and `failed` blocks for the same command/function. - -**Commands:** -```ab -$ echo "hello" $ succeeded { - echo "Command worked!" -} -``` - -**Failable Functions:** -```ab -fun test(): Num? { - // ... logic that might fail ... - return 42 -} - -test() succeeded { - echo "Function succeeded!" -} -``` - -## Enhanced `failed` Block with Parameter Support - -The `failed` block now supports an optional parameter that captures the exit code of the failed command or failable function. This eliminates the need for temporary variables and preserves the original exit code, even if other commands are run within the `failed` block. - -**Basic usage:** -```ab -silent $ nonexistent_command $ failed(code) { - echo "Command failed with exit code: {code}" -} -``` - -**Parameter isolation:** -```ab -silent $ false $ failed(error) { - trust $ ls > /dev/null $ // This changes 'status' - echo "Original error: {error}" // But parameter preserves original code - echo "Current status: {status}" -} -``` - -## `exited` Block - -Amber now introduces a `exited` block for handling command and failable function exit codes directly. It offers a unified way to access the exit status (success or failure) as a typed integer variable, providing an alternative to separate `failed` and `succeeded` blocks. This enhances code clarity and type safety. The `exited` block requires a mandatory parameter (e.g., `exited(code)`) and cannot be combined with `failed` or `succeeded` blocks for the same failable expression. - -**Commands:** ```ab -$ command $ exited(code) { - echo "Command finished with exit code: {code}" +test "can multiply numbers" { + let result = 10 * 2 + // assertions ... } ``` -**Failable Functions:** -```ab -fun my_failable_func(): Text? { - // ... logic that might fail ... - return "Success" -} - -my_failable_func() exited(code) { - echo "Function finished with exit code: {code}" -} -``` - -# Standard library - -- New standard library function `bash_version` (in `std/env`) that returns currently installed version of bash. -- New `temp_dir_create` function that properly creates a temporary directory on Linux and macOS. Thanks [@lens0021](https://github.com/lens0021) -- New standard library function `parse_int` to parse text to an integer. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Renamed `parse_number` to `parse_num` for clarity. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- `math_sum` no longer uses `awk`, improving portability. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Five standard library functions (`symlink_create`, `dir_create`, `file_chmod`, `file_chown`, `file_download`) have been updated to be failable, providing more robust error handling. Thanks [@lens0021](https://github.com/lens0021). -- New standard library function `array_filled` (in `std/array`) to create an array of a specified size, filled with a given value. Thanks [@UrbanCoffee](https://github.com/UrbanCoffee). -- Removed `env_const_get` function from `std/env`. Use `env_var_get` instead. - -## `std/date` - -Improved date library by replacing old functions with new ones. - -### Removed functions: - -| Name | Description | -|:--|:--| -| `date_posix` | By default reads date in a `YYYY-MM-DDTHH:MM:SST` format and stores in a platform dependent representation | -| `date_add` | Adds time to already parsed date | -| `date_compare` | Compares two dates and returns value of a sign function | - -### Introduced functions: +You can also name your tests for better readability and filter them by name or filename using CLI arguments. Read more in the [Testing Guide](testing). -| Name | Description | -|:--|:--| -| `date_from_posix` | Converts textual representation in a default `YYYY-MM-DD HH:MM:SS` format to [unix epoch time](https://en.wikipedia.org/wiki/Unix_time) | -| `date_format_posix` | Converts [unix epoch time](https://en.wikipedia.org/wiki/Unix_time) to a textual representation. | -| `date_add` | Adds time to passed date. | -| `date_sub` | Subtracts time to passed date. | +# Standard library improvements -How to compare dates now? Since date is now stored as milliseconds since epoch, we can simply compare them with `>`, `>=`, `<` and `<=` operators. +> WARNING: Brief description of new changes TBD when releasing -# Sudo Command Modifier +## New `std/test` module -Amber now includes a new `sudo` command modifier that intelligently handles privilege escalation. This modifier automatically detects at runtime whether `sudo` is necessary and available, ensuring your scripts run correctly whether executed as root or a regular user. +We introduced a new [`std/test`](stdlib/doc/test) library that provides `assert` and `assert_eq` functions to help you write tests. -Its features include runtime detection of `sudo` availability (checked when the script runs, not during compilation), portable scripts that adapt to different environments, and seamless integration alongside existing command modifiers like `trust` and `silent`. - -**Single command:** ```ab -sudo $ mv /test.txt /test1.txt $? -``` +import { assert, assert_eq } from "std/test" -**Block syntax:** -```ab -sudo { - $ systemctl restart nginx $? - $ chown user:group /var/log/app.log $? +test "can multiply numbers" { + let result = 10 * 2 + assert(result == 20) + assert_eq(result, 20) } ``` - -**Combined with other modifiers:** -```ab -sudo trust silent $ systemctl status nginx $ -``` - -# Other Features - -- Documentation Generator can output generated.documentation to standard output. Thanks [@hdwalters](https://github.com/hdwalters). -- The documentation now uses `CARGO_PKG_VERSION` instead of `master` when linking, improving reliability. Thanks [@lens0021](https://github.com/amber-lang/amber/pull/649). -- Improved compiler error reporting. -- Refactored internal failable operations from "failable types" to "failable functions" for improved consistency. Thanks [@b1ek](https://github.com/b1ek). -- Added warnings for invalid escape sequences in string literals, improving developer experience by highlighting potential issues. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Improved error handling for invalid import statements, providing more helpful messages when `*` is incorrectly used in import closures. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Suppressed unnecessary warnings for valid escape characters used within commands, improving clarity in compiler output. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Introduced `AMBER_HEADER` and `AMBER_FOOTER` environment variables, allowing users to customize the header and footer of generated Bash scripts. Thanks [@Thesola10](https://github.com/Thesola10). -- Improved error messages when a `failed` block is not used after a failable expression, providing clearer guidance for error handling. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Improved error message for `?` operator usage, providing more helpful feedback for developers. Thanks [@Mte90](https://github.com/Mte90). -- The compiler now consistently supports both single-line (`:`) and multi-line (`{}`) block syntax across various language constructs. This enhances flexibility, allowing developers to choose the most readable and concise style for their code. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). For example: - ```ab - main: - run()? - ``` - -# Bugfixes - -- Duplicate argument names are not allowed. Thanks [@MuhamedMagdi](https://github.com/MuhamedMagdi). -- Standard library `replace_regex` now properly works on macOS and Linux musl. Thanks [@Aleksanaa](https://github.com/Aleksanaa). -- Casting `Text` to `Bool` now raises an absurd cast warning. Thanks [@lens0021](https://github.com/lens0021). -- Fixed escaping of backticks in text literals. -- The `replace_one` and `replace` functions now properly work when replacing backslash. -- Fixed an issue where `shfmt` failed when processing generated Bash code for array comparisons. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Improved cross-platform compatibility for `match_regex()` and `replace_regex()` by disabling certain GNU Sed-specific regular expression features. Thanks [@lens0021](https://github.com/lens0021). -- Fixed bad escaping for strings containing `$` sequences, ensuring correct literal interpretation. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Fixed an issue where escaped newlines in comments were not correctly ignored during parsing. Thanks [@b1ek](https://github.com/b1ek). -- Fixed a bug where local variables in functions could be unintentionally overwritten by variables from nested function calls, ensuring correct variable scoping. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Fixed incorrect interpolation of backticks within `Text` literals, ensuring proper command substitution behavior. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Fixed an error that occurred when attempting to use nested arrays, ensuring proper array handling. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Fixed an issue where reversed ranges on Linux did not function correctly, ensuring consistent behavior across platforms. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Fixed an issue where arguments of the main function could be shadowed, ensuring globally unique IDs for main function arguments. Thanks [@lens0021](https://github.com/lens0021). -- Corrected interpolation within single-quoted strings in commands, resolving issues where interpolated values were not properly parsed. Thanks [@lens0021](https://github.com/lens0021). For example: - ```ab - trust $ echo '{"a":1, "b":2}' | jq '.["b"]' $ - ``` - This example now correctly prints `2`. - -# Internal Improvements - -- When Amber is built by development branch, now the binary version includes commit hash. Thanks [@Thesola10](https://github.com/Thesola10). -- Improved shellcheck code coverage. -- Compiler collaborators can now benefit from a ready VS Code debug profile. Thanks [@b1ek](https://github.com/b1ek). -- Improved internal documentation generation and usage links by correctly referencing prefixed test files and removing excess blank lines from generated Markdown. Thanks [@hdwalters](https://github.com/hdwalters). -- The compiled installation scripts have been removed from the repository and are now published via CI, streamlining the installation process. Thanks [@Mte90](https://github.com/Mte90). -- Implemented a new translation modules architecture for the compiler, introducing a Bash pseudo AST for improved code generation. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Added Git version information at build-time, which is now included in the command-line `-V` option and generated script headers for better version tracking. Thanks [@Thesola10](https://github.com/Thesola10). -- Refactored the variable handling system in the compiler, transitioning to `VarExprFragment` and `VarStmtFragment` for improved clarity and maintainability. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Updated CI/CD workflows to run on `main` and `staging` branches, ensuring continuous integration for key development branches. Thanks [@b1ek](https://github.com/b1ek). -- Addressed `clippy::uninlined_format_args` warnings, improving code quality and adherence to Rust best practices. Thanks [@lens0021](https://github.com/lens0021). -- Removed `shfmt` postprocessor support, as it was rendered redundant by internal compiler improvements, streamlining the build process. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Renamed parameters of `text_contain()`, `text_contain_any()` and `text_contain_all()` functions to `source` and `search` for improved clarity. Thanks [@lens0021](https://github.com/lens0021). -- Improved test suite robustness by fixing concurrency issues in input tests using unique temporary files. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Refactored CLI tests to use internal API with inline logic, improving simplicity, reliability, and speed. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Implemented a new and simpler release pipeline, replacing `cargo-dist` for improved maintainability and efficiency. Thanks [@Ph0enixKM](https://github.com/Ph0enixKM). -- Introduced an intermediate state for text handling between parsing and translation, simplifying escaping logic and improving compiler architecture. Thanks [@lens0021](https://github.com/lens0021). -- Improved internal documentation and code clarity through various fixes, including correcting internal comments, fixing typos in the standard library documentation, and updating `std/array` documentation to accurately reflect current behaviors. Thanks [@lens0021](https://github.com/lens0021). -- Removed the `build.ab` script, as its functionality has been replaced by the new release pipeline, streamlining the build process. Thanks [@lens0021](https://github.com/lens0021). -- Migrated bash calls in test files to use built-in functions, improving test efficiency and reliability. Thanks [@lens0021](https://github.com/lens0021). -- Updated internal installation, shared, and uninstallation scripts to use recent syntax and standard library features, improving maintainability. Thanks [@lens0021](https://github.com/lens0021). -- Removed rotten TODOs from the codebase. Thanks [@lens0021](https://github.com/lens0021). diff --git a/docs/0.6.0-alpha/index.json b/docs/0.6.0-alpha/index.json index 58fb9d8..eb06abf 100644 --- a/docs/0.6.0-alpha/index.json +++ b/docs/0.6.0-alpha/index.json @@ -12,6 +12,10 @@ "path": "getting_started/usage", "title": "Usage" }, + { + "path": "getting_started/testing", + "title": "Testing" + }, { "path": "getting_started/whats_new", "title": "What's new" @@ -120,6 +124,11 @@ "title": "Math", "disableLevels": [3] }, + { + "path": "stdlib/doc/test", + "title": "Test", + "disableLevels": [3] + }, { "path": "stdlib/doc/text", "title": "Text", diff --git a/docs/0.6.0-alpha/stdlib/doc/test.md b/docs/0.6.0-alpha/stdlib/doc/test.md new file mode 100644 index 0000000..9f703c2 --- /dev/null +++ b/docs/0.6.0-alpha/stdlib/doc/test.md @@ -0,0 +1,31 @@ +## `assert` + +```ab +pub fun assert(condition: Bool) +``` + +Asserts that a boolean condition is true. Fails the test with exit code `1` if false. +### Usage +```ab +import { assert } from "std/test" + +let user_age = 18 +assert(user_age >= 18) +``` + +## `assert_eq` + +```ab +pub fun assert_eq(left, right) +``` + +Asserts that two values are equal. Fails the test with exit code `1` if they are not equal. +### Usage +```ab +import { assert_eq } from "std/test" + +let expected = [1, 2, 3] +let actual = [1, 2, 3] +assert_eq(expected, actual) +``` + diff --git a/src/components/Markdown/amber-config.json b/src/components/Markdown/amber-config.json index 42d1ca1..e82412a 100644 --- a/src/components/Markdown/amber-config.json +++ b/src/components/Markdown/amber-config.json @@ -35,6 +35,7 @@ "succeeded", "sudo", "exited", + "test", "then", "trust", "unsafe",