on master help sign in
Pedantic tests
commit1b2b46c079215ca15d6e4d4682a224234eb71627 authorMichael Snoyman <michael@snoyman.com> dateThu 28 Jun 2018, 16:33 (8 years ago) parente645c63
1 file changed+73−90
test/Data/YamlSpec.hs+73−90
test/Data/YamlSpec.hs+73−90
@@ -46,6 +46,11 @@ data TestJSON = TestJSON
4646
4747deriveJSON defaultOptions ''TestJSON
4848
49+shouldDecode :: (Show a, D.FromJSON a, Eq a) => B8.ByteString -> a -> IO ()
50+shouldDecode bs expected = do
51+ actual <- D.decodeThrow bs
52+ actual `shouldBe` expected
53+
4954main :: IO ()
5055main = hspec spec
5156
@@ -120,13 +125,13 @@ spec = do
120125 describe "special keys" $ do
121126 let tester key = it (T.unpack key) $
122127 let value = object [key .= True]
123− in D.decode (D.encode value) `shouldBe` Just value
128+ in D.encode value `shouldDecode` value
124129 mapM_ tester specialStrings
125130
126131 describe "special values" $ do
127132 let tester value = it (T.unpack value) $
128133 let value' = object ["foo" .= value]
129− in D.decode (D.encode value') `shouldBe` Just value'
134+ in D.encode value' `shouldDecode` value'
130135 mapM_ tester specialStrings
131136
132137 describe "decodeFileEither" $ do
@@ -149,13 +154,13 @@ spec = do
149154 let special = words "y Y On ON false 12345 12345.0 12345a 12e3"
150155 forM_ special $ \w -> it w $
151156 let v = object ["word" .= w]
152− in D.decode (D.encode v) `shouldBe` Just v
157+ in D.encode v `shouldDecode` v
153158 it "no tags" $ D.encode (object ["word" .= ("true" :: String)]) `shouldBe` "word: 'true'\n"
154159
155160 it "aliases in keys #49" caseIssue49
156161
157162 it "serialization of +123 #64" $ do
158− D.decode (D.encode ("+123" :: String)) `shouldBe` Just ("+123" :: String)
163+ D.encode ("+123" :: String) `shouldDecode` ("+123" :: String)
159164
160165 it "preserves Scientific precision" casePreservesScientificPrecision
161166
@@ -299,9 +304,6 @@ mappingKey :: D.Value-> String -> D.Value
299304mappingKey (D.Object m) k = (fromJust . M.lookup (T.pack k) $ m)
300305mappingKey _ _ = error "expected Object"
301306
302−decodeYaml :: String -> Maybe D.Value
303−decodeYaml s = D.decode $ B8.pack s
304−
305307sample :: D.Value
306308sample = array
307309 [ D.String "foo"
@@ -313,20 +315,17 @@ sample = array
313315 ]
314316
315317caseEncodeDecodeData :: Assertion
316−caseEncodeDecodeData = do
317− let out = D.decode $ D.encode sample
318− out @?= Just sample
318+caseEncodeDecodeData = D.encode sample `shouldDecode` sample
319319
320320caseEncodeDecodeDataPretty :: Assertion
321−caseEncodeDecodeDataPretty = do
322− let out = D.decode $ Pretty.encodePretty Pretty.defConfig sample
323− out @?= Just sample
321+caseEncodeDecodeDataPretty =
322+ Pretty.encodePretty Pretty.defConfig sample `shouldDecode` sample
324323
325324caseEncodeDecodeFileData :: Assertion
326325caseEncodeDecodeFileData = withFile "" $ \fp -> do
327326 D.encodeFile fp sample
328− out <- D.decodeFile fp
329− out @?= Just sample
327+ out <- D.decodeFileThrow fp
328+ out @?= sample
330329
331330caseEncodeDecodeNonAsciiFileData :: Assertion
332331caseEncodeDecodeNonAsciiFileData = do
@@ -334,89 +333,74 @@ caseEncodeDecodeNonAsciiFileData = do
334333 inTempDirectory $ do
335334 createDirectory "accenté"
336335 D.encodeFile "accenté/bar.yaml" mySample
337− out1 <- D.decodeFile "accenté/bar.yaml"
338− out1 @?= Just mySample
336+ out1 <- D.decodeFileThrow "accenté/bar.yaml"
337+ out1 @?= mySample
339338
340339 c <- readFile "test/resources/accent/foo.yaml"
341340 inTempDirectory $ do
342341 createDirectoryIfMissing True "test/resources/unicode/accenté/"
343342 writeFile "test/resources/unicode/accenté/foo.yaml" c
344− out2 <- D.decodeFile "test/resources/unicode/accenté/foo.yaml"
345− out2 @?= Just mySample
343+ out2 <- D.decodeFileThrow "test/resources/unicode/accenté/foo.yaml"
344+ out2 @?= mySample
346345
347346caseEncodeDecodeStrings :: Assertion
348−caseEncodeDecodeStrings = do
349− let out = D.decode $ D.encode sample
350− out @?= Just sample
347+caseEncodeDecodeStrings = D.encode sample `shouldDecode` sample
351348
352349caseEncodeDecodeStringsPretty :: Assertion
353−caseEncodeDecodeStringsPretty = do
354− let out = D.decode $ Pretty.encodePretty Pretty.defConfig sample
355− out @?= Just sample
350+caseEncodeDecodeStringsPretty =
351+ Pretty.encodePretty Pretty.defConfig sample `shouldDecode` sample
356352
357353caseDecodeInvalid :: Assertion
358−caseDecodeInvalid = do
359− let invalid = B8.pack "\tthis is 'not' valid :-)"
360− Nothing @=? (D.decode invalid :: Maybe D.Value)
354+caseDecodeInvalid =
355+ D.decodeThrow "\tthis is 'not' valid :-)" `shouldBe`
356+ (Nothing :: Maybe D.Value)
361357
362358caseSimpleScalarAlias :: Assertion
363−caseSimpleScalarAlias = do
364− let maybeRes = decodeYaml "- &anch foo\n- baz\n- *anch"
365− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
366− let res = fromJust maybeRes
367− res @?= array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo")]
359+caseSimpleScalarAlias =
360+ "- &anch foo\n- baz\n- *anch" `shouldDecode`
361+ array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo")]
368362
369363caseSimpleSequenceAlias :: Assertion
370−caseSimpleSequenceAlias = do
371− let maybeRes = decodeYaml "seq: &anch\n - foo\n - baz\nseq2: *anch"
372− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
373− let res = fromJust maybeRes
374− res @?= object [("seq", array [(mkScalar "foo"), (mkScalar "baz")]), ("seq2", array [(mkScalar "foo"), (mkScalar "baz")])]
364+caseSimpleSequenceAlias =
365+ "seq: &anch\n - foo\n - baz\nseq2: *anch" `shouldDecode`
366+ object [("seq", array [(mkScalar "foo"), (mkScalar "baz")]), ("seq2", array [(mkScalar "foo"), (mkScalar "baz")])]
375367
376368caseSimpleMappingAlias :: Assertion
377−caseSimpleMappingAlias = do
378− let maybeRes = decodeYaml "map: &anch\n key1: foo\n key2: baz\nmap2: *anch"
379− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
380− let res = fromJust maybeRes
381− res @?= object [(T.pack "map", object [("key1", mkScalar "foo"), ("key2", (mkScalar "baz"))]), (T.pack "map2", object [("key1", (mkScalar "foo")), ("key2", mkScalar "baz")])]
369+caseSimpleMappingAlias =
370+ "map: &anch\n key1: foo\n key2: baz\nmap2: *anch" `shouldDecode`
371+ object [(T.pack "map", object [("key1", mkScalar "foo"), ("key2", (mkScalar "baz"))]), (T.pack "map2", object [("key1", (mkScalar "foo")), ("key2", mkScalar "baz")])]
382372
383373caseMappingAliasBeforeAnchor :: Assertion
384−caseMappingAliasBeforeAnchor = do
385− let res = decodeYaml "map: *anch\nmap2: &anch\n key1: foo\n key2: baz"
386− isNothing res @? "decode should return Nothing due to unknown alias"
374+caseMappingAliasBeforeAnchor =
375+ case D.decodeThrow "map: *anch\nmap2: &anch\n key1: foo\n key2: baz" of
376+ Nothing -> pure ()
377+ Just (_ :: D.Value) -> error "decode should return Nothing due to unknown alias"
387378
388379caseMappingAliasInsideAnchor :: Assertion
389380caseMappingAliasInsideAnchor = do
390− let res = decodeYaml "map: &anch\n key1: foo\n key2: *anch"
391− isNothing res @? "decode should return Nothing due to unknown alias"
381+ case D.decodeThrow "map: &anch\n key1: foo\n key2: *anch" of
382+ Nothing -> pure ()
383+ Just (_ :: D.Value) -> error "decode should return Nothing due to unknown alias"
392384
393385caseScalarAliasOverriding :: Assertion
394−caseScalarAliasOverriding = do
395− let maybeRes = decodeYaml "- &anch foo\n- baz\n- *anch\n- &anch boo\n- buz\n- *anch"
396− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
397− let res = fromJust maybeRes
398− res @?= array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo"), (mkScalar "boo"), (mkScalar "buz"), (mkScalar "boo")]
386+caseScalarAliasOverriding =
387+ "- &anch foo\n- baz\n- *anch\n- &anch boo\n- buz\n- *anch" `shouldDecode`
388+ array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo"), (mkScalar "boo"), (mkScalar "buz"), (mkScalar "boo")]
399389
400390caseAllKeysShouldBeUnique :: Assertion
401391caseAllKeysShouldBeUnique = do
402− let maybeRes = decodeYaml "foo1: foo\nfoo2: baz\nfoo1: buz"
403− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
404− let res = fromJust maybeRes
405− mappingKey res "foo1" @?= (mkScalar "buz")
392+ res <- D.decodeThrow "foo1: foo\nfoo2: baz\nfoo1: buz"
393+ mappingKey res "foo1" `shouldBe` mkScalar "buz"
406394
407395caseSimpleMappingMerge :: Assertion
408396caseSimpleMappingMerge = do
409− let maybeRes = decodeYaml "foo1: foo\nfoo2: baz\n<<:\n foo1: buz\n foo3: fuz"
410− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
411− let res = fromJust maybeRes
412− mappingKey res "foo1" @?= (mkScalar "foo")
413− mappingKey res "foo3" @?= (mkScalar "fuz")
397+ res <- D.decodeThrow "foo1: foo\nfoo2: baz\n<<:\n foo1: buz\n foo3: fuz"
398+ mappingKey res "foo1" `shouldBe` mkScalar "foo"
399+ mappingKey res "foo3" `shouldBe` mkScalar "fuz"
414400
415401caseMergeSequence :: Assertion
416402caseMergeSequence = do
417− let maybeRes = decodeYaml "m1: &m1\n k1: !!str 1\n k2: !!str 2\nm2: &m2\n k1: !!str 3\n k3: !!str 4\nfoo1: foo\n<<: [ *m1, *m2 ]"
418− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
419− let res = fromJust maybeRes
403+ res <- D.decodeThrow "m1: &m1\n k1: !!str 1\n k2: !!str 2\nm2: &m2\n k1: !!str 3\n k3: !!str 4\nfoo1: foo\n<<: [ *m1, *m2 ]"
420404 mappingKey res "foo1" @?= (mkScalar "foo")
421405 mappingKey res "k1" @?= (D.String "1")
422406 mappingKey res "k2" @?= (D.String "2")
@@ -424,7 +408,7 @@ caseMergeSequence = do
424408
425409caseDataTypes :: Assertion
426410caseDataTypes =
427− D.decode (D.encode val) @?= Just val
411+ D.encode val `shouldDecode` val
428412 where
429413 val = object
430414 [ ("string", D.String "foo")
@@ -437,11 +421,11 @@ caseDataTypes =
437421
438422caseEncodeInvalidNumbers :: Assertion
439423caseEncodeInvalidNumbers =
440− D.encode (D.String ".") @?= ".\n"
424+ D.encode (D.String ".") `shouldBe` ".\n"
441425
442426caseDataTypesPretty :: Assertion
443427caseDataTypesPretty =
444− D.decode (Pretty.encodePretty Pretty.defConfig val) @?= Just val
428+ Pretty.encodePretty Pretty.defConfig val `shouldDecode` val
445429 where
446430 val = object
447431 [ ("string", D.String "foo")
@@ -452,21 +436,21 @@ caseDataTypesPretty =
452436 , ("null", D.Null)
453437 ]
454438caseQuotedNumber, caseUnquotedNumber, caseAttribNumber, caseIntegerDecimals :: Assertion
455−caseQuotedNumber = D.decode "foo: \"1234\"" @?= Just (object [("foo", D.String "1234")])
456−caseUnquotedNumber = D.decode "foo: 1234" @?= Just (object [("foo", D.Number 1234)])
457−caseAttribNumber = D.decode "foo: !!str 1234" @?= Just (object [("foo", D.String "1234")])
458−caseIntegerDecimals = D.encode (1 :: Int) @?= "1\n"
439+caseQuotedNumber = "foo: \"1234\"" `shouldDecode` object [("foo", D.String "1234")]
440+caseUnquotedNumber = "foo: 1234" `shouldDecode` object [("foo", D.Number 1234)]
441+caseAttribNumber = "foo: !!str 1234" `shouldDecode` object [("foo", D.String "1234")]
442+caseIntegerDecimals = "1\n" `shouldDecode` (1 :: Int)
459443
460−obj :: Maybe D.Value
461−obj = Just (object [("foo", D.Bool False), ("bar", D.Bool True), ("baz", D.Bool True)])
444+obj :: D.Value
445+obj = object [("foo", D.Bool False), ("bar", D.Bool True), ("baz", D.Bool True)]
462446
463447caseLowercaseBool, caseUppercaseBool, caseTitlecaseBool :: Assertion
464−caseLowercaseBool = D.decode "foo: off\nbar: y\nbaz: true" @?= obj
465−caseUppercaseBool = D.decode "foo: FALSE\nbar: Y\nbaz: ON" @?= obj
466−caseTitlecaseBool = D.decode "foo: No\nbar: Yes\nbaz: True" @?= obj
448+caseLowercaseBool = "foo: off\nbar: y\nbaz: true" `shouldDecode` obj
449+caseUppercaseBool = "foo: FALSE\nbar: Y\nbaz: ON" `shouldDecode` obj
450+caseTitlecaseBool = "foo: No\nbar: Yes\nbaz: True" `shouldDecode` obj
467451
468452caseEmptyInput :: Assertion
469−caseEmptyInput = D.decodeEither B8.empty @?= Right D.Null
453+caseEmptyInput = B8.empty `shouldDecode` D.Null
470454
471455caseEmptyInputFile :: Assertion
472456caseEmptyInputFile = do
@@ -474,7 +458,7 @@ caseEmptyInputFile = do
474458 either (Left . D.prettyPrintParseException) Right out @?= Right D.Null
475459
476460caseCommentOnlyInput :: Assertion
477−caseCommentOnlyInput = D.decodeEither "# comment\n" @?= Right D.Null
461+caseCommentOnlyInput = "# comment\n" `shouldDecode` D.Null
478462
479463caseCommentOnlyInputFile :: Assertion
480464caseCommentOnlyInputFile = do
@@ -483,13 +467,12 @@ caseCommentOnlyInputFile = do
483467
484468checkNull :: T.Text -> Spec
485469checkNull x =
486− it ("null recognized: " ++ show x) assertion
487− where
488− assertion = Just (object [("foo", D.Null)]) @=? D.decode (B8.pack $ "foo: " ++ T.unpack x)
470+ it ("null recognized: " ++ show x) $
471+ B8.pack ("foo: " ++ T.unpack x) `shouldDecode` object [("foo", D.Null)]
489472
490473caseStripAlias :: Assertion
491474caseStripAlias =
492− D.decode src @?= Just (object
475+ src `shouldDecode` object
493476 [ "Default" .= object
494477 [ "foo" .= (1 :: Int)
495478 , "bar" .= (2 :: Int)
@@ -499,24 +482,24 @@ caseStripAlias =
499482 , "bar" .= (2 :: Int)
500483 , "key" .= (3 :: Int)
501484 ]
502− ])
485+ ]
503486 where
504487 src = "Default: &def\n foo: 1\n bar: 2\nObj:\n <<: *def\n key: 3\n"
505488
506489caseIssue49 :: Assertion
507490caseIssue49 =
508− D.decodeEither src @?= Right (object
491+ src `shouldDecode` object
509492 [ "a" .= object [ "value" .= (1.0 :: Double) ]
510493 , "b" .= object [ "value" .= (1.2 :: Double) ]
511− ])
494+ ]
512495 where
513496 src = "---\na:\n &id5 value: 1.0\nb:\n *id5: 1.2"
514497
515498-- | We cannot guarantee this before aeson started using 'Scientific'.
516499casePreservesScientificPrecision :: Assertion
517500casePreservesScientificPrecision = do
518− D.decodeEither "x: 1e-100000" @?= Right (object
519− [ "x" .= D.Number (read "1e-100000") ])
501+ "x: 1e-100000" `shouldDecode` object
502+ [ "x" .= D.Number (read "1e-100000") ]
520503 -- Note that this ought to work also without 'Scientific', given
521504 -- that @read (show "9.78159610558926e-5") == 9.78159610558926e-5@.
522505 -- However, it didn't work (and still doesn't work with aeson < 0.7)
@@ -526,8 +509,8 @@ casePreservesScientificPrecision = do
526509 -- can be;
527510 -- * Even if we used 'Data.Text.Read.rational' we would not get good
528511 -- results, because of <https://github.com/bos/text/issues/34>.
529− D.decodeEither "x: 9.78159610558926e-5" @?= Right (object
530− [ "x" .= D.Number (read "9.78159610558926e-5") ])
512+ "x: 9.78159610558926e-5" `shouldDecode` object
513+ [ "x" .= D.Number (read "9.78159610558926e-5") ]
531514
532515caseTruncatesFiles :: Assertion
533516caseTruncatesFiles = withSystemTempFile "truncate.yaml" $ \fp h -> do