From a2521c174c6169f11149164160fe2a88447ca324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Hurlin?= Date: Thu, 22 Aug 2024 17:19:42 +0200 Subject: [PATCH] Add tests for the new Parsec parsers --- cardano-cli/cardano-cli.cabal | 2 + .../test/cardano-cli-test/Test/Cli/Parser.hs | 99 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 cardano-cli/test/cardano-cli-test/Test/Cli/Parser.hs diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 71f6aa0dfa..8e496db145 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -323,6 +323,7 @@ test-suite cardano-cli-test filepath, hedgehog, hedgehog-extras ^>=0.6.1.0, + parsec, regex-tdfa, tasty, tasty-hedgehog, @@ -340,6 +341,7 @@ test-suite cardano-cli-test Test.Cli.ITN Test.Cli.Json Test.Cli.MonadWarning + Test.Cli.Parser Test.Cli.Pioneers.Exercise1 Test.Cli.Pioneers.Exercise2 Test.Cli.Pioneers.Exercise3 diff --git a/cardano-cli/test/cardano-cli-test/Test/Cli/Parser.hs b/cardano-cli/test/cardano-cli-test/Test/Cli/Parser.hs new file mode 100644 index 0000000000..4c6beec458 --- /dev/null +++ b/cardano-cli/test/cardano-cli-test/Test/Cli/Parser.hs @@ -0,0 +1,99 @@ +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} + +module Test.Cli.Parser + ( hprop_integral_reader + , hprop_integral_pair_reader_positive + , hprop_integral_pair_reader_negative + ) +where + +import Cardano.CLI.EraBased.Options.Common (integralParsecParser, + pairIntegralParsecParser) + +import Data.Bits (Bits) +import Data.Data (Proxy (..), Typeable) +import Data.Either (isLeft, isRight) +import Data.Word (Word16) +import qualified Text.Parsec as Parsec + +import Hedgehog (Gen, Property, assert, property) +import Hedgehog.Extras (propertyOnce) +import qualified Hedgehog.Gen as Gen +import Hedgehog.Internal.Property (forAll) +import qualified Hedgehog.Range as Gen +import qualified Hedgehog.Range as Range + +-- | Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/integral reader/"'@ +hprop_integral_reader :: Property +hprop_integral_reader = property $ do + assert $ isRight $ parse @Word "0" + assert $ isRight $ parse @Word "42" + assert $ isLeft $ parse @Word "-1" + assert $ isLeft $ parse @Word "18446744073709551616" + assert $ isLeft $ parse @Word "-1987090" + + w <- forAll $ Gen.word $ Gen.linear minBound maxBound + assert $ isRight $ parse @Word (show w) + + assert $ isRight $ parse @Word16 "0" + assert $ isRight $ parse @Word16 "42" + assert $ isLeft $ parse @Word16 "-1" + assert $ isLeft $ parse @Word16 "65536" + assert $ isLeft $ parse @Word16 "298709870987" + assert $ isLeft $ parse @Word16 "-1987090" + where + parse :: (Typeable a, Integral a, Bits a) => String -> Either String a + parse s = + case Parsec.runParser integralParsecParser () "" s of + Left parsecError -> Left $ show parsecError + Right x -> Right x + +-- | Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/integral pair reader positive/"'@ +hprop_integral_pair_reader_positive :: Property +hprop_integral_pair_reader_positive = property $ do + validArbitraryTuple <- forAll $ genNumberTuple (Proxy :: Proxy Word) + assert $ isRight $ parse @Word validArbitraryTuple + where + parse :: (Typeable a, Integral a, Bits a) => String -> Either String (a, a) + parse s = + case Parsec.runParser pairIntegralParsecParser () "" s of + Left parsecError -> Left $ show parsecError + Right x -> Right x + +genNumberTuple :: forall a. Integral a => Show a => Proxy a -> Gen String +genNumberTuple _ = do + x :: a <- Gen.integral (Range.linear 0 100) + y :: a <- Gen.integral (Range.linear 0 100) + space0 <- genArbitrarySpace + space1 <- genArbitrarySpace + space2 <- genArbitrarySpace + space3 <- genArbitrarySpace + return $ + space0 ++ "(" ++ space2 ++ show x ++ space1 ++ "," ++ space2 ++ show y ++ space1 ++ ")" ++ space3 + +genArbitrarySpace :: Gen String +genArbitrarySpace = Gen.string (Range.linear 0 5) (return ' ') + +-- | Execute me with: +-- @cabal test cardano-cli-test --test-options '-p "/integral pair reader negative/"'@ +hprop_integral_pair_reader_negative :: Property +hprop_integral_pair_reader_negative = propertyOnce $ do + assert $ isLeft $ parse @Word "(0, 0, 0)" + assert $ isLeft $ parse @Word "(-1, 0)" + assert $ isLeft $ parse @Word "(18446744073709551616, 0)" + assert $ isLeft $ parse @Word "(0, 18446744073709551616)" + assert $ isLeft $ parse @Word "(0, -1)" + assert $ isLeft $ parse @Word "0, 0)" + assert $ isLeft $ parse @Word "(0, 0" + assert $ isLeft $ parse @Word "(0 0)" + assert $ isLeft $ parse @Word "( 0, 0" + where + parse :: (Typeable a, Integral a, Bits a) => String -> Either String (a, a) + parse s = + case Parsec.runParser pairIntegralParsecParser () "" s of + Left parsecError -> Left $ show parsecError + Right x -> Right x