morley-upgradeable-0.3: test/Test/Lorentz/Contracts/UpgradeableCounterSdu.hs
-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ
module Test.Lorentz.Contracts.UpgradeableCounterSdu
( spec_UpgradeableCounterSdu
, test_Documentation
) where
import Lorentz (VoidResult(..), mkView, mkVoid)
import Data.Coerce (coerce)
import Test.Hspec (Spec, describe, it)
import Test.Tasty (TestTree)
import Lorentz.Constraints
import Lorentz.Contracts.Upgradeable.Common
import Lorentz.Contracts.Upgradeable.Test
import Lorentz.Contracts.UpgradeableCounterSdu
import qualified Lorentz.Contracts.UpgradeableCounterSdu.V1 as V1
import qualified Lorentz.Contracts.UpgradeableCounterSdu.V2 as V2
import Lorentz.Test
import Lorentz.Test.Doc
import Lorentz.UParam
import Lorentz.Value
import Util.Instances ()
import Util.Named
{-# ANN module ("HLint: ignore Reduce duplication" :: Text) #-}
admin :: Address
admin = genesisAddress1
originateUpgradeableCounter
:: IntegrationalScenarioM (UTAddress (CounterSduV 0))
originateUpgradeableCounter =
lOriginate upgradeableCounterContractSdu "UpgradeableCounter"
(mkEmptyStorage admin) (toMutez 1000)
originateUpgradeableCounterV1
:: IntegrationalScenarioM (UTAddress (CounterSduV 1))
originateUpgradeableCounterV1 = do
contract <- originateUpgradeableCounter
withSender admin $ upgradeToV1 UpgEntrypointWise contract
upgradeToV1
:: SimpleUpgradeWay
-> UTAddress (CounterSduV 0)
-> IntegrationalScenarioM (UTAddress (CounterSduV 1))
upgradeToV1 = integrationalTestUpgrade V1.counterUpgradeParameters
upgradeToV2
:: SimpleUpgradeWay
-> UTAddress (CounterSduV 1)
-> IntegrationalScenarioM (UTAddress (CounterSduV 2))
upgradeToV2 = integrationalTestUpgrade V2.counterUpgradeParameters
upgradeV0ToV2
:: SimpleUpgradeWay
-> UTAddress (CounterSduV 0)
-> IntegrationalScenarioM (UTAddress (CounterSduV 2))
upgradeV0ToV2 = integrationalTestUpgrade V2.counterUpgradeParametersFromV0
uCall
:: forall a name (ver :: VersionKind) (interface :: [EntrypointKind]).
( interface ~ VerInterface ver
, NicePackedValue a
, PermConstraint ver
, RequireUniqueEntrypoints interface
, LookupEntrypoint name interface ~ a
)
=> UTAddress ver
-> Label name
-> a
-> IntegrationalScenarioM ()
uCall contract method arg = do
lCallDef contract $ Run ((mkUParam method arg) :: UParam interface)
getCounterValueV1
:: UTAddress (CounterSduV 1)
-> IntegrationalScenarioM ()
getCounterValueV1 contract = do
uCall contract #epGetCounterValue $ mkVoid ()
getCounterValueV2
:: UTAddress (CounterSduV 2)
-> IntegrationalScenarioM ()
getCounterValueV2 contract = do
uCall contract #epGetCounterValue $ mkVoid ()
spec_UpgradeableCounterSdu :: Spec
spec_UpgradeableCounterSdu =
forM_ [UpgOneShot, UpgEntrypointWise] $ \upgWay ->
describe (show upgWay) $ do
-- Most of the logic is covered in tests for similar 'UpgradeableCounter'
-- contract (with entrypoint-wise migration way), not including such tests
-- here, only ones on the main functionality
describe "v1" $ do
it "Updates counter after each operation" $ do
integrationalTestExpectation $ do
contract <- originateUpgradeableCounterV1
uCall contract #epAdd (2 :: Natural)
uCall contract #epInc ()
getCounterValueV1 contract `catchExpectedError`
lExpectError (== VoidResult @Natural 3)
it "Can call permanent entrypoint" $ do
integrationalTestExpectation $ do
contract <- originateUpgradeableCounterV1
uCall contract #epAdd (5 :: Natural)
lCallEP contract (Call @"GetCounter") (mkVoid ()) `catchExpectedError`
lExpectError (== VoidResult @Integer 5)
describe "v2" $ do
it "Upgrade and further operations work fine" $ do
integrationalTestExpectation $ do
contract <- originateUpgradeableCounterV1
uCall contract #epAdd (2 :: Natural)
offshoot "Before migration" $ do
getCounterValueV1 contract `catchExpectedError`
lExpectError (== VoidResult @Natural 2)
contract2 <- withSender admin $ upgradeToV2 upgWay contract
offshoot "Right after migration" $ do
getCounterValueV2 contract2 `catchExpectedError`
lExpectError (== VoidResult @Integer 2)
offshoot "Cannot call removed entrypoint" $ do
uCall contract #epAdd (5 :: Natural) `catchExpectedError`
lExpectCustomError #uparamNoSuchEntrypoint [mt|epAdd|]
uCall contract2 #epDec ()
offshoot "After dec" $ do
getCounterValueV2 contract2 `catchExpectedError`
lExpectError (== VoidResult @Integer 1)
it "Upgrade from scratch works fine" $
integrationalTestExpectation $ do
contractV0 <- originateUpgradeableCounter
contract <- withSender admin $ upgradeV0ToV2 upgWay contractV0
branchout
[ "Can call operations" ?- do
uCall contract #epInc ()
uCall contract #epDec ()
, "Version field has expected value" ?- do
consumer <- lOriginateEmpty contractConsumer "consumer"
lCallEP contract (Call @"GetVersion") (mkView () consumer)
lExpectViewConsumerStorage consumer [2]
]
it "Can decrease version" $ do
integrationalTestExpectation $ do
contractV2 <- originateUpgradeableCounterV1 >>=
withSender admin . upgradeToV2 upgWay
contractV1 <-
withSender admin $
integrationalTestUpgrade V2.counterRollbackParameters upgWay contractV2
consumer <- lOriginateEmpty contractConsumer "consumer"
lCallDef contractV1 $ GetVersion (mkView () consumer)
lExpectViewConsumerStorage consumer [1]
it "Fails if wrong old version is provided" $ do
integrationalTestExpectation $ do
contract <- originateUpgradeableCounterV1
withSender admin (upgradeV0ToV2 upgWay (coerce contract)) `catchExpectedError`
lExpectCustomError #upgVersionMismatch
(#expectedCurrent .! 0, #actualCurrent .! 1)
it "Can call permanent entrypoint" $ do
integrationalTestExpectation $ do
contract <- originateUpgradeableCounterV1
uCall contract #epAdd (5 :: Natural)
contract2 <- withSender admin $ upgradeToV2 upgWay contract
uCall contract2 #epInc ()
lCallDef contract2 (RunPerm (GetCounter $ mkVoid ())) `catchExpectedError`
lExpectError (== VoidResult @Integer 6)
test_Documentation :: [TestTree]
test_Documentation =
runDocTests testSuites V1.counterDoc
where
testSuites =
testUpgradeableContractDoc `excludeDocTests`
[ testEachEntrypointIsDescribed
]