From b685d9025889ad010b5b8c04ecb67204cc8317c5 Mon Sep 17 00:00:00 2001 From: Andrew Werner Date: Thu, 28 Sep 2023 13:15:54 -0400 Subject: [PATCH] integration-test: deflake test_loaded_at The test could fail due to the lack of clock monotonicity. This PR deflakes the test by adding retries. See https://github.com/aya-rs/aya/actions/runs/6340369670/job/17221591723. --- test/integration-test/src/tests/load.rs | 41 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 795f396d7..aef4f8e1c 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -154,22 +154,39 @@ fn unload_xdp() { fn test_loaded_at() { let mut bpf = Bpf::load(crate::TEST).unwrap(); let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); - let t1 = SystemTime::now(); - prog.load().unwrap(); - let t2 = SystemTime::now(); - assert_loaded("pass"); - - let loaded_at = prog.info().unwrap().loaded_at(); - let range = t1..t2; + // The SystemTime timestamps are not monotonic, which can cause this test + // to flake. We don't expect the clock timestamp to continuously jump around, + // so we add some retries. If the test is ever correct, we know that loaded_at + // was reasonable. + let mut failures = Vec::new(); + for _ in 0..5 { + let t1 = SystemTime::now(); + prog.load().unwrap(); + let t2 = SystemTime::now(); + assert_loaded("pass"); + let loaded_at = prog.info().unwrap().loaded_at(); + let range = t1..t2; + prog.unload().unwrap(); + if range.contains(&loaded_at) { + failures.clear(); + break; + } + failures.push(LoadedAtRange(loaded_at, range)); + } assert!( - range.contains(&loaded_at), - "{range:?}.contains({loaded_at:?})" + failures.is_empty(), + "loaded_at was not in range: {failures:?}", ); - - prog.unload().unwrap(); - assert_unloaded("pass"); + + struct LoadedAtRange(SystemTime, std::ops::Range); + impl std::fmt::Debug for LoadedAtRange { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self(loaded_at, range) = self; + write!(f, "{range:?}.contains({loaded_at:?})") + } + } } #[test]