Roman Gonzalez avatar Roman Gonzalez committed ce82525

Add QuickCheck test, use Hspec for tests (reusing old tests)

Comments (0)

Files changed (5)

--- Initial hedn.cabal generated by cabal init.  For further documentation, 
+-- Initial hedn.cabal generated by cabal init.  For further documentation,
 -- see http://haskell.org/cabal/users-guide/
 
 name:                hedn
   exposed-modules:     Data.EDN, Data.EDN.Types, Data.EDN.Parser, Data.EDN.Encode, Data.EDN.Types.Class
   other-modules:       Data.Parser
   hs-source-dirs:      src/
-  build-depends:       base ==4.*, attoparsec, text, bytestring, containers, vector, stringsearch, mtl, deepseq
+  build-depends:       base ==4.*, attoparsec, text, bytestring, containers, vector, stringsearch, mtl, deepseq, old-locale, time
 
   if flag(developer)
     ghc-options: -Werror -fhpc
 
   ghc-options: -O2 -Wall -fno-warn-unused-do-bind
 
-
 Test-Suite tests
   type:              exitcode-stdio-1.0
   main-is:           Main.hs
   hs-source-dirs:    tests/
-  build-depends:     base, hedn, HUnit, bytestring, text, containers, vector
+  build-depends:     base, hedn, bytestring, text, containers, vector, template-haskell, time,
+                     QuickCheck >= 2.5.1, hspec == 1.5.*, HUnit >= 1.2.5
   ghc-options:       -Wall
 
   if flag(developer)

tests/Data/EDN/Test/QuickCheck.hs

+{-# LANGUAGE TemplateHaskell #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Data.EDN.Test.QuickCheck where
+
+import           Data.EDN.Test.QuickCheck.TH
+import           Data.Time                   (UTCTime)
+
+import qualified Data.Time.Calendar          as Calendar
+import           Data.Time.Clock             (UTCTime (..), UniversalTime (..),
+                                              secondsToDiffTime)
+import           Data.Time.LocalTime         (localTimeToUT1, localTimeToUTC,
+                                              ut1ToLocalTime, utc,
+                                              utcToLocalTime)
+
+import qualified Test.QuickCheck             as QC
+
+-- * UTCTime Arbitrary instance ------------------------------------------------
+
+fromGregorian :: Integer -> Int -> Int -> Int -> Int -> Int -> UTCTime
+fromGregorian year month day hours minutes seconds =
+    UTCTime day' (secondsToDiffTime . fromIntegral $ seconds')
+  where
+    day'     = Calendar.fromGregorian year month day
+    seconds' = 3600 * hours + 60 * minutes + seconds
+
+fromUniversalTime :: UniversalTime -> UTCTime
+fromUniversalTime = localTimeToUTC utc . ut1ToLocalTime 0
+
+toUniversalTime :: UTCTime -> UniversalTime
+toUniversalTime = localTimeToUT1 0 . utcToLocalTime utc
+
+fromGregorian' :: Integer -> Int -> Int -> UTCTime
+fromGregorian' y m d = fromGregorian y m d 0 0 0
+
+startOfTime :: UTCTime
+startOfTime = fromGregorian' 1970 1 1
+
+fromMJD :: Rational -> UTCTime
+fromMJD = fromUniversalTime . ModJulianDate
+
+fromMJD' :: Float -> UTCTime
+fromMJD' = fromMJD . realToFrac
+
+startOfTimeMJD :: Rational
+startOfTimeMJD = toMJD startOfTime
+
+toMJD :: UTCTime -> Rational
+toMJD = getModJulianDate . toUniversalTime
+
+instance QC.Arbitrary UTCTime where
+    -- coarbitrary = undefined
+    arbitrary = do
+      offset <- QC.choose (0, 20000) :: QC.Gen Float
+      return . fromMJD' $ offset + fromRational startOfTimeMJD
+
+--------------------------------------------------------------------------------
+
+type MUTCTime = Maybe UTCTime
+type Tuple  = (Int, Int)
+type Triple = (Int, String, UTCTime)
+type Tuple4 = (Int, String, [Maybe UTCTime], [Maybe Bool])
+type Tuple5 = (Int, [String], [Maybe UTCTime], [Maybe Bool], (Bool, Bool))
+
+$(mkSerializeSpecs [
+                   -- ''Char    -- encode/decode are not isomorphic with Char
+                   --  ''Double -- encode/decode are not isomorphic with Double
+                   -- ''String
+                     ''UTCTime
+                   , ''MUTCTime
+                   -- , ''Tuple
+                   -- , ''Triple
+                   -- , ''Tuple4
+                   -- , ''Tuple5
+                   ])

