mukan-ignite/ignite/pkg/protoanalysis/protoutil/proto_test.go
Mukan Erkin Törük 26b204bd04
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
feat: fork Ignite CLI v29 as Mukan Ignite — remove cosmos-sdk restrictions
2026-05-11 03:31:37 +03:00

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))
}