diff --git a/blockchain/pool.go b/blockchain/pool.go index 236bf7e09..804a43250 100644 --- a/blockchain/pool.go +++ b/blockchain/pool.go @@ -364,22 +364,23 @@ func (pool *BlockPool) sendError(err error, peerID p2p.ID) { } // for debugging purposes -// func (pool *BlockPool) debug() string { -// pool.mtx.Lock() -// defer pool.mtx.Unlock() - -// str := "" -// nextHeight := pool.height + pool.requestersLen() -// for h := pool.height; h < nextHeight; h++ { -// if pool.requesters[h] == nil { -// str += fmt.Sprintf("H(%v):X ", h) -// } else { -// str += fmt.Sprintf("H(%v):", h) -// str += fmt.Sprintf("B?(%v) ", pool.requesters[h].block != nil) -// } -// } -// return str -// } +//nolint:unused +func (pool *BlockPool) debug() string { + pool.mtx.Lock() + defer pool.mtx.Unlock() + + str := "" + nextHeight := pool.height + pool.requestersLen() + for h := pool.height; h < nextHeight; h++ { + if pool.requesters[h] == nil { + str += fmt.Sprintf("H(%v):X ", h) + } else { + str += fmt.Sprintf("H(%v):", h) + str += fmt.Sprintf("B?(%v) ", pool.requesters[h].block != nil) + } + } + return str +} //------------------------------------- diff --git a/consensus/common_test.go b/consensus/common_test.go index 4e3d60e1d..e6e64c252 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -378,36 +378,6 @@ func ensureNewEvent( } } -// func ensureNewRoundStep(stepCh <-chan interface{}, height int64, round int) { -// ensureNewEvent( -// stepCh, -// height, -// round, -// ensureTimeout, -// "Timeout expired while waiting for NewStep event") -// } - -// func ensureNewVote(voteCh <-chan interface{}, height int64, round int) { -// select { -// case <-time.After(ensureTimeout): -// break -// case v := <-voteCh: -// edv, ok := v.(types.EventDataVote) -// if !ok { -// panic(fmt.Sprintf("expected a *types.Vote, "+ -// "got %v. wrong subscription channel?", -// reflect.TypeOf(v))) -// } -// vote := edv.Vote -// if vote.Height != height { -// panic(fmt.Sprintf("expected height %v, got %v", height, vote.Height)) -// } -// if vote.Round != round { -// panic(fmt.Sprintf("expected round %v, got %v", round, vote.Round)) -// } -// } -// } - func ensureNewRound(roundCh <-chan interface{}, height int64, round int) { select { case <-time.After(ensureTimeout): diff --git a/crypto/merkle/proof_test.go b/crypto/merkle/proof_test.go index 504156246..4de3246f1 100644 --- a/crypto/merkle/proof_test.go +++ b/crypto/merkle/proof_test.go @@ -26,17 +26,18 @@ func NewDominoOp(key, input, output string) DominoOp { } } -// func DominoOpDecoder(pop ProofOp) (ProofOperator, error) { -// if pop.Type != ProofOpDomino { -// panic("unexpected proof op type") -// } -// var op DominoOp // a bit strange as we'll discard this, but it works. -// err := amino.UnmarshalBinaryLengthPrefixed(pop.Data, &op) -// if err != nil { -// return nil, cmn.ErrorWrap(err, "decoding ProofOp.Data into SimpleValueOp") -// } -// return NewDominoOp(string(pop.Key), op.Input, op.Output), nil -// } +//nolint:unused +func DominoOpDecoder(pop ProofOp) (ProofOperator, error) { + if pop.Type != ProofOpDomino { + panic("unexpected proof op type") + } + var op DominoOp // a bit strange as we'll discard this, but it works. + err := amino.UnmarshalBinaryLengthPrefixed(pop.Data, &op) + if err != nil { + return nil, cmn.ErrorWrap(err, "decoding ProofOp.Data into SimpleValueOp") + } + return NewDominoOp(string(pop.Key), op.Input, op.Output), nil +} func (dop DominoOp) ProofOp() ProofOp { bz := amino.MustMarshalBinaryLengthPrefixed(dop) diff --git a/libs/clist/clist_test.go b/libs/clist/clist_test.go index edf013752..7fb7db4d2 100644 --- a/libs/clist/clist_test.go +++ b/libs/clist/clist_test.go @@ -2,6 +2,8 @@ package clist import ( "fmt" + "runtime" + "sync/atomic" "testing" "time" @@ -65,98 +67,100 @@ func TestSmall(t *testing.T) { // This test is quite hacky because it relies on SetFinalizer // which isn't guaranteed to run at all. -//func TestGCFifo(t *testing.T) { -// if runtime.GOARCH != "amd64" { -// t.Skipf("Skipping on non-amd64 machine") -// } - -// const numElements = 1000000 -// l := New() -// gcCount := new(uint64) - -// // SetFinalizer doesn't work well with circular structures, -// // so we construct a trivial non-circular structure to -// // track. -// type value struct { -// Int int -// } -// done := make(chan struct{}) - -// for i := 0; i < numElements; i++ { -// v := new(value) -// v.Int = i -// l.PushBack(v) -// runtime.SetFinalizer(v, func(v *value) { -// atomic.AddUint64(gcCount, 1) -// }) -// } - -// for el := l.Front(); el != nil; { -// l.Remove(el) -// //oldEl := el -// el = el.Next() -// //oldEl.DetachPrev() -// //oldEl.DetachNext() -// } - -// runtime.GC() -// time.Sleep(time.Second * 3) -// runtime.GC() -// time.Sleep(time.Second * 3) -// _ = done - -// if *gcCount != numElements { -// t.Errorf("Expected gcCount to be %v, got %v", numElements, -// *gcCount) -// } -//} +//nolint:unused,deadcode +func _TestGCFifo(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skipf("Skipping on non-amd64 machine") + } + + const numElements = 1000000 + l := New() + gcCount := new(uint64) + + // SetFinalizer doesn't work well with circular structures, + // so we construct a trivial non-circular structure to + // track. + type value struct { + Int int + } + done := make(chan struct{}) + + for i := 0; i < numElements; i++ { + v := new(value) + v.Int = i + l.PushBack(v) + runtime.SetFinalizer(v, func(v *value) { + atomic.AddUint64(gcCount, 1) + }) + } + + for el := l.Front(); el != nil; { + l.Remove(el) + //oldEl := el + el = el.Next() + //oldEl.DetachPrev() + //oldEl.DetachNext() + } + + runtime.GC() + time.Sleep(time.Second * 3) + runtime.GC() + time.Sleep(time.Second * 3) + _ = done + + if *gcCount != numElements { + t.Errorf("Expected gcCount to be %v, got %v", numElements, + *gcCount) + } +} // This test is quite hacky because it relies on SetFinalizer // which isn't guaranteed to run at all. -// func TestGCRandom(t *testing.T) { -// if runtime.GOARCH != "amd64" { -// t.Skipf("Skipping on non-amd64 machine") -// } - -// const numElements = 1000000 -// l := New() -// gcCount := 0 - -// // SetFinalizer doesn't work well with circular structures, -// // so we construct a trivial non-circular structure to -// // track. -// type value struct { -// Int int -// } - -// for i := 0; i < numElements; i++ { -// v := new(value) -// v.Int = i -// l.PushBack(v) -// runtime.SetFinalizer(v, func(v *value) { -// gcCount++ -// }) -// } - -// els := make([]*CElement, 0, numElements) -// for el := l.Front(); el != nil; el = el.Next() { -// els = append(els, el) -// } - -// for _, i := range cmn.RandPerm(numElements) { -// el := els[i] -// l.Remove(el) -// _ = el.Next() -// } - -// runtime.GC() -// time.Sleep(time.Second * 3) - -// if gcCount != numElements { -// t.Errorf("Expected gcCount to be %v, got %v", numElements, -// gcCount) -// } -// } +//nolint:unused,deadcode +func TestGCRandom(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skipf("Skipping on non-amd64 machine") + } + + const numElements = 1000000 + l := New() + gcCount := 0 + + // SetFinalizer doesn't work well with circular structures, + // so we construct a trivial non-circular structure to + // track. + type value struct { + Int int + } + + for i := 0; i < numElements; i++ { + v := new(value) + v.Int = i + l.PushBack(v) + runtime.SetFinalizer(v, func(v *value) { + gcCount++ + }) + } + + els := make([]*CElement, 0, numElements) + for el := l.Front(); el != nil; el = el.Next() { + els = append(els, el) + } + + for _, i := range cmn.RandPerm(numElements) { + el := els[i] + l.Remove(el) + _ = el.Next() + } + + runtime.GC() + time.Sleep(time.Second * 3) + + if gcCount != numElements { + t.Errorf("Expected gcCount to be %v, got %v", numElements, + gcCount) + } +} func TestScanRightDeleteRandom(t *testing.T) { diff --git a/lite/proxy/query_test.go b/lite/proxy/query_test.go index 707430b61..9547f7713 100644 --- a/lite/proxy/query_test.go +++ b/lite/proxy/query_test.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -20,7 +21,8 @@ import ( var node *nm.Node var chainID = "tendermint_test" // TODO use from config. -// var waitForEventTimeout = 5 * time.Second +//nolint:unused +var waitForEventTimeout = 5 * time.Second // TODO fix tests!! @@ -41,83 +43,84 @@ func kvstoreTx(k, v []byte) []byte { // TODO: enable it after general proof format has been adapted // in abci/examples/kvstore.go -// func TestAppProofs(t *testing.T) { -// assert, require := assert.New(t), require.New(t) - -// prt := defaultProofRuntime() -// cl := client.NewLocal(node) -// client.WaitForHeight(cl, 1, nil) - -// // This sets up our trust on the node based on some past point. -// source := certclient.NewProvider(chainID, cl) -// seed, err := source.LatestFullCommit(chainID, 1, 1) -// require.NoError(err, "%#v", err) -// cert := lite.NewBaseVerifier(chainID, seed.Height(), seed.Validators) - -// // Wait for tx confirmation. -// done := make(chan int64) -// go func() { -// evtTyp := types.EventTx -// _, err = client.WaitForOneEvent(cl, evtTyp, waitForEventTimeout) -// require.Nil(err, "%#v", err) -// close(done) -// }() - -// // Submit a transaction. -// k := []byte("my-key") -// v := []byte("my-value") -// tx := kvstoreTx(k, v) -// br, err := cl.BroadcastTxCommit(tx) -// require.NoError(err, "%#v", err) -// require.EqualValues(0, br.CheckTx.Code, "%#v", br.CheckTx) -// require.EqualValues(0, br.DeliverTx.Code) -// brh := br.Height - -// // Fetch latest after tx commit. -// <-done -// latest, err := source.LatestFullCommit(chainID, 1, 1<<63-1) -// require.NoError(err, "%#v", err) -// rootHash := latest.SignedHeader.AppHash -// if rootHash == nil { -// // Fetch one block later, AppHash hasn't been committed yet. -// // TODO find a way to avoid doing this. -// client.WaitForHeight(cl, latest.SignedHeader.Height+1, nil) -// latest, err = source.LatestFullCommit(chainID, latest.SignedHeader.Height+1, 1<<63-1) -// require.NoError(err, "%#v", err) -// rootHash = latest.SignedHeader.AppHash -// } -// require.NotNil(rootHash) - -// // verify a query before the tx block has no data (and valid non-exist proof) -// bs, height, proof, err := GetWithProof(prt, k, brh-1, cl, cert) -// require.NoError(err, "%#v", err) -// // require.NotNil(proof) -// // TODO: Ensure that *some* keys will be there, ensuring that proof is nil, -// // (currently there's a race condition) -// // and ensure that proof proves absence of k. -// require.Nil(bs) - -// // but given that block it is good -// bs, height, proof, err = GetWithProof(prt, k, brh, cl, cert) -// require.NoError(err, "%#v", err) -// require.NotNil(proof) -// require.Equal(height, brh) - -// assert.EqualValues(v, bs) -// err = prt.VerifyValue(proof, rootHash, string(k), bs) // XXX key encoding -// assert.NoError(err, "%#v", err) - -// // Test non-existing key. -// missing := []byte("my-missing-key") -// bs, _, proof, err = GetWithProof(prt, missing, 0, cl, cert) -// require.NoError(err) -// require.Nil(bs) -// require.NotNil(proof) -// err = prt.VerifyAbsence(proof, rootHash, string(missing)) // XXX VerifyAbsence(), keyencoding -// assert.NoError(err, "%#v", err) -// err = prt.VerifyAbsence(proof, rootHash, string(k)) // XXX VerifyAbsence(), keyencoding -// assert.Error(err, "%#v", err) -// } +//nolint:unused,deadcode +func _TestAppProofs(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + prt := defaultProofRuntime() + cl := client.NewLocal(node) + client.WaitForHeight(cl, 1, nil) + + // This sets up our trust on the node based on some past point. + source := certclient.NewProvider(chainID, cl) + seed, err := source.LatestFullCommit(chainID, 1, 1) + require.NoError(err, "%#v", err) + cert := lite.NewBaseVerifier(chainID, seed.Height(), seed.Validators) + + // Wait for tx confirmation. + done := make(chan int64) + go func() { + evtTyp := types.EventTx + _, err = client.WaitForOneEvent(cl, evtTyp, waitForEventTimeout) + require.Nil(err, "%#v", err) + close(done) + }() + + // Submit a transaction. + k := []byte("my-key") + v := []byte("my-value") + tx := kvstoreTx(k, v) + br, err := cl.BroadcastTxCommit(tx) + require.NoError(err, "%#v", err) + require.EqualValues(0, br.CheckTx.Code, "%#v", br.CheckTx) + require.EqualValues(0, br.DeliverTx.Code) + brh := br.Height + + // Fetch latest after tx commit. + <-done + latest, err := source.LatestFullCommit(chainID, 1, 1<<63-1) + require.NoError(err, "%#v", err) + rootHash := latest.SignedHeader.AppHash + if rootHash == nil { + // Fetch one block later, AppHash hasn't been committed yet. + // TODO find a way to avoid doing this. + client.WaitForHeight(cl, latest.SignedHeader.Height+1, nil) + latest, err = source.LatestFullCommit(chainID, latest.SignedHeader.Height+1, 1<<63-1) + require.NoError(err, "%#v", err) + rootHash = latest.SignedHeader.AppHash + } + require.NotNil(rootHash) + + // verify a query before the tx block has no data (and valid non-exist proof) + bs, height, proof, err := GetWithProof(prt, k, brh-1, cl, cert) + require.NoError(err, "%#v", err) + // require.NotNil(proof) + // TODO: Ensure that *some* keys will be there, ensuring that proof is nil, + // (currently there's a race condition) + // and ensure that proof proves absence of k. + require.Nil(bs) + + // but given that block it is good + bs, height, proof, err = GetWithProof(prt, k, brh, cl, cert) + require.NoError(err, "%#v", err) + require.NotNil(proof) + require.Equal(height, brh) + + assert.EqualValues(v, bs) + err = prt.VerifyValue(proof, rootHash, string(k), bs) // XXX key encoding + assert.NoError(err, "%#v", err) + + // Test non-existing key. + missing := []byte("my-missing-key") + bs, _, proof, err = GetWithProof(prt, missing, 0, cl, cert) + require.NoError(err) + require.Nil(bs) + require.NotNil(proof) + err = prt.VerifyAbsence(proof, rootHash, string(missing)) // XXX VerifyAbsence(), keyencoding + assert.NoError(err, "%#v", err) + err = prt.VerifyAbsence(proof, rootHash, string(k)) // XXX VerifyAbsence(), keyencoding + assert.Error(err, "%#v", err) +} func TestTxProofs(t *testing.T) { assert, require := assert.New(t), require.New(t) diff --git a/p2p/trust/metric_test.go b/p2p/trust/metric_test.go index 89327c0e1..0273dad69 100644 --- a/p2p/trust/metric_test.go +++ b/p2p/trust/metric_test.go @@ -65,44 +65,45 @@ func TestTrustMetricCopyNilPointer(t *testing.T) { } // XXX: This test fails non-deterministically -// func _TestTrustMetricStopPause(t *testing.T) { -// // The TestTicker will provide manual control over -// // the passing of time within the metric -// tt := NewTestTicker() -// tm := NewMetric() -// tm.SetTicker(tt) -// tm.Start() -// // Allow some time intervals to pass and pause -// tt.NextTick() -// tt.NextTick() -// tm.Pause() - -// // could be 1 or 2 because Pause and NextTick race -// first := tm.Copy().numIntervals - -// // Allow more time to pass and check the intervals are unchanged -// tt.NextTick() -// tt.NextTick() -// assert.Equal(t, first, tm.Copy().numIntervals) - -// // Get the trust metric activated again -// tm.GoodEvents(5) -// // Allow some time intervals to pass and stop -// tt.NextTick() -// tt.NextTick() -// tm.Stop() -// tm.Wait() - -// second := tm.Copy().numIntervals -// // Allow more intervals to pass while the metric is stopped -// // and check that the number of intervals match -// tm.NextTimeInterval() -// tm.NextTimeInterval() -// // XXX: fails non-deterministically: -// // expected 5, got 6 -// assert.Equal(t, second+2, tm.Copy().numIntervals) - -// if first > second { -// t.Fatalf("numIntervals should always increase or stay the same over time") -// } -// } +//nolint:unused,deadcode +func _TestTrustMetricStopPause(t *testing.T) { + // The TestTicker will provide manual control over + // the passing of time within the metric + tt := NewTestTicker() + tm := NewMetric() + tm.SetTicker(tt) + tm.Start() + // Allow some time intervals to pass and pause + tt.NextTick() + tt.NextTick() + tm.Pause() + + // could be 1 or 2 because Pause and NextTick race + first := tm.Copy().numIntervals + + // Allow more time to pass and check the intervals are unchanged + tt.NextTick() + tt.NextTick() + assert.Equal(t, first, tm.Copy().numIntervals) + + // Get the trust metric activated again + tm.GoodEvents(5) + // Allow some time intervals to pass and stop + tt.NextTick() + tt.NextTick() + tm.Stop() + tm.Wait() + + second := tm.Copy().numIntervals + // Allow more intervals to pass while the metric is stopped + // and check that the number of intervals match + tm.NextTimeInterval() + tm.NextTimeInterval() + // XXX: fails non-deterministically: + // expected 5, got 6 + assert.Equal(t, second+2, tm.Copy().numIntervals) + + if first > second { + t.Fatalf("numIntervals should always increase or stay the same over time") + } +}