Skip to content

Commit

Permalink
Add execution tests (#61) for simulator only (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
boozook authored Sep 16, 2023
1 parent aec2787 commit 24b9e3e
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 18 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,15 @@ jobs:
cargo test -p=playdate-build --all-features
cargo test -p=playdate-tool --all-features
- name: Install Sim Deps
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
sudo apt update
sudo apt -y install libwebkit2gtk-4.0-dev
- name: Test
run: |
cargo test -p=cargo-playdate -- --nocapture --test-threads=1
cargo test -p=cargo-playdate -- --nocapture
rm -rf ./target/tmp
use-tool:
Expand Down
34 changes: 23 additions & 11 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions cargo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ features = [
target = "2.0.0"
rand = "0.8"

[target.'cfg(unix)'.dev-dependencies]
nix = { version = "0.27", features = ["signal"] }


[features]
default = []
Expand Down
22 changes: 17 additions & 5 deletions cargo/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ use anyhow::Result;

pub use playdate::compile::dylib_suffix_for_host;

#[path = "./shared.rs"]
mod shared;
pub use shared::*;


pub struct Tool<'p>(Cow<'p, Path>);

Expand All @@ -35,14 +39,16 @@ impl Tool<'_> {
pub fn execute<I, S>(pwd: &Path, args: I) -> Result<Output>
where I: IntoIterator<Item = S>,
S: AsRef<OsStr> {
let output = Command::new(Self::path()).current_dir(pwd)
.args(args)
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()?;
let output = Self::command().current_dir(pwd).args(args).output()?;
Ok(output)
}

pub fn command() -> Command {
let mut cmd = Command::new(Self::path());
cmd.stdout(Stdio::inherit()).stderr(Stdio::inherit());
cmd
}


#[track_caller]
pub fn build<S>(pwd: &Path, args: impl IntoIterator<Item = S>) -> Result<Output>
Expand Down Expand Up @@ -98,6 +104,12 @@ pub fn workspace() -> Result<&'static Path> {
Ok(root)
}

pub fn metadata_workspace() -> Result<&'static Path> {
let root = Path::new("tests/crates/metadata");
assert!(root.exists());
Ok(root)
}


