packages feed

ca-patterns-0.2.0.0: test/Data/CA/PatternSpec.hs

{-# LANGUAGE BlockArguments, OverloadedStrings #-}

module Data.CA.PatternSpec (spec) where

import qualified Data.Vector as Vec

import Test.Hspec (Spec, it, describe, shouldBe)

import qualified Data.CA.Pattern as Pat
import TestPatterns

spec :: Spec
spec = do
  describe "Prelude.show" do
    it "shows a pattern's list structure" do
      show glider `shouldBe` ("fromList " ++
        "[[False,True,False],[False,False,True],[True,True,True]]")

  describe "Data.CA.Pattern.lookup" do
    it "returns False for dead cells" do
      Pat.lookup 0 0 glider `shouldBe` False
      Pat.lookup 0 2 glider `shouldBe` False
    it "returns True for live cells" do
      Pat.lookup 2 0 glider `shouldBe` True
      Pat.lookup 2 2 glider `shouldBe` True
    it "returns False when out of bounds" do
      Pat.lookup 4 0 glider `shouldBe` False
      Pat.lookup 0 (-2) glider `shouldBe` False

  describe "Data.CA.Pattern.generate" do
    it "creates diagonal lines" do
      Pat.generate 3 4 (==) `shouldBe` diagonal
    it "creates horizontal stripes" do
      Pat.generate 5 3 (\r _ -> even r) `shouldBe` horizontal

  describe "Data.CA.Pattern.height" do
    it "returns a pattern's height" do
      Pat.height glider `shouldBe` 3
      Pat.height horizontal `shouldBe` 5
      Pat.height empty `shouldBe` 0

  describe "Data.CA.Pattern.width" do
    it "returns a pattern's width" do
      Pat.width glider `shouldBe` 3
      Pat.width horizontal `shouldBe` 3
      Pat.width empty `shouldBe` 0

  describe "Data.CA.Pattern.dimensions" do
    it "returns a pattern's height and width" do
      Pat.dimensions glider `shouldBe` (3, 3)
      Pat.dimensions horizontal `shouldBe` (5, 3)
      Pat.dimensions empty `shouldBe` (0, 0)

  describe "Data.CA.Pattern.valid" do
    it "returns True for rectangular patterns" do
      Pat.valid glider `shouldBe` True
      Pat.valid diagonal `shouldBe` True
      Pat.valid empty `shouldBe` True
    it "returns False for non-rectangular patterns" do
      Pat.valid fromRectList1 `shouldBe` False
      Pat.valid fromRectList2 `shouldBe` False

  describe "Data.CA.Pattern.fromRectList" do
    it "converts lists directly into patterns" do
      Pat.toList fromRectList1 `shouldBe` list1
      Pat.toList fromRectList2 `shouldBe` list2

  describe "Data.CA.Pattern.fromList" do
    it "pads non-rectangular patterns with dead cells" do
      Pat.toList fromList1 `shouldBe` paddedList1
      Pat.toList fromList2 `shouldBe` paddedList2

  describe "Data.CA.Pattern.toList" do
    it "converts patterns into lists" do
      Pat.toList glider `shouldBe`
        [ [ o, O, o ]
        , [ o, o, O ]
        , [ O, O, O ]
        ]

  describe "Data.CA.Pattern.fromRectVector" do
    it "converts vectors directly into patterns" do
      Pat.toVector fromRectVector1 `shouldBe` vector1
      Pat.toVector fromRectVector2 `shouldBe` vector2

  describe "Data.CA.Pattern.fromVector" do
    it "pads non-rectangular patterns with dead cells" do
      Pat.toVector fromVector1 `shouldBe` paddedVector1
      Pat.toVector fromVector2 `shouldBe` paddedVector2

  describe "Data.CA.Pattern.toVector" do
    it "converts patterns into vectors" do
      Pat.toVector glider `shouldBe` Vec.fromList
        [ Vec.fromList [ o, O, o ]
        , Vec.fromList [ o, o, O ]
        , Vec.fromList [ O, O, O ]
        ]

  describe "Data.CA.Pattern.toText" do
    it "converts patterns into text" do
      Pat.toText '.' 'O' glider `shouldBe` gliderStr1
      Pat.toText '_' '*' glider `shouldBe` gliderStr2
      Pat.toText 'v' 'v' empty `shouldBe` ""

  describe "Data.CA.Pattern.toString" do
    it "converts patterns into strings" do
      Pat.toString '.' 'O' glider `shouldBe` gliderStr1
      Pat.toString '_' '*' glider `shouldBe` gliderStr2
      Pat.toString 'v' 'v' empty `shouldBe` ""

  describe "Data.CA.Pattern.trimTop" do
    it "removes rows of dead cells from the top" do
      Pat.trimTop untrimmed `shouldBe` trimmedTop
    it "is idempotent" do
      Pat.trimTop trimmedTop `shouldBe` trimmedTop
    it "does nothing to the empty pattern" do
      Pat.trimTop empty `shouldBe` empty

  describe "Data.CA.Pattern.trimBottom" do
    it "removes rows of dead cells from the bottom" do
      Pat.trimBottom untrimmed `shouldBe` trimmedBottom
    it "is idempotent" do
      Pat.trimBottom trimmedBottom `shouldBe` trimmedBottom
    it "does nothing to the empty pattern" do
      Pat.trimBottom empty `shouldBe` empty

  describe "Data.CA.Pattern.trimLeft" do
    it "removes columns of dead cells from the left" do
      Pat.trimLeft untrimmed `shouldBe` trimmedLeft
    it "is idempotent" do
      Pat.trimLeft trimmedLeft `shouldBe` trimmedLeft
    it "does nothing to the empty pattern" do
      Pat.trimLeft empty `shouldBe` empty

  describe "Data.CA.Pattern.trimRight" do
    it "removes columns of dead cells from the right" do
      Pat.trimRight untrimmed `shouldBe` trimmedRight
    it "is idempotent" do
      Pat.trimRight trimmedRight `shouldBe` trimmedRight
    it "does nothing to the empty pattern" do
      Pat.trimRight empty `shouldBe` empty

  describe "Data.CA.Pattern.trim" do
    it "removes all layers of dead cells" do
      Pat.trim untrimmed `shouldBe` singleton
    it "is idempotent" do
      Pat.trim singleton `shouldBe` singleton
    it "does nothing to the empty pattern" do
      Pat.trim empty `shouldBe` empty

  describe "Data.CA.Pattern.setHeight" do
    it "adds rows of dead cells to the bottom" do
      Pat.setHeight 5 trimmedBottom `shouldBe` untrimmed
    it "removes rows from the bottom" do
      Pat.setHeight 3 untrimmed `shouldBe` trimmedBottom

  describe "Data.CA.Pattern.setWidth" do
    it "adds columns of dead cells to the right" do
      Pat.setWidth 5 trimmedRight `shouldBe` untrimmed
    it "removes columns from the right" do
      Pat.setWidth 3 untrimmed `shouldBe` trimmedRight

  describe "Data.CA.Pattern.setDimensions" do
    it "sets the height and width of a pattern" do
      Pat.setDimensions 4 5 glider `shouldBe` largeGlider
      Pat.setDimensions 2 4 glider `shouldBe` cutGlider
      Pat.setDimensions 2 3 empty `shouldBe` allDead

  describe "Data.CA.Pattern.reflectX" do
    it "reflects a pattern horizontally" do
      Pat.reflectX diagonal `shouldBe` reflectedX
    it "does nothing to the empty pattern" do
      Pat.reflectX empty `shouldBe` empty

  describe "Data.CA.Pattern.reflectY" do
    it "reflects a pattern vertically" do
      Pat.reflectY diagonal `shouldBe` reflectedY
    it "does nothing to the empty pattern" do
      Pat.reflectY empty `shouldBe` empty

  describe "Data.CA.Pattern.rotateL" do
    it "rotates a pattern counterclockwise" do
      Pat.rotateL diagonal `shouldBe` rotatedL
    it "does nothing to the empty pattern" do
      Pat.rotateL empty `shouldBe` empty

  describe "Data.CA.Pattern.rotateR" do
    it "rotates a pattern clockwise" do
      Pat.rotateR diagonal `shouldBe` rotatedR
    it "does nothing to the empty pattern" do
      Pat.rotateR empty `shouldBe` empty

  describe "Data.CA.Pattern.combine" do
    it "combines two patterns" do
      Pat.combine 3 2 glider glider `shouldBe` twoGliders1
      Pat.combine (-3) (-2) glider glider `shouldBe` twoGliders1
      Pat.combine 3 (-2) glider glider `shouldBe` twoGliders2
      Pat.combine (-3) 2 glider glider `shouldBe` twoGliders2