Skip to content

Commit 40e8d59

Browse files
committed
feat: Initial HIL test
1 parent a8ce6d9 commit 40e8d59

File tree

6 files changed

+287
-2
lines changed

6 files changed

+287
-2
lines changed

.github/actions/setup-target/action.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ runs:
6060
if: inputs.target == 'x86_64-unknown-linux-gnu' || inputs.target == 'x86_64-unknown-linux-musl'
6161
shell: bash
6262
run: |
63-
sudo apt-get update && sudo apt-get install musl-tools libudev-dev
63+
sudo apt-get update && sudo apt-get -y install musl-tools libudev-dev pkg-config
6464
6565
- name: Set environment variables
6666
if: inputs.arch != 'x86_64'

.github/workflows/hil.yml

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Build and Run Integration tests
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
push:
8+
workflow_dispatch:
9+
10+
env:
11+
CARGO_TERM_COLOR: always
12+
13+
# Cancel any currently running workflows from the same PR, branch, or
14+
# tag when a new workflow is triggered.
15+
#
16+
# https://stackoverflow.com/a/66336834
17+
concurrency:
18+
cancel-in-progress: true
19+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
20+
21+
22+
jobs:
23+
build:
24+
name: Generate and Build App
25+
strategy:
26+
fail-fast: false
27+
runs-on: ubuntu-20.04
28+
steps:
29+
- uses: dtolnay/rust-toolchain@nightly
30+
with:
31+
target: riscv32imac-unknown-none-elf
32+
components: clippy,rustfmt,rust-src
33+
34+
- uses: Swatinem/rust-cache@v2
35+
36+
- name: Install cargo-generate (binary)
37+
continue-on-error: true
38+
id: binary
39+
run: |
40+
VERSION="$(git ls-remote --refs --sort="version:refname" --tags "https://github.com/cargo-generate/cargo-generate" | cut -d/ -f3- | tail -n1)"
41+
sudo curl \
42+
-L "https://github.com/cargo-generate/cargo-generate/releases/latest/download/cargo-generate-$VERSION-x86_64-unknown-linux-gnu.tar.gz" \
43+
-o "/home/runner/.cargo/bin/cargo-generate.tar.gz"
44+
tar xf "/home/runner/.cargo/bin/cargo-generate.tar.gz" -C "/home/runner/.cargo/bin/"
45+
chmod u+x "/home/runner/.cargo/bin/cargo-generate"
46+
47+
- name: Install cargo-generate (source)
48+
if: steps.binary.outcome != 'success'
49+
run: cargo install cargo-generate
50+
51+
- run: cargo generate esp-rs/esp-template --name app -d mcu=esp32c3 -d advanced=false
52+
53+
- run: cargo build --release
54+
working-directory: app
55+
56+
- uses: actions/upload-artifact@v3
57+
with:
58+
name: esp32c3_app
59+
path: /home/runner/work/espflash/espflash/app/target/riscv32imc-unknown-none-elf/release/app
60+
if-no-files-found: error
61+
62+
run-target:
63+
name: Run Tests on Target
64+
if: ${{ github.repository_owner == 'esp-rs' }}
65+
needs: build
66+
runs-on: [self-hosted, linux, x64, esp32c3]
67+
steps:
68+
- uses: actions/checkout@v4
69+
- uses: actions/download-artifact@v3
70+
with:
71+
name: esp32c3_app
72+
path: espflash/esp32c3_app
73+
74+
- uses: ./.github/actions/setup-target
75+
with:
76+
arch: x86_64
77+
target: x86_64-unknown-linux-gnu
78+
79+
- name: Run Tests
80+
run: ESPFLASH_PORT=/dev/ttyACM0 ESPFLASH_APP=esp32c3_app/app cargo test

Cargo.lock

+81-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

espflash/Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,8 @@ cli = [
8484
]
8585

8686
raspberry = ["dep:rppal"]
87+
88+
89+
[dev-dependencies]
90+
assert_cmd = "2.0.12"
91+
# predicates = "3.0.4"