pub fn to_dyn_lib_name<S: Display>(crate_name: S) -> String {
let prefix = if cfg!(windows) { "" } else { "lib" };
Expand Down
2 changes: 1 addition & 1 deletion cargo/tests/crates/metadata/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
resolver = "2"
members = ["sub"]


[package]
name = "test-workspace-main-crate"
version = "0.1.0"
Expand All @@ -12,6 +11,7 @@ publish = false

[package.metadata.playdate]
bundle-id = "test.workspace.main.crate"
description = "test"

[package.metadata.playdate.assets]
"main/" = "Cargo.toml"
Expand Down
7 changes: 7 additions & 0 deletions cargo/tests/crates/simple/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ extern crate alloc;
extern crate pd;
use pd::ffi::*;

#[path = "../../shared.rs"]
mod shared;

pd::ll_symbols!();

Expand Down Expand Up @@ -40,6 +42,11 @@ pub extern "C" fn eventHandlerShim(api: *const PlaydateAPI, event: PDSystemEvent


unsafe extern "C" fn on_update(_: *mut c_void) -> i32 {
// This is used for execution tests:
if let Some(s) = shared::CARGO_PLAYDATE_TEST_VALUE {
println!("{}{s}", shared::CARGO_PLAYDATE_TEST_VALUE_PREFIX);
}

check_crank_docked();
1
}
Expand Down
5 changes: 5 additions & 0 deletions cargo/tests/run.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod common;

pub mod run {
pub mod simple;
}
119 changes: 119 additions & 0 deletions cargo/tests/run/simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use std::ffi::OsStr;
use std::ffi::OsString;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::path::Path;
use std::process::Stdio;
use std::time::Duration;
use std::time::Instant;
use anyhow::Result;

use crate::common::*;


fn run(crate_name: &str, crate_path: &Path, args: impl IntoIterator<Item = impl Into<OsString>>) -> Result<()> {
println!("crate: {}", crate_path.display());

let value = test_value();
let target_dir = target_dir().join(crate_name);
let target_dir_arg = format!("--target-dir={}", target_dir.display());
let args = [OsString::from("run")].into_iter()
.chain(args.into_iter().map(Into::into))
.chain([OsString::from(target_dir_arg)]);
if !target_dir.exists() {
std::fs::create_dir_all(&target_dir)?;
}

let mut cmd = Tool::command();
cmd.args(args);
cmd.current_dir(crate_path);
cmd.env(CARGO_PLAYDATE_TEST_VALUE_ENV, &value);


let expected_value = format!("{CARGO_PLAYDATE_TEST_VALUE_PREFIX}{value}");

let log_path = target_dir.join("stdout.log");
let file = File::create(&log_path)?;
cmd.stdout(Stdio::from(file));
let mut handle = cmd.spawn()?;

println!("cmd: {:?}", cmd);

let start = Instant::now();
let limit = Duration::from_secs(60 * 1);


while start.elapsed() < limit {
std::thread::sleep(Duration::from_millis(100))
}

println!("timeout reached");

let pid = handle.id();
#[cfg(unix)]
{
use nix::unistd::Pid;
use nix::sys::signal::{self, Signal};
signal::kill(
Pid::from_raw(pid.try_into().expect("invalid PID")),
Signal::SIGTERM, // mb. send SIGKILL?
).ok();
}
handle.kill()
.expect(&format!("Unable to kill child process (pid={pid}"));

println!("Child process killed");

// take a time to flush:
std::thread::sleep(Duration::from_secs(4));

println!("Reading log");

let file = File::open(log_path)?;
let found = BufReader::new(file).lines()
.map_while(|r| r.ok())
.find(|line| line.trim().contains(&expected_value));
println!("Found expected value: {:?}", found);

assert!(found.is_some(), "Test value didn't found.");

Ok(())
}


fn test_value() -> String {
use rand::RngCore;
let mut values = [0u8; 8];
rand::thread_rng().fill_bytes(&mut values);
let rand = values.into_iter().fold(String::new(), |mut acc, n| {
acc.push_str(&n.to_string());
acc
});
rand
}


#[test]
#[cfg_attr(not(target_os = "macos"), ignore = "Simulator as headless work on mac only")]
fn run_metadata_workspace_root_dev() -> Result<()> {
let crate_name = "test-workspace-main-crate";
let args = ["--simulator", "-p", crate_name, "--lib"].into_iter()
.map(OsStr::new);
let ws = metadata_workspace()?;
run(crate_name, &ws, args)?;

Ok(())
}

#[test]
#[cfg_attr(not(target_os = "macos"), ignore = "Simulator as headless work on mac only")]
fn run_metadata_workspace_root_release() -> Result<()> {
let crate_name = "test-workspace-main-crate";
let args = ["--simulator", "-p", crate_name, "--lib", "--release"].into_iter()
.map(OsStr::new);
let ws = metadata_workspace()?;
run(crate_name, &ws, args)?;

Ok(())
}
6 changes: 6 additions & 0 deletions cargo/tests/shared.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//! Shared consts between tests and test-crates
#![allow(dead_code)]

pub const CARGO_PLAYDATE_TEST_VALUE_ENV: &'static str = "CARGO_PLAYDATE_TEST_VALUE";
pub const CARGO_PLAYDATE_TEST_VALUE: Option<&'static str> = option_env!("CARGO_PLAYDATE_TEST_VALUE");
pub const CARGO_PLAYDATE_TEST_VALUE_PREFIX: &'static str = "TEST";

0 comments on commit 24b9e3e

Please sign in to comment.