goatee-0.3.0: tests/Game/Goatee/Lib/TypesTest.hs
-- This file is part of Goatee.
--
-- Copyright 2014 Bryan Gardiner
--
-- Goatee is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- Goatee is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with Goatee. If not, see <http://www.gnu.org/licenses/>.
module Game.Goatee.Lib.TypesTest (tests) where
import Data.List (sort)
import Game.Goatee.Lib.Types
import Game.Goatee.Test.Common
import Test.HUnit ((~:), (@=?), (@?=), Assertion, Test (TestList))
tests = "Game.Goatee.Lib.Types" ~: TestList
[ expandCoordListTests
, buildCoordListTests
, starLinesTests
, isStarPointTests
, handicapStonesTests
, simpleTextTests
, cnotTests
, lineTests
]
expandCoordListTests = "expandCoordList" ~: TestList
[ "works with an empty CoordList" ~: do
[] @=? expandCoordList (coords [])
[] @=? expandCoordList (coords' [] [])
, "works for single points" ~: do
[(1,2)] @=? expandCoordList (coord1 (1,2))
[(3,4), (1,2)] @=? expandCoordList (coords [(3,4), (1,2)])
let ten = [(i,i) | i <- [1..10]]
ten @=? expandCoordList (coords ten)
-- TODO Test that a 1x1 rectangle is rejected.
, "works for a nx1 rect" ~:
[(5,2), (5,3), (5,4)] @=? expandCoordList (coords' [] [((5,2), (5,4))])
, "works for a 1xn rect" ~:
[(1,0), (1,1), (1,2), (1,3)] @=? expandCoordList (coords' [] [((1,0), (1,3))])
, "works for an mxn rect" ~:
[(m,n) | m <- [2..5], n <- [3..7]] @=?
expandCoordList (coords' [] [((2,3), (5,7))])
-- TODO Test that x0 > x1 || y0 > y1 is rejected.
, "works with multiple rects" ~:
[(0,0), (0,1), (0,2), (3,4), (4,4), (5,4)] @=?
expandCoordList (coords' [] [((0,0), (0,2)), ((3,4), (5,4))])
, "concatenates single points and rects" ~:
[(1,1), (0,0), (2,2), (2,3), (2,4)] @=?
expandCoordList (coords' [(1,1), (0,0)] [((2,2), (2,4))])
]
buildCoordListTests = "buildCoordList" ~: TestList
[ "handles the empty case" ~: assertSinglesAndRects [] [] []
, "handles one single" ~:
assertSinglesAndRects [(0,1)] [] [(0,1)]
, "handles multiple singles" ~:
assertSinglesAndRects [(0,0), (1,1)] [] [(0,0), (1,1)]
, "handles a small rect (1x2)" ~:
assertSinglesAndRects [] [((0,1), (0,2))] [(0,1), (0,2)]
, "handles a small square (2x2)" ~:
assertSinglesAndRects [] [((1,1), (2,2))] [(x,y) | x <- [1..2], y <- [1..2]]
, "handles a larger rect" ~:
assertSinglesAndRects [] [((0,0), (2,4))] [(x,y) | x <- [0..2], y <- [0..4]]
, "handles two rects" ~:
assertSinglesAndRects [] [((0,1), (1,2)), ((3,0), (4,1))]
[(0,1), (1,1), (0,2), (1,2), (3,0), (4,0), (3,1), (4,1)]
, "handles rects and singles together" ~:
assertSinglesAndRects [(0,0)] [((1,1), (2,2))]
[(0,0), (1,1), (1,2), (2,1), (2,2)]
, "handles five points together" ~: do
assertCoords [(1,0), (0,1), (1,1), (0,2), (1,2)]
assertCoords [(0,0), (1,0), (0,1), (1,1), (0,2)]
assertCoords [(0,0), (1,0), (2,0), (0,1), (1,1)]
assertCoords [(1,0), (2,0), (0,1), (1,1), (2,1)]
, "handles a more complex case" ~:
assertCoords [(3,0), (4,0),
(3,1), (4,1),
(0,2), (1,2), (2,2), (3,2), (4,2),
(0,3), (1,3),
(0,4), (1,4), (3,4), (4,4)]
, "handles a diagonal pattern" ~:
assertCoords [(0,0), (2,0), (4,0),
(1,1), (3,1), (5,1),
(2,2)]
]
where -- | Asserts that the given grid of booleans parses to a 'CoordList'
-- that has the expected single points (not necessarily in the same
-- order), as well as the expected rectangles (not necessarily in the
-- same order).
assertSinglesAndRects :: [Coord] -> [(Coord, Coord)] -> [Coord] -> Assertion
assertSinglesAndRects expectedSingles expectedRects input =
coords' expectedSingles expectedRects @=? buildCoordList input
-- | Asserts that the set of points returned from applying
-- 'buildCoordList' to the given grid of booleans is equal to
-- the given set of points.
assertCoords :: [Coord] -> Assertion
assertCoords input = sort input @=? sort (expandCoordList $ buildCoordList input)
starLinesTests = "starLines" ~: TestList
[ "knows 9x9 boards" ~: Just [2, 4, 6] @=? starLines 9 9
, "knows 13x13 boards" ~: Just [3, 6, 9] @=? starLines 13 13
, "knows 19x19 boards" ~: Just [3, 9, 15] @=? starLines 19 19
, "doesn't know 13x19" ~: Nothing @=? starLines 13 19
, "doesn't know 10x10" ~: Nothing @=? starLines 10 10
]
isStarPointTests = "isStarPoint" ~: TestList
[ "only knows correct star points on a 9x9 board" ~:
let expected = [(x, y) | x <- [2, 4, 6], y <- [2, 4, 6]]
actual = actualStarPoints 9 9
in expected @=?* actual
, "only knows correct star points on a 13x13 board" ~:
let expected = [(x, y) | x <- [3, 6, 9], y <- [3, 6, 9]]
actual = actualStarPoints 13 13
in expected @=?* actual
, "only knows correct star points on a 19x19 board" ~:
let expected = [(x, y) | x <- [3, 9, 15], y <- [3, 9, 15]]
actual = actualStarPoints 19 19
in expected @=?* actual
, "knows no star poinst on a 5x1 board" ~:
[] @=? actualStarPoints 5 1
, "knows no star points on a 15x15 board" ~:
[] @=? actualStarPoints 15 15
, "knows no star points on a 20x20 board" ~:
[] @=? actualStarPoints 20 20
]
where actualStarPoints width height =
map fst $ filter snd
[((x, y), isStarPoint width height x y) | x <- [0..width-1], y <- [0..height-1]]
handicapStonesTests = "handicapStones" ~: TestList
[ "returns nothing for invalid handicaps" ~: do
Nothing @=? handicapStones 9 9 (-1)
Nothing @=? handicapStones 9 9 10
Nothing @=? handicapStones 4 4 25
, "9x9 0 handicap" ~: assertHandicap 9 9 0 $ Just []
, "9x9 1 handicap" ~: assertHandicap 9 9 1 $ Just []
, "9x9 2 handicap" ~: assertHandicap 9 9 2 $ Just [(2,6), (6,2)]
, "9x9 3 handicap" ~: assertHandicap 9 9 3 $ Just [(2,6), (6,2), (6,6)]
, "9x9 4 handicap" ~: assertHandicap 9 9 4 $ Just [(2,2), (2,6), (6,2), (6,6)]
, "9x9 5 handicap" ~: assertHandicap 9 9 5 $ Just [(2,2), (2,6), (4,4), (6,2), (6,6)]
, "9x9 6 handicap" ~: assertHandicap 9 9 6 $
Just [(2,2), (2,4), (2,6), (6,2), (6,4), (6,6)]
, "9x9 7 handicap" ~: assertHandicap 9 9 7 $
Just [(2,2), (2,4), (2,6), (4,4), (6,2), (6,4), (6,6)]
, "9x9 8 handicap" ~: assertHandicap 9 9 8 $
Just [(2,2), (2,4), (2,6), (4,2), (4,6), (6,2), (6,4), (6,6)]
, "9x9 9 handicap" ~: assertHandicap 9 9 9 $
Just [(2,2), (2,4), (2,6), (4,2), (4,4), (4,6), (6,2), (6,4), (6,6)]
, "13x13 0 handicap" ~: assertHandicap 13 13 0 $ Just []
, "13x13 1 handicap" ~: assertHandicap 13 13 1 $ Just []
, "13x13 2 handicap" ~: assertHandicap 13 13 2 $ Just [(3,9), (9,3)]
, "13x13 3 handicap" ~: assertHandicap 13 13 3 $ Just [(3,9), (9,3), (9,9)]
, "13x13 4 handicap" ~: assertHandicap 13 13 4 $ Just [(3,3), (3,9), (9,3), (9,9)]
, "13x13 5 handicap" ~: assertHandicap 13 13 5 $ Just [(3,3), (3,9), (6,6), (9,3), (9,9)]
, "13x13 6 handicap" ~: assertHandicap 13 13 6 $
Just [(3,3), (3,6), (3,9), (9,3), (9,6), (9,9)]
, "13x13 7 handicap" ~: assertHandicap 13 13 7 $
Just [(3,3), (3,6), (3,9), (6,6), (9,3), (9,6), (9,9)]
, "13x13 8 handicap" ~: assertHandicap 13 13 8 $
Just [(3,3), (3,6), (3,9), (6,3), (6,9), (9,3), (9,6), (9,9)]
, "13x13 9 handicap" ~: assertHandicap 13 13 9 $
Just [(3,3), (3,6), (3,9), (6,3), (6,6), (6,9), (9,3), (9,6), (9,9)]
, "19x19 0 handicap" ~: assertHandicap 19 19 0 $ Just []
, "19x19 1 handicap" ~: assertHandicap 19 19 1 $ Just []
, "19x19 2 handicap" ~: assertHandicap 19 19 2 $ Just [(3,15), (15,3)]
, "19x19 3 handicap" ~: assertHandicap 19 19 3 $ Just [(3,15), (15,3), (15,15)]
, "19x19 4 handicap" ~: assertHandicap 19 19 4 $ Just [(3,3), (3,15), (15,3), (15,15)]
, "19x19 5 handicap" ~: assertHandicap 19 19 5 $ Just [(3,3), (3,15), (9,9), (15,3), (15,15)]
, "19x19 6 handicap" ~: assertHandicap 19 19 6 $
Just [(3,3), (3,9), (3,15), (15,3), (15,9), (15,15)]
, "19x19 7 handicap" ~: assertHandicap 19 19 7 $
Just [(3,3), (3,9), (3,15), (9,9), (15,3), (15,9), (15,15)]
, "19x19 8 handicap" ~: assertHandicap 19 19 8 $
Just [(3,3), (3,9), (3,15), (9,3), (9,15), (15,3), (15,9), (15,15)]
, "19x19 9 handicap" ~: assertHandicap 19 19 9 $
Just [(3,3), (3,9), (3,15), (9,3), (9,9), (9,15), (15,3), (15,9), (15,15)]
]
where assertHandicap width height handicap maybeExpectedStones =
case (handicapStones width height handicap, maybeExpectedStones) of
(Just actualStones, Just expectedStones) -> actualStones @?=* expectedStones
(actual, _) -> actual @?= maybeExpectedStones
simpleTextTests = "SimpleText" ~: TestList
[ "accepts the empty string" ~:
"" @=? fromSimpleText (toSimpleText "")
, "passes through strings without newlines" ~: do
"Hello." @=? fromSimpleText (toSimpleText "Hello.")
"Bad for B." @=? fromSimpleText (toSimpleText "Bad for B.")
"[4k?]" @=? fromSimpleText (toSimpleText "[4k?]")
printableAsciiChars @=? fromSimpleText (toSimpleText printableAsciiChars)
, "converts newlines to spaces" ~: do
" " @=? fromSimpleText (toSimpleText "\n")
"Hello, world." @=? fromSimpleText (toSimpleText "Hello,\nworld.")
"Hello, world." @=? fromSimpleText (toSimpleText "Hello, \n world.")
" Hello, world. " @=? fromSimpleText (toSimpleText "\nHello, world.\n")
]
cnotTests = "cnot" ~: TestList
[ "changes Black to White" ~: White @=? cnot Black
, "changes White to Black" ~: Black @=? cnot White
]
lineTests = "Line" ~: TestList
[ "Eq instance" ~: TestList
[ "Line a b == Line a b" ~: Line (1,2) (3,4) @=? Line (1,2) (3,4)
, "Line a b == Line b a" ~: Line (1,2) (3,4) @=? Line (3,4) (1,2)
, "Line a b /= Line c b" ~: do Line (1,2) (3,4) @/=? Line (0,2) (3,4)
Line (1,2) (3,4) @/=? Line (1,0) (3,4)
, "Line a b /= Line a c" ~: do Line (1,2) (3,4) @/=? Line (1,2) (0,4)
Line (1,2) (3,4) @/=? Line (1,2) (3,0)
]
, "lineToPair" ~:
((10,2), (5,7)) @=? lineToPair (Line (10,2) (5,7))
]