diff --git a/eras/alonzo/test-suite/cardano-ledger-alonzo-test.cabal b/eras/alonzo/test-suite/cardano-ledger-alonzo-test.cabal index 6abbef44e99..c16f8d3c35d 100644 --- a/eras/alonzo/test-suite/cardano-ledger-alonzo-test.cabal +++ b/eras/alonzo/test-suite/cardano-ledger-alonzo-test.cabal @@ -82,7 +82,6 @@ test-suite cardano-ledger-alonzo-test -rtsopts build-depends: - QuickCheck, aeson >=2, base, base16-bytestring, @@ -99,10 +98,8 @@ test-suite cardano-ledger-alonzo-test cardano-slotting, cardano-strict-containers, containers, + hspec, microlens, plutus-ledger-api, small-steps:{small-steps, testlib} >=1.1, - tasty, - tasty-hunit, - tasty-quickcheck, time, diff --git a/eras/alonzo/test-suite/test/Test/Cardano/Ledger/Alonzo/ChainTrace.hs b/eras/alonzo/test-suite/test/Test/Cardano/Ledger/Alonzo/ChainTrace.hs index 6a75cbcc017..b979995e79e 100644 --- a/eras/alonzo/test-suite/test/Test/Cardano/Ledger/Alonzo/ChainTrace.hs +++ b/eras/alonzo/test-suite/test/Test/Cardano/Ledger/Alonzo/ChainTrace.hs @@ -39,6 +39,7 @@ import Lens.Micro.Extras (view) import Test.Cardano.Ledger.Alonzo.AlonzoEraGen (sumCollateral) import Test.Cardano.Ledger.Alonzo.EraMapping () import Test.Cardano.Ledger.Alonzo.Trace () +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Shelley.Constants (defaultConstants) import Test.Cardano.Ledger.Shelley.Rules.Chain ( CHAIN, @@ -51,15 +52,6 @@ import Test.Cardano.Ledger.Shelley.Rules.TestChain ( ledgerTraceFromBlock, ) import Test.Control.State.Transition.Trace (SourceSignalTarget (..), sourceSignalTargets) -import Test.QuickCheck ( - Property, - conjoin, - counterexample, - (.&&.), - (===), - ) -import Test.Tasty -import qualified Test.Tasty.QuickCheck as TQC instance Embed (AlonzoBBODY AlonzoEra) (CHAIN AlonzoEra) where wrapFailed = BbodyFailure @@ -71,9 +63,9 @@ traceLen = 100 data HasPlutus = HasPlutus | NoPlutus deriving (Show) -tests :: TestTree +tests :: Spec tests = - TQC.testProperty "alonzo specific" $ + prop "alonzo specific" $ forAllChainTrace @AlonzoEra traceLen defaultConstants $ \tr -> conjoin $ map alonzoSpecificProps (sourceSignalTargets tr) diff --git a/eras/alonzo/test-suite/test/Test/Cardano/Ledger/Alonzo/Golden.hs b/eras/alonzo/test-suite/test/Test/Cardano/Ledger/Alonzo/Golden.hs index 5e75fb50a52..e057c9e199b 100644 --- a/eras/alonzo/test-suite/test/Test/Cardano/Ledger/Alonzo/Golden.hs +++ b/eras/alonzo/test-suite/test/Test/Cardano/Ledger/Alonzo/Golden.hs @@ -68,8 +68,7 @@ import Test.Cardano.Protocol.TPraos.Examples ( ProtocolLedgerExamples (..), ledgerExamplesAlonzo, ) -import Test.Tasty (TestTree, testGroup) -import Test.Tasty.HUnit (Assertion, testCase, (@?=)) +import Test.Hspec (Expectation, Spec, describe, it, shouldBe) readDataFile :: FilePath -> IO BSL.ByteString readDataFile name = getDataFileName name >>= BSL.readFile @@ -84,241 +83,229 @@ coinsPerUTxOWordLocal = quot minUTxOValueShelleyMA utxoEntrySizeWithoutValLocal calcMinUTxO :: AlonzoTxOut AlonzoEra -> Coin calcMinUTxO tout = Coin (utxoEntrySize tout * coinsPerUTxOWordLocal) -tests :: TestTree +tests :: Spec tests = - testGroup - "Alonzo Golden Tests" - [ goldenCborSerialization - , goldenJsonSerialization - , goldenMinFee - , goldenScriptIntegrity - , goldenGenesisSerialization - , goldenUTxOEntryMinAda - ] + describe "Alonzo Golden Tests" $ do + goldenCborSerialization + goldenJsonSerialization + goldenMinFee + goldenScriptIntegrity + goldenGenesisSerialization + goldenUTxOEntryMinAda -- | (heapWords of a DataHash) * coinsPerUTxOWordLocal is 344820 -goldenUTxOEntryMinAda :: TestTree +goldenUTxOEntryMinAda :: Spec goldenUTxOEntryMinAda = - testGroup - "golden tests - UTxOEntryMinAda" - [ testCase "one policy, one (smallest) name, yes datum hash" $ - calcMinUTxO - ( AlonzoTxOut - carlAddr - (valueFromList (Coin 1407406) [(pid1, smallestName, 1)]) - (SJust $ hashData @AlonzoEra (Data (PV1.List []))) - ) - @?= Coin 1655136 - , testCase "one policy, one (smallest) name, no datum hash" $ - calcMinUTxO - ( AlonzoTxOut - bobAddr - (valueFromList (Coin 1407406) [(pid1, smallestName, 1)]) - SNothing - ) - @?= Coin 1310316 - , testCase "one policy, one (small) name" $ - calcMinUTxO - ( AlonzoTxOut - aliceAddr - (valueFromList (Coin 1444443) [(pid1, smallName 1, 1)]) - SNothing - ) - @?= Coin 1344798 - , testCase "one policy, three (small) names" $ - calcMinUTxO - ( AlonzoTxOut - aliceAddr - ( valueFromList - (Coin 1555554) - [ (pid1, smallName 1, 1) - , (pid1, smallName 2, 1) - , (pid1, smallName 3, 1) - ] - ) - SNothing - ) - @?= Coin 1448244 - , testCase "one policy, one (largest) name" $ - calcMinUTxO - ( AlonzoTxOut - carlAddr - (valueFromList (Coin 1555554) [(pid1, largestName 65, 1)]) - SNothing - ) - @?= Coin 1448244 - , testCase "one policy, three (largest) name, with hash" $ - calcMinUTxO - ( AlonzoTxOut - carlAddr - ( valueFromList - (Coin 1962961) - [ (pid1, largestName 65, 1) - , (pid1, largestName 66, 1) - , (pid1, largestName 67, 1) - ] - ) - (SJust $ hashData @AlonzoEra (Data (PV1.Constr 0 [PV1.Constr 0 []]))) - ) - @?= Coin 2172366 - , testCase "two policies, one (smallest) name" $ - calcMinUTxO - ( AlonzoTxOut - aliceAddr - (valueFromList (Coin 1592591) [(pid1, smallestName, 1), (pid2, smallestName, 1)]) - SNothing - ) - @?= Coin 1482726 - , testCase "two policies, one (smallest) name, with hash" $ - calcMinUTxO - ( AlonzoTxOut - aliceAddr - (valueFromList (Coin 1592591) [(pid1, smallestName, 1), (pid2, smallestName, 1)]) - (SJust $ hashData @AlonzoEra (Data (PV1.Constr 0 []))) - ) - @?= Coin 1827546 - , testCase "two policies, two (small) names" $ - calcMinUTxO - ( AlonzoTxOut - bobAddr - (valueFromList (Coin 1629628) [(pid1, smallName 1, 1), (pid2, smallName 2, 1)]) - SNothing - ) - @?= Coin 1517208 - , testCase "three policies, ninety-six (small) names" $ - calcMinUTxO - ( AlonzoTxOut - aliceAddr - ( let f i c = (i, smallName c, 1) - in valueFromList - (Coin 7407400) - [ f i c - | (i, cs) <- - [(pid1, [32 .. 63]), (pid2, [64 .. 95]), (pid3, [96 .. 127])] - , c <- cs - ] - ) - SNothing - ) - @?= Coin 6896400 - , testCase "utxo entry size of ada-only" $ - -- This value, 29, is helpful for comparing the alonzo protocol parameter utxoCostPerWord - -- with the old parameter minUTxOValue. - -- If we wish to keep the ada-only, no datum hash, minimum value nearly the same, - -- we can divide minUTxOValue by 29 and round. - utxoEntrySize @AlonzoEra (AlonzoTxOut aliceAddr mempty SNothing) @?= 29 - ] + describe "golden tests - UTxOEntryMinAda" $ do + it "one policy, one (smallest) name, yes datum hash" $ + calcMinUTxO + ( AlonzoTxOut + carlAddr + (valueFromList (Coin 1407406) [(pid1, smallestName, 1)]) + (SJust $ hashData @AlonzoEra (Data (PV1.List []))) + ) + `shouldBe` Coin 1655136 + it "one policy, one (smallest) name, no datum hash" $ + calcMinUTxO + ( AlonzoTxOut + bobAddr + (valueFromList (Coin 1407406) [(pid1, smallestName, 1)]) + SNothing + ) + `shouldBe` Coin 1310316 + it "one policy, one (small) name" $ + calcMinUTxO + ( AlonzoTxOut + aliceAddr + (valueFromList (Coin 1444443) [(pid1, smallName 1, 1)]) + SNothing + ) + `shouldBe` Coin 1344798 + it "one policy, three (small) names" $ + calcMinUTxO + ( AlonzoTxOut + aliceAddr + ( valueFromList + (Coin 1555554) + [ (pid1, smallName 1, 1) + , (pid1, smallName 2, 1) + , (pid1, smallName 3, 1) + ] + ) + SNothing + ) + `shouldBe` Coin 1448244 + it "one policy, one (largest) name" $ + calcMinUTxO + ( AlonzoTxOut + carlAddr + (valueFromList (Coin 1555554) [(pid1, largestName 65, 1)]) + SNothing + ) + `shouldBe` Coin 1448244 + it "one policy, three (largest) name, with hash" $ + calcMinUTxO + ( AlonzoTxOut + carlAddr + ( valueFromList + (Coin 1962961) + [ (pid1, largestName 65, 1) + , (pid1, largestName 66, 1) + , (pid1, largestName 67, 1) + ] + ) + (SJust $ hashData @AlonzoEra (Data (PV1.Constr 0 [PV1.Constr 0 []]))) + ) + `shouldBe` Coin 2172366 + it "two policies, one (smallest) name" $ + calcMinUTxO + ( AlonzoTxOut + aliceAddr + (valueFromList (Coin 1592591) [(pid1, smallestName, 1), (pid2, smallestName, 1)]) + SNothing + ) + `shouldBe` Coin 1482726 + it "two policies, one (smallest) name, with hash" $ + calcMinUTxO + ( AlonzoTxOut + aliceAddr + (valueFromList (Coin 1592591) [(pid1, smallestName, 1), (pid2, smallestName, 1)]) + (SJust $ hashData @AlonzoEra (Data (PV1.Constr 0 []))) + ) + `shouldBe` Coin 1827546 + it "two policies, two (small) names" $ + calcMinUTxO + ( AlonzoTxOut + bobAddr + (valueFromList (Coin 1629628) [(pid1, smallName 1, 1), (pid2, smallName 2, 1)]) + SNothing + ) + `shouldBe` Coin 1517208 + it "three policies, ninety-six (small) names" $ + calcMinUTxO + ( AlonzoTxOut + aliceAddr + ( let f i c = (i, smallName c, 1) + in valueFromList + (Coin 7407400) + [ f i c + | (i, cs) <- + [(pid1, [32 .. 63]), (pid2, [64 .. 95]), (pid3, [96 .. 127])] + , c <- cs + ] + ) + SNothing + ) + `shouldBe` Coin 6896400 + it "utxo entry size of ada-only" $ + -- This value, 29, is helpful for comparing the alonzo protocol parameter utxoCostPerWord + -- with the old parameter minUTxOValue. + -- If we wish to keep the ada-only, no datum hash, minimum value nearly the same, + -- we can divide minUTxOValue by 29 and round. + utxoEntrySize @AlonzoEra (AlonzoTxOut aliceAddr mempty SNothing) `shouldBe` 29 -goldenCborSerialization :: TestTree +goldenCborSerialization :: Spec goldenCborSerialization = - testGroup - "golden tests - CBOR serialization" - [ testCase "Alonzo Block" $ do - expected <- readDataFile "golden/block.cbor" - Plain.serialize (pleBlock ledgerExamplesAlonzo) @?= expected - , testCase "Alonzo Tx" $ do - expected <- readDataFile "golden/tx.cbor" - Plain.serialize (leTx $ pleLedgerExamples ledgerExamplesAlonzo) @?= expected - ] + describe "golden tests - CBOR serialization" $ do + it "Alonzo Block" $ do + expected <- readDataFile "golden/block.cbor" + Plain.serialize (pleBlock ledgerExamplesAlonzo) `shouldBe` expected + it "Alonzo Tx" $ do + expected <- readDataFile "golden/tx.cbor" + Plain.serialize (leTx $ pleLedgerExamples ledgerExamplesAlonzo) `shouldBe` expected -goldenJsonSerialization :: TestTree +goldenJsonSerialization :: Spec goldenJsonSerialization = - testGroup - "golden tests - JSON serialization" - [ testCase "ValidityInterval" $ do - let value = - [ ValidityInterval - { invalidBefore = SNothing - , invalidHereafter = SNothing - } - , ValidityInterval - { invalidBefore = SJust (SlotNo 12345) - , invalidHereafter = SNothing - } - , ValidityInterval - { invalidBefore = SNothing - , invalidHereafter = SJust (SlotNo 12354) - } - , ValidityInterval - { invalidBefore = SJust (SlotNo 12345) - , invalidHereafter = SJust (SlotNo 12354) - } - ] - expected <- Aeson.throwDecode =<< readDataFile "golden/ValidityInterval.json" - Aeson.toJSON value @?= expected - , testCase "IsValid" $ do - let value = - [ IsValid True - , IsValid False - ] - expected <- Aeson.throwDecode =<< readDataFile "golden/IsValid.json" - Aeson.toJSON value @?= expected - , testCase "FailureDescription" $ do - let value = - [ PlutusFailure "A description" "A reconstruction" - ] - expected <- Aeson.throwDecode =<< readDataFile "golden/FailureDescription.json" - Aeson.toJSON value @?= expected - , testCase "TagMismatchDescription" $ do - let value = - [ PassedUnexpectedly - , FailedUnexpectedly (NE.fromList [PlutusFailure "A description" "A reconstruction"]) - ] - expected <- Aeson.throwDecode =<< readDataFile "golden/TagMismatchDescription.json" - Aeson.toJSON value @?= expected - ] + describe "golden tests - JSON serialization" $ do + it "ValidityInterval" $ do + let value = + [ ValidityInterval + { invalidBefore = SNothing + , invalidHereafter = SNothing + } + , ValidityInterval + { invalidBefore = SJust (SlotNo 12345) + , invalidHereafter = SNothing + } + , ValidityInterval + { invalidBefore = SNothing + , invalidHereafter = SJust (SlotNo 12354) + } + , ValidityInterval + { invalidBefore = SJust (SlotNo 12345) + , invalidHereafter = SJust (SlotNo 12354) + } + ] + expected <- Aeson.throwDecode =<< readDataFile "golden/ValidityInterval.json" + Aeson.toJSON value `shouldBe` expected + it "IsValid" $ do + let value = + [ IsValid True + , IsValid False + ] + expected <- Aeson.throwDecode =<< readDataFile "golden/IsValid.json" + Aeson.toJSON value `shouldBe` expected + it "FailureDescription" $ do + let value = + [ PlutusFailure "A description" "A reconstruction" + ] + expected <- Aeson.throwDecode =<< readDataFile "golden/FailureDescription.json" + Aeson.toJSON value `shouldBe` expected + it "TagMismatchDescription" $ do + let value = + [ PassedUnexpectedly + , FailedUnexpectedly (NE.fromList [PlutusFailure "A description" "A reconstruction"]) + ] + expected <- Aeson.throwDecode =<< readDataFile "golden/TagMismatchDescription.json" + Aeson.toJSON value `shouldBe` expected -goldenGenesisSerialization :: TestTree +goldenGenesisSerialization :: Spec goldenGenesisSerialization = - testGroup - "golden tests - Alonzo Genesis serialization" - [ testCase "JSON deserialization" $ do - let file = "golden/mainnet-alonzo-genesis.json" - deserialized <- (eitherDecodeFileStrict file :: IO (Either String AlonzoGenesis)) - deserialized @?= Right expectedGenesis - ] + describe "golden tests - Alonzo Genesis serialization" $ do + it "JSON deserialization" $ do + let file = "golden/mainnet-alonzo-genesis.json" + deserialized <- (eitherDecodeFileStrict file :: IO (Either String AlonzoGenesis)) + deserialized `shouldBe` Right expectedGenesis -goldenMinFee :: TestTree +goldenMinFee :: Spec goldenMinFee = - testGroup - "golden tests - minimum fee calculation" - [ testCase "Alonzo Block" $ do - -- This golden test uses the block from: - -- https://github.com/input-output-hk/cardano-node/issues/4228#issuecomment-1195707491 - -- - -- The first transaction in this block is invalid due to: - -- FeeTooSmallUTxO (Coin 1006053) (Coin 1001829) - -- - -- The correct behavior is for the minimum fee for this transaction - -- to be 1006053 lovelace, as indicated by the failure above. - -- Nodes that had the bug determined the minimum fee to be 1001829. - hex <- readDataFile "golden/hex-block-node-issue-4228.cbor" - let cborBytesBlock = - case B16L.decode hex of - Left err -> error err - Right val -> val - blockBody = - case decodeFullAnnotator (eraProtVerHigh @AlonzoEra) "Block" decCBOR cborBytesBlock of - Left err -> error (show err) - Right (Block _bHeader bBody :: Block (BHeader StandardCrypto) AlonzoEra) -> bBody - firstTx = - case blockBody ^. txSeqBlockBodyL of - tx :<| _ -> (tx :: Tx AlonzoEra) - Empty -> error "Block doesn't have any transactions" + describe "golden tests - minimum fee calculation" $ do + it "Alonzo Block" $ do + -- This golden test uses the block from: + -- https://github.com/input-output-hk/cardano-node/issues/4228#issuecomment-1195707491 + -- + -- The first transaction in this block is invalid due to: + -- FeeTooSmallUTxO (Coin 1006053) (Coin 1001829) + -- + -- The correct behavior is for the minimum fee for this transaction + -- to be 1006053 lovelace, as indicated by the failure above. + -- Nodes that had the bug determined the minimum fee to be 1001829. + hex <- readDataFile "golden/hex-block-node-issue-4228.cbor" + let cborBytesBlock = + case B16L.decode hex of + Left err -> error err + Right val -> val + blockBody = + case decodeFullAnnotator (eraProtVerHigh @AlonzoEra) "Block" decCBOR cborBytesBlock of + Left err -> error (show err) + Right (Block _bHeader bBody :: Block (BHeader StandardCrypto) AlonzoEra) -> bBody + firstTx = + case blockBody ^. txSeqBlockBodyL of + tx :<| _ -> (tx :: Tx AlonzoEra) + Empty -> error "Block doesn't have any transactions" - -- Below are the relevant protocol parameters that were active - -- at the time this block was rejected. - priceMem = fromJust $ boundRational 0.0577 - priceSteps = fromJust $ boundRational 0.0000721 - pricesParam = Prices priceMem priceSteps - pp = - emptyPParams - & ppMinFeeAL .~ Coin 44 - & ppMinFeeBL .~ Coin 155381 - & ppPricesL .~ pricesParam + -- Below are the relevant protocol parameters that were active + -- at the time this block was rejected. + priceMem = fromJust $ boundRational 0.0577 + priceSteps = fromJust $ boundRational 0.0000721 + pricesParam = Prices priceMem priceSteps + pp = + emptyPParams + & ppMinFeeAL .~ Coin 44 + & ppMinFeeBL .~ Coin 155381 + & ppPricesL .~ pricesParam - Coin 1006053 @?= alonzoMinFeeTx pp firstTx - ] + Coin 1006053 `shouldBe` alonzoMinFeeTx pp firstTx fromRightError :: (HasCallStack, Show a) => String -> Either a b -> b fromRightError errorMsg = @@ -366,16 +353,14 @@ testScriptIntegritpHash :: PParams AlonzoEra -> Language -> LangDepView -> - Assertion -testScriptIntegritpHash pp lang view = getLanguageView pp lang @?= view + Expectation +testScriptIntegritpHash pp lang view = getLanguageView pp lang `shouldBe` view -goldenScriptIntegrity :: TestTree +goldenScriptIntegrity :: Spec goldenScriptIntegrity = - testGroup - "golden tests - script integrity hash" - [ testCase "PlutusV1" $ testScriptIntegritpHash exPP PlutusV1 exampleLangDepViewPV1 - , testCase "PlutusV2" $ testScriptIntegritpHash exPP PlutusV2 exampleLangDepViewPV2 - ] + describe "golden tests - script integrity hash" $ do + it "PlutusV1" $ testScriptIntegritpHash exPP PlutusV1 exampleLangDepViewPV1 + it "PlutusV2" $ testScriptIntegritpHash exPP PlutusV2 exampleLangDepViewPV2 expectedGenesis :: AlonzoGenesis expectedGenesis = diff --git a/eras/alonzo/test-suite/test/Tests.hs b/eras/alonzo/test-suite/test/Tests.hs index 20ffac27df5..441d97189b7 100644 --- a/eras/alonzo/test-suite/test/Tests.hs +++ b/eras/alonzo/test-suite/test/Tests.hs @@ -13,31 +13,29 @@ import System.Environment (lookupEnv) import qualified Test.Cardano.Ledger.Alonzo.ChainTrace as ChainTrace import qualified Test.Cardano.Ledger.Alonzo.Golden as Golden import Test.Cardano.Ledger.Alonzo.ImpTest () +import Test.Cardano.Ledger.Common import qualified Test.Cardano.Ledger.Shelley.PropertyTests as Shelley import qualified Test.Cardano.Ledger.Shelley.Rules.AdaPreservation as AdaPreservation import qualified Test.Cardano.Ledger.Shelley.Rules.IncrementalStake as IncrementalStake -import Test.Tasty main :: IO () main = do nightly <- lookupEnv "NIGHTLY" - defaultMain $ case nightly of + ledgerTestMain $ case nightly of Nothing -> defaultTests Just _ -> nightlyTests -defaultTests :: TestTree +defaultTests :: Spec defaultTests = - testGroup - "Alonzo tests" - [ AdaPreservation.tests @AlonzoEra 50 - , Golden.tests - ] + describe "Alonzo tests" $ do + AdaPreservation.tests @AlonzoEra 50 + Golden.tests -nightlyTests :: TestTree +nightlyTests :: Spec nightlyTests = - testGroup - "Alonzo tests - nightly" - $ Shelley.commonTests @AlonzoEra - ++ [ IncrementalStake.incrStakeComparisonTest (Proxy :: Proxy AlonzoEra) - , ChainTrace.tests - ] + describe "Alonzo tests - nightly" $ do + describe "Shelley common tests" $ + sequence_ $ + Shelley.commonTests @AlonzoEra + IncrementalStake.incrStakeComparisonTest (Proxy :: Proxy AlonzoEra) + ChainTrace.tests diff --git a/eras/shelley-ma/test-suite/cardano-ledger-shelley-ma-test.cabal b/eras/shelley-ma/test-suite/cardano-ledger-shelley-ma-test.cabal index 6c9882a13a8..d4be9942eb7 100644 --- a/eras/shelley-ma/test-suite/cardano-ledger-shelley-ma-test.cabal +++ b/eras/shelley-ma/test-suite/cardano-ledger-shelley-ma-test.cabal @@ -46,7 +46,7 @@ library bytestring, cardano-ledger-allegra:{cardano-ledger-allegra, testlib} ^>=1.9, cardano-ledger-binary:{cardano-ledger-binary, testlib} >=1.7, - cardano-ledger-core ^>=1.19, + cardano-ledger-core:{cardano-ledger-core, tasty-compat} ^>=1.19, cardano-ledger-mary:{cardano-ledger-mary, testlib} ^>=1.9, cardano-ledger-shelley:{cardano-ledger-shelley, testlib} >=1.12, cardano-ledger-shelley-test >=1.6, @@ -57,9 +57,6 @@ library microlens, mtl, small-steps >=1.1, - tasty, - tasty-hunit, - tasty-quickcheck, text, test-suite cardano-ledger-shelley-ma-test @@ -100,7 +97,7 @@ test-suite cardano-ledger-shelley-ma-test cardano-data, cardano-ledger-allegra, cardano-ledger-binary:{cardano-ledger-binary, testlib}, - cardano-ledger-core:{cardano-ledger-core, testlib}, + cardano-ledger-core:{cardano-ledger-core, tasty-compat, testlib}, cardano-ledger-mary:{cardano-ledger-mary, testlib}, cardano-ledger-shelley, cardano-ledger-shelley-ma-test, @@ -116,6 +113,3 @@ test-suite cardano-ledger-shelley-ma-test microlens, mtl, small-steps:{small-steps, testlib} >=1.1, - tasty, - tasty-hunit, - tasty-quickcheck, diff --git a/eras/shelley-ma/test-suite/test/Test/Cardano/Ledger/Mary/Value.hs b/eras/shelley-ma/test-suite/test/Test/Cardano/Ledger/Mary/Value.hs index 988c287b7f2..3c4d6b82f9a 100644 --- a/eras/shelley-ma/test-suite/test/Test/Cardano/Ledger/Mary/Value.hs +++ b/eras/shelley-ma/test-suite/test/Test/Cardano/Ledger/Mary/Value.hs @@ -37,6 +37,7 @@ import Data.Maybe (fromMaybe) import Test.Cardano.Ledger.Mary.Arbitrary () import Test.Cardano.Ledger.Shelley.Serialisation.EraIndepGenerators () import Test.Cardano.Ledger.Shelley.Serialisation.Generators () +import Test.QuickCheck ((===)) import qualified Test.QuickCheck as QC import Test.Tasty import Test.Tasty.QuickCheck hiding (scale) diff --git a/eras/shelley/test-suite/cardano-ledger-shelley-test.cabal b/eras/shelley/test-suite/cardano-ledger-shelley-test.cabal index 286fbb04db4..c49f441dc8f 100644 --- a/eras/shelley/test-suite/cardano-ledger-shelley-test.cabal +++ b/eras/shelley/test-suite/cardano-ledger-shelley-test.cabal @@ -80,7 +80,7 @@ library cardano-data >=1.2, cardano-ledger-binary:{cardano-ledger-binary, testlib} >=1.7, cardano-ledger-byron, - cardano-ledger-core:{cardano-ledger-core, testlib} >=1.19, + cardano-ledger-core:{cardano-ledger-core, tasty-compat, testlib} >=1.19, cardano-ledger-shelley:{cardano-ledger-shelley, testlib} >=1.18, cardano-protocol-tpraos:{cardano-protocol-tpraos, testlib} >=1.4, cardano-slotting:{cardano-slotting, testlib}, @@ -97,9 +97,6 @@ library serialise, set-algebra, small-steps:{small-steps, testlib} >=1.1, - tasty, - tasty-hunit, - tasty-quickcheck, text, transformers, tree-diff, @@ -160,7 +157,7 @@ test-suite cardano-ledger-shelley-test cardano-data, cardano-ledger-binary:{cardano-ledger-binary, testlib}, cardano-ledger-byron, - cardano-ledger-core:{cardano-ledger-core, testlib}, + cardano-ledger-core:{cardano-ledger-core, tasty-compat, testlib}, cardano-ledger-shelley:{cardano-ledger-shelley, testlib}, cardano-ledger-shelley-test, cardano-protocol-tpraos:{cardano-protocol-tpraos, testlib}, @@ -176,9 +173,6 @@ test-suite cardano-ledger-shelley-test prettyprinter, scientific, small-steps:{small-steps, testlib} >=1.1, - tasty, - tasty-hunit, - tasty-quickcheck, time, benchmark mainbench diff --git a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/ByronTranslation.hs b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/ByronTranslation.hs index 20347028547..9b983ed13cd 100644 --- a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/ByronTranslation.hs +++ b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/ByronTranslation.hs @@ -1,8 +1,3 @@ -{-# LANGUAGE GADTs #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -{-# OPTIONS_GHC -Wno-orphans #-} - module Test.Cardano.Ledger.Shelley.ByronTranslation (testGroupByronTranslation) where import qualified Cardano.Chain.Common as Byron @@ -13,6 +8,7 @@ import Cardano.Ledger.Shelley (ShelleyEra) import Cardano.Ledger.Shelley.API.ByronTranslation import Cardano.Ledger.Shelley.Core import Test.Cardano.Ledger.Shelley.Arbitrary () +import Test.QuickCheck ((===)) import Test.Tasty import Test.Tasty.QuickCheck diff --git a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rewards.hs b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rewards.hs index c9fbdb44994..ced0a19f51b 100644 --- a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rewards.hs +++ b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rewards.hs @@ -136,6 +136,7 @@ import Test.Cardano.Ledger.Shelley.Utils ( ) import Test.Cardano.Ledger.TerseTools (Terse (..), tersemapdiffs) import Test.Control.State.Transition.Trace (SourceSignalTarget (..), getEvents, sourceSignalTargets) +import Test.QuickCheck ((===)) import Test.Tasty (TestTree, defaultMain, testGroup) import Test.Tasty.QuickCheck ( Gen, @@ -148,7 +149,6 @@ import Test.Tasty.QuickCheck ( property, testProperty, withMaxSuccess, - (===), ) -- ======================================================================== diff --git a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/ShelleyTranslation.hs b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/ShelleyTranslation.hs index 0d922d95f60..34ecd82ef3f 100644 --- a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/ShelleyTranslation.hs +++ b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/ShelleyTranslation.hs @@ -6,6 +6,7 @@ import Cardano.Ledger.Shelley.LedgerState (EpochState, returnRedeemAddrsToReserv import Test.Cardano.Ledger.Shelley.Generator.ShelleyEraGen () import Test.Cardano.Ledger.Shelley.Serialisation.EraIndepGenerators () import Test.Cardano.Ledger.Shelley.Serialisation.Generators () +import Test.QuickCheck ((===)) import Test.Tasty import Test.Tasty.QuickCheck diff --git a/eras/shelley/test-suite/test/Test/Cardano/Ledger/Shelley/UnitTests.hs b/eras/shelley/test-suite/test/Test/Cardano/Ledger/Shelley/UnitTests.hs index 2e0a17583ba..b56829da41c 100644 --- a/eras/shelley/test-suite/test/Test/Cardano/Ledger/Shelley/UnitTests.hs +++ b/eras/shelley/test-suite/test/Test/Cardano/Ledger/Shelley/UnitTests.hs @@ -82,6 +82,7 @@ import Test.Cardano.Ledger.Shelley.Generator.ShelleyEraGen () import Test.Cardano.Ledger.Shelley.Utils import Test.Cardano.Protocol.TPraos.Arbitrary (VRFNatVal (VRFNatVal)) import Test.Control.State.Transition.Trace (checkTrace, (.-), (.->>)) +import Test.QuickCheck ((===), (==>)) import qualified Test.QuickCheck.Gen as QC import qualified Test.QuickCheck.Random as QC import Test.Tasty diff --git a/hie.yaml b/hie.yaml index 1d4d79e5c81..01c9a6f38b1 100644 --- a/hie.yaml +++ b/hie.yaml @@ -234,6 +234,9 @@ cradle: - path: "libs/cardano-ledger-core/testlib" component: "cardano-ledger-core:lib:testlib" + - path: "libs/cardano-ledger-core/tasty-compat" + component: "cardano-ledger-core:lib:tasty-compat" + - path: "libs/cardano-ledger-core/app/PlutusDebug.hs" component: "cardano-ledger-core:exe:plutus-debug" diff --git a/libs/cardano-ledger-binary/CHANGELOG.md b/libs/cardano-ledger-binary/CHANGELOG.md index d780ab5e73b..1fc6e168a48 100644 --- a/libs/cardano-ledger-binary/CHANGELOG.md +++ b/libs/cardano-ledger-binary/CHANGELOG.md @@ -6,6 +6,10 @@ * Remove `Typeable` superconstraint from `EncCBOR` * Remove `Range`, `szEval`, `Size`, `Case`, `caseValue`, `LengthOf`, `SizeOverride`, `isTodo`, `szCases`, `szLazy`, `szGreedy`, `szForce`, `szWithCtx`, `szSimplify`, `apMono`, `szBounds`, `encodedVerKeyDSIGNSizeExpr`, `encodedSignKeyDSIGNSizeExpr`, `encodedSigDSIGNSizeExpr`, `encodedSignedDSIGNSizeExpr`, `encodedVerKeyKESSizeExpr`, `encodedSignKeyKESSizeExpr`, `encodedSigKESSizeExpr`, `encodedVerKeyVRFSizeExpr`, `encodedSignKeyVRFSizeExpr` and `encodedCertVRFSizeExpr` +### `testlib` + +* Remove `assertExprEqualWithMessage` + ## 1.7.0.0 * Add `Random` instance for `Version`. diff --git a/libs/cardano-ledger-binary/cardano-ledger-binary.cabal b/libs/cardano-ledger-binary/cardano-ledger-binary.cabal index 9c3f2dce941..e16442bc4f8 100644 --- a/libs/cardano-ledger-binary/cardano-ledger-binary.cabal +++ b/libs/cardano-ledger-binary/cardano-ledger-binary.cabal @@ -136,7 +136,6 @@ library testlib primitive, quickcheck-instances >=0.3.32, random >=1.2, - tasty-hunit, text, tree-diff, typed-process, diff --git a/libs/cardano-ledger-binary/testlib/Test/Cardano/Ledger/Binary/TreeDiff.hs b/libs/cardano-ledger-binary/testlib/Test/Cardano/Ledger/Binary/TreeDiff.hs index 1cfe2a0204c..ca8ba13bbc4 100644 --- a/libs/cardano-ledger-binary/testlib/Test/Cardano/Ledger/Binary/TreeDiff.hs +++ b/libs/cardano-ledger-binary/testlib/Test/Cardano/Ledger/Binary/TreeDiff.hs @@ -21,7 +21,6 @@ module Test.Cardano.Ledger.Binary.TreeDiff ( assertColorFailure, expectExprEqual, expectExprEqualWithMessage, - assertExprEqualWithMessage, callStackToLocation, srcLocToLocation, Expr (App, Rec, Lst), @@ -61,7 +60,6 @@ import Test.Cardano.Slotting.TreeDiff () import Test.Hspec (Expectation) import Test.ImpSpec (ansiDocToString) import Test.ImpSpec.Expectations (assertColorFailure, callStackToLocation, srcLocToLocation) -import Test.Tasty.HUnit (Assertion, assertFailure) -- ===================================================== -- Cardano functions that deal with TreeDiff and ToExpr @@ -218,14 +216,9 @@ showHexBytesGrouped n bs expectExprEqual :: (Eq a, ToExpr a) => a -> a -> Expectation expectExprEqual = expectExprEqualWithMessage "Expected two values to be equal:" --- | Use this with HSpec, but with Tasty use 'assertExprEqualWithMessage' below expectExprEqualWithMessage :: (ToExpr a, Eq a, HasCallStack) => String -> a -> a -> Expectation expectExprEqualWithMessage = requireExprEqualWithMessage (assertColorFailure . ansiDocToString) . Pretty.pretty --- | Use this with Tasty, but with HSpec use 'expectExprEqualWithMessage' above -assertExprEqualWithMessage :: (ToExpr a, Eq a, HasCallStack) => String -> a -> a -> Assertion -assertExprEqualWithMessage = requireExprEqualWithMessage (assertFailure . ansiDocToString) . Pretty.pretty - requireExprEqualWithMessage :: (ToExpr a, Eq a, Monoid b) => (Doc AnsiStyle -> b) -> Doc AnsiStyle -> a -> a -> b requireExprEqualWithMessage fail_ message expected actual = diff --git a/libs/cardano-ledger-core/CHANGELOG.md b/libs/cardano-ledger-core/CHANGELOG.md index bf38d8d1bc7..21cea800f29 100644 --- a/libs/cardano-ledger-core/CHANGELOG.md +++ b/libs/cardano-ledger-core/CHANGELOG.md @@ -27,6 +27,10 @@ - `genInsertDeleteRoundtripSPool` - `genInsertDeleteRoundtripDRep` +### `tasty-compat` + +* Library added as an interim compatibility layer for migrating from `tasty` to `hspec` + ## 1.18.0.0 * Changed the type of `AtMostEra` and `AtLeastEra` to accept a type level string instead of an actual era type. diff --git a/libs/cardano-ledger-core/cardano-ledger-core.cabal b/libs/cardano-ledger-core/cardano-ledger-core.cabal index bdf44f6de2e..ef047b796af 100644 --- a/libs/cardano-ledger-core/cardano-ledger-core.cabal +++ b/libs/cardano-ledger-core/cardano-ledger-core.cabal @@ -24,7 +24,24 @@ flag asserts description: Enable assertions default: False +common warnings + ghc-options: + -Wall + -Wcompat + -Wincomplete-record-updates + -Wincomplete-uni-patterns + -Wredundant-constraints + -Wpartial-fields + -Wunused-packages + +common rtsopts + ghc-options: + -threaded + -rtsopts + -with-rtsopts=-N + library + import: warnings exposed-modules: Cardano.Ledger.Address Cardano.Ledger.AuxiliaryData @@ -88,15 +105,6 @@ library Cardano.Ledger.State.UTxO default-language: Haskell2010 - ghc-options: - -Wall - -Wcompat - -Wincomplete-record-updates - -Wincomplete-uni-patterns - -Wredundant-constraints - -Wpartial-fields - -Wunused-packages - build-depends: FailT, aeson >=2, @@ -147,6 +155,7 @@ library ghc-options: -fno-ignore-asserts library internal + import: warnings build-depends: base, cardano-ledger-binary, @@ -160,16 +169,9 @@ library internal visibility: public hs-source-dirs: internal default-language: Haskell2010 - ghc-options: - -Wall - -Wcompat - -Wincomplete-record-updates - -Wincomplete-uni-patterns - -Wredundant-constraints - -Wpartial-fields - -Wunused-packages library testlib + import: warnings exposed-modules: Test.Cardano.Ledger.Common Test.Cardano.Ledger.Core.Address @@ -194,15 +196,6 @@ library testlib visibility: public hs-source-dirs: testlib default-language: Haskell2010 - ghc-options: - -Wall - -Wcompat - -Wincomplete-record-updates - -Wincomplete-uni-patterns - -Wredundant-constraints - -Wpartial-fields - -Wunused-packages - build-depends: FailT, ImpSpec, @@ -241,25 +234,30 @@ library testlib unliftio, vector-map:{vector-map, testlib}, +library tasty-compat + import: warnings + visibility: public + default-language: Haskell2010 + hs-source-dirs: tasty-compat + exposed-modules: + Test.Tasty + Test.Tasty.HUnit + Test.Tasty.QuickCheck + + build-depends: + HUnit, + QuickCheck, + base, + hspec, + executable plutus-debug + import: warnings, rtsopts main-is: PlutusDebug.hs hs-source-dirs: app other-modules: CLI default-language: Haskell2010 - ghc-options: - -Wall - -Wcompat - -Wincomplete-record-updates - -Wincomplete-uni-patterns - -Wredundant-constraints - -Wpartial-fields - -Wunused-packages - -threaded - -rtsopts - -with-rtsopts=-N - build-depends: base >=4.18 && <5, cardano-ledger-binary, @@ -267,6 +265,7 @@ executable plutus-debug optparse-applicative, test-suite tests + import: warnings, rtsopts type: exitcode-stdio-1.0 main-is: Main.hs hs-source-dirs: test @@ -280,18 +279,6 @@ test-suite tests Test.Cardano.Ledger.ToolsSpec default-language: Haskell2010 - ghc-options: - -Wall - -Wcompat - -Wincomplete-record-updates - -Wincomplete-uni-patterns - -Wredundant-constraints - -Wpartial-fields - -Wunused-packages - -threaded - -rtsopts - -with-rtsopts=-N - build-depends: FailT, aeson, @@ -312,21 +299,11 @@ test-suite tests testlib, benchmark addr + import: warnings, rtsopts type: exitcode-stdio-1.0 main-is: Addr.hs hs-source-dirs: bench default-language: Haskell2010 - ghc-options: - -Wall - -Wcompat - -Wincomplete-record-updates - -Wincomplete-uni-patterns - -Wredundant-constraints - -Wunused-packages - -threaded - -rtsopts - -O2 - build-depends: QuickCheck, base, diff --git a/libs/cardano-ledger-core/tasty-compat/README.md b/libs/cardano-ledger-core/tasty-compat/README.md new file mode 100644 index 00000000000..871d4401f06 --- /dev/null +++ b/libs/cardano-ledger-core/tasty-compat/README.md @@ -0,0 +1,9 @@ +# tasty-compat + +This is a compatibility library to allow Tasty-based test code to be used with +Hspec instead. It defines some of the basic Tasty functions and types in terms +of their Hspec equivalents using the same module names as Tasty. If the Tasty +usage is simple, it's possible just to replace the `tasty*` module names with a +single `tasty-compat` in `build-depends`. + +Currently, only the functionality needed by `cardano-ledger` is provided. diff --git a/libs/cardano-ledger-core/tasty-compat/Test/Tasty.hs b/libs/cardano-ledger-core/tasty-compat/Test/Tasty.hs new file mode 100644 index 00000000000..e99b43688b4 --- /dev/null +++ b/libs/cardano-ledger-core/tasty-compat/Test/Tasty.hs @@ -0,0 +1,18 @@ +module Test.Tasty where + +import Test.Hspec +import Test.Hspec.QuickCheck +import Test.Tasty.QuickCheck (QuickCheckMaxRatio (..)) + +type TestName = String + +type TestTree = Spec + +defaultMain :: Spec -> IO () +defaultMain = hspec + +testGroup :: HasCallStack => String -> [SpecWith a] -> SpecWith a +testGroup s = describe s . sequence_ + +localOption :: QuickCheckMaxRatio -> SpecWith a -> SpecWith a +localOption (QuickCheckMaxRatio i) = modifyMaxDiscardRatio (const i) diff --git a/libs/cardano-ledger-core/tasty-compat/Test/Tasty/HUnit.hs b/libs/cardano-ledger-core/tasty-compat/Test/Tasty/HUnit.hs new file mode 100644 index 00000000000..9af4d71f727 --- /dev/null +++ b/libs/cardano-ledger-core/tasty-compat/Test/Tasty/HUnit.hs @@ -0,0 +1,23 @@ +module Test.Tasty.HUnit where + +import Control.Monad (unless) +import qualified Test.HUnit as HU +import Test.Hspec + +type Assertion = Expectation + +(@?=) :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation +(@?=) = shouldBe + +testCase :: HasCallStack => String -> Expectation -> Spec +testCase = it + +assertBool :: HasCallStack => String -> Bool -> Expectation +assertBool s b = unless b $ expectationFailure s + +assertEqual :: (HasCallStack, Show a, Eq a) => String -> a -> a -> Expectation +assertEqual _s = shouldBe + +-- We can't use expectationFailure because we need to return IO a +assertFailure :: HasCallStack => String -> IO a +assertFailure = HU.assertFailure diff --git a/libs/cardano-ledger-core/tasty-compat/Test/Tasty/QuickCheck.hs b/libs/cardano-ledger-core/tasty-compat/Test/Tasty/QuickCheck.hs new file mode 100644 index 00000000000..77cdfcbe366 --- /dev/null +++ b/libs/cardano-ledger-core/tasty-compat/Test/Tasty/QuickCheck.hs @@ -0,0 +1,19 @@ +{-# LANGUAGE GeneralizedNewtypeDeriving #-} + +module Test.Tasty.QuickCheck ( + module QC, + QuickCheckMaxRatio (..), + testProperty, +) where + +import GHC.Stack +import Test.Hspec +import Test.Hspec.QuickCheck +-- Using re-exported operators causes fourmolu not to know their fixity +import Test.QuickCheck as QC hiding ((.&&.), (.&.), (.||.), (=/=), (===), (==>), (><)) + +newtype QuickCheckMaxRatio = QuickCheckMaxRatio Int + deriving (Num, Ord, Eq, Real, Enum, Integral) + +testProperty :: (HasCallStack, Testable prop) => String -> prop -> Spec +testProperty = prop diff --git a/libs/cardano-ledger-test/benchProperty/Main.hs b/libs/cardano-ledger-test/benchProperty/Main.hs index 77af2345fc1..22154446f7a 100644 --- a/libs/cardano-ledger-test/benchProperty/Main.hs +++ b/libs/cardano-ledger-test/benchProperty/Main.hs @@ -45,13 +45,13 @@ import Cardano.Ledger.Shelley.Rules ( import Control.State.Transition.Extended (Embed (..)) import Test.Cardano.Ledger.Alonzo.AlonzoEraGen () import Test.Cardano.Ledger.Alonzo.EraMapping () +import Test.Cardano.Ledger.Common (ledgerTestMain) import Test.Cardano.Ledger.Shelley.Rules.Chain ( CHAIN, ChainEvent (..), TestChainPredicateFailure (..), ) import Test.Cardano.Ledger.Shelley.Rules.ClassifyTraces (relevantCasesAreCovered) -import qualified Test.Tasty as T -- =============================================================== @@ -65,7 +65,7 @@ instance Embed (AlonzoUTXOW AlonzoEra) (ShelleyLEDGER AlonzoEra) where profileCover :: IO () profileCover = - T.defaultMain $ + ledgerTestMain $ relevantCasesAreCovered @AlonzoEra 1 main :: IO () diff --git a/libs/cardano-ledger-test/cardano-ledger-test.cabal b/libs/cardano-ledger-test/cardano-ledger-test.cabal index 71ca528b8ed..3e432eefa43 100644 --- a/libs/cardano-ledger-test/cardano-ledger-test.cabal +++ b/libs/cardano-ledger-test/cardano-ledger-test.cabal @@ -113,9 +113,6 @@ library prettyprinter, random, small-steps:{small-steps, testlib}, - tasty, - tasty-hunit, - tasty-quickcheck, text, time, transformers, @@ -143,7 +140,6 @@ test-suite cardano-ledger-test base, cardano-ledger-core:testlib, cardano-ledger-test, - tasty, benchmark bench type: exitcode-stdio-1.0 @@ -224,7 +220,7 @@ benchmark benchProperty base, cardano-ledger-alonzo, cardano-ledger-alonzo-test, + cardano-ledger-core:testlib, cardano-ledger-shelley, cardano-ledger-shelley-test, small-steps >=1.1, - tasty, diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoAPI.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoAPI.hs index 47e0c19ade0..ad39df062bb 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoAPI.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoAPI.hs @@ -49,6 +49,7 @@ import qualified Data.Map.Strict as Map import qualified Data.Set as Set import Lens.Micro ((&), (.~)) import qualified PlutusLedgerApi.V1 as PV1 +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Core.KeyPair (mkWitnessVKey) import Test.Cardano.Ledger.Examples.STSTestUtils ( EraModel (..), @@ -63,12 +64,12 @@ import Test.Cardano.Ledger.Generic.Instances () import Test.Cardano.Ledger.Generic.Proof (AlonzoEra, Reflect (..)) import Test.Cardano.Ledger.Generic.TxGen () import Test.Cardano.Ledger.Plutus (zeroTestingCostModels) -import Test.Tasty (TestTree, testGroup) -import Test.Tasty.HUnit (Assertion, testCase, (@?=)) -tests :: TestTree +tests :: Spec tests = - testGroup "Alonzo API" [testCase "estimateMinFee" $ testEstimateMinFee @AlonzoEra] + describe "Alonzo API" $ do + it "estimateMinFee" $ do + testEstimateMinFee @AlonzoEra testEstimateMinFee :: forall era. @@ -77,7 +78,7 @@ testEstimateMinFee :: , AlonzoEraTxBody era , EraModel era ) => - Assertion + Expectation testEstimateMinFee = estimateMinFeeTx @era pparams @@ -85,7 +86,7 @@ testEstimateMinFee = 1 0 0 - @?= alonzoMinFeeTx pparams validatingTx + `shouldBe` alonzoMinFeeTx pparams validatingTx where pparams = defaultPPs emptyPParams diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoBBODY.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoBBODY.hs index 605045500c2..074295cc465 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoBBODY.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoBBODY.hs @@ -69,9 +69,9 @@ import Data.Maybe (fromJust) import qualified Data.Sequence.Strict as SSeq import qualified Data.Sequence.Strict as StrictSeq import qualified Data.Set as Set -import Data.TreeDiff (ToExpr) import Lens.Micro ((&), (.~)) import qualified PlutusLedgerApi.V1 as PV1 +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Core.KeyPair (KeyPair (..), mkAddr, mkWitnessVKey) import Test.Cardano.Ledger.Era (registerTestAccount) import Test.Cardano.Ledger.Examples.STSTestUtils ( @@ -99,8 +99,6 @@ import Test.Cardano.Ledger.Shelley.Utils ( mkVRFKeyPair, ) import Test.Cardano.Protocol.TPraos.Create (VRFKeyPair (..)) -import Test.Tasty (TestTree, testGroup) -import Test.Tasty.HUnit (testCase) forge :: forall era. EraScript era => Integer -> Script era -> MultiAsset forge n s = MultiAsset $ Map.singleton pid (Map.singleton an n) @@ -108,14 +106,12 @@ forge n s = MultiAsset $ Map.singleton pid (Map.singleton an n) pid = PolicyID (hashScript @era s) an = AssetName "an" -tests :: TestTree +tests :: Spec tests = - testGroup - "Generic Tests, testing Alonzo PredicateFailures, in postAlonzo eras." - [ alonzoBBODYexamplesP Alonzo - , alonzoBBODYexamplesP Babbage - , alonzoBBODYexamplesP Conway - ] + describe "Generic Tests, testing Alonzo PredicateFailures, in postAlonzo eras" $ do + alonzoBBODYexamplesP Alonzo + alonzoBBODYexamplesP Babbage + alonzoBBODYexamplesP Conway alonzoBBODYexamplesP :: forall era. @@ -134,19 +130,17 @@ alonzoBBODYexamplesP :: , EraPlutusTxInfo PlutusV1 era ) => Proof era -> - TestTree + Spec alonzoBBODYexamplesP proof = - testGroup - (show proof ++ " BBODY examples") - [ testCase "eight plutus scripts cases" $ - runSTS @"BBODY" @era - (TRC (BbodyEnv @era defaultPParams def, initialBBodyState @era initUTxO, testAlonzoBlock @era)) - (genericCont "" $ Right testBBodyState) - , testCase "block with bad pool md hash in tx" $ - runSTS @"BBODY" @era - (TRC (BbodyEnv @era defaultPParams def, initialBBodyState initUTxO, testAlonzoBadPMDHBlock)) - (genericCont "" . Left . pure $ makeTooBig @era) - ] + describe (show proof ++ " BBODY examples") $ do + it "eight plutus scripts cases" $ + runSTS @"BBODY" @era + (TRC (BbodyEnv @era defaultPParams def, initialBBodyState @era initUTxO, testAlonzoBlock @era)) + (genericCont "" $ Right testBBodyState) + it "block with bad pool md hash in tx" $ + runSTS @"BBODY" @era + (TRC (BbodyEnv @era defaultPParams def, initialBBodyState initUTxO, testAlonzoBadPMDHBlock)) + (genericCont "" . Left . pure $ makeTooBig @era) initialBBodyState :: forall era. diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoCollectInputs.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoCollectInputs.hs index a7c6b15cb38..f9ebdd755f4 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoCollectInputs.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/AlonzoCollectInputs.hs @@ -58,6 +58,7 @@ import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Lens.Micro import qualified PlutusLedgerApi.V1 as PV1 import Test.Cardano.Ledger.Alonzo.Scripts (alwaysSucceeds) +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Core.KeyPair (mkWitnessVKey) import Test.Cardano.Ledger.Examples.AlonzoAPI (defaultPParams) import Test.Cardano.Ledger.Examples.STSTestUtils ( @@ -73,12 +74,10 @@ import Test.Cardano.Ledger.Plutus ( alwaysSucceedsPlutus, zeroTestingCostModel, ) -import Test.Tasty (TestTree) -import Test.Tasty.HUnit (Assertion, testCase, (@?=)) -tests :: TestTree +tests :: Spec tests = - testCase + it "collectTwoPhaseScriptInputs output order" collectTwoPhaseScriptInputsOutputOrdering @@ -86,10 +85,10 @@ tests = -- | Never apply this to any Era but Alonzo or Babbage collectTwoPhaseScriptInputsOutputOrdering :: - Assertion + Expectation collectTwoPhaseScriptInputsOutputOrdering = do collectInputs @AlonzoEra testEpochInfo testSystemStart defaultPParams validatingTx initUTxO - @?= Right + `shouldBe` Right [ PlutusWithContext { pwcProtocolVersion = pvMajor (defaultPParams @AlonzoEra ^. ppProtocolVersionL) , pwcScript = Left plutus diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/BabbageFeatures.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/BabbageFeatures.hs index a355838cba2..c032cbe2904 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/BabbageFeatures.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/BabbageFeatures.hs @@ -52,6 +52,7 @@ import GHC.Stack import Lens.Micro import qualified PlutusLedgerApi.V1 as PV1 import Test.Cardano.Ledger.Alonzo.Scripts (alwaysSucceeds) +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Conway.Era () import Test.Cardano.Ledger.Core.KeyPair (KeyPair (..), mkAddr, mkWitnessVKey) import Test.Cardano.Ledger.Examples.STSTestUtils ( @@ -65,9 +66,6 @@ import Test.Cardano.Ledger.Generic.Proof import Test.Cardano.Ledger.Plutus (zeroTestingCostModels) import Test.Cardano.Ledger.Shelley.Era (ShelleyEraTest) import Test.Cardano.Ledger.Shelley.Utils (RawSeed (..), mkKeyPair, mkKeyPair') -import Test.Cardano.Ledger.TreeDiff (ToExpr, showExpr) -import Test.Tasty -import Test.Tasty.HUnit (Assertion, assertEqual, assertFailure, testCase) someKeys :: KeyPair 'Payment someKeys = KeyPair vk sk @@ -233,7 +231,7 @@ testExpectSuccessValid :: , BabbageEraPParams era ) => TestCaseData era -> - Assertion + Expectation testExpectSuccessValid tc = let txBody' = txBody tc tx' = txFromTestCaseData tc @@ -253,18 +251,16 @@ testExpectSuccessValid tc = (TRC (env, state, assumedValidTx)) (genericCont (show assumedValidTx) $ Right expectedState) -babbageFeatures :: TestTree +babbageFeatures :: Spec babbageFeatures = - testGroup - "Babbage Features" - [ testCase "inputs and refinputs overlap in Babbage and don't Fail" $ - testExpectSuccessValid @BabbageEra commonReferenceScript - , testCase "inputs and refinputs overlap in Conway and Fail" $ - testExpectUTXOFailure - @ConwayEra - commonReferenceScript - (Conway.BabbageNonDisjointRefInputs (pure commonTxIn)) - ] + describe "Babbage Features" $ do + it "inputs and refinputs overlap in Babbage and don't Fail" $ + testExpectSuccessValid @BabbageEra commonReferenceScript + it "inputs and refinputs overlap in Conway and Fail" $ + testExpectUTXOFailure + @ConwayEra + commonReferenceScript + (Conway.BabbageNonDisjointRefInputs (pure commonTxIn)) testExpectUTXOFailure :: forall era. @@ -280,7 +276,7 @@ testExpectUTXOFailure :: ) => TestCaseData era -> PredicateFailure (EraRule "UTXO" era) -> - Assertion + Expectation testExpectUTXOFailure tc failure = let tx' = txFromTestCaseData tc InitUtxo inputs' refInputs' collateral' = initUtxoFromTestCaseData @era tc @@ -295,9 +291,9 @@ testExpectUTXOFailure tc failure = state tx' ( \case - Left (predfail :| []) -> assertEqual "unexpected failure" predfail failure - Left xs -> assertFailure $ "not exactly one failure" <> showExpr xs - Right _ -> assertFailure "testExpectUTXOFailure succeeds" + Left (predfail :| []) -> predfail `shouldBe` failure + Left xs -> expectationFailure $ "not exactly one failure" <> showExpr xs + Right _ -> expectationFailure "testExpectUTXOFailure succeeds" ) defaultPParams :: forall era. (AlonzoEraScript era, BabbageEraPParams era) => PParams era diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/STSTestUtils.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/STSTestUtils.hs index f6013fbb1cf..0f962ce873d 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/STSTestUtils.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Examples/STSTestUtils.hs @@ -73,7 +73,6 @@ import Cardano.Ledger.State import Cardano.Ledger.TxIn (TxIn (..)) import Cardano.Ledger.Val (inject) import Cardano.Slotting.Slot (SlotNo (..)) -import Control.Monad (when) import Control.State.Transition.Extended (STS (..), TRC (..)) import Data.Default (Default (..)) import Data.Foldable (Foldable (..)) @@ -86,11 +85,7 @@ import GHC.Stack import Lens.Micro (Lens', (&), (.~)) import Numeric.Natural (Natural) import qualified PlutusLedgerApi.V1 as PV1 -import Test.Cardano.Ledger.Conway.TreeDiff ( - ToExpr (..), - ansiDocToString, - diffExpr, - ) +import Test.Cardano.Ledger.Common hiding (Result) import Test.Cardano.Ledger.Core.KeyPair (KeyPair (..), mkAddr) import Test.Cardano.Ledger.Generic.Indexed (theKeyHash) import Test.Cardano.Ledger.Generic.ModelState (Model) @@ -98,7 +93,6 @@ import Test.Cardano.Ledger.Generic.Proof (Proof (..), Reflect (..), runSTS, runS import Test.Cardano.Ledger.Shelley.Era (EraTest, ShelleyEraTest) import Test.Cardano.Ledger.Shelley.Generator.EraGen (genesisId) import Test.Cardano.Ledger.Shelley.Utils (RawSeed (..), mkKeyPair, mkKeyPair') -import Test.Tasty.HUnit (Assertion, assertFailure, (@?=)) data PlutusPurposeTag = Spending @@ -274,7 +268,7 @@ testBBODY :: Block BHeaderView era -> Either (NonEmpty (PredicateFailure (EraRule "BBODY" era))) (ShelleyBbodyState era) -> PParams era -> - Assertion + Expectation testBBODY initialSt block expected pparams = let env = BbodyEnv pparams def in runSTS @"BBODY" @era (TRC (env, initialSt, block)) (genericCont "" expected) @@ -296,7 +290,7 @@ testUTXOW :: PParams era -> Tx era -> Either (NonEmpty (PredicateFailure (EraRule "UTXOW" era))) (State (EraRule "UTXOW" era)) -> - Assertion + Expectation testUTXOW utxo p tx = testUTXOWwith (genericCont (show (utxo, tx))) utxo p tx -- | Use a subset test on the expected and computed [PredicateFailure] @@ -315,7 +309,7 @@ testUTXOWsubset :: PParams era -> Tx era -> Either (NonEmpty (PredicateFailure (EraRule "UTXOW" era))) (State (EraRule "UTXOW" era)) -> - Assertion + Expectation testUTXOWsubset = testUTXOWwith subsetCont -- | Use a test where any two (ValidationTagMismatch x y) failures match regardless of 'x' and 'y' @@ -333,7 +327,7 @@ testUTXOspecialCase :: PParams era -> Tx era -> Either (NonEmpty (PredicateFailure (EraRule "UTXOW" era))) (State (EraRule "UTXOW" era)) -> - Assertion + Expectation testUTXOspecialCase utxo pparam tx expected = let env = UtxoEnv (SlotNo 0) pparam def state = smartUTxOState pparam utxo (Coin 0) (Coin 0) def mempty @@ -353,12 +347,12 @@ testUTXOWwith :: , State (EraRule "UTXOW" era) ~ UTxOState era , Tx era ~ Signal (EraRule "UTXOW" era) ) => - (Result era -> Result era -> Assertion) -> + (Result era -> Result era -> Expectation) -> UTxO era -> PParams era -> Tx era -> Result era -> - Assertion + Expectation testUTXOWwith cont utxo pparams tx expected = let env = UtxoEnv (SlotNo 0) pparams def state = smartUTxOState pparams utxo (Coin 0) (Coin 0) def mempty @@ -391,7 +385,7 @@ genericCont :: String -> Either (t x) y -> Either (t x) y -> - Assertion + Expectation genericCont cause expected computed = when (computed /= expected) $ assertFailure $ @@ -411,7 +405,7 @@ subsetCont :: ) => Either (t x) y -> Either (t x) y -> - Assertion + Expectation subsetCont expected computed = let isSubset small big = all (`elem` big) small @@ -419,8 +413,8 @@ subsetCont expected computed = case (computed, expected) of (Left c, Left e) -> -- It is OK if the expected is a subset of what's computed - if isSubset e c then e @?= e else c @?= e - (Right c, Right e) -> c @?= e + if isSubset e c then e `shouldBe` e else c `shouldBe` e + (Right c, Right e) -> c `shouldBe` e (Left x, Right y) -> error $ "expected to pass with " @@ -445,15 +439,15 @@ specialCont :: ) => Either (NonEmpty (PredicateFailure (EraRule "UTXOW" era))) a -> Either (NonEmpty (PredicateFailure (EraRule "UTXOW" era))) a -> - Assertion + Expectation specialCont expected computed = case (computed, expected) of (Left (x :| []), Left (y :| [])) -> case (findMismatch (reify @era) x, findMismatch (reify @era) y) of - (Just _, Just _) -> y @?= y + (Just _, Just _) -> y `shouldBe` y (_, _) -> error "Not both ValidationTagMismatch case 1" (Left _, Left _) -> error "Not both ValidationTagMismatch case 2" - (Right x, Right y) -> x @?= y + (Right x, Right y) -> x `shouldBe` y (Left _, Right _) -> error "expected to pass, but failed." (Right _, Left _) -> error "expected to fail, but passed." diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/AggPropTests.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/AggPropTests.hs index 32a434ae4b2..0a2f1040289 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/AggPropTests.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/AggPropTests.hs @@ -27,7 +27,7 @@ import qualified Data.Map.Strict as Map import qualified Data.Set as Set import Lens.Micro ((^.)) import qualified Prettyprinter as Pretty -import Test.Cardano.Ledger.Binary.TreeDiff (ansiDocToString) +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Generic.Functions ( getBody, getCollateralInputs, @@ -59,9 +59,6 @@ import Test.Control.State.Transition.Trace ( traceSignals, ) import Test.Control.State.Transition.Trace.Generator.QuickCheck (HasTrace (..)) -import Test.QuickCheck -import Test.Tasty -import Test.Tasty.QuickCheck (testProperty) -- ============================================================ @@ -104,14 +101,12 @@ aggUTxO proof = do trace1 <- genTrace 100 (defaultGenSize {blocksizeMax = 4, slotDelta = (6, 12)}) initStableFields pure $ consistentUtxoSizeProp proof trace1 -aggTests :: TestTree +aggTests :: Spec aggTests = - testGroup - "tests, aggregating Tx's over a Trace." - [ testPropMax 30 "UTxO size in Babbage" (aggUTxO Babbage) - , testPropMax 30 "UTxO size in Alonzo" (aggUTxO Alonzo) - , testPropMax 30 "UTxO size in Mary" (aggUTxO Mary) - ] + describe "tests, aggregating Tx's over a Trace." $ do + testPropMax 30 "UTxO size in Babbage" (aggUTxO Babbage) + testPropMax 30 "UTxO size in Alonzo" (aggUTxO Alonzo) + testPropMax 30 "UTxO size in Mary" (aggUTxO Mary) -- =============================================================== @@ -167,22 +162,18 @@ depositEra :: , EraGenericGen era , ShelleyEraAccounts era ) => - TestTree + Spec depositEra = - testGroup - (eraName @era) - [ testProperty - "Deposits = KeyDeposits + PoolDeposits" - (forAllChainTrace 10 (itemPropToTraceProp (depositInvariant @era))) - ] + describe (eraName @era) $ do + prop + "Deposits = KeyDeposits + PoolDeposits" + (forAllChainTrace 10 (itemPropToTraceProp (depositInvariant @era))) -depositTests :: TestTree +depositTests :: Spec depositTests = - testGroup - "deposit invariants" - [ depositEra @ShelleyEra - , depositEra @AllegraEra - , depositEra @MaryEra - , depositEra @AlonzoEra - , depositEra @BabbageEra - ] + describe "deposit invariants" $ do + depositEra @ShelleyEra + depositEra @AllegraEra + depositEra @MaryEra + depositEra @AlonzoEra + depositEra @BabbageEra diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/GenState.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/GenState.hs index a4a0d8f86d6..2ec5c15437a 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/GenState.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/GenState.hs @@ -150,7 +150,7 @@ import Test.Cardano.Ledger.Generic.ModelState ( ) import Test.Cardano.Ledger.Generic.Proof hiding (lift) import Test.Cardano.Ledger.Shelley.Era -import Test.Tasty.QuickCheck ( +import Test.QuickCheck ( Gen, Positive (..), arbitrary, diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/Properties.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/Properties.hs index 9a97e836bc5..a139ed6e014 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/Properties.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/Properties.hs @@ -45,7 +45,7 @@ import Test.Cardano.Ledger.Babbage.Binary.Twiddle () import Test.Cardano.Ledger.Babbage.ImpTest () import Test.Cardano.Ledger.Binary.Arbitrary () import Test.Cardano.Ledger.Binary.Twiddle (Twiddle, twiddleInvariantProp) -import Test.Cardano.Ledger.Common (ToExpr (..), showExpr) +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Conway.Arbitrary () import Test.Cardano.Ledger.Era (EraTest) import Test.Cardano.Ledger.Generic.Functions (TotalAda (totalAda), isValid') @@ -77,8 +77,6 @@ import Test.Cardano.Ledger.Shelley.Serialisation.EraIndepGenerators () import Test.Cardano.Ledger.Shelley.TreeDiff () import Test.Control.State.Transition.Trace (Trace (..), lastState) import Test.Control.State.Transition.Trace.Generator.QuickCheck (HasTrace (..)) -import Test.QuickCheck -import Test.Tasty (TestTree, testGroup) -- ===================================== -- Top level generators of TRC @@ -163,21 +161,19 @@ testTxValidForLEDGER (trc@(TRC (env, ledgerState, vtx)), _genstate) = -- The generic types make a roundtrip without adding or losing information -- | A single Tx preserves Ada -txPreserveAda :: GenSize -> TestTree +txPreserveAda :: GenSize -> Spec txPreserveAda genSize = - testGroup - "Individual Tx's preserve Ada" - [ testPropMax 30 "Shelley Tx preserves Ada" $ - forAll (genTxAndLEDGERState @ShelleyEra genSize) testTxValidForLEDGER - , testPropMax 30 "Allegra Tx preserves ADA" $ - forAll (genTxAndLEDGERState @AllegraEra genSize) testTxValidForLEDGER - , testPropMax 30 "Mary Tx preserves ADA" $ - forAll (genTxAndLEDGERState @MaryEra genSize) testTxValidForLEDGER - , testPropMax 30 "Alonzo ValidTx preserves ADA" $ - forAll (genTxAndLEDGERState @AlonzoEra genSize) testTxValidForLEDGER - , testPropMax 30 "Babbage ValidTx preserves ADA" $ - forAll (genTxAndLEDGERState @BabbageEra genSize) testTxValidForLEDGER - ] + describe "Individual Tx's preserve Ada" $ do + testPropMax 30 "Shelley Tx preserves Ada" $ + forAll (genTxAndLEDGERState @ShelleyEra genSize) testTxValidForLEDGER + testPropMax 30 "Allegra Tx preserves ADA" $ + forAll (genTxAndLEDGERState @AllegraEra genSize) testTxValidForLEDGER + testPropMax 30 "Mary Tx preserves ADA" $ + forAll (genTxAndLEDGERState @MaryEra genSize) testTxValidForLEDGER + testPropMax 30 "Alonzo ValidTx preserves ADA" $ + forAll (genTxAndLEDGERState @AlonzoEra genSize) testTxValidForLEDGER + testPropMax 30 "Babbage ValidTx preserves ADA" $ + forAll (genTxAndLEDGERState @BabbageEra genSize) testTxValidForLEDGER -- | Ada is preserved over a trace of length 100 adaIsPreserved :: @@ -188,7 +184,7 @@ adaIsPreserved :: ) => Int -> GenSize -> - TestTree + Spec adaIsPreserved numTx gensize = testPropMax 30 (eraName @era ++ " era. Trace length = " ++ show numTx) $ traceProp @era @@ -196,16 +192,14 @@ adaIsPreserved numTx gensize = gensize (\firstSt lastSt -> totalAda (mcsNes firstSt) === totalAda (mcsNes lastSt)) -tracePreserveAda :: Int -> GenSize -> TestTree +tracePreserveAda :: Int -> GenSize -> Spec tracePreserveAda numTx gensize = - testGroup - ("Total Ada is preserved over traces of length " ++ show numTx) - [ adaIsPreserved @BabbageEra numTx gensize - , adaIsPreserved @AlonzoEra numTx gensize - , adaIsPreserved @MaryEra numTx gensize - , adaIsPreserved @AllegraEra numTx gensize - , adaIsPreserved @ShelleyEra numTx gensize - ] + describe ("Total Ada is preserved over traces of length " ++ show numTx) $ do + adaIsPreserved @BabbageEra numTx gensize + adaIsPreserved @AlonzoEra numTx gensize + adaIsPreserved @MaryEra numTx gensize + adaIsPreserved @AllegraEra numTx gensize + adaIsPreserved @ShelleyEra numTx gensize -- | The incremental Stake invaraint is preserved over a trace of length 100= stakeInvariant :: EraStake era => MockChainState era -> MockChainState era -> Property @@ -220,46 +214,40 @@ incrementStakeInvariant :: , ShelleyEraAccounts era ) => GenSize -> - TestTree + Spec incrementStakeInvariant gensize = testPropMax 30 (eraName @era ++ " era. Trace length = 100") $ traceProp @era 100 gensize stakeInvariant -incrementalStake :: GenSize -> TestTree +incrementalStake :: GenSize -> Spec incrementalStake genSize = - testGroup - "Incremental Stake invariant holds" - [ -- TODO re-enable this once we have added all the new rules to Conway - -- incrementStakeInvariant Conway genSize, - incrementStakeInvariant @BabbageEra genSize - , incrementStakeInvariant @AlonzoEra genSize - , incrementStakeInvariant @MaryEra genSize - , incrementStakeInvariant @AllegraEra genSize - , incrementStakeInvariant @ShelleyEra genSize - ] + describe "Incremental Stake invariant holds" $ do + -- TODO re-enable this once we have added all the new rules to Conway + -- incrementStakeInvariant Conway genSize, + incrementStakeInvariant @BabbageEra genSize + incrementStakeInvariant @AlonzoEra genSize + incrementStakeInvariant @MaryEra genSize + incrementStakeInvariant @AllegraEra genSize + incrementStakeInvariant @ShelleyEra genSize -genericProperties :: GenSize -> TestTree +genericProperties :: GenSize -> Spec genericProperties genSize = - testGroup - "Generic Property tests" - [ txPreserveAda genSize - , tracePreserveAda 45 genSize - , incrementalStake genSize - , testTraces 45 - , epochPreserveAda genSize - , twiddleInvariantHoldsEras - ] + describe "Generic Property tests" $ do + txPreserveAda genSize + tracePreserveAda 45 genSize + incrementalStake genSize + testTraces 45 + epochPreserveAda genSize + twiddleInvariantHoldsEras -epochPreserveAda :: GenSize -> TestTree +epochPreserveAda :: GenSize -> Spec epochPreserveAda genSize = - testGroup - "Ada is preserved in each epoch" - [ adaIsPreservedInEachEpoch @BabbageEra genSize - , adaIsPreservedInEachEpoch @AlonzoEra genSize - , adaIsPreservedInEachEpoch @MaryEra genSize - , adaIsPreservedInEachEpoch @AllegraEra genSize - , adaIsPreservedInEachEpoch @ShelleyEra genSize - ] + describe "Ada is preserved in each epoch" $ do + adaIsPreservedInEachEpoch @BabbageEra genSize + adaIsPreservedInEachEpoch @AlonzoEra genSize + adaIsPreservedInEachEpoch @MaryEra genSize + adaIsPreservedInEachEpoch @AllegraEra genSize + adaIsPreservedInEachEpoch @ShelleyEra genSize adaIsPreservedInEachEpoch :: forall era. @@ -292,7 +280,7 @@ adaIsPreservedInEachEpoch :: , Show (PredicateFailure (EraRule "LEDGER" era)) ) => GenSize -> - TestTree + Spec adaIsPreservedInEachEpoch genSize = testPropMax 30 (eraName @era) $ forEachEpochTrace @era 200 genSize withTrace @@ -310,14 +298,12 @@ twiddleInvariantHolds :: , Twiddle a ) => String -> - TestTree + Spec twiddleInvariantHolds name = testPropMax 30 name $ twiddleInvariantProp @a -twiddleInvariantHoldsEras :: TestTree +twiddleInvariantHoldsEras :: Spec twiddleInvariantHoldsEras = - testGroup - "Twiddle invariant holds for TxBody" - [ twiddleInvariantHolds @(TxBody AlonzoEra) "Alonzo" - , twiddleInvariantHolds @(TxBody BabbageEra) "Babbage" - ] + describe "Twiddle invariant holds for TxBody" $ do + twiddleInvariantHolds @(TxBody AlonzoEra) "Alonzo" + twiddleInvariantHolds @(TxBody BabbageEra) "Babbage" diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/Trace.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/Trace.hs index 68280e99fb0..a4f6e3cdee5 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/Trace.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Generic/Trace.hs @@ -64,6 +64,7 @@ import qualified Debug.Trace as Debug import GHC.Word (Word64) import Lens.Micro ((&), (.~), (^.)) import Test.Cardano.Ledger.Alonzo.Era +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Examples.STSTestUtils (EraModel (..)) import Test.Cardano.Ledger.Generic.Functions ( adaPots, @@ -92,13 +93,9 @@ import Test.Cardano.Ledger.Generic.ModelState (MUtxo, stashedAVVMAddressesZero) import Test.Cardano.Ledger.Generic.Proof hiding (lift) import Test.Cardano.Ledger.Generic.TxGen (genAlonzoTx) import Test.Cardano.Ledger.Shelley.Rules.IncrementalStake (stakeDistr) -import Test.Cardano.Ledger.Shelley.TreeDiff (showExpr) import Test.Cardano.Ledger.Shelley.Utils (applySTSTest, runShelleyBase, testGlobals) import Test.Control.State.Transition.Trace (Trace (..), lastState, splitTrace) import Test.Control.State.Transition.Trace.Generator.QuickCheck (HasTrace (..), traceFromInitState) -import Test.QuickCheck -import Test.Tasty (TestTree, testGroup) -import Test.Tasty.QuickCheck (testProperty) -- =========================================== @@ -458,8 +455,8 @@ forAllTraceFromInitState baseEnv maxTraceLength traceGenEnv genSt0 = -- Under the assumption that shorter tests have advantages -- like not getting turned off because the tests take too long. A glaring failure is -- likely to be caught in 'n' tests, rather than the standard '100' -testPropMax :: Testable prop => Int -> String -> prop -> TestTree -testPropMax n name x = testProperty name (withMaxSuccess n x) +testPropMax :: Testable prop => Int -> String -> prop -> Spec +testPropMax n name x = prop name (withMaxSuccess n x) chainTest :: forall era. @@ -470,7 +467,7 @@ chainTest :: ) => Int -> GenSize -> - TestTree + Spec chainTest n gsize = testPropMax 30 (eraName @era) action where action = do @@ -485,17 +482,15 @@ chainTest n gsize = testPropMax 30 (eraName @era) action -- Here is where we can add some properties for traces: pure (_traceInitState trace1 === initState) -testTraces :: Int -> TestTree +testTraces :: Int -> Spec testTraces n = - testGroup - "MockChainTrace" - [ chainTest @BabbageEra n defaultGenSize - , chainTest @AlonzoEra n defaultGenSize - , chainTest @MaryEra n defaultGenSize - , chainTest @AllegraEra n defaultGenSize - , multiEpochTest @BabbageEra 225 defaultGenSize - , multiEpochTest @ShelleyEra 225 defaultGenSize - ] + describe "MockChainTrace" $ do + chainTest @BabbageEra n defaultGenSize + chainTest @AlonzoEra n defaultGenSize + chainTest @MaryEra n defaultGenSize + chainTest @AllegraEra n defaultGenSize + multiEpochTest @BabbageEra 225 defaultGenSize + multiEpochTest @ShelleyEra 225 defaultGenSize -- | Show that Ada is preserved across multiple Epochs multiEpochTest :: @@ -506,7 +501,7 @@ multiEpochTest :: ) => Int -> GenSize -> - TestTree + Spec multiEpochTest numTx gsize = let gensize = gsize {blocksizeMax = 4, slotDelta = (6, 12)} getEpoch mockchainstate = nesEL (mcsNes mockchainstate) diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/NoThunks.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/NoThunks.hs index 8edc64fe0a5..0c2d5516a46 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/NoThunks.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/NoThunks.hs @@ -15,6 +15,7 @@ import Cardano.Ledger.Conway.Core (Era (..)) import Cardano.Ledger.Shelley.LedgerState (StashedAVVMAddresses) import Cardano.Ledger.Shelley.State import NoThunks.Class (NoThunks) +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Generic.GenState (EraGenericGen, GenSize, defaultGenSize) import Test.Cardano.Ledger.Generic.MockChain (MOCKCHAIN, noThunksGen) import Test.Cardano.Ledger.Generic.Proof ( @@ -27,19 +28,15 @@ import Test.Cardano.Ledger.Generic.Proof ( import Test.Cardano.Ledger.Generic.Trace (Gen1, traceProp) import Test.Cardano.Ledger.Shelley.TreeDiff () import Test.Control.State.Transition.Trace.Generator.QuickCheck (HasTrace) -import Test.Tasty (TestTree, testGroup) -import Test.Tasty.QuickCheck (testProperty) -test :: TestTree +test :: Spec test = - testGroup - "There are no unexpected thunks in MockChainState" - [ f @ShelleyEra - , f @AllegraEra - , f @MaryEra - , f @AlonzoEra - , f @BabbageEra - ] + describe "There are no unexpected thunks in MockChainState" $ do + f @ShelleyEra + f @AllegraEra + f @MaryEra + f @AlonzoEra + f @BabbageEra where f :: forall era. @@ -48,7 +45,7 @@ test = , ShelleyEraAccounts era , NoThunks (StashedAVVMAddresses era) ) => - TestTree + Spec f = testThunks @era 100 defaultGenSize testThunks :: @@ -60,9 +57,9 @@ testThunks :: ) => Int -> GenSize -> - TestTree + Spec testThunks numTx gensize = - testProperty (eraName @era ++ " era. Trace length = " ++ show numTx) $ + prop (eraName @era ++ " era. Trace length = " ++ show numTx) $ traceProp @era numTx gensize diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/STS.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/STS.hs index b4d6146547f..685ca1321fc 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/STS.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/STS.hs @@ -23,7 +23,7 @@ import Control.State.Transition.Extended import qualified Data.List.NonEmpty as NE import Data.Map (Map) import Data.Set (Set) -import Test.Cardano.Ledger.Common (ToExpr (..)) +import Test.Cardano.Ledger.Common hiding (witness) import Test.Cardano.Ledger.Constrained.Conway.Cert import Test.Cardano.Ledger.Constrained.Conway.Deleg import Test.Cardano.Ledger.Constrained.Conway.Epoch @@ -32,9 +32,6 @@ import Test.Cardano.Ledger.Constrained.Conway.GovCert import Test.Cardano.Ledger.Constrained.Conway.Pool import Test.Cardano.Ledger.Constrained.Conway.WitnessUniverse (WitUniv, genWitUniv, witness) import Test.Cardano.Ledger.Shelley.Utils -import Test.QuickCheck hiding (witness) -import Test.Tasty -import Test.Tasty.QuickCheck hiding (witness) -- ================================================== @@ -83,8 +80,8 @@ stsPropertyV2 :: (env -> st -> Specification sig) -> (env -> st -> sig -> st -> p) -> Property -stsPropertyV2 specEnv specState specSig prop = - stsPropertyV2' @r specEnv specState specSig (\env _ _ -> specState env) prop +stsPropertyV2 specEnv specState specSig = + stsPropertyV2' @r specEnv specState specSig (\env _ _ -> specState env) stsPropertyV2' :: forall r env st sig fail p. @@ -111,7 +108,7 @@ stsPropertyV2' :: (env -> st -> sig -> Specification st) -> (env -> st -> sig -> st -> p) -> Property -stsPropertyV2' specEnv specState specSig specPostState prop = +stsPropertyV2' specEnv specState specSig specPostState theProp = uncurry forAllShrinkBlind (genShrinkFromSpec specEnv) $ \env -> counterexample (show $ toExpr env) $ uncurry forAllShrinkBlind (genShrinkFromSpec $ specState env) $ \st -> @@ -133,7 +130,7 @@ stsPropertyV2' specEnv specState specSig specPostState prop = ( show (toExpr st', show (specState env)) ) - $ prop env st sig st' + $ theProp env st sig st' -- STS properties --------------------------------------------------------- @@ -328,45 +325,37 @@ prop_UTXOW = -- Test Tree ------------------------------------------------------------------------ -tests_STS :: TestTree +tests_STS :: Spec tests_STS = - testGroup - "STS property tests" - [ govTests - , -- , utxoTests - -- TODO: this is probably one of the last things we want to - -- get passing as it depends on being able to generate a complete - -- `EpochState era` - testProperty "prop_EPOCH" prop_EPOCH - -- , testProperty "prop_LEDGER" prop_LEDGER - ] - -govTests :: TestTree + describe "STS property tests" $ do + govTests + -- utxoTests + -- prop "prop_LEDGER" prop_LEDGER + -- TODO: this is probably one of the last things we want to + -- get passing as it depends on being able to generate a complete + -- `EpochState era` + prop "prop_EPOCH" prop_EPOCH + +govTests :: Spec govTests = - testGroup - "GOV tests" - [ testProperty "prop_GOVCERT" prop_GOVCERT - , testProperty "prop_POOL" prop_POOL - , testProperty "prop_DELEG" prop_DELEG - , testProperty "prop_ENACT" prop_ENACT - , testProperty "prop_RATIFY" prop_RATIFY - , testProperty "prop_CERT" prop_CERT - , testProperty "prop_GOV" prop_GOV - ] - -utxoTests :: TestTree + describe "GOV tests" $ do + prop "prop_GOVCERT" prop_GOVCERT + prop "prop_POOL" prop_POOL + prop "prop_DELEG" prop_DELEG + prop "prop_ENACT" prop_ENACT + prop "prop_RATIFY" prop_RATIFY + prop "prop_CERT" prop_CERT + prop "prop_GOV" prop_GOV + +utxoTests :: Spec utxoTests = - testGroup - "UTXO* rules" - [ {-testProperty "prop_UTXO" prop_UTXO - ,-} testProperty "prop_UTXOW" prop_UTXOW - , testProperty "prop_UTXOS" prop_UTXOS - ] - -epoch :: TestTree + describe "UTXO* rules" $ do + -- prop "prop_UTXO" prop_UTXO + prop "prop_UTXOW" prop_UTXOW + prop "prop_UTXOS" prop_UTXOS + +epoch :: Spec epoch = - testGroup - "STS property tests" - [ govTests - , testProperty "prop_EPOCH" prop_EPOCH - ] + describe "STS property tests" $ do + govTests + prop "prop_EPOCH" prop_EPOCH diff --git a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Tickf.hs b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Tickf.hs index cf0ed6ed2f1..d9c7e77a915 100644 --- a/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Tickf.hs +++ b/libs/cardano-ledger-test/src/Test/Cardano/Ledger/Tickf.hs @@ -22,28 +22,19 @@ import Cardano.Ledger.State ( import qualified Data.Map.Strict as Map import Data.Ratio ((%)) import qualified Data.VMap as VMap +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Shelley.Arbitrary () import Test.Cardano.Ledger.Shelley.Serialisation.EraIndepGenerators () -import Test.Tasty -import Test.Tasty.QuickCheck -- ===================================== -calcPoolDistOldEqualsNew :: TestTree +calcPoolDistOldEqualsNew :: Spec calcPoolDistOldEqualsNew = - testGroup - "calculatePoolDistr" - [ testProperty - "old==new" - ( withMaxSuccess - 500 - ( \snap -> - counterexample - "BAD" - (oldCalculatePoolDistr (const True) snap === calculatePoolDistr snap) - ) - ) - ] + describe "calculatePoolDistr" $ do + prop "old==new" $ + withMaxSuccess 500 $ \snap -> + counterexample "BAD" $ + oldCalculatePoolDistr (const True) snap === calculatePoolDistr snap -- | The original version of calculatePoolDistr oldCalculatePoolDistr :: (KeyHash 'StakePool -> Bool) -> SnapShot -> PoolDistr diff --git a/libs/cardano-ledger-test/test/Tests.hs b/libs/cardano-ledger-test/test/Tests.hs index e59e018ef16..74ab03c3618 100644 --- a/libs/cardano-ledger-test/test/Tests.hs +++ b/libs/cardano-ledger-test/test/Tests.hs @@ -1,15 +1,13 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} module Main where import System.Environment (lookupEnv) -import System.IO (hSetEncoding, stdout, utf8) -import Test.Cardano.Ledger.Common (hspec) +import Test.Cardano.Ledger.Common import qualified Test.Cardano.Ledger.Constrained.Conway.LedgerTypes.Tests as LedgerTypes import qualified Test.Cardano.Ledger.Constrained.Conway.MiniTrace as MiniTrace import qualified Test.Cardano.Ledger.Examples.AlonzoAPI as AlonzoAPI (tests) @@ -22,35 +20,33 @@ import Test.Cardano.Ledger.Generic.Properties (genericProperties) import qualified Test.Cardano.Ledger.NoThunks as NoThunks import qualified Test.Cardano.Ledger.STS as ConstraintSTS import Test.Cardano.Ledger.Tickf (calcPoolDistOldEqualsNew) -import Test.Tasty (TestTree, defaultMain, testGroup) main :: IO () main = do - hSetEncoding stdout utf8 nightly <- lookupEnv "NIGHTLY" - hspec MiniTrace.spec - case nightly of - Nothing -> defaultMain $ testGroup "cardano-core" defaultTests - Just _ -> do - hspec LedgerTypes.spec - defaultMain $ testGroup "cardano-core - nightly" nightlyTests + ledgerTestMain $ do + MiniTrace.spec + case nightly of + Nothing -> + describe "cardano-core" defaultTests + Just _ -> do + LedgerTypes.spec + describe "cardano-core - nightly" nightlyTests -defaultTests :: [TestTree] -defaultTests = - [ depositTests - , calcPoolDistOldEqualsNew - , testGroup - "STS Tests" - [ babbageFeatures - , AlonzoBBODY.tests - , AlonzoAPI.tests - , AlonzoCollectInputs.tests - ] - , genericProperties defaultGenSize - , aggTests - , ConstraintSTS.tests_STS - ] +defaultTests :: Spec +defaultTests = do + depositTests + calcPoolDistOldEqualsNew + describe "STS Tests" $ do + babbageFeatures + AlonzoBBODY.tests + AlonzoAPI.tests + AlonzoCollectInputs.tests + genericProperties defaultGenSize + aggTests + ConstraintSTS.tests_STS -nightlyTests :: [TestTree] -nightlyTests = - defaultTests <> [NoThunks.test] +nightlyTests :: Spec +nightlyTests = do + defaultTests + NoThunks.test diff --git a/libs/set-algebra/set-algebra.cabal b/libs/set-algebra/set-algebra.cabal index 706550c1b1c..e0e28e28795 100644 --- a/libs/set-algebra/set-algebra.cabal +++ b/libs/set-algebra/set-algebra.cabal @@ -59,10 +59,9 @@ test-suite tests -rtsopts build-depends: + QuickCheck, base, cardano-data, containers, + hspec, set-algebra, - tasty, - tasty-hunit, - tasty-quickcheck, diff --git a/libs/set-algebra/test/Main.hs b/libs/set-algebra/test/Main.hs index ec07115bca2..28c4a735e75 100644 --- a/libs/set-algebra/test/Main.hs +++ b/libs/set-algebra/test/Main.hs @@ -2,17 +2,15 @@ module Main where import Test.Control.Iterate.RelationReference (relationTests) import Test.Control.Iterate.SetAlgebra (setAlgTest) -import Test.Tasty (TestTree, defaultMain, testGroup) +import Test.Hspec (Spec, describe, hspec) -- ==================================================================================== -tests :: TestTree +tests :: Spec tests = - testGroup - "set-algebra" - [ setAlgTest - , relationTests - ] + describe "set-algebra" $ do + setAlgTest + relationTests main :: IO () -main = defaultMain tests +main = hspec tests diff --git a/libs/set-algebra/test/Test/Control/Iterate/RelationReference.hs b/libs/set-algebra/test/Test/Control/Iterate/RelationReference.hs index 1daae2eaf19..8b6973431ba 100644 --- a/libs/set-algebra/test/Test/Control/Iterate/RelationReference.hs +++ b/libs/set-algebra/test/Test/Control/Iterate/RelationReference.hs @@ -18,8 +18,9 @@ import Data.Monoid (Sum) import Data.Set (Set, intersection, isSubsetOf) import qualified Data.Set as Set import Test.Control.Iterate.SetAlgebra () -import Test.Tasty (TestName, TestTree, testGroup) -import Test.Tasty.QuickCheck (Arbitrary, testProperty, (===)) +import Test.Hspec (Spec, describe) +import Test.Hspec.QuickCheck (prop) +import Test.QuickCheck (Arbitrary, (===)) --------------------------------------------------------------------------------- -- Domain restriction and exclusion @@ -126,41 +127,39 @@ toSet = Set.fromList . toList propUnary :: forall b a e. (Eq a, Show a, Arbitrary b, Show b, SA.Embed a e) => - TestName -> + String -> (b -> SA.Exp e) -> (b -> a) -> - TestTree + Spec propUnary name expr relExpr = - testProperty name (\arg -> SA.eval (expr arg) === relExpr arg) + prop name (\arg -> SA.eval (expr arg) === relExpr arg) propBinary :: forall b c a e. (Eq a, Show a, Arbitrary b, Show b, Arbitrary c, Show c, SA.Embed a e) => - TestName -> + String -> (b -> c -> SA.Exp e) -> (b -> c -> a) -> - TestTree + Spec propBinary name expr relExpr = - testProperty name (\arg1 arg2 -> SA.eval (expr arg1 arg2) === relExpr arg1 arg2) + prop name (\arg1 arg2 -> SA.eval (expr arg1 arg2) === relExpr arg1 arg2) type M = Map Int (Sum Float) -relationTests :: TestTree +relationTests :: Spec relationTests = - testGroup - "RelationTests - check conformance with the original implementation" - [ propUnary @M "dom" SA.dom dom - , propUnary @M "range" SA.rng range - , propBinary @_ @M "∈" (\k m -> k SA.∈ range m) (∈) - , propBinary @_ @M "∉" (\k m -> k SA.∉ range m) (∉) - , propBinary @_ @M "haskey" (\k m -> k SA.∈ dom m) haskey - , propBinary @_ @M "◁" (SA.◁) (◁) - , propBinary @_ @M "⋪" (SA.⋪) (⋪) - , propBinary @M "▷" (SA.▷) (▷) - , propBinary @M "⋫" (SA.⋫) (⋫) - , propBinary @M "∪" (SA.∪) (∪) - , propBinary @M "⨃" (SA.⨃) (⨃) - , propBinary @M "∪+" (SA.∪+) (∪+) - , propBinary @M @M "⊆" (\m1 m2 -> SA.rng m1 SA.⊆ SA.rng m2) (⊆) - , propBinary @(Set Int) "∩" (SA.∩) (∩) - ] + describe "RelationTests - check conformance with the original implementation" $ do + propUnary @M "dom" SA.dom dom + propUnary @M "range" SA.rng range + propBinary @_ @M "∈" (\k m -> k SA.∈ range m) (∈) + propBinary @_ @M "∉" (\k m -> k SA.∉ range m) (∉) + propBinary @_ @M "haskey" (\k m -> k SA.∈ dom m) haskey + propBinary @_ @M "◁" (SA.◁) (◁) + propBinary @_ @M "⋪" (SA.⋪) (⋪) + propBinary @M "▷" (SA.▷) (▷) + propBinary @M "⋫" (SA.⋫) (⋫) + propBinary @M "∪" (SA.∪) (∪) + propBinary @M "⨃" (SA.⨃) (⨃) + propBinary @M "∪+" (SA.∪+) (∪+) + propBinary @M @M "⊆" (\m1 m2 -> SA.rng m1 SA.⊆ SA.rng m2) (⊆) + propBinary @(Set Int) "∩" (SA.∩) (∩) diff --git a/libs/set-algebra/test/Test/Control/Iterate/SetAlgebra.hs b/libs/set-algebra/test/Test/Control/Iterate/SetAlgebra.hs index 00838fe1a82..8639834a6cf 100644 --- a/libs/set-algebra/test/Test/Control/Iterate/SetAlgebra.hs +++ b/libs/set-algebra/test/Test/Control/Iterate/SetAlgebra.hs @@ -25,6 +25,7 @@ import Control.Iterate.SetAlgebra ( runSet, sameDomain, ) +import Control.Monad (zipWithM_) import Control.SetAlgebra ( BaseRep (ListR, MapR, SetR, SingleR), Iter (element), @@ -52,9 +53,9 @@ import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import Data.MapExtras (intersectDomP, intersectDomPLeft) import qualified Data.Set as Set -import Test.Tasty (TestTree, testGroup) -import Test.Tasty.HUnit (assertEqual, testCase) -import Test.Tasty.QuickCheck ( +import Test.Hspec (Spec, describe, shouldBe, specify) +import Test.Hspec.QuickCheck (prop) +import Test.QuickCheck ( Arbitrary (arbitrary), Gen, Property, @@ -62,7 +63,6 @@ import Test.Tasty.QuickCheck ( conjoin, counterexample, frequency, - testProperty, vectorOf, (===), ) @@ -163,59 +163,57 @@ z4 = Map.fromList [(3, "c"), (5, "e"), (10, "j"), (21, "v"), (9, "3"), (30, "a") -- Test that computing x::(Exp t) computes to the given object with type t. -evalTest :: (Show t, Eq t) => String -> Exp t -> t -> TestTree -evalTest nm expr ans = testCase name (assertEqual name (compute expr) ans) +evalTest :: (Show t, Eq t) => String -> Exp t -> t -> Spec +evalTest nm expr ans = specify name $ compute expr `shouldBe` ans where - name = (show expr ++ " where Map? = " ++ nm) + name = show expr ++ " where Map? = " ++ nm -- Test that (eval x) and runSet(x) get the same answers -evalCompile :: (Show (f k v), Ord k, Eq (f k v)) => Exp (f k v) -> TestTree -evalCompile expr = testCase name (assertEqual name (compute expr) (runSet expr)) +evalCompile :: (Show (f k v), Ord k, Eq (f k v)) => Exp (f k v) -> Spec +evalCompile expr = specify name $ compute expr `shouldBe` runSet expr where - name = ("compute and runSet of " ++ show expr ++ " are the same") + name = "compute and runSet of " ++ show expr ++ " are the same" -evalTests :: TestTree +evalTests :: Spec evalTests = - testGroup - "eval tests" - [ evalTest "m12" (5 ∈ (dom m12)) True - , evalTest "m12" (70 ∈ (dom m12)) False - , evalTest "m0" (m0 ∪ (singleton 3 'b')) (Map.fromList [(1, 'a'), (2, 'z'), (3, 'b'), (4, 'g')]) - , evalTest "m0" ((setSingleton 2) ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) - , evalTest "m0" (dom (singleton 2 'z') ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) - , evalTest "m0" (rng (singleton 'z' 2) ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) - , evalTest - "m0" - ((Map.fromList [(1, 'a'), (2, 'n'), (3, 'r')]) ∪ (singleton 2 'b')) - (Map.fromList [(1 :: Int, 'a'), (2, 'n'), (3, 'r')]) - , evalTest "m0" ([(1, 'a'), (3, 'r')] ∪ singleton 3 'b') (UnSafeList [(1 :: Int, 'a'), (3, 'r')]) - , evalTest "m0" (70 ∉ dom m12) True - , evalTest - "((dom stkcred) ◁ deleg) ▷ (dom stpool)" - ((dom stkcred ◁ deleg) ▷ dom stpool) - (Map.fromList [(5, 'F')]) - , evalTest "Range exclude 1" (l4 ⋫ Set.empty) (UnSafeList l4) - , evalTest "Range exclude 2" (l4 ⋫ Fail) (UnSafeList l4) - , evalTest - "Range exclude 3" - (l4 ⋫ Set.fromList ["m", "Z"]) - (UnSafeList [(2, "a"), (5, "z"), (6, "b"), (7, "r"), (12, "w"), (34, "v"), (50, "q"), (51, "l")]) - , evalTest "DomExclude Union" ((z2 ⋪ z1) ∪ z3) z4 - , evalTest "Set difference" (z2 ➖ dom z1) (Sett (Set.fromList [2 :: Int, 13])) - , evalCompile ((dom stkcred ◁ deleg) ▷ dom stpool) - , evalCompile (l4 ⋫ Set.fromList ["m", "Z"]) - , evalCompile (m0 ∪ singleton 3 'b') - , evalCompile (setSingleton 2 ⋪ m0) - , evalTest "ex1" (5 ∈ dom m12) True - , evalTest "ex2" (70 ∈ dom m12) False - , evalTest "ex3" (70 ∉ dom m12) True - , evalTest "ex4" (m0 ∪ singleton 3 'b') (Map.insert 3 'b' m0) - , evalTest "ex5" (setSingleton 2 ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) - , evalTest "ex6" (dom (singleton 2 'z') ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) - , evalTest "ex7" (rng (singleton 'z' 2) ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) - , evalTest "ex8" (z2 ➖ dom z1) (Sett $ Set.fromList [13, 2]) - ] + describe "eval tests" $ do + evalTest "m12" (5 ∈ (dom m12)) True + evalTest "m12" (70 ∈ (dom m12)) False + evalTest "m0" (m0 ∪ (singleton 3 'b')) (Map.fromList [(1, 'a'), (2, 'z'), (3, 'b'), (4, 'g')]) + evalTest "m0" ((setSingleton 2) ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) + evalTest "m0" (dom (singleton 2 'z') ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) + evalTest "m0" (rng (singleton 'z' 2) ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) + evalTest + "m0" + ((Map.fromList [(1, 'a'), (2, 'n'), (3, 'r')]) ∪ (singleton 2 'b')) + (Map.fromList [(1 :: Int, 'a'), (2, 'n'), (3, 'r')]) + evalTest "m0" ([(1, 'a'), (3, 'r')] ∪ singleton 3 'b') (UnSafeList [(1 :: Int, 'a'), (3, 'r')]) + evalTest "m0" (70 ∉ dom m12) True + evalTest + "((dom stkcred) ◁ deleg) ▷ (dom stpool)" + ((dom stkcred ◁ deleg) ▷ dom stpool) + (Map.fromList [(5, 'F')]) + evalTest "Range exclude 1" (l4 ⋫ Set.empty) (UnSafeList l4) + evalTest "Range exclude 2" (l4 ⋫ Fail) (UnSafeList l4) + evalTest + "Range exclude 3" + (l4 ⋫ Set.fromList ["m", "Z"]) + (UnSafeList [(2, "a"), (5, "z"), (6, "b"), (7, "r"), (12, "w"), (34, "v"), (50, "q"), (51, "l")]) + evalTest "DomExclude Union" ((z2 ⋪ z1) ∪ z3) z4 + evalTest "Set difference" (z2 ➖ dom z1) (Sett (Set.fromList [2 :: Int, 13])) + evalCompile ((dom stkcred ◁ deleg) ▷ dom stpool) + evalCompile (l4 ⋫ Set.fromList ["m", "Z"]) + evalCompile (m0 ∪ singleton 3 'b') + evalCompile (setSingleton 2 ⋪ m0) + evalTest "ex1" (5 ∈ dom m12) True + evalTest "ex2" (70 ∈ dom m12) False + evalTest "ex3" (70 ∉ dom m12) True + evalTest "ex4" (m0 ∪ singleton 3 'b') (Map.insert 3 'b' m0) + evalTest "ex5" (setSingleton 2 ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) + evalTest "ex6" (dom (singleton 2 'z') ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) + evalTest "ex7" (rng (singleton 'z' 2) ⋪ m0) (Map.fromList [(1, 'a'), (4, 'g')]) + evalTest "ex8" (z2 ➖ dom z1) (Sett $ Set.fromList [13, 2]) -- =============== test of KeysEqual and its variants ===================== @@ -227,32 +225,30 @@ tree3 = Map.fromList [(i, i :: Int) | i <- [1 .. 19]] set1 :: Set.Set Int set1 = Set.fromList [1 .. 20] -keysEqTests :: TestTree +keysEqTests :: Spec keysEqTests = - testGroup - "keysEqual tests" - ( zipWith - tst - [(1 :: Int) ..] - [ (keysEqual tree1 tree2, True) - , (keysEqual tree2 tree1, True) - , (keysEqual tree1 tree3, False) - , (sameDomain tree1 tree2, True) - , (sameDomain tree2 tree1, True) - , (sameDomain tree1 tree3, False) - , (eval (tree1 ≍ tree2), True) - , (eval (tree1 ≍ tree3), False) - , (eval (tree1 ≍ set1), True) - , (eval (tree3 ≍ set1), False) - ] - ) + describe "keysEqual tests" $ do + zipWithM_ + tst + [(1 :: Int) ..] + [ (keysEqual tree1 tree2, True) + , (keysEqual tree2 tree1, True) + , (keysEqual tree1 tree3, False) + , (sameDomain tree1 tree2, True) + , (sameDomain tree2 tree1, True) + , (sameDomain tree1 tree3, False) + , (eval (tree1 ≍ tree2), True) + , (eval (tree1 ≍ tree3), False) + , (eval (tree1 ≍ set1), True) + , (eval (tree3 ≍ set1), False) + ] where - tst n (x, y) = testCase ("keysEqual " ++ show n) (assertEqual ("keysEqual " ++ show n) y x) + tst n (x, y) = specify ("keysEqual " ++ show n) $ y `shouldBe` x -- ========================== test that various Compound iterators work ================ -testcase :: (Eq k, Eq v, Show k, Show v, Iter f) => String -> f k v -> [(k, v)] -> TestTree -testcase nm col ans = testCase nm (assertEqual nm ans (runCollect (fifo col) [] (:))) +testcase :: (Eq k, Eq v, Show k, Show v, Iter f) => String -> f k v -> [(k, v)] -> Spec +testcase nm col ans = specify nm $ ans `shouldBe` runCollect (fifo col) [] (:) fromListD :: (Ord k, Iter f) => BaseRep f k v -> [(k, v)] -> Query k v fromListD rep xs = BaseD rep (fromList rep (\l _r -> l) xs) @@ -265,20 +261,17 @@ testAnd1 , testOr , testDiff1 , testDiff2 :: - Iter g => String -> BaseRep g Int String -> TestTree + Iter g => String -> BaseRep g Int String -> Spec testAnd1 nm rep = testcase nm (AndD (fromListD rep l1) (fromListD rep l2)) [(4, ("d", "d")), (5, ("e", "e")), (10, ("j", "j")), (21, ("v", "v"))] testAnd2 nm rep = - testCase - nm - ( assertEqual - nm - (runCollect (lifo (AndD (fromListD rep l1) (fromListD rep l2))) [] (:)) - (reverse [(4, ("d", "d")), (5, ("e", "e")), (10, ("j", "j")), (21, ("v", "v"))]) - ) + specify nm $ + shouldBe + (runCollect (lifo (AndD (fromListD rep l1) (fromListD rep l2))) [] (:)) + (reverse [(4, ("d", "d")), (5, ("e", "e")), (10, ("j", "j")), (21, ("v", "v"))]) testOr nm rep = testcase nm @@ -304,14 +297,14 @@ testDiff2 nm rep = testcase nm (DiffD (fromListD rep l2) (fromListD rep l1)) [(3 -- ========================================================================== -- tests where we vary both the data, and how it is represented. -testGuard :: (Show b, Iter f, Ord b) => String -> BaseRep f Int b -> [(Int, b)] -> TestTree +testGuard :: (Show b, Iter f, Ord b) => String -> BaseRep f Int b -> [(Int, b)] -> Spec testGuard nm rep f = testcase nm (GuardD (fromListD rep f) (domElem evens)) (filter (even . fst) f) -testProj :: (Show k, Ord k, Iter f) => String -> BaseRep f k [Char] -> [(k, [Char])] -> TestTree +testProj :: (Show k, Ord k, Iter f) => String -> BaseRep f k [Char] -> [(k, [Char])] -> Spec testProj nm rep f = testcase nm @@ -322,14 +315,14 @@ testProj nm rep f = -- tests where we AndP l1 and l3, and use different type of data for l1 from l3 -- We use the second projection in AndP, that is the value will come from l3 -testAndP :: (Iter f, Iter g) => String -> BaseRep f Int String -> BaseRep g Int Int -> TestTree +testAndP :: (Iter f, Iter g) => String -> BaseRep f Int String -> BaseRep g Int Int -> Spec testAndP nm rep1 rep2 = testcase nm (AndPD (fromListD rep1 l1) (fromListD rep2 l3) rngSnd) [(4, 12), (12, 44)] -testChain :: (Iter f, Iter g) => String -> BaseRep f Int String -> BaseRep g String Int -> TestTree +testChain :: (Iter f, Iter g) => String -> BaseRep f Int String -> BaseRep g String Int -> Spec testChain nm rep1 rep2 = testcase nm @@ -341,7 +334,7 @@ testChain nm rep1 rep2 = , (50, (50, "q", 107)) ] -testChain2 :: (Iter f, Iter g) => String -> BaseRep f String Int -> BaseRep g Int String -> TestTree +testChain2 :: (Iter f, Iter g) => String -> BaseRep f String Int -> BaseRep g Int String -> Spec testChain2 nm rep1 rep2 = testcase nm @@ -349,69 +342,64 @@ testChain2 nm rep1 rep2 = [("m", ("m", 105, "Z"))] -- This test inspired by set expression in EpochBoundary.hs -testEpochEx :: TestTree +testEpochEx :: Spec testEpochEx = - testCase - "Epoch Boundary Example" - ( assertEqual - "Epoch Boundary Example" - (Map.fromList [(6, True)]) - (eval (DRestrict (Dom (RRestrict (Base MapR delegs) (SetSingleton hk))) (Base MapR state))) - ) + specify "Epoch Boundary Example" $ + shouldBe + (Map.fromList [(6, True)]) + (eval (DRestrict (Dom (RRestrict (Base MapR delegs) (SetSingleton hk))) (Base MapR state))) where delegs = Map.fromList [(5 :: Int, "a"), (6, "b"), (12, "c"), (14, "e"), (20, "f"), (25, "g")] hk = "b" state = Map.fromList [(n, even n) | n <- [1 .. 13]] -iterTests :: TestTree +iterTests :: Spec iterTests = - testGroup - "Iterator tests" - [ testAnd1 "(And l1 l2) as List, fifo" ListR - , testAnd1 "(And l1 l2) as Map, fifo" MapR - , testAnd2 "(And l1 l2) as List, lifo" ListR - , testAnd2 "(And l1 l2) as Map, lifo" MapR - , testOr "(Or l1 l2) as List" ListR - , testOr "(Or l1 l2) as Map" MapR - , testDiff1 "(Diff l1 l2) as List" ListR -- (Diff is not symmetric) - , testDiff2 "(Diff l2 l1) as List" ListR - , testDiff1 "(Diff l1 l2) as Map" MapR - , testDiff2 "(Diff l2 l1) as Map" MapR - , testGuard "(Guard l1 even) as List" ListR l1 - , testGuard "(Guard l1 even) as Map" MapR l1 - , testGuard "(Guard l2 even) as List" ListR l2 - , testGuard "(Guard l2 even) as Map" MapR l2 - , testProj "(Proj l1 ord) as List" ListR l1 - , testProj "(Proj l1 ord) as Map" MapR l1 - , testProj "(Proj l2 ord) as List" ListR l2 - , testProj "(Proj l2 ord) as Map" MapR l2 - , testAndP "(AndP l1:List l3:Map ord)" ListR MapR - , testAndP "(AndP l1:Map l3:List ord)" MapR ListR - , testAndP "(AndP l1:Map l3:List Map)" MapR MapR - , testChain "(Chain l4:List l5:Map)" ListR MapR - , testChain "(Chain l4:Map l5:List)" MapR ListR - , testChain "(Chain l4:Map l5:List Map)" MapR MapR - , testChain2 "(Chain2 l5:List l4:Map)" ListR MapR - , testChain2 "(Chain2 l5:Map l4:List)" MapR ListR - , testChain2 "(Chain2 l5:Map l4:List Map)" MapR MapR - , testEpochEx - ] + describe "Iterator tests" $ do + testAnd1 "(And l1 l2) as List, fifo" ListR + testAnd1 "(And l1 l2) as Map, fifo" MapR + testAnd2 "(And l1 l2) as List, lifo" ListR + testAnd2 "(And l1 l2) as Map, lifo" MapR + testOr "(Or l1 l2) as List" ListR + testOr "(Or l1 l2) as Map" MapR + testDiff1 "(Diff l1 l2) as List" ListR -- (Diff is not symmetric) + testDiff2 "(Diff l2 l1) as List" ListR + testDiff1 "(Diff l1 l2) as Map" MapR + testDiff2 "(Diff l2 l1) as Map" MapR + testGuard "(Guard l1 even) as List" ListR l1 + testGuard "(Guard l1 even) as Map" MapR l1 + testGuard "(Guard l2 even) as List" ListR l2 + testGuard "(Guard l2 even) as Map" MapR l2 + testProj "(Proj l1 ord) as List" ListR l1 + testProj "(Proj l1 ord) as Map" MapR l1 + testProj "(Proj l2 ord) as List" ListR l2 + testProj "(Proj l2 ord) as Map" MapR l2 + testAndP "(AndP l1:List l3:Map ord)" ListR MapR + testAndP "(AndP l1:Map l3:List ord)" MapR ListR + testAndP "(AndP l1:Map l3:List Map)" MapR MapR + testChain "(Chain l4:List l5:Map)" ListR MapR + testChain "(Chain l4:Map l5:List)" MapR ListR + testChain "(Chain l4:Map l5:List Map)" MapR MapR + testChain2 "(Chain2 l5:List l4:Map)" ListR MapR + testChain2 "(Chain2 l5:Map l4:List)" MapR ListR + testChain2 "(Chain2 l5:Map l4:List Map)" MapR MapR + testEpochEx intersect2ways :: Map Int Char -> Map Int String -> Char -> Bool intersect2ways delegs stake hk = materialize MapR (do (x, y, z) <- delegs `domEq` stake; when (y == hk); one (x, z)) == intersectDomPLeft (\_k v2 -> v2 == hk) stake delegs -intersectDomPLeftTest :: TestTree -intersectDomPLeftTest = testProperty "intersect2ways" intersect2ways +intersectDomPLeftTest :: Spec +intersectDomPLeftTest = prop "intersect2ways" intersect2ways ledgerStateProp :: Map Int Bool -> Map Int Char -> Map Char String -> Bool ledgerStateProp xx yy zz = materialize MapR (do (x, _, y) <- xx `domEq` yy; y `element` zz; one (x, y)) == intersectDomP (\_k v -> Map.member v zz) xx yy -ledgerStateTest :: TestTree -ledgerStateTest = testProperty "ledgerStateExample2ways" ledgerStateProp +ledgerStateTest :: Spec +ledgerStateTest = prop "ledgerStateExample2ways" ledgerStateProp threeWay :: Map Int Char -> Map Int String -> Char -> Bool threeWay delegs stake hk = @@ -420,8 +408,8 @@ threeWay delegs stake hk = && runSet (dom (delegs ▷ Set.singleton hk) ◁ stake) == materialize MapR (do (x, y, z) <- delegs `domEq` stake; when (y == hk); one (x, z)) -threeWayTest :: TestTree -threeWayTest = testProperty "eval-materialize-intersectDom" threeWay +threeWayTest :: Spec +threeWayTest = prop "eval-materialize-intersectDom" threeWay -- ============================================================================== -- Slow property tests show that (compute e) and (runExp e) have the same answer. @@ -469,8 +457,8 @@ qtest expr = compute expr === runSet expr -- ====================================================== -slowFastEquiv :: TestTree -slowFastEquiv = testProperty "slowFastEquiv" slowProperties +slowFastEquiv :: Spec +slowFastEquiv = prop "slowFastEquiv" slowProperties slowProperties :: Key -> -- k @@ -485,7 +473,7 @@ slowProperties :: slowProperties k v m1 m2 s1 s2 rs ls = conjoin $ map - (\(prop, name) -> counterexample name prop) + (\(property, name) -> counterexample name property) [ (qtest (Dom (Base SetR (Sett s1))), "slow1") , (qtest (Dom (Base MapR m1)), "slow2") , (qtest (Dom (Base SetR (Sett s1))), "slow3") @@ -628,15 +616,13 @@ instance (Ord k, Arbitrary k) => Arbitrary (Sett k ()) where -- Tie all the tests together -- ==================================================== -setAlgTest :: TestTree +setAlgTest :: Spec setAlgTest = - testGroup - "Set Algebra Tests" - [ evalTests - , keysEqTests - , iterTests - , intersectDomPLeftTest - , ledgerStateTest - , threeWayTest - , slowFastEquiv - ] + describe "Set Algebra Tests" $ do + evalTests + keysEqTests + iterTests + intersectDomPLeftTest + ledgerStateTest + threeWayTest + slowFastEquiv diff --git a/libs/small-steps/small-steps.cabal b/libs/small-steps/small-steps.cabal index 5625fe27aa5..f11487408b6 100644 --- a/libs/small-steps/small-steps.cabal +++ b/libs/small-steps/small-steps.cabal @@ -79,12 +79,12 @@ library testlib cardano-strict-containers, deepseq, hedgehog >=1.0.4, + hspec, microlens, microlens-th, mtl, nothunks, small-steps >=1.0, - tasty-hunit, transformers >=0.5, test-suite tests diff --git a/libs/small-steps/testlib/Test/Control/State/Transition/Trace.hs b/libs/small-steps/testlib/Test/Control/State/Transition/Trace.hs index d6b980667bf..0940298639b 100644 --- a/libs/small-steps/testlib/Test/Control/State/Transition/Trace.hs +++ b/libs/small-steps/testlib/Test/Control/State/Transition/Trace.hs @@ -70,8 +70,8 @@ import GHC.Stack (HasCallStack) import Lens.Micro (Lens', lens, to, (^.), (^..)) import Lens.Micro.TH (makeLenses) import NoThunks.Class (NoThunks (..)) -import Test.Cardano.Ledger.Binary.TreeDiff (ToExpr, assertExprEqualWithMessage) -import Test.Tasty.HUnit (assertFailure, (@?=)) +import Test.Cardano.Ledger.Binary.TreeDiff (ToExpr, expectExprEqualWithMessage) +import Test.Hspec (expectationFailure, shouldBe) -- Signal and resulting state. -- @@ -412,7 +412,9 @@ mSt .- sig = do st <- mSt validation <- ask -- Get the validation function from the environment case validation st sig of - Left pfs -> liftIO . assertFailure . show $ pfs + Left pfs -> do + liftIO . expectationFailure . show $ pfs + pure st Right st' -> pure st' -- | Bind the state inside the first argument, and check whether it is equal to @@ -426,7 +428,7 @@ mSt .- sig = do m st mSt .->> stExpected = do stActual <- mSt - liftIO $ assertExprEqualWithMessage "Check trace with (.->>) fails" stExpected stActual + liftIO $ expectExprEqualWithMessage "Check trace with (.->>) fails" stExpected stActual return stActual -- | Bind the state inside the first argument, and check whether it is equal to @@ -439,7 +441,7 @@ mSt .->> stExpected = do m st mSt .-> stExpected = do stActual <- mSt - liftIO $ stActual @?= stExpected + liftIO $ stActual `shouldBe` stExpected return stActual checkTrace :: diff --git a/libs/vector-map/test/Main.hs b/libs/vector-map/test/Main.hs index e6fcf7ada6a..18d12eb83ff 100644 --- a/libs/vector-map/test/Main.hs +++ b/libs/vector-map/test/Main.hs @@ -1,16 +1,14 @@ module Main where -import Test.Tasty +import Test.Hspec import Test.VMap -- ==================================================================================== -tests :: TestTree +tests :: Spec tests = - testGroup - "vector-map" - [ vMapTests - ] + describe "vector-map" $ do + vMapTests main :: IO () -main = defaultMain tests +main = hspec tests diff --git a/libs/vector-map/test/Test/Common.hs b/libs/vector-map/test/Test/Common.hs index 72359da4065..07f6623efd1 100644 --- a/libs/vector-map/test/Test/Common.hs +++ b/libs/vector-map/test/Test/Common.hs @@ -9,21 +9,23 @@ module Test.Common ( ) where import Control.Applicative +import Data.Foldable (traverse_) import Data.Proxy as X +import Test.Hspec as X +import Test.Hspec.QuickCheck as X +import Test.QuickCheck as X import Test.QuickCheck.Classes.Base as X import Test.QuickCheck.Property (mapTotalResult, maybeNumTests) -import Test.Tasty as X -import Test.Tasty.QuickCheck as X withMaxTimesSuccess :: Testable prop => Int -> prop -> Property withMaxTimesSuccess !n = mapTotalResult $ \res -> res {maybeNumTests = (n *) <$> (maybeNumTests res <|> Just 100)} -testPropertyN :: Testable prop => Int -> TestName -> prop -> TestTree -testPropertyN n name = testProperty name . withMaxTimesSuccess n +testPropertyN :: Testable prop => Int -> String -> prop -> Spec +testPropertyN n name = prop name . withMaxTimesSuccess n -testLawsGroup :: TestName -> [Laws] -> TestTree -testLawsGroup name = testGroup name . fmap testLaws +testLawsGroup :: String -> [Laws] -> Spec +testLawsGroup name = describe name . traverse_ testLaws where testLaws Laws {..} = - testGroup lawsTypeclass $ fmap (uncurry testProperty) lawsProperties + describe lawsTypeclass $ traverse_ (uncurry prop) lawsProperties diff --git a/libs/vector-map/test/Test/VMap.hs b/libs/vector-map/test/Test/VMap.hs index 8c5364f68d7..306ce318a61 100644 --- a/libs/vector-map/test/Test/VMap.hs +++ b/libs/vector-map/test/Test/VMap.hs @@ -29,52 +29,46 @@ prop_AsMapTo fromVM fromM vm = fromVM vm === fromM (toMap vm) prop_AsMapFrom :: (a -> VMapT) -> (a -> MapT) -> a -> Property prop_AsMapFrom mkVMap mkMap a = toMap (mkVMap a) === mkMap a -vMapTests :: TestTree +vMapTests :: Spec vMapTests = - testGroup - "VMap" - [ testGroup - "roundtrip" - [ testProperty "to/fromAscDistinctList" $ - prop_Roundtrip VMap.toAscList VMap.fromDistinctAscList - , testProperty "to/fromAscList" $ prop_Roundtrip VMap.toAscList VMap.fromAscList - , testProperty "to/fromList" $ prop_Roundtrip VMap.toAscList VMap.fromList - , testProperty "to/fromMap" $ prop_Roundtrip VMap.toMap VMap.fromMap - ] - , testGroup - "asMap" - [ testProperty "fromList" $ prop_AsMapFrom VMap.fromList Map.fromList - , testProperty "fromAscListWithKey" $ \xs f -> - prop_AsMapFrom - (VMap.fromAscListWithKey (applyFun3 f)) - (Map.fromAscListWithKey (applyFun3 f)) - (List.sortOn fst xs) - , testProperty "fromAscListWithKeyN" $ \n xs f -> - prop_AsMapFrom - (VMap.fromAscListWithKeyN n (applyFun3 f)) - (Map.fromAscListWithKey (applyFun3 f) . take n) - (List.sortOn fst xs) - , testProperty "toAscList" $ prop_AsMapTo VMap.toAscList Map.toAscList - , testProperty "foldMapWithKey" $ \f -> - let f' k v = applyFun2 f k v :: String - in prop_AsMapTo (VMap.foldMapWithKey f') (Map.foldMapWithKey f') - , testProperty "lookup" $ \k -> prop_AsMapTo (VMap.lookup k) (Map.lookup k) - , testProperty "lookup (existing)" $ \k v xs -> - let xs' = xs <> [(k, v)] - in (VMap.lookup k (VMap.fromList xs' :: VMapT) === Just v) - .&&. (Map.lookup k (Map.fromList xs' :: MapT) === Just v) - , testProperty "finsWithDefault" $ \d k -> - prop_AsMapTo (VMap.findWithDefault d k) (Map.findWithDefault d k) - , testProperty "finsWithDefault (existing)" $ \k v xs -> - let xs' = xs <> [(k, v)] - in (VMap.findWithDefault undefined k (VMap.fromList xs' :: VMapT) === v) - .&&. (Map.findWithDefault undefined k (Map.fromList xs' :: MapT) === v) - ] - , testLawsGroup - "classes" - [ eqLaws (Proxy @VMapT) - , semigroupLaws (Proxy @VMapT) - , monoidLaws (Proxy @VMapT) - , isListLaws (Proxy @VMapT) - ] - ] + describe "VMap" $ do + describe "roundtrip" $ do + prop "to/fromAscDistinctList" $ + prop_Roundtrip VMap.toAscList VMap.fromDistinctAscList + prop "to/fromAscList" $ prop_Roundtrip VMap.toAscList VMap.fromAscList + prop "to/fromList" $ prop_Roundtrip VMap.toAscList VMap.fromList + prop "to/fromMap" $ prop_Roundtrip VMap.toMap VMap.fromMap + describe "asMap" $ do + prop "fromList" $ prop_AsMapFrom VMap.fromList Map.fromList + prop "fromAscListWithKey" $ \xs f -> + prop_AsMapFrom + (VMap.fromAscListWithKey (applyFun3 f)) + (Map.fromAscListWithKey (applyFun3 f)) + (List.sortOn fst xs) + prop "fromAscListWithKeyN" $ \n xs f -> + prop_AsMapFrom + (VMap.fromAscListWithKeyN n (applyFun3 f)) + (Map.fromAscListWithKey (applyFun3 f) . take n) + (List.sortOn fst xs) + prop "toAscList" $ prop_AsMapTo VMap.toAscList Map.toAscList + prop "foldMapWithKey" $ \f -> + let f' k v = applyFun2 f k v :: String + in prop_AsMapTo (VMap.foldMapWithKey f') (Map.foldMapWithKey f') + prop "lookup" $ \k -> prop_AsMapTo (VMap.lookup k) (Map.lookup k) + prop "lookup (existing)" $ \k v xs -> + let xs' = xs <> [(k, v)] + in (VMap.lookup k (VMap.fromList xs' :: VMapT) === Just v) + .&&. (Map.lookup k (Map.fromList xs' :: MapT) === Just v) + prop "findWithDefault" $ \d k -> + prop_AsMapTo (VMap.findWithDefault d k) (Map.findWithDefault d k) + prop "findWithDefault (existing)" $ \k v xs -> + let xs' = xs <> [(k, v)] + unfound = error $ "the expected key " <> show k <> " was not found" + in (VMap.findWithDefault unfound k (VMap.fromList xs' :: VMapT) === v) + .&&. (Map.findWithDefault unfound k (Map.fromList xs' :: MapT) === v) + testLawsGroup "classes" $ + [ eqLaws (Proxy @VMapT) + , semigroupLaws (Proxy @VMapT) + , monoidLaws (Proxy @VMapT) + , isListLaws (Proxy @VMapT) + ] diff --git a/libs/vector-map/vector-map.cabal b/libs/vector-map/vector-map.cabal index faafb4ce95f..43cdc33f78e 100644 --- a/libs/vector-map/vector-map.cabal +++ b/libs/vector-map/vector-map.cabal @@ -83,9 +83,8 @@ test-suite tests QuickCheck, base, containers, + hspec, quickcheck-classes-base, - tasty, - tasty-quickcheck, vector-map, benchmark bench