cleveland-0.1.1: lorentz-test/Test/Lorentz/Tickets/Helpers.hs
-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA
-- | Tests on tickets helpers from "Lorentz.Tickets" module.
module Test.Lorentz.Tickets.Helpers
( test_ActionAuth
, test_TokenAllowance
) where
import Test.Tasty (TestTree, testGroup)
import Lorentz qualified as L
import Lorentz.Value
import Morley.Util.Named
import Test.Cleveland
import Test.Cleveland.Lorentz.Ticketer
import Test.Lorentz.Tickets.Contracts
test_ActionAuth :: [TestTree]
test_ActionAuth =
let prepare
:: MonadCleveland caps m
=> m ( ContractHandle (Ticket Integer) Bool ()
, ContractHandle (L.View_ ((), (Natural, Integer)) (Ticket Integer)) () ()
)
prepare = do
ticketer <- originateSimple "ticketer" () (ticketerContract' L.drop)
launcher <- originateSimple "launcher" False (atomicMissileLaunchContract $ toTAddress ticketer)
return (launcher, ticketer)
in
[ testScenario "Normal scenario works" $ scenario do
(launcher, ticketer) <- prepare
callViaTicketer ticketer 1 12345 launcher ()
, testScenario "Bad ticket data causes failure" $ scenario do
(launcher, ticketer) <- prepare
callViaTicketer ticketer 1 123 launcher ()
& expectFailedWith [mt|Bad code|]
, testScenario "Bad tokens number causes failure" $ scenario do
(launcher, ticketer) <- prepare
callViaTicketer ticketer 0 12345 launcher ()
& expectCustomErrorNoArg #nOT_SINGLE_TICKET_TOKEN
callViaTicketer ticketer 3 12345 launcher ()
& expectCustomErrorNoArg #nOT_SINGLE_TICKET_TOKEN
, testScenario "Wrong ticketer causes failure" $ scenario do
(launcher, _ticketer) <- prepare
fakeTicketer <- originateSimple "fake-ticketer" () (ticketerContract' L.drop)
callViaTicketer fakeTicketer 3 12345 launcher ()
& expectCustomErrorNoArg #wRONG_TICKETER
]
test_TokenAllowance :: [TestTree]
test_TokenAllowance =
let prepare
:: MonadCleveland caps m
=> m ( ContractHandle PermitTokensParameter PermitTokensStorage ()
, ContractHandle (L.View_ ((), (Natural, ())) (Ticket ())) () ()
)
prepare = do
ticketer <- originateSimple "ticketer" () (ticketerContract' L.drop)
let initStorage = PermitTokensStorage Nothing (toAddress ticketer)
token <- originateSimple "token" initStorage permitTokensContract
return (token, ticketer)
in
[ testGroup "Allowances"
[ testScenario "Permitting tokens works" $ scenario do
-- TODO: Would be actually nice to try hedgehog here once it is available for cleveland
(token, ticketer) <- prepare
callViaTicketer ticketer 5 () (callingAddress token (Call @"PermitAllow")) ()
callViaTicketer ticketer 3 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitGet") (L.mkVoid ())
& expectError (L.VoidResult @Natural 8)
, testScenario "Permitting 0 tokens works" $ scenario do
(token, ticketer) <- prepare
callViaTicketer ticketer 0 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitGet") (L.mkVoid ())
& expectError (L.VoidResult @Natural 0)
, testScenario "Permitting tokens from wrong ticketer fails" $ scenario do
(token, _ticketer) <- prepare
fakeTicketer <- originateSimple "fake-ticketer" () (ticketerContract' L.drop)
callViaTicketer fakeTicketer 1 () (callingAddress token (Call @"PermitAllow")) ()
& expectCustomErrorNoArg #wRONG_TICKETER
]
, testGroup "Spendings"
[ testScenario "Spending tokens works" $ scenario do
(token, ticketer) <- prepare
callViaTicketer ticketer 5 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitSpend") 3
call token (Call @"PermitGet") (L.mkVoid ())
& expectError (L.VoidResult @Natural 2)
, testScenario "Spending too many tokens fails" $ scenario do
(token, ticketer) <- prepare
callViaTicketer ticketer 5 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitSpend") 8
& expectCustomError #insufficient_tokens_permitted_by_ticket
(#permitted :! 5, #spent :! 8)
, testScenario "Can repeatedly exhaust all allowances" $ scenario do
(token, ticketer) <- prepare
callViaTicketer ticketer 5 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitSpend") 3
call token (Call @"PermitSpend") 2
callViaTicketer ticketer 0 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitSpend") 0
callViaTicketer ticketer 1 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitSpend") 1
callViaTicketer ticketer 3 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitGet") (L.mkVoid ())
& expectError (L.VoidResult @Natural 3)
]
, testGroup "Admin change"
[ testScenario "Admin change takes effect" $ scenario do
(token, ticketer) <- prepare
ticketer2 <- originateSimple "ticketer2" () (ticketerContract' L.drop)
callViaTicketer ticketer 5 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitSetAdmin") (toAddress ticketer2)
call token (Call @"PermitGet") (L.mkVoid ())
& expectError (L.VoidResult @Natural 0)
callViaTicketer ticketer 5 () (callingAddress token (Call @"PermitAllow")) ()
& expectCustomErrorNoArg #wRONG_TICKETER
callViaTicketer ticketer2 5 () (callingAddress token (Call @"PermitAllow")) ()
call token (Call @"PermitGet") (L.mkVoid ())
& expectError (L.VoidResult @Natural 5)
]
]
{- We do not cover 'allowancesContract' with tests since there is nothing
special there comparing to 'permitTokensContract', the contract exists only to
demonstrate implementation for a contract that stores an entire map of tickets.
-}
_untestedContract1 :: [TestTree]
_untestedContract1 = const [] allowancesContract
{-# ANN _untestedContract1 ("HLint: ignore Evaluate" :: Text) #-}