mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-29 12:41:44 +00:00
Merge pull request #3 from tendermint/console
tmsp cli enhancements and simple tests
This commit is contained in:
22
cmd/counter/main.go
Normal file
22
cmd/counter/main.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/tendermint/go-common"
|
||||||
|
"github.com/tendermint/tmsp/example"
|
||||||
|
"github.com/tendermint/tmsp/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// Start the listener
|
||||||
|
_, err := server.StartListener("tcp://127.0.0.1:8080", example.NewCounterApplication())
|
||||||
|
if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait forever
|
||||||
|
TrapSignal(func() {
|
||||||
|
// Cleanup
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
144
cmd/tmsp/cli.go
144
cmd/tmsp/cli.go
@ -1,9 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
. "github.com/tendermint/go-common"
|
. "github.com/tendermint/go-common"
|
||||||
"github.com/tendermint/go-wire"
|
"github.com/tendermint/go-wire"
|
||||||
@ -12,6 +16,9 @@ import (
|
|||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// connection is a global variable so it can be reused by the console
|
||||||
|
var conn net.Conn
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "cli"
|
app.Name = "cli"
|
||||||
@ -24,6 +31,34 @@ func main() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
|
{
|
||||||
|
Name: "batch",
|
||||||
|
Usage: "Run a batch of tmsp commands against an application",
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
cmdBatch(app, c)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "console",
|
||||||
|
Usage: "Start an interactive tmsp console for multiple commands",
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
cmdConsole(app, c)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "info",
|
||||||
|
Usage: "Get some info about the application",
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
cmdInfo(c)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "set_option",
|
||||||
|
Usage: "Set an option on the application",
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
cmdSetOption(c)
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "append_tx",
|
Name: "append_tx",
|
||||||
Usage: "Append a new tx to application",
|
Usage: "Append a new tx to application",
|
||||||
@ -53,46 +88,115 @@ func main() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
app.Before = before
|
||||||
app.Run(os.Args)
|
app.Run(os.Args)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func before(c *cli.Context) error {
|
||||||
|
if conn == nil {
|
||||||
|
var err error
|
||||||
|
conn, err = Connect(c.GlobalString("address"))
|
||||||
|
if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func cmdBatch(app *cli.App, c *cli.Context) {
|
||||||
|
bufReader := bufio.NewReader(os.Stdin)
|
||||||
|
for {
|
||||||
|
line, more, err := bufReader.ReadLine()
|
||||||
|
if more {
|
||||||
|
Exit("input line is too long")
|
||||||
|
} else if err == io.EOF {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
args := []string{"tmsp"}
|
||||||
|
args = append(args, strings.Split(string(line), " ")...)
|
||||||
|
app.Run(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdConsole(app *cli.App, c *cli.Context) {
|
||||||
|
for {
|
||||||
|
fmt.Printf("> ")
|
||||||
|
bufReader := bufio.NewReader(os.Stdin)
|
||||||
|
line, more, err := bufReader.ReadLine()
|
||||||
|
if more {
|
||||||
|
Exit("input is too long")
|
||||||
|
} else if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{"tmsp"}
|
||||||
|
args = append(args, strings.Split(string(line), " ")...)
|
||||||
|
app.Run(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get some info from the application
|
||||||
|
func cmdInfo(c *cli.Context) {
|
||||||
|
res, err := makeRequest(conn, types.RequestInfo{})
|
||||||
|
if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
fmt.Println(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set an option on the application
|
||||||
|
func cmdSetOption(c *cli.Context) {
|
||||||
|
args := c.Args()
|
||||||
|
if len(args) != 2 {
|
||||||
|
Exit("set_option takes 2 arguments (key, value)")
|
||||||
|
}
|
||||||
|
_, err := makeRequest(conn, types.RequestSetOption{args[0], args[1]})
|
||||||
|
if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
fmt.Printf("%s=%s\n", args[0], args[1])
|
||||||
|
}
|
||||||
|
|
||||||
// Append a new tx to application
|
// Append a new tx to application
|
||||||
func cmdAppendTx(c *cli.Context) {
|
func cmdAppendTx(c *cli.Context) {
|
||||||
args := c.Args() // Args to AppendTx
|
args := c.Args()
|
||||||
conn, err := Connect(c.GlobalString("address"))
|
if len(args) != 1 {
|
||||||
|
Exit("append_tx takes 1 argument")
|
||||||
|
}
|
||||||
|
txString := args[0]
|
||||||
|
tx := []byte(txString)
|
||||||
|
if len(txString) > 2 && strings.HasPrefix(txString, "0x") {
|
||||||
|
var err error
|
||||||
|
tx, err = hex.DecodeString(txString[2:])
|
||||||
|
if err != nil {
|
||||||
|
Exit(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := makeRequest(conn, types.RequestAppendTx{tx})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Exit(err.Error())
|
Exit(err.Error())
|
||||||
}
|
}
|
||||||
res, err := makeRequest(conn, types.RequestAppendTx{[]byte(args[0])})
|
fmt.Println("Sent tx:", txString, "response:", res)
|
||||||
if err != nil {
|
|
||||||
Exit(err.Error())
|
|
||||||
}
|
|
||||||
fmt.Println("Sent tx:", args[0], "response:", res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get application Merkle root hash
|
// Get application Merkle root hash
|
||||||
func cmdGetHash(c *cli.Context) {
|
func cmdGetHash(c *cli.Context) {
|
||||||
conn, err := Connect(c.GlobalString("address"))
|
|
||||||
if err != nil {
|
|
||||||
Exit(err.Error())
|
|
||||||
}
|
|
||||||
res, err := makeRequest(conn, types.RequestGetHash{})
|
res, err := makeRequest(conn, types.RequestGetHash{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Exit(err.Error())
|
Exit(err.Error())
|
||||||
}
|
}
|
||||||
fmt.Println("Got hash:", Fmt("%X", res.(types.ResponseGetHash).Hash))
|
fmt.Printf("%X\n", res.(types.ResponseGetHash).Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit the application state
|
// Commit the application state
|
||||||
func cmdCommit(c *cli.Context) {
|
func cmdCommit(c *cli.Context) {
|
||||||
conn, err := Connect(c.GlobalString("address"))
|
_, err := makeRequest(conn, types.RequestCommit{})
|
||||||
if err != nil {
|
|
||||||
Exit(err.Error())
|
|
||||||
}
|
|
||||||
_, err = makeRequest(conn, types.RequestCommit{})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Exit(err.Error())
|
Exit(err.Error())
|
||||||
}
|
}
|
||||||
@ -101,11 +205,7 @@ func cmdCommit(c *cli.Context) {
|
|||||||
|
|
||||||
// Roll back the application state to the latest commit
|
// Roll back the application state to the latest commit
|
||||||
func cmdRollback(c *cli.Context) {
|
func cmdRollback(c *cli.Context) {
|
||||||
conn, err := Connect(c.GlobalString("address"))
|
_, err := makeRequest(conn, types.RequestRollback{})
|
||||||
if err != nil {
|
|
||||||
Exit(err.Error())
|
|
||||||
}
|
|
||||||
_, err = makeRequest(conn, types.RequestRollback{})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Exit(err.Error())
|
Exit(err.Error())
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ func (appC *CounterAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode
|
|||||||
|
|
||||||
func (appC *CounterAppContext) GetHash() ([]byte, types.RetCode) {
|
func (appC *CounterAppContext) GetHash() ([]byte, types.RetCode) {
|
||||||
hash := make([]byte, 32)
|
hash := make([]byte, 32)
|
||||||
binary.PutVarint(hash, int64(appC.hashCount))
|
binary.PutVarint(hash, int64(appC.txCount))
|
||||||
appC.hashCount += 1
|
appC.hashCount += 1
|
||||||
return hash, 0
|
return hash, 0
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -86,7 +87,11 @@ func handleRequests(appC types.AppContext, closeConn chan error, conn net.Conn,
|
|||||||
var req types.Request
|
var req types.Request
|
||||||
wire.ReadBinaryPtr(&req, bufReader, 0, &n, &err)
|
wire.ReadBinaryPtr(&req, bufReader, 0, &n, &err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
closeConn <- fmt.Errorf("Error in handleRequests: %v", err.Error())
|
if err == io.EOF {
|
||||||
|
closeConn <- fmt.Errorf("Connection closed by client")
|
||||||
|
} else {
|
||||||
|
closeConn <- fmt.Errorf("Error in handleRequests: %v", err.Error())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
|
100
test.sh
Normal file
100
test.sh
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
# Make sure the tmsp cli can connect to the dummy
|
||||||
|
echo "Dummy test ..."
|
||||||
|
dummy &> /dev/null &
|
||||||
|
PID=`echo $!`
|
||||||
|
sleep 1
|
||||||
|
RESULT_HASH=`tmsp get_hash`
|
||||||
|
if [[ "$RESULT_HASH" != "" ]]; then
|
||||||
|
echo "Expected nothing but got: $RESULT_HASH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "... Pass!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Add a tx, get hash, commit, get hash
|
||||||
|
# hashes should be non-empty and identical
|
||||||
|
echo "Dummy batch test ..."
|
||||||
|
OUTPUT=`(tmsp batch) <<STDIN
|
||||||
|
append_tx abc
|
||||||
|
get_hash
|
||||||
|
commit
|
||||||
|
get_hash
|
||||||
|
STDIN`
|
||||||
|
|
||||||
|
HASH1=`echo "$OUTPUT" | tail -n 3 | head -n 1`
|
||||||
|
HASH2=`echo "$OUTPUT" | tail -n 1`
|
||||||
|
|
||||||
|
if [[ "$HASH1" == "" ]]; then
|
||||||
|
echo "Expected non empty hash!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$HASH1" != "$HASH2" ]]; then
|
||||||
|
echo "Expected hashes before and after commit to match: $HASH1, $HASH2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "... Pass!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Start a new connection and ensure the hash is the same
|
||||||
|
echo "New connection test ..."
|
||||||
|
RESULT_HASH=`tmsp get_hash`
|
||||||
|
if [[ "$HASH1" != "$RESULT_HASH" ]]; then
|
||||||
|
echo "Expected hash to persist as $HASH1 for new connection. Got $RESULT_HASH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "... Pass!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
|
kill $PID
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# test the counter app
|
||||||
|
echo "Counter test ..."
|
||||||
|
counter &> /dev/null &
|
||||||
|
PID=`echo $!`
|
||||||
|
sleep 1
|
||||||
|
OUTPUT=`(tmsp batch) <<STDIN
|
||||||
|
set_option serial on
|
||||||
|
get_hash
|
||||||
|
append_tx abc
|
||||||
|
STDIN`
|
||||||
|
|
||||||
|
# why can't we pick up the non-zero exit code here?
|
||||||
|
# echo $?
|
||||||
|
|
||||||
|
HASH1=`echo "$OUTPUT" | tail -n +2 | head -n 1`
|
||||||
|
if [[ "${HASH1:0:2}" != "00" ]]; then
|
||||||
|
echo "Expected opening hash to lead with 00. Got $HASH1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUTPUT=`(tmsp batch) <<STDIN
|
||||||
|
set_option serial on
|
||||||
|
append_tx 0x00
|
||||||
|
get_hash
|
||||||
|
append_tx 0x02
|
||||||
|
get_hash
|
||||||
|
STDIN`
|
||||||
|
|
||||||
|
HASH1=`echo "$OUTPUT" | tail -n +3 | head -n 1`
|
||||||
|
HASH2=`echo "$OUTPUT" | tail -n +5 | head -n 1`
|
||||||
|
|
||||||
|
if [[ "${HASH1:0:2}" != "02" ]]; then
|
||||||
|
echo "Expected hash to lead with 02. Got $HASH1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${HASH2:0:2}" != "04" ]]; then
|
||||||
|
echo "Expected hash to lead with 04. Got $HASH2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "... Pass!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
kill $PID
|
||||||
|
|
Reference in New Issue
Block a user