cleveland-0.1.1: lorentz-test/Test/Lorentz/StoreClass/StorageEntrypoints.hs
-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA
module Test.Lorentz.StoreClass.StorageEntrypoints
( test_Storage_entrypoints
) where
import Prelude hiding (drop, swap)
import Data.Constraint (Dict(..), (:-)(Sub))
import Test.Tasty (TestTree)
import Lorentz.ADT
import Lorentz.Annotation (HasAnnotation)
import Lorentz.Base
import Lorentz.Constraints
import Lorentz.Entrypoints
import Lorentz.Entrypoints.Doc
import Lorentz.Instr
import Lorentz.Macro
import Lorentz.Run
import Lorentz.StoreClass
import Lorentz.Value
import Test.Cleveland
import Test.Cleveland.Lorentz
----------------------------------------------------------------------------
-- Types
----------------------------------------------------------------------------
data ParameterEpTest
= AddNat Natural
| SubNat Natural
| GetValue (View_ () Natural)
| SetSubNat (EntrypointLambda Natural Natural)
deriving stock Generic
deriving anyclass (IsoValue)
instance ParameterHasEntrypoints ParameterEpTest where
type ParameterEntrypointsDerivation ParameterEpTest = EpdPlain
data StorageEpTest = StorageEpTest
{ epNats :: EntrypointsField Natural Natural
, storeNat :: Natural
} deriving stock Generic
deriving anyclass IsoValue
deriving anyclass HasAnnotation
instance StoreHasEntrypoint StorageEpTest "addNat" Natural Natural where
storeEpOps = storeEntrypointOpsADT #epNats #storeNat
instance StoreHasEntrypoint StorageEpTest "subNat" Natural Natural where
storeEpOps = storeEntrypointOpsADT #epNats #storeNat
instance StoreHasField StorageEpTest "storeNat" Natural where
storeFieldOps = storeFieldOpsADT
type StorageIsEpTest store =
( StorageContains store
[ "addNat" := Natural ::-> Natural
, "subNat" := Natural ::-> Natural
, "storeNat" := Natural
]
, Dupable store
)
----------------------------------------------------------------------------
-- Impl
----------------------------------------------------------------------------
addNat :: EntrypointLambda Natural Natural
addNat = unpair # add # nil # pair
subNat :: EntrypointLambda Natural Natural
subNat = unpair # swap # sub # isNat # ifSome nop (push 0) # nil # pair
mkStorageEpTestFull :: Natural -> StorageEpTest
mkStorageEpTestFull n = StorageEpTest
{ epNats = mkStoreEp #addNat addNat <> mkStoreEp #subNat subNat
, storeNat = n
}
mkStorageEpTestPart :: Natural -> StorageEpTest
mkStorageEpTestPart n = StorageEpTest
{ epNats = mkStoreEp #addNat addNat
, storeNat = n
}
contractEpTest :: StorageIsEpTest store => ContractCode ParameterEpTest store
contractEpTest = unpair # entryCaseSimple @ParameterEpTest
( #cAddNat /-> stEntrypoint #addNat
, #cSubNat /-> stEntrypoint #subNat
, #cGetValue /-> view_ (drop @() # stToField #storeNat)
, #cSetSubNat /-> stSetEpLambda #subNat # nil # pair
)
----------------------------------------------------------------------------
-- Tests
----------------------------------------------------------------------------
originateEpContract
:: MonadCleveland caps m
=> StorageEpTest
-> m (ContractHandle ParameterEpTest StorageEpTest ())
originateEpContract st = originate $ OriginateData "StEps" 0 st (defaultContract contractEpTest)
test_Storage_entrypoints :: [TestTree]
test_Storage_entrypoints =
[ testScenario "Executes both entrypoints correctly when set at origination" $ scenario do
testCon <- originateEpContract $ mkStorageEpTestFull 10
consumer <- originateSimple "consumer" def contractConsumer
call testCon CallDefault $ GetValue (mkView_ () consumer)
call testCon CallDefault $ AddNat 10
call testCon CallDefault $ GetValue (mkView_ () consumer)
call testCon CallDefault $ SubNat 5
call testCon CallDefault $ GetValue (mkView_ () consumer)
getStorage consumer @@== [15, 20, 10]
, testScenario "Cannot set entrypoint that was set at origination" $ scenario do
testCon <- originateEpContract $ mkStorageEpTestFull 10
expectFailedWith [mt|Storage entrypoint already set: subNat|] $
call testCon CallDefault (SetSubNat subNat)
, testScenario "Cannot set entrypoint twice" $ scenario do
testCon <- originateEpContract $ mkStorageEpTestPart 10
call testCon CallDefault $ SetSubNat subNat
expectFailedWith [mt|Storage entrypoint already set: subNat|] $
call testCon CallDefault (SetSubNat subNat)
, testScenario "Executes correctly entrypoint set after origination" $ scenario do
testCon <- originateEpContract $ mkStorageEpTestPart 10
consumer <- originateSimple "consumer" def contractConsumer
call testCon CallDefault $ GetValue (mkView_ () consumer)
call testCon CallDefault $ AddNat 5
call testCon CallDefault $ GetValue (mkView_ () consumer)
call testCon CallDefault $ SetSubNat subNat
call testCon CallDefault $ SubNat 20
call testCon CallDefault $ GetValue (mkView_ () consumer)
getStorage consumer @@== [0, 15, 10]
]
----------------------------------------------------------------------------
-- Tests on conveniences
----------------------------------------------------------------------------
type StorageC store meta = StorageContains store
'[ "field" := Identity meta
]
_storeFieldConstraintInterpretedCorrectly :: StorageC store meta :- StoreHasField store "field" meta
_storeFieldConstraintInterpretedCorrectly = Sub Dict