avro-0.3.6.0: test/Avro/JSONSpec.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Avro.JSONSpec where
import Control.Monad (forM_)
import qualified Data.Aeson as Aeson
import qualified Data.ByteString.Lazy as LBS
import Data.Avro.Deriving
import Data.Avro.EitherN
import Data.Avro.JSON
import Test.Hspec
import Paths_avro
import System.Directory (doesFileExist, getCurrentDirectory)
import System.Environment (setEnv)
deriveAvro "test/data/enums.avsc"
deriveAvro "test/data/reused.avsc"
deriveAvro "test/data/small.avsc"
deriveAvro "test/data/unions.avsc"
spec :: Spec
spec = describe "Avro.JSONSpec: JSON serialization/parsing" $ do
it "should do roundtrip (enums)" $ do
let msg = EnumWrapper
{ enumWrapperId = 42
, enumWrapperName = "Text"
, enumWrapperReason = EnumReasonBecause
}
parseJSON (Aeson.encode (toJSON msg)) `shouldBe` pure msg
it "should do roundtrip (reused)" $ do
let msg = ReusedWrapper
{ reusedWrapperFull = ReusedChild 42
, reusedWrapperInner = ContainerChild
{ containerChildFstIncluded = ReusedChild 37
, containerChildSndIncluded = ReusedChild 64
}
}
parseJSON (Aeson.encode (toJSON msg)) `shouldBe` pure msg
it "should do roundtrip (small)" $ do
let msgs =
[ Endpoint
{ endpointIps = ["192.168.1.1", "127.0.0.1"]
, endpointPorts = [PortRange 1 10, PortRange 11 20]
, endpointOpaque = Opaque "16-b-long-string"
, endpointCorrelation = Opaque "opaq-correlation"
, endpointTag = Left 14
}
, Endpoint
{ endpointIps = []
, endpointPorts = [PortRange 1 10, PortRange 11 20]
, endpointOpaque = Opaque "opaque-long-text"
, endpointCorrelation = Opaque "correlation-data"
, endpointTag = Right "first-tag"
}
]
forM_ msgs $ \ msg ->
parseJSON (Aeson.encode (toJSON msg)) `shouldBe` pure msg
enumsExampleJSON <- runIO $ getFileName "test/data/enums-object.json" >>= LBS.readFile
it "should parse (enums)" $ do
let expected = EnumWrapper 37 "blarg" EnumReasonInstead
parseJSON enumsExampleJSON `shouldBe` pure expected
let unionsExampleA = Unions
{ unionsScalars = Left "blarg"
, unionsNullable = Nothing
, unionsRecords = Left $ Foo { fooStuff = "stuff" }
, unionsSameFields = Left $ Foo { fooStuff = "foo stuff" }
, unionsThree = E3_1 37
, unionsFour = E4_2 "foo"
, unionsFive = E5_4 $ Foo { fooStuff = "foo stuff" }
}
unionsExampleB = Unions
{ unionsScalars = Right 37
, unionsNullable = Just 42
, unionsRecords = Right $ Bar { barStuff = "stuff"
, barThings = Foo "things"
}
, unionsSameFields = Right $ NotFoo { notFooStuff = "not foo stuff" }
, unionsThree = E3_3 37
, unionsFour = E4_4 $ Foo { fooStuff = "foo stuff" }
, unionsFive = E5_5 $ NotFoo { notFooStuff = "not foo stuff" }
}
it "should roundtrip (unions)" $ do
forM_ [unionsExampleA, unionsExampleB] $ \ msg ->
parseJSON (Aeson.encode (toJSON msg)) `shouldBe` pure msg
unionsJsonA <- runIO $ getFileName "test/data/unions-object-a.json" >>= LBS.readFile
unionsJsonB <- runIO $ getFileName "test/data/unions-object-b.json" >>= LBS.readFile
it "should parse (unions)" $ do
parseJSON unionsJsonA `shouldBe` pure unionsExampleA
parseJSON unionsJsonB `shouldBe` pure unionsExampleB
getFileName :: FilePath -> IO FilePath
getFileName p = do
path <- getDataFileName p
isOk <- doesFileExist path
pure $ if isOk then path else p