tests/Data/EDN/Test/QuickCheck/TH.hs

+{-# LANGUAGE TemplateHaskell #-}
+module Data.EDN.Test.QuickCheck.TH where
+
+import           Control.Applicative   ((<$>), (<*>))
+import           Language.Haskell.TH
+import           Test.Hspec            (Spec, describe)
+import           Test.Hspec.QuickCheck (prop)
+
+
+
+import qualified Data.EDN              as E
+import qualified Test.QuickCheck       as QC
+
+--------------------------------------------------------------------------------
+
+serializeProperty :: (QC.Arbitrary a, Eq a, E.ToEDN a, E.FromEDN a) => a -> Bool
+serializeProperty object = do
+  case decoded of
+    Just result -> result == object
+    Nothing -> False
+  where
+      encoded = E.encode object
+      decoded = E.decode encoded
+
+getTestPropertyName :: Name -> Name
+getTestPropertyName qualTypeName =
+    mkName $ "test" ++ (nameBase qualTypeName) ++ "Serialization"
+
+mkEDNSerializeSpecGroup :: [Name] -> Q [Dec]
+mkEDNSerializeSpecGroup names = do
+    let fnName = mkName "ednSerializationProperties"
+    specType <- [t| Spec |]
+    describeFn <- [| describe |]
+    return $ [ SigD fnName specType
+             , ValD (VarP fnName)
+                    (NormalB (AppE (AppE describeFn
+                                        (LitE (StringL "EDN.Serialization")))
+                                   (DoE (map (NoBindS . VarE . getTestPropertyName)
+                                             names)))) []]
+
+mkSerializeSpec :: Name -> Q [Dec]
+mkSerializeSpec qualTypeName = do
+    let typeName = nameBase qualTypeName
+        fnName = getTestPropertyName qualTypeName
+    propFn <- [| prop |]
+    serializePropertyFn <- [| serializeProperty |]
+    boolType <- [t| Bool |]
+    specType <- [t| Spec |]
+    return [ SigD fnName specType
+           , ValD (VarP fnName)
+                    (NormalB (AppE
+                      (AppE propFn
+                        (LitE (StringL $ typeName ++ " serialization/deserialization")))
+                      (SigE serializePropertyFn
+                        (AppT (AppT ArrowT (ConT qualTypeName))
+                              boolType)))) []]
+
+mkSerializeSpecs :: [Name] -> Q [Dec]
+mkSerializeSpecs types =
+    (++) <$> (concat `fmap` mapM mkSerializeSpec types)
+         <*> (mkEDNSerializeSpecGroup types)

tests/Data/EDN/Test/Unit.hs

+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ExistentialQuantification #-}
+module Data.EDN.Test.Unit (tests) where
+
+import Test.HUnit
+
+import qualified Data.ByteString.Lazy.Char8 as BSL
+import qualified Data.ByteString.Char8 as BS
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text as T
+
+import qualified Data.Vector as V
+import qualified Data.Set as S
+import qualified Data.Map as M
+
+import Data.EDN (encode, decode, ToEDN, toEDN, FromEDN, fromEDN)
+import Data.EDN.Types as E
+import Data.EDN.Types.Class (Result(..), (.=))
+import Data.EDN.Parser (parseMaybe)
+
+tests :: Test
+tests = TestList [ TestLabel "BSL -> TV parser" $ TestList $ map makeParserCase parserCases
+                 , TestLabel "TV -> BSL encoder" $ TestList $ map makeEncodeCase encodeCases
+                 , TestLabel "ToEDN conversion" $ TestList $ map makeToEDNcase toEDNcases
+                 , TestLabel "FromEDN converter/decoder" $ TestList $ map makeFromEDNcase fromEDNcases
+                 , TestLabel "decoder fail" (TestCase (assertEqual "bad unicode" Nothing (parseMaybe "№")))
+                 , TestLabel "'Tagged a' conversion" $ TestList taggedConversion
+                 ]
+
+makeParserCase :: (BSL.ByteString, E.TaggedValue) -> Test
+makeParserCase (i, o) = TestCase (assertEqual (BSL.unpack i) (Just o) (parseMaybe i))
+
+makeEncodeCase :: (E.TaggedValue, BSL.ByteString) -> Test
+makeEncodeCase (i, o) = TestCase (assertEqual (BSL.unpack o) o (encode i))
+
+parserCases :: [(BSL.ByteString, E.TaggedValue)]
+parserCases = [ ("nil", E.nil)
+
+              , ("true", E.true)
+              , ("false", E.false)
+
+              , ("\"a nice string\"", "a nice string")
+              , ("\"split\\second \\t\\rai\\n\"", "split\\second \t\rai\n")
+              , ("\"test \\\"sausage\\\" shmest\"", "test \"sausage\" shmest")
+              , ("\"\"", "")
+
+              , ("\\c", E.char 'c')
+              , ("\\\\", E.char '\\')
+              , ("\\newline", E.char '\n')
+              , ("\\space", E.char ' ')
+              , ("\\tab", E.char '\t')
+
+              , ("justasymbol", E.symbol "justasymbol")
+              , ("with#stuff:inside", E.symbol "with#stuff:inside")
+              , ("my-namespace/foo", E.symbolNS "my-namespace" "foo")
+              , ("/", E.symbol "/")
+
+              , (":fred", E.keyword "fred")
+              , (":my/fred", E.keyword "my/fred")
+
+              , ("42", E.integer 42)
+              , ("-1", E.integer (-1))
+
+              , ("100.50", E.floating 100.5)
+              , ("-3.14", E.floating (-3.14))
+               -- ...and many other strange stuff...
+
+              , ("(a b 42)", sampleList)
+              , ("()", E.notag $ E.makeList [])
+
+              , ("[a b 42]", sampleVec)
+              , ("[]", E.notag $ E.makeVec [])
+
+              , ("{:a 1, \"foo\" :bar, [1 2 3] four}", sampleMap)
+              , ("{}", E.notag $ E.makeMap [])
+
+              , ("#{a b [1 2 3]}", sampleSet)
+              , ("#{}", E.notag $ E.makeSet [])
+
+              , ("[a b #_foo 42]", sampleDiscard)
+              , ("(1 2 ;more to go!\n 3 4)", sampleComment)
+
+              , ("#myapp/Person {:first \"Fred\" :last \"Mertz\"}", E.tag "myapp" "Person" sampleTaggedMap)
+              , ("{:first \"Fred\" :last \"Mertz\"}", E.notag sampleTaggedMap)
+              ]
+
+encodeCases :: [(E.TaggedValue, BSL.ByteString)]
+encodeCases = [ (E.nil, "nil")
+
+              , (E.true, "true")
+              , (E.false, "false")
+
+              , (E.string "a nice string", "\"a nice string\"")
+              , ("overloaded", "\"overloaded\"")
+              , ("escape \rou\te \\ \"\north\"", "\"escape \\rou\\te \\\\ \\\"\\north\\\"\"")
+
+              , (E.char 'c', "\\c")
+              , (E.char '\\', "\\\\")
+              , (E.char '\n', "\\newline")
+              , (E.char '\r', "\\return")
+              , (E.char '\t', "\\tab")
+              , (E.char ' ', "\\space")
+
+              , (E.symbol "justasymbol", "justasymbol")
+              , (E.symbol "with#stuff:inside", "with#stuff:inside")
+              , (E.symbolNS "whatever" "whenever", "whatever/whenever")
+              , (E.symbol "/", "/")
+
+              , (E.keyword "fred", ":fred")
+              , (E.keyword "my/fred", ":my/fred")
+              , (E.notag ":overloaded", ":overloaded") -- IsString kw transform only for untagged values
+
+              , (E.integer 42, "42")
+              , (E.integer (-1), "-1")
+
+              , (E.floating 100.50, "100.5")
+              , (E.floating (-3.14), "-3.14")
+
+              , (sampleList, "(a b 42)")
+              , (E.notag $ E.makeList [], "()")
+
+              , (sampleVec, "[a b 42]")
+              , (E.notag $ E.makeVec [], "[]")
+
+              , (sampleMap, "{\"foo\" :bar :a 1 [1 2 3] four}") -- Order not guaranteed
+              , (E.notag $ E.makeMap [], "{}")
+
+              , (E.tag "myapp" "Person" sampleTaggedMap, "#myapp/Person {:first \"Fred\" :last \"Mertz\"}")
+              ]
+
+sampleList :: E.TaggedValue
+sampleList = E.notag $ E.makeList [E.symbol "a", E.symbol "b", E.integer 42]
+
+sampleVec :: E.TaggedValue
+sampleVec = E.notag $ E.makeVec [E.symbol "a", E.symbol "b", E.integer 42]
+
+sampleMap :: E.TaggedValue
+sampleMap = E.notag $ E.makeMap [ (":a",                                              E.integer 1)
+                                , ("foo",                                             E.keyword "bar")
+                                , (E.makeVec [E.integer 1, E.integer 2, E.integer 3], E.symbol "four")
+                                ]
+
+sampleSet :: E.TaggedValue
+sampleSet = E.notag $ E.makeSet [ E.symbol "a"
+                                , E.symbol "b"
+                                , E.notag $ E.makeVec [E.integer 1, E.integer 2, E.integer 3]
+                                ]
+
+sampleDiscard :: E.TaggedValue
+sampleDiscard = E.notag $ E.makeVec [E.symbol "a", E.symbol "b", E.integer 42]
+
+sampleComment :: E.TaggedValue
+sampleComment = E.notag $ E.makeList [E.integer 1, E.integer 2, E.integer 3, E.integer 4]
+
+sampleTaggedMap :: E.Value
+sampleTaggedMap = E.makeMap [ "first" .= E.string "Fred", "last" .= E.string "Mertz" ]
+
+data ToEDNCase = forall a. ToEDN a => ToEDNCase !a !E.TaggedValue
+
+makeToEDNcase :: ToEDNCase -> Test
+makeToEDNcase (ToEDNCase i o) = TestCase (assertEqual (show o) o (toEDN i))
+
+toEDNcases :: [ToEDNCase]
+toEDNcases = [ ToEDNCase (Nothing :: Maybe Bool) E.nil
+
+             , ToEDNCase (Left "hi" :: Either String ()) $ E.tag "either" "left" "hi"
+             , ToEDNCase (Right "z" :: Either () String) $ E.tag "either" "right" "z"
+             , ToEDNCase (Just '!') (E.char '!')
+
+             , ToEDNCase True E.true
+             , ToEDNCase False E.false
+
+             , ToEDNCase ("test" :: String) (E.string "test")
+             , ToEDNCase ("test" :: BSL.ByteString) "test"
+             , ToEDNCase ("test" :: BS.ByteString) "test"
+             , ToEDNCase ("test" :: TL.Text) "test"
+             , ToEDNCase ("test" :: T.Text) "test"
+
+             , ToEDNCase 'c' $ E.char 'c'
+             , ToEDNCase '\n' $ E.char '\n'
+             , ToEDNCase '\\' $ E.char '\\'
+
+             , ToEDNCase (3.14 :: Double) $ E.floating 3.14
+             , ToEDNCase (42 :: Integer) $ E.integer 42
+
+             , ToEDNCase () (E.notag $ E.makeList [])
+             , ToEDNCase ([] :: [()]) (E.notag $ E.makeList [])
+             , ToEDNCase (["yo", "wassup"] :: [String]) (E.notag $ E.makeList ["yo", "wassup"])
+             , ToEDNCase [E.string "i", "am", E.symbolNS "boxed" "container"] (E.notag $ E.makeList [E.string "i", "am", E.symbolNS "boxed" "container"])
+
+             , ToEDNCase (V.fromList ['o', 'm', 'g']) (E.notag $ E.makeVec [E.char 'o', E.char 'm', E.char 'g'])
+
+             , ToEDNCase (S.fromList ['o', 'm', 'g']) (E.notag $ E.makeSet [E.char 'o', E.char 'm', E.char 'g'])
+
+             , ToEDNCase (M.fromList [("test", "shmest"), ("foo", "bar")] :: M.Map String String) (E.notag $ E.makeMap [("test", "shmest"), ("foo", "bar")])
+             , ToEDNCase (M.fromList [(":test", "shmest"), (":foo", "bar")] :: EDNMap) (E.notag $ E.makeMap ["test" .= E.string "shmest", "foo" .= E.string "bar"])
+             ]
+
+data FromEDNCase = forall a. (FromEDN a, Show a, Eq a) => FromEDNCase !BSL.ByteString !a
+
+makeFromEDNcase :: FromEDNCase -> Test
+makeFromEDNcase (FromEDNCase i o) = TestCase $ assertEqual (BSL.unpack i) (Just o) (decode i)
+
+fromEDNcases :: [FromEDNCase]
+fromEDNcases = [ FromEDNCase "nil" (Nothing :: Maybe Bool)
+
+               , FromEDNCase "false" False
+               , FromEDNCase "true" True
+
+               , FromEDNCase "#either/left hi" (Left "hi" :: Either String ())
+               , FromEDNCase "#either/right z" (Right "z" :: Either () String)
+               , FromEDNCase "\"ok fine\"" (Just "ok fine" :: Maybe T.Text)
+               , FromEDNCase "nil" (Nothing :: Maybe BSL.ByteString)
+
+               , FromEDNCase "\\newline" '\n'
+               , FromEDNCase "\\z" 'z'
+
+               , FromEDNCase "42" (42 :: Integer)
+               , FromEDNCase "-3.14" (-3.14 :: Double)
+
+               , FromEDNCase "(hello world)" (["hello", "world"] :: [String])
+               , FromEDNCase "[3 2 1 \"Kaboom!\"]" $ E.makeVec [E.integer 3, E.integer 2, E.integer 1, "Kaboom!"]
+               , FromEDNCase "#{a/bag :of \"bugs\"}" $ E.makeSet [E.symbolNS "a" "bag", E.keyword "of", E.string "bugs"]
+               , FromEDNCase "{json: \"like\", but/not: \"really\"}" $ (M.fromList [("json:", "like"), ("but/not:", "really")] :: M.Map String String)
+               , FromEDNCase "{ json: \"like\", but/not: \"really\" }" $ (M.fromList [("json:", "like"), ("but/not:", "really")] :: M.Map String String)
+               ]
+
+taggedConversion :: [Test]
+taggedConversion = [ TestCase (assertEqual "toEDN tagged" (E.tag "wo" "ot" (E.Boolean False)) (toEDN $ E.tag "wo" "ot" False))
+                   , TestCase (assertEqual "toEDN notag" E.false (toEDN $ E.notag False))
+                   , TestCase (assertEqual "fromEDN tagged" (Success $ E.tag "wo" "ot" False) (fromEDN $ E.tag "wo" "ot" (E.Boolean False)))
+                   , TestCase (assertEqual "fromEDN notag" (Success $ E.notag False) (fromEDN $ E.false))
+                   ]
-{-# LANGUAGE OverloadedStrings, ExistentialQuantification #-}
+module Main where
+import           Test.Hspec.HUnit         (fromHUnitTest)
+import           Test.Hspec.Runner        (hspec)
 
-module Main where
-
-import Test.HUnit
-import Control.Monad (when)
-import System.Exit (exitFailure)
-
-import qualified Data.ByteString.Lazy.Char8 as BSL
-import qualified Data.ByteString.Char8 as BS
-import qualified Data.Text.Lazy as TL
-import qualified Data.Text as T
-
-import qualified Data.Vector as V
-import qualified Data.Set as S
-import qualified Data.Map as M
-
-import Data.EDN (encode, decode, ToEDN, toEDN, FromEDN, fromEDN)
-import Data.EDN.Types as E
-import Data.EDN.Types.Class (Result(..), (.=))
-import Data.EDN.Parser (parseMaybe)
+import           Data.EDN.Test.QuickCheck (ednSerializationProperties)
+import           Data.EDN.Test.Unit       (tests)
 
 main :: IO ()
-main = do
-    (Counts _ _ e f) <- runTestTT tests
-    when (e > 0 || f > 0) $ exitFailure
-
-tests :: Test
-tests = TestList [ TestLabel "BSL -> TV parser" $ TestList $ map makeParserCase parserCases
-                 , TestLabel "TV -> BSL encoder" $ TestList $ map makeEncodeCase encodeCases
-                 , TestLabel "ToEDN conversion" $ TestList $ map makeToEDNcase toEDNcases
-                 , TestLabel "FromEDN converter/decoder" $ TestList $ map makeFromEDNcase fromEDNcases
-                 , TestLabel "decoder fail" (TestCase (assertEqual "bad unicode" Nothing (parseMaybe "№")))
-                 , TestLabel "'Tagged a' conversion" $ TestList taggedConversion
-                 ]
-
-makeParserCase :: (BSL.ByteString, E.TaggedValue) -> Test
-makeParserCase (i, o) = TestCase (assertEqual (BSL.unpack i) (Just o) (parseMaybe i))
-
-makeEncodeCase :: (E.TaggedValue, BSL.ByteString) -> Test
-makeEncodeCase (i, o) = TestCase (assertEqual (BSL.unpack o) o (encode i))
-
-parserCases :: [(BSL.ByteString, E.TaggedValue)]
-parserCases = [ ("nil", E.nil)
-
-              , ("true", E.true)
-              , ("false", E.false)
-
-              , ("\"a nice string\"", "a nice string")
-              , ("\"split\\second \\t\\rai\\n\"", "split\\second \t\rai\n")
-              , ("\"test \\\"sausage\\\" shmest\"", "test \"sausage\" shmest")
-              , ("\"\"", "")
-
-              , ("\\c", E.char 'c')
-              , ("\\\\", E.char '\\')
-              , ("\\newline", E.char '\n')
-              , ("\\space", E.char ' ')
-              , ("\\tab", E.char '\t')
-
-              , ("justasymbol", E.symbol "justasymbol")
-              , ("with#stuff:inside", E.symbol "with#stuff:inside")
-              , ("my-namespace/foo", E.symbolNS "my-namespace" "foo")
-              , ("/", E.symbol "/")
-
-              , (":fred", E.keyword "fred")
-              , (":my/fred", E.keyword "my/fred")
-
-              , ("42", E.integer 42)
-              , ("-1", E.integer (-1))
-
-              , ("100.50", E.floating 100.5)
-              , ("-3.14", E.floating (-3.14))
-               -- ...and many other strange stuff...
-
-              , ("(a b 42)", sampleList)
-              , ("()", E.notag $ E.makeList [])
-
-              , ("[a b 42]", sampleVec)
-              , ("[]", E.notag $ E.makeVec [])
-
-              , ("{:a 1, \"foo\" :bar, [1 2 3] four}", sampleMap)
-              , ("{}", E.notag $ E.makeMap [])
-
-              , ("#{a b [1 2 3]}", sampleSet)
-              , ("#{}", E.notag $ E.makeSet [])
-
-              , ("[a b #_foo 42]", sampleDiscard)
-              , ("(1 2 ;more to go!\n 3 4)", sampleComment)
-
-              , ("#myapp/Person {:first \"Fred\" :last \"Mertz\"}", E.tag "myapp" "Person" sampleTaggedMap)
-              , ("{:first \"Fred\" :last \"Mertz\"}", E.notag sampleTaggedMap)
-              ]
-
-encodeCases :: [(E.TaggedValue, BSL.ByteString)]
-encodeCases = [ (E.nil, "nil")
-
-              , (E.true, "true")
-              , (E.false, "false")
-
-              , (E.string "a nice string", "\"a nice string\"")
-              , ("overloaded", "\"overloaded\"")
-              , ("escape \rou\te \\ \"\north\"", "\"escape \\rou\\te \\\\ \\\"\\north\\\"\"")
-
-              , (E.char 'c', "\\c")
-              , (E.char '\\', "\\\\")
-              , (E.char '\n', "\\newline")
-              , (E.char '\r', "\\return")
-              , (E.char '\t', "\\tab")
-              , (E.char ' ', "\\space")
-
-              , (E.symbol "justasymbol", "justasymbol")
-              , (E.symbol "with#stuff:inside", "with#stuff:inside")
-              , (E.symbolNS "whatever" "whenever", "whatever/whenever")
-              , (E.symbol "/", "/")
-
-              , (E.keyword "fred", ":fred")
-              , (E.keyword "my/fred", ":my/fred")
-              , (E.notag ":overloaded", ":overloaded") -- IsString kw transform only for untagged values
-
-              , (E.integer 42, "42")
-              , (E.integer (-1), "-1")
-
-              , (E.floating 100.50, "100.5")
-              , (E.floating (-3.14), "-3.14")
-
-              , (sampleList, "(a b 42)")
-              , (E.notag $ E.makeList [], "()")
-
-              , (sampleVec, "[a b 42]")
-              , (E.notag $ E.makeVec [], "[]")
-
-              , (sampleMap, "{\"foo\" :bar :a 1 [1 2 3] four}") -- Order not guaranteed
-              , (E.notag $ E.makeMap [], "{}")
-
-              , (E.tag "myapp" "Person" sampleTaggedMap, "#myapp/Person {:first \"Fred\" :last \"Mertz\"}")
-              ]
-
-sampleList :: E.TaggedValue
-sampleList = E.notag $ E.makeList [E.symbol "a", E.symbol "b", E.integer 42]
-
-sampleVec :: E.TaggedValue
-sampleVec = E.notag $ E.makeVec [E.symbol "a", E.symbol "b", E.integer 42]
-
-sampleMap :: E.TaggedValue
-sampleMap = E.notag $ E.makeMap [ (":a",                                              E.integer 1)
-                                , ("foo",                                             E.keyword "bar")
-                                , (E.makeVec [E.integer 1, E.integer 2, E.integer 3], E.symbol "four")
-                                ]
-
-sampleSet :: E.TaggedValue
-sampleSet = E.notag $ E.makeSet [ E.symbol "a"
-                                , E.symbol "b"
-                                , E.notag $ E.makeVec [E.integer 1, E.integer 2, E.integer 3]
-                                ]
-
-sampleDiscard :: E.TaggedValue
-sampleDiscard = E.notag $ E.makeVec [E.symbol "a", E.symbol "b", E.integer 42]
-
-sampleComment :: E.TaggedValue
-sampleComment = E.notag $ E.makeList [E.integer 1, E.integer 2, E.integer 3, E.integer 4]
-
-sampleTaggedMap :: E.Value
-sampleTaggedMap = E.makeMap [ "first" .= E.string "Fred", "last" .= E.string "Mertz" ]
-
-data ToEDNCase = forall a. ToEDN a => ToEDNCase !a !E.TaggedValue
-
-makeToEDNcase :: ToEDNCase -> Test
-makeToEDNcase (ToEDNCase i o) = TestCase (assertEqual (show o) o (toEDN i))
-
-toEDNcases :: [ToEDNCase]
-toEDNcases = [ ToEDNCase (Nothing :: Maybe Bool) E.nil
-
-             , ToEDNCase (Left "hi" :: Either String ()) $ E.tag "either" "left" "hi"
-             , ToEDNCase (Right "z" :: Either () String) $ E.tag "either" "right" "z"
-             , ToEDNCase (Just '!') (E.char '!')
-
-             , ToEDNCase True E.true
-             , ToEDNCase False E.false
-
-             , ToEDNCase ("test" :: String) (E.string "test")
-             , ToEDNCase ("test" :: BSL.ByteString) "test"
-             , ToEDNCase ("test" :: BS.ByteString) "test"
-             , ToEDNCase ("test" :: TL.Text) "test"
-             , ToEDNCase ("test" :: T.Text) "test"
-
-             , ToEDNCase 'c' $ E.char 'c'
-             , ToEDNCase '\n' $ E.char '\n'
-             , ToEDNCase '\\' $ E.char '\\'
-
-             , ToEDNCase (3.14 :: Double) $ E.floating 3.14
-             , ToEDNCase (42 :: Integer) $ E.integer 42
-
-             , ToEDNCase () (E.notag $ E.makeList [])
-             , ToEDNCase ([] :: [()]) (E.notag $ E.makeList [])
-             , ToEDNCase (["yo", "wassup"] :: [String]) (E.notag $ E.makeList ["yo", "wassup"])
-             , ToEDNCase [E.string "i", "am", E.symbolNS "boxed" "container"] (E.notag $ E.makeList [E.string "i", "am", E.symbolNS "boxed" "container"])
-
-             , ToEDNCase (V.fromList ['o', 'm', 'g']) (E.notag $ E.makeVec [E.char 'o', E.char 'm', E.char 'g'])
-
-             , ToEDNCase (S.fromList ['o', 'm', 'g']) (E.notag $ E.makeSet [E.char 'o', E.char 'm', E.char 'g'])
-
-             , ToEDNCase (M.fromList [("test", "shmest"), ("foo", "bar")] :: M.Map String String) (E.notag $ E.makeMap [("test", "shmest"), ("foo", "bar")])
-             , ToEDNCase (M.fromList [(":test", "shmest"), (":foo", "bar")] :: EDNMap) (E.notag $ E.makeMap ["test" .= E.string "shmest", "foo" .= E.string "bar"])
-             ]
-
-data FromEDNCase = forall a. (FromEDN a, Show a, Eq a) => FromEDNCase !BSL.ByteString !a
-
-makeFromEDNcase :: FromEDNCase -> Test
-makeFromEDNcase (FromEDNCase i o) = TestCase $ assertEqual (BSL.unpack i) (Just o) (decode i)
-
-fromEDNcases :: [FromEDNCase]
-fromEDNcases = [ FromEDNCase "nil" (Nothing :: Maybe Bool)
-
-               , FromEDNCase "false" False
-               , FromEDNCase "true" True
-
-               , FromEDNCase "#either/left hi" (Left "hi" :: Either String ())
-               , FromEDNCase "#either/right z" (Right "z" :: Either () String)
-               , FromEDNCase "\"ok fine\"" (Just "ok fine" :: Maybe T.Text)
-               , FromEDNCase "nil" (Nothing :: Maybe BSL.ByteString)
-
-               , FromEDNCase "\\newline" '\n'
-               , FromEDNCase "\\z" 'z'
-
-               , FromEDNCase "42" (42 :: Integer)
-               , FromEDNCase "-3.14" (-3.14 :: Double)
-
-               , FromEDNCase "(hello world)" (["hello", "world"] :: [String])
-               , FromEDNCase "[3 2 1 \"Kaboom!\"]" $ E.makeVec [E.integer 3, E.integer 2, E.integer 1, "Kaboom!"]
-               , FromEDNCase "#{a/bag :of \"bugs\"}" $ E.makeSet [E.symbolNS "a" "bag", E.keyword "of", E.string "bugs"]
-               , FromEDNCase "{json: \"like\", but/not: \"really\"}" $ (M.fromList [("json:", "like"), ("but/not:", "really")] :: M.Map String String)
-               ]
-
-taggedConversion :: [Test]
-taggedConversion = [ TestCase (assertEqual "toEDN tagged" (E.tag "wo" "ot" (E.Boolean False)) (toEDN $ E.tag "wo" "ot" False))
-                   , TestCase (assertEqual "toEDN notag" E.false (toEDN $ E.notag False))
-                   , TestCase (assertEqual "fromEDN tagged" (Success $ E.tag "wo" "ot" False) (fromEDN $ E.tag "wo" "ot" (E.Boolean False)))
-                   , TestCase (assertEqual "fromEDN notag" (Success $ E.notag False) (fromEDN $ E.false))
-                   ]
+main = hspec $ do
+  fromHUnitTest tests
+  ednSerializationProperties
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.