mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-29 04:31:44 +00:00
Add tests for client-server proofs over socket and grpc
This commit is contained in:
12
README.md
12
README.md
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
Blockchains are a system for creating shared multi-master application state.
|
Blockchains are a system for creating shared multi-master application state.
|
||||||
**ABCI** is a socket protocol enabling a blockchain consensus engine, running in one process,
|
**ABCI** is a socket protocol enabling a blockchain consensus engine, running in one process,
|
||||||
to manage a blockchain application state, running in another.
|
|
||||||
|
|
||||||
For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/abci-the-tendermint-socket-protocol).
|
For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/abci-the-tendermint-socket-protocol).
|
||||||
|
|
||||||
@ -92,6 +91,17 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil
|
|||||||
* `Data ([]byte)`: The query response bytes
|
* `Data ([]byte)`: The query response bytes
|
||||||
* `Log (string)`: Debug or error message
|
* `Log (string)`: Debug or error message
|
||||||
|
|
||||||
|
#### Proof
|
||||||
|
* __Arguments__:
|
||||||
|
* `Key ([]byte)`: The key whose data you want to verifiably query
|
||||||
|
* `Height (int64)`: The block height for which you want the proof (default=0 returns the proof for last committed block)
|
||||||
|
* __Returns__:
|
||||||
|
* `Code (uint32)`: Response code
|
||||||
|
* `Data ([]byte)`: The query response bytes
|
||||||
|
* `Log (string)`: Debug or error message
|
||||||
|
* __Usage__:<br/>
|
||||||
|
Return a Merkle proof from the key/value pair back to the application hash.
|
||||||
|
|
||||||
#### Flush
|
#### Flush
|
||||||
* __Usage__:<br/>
|
* __Usage__:<br/>
|
||||||
Flush the response queue. Applications that implement `types.Application` need not implement this message -- it's handled by the project.
|
Flush the response queue. Applications that implement `types.Application` need not implement this message -- it's handled by the project.
|
||||||
|
@ -6,56 +6,40 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
abcicli "github.com/tendermint/abci/client"
|
||||||
|
"github.com/tendermint/abci/server"
|
||||||
|
"github.com/tendermint/abci/types"
|
||||||
. "github.com/tendermint/go-common"
|
. "github.com/tendermint/go-common"
|
||||||
"github.com/tendermint/go-crypto"
|
"github.com/tendermint/go-crypto"
|
||||||
merkle "github.com/tendermint/go-merkle"
|
merkle "github.com/tendermint/go-merkle"
|
||||||
"github.com/tendermint/go-wire"
|
"github.com/tendermint/go-wire"
|
||||||
"github.com/tendermint/abci/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func testDummy(t *testing.T, dummy types.Application, tx []byte, key, value string) {
|
func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) {
|
||||||
if r := dummy.DeliverTx(tx); r.IsErr() {
|
ar := app.DeliverTx(tx)
|
||||||
t.Fatal(r)
|
require.False(t, ar.IsErr(), ar)
|
||||||
}
|
// repeating tx doesn't raise error
|
||||||
if r := dummy.DeliverTx(tx); r.IsErr() {
|
ar = app.DeliverTx(tx)
|
||||||
t.Fatal(r)
|
require.False(t, ar.IsErr(), ar)
|
||||||
}
|
|
||||||
|
|
||||||
r := dummy.Query([]byte(key))
|
|
||||||
if r.IsErr() {
|
|
||||||
t.Fatal(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// make sure query is fine
|
||||||
|
r := app.Query([]byte(key))
|
||||||
|
require.False(t, r.IsErr(), r)
|
||||||
q := new(QueryResult)
|
q := new(QueryResult)
|
||||||
if err := wire.ReadJSONBytes(r.Data, q); err != nil {
|
err := wire.ReadJSONBytes(r.Data, q)
|
||||||
t.Fatal(err)
|
require.Nil(t, err)
|
||||||
}
|
require.Equal(t, value, q.Value)
|
||||||
|
|
||||||
if q.Value != value {
|
|
||||||
t.Fatalf("Got %s, expected %s", q.Value, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
rp := dummy.Proof([]byte(key), 0)
|
|
||||||
if rp.IsErr() {
|
|
||||||
t.Fatal(rp)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// make sure proof is fine
|
||||||
|
rp := app.Proof([]byte(key), 0)
|
||||||
|
require.False(t, rp.IsErr(), rp)
|
||||||
p, err := merkle.LoadProof(rp.Data)
|
p, err := merkle.LoadProof(rp.Data)
|
||||||
if err != nil {
|
require.Nil(t, err)
|
||||||
t.Fatal(err)
|
require.True(t, p.Valid())
|
||||||
}
|
assert.Equal(t, []byte(key), p.Key())
|
||||||
|
assert.Equal(t, []byte(value), p.Value())
|
||||||
if !p.Valid() {
|
|
||||||
t.Fatal("Invalid proof")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal([]byte(key), p.Key()) {
|
|
||||||
t.Fatalf("Invalid key: %s", p.Key())
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal([]byte(value), p.Value()) {
|
|
||||||
t.Fatalf("Invalid key: %s", p.Value())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDummyKV(t *testing.T) {
|
func TestDummyKV(t *testing.T) {
|
||||||
@ -223,3 +207,97 @@ func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeSocketClientServer(app types.Application, name string) (abcicli.Client, Service, error) {
|
||||||
|
// Start the listener
|
||||||
|
socket := Fmt("unix://%s.sock", name)
|
||||||
|
server, err := server.NewSocketServer(socket, app)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to the socket
|
||||||
|
client, err := abcicli.NewSocketClient(socket, false)
|
||||||
|
if err != nil {
|
||||||
|
server.Stop()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
client.Start()
|
||||||
|
|
||||||
|
return client, server, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, Service, error) {
|
||||||
|
// Start the listener
|
||||||
|
socket := Fmt("unix://%s.sock", name)
|
||||||
|
|
||||||
|
gapp := types.NewGRPCApplication(app)
|
||||||
|
server, err := server.NewGRPCServer(socket, gapp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := abcicli.NewGRPCClient(socket, true)
|
||||||
|
if err != nil {
|
||||||
|
server.Stop()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return client, server, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientServer(t *testing.T) {
|
||||||
|
// set up socket app
|
||||||
|
dummy := NewDummyApplication()
|
||||||
|
client, server, err := makeSocketClientServer(dummy, "dummy-socket")
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Stop()
|
||||||
|
|
||||||
|
runClientTests(t, client)
|
||||||
|
|
||||||
|
// set up grpc app
|
||||||
|
dummy = NewDummyApplication()
|
||||||
|
gclient, gserver, err := makeGRPCClientServer(dummy, "dummy-grpc")
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer gserver.Stop()
|
||||||
|
defer gclient.Stop()
|
||||||
|
|
||||||
|
runClientTests(t, gclient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runClientTests(t *testing.T, client abcicli.Client) {
|
||||||
|
// run some tests....
|
||||||
|
key := "abc"
|
||||||
|
value := key
|
||||||
|
tx := []byte(key)
|
||||||
|
testClient(t, client, tx, key, value)
|
||||||
|
|
||||||
|
value = "def"
|
||||||
|
tx = []byte(key + "=" + value)
|
||||||
|
testClient(t, client, tx, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) {
|
||||||
|
ar := app.DeliverTxSync(tx)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
// repeating tx doesn't raise error
|
||||||
|
ar = app.DeliverTxSync(tx)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
|
||||||
|
// make sure query is fine
|
||||||
|
r := app.QuerySync([]byte(key))
|
||||||
|
require.False(t, r.IsErr(), r)
|
||||||
|
q := new(QueryResult)
|
||||||
|
err := wire.ReadJSONBytes(r.Data, q)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, value, q.Value)
|
||||||
|
|
||||||
|
// make sure proof is fine
|
||||||
|
rp := app.ProofSync([]byte(key), 0)
|
||||||
|
require.False(t, rp.IsErr(), rp)
|
||||||
|
p, err := merkle.LoadProof(rp.Data)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.True(t, p.Valid())
|
||||||
|
assert.Equal(t, []byte(key), p.Key())
|
||||||
|
assert.Equal(t, []byte(value), p.Value())
|
||||||
|
}
|
||||||
|
321
example/dummy/dummy_test.go.orig
Normal file
321
example/dummy/dummy_test.go.orig
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
package dummy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
. "github.com/tendermint/go-common"
|
||||||
|
"github.com/tendermint/go-crypto"
|
||||||
|
merkle "github.com/tendermint/go-merkle"
|
||||||
|
"github.com/tendermint/go-wire"
|
||||||
|
<<<<<<< HEAD
|
||||||
|
"github.com/tendermint/abci/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testDummy(t *testing.T, dummy types.Application, tx []byte, key, value string) {
|
||||||
|
if r := dummy.DeliverTx(tx); r.IsErr() {
|
||||||
|
t.Fatal(r)
|
||||||
|
}
|
||||||
|
if r := dummy.DeliverTx(tx); r.IsErr() {
|
||||||
|
t.Fatal(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := dummy.Query([]byte(key))
|
||||||
|
if r.IsErr() {
|
||||||
|
t.Fatal(r)
|
||||||
|
}
|
||||||
|
=======
|
||||||
|
tmspcli "github.com/tendermint/tmsp/client"
|
||||||
|
"github.com/tendermint/tmsp/server"
|
||||||
|
"github.com/tendermint/tmsp/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) {
|
||||||
|
ar := app.AppendTx(tx)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
// repeating tx doesn't raise error
|
||||||
|
ar = app.AppendTx(tx)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
>>>>>>> Add tests for client-server proofs over socket and grpc
|
||||||
|
|
||||||
|
// make sure query is fine
|
||||||
|
r := app.Query([]byte(key))
|
||||||
|
require.False(t, r.IsErr(), r)
|
||||||
|
q := new(QueryResult)
|
||||||
|
err := wire.ReadJSONBytes(r.Data, q)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, value, q.Value)
|
||||||
|
|
||||||
|
// make sure proof is fine
|
||||||
|
rp := app.Proof([]byte(key), 0)
|
||||||
|
require.False(t, rp.IsErr(), rp)
|
||||||
|
p, err := merkle.LoadProof(rp.Data)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.True(t, p.Valid())
|
||||||
|
assert.Equal(t, []byte(key), p.Key())
|
||||||
|
assert.Equal(t, []byte(value), p.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDummyKV(t *testing.T) {
|
||||||
|
dummy := NewDummyApplication()
|
||||||
|
key := "abc"
|
||||||
|
value := key
|
||||||
|
tx := []byte(key)
|
||||||
|
testDummy(t, dummy, tx, key, value)
|
||||||
|
|
||||||
|
value = "def"
|
||||||
|
tx = []byte(key + "=" + value)
|
||||||
|
testDummy(t, dummy, tx, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPersistentDummyKV(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
dummy := NewPersistentDummyApplication(dir)
|
||||||
|
key := "abc"
|
||||||
|
value := key
|
||||||
|
tx := []byte(key)
|
||||||
|
testDummy(t, dummy, tx, key, value)
|
||||||
|
|
||||||
|
value = "def"
|
||||||
|
tx = []byte(key + "=" + value)
|
||||||
|
testDummy(t, dummy, tx, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPersistentDummyInfo(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
dummy := NewPersistentDummyApplication(dir)
|
||||||
|
height := uint64(0)
|
||||||
|
|
||||||
|
resInfo := dummy.Info()
|
||||||
|
if resInfo.LastBlockHeight != height {
|
||||||
|
t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make and apply block
|
||||||
|
height = uint64(1)
|
||||||
|
hash := []byte("foo")
|
||||||
|
header := &types.Header{
|
||||||
|
Height: uint64(height),
|
||||||
|
}
|
||||||
|
dummy.BeginBlock(hash, header)
|
||||||
|
dummy.EndBlock(height)
|
||||||
|
dummy.Commit()
|
||||||
|
|
||||||
|
resInfo = dummy.Info()
|
||||||
|
if resInfo.LastBlockHeight != height {
|
||||||
|
t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a validator, remove a validator, update a validator
|
||||||
|
func TestValSetChanges(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
dummy := NewPersistentDummyApplication(dir)
|
||||||
|
|
||||||
|
// init with some validators
|
||||||
|
total := 10
|
||||||
|
nInit := 5
|
||||||
|
vals := make([]*types.Validator, total)
|
||||||
|
for i := 0; i < total; i++ {
|
||||||
|
pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(Fmt("test%d", i))).PubKey().Bytes()
|
||||||
|
power := RandInt()
|
||||||
|
vals[i] = &types.Validator{pubkey, uint64(power)}
|
||||||
|
}
|
||||||
|
// iniitalize with the first nInit
|
||||||
|
dummy.InitChain(vals[:nInit])
|
||||||
|
|
||||||
|
vals1, vals2 := vals[:nInit], dummy.Validators()
|
||||||
|
valsEqual(t, vals1, vals2)
|
||||||
|
|
||||||
|
var v1, v2, v3 *types.Validator
|
||||||
|
|
||||||
|
// add some validators
|
||||||
|
v1, v2 = vals[nInit], vals[nInit+1]
|
||||||
|
diff := []*types.Validator{v1, v2}
|
||||||
|
tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power)
|
||||||
|
tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power)
|
||||||
|
|
||||||
|
makeApplyBlock(t, dummy, 1, diff, tx1, tx2)
|
||||||
|
|
||||||
|
vals1, vals2 = vals[:nInit+2], dummy.Validators()
|
||||||
|
valsEqual(t, vals1, vals2)
|
||||||
|
|
||||||
|
// remove some validators
|
||||||
|
v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit]
|
||||||
|
v1.Power = 0
|
||||||
|
v2.Power = 0
|
||||||
|
v3.Power = 0
|
||||||
|
diff = []*types.Validator{v1, v2, v3}
|
||||||
|
tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
|
||||||
|
tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power)
|
||||||
|
tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power)
|
||||||
|
|
||||||
|
makeApplyBlock(t, dummy, 2, diff, tx1, tx2, tx3)
|
||||||
|
|
||||||
|
vals1 = append(vals[:nInit-2], vals[nInit+1])
|
||||||
|
vals2 = dummy.Validators()
|
||||||
|
valsEqual(t, vals1, vals2)
|
||||||
|
|
||||||
|
// update some validators
|
||||||
|
v1 = vals[0]
|
||||||
|
if v1.Power == 5 {
|
||||||
|
v1.Power = 6
|
||||||
|
} else {
|
||||||
|
v1.Power = 5
|
||||||
|
}
|
||||||
|
diff = []*types.Validator{v1}
|
||||||
|
tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
|
||||||
|
|
||||||
|
makeApplyBlock(t, dummy, 3, diff, tx1)
|
||||||
|
|
||||||
|
vals1 = append([]*types.Validator{v1}, vals1[1:len(vals1)]...)
|
||||||
|
vals2 = dummy.Validators()
|
||||||
|
valsEqual(t, vals1, vals2)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []*types.Validator, txs ...[]byte) {
|
||||||
|
// make and apply block
|
||||||
|
height := uint64(heightInt)
|
||||||
|
hash := []byte("foo")
|
||||||
|
header := &types.Header{
|
||||||
|
Height: height,
|
||||||
|
}
|
||||||
|
|
||||||
|
dummyChain := dummy.(types.BlockchainAware) // hmm...
|
||||||
|
dummyChain.BeginBlock(hash, header)
|
||||||
|
for _, tx := range txs {
|
||||||
|
if r := dummy.DeliverTx(tx); r.IsErr() {
|
||||||
|
t.Fatal(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resEndBlock := dummyChain.EndBlock(height)
|
||||||
|
dummy.Commit()
|
||||||
|
|
||||||
|
valsEqual(t, diff, resEndBlock.Diffs)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// order doesn't matter
|
||||||
|
func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) {
|
||||||
|
if len(vals1) != len(vals2) {
|
||||||
|
t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1))
|
||||||
|
}
|
||||||
|
sort.Sort(types.Validators(vals1))
|
||||||
|
sort.Sort(types.Validators(vals2))
|
||||||
|
for i, v1 := range vals1 {
|
||||||
|
v2 := vals2[i]
|
||||||
|
if !bytes.Equal(v1.PubKey, v2.PubKey) ||
|
||||||
|
v1.Power != v2.Power {
|
||||||
|
t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeSocketClientServer(app types.Application, name string) (tmspcli.Client, Service, error) {
|
||||||
|
// Start the listener
|
||||||
|
socket := Fmt("unix://%s.sock", name)
|
||||||
|
server, err := server.NewSocketServer(socket, app)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to the socket
|
||||||
|
client, err := tmspcli.NewSocketClient(socket, false)
|
||||||
|
if err != nil {
|
||||||
|
server.Stop()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
client.Start()
|
||||||
|
|
||||||
|
return client, server, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeGRPCClientServer(app types.Application, name string) (tmspcli.Client, Service, error) {
|
||||||
|
// Start the listener
|
||||||
|
socket := Fmt("unix://%s.sock", name)
|
||||||
|
|
||||||
|
gapp := types.NewGRPCApplication(app)
|
||||||
|
server, err := server.NewGRPCServer(socket, gapp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := tmspcli.NewGRPCClient(socket, true)
|
||||||
|
if err != nil {
|
||||||
|
server.Stop()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return client, server, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientServer(t *testing.T) {
|
||||||
|
// set up socket app
|
||||||
|
dummy := NewDummyApplication()
|
||||||
|
client, server, err := makeSocketClientServer(dummy, "dummy-socket")
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Stop()
|
||||||
|
|
||||||
|
runClientTests(t, client)
|
||||||
|
|
||||||
|
// set up grpc app
|
||||||
|
dummy = NewDummyApplication()
|
||||||
|
gclient, gserver, err := makeGRPCClientServer(dummy, "dummy-grpc")
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer gserver.Stop()
|
||||||
|
defer gclient.Stop()
|
||||||
|
|
||||||
|
runClientTests(t, gclient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runClientTests(t *testing.T, client tmspcli.Client) {
|
||||||
|
// run some tests....
|
||||||
|
key := "abc"
|
||||||
|
value := key
|
||||||
|
tx := []byte(key)
|
||||||
|
testClient(t, client, tx, key, value)
|
||||||
|
|
||||||
|
value = "def"
|
||||||
|
tx = []byte(key + "=" + value)
|
||||||
|
testClient(t, client, tx, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testClient(t *testing.T, app tmspcli.Client, tx []byte, key, value string) {
|
||||||
|
ar := app.AppendTxSync(tx)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
// repeating tx doesn't raise error
|
||||||
|
ar = app.AppendTxSync(tx)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
|
||||||
|
// make sure query is fine
|
||||||
|
r := app.QuerySync([]byte(key))
|
||||||
|
require.False(t, r.IsErr(), r)
|
||||||
|
q := new(QueryResult)
|
||||||
|
err := wire.ReadJSONBytes(r.Data, q)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, value, q.Value)
|
||||||
|
|
||||||
|
// make sure proof is fine
|
||||||
|
rp := app.ProofSync([]byte(key), 0)
|
||||||
|
require.False(t, rp.IsErr(), rp)
|
||||||
|
p, err := merkle.LoadProof(rp.Data)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.True(t, p.Valid())
|
||||||
|
assert.Equal(t, []byte(key), p.Key())
|
||||||
|
assert.Equal(t, []byte(value), p.Value())
|
||||||
|
}
|
15
glide.lock
generated
15
glide.lock
generated
@ -19,6 +19,11 @@ imports:
|
|||||||
version: d228849504861217f796da67fae4f6e347643f15
|
version: d228849504861217f796da67fae4f6e347643f15
|
||||||
- name: github.com/mattn/go-isatty
|
- name: github.com/mattn/go-isatty
|
||||||
version: 30a891c33c7cde7b02a981314b4228ec99380cca
|
version: 30a891c33c7cde7b02a981314b4228ec99380cca
|
||||||
|
- name: github.com/stretchr/testify
|
||||||
|
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
|
||||||
|
subpackages:
|
||||||
|
- assert
|
||||||
|
- require
|
||||||
- name: github.com/syndtr/goleveldb
|
- name: github.com/syndtr/goleveldb
|
||||||
version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65
|
version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65
|
||||||
subpackages:
|
subpackages:
|
||||||
@ -102,4 +107,12 @@ imports:
|
|||||||
- stats
|
- stats
|
||||||
- tap
|
- tap
|
||||||
- transport
|
- transport
|
||||||
testImports: []
|
testImports:
|
||||||
|
- name: github.com/davecgh/go-spew
|
||||||
|
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||||
|
subpackages:
|
||||||
|
- spew
|
||||||
|
- name: github.com/pmezard/go-difflib
|
||||||
|
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||||
|
subpackages:
|
||||||
|
- difflib
|
||||||
|
@ -15,3 +15,7 @@ import:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- context
|
- context
|
||||||
- package: google.golang.org/grpc
|
- package: google.golang.org/grpc
|
||||||
|
- package: github.com/stretchr/testify
|
||||||
|
version: ^1.1.4
|
||||||
|
subpackages:
|
||||||
|
- require
|
||||||
|
Reference in New Issue
Block a user