on master help sign in
Split examples in test suites into a separate module and add a module

for testing error messages (only a few tests for now).

commitb8dac1d2c29a92e15418508b6dfc25e9eda4d7cf authorAdam Bergmark <adam@bergmark.nl> dateSun 1 Jan 2017, 11:55 (10 years ago) parentcc7f404
4 files changed+314−224
aeson.cabal+2 tests/ErrorMessages.hs+57 tests/SerializationFormatSpec.hs+245 tests/UnitTests.hs+10−224
aeson.cabal+2
@@ -163,10 +163,12 @@ test-suite tests
163163 DataFamilies.Encoders
164164 DataFamilies.Types
165165 Encoders
166+ ErrorMessages
166167 Functions
167168 Instances
168169 Options
169170 Properties
171+ SerializationFormatSpec
170172 Types
171173 UnitTests
172174 UnitTests.NullaryConstructors
tests/ErrorMessages.hsnew file+57
@@ -0,0 +1,57 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+
4+module ErrorMessages
5+ (
6+ tests
7+ ) where
8+
9+import Prelude ()
10+import Prelude.Compat
11+
12+import Data.Aeson (FromJSON(..), eitherDecode)
13+import Data.Proxy (Proxy(..))
14+import Instances ()
15+import Test.Framework (Test)
16+import Test.Framework.Providers.HUnit (testCase)
17+import Test.HUnit (Assertion, assertFailure, assertEqual)
18+import qualified Data.ByteString.Lazy.Char8 as L
19+import qualified Data.HashMap.Strict as HM
20+
21+tests :: [Test]
22+tests =
23+ [
24+ testCase "Int" int
25+ , testCase "String" string
26+ , testCase "HashMap" hashMap
27+ ]
28+
29+int :: Assertion
30+int = do
31+ let t = test (Proxy :: Proxy Int)
32+ t "\"\"" $ expected "Int" "String"
33+ t "[]" $ expected "Int" "Array"
34+ t "{}" $ expected "Int" "Object"
35+ t "null" $ expected "Int" "Null"
36+
37+string :: Assertion
38+string = do
39+ let t = test (Proxy :: Proxy String)
40+ t "1" $ expected "String" "Number"
41+ t "[]" $ expected "String" "Array"
42+ t "{}" $ expected "String" "Object"
43+ t "null" $ expected "String" "Null"
44+
45+hashMap :: Assertion
46+hashMap = do
47+ let t = test (Proxy :: Proxy (HM.HashMap String Int))
48+ t "\"\"" $ expected "HashMap k v" "String"
49+ t "[]" $ expected "HashMap k v" "Array"
50+
51+expected :: String -> String -> String
52+expected ex enc = "Error in $: expected " ++ ex ++ ", encountered " ++ enc
53+
54+test :: forall a proxy . (FromJSON a, Show a) => proxy a -> L.ByteString -> String -> Assertion
55+test _ v msg = case eitherDecode v of
56+ Left e -> assertEqual "Invalid error message" msg e
57+ Right (x :: a) -> assertFailure $ "Expected parsing to fail but it suceeded with: " ++ show x
tests/SerializationFormatSpec.hsnew file+245
@@ -0,0 +1,245 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE DeriveGeneric #-}
3+{-# LANGUAGE GADTs #-}
4+{-# LANGUAGE OverloadedStrings #-}
5+#if __GLASGOW_HASKELL__ >= 708
6+{-# LANGUAGE DataKinds #-}
7+#endif
8+
9+------------------------------------------------------------------------------
10+-- These tests assert that the JSON serialization doesn't change by accident.
11+-----------------------------------------------------------------------------
12+
13+module SerializationFormatSpec
14+ (
15+ tests
16+ ) where
17+
18+import Prelude ()
19+import Prelude.Compat
20+
21+import Control.Applicative (Const(..))
22+import Data.Aeson (FromJSON(..), decode, encode, genericParseJSON, genericToEncoding, genericToJSON)
23+import Data.Aeson.Types (Options(..), SumEncoding(..), ToJSON(..), defaultOptions)
24+import Data.Fixed (Pico)
25+import Data.Functor.Compose (Compose(..))
26+import Data.Functor.Identity (Identity(..))
27+import Data.Functor.Product (Product(..))
28+import Data.Functor.Sum (Sum(..))
29+import Data.List.NonEmpty (NonEmpty(..))
30+import Data.Proxy (Proxy(..))
31+import Data.Scientific (Scientific)
32+import Data.Tagged (Tagged(..))
33+import Data.Time (fromGregorian)
34+import Data.Word (Word8)
35+import GHC.Generics (Generic)
36+import Instances ()
37+import Test.Framework (Test, testGroup)
38+import Test.Framework.Providers.HUnit (testCase)
39+import Test.HUnit (assertFailure, assertEqual)
40+import Types (Approx(..), Compose3, Compose3', I)
41+import qualified Data.ByteString.Lazy.Char8 as L
42+import qualified Data.DList as DList
43+import qualified Data.HashMap.Strict as HM
44+import qualified Data.HashSet as HashSet
45+import qualified Data.IntMap as IntMap
46+import qualified Data.IntSet as IntSet
47+import qualified Data.Map as M
48+import qualified Data.Monoid as Monoid
49+import qualified Data.Semigroup as Semigroup
50+import qualified Data.Sequence as Seq
51+import qualified Data.Set as Set
52+import qualified Data.Tree as Tree
53+import qualified Data.UUID.Types as UUID
54+import qualified Data.Vector as Vector
55+
56+tests :: [Test]
57+tests =
58+ [
59+ testGroup "To JSON representation" $ fmap assertJsonEncodingExample jsonEncodingExamples
60+ , testGroup "From JSON representation" $ fmap assertJsonExample jsonDecodingExamples
61+ , testGroup "To/From JSON representation" $ fmap assertJsonExample jsonExamples
62+
63+ ]
64+
65+jsonExamples :: [Example]
66+jsonExamples =
67+ [
68+ Example "Either Left" "{\"Left\":1}" (Left 1 :: Either Int Int)
69+ , Example "Either Right" "{\"Right\":1}" (Right 1 :: Either Int Int)
70+ , Example "Nothing" "null" (Nothing :: Maybe Int)
71+ , Example "Just" "1" (Just 1 :: Maybe Int)
72+ , Example "Proxy Int" "null" (Proxy :: Proxy Int)
73+ , Example "Tagged Char Int" "1" (Tagged 1 :: Tagged Char Int)
74+#if __GLASGOW_HASKELL__ >= 708
75+ -- Test Tagged instance is polykinded
76+ , Example "Tagged 123 Int" "1" (Tagged 1 :: Tagged 123 Int)
77+#endif
78+ , Example "Const Char Int" "\"c\"" (Const 'c' :: Const Char Int)
79+ , Example "Tuple" "[1,2]" ((1, 2) :: (Int, Int))
80+ , Example "NonEmpty" "[1,2,3]" (1 :| [2, 3] :: NonEmpty Int)
81+ , Example "Seq" "[1,2,3]" (Seq.fromList [1, 2, 3] :: Seq.Seq Int)
82+ , Example "DList" "[1,2,3]" (DList.fromList [1, 2, 3] :: DList.DList Int)
83+ , Example "()" "[]" ()
84+
85+ , Example "HashMap Int Int" "{\"0\":1,\"2\":3}" (HM.fromList [(0,1),(2,3)] :: HM.HashMap Int Int)
86+ , Example "Map Int Int" "{\"0\":1,\"2\":3}" (M.fromList [(0,1),(2,3)] :: M.Map Int Int)
87+ , Example "Map (Tagged Int Int) Int" "{\"0\":1,\"2\":3}" (M.fromList [(Tagged 0,1),(Tagged 2,3)] :: M.Map (Tagged Int Int) Int)
88+ , Example "Map [Int] Int" "[[[0],1],[[2],3]]" (M.fromList [([0],1),([2],3)] :: M.Map [Int] Int)
89+ , Example "Map [Char] Int" "{\"ab\":1,\"cd\":3}" (M.fromList [("ab",1),("cd",3)] :: M.Map [Char] Int)
90+ , Example "Map [I Char] Int" "{\"ab\":1,\"cd\":3}" (M.fromList [(map pure "ab",1),(map pure "cd",3)] :: M.Map [I Char] Int)
91+
92+ , Example "nan :: Double" "null" (Approx $ 0/0 :: Approx Double)
93+
94+ , Example "Ordering LT" "\"LT\"" LT
95+ , Example "Ordering EQ" "\"EQ\"" EQ
96+ , Example "Ordering GT" "\"GT\"" GT
97+
98+ , Example "Float" "3.14" (3.14 :: Float)
99+ , Example "Pico" "3.14" (3.14 :: Pico)
100+ , Example "Scientific" "3.14" (3.14 :: Scientific)
101+
102+ , Example "UUID" "\"c2cc10e1-57d6-4b6f-9899-38d972112d8c\"" $ UUID.fromWords
103+ 0xc2cc10e1 0x57d64b6f 0x989938d9 0x72112d8c
104+
105+ , Example "Set Int" "[1,2,3]" (Set.fromList [3, 2, 1] :: Set.Set Int)
106+ , Example "IntSet" "[1,2,3]" (IntSet.fromList [3, 2, 1])
107+ , Example "IntMap" "[[1,2],[3,4]]" (IntMap.fromList [(3,4), (1,2)] :: IntMap.IntMap Int)
108+ , Example "Vector" "[1,2,3]" (Vector.fromList [1, 2, 3] :: Vector.Vector Int)
109+ , Example "HashSet Int" "[1,2,3]" (HashSet.fromList [3, 2, 1] :: HashSet.HashSet Int)
110+ , Example "Tree Int" "[1,[[2,[[3,[]],[4,[]]]],[5,[]]]]" (let n = Tree.Node in n 1 [n 2 [n 3 [], n 4 []], n 5 []] :: Tree.Tree Int)
111+
112+ -- Three separate cases, as ordering in HashMap is not defined
113+ , Example "HashMap Float Int, NaN" "{\"NaN\":1}" (Approx $ HM.singleton (0/0) 1 :: Approx (HM.HashMap Float Int))
114+ , Example "HashMap Float Int, Infinity" "{\"Infinity\":1}" (HM.singleton (1/0) 1 :: HM.HashMap Float Int)
115+ , Example "HashMap Float Int, +Infinity" "{\"-Infinity\":1}" (HM.singleton (negate 1/0) 1 :: HM.HashMap Float Int)
116+
117+ -- Functors
118+ , Example "Identity Int" "1" (pure 1 :: Identity Int)
119+
120+ , Example "Identity Char" "\"x\"" (pure 'x' :: Identity Char)
121+ , Example "Identity String" "\"foo\"" (pure "foo" :: Identity String)
122+ , Example "[Identity Char]" "\"xy\"" ([pure 'x', pure 'y'] :: [Identity Char])
123+
124+ , Example "Maybe Char" "\"x\"" (pure 'x' :: Maybe Char)
125+ , Example "Maybe String" "\"foo\"" (pure "foo" :: Maybe String)
126+ , Example "Maybe [Identity Char]" "\"xy\"" (pure [pure 'x', pure 'y'] :: Maybe [Identity Char])
127+
128+ , Example "Day; year >= 1000" "\"1999-10-12\"" (fromGregorian 1999 10 12)
129+ , Example "Day; year > 0 && < 1000" "\"0500-03-04\"" (fromGregorian 500 3 4)
130+ , Example "Day; year == 0" "\"0000-02-20\"" (fromGregorian 0 2 20)
131+ , Example "Day; year < 0" "\"-0234-01-01\"" (fromGregorian (-234) 1 1)
132+ , Example "Day; year < -1000" "\"-1234-01-01\"" (fromGregorian (-1234) 1 1)
133+
134+ , Example "Product I Maybe Int" "[1,2]" (Pair (pure 1) (pure 2) :: Product I Maybe Int)
135+ , Example "Product I Maybe Int" "[1,null]" (Pair (pure 1) Nothing :: Product I Maybe Int)
136+ , Example "Product I [] Char" "[\"a\",\"foo\"]" (Pair (pure 'a') "foo" :: Product I [] Char)
137+
138+ , Example "Sum I [] Int: InL" "{\"InL\":1}" (InL (pure 1) :: Sum I [] Int)
139+ , Example "Sum I [] Int: InR" "{\"InR\":[1,2]}" (InR [1, 2] :: Sum I [] Int)
140+ , Example "Sum I [] Char: InR" "{\"InR\":\"foo\"}" (InR "foo" :: Sum I [] Char)
141+
142+ , Example "Compose I I Int" "1" (pure 1 :: Compose I I Int)
143+ , Example "Compose I [] Int" "[1]" (pure 1 :: Compose I [] Int)
144+ , Example "Compose [] I Int" "[1]" (pure 1 :: Compose [] I Int)
145+ , Example "Compose [] [] Int" "[[1]]" (pure 1 :: Compose [] [] Int)
146+
147+ , Example "Compose I I Char" "\"x\"" (pure 'x' :: Compose I I Char)
148+ , Example "Compose I [] Char" "\"x\"" (pure 'x' :: Compose I [] Char)
149+ , Example "Compose [] I Char" "\"x\"" (pure 'x' :: Compose [] I Char)
150+ , Example "Compose [] [] Char" "[\"x\"]" (pure 'x' :: Compose [] [] Char)
151+
152+ , Example "Compose3 I I I Char" "\"x\"" (pure 'x' :: Compose3 I I I Char)
153+ , Example "Compose3 I I [] Char" "\"x\"" (pure 'x' :: Compose3 I I [] Char)
154+ , Example "Compose3 I [] I Char" "\"x\"" (pure 'x' :: Compose3 I [] I Char)
155+ , Example "Compose3 I [] [] Char" "[\"x\"]" (pure 'x' :: Compose3 I [] [] Char)
156+ , Example "Compose3 [] I I Char" "\"x\"" (pure 'x' :: Compose3 [] I I Char)
157+ , Example "Compose3 [] I [] Char" "[\"x\"]" (pure 'x' :: Compose3 [] I [] Char)
158+ , Example "Compose3 [] [] I Char" "[\"x\"]" (pure 'x' :: Compose3 [] [] I Char)
159+ , Example "Compose3 [] [] [] Char" "[[\"x\"]]" (pure 'x' :: Compose3 [] [] [] Char)
160+
161+ , Example "Compose3' I I I Char" "\"x\"" (pure 'x' :: Compose3' I I I Char)
162+ , Example "Compose3' I I [] Char" "\"x\"" (pure 'x' :: Compose3' I I [] Char)
163+ , Example "Compose3' I [] I Char" "\"x\"" (pure 'x' :: Compose3' I [] I Char)
164+ , Example "Compose3' I [] [] Char" "[\"x\"]" (pure 'x' :: Compose3' I [] [] Char)
165+ , Example "Compose3' [] I I Char" "\"x\"" (pure 'x' :: Compose3' [] I I Char)
166+ , Example "Compose3' [] I [] Char" "[\"x\"]" (pure 'x' :: Compose3' [] I [] Char)
167+ , Example "Compose3' [] [] I Char" "[\"x\"]" (pure 'x' :: Compose3' [] [] I Char)
168+ , Example "Compose3' [] [] [] Char" "[[\"x\"]]" (pure 'x' :: Compose3' [] [] [] Char)
169+
170+ , Example "MyEither Int String: Left" "42" (MyLeft 42 :: MyEither Int String)
171+ , Example "MyEither Int String: Right" "\"foo\"" (MyRight "foo" :: MyEither Int String)
172+
173+ -- newtypes from Monoid/Semigroup
174+ , Example "Monoid.Dual Int" "2" (pure 2 :: Monoid.Dual Int)
175+ , Example "Monoid.First Int" "2" (pure 2 :: Monoid.First Int)
176+ , Example "Monoid.Last Int" "2" (pure 2 :: Monoid.Last Int)
177+ , Example "Semigroup.Min Int" "2" (pure 2 :: Semigroup.Min Int)
178+ , Example "Semigroup.Max Int" "2" (pure 2 :: Semigroup.Max Int)
179+ , Example "Semigroup.First Int" "2" (pure 2 :: Semigroup.First Int)
180+ , Example "Semigroup.Last Int" "2" (pure 2 :: Semigroup.Last Int)
181+ , Example "Semigroup.WrappedMonoid Int" "2" (Semigroup.WrapMonoid 2 :: Semigroup.WrappedMonoid Int)
182+ , Example "Semigroup.Option Just" "2" (pure 2 :: Semigroup.Option Int)
183+ , Example "Semigroup.Option Nothing" "null" (Semigroup.Option (Nothing :: Maybe Bool))
184+ ]
185+
186+jsonEncodingExamples :: [Example]
187+jsonEncodingExamples =
188+ [
189+ -- Maybe serialising is lossy
190+ -- https://github.com/bos/aeson/issues/376
191+ Example "Just Nothing" "null" (Just Nothing :: Maybe (Maybe Int))
192+ -- infinities cannot be recovered, null is decoded as NaN
193+ , Example "inf :: Double" "null" (Approx $ 1/0 :: Approx Double)
194+ ]
195+
196+jsonDecodingExamples :: [Example]
197+jsonDecodingExamples = [
198+ -- Maybe serialising is lossy
199+ -- https://github.com/bos/aeson/issues/376
200+ MaybeExample "Nothing" "null" (Just $ Nothing :: Maybe (Maybe Int))
201+ , MaybeExample "Just" "1" (Just $ Just 1 :: Maybe (Maybe Int))
202+ , MaybeExample "Just Nothing" "null" (Just $ Nothing :: Maybe (Maybe (Maybe Int)))
203+ -- Integral values are truncated, and overflowed
204+ -- https://github.com/bos/aeson/issues/317
205+ , MaybeExample "Word8 3" "3" (Just 3 :: Maybe Word8)
206+ , MaybeExample "Word8 3.00" "3.00" (Just 3 :: Maybe Word8)
207+ , MaybeExample "Word8 3.14" "3.14" (Nothing :: Maybe Word8)
208+ , MaybeExample "Word8 -1" "-1" (Nothing :: Maybe Word8)
209+ , MaybeExample "Word8 300" "300" (Nothing :: Maybe Word8)
210+ -- Negative zero year, encoding never produces such:
211+ , MaybeExample "Day -0000-02-03" "\"-0000-02-03\"" (Just (fromGregorian 0 2 3))
212+ ]
213+
214+data Example where
215+ Example
216+ :: (Eq a, Show a, ToJSON a, FromJSON a)
217+ => String -> L.ByteString -> a -> Example
218+ MaybeExample
219+ :: (Eq a, Show a, FromJSON a)
220+ => String -> L.ByteString -> Maybe a -> Example
221+
222+data MyEither a b = MyLeft a | MyRight b
223+ deriving (Generic, Show, Eq)
224+
225+instance (ToJSON a, ToJSON b) => ToJSON (MyEither a b) where
226+ toJSON = genericToJSON defaultOptions { sumEncoding = UntaggedValue }
227+ toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }
228+
229+instance (FromJSON a, FromJSON b) => FromJSON (MyEither a b) where
230+ parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }
231+
232+assertJsonExample :: Example -> Test
233+assertJsonExample (Example name bs val) = testCase name $ do
234+ assertEqual "encode" bs (encode val)
235+ assertEqual "encode/via value" bs (encode $ toJSON val)
236+ assertEqual "decode" (Just val) (decode bs)
237+assertJsonExample (MaybeExample name bs mval) = testCase name $
238+ assertEqual "decode" mval (decode bs)
239+
240+assertJsonEncodingExample :: Example -> Test
241+assertJsonEncodingExample (Example name bs val) = testCase name $ do
242+ assertEqual "encode" bs (encode val)
243+ assertEqual "encode/via value" bs (encode $ toJSON val)
244+assertJsonEncodingExample (MaybeExample name _ _) = testCase name $
245+ assertFailure "cannot encode MaybeExample"
tests/UnitTests.hs+10−224
@@ -1,14 +1,11 @@
11{-# LANGUAGE CPP #-}
22{-# LANGUAGE DeriveGeneric #-}
3−{-# LANGUAGE GADTs #-}
43{-# LANGUAGE GeneralizedNewtypeDeriving #-}
54{-# LANGUAGE OverloadedStrings #-}
65{-# LANGUAGE ScopedTypeVariables #-}
76{-# LANGUAGE TemplateHaskell #-}
8−#if __GLASGOW_HASKELL__ >= 708
9−{-# LANGUAGE DataKinds #-}
10−#endif
117
8+-- For Data.Aeson.Types.camelTo
129{-# OPTIONS_GHC -fno-warn-deprecations #-}
1310
1411module UnitTests
@@ -20,68 +17,49 @@ module UnitTests
2017import Prelude ()
2118import Prelude.Compat
2219
23−import Control.Applicative (Const(..))
2420import Control.Monad (forM, forM_, unless)
25−import Data.Aeson ((.=), (.:), (.:?), (.:!), FromJSON(..), FromJSONKeyFunction(..), FromJSONKey(..), ToJSON1(..), decode, eitherDecode, encode, genericParseJSON, genericToEncoding, genericToJSON, object, withObject)
21+import Data.Aeson ((.=), (.:), (.:?), (.:!), FromJSON(..), FromJSONKeyFunction(..), FromJSONKey(..), ToJSON1(..), decode, eitherDecode, encode, genericToEncoding, genericToJSON, object, withObject)
2622import Data.Aeson.Internal (JSONPathElement(..), formatError)
2723import Data.Aeson.TH (deriveJSON, deriveToJSON, deriveToJSON1)
2824import Data.Aeson.Text (encodeToTextBuilder)
29−import Data.Aeson.Types (Options(..), SumEncoding(..), ToJSON(..), Value, camelTo, camelTo2, defaultOptions, omitNothingFields)
25+import Data.Aeson.Types (Options(..), ToJSON(..), Value, camelTo, camelTo2, defaultOptions, omitNothingFields)
3026import Data.Char (toUpper)
3127import Data.Either.Compat (isLeft, isRight)
32−import Data.Fixed (Pico)
33−import Data.Functor.Compose (Compose(..))
34−import Data.Functor.Identity (Identity(..))
35−import Data.Functor.Product (Product(..))
36−import Data.Functor.Sum (Sum(..))
3728import Data.Hashable (hash)
3829import Data.List (sort)
39−import Data.List.NonEmpty (NonEmpty(..))
4030import Data.Maybe (fromMaybe)
41−import Data.Proxy (Proxy(..))
42−import Data.Scientific (Scientific)
4331import Data.Sequence (Seq)
4432import Data.Tagged (Tagged(..))
4533import Data.Text (Text)
46−import Data.Time (UTCTime, fromGregorian)
34+import Data.Time (UTCTime)
4735import Data.Time.Format (parseTime)
4836import Data.Time.Locale.Compat (defaultTimeLocale)
49−import Data.Word (Word8)
5037import GHC.Generics (Generic)
5138import Instances ()
5239import System.Directory (doesDirectoryExist, getDirectoryContents)
5340import System.Exit (exitWith, ExitCode(ExitFailure))
54−import System.IO (hPutStrLn, stderr)
5541import System.FilePath ((</>), takeExtension, takeFileName)
42+import System.IO (hPutStrLn, stderr)
5643import Test.Framework (Test, testGroup)
5744import Test.Framework.Providers.HUnit (testCase)
5845import Test.HUnit (Assertion, assertBool, assertFailure, assertEqual)
5946import Text.Printf (printf)
60−import Types (Approx(..), Compose3, Compose3', I)
6147import UnitTests.NullaryConstructors (nullaryConstructors)
6248import qualified Data.ByteString.Base16.Lazy as LBase16
6349import qualified Data.ByteString.Lazy.Char8 as L
64−import qualified Data.DList as DList
65−import qualified Data.HashMap.Strict as HM
6650import qualified Data.HashSet as HashSet
67−import qualified Data.IntMap as IntMap
68−import qualified Data.IntSet as IntSet
69−import qualified Data.Map as M
70−import qualified Data.Monoid as Monoid
71−import qualified Data.Semigroup as Semigroup
72−import qualified Data.Sequence as Seq
73−import qualified Data.Set as Set
7451import qualified Data.Text.Lazy as LT
7552import qualified Data.Text.Lazy.Builder as TLB
7653import qualified Data.Text.Lazy.Encoding as LT
7754import qualified Data.Text.Lazy.Encoding as TLE
78−import qualified Data.Tree as Tree
79−import qualified Data.UUID.Types as UUID
80−import qualified Data.Vector as Vector
55+import qualified ErrorMessages
56+import qualified SerializationFormatSpec
8157
8258tests :: Test
8359tests = testGroup "unit" [
84− testGroup "camelCase" [
60+ testGroup "SerializationFormatSpec" SerializationFormatSpec.tests
61+ , testGroup "ErrorMessages" ErrorMessages.tests
62+ , testGroup "camelCase" [
8563 testCase "camelTo" $ roundTripCamel "aName"
8664 , testCase "camelTo" $ roundTripCamel "another"
8765 , testCase "camelTo" $ roundTripCamel "someOtherName"
@@ -104,9 +82,6 @@ tests = testGroup "unit" [
10482 testCase "example 1" $ formatErrorExample
10583 ]
10684 , testGroup ".:, .:?, .:!" $ fmap (testCase "-") dotColonMark
107− , testGroup "To JSON representation" $ fmap assertJsonEncodingExample jsonEncodingExamples
108− , testGroup "From JSON representation" $ fmap assertJsonExample jsonDecodingExamples
109− , testGroup "To/From JSON representation" $ fmap assertJsonExample jsonExamples
11085 , testGroup "JSONPath" $ fmap (testCase "-") jsonPath
11186 , testGroup "Hashable laws" $ fmap (testCase "-") hashableLaws
11287 , testGroup "Issue #351" $ fmap (testCase "-") issue351
@@ -130,17 +105,6 @@ camelFrom c s = let (p:ps) = split c s
130105 capitalize t = toUpper (head t) : tail t
131106
132107
133−data MyEither a b = MyLeft a | MyRight b
134− deriving (Generic, Show, Eq)
135−
136−instance (ToJSON a, ToJSON b) => ToJSON (MyEither a b) where
137− toJSON = genericToJSON defaultOptions { sumEncoding = UntaggedValue }
138− toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }
139−
140−instance (FromJSON a, FromJSON b) => FromJSON (MyEither a b) where
141− parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }
142−
143−
144108data Wibble = Wibble {
145109 wibbleString :: String
146110 , wibbleInt :: Int
@@ -280,184 +244,6 @@ dotColonMark = [
280244 ex2 = "{\"value\": 42 }"
281245 ex3 = "{\"value\": null }"
282246
283−------------------------------------------------------------------------------
284−-- These tests assert that the JSON serialization doesn't change by accident.
285−-----------------------------------------------------------------------------
286−
287−data Example where
288− Example
289− :: (Eq a, Show a, ToJSON a, FromJSON a)
290− => String -> L.ByteString -> a -> Example
291− MaybeExample
292− :: (Eq a, Show a, FromJSON a)
293− => String -> L.ByteString -> Maybe a -> Example
294−
295−assertJsonExample :: Example -> Test
296−assertJsonExample (Example name bs val) = testCase name $ do
297− assertEqual "encode" bs (encode val)
298− assertEqual "encode/via value" bs (encode $ toJSON val)
299− assertEqual "decode" (Just val) (decode bs)
300−assertJsonExample (MaybeExample name bs mval) = testCase name $
301− assertEqual "decode" mval (decode bs)
302−
303−assertJsonEncodingExample :: Example -> Test
304−assertJsonEncodingExample (Example name bs val) = testCase name $ do
305− assertEqual "encode" bs (encode val)
306− assertEqual "encode/via value" bs (encode $ toJSON val)
307−assertJsonEncodingExample (MaybeExample name _ _) = testCase name $
308− assertFailure "cannot encode MaybeExample"
309−
310−jsonEncodingExamples :: [Example]
311−jsonEncodingExamples =
312− [
313− -- Maybe serialising is lossy
314− -- https://github.com/bos/aeson/issues/376
315− Example "Just Nothing" "null" (Just Nothing :: Maybe (Maybe Int))
316− -- infinities cannot be recovered, null is decoded as NaN
317− , Example "inf :: Double" "null" (Approx $ 1/0 :: Approx Double)
318− ]
319−
320−jsonDecodingExamples :: [Example]
321−jsonDecodingExamples = [
322− -- Maybe serialising is lossy
323− -- https://github.com/bos/aeson/issues/376
324− MaybeExample "Nothing" "null" (Just $ Nothing :: Maybe (Maybe Int))
325− , MaybeExample "Just" "1" (Just $ Just 1 :: Maybe (Maybe Int))
326− , MaybeExample "Just Nothing" "null" (Just $ Nothing :: Maybe (Maybe (Maybe Int)))
327− -- Integral values are truncated, and overflowed
328− -- https://github.com/bos/aeson/issues/317
329− , MaybeExample "Word8 3" "3" (Just 3 :: Maybe Word8)
330− , MaybeExample "Word8 3.00" "3.00" (Just 3 :: Maybe Word8)
331− , MaybeExample "Word8 3.14" "3.14" (Nothing :: Maybe Word8)
332− , MaybeExample "Word8 -1" "-1" (Nothing :: Maybe Word8)
333− , MaybeExample "Word8 300" "300" (Nothing :: Maybe Word8)
334− -- Negative zero year, encoding never produces such:
335− , MaybeExample "Day -0000-02-03" "\"-0000-02-03\"" (Just (fromGregorian 0 2 3))
336− ]
337−
338−jsonExamples :: [Example]
339−jsonExamples =
340− [
341− Example "Either Left" "{\"Left\":1}" (Left 1 :: Either Int Int)
342− , Example "Either Right" "{\"Right\":1}" (Right 1 :: Either Int Int)
343− , Example "Nothing" "null" (Nothing :: Maybe Int)
344− , Example "Just" "1" (Just 1 :: Maybe Int)
345− , Example "Proxy Int" "null" (Proxy :: Proxy Int)
346− , Example "Tagged Char Int" "1" (Tagged 1 :: Tagged Char Int)
347−#if __GLASGOW_HASKELL__ >= 708
348− -- Test Tagged instance is polykinded
349− , Example "Tagged 123 Int" "1" (Tagged 1 :: Tagged 123 Int)
350−#endif
351− , Example "Const Char Int" "\"c\"" (Const 'c' :: Const Char Int)
352− , Example "Tuple" "[1,2]" ((1, 2) :: (Int, Int))
353− , Example "NonEmpty" "[1,2,3]" (1 :| [2, 3] :: NonEmpty Int)
354− , Example "Seq" "[1,2,3]" (Seq.fromList [1, 2, 3] :: Seq.Seq Int)
355− , Example "DList" "[1,2,3]" (DList.fromList [1, 2, 3] :: DList.DList Int)
356− , Example "()" "[]" ()
357−
358− , Example "HashMap Int Int" "{\"0\":1,\"2\":3}" (HM.fromList [(0,1),(2,3)] :: HM.HashMap Int Int)
359− , Example "Map Int Int" "{\"0\":1,\"2\":3}" (M.fromList [(0,1),(2,3)] :: M.Map Int Int)
360− , Example "Map (Tagged Int Int) Int" "{\"0\":1,\"2\":3}" (M.fromList [(Tagged 0,1),(Tagged 2,3)] :: M.Map (Tagged Int Int) Int)
361− , Example "Map [Int] Int" "[[[0],1],[[2],3]]" (M.fromList [([0],1),([2],3)] :: M.Map [Int] Int)
362− , Example "Map [Char] Int" "{\"ab\":1,\"cd\":3}" (M.fromList [("ab",1),("cd",3)] :: M.Map [Char] Int)
363− , Example "Map [I Char] Int" "{\"ab\":1,\"cd\":3}" (M.fromList [(map pure "ab",1),(map pure "cd",3)] :: M.Map [I Char] Int)
364−
365− , Example "nan :: Double" "null" (Approx $ 0/0 :: Approx Double)
366−
367− , Example "Ordering LT" "\"LT\"" LT
368− , Example "Ordering EQ" "\"EQ\"" EQ
369− , Example "Ordering GT" "\"GT\"" GT
370−
371− , Example "Float" "3.14" (3.14 :: Float)
372− , Example "Pico" "3.14" (3.14 :: Pico)
373− , Example "Scientific" "3.14" (3.14 :: Scientific)
374−
375− , Example "UUID" "\"c2cc10e1-57d6-4b6f-9899-38d972112d8c\"" $ UUID.fromWords
376− 0xc2cc10e1 0x57d64b6f 0x989938d9 0x72112d8c
377−
378− , Example "Set Int" "[1,2,3]" (Set.fromList [3, 2, 1] :: Set.Set Int)
379− , Example "IntSet" "[1,2,3]" (IntSet.fromList [3, 2, 1])
380− , Example "IntMap" "[[1,2],[3,4]]" (IntMap.fromList [(3,4), (1,2)] :: IntMap.IntMap Int)
381− , Example "Vector" "[1,2,3]" (Vector.fromList [1, 2, 3] :: Vector.Vector Int)
382− , Example "HashSet Int" "[1,2,3]" (HashSet.fromList [3, 2, 1] :: HashSet.HashSet Int)
383− , Example "Tree Int" "[1,[[2,[[3,[]],[4,[]]]],[5,[]]]]" (let n = Tree.Node in n 1 [n 2 [n 3 [], n 4 []], n 5 []] :: Tree.Tree Int)
384−
385− -- Three separate cases, as ordering in HashMap is not defined
386− , Example "HashMap Float Int, NaN" "{\"NaN\":1}" (Approx $ HM.singleton (0/0) 1 :: Approx (HM.HashMap Float Int))
387− , Example "HashMap Float Int, Infinity" "{\"Infinity\":1}" (HM.singleton (1/0) 1 :: HM.HashMap Float Int)
388− , Example "HashMap Float Int, +Infinity" "{\"-Infinity\":1}" (HM.singleton (negate 1/0) 1 :: HM.HashMap Float Int)
389−
390− -- Functors
391− , Example "Identity Int" "1" (pure 1 :: Identity Int)
392−
393− , Example "Identity Char" "\"x\"" (pure 'x' :: Identity Char)
394− , Example "Identity String" "\"foo\"" (pure "foo" :: Identity String)
395− , Example "[Identity Char]" "\"xy\"" ([pure 'x', pure 'y'] :: [Identity Char])
396−
397− , Example "Maybe Char" "\"x\"" (pure 'x' :: Maybe Char)
398− , Example "Maybe String" "\"foo\"" (pure "foo" :: Maybe String)
399− , Example "Maybe [Identity Char]" "\"xy\"" (pure [pure 'x', pure 'y'] :: Maybe [Identity Char])
400−
401− , Example "Day; year >= 1000" "\"1999-10-12\"" (fromGregorian 1999 10 12)
402− , Example "Day; year > 0 && < 1000" "\"0500-03-04\"" (fromGregorian 500 3 4)
403− , Example "Day; year == 0" "\"0000-02-20\"" (fromGregorian 0 2 20)
404− , Example "Day; year < 0" "\"-0234-01-01\"" (fromGregorian (-234) 1 1)
405− , Example "Day; year < -1000" "\"-1234-01-01\"" (fromGregorian (-1234) 1 1)
406−
407− , Example "Product I Maybe Int" "[1,2]" (Pair (pure 1) (pure 2) :: Product I Maybe Int)
408− , Example "Product I Maybe Int" "[1,null]" (Pair (pure 1) Nothing :: Product I Maybe Int)
409− , Example "Product I [] Char" "[\"a\",\"foo\"]" (Pair (pure 'a') "foo" :: Product I [] Char)
410−
411− , Example "Sum I [] Int: InL" "{\"InL\":1}" (InL (pure 1) :: Sum I [] Int)
412− , Example "Sum I [] Int: InR" "{\"InR\":[1,2]}" (InR [1, 2] :: Sum I [] Int)
413− , Example "Sum I [] Char: InR" "{\"InR\":\"foo\"}" (InR "foo" :: Sum I [] Char)
414−
415− , Example "Compose I I Int" "1" (pure 1 :: Compose I I Int)
416− , Example "Compose I [] Int" "[1]" (pure 1 :: Compose I [] Int)
417− , Example "Compose [] I Int" "[1]" (pure 1 :: Compose [] I Int)
418− , Example "Compose [] [] Int" "[[1]]" (pure 1 :: Compose [] [] Int)
419−
420− , Example "Compose I I Char" "\"x\"" (pure 'x' :: Compose I I Char)
421− , Example "Compose I [] Char" "\"x\"" (pure 'x' :: Compose I [] Char)
422− , Example "Compose [] I Char" "\"x\"" (pure 'x' :: Compose [] I Char)
423− , Example "Compose [] [] Char" "[\"x\"]" (pure 'x' :: Compose [] [] Char)
424−
425− , Example "Compose3 I I I Char" "\"x\"" (pure 'x' :: Compose3 I I I Char)
426− , Example "Compose3 I I [] Char" "\"x\"" (pure 'x' :: Compose3 I I [] Char)
427− , Example "Compose3 I [] I Char" "\"x\"" (pure 'x' :: Compose3 I [] I Char)
428− , Example "Compose3 I [] [] Char" "[\"x\"]" (pure 'x' :: Compose3 I [] [] Char)
429− , Example "Compose3 [] I I Char" "\"x\"" (pure 'x' :: Compose3 [] I I Char)
430− , Example "Compose3 [] I [] Char" "[\"x\"]" (pure 'x' :: Compose3 [] I [] Char)
431− , Example "Compose3 [] [] I Char" "[\"x\"]" (pure 'x' :: Compose3 [] [] I Char)
432− , Example "Compose3 [] [] [] Char" "[[\"x\"]]" (pure 'x' :: Compose3 [] [] [] Char)
433−
434− , Example "Compose3' I I I Char" "\"x\"" (pure 'x' :: Compose3' I I I Char)
435− , Example "Compose3' I I [] Char" "\"x\"" (pure 'x' :: Compose3' I I [] Char)
436− , Example "Compose3' I [] I Char" "\"x\"" (pure 'x' :: Compose3' I [] I Char)
437− , Example "Compose3' I [] [] Char" "[\"x\"]" (pure 'x' :: Compose3' I [] [] Char)
438− , Example "Compose3' [] I I Char" "\"x\"" (pure 'x' :: Compose3' [] I I Char)
439− , Example "Compose3' [] I [] Char" "[\"x\"]" (pure 'x' :: Compose3' [] I [] Char)
440− , Example "Compose3' [] [] I Char" "[\"x\"]" (pure 'x' :: Compose3' [] [] I Char)
441− , Example "Compose3' [] [] [] Char" "[[\"x\"]]" (pure 'x' :: Compose3' [] [] [] Char)
442−
443− , Example "MyEither Int String: Left" "42" (MyLeft 42 :: MyEither Int String)
444− , Example "MyEither Int String: Right" "\"foo\"" (MyRight "foo" :: MyEither Int String)
445−
446− -- newtypes from Monoid/Semigroup
447− , Example "Monoid.Dual Int" "2" (pure 2 :: Monoid.Dual Int)
448− , Example "Monoid.First Int" "2" (pure 2 :: Monoid.First Int)
449− , Example "Monoid.Last Int" "2" (pure 2 :: Monoid.Last Int)
450− , Example "Semigroup.Min Int" "2" (pure 2 :: Semigroup.Min Int)
451− , Example "Semigroup.Max Int" "2" (pure 2 :: Semigroup.Max Int)
452− , Example "Semigroup.First Int" "2" (pure 2 :: Semigroup.First Int)
453− , Example "Semigroup.Last Int" "2" (pure 2 :: Semigroup.Last Int)
454− , Example "Semigroup.WrappedMonoid Int" "2" (Semigroup.WrapMonoid 2 :: Semigroup.WrappedMonoid Int)
455− , Example "Semigroup.Option Just" "2" (pure 2 :: Semigroup.Option Int)
456− , Example "Semigroup.Option Nothing" "null" (Semigroup.Option (Nothing :: Maybe Bool))
457− ]
458−
459−
460−
461247------------------------------------------------------------------------------
462248-- These tests check that JSONPath is tracked correctly
463249-----------------------------------------------------------------------------