You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
6.8 KiB
201 lines
6.8 KiB
package judgment
|
|
|
|
import (
|
|
"github.com/stretchr/testify/assert"
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
func TestBunchOfWorkingScenarios(t *testing.T) {
|
|
type rawRanks []int
|
|
type rawTally []uint64
|
|
type test struct {
|
|
Name string
|
|
AmountOfJudges uint64
|
|
Proposals []rawTally
|
|
Ranks rawRanks
|
|
}
|
|
tests := []test{
|
|
{
|
|
Name: "Basic 01",
|
|
AmountOfJudges: 3,
|
|
Proposals: []rawTally{
|
|
[]uint64{1, 1, 1},
|
|
[]uint64{1, 2, 0},
|
|
[]uint64{0, 2, 1},
|
|
},
|
|
Ranks: []int{2, 3, 1},
|
|
},
|
|
{
|
|
Name: "Billions of participants",
|
|
AmountOfJudges: 20e9, // 20 billion
|
|
Proposals: []rawTally{
|
|
[]uint64{10e9, 10e9},
|
|
[]uint64{9999999999, 10000000001},
|
|
},
|
|
Ranks: []int{2, 1},
|
|
},
|
|
// …
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.Name, func(t *testing.T) {
|
|
proposalsTallies := make([]*ProposalTally, 0, 10)
|
|
for _, p := range tt.Proposals {
|
|
proposalTally := &ProposalTally{Tally: p}
|
|
proposalsTallies = append(proposalsTallies, proposalTally)
|
|
}
|
|
poll := &PollTally{
|
|
AmountOfJudges: tt.AmountOfJudges,
|
|
Proposals: proposalsTallies,
|
|
}
|
|
deliberator := &MajorityJudgment{}
|
|
result, err := deliberator.Deliberate(poll)
|
|
assert.NoError(t, err, "Deliberation should succeed")
|
|
for proposalResultIndex, proposalResult := range result.Proposals {
|
|
assert.Equal(t, tt.Ranks[proposalResultIndex], proposalResult.Rank, "Rank of proposal")
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestReadmeDemo(t *testing.T) {
|
|
poll := &PollTally{
|
|
AmountOfJudges: 10,
|
|
Proposals: []*ProposalTally{
|
|
{Tally: []uint64{2, 2, 2, 2, 2}},
|
|
{Tally: []uint64{2, 1, 1, 1, 5}},
|
|
{Tally: []uint64{2, 1, 1, 2, 4}},
|
|
{Tally: []uint64{2, 1, 5, 0, 2}},
|
|
{Tally: []uint64{2, 2, 2, 2, 2}},
|
|
},
|
|
}
|
|
deliberator := &MajorityJudgment{}
|
|
result, err := deliberator.Deliberate(poll)
|
|
assert.NoError(t, err, "Deliberation should succeed")
|
|
assert.Len(t, result.Proposals, len(poll.Proposals), "There should be as many results as there are tallies.")
|
|
assert.Equal(t, 4, result.Proposals[0].Rank, "Rank of proposal A")
|
|
assert.Equal(t, 1, result.Proposals[1].Rank, "Rank of proposal B")
|
|
assert.Equal(t, 2, result.Proposals[2].Rank, "Rank of proposal C")
|
|
assert.Equal(t, 3, result.Proposals[3].Rank, "Rank of proposal D")
|
|
assert.Equal(t, 4, result.Proposals[4].Rank, "Rank of proposal E")
|
|
|
|
assert.Equal(t, 1, result.ProposalsSorted[0].Rank, "Rank of sorted proposal A")
|
|
assert.Equal(t, 2, result.ProposalsSorted[1].Rank, "Rank of sorted proposal 1")
|
|
assert.Equal(t, 3, result.ProposalsSorted[2].Rank, "Rank of sorted proposal 2")
|
|
assert.Equal(t, 4, result.ProposalsSorted[3].Rank, "Rank of sorted proposal 3")
|
|
assert.Equal(t, 4, result.ProposalsSorted[4].Rank, "Rank of sorted proposal 4")
|
|
|
|
assert.Equal(t, 1, result.ProposalsSorted[0].Index, "Index of sorted proposal A")
|
|
assert.Equal(t, 2, result.ProposalsSorted[1].Index, "Index of sorted proposal 1")
|
|
assert.Equal(t, 3, result.ProposalsSorted[2].Index, "Index of sorted proposal 2")
|
|
assert.Equal(t, 0, result.ProposalsSorted[3].Index, "Index of sorted proposal 3")
|
|
assert.Equal(t, 4, result.ProposalsSorted[4].Index, "Index of sorted proposal 4")
|
|
|
|
}
|
|
|
|
func TestGuessingAmountOfJudges(t *testing.T) {
|
|
poll := &PollTally{
|
|
Proposals: []*ProposalTally{
|
|
{Tally: []uint64{2, 2, 2, 2, 2}},
|
|
{Tally: []uint64{2, 1, 1, 1, 5}},
|
|
{Tally: []uint64{2, 1, 1, 2, 4}},
|
|
{Tally: []uint64{2, 1, 5, 0, 2}},
|
|
{Tally: []uint64{2, 2, 2, 2, 2}},
|
|
},
|
|
}
|
|
deliberator := &MajorityJudgment{}
|
|
result, err := deliberator.Deliberate(poll)
|
|
assert.NoError(t, err, "Deliberation should succeed")
|
|
assert.Len(t, result.Proposals, len(poll.Proposals), "There should be as many results as there are tallies.")
|
|
assert.Equal(t, 4, result.Proposals[0].Rank, "Rank of proposal A")
|
|
assert.Equal(t, 1, result.Proposals[1].Rank, "Rank of proposal B")
|
|
assert.Equal(t, 2, result.Proposals[2].Rank, "Rank of proposal C")
|
|
assert.Equal(t, 3, result.Proposals[3].Rank, "Rank of proposal D")
|
|
assert.Equal(t, 4, result.Proposals[4].Rank, "Rank of proposal E")
|
|
|
|
assert.Equal(t, 1, result.ProposalsSorted[0].Rank, "Rank of sorted proposal A")
|
|
assert.Equal(t, 2, result.ProposalsSorted[1].Rank, "Rank of sorted proposal 1")
|
|
assert.Equal(t, 3, result.ProposalsSorted[2].Rank, "Rank of sorted proposal 2")
|
|
assert.Equal(t, 4, result.ProposalsSorted[3].Rank, "Rank of sorted proposal 3")
|
|
assert.Equal(t, 4, result.ProposalsSorted[4].Rank, "Rank of sorted proposal 4")
|
|
|
|
assert.Equal(t, 1, result.ProposalsSorted[0].Index, "Index of sorted proposal A")
|
|
assert.Equal(t, 2, result.ProposalsSorted[1].Index, "Index of sorted proposal 1")
|
|
assert.Equal(t, 3, result.ProposalsSorted[2].Index, "Index of sorted proposal 2")
|
|
assert.Equal(t, 0, result.ProposalsSorted[3].Index, "Index of sorted proposal 3")
|
|
assert.Equal(t, 4, result.ProposalsSorted[4].Index, "Index of sorted proposal 4")
|
|
|
|
}
|
|
|
|
func TestNoProposals(t *testing.T) {
|
|
poll := &PollTally{
|
|
AmountOfJudges: 0,
|
|
Proposals: []*ProposalTally{},
|
|
}
|
|
deliberator := &MajorityJudgment{}
|
|
result, err := deliberator.Deliberate(poll)
|
|
assert.NoError(t, err, "Deliberation should succeed")
|
|
assert.Len(t, result.Proposals, len(poll.Proposals), "There should be as many results as there are tallies.")
|
|
}
|
|
|
|
func TestIncoherentTally(t *testing.T) {
|
|
poll := &PollTally{
|
|
AmountOfJudges: 2, // lower than expected 8
|
|
Proposals: []*ProposalTally{
|
|
{Tally: []uint64{4, 4}},
|
|
{Tally: []uint64{2, 6}},
|
|
},
|
|
}
|
|
deliberator := &MajorityJudgment{}
|
|
result, err := deliberator.Deliberate(poll)
|
|
assert.Error(t, err, "Deliberation should fail")
|
|
assert.Nil(t, result, "Deliberation result should be nil")
|
|
}
|
|
|
|
func TestMishapedTally(t *testing.T) {
|
|
poll := &PollTally{
|
|
AmountOfJudges: 10,
|
|
Proposals: []*ProposalTally{
|
|
{Tally: []uint64{2, 2, 2, 2, 2}},
|
|
{Tally: []uint64{2, 2, 2, 2}},
|
|
},
|
|
}
|
|
deliberator := &MajorityJudgment{}
|
|
result, err := deliberator.Deliberate(poll)
|
|
assert.Error(t, err, "Deliberation should fail")
|
|
assert.Nil(t, result, "Deliberation result should be nil")
|
|
}
|
|
|
|
func TestUnbalancedTally(t *testing.T) {
|
|
poll := &PollTally{
|
|
AmountOfJudges: 10,
|
|
Proposals: []*ProposalTally{
|
|
{Tally: []uint64{2, 2, 2, 2, 2}},
|
|
{Tally: []uint64{2, 0, 0, 0, 2}},
|
|
},
|
|
}
|
|
deliberator := &MajorityJudgment{}
|
|
result, err := deliberator.Deliberate(poll)
|
|
assert.Error(t, err, "Deliberation should fail")
|
|
assert.Nil(t, result, "Deliberation result should be nil")
|
|
}
|
|
|
|
func TestExcessivelyBigTally(t *testing.T) {
|
|
// math.MaxInt64 + 1 is a valid uint64 value, but we need to cast to int internally so it overflows
|
|
poll := &PollTally{
|
|
AmountOfJudges: math.MaxInt64 + 1,
|
|
Proposals: []*ProposalTally{
|
|
{Tally: []uint64{math.MaxInt64, 1}},
|
|
{Tally: []uint64{math.MaxInt64, 1}},
|
|
},
|
|
}
|
|
deliberator := &MajorityJudgment{}
|
|
result, err := deliberator.Deliberate(poll)
|
|
if assert.Error(t, err, "Deliberation should fail") {
|
|
//println(err.Error())
|
|
}
|
|
assert.Nil(t, result, "Deliberation result should be nil")
|
|
}
|