Skip to content

Commit ccecf86

Browse files
authored
chore(ci): break setup into composite action, and add cargo-mutants (#5)
2 parents c7dadf8 + bd6525e commit ccecf86

25 files changed

Lines changed: 612 additions & 98 deletions

.cargo/mutants.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
exclude_globs = [
2+
"src/passes/codegen.rs", # Until LLVM snapshot tests are implemented.
3+
"src/ty/solver.rs", # Until solver is hardened and tested.
4+
]
5+
6+
test_tool = "nextest"

.github/actions/setup/action.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Setup
2+
description: Setup for CI.
3+
4+
inputs:
5+
llvm-path:
6+
description: Path to install LLVM to.
7+
required: true
8+
llvm-version:
9+
description: Version of LLVM to install.
10+
required: true
11+
12+
runs:
13+
using: composite
14+
steps:
15+
- name: Install LLVM Dependencies
16+
shell: bash
17+
run: |
18+
sudo apt update
19+
wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb
20+
sudo apt install ./libtinfo5_6.3-2ubuntu0.1_amd64.deb
21+
22+
- name: Install LLVM and Clang
23+
uses: KyleMayes/install-llvm-action@v2
24+
with:
25+
version: "${{ inputs.llvm-version }}"
26+
directory: "${{ inputs.llvm-path }}"
27+
28+
- name: Install rust
29+
shell: bash
30+
run: |
31+
rustup toolchain install stable --profile minimal --no-self-update
32+
33+
- uses: Swatinem/rust-cache@v2

.github/workflows/ci.yaml

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
env:
1010
CARGO_TERM_COLOR: "always"
1111
LLVM_PATH: "${{ github.workspace }}/llvm"
12+
LLVM_VERSION: "18.1"
1213

1314
jobs:
1415
test:
@@ -17,29 +18,15 @@ jobs:
1718
steps:
1819
- uses: actions/checkout@v5
1920

20-
- name: Install LLVM Dependencies
21-
run: |
22-
sudo apt update
23-
wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb
24-
sudo apt install ./libtinfo5_6.3-2ubuntu0.1_amd64.deb
25-
26-
- name: Install LLVM and Clang
27-
uses: KyleMayes/install-llvm-action@v2
21+
- uses: ./.github/actions/setup
2822
with:
29-
version: "18.1"
30-
directory: "${{ env.LLVM_PATH }}"
31-
32-
- name: Install rust
33-
run: |
34-
rustup toolchain install stable --profile minimal --no-self-update
23+
llvm-version: ${{ env.LLVM_VERSION }}
24+
llvm-path: ${{ env.LLVM_PATH }}
3525

36-
- name: Install cargo-llvm-cov
37-
uses: taiki-e/install-action@cargo-llvm-cov
38-
39-
- name: Install cargo-nextest
40-
uses: taiki-e/install-action@nextest
41-
42-
- uses: Swatinem/rust-cache@v2
26+
- name: Install cargo-llvm-cov and nextest
27+
uses: taiki-e/install-action@v2
28+
with:
29+
tool: cargo-llvm-cov,nextest
4330

4431
- name: Test with code coverage
4532
run: |
@@ -69,23 +56,10 @@ jobs:
6956
steps:
7057
- uses: actions/checkout@v5
7158

72-
- name: Install LLVM Dependencies
73-
run: |
74-
sudo apt update
75-
wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb
76-
sudo apt install ./libtinfo5_6.3-2ubuntu0.1_amd64.deb
77-
78-
- name: Install LLVM and Clang
79-
uses: KyleMayes/install-llvm-action@v2
59+
- uses: ./.github/actions/setup
8060
with:
81-
version: "18.1"
82-
directory: "${{ env.LLVM_PATH }}"
83-
84-
- name: Install rust
85-
run: |
86-
rustup toolchain install stable --profile minimal --no-self-update
87-
88-
- uses: Swatinem/rust-cache@v2
61+
llvm-version: ${{ env.LLVM_VERSION }}
62+
llvm-path: ${{ env.LLVM_PATH }}
8963

9064
- name: Run clippy
9165
run: |
@@ -98,8 +72,33 @@ jobs:
9872

9973
steps:
10074
- uses: actions/checkout@v5
75+
10176
- uses: streetsidesoftware/cspell-action@v8
10277
with:
10378
incremental_files_only: false
10479

80+
cargo-mutants:
81+
runs-on: ubuntu-latest
82+
83+
steps:
84+
- uses: actions/checkout@v5
85+
86+
- uses: ./.github/actions/setup
87+
with:
88+
llvm-version: ${{ env.LLVM_VERSION }}
89+
llvm-path: ${{ env.LLVM_PATH }}
90+
91+
- name: Install cargo-mutants and nextest
92+
uses: taiki-e/install-action@v2
93+
with:
94+
tool: cargo-mutants,nextest
95+
96+
- run: cargo mutants -vV --in-place
97+
98+
- uses: actions/upload-artifact@v4
99+
if: always()
100+
with:
101+
name: mutants-out
102+
path: mutants.out
103+
105104
# spell-checker:ignore libtinfo,Swatinem

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/target
2+
mutants.out*

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
inkwell = { version = "0.8.0", features = ["llvm18-1"] }
8+
mutants = "0.0.4"
89
thiserror = "2.0.17"
910

1011
[dev-dependencies]

src/error/mod.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,57 @@ macro_rules! run_and_report {
163163
})
164164
};
165165
}
166+
167+
#[cfg(test)]
168+
mod test {
169+
use super::*;
170+
171+
mod error {
172+
use super::*;
173+
174+
#[rstest]
175+
#[case("standard_error", CError::from(HirGenError::IfMustHaveBlock))]
176+
#[case("fatal_error", CError::from(HirGenError::IfMustHaveBlock).fatal())]
177+
#[case("message_error", CError::from(HirGenError::IfMustHaveBlock).with_message("some message"))]
178+
#[case("fatal_and_message_error", CError::from(HirGenError::IfMustHaveBlock).fatal().with_message("some message"))]
179+
fn formatting(#[case] name: &str, #[case] error: CError) {
180+
assert_snapshot!(name, error, &format!("{error:?}"));
181+
}
182+
}
183+
184+
mod list {
185+
use super::*;
186+
187+
#[rstest]
188+
#[case::empty([])]
189+
#[case::single_non_fatal([CError::from(HirGenError::IfMustHaveBlock)])]
190+
#[case::single_fatal([CError::from(HirGenError::IfMustHaveBlock).fatal()])]
191+
#[case::multiple_non_fatal(vec![CError::from(HirGenError::IfMustHaveBlock); 3])]
192+
#[case::multiple_fatal(vec![CError::from(HirGenError::IfMustHaveBlock).fatal(); 3])]
193+
#[case::multiple([
194+
CError::from(HirGenError::IfMustHaveBlock).fatal(),
195+
CError::from(HirGenError::IfMustHaveBlock),
196+
CError::from(HirGenError::IfMustHaveBlock).fatal(),
197+
])]
198+
fn counting(#[case] errors: impl IntoIterator<Item = CError>) {
199+
let mut list = CErrorList::default();
200+
let mut fatal = 0;
201+
let mut non_fatal = 0;
202+
203+
for error in errors {
204+
// Count fatal errors.
205+
if error.fatal {
206+
fatal += 1;
207+
} else {
208+
non_fatal += 1;
209+
}
210+
211+
// Report the error.
212+
list.report(error);
213+
}
214+
215+
assert_eq!(list.iter_fatal().count(), fatal);
216+
assert_eq!(list.iter_non_fatal().count(), non_fatal);
217+
}
218+
}
219+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: src/error/mod.rs
3+
expression: error
4+
---
5+
FATAL: an `if` expression must contain at least one block. (some message)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: src/error/mod.rs
3+
expression: "CError { kind: HirGen(IfMustHaveBlock), message: None, fatal: true }"
4+
---
5+
FATAL: an `if` expression must contain at least one block.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
source: src/error/mod.rs
3+
expression: "CError { kind: HirGen(IfMustHaveBlock), message: Some(\"some message\"), fatal: false }"
4+
---
5+
an `if` expression must contain at least one block. (some message)

0 commit comments

Comments
 (0)