275 lines
11 KiB
Haskell
275 lines
11 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 Agora.Proposal (
|
|
Proposal (..),
|
|
ProposalStatus (..),
|
|
)
|
|
import Agora.Proposal.Scripts (proposalPolicy)
|
|
import Sample.Proposal qualified as Proposal
|
|
import Sample.Proposal.Advance qualified as Advance
|
|
import Sample.Proposal.Cosign qualified as Cosign
|
|
import Sample.Proposal.UnlockStake qualified as UnlockStake
|
|
import Sample.Proposal.Vote qualified as Vote
|
|
import Sample.Shared qualified as Shared (proposal)
|
|
import Test.Specification (
|
|
SpecificationTree,
|
|
group,
|
|
policySucceedsWith,
|
|
)
|
|
|
|
-- | Stake specs.
|
|
specs :: [SpecificationTree]
|
|
specs =
|
|
[ group
|
|
"policy"
|
|
[ policySucceedsWith
|
|
"proposalCreation"
|
|
(proposalPolicy Shared.proposal.governorSTAssetClass)
|
|
()
|
|
Proposal.proposalCreation
|
|
]
|
|
, group
|
|
"validator"
|
|
[ group
|
|
"cosignature"
|
|
$ let cosignerCases = [1, 5, 10]
|
|
|
|
mkLegalGroup nCosigners =
|
|
Cosign.mkTestTree
|
|
("with " <> show nCosigners <> " cosigners")
|
|
(Cosign.validCosignNParameters nCosigners)
|
|
True
|
|
legalGroup =
|
|
group "legal" $
|
|
map mkLegalGroup cosignerCases
|
|
|
|
mkIllegalStatusNotDraftGroup nCosigners =
|
|
group ("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
|
|
, Cosign.mkTestTree
|
|
"altered output stake"
|
|
Cosign.invalidStakeOutputParameters
|
|
False
|
|
, illegalStatusNotDraftGroup
|
|
]
|
|
in [legalGroup, illegalGroup]
|
|
, group
|
|
"voting"
|
|
[ Vote.mkTestTree "legal" Vote.validVoteParameters True
|
|
-- TODO: add negative test cases
|
|
]
|
|
, group "advancing" $
|
|
let mkFromDraft nCosigners =
|
|
let name = "with " <> show nCosigners <> " cosigner(s)"
|
|
|
|
legalGroup =
|
|
group
|
|
"legal"
|
|
[ Advance.mkTestTree
|
|
"to next state"
|
|
( head $
|
|
Advance.advanceToNextStateInTimeParameters
|
|
nCosigners
|
|
)
|
|
True
|
|
, Advance.mkTestTree
|
|
"to failed state"
|
|
( head $
|
|
Advance.advanceToFailedStateDueToTimeoutParameters
|
|
nCosigners
|
|
)
|
|
True
|
|
]
|
|
|
|
illegalGroup =
|
|
group
|
|
"illegal"
|
|
[ Advance.mkTestTree
|
|
"insufficient cosigns"
|
|
(Advance.insufficientCosignsParameters nCosigners)
|
|
False
|
|
, Advance.mkTestTree
|
|
"invalid stake output"
|
|
(head $ Advance.invalidOutputStakeParameters nCosigners)
|
|
False
|
|
]
|
|
in group name [legalGroup, illegalGroup]
|
|
|
|
draftGroup = group "from draft" $ map mkFromDraft [1, 5, 10]
|
|
|
|
legalGroup =
|
|
group
|
|
"legal"
|
|
[ group "advance to next state" $
|
|
map
|
|
( \ps ->
|
|
let name = "from: " <> show ps.fromStatus
|
|
in Advance.mkTestTree name ps True
|
|
)
|
|
(tail $ Advance.advanceToNextStateInTimeParameters 1)
|
|
, group "advance to failed state" $
|
|
map
|
|
( \ps ->
|
|
let name = "from: " <> show ps.fromStatus
|
|
in Advance.mkTestTree name ps True
|
|
)
|
|
(tail $ Advance.advanceToFailedStateDueToTimeoutParameters 1)
|
|
]
|
|
|
|
illegalGroup =
|
|
group
|
|
"illegal"
|
|
[ Advance.mkTestTree
|
|
"insufficient votes"
|
|
Advance.insufficientVotesParameters
|
|
False
|
|
, Advance.mkTestTree
|
|
"initial state is Finished"
|
|
Advance.advanceFromFinishedParameters
|
|
False
|
|
, group
|
|
"invalid stake output"
|
|
$ do
|
|
nStake <- [1, 5]
|
|
ps <- tail $ Advance.invalidOutputStakeParameters nStake
|
|
|
|
let name =
|
|
"from " <> show ps.fromStatus <> "with "
|
|
<> show nStake
|
|
<> " stakes"
|
|
|
|
pure $ Advance.mkTestTree name ps False
|
|
]
|
|
in [draftGroup, legalGroup, illegalGroup]
|
|
, group "unlocking" $ do
|
|
proposalCount <- [1, 42]
|
|
|
|
let legalGroup = group "legal" $ do
|
|
let voterRetractVotesAndUnlockStakeWhileVoting =
|
|
UnlockStake.mkProposalValidatorTestCase
|
|
UnlockStake.UnlockStakeParameters
|
|
{ UnlockStake.proposalCount = proposalCount
|
|
, UnlockStake.stakeUsage = UnlockStake.Voter
|
|
, UnlockStake.retractVotes = True
|
|
, UnlockStake.proposalStatus = VotingReady
|
|
}
|
|
True
|
|
creatorUnlockStakeWhileFinished =
|
|
UnlockStake.mkProposalValidatorTestCase
|
|
UnlockStake.UnlockStakeParameters
|
|
{ UnlockStake.proposalCount = proposalCount
|
|
, UnlockStake.stakeUsage = UnlockStake.Creator
|
|
, UnlockStake.retractVotes = False
|
|
, UnlockStake.proposalStatus = Finished
|
|
}
|
|
True
|
|
|
|
let voterUnlockStakeAfterVoting = group "voter unlocks stake after voting" $ do
|
|
status <- [Finished, Locked]
|
|
|
|
pure $
|
|
UnlockStake.mkProposalValidatorTestCase
|
|
UnlockStake.UnlockStakeParameters
|
|
{ UnlockStake.proposalCount = proposalCount
|
|
, UnlockStake.stakeUsage = UnlockStake.Voter
|
|
, UnlockStake.retractVotes = False
|
|
, UnlockStake.proposalStatus = status
|
|
}
|
|
True
|
|
|
|
[ voterRetractVotesAndUnlockStakeWhileVoting
|
|
, creatorUnlockStakeWhileFinished
|
|
, voterUnlockStakeAfterVoting
|
|
]
|
|
|
|
let illegalGroup = group "illegal" $ do
|
|
let retractsVotesWhileNotVotingReady =
|
|
group "voter retracts votes while not voting" $ do
|
|
status <- [Draft, Locked, Finished]
|
|
|
|
pure $
|
|
UnlockStake.mkProposalValidatorTestCase
|
|
UnlockStake.UnlockStakeParameters
|
|
{ UnlockStake.proposalCount = proposalCount
|
|
, UnlockStake.stakeUsage = UnlockStake.Voter
|
|
, UnlockStake.retractVotes = True
|
|
, UnlockStake.proposalStatus = status
|
|
}
|
|
False
|
|
|
|
unlockIrrelevantStake =
|
|
group "unlock an irrelevant stake" $ do
|
|
status <- [Draft, VotingReady, Locked, Finished]
|
|
shouldRetractVotes <- [True, False]
|
|
|
|
pure $
|
|
UnlockStake.mkProposalValidatorTestCase
|
|
UnlockStake.UnlockStakeParameters
|
|
{ UnlockStake.proposalCount = proposalCount
|
|
, UnlockStake.stakeUsage = UnlockStake.Irrelevant
|
|
, UnlockStake.retractVotes = shouldRetractVotes
|
|
, UnlockStake.proposalStatus = status
|
|
}
|
|
False
|
|
|
|
unlockCreatorStakeBeforeFinished =
|
|
group "unlock creator stake before finished" $ do
|
|
status <- [Draft, VotingReady, Locked]
|
|
|
|
pure $
|
|
UnlockStake.mkProposalValidatorTestCase
|
|
UnlockStake.UnlockStakeParameters
|
|
{ UnlockStake.proposalCount = proposalCount
|
|
, UnlockStake.stakeUsage = UnlockStake.Creator
|
|
, UnlockStake.retractVotes = False
|
|
, UnlockStake.proposalStatus = status
|
|
}
|
|
False
|
|
retractVotesWithCreatorStake =
|
|
group "creator stake retracts votes" $ do
|
|
status <- [Draft, VotingReady, Locked, Finished]
|
|
|
|
pure $
|
|
UnlockStake.mkProposalValidatorTestCase
|
|
UnlockStake.UnlockStakeParameters
|
|
{ UnlockStake.proposalCount = proposalCount
|
|
, UnlockStake.stakeUsage = UnlockStake.Creator
|
|
, UnlockStake.retractVotes = True
|
|
, UnlockStake.proposalStatus = status
|
|
}
|
|
False
|
|
|
|
[ retractsVotesWhileNotVotingReady
|
|
, unlockIrrelevantStake
|
|
, unlockCreatorStakeBeforeFinished
|
|
, retractVotesWithCreatorStake
|
|
]
|
|
|
|
[legalGroup, illegalGroup]
|
|
]
|
|
]
|