espflash/tests/cli.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use assert_cmd::prelude::*; // Add methods on commands
2+
// use predicates::prelude::*; // Used for writing assertions
3+
use std::process::Command; // Run programs
4+
5+
#[test]
6+
fn flash() -> Result<(), Box<dyn std::error::Error>> {
7+
// board-info
8+
let mut cmd: Command = Command::cargo_bin("espflash")?;
9+
10+
cmd.arg("board-info");
11+
cmd.assert().success();
12+
13+
let mut cmd = Command::cargo_bin("espflash")?;
14+
15+
// flash
16+
let image = std::env::var("ESPFLASH_APP").expect("ESPFLASH_APP not set");
17+
18+
cmd.arg("flash").arg(image);
19+
cmd.assert().success();
20+
21+
Ok(())
22+
}

espflash/tests/flash.rs

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#[test]
2+
fn flash_test() {
3+
use espflash::cli::{
4+
config::Config, connect, erase_partitions, flash_elf_image, monitor::LogFormat,
5+
parse_partition_table, ConnectArgs, EspflashProgress, FlashArgs, FlashConfigArgs,
6+
};
7+
use espflash::targets::Chip;
8+
use std::{fs, path::PathBuf};
9+
10+
// let image = PathBuf::from("esp32c3");
11+
let image = PathBuf::from(std::env::var("ESPFLASH_APP").expect("ESPFLASH_APP not set"));
12+
let port = std::env::var("ESPFLASH_PORT").expect("ESPFLASH_PORT not set");
13+
14+
let config = Config::default();
15+
16+
let conn = ConnectArgs {
17+
baud: Some(460800),
18+
chip: Some(Chip::Esp32c3),
19+
confirm_port: false,
20+
no_stub: false,
21+
port: Some(port),
22+
};
23+
24+
let mut flasher = connect(&conn, &config).unwrap();
25+
26+
let flash_config_args = FlashConfigArgs {
27+
flash_freq: None,
28+
flash_mode: None,
29+
flash_size: None,
30+
};
31+
32+
if let Some(flash_size) = flash_config_args.flash_size {
33+
flasher.set_flash_size(flash_size);
34+
}
35+
36+
let flash_args = FlashArgs {
37+
bootloader: None,
38+
erase_parts: None,
39+
erase_data_parts: None,
40+
format: None,
41+
log_format: LogFormat::Serial,
42+
monitor: true,
43+
monitor_baud: None,
44+
partition_table: None,
45+
target_app_partition: None,
46+
partition_table_offset: None,
47+
ram: false,
48+
};
49+
50+
// Read the ELF data from the build path and load it to the target.
51+
let elf_data = fs::read(&image).unwrap();
52+
53+
if flash_args.ram {
54+
flasher
55+
.load_elf_to_ram(&elf_data, Some(&mut EspflashProgress::default()))
56+
.unwrap();
57+
} else {
58+
let bootloader = flash_args.bootloader.as_deref();
59+
let partition_table = flash_args.partition_table.as_deref();
60+
61+
// if let Some(path) = bootloader {
62+
// println!("Bootloader: {}", path.display());
63+
// }
64+
// if let Some(path) = partition_table {
65+
// println!("Partition table: {}", path.display());
66+
// }
67+
68+
let partition_table = match partition_table {
69+
Some(path) => Some(parse_partition_table(path).unwrap()),
70+
None => None,
71+
};
72+
73+
if flash_args.erase_parts.is_some() || flash_args.erase_data_parts.is_some() {
74+
erase_partitions(
75+
&mut flasher,
76+
partition_table.clone(),
77+
flash_args.erase_parts,
78+
flash_args.erase_data_parts,
79+
)
80+
.unwrap();
81+
}
82+
83+
flash_elf_image(
84+
&mut flasher,
85+
&elf_data,
86+
bootloader,
87+
partition_table,
88+
flash_args.target_app_partition,
89+
flash_args.format,
90+
flash_config_args.flash_mode,
91+
flash_config_args.flash_size,
92+
flash_config_args.flash_freq,
93+
flash_args.partition_table_offset,
94+
)
95+
.unwrap();
96+
}
97+
// println!("Firmware flashing completed. ");
98+
}

0 commit comments

Comments
 (0)