content: {-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
  
  {- |
     Module      : TestSuite
     Description : fgl test suite
     Copyright   : (c) Ivan Lazar Miljenovic
     License     : BSD3
     Maintainer  : Ivan.Miljenovic@gmail.com
  
  
  
   -}
  module Main where
  
  import Data.Graph.Inductive.Arbitrary        ()
  import Data.Graph.Inductive.Graph
  import Data.Graph.Inductive.Graph.Properties
  import Data.Graph.Inductive.Proxy
  import Data.Graph.Inductive.Query.Properties
  
  import Test.Hspec
  import Test.Hspec.QuickCheck
  import Test.QuickCheck       (Arbitrary, Testable)
  
  -- -----------------------------------------------------------------------------
  
  main :: IO ()
  main = hspec $ do
    graphTests "Tree Graphs"         (Proxy :: TreeP)
    graphTests "PatriciaTree Graphs" (Proxy :: PatriciaTreeP)
    queryTests
    describe "Miscellaneous" $
      prop "edge projections" (edge_projections :: LEdge Char -> Bool)
  
  -- -----------------------------------------------------------------------------
  
  -- | Run all available tests on the specified graph type.  Requires
  --   multiple edges and loops to be permissible.
  graphTests :: forall gr. (DynGraph gr, Eq (GraphType gr), Arbitrary (GraphType gr), Show (GraphType gr))
                 => String -> GraphProxy gr -> Spec
  graphTests nm p = describe nm $ do
    describe "Static tests" $ do
      propType  "Eq instance"     valid_Eq
      propType  "node count"      valid_node_count
      propType  "nodeRange"       valid_nodeRange
      proxyProp "mkGraph (nodes)" valid_mkGraph_nodes
      proxyProp "mkGraph (edges)" valid_mkGraph_edges
      proxyProp "mkGraph (order)" valid_mkGraph_order
      propType  "match"           valid_match
      propType  "matchAny"        valid_matchAny
      propType  "newNodes"        newNodes_really_new
      propType  "ufold (nodes)"   ufold_all_nodes
      propType  "gelem"           all_nodes_gelem
      propType  "gelem vs nodes"  gelem_in_nodes
      propType  "hasNeighborAdj"  valid_hasNeighborAdj
      propType  "hasNeighbor"     valid_hasNeighbor
      propType  "hasLEdge"        valid_hasLEdge
  
    describe "Dynamic tests" $ do
      propType  "merging (&)"       valid_merge
      propType  "gmap (id)"         gmap_id
      propType  "insNode"           valid_insNode
      propType  "insNodes"          valid_insNodes
      propType  "insEdge"           valid_insEdge
      propType  "insEdges"          valid_insEdges
      propType  "insEdges (mult)"   valid_insEdges_multiple
      propType  "delNode"           valid_delNode
      propType  "delNodes"          valid_delNodes
      propType  "delEdge"           valid_delEdge
      propType  "delEdges"          valid_delEdges
      propType  "delLEdge"          valid_delLEdge
      propType  "delAllLEdge"       valid_delAllLEdge
      proxyProp "valid_mkGraph"     valid_mkGraph
      propType  "valid_buildGr"     valid_buildGr
      propType  "gfiltermap (id)"   gfiltermap_id
      propType  "nfilter (true)"    nfilter_true
      propType  "labnfilter (true)" labnfilter_true
      propType  "labfilter (true)"  labfilter_true
      propType  "subgraph"          valid_subgraph
  
    where
      proxyProp str = prop str . ($p)
  
      propType :: (Testable pr) => String -> (GraphType gr -> pr) -> Spec
      propType = prop
  
  -- -----------------------------------------------------------------------------
  
  -- | Run all available tests for query functions.  Only tested with
  --   one graph data structure, as it is assumed that any functions
  --   used by a query function are adequately tested with 'graphTests'.
  queryTests :: Spec
  queryTests = describe "Queries" $ do
    propP   "ap"         test_ap
    propP   "bcc"        test_bcc
    describe "BFS" $ do
      propP "bfs"        test_bfs
      propP "level"      test_level
    describe "DFS" $ do
      propP "components"   test_components
      propP "scc"          test_scc
      propP "reachable"    test_reachable
      propP "condensation" test_condensation
    describe "Dominators" $ do
      test_dom
      test_iDom
    describe "GVD" $ do
      test_voronoiSet
      test_nearestNode
      test_nearestDist
      test_nearestPath
    describe "Indep"  . keepSmall $ do
      -- Due to exponential behaviour of indep, limit the maximum size.
      propP  "indepSize" test_indepSize
      propP  "indep"     test_indep
    test_maxFlow2
    test_maxFlow
    propP "msTree"       test_msTree
    describe "SP" $ do
      propP "sp"         test_sp
      propP "sp_Just"    test_sp_Just
      propP "sp_Nothing" test_sp_Nothing
    keepSmall $ do
      -- Just producing the sample graph to compare against is O(|V|^2)
      propP "trc"        test_trc
      propP "tc"         test_tc
      propP "rc"         test_rc
    where
      propP str = prop str . ($p)
  
      p :: PatriciaTreeP
      p = Proxy
  
      keepSmall = modifyMaxSize (min 30)
  