From 014b0b9944e76c0661e9a9770b333c006216a377 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 22 Nov 2017 23:15:10 +0000 Subject: [PATCH] evidence: reactor test --- evidence/reactor_test.go | 127 +++++++++++++++++++++++++++++++++++++++ evidence/store_test.go | 10 +-- 2 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 evidence/reactor_test.go diff --git a/evidence/reactor_test.go b/evidence/reactor_test.go new file mode 100644 index 000000000..d6e8653bc --- /dev/null +++ b/evidence/reactor_test.go @@ -0,0 +1,127 @@ +package evidence + +import ( + "fmt" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/go-kit/kit/log/term" + + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" + + cfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/types" +) + +// evidenceLogger is a TestingLogger which uses a different +// color for each validator ("validator" key must exist). +func evidenceLogger() log.Logger { + return log.TestingLoggerWithColorFn(func(keyvals ...interface{}) term.FgBgColor { + for i := 0; i < len(keyvals)-1; i += 2 { + if keyvals[i] == "validator" { + return term.FgBgColor{Fg: term.Color(uint8(keyvals[i+1].(int) + 1))} + } + } + return term.FgBgColor{} + }) +} + +// connect N evidence reactors through N switches +func makeAndConnectEvidenceReactors(config *cfg.Config, N int) []*EvidenceReactor { + reactors := make([]*EvidenceReactor, N) + logger := evidenceLogger() + for i := 0; i < N; i++ { + + config := &cfg.EvidenceConfig{} + store := NewEvidenceStore(dbm.NewMemDB()) + state := mockState{} + pool := NewEvidencePool(config, store, state) + reactors[i] = NewEvidenceReactor(config, pool) + reactors[i].SetLogger(logger.With("validator", i)) + } + + p2p.MakeConnectedSwitches(config.P2P, N, func(i int, s *p2p.Switch) *p2p.Switch { + s.AddReactor("EVIDENCE", reactors[i]) + return s + + }, p2p.Connect2Switches) + return reactors +} + +// wait for all evidence on all reactors +func waitForEvidence(t *testing.T, evs types.EvidenceList, reactors []*EvidenceReactor) { + // wait for the evidence in all evpools + wg := new(sync.WaitGroup) + for i := 0; i < len(reactors); i++ { + wg.Add(1) + go _waitForEvidence(t, wg, evs, i, reactors) + } + + done := make(chan struct{}) + go func() { + wg.Wait() + close(done) + }() + + timer := time.After(TIMEOUT) + select { + case <-timer: + t.Fatal("Timed out waiting for evidence") + case <-done: + } +} + +// wait for all evidence on a single evpool +func _waitForEvidence(t *testing.T, wg *sync.WaitGroup, evs types.EvidenceList, reactorIdx int, reactors []*EvidenceReactor) { + + evpool := reactors[reactorIdx].evpool + for len(evpool.PendingEvidence()) != len(evs) { + time.Sleep(time.Millisecond * 100) + } + + reapedEv := evpool.PendingEvidence() + // put the reaped evidence is a map so we can quickly check we got everything + evMap := make(map[string]types.Evidence) + for _, e := range reapedEv { + evMap[string(e.Hash())] = e + } + for i, expectedEv := range evs { + gotEv := evMap[string(expectedEv.Hash())] + assert.Equal(t, expectedEv, gotEv, + fmt.Sprintf("evidence at index %d on reactor %d don't match: %v vs %v", + i, reactorIdx, expectedEv, gotEv)) + } + wg.Done() +} + +func sendEvidence(t *testing.T, evpool *EvidencePool, n int) types.EvidenceList { + evList := make([]types.Evidence, n) + for i := 0; i < n; i++ { + ev := newMockGoodEvidence(i, 2, []byte("val")) + err := evpool.AddEvidence(ev) + assert.Nil(t, err) + evList[i] = ev + } + return evList +} + +var ( + NUM_EVIDENCE = 1000 + TIMEOUT = 120 * time.Second // ridiculously high because CircleCI is slow +) + +func TestReactorBroadcastEvidence(t *testing.T) { + config := cfg.TestConfig() + N := 7 + reactors := makeAndConnectEvidenceReactors(config, N) + + // send a bunch of evidence to the first reactor's evpool + // and wait for them all to be received in the others + evList := sendEvidence(t, reactors[0].evpool, NUM_EVIDENCE) + waitForEvidence(t, evList, reactors) +} diff --git a/evidence/store_test.go b/evidence/store_test.go index 6cd9b244e..ca55a98dc 100644 --- a/evidence/store_test.go +++ b/evidence/store_test.go @@ -131,10 +131,12 @@ func newMockGoodEvidence(height, index int, address []byte) MockGoodEvidence { return MockGoodEvidence{height, address, index} } -func (e MockGoodEvidence) Height() int { return e.Height_ } -func (e MockGoodEvidence) Address() []byte { return e.Address_ } -func (e MockGoodEvidence) Index() int { return e.Index_ } -func (e MockGoodEvidence) Hash() []byte { return []byte{byte(e.Index_)} } +func (e MockGoodEvidence) Height() int { return e.Height_ } +func (e MockGoodEvidence) Address() []byte { return e.Address_ } +func (e MockGoodEvidence) Index() int { return e.Index_ } +func (e MockGoodEvidence) Hash() []byte { + return []byte(fmt.Sprintf("%d-%d", e.Height_, e.Index_)) +} func (e MockGoodEvidence) Verify(chainID string) error { return nil } func (e MockGoodEvidence) Equal(ev types.Evidence) bool { e2 := ev.(MockGoodEvidence)