apply-merge-0.1.0.0: test/Test/Data/DoublyLinkedList/STRef.hs
-- SPDX-FileCopyrightText: Copyright Preetham Gujjula
-- SPDX-License-Identifier: BSD-3-Clause
module Test.Data.DoublyLinkedList.STRef (tests) where
import Control.Monad (void)
import Control.Monad.ST (runST)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Maybe (MaybeT (..), runMaybeT)
import Data.DoublyLinkedList.STRef
( cons,
delete,
empty,
fromList,
head,
last,
next,
null,
toList,
value,
)
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.ExpectedFailure (ignoreTest)
import Test.Tasty.HUnit (Assertion, assertBool, assertFailure, testCase, (@?=))
import Prelude hiding (head, last, null)
tests :: TestTree
tests =
testGroup
"Data.DoublyLinkedList.STRef"
[ constructionTests,
traversalTests,
queryTests,
insertionTests,
deletionTests,
listConversionTests,
integrationTests
]
unimplemented :: Assertion
unimplemented = assertFailure "unimplemented"
-- Construction
constructionTests :: TestTree
constructionTests =
testGroup
"Construction"
[ emptyTests,
fromListTests
]
emptyTests :: TestTree
emptyTests = testCase "empty" (pure ())
fromListTests :: TestTree
fromListTests = testCase "fromList" (pure ())
-- Traversal
traversalTests :: TestTree
traversalTests =
testGroup "Traversal" [headTests, lastTests, nextTests, prevTests]
headTests :: TestTree
headTests =
testGroup
"head"
[ testCase "head of empty list" $ do
-- Construct empty list using empty
let firstNodeValue1 :: Maybe Int
firstNodeValue1 = runST $ do
list <- empty
firstNode <- head list
pure (value <$> firstNode)
firstNodeValue1 @?= Nothing
-- Construct empty list using fromList
let firstNodeValue2 :: Maybe Int
firstNodeValue2 = runST $ do
list <- fromList []
firstNode <- head list
pure (value <$> firstNode)
firstNodeValue2 @?= Nothing,
testCase "head of non-empty lists" $ do
let firstNodeValue1 :: Maybe Int
firstNodeValue1 = runST $ do
list <- fromList [1]
firstNode <- head list
pure (value <$> firstNode)
firstNodeValue1 @?= Just 1
let firstNodeValue2 :: Maybe Int
firstNodeValue2 = runST $ do
list <- fromList [2, 1]
firstNode <- head list
pure (value <$> firstNode)
firstNodeValue2 @?= Just 2
let firstNodeValue3 :: Maybe Int
firstNodeValue3 = runST $ do
list <- fromList [3, 2, 1]
firstNode <- head list
pure (value <$> firstNode)
firstNodeValue3 @?= Just 3
]
lastTests :: TestTree
lastTests =
testGroup
"last"
[ testCase "last of empty list" $ do
-- Construct empty list using empty
let lastNodeValue1 :: Maybe Int
lastNodeValue1 = runST $ do
list <- empty
lastNode <- last list
pure (value <$> lastNode)
lastNodeValue1 @?= Nothing
-- Construct empty list using fromList
let lastNodeValue2 :: Maybe Int
lastNodeValue2 = runST $ do
list <- fromList []
lastNode <- last list
pure (value <$> lastNode)
lastNodeValue2 @?= Nothing,
testCase "last of non-empty lists" $ do
let lastNodeValue1 :: Maybe Int
lastNodeValue1 = runST $ do
list <- fromList [1]
lastNode <- last list
pure (value <$> lastNode)
lastNodeValue1 @?= Just 1
let lastNodeValue2 :: Maybe Int
lastNodeValue2 = runST $ do
list <- fromList [1, 2]
lastNode <- last list
pure (value <$> lastNode)
lastNodeValue2 @?= Just 2
let lastNodeValue3 :: Maybe Int
lastNodeValue3 = runST $ do
list <- fromList [1, 2, 3]
lastNode <- last list
pure (value <$> lastNode)
lastNodeValue3 @?= Just 3
]
nextTests :: TestTree
nextTests =
ignoreTest $
testGroup
"next"
[ testCase "next on empty list" unimplemented,
testCase "next on [1]" unimplemented,
testCase "next on [3, 2, 1]" unimplemented,
testCase "next on [1, 1, 1, 1, 1]" unimplemented
]
prevTests :: TestTree
prevTests =
ignoreTest $
testGroup
"prev"
[ testCase "prev on empty list" unimplemented,
testCase "prev on [1]" unimplemented,
testCase "prev on [3, 2, 1]" unimplemented,
testCase "prev on [1, 1, 1, 1, 1]" unimplemented
]
-- Query
queryTests :: TestTree
queryTests = testGroup "Query" [nullTests, valueTests]
nullTests :: TestTree
nullTests =
testGroup
"null"
[ testCase "null of empty list" $ do
-- Construct empty list using empty
let isNull1 :: Bool
isNull1 = runST (empty >>= null)
assertBool "empty list is null" isNull1
-- Construct empty list using fromList
let isNull2 :: Bool
isNull2 = runST (fromList [] >>= null)
assertBool "empty list is null" isNull2,
testCase "null of non-empty list" $ do
let isNull1 :: Bool
isNull1 = runST (fromList [1 :: Int] >>= null)
assertBool "non-empty list is not null" (not isNull1)
let isNull2 :: Bool
isNull2 = runST (fromList [1 :: Int, 2] >>= null)
assertBool "non-empty list is not null" (not isNull2)
let isNull3 :: Bool
isNull3 = runST (fromList [1 :: Int, 2, 3] >>= null)
assertBool "non-empty list is not null" (not isNull3)
]
valueTests :: TestTree
valueTests = testCase "value" (pure ())
-- Insertion
insertionTests :: TestTree
insertionTests =
testGroup
"Insertion"
[ consTests,
snocTests,
insertBeforeTests,
insertAfterTests,
insertBeforeAfterTests
]
consTests :: TestTree
consTests =
testGroup
"cons"
[ testCase "Create [1] with cons" $
let xs :: [Int]
xs = runST $ do
ys <- empty
void (cons ys 1)
toList ys
in xs @?= [1],
testCase "Create [1, 2] with cons" $
let xs :: [Int]
xs = runST $ do
ys <- empty
void (cons ys 2)
void (cons ys 1)
toList ys
in xs @?= [1, 2],
testCase "Create [1, 2, 3] with cons" $
let xs :: [Int]
xs = runST $ do
ys <- empty
void (cons ys 3)
void (cons ys 2)
void (cons ys 1)
toList ys
in xs @?= [1, 2, 3]
]
snocTests :: TestTree
snocTests =
testGroup
"snoc"
[ ignoreTest $ testCase "Create [1] with snoc" unimplemented,
ignoreTest $ testCase "Create [1, 2] with snoc" unimplemented,
ignoreTest $ testCase "Create [1, 2, 3] with snoc" unimplemented
]
insertBeforeTests :: TestTree
insertBeforeTests =
testGroup
"insertBefore"
[ ignoreTest $ testCase "Create [1, 0] with insertBefore" unimplemented,
ignoreTest $ testCase "Create [1, 2, 0] with insertBefore" unimplemented,
ignoreTest $
testCase "Create [1, 2, 3, 0] with insertBefore" unimplemented
]
insertAfterTests :: TestTree
insertAfterTests =
testGroup
"insertAfter"
[ ignoreTest $ testCase "Create [0, 1] with insertAfter" unimplemented,
ignoreTest $ testCase "Create [0, 1, 2] with insertAfter" unimplemented,
ignoreTest $ testCase "Create [0, 1, 2, 3] with insertAfter" unimplemented
]
insertBeforeAfterTests :: TestTree
insertBeforeAfterTests =
testGroup
"insertBefore and insertAfter"
[ ignoreTest $
testCase
"Create [-1, 0, 1] with insertBefore and insertAfter"
unimplemented,
ignoreTest $
testCase
"Create [-2, -1, 0, 1, 2] with insertBefore and insertAfter"
unimplemented,
ignoreTest $
testCase
"Create [-3, -2, -1, 0, 1, 2, 3] with insertBefore and insertAfter"
unimplemented
]
-- Deletion
deletionTests :: TestTree
deletionTests = testGroup "Deletion" [deleteTests]
deleteTests :: TestTree
deleteTests =
testGroup
"delete"
[ testCase "Turn [-2, -1, 0, 1, 2] -> [-2, -1, 1, 2] using delete" $ do
let xs :: Maybe [Int]
xs = runST $ runMaybeT $ do
dllist <- lift $ fromList [-2 .. 2]
node1 <- MaybeT $ head dllist
node2 <- MaybeT $ next node1
node3 <- MaybeT $ next node2
lift (delete node3)
lift (toList dllist)
in xs @?= Just [-2, -1, 1, 2],
testCase "Turn [1, 2, 3, 4, 5, 6] -> [2, 4, 6] using delete" $
let xs :: Maybe [Int]
xs = runST $ runMaybeT $ do
dlist <- lift $ fromList [1 .. 6]
node1 <- MaybeT (head dlist)
lift (delete node1)
node2 <- MaybeT (next node1)
node3 <- MaybeT (next node2)
node4 <- MaybeT (next node3)
lift (delete node3)
node5 <- MaybeT (next node4)
lift (delete node5)
lift (toList dlist)
in xs @?= Just [2, 4, 6]
]
-- List conversion
listConversionTests :: TestTree
listConversionTests = testGroup "List conversion" [toListTests]
toListTests :: TestTree
toListTests = testCase "toList" (pure ())
-- Integration
integrationTests :: TestTree
integrationTests = ignoreTest $ testCase "Integration" unimplemented