hydra-0.5.0: src/test/haskell/Hydra/Tools/SortingSpec.hs
module Hydra.Tools.SortingSpec where
import qualified Test.Hspec as H
import Hydra.Tools.Sorting
checkSort :: (Ord a, Show a) => [(a, [a])] -> Either [[a]] [a] -> H.Expectation
checkSort adj exp = H.shouldBe (topologicalSort adj) exp
checkSortSCC :: (Ord a, Show a) => [(a, [a])] -> [[a]] -> H.Expectation
checkSortSCC adj exp = H.shouldBe (topologicalSortComponents adj) exp
checkSortDiscreteSet :: H.SpecWith ()
checkSortDiscreteSet = H.describe "Check sorting of discrete sets (no dependencies)" $ do
H.it "Empty set" $
checkSort [] (Right [] :: Either [[Int]] [Int])
H.it "Singleton set" $
checkSort [(1, [])]
(Right [1])
H.it "Discrete set with multiple elements" $
checkSort [(3, []), (1, []), (2, [])]
(Right [3, 2, 1])
checkSortTreesAndDags :: H.SpecWith ()
checkSortTreesAndDags = H.describe "Check sorting of trees and DAGs" $ do
H.it "Linked list" $
checkSort [(3, [1]), (2, [3]), (1, [])]
(Right [1, 3, 2])
H.it "Binary tree" $
checkSort [(3, [1, 4]), (4, [6, 2]), (1, [5]), (2, []), (6, []), (5, [])]
(Right [6, 5, 2, 4, 1, 3])
H.it "Two trees" $
checkSort [(3, [1, 4]), (5, [6, 2]), (2, [7]), (1, []), (4, []), (6, []), (7, [])]
(Right [7, 6, 4, 2, 5, 1, 3])
H.it "Diamond (DAG)" $
checkSort [(1, [3, 4]), (3, [2]), (4, [2]), (2, [5]), (5, [])]
(Right [5, 2, 3, 4, 1])
checkSortCycles :: H.SpecWith ()
checkSortCycles = H.describe "Check that sorting of graphs with cycles fails" $ do
H.it "Two-node cycle" $
checkSort [(1, [2]), (2, [1])]
(Left [[1, 2]])
H.it "Cycle with incoming and outgoing edges" $
checkSort [(1, [3]), (3, [2]), (2, [3, 4]), (4, [5]), (5, [])]
(Left [[2, 3]])
checkSortSCCDiscreteSet :: H.SpecWith ()
checkSortSCCDiscreteSet = H.describe "Check sorting of discrete sets (no dependencies)" $ do
H.it "Empty set" $
checkSortSCC []
([] :: [[Int]])
H.it "Singleton set" $
checkSortSCC [(1, [])]
[[1]]
H.it "Discrete set with multiple elements" $
checkSortSCC [(3, []), (1, []), (2, [])]
[[3],[2],[1]]
checkSortSCCWeaklyConnectedComponents :: H.SpecWith ()
checkSortSCCWeaklyConnectedComponents = H.describe "Check weakly-connected components" $ do
H.describe "Single, two-element component" $ do
H.it "test #1" $
checkSortSCC [(1, [2]), (2, [])]
[[2], [1]]
H.it "test #2" $
checkSortSCC [(2, [1]), (1, [])]
[[1], [2]]
H.it "Multiple-element component" $ do
checkSortSCC [(2, [1, 3]), (1, [3]), (3, [])]
[[3], [1], [2]]
checkSortSCCStronglyConnectedComponents :: H.SpecWith ()
checkSortSCCStronglyConnectedComponents = H.describe "Check strongly-connected components" $ do
H.describe "Cycle of two nodes" $ do
H.it "test #1" $
checkSortSCC [(1, [2]), (2, [1])]
[[1, 2]]
H.it "test #2" $
checkSortSCC [(2, [1]), (1, [2])]
[[1, 2]]
H.describe "Cycle of three nodes, ordered naturally" $ do
H.it "test #1" $
checkSortSCC [(1, [2]), (2, [3]), (3, [1])]
[[1, 2, 3]]
H.it "test #2" $
checkSortSCC [(2, [1]), (3, [2]), (1, [3])]
[[1, 2, 3]]
H.it "Multiple, disconnected cycles, each ordered naturally" $ do
checkSortSCC
([(200, [])] ++ [(100, [])] ++ [(300, [])] ++ [(10, [20]), (20, [10])] ++ [(1, [2]), (2, [3]), (3, [1])])
[[300], [200], [100], [10, 20], [1, 2, 3]]
H.it "Complex cycles" $ do
checkSortSCC [(1, [2, 3]), (2, [3]), (3, [1])]
[[1, 2, 3]]
checkSortSCCMixed :: H.SpecWith ()
checkSortSCCMixed = H.describe "Check graphs which are a mix of weakly- and strongly-connected components" $ do
H.it "Chain of three SCCs" $
checkSortSCC
[(1, [2, 10]), (2, [3]), (3, [1]), (10, [20]), (20, [100, 10]), (100, [])]
[[100], [10, 20], [1, 2, 3]]
H.it "SCCs with dependencies to/from non-SCC nodes" $
checkSortSCC
[(1, [2, 3, 10]), (2, [3]), (3, [1]),
(10, [20, 30]), (20, [30]), (30, []),
(100, [200, 2]), (200, []), (300, [100]),
(1000, []),
(2000, [])]
[[2000], [1000], [200], [30], [20], [10], [1, 2, 3], [100], [300]]
spec :: H.Spec
spec = do
H.describe "Check topological sort (without cycles)" $ do
checkSortDiscreteSet
checkSortTreesAndDags
checkSortCycles
H.describe "Check sorting of strongly connected components" $ do
checkSortSCCDiscreteSet
checkSortSCCWeaklyConnectedComponents
checkSortSCCStronglyConnectedComponents
checkSortSCCMixed