algebraic-graphs-0.8: test/Algebra/Graph/Test/Export.hs
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
-- |
-- Module : Algebra.Graph.Test.Export
-- Copyright : (c) Andrey Mokhov 2016-2025
-- License : MIT (see the file LICENSE)
-- Maintainer : andrey.mokhov@gmail.com
-- Stability : experimental
--
-- Testsuite for "Algebra.Graph.Export" and "Algebra.Graph.Export.Dot".
-----------------------------------------------------------------------------
module Algebra.Graph.Test.Export (
-- * Testsuite
testExport
) where
import Algebra.Graph (Graph, circuit)
import Algebra.Graph.Export hiding (unlines)
import Algebra.Graph.Export.Dot (Attribute (..))
import Algebra.Graph.Test
import qualified Algebra.Graph.Export as E
import qualified Algebra.Graph.Export.Dot as ED
testExport :: IO ()
testExport = do
putStrLn "\n============ Export.Eq ============"
test "mempty /= literal \"\"" $
mempty /= (literal "" :: Doc String)
putStrLn "\n============ Export.Ord ============"
test "mempty < literal \"\"" $
mempty < (literal "" :: Doc String)
putStrLn "\n============ Export.isEmpty ============"
test "isEmpty mempty == True" $
isEmpty mempty == True
test "isEmpty (literal \"\") == False" $
isEmpty (literal "" :: Doc String) == False
test "isEmpty x == (x == mempty)" $ \(x :: Doc String) ->
isEmpty x == (x == mempty)
putStrLn "\n============ Export.literal ============"
test "literal \"Hello, \" <> literal \"World!\" == literal \"Hello, World!\"" $
literal "Hello, " <> literal "World!" == literal ("Hello, World!" :: String)
test "literal \"I am just a string literal\" == \"I am just a string literal\"" $
literal "I am just a string literal" == ("I am just a string literal" :: Doc String)
test "render . literal == id" $ \(x :: String) ->
(render . literal) x == x
putStrLn "\n============ Export.render ============"
test "render (literal \"al\" <> literal \"ga\") == \"alga\"" $
render (literal "al" <> literal "ga") == ("alga" :: String)
test "render mempty == mempty" $
render mempty == (mempty :: Doc String)
putStrLn "\n============ Export.<+> ============"
test "x <+> mempty == x" $ \(x :: Doc String) ->
x <+> mempty == x
test "mempty <+> x == x" $ \(x :: Doc String) ->
mempty <+> x == x
test "x <+> (y <+> z) == (x <+> y) <+> z" $ \(x :: Doc String) y z ->
x <+> (y <+> z) == (x <+> y) <+> z
test "\"name\" <+> \"surname\" == \"name surname\"" $
"name" <+> "surname" == ("name surname" :: Doc String)
putStrLn "\n============ Export.brackets ============"
test "brackets \"i\" == \"[i]\"" $
brackets "i" == ("[i]" :: Doc String)
test "brackets mempty == \"[]\"" $
brackets mempty == ("[]" :: Doc String)
putStrLn "\n============ Export.doubleQuotes ============"
test "doubleQuotes \"/path/with spaces\" == \"\\\"/path/with spaces\\\"\"" $
doubleQuotes "/path/with spaces" == ("\"/path/with spaces\"" :: Doc String)
test "doubleQuotes (doubleQuotes mempty) == \"\\\"\\\"\\\"\\\"\"" $
doubleQuotes (doubleQuotes mempty) == ("\"\"\"\"" :: Doc String)
putStrLn "\n============ Export.indent ============"
test "indent 0 == id" $ \(x :: String) ->
indent 0 (literal x) == literal x
test "indent 1 mempty == \" \"" $
indent 1 mempty == (" " :: Doc String)
putStrLn "\n============ Export.unlines ============"
test "unlines [] == mempty" $
E.unlines [] == (mempty :: Doc String)
test "unlines [mempty] == \"\\n\"" $
E.unlines [mempty] == ("\n" :: Doc String)
test "unlines [\"title\", \"subtitle\"] == \"title\\nsubtitle\\n\"" $
E.unlines ["title", "subtitle" ] == ("title\nsubtitle\n" :: Doc String)
putStrLn "\n============ Export.export ============"
let vDoc x = literal (show x) <> "\n"
eDoc x y = literal (show x) <> " -> " <> literal (show y) <> "\n"
test "render $ export vDoc eDoc (1 + 2 * (3 + 4) :: Graph Int)" $
(render (export vDoc eDoc (1 + 2 * (3 + 4) :: Graph Int)) :: String) ==
unlines [ "1"
, "2"
, "3"
, "4"
, "2 -> 3"
, "2 -> 4" ]
putStrLn "\n============ Export.Dot.export ============"
let style = ED.Style
{ ED.graphName = "Example"
, ED.preamble = [" // This is an example", ""]
, ED.graphAttributes = ["label" := "Example", "labelloc" := "top"]
, ED.defaultVertexAttributes = ["shape" := "circle"]
, ED.defaultEdgeAttributes = mempty
, ED.vertexName = \x -> "v" ++ show x
, ED.vertexAttributes = \x -> ["color" := "blue" | odd x ]
, ED.edgeAttributes = \x y -> ["style" := "dashed" | odd (x * y)]
, ED.attributeQuoting = ED.DoubleQuotes }
test "export style (1 * 2 + 3 * 4 * 5 :: Graph Int)" $
(ED.export style (1 * 2 + 3 * 4 * 5 :: Graph Int) :: String) ==
unlines [ "digraph Example"
, "{"
, " // This is an example"
, ""
, " graph [label=\"Example\" labelloc=\"top\"]"
, " node [shape=\"circle\"]"
, " \"v1\" [color=\"blue\"]"
, " \"v2\""
, " \"v3\" [color=\"blue\"]"
, " \"v4\""
, " \"v5\" [color=\"blue\"]"
, " \"v1\" -> \"v2\""
, " \"v3\" -> \"v4\""
, " \"v3\" -> \"v5\" [style=\"dashed\"]"
, " \"v4\" -> \"v5\""
, "}" ]
putStrLn "\n=========== Export.Dot.attributeQuoting ============"
let style' = style { ED.attributeQuoting = ED.NoQuotes }
test "export style' (1 * 2 + 3 * 4 * 5 :: Graph Int)" $
(ED.export style' (1 * 2 + 3 * 4 * 5 :: Graph Int) :: String) ==
unlines [ "digraph Example"
, "{"
, " // This is an example"
, ""
, " graph [label=Example labelloc=top]"
, " node [shape=circle]"
, " \"v1\" [color=blue]"
, " \"v2\""
, " \"v3\" [color=blue]"
, " \"v4\""
, " \"v5\" [color=blue]"
, " \"v1\" -> \"v2\""
, " \"v3\" -> \"v4\""
, " \"v3\" -> \"v5\" [style=dashed]"
, " \"v4\" -> \"v5\""
, "}" ]
putStrLn "\n============ Export.Dot.exportAsIs ============"
test "exportAsIs (circuit [\"a\", \"b\", \"c\"] :: Graph String)" $
(ED.exportAsIs (circuit ["a", "b", "c"] :: Graph String) :: String) ==
unlines [ "digraph "
, "{"
, " \"a\""
, " \"b\""
, " \"c\""
, " \"a\" -> \"b\""
, " \"b\" -> \"c\""
, " \"c\" -> \"a\""
, "}" ]
putStrLn "\n============ Export.Dot.exportViaShow ============"
test "exportViaShow (1 + 2 * (3 + 4) :: Graph Int)" $
(ED.exportViaShow (1 + 2 * (3 + 4) :: Graph Int) :: String) ==
unlines [ "digraph "
, "{"
, " \"1\""
, " \"2\""
, " \"3\""
, " \"4\""
, " \"2\" -> \"3\""
, " \"2\" -> \"4\""
, "}" ]