packages feed

cursor-gen-0.0.0.0: test/Cursor/Simple/Tree/TestUtils.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Cursor.Simple.Tree.TestUtils where

import Data.Tree

import Control.Monad (unless)

import Test.Hspec

import Test.QuickCheck
import Test.Validity

import Cursor.Simple.Tree hiding (TreeCursor)
import qualified Cursor.Simple.Tree as STC (TreeCursor)
import Cursor.Simple.Tree.Gen ()
import Cursor.Tree (CTree(..), closedForest)

testMovement :: (forall a. STC.TreeCursor a -> STC.TreeCursor a) -> Spec
testMovement func = do
    it "produces valids on valids" $ producesValidsOnValids $ func @Double
    it "is a movement" $ isMovement func

testMovementM ::
       (forall a. STC.TreeCursor a -> Maybe (STC.TreeCursor a)) -> Spec
testMovementM func = do
    it "produces valids on valids" $ producesValidsOnValids $ func @Double
    it "is a movement" $ isMovementM func

isMovementM ::
       (forall a. STC.TreeCursor a -> Maybe (STC.TreeCursor a)) -> Property
isMovementM func =
    forAllValid @(STC.TreeCursor Int) $ \lec ->
        case func lec of
            Nothing -> pure () -- Fine
            Just lec' ->
                let ne = rebuildCTree $ rebuildTreeCursor lec
                    ne' = rebuildCTree $ rebuildTreeCursor lec'
                in unless (ne == ne') $
                   expectationFailure $
                   unlines
                       [ "Cursor before:\n" ++ drawTreeCursor lec
                       , "Tree before:  \n" ++ drawTree (fmap show ne)
                       , "Cursor after: \n" ++ drawTreeCursor lec'
                       , "Tree after:   \n" ++ drawTree (fmap show ne')
                       ]

isMovement :: (forall a. STC.TreeCursor a -> STC.TreeCursor a) -> Property
isMovement func =
    forAllValid $ \lec ->
        rebuildTreeCursor (lec :: STC.TreeCursor Int) `shouldBe`
        rebuildTreeCursor (func lec)

treeShouldBe ::
       (Show a, Eq a) => STC.TreeCursor a -> STC.TreeCursor a -> Expectation
treeShouldBe actual expected =
    unless (actual == expected) $
    expectationFailure $
    unlines
        [ "The following should have been equal."
        , "actual:"
        , drawTreeCursor actual
        , "expected:"
        , drawTreeCursor expected
        ]

instance CanFail SwapResult where
    hasFailed (Swapped _) = False
    hasFailed _ = True
    resultIfSucceeded (Swapped a) = Just a
    resultIfSucceeded _ = Nothing

node :: a -> [CTree a] -> CTree a
node a ts = CNode a $ closedForest $ map rebuildCTree ts