aboutsummaryrefslogtreecommitdiff
path: root/middleware/commands_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'middleware/commands_test.go')
-rw-r--r--middleware/commands_test.go291
1 files changed, 291 insertions, 0 deletions
diff --git a/middleware/commands_test.go b/middleware/commands_test.go
new file mode 100644
index 000000000..3001e65a5
--- /dev/null
+++ b/middleware/commands_test.go
@@ -0,0 +1,291 @@
+package middleware
+
+import (
+ "fmt"
+ "runtime"
+ "strings"
+ "testing"
+)
+
+func TestParseUnixCommand(t *testing.T) {
+ tests := []struct {
+ input string
+ expected []string
+ }{
+ // 0 - emtpy command
+ {
+ input: ``,
+ expected: []string{},
+ },
+ // 1 - command without arguments
+ {
+ input: `command`,
+ expected: []string{`command`},
+ },
+ // 2 - command with single argument
+ {
+ input: `command arg1`,
+ expected: []string{`command`, `arg1`},
+ },
+ // 3 - command with multiple arguments
+ {
+ input: `command arg1 arg2`,
+ expected: []string{`command`, `arg1`, `arg2`},
+ },
+ // 4 - command with single argument with space character - in quotes
+ {
+ input: `command "arg1 arg1"`,
+ expected: []string{`command`, `arg1 arg1`},
+ },
+ // 5 - command with multiple spaces and tab character
+ {
+ input: "command arg1 arg2\targ3",
+ expected: []string{`command`, `arg1`, `arg2`, `arg3`},
+ },
+ // 6 - command with single argument with space character - escaped with backspace
+ {
+ input: `command arg1\ arg2`,
+ expected: []string{`command`, `arg1 arg2`},
+ },
+ // 7 - single quotes should escape special chars
+ {
+ input: `command 'arg1\ arg2'`,
+ expected: []string{`command`, `arg1\ arg2`},
+ },
+ }
+
+ for i, test := range tests {
+ errorPrefix := fmt.Sprintf("Test [%d]: ", i)
+ errorSuffix := fmt.Sprintf(" Command to parse: [%s]", test.input)
+ actual, _ := parseUnixCommand(test.input)
+ if len(actual) != len(test.expected) {
+ t.Errorf(errorPrefix+"Expected %d parts, got %d: %#v."+errorSuffix, len(test.expected), len(actual), actual)
+ continue
+ }
+ for j := 0; j < len(actual); j++ {
+ if expectedPart, actualPart := test.expected[j], actual[j]; expectedPart != actualPart {
+ t.Errorf(errorPrefix+"Expected: %v Actual: %v (index %d)."+errorSuffix, expectedPart, actualPart, j)
+ }
+ }
+ }
+}
+
+func TestParseWindowsCommand(t *testing.T) {
+ tests := []struct {
+ input string
+ expected []string
+ }{
+ { // 0 - empty command - do not fail
+ input: ``,
+ expected: []string{},
+ },
+ { // 1 - cmd without args
+ input: `cmd`,
+ expected: []string{`cmd`},
+ },
+ { // 2 - multiple args
+ input: `cmd arg1 arg2`,
+ expected: []string{`cmd`, `arg1`, `arg2`},
+ },
+ { // 3 - multiple args with space
+ input: `cmd "combined arg" arg2`,
+ expected: []string{`cmd`, `combined arg`, `arg2`},
+ },
+ { // 4 - path without spaces
+ input: `mkdir C:\Windows\foo\bar`,
+ expected: []string{`mkdir`, `C:\Windows\foo\bar`},
+ },
+ { // 5 - command with space in quotes
+ input: `"command here"`,
+ expected: []string{`command here`},
+ },
+ { // 6 - argument with escaped quotes (two quotes)
+ input: `cmd ""arg""`,
+ expected: []string{`cmd`, `"arg"`},
+ },
+ { // 7 - argument with escaped quotes (backslash)
+ input: `cmd \"arg\"`,
+ expected: []string{`cmd`, `"arg"`},
+ },
+ { // 8 - two quotes (escaped) inside an inQuote element
+ input: `cmd "a ""quoted value"`,
+ expected: []string{`cmd`, `a "quoted value`},
+ },
+ // TODO - see how many quotes are dislayed if we use "", """, """""""
+ { // 9 - two quotes outside an inQuote element
+ input: `cmd a ""quoted value`,
+ expected: []string{`cmd`, `a`, `"quoted`, `value`},
+ },
+ { // 10 - path with space in quotes
+ input: `mkdir "C:\directory name\foobar"`,
+ expected: []string{`mkdir`, `C:\directory name\foobar`},
+ },
+ { // 11 - space without quotes
+ input: `mkdir C:\ space`,
+ expected: []string{`mkdir`, `C:\`, `space`},
+ },
+ { // 12 - space in quotes
+ input: `mkdir "C:\ space"`,
+ expected: []string{`mkdir`, `C:\ space`},
+ },
+ { // 13 - UNC
+ input: `mkdir \\?\C:\Users`,
+ expected: []string{`mkdir`, `\\?\C:\Users`},
+ },
+ { // 14 - UNC with space
+ input: `mkdir "\\?\C:\Program Files"`,
+ expected: []string{`mkdir`, `\\?\C:\Program Files`},
+ },
+
+ { // 15 - unclosed quotes - treat as if the path ends with quote
+ input: `mkdir "c:\Program files`,
+ expected: []string{`mkdir`, `c:\Program files`},
+ },
+ { // 16 - quotes used inside the argument
+ input: `mkdir "c:\P"rogra"m f"iles`,
+ expected: []string{`mkdir`, `c:\Program files`},
+ },
+ }
+
+ for i, test := range tests {
+ errorPrefix := fmt.Sprintf("Test [%d]: ", i)
+ errorSuffix := fmt.Sprintf(" Command to parse: [%s]", test.input)
+
+ actual := parseWindowsCommand(test.input)
+ if len(actual) != len(test.expected) {
+ t.Errorf(errorPrefix+"Expected %d parts, got %d: %#v."+errorSuffix, len(test.expected), len(actual), actual)
+ continue
+ }
+ for j := 0; j < len(actual); j++ {
+ if expectedPart, actualPart := test.expected[j], actual[j]; expectedPart != actualPart {
+ t.Errorf(errorPrefix+"Expected: %v Actual: %v (index %d)."+errorSuffix, expectedPart, actualPart, j)
+ }
+ }
+ }
+}
+
+func TestSplitCommandAndArgs(t *testing.T) {
+
+ // force linux parsing. It's more robust and covers error cases
+ runtimeGoos = "linux"
+ defer func() {
+ runtimeGoos = runtime.GOOS
+ }()
+
+ var parseErrorContent = "error parsing command:"
+ var noCommandErrContent = "no command contained in"
+
+ tests := []struct {
+ input string
+ expectedCommand string
+ expectedArgs []string
+ expectedErrContent string
+ }{
+ // 0 - emtpy command
+ {
+ input: ``,
+ expectedCommand: ``,
+ expectedArgs: nil,
+ expectedErrContent: noCommandErrContent,
+ },
+ // 1 - command without arguments
+ {
+ input: `command`,
+ expectedCommand: `command`,
+ expectedArgs: nil,
+ expectedErrContent: ``,
+ },
+ // 2 - command with single argument
+ {
+ input: `command arg1`,
+ expectedCommand: `command`,
+ expectedArgs: []string{`arg1`},
+ expectedErrContent: ``,
+ },
+ // 3 - command with multiple arguments
+ {
+ input: `command arg1 arg2`,
+ expectedCommand: `command`,
+ expectedArgs: []string{`arg1`, `arg2`},
+ expectedErrContent: ``,
+ },
+ // 4 - command with unclosed quotes
+ {
+ input: `command "arg1 arg2`,
+ expectedCommand: "",
+ expectedArgs: nil,
+ expectedErrContent: parseErrorContent,
+ },
+ // 5 - command with unclosed quotes
+ {
+ input: `command 'arg1 arg2"`,
+ expectedCommand: "",
+ expectedArgs: nil,
+ expectedErrContent: parseErrorContent,
+ },
+ }
+
+ for i, test := range tests {
+ errorPrefix := fmt.Sprintf("Test [%d]: ", i)
+ errorSuffix := fmt.Sprintf(" Command to parse: [%s]", test.input)
+ actualCommand, actualArgs, actualErr := SplitCommandAndArgs(test.input)
+
+ // test if error matches expectation
+ if test.expectedErrContent != "" {
+ if actualErr == nil {
+ t.Errorf(errorPrefix+"Expected error with content [%s], found no error."+errorSuffix, test.expectedErrContent)
+ } else if !strings.Contains(actualErr.Error(), test.expectedErrContent) {
+ t.Errorf(errorPrefix+"Expected error with content [%s], found [%v]."+errorSuffix, test.expectedErrContent, actualErr)
+ }
+ } else if actualErr != nil {
+ t.Errorf(errorPrefix+"Expected no error, found [%v]."+errorSuffix, actualErr)
+ }
+
+ // test if command matches
+ if test.expectedCommand != actualCommand {
+ t.Errorf(errorPrefix+"Expected command: [%s], actual: [%s]."+errorSuffix, test.expectedCommand, actualCommand)
+ }
+
+ // test if arguments match
+ if len(test.expectedArgs) != len(actualArgs) {
+ t.Errorf(errorPrefix+"Wrong number of arguments! Expected [%v], actual [%v]."+errorSuffix, test.expectedArgs, actualArgs)
+ } else {
+ // test args only if the count matches.
+ for j, actualArg := range actualArgs {
+ expectedArg := test.expectedArgs[j]
+ if actualArg != expectedArg {
+ t.Errorf(errorPrefix+"Argument at position [%d] differ! Expected [%s], actual [%s]"+errorSuffix, j, expectedArg, actualArg)
+ }
+ }
+ }
+ }
+}
+
+func ExampleSplitCommandAndArgs() {
+ var commandLine string
+ var command string
+ var args []string
+
+ // just for the test - change GOOS and reset it at the end of the test
+ runtimeGoos = "windows"
+ defer func() {
+ runtimeGoos = runtime.GOOS
+ }()
+
+ commandLine = `mkdir /P "C:\Program Files"`
+ command, args, _ = SplitCommandAndArgs(commandLine)
+
+ fmt.Printf("Windows: %s: %s [%s]\n", commandLine, command, strings.Join(args, ","))
+
+ // set GOOS to linux
+ runtimeGoos = "linux"
+
+ commandLine = `mkdir -p /path/with\ space`
+ command, args, _ = SplitCommandAndArgs(commandLine)
+
+ fmt.Printf("Linux: %s: %s [%s]\n", commandLine, command, strings.Join(args, ","))
+
+ // Output:
+ // Windows: mkdir /P "C:\Program Files": mkdir [/P,C:\Program Files]
+ // Linux: mkdir -p /path/with\ space: mkdir [-p,/path/with space]
+}