Skip to content

Commit

Permalink
more of the same
Browse files Browse the repository at this point in the history
  • Loading branch information
facundomedica committed Dec 27, 2024
1 parent 28c29bb commit df1f891
Show file tree
Hide file tree
Showing 4 changed files with 524 additions and 0 deletions.
149 changes: 149 additions & 0 deletions server/v2/api/grpc/codec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package grpc

import (
"testing"

"github.com/cosmos/gogoproto/proto"
"github.com/stretchr/testify/require"
protov2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
)

type mockInterfaceRegistry struct{}

func (m mockInterfaceRegistry) Resolve(typeUrl string) (interface {
ProtoMessage()
Reset()
String() string
}, error) {
return nil, nil
}

func (m mockInterfaceRegistry) RegisterInterface(string, interface{}, ...interface{}) {}
func (m mockInterfaceRegistry) RegisterImplementations(interface{}, ...interface{}) {}
func (m mockInterfaceRegistry) ListAllInterfaces() []string { return nil }
func (m mockInterfaceRegistry) ListImplementations(string) []string { return nil }
func (m mockInterfaceRegistry) UnpackAny(*anypb.Any, interface{}) error { return nil }

func TestProtoCodec_Marshal(t *testing.T) {
registry := mockInterfaceRegistry{}
codec := newProtoCodec(registry)

tests := []struct {
name string
input proto.Message
wantErr bool
}{
{
name: "nil message",
input: nil,
wantErr: false,
},
{
name: "empty message",
input: &anypb.Any{},
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bz, err := codec.Marshal(tt.input)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
if tt.input == nil {
require.Empty(t, bz)
}
})
}
}

func TestGRPCCodec_Marshal(t *testing.T) {
registry := mockInterfaceRegistry{}
pc := newProtoCodec(registry)
codec := pc.GRPCCodec()

tests := []struct {
name string
input interface{}
wantErr bool
}{
{
name: "protov2 message",
input: &anypb.Any{},
wantErr: false,
},
{
name: "invalid type",
input: "not a proto message",
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bz, err := codec.Marshal(tt.input)
if tt.wantErr {
require.Error(t, err)
require.ErrorIs(t, err, errUnknownProtoType)
return
}
require.NoError(t, err)
require.NotNil(t, bz)
})
}
}

func TestGRPCCodec_Unmarshal(t *testing.T) {
registry := mockInterfaceRegistry{}
pc := newProtoCodec(registry)
codec := pc.GRPCCodec()

msg := &anypb.Any{}
bz, err := protov2.Marshal(msg)
require.NoError(t, err)

tests := []struct {
name string
data []byte
msg interface{}
wantErr bool
}{
{
name: "protov2 message",
data: bz,
msg: &anypb.Any{},
wantErr: false,
},
{
name: "invalid type",
data: bz,
msg: &struct{}{},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := codec.Unmarshal(tt.data, tt.msg)
if tt.wantErr {
require.Error(t, err)
require.ErrorIs(t, err, errUnknownProtoType)
return
}
require.NoError(t, err)
})
}
}

func TestCodecName(t *testing.T) {
registry := mockInterfaceRegistry{}
pc := newProtoCodec(registry)
require.Equal(t, "cosmos-sdk-grpc-codec", pc.Name())

grpcCodec := pc.GRPCCodec()
require.Equal(t, "cosmos-sdk-grpc-codec", grpcCodec.Name())
}
131 changes: 131 additions & 0 deletions server/v2/api/grpc/server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package grpc

import (
"context"
"testing"

appmodulev2 "cosmossdk.io/core/appmodule/v2"
"cosmossdk.io/core/transaction"
"cosmossdk.io/log"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/metadata"
)

func TestGetHeightFromCtx(t *testing.T) {
tests := []struct {
name string
ctx context.Context
wantHeight uint64
wantErr bool
errContains string
}{
{
name: "no metadata returns zero height",
ctx: context.Background(),
wantHeight: 0,
wantErr: false,
},
{
name: "valid height",
ctx: metadata.NewIncomingContext(
context.Background(),
metadata.Pairs(BlockHeightHeader, "100"),
),
wantHeight: 100,
wantErr: false,
},
{
name: "invalid height format",
ctx: metadata.NewIncomingContext(
context.Background(),
metadata.Pairs(BlockHeightHeader, "invalid"),
),
wantHeight: 0,
wantErr: true,
errContains: "unable to parse height",
},
{
name: "multiple height values",
ctx: metadata.NewIncomingContext(
context.Background(),
metadata.Pairs(BlockHeightHeader, "100", BlockHeightHeader, "200"),
),
wantHeight: 0,
wantErr: true,
errContains: "must be of length 1",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
height, err := getHeightFromCtx(tt.ctx)
if tt.wantErr {
assert.ErrorContains(t, err, tt.errContains)
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if height != tt.wantHeight {
t.Errorf("height = %v, want %v", height, tt.wantHeight)
}
})
}
}

func TestServerConfig(t *testing.T) {
tests := []struct {
name string
cfgOptions []CfgOption
wantAddress string
}{
{
name: "default config",
cfgOptions: nil,
wantAddress: "localhost:9090",
},
{
name: "custom address",
cfgOptions: []CfgOption{
func(cfg *Config) {
cfg.Address = "localhost:8080"
},
},
wantAddress: "localhost:8080",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
srv := NewWithConfigOptions[transaction.Tx](tt.cfgOptions...)
cfg := srv.Config().(*Config)
if cfg.Address != tt.wantAddress {
t.Errorf("address = %v, want %v", cfg.Address, tt.wantAddress)
}
})
}
}

func TestNewServer(t *testing.T) {
logger := log.NewNopLogger()
handlers := make(map[string]appmodulev2.Handler)
queryable := func(ctx context.Context, version uint64, msg transaction.Msg) (transaction.Msg, error) {
return msg, nil
}

srv, err := New[transaction.Tx](
logger,
nil,
handlers,
queryable,
nil,
)

if err != nil {
t.Fatalf("failed to create server: %v", err)
}

if srv.Name() != ServerName {
t.Errorf("server name = %v, want %v", srv.Name(), ServerName)
}
}
Loading

0 comments on commit df1f891

Please sign in to comment.