avro-0.4.2.0: test/Avro/THUnionSpec.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Avro.THUnionSpec
where
import qualified Data.List.NonEmpty as NE
import qualified Data.Aeson as Aeson
import Data.Avro
import Data.Avro.Deriving
import Data.Avro.EitherN
import qualified Data.Avro.Schema as Schema
import qualified Data.Avro.Types as Avro
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Map as Map
import System.Directory (doesFileExist)
import Test.Hspec
import Paths_avro
deriveAvro "test/data/unions.avsc"
spec :: Spec
spec = describe "Avro.THUnionSpec: Schema with unions." $ do
let objA = Unions
{ unionsScalars = Left "foo"
, unionsNullable = Nothing
, unionsRecords = Left $ Foo { fooStuff = "stuff" }
, unionsSameFields = Left $ Foo { fooStuff = "more stuff" }
, unionsArrayAndMap = Left ["foo"]
, unionsThree = E3_1 37
, unionsFour = E4_2 "foo"
, unionsFive = E5_4 $ Foo { fooStuff = "foo stuff" }
}
objB = Unions
{ unionsScalars = Right 42
, unionsNullable = Just 37
, unionsRecords = Right $ Bar { barStuff = "stuff"
, barThings = Foo { fooStuff = "things" }
}
, unionsSameFields = Right $ NotFoo { notFooStuff = "different from Foo" }
, unionsArrayAndMap = Right $ Map.fromList [("a", 5)]
, unionsThree = E3_3 37
, unionsFour = E4_4 $ Foo { fooStuff = "foo stuff" }
, unionsFive = E5_5 $ NotFoo { notFooStuff = "not foo stuff" }
}
field name schema def = Schema.Field name [] Nothing (Just Schema.Ascending) schema def
record name fields =
Schema.Record name [] Nothing (Just Schema.Ascending) fields
named = Schema.NamedType
foo = named "haskell.avro.example.Foo"
notFoo = named "haskell.avro.example.NotFoo"
expectedSchema = record "haskell.avro.example.Unions"
[ field "scalars" (Schema.mkUnion (NE.fromList [Schema.String, Schema.Long])) scalarsDefault
, field "nullable" (Schema.mkUnion (NE.fromList [Schema.Null, Schema.Int])) nullableDefault
, field "records" (Schema.mkUnion (NE.fromList [fooSchema, barSchema])) Nothing
, field "sameFields" (Schema.mkUnion (NE.fromList [foo, notFooSchema])) Nothing
, field "arrayAndMap" (Schema.mkUnion (NE.fromList [array, map])) Nothing
, field "three" (Schema.mkUnion (NE.fromList [Schema.Int, Schema.String, Schema.Long])) Nothing
, field "four" (Schema.mkUnion (NE.fromList [Schema.Int, Schema.String, Schema.Long, foo])) Nothing
, field "five" (Schema.mkUnion (NE.fromList [Schema.Int, Schema.String, Schema.Long, foo, notFoo])) Nothing
]
scalarsDefault = Just $ Avro.Union (NE.fromList [Schema.String, Schema.Long]) Schema.String (Avro.String "foo")
nullableDefault = Just $ Avro.Union (NE.fromList [Schema.Null, Schema.Int]) Schema.Null Avro.Null
fooSchema = record "haskell.avro.example.Foo" [field "stuff" Schema.String Nothing]
barSchema = record "haskell.avro.example.Bar"
[ field "stuff" Schema.String Nothing
, field "things" (named "haskell.avro.example.Foo") Nothing
]
notFooSchema = record "haskell.avro.example.NotFoo" [field "stuff" Schema.String Nothing]
array = Schema.Array { Schema.item = Schema.String }
map = Schema.Map { Schema.values = Schema.Long }
unionsSchemaFile <- runIO $ getFileName "test/data/unions.avsc" >>= LBS.readFile
let Just unionsSchemaFromJSON = Aeson.decode unionsSchemaFile
it "produces valid schemas" $ do
schema'Unions `shouldBe` expectedSchema
unionsSchemaFromJSON `shouldBe` expectedSchema
it "records with unions should roundtrip" $ do
fromAvro (toAvro objA) `shouldBe` pure objA
fromAvro (toAvro objB) `shouldBe` pure objB
getFileName :: FilePath -> IO FilePath
getFileName p = do
path <- getDataFileName p
isOk <- doesFileExist path
pure $ if isOk then path else p