Skip to content

Commit

Permalink
feat(template): scaffold genesis validation tests (ignite#1489)
Browse files Browse the repository at this point in the history
* Initialize test template

* Add placeholder

* Genesis test patch

* map test case

* Small fix

* list genesis tests

* Small fix

* Template fixes

* lint template

* Lint

* Small fix template

* Small fix template

* Valid case tests

* Lint

* docs: update changelog

* Fix issue with ibc

Co-authored-by: Danilo Pantani <[email protected]>
Co-authored-by: Denis Fadeev <[email protected]>
  • Loading branch information
3 people authored Aug 26, 2021
1 parent 1b65dfb commit 4a6aea6
Show file tree
Hide file tree
Showing 13 changed files with 316 additions and 48 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Added `starport scaffold flutter` to scaffold a Flutter mobile app template
- Added `starport account` commands to manage accounts (key pairs)
- `starport version` now prints out detailed information about OS, Go version and more.
- Module scaffolding now creates `x/.../types/genesis_test.go` for genesis validation tests

### Fixes:

Expand Down
37 changes: 0 additions & 37 deletions starport/services/scaffolder/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import (
"os"
"path/filepath"

"github.com/gobuffalo/genny"
"github.com/tendermint/starport/starport/pkg/multiformatname"
"github.com/tendermint/starport/starport/pkg/placeholder"
modulecreate "github.com/tendermint/starport/starport/templates/module/create"
)

const (
Expand All @@ -21,40 +18,6 @@ const (
componentPacket = "packet"
)

// supportMsgServer checks if the module supports the MsgServer convention
// if not, the module codebase is modified to support it
// https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-031-msg-service.md
func supportMsgServer(
replacer placeholder.Replacer,
appPath string,
opts *modulecreate.MsgServerOptions,
) (*genny.Generator, error) {
// Check if convention used
msgServerDefined, err := isMsgServerDefined(appPath, opts.ModuleName)
if err != nil {
return nil, err
}
if !msgServerDefined {
// Patch the module to support the convention
return modulecreate.AddMsgServerConventionToLegacyModule(replacer, opts)
}
return nil, nil
}

// isMsgServerDefined checks if the module uses the MsgServer convention for transactions
// this is checked by verifying the existence of the tx.proto file
func isMsgServerDefined(appPath, moduleName string) (bool, error) {
txProto, err := filepath.Abs(filepath.Join(appPath, "proto", moduleName, "tx.proto"))
if err != nil {
return false, err
}

if _, err := os.Stat(txProto); os.IsNotExist(err) {
return false, nil
}
return true, err
}

// checkComponentValidity performs various checks common to all components to verify if it can be scaffolded
func checkComponentValidity(appPath, moduleName string, compName multiformatname.Name, noMessage bool) error {
ok, err := moduleExists(appPath, moduleName)
Expand Down
6 changes: 2 additions & 4 deletions starport/services/scaffolder/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ func (s *Scaffolder) AddMessage(

// Check and support MsgServer convention
var gens []*genny.Generator
g, err = supportMsgServer(
gens, err = supportMsgServer(
gens,
tracer,
s.path,
&modulecreate.MsgServerOptions{
Expand All @@ -129,9 +130,6 @@ func (s *Scaffolder) AddMessage(
if err != nil {
return sm, err
}
if g != nil {
gens = append(gens, g)
}

// Scaffold
g, err = message.NewStargate(tracer, opts)
Expand Down
72 changes: 72 additions & 0 deletions starport/services/scaffolder/patch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package scaffolder

import (
"os"
"path/filepath"

"github.com/gobuffalo/genny"
"github.com/tendermint/starport/starport/pkg/placeholder"
modulecreate "github.com/tendermint/starport/starport/templates/module/create"
)

// supportGenesisTests checks if types/genesis_test.go exists
// appends the generator to create the file if it doesn't
func supportGenesisTests(
gens []*genny.Generator,
appPath,
appName,
modulePath,
moduleName string,
) ([]*genny.Generator, error) {
filepath, err := filepath.Abs(filepath.Join(appPath, "x", moduleName, "types", "genesis_test.go"))
if err != nil {
return nil, err
}
if _, err := os.Stat(filepath); os.IsNotExist(err) {
g, err := modulecreate.AddGenesisTest(appName, modulePath, moduleName)
if err != nil {
return nil, err
}
gens = append(gens, g)
}
return gens, err
}

// supportMsgServer checks if the module supports the MsgServer convention
// appends the generator to support it if it doesn't
// https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-031-msg-service.md
func supportMsgServer(
gens []*genny.Generator,
replacer placeholder.Replacer,
appPath string,
opts *modulecreate.MsgServerOptions,
) ([]*genny.Generator, error) {
// Check if convention used
msgServerDefined, err := isMsgServerDefined(appPath, opts.ModuleName)
if err != nil {
return nil, err
}
if !msgServerDefined {
// Patch the module to support the convention
g, err := modulecreate.AddMsgServerConventionToLegacyModule(replacer, opts)
if err != nil {
return nil, err
}
gens = append(gens, g)
}
return gens, nil
}

// isMsgServerDefined checks if the module uses the MsgServer convention for transactions
// this is checked by verifying the existence of the tx.proto file
func isMsgServerDefined(appPath, moduleName string) (bool, error) {
txProto, err := filepath.Abs(filepath.Join(appPath, "proto", moduleName, "tx.proto"))
if err != nil {
return false, err
}

if _, err := os.Stat(txProto); os.IsNotExist(err) {
return false, nil
}
return true, err
}
15 changes: 12 additions & 3 deletions starport/services/scaffolder/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ func (s *Scaffolder) AddType(
gens []*genny.Generator
)
// Check and support MsgServer convention
g, err = supportMsgServer(
gens, err = supportMsgServer(
gens,
tracer,
s.path,
&modulecreate.MsgServerOptions{
Expand All @@ -176,8 +177,16 @@ func (s *Scaffolder) AddType(
if err != nil {
return sm, err
}
if g != nil {
gens = append(gens, g)

gens, err = supportGenesisTests(
gens,
opts.AppPath,
opts.AppName,
opts.ModulePath,
opts.ModuleName,
)
if err != nil {
return sm, err
}

// create the type generator depending on the model
Expand Down
23 changes: 23 additions & 0 deletions starport/templates/module/create/genesistest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package modulecreate

import (
"github.com/gobuffalo/genny"
"github.com/gobuffalo/plush"
"github.com/gobuffalo/plushgen"
)

// AddGenesisTest returns the generator to generate genesis_test.go
func AddGenesisTest(appName, modulePath, moduleName string) (*genny.Generator, error) {
g := genny.New()
if err := g.Box(genesisTestTemplate); err != nil {
return g, err
}
ctx := plush.NewContext()
ctx.Set("moduleName", moduleName)
ctx.Set("modulePath", modulePath)
ctx.Set("appName", appName)

g.Transformer(plushgen.Transformer(ctx))
g.Transformer(genny.Replace("{{moduleName}}", moduleName))
return g, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package types_test

import (
"testing"
"github.com/stretchr/testify/require"
"<%= modulePath %>/x/<%= moduleName %>/types"
)

func TestGenesisState_Validate(t *testing.T) {
for _, tc := range []struct {
desc string
genState *types.GenesisState
valid bool
} {
{
desc: "default is valid",
genState: types.DefaultGenesis(),
valid: true,
},
{
desc: "valid genesis state",
genState: &types.GenesisState{
// this line is used by starport scaffolding # types/genesis/validField
},
valid: true,
},
// this line is used by starport scaffolding # types/genesis/testcase
} {
tc := tc
t.Run(tc.desc, func(t *testing.T) {
err := tc.genState.Validate()
if tc.valid {
require.NoError(t, err)
} else {
require.Error(t, err)
}
})
}
}
17 changes: 17 additions & 0 deletions starport/templates/module/create/ibc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func NewIBC(replacer placeholder.Replacer, opts *CreateOptions) (*genny.Generato
g.RunFn(errorsModify(replacer, opts))
g.RunFn(genesisTypeModify(replacer, opts))
g.RunFn(genesisProtoModify(replacer, opts))
g.RunFn(genesisTestsModify(replacer, opts))
g.RunFn(keysModify(replacer, opts))
g.RunFn(keeperModify(replacer, opts))

Expand Down Expand Up @@ -163,6 +164,22 @@ func genesisProtoModify(replacer placeholder.Replacer, opts *CreateOptions) genn
}
}

func genesisTestsModify(replacer placeholder.Replacer, opts *CreateOptions) genny.RunFn {
return func(r *genny.Runner) error {
path := fmt.Sprintf("x/%s/types/genesis_test.go", opts.ModuleName)
f, err := r.Disk.Find(path)
if err != nil {
return err
}

replacement := fmt.Sprintf("PortId: types.PortID,\n%s", module.PlaceholderTypesGenesisValidField)
content := replacer.Replace(f.String(), module.PlaceholderTypesGenesisValidField, replacement)

newFile := genny.NewFileS(path, content)
return r.File(newFile)
}
}

func keysModify(replacer placeholder.Replacer, opts *CreateOptions) genny.RunFn {
return func(r *genny.Runner) error {
path := fmt.Sprintf("x/%s/types/keys.go", opts.ModuleName)
Expand Down
3 changes: 3 additions & 0 deletions starport/templates/module/create/stargate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ func NewStargate(opts *CreateOptions) (*genny.Generator, error) {
if err := g.Box(msgServerTemplate); err != nil {
return g, err
}
if err := g.Box(genesisTestTemplate); err != nil {
return g, err
}
if err := g.Box(stargateTemplate); err != nil {
return g, err
}
Expand Down
10 changes: 7 additions & 3 deletions starport/templates/module/create/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ var (
//go:embed msgserver/* msgserver/**/*
fsMsgServer embed.FS

stargateTemplate = xgenny.NewEmbedWalker(fsStargate, "stargate/")
ibcTemplate = xgenny.NewEmbedWalker(fsIBC, "ibc/")
msgServerTemplate = xgenny.NewEmbedWalker(fsMsgServer, "msgserver/")
//go:embed genesistest/* genesistest/**/*
fsGenesisTest embed.FS

stargateTemplate = xgenny.NewEmbedWalker(fsStargate, "stargate/")
ibcTemplate = xgenny.NewEmbedWalker(fsIBC, "ibc/")
msgServerTemplate = xgenny.NewEmbedWalker(fsMsgServer, "msgserver/")
genesisTestTemplate = xgenny.NewEmbedWalker(fsGenesisTest, "genesistest/")
)
4 changes: 4 additions & 0 deletions starport/templates/module/placeholders.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ const (
PlaceholderIBCAppScopedKeeperDefinition = "// this line is used by starport scaffolding # ibc/app/scopedKeeper/definition"
PlaceholderIBCAppKeeperArgument = "// this line is used by starport scaffolding # ibc/app/keeper/argument"
PlaceholderIBCAppRouter = "// this line is used by starport scaffolding # ibc/app/router"

// Genesis test
PlaceholderTypesGenesisTestcase = "// this line is used by starport scaffolding # types/genesis/testcase"
PlaceholderTypesGenesisValidField = "// this line is used by starport scaffolding # types/genesis/validField"
)
67 changes: 67 additions & 0 deletions starport/templates/typed/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import (

"github.com/gobuffalo/genny"
"github.com/tendermint/starport/starport/pkg/placeholder"
"github.com/tendermint/starport/starport/templates/module"
)

func (t *typedStargate) genesisModify(replacer placeholder.Replacer, opts *Options, g *genny.Generator) {
g.RunFn(t.genesisProtoModify(replacer, opts))
g.RunFn(t.genesisTypesModify(replacer, opts))
g.RunFn(t.genesisModuleModify(replacer, opts))
g.RunFn(t.genesisTestsModify(replacer, opts))
}

func (t *typedStargate) genesisProtoModify(replacer placeholder.Replacer, opts *Options) genny.RunFn {
Expand Down Expand Up @@ -146,6 +148,71 @@ genesis.%[2]vCount = k.Get%[2]vCount(ctx)
}
}

func (t *typedStargate) genesisTestsModify(replacer placeholder.Replacer, opts *Options) genny.RunFn {
return func(r *genny.Runner) error {
path := fmt.Sprintf("x/%s/types/genesis_test.go", opts.ModuleName)
f, err := r.Disk.Find(path)
if err != nil {
return err
}

templateValid := `%[1]v
%[2]vList: []types.%[2]v{
{
Id: 0,
},
{
Id: 1,
},
},
%[2]vCount: 2,`
replacementValid := fmt.Sprintf(
templateValid,
module.PlaceholderTypesGenesisValidField,
opts.TypeName.UpperCamel,
)
content := replacer.Replace(f.String(), module.PlaceholderTypesGenesisValidField, replacementValid)

templateTests := `%[1]v
{
desc: "duplicated %[2]v",
genState: &types.GenesisState{
%[3]vList: []types.%[3]v{
{
Id: 0,
},
{
Id: 0,
},
},
},
valid: false,
},
{
desc: "invalid %[2]v count",
genState: &types.GenesisState{
%[3]vList: []types.%[3]v{
{
Id: 1,
},
},
%[3]vCount: 0,
},
valid: false,
},`
replacementTests := fmt.Sprintf(
templateTests,
module.PlaceholderTypesGenesisTestcase,
opts.TypeName.LowerCamel,
opts.TypeName.UpperCamel,
)
content = replacer.Replace(content, module.PlaceholderTypesGenesisTestcase, replacementTests)

newFile := genny.NewFileS(path, content)
return r.File(newFile)
}
}

// PatchGenesisTypeImport patches types/genesis.go content from the issue:
// https://github.com/tendermint/starport/issues/992
func PatchGenesisTypeImport(replacer placeholder.Replacer, content string) string {
Expand Down
Loading

0 comments on commit 4a6aea6

Please sign in to comment.