vm: add 'env' command showing state of the blockchain-backed VM CLI

A useful one.
This commit is contained in:
Anna Shaleva 2022-10-04 14:19:42 +03:00
parent f1ecdb82cc
commit 0036c89d63
2 changed files with 69 additions and 0 deletions

View file

@ -39,6 +39,7 @@ import (
const ( const (
chainKey = "chain" chainKey = "chain"
chainCfgKey = "chainCfg"
icKey = "ic" icKey = "ic"
manifestKey = "manifest" manifestKey = "manifest"
exitFuncKey = "exitFunc" exitFuncKey = "exitFunc"
@ -51,6 +52,11 @@ const (
stringType = "string" stringType = "string"
) )
// Various flag names.
const (
verboseFlagFullName = "verbose"
)
var commands = []cli.Command{ var commands = []cli.Command{
{ {
Name: "exit", Name: "exit",
@ -231,6 +237,24 @@ example:
Description: "Dump events emitted by the current loaded program", Description: "Dump events emitted by the current loaded program",
Action: handleEvents, Action: handleEvents,
}, },
{
Name: "env",
Usage: "Dump state of the chain that is used for VM CLI invocations (use -v for verbose node configuration)",
UsageText: `env [-v]`,
Flags: []cli.Flag{
cli.BoolFlag{
Name: verboseFlagFullName + ",v",
Usage: "Print the whole blockchain node configuration.",
},
},
Description: `env [-v]
Dump state of the chain that is used for VM CLI invocations (use -v for verbose node configuration).
Example:
> env -v`,
Action: handleEnv,
},
} }
var completer *readline.PrefixCompleter var completer *readline.PrefixCompleter
@ -318,6 +342,7 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg
vmcli.shell.Metadata = map[string]interface{}{ vmcli.shell.Metadata = map[string]interface{}{
chainKey: chain, chainKey: chain,
chainCfgKey: cfg,
icKey: ic, icKey: ic,
manifestKey: new(manifest.Manifest), manifestKey: new(manifest.Manifest),
exitFuncKey: exitF, exitFuncKey: exitF,
@ -344,6 +369,10 @@ func getChainFromContext(app *cli.App) *core.Blockchain {
return app.Metadata[chainKey].(*core.Blockchain) return app.Metadata[chainKey].(*core.Blockchain)
} }
func getChainConfigFromContext(app *cli.App) config.Config {
return app.Metadata[chainCfgKey].(config.Config)
}
func getInteropContextFromContext(app *cli.App) *interop.Context { func getInteropContextFromContext(app *cli.App) *interop.Context {
return app.Metadata[icKey].(*interop.Context) return app.Metadata[icKey].(*interop.Context)
} }
@ -764,6 +793,21 @@ func handleEvents(c *cli.Context) error {
return nil return nil
} }
func handleEnv(c *cli.Context) error {
bc := getChainFromContext(c.App)
cfg := getChainConfigFromContext(c.App)
message := fmt.Sprintf("Chain height: %d\nNetwork magic: %d\nDB type: %s\n", bc.BlockHeight(), bc.GetConfig().Magic, cfg.ApplicationConfiguration.DBConfiguration.Type)
if c.Bool(verboseFlagFullName) {
cfgBytes, err := json.MarshalIndent(cfg, "", "\t")
if err != nil {
return fmt.Errorf("failed to marshal node configuration: %w", err)
}
message += "Node config:\n" + string(cfgBytes) + "\n"
}
fmt.Fprint(c.App.Writer, message)
return nil
}
func dumpEvents(app *cli.App) (string, error) { func dumpEvents(app *cli.App) (string, error) {
ic := getInteropContextFromContext(app) ic := getInteropContextFromContext(app)
if len(ic.Notifications) == 0 { if len(ic.Notifications) == 0 {

View file

@ -786,3 +786,28 @@ func TestEvents(t *testing.T) {
e.checkEvents(t, true, expectedEvent) // automatically printed after `run` command e.checkEvents(t, true, expectedEvent) // automatically printed after `run` command
e.checkEvents(t, false, expectedEvent) // printed after `events` command e.checkEvents(t, false, expectedEvent) // printed after `events` command
} }
func TestEnv(t *testing.T) {
t.Run("default setup", func(t *testing.T) {
e := newTestVMCLI(t)
e.runProg(t, "env")
e.checkNextLine(t, "Chain height: 0")
e.checkNextLine(t, "Network magic: 42")
e.checkNextLine(t, "DB type: inmemory")
})
t.Run("setup with state", func(t *testing.T) {
e := newTestVMClIWithState(t)
e.runProg(t, "env")
e.checkNextLine(t, "Chain height: 5")
e.checkNextLine(t, "Network magic: 42")
e.checkNextLine(t, "DB type: leveldb")
})
t.Run("verbose", func(t *testing.T) {
e := newTestVMClIWithState(t)
e.runProg(t, "env -v")
e.checkNextLine(t, "Chain height: 5")
e.checkNextLine(t, "Network magic: 42")
e.checkNextLine(t, "DB type: leveldb")
e.checkNextLine(t, "Node config:") // Do not check exact node config.
})
}