From 514c56edc7d9144651be64ad8c429cb4fd68aa62 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 4 Apr 2021 12:53:08 +0100 Subject: [PATCH] wdt, at: Use vpid mapping everywhere, rather than hardcoded Races can affect the vpid layout! This fixes flakiness in the tests. Signed-off-by: Ian Jackson --- src/prelude.rs | 2 +- wdriver/wdriver.rs | 51 +++++++++++++++++++++++++++++++++++++------ wdriver/wdt-hand.rs | 6 ++--- wdriver/wdt-simple.rs | 14 ++++++------ 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/prelude.rs b/src/prelude.rs index 933de8a1..5766b453 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -95,7 +95,7 @@ pub use strum::{IntoEnumIterator, IntoStaticStr}; pub use thiserror::Error; pub use url::Url; pub use vecdeque_stableix::Deque as StableIndexVecDeque; -pub use void::{Void, ResultVoidExt, ResultVoidErrExt}; +pub use void::{unreachable, Void, ResultVoidExt, ResultVoidErrExt}; use nix::time::ClockId; pub const CLOCK_REALTIME : ClockId = ClockId::CLOCK_REALTIME ; diff --git a/wdriver/wdriver.rs b/wdriver/wdriver.rs index 34c09cf8..0ad43dc2 100644 --- a/wdriver/wdriver.rs +++ b/wdriver/wdriver.rs @@ -59,6 +59,12 @@ pub struct Window { pub instance: InstanceName, } +#[derive(Debug,Clone,Eq,PartialEq,Ord,PartialOrd,Hash)] +pub struct Vpid(pub String); +impl Display for Vpid { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.0) } +} + impl Window { pub fn table(&self) -> String { self.instance.to_string() } } @@ -204,11 +210,42 @@ impl Debug for WindowGuard<'_> { impl<'g> WindowGuard<'g> { #[throws(AE)] - pub fn find_piece(&'g self, pieceid: &'g str) -> PieceElement<'g> { - let id = format!("use{}", pieceid); - let elem = self.su.driver.find_element(By::Id(&id))?; + pub fn piece_vpid(&'g self, some_pieceid: &'_ str) -> Vpid { + if some_pieceid.contains('.') { return Vpid(some_pieceid.to_owned()) } + let (l, r) = some_pieceid.split_once('v').unwrap(); + let s = format!(r#"{{ "idx":{}, "version":{} }}"#, l,r); // cheesy! + let kd: slotmap::KeyData = serde_json::from_str(&s).unwrap(); + let piece: PieceId = kd.into(); + let resp = self.su.mgmt_conn().cmd(&MC::AlterGame { + game: TABLE.parse().unwrap(), + how: MgmtGameUpdateMode::Online, + insns: vec![ MgmtGameInstruction::PieceIdLookupFwd { + piece, + player: self.w.player, + } ], + })?; + let vpid = if_chain!{ + if let MgmtResponse::AlterGame { error: None, responses } = &resp; + if let [MgmtGameResponse::VisiblePieceId(vpid)] = responses.as_slice(); + then { vpid } + else { unreachable(Err::(&resp).unwrap()) } + }; + Vpid(vpid.unwrap().to_string()) + } + + #[throws(AE)] + pub fn vpidelem(&'g self, prefix: &'_ str, some_pieceid: &'_ str) -> String { + prefix.to_string() + &self.piece_vpid(some_pieceid)?.0 + } + + #[throws(AE)] + pub fn find_piece(&'g self, pieceid: &'_ str) -> PieceElement<'g> { + let pieceid = self.piece_vpid(pieceid)?; + let elemid = format!("use{}", &pieceid); + let elem = self.su.driver.find_element(By::Id(&elemid))?; PieceElement { - pieceid, elem, + elem, + pieceid: pieceid.clone(), w: self, } } @@ -230,7 +267,7 @@ impl<'g> WindowGuard<'g> { let held = self.execute_script(&format!(r##" let pc = pieces['{}']; return pc.held; - "##, &pc))?; + "##, &self.piece_vpid(pc)?))?; let held = held.value(); dbg!(held); match held { @@ -330,7 +367,7 @@ pub type WebCoord = i32; pub type WebPos = (WebCoord, WebCoord); pub struct PieceElement<'g> { - pieceid: &'g str, + pieceid: Vpid, w: &'g WindowGuard<'g>, elem: t4::WebElement<'g>, } @@ -613,7 +650,7 @@ impl<'a> t4::action_chain::ActionChain<'a> { } #[throws(AE)] - fn move_pc<'g>(self, w: &'g WindowGuard, pc: &str) -> Self { + fn move_pc<'g>(self, w: &'g WindowGuard, pc: &'_ str) -> Self { (||{ let p = w.find_piece(pc).context("find")?; let pos = p.posw().context("get pos")?; diff --git a/wdriver/wdt-hand.rs b/wdriver/wdt-hand.rs index f3120965..008e5aa6 100644 --- a/wdriver/wdt-hand.rs +++ b/wdriver/wdt-hand.rs @@ -12,8 +12,8 @@ struct Ctx { deref_to_field!{Ctx, Setup, su} usual_wanted_tests!{Ctx, su} -const HAND: &str = "6.1"; -const PAWN: &str = "7.1"; +const HAND: &str = "6v1"; +const PAWN: &str = "7v1"; const ALICE: &str = "1#1"; #[throws(AE)] @@ -39,7 +39,7 @@ impl Ctx { w.synch()?; let dasharray = player.map(player_dasharray).transpose()?; - let euse = w.find_element(By::Id(&format!("piece{}", pc)))?; + let euse = w.find_element(By::Id(&w.vpidelem("piece", pc)?))?; let epath = euse.find_element(By::Tag("path"))?; let attr = epath.get_attribute("stroke-dasharray")?; diff --git a/wdriver/wdt-simple.rs b/wdriver/wdt-simple.rs index 35e37c5a..8c8f487c 100644 --- a/wdriver/wdt-simple.rs +++ b/wdriver/wdt-simple.rs @@ -21,8 +21,8 @@ impl Ctx { let alice_p1g = { let mut w = su.w(&self.alice)?; w.synch()?; - let p1 = w.find_piece("1.1")?; - let p2 = w.find_piece("2.1")?; + let p1 = w.find_piece("1v1")?; + let p2 = w.find_piece("2v1")?; let p1g_old = p1.posg()?; let (p2x,p2y) = p2.posw()?; @@ -44,19 +44,19 @@ impl Ctx { { let mut w = su.w(&self.bob)?; w.synch()?; - let p1 = w.find_piece("1.1")?; + let p1 = w.find_piece("1v1")?; assert_eq!(p1.posg()?, alice_p1g); } } #[throws(AE)] fn rotate(&mut self) -> &'static str { - let pc = "4.1"; + let pc = "4v1"; let su = &mut self.su; let chk = |w: &WindowGuard<'_>| { let transform = format!("rotate(-90)"); - let pd = w.find_element(By::Id(&format!("piece{}",pc)))?; + let pd = w.find_element(By::Id(&w.vpidelem("piece",pc)?))?; assert_eq!(pd.get_attribute("transform")?, Some(transform)); Ok::<_,AE>(()) }; @@ -160,11 +160,11 @@ impl Ctx { #[throws(AE)] fn conflict(&mut self) { - let pc = "1.1"; + let pc = "1v1"; let su = &mut self.su; { - let pc = "4.1"; + let pc = "4v1"; let w = su.w(&self.alice)?; w.action_chain() .move_pc(&w, pc)? -- 2.30.2