Some checks are pending
Docs Deploy / build_and_deploy (push) Waiting to run
Generate Docs / cli (push) Waiting to run
Generate Config Doc / cli (push) Waiting to run
Go formatting / go-formatting (push) Waiting to run
Check links / markdown-link-check (push) Waiting to run
Integration / pre-test (push) Waiting to run
Integration / test on (push) Blocked by required conditions
Integration / status (push) Blocked by required conditions
Lint / Lint Go code (push) Waiting to run
Test / test (ubuntu-latest) (push) Waiting to run
231 lines
6.4 KiB
Go
231 lines
6.4 KiB
Go
package protoutil
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/emicklei/proto"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// Helpers:
|
|
// Only checks containment, not positioning.
|
|
func containsElement(f proto.Visitee, v proto.Visitee) bool {
|
|
contains := false
|
|
Apply(f, nil, func(c *Cursor) bool {
|
|
if reflect.DeepEqual(c.Node(), v) {
|
|
contains = true
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
return contains
|
|
}
|
|
|
|
// parseStringProto takes a string, parses it into a proto.File, and returns a ProtoFile.
|
|
// Nodes can be created easily (newnode) by wrapping them correctly. (e.g field in a message).
|
|
func parseStringProto(s string) (*proto.Proto, error) {
|
|
p, err := proto.NewParser(strings.NewReader(s)).Parse()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return p, nil
|
|
}
|
|
|
|
// Test that the changes from adding a list with starport scaffold list <Type>
|
|
// Relatively old files but still exercise some paths of the code.
|
|
|
|
var (
|
|
genesisProto = `syntax = "proto3";
|
|
package cosmonaut.chainname.chainname;
|
|
|
|
import "gogoproto/gogo.proto";
|
|
import "chainname/params.proto";
|
|
|
|
option go_package = "github.com/cosmonaut/chainname/x/chainname/types";
|
|
|
|
// GenesisState defines the houhah module's genesis state.
|
|
message GenesisState {
|
|
Params params = 1 [(gogoproto.nullable) = false];
|
|
}
|
|
`
|
|
queryProto = `syntax = "proto3";
|
|
package cosmonaut.chainname.chainname;
|
|
|
|
import "gogoproto/gogo.proto";
|
|
import "google/api/annotations.proto";
|
|
import "cosmos/base/query/v1beta1/pagination.proto";
|
|
import "chainname/params.proto";
|
|
|
|
option go_package = "github.com/cosmonaut/chainname/x/houhah/types";
|
|
|
|
// Query defines the gRPC querier service.
|
|
service Query {
|
|
// Parameters queries the parameters of the module.
|
|
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
|
|
option (google.api.http).get = "/cosmonaut/chainname/chainname/params";
|
|
}
|
|
}
|
|
|
|
// QueryParamsRequest is request type for the Query/Params RPC method.
|
|
message QueryParamsRequest {}
|
|
|
|
// QueryParamsResponse is response type for the Query/Params RPC method.
|
|
message QueryParamsResponse {
|
|
// params holds all the parameters of this module.
|
|
Params params = 1 [(gogoproto.nullable) = false];
|
|
}`
|
|
txProto = `syntax = "proto3";
|
|
package cosmonautchainname.chainname;
|
|
|
|
option go_package = "github.com/cosmonaut/chainname/x/chainname/types";
|
|
|
|
// Msg defines the Msg service.
|
|
service Msg {}
|
|
`
|
|
)
|
|
|
|
// Test that the changes from adding a list with starport scaffold list <Type>
|
|
// are applied correctly to tx.proto.
|
|
func TestAddEmptyList_tx(t *testing.T) {
|
|
typename, modname := kirby, "chainname"
|
|
f, err := parseStringProto(txProto)
|
|
require.NoError(t, err)
|
|
|
|
// 1) Add import for the new type (module/lowercase_typ)
|
|
imp := NewImport(fmt.Sprintf("%s/%s.proto", modname, strings.ToLower(typename)))
|
|
err = AddImports(f, true, imp)
|
|
require.NoError(t, err)
|
|
require.True(t, containsElement(f, imp))
|
|
|
|
// 2) Add rpcs
|
|
var rpcs []*proto.RPC
|
|
for _, op := range []string{"Create", "Update", "Delete"} {
|
|
rpc := NewRPC(op+typename, "Msg"+op+typename, "Msg"+op+typename+"Response")
|
|
rpcs = append(rpcs, rpc)
|
|
}
|
|
Apply(f, nil, func(c *Cursor) bool {
|
|
// Find the specific service and append.
|
|
if m, ok := c.Node().(*proto.Service); ok {
|
|
if m.Name == "Msg" {
|
|
for _, rpc := range rpcs {
|
|
Append(m, rpc)
|
|
}
|
|
return false // stop
|
|
}
|
|
}
|
|
// Msg will be traversed first.
|
|
// If it was empty, we just stop traversing.
|
|
return true
|
|
})
|
|
for _, rpc := range rpcs {
|
|
require.True(t, containsElement(f, rpc))
|
|
}
|
|
// Add the messages after service Msgs at the end of f.
|
|
createtyp := NewMessage("MsgCreateKirby",
|
|
WithFields(NewField("creator", "string", 1)))
|
|
resp := NewMessage("MsgCreateKirbyResponse",
|
|
WithFields(
|
|
NewField("id", "uint64", 1),
|
|
),
|
|
)
|
|
Append(f, createtyp, resp)
|
|
require.True(t, containsElement(f, createtyp))
|
|
require.True(t, containsElement(f, resp))
|
|
|
|
updatetyp := NewMessage("MsgUpdateKirby",
|
|
WithFields(
|
|
NewField("creator", "string", 1),
|
|
NewField("id", "uint64", 2),
|
|
),
|
|
)
|
|
updateResp := NewMessage("MsgUpdateKirbyResponse")
|
|
Append(f, updatetyp, updateResp)
|
|
require.True(t, containsElement(f, updatetyp))
|
|
require.True(t, containsElement(f, updateResp))
|
|
|
|
deltyp := NewMessage("MsgDeleteKirby",
|
|
WithFields(
|
|
NewField("creator", "string", 1),
|
|
NewField("id", "uint64", 2),
|
|
),
|
|
)
|
|
delResp := NewMessage("MsgDeleteResponse")
|
|
Append(f, deltyp, delResp)
|
|
require.True(t, containsElement(f, deltyp))
|
|
require.True(t, containsElement(f, delResp))
|
|
}
|
|
|
|
// Test that the changes from adding a list with starport scaffold list <Type>
|
|
// are applied correctly to genesis.proto.
|
|
func TestAddEmptyList_genesis(t *testing.T) {
|
|
typename, modname := "Kirby", "mod"
|
|
f, err := parseStringProto(genesisProto)
|
|
require.NoError(t, err)
|
|
|
|
// 1) Add import for the new type (module/lowercase_typ)
|
|
imp := NewImport(fmt.Sprintf("%s/%s.proto", modname, strings.ToLower(typename)))
|
|
err = AddImports(f, true, imp)
|
|
require.NoError(t, err)
|
|
require.True(t, containsElement(f, imp))
|
|
|
|
// 2) Add fields to GenesisState. Append.
|
|
Apply(f, nil, func(c *Cursor) bool {
|
|
if m, ok := c.Node().(*proto.Message); ok {
|
|
if m.Name == "GenesisState" {
|
|
lst := NewField(typename+"_list", typename, 2,
|
|
WithFieldOptions(NewOption("gogoproto.nullable", "false", Custom())),
|
|
Repeated(),
|
|
)
|
|
field := NewField(typename+"Count", typename, 3)
|
|
Append(m, lst, field)
|
|
require.True(t, containsElement(f, lst))
|
|
require.True(t, containsElement(f, field))
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
func TestAddEmptyList_query(t *testing.T) {
|
|
typename, modname := "Kirby", "mod"
|
|
f, err := parseStringProto(queryProto)
|
|
require.NoError(t, err)
|
|
|
|
// 1) Add import for the new type (module/lowercase_typ)
|
|
imp := NewImport(fmt.Sprintf("%s/%s.proto", modname, strings.ToLower(typename)))
|
|
err = AddImports(f, true, imp)
|
|
require.NoError(t, err)
|
|
require.True(t, containsElement(f, imp))
|
|
|
|
q, err := GetServiceByName(f, "Query")
|
|
require.NoError(t, err)
|
|
// Add the rpcs
|
|
single := NewRPC(typename, "QueryGet"+typename+"Request", "QueryGet"+typename+"Response",
|
|
WithRPCOptions(
|
|
NewOption(
|
|
"google.api.http",
|
|
"/cosmonaut/chainname/chainname/"+typename+"/{id}",
|
|
Custom(),
|
|
SetField("get"),
|
|
),
|
|
),
|
|
)
|
|
all := NewRPC(typename+"All", "QueryAll"+typename+"Request", "QueryAll"+typename+"Response",
|
|
WithRPCOptions(
|
|
NewOption(
|
|
"google.api.http",
|
|
"/cosmonaut/chainname/chainname/"+typename,
|
|
Custom(),
|
|
SetField("get"),
|
|
),
|
|
),
|
|
)
|
|
Append(q, single, all)
|
|
require.True(t, containsElement(f, single))
|
|
require.True(t, containsElement(f, all))
|
|
}
|