Skip to content
This repository was archived by the owner on Apr 19, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 162 additions & 11 deletions client/broadcast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package client
import (
"context"
"errors"
"fmt"
"testing"
"time"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/stretchr/testify/assert"
"github.com/tendermint/tendermint/crypto/tmhash"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
tmtypes "github.com/tendermint/tendermint/types"
)
Expand Down Expand Up @@ -40,6 +43,15 @@ func (m myFakeTx) GetMsgs() (msgs []sdk.Msg) {
func (m myFakeTx) ValidateBasic() error { return nil }
func (m myFakeTx) AsAny() *codectypes.Any { return &codectypes.Any{} }

type fakeTx struct {
}

func (fakeTx) GetMsgs() (msgs []sdk.Msg) {
return nil
}

func (fakeTx) ValidateBasic() error { return nil }

type fakeBroadcaster struct {
tx func(context.Context, []byte, bool) (*ctypes.ResultTx, error)
broadcastSync func(context.Context, tmtypes.Tx) (*ctypes.ResultBroadcastTx, error)
Expand All @@ -60,16 +72,15 @@ func (f fakeBroadcaster) BroadcastTxSync(ctx context.Context, tx tmtypes.Tx) (*c
}

func TestBroadcast(t *testing.T) {
ctx := context.Background()

for _, tt := range []struct {
name string
broadcaster fakeBroadcaster
txDecoder sdk.TxDecoder
txBytes []byte
waitTimeout time.Duration
expectedRes *sdk.TxResponse
expectedErr error
name string
broadcaster fakeBroadcaster
txDecoder sdk.TxDecoder
txBytes []byte
waitTimeout time.Duration
isContextCancelled bool
expectedRes *sdk.TxResponse
expectedErr error
}{
{
name: "simple success returns result",
Expand Down Expand Up @@ -110,7 +121,7 @@ func TestBroadcast(t *testing.T) {
return nil, nil
},
},
expectedErr: ErrTimeoutAfterWaitingForTxBroadcast,
expectedErr: fmt.Errorf("timed out after: %d; %w", time.Microsecond, ErrTimeoutAfterWaitingForTxBroadcast),
},
{
name: "broadcasting returns an error",
Expand All @@ -121,12 +132,96 @@ func TestBroadcast(t *testing.T) {
},
expectedErr: errExpected,
},
{
name: "broadcasting returns an error that Tx already exist",
broadcaster: fakeBroadcaster{
broadcastSync: func(_ context.Context, _ tmtypes.Tx) (*ctypes.ResultBroadcastTx, error) {
return nil, errors.New("tx already exists in cache")
},
},
expectedErr: nil,
expectedRes: &sdk.TxResponse{
Code: sdkerrors.ErrTxInMempoolCache.ABCICode(),
Codespace: sdkerrors.ErrTxInMempoolCache.Codespace(),
TxHash: fmt.Sprintf("%X", tmhash.Sum([]byte{1, 2, 3, 4})),
},
txBytes: []byte{1, 2, 3, 4},
},
{
name: "request is canceled",
isContextCancelled: true,
broadcaster: fakeBroadcaster{
broadcastSync: func(_ context.Context, _ tmtypes.Tx) (*ctypes.ResultBroadcastTx, error) {
return &ctypes.ResultBroadcastTx{
Code: 1,
Hash: []byte(`123bob`),
}, nil
},
tx: func(_ context.Context, hash []byte, _ bool) (*ctypes.ResultTx, error) {
assert.Equal(t, []byte(`123bob`), hash)
return &ctypes.ResultTx{}, nil
},
},
txDecoder: func(txBytes []byte) (sdk.Tx, error) {
return myFakeTx{
[]myFakeMsg{{"hello"}},
}, nil
},
expectedRes: nil,
expectedErr: context.Canceled,
},
{
name: "tx decode failed",
broadcaster: fakeBroadcaster{
broadcastSync: func(_ context.Context, _ tmtypes.Tx) (*ctypes.ResultBroadcastTx, error) {
return &ctypes.ResultBroadcastTx{
Code: 1,
Hash: []byte(`123bob`),
}, nil
},
tx: func(_ context.Context, hash []byte, _ bool) (*ctypes.ResultTx, error) {
assert.Equal(t, []byte(`123bob`), hash)
return &ctypes.ResultTx{}, nil
},
},
txDecoder: func(txBytes []byte) (sdk.Tx, error) {
return nil, sdkerrors.ErrTxDecode
},
expectedRes: nil,
expectedErr: sdkerrors.ErrTxDecode,
},
{
name: "result doesn't implement the interface intoAny",
broadcaster: fakeBroadcaster{
broadcastSync: func(_ context.Context, _ tmtypes.Tx) (*ctypes.ResultBroadcastTx, error) {
return &ctypes.ResultBroadcastTx{
Code: 1,
Hash: []byte(`123bob`),
}, nil
},
tx: func(_ context.Context, hash []byte, _ bool) (*ctypes.ResultTx, error) {
assert.Equal(t, []byte(`123bob`), hash)
return &ctypes.ResultTx{}, nil
},
},
txDecoder: func(txBytes []byte) (sdk.Tx, error) {
return fakeTx{}, nil
},
expectedRes: nil,
expectedErr: fmt.Errorf("expecting a type implementing intoAny, got: %T", fakeTx{}),
},
} {
t.Run(tt.name, func(t *testing.T) {
duration := 1 * time.Second
if tt.waitTimeout > 0 {
duration = tt.waitTimeout
}
ctx := context.Background()
if tt.isContextCancelled {
var cancel context.CancelFunc
ctx, cancel = context.WithCancel(context.Background())
cancel()
}
gotRes, gotErr := broadcastTx(
ctx,
tt.broadcaster,
Expand All @@ -139,8 +234,64 @@ func TestBroadcast(t *testing.T) {
gotRes.Timestamp = ""
}
assert.Equal(t, tt.expectedRes, gotRes)
assert.ErrorIs(t, gotErr, tt.expectedErr)
assert.Equal(t, gotErr, tt.expectedErr)
})
}
}

func TestCheckTendermintError(t *testing.T) {
for _, tt := range []struct {
name string
tx tmtypes.Tx
err error
expectedRes *sdk.TxResponse
}{
{
name: "Error is nil",
tx: nil,
err: nil,
expectedRes: nil,
},
{
name: "Tx already exist in the cache",
tx: tmtypes.Tx{1, 2, 3, 4},
err: errors.New("tx already exists in cache"),
expectedRes: &sdk.TxResponse{
Code: sdkerrors.ErrTxInMempoolCache.ABCICode(),
Codespace: sdkerrors.ErrTxInMempoolCache.Codespace(),
TxHash: fmt.Sprintf("%X", tmhash.Sum([]byte{1, 2, 3, 4})),
},
},
{
name: "mempool is full",
tx: tmtypes.Tx{5, 6, 7, 8},
err: errors.New("mempool is full"),
expectedRes: &sdk.TxResponse{
Code: sdkerrors.ErrMempoolIsFull.ABCICode(),
Codespace: sdkerrors.ErrMempoolIsFull.Codespace(),
TxHash: fmt.Sprintf("%X", tmhash.Sum([]byte{5, 6, 7, 8})),
},
},
{
name: "tx too large",
tx: tmtypes.Tx{9, 10, 11, 12},
err: errors.New("tx too large"),
expectedRes: &sdk.TxResponse{
Code: sdkerrors.ErrTxTooLarge.ABCICode(),
Codespace: sdkerrors.ErrTxTooLarge.Codespace(),
TxHash: fmt.Sprintf("%X", tmhash.Sum([]byte{9, 10, 11, 12})),
},
},
{
name: "Unknown error",
tx: tmtypes.Tx{13, 14, 15, 16},
err: errors.New("unknown error"),
expectedRes: nil,
},
} {
t.Run(tt.name, func(t *testing.T) {
actualRes := CheckTendermintError(tt.err, tt.tx)
assert.Equal(t, tt.expectedRes, actualRes)
})
}
}
2 changes: 1 addition & 1 deletion client/chain_registry/chain_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ type ChainRegistry interface {
}

func DefaultChainRegistry(log *zap.Logger) ChainRegistry {
return NewCosmosGithubRegistry(log.With(zap.String("registry", "cosmos_github")))
return NewCosmosGithubRegistry(log.With(zap.String("registry", "cosmos_github")), nil)
}
22 changes: 11 additions & 11 deletions client/chain_registry/cosmos_github_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,32 @@ import (
)

type CosmosGithubRegistry struct {
log *zap.Logger
log *zap.Logger
client *github.Client
}

func NewCosmosGithubRegistry(log *zap.Logger) CosmosGithubRegistry {
return CosmosGithubRegistry{log: log}
func NewCosmosGithubRegistry(log *zap.Logger, c *http.Client) CosmosGithubRegistry {
if c == nil {
c = http.DefaultClient
}
return CosmosGithubRegistry{log: log, client: github.NewClient(c)}
}

func (c CosmosGithubRegistry) ListChains(ctx context.Context) ([]string, error) {
client := github.NewClient(http.DefaultClient)
var chains []string

ctx, cancel := context.WithTimeout(ctx, time.Minute*5)
defer cancel()

tree, res, err := client.Git.GetTree(
tree, res, err := c.client.Git.GetTree(
ctx,
"cosmos",
"chain-registry",
"master",
false)
if err != nil || res.StatusCode != 200 {
return chains, err
return nil, err
}

var chains []string
for _, entry := range tree.Entries {
if *entry.Type == "tree" && !strings.HasPrefix(*entry.Path, ".") {
chains = append(chains, *entry.Path)
Expand All @@ -48,10 +50,8 @@ func (c CosmosGithubRegistry) ListChains(ctx context.Context) ([]string, error)
}

func (c CosmosGithubRegistry) GetChain(ctx context.Context, name string) (ChainInfo, error) {
client := github.NewClient(http.DefaultClient)

chainFileName := path.Join(name, "chain.json")
fileContent, _, res, err := client.Repositories.GetContents(
fileContent, _, res, err := c.client.Repositories.GetContents(
ctx,
"cosmos",
"chain-registry",
Expand Down
Loading