Add tests to minikube shell

Refactor shell.go to use nested structure for shell - prefix/suffix mapping
pull/8314/head
Marcin Niemira 2020-05-30 01:28:59 +10:00
parent 27806c5c64
commit 49c3a73563
No known key found for this signature in database
GPG Key ID: 053E25BDC33ED6A3
2 changed files with 169 additions and 85 deletions

View File

@ -28,48 +28,50 @@ import (
"github.com/docker/machine/libmachine/shell"
)
const (
fishSetPfx = "set -gx "
fishSetSfx = "\";\n" // semi-colon required for fish 2.7
fishSetDelim = " \""
fishUnsetPfx = "set -e "
fishUnsetSfx = ";\n"
psSetPfx = "$Env:"
psSetSfx = "\"\n"
psSetDelim = " = \""
psUnsetPfx = `Remove-Item Env:\\`
psUnsetSfx = "\n"
cmdSetPfx = "SET "
cmdSetSfx = "\n"
cmdSetDelim = "="
cmdUnsetPfx = "SET "
cmdUnsetSfx = "\n"
cmdUnsetDelim = "="
emacsSetPfx = "(setenv \""
emacsSetSfx = "\")\n"
emacsSetDelim = "\" \""
emacsUnsetPfx = "(setenv \""
emacsUnsetSfx = ")\n"
emacsUnsetDelim = "\" nil"
bashSetPfx = "export "
bashSetSfx = "\"\n"
bashSetDelim = "=\""
bashUnsetPfx = "unset "
bashUnsetSfx = "\n"
nonePfx = ""
noneSfx = "\n"
noneDelim = "="
)
var shellConfigMap = map[string]map[string]string{
"fish": {
"Prefix": "set -gx ",
"Suffix": "\";\n", // semi-colon required for fish 2.7
"Delimiter": " \"",
"UnsetPrefix": "set -e ",
"UnsetSuffix": ";\n",
},
"powershell": {
"Prefix": "$Env:",
"Suffix": "\"\n",
"Delimiter": " = \"",
"UnsetPrefix": `Remove-Item Env:\\`,
"UnsetSuffix": "\n",
},
"cmd": {
"Prefix": "SET ",
"Suffix": "\n",
"Delimiter": "=",
"UnsetPrefix": "SET ",
"UnsetSuffix": "\n",
"setDelim": "=",
},
"emacs": {
"Prefix": "(setenv \"",
"Suffix": "\")\n",
"Delimiter": "\" \"",
"UnsetPrefix": "(setenv \"",
"UnsetSuffix": ")\n",
"UnsetDelim": "\" nil",
},
"bash": {
"Prefix": "export ",
"Suffix": "\"\n",
"Delimiter": "=\"",
"UnsetPrefix": "unset ",
"UnsetSuffix": "\n",
},
"none": {
"Prefix": "",
"Suffix": "\n",
"Delimiter": "=",
},
}
// Config represents the shell config
type Config struct {
@ -119,37 +121,18 @@ REM @FOR /f "tokens=*" %%i IN ('%s') DO @%%i
// CfgSet generates context variables for shell
func CfgSet(ec EnvConfig, plz, cmd string) *Config {
s := &Config{
UsageHint: generateUsageHint(ec.Shell, plz, cmd),
shellKey, s := ec.Shell, &Config{}
if _, ok := shellConfigMap[shellKey]; !ok {
shellKey = "bash"
}
shellParams := shellConfigMap[shellKey]
s.Suffix, s.Prefix, s.Delimiter = shellParams["Suffix"], shellParams["Prefix"], shellParams["Delimiter"]
if shellKey != "none" {
s.UsageHint = generateUsageHint(ec.Shell, plz, cmd)
}
switch ec.Shell {
case "fish":
s.Prefix = fishSetPfx
s.Suffix = fishSetSfx
s.Delimiter = fishSetDelim
case "powershell":
s.Prefix = psSetPfx
s.Suffix = psSetSfx
s.Delimiter = psSetDelim
case "cmd":
s.Prefix = cmdSetPfx
s.Suffix = cmdSetSfx
s.Delimiter = cmdSetDelim
case "emacs":
s.Prefix = emacsSetPfx
s.Suffix = emacsSetSfx
s.Delimiter = emacsSetDelim
case "none":
s.Prefix = nonePfx
s.Suffix = noneSfx
s.Delimiter = noneDelim
s.UsageHint = ""
default:
s.Prefix = bashSetPfx
s.Suffix = bashSetSfx
s.Delimiter = bashSetDelim
}
return s
}
@ -167,25 +150,17 @@ func SetScript(ec EnvConfig, w io.Writer, envTmpl string, data interface{}) erro
// UnsetScript writes out a shell-compatible unset script
func UnsetScript(ec EnvConfig, w io.Writer, vars []string) error {
var sb strings.Builder
shCfg := shellConfigMap[ec.Shell]
pfx, sfx, delim := shCfg["Prefix"], shCfg["Suffix"], shCfg["Delimiter"]
switch ec.Shell {
case "fish":
case "cmd", "emacs", "fish":
for _, v := range vars {
sb.WriteString(fmt.Sprintf("%s%s%s", fishUnsetPfx, v, fishUnsetSfx))
sb.WriteString(fmt.Sprintf("%s%s%s%s", pfx, v, delim, sfx))
}
case "powershell":
sb.WriteString(fmt.Sprintf("%s%s%s", psUnsetPfx, strings.Join(vars, " Env:\\\\"), psUnsetSfx))
case "cmd":
for _, v := range vars {
sb.WriteString(fmt.Sprintf("%s%s%s%s", cmdUnsetPfx, v, cmdUnsetDelim, cmdUnsetSfx))
}
case "emacs":
for _, v := range vars {
sb.WriteString(fmt.Sprintf("%s%s%s%s", emacsUnsetPfx, v, emacsUnsetDelim, emacsUnsetSfx))
}
case "none":
sb.WriteString(fmt.Sprintf("%s%s%s", nonePfx, strings.Join(vars, " "), noneSfx))
sb.WriteString(fmt.Sprintf("%s%s%s", pfx, strings.Join(vars, " Env:\\\\"), sfx))
default:
sb.WriteString(fmt.Sprintf("%s%s%s", bashUnsetPfx, strings.Join(vars, " "), bashUnsetSfx))
sb.WriteString(fmt.Sprintf("%s%s%s", pfx, strings.Join(vars, " "), sfx))
}
_, err := w.Write([]byte(sb.String()))
return err

View File

@ -0,0 +1,109 @@
/*
Copyright 2020 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package shell
import (
"bytes"
"strings"
"testing"
)
func TestGenerateUsageHint(t *testing.T) {
var testCases = []struct {
shellType, hintContains string
}{
{"", "eval"},
{"powershell", "Invoke-Expression"},
{"bash", "eval"},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.shellType, func(t *testing.T) {
hint := generateUsageHint(tc.shellType, "foo", "bar")
if !strings.Contains(hint, tc.hintContains) {
t.Errorf("Hint doesn't contain expected string. Expected to find '%v' in '%v'", tc.hintContains, hint)
}
})
}
}
func TestCfgSet(t *testing.T) {
var testCases = []struct {
plz, cmd string
ec EnvConfig
suffixContains string
}{
{"", "eval", EnvConfig{"bash"}, "\n"},
{"", "eval", EnvConfig{""}, "\n"},
{"", "eval", EnvConfig{"fish"}, "\n"},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.ec.Shell, func(t *testing.T) {
conf := CfgSet(tc.ec, tc.plz, tc.cmd)
if !strings.Contains(conf.Suffix, tc.suffixContains) {
t.Errorf("Suffix doesn't contain expected string. Expected to find '%v' in '%v'", tc.suffixContains, conf.Suffix)
}
})
}
}
func TestUnsetScript(t *testing.T) {
var testCases = []struct {
vars []string
ec EnvConfig
expected string
}{
{[]string{"foo"}, EnvConfig{"bash"}, `export foo"`},
{[]string{"bar"}, EnvConfig{"powershell"}, `$Env:bar"`},
{[]string{"baz"}, EnvConfig{"cmd"}, `SET baz=`},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.ec.Shell, func(t *testing.T) {
var b bytes.Buffer
if err := UnsetScript(tc.ec, &b, tc.vars); err != nil {
t.Fatalf("Unexpected error when unseting script happen: %v", err)
} else {
writtenMessage := strings.Trim(b.String(), " \t\n")
if writtenMessage != tc.expected {
t.Fatalf("Unset script failed. Expected written '%v' but got '%v' ", tc.expected, writtenMessage)
}
}
})
}
}
func TestDetect(t *testing.T) {
if s, err := Detect(); err != nil {
t.Fatalf("unexpected error: '%v' during shell detection", err)
} else if s == "" {
t.Fatalf("Detected shell expected to be non empty string")
}
}
func TestSetScript(t *testing.T) {
ec := EnvConfig{"bash"}
var w bytes.Buffer
if err := SetScript(ec, &w, "foo", nil); err != nil {
t.Fatalf("Unexpected error: '%v' during Setting script", err)
}
if w.String() != "foo" {
t.Fatalf("Expected foo writed by SetScript, but got '%v'", w.String())
}
}