mirror of
https://github.com/rust-windowing/winit.git
synced 2026-08-30 13:20:06 -04:00
feat: Add Docker support to integration tests
This allows the tests to be run inside of a Docker container with linux with X11 inside. Signed-off-by: John Nunley <dev@notgull.net>
This commit is contained in:
@@ -14,4 +14,4 @@ async-process = "2.1.0"
|
||||
inventory = "0.3.15"
|
||||
owo-colors = "4.0.0"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = "1.0.114"
|
||||
serde_json.workspace = true
|
||||
|
||||
@@ -10,10 +10,11 @@ use std::env;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::mem;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::panic;
|
||||
|
||||
const GUI_TEST_CURRENT_TEST_NAME: &str = "GUI_TEST_CURRENT_TEST_NAME";
|
||||
const GUI_TEST_SUBPROCESS_LIMIT: &str = "GUI_TEST_SUBPROCESS_LIMIT";
|
||||
const DEFAULT_LIMIT: usize = 4;
|
||||
const DEFAULT_LIMIT: usize = 1;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use inventory as __inventory;
|
||||
@@ -23,7 +24,7 @@ pub use inventory as __inventory;
|
||||
macro_rules! main {
|
||||
($handler:expr) => {
|
||||
fn main() {
|
||||
$crate::__entry($handler)
|
||||
$crate::__entry(|| $handler)
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -136,8 +137,22 @@ impl Harness {
|
||||
|
||||
/// Run a closure as a test.
|
||||
pub fn with_test<T>(&mut self, name: impl Into<String>, f: impl FnOnce() -> T) -> T {
|
||||
let _test = self.test(name.into());
|
||||
f()
|
||||
let test = self.test(name.into());
|
||||
match panic::catch_unwind(panic::AssertUnwindSafe(f)) {
|
||||
Ok(x) => x,
|
||||
|
||||
Err(err) => {
|
||||
if let Some(panic) = err.downcast_ref::<&'static str>() {
|
||||
test.fail(panic.to_string());
|
||||
} else if let Some(panic) = err.downcast_ref::<String>() {
|
||||
test.fail(panic.clone());
|
||||
} else {
|
||||
test.fail("unintelligible error".to_string());
|
||||
}
|
||||
|
||||
panic::resume_unwind(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Begin a test group.
|
||||
@@ -238,6 +253,14 @@ impl Testing<'_> {
|
||||
// Send the "skipped" event.
|
||||
self.harness.take().unwrap().end_test(TestResult::Skipped);
|
||||
}
|
||||
|
||||
/// Fail this test.
|
||||
fn fail(mut self, panic: String) {
|
||||
self.harness
|
||||
.take()
|
||||
.unwrap()
|
||||
.end_test(TestResult::Failed(panic));
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Testing<'_> {
|
||||
@@ -351,7 +374,7 @@ pub enum TestResult {
|
||||
|
||||
/// Entry point of the test.
|
||||
#[doc(hidden)]
|
||||
pub fn __entry<H: TestHandler + Send + 'static>(handler: H) {
|
||||
pub fn __entry<H: TestHandler + Send + 'static>(handler: impl FnOnce() -> H) {
|
||||
// Look for the test name environment variable.
|
||||
if let Some(test_name) = env::var(GUI_TEST_CURRENT_TEST_NAME)
|
||||
.ok()
|
||||
@@ -364,10 +387,13 @@ pub fn __entry<H: TestHandler + Send + 'static>(handler: H) {
|
||||
.unwrap_or_else(|| panic!("unable to find test '{test_name}'"));
|
||||
|
||||
// Create a harness.
|
||||
let mut harness = Harness::new(test_to_run.name, handler);
|
||||
let mut harness = Harness::new(test_to_run.name, handler());
|
||||
|
||||
// Run the test.
|
||||
(test_to_run.func)(&mut harness);
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(move || {
|
||||
(test_to_run.func)(&mut harness)
|
||||
}))
|
||||
.ok();
|
||||
} else {
|
||||
// Run a subprocess for every test.
|
||||
let limit = env::var(GUI_TEST_SUBPROCESS_LIMIT)
|
||||
|
||||
@@ -8,7 +8,8 @@ use crate::{TestEvent, TestHandler};
|
||||
use std::io::Write;
|
||||
|
||||
/// A wrapper around a writer that sends data down a stream.
|
||||
pub struct WriteHandler<W> {
|
||||
#[derive(Debug)]
|
||||
pub struct WriteHandler<W: Write> {
|
||||
/// The inner writer.
|
||||
writer: W,
|
||||
}
|
||||
@@ -30,3 +31,9 @@ impl<W: Write> TestHandler for WriteHandler<W> {
|
||||
self.writer.write_all(&payload).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Drop for WriteHandler<W> {
|
||||
fn drop(&mut self) {
|
||||
self.writer.flush().ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ impl UserHandler {
|
||||
|
||||
// If this is the end, dump other events.
|
||||
while ender {
|
||||
ender = false;
|
||||
assert!(self.current_start.take().is_some());
|
||||
|
||||
// Pick one set.
|
||||
@@ -78,11 +79,12 @@ impl UserHandler {
|
||||
self.current_start = Some(test_name);
|
||||
|
||||
// Dump events and look for a conclusion.
|
||||
ender = false;
|
||||
self.dump_events(entries.into_iter().inspect(|ty| {
|
||||
ender |= matches!(ty, TestEventType::Complete { .. });
|
||||
}));
|
||||
}
|
||||
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,5 +162,19 @@ impl TestHandler for UserHandler {
|
||||
impl Drop for UserHandler {
|
||||
fn drop(&mut self) {
|
||||
assert!(self.cache.is_empty());
|
||||
|
||||
// Write the final bit to the stdout.
|
||||
let mut stdout = io::stdout().lock();
|
||||
|
||||
if !self.failures.is_empty() {
|
||||
writeln!(stdout, "Test Failures:").ok();
|
||||
|
||||
for (test_name, panic) in &self.failures {
|
||||
writeln!(stdout, " {}", test_name).ok();
|
||||
writeln!(stdout, "-------------").ok();
|
||||
writeln!(stdout, "{}", panic).ok();
|
||||
writeln!(stdout, "-------------").ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user