Skip to content

Commit

Permalink
Add Aeson roundtrip tests (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanjameswatson authored Apr 6, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 671e5aa commit cddcaea
Showing 7 changed files with 101 additions and 18 deletions.
5 changes: 5 additions & 0 deletions test/lowarn-test.cabal

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions test/package.yaml
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ category: System
description: Please see the README on GitHub at <https://github.com/jonathanjameswatson/lowarn/tree/main/test#readme>

dependencies:
- aeson
- base >= 4.7 && < 5
- filepath
- generics-sop >= 0.5.1 && < 0.6
@@ -27,6 +28,7 @@ dependencies:
- sop-core
- tasty
- tasty-golden
- text >= 1.2.5 && < 1.3
- transformers
- unix

@@ -54,6 +56,7 @@ tests:
- -with-rtsopts=-N
dependencies:
- following
- lowarn-aeson
- lowarn-arbitrary
- lowarn-test
- lowarn-test-types
50 changes: 44 additions & 6 deletions test/src/Test/Lowarn/Property.hs
Original file line number Diff line number Diff line change
@@ -1,19 +1,57 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

-- |
-- Module : Test.Lowarn.Property
-- SPDX-License-Identifier : MIT
-- Stability : stable
-- Portability : portable
--
-- Module for property testing utilities for Lowarn.
module Test.Lowarn.Property (roundTripProperty) where
module Test.Lowarn.Property
( roundTripPropertyShow,
parserCombinatorRoundTripProperty,
aesonRoundTripProperty,
)
where

import Data.Aeson
import Data.Proxy
import Data.Text.Lazy
import Data.Text.Lazy.Encoding
import Lowarn.ParserCombinators
import Test.QuickCheck
import Test.QuickCheck hiding (Success)
import Text.ParserCombinators.ReadP

-- | Give the property that the result of applying a custom function to a type
-- and parsing the result is the original value, with a custom show function
-- used for error messages.
roundTripPropertyShow ::
(Arbitrary a, Eq a) => (a -> String) -> (a -> b) -> (b -> Maybe a) -> Property
roundTripPropertyShow customShow to parse =
propertyForAllShrinkShow arbitrary shrink (return . customShow) $
\x -> Just x == parse (to x)

-- | Give the property that the result of parsing the result of showing a value,
-- with a given custom parser and show function, is the original value.
roundTripProperty :: (Arbitrary a, Eq a) => (a -> String) -> ReadP a -> Property
roundTripProperty customShow customParse =
propertyForAllShrinkShow arbitrary shrink (return . customShow) $
\a -> Just a == readWithParser customParse (customShow a)
parserCombinatorRoundTripProperty ::
(Arbitrary a, Eq a) => (a -> String) -> ReadP a -> Property
parserCombinatorRoundTripProperty customShow customParse =
roundTripPropertyShow customShow customShow (readWithParser customParse)

-- | Give the property that the result of converting a given value to and from
-- JSON is the original value.
aesonRoundTripProperty ::
forall a. (Arbitrary a, Eq a, ToJSON a, FromJSON a) => Proxy a -> Property
aesonRoundTripProperty =
const $
roundTripPropertyShow @a
(unpack . decodeUtf8 . encode)
toJSON
( ( \case
Error _ -> Nothing
Success x -> Just x
)
. fromJSON
)
15 changes: 12 additions & 3 deletions test/test/Spec/ProgramName.hs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE TypeApplications #-}

module Spec.ProgramName (programNameTests) where

import Data.Proxy
import Lowarn.ProgramName
import Lowarn.ProgramName.Aeson ()
import Lowarn.ProgramName.Arbitrary ()
import Test.Lowarn.Property
import Test.Tasty
@@ -11,19 +14,25 @@ import Test.Tasty.QuickCheck
programNameRoundTrip :: TestTree
programNameRoundTrip =
testProperty (show 'programNameRoundTrip) $
roundTripProperty unProgramName parseProgramName
parserCombinatorRoundTripProperty unProgramName parseProgramName

prefixModuleNameRoundTrip :: TestTree
prefixModuleNameRoundTrip =
testProperty (show 'prefixModuleNameRoundTrip) $
roundTripProperty
parserCombinatorRoundTripProperty
(showPrefixModuleName "EntryPoint")
(parsePrefixModuleName "EntryPoint")

encodedProgramNameRoundTrip :: TestTree
encodedProgramNameRoundTrip =
testProperty (show 'encodedProgramNameRoundTrip) $
aesonRoundTripProperty (Proxy :: Proxy ProgramName)

programNameTests :: TestTree
programNameTests =
testGroup
"Program name"
[ programNameRoundTrip,
prefixModuleNameRoundTrip
prefixModuleNameRoundTrip,
encodedProgramNameRoundTrip
]
16 changes: 13 additions & 3 deletions test/test/Spec/UpdateId.hs
Original file line number Diff line number Diff line change
@@ -2,7 +2,9 @@

module Spec.UpdateId (updateIdTests) where

import Data.Proxy
import Lowarn.UpdateId
import Lowarn.UpdateId.Aeson ()
import Lowarn.UpdateId.Arbitrary ()
import Test.Lowarn.Property
import Test.Tasty
@@ -11,17 +13,25 @@ import Test.Tasty.QuickCheck
updateIdRoundTrip :: TestTree
updateIdRoundTrip =
testProperty (show 'updateIdRoundTrip) $
roundTripProperty showUpdateId parseUpdateId
parserCombinatorRoundTripProperty showUpdateId parseUpdateId

updatePackageNameRoundTrip :: TestTree
updatePackageNameRoundTrip =
testProperty (show 'updatePackageNameRoundTrip) $
roundTripProperty showUpdatePackageName parseUpdatePackageName
parserCombinatorRoundTripProperty
showUpdatePackageName
parseUpdatePackageName

encodedUpdateIdRoundTrip :: TestTree
encodedUpdateIdRoundTrip =
testProperty (show 'encodedUpdateIdRoundTrip) $
aesonRoundTripProperty (Proxy :: Proxy UpdateId)

updateIdTests :: TestTree
updateIdTests =
testGroup
"Update ID"
[ updateIdRoundTrip,
updatePackageNameRoundTrip
updatePackageNameRoundTrip,
encodedUpdateIdRoundTrip
]
16 changes: 13 additions & 3 deletions test/test/Spec/VersionId.hs
Original file line number Diff line number Diff line change
@@ -2,7 +2,9 @@

module Spec.VersionId (versionIdTests) where

import Data.Proxy
import Lowarn.VersionId
import Lowarn.VersionId.Aeson ()
import Lowarn.VersionId.Arbitrary ()
import Test.Lowarn.Property
import Test.Tasty
@@ -11,17 +13,25 @@ import Test.Tasty.QuickCheck
versionIdRoundTrip :: TestTree
versionIdRoundTrip =
testProperty (show 'versionIdRoundTrip) $
roundTripProperty showVersionId parseVersionId
parserCombinatorRoundTripProperty showVersionId parseVersionId

versionPackageNameRoundTrip :: TestTree
versionPackageNameRoundTrip =
testProperty (show 'versionPackageNameRoundTrip) $
roundTripProperty showVersionPackageName parseVersionPackageName
parserCombinatorRoundTripProperty
showVersionPackageName
parseVersionPackageName

encodedVersionIdRoundTrip :: TestTree
encodedVersionIdRoundTrip =
testProperty (show 'encodedVersionIdRoundTrip) $
aesonRoundTripProperty (Proxy :: Proxy VersionId)

versionIdTests :: TestTree
versionIdTests =
testGroup
"Version ID"
[ versionIdRoundTrip,
versionPackageNameRoundTrip
versionPackageNameRoundTrip,
encodedVersionIdRoundTrip
]
14 changes: 11 additions & 3 deletions test/test/Spec/VersionNumber.hs
Original file line number Diff line number Diff line change
@@ -4,7 +4,9 @@ module Spec.VersionNumber (versionNumberTests) where

import Data.List.NonEmpty (NonEmpty ((:|)))
import Data.Maybe
import Data.Proxy
import Lowarn.VersionNumber
import Lowarn.VersionNumber.Aeson ()
import Lowarn.VersionNumber.Arbitrary ()
import Test.Lowarn.Property
import Test.Tasty
@@ -19,18 +21,24 @@ lexicographicOrdering = testProperty (show 'lexicographicOrdering) prop
withDotsRoundTrip :: TestTree
withDotsRoundTrip =
testProperty (show 'withDotsRoundTrip) $
roundTripProperty showWithDots parseWithDots
parserCombinatorRoundTripProperty showWithDots parseWithDots

withLettersRoundTrip :: TestTree
withLettersRoundTrip =
testProperty (show 'withLettersRoundTrip) $
roundTripProperty showWithLetters parseWithLetters
parserCombinatorRoundTripProperty showWithLetters parseWithLetters

encodedVersionNumberRoundTrip :: TestTree
encodedVersionNumberRoundTrip =
testProperty (show 'encodedVersionNumberRoundTrip) $
aesonRoundTripProperty (Proxy :: Proxy VersionNumber)

versionNumberTests :: TestTree
versionNumberTests =
testGroup
"Version number"
[ lexicographicOrdering,
withDotsRoundTrip,
withLettersRoundTrip
withLettersRoundTrip,
encodedVersionNumberRoundTrip
]

0 comments on commit cddcaea

Please sign in to comment.