Merge PR #3517: Increasing test coverage in keys/client package
This commit is contained in:
+17
-1
@@ -15,10 +15,26 @@ import (
|
||||
// MinPassLength is the minimum acceptable password length
|
||||
const MinPassLength = 8
|
||||
|
||||
var currentStdin *bufio.Reader
|
||||
|
||||
func init() {
|
||||
currentStdin = bufio.NewReader(os.Stdin)
|
||||
}
|
||||
|
||||
// BufferStdin is used to allow reading prompts for stdin
|
||||
// multiple times, when we read from non-tty
|
||||
func BufferStdin() *bufio.Reader {
|
||||
return bufio.NewReader(os.Stdin)
|
||||
return currentStdin
|
||||
}
|
||||
|
||||
// OverrideStdin allows to temporarily override stdin
|
||||
func OverrideStdin(newStdin *bufio.Reader) (cleanUp func()) {
|
||||
prevStdin := currentStdin
|
||||
currentStdin = newStdin
|
||||
cleanUp = func() {
|
||||
currentStdin = prevStdin
|
||||
}
|
||||
return cleanUp
|
||||
}
|
||||
|
||||
// GetPassword will prompt for a password one-time (to sign a tx)
|
||||
|
||||
+3
-3
@@ -90,7 +90,7 @@ input
|
||||
output
|
||||
- armor encrypted private key (saved to file)
|
||||
*/
|
||||
func runAddCmd(cmd *cobra.Command, args []string) error {
|
||||
func runAddCmd(_ *cobra.Command, args []string) error {
|
||||
var kb keys.Keybase
|
||||
var err error
|
||||
var encryptPassword string
|
||||
@@ -265,7 +265,7 @@ func printCreate(info keys.Info, showMnemonic bool, mnemonic string) error {
|
||||
output := viper.Get(cli.OutputFlag)
|
||||
|
||||
switch output {
|
||||
case "text":
|
||||
case OutputFormatText:
|
||||
fmt.Fprintln(os.Stderr)
|
||||
printKeyInfo(info, Bech32KeyOutput)
|
||||
|
||||
@@ -276,7 +276,7 @@ func printCreate(info keys.Info, showMnemonic bool, mnemonic string) error {
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
fmt.Fprintln(os.Stderr, mnemonic)
|
||||
}
|
||||
case "json":
|
||||
case OutputFormatJSON:
|
||||
out, err := Bech32KeyOutput(info)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_runAddCmdBasic(t *testing.T) {
|
||||
cmd := addKeyCommand()
|
||||
assert.NotNil(t, cmd)
|
||||
|
||||
// Missing input (enter password)
|
||||
err := runAddCmd(cmd, []string{"keyname"})
|
||||
assert.EqualError(t, err, "EOF")
|
||||
|
||||
// Prepare a keybase
|
||||
kbHome, kbCleanUp, err := tests.GetTempDir("Test_runDeleteCmd")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, kbHome)
|
||||
defer kbCleanUp()
|
||||
viper.Set(cli.HomeFlag, kbHome)
|
||||
|
||||
/// Test Text
|
||||
viper.Set(cli.OutputFlag, OutputFormatText)
|
||||
// Now enter password
|
||||
cleanUp1 := client.OverrideStdin(bufio.NewReader(strings.NewReader("test1234\ntest1234\n")))
|
||||
defer cleanUp1()
|
||||
err = runAddCmd(cmd, []string{"keyname1"})
|
||||
assert.NoError(t, err)
|
||||
|
||||
/// Test Text - Replace? >> FAIL
|
||||
viper.Set(cli.OutputFlag, OutputFormatText)
|
||||
// Now enter password
|
||||
cleanUp2 := client.OverrideStdin(bufio.NewReader(strings.NewReader("test1234\ntest1234\n")))
|
||||
defer cleanUp2()
|
||||
err = runAddCmd(cmd, []string{"keyname1"})
|
||||
assert.Error(t, err)
|
||||
|
||||
/// Test Text - Replace? Answer >> PASS
|
||||
viper.Set(cli.OutputFlag, OutputFormatText)
|
||||
// Now enter password
|
||||
cleanUp3 := client.OverrideStdin(bufio.NewReader(strings.NewReader("y\ntest1234\ntest1234\n")))
|
||||
defer cleanUp3()
|
||||
err = runAddCmd(cmd, []string{"keyname1"})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check JSON
|
||||
viper.Set(cli.OutputFlag, OutputFormatJSON)
|
||||
// Now enter password
|
||||
cleanUp4 := client.OverrideStdin(bufio.NewReader(strings.NewReader("test1234\ntest1234\n")))
|
||||
defer cleanUp4()
|
||||
err = runAddCmd(cmd, []string{"keyname2"})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
type MockResponseWriter struct {
|
||||
dataHeaderStatus int
|
||||
dataBody []byte
|
||||
}
|
||||
|
||||
func (MockResponseWriter) Header() http.Header {
|
||||
panic("Unexpected call!")
|
||||
}
|
||||
|
||||
func (w *MockResponseWriter) Write(data []byte) (int, error) {
|
||||
w.dataBody = append(w.dataBody, data...)
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (w *MockResponseWriter) WriteHeader(statusCode int) {
|
||||
w.dataHeaderStatus = statusCode
|
||||
}
|
||||
|
||||
func TestCheckAndWriteErrorResponse(t *testing.T) {
|
||||
mockRW := MockResponseWriter{}
|
||||
|
||||
mockRW.WriteHeader(100)
|
||||
assert.Equal(t, 100, mockRW.dataHeaderStatus)
|
||||
|
||||
detected := CheckAndWriteErrorResponse(&mockRW, http.StatusBadRequest, errors.New("some ERROR"))
|
||||
require.True(t, detected)
|
||||
require.Equal(t, http.StatusBadRequest, mockRW.dataHeaderStatus)
|
||||
require.Equal(t, "some ERROR", string(mockRW.dataBody[:]))
|
||||
|
||||
mockRW = MockResponseWriter{}
|
||||
detected = CheckAndWriteErrorResponse(&mockRW, http.StatusBadRequest, nil)
|
||||
require.False(t, detected)
|
||||
require.Equal(t, 0, mockRW.dataHeaderStatus)
|
||||
require.Equal(t, "", string(mockRW.dataBody[:]))
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type testCases struct {
|
||||
Keys []KeyOutput
|
||||
Answers []KeyOutput
|
||||
JSON [][]byte
|
||||
}
|
||||
|
||||
func getTestCases() testCases {
|
||||
return testCases{
|
||||
[]KeyOutput{
|
||||
{"A", "B", "C", "D", "E"},
|
||||
{"A", "B", "C", "D", ""},
|
||||
{"", "B", "C", "D", ""},
|
||||
{"", "", "", "", ""},
|
||||
},
|
||||
make([]KeyOutput, 4),
|
||||
[][]byte{
|
||||
[]byte(`{"name":"A","type":"B","address":"C","pub_key":"D","mnemonic":"E"}`),
|
||||
[]byte(`{"name":"A","type":"B","address":"C","pub_key":"D"}`),
|
||||
[]byte(`{"name":"","type":"B","address":"C","pub_key":"D"}`),
|
||||
[]byte(`{"name":"","type":"","address":"","pub_key":""}`),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalJSON(t *testing.T) {
|
||||
type args struct {
|
||||
o KeyOutput
|
||||
}
|
||||
|
||||
data := getTestCases()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []byte
|
||||
wantErr bool
|
||||
}{
|
||||
{"basic", args{data.Keys[0]}, []byte(data.JSON[0]), false},
|
||||
{"mnemonic is optional", args{data.Keys[1]}, []byte(data.JSON[1]), false},
|
||||
|
||||
// REVIEW: Are the next results expected??
|
||||
{"empty name", args{data.Keys[2]}, []byte(data.JSON[2]), false},
|
||||
{"empty object", args{data.Keys[3]}, []byte(data.JSON[3]), false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := MarshalJSON(tt.args.o)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("MarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%s\n", got)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("MarshalJSON() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalJSON(t *testing.T) {
|
||||
type args struct {
|
||||
bz []byte
|
||||
ptr interface{}
|
||||
}
|
||||
|
||||
data := getTestCases()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"basic", args{data.JSON[0], &data.Answers[0]}, false},
|
||||
{"mnemonic is optional", args{data.JSON[1], &data.Answers[1]}, false},
|
||||
|
||||
// REVIEW: Are the next results expected??
|
||||
{"empty name", args{data.JSON[2], &data.Answers[2]}, false},
|
||||
{"empty object", args{data.JSON[3], &data.Answers[3]}, false},
|
||||
}
|
||||
for idx, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := UnmarshalJSON(tt.args.bz, tt.args.ptr); (err != nil) != tt.wantErr {
|
||||
t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
// Confirm deserialized objects are the same
|
||||
require.Equal(t, data.Keys[idx], data.Answers[idx])
|
||||
})
|
||||
}
|
||||
}
|
||||
+16
-16
@@ -91,6 +91,17 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func confirmDeletion(buf *bufio.Reader) error {
|
||||
answer, err := client.GetConfirmation("Key reference will be deleted. Continue?", buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !answer {
|
||||
return errors.New("aborted")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// REST
|
||||
|
||||
@@ -110,42 +121,31 @@ func DeleteKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err := decoder.Decode(&m)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
kb, err = NewKeyBaseFromHomeFlag()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
err = kb.Delete(name, m.Password, false)
|
||||
if keyerror.IsErrKeyNotFound(err) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
} else if keyerror.IsErrWrongPassword(err) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
} else if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func confirmDeletion(buf *bufio.Reader) error {
|
||||
answer, err := client.GetConfirmation("Key reference will be deleted. Continue?", buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !answer {
|
||||
return errors.New("aborted")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
)
|
||||
|
||||
func Test_runDeleteCmd(t *testing.T) {
|
||||
deleteKeyCommand := deleteKeyCommand()
|
||||
|
||||
yesF, _ := deleteKeyCommand.Flags().GetBool(flagYes)
|
||||
forceF, _ := deleteKeyCommand.Flags().GetBool(flagForce)
|
||||
assert.False(t, yesF)
|
||||
assert.False(t, forceF)
|
||||
|
||||
fakeKeyName1 := "runDeleteCmd_Key1"
|
||||
fakeKeyName2 := "runDeleteCmd_Key2"
|
||||
|
||||
// Now add a temporary keybase
|
||||
kbHome, cleanUp, err := tests.GetTempDir("Test_runDeleteCmd")
|
||||
assert.NoError(t, err)
|
||||
defer cleanUp()
|
||||
viper.Set(cli.HomeFlag, kbHome)
|
||||
|
||||
// Now
|
||||
kb, err := NewKeyBaseFromHomeFlag()
|
||||
assert.NoError(t, err)
|
||||
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
|
||||
assert.NoError(t, err)
|
||||
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = runDeleteCmd(deleteKeyCommand, []string{"blah"})
|
||||
require.Error(t, err)
|
||||
require.Equal(t, "Key blah not found", err.Error())
|
||||
|
||||
// User confirmation missing
|
||||
err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1})
|
||||
require.Error(t, err)
|
||||
require.Equal(t, "EOF", err.Error())
|
||||
|
||||
{
|
||||
_, err = kb.Get(fakeKeyName1)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Now there is a confirmation
|
||||
cleanUp := client.OverrideStdin(bufio.NewReader(strings.NewReader("y\n")))
|
||||
defer cleanUp()
|
||||
err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = kb.Get(fakeKeyName1)
|
||||
require.Error(t, err) // Key1 is gone
|
||||
}
|
||||
|
||||
viper.Set(flagYes, true)
|
||||
_, err = kb.Get(fakeKeyName2)
|
||||
require.NoError(t, err)
|
||||
err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName2})
|
||||
require.NoError(t, err)
|
||||
_, err = kb.Get(fakeKeyName2)
|
||||
require.Error(t, err) // Key2 is gone
|
||||
|
||||
// TODO: Write another case for !keys.Local
|
||||
}
|
||||
|
||||
func Test_confirmDeletion(t *testing.T) {
|
||||
type args struct {
|
||||
buf *bufio.Reader
|
||||
}
|
||||
|
||||
answerYes := bufio.NewReader(strings.NewReader("y\n"))
|
||||
answerYes2 := bufio.NewReader(strings.NewReader("Y\n"))
|
||||
answerNo := bufio.NewReader(strings.NewReader("n\n"))
|
||||
answerInvalid := bufio.NewReader(strings.NewReader("245\n"))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"Y", args{answerYes}, false},
|
||||
{"y", args{answerYes2}, false},
|
||||
{"N", args{answerNo}, true},
|
||||
{"BAD", args{answerInvalid}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := confirmDeletion(tt.args.buf); (err != nil) != tt.wantErr {
|
||||
t.Errorf("confirmDeletion() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
+10
-11
@@ -6,15 +6,14 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// CMD
|
||||
|
||||
// listKeysCmd represents the list command
|
||||
var listKeysCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List all keys",
|
||||
Long: `Return a list of all public keys stored by this key manager
|
||||
func listKeysCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List all keys",
|
||||
Long: `Return a list of all public keys stored by this key manager
|
||||
along with their associated name and address.`,
|
||||
RunE: runListCmd,
|
||||
RunE: runListCmd,
|
||||
}
|
||||
}
|
||||
|
||||
func runListCmd(cmd *cobra.Command, args []string) error {
|
||||
@@ -39,13 +38,13 @@ func QueryKeysRequestHandler(indent bool) http.HandlerFunc {
|
||||
kb, err := NewKeyBaseFromHomeFlag()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
infos, err := kb.List()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
// an empty list will be JSONized as null, but we want to keep the empty list
|
||||
@@ -56,7 +55,7 @@ func QueryKeysRequestHandler(indent bool) http.HandlerFunc {
|
||||
keysOutput, err := Bech32KeysOutput(infos)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
PostProcessResponse(w, cdc, keysOutput, indent)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func Test_runListCmd(t *testing.T) {
|
||||
type args struct {
|
||||
cmd *cobra.Command
|
||||
args []string
|
||||
}
|
||||
|
||||
cmdBasic := listKeysCmd()
|
||||
|
||||
// Prepare some keybases
|
||||
kbHome1, cleanUp1, err := tests.GetTempDir("Test_runListCmd")
|
||||
defer cleanUp1()
|
||||
assert.NoError(t, err)
|
||||
// Do nothing, leave home1 empty
|
||||
|
||||
kbHome2, cleanUp2, err := tests.GetTempDir("Test_runListCmd")
|
||||
defer cleanUp2()
|
||||
viper.Set(cli.HomeFlag, kbHome2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
kb, err := NewKeyBaseFromHomeFlag()
|
||||
assert.NoError(t, err)
|
||||
_, err = kb.CreateAccount("something", tests.TestMnemonic, "", "", 0, 0)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testData := []struct {
|
||||
name string
|
||||
kbDir string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"invalid keybase", "/dev/null", args{cmdBasic, []string{}}, true},
|
||||
{"keybase: empty", kbHome1, args{cmdBasic, []string{}}, false},
|
||||
{"keybase: w/key", kbHome2, args{cmdBasic, []string{}}, false},
|
||||
}
|
||||
for _, tt := range testData {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
viper.Set(cli.HomeFlag, tt.kbDir)
|
||||
if err := runListCmd(tt.args.cmd, tt.args.args); (err != nil) != tt.wantErr {
|
||||
t.Errorf("runListCmd() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -43,9 +43,7 @@ func runMnemonicCmd(cmd *cobra.Command, args []string) error {
|
||||
if len(inputEntropy) < 43 {
|
||||
return fmt.Errorf("256-bits is 43 characters in Base-64, and 100 in Base-6. You entered %v, and probably want more", len(inputEntropy))
|
||||
}
|
||||
conf, err := client.GetConfirmation(
|
||||
fmt.Sprintf("> Input length: %d", len(inputEntropy)),
|
||||
buf)
|
||||
conf, err := client.GetConfirmation(fmt.Sprintf("> Input length: %d", len(inputEntropy)), buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_RunMnemonicCmdNormal(t *testing.T) {
|
||||
cmdBasic := mnemonicKeyCommand()
|
||||
err := runMnemonicCmd(cmdBasic, []string{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_RunMnemonicCmdUser(t *testing.T) {
|
||||
cmdUser := mnemonicKeyCommand()
|
||||
err := cmdUser.Flags().Set(flagUserEntropy, "1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = runMnemonicCmd(cmdUser, []string{})
|
||||
require.Error(t, err)
|
||||
require.Equal(t, "EOF", err.Error())
|
||||
|
||||
// Try again
|
||||
cleanUp := client.OverrideStdin(bufio.NewReader(strings.NewReader("Hi!\n")))
|
||||
defer cleanUp()
|
||||
err = runMnemonicCmd(cmdUser, []string{})
|
||||
require.Error(t, err)
|
||||
require.Equal(t,
|
||||
"256-bits is 43 characters in Base-64, and 100 in Base-6. You entered 3, and probably want more",
|
||||
err.Error())
|
||||
|
||||
// Now provide "good" entropy :)
|
||||
fakeEntropy := strings.Repeat(":)", 40) + "\ny\n" // entropy + accept count
|
||||
cleanUp2 := client.OverrideStdin(bufio.NewReader(strings.NewReader(fakeEntropy)))
|
||||
defer cleanUp2()
|
||||
err = runMnemonicCmd(cmdUser, []string{})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Now provide "good" entropy but no answer
|
||||
fakeEntropy = strings.Repeat(":)", 40) + "\n" // entropy + accept count
|
||||
cleanUp3 := client.OverrideStdin(bufio.NewReader(strings.NewReader(fakeEntropy)))
|
||||
defer cleanUp3()
|
||||
err = runMnemonicCmd(cmdUser, []string{})
|
||||
require.Error(t, err)
|
||||
|
||||
// Now provide "good" entropy but say no
|
||||
fakeEntropy = strings.Repeat(":)", 40) + "\nn\n" // entropy + accept count
|
||||
cleanUp4 := client.OverrideStdin(bufio.NewReader(strings.NewReader(fakeEntropy)))
|
||||
defer cleanUp4()
|
||||
err = runMnemonicCmd(cmdUser, []string{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
+1
-1
@@ -22,7 +22,7 @@ func Commands() *cobra.Command {
|
||||
cmd.AddCommand(
|
||||
mnemonicKeyCommand(),
|
||||
addKeyCommand(),
|
||||
listKeysCmd,
|
||||
listKeysCmd(),
|
||||
showKeysCmd(),
|
||||
client.LineBreak,
|
||||
deleteKeyCommand(),
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func TestCommands(t *testing.T) {
|
||||
rootCommands := Commands()
|
||||
assert.NotNil(t, rootCommands)
|
||||
|
||||
// Commands are registered
|
||||
assert.Equal(t, 7, len(rootCommands.Commands()))
|
||||
}
|
||||
|
||||
func TestRegisterRoutes(t *testing.T) {
|
||||
fakeRouter := mux.Router{}
|
||||
RegisterRoutes(&fakeRouter, false)
|
||||
}
|
||||
+10
-5
@@ -93,7 +93,12 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
|
||||
|
||||
isShowAddr := viper.GetBool(FlagAddress)
|
||||
isShowPubKey := viper.GetBool(FlagPublicKey)
|
||||
isOutputSet := cmd.Flag(cli.OutputFlag).Changed
|
||||
|
||||
isOutputSet := false
|
||||
tmp := cmd.Flag(cli.OutputFlag)
|
||||
if tmp != nil {
|
||||
isOutputSet = tmp.Changed
|
||||
}
|
||||
|
||||
if isShowAddr && isShowPubKey {
|
||||
return errors.New("cannot use both --address and --pubkey at once")
|
||||
@@ -161,25 +166,25 @@ func GetKeyRequestHandler(indent bool) http.HandlerFunc {
|
||||
bechKeyOut, err := getBechKeyOut(bechPrefix)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
info, err := GetKeyInfo(name)
|
||||
if keyerror.IsErrKeyNotFound(err) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
} else if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
keyOutput, err := bechKeyOut(info)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
)
|
||||
|
||||
func Test_multiSigKey_Properties(t *testing.T) {
|
||||
tmpKey1 := secp256k1.GenPrivKeySecp256k1([]byte("mySecret"))
|
||||
|
||||
tmp := multiSigKey{
|
||||
name: "myMultisig",
|
||||
key: tmpKey1.PubKey(),
|
||||
}
|
||||
|
||||
assert.Equal(t, "myMultisig", tmp.GetName())
|
||||
assert.Equal(t, keys.TypeLocal, tmp.GetType())
|
||||
assert.Equal(t, "015ABFFB09DB738A45745A91E8C401423ECE4016", tmp.GetPubKey().Address().String())
|
||||
assert.Equal(t, "cosmos1q9dtl7cfmdec53t5t2g733qpgglvusqk6xdntl", tmp.GetAddress().String())
|
||||
}
|
||||
|
||||
func Test_showKeysCmd(t *testing.T) {
|
||||
cmd := showKeysCmd()
|
||||
assert.NotNil(t, cmd)
|
||||
assert.Equal(t, "false", cmd.Flag(FlagAddress).DefValue)
|
||||
assert.Equal(t, "false", cmd.Flag(FlagPublicKey).DefValue)
|
||||
}
|
||||
|
||||
func Test_runShowCmd(t *testing.T) {
|
||||
cmd := showKeysCmd()
|
||||
|
||||
err := runShowCmd(cmd, []string{"invalid"})
|
||||
assert.EqualError(t, err, "Key invalid not found")
|
||||
|
||||
err = runShowCmd(cmd, []string{"invalid1", "invalid2"})
|
||||
assert.EqualError(t, err, "Key invalid1 not found")
|
||||
|
||||
// Prepare a key base
|
||||
// Now add a temporary keybase
|
||||
kbHome, cleanUp, err := tests.GetTempDir("Test_runShowCmd")
|
||||
assert.NoError(t, err)
|
||||
defer cleanUp()
|
||||
viper.Set(cli.HomeFlag, kbHome)
|
||||
|
||||
fakeKeyName1 := "runShowCmd_Key1"
|
||||
fakeKeyName2 := "runShowCmd_Key2"
|
||||
kb, err := NewKeyBaseFromHomeFlag()
|
||||
assert.NoError(t, err)
|
||||
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
|
||||
assert.NoError(t, err)
|
||||
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Now try single key
|
||||
err = runShowCmd(cmd, []string{fakeKeyName1})
|
||||
assert.EqualError(t, err, "invalid Bech32 prefix encoding provided: ")
|
||||
|
||||
// Now try single key - set bech to acc
|
||||
viper.Set(FlagBechPrefix, "acc")
|
||||
err = runShowCmd(cmd, []string{fakeKeyName1})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Now try multisig key - set bech to acc
|
||||
viper.Set(FlagBechPrefix, "acc")
|
||||
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
|
||||
assert.EqualError(t, err, "threshold must be a positive integer")
|
||||
|
||||
// Now try multisig key - set bech to acc + threshold=2
|
||||
viper.Set(FlagBechPrefix, "acc")
|
||||
viper.Set(flagMultiSigThreshold, 2)
|
||||
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// TODO: Capture stdout and compare
|
||||
}
|
||||
|
||||
func Test_validateMultisigThreshold(t *testing.T) {
|
||||
type args struct {
|
||||
k int
|
||||
nKeys int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"zeros", args{0, 0}, true},
|
||||
{"1-0", args{1, 0}, true},
|
||||
{"1-1", args{1, 1}, false},
|
||||
{"1-2", args{1, 1}, false},
|
||||
{"1-2", args{2, 1}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := validateMultisigThreshold(tt.args.k, tt.args.nKeys); (err != nil) != tt.wantErr {
|
||||
t.Errorf("validateMultisigThreshold() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getBechKeyOut(t *testing.T) {
|
||||
type args struct {
|
||||
bechPrefix string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bechKeyOutFn
|
||||
wantErr bool
|
||||
}{
|
||||
{"empty", args{""}, nil, true},
|
||||
{"wrong", args{"???"}, nil, true},
|
||||
{"acc", args{"acc"}, Bech32KeyOutput, false},
|
||||
{"val", args{"val"}, Bech32ValKeyOutput, false},
|
||||
{"cons", args{"cons"}, Bech32ConsKeyOutput, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := getBechKeyOut(tt.args.bechPrefix)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("getBechKeyOut() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !tt.wantErr {
|
||||
assert.NotNil(t, got)
|
||||
}
|
||||
|
||||
// TODO: Still not possible to compare functions
|
||||
// Maybe in next release: https://github.com/stretchr/testify/issues/182
|
||||
//if &got != &tt.want {
|
||||
// t.Errorf("getBechKeyOut() = %v, want %v", got, tt.want)
|
||||
//}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
keys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -73,14 +73,14 @@ func UpdateKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err := decoder.Decode(&m)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
kb, err = NewKeyBaseFromHomeFlag()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -89,15 +89,15 @@ func UpdateKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err = kb.Update(name, m.OldPassword, getNewpass)
|
||||
if keyerror.IsErrKeyNotFound(err) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
} else if keyerror.IsErrWrongPassword(err) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
} else if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_updateKeyCommand(t *testing.T) {
|
||||
cmd := updateKeyCommand()
|
||||
assert.NotNil(t, cmd)
|
||||
// No flags or defaults to validate
|
||||
}
|
||||
|
||||
func Test_runUpdateCmd(t *testing.T) {
|
||||
fakeKeyName1 := "runUpdateCmd_Key1"
|
||||
fakeKeyName2 := "runUpdateCmd_Key2"
|
||||
|
||||
cmd := updateKeyCommand()
|
||||
|
||||
// fails because it requests a password
|
||||
err := runUpdateCmd(cmd, []string{fakeKeyName1})
|
||||
assert.EqualError(t, err, "EOF")
|
||||
|
||||
cleanUp := client.OverrideStdin(bufio.NewReader(strings.NewReader("pass1234\n")))
|
||||
defer cleanUp()
|
||||
|
||||
// try again
|
||||
err = runUpdateCmd(cmd, []string{fakeKeyName1})
|
||||
assert.EqualError(t, err, "Key runUpdateCmd_Key1 not found")
|
||||
|
||||
// Prepare a key base
|
||||
// Now add a temporary keybase
|
||||
kbHome, cleanUp1, err := tests.GetTempDir("Test_runShowCmd")
|
||||
assert.NoError(t, err)
|
||||
defer cleanUp1()
|
||||
viper.Set(cli.HomeFlag, kbHome)
|
||||
|
||||
kb, err := NewKeyBaseFromHomeFlag()
|
||||
assert.NoError(t, err)
|
||||
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
|
||||
assert.NoError(t, err)
|
||||
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try again now that we have keys
|
||||
cleanUp2 := client.OverrideStdin(bufio.NewReader(strings.NewReader("pass1234\nNew1234\nNew1234")))
|
||||
defer cleanUp2()
|
||||
|
||||
// Incorrect key type
|
||||
err = runUpdateCmd(cmd, []string{fakeKeyName1})
|
||||
assert.EqualError(t, err, "locally stored key required. Received: keys.offlineInfo")
|
||||
|
||||
// TODO: Check for other type types?
|
||||
|
||||
}
|
||||
+10
-6
@@ -15,7 +15,11 @@ import (
|
||||
)
|
||||
|
||||
// KeyDBName is the directory under root where we store the keys
|
||||
const KeyDBName = "keys"
|
||||
const (
|
||||
KeyDBName = "keys"
|
||||
OutputFormatText = "text"
|
||||
OutputFormatJSON = "json"
|
||||
)
|
||||
|
||||
type bechKeyOutFn func(keyInfo keys.Info) (KeyOutput, error)
|
||||
|
||||
@@ -157,7 +161,7 @@ func printKeyInfo(keyInfo keys.Info, bechKeyOut bechKeyOutFn) {
|
||||
}
|
||||
|
||||
switch viper.Get(cli.OutputFlag) {
|
||||
case "text":
|
||||
case OutputFormatText:
|
||||
fmt.Printf("NAME:\tTYPE:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n")
|
||||
printKeyOutput(ko)
|
||||
case "json":
|
||||
@@ -176,12 +180,12 @@ func printInfos(infos []keys.Info) {
|
||||
panic(err)
|
||||
}
|
||||
switch viper.Get(cli.OutputFlag) {
|
||||
case "text":
|
||||
case OutputFormatText:
|
||||
fmt.Printf("NAME:\tTYPE:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n")
|
||||
for _, ko := range kos {
|
||||
printKeyOutput(ko)
|
||||
}
|
||||
case "json":
|
||||
case OutputFormatJSON:
|
||||
out, err := MarshalJSON(kos)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -225,12 +229,12 @@ func PostProcessResponse(w http.ResponseWriter, cdc *codec.Codec, response inter
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
case []byte:
|
||||
output = response.([]byte)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(output)
|
||||
_, _ = w.Write(output)
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ func TestVersion(t *testing.T) {
|
||||
reg, err := regexp.Compile(`\d+\.\d+\.\d+.*`)
|
||||
require.Nil(t, err)
|
||||
match := reg.MatchString(body)
|
||||
require.True(t, match, body, fmt.Sprintf("%s", body))
|
||||
require.True(t, match, body, body)
|
||||
|
||||
// node info
|
||||
res, body = Request(t, port, "GET", "/node_version", nil)
|
||||
|
||||
Reference in New Issue
Block a user