Skip to content

Commit

Permalink
Merge pull request #884 from andrewdavidmackenzie/hardware_tests
Browse files Browse the repository at this point in the history
hardware_tests
  • Loading branch information
andrewdavidmackenzie authored Feb 27, 2025
2 parents 8ea4259 + b4d38a0 commit ebdc878
Show file tree
Hide file tree
Showing 12 changed files with 399 additions and 17 deletions.
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
members = ["pigdef", "piggui", "piglet", "pignet", "pigpio"]
default-members = ["pigdef", "piggui", "piglet", "pignet", "pigpio"]
members = ["pigdef", "piggui", "piglet", "pignet", "pigpio", "hw_test"]
default-members = ["pigdef", "piggui", "piglet", "pignet", "pigpio", "hw_test"]
resolver = "2"

[workspace.package]
Expand Down
26 changes: 15 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@
# target/aarch64-unknown-linux-gnu/release/piggui - GUI version for Pi with GPIO, can be run natively from RPi command line
# target/armv7-unknown-linux-gnueabihf/release/piggui - GUI version for armv7 based architecture with GPIO, can be run natively

# MacOS pre-requisites for cross-compiling to armv7
# brew install arm-linux-gnueabihf-binutils
# rustup target add armv7-unknown-linux-musleabihf
#
# See: https://github.com/messense/homebrew-macos-cross-toolchains
#
# brew tap messense/macos-cross-toolchains
# brew install aarch64-unknown-linux-gnu
# brew install arm-unknown-linux-gnueabihf
# brew install arm-unknown-linux-musleabihf

# Detect if on a Raspberry Pi
$(eval PI = $(shell cat /proc/cpuinfo 2>&1 | grep "Raspberry Pi"))

Expand All @@ -31,6 +20,16 @@ all: clippy build build-arm build-porky build-web test
clean:
@cargo clean

.PHONY: macos-setup
macos-setup: setup
@cd piggui && make macos-setup
@cd piglet && make macos-setup

.PHONY: setup
setup:
@cd piggui && make setup
@cd piglet && make setup

.PHONY: clippy
clippy:
cargo clippy --tests --no-deps
Expand Down Expand Up @@ -70,6 +69,11 @@ build-porky:
test:
cargo test


.PHONY: hw_tests
hw_tests:
cargo test --package hw_tests

.PHONY: features
features:
cargo build-all-features
Expand Down
25 changes: 25 additions & 0 deletions hw_test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "hw_test"
version = "0.6.0"
edition = "2021"
rust-version = "1.80"

[features]
default = ["usb", "tcp", "discovery"]
usb = ["pigdef/usb", "pignet/usb"]
tcp = ["pigdef/tcp", "pignet/tcp"]
discovery = ["pigdef/discovery", "pignet/discovery"]
iroh = ["pigdef/iroh", "pignet/iroh"]

[dev-dependencies]
pigdef = { path = "../pigdef" }
pignet = { path = "../pignet" }
tokio = { version = "1.43", default-features = false, features = ["time", "rt", "rt-multi-thread", "macros"] }
async-std = "1.13.0"
serial_test = "3.1.1"
anyhow = "1.0.96"
mdns-sd = { version = "0.13.2", default-features = false, features = ["async"] }
iroh = { version = "0.33.0", default-features = false }

[package.metadata.cargo-all-features]
skip_optional_dependencies = true
53 changes: 53 additions & 0 deletions hw_test/tests/mdns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#![cfg(feature = "discovery")]

use anyhow::anyhow;
#[cfg(feature = "iroh")]
use iroh::{NodeId, RelayUrl};
#[cfg(feature = "discovery")]
use mdns_sd::{ServiceDaemon, ServiceEvent};
#[cfg(feature = "discovery")]
use pigdef::description::TCP_MDNS_SERVICE_TYPE;
#[cfg(feature = "tcp")]
use std::net::IpAddr;
#[cfg(all(feature = "tcp", feature = "iroh"))]
use std::str::FromStr;

#[cfg(feature = "tcp")]
pub async fn get_ip_and_port_by_mdns() -> anyhow::Result<(IpAddr, u16)> {
let mdns = ServiceDaemon::new().expect("Failed to create daemon");
if let Ok(receiver) = mdns.browse(TCP_MDNS_SERVICE_TYPE) {
while let Ok(event) = receiver.recv_async().await {
if let ServiceEvent::ServiceResolved(info) = event {
if let Some(ip) = info.get_addresses_v4().drain().next() {
let port = info.get_port();
return Ok((IpAddr::V4(*ip), port));
}
}
}
}

Err(anyhow!("Could not discover device by mDNS"))
}

