avro-0.4.7.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 Control.Monad.Identity (Identity (..))
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 as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Map as Map
import qualified Data.Vector as V
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"]
, unionsOne = Identity 42
, unionsThree = E3_1 37
, unionsFour = E4_2 "foo"
, unionsFive = E5_4 $ Foo { fooStuff = "foo stuff" }
, unionsSix = E6_2 "foo"
, unionsSeven = E7_6 6.28
, unionsEight = E8_3 37
, unionsNine = E9_1 37
, unionsTen = E10_9 $ BS.pack [70, 79, 79, 66, 65, 82]
}
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)]
, unionsOne = Identity 42
, unionsThree = E3_3 37
, unionsFour = E4_4 $ Foo { fooStuff = "foo stuff" }
, unionsFive = E5_5 $ NotFoo { notFooStuff = "not foo stuff" }
, unionsSix = E6_6 6.28
, unionsSeven = E7_7 False
, unionsEight = E8_8 2.718
, unionsNine = E9_9 $ BS.pack [70, 79, 79, 66, 65, 82]
, unionsTen = E10_10 $ Bar { barStuff = "bar stuff",
barThings = Foo { fooStuff = "things" }
}
}
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"
bar = named "haskell.avro.example.Bar"
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 "one" (Schema.mkUnion (NE.fromList [Schema.Int'])) 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
, field "six" (Schema.mkUnion (NE.fromList [Schema.Int', Schema.String', Schema.Long', foo, notFoo, Schema.Float])) Nothing
, field "seven" (Schema.mkUnion (NE.fromList [Schema.Int', Schema.String', Schema.Long', foo, notFoo, Schema.Float, Schema.Boolean])) Nothing
, field "eight" (Schema.mkUnion (NE.fromList [Schema.Int', Schema.String', Schema.Long', foo, notFoo, Schema.Float, Schema.Boolean, Schema.Double])) Nothing
, field "nine" (Schema.mkUnion (NE.fromList [Schema.Int', Schema.String', Schema.Long', foo, notFoo, Schema.Float, Schema.Boolean, Schema.Double, Schema.Bytes'])) Nothing
, field "ten" (Schema.mkUnion (NE.fromList [Schema.Int', Schema.String', Schema.Long', foo, notFoo, Schema.Float, Schema.Boolean, Schema.Double, Schema.Bytes', bar])) Nothing
]
scalarsDefault = Just $ Avro.Union (V.fromList [Schema.String', Schema.Long']) Schema.String' (Avro.String "foo")
nullableDefault = Just $ Avro.Union (V.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