#[test] meets simavr!
  • Rust 98.8%
  • Nix 0.7%
  • Dockerfile 0.3%
  • Just 0.2%
Find a file
2026-04-28 19:13:51 +02:00
.devcontainer Add devcontainer configuration 2025-09-15 02:51:20 +02:00
avr-simulator chore: Release v0.6.3 2026-04-28 19:13:14 +02:00
avr-tester chore: Release v0.6.3 2026-04-28 19:13:14 +02:00
avr-tester-fixtures refactor: PortState -> PinMode 2026-04-04 21:07:18 +02:00
.envrc Initial commit 2022-05-24 21:43:24 +02:00
.gitignore Initial commit 2022-05-24 21:43:24 +02:00
Cargo.lock chore: Release v0.6.3 2026-04-28 19:13:14 +02:00
Cargo.toml tests: Refactor 2024-10-29 20:33:11 +01:00
CHANGELOG.md changelog: Fix misplaced dot 2026-04-28 19:13:51 +02:00
flake.lock nix: Use Flakes 2024-10-29 20:31:22 +01:00
flake.nix nix: Use Flakes 2024-10-29 20:31:22 +01:00
Justfile tests: Support custom compiler-builtins 2025-03-16 11:46:43 +01:00
LICENSE chore: Update year 2024-01-02 15:57:05 +01:00
README.md chore: Release v0.6.0 2025-09-15 14:04:07 +02:00
rust-toolchain.toml chore: Bump toolchain 2025-04-15 21:58:14 +02:00
rustfmt.toml chore: Bump toolchain 2024-10-29 12:23:10 +01:00

avr-tester   crates-badge docs-badge

Framework for testing AVR binaries, powered by simavr.

tl;dr get your microcontroller's firmware black-box-tested in seconds!

Getting started

Create a crate dedicated to your firmware's tests:

$ cargo new firmware-tests --lib

... add avr-tester as its dependency:

# firmware-tests/Cargo.toml

[dependencies]
avr-tester = "0.6"

... and start writing tests:

// firmware-tests/src/lib.rs

use avr_tester::*;

fn avr() -> AvrTester {
    AvrTester::atmega328p()
        .with_clock_of_16_mhz()
        .load("../../firmware/target/avr-none/release/firmware.elf")
}

// Assuming `firmware` implements a ROT-13 encoder:

#[test]
fn short_text() {
    let mut avr = avr();

    // Let's give our firmware a moment to initialize:
    avr.run_for_ms(1);

    // Now, let's send the string:
    avr.uart0().write("Hello, World!");

    // ... give the AVR a moment to retrieve it & send back, encoded:
    avr.run_for_ms(1);

    // ... and, finally, let's assert the outcome:
    assert_eq!("Uryyb, Jbeyq!", avr.uart0().read::<String>());
}

#[test]
fn long_text() {
    let mut avr = avr();

    avr.run_for_ms(1);
    avr.uart0().write("Lorem ipsum dolor sit amet, consectetur adipiscing elit");
    avr.run_for_ms(10);

    assert_eq!(
        "Yberz vcfhz qbybe fvg nzrg, pbafrpgrghe nqvcvfpvat ryvg",
        avr.uart0().read::<String>(),
    );
}

... having the tests ready, just run cargo test inside firmware-tests.

Since AvrTester emulates an actual AVR, you don't have to modify your firmware at all - it can use timers, GPIOs etc. and everything should just work ™.

In fact, your project doesn't even have to be written in Rust - you can create Rust tests for a firmware written in C, Zig and anything else!

Features

See more: ./avr-tester/tests/examples.

Supported platforms

See: simavr-ffi.

Roadmap

Following features are supported by simavr, but haven't been yet exposed in AvrTester:

  • Interrupts,
  • EEPROM,
  • Watchdog,
  • USB.

Your firmware can use those features, you just won't be able to test them.

Caveats

  • Triggering AVR's sleep mode will cause the Rust code to panic, because the only way to wake an AVR is to trigger an interrupt and those are not yet supported.

Contributing

Pull requests are very much welcome!

Tests

Use just test to test AvrTester (so meta!) -- note that you might need some additional dependencies:

... using Nix (Linux / Mac)

$ nix develop
# and then `just test`

... on Ubuntu

$ sudo apt install avr-libc build-essential clang elfutils gcc-avr libelf-dev pkg-config
# and then `just test`

See also: .devcontainer.

License

Copyright (c) 2022 Patryk Wychowaniec [email protected].
Licensed under the MIT license.