diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f79b10d..87f9470b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,10 +12,10 @@ permissions: {} jobs: build-and-test-native: - runs-on: ${{ matrix.operating-system }} + runs-on: ${{ matrix.os }} strategy: matrix: - operating-system: [ubuntu-22.04, ubuntu-24.04, ubuntu-24.04-arm] + os: [ubuntu-22.04, ubuntu-24.04, ubuntu-24.04-arm, macos-15] steps: - uses: actions/checkout@v4 @@ -26,6 +26,8 @@ jobs: run: | if [[ "${{ runner.os }}-${{ runner.arch }}" == "Linux-ARM64" ]]; then curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_arm64-latest.tar.gz + elif [[ "${{ runner.os }}" == "macOS" ]]; then + curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-macos_apple_silicon-latest.tar.gz else curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-latest.tar.gz fi @@ -43,12 +45,17 @@ jobs: - run: ./roc_nightly/roc version - - run: | - sudo apt update - sudo apt install -y expect ncat valgrind ripgrep - # expect for testing - # ncat for tcp-client example - # ripgrep for ci/check_all_exposed_funs_tested.roc + - name: Install dependencies (Ubuntu) + if: startsWith(matrix.os, 'ubuntu-') + run: | + sudo apt install -y expect ncat ripgrep + + - name: Install dependencies (macOS) + if: startsWith(matrix.os, 'macos-') + run: | + brew install expect # expect for testing + brew install nmap # includes ncat, for tcp-client example + brew install ripgrep # ripgrep for ci/check_all_exposed_funs_tested.roc - run: expect -v @@ -56,9 +63,10 @@ jobs: run: ROC=./roc_nightly/roc EXAMPLES_DIR=./examples/ ./ci/all_tests.sh - name: Install dependencies for musl build + if: startsWith(matrix.os, 'ubuntu-') run: | sudo apt-get install -y musl-tools - if [[ "${{ matrix.operating-system }}" == *"-arm" ]]; then + if [[ "${{ matrix.os }}" == *"-arm" ]]; then # TODO re-enable once TODO below is done: rustup target add aarch64-unknown-linux-musl echo "no-op" else @@ -66,10 +74,11 @@ jobs: fi - name: Test building with musl target + if: startsWith(matrix.os, 'ubuntu-') env: ROC: ./roc_nightly/roc run: | - if [[ "${{ matrix.operating-system }}" == *"-arm" ]]; then + if [[ "${{ matrix.os}}" == *"-arm" ]]; then # TODO debug this: CARGO_BUILD_TARGET=aarch64-unknown-linux-musl $ROC build.roc echo "no-op" else @@ -77,8 +86,9 @@ jobs: fi - name: Test using musl build + if: startsWith(matrix.os, 'ubuntu-') run: | # TODO remove `if` when above TODOs are done - if [[ "${{ matrix.operating-system }}" != *"-arm" ]]; then + if [[ "${{ matrix.os }}" != *"-arm" ]]; then NO_BUILD=1 IS_MUSL=1 ROC=./roc_nightly/roc EXAMPLES_DIR=./examples/ ./ci/all_tests.sh fi diff --git a/ci/expect_scripts/path-test.exp b/ci/expect_scripts/path-test.exp old mode 100644 new mode 100755 index 79f20dfe..5d3da4f8 --- a/ci/expect_scripts/path-test.exp +++ b/ci/expect_scripts/path-test.exp @@ -45,14 +45,14 @@ test_parent/test_child/test_grandchild Number of directories created: 3 Directory contents: total \\d+ -dr\[-rwx\]+ +\\d+ \\w+ (\\w+ )? *\\d+ \\w+ +\\d+ \\d+:\\d+ \\. -dr\[-rwx\]+ +\\d+ \\w+ (\\w+ )? *\\d+ \\w+ +\\d+ \\d+:\\d+ \\.\\. --\[-rwx\]+ +\\d+ \\w+ (\\w+ )? *\\d+ \\w+ +\\d+ \\d+:\\d+ file1\\.txt --\[-rwx\]+ +\\d+ \\w+ (\\w+ )? *\\d+ \\w+ +\\d+ \\d+:\\d+ file2\\.txt -dr\[-rwx\]+ +\\d+ \\w+ (\\w+ )? *\\d+ \\w+ +\\d+ \\d+:\\d+ subdir +d.* \\. +d.* \\.\\. +-.* file1\\.txt +-.* file2\\.txt +d.* subdir Empty dir was deleted: Bool.true -Size before delete_all: \\d+\\w*\\s*test_parent +Size before delete_all:\\s*\\d+\\w*\\s*test_parent Parent dir no longer exists: Bool.true @@ -63,8 +63,8 @@ Original content: Original content for Path hard link test Link content: Original content for Path hard link test Content matches: Bool.true Inode information: -\\d+ -rw-r--r-- \\d+ \\w+ (\\w+ )? *\\d+ \\w+ +\\d+ \\d+:\\d+ test_path_hardlink\\.txt -\\d+ -rw-r--r-- \\d+ \\w+ (\\w+ )? *\\d+ \\w+ +\\d+ \\d+:\\d+ test_path_original\\.txt +\\d+ .* test_path_hardlink\\.txt +\\d+ .* test_path_original\\.txt First file inode: \\\[\"\\d+\"\\\] Second file inode: \\\[\"\\d+\"\\\] @@ -83,19 +83,19 @@ I ran all Path function tests. Cleaning up test files... Files to clean up: --rw-r--r-- \\d+ \\w+ \\w+ \\d+ \\w+ +\\d+ \\d+:\\d+ test_path_bytes\\.txt --rw-r--r-- \\d+ \\w+ \\w+ \\d+ \\w+ +\\d+ \\d+:\\d+ test_path_hardlink\\.txt --rw-r--r-- \\d+ \\w+ \\w+ \\d+ \\w+ +\\d+ \\d+:\\d+ test_path_json\\.json --rw-r--r-- \\d+ \\w+ \\w+ \\d+ \\w+ +\\d+ \\d+:\\d+ test_path_original\\.txt --rw-r--r-- \\d+ \\w+ \\w+ \\d+ \\w+ +\\d+ \\d+:\\d+ test_path_rename_new\\.txt --rw-r--r-- \\d+ \\w+ \\w+ \\d+ \\w+ +\\d+ \\d+:\\d+ test_path_utf8\\.txt - -ls: cannot access .* -ls: cannot access .* -ls: cannot access .* -ls: cannot access .* -ls: cannot access .* -ls: cannot access .* +-.* test_path_bytes\\.txt +-.* test_path_hardlink\\.txt +-.* test_path_json\\.json +-.* test_path_original\\.txt +-.* test_path_rename_new\\.txt +-.* test_path_utf8\\.txt + +ls: .* +ls: .* +ls: .* +ls: .* +ls: .* +ls: .* Files deleted successfully: Bool.true "] diff --git a/platform/main.roc b/platform/main.roc index 0d7ed3b1..63846ce0 100644 --- a/platform/main.roc +++ b/platform/main.roc @@ -61,7 +61,7 @@ main_for_host! = |raw_args| Program exited with error: - ❌ ${clean_err_str} + ❌ ${clean_err_str} """ _ = Stderr.line!(help_msg) diff --git a/tests/cmd-test.roc b/tests/cmd-test.roc index 88209a44..323b70c4 100644 --- a/tests/cmd-test.roc +++ b/tests/cmd-test.roc @@ -51,9 +51,9 @@ main! = |_args| # Test StdoutContainsInvalidUtf8 - using printf to output invalid UTF-8 bytes expect_err( Cmd.new("printf") - |> Cmd.args(["%b", "\\xff\\xfe"]) # Invalid UTF-8 sequence + |> Cmd.args(["\\377\\376"]) # Invalid UTF-8 sequence |> Cmd.exec_output!, - "(Err (StdoutContainsInvalidUtf8 {cmd_str: \"{ cmd: printf, args: %b \\xff\\xfe }\", err: (BadUtf8 {index: 0, problem: InvalidStartByte})}))" + "(Err (StdoutContainsInvalidUtf8 {cmd_str: \"{ cmd: printf, args: \\377\\376 }\", err: (BadUtf8 {index: 0, problem: InvalidStartByte})}))" )? # exec_output_bytes! diff --git a/tests/file.roc b/tests/file.roc old mode 100644 new mode 100755 index 953cabd2..0c423da6 --- a/tests/file.roc +++ b/tests/file.roc @@ -16,7 +16,7 @@ main! = |_args| Ok(_) -> cleanup_test_files!(FilesNeedToExist) Err(err) -> - cleanup_test_files!(FilesMaybeExist)? + _ = cleanup_test_files!(FilesMaybeExist) Err(Exit(1, "Test run failed:\n\t${Inspect.to_str(err)}")) run_tests! : {} => Result {} _ diff --git a/tests/path-test.roc b/tests/path-test.roc old mode 100644 new mode 100755 index cc5d893d..3a2f87c3 --- a/tests/path-test.roc +++ b/tests/path-test.roc @@ -16,7 +16,7 @@ main! = |_args| Ok(_) -> cleanup_test_files!(FilesNeedToExist) Err(err) -> - cleanup_test_files!(FilesMaybeExist)? + _ = cleanup_test_files!(FilesMaybeExist) Err(Exit(1, "Test run failed:\n\t${Inspect.to_str(err)}")) run_tests!: {} => Result {} _ @@ -247,6 +247,21 @@ test_directory_operations! = |{}| Ok({}) +get_hard_link_count! : Str => Result Str _ +get_hard_link_count! = |path_str| + ls_l = + Cmd.new("ls") + |> Cmd.args(["-l", path_str]) + |> Cmd.exec_output!()? + + hard_link_count_str = + (ls_l.stdout_utf8 + |> Str.split_on(" ") + |> List.keep_if(|str| !Str.is_empty(str)) + |> List.get(1)) ? |_| IExpectedALineWithASpaceHere(ls_l) + + Ok(hard_link_count_str) + test_hard_link! : {} => Result {} _ test_hard_link! = |{}| Stdout.line!("\nTesting Path.hard_link!:")? @@ -255,15 +270,14 @@ test_hard_link! = |{}| original_path = Path.from_str("test_path_original.txt") Path.write_utf8!("Original content for Path hard link test", original_path)? - # Get original file stats - stat_before = Cmd.new("stat") |> Cmd.args(["-c", "%h", "test_path_original.txt"]) |> Cmd.exec_output!()? + hard_link_count_before = get_hard_link_count!("test_path_original.txt")? # Create hard link link_path = Path.from_str("test_path_hardlink.txt") when Path.hard_link!(original_path, link_path) is Ok({}) -> # Get link count after - stat_after = Cmd.new("stat") |> Cmd.args(["-c", "%h", "test_path_original.txt"]) |> Cmd.exec_output!()? + hard_link_count_after = get_hard_link_count!("test_path_original.txt")? # Verify both files exist and have same content original_content = Path.read_utf8!(original_path)? @@ -271,8 +285,8 @@ test_hard_link! = |{}| Stdout.line!( """ - Hard link count before: ${Str.trim(stat_before.stdout_utf8)} - Hard link count after: ${Str.trim(stat_after.stdout_utf8)} + Hard link count before: ${hard_link_count_before} + Hard link count after: ${hard_link_count_after} Original content: ${original_content} Link content: ${link_content} Content matches: ${Inspect.to_str(original_content == link_content)}