agora/agora-specs/Spec/Proposal.hs
2022-10-03 17:20:41 +08:00

426 lines
18 KiB
Haskell

{- |
Module : Spec.Proposal
Maintainer : emi@haskell.fyi
Description: Tests for Proposal policy and validator
Tests for Proposal policy and validator
-}
module Spec.Proposal (specs) where
import Sample.Proposal.Advance qualified as Advance
import Sample.Proposal.Cosign qualified as Cosign
import Sample.Proposal.Create qualified as Create
import Sample.Proposal.UnlockStake qualified as UnlockStake
import Sample.Proposal.Vote qualified as Vote
-- import Sample.Proposal.UnlockStake qualified as UnlockStake
import Test.Specification (
SpecificationTree,
group,
)
-- | Stake specs.
specs :: [SpecificationTree]
specs =
[ group
"policy (proposal creation)"
[ Create.mkTestTree
"legal"
Create.totallyValidParameters
True
True
True
, group
"illegal"
[ Create.mkTestTree
"invalid next proposal id"
Create.invalidOutputGovernorDatumParameters
True
False
True
, Create.mkTestTree
"use other's stake"
Create.useStakeOwnBySomeoneElseParameters
True
True
False
, Create.mkTestTree
"altered stake"
Create.invalidOutputStakeParameters
True
False
False
, Create.mkTestTree
"invalid stake locks"
Create.addInvalidLocksParameters
True
True
False
, Create.mkTestTree
"has reached maximum proposals limit"
Create.exceedMaximumProposalsParameters
True
False
True
, Create.mkTestTree
"loose time range"
Create.timeRangeNotTightParameters
True
False
True
, Create.mkTestTree
"open time range"
Create.timeRangeNotClosedParameters
True
False
True
, group "invalid proposal status" $
map
( \ps ->
Create.mkTestTree
(show ps.proposalStatus)
ps
True
False
True
)
Create.invalidProposalStatusParameters
]
]
, group
"validator"
[ group
"cosignature"
$ let cosignerCases = [1, 5, 10]
mkLegalGroup nCosigners =
Cosign.mkTestTree
(unwords ["with", show nCosigners, "cosigners"])
(Cosign.validCosignNParameters nCosigners)
True
legalGroup =
group "legal" $
map mkLegalGroup cosignerCases
mkIllegalStatusNotDraftGroup nCosigners =
group (unwords ["with", show nCosigners, "cosigners"]) $
map
( \ps ->
Cosign.mkTestTree
("status: " <> show ps.proposalStatus)
ps
False
)
(Cosign.statusNotDraftCosignNParameters nCosigners)
illegalStatusNotDraftGroup =
group "proposal status not Draft" $
map mkIllegalStatusNotDraftGroup cosignerCases
illegalGroup =
group
"illegal"
[ Cosign.mkTestTree
"duplicate cosigners"
Cosign.duplicateCosignersParameters
False
, illegalStatusNotDraftGroup
]
in [legalGroup, illegalGroup]
, group
"voting"
[ group
"legal"
[ group "different number of stakes" $
map
( \s ->
group
(unwords [show s, "stakes"])
[ Vote.mkTestTree
"by owner"
(Vote.mkValidOwnerVoteBundle s)
(Vote.Validity True True)
, Vote.mkTestTree
"by delegatee"
(Vote.mkValidDelegateeVoteBundle s)
(Vote.Validity True True)
]
)
[1, 3, 5, 7, 9]
, Vote.mkTestTree
"transparent non-GT tokens"
Vote.transparentAssets
(Vote.Validity True True)
]
, group
"illegal"
[ Vote.mkTestTree
"vote for nonexistent outcome"
Vote.voteForNonexistentOutcome
(Vote.Validity False True)
, Vote.mkTestTree
"unauthorized tx"
Vote.transactionNotAuthorized
(Vote.Validity True False)
, Vote.mkTestTree
"no proposal"
Vote.noProposal
(Vote.Validity False False)
, Vote.mkTestTree
"more than one proposals"
Vote.voteForNonexistentOutcome
(Vote.Validity False True)
, Vote.mkTestTree
"locks not added"
Vote.invalidLocks
(Vote.Validity True False)
, Vote.mkTestTree
"attempt to burn stakes"
Vote.destroyStakes
(Vote.Validity True False)
]
]
, group
"advancing"
$ let possibleCosigners = [1, 5, 10]
possibleEffects = [1, 2, 5]
in do
cs <- possibleCosigners
es <- possibleEffects
let groupName =
unwords
[ "with"
, show cs
, "cosigners"
, "and"
, show es
, "effects"
]
pure $
group
groupName
[ group
"legal"
$ let allValid =
Advance.Validity
{ forProposalValidator = True
, forStakeValidator = True
, forGovernorValidator = Just True
, forAuthorityTokenPolicy = Just True
}
mkName b =
unwords
[ "from"
, show b.proposalParameters.fromStatus
, "to"
, show b.proposalParameters.toStatus
]
in [ Advance.mkTestTree'
"to next state"
mkName
(Advance.mkValidToNextStateBundles cs es)
allValid
, Advance.mkTestTree'
"to failed state"
mkName
(Advance.mkValidToFailedStateBundles cs es)
allValid
]
, group
"illegal"
[ Advance.mkTestTree'
"advance finished proposals"
(const "(negative test)")
(Advance.mkFromFinishedBundles cs es)
Advance.Validity
{ forProposalValidator = False
, forStakeValidator = True
, forGovernorValidator = Just False
, forAuthorityTokenPolicy = Just True
}
, Advance.mkTestTree
"insufficient cosigns"
(Advance.mkInsufficientCosignsBundle cs es)
Advance.Validity
{ forProposalValidator = False
, forStakeValidator = True
, forGovernorValidator = Nothing
, forAuthorityTokenPolicy = Nothing
}
, Advance.mkTestTree
"insufficient votes"
(Advance.mkInsufficientVotesBundle cs es)
Advance.Validity
{ forProposalValidator = False
, forStakeValidator = True
, forGovernorValidator = Nothing
, forAuthorityTokenPolicy = Nothing
}
, Advance.mkTestTree
"ambiguous winning effect"
(Advance.mkAmbiguousWinnerBundle cs es)
Advance.Validity
{ forProposalValidator = False
, forStakeValidator = True
, forGovernorValidator = Nothing
, forAuthorityTokenPolicy = Nothing
}
, Advance.mkTestTree'
"to next state too late"
(\b -> unwords ["from", show b.proposalParameters.fromStatus])
(Advance.mkToNextStateTooLateBundles cs es)
Advance.Validity
{ forProposalValidator = False
, forStakeValidator = True
, forGovernorValidator = Just True
, forAuthorityTokenPolicy = Just True
}
, Advance.mkTestTree
"forget to mint GATs"
(Advance.mkNoGATMintedBundle cs es)
Advance.Validity
{ forProposalValidator = True
, forStakeValidator = True
, forGovernorValidator = Just False
, forAuthorityTokenPolicy = Nothing
}
, Advance.mkTestTree
"mint GATs for wrong validators"
(Advance.mkMintGATsForWrongEffectsBundle cs es)
Advance.Validity
{ forProposalValidator = True
, forStakeValidator = True
, forGovernorValidator = Just False
, forAuthorityTokenPolicy = Just True
}
, Advance.mkTestTree
"mint GATs with bad token name"
(Advance.mkMintGATsWithoutTagBundle cs es)
Advance.Validity
{ forProposalValidator = True
, forStakeValidator = True
, forGovernorValidator = Just False
, forAuthorityTokenPolicy = Just True
}
, Advance.mkTestTree
"wrong GAT datum"
(Advance.mkGATsWithWrongDatumBundle cs es)
Advance.Validity
{ forProposalValidator = True
, forStakeValidator = True
, forGovernorValidator = Just False
, forAuthorityTokenPolicy = Just True
}
, Advance.mkTestTree
"invalid governor output datum"
(Advance.mkBadGovernorOutputDatumBundle cs es)
Advance.Validity
{ forProposalValidator = True
, forStakeValidator = True
, forGovernorValidator = Just False
, forAuthorityTokenPolicy = Just True
}
]
]
, group "unlocking" $
let proposalCountCases = [1, 5, 10, 42]
mkSubgroupName nProposals = unwords ["with", show nProposals, "proposals"]
mkLegalGroup nProposals =
group
(mkSubgroupName nProposals)
[ UnlockStake.mkTestTree
"voter: retract votes while voting"
(UnlockStake.mkVoterRetractVotesWhileVotingParameters nProposals)
True
, UnlockStake.mkTestTree
"voter/creator: retract votes while voting"
(UnlockStake.mkVoterCreatorRetractVotesWhileVotingParameters nProposals)
True
, UnlockStake.mkTestTree
"creator: remove creator locks when finished"
(UnlockStake.mkCreatorRemoveCreatorLocksWhenFinishedParameters nProposals)
True
, UnlockStake.mkTestTree
"voter/creator: remove all locks when finished"
(UnlockStake.mkVoterCreatorRemoveAllLocksWhenFinishedParameters nProposals)
True
, group "voter: unlock after voting" $
map
( \ps ->
let name = show ps.proposalStatus
in UnlockStake.mkTestTree name ps True
)
(UnlockStake.mkVoterUnlockStakeAfterVotingParameters nProposals)
, UnlockStake.mkTestTree
"voter/creator: remove vote locks when locked"
(UnlockStake.mkVoterCreatorRemoveVoteLocksWhenLockedParameters nProposals)
True
]
mkIllegalGroup nProposals =
group
(mkSubgroupName nProposals)
[ group "retract votes while not voting" $
map
( \ps ->
let name =
unwords
[ "role:"
, show ps.stakeRole
, ","
, "status:"
, show ps.proposalStatus
]
in UnlockStake.mkTestTree name ps False
)
(UnlockStake.mkRetractVotesWhileNotVoting nProposals)
, group "unlock an irrelevant stake" $
map
( \ps ->
let name =
unwords
[ "status:"
, show ps.proposalStatus
, "retract votes:"
, show ps.retractVotes
]
in UnlockStake.mkTestTree name ps False
)
(UnlockStake.mkUnockIrrelevantStakeParameters nProposals)
, group "remove creator too early" $
map
( \ps ->
let name =
unwords
["status:", show ps.proposalStatus]
in UnlockStake.mkTestTree name ps False
)
(UnlockStake.mkRemoveCreatorLockBeforeFinishedParameters nProposals)
, UnlockStake.mkTestTree
"creator: retract votes"
(UnlockStake.mkRetractVotesWithCreatorStakeParamaters nProposals)
False
, group "alter output stake datum" $
map
( \ps ->
let name =
unwords
[ "role:"
, show ps.stakeRole
, ","
, "status:"
, show ps.proposalStatus
]
in UnlockStake.mkTestTree name ps False
)
(UnlockStake.mkAlterStakeParameters nProposals)
]
legalGroup = group "legal" $ map mkLegalGroup proposalCountCases
illegalGroup = group "illegal" $ map mkIllegalGroup proposalCountCases
in [legalGroup, illegalGroup]
]
]