#[allow(dead_code)] // Only piglet device will offer Iroh properties
#[cfg(feature = "iroh")]
pub async fn get_iroh_by_mdns() -> anyhow::Result<(NodeId, Option<RelayUrl>)> {
let mdns = ServiceDaemon::new().expect("Failed to create daemon");
if let Ok(receiver) = mdns.browse(TCP_MDNS_SERVICE_TYPE) {
while let Ok(event) = receiver.recv_async().await {
if let ServiceEvent::ServiceResolved(info) = event {
let device_properties = info.get_properties();
if let Some(nodeid_str) = device_properties.get_property_val_str("IrohNodeID") {
if let Ok(nodeid) = NodeId::from_str(nodeid_str) {
let relay_url = device_properties
.get_property_val_str("IrohRelayURL")
.map(|s| RelayUrl::from_str(s).unwrap());
return Ok((nodeid, relay_url));
}
}
}
}
}

Err(anyhow!("Could not discover device by mDNS"))
}
103 changes: 103 additions & 0 deletions hw_test/tests/tcp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#![cfg(feature = "tcp")]

use async_std::net::TcpStream;
use pigdef::config::HardwareConfig;
use pigdef::config::HardwareConfigMessage::{Disconnect, GetConfig};
use pigdef::description::HardwareDescription;
use pignet::tcp_host;
use serial_test::serial;
use std::future::Future;
use std::net::IpAddr;
use std::time::Duration;

mod usb;
#[cfg(feature = "usb")]
use usb::get_ip_and_port_by_usb;

mod mdns;
#[cfg(feature = "discovery")]
use mdns::get_ip_and_port_by_mdns;

async fn connect_tcp<F, Fut>(ip: IpAddr, port: u16, test: F)
where
F: FnOnce(HardwareDescription, HardwareConfig, TcpStream) -> Fut,
Fut: Future<Output = ()>,
{
match tcp_host::connect(ip, port).await {
Ok((hw_desc, hw_config, tcp_stream)) => {
if !hw_desc.details.model.contains("Fake") {
panic!("Didn't connect to fake hardware piglet")
} else {
test(hw_desc, hw_config, tcp_stream).await;
}
}
_ => panic!("Could not connect to piglet"),
}
}

#[tokio::test]
#[serial]
async fn can_connect_tcp() {
if let Ok((ip, port)) = get_ip_and_port_by_usb().await {
connect_tcp(ip, port, |_d, _c, _co| async {}).await;
}
}

#[tokio::test]
#[serial]
async fn disconnect_tcp() {
if let Ok((ip, port)) = get_ip_and_port_by_usb().await {
connect_tcp(ip, port, |_d, _c, tcp_stream| async move {
tcp_host::send_config_message(tcp_stream, &Disconnect)
.await
.expect("Could not send Disconnect");
})
.await;
}
}

#[tokio::test]
#[serial]
async fn get_config_tcp() {
if let Ok((ip, port)) = get_ip_and_port_by_usb().await {
connect_tcp(ip, port, |_d, _c, tcp_stream| async move {
tcp_host::send_config_message(tcp_stream, &GetConfig)
.await
.expect("Could not GetConfig");
})
.await;
}
}

#[tokio::test]
#[serial]
async fn reconnect_tcp() {
if let Ok((ip, port)) = get_ip_and_port_by_usb().await {
connect_tcp(ip, port, |_d, _c, tcp_stream| async move {
tcp_host::send_config_message(tcp_stream, &Disconnect)
.await
.expect("Could not send Disconnect");
})
.await;

tokio::time::sleep(Duration::from_secs(1)).await;

// Test we can re-connect after sending a disconnect request
connect_tcp(ip, port, |_d, _c, _tcp_stream| async {}).await;
}
}

#[ignore]
#[cfg(feature = "discovery")]
#[tokio::test]
#[serial]
async fn discover_and_connect_tcp() {
if let Ok((ip, port)) = get_ip_and_port_by_mdns().await {
connect_tcp(ip, port, |_d, _c, _co| async {}).await;
}
}

// piggui tests
// connect using usb from piggui via CLI option
// connect using tcp from piggui via CLI option
// connect using usb from piggui via CLI option
Loading

0 comments on commit ebdc878

Please sign in to comment.