// Copyright (C) 2021 Leandro Lisboa Penz // This file is subject to the terms and conditions defined in // file 'LICENSE', which is part of this source code package. use sqrid; use sqrid::postrait::PosT; use anyhow::{anyhow, Result}; use std::collections::HashSet; use std::convert::TryFrom; type Pos = sqrid::Pos<6, 7>; type Pos2 = sqrid::Pos<2, 2>; type Pos5 = sqrid::Pos<5, 5>; #[test] fn test_basic() -> Result<()> { let q1 = Pos::try_from((2_u16, 3_u16))?; println!("{:?} {}", q1, q1); assert_eq!((2_u16, 3_u16), q1.into()); let q2 = Pos::try_from(&(3_u16, 4_u16))?; assert_eq!((3_u16, 4_u16), (&q2).into()); let q3 = Pos::try_from(&(5_u16, 6_u16)); assert_eq!((5_u16, 6_u16), q3.unwrap().into()); const Q4: Pos = Pos::new_unwrap(5, 4); assert_eq!((5_u16, 4_u16), Q4.into()); let q5 = Pos::new_static::<4, 3>(); assert_eq!((4_u16, 3_u16), q5.into()); Ok(()) } #[test] fn test_usize() -> Result<()> { assert_eq!(Pos::FIRST, Pos::try_from(0_usize)?); assert_eq!(usize::from(Pos::LAST), Pos::SIZE - 1); Ok(()) } #[test] fn test_tryfrom_pos() -> Result<()> { assert_eq!(Pos::tryfrom_pos(Pos2::FIRST)?, Pos::try_from(0_usize)?); assert_eq!(Pos::tryfrom_pos(Pos5::FIRST)?, Pos::try_from(0_usize)?); assert_eq!(Pos::tryfrom_pos(Pos2::LAST)?, Pos::tryfrom_tuple((1, 1))?); assert_eq!(Pos::tryfrom_pos(Pos5::LAST)?, Pos::tryfrom_tuple((4, 4))?); assert!(Pos2::tryfrom_pos(Pos::LAST).is_err()); Ok(()) } #[test] fn test_out_of_bounds() -> Result<()> { let q1result = Pos::try_from((6_u16, 3_u16)); assert!(q1result.is_err()); println!("{:?}", q1result); println!("{}", q1result.unwrap_err()); let q2result = Pos::try_from((0_u16, 7_u16)); assert!(q2result.is_err()); assert_eq!(q2result.unwrap_err(), sqrid::Error::OutOfBounds); let q3result = Pos::try_from(Pos::SIZE); assert_eq!(q3result.unwrap_err(), sqrid::Error::OutOfBounds); Ok(()) } #[test] fn test_iter() -> Result<()> { let iter = Pos::iter(); println!("{:?}", iter); for pos in iter { println!("{}", pos); } let v = Pos::iter().collect::>(); assert_eq!(v.len(), iter.size_hint().0); assert_eq!(v.len(), iter.size_hint().1.unwrap()); Ok(()) } #[test] fn test_iter_in_xy() -> Result<()> { let ally = Pos::iter_in_x(0) .ok_or(anyhow!("iter_in_x error"))? .collect::>(); assert_eq!(ally.len(), Pos::HEIGHT as usize); for x in 0..Pos::WIDTH { let posx1 = Pos::iter_in_x(x) .ok_or(anyhow!("iter_in_x error"))? .collect::>(); for (y, pos) in (0..Pos::HEIGHT).zip(posx1) { assert_eq!(pos.tuple(), (x, y)); } } let allx = Pos::iter_in_y(0) .ok_or(anyhow!("iter_in_y error"))? .collect::>(); assert_eq!(allx.len(), Pos::WIDTH as usize); for y in 0..Pos::HEIGHT { let posy1 = Pos::iter_in_y(y) .ok_or(anyhow!("iter_in_y error"))? .collect::>(); for (x, pos) in (0..Pos::WIDTH).zip(posy1) { assert_eq!(pos.tuple(), (x, y)); } } Ok(()) } #[test] fn test_max() -> Result<()> { type Pos = sqrid::Pos<0x7fff, 0x7fff>; assert_eq!(Pos::SIZE, 0x7fff * 0x7fff); assert_eq!(usize::from(&Pos::LAST), 0x7fff * 0x7fff - 1); assert_eq!(Pos::new(0x7ffe, 0x7ffe)?, Pos::LAST); assert_eq!(Pos::try_from((0x7ffe, 0x7ffe)), Ok(Pos::LAST)); assert_eq!(Pos::try_from(usize::from(Pos::LAST)), Ok(Pos::LAST)); let prevlast = Pos::new_static::<0x7ffd, 0x7ffe>(); assert_eq!(prevlast.next(), Some(Pos::LAST)); Ok(()) } #[test] fn test_corner_side() -> Result<()> { let v = vec![ Pos::TOP_LEFT, Pos::TOP_RIGHT, Pos::BOTTOM_LEFT, Pos::BOTTOM_RIGHT, ]; assert_eq!(v.len(), 4); for pos in &v { assert!(pos.is_corner()); } let v2 = Pos::iter() .filter(|pos| pos.is_corner()) .collect::>(); assert_eq!(v, v2); let v3 = Pos::iter().filter(|pos| pos.is_side()).collect::>(); assert_eq!(v3.len(), 22); Ok(()) } #[test] fn test_manhattan() -> Result<()> { assert_eq!(Pos2::manhattan(&Pos2::TOP_LEFT, &Pos2::BOTTOM_RIGHT), 2); assert_eq!(Pos2::manhattan(&Pos2::BOTTOM_RIGHT, &Pos2::TOP_LEFT), 2); Ok(()) } #[test] fn test_inside() -> Result<()> { for pos in Pos::iter() { assert!(pos.inside(&Pos::TOP_LEFT, &Pos::BOTTOM_RIGHT)); assert!(pos.inside(&pos, &pos)); } assert!(!Pos::BOTTOM_RIGHT.inside(&Pos::TOP_LEFT, &Pos::CENTER)); Ok(()) } #[test] fn test_flips() -> Result<()> { assert_eq!(Pos::TOP_LEFT.flip_v(), Pos::BOTTOM_LEFT); assert_eq!(Pos::TOP_RIGHT.flip_v(), Pos::BOTTOM_RIGHT); assert_eq!(Pos::TOP_LEFT.flip_h(), Pos::TOP_RIGHT); assert_eq!(Pos::BOTTOM_LEFT.flip_h(), Pos::BOTTOM_RIGHT); assert_eq!( Pos::new_static::<2, 3>().flip_h(), Pos::new_static::<3, 3>() ); assert_eq!( Pos::new_static::<2, 3>().flip_v(), Pos::new_static::<2, 3>() ); for pos in Pos::iter() { assert_eq!(pos.flip_h().flip_h(), pos); assert_eq!(pos.flip_v().flip_v(), pos); assert_eq!(pos.flip_v().is_corner(), pos.is_corner()); assert_eq!(pos.flip_h().is_corner(), pos.is_corner()); assert_eq!(pos.flip_v().is_side(), pos.is_side()); assert_eq!(pos.flip_h().is_side(), pos.is_side()); } Ok(()) } #[test] fn test_rotate_cw() -> Result<()> { assert_eq!(Pos5::TOP_LEFT.rotate_cw(), Pos5::TOP_RIGHT); assert_eq!(Pos5::TOP_RIGHT.rotate_cw(), Pos5::BOTTOM_RIGHT); assert_eq!(Pos5::BOTTOM_RIGHT.rotate_cw(), Pos5::BOTTOM_LEFT); assert_eq!(Pos5::BOTTOM_LEFT.rotate_cw(), Pos5::TOP_LEFT); for pos in Pos5::iter() { assert_eq!(pos.rotate_cw().rotate_cw().rotate_cw().rotate_cw(), pos); assert_eq!(pos.rotate_cw().is_corner(), pos.is_corner()); assert_eq!(pos.rotate_cw().is_corner(), pos.is_corner()); assert_eq!(pos.rotate_cw().rotate_cw(), pos.rotate_cc().rotate_cc()); } Ok(()) } #[test] fn test_rotate_cc() -> Result<()> { assert_eq!(Pos5::TOP_LEFT.rotate_cc(), Pos5::BOTTOM_LEFT); assert_eq!(Pos5::BOTTOM_LEFT.rotate_cc(), Pos5::BOTTOM_RIGHT); assert_eq!(Pos5::BOTTOM_RIGHT.rotate_cc(), Pos5::TOP_RIGHT); assert_eq!(Pos5::TOP_RIGHT.rotate_cc(), Pos5::TOP_LEFT); for pos in Pos5::iter() { assert_eq!(pos.rotate_cc().rotate_cc().rotate_cc().rotate_cc(), pos); assert_eq!(pos.rotate_cc().is_side(), pos.is_side()); assert_eq!(pos.rotate_cc().is_side(), pos.is_side()); assert_eq!(pos.rotate_cw().rotate_cw(), pos.rotate_cc().rotate_cc()); } Ok(()) } #[test] fn test_iter_vertical() -> Result<()> { let pos = Pos2::iter_vertical().collect::>(); assert_eq!( pos, vec![ Pos2::new(0, 0)?, Pos2::new(0, 1)?, Pos2::new(1, 0)?, Pos2::new(1, 1)?, ] ); Ok(()) } #[test] fn test_iter_back() -> Result<()> { let rev = Pos::iter() .collect::>() .into_iter() .rev() .collect::>(); assert_eq!(Pos::iter().rev().collect::>(), rev); let fullset = Pos2::iter().collect::>(); // Check that we get fullset for all combinations of next and // next_back: for vertical in [false, true] { for mask in 0..15 { let mut set = HashSet::new(); let mut iter = if vertical { Pos2::iter_vertical() } else { Pos2::iter_horizontal() }; for i in 0..Pos2::SIZE { if ((1 << i) & mask) > 0 { set.insert(iter.next().unwrap()); } else { set.insert(iter.next_back().unwrap()); } } assert_eq!(iter.next(), None); assert_eq!(fullset, set); } } Ok(()) } #[test] fn test_iter_range() -> Result<()> { assert_eq!( Pos::iter_range(Pos::TOP_LEFT, Pos::BOTTOM_RIGHT).collect::>(), Pos::iter().collect::>() ); let tl = Pos::try_from((1, 1))?; let br = Pos::try_from((2, 2))?; let range = Pos::iter_range(tl, br).collect::>(); assert_eq!(range.len(), 4); assert_eq!( range, vec![ Pos::try_from((1, 1))?, Pos::try_from((2, 1))?, Pos::try_from((1, 2))?, Pos::try_from((2, 2))?, ] ); Ok(()) } #[test] fn test_tlbr() -> Result<()> { let (tl, br) = Pos::tlbr_of(Pos::iter())?; assert_eq!(Pos::TOP_LEFT, tl); assert_eq!(Pos::BOTTOM_RIGHT, br); let tr = Pos::try_from((4_u16, 3_u16))?; let bl = Pos::try_from((1_u16, 5_u16))?; let v = vec![ tr, Pos::try_from((4_u16, 4_u16))?, Pos::try_from((1_u16, 4_u16))?, Pos::try_from((3_u16, 4_u16))?, Pos::try_from((2_u16, 4_u16))?, bl, ]; let (tl, br) = Pos::tlbr_of(v.into_iter())?; assert_eq!((1_u16, 3_u16), tl.into()); assert_eq!((4_u16, 5_u16), br.into()); Ok(()) }