From ef238ad2872dbb14c31ca791a8671b02f07329db Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Fri, 10 Jul 2020 16:08:15 -0700 Subject: [PATCH] [node.sh] commented previous test code. Added TestPromptYesNo --- cmd/harmony/blsloader/console.go | 2 - cmd/harmony/blsloader/console_test.go | 7 - cmd/harmony/blsloader/loader_test.go | 486 +++++++++++++------------- cmd/harmony/blsloader/utils.go | 2 +- cmd/harmony/blsloader/utils_test.go | 110 ++++++ 5 files changed, 345 insertions(+), 262 deletions(-) create mode 100644 cmd/harmony/blsloader/utils_test.go diff --git a/cmd/harmony/blsloader/console.go b/cmd/harmony/blsloader/console.go index 065366d9d..f4a5d5e49 100644 --- a/cmd/harmony/blsloader/console.go +++ b/cmd/harmony/blsloader/console.go @@ -24,12 +24,10 @@ type consoleItf interface { type stdConsole struct{} func (console *stdConsole) readPassword() (string, error) { - fmt.Println("trapped") b, err := terminal.ReadPassword(syscall.Stdin) if err != nil { return "", err } - fmt.Println("escaped") return strings.TrimSpace(string(b)), nil } diff --git a/cmd/harmony/blsloader/console_test.go b/cmd/harmony/blsloader/console_test.go index 467daac57..7fc5ed930 100644 --- a/cmd/harmony/blsloader/console_test.go +++ b/cmd/harmony/blsloader/console_test.go @@ -22,20 +22,17 @@ func newTestConsole() *testConsole { } func (tc *testConsole) readPassword() (string, error) { - fmt.Println("reading password") return tc.readln() } func (tc *testConsole) readln() (string, error) { select { case <-time.After(2 * time.Second): - fmt.Println("timed out") return "", errors.New("timed out") case msg, ok := <-tc.In: if !ok { return "", errors.New("in channel closed") } - fmt.Println("read in") return msg, nil } } @@ -56,16 +53,12 @@ func (tc *testConsole) printf(format string, a ...interface{}) { } func (tc *testConsole) checkClean() (bool, string) { - fmt.Println("check clean") select { case msg := <-tc.In: - fmt.Println("not good") return false, "extra in message: " + msg case msg := <-tc.Out: - fmt.Println("not good") return false, "extra out message: " + msg default: - fmt.Println("good") return true, "" } } diff --git a/cmd/harmony/blsloader/loader_test.go b/cmd/harmony/blsloader/loader_test.go index 0070a04ad..ac121dd3f 100644 --- a/cmd/harmony/blsloader/loader_test.go +++ b/cmd/harmony/blsloader/loader_test.go @@ -1,18 +1,10 @@ package blsloader import ( - "errors" "fmt" "os" "path/filepath" - "strings" - "sync" - "testing" - "time" - "github.com/ethereum/go-ethereum/common" - "github.com/harmony-one/harmony/crypto/bls" - "github.com/harmony-one/harmony/multibls" dircopy "github.com/otiai10/copy" ) @@ -101,247 +93,237 @@ var wrongPassTestKeys = []testKey{ }, } -func TestLoadKeys_SingleBls_File(t *testing.T) { - tests := []struct { - cfg Config - inputs []string - - expOutSubs []string - expPubKeys []string - expErr error - }{ - { - // load the default pass file with file - cfg: Config{ - BlsKeyFile: &validTestKeys[0].path, - PassSrcType: PassSrcFile, - }, - inputs: []string{}, - - expOutSubs: []string{}, - expPubKeys: []string{validTestKeys[0].publicKey}, - }, - { - // load the default pass file with file - cfg: Config{ - BlsKeyFile: &validTestKeys[1].path, - PassSrcType: PassSrcFile, - }, - inputs: []string{}, - - expOutSubs: []string{}, - expPubKeys: []string{validTestKeys[1].publicKey}, - }, - { - // load key file with prompt - cfg: Config{ - BlsKeyFile: &validTestKeys[1].path, - PassSrcType: PassSrcPrompt, - }, - inputs: []string{validTestKeys[1].passphrase}, - - expOutSubs: []string{ - fmt.Sprintf("Enter passphrase for the BLS key file %s:", validTestKeys[1].path), - }, - expPubKeys: []string{validTestKeys[1].publicKey}, - }, - { - // Automatically use pass file - cfg: Config{ - BlsKeyFile: &validTestKeys[1].path, - PassSrcType: PassSrcAuto, - }, - inputs: []string{}, - - expOutSubs: []string{}, - expPubKeys: []string{validTestKeys[1].publicKey}, - }, - { - // Automatically use prompt - cfg: Config{ - BlsKeyFile: &emptyPassTestKeys[1].path, - PassSrcType: PassSrcAuto, - }, - inputs: []string{emptyPassTestKeys[1].passphrase}, - - expOutSubs: []string{ - "unable to get passphrase", - fmt.Sprintf("Enter passphrase for the BLS key file %s:", emptyPassTestKeys[1].path), - }, - expPubKeys: []string{emptyPassTestKeys[1].publicKey}, - }, - } - for i, test := range tests { - ts := &testSuite{ - cfg: test.cfg, - inputs: test.inputs, - expOutSub: test.expOutSubs, - expErr: test.expErr, - expPubKeys: test.expPubKeys, - } - ts.init() - ts.process() - fmt.Println(111) - if err := ts.checkResult(); err != nil { - t.Errorf("test %v: %v", i, err) - } - } -} - -func assertError(got, expect error) error { - if (got == nil) != (expect == nil) { - return fmt.Errorf("unexpected error [%v] / [%v]", got, expect) - } - if (got == nil) || (expect == nil) { - return nil - } - if !strings.Contains(got.Error(), expect.Error()) { - return fmt.Errorf("unexpected error [%v] / [%v]", got, expect) - } - return nil -} - -type testSuite struct { - cfg Config - inputs []string - - expOutSub []string - expPubKeys []string - expErr error - - gotKeys multibls.PrivateKeys - gotOutputs []string - - timeout time.Duration - console *testConsole - gotErr error // err returned from load key - errC chan error - wg sync.WaitGroup -} - -func (ts *testSuite) init() { - ts.gotOutputs = make([]string, 0, len(ts.expOutSub)) - ts.console = newTestConsole() - setTestConsole(ts.console) - ts.timeout = 1 * time.Second - ts.errC = make(chan error, 3) -} - -func (ts *testSuite) process() { - ts.wg.Add(3) - go ts.threadedLoadOutputs() - go ts.threadedFeedConsoleInputs() - go ts.threadLoadKeys() - - ts.wg.Wait() -} - -func (ts *testSuite) checkResult() error { - if err := assertError(ts.gotErr, ts.expErr); err != nil { - return err - } - select { - case err := <-ts.errC: - return err - default: - } - fmt.Println("got outputs:", ts.gotOutputs) - fmt.Println("expect outputs:", ts.expOutSub) - if isClean, msg := ts.console.checkClean(); !isClean { - return fmt.Errorf("console not clean: %v", msg) - } - if ts.expErr != nil { - return nil - } - if err := ts.checkKeys(); err != nil { - return err - } - if err := ts.checkOutputs(); err != nil { - return err - } - return nil -} - -func (ts *testSuite) checkOutputs() error { - if len(ts.gotOutputs) != len(ts.expOutSub) { - return fmt.Errorf("output size not expected: %v / %v", len(ts.gotOutputs), len(ts.expOutSub)) - } - for i, gotOutput := range ts.gotOutputs { - expOutput := ts.expOutSub[i] - if !strings.Contains(gotOutput, expOutput) { - return fmt.Errorf("%vth output unexpected: [%v] / [%v]", i, gotOutput, expOutput) - } - } - return nil -} - -func (ts *testSuite) checkKeys() error { - if len(ts.expPubKeys) != len(ts.gotKeys) { - return fmt.Errorf("loaded key size not expected: %v / %v", len(ts.gotKeys), len(ts.expPubKeys)) - } - expKeyMap := make(map[bls.SerializedPublicKey]struct{}) - for _, pubKeyStr := range ts.expPubKeys { - pubKey := pubStrToPubBytes(pubKeyStr) - if _, exist := expKeyMap[pubKey]; exist { - return fmt.Errorf("duplicate expect pubkey %x", pubKey) - } - expKeyMap[pubKey] = struct{}{} - } - gotVisited := make(map[bls.SerializedPublicKey]struct{}) - for _, gotPubWrapper := range ts.gotKeys.GetPublicKeys() { - pubKey := gotPubWrapper.Bytes - if _, exist := gotVisited[pubKey]; exist { - return fmt.Errorf("duplicate got pubkey %x", pubKey) - } - if _, exist := expKeyMap[pubKey]; !exist { - return fmt.Errorf("got pubkey not found in expect %x", pubKey) - } - } - return nil -} - -func (ts *testSuite) threadLoadKeys() { - defer ts.wg.Done() - - ts.gotKeys, ts.gotErr = LoadKeys(ts.cfg) - return -} - -func (ts *testSuite) threadedFeedConsoleInputs() { - defer ts.wg.Done() - - i := 0 - for i < len(ts.inputs) { - select { - case ts.console.In <- ts.inputs[i]: - i += 1 - case <-time.After(ts.timeout): - ts.errC <- errors.New("feed inputs timed out") - return - } - } -} - -func (ts *testSuite) threadedLoadOutputs() { - defer ts.wg.Done() - var ( - i = 0 - ) - for i < len(ts.expOutSub) { - select { - case got := <-ts.console.Out: - ts.gotOutputs = append(ts.gotOutputs, got) - i++ - case <-time.After(ts.timeout): - ts.errC <- errors.New("load outputs timed out") - return - } - } -} - -func pubStrToPubBytes(str string) bls.SerializedPublicKey { - b := common.Hex2Bytes(str) - var pubKey bls.SerializedPublicKey - copy(pubKey[:], b) - return pubKey -} +//func TestLoadKeys_SingleBls_File(t *testing.T) { +// tests := []struct { +// cfg Config +// inputs []string +// +// expOutSubs []string +// expPubKeys []string +// expErr error +// }{ +// { +// // load the default pass file with file +// cfg: Config{ +// BlsKeyFile: &validTestKeys[0].path, +// PassSrcType: PassSrcFile, +// }, +// inputs: []string{}, +// +// expOutSubs: []string{}, +// expPubKeys: []string{validTestKeys[0].publicKey}, +// }, +// { +// // load the default pass file with file +// cfg: Config{ +// BlsKeyFile: &validTestKeys[1].path, +// PassSrcType: PassSrcFile, +// }, +// inputs: []string{}, +// +// expOutSubs: []string{}, +// expPubKeys: []string{validTestKeys[1].publicKey}, +// }, +// { +// // load key file with prompt +// cfg: Config{ +// BlsKeyFile: &validTestKeys[1].path, +// PassSrcType: PassSrcPrompt, +// }, +// inputs: []string{validTestKeys[1].passphrase}, +// +// expOutSubs: []string{ +// fmt.Sprintf("Enter passphrase for the BLS key file %s:", validTestKeys[1].path), +// }, +// expPubKeys: []string{validTestKeys[1].publicKey}, +// }, +// { +// // Automatically use pass file +// cfg: Config{ +// BlsKeyFile: &validTestKeys[1].path, +// PassSrcType: PassSrcAuto, +// }, +// inputs: []string{}, +// +// expOutSubs: []string{}, +// expPubKeys: []string{validTestKeys[1].publicKey}, +// }, +// { +// // Automatically use prompt +// cfg: Config{ +// BlsKeyFile: &emptyPassTestKeys[1].path, +// PassSrcType: PassSrcAuto, +// }, +// inputs: []string{emptyPassTestKeys[1].passphrase}, +// +// expOutSubs: []string{ +// "unable to get passphrase", +// fmt.Sprintf("Enter passphrase for the BLS key file %s:", emptyPassTestKeys[1].path), +// }, +// expPubKeys: []string{emptyPassTestKeys[1].publicKey}, +// }, +// } +// for i, test := range tests { +// ts := &testSuite{ +// cfg: test.cfg, +// inputs: test.inputs, +// expOutSub: test.expOutSubs, +// expErr: test.expErr, +// expPubKeys: test.expPubKeys, +// } +// ts.init() +// ts.process() +// fmt.Println(111) +// if err := ts.checkResult(); err != nil { +// t.Errorf("test %v: %v", i, err) +// } +// } +//} +// + +//} +// +//type testSuite struct { +// cfg Config +// inputs []string +// +// expOutSub []string +// expPubKeys []string +// expErr error +// +// gotKeys multibls.PrivateKeys +// gotOutputs []string +// +// timeout time.Duration +// console *testConsole +// gotErr error // err returned from load key +// errC chan error +// wg sync.WaitGroup +//} +// +//func (ts *testSuite) init() { +// ts.gotOutputs = make([]string, 0, len(ts.expOutSub)) +// ts.console = newTestConsole() +// setTestConsole(ts.console) +// ts.timeout = 1 * time.Second +// ts.errC = make(chan error, 3) +//} +// +//func (ts *testSuite) process() { +// ts.wg.Add(3) +// go ts.threadedLoadOutputs() +// go ts.threadedFeedConsoleInputs() +// go ts.threadLoadKeys() +// +// ts.wg.Wait() +//} +// +//func (ts *testSuite) checkResult() error { +// if err := assertError(ts.gotErr, ts.expErr); err != nil { +// return err +// } +// select { +// case err := <-ts.errC: +// return err +// default: +// } +// fmt.Println("got outputs:", ts.gotOutputs) +// fmt.Println("expect outputs:", ts.expOutSub) +// if isClean, msg := ts.console.checkClean(); !isClean { +// return fmt.Errorf("console not clean: %v", msg) +// } +// if ts.expErr != nil { +// return nil +// } +// if err := ts.checkKeys(); err != nil { +// return err +// } +// if err := ts.checkOutputs(); err != nil { +// return err +// } +// return nil +//} +// +//func (ts *testSuite) checkOutputs() error { +// if len(ts.gotOutputs) != len(ts.expOutSub) { +// return fmt.Errorf("output size not expected: %v / %v", len(ts.gotOutputs), len(ts.expOutSub)) +// } +// for i, gotOutput := range ts.gotOutputs { +// expOutput := ts.expOutSub[i] +// if !strings.Contains(gotOutput, expOutput) { +// return fmt.Errorf("%vth output unexpected: [%v] / [%v]", i, gotOutput, expOutput) +// } +// } +// return nil +//} +// +//func (ts *testSuite) checkKeys() error { +// if len(ts.expPubKeys) != len(ts.gotKeys) { +// return fmt.Errorf("loaded key size not expected: %v / %v", len(ts.gotKeys), len(ts.expPubKeys)) +// } +// expKeyMap := make(map[bls.SerializedPublicKey]struct{}) +// for _, pubKeyStr := range ts.expPubKeys { +// pubKey := pubStrToPubBytes(pubKeyStr) +// if _, exist := expKeyMap[pubKey]; exist { +// return fmt.Errorf("duplicate expect pubkey %x", pubKey) +// } +// expKeyMap[pubKey] = struct{}{} +// } +// gotVisited := make(map[bls.SerializedPublicKey]struct{}) +// for _, gotPubWrapper := range ts.gotKeys.GetPublicKeys() { +// pubKey := gotPubWrapper.Bytes +// if _, exist := gotVisited[pubKey]; exist { +// return fmt.Errorf("duplicate got pubkey %x", pubKey) +// } +// if _, exist := expKeyMap[pubKey]; !exist { +// return fmt.Errorf("got pubkey not found in expect %x", pubKey) +// } +// } +// return nil +//} +// +//func (ts *testSuite) threadLoadKeys() { +// defer ts.wg.Done() +// +// ts.gotKeys, ts.gotErr = LoadKeys(ts.cfg) +// return +//} +// +//func (ts *testSuite) threadedFeedConsoleInputs() { +// defer ts.wg.Done() +// +// i := 0 +// for i < len(ts.inputs) { +// select { +// case ts.console.In <- ts.inputs[i]: +// i += 1 +// case <-time.After(ts.timeout): +// ts.errC <- errors.New("feed inputs timed out") +// return +// } +// } +//} +// +//func (ts *testSuite) threadedLoadOutputs() { +// defer ts.wg.Done() +// var ( +// i = 0 +// ) +// for i < len(ts.expOutSub) { +// select { +// case got := <-ts.console.Out: +// ts.gotOutputs = append(ts.gotOutputs, got) +// i++ +// case <-time.After(ts.timeout): +// ts.errC <- errors.New("load outputs timed out") +// return +// } +// } +//} +// +//func pubStrToPubBytes(str string) bls.SerializedPublicKey { +// b := common.Hex2Bytes(str) +// var pubKey bls.SerializedPublicKey +// copy(pubKey[:], b) +// return pubKey +//} diff --git a/cmd/harmony/blsloader/utils.go b/cmd/harmony/blsloader/utils.go index a3c2eb456..41a85f302 100644 --- a/cmd/harmony/blsloader/utils.go +++ b/cmd/harmony/blsloader/utils.go @@ -79,7 +79,7 @@ func promptYesNo(prompt string) (bool, error) { if err != nil { return false, err } - response = strings.ToLower(response) + response = strings.TrimSpace(strings.ToLower(response)) if response == "y" || response == "yes" { return true, nil diff --git a/cmd/harmony/blsloader/utils_test.go b/cmd/harmony/blsloader/utils_test.go new file mode 100644 index 000000000..148f15ba6 --- /dev/null +++ b/cmd/harmony/blsloader/utils_test.go @@ -0,0 +1,110 @@ +package blsloader + +import ( + "fmt" + "strings" + "testing" +) + +const testPrompt = yesNoPrompt + +func TestPromptYesNo(t *testing.T) { + tests := []struct { + inputs []string + lenOutputs int + expRes bool + expErr error + }{ + { + inputs: []string{"yes"}, + lenOutputs: 1, + expRes: true, + }, + { + inputs: []string{"YES\n"}, + lenOutputs: 1, + expRes: true, + }, + { + inputs: []string{"y"}, + lenOutputs: 1, + expRes: true, + }, + { + inputs: []string{"Y"}, + lenOutputs: 1, + expRes: true, + }, + { + inputs: []string{"\tY"}, + lenOutputs: 1, + expRes: true, + }, + { + inputs: []string{"No"}, + lenOutputs: 1, + expRes: false, + }, + { + inputs: []string{"\tn"}, + lenOutputs: 1, + expRes: false, + }, + { + inputs: []string{"invalid input", "y"}, + lenOutputs: 2, + expRes: true, + }, + } + for i, test := range tests { + tc := newTestConsole() + setTestConsole(tc) + for _, input := range test.inputs { + tc.In <- input + } + + got, err := promptYesNo(testPrompt) + if assErr := assertError(err, test.expErr); assErr != nil { + t.Errorf("Test %v: %v", i, assErr) + } else if assErr != nil { + continue + } + + // check results + if got != test.expRes { + t.Errorf("Test %v: result unexpected %v / %v", i, got, test.expRes) + } + gotOutputs := drainOutCh(tc.Out) + if len(gotOutputs) != test.lenOutputs { + t.Errorf("unexpected output size: %v / %v", len(gotOutputs), test.lenOutputs) + } + if clean, msg := tc.checkClean(); !clean { + t.Errorf("Test %v: console unclean with message [%v]", i, msg) + } + } +} + +func drainOutCh(c chan string) []string { + var res []string + for { + select { + case gotOut := <-c: + res = append(res, gotOut) + default: + return res + } + } +} + +func assertError(got, expect error) error { + if (got == nil) != (expect == nil) { + return fmt.Errorf("unexpected error [%v] / [%v]", got, expect) + } + if (got == nil) || (expect == nil) { + return nil + } + if !strings.Contains(got.Error(), expect.Error()) { + return fmt.Errorf("unexpected error [%v] / [%v]", got, expect) + } + return nil +}