Skip to content

Commit

Permalink
tests: Fix flaky TestAccountSelected test (#5788)
Browse files Browse the repository at this point in the history
  • Loading branch information
ohill committed Oct 19, 2023
1 parent ad162dc commit 51db0fa
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
18 changes: 13 additions & 5 deletions data/committee/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,19 @@ func signTx(s *crypto.SignatureSecrets, t transactions.Transaction) transactions
return t.Sign(s)
}

func testingenv(t testing.TB, numAccounts, numTxs int) (selectionParameterFn, selectionParameterListFn, basics.Round, []basics.Address, []*crypto.SignatureSecrets, []*crypto.VrfPrivkey, []*crypto.OneTimeSignatureSecrets, []transactions.SignedTxn) {
return testingenvMoreKeys(t, numAccounts, numTxs, uint(5))
// testingenv creates a random set of participating accounts and random transactions between them, and
// the associated selection parameters for use testing committee membership and credential validation.
// seedGen is provided as an external source of randomness for the selection seed and transaction notes;
// if the caller persists seedGen between calls to testingenv, each iteration that calls testingenv will
// exercise a new selection seed.
func testingenv(t testing.TB, numAccounts, numTxs int, seedGen io.Reader) (selectionParameterFn, selectionParameterListFn, basics.Round, []basics.Address, []*crypto.SignatureSecrets, []*crypto.VrfPrivkey, []*crypto.OneTimeSignatureSecrets, []transactions.SignedTxn) {
return testingenvMoreKeys(t, numAccounts, numTxs, uint(5), seedGen)
}

func testingenvMoreKeys(t testing.TB, numAccounts, numTxs int, keyBatchesForward uint) (selectionParameterFn, selectionParameterListFn, basics.Round, []basics.Address, []*crypto.SignatureSecrets, []*crypto.VrfPrivkey, []*crypto.OneTimeSignatureSecrets, []transactions.SignedTxn) {
func testingenvMoreKeys(t testing.TB, numAccounts, numTxs int, keyBatchesForward uint, seedGen io.Reader) (selectionParameterFn, selectionParameterListFn, basics.Round, []basics.Address, []*crypto.SignatureSecrets, []*crypto.VrfPrivkey, []*crypto.OneTimeSignatureSecrets, []transactions.SignedTxn) {
if seedGen == nil {
seedGen = rand.New(rand.NewSource(1)) // same source as setting GODEBUG=randautoseed=0, same as pre-Go 1.20 default seed
}
P := numAccounts // n accounts
TXs := numTxs // n txns
maxMoneyAtStart := 100000 // max money start
Expand Down Expand Up @@ -89,7 +97,7 @@ func testingenvMoreKeys(t testing.TB, numAccounts, numTxs int, keyBatchesForward
}

var seed Seed
rand.Read(seed[:])
seedGen.Read(seed[:])

tx := make([]transactions.SignedTxn, TXs)
for i := 0; i < TXs; i++ {
Expand All @@ -115,7 +123,7 @@ func testingenvMoreKeys(t testing.TB, numAccounts, numTxs int, keyBatchesForward
Amount: amt,
},
}
rand.Read(t.Note)
seedGen.Read(t.Note) // to match output from previous versions, which shared global RNG for seed & note
tx[i] = t.Sign(secrets[send])
}

Expand Down
37 changes: 28 additions & 9 deletions data/committee/credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"math/rand" // used for replicability of sortition benchmark
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/algorand/go-algorand/data/basics"
Expand All @@ -31,9 +32,10 @@ import (
func TestAccountSelected(t *testing.T) {
partitiontest.PartitionTest(t)

seedGen := rand.New(rand.NewSource(1))
N := 1
for i := 0; i < N; i++ {
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, seedGen)
period := Period(0)

leaders := uint64(0)
Expand Down Expand Up @@ -85,13 +87,18 @@ func TestAccountSelected(t *testing.T) {
if (committee < uint64(0.8*float64(step.CommitteeSize(proto)))) || (committee > uint64(1.2*float64(step.CommitteeSize(proto)))) {
t.Errorf("bad number of committee members %v expected %v", committee, step.CommitteeSize(proto))
}
if i == 0 {
// pin down deterministic outputs for first iteration
assert.EqualValues(t, 17, leaders)
assert.EqualValues(t, 2918, committee)
}
}
}

func TestRichAccountSelected(t *testing.T) {
partitiontest.PartitionTest(t)

selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 10, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 10, 2000, nil)

period := Period(0)
ok, record, selectionSeed, _ := selParams(addresses[0])
Expand Down Expand Up @@ -139,16 +146,20 @@ func TestRichAccountSelected(t *testing.T) {
if (ccred.Weight < uint64(0.4*float64(step.CommitteeSize(proto)))) || (ccred.Weight > uint64(.6*float64(step.CommitteeSize(proto)))) {
t.Errorf("bad number of committee members %v expected %v", ccred.Weight, step.CommitteeSize(proto))
}
// pin down deterministic outputs, given initial seed values
assert.EqualValues(t, 6, lcred.Weight)
assert.EqualValues(t, 735, ccred.Weight)
}

func TestPoorAccountSelectedLeaders(t *testing.T) {
partitiontest.PartitionTest(t)

seedGen := rand.New(rand.NewSource(1))
N := 2
failsLeaders := 0
leaders := make([]uint64, N)
for i := 0; i < N; i++ {
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, seedGen)
period := Period(0)
for j := range addresses {
ok, record, selectionSeed, _ := selParams(addresses[j])
Expand Down Expand Up @@ -184,15 +195,19 @@ func TestPoorAccountSelectedLeaders(t *testing.T) {
if failsLeaders == 2 {
t.Errorf("bad number of leaders %v expected %v", leaders, proto.NumProposers)
}
// pin down deterministic outputs, given initial seed values
assert.EqualValues(t, 18, leaders[0])
assert.EqualValues(t, 20, leaders[1])
}

func TestPoorAccountSelectedCommittee(t *testing.T) {
partitiontest.PartitionTest(t)

seedGen := rand.New(rand.NewSource(1))
N := 1
committee := uint64(0)
for i := 0; i < N; i++ {
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, seedGen)
period := Period(0)

step := Cert
Expand Down Expand Up @@ -223,15 +238,19 @@ func TestPoorAccountSelectedCommittee(t *testing.T) {
if (committee < uint64(0.8*float64(step.CommitteeSize(proto)))) || (committee > uint64(1.2*float64(step.CommitteeSize(proto)))) {
t.Errorf("bad number of committee members %v expected %v", committee, step.CommitteeSize(proto))
}
if i == 0 { // pin down deterministic committee size, given initial seed value
assert.EqualValues(t, 1513, committee)
}
}
}

func TestNoMoneyAccountNotSelected(t *testing.T) {
partitiontest.PartitionTest(t)

seedGen := rand.New(rand.NewSource(1))
N := 1
for i := 0; i < N; i++ {
selParams, _, round, addresses, _, _, _, _ := testingenv(t, 10, 2000)
selParams, _, round, addresses, _, _, _, _ := testingenv(t, 10, 2000, seedGen)
lookback := basics.Round(2*proto.SeedRefreshInterval + proto.SeedLookback + 1)
gen := rand.New(rand.NewSource(2))
_, _, zeroVRFSecret, _ := newAccount(t, gen, lookback, 5)
Expand Down Expand Up @@ -262,7 +281,7 @@ func TestNoMoneyAccountNotSelected(t *testing.T) {
func TestLeadersSelected(t *testing.T) {
partitiontest.PartitionTest(t)

selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, nil)

period := Period(0)
step := Propose
Expand Down Expand Up @@ -294,7 +313,7 @@ func TestLeadersSelected(t *testing.T) {
func TestCommitteeSelected(t *testing.T) {
partitiontest.PartitionTest(t)

selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, nil)

period := Period(0)
step := Soft
Expand Down Expand Up @@ -326,7 +345,7 @@ func TestCommitteeSelected(t *testing.T) {
func TestAccountNotSelected(t *testing.T) {
partitiontest.PartitionTest(t)

selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, nil)
period := Period(0)
leaders := uint64(0)
for i := range addresses {
Expand Down Expand Up @@ -356,7 +375,7 @@ func TestAccountNotSelected(t *testing.T) {

// TODO update to remove VRF verification overhead
func BenchmarkSortition(b *testing.B) {
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(b, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(b, 100, 2000, nil)

period := Period(0)
step := Soft
Expand Down

0 comments on commit 51db0fa

Please sign in to comment.