Improve error handling #143
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Rust | |
| on: | |
| push: | |
| pull_request: | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| linux-ubuntu: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Fetch | |
| run: cargo fetch | |
| - name: Build | |
| run: cargo build --release --verbose | |
| - name: Run tests | |
| run: cargo test --release --verbose | |
| - name: Run fmt check | |
| run: cargo fmt --all -- --check | |
| - name: Run clippy | |
| run: cargo clippy --release --all-targets -- -D warnings | |
| # The examples are the only programs compiled and run end to end through | |
| # the real driver -- shelling out to the assembler and linker -- rather | |
| # than through the test harness. | |
| - name: Compile and run the examples | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| for f in examples/*.bas; do | |
| echo "== $f" | |
| ./target/release/xbasic64 "$f" -o /tmp/example | |
| /tmp/example </dev/null >/dev/null | |
| done | |
| windows-native: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup MSVC | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| with: | |
| arch: x64 | |
| - name: Install LLVM/Clang | |
| run: choco install llvm -y | |
| - name: Add LLVM to PATH | |
| run: echo "C:\Program Files\LLVM\bin" >> $env:GITHUB_PATH | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build | |
| run: cargo build --release --verbose | |
| - name: Run tests | |
| run: cargo test --release --verbose | |
| - name: Run fmt check | |
| run: cargo fmt --all -- --check | |
| - name: Run clippy | |
| run: cargo clippy --release --all-targets -- -D warnings | |
| # Worth repeating here rather than trusting the Linux job: this is the | |
| # only step that drives link.exe over whole programs, and the Win64 | |
| # runtime is the half that cannot be run anywhere else. | |
| # | |
| # Deliberately PowerShell, the shell the rest of this job uses. Under | |
| # `shell: bash` the PATH leads with Git for Windows' usr/bin, whose GNU | |
| # coreutils `link.exe` shadows the MSVC linker -- the compiler then hands | |
| # MSVC flags to coreutils and gets "extra operand '/SUBSYSTEM:CONSOLE'". | |
| - name: Compile and run the examples | |
| shell: pwsh | |
| run: | | |
| Get-ChildItem examples/*.bas | ForEach-Object { | |
| Write-Host "== $($_.Name)" | |
| & ./target/release/xbasic64.exe $_.FullName -o example.exe | |
| if ($LASTEXITCODE -ne 0) { throw "compile failed: $($_.Name)" } | |
| & ./example.exe | Out-Null | |
| # Report the code, not just the failure. Windows says what went | |
| # wrong in it, and nothing else here can: 1 is the compiler's own | |
| # diagnosed abort, while 0xC0000005 (access violation), 0xC0000409 | |
| # (stack buffer overrun) and 0xC0000374 (heap corruption) each name | |
| # a different defect, and none of the three can be reproduced on | |
| # the Linux job. | |
| if ($LASTEXITCODE -ne 0) { | |
| # `-f` with X8 renders a negative Int32 as its two's-complement | |
| # hex on its own. Masking first needed no cast and got one: in | |
| # PowerShell 0xFFFFFFFF is Int32 -1, so the -band was a no-op and | |
| # [uint32] then threw on the very value it was there to show. | |
| throw ("run failed: {0} (exit {1}, 0x{2:X8})" -f $_.Name, $LASTEXITCODE, $LASTEXITCODE) | |
| } | |
| } | |
| # An example is a whole program, so a crash in one names the program and | |
| # not the statement. These are one statement each, and they are the only | |
| # coverage the console statements have anywhere: the test suite runs on | |
| # Linux, and CLS, LOCATE and COLOR are precisely the helpers whose two | |
| # implementations differ most. | |
| # | |
| # Every probe runs, and the step reports the whole table before failing, | |
| # so one CI run says which statements are broken rather than the first. | |
| - name: Probe each console statement | |
| if: always() | |
| shell: pwsh | |
| run: | | |
| $probes = [ordered]@{ | |
| 'CLS' = 'CLS' | |
| 'CLS after PRINT' = "PRINT `"x`"`nCLS" | |
| 'CLS twice' = "CLS`nCLS" | |
| 'PRINT alone' = 'PRINT "x"' | |
| 'COLOR' = 'COLOR 14, 1' | |
| 'LOCATE' = 'LOCATE 2, 5' | |
| 'LOCATE row only' = 'LOCATE 3' | |
| 'POS' = 'PRINT POS(0)' | |
| 'TIMER' = 'PRINT TIMER' | |
| 'RANDOMIZE n' = 'RANDOMIZE 42' | |
| 'RANDOMIZE TIMER' = 'RANDOMIZE TIMER' | |
| 'RND' = 'PRINT RND' | |
| 'RND(0)' = 'PRINT RND(0)' | |
| 'BEEP' = 'BEEP' | |
| 'DATE$' = 'PRINT DATE$' | |
| 'TIME$' = 'PRINT TIME$' | |
| 'FRE' = 'PRINT FRE(0)' | |
| 'DEFINT' = "DEFINT A-Z`nX = 3`nPRINT X" | |
| 'EQV' = 'PRINT 1 EQV 1' | |
| 'ERASE' = "DIM A(3)`nERASE A" | |
| 'SYSTEM' = 'SYSTEM' | |
| } | |
| $failed = @() | |
| foreach ($p in $probes.GetEnumerator()) { | |
| Set-Content -Path probe.bas -Value $p.Value | |
| & ./target/release/xbasic64.exe probe.bas -o probe.exe | Out-Null | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host ("{0,-20} DID NOT COMPILE" -f $p.Key) | |
| $failed += $p.Key | |
| continue | |
| } | |
| & ./probe.exe | Out-Null | |
| $code = $LASTEXITCODE | |
| Write-Host ("{0,-20} exit {1} (0x{2:X8})" -f $p.Key, $code, $code) | |
| if ($code -ne 0) { $failed += $p.Key } | |
| } | |
| if ($failed.Count -gt 0) { throw "crashed: $($failed -join ', ')" } |