Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 41 additions & 9 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Rust

on:
push:
branches: [ main, tests ]
branches: [ main, tests, ci ]
pull_request:
branches: [ main ]

Expand Down Expand Up @@ -50,20 +50,31 @@ jobs:
chmod +x llvm.sh
sudo ./llvm.sh 18
sudo apt-get install -y llvm-18-dev libpolly-18-dev
sudo ln -s /usr/bin/llc-18 /usr/bin/llc

- name: Install LLVM (macOS)
if: matrix.os == 'macos-latest'
run: |
brew install llvm@18
echo "LLVM_SYS_180_PREFIX=$(brew --prefix llvm@18)" >> $GITHUB_ENV
echo "$(brew --prefix llvm@18)/bin" >> $GITHUB_PATH

- name: Run unit tests
run: cargo test --lib --bins

- name: Install npiet (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt install libgd-dev groff
git clone https://github.com/gleitz/npiet.git && cd npiet
./configure
make
sudo make install

# npiet installation skipped on macOS due to giflib 5.x API incompatibility
# npiet was written for giflib 4.x and requires patching for giflib 5.x

- name: Build release binary
run: cargo build --release

- name: Run integration tests
- name: Run integration tests (Ubuntu)
run: cargo test --test '*'

lint:
Expand All @@ -83,15 +94,18 @@ jobs:
chmod +x llvm.sh
sudo ./llvm.sh 18
sudo apt-get install -y llvm-18-dev libpolly-18-dev
sudo ln -s /usr/bin/llc-18 /usr/bin/llc

- name: Run rustfmt
run: cargo fmt -- --check

- name: Install npiet
run: |
git clone git@github.com:gleitz/npiet.git && cd npiet
make install
sudo cp npiet /bin/
sudo apt install libgd-dev groff
git clone https://github.com/gleitz/npiet.git && cd npiet
./configure
make
sudo make install

- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings
Expand All @@ -111,6 +125,15 @@ jobs:
chmod +x llvm.sh
sudo ./llvm.sh 18
sudo apt-get install -y llvm-18-dev libpolly-18-dev
sudo ln -s /usr/bin/llc-18 /usr/bin/llc

- name: Install npiet
run: |
sudo apt install libgd-dev groff
git clone https://github.com/gleitz/npiet.git && cd npiet
./configure
make
sudo make install

- name: Check compilation
run: cargo check --all-targets
Expand All @@ -127,12 +150,21 @@ jobs:
- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Install npiet
run: |
sudo apt install libgd-dev groff
git clone https://github.com/gleitz/npiet.git && cd npiet
./configure
make
sudo make install

- name: Install LLVM
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 18
sudo apt-get install -y llvm-18-dev libpolly-18-dev
sudo apt-get install -y llvm-18-dev libpolly-18-dev llvm-18-tools
sudo ln -s /usr/bin/llc-18 /usr/bin/llc

- name: Install cargo-tarpaulin
run: cargo install cargo-tarpaulin
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,25 @@ Alternatively, it is possible to combine the build / run workflow via

## Testing

PietCC includes comprehensive unit and integration tests. To run all tests:
PietCC includes comprehensive unit and integration tests.

### Prerequisites

Integration tests require [npiet](https://github.com/gleitz/npiet) to be installed:

**Ubuntu/Debian:**
```bash
sudo apt install libgd-dev groff
git clone https://github.com/gleitz/npiet.git && cd npiet
./configure
make
sudo make install
```

**macOS:**
npiet is not currently supported on macOS due to giflib API incompatibilities. Unit tests will still work.

### Running Tests

```bash
# Run all tests
Expand Down
26 changes: 9 additions & 17 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ fn main() -> Result<(), Error> {

if let Some(val) = matches.value_of("codel_size") {
if let Ok(val) = val.parse::<u32>() {
if program.dimensions().0 % val != 0 || program.dimensions().1 % val != 0 {
if !program.dimensions().0.is_multiple_of(val)
|| !program.dimensions().1.is_multiple_of(val)
{
match env::consts::OS {
"linux" => {
eprintln!(
Expand Down Expand Up @@ -187,7 +189,7 @@ fn main() -> Result<(), Error> {
}
}

if let Some(_) = matches.value_of("use_default") {
if matches.value_of("use_default").is_some() {
codel_settings = CodelSettings::Default
}

Expand Down Expand Up @@ -256,16 +258,8 @@ fn main() -> Result<(), Error> {
}

let warn_nt = matches.is_present("warn_nontermination");

let show_codel_size = match verbosity {
Verbosity::Low | Verbosity::Normal => false,
_ => true,
};

let show_cfg_size = match verbosity {
Verbosity::Low => false,
_ => true,
};
let show_codel_size = !matches!(verbosity, Verbosity::Low | Verbosity::Normal);
let show_cfg_size = !matches!(verbosity, Verbosity::Low);

let compile_options = CompilerSettings {
opt_level,
Expand All @@ -281,11 +275,9 @@ fn main() -> Result<(), Error> {
// Use the already-built CFG instead of creating a new one
let mut piet_ctx =
LoweringCtx::new(&context, module, builder, cfg_builder, compile_options);
if let Err(e) = pipeline::run_piet_optimization_pipeline(
&mut piet_ctx,
&mut cfg,
compile_options,
) {
if let Err(e) =
pipeline::run_piet_optimization_pipeline(&mut piet_ctx, &mut cfg, compile_options)
{
println!("{:?}", e);
}
}
Expand Down
7 changes: 3 additions & 4 deletions tests/integration/compiler_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ fn compile_program(
opt_level: Option<&str>,
) -> Result<(), String> {
let mut cmd = Command::new(pietcc_binary());
cmd.arg(image_path)
.arg("--uw"); // Treat unknown pixels as white (some test images need this)
cmd.arg(image_path).arg("--uw"); // Treat unknown pixels as white (some test images need this)

// Add optimization flag if specified
if let Some(opt) = opt_level {
Expand Down Expand Up @@ -124,10 +123,10 @@ fn compile_and_run(
/// Helper to test that pietcc output matches npiet output
fn test_against_npiet(image_path: &str, input: &str, opt_level: Option<&str>) {
let npiet_output =
run_npiet(image_path, input).expect(&format!("npiet failed for {}", image_path));
run_npiet(image_path, input).unwrap_or_else(|_| panic!("npiet failed for {}", image_path));

let pietcc_raw_output = compile_and_run(image_path, input, opt_level)
.expect(&format!("pietcc failed for {}", image_path));
.unwrap_or_else(|_| panic!("pietcc failed for {}", image_path));

// Strip debug output (lines containing "Stack") from pietcc output
let pietcc_output: String = pietcc_raw_output
Expand Down
12 changes: 6 additions & 6 deletions tests/integration/interpreter_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ fn test_hi_interpreter() {
assert!(result.is_ok(), "Interpreter failed: {:?}", result.err());
let output = result.unwrap();
assert!(
output.contains("Hi") || output.len() > 0,
output.contains("Hi") || !output.is_empty(),
"Expected non-empty output, got: {}",
output
);
Expand All @@ -112,7 +112,7 @@ fn test_pi_interpreter() {
assert!(result.is_ok(), "Interpreter failed: {:?}", result.err());
let output = result.unwrap();
// Pi calculation should produce digits
assert!(output.len() > 0, "Expected output from pi calculation");
assert!(!output.is_empty(), "Expected output from pi calculation");
}

#[test]
Expand All @@ -124,7 +124,7 @@ fn test_fizzbuzz_interpreter() {
let output = result.unwrap();
// FizzBuzz should contain Fizz or Buzz
assert!(
output.contains("Fizz") || output.contains("Buzz") || output.len() > 0,
output.contains("Fizz") || output.contains("Buzz") || !output.is_empty(),
"Expected FizzBuzz output, got: {}",
output
);
Expand All @@ -139,7 +139,7 @@ fn test_factorial_interpreter() {
let output = result.unwrap();
// 5! = 120
assert!(
output.contains("120") || output.len() > 0,
output.contains("120") || !output.is_empty(),
"Expected factorial output, got: {}",
output
);
Expand All @@ -154,7 +154,7 @@ fn test_adder_interpreter() {
let output = result.unwrap();
// Should add 3 + 5 = 8
assert!(
output.contains("8") || output.len() > 0,
output.contains("8") || !output.is_empty(),
"Expected addition output, got: {}",
output
);
Expand All @@ -169,7 +169,7 @@ fn test_euclid_interpreter() {
let output = result.unwrap();
// GCD of 48 and 18 is 6
assert!(
output.contains("6") || output.len() > 0,
output.contains("6") || !output.is_empty(),
"Expected GCD output, got: {}",
output
);
Expand Down
1 change: 1 addition & 0 deletions tests/integration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
#[path = "../common/mod.rs"]
mod common;

#[cfg(not(target_os = "macos"))]
mod compiler_tests;
mod interpreter_tests;
Loading