11{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE NamedFieldPuns #-}
33{-# LANGUAGE TypeApplications #-}
4+ {-# LANGUAGE ViewPatterns #-}
45
56-- | Utility functions for using the mockchain types in @hunit@ or @QuickCheck@ tests
67module Convex.MockChain.Utils (
@@ -22,12 +23,13 @@ module Convex.MockChain.Utils (
2223 -- * Options for running mockchain testCase
2324 Options (.. ),
2425 defaultOptions ,
26+ modifyTransactionLimits ,
2527) where
2628
2729import Cardano.Api (ConwayEra )
2830import Cardano.Api qualified as C
2931import Control.Exception (SomeException , try )
30- import Control.Lens ((^.) )
32+ import Control.Lens ((&) , (.~) , ( ^.) )
3133import Control.Monad.Except (ExceptT , runExceptT )
3234import Control.Monad.IO.Class (liftIO )
3335import Convex.Class (coverageData )
@@ -39,19 +41,25 @@ import Convex.MockChain (
3941 runMockchain ,
4042 runMockchain0IOWith ,
4143 )
44+
45+ import Cardano.Ledger.Core qualified as L
4246import Convex.MockChain.Defaults qualified as Defaults
43- import Convex.NodeParams (NodeParams )
47+ import Convex.NodeParams (NodeParams ( .. ) )
4448import Convex.Wallet.MockWallet qualified as Wallet
4549import Data.Functor.Identity (Identity )
4650import Data.IORef (IORef , modifyIORef )
47- import PlutusTx.Coverage (CoverageData )
51+ import Data.Maybe (fromMaybe )
52+ import Data.Word (Word32 )
53+ import PlutusTx.Coverage (CoverageData , coverageDataFromLogMsg )
4854import Test.HUnit (Assertion )
4955import Test.QuickCheck (
5056 Property ,
5157 Testable (.. ),
5258 counterexample ,
5359 )
5460import Test.QuickCheck.Monadic (PropertyM (.. ), monadic , monadicIO )
61+ import Text.Read (readMaybe )
62+ import Text.Show.Pretty (ppShow )
5563
5664data Options era = Options
5765 { params :: NodeParams era
@@ -65,6 +73,14 @@ defaultOptions =
6573 , coverageRef = Nothing
6674 }
6775
76+ -- | Modify the maximum transaction size in the protocol parameters of the given options
77+ modifyTransactionLimits :: Options ConwayEra -> Word32 -> Options ConwayEra
78+ modifyTransactionLimits opts@ Options {params = Defaults. pParams -> pp} newVal =
79+ -- TODO: use lenses to make this cleaner
80+ opts
81+ { params = (params opts){npProtocolParameters = C. LedgerProtocolParameters $ pp & L. ppMaxTxSizeL .~ newVal}
82+ }
83+
6884-- | Run the 'Mockchain' action and fail if there is an error
6985mockchainSucceeds :: MockchainIO C. ConwayEra a -> Assertion
7086mockchainSucceeds = mockchainSucceedsWith Defaults. nodeParams
@@ -78,13 +94,11 @@ mockchainSucceedsWithOptions :: (C.IsShelleyBasedEra era) => Options era -> Mock
7894mockchainSucceedsWithOptions Options {params, coverageRef} action =
7995 try @ SomeException (runMockchain0IOWith Wallet. initialUTxOs params action) >>= \ case
8096 Right (_, st) -> do
81- case coverageRef of
82- Nothing -> pure ()
83- Just ref -> do
84- let covData = st ^. coverageData
85- modifyIORef ref (<> covData)
97+ appendCovData coverageRef $ st ^. coverageData
8698 pure ()
87- Left err -> fail (show err)
99+ Left err -> do
100+ appendCovData coverageRef $ tryExtractCovverageData err
101+ fail (show err)
88102
89103{- | Run the 'Mockchain' action, fail if it succeeds, and handle the error
90104 appropriately.
@@ -106,13 +120,13 @@ mockchainFailsWithOptions :: (C.IsShelleyBasedEra era) => Options era -> Mockcha
106120mockchainFailsWithOptions Options {params, coverageRef} action handleError =
107121 try @ SomeException (runMockchain0IOWith Wallet. initialUTxOs params action) >>= \ case
108122 Right (_, st) -> do
109- case coverageRef of
110- Nothing -> pure ()
111- Just ref -> do
112- let covData = st ^. coverageData
113- modifyIORef ref (<> covData)
123+ let covData = st ^. coverageData
124+ appendCovData coverageRef covData
114125 fail " mockchainFailsWithOptions: Did not fail"
115- Left err -> handleError err
126+ Left err -> do
127+ let covData = tryExtractCovverageData err
128+ appendCovData coverageRef covData
129+ handleError err
116130
117131{- | Run the 'Mockchain' action as a QuickCheck property, considering all 'MockchainError'
118132as test failures.
@@ -145,21 +159,16 @@ runMockchainPropWithOptions
145159 -- ^ The mockchain action to run
146160 -> Property
147161runMockchainPropWithOptions Options {params, coverageRef} utxos =
148- monadic runFinalPredicate
149- where
150- runFinalPredicate
151- :: MockchainT era Identity Property
152- -> Property
153- runFinalPredicate m =
154- let (prop', state) = runMockchain m params iState
155- in case coverageRef of
156- Nothing -> prop'
157- Just ref -> monadicIO $ do
158- liftIO $ do
159- let covData = state ^. coverageData
160- modifyIORef ref (<> covData)
161- pure prop'
162- iState = initialStateFor params utxos
162+ let iState = initialStateFor params utxos
163+ in monadic $ \ m ->
164+ let (prop', state) = runMockchain m params iState
165+ in case coverageRef of
166+ Nothing -> prop'
167+ Just ref -> monadicIO $ do
168+ liftIO $ do
169+ let covData = state ^. coverageData
170+ modifyIORef ref (<> covData)
171+ pure prop'
163172
164173{- | Run the 'Mockchain' action as a QuickCheck property, using the default node params
165174 and initial distribution, and considering all 'MockchainError's as test failures.
@@ -180,3 +189,20 @@ instance (Show e, Testable a) => Testable (TestableErr e a) where
180189-}
181190runTestableErr :: forall e m a . (Functor m ) => ExceptT e m a -> m (TestableErr e a )
182191runTestableErr = fmap TestableErr . runExceptT
192+
193+ appendCovData :: Maybe (IORef CoverageData ) -> CoverageData -> IO ()
194+ appendCovData Nothing _ = pure ()
195+ appendCovData (Just ref) cd = modifyIORef ref (<> cd)
196+
197+ -- TODO: ugly hack, we have to somehow extract the coverage data from the Exception
198+ -- the problem is that BalanceError is exposed on the upper level, so we cannot pattern match on it directly
199+ tryExtractCovverageData :: SomeException -> CoverageData
200+ tryExtractCovverageData e = mconcat $ map coverageDataFromLogMsg xs
201+ where
202+ xs = fromErrToStringList e
203+ dropO = dropWhile (/= ' [' )
204+ dropC = dropWhile (/= ' ]' )
205+ tail' [] = []
206+ tail' (_ : xs') = xs'
207+ parse = reverse . dropC . tail' . dropC . reverse . dropO . tail' . dropO
208+ fromErrToStringList err = fromMaybe [] (readMaybe @ [String ] $ parse $ show err)
0 commit comments