func TestEqual(t *testing.T) { t.Run("should not end testing if the expected equals the actual", func(t *testing.T) { tester := new(mockTester) assert.Equal(tester, 42, 42) if tester.errorfCalls != 0 { t.Errorf( "Expected Errorf not to have been called, it had been called %d times.", tester.errorfCalls, ) } }) t.Run("should end testing if the expected does not equal the actual", func(t *testing.T) { tester := new(mockTester) assert.Equal(tester, 24, 42) if tester.errorfCalls != 1 { t.Errorf( "Expected Errorf to have been called once, it had been called %d times.", tester.errorfCalls, ) } }) }
func TestParseArgumentSpecification(t *testing.T) { t.Run("should set the name", func(t *testing.T) { argument, err := specification.ParseArgumentSpecification("GALAXY_QUEST") assert.OK(t, err) assert.Equal(t, "GALAXY_QUEST", argument.Name) }) t.Run("should set whether or not the argument is required", func(t *testing.T) { argument, err := specification.ParseArgumentSpecification("GALAXY_QUEST") assert.OK(t, err) assert.Equal(t, true, argument.Required) argument, err = specification.ParseArgumentSpecification("[MEMENTO]") assert.OK(t, err) assert.Equal(t, false, argument.Required) }) t.Run("should expect a close bracket if an opening one is given", func(t *testing.T) { _, err := specification.ParseArgumentSpecification("[MEMENTO") assert.NotOK(t, err) }) t.Run("should not expect any whitespace", func(t *testing.T) { _, err := specification.ParseArgumentSpecification("GALAXY QUEST") assert.NotOK(t, err) }) t.Run("should always expect an identifier", func(t *testing.T) { _, err := specification.ParseArgumentSpecification("") assert.NotOK(t, err) _, err = specification.ParseArgumentSpecification("[]") assert.NotOK(t, err) }) }
func TestUrlValue(t *testing.T) { t.Run("NewURLValue()", func(t *testing.T) { expected := "https://www.google.co.uk/" actual, err := url.Parse(expected) assert.OK(t, err) actualValue := parameters.NewURLValue(actual) assert.Equal(t, expected, actualValue.String()) }) t.Run("Set()", func(t *testing.T) { t.Run("should not error for valid values", func(t *testing.T) { var value parameters.URLValue valid := []string{ "https://www.google.co.uk/", "ws://www.elliotdwright.com:9000/", "ftp://whouses.ftpanymore.com:21/", } for _, item := range valid { err := value.Set(item) assert.OK(t, err) } }) t.Run("should modify the URL that it references", func(t *testing.T) { oldURL := "https://www.google.co.uk/" newURL := "https://www.elliotdwright.com/" ref, err := url.Parse(oldURL) assert.OK(t, err) value := parameters.NewURLValue(ref) assert.Equal(t, oldURL, ref.String()) value.Set(newURL) assert.Equal(t, newURL, ref.String()) }) }) t.Run("String()", func(t *testing.T) { inOut := map[string]string{ "https://www.google.co.uk/": "https://www.google.co.uk/", "ws://www.elliotdwright.com:9000/": "ws://www.elliotdwright.com:9000/", "ftp://whouses.ftpanymore.com:21/": "ftp://whouses.ftpanymore.com:21/", } for in, expected := range inOut { value := new(parameters.URLValue) value.Set(in) actual := value.String() assert.Equal(t, expected, actual) } }) }
func TestStringValue(t *testing.T) { t.Run("NewStringValue()", func(t *testing.T) { expected := "Hello, World!" actual := parameters.NewStringValue(&expected) assert.Equal(t, expected, actual.String()) }) t.Run("Set()", func(t *testing.T) { t.Run("should not error for valid values", func(t *testing.T) { var value parameters.StringValue valid := []string{ "Hello", "World", "Hello, World!", "3.14", "http://www.google.co.uk/", } for _, item := range valid { err := value.Set(item) assert.OK(t, err) } }) t.Run("should modify the string that it references", func(t *testing.T) { ref := "Hello" value := parameters.NewStringValue(&ref) assert.Equal(t, "Hello", ref) value.Set("World") assert.Equal(t, "World", ref) }) }) t.Run("String()", func(t *testing.T) { inOut := map[string]string{ "Hello": "Hello", "World": "World", "hello": "hello", "world": "world", } for in, expected := range inOut { value := new(parameters.StringValue) value.Set(in) actual := value.String() assert.Equal(t, expected, actual) } }) }
func TestParseOptionSpecification(t *testing.T) { t.Run("should set the name(s)", func(t *testing.T) { option, err := specification.ParseOptionSpecification("--galaxy-quest") assert.OK(t, err) assert.True(t, len(option.Names) == 1, "Expected an option name") name := option.Names[0] assert.Equal(t, "galaxy-quest", name) option, err = specification.ParseOptionSpecification("-g, --galaxy-quest") assert.OK(t, err) assert.True(t, len(option.Names) == 2, "Expected 2 option names") shortName := option.Names[0] longName := option.Names[1] assert.Equal(t, "g", shortName) assert.Equal(t, "galaxy-quest", longName) option, err = specification.ParseOptionSpecification("-a, -b, -c, --dee, --ee, --eff") assert.OK(t, err) assert.True(t, len(option.Names) == 6, "Expected 6 option names") }) t.Run("should allow no value mode to be set", func(t *testing.T) { option, err := specification.ParseOptionSpecification("--galaxy-quest") assert.OK(t, err) assert.Equal(t, parameters.OptionValueNone, option.ValueMode) }) t.Run("should allow option values", func(t *testing.T) { option, err := specification.ParseOptionSpecification("--galaxy-quest-2[=ALAN_RICKMAN]") assert.OK(t, err) assert.Equal(t, parameters.OptionValueOptional, option.ValueMode) }) t.Run("should allow required values", func(t *testing.T) { option, err := specification.ParseOptionSpecification("--galaxy-quest=ALAN_RICKMAN") assert.OK(t, err) assert.Equal(t, parameters.OptionValueRequired, option.ValueMode) }) t.Run("should error when given an invalid long option name", func(t *testing.T) { _, err := specification.ParseOptionSpecification("--$$$") assert.NotOK(t, err) }) t.Run("should error when given an invalid short option name", func(t *testing.T) { _, err := specification.ParseOptionSpecification("-$") assert.NotOK(t, err) }) t.Run("should error when given an short option name that's too long", func(t *testing.T) { _, err := specification.ParseOptionSpecification("-abc") assert.NotOK(t, err) }) t.Run("should error when given an invalid specification", func(t *testing.T) { _, err := specification.ParseOptionSpecification("abc") assert.NotOK(t, err) }) t.Run("should error if no identifier is given for the value name", func(t *testing.T) { _, err := specification.ParseOptionSpecification("--galaxy-quest=") assert.NotOK(t, err) _, err = specification.ParseOptionSpecification("--galaxy-quest[=]") assert.NotOK(t, err) }) t.Run("should expect EQUALS if an LBRACK is found", func(t *testing.T) { _, err := specification.ParseOptionSpecification("--galaxy-quest[]") assert.NotOK(t, err) _, err = specification.ParseOptionSpecification("--galaxy-quest[") assert.NotOK(t, err) }) t.Run("should expect an RBRACK if an LBRACK is given", func(t *testing.T) { _, err := specification.ParseOptionSpecification("--galaxy-quest-2[=ALAN_RICKMAN") assert.NotOK(t, err) }) t.Run("should expect EOF after value identifier is no LBRACK is given", func(t *testing.T) { _, err := specification.ParseOptionSpecification("--galaxy-quest-2=ALAN_RICKMAN]") assert.NotOK(t, err) }) }
func TestOutput(t *testing.T) { // Realistically, these tests are a little lacking, but that's mainly because we're pretty much // transparently passing everything over to the fmt package. "So why are you bothering to do // that?", simply so we can customise the writer in the application, and not have to specify it // every time we write. t.Run("Print()", func(t *testing.T) { t.Run("should handle printing", func(t *testing.T) { buffer := bytes.Buffer{} output := console.NewOutput(&buffer) message := "Hello, World!" nbytes, err := output.Print(message) assert.OK(t, err) assert.Equal(t, 13, nbytes) assert.Equal(t, message, buffer.String()) }) t.Run("should handle printing multiple values", func(t *testing.T) { buffer := bytes.Buffer{} output := console.NewOutput(&buffer) message1 := "Go " message2 := "testing!" nbytes, err := output.Print(message1, message2) assert.OK(t, err) assert.Equal(t, 11, nbytes) assert.Equal(t, message1+message2, buffer.String()) }) }) t.Run("Printf()", func(t *testing.T) { t.Run("should handle printing", func(t *testing.T) { buffer := bytes.Buffer{} output := console.NewOutput(&buffer) nbytes, err := output.Printf("Hello, %s!", "World") assert.OK(t, err) assert.Equal(t, 13, nbytes) assert.Equal(t, "Hello, World!", buffer.String()) }) t.Run("should handle multiple parameters", func(t *testing.T) { buffer := bytes.Buffer{} output := console.NewOutput(&buffer) message := "Hello %s, the answer to life the universe and everything is %d!" param1 := "Go" param2 := 42 expected := "Hello Go, the answer to life the universe and everything is 42!" nbytes, err := output.Printf(message, param1, param2) assert.OK(t, err) assert.Equal(t, 63, nbytes) assert.Equal(t, expected, buffer.String()) }) }) t.Run("Println()", func(t *testing.T) { t.Run("should handle printing", func(t *testing.T) { buffer := bytes.Buffer{} output := console.NewOutput(&buffer) message := "Hello, World!" expected := "Hello, World!\n" nbytes, err := output.Println(message) assert.OK(t, err) assert.Equal(t, 14, nbytes) assert.Equal(t, expected, buffer.String()) }) t.Run("should handle printing multiple values", func(t *testing.T) { buffer := bytes.Buffer{} output := console.NewOutput(&buffer) message1 := "Go " message2 := "testing!" // Remember, fmt.Println adds spaces between things. expected := "Go testing!\n" nbytes, err := output.Println(message1, message2) assert.OK(t, err) assert.Equal(t, 13, nbytes) assert.Equal(t, expected, buffer.String()) }) }) }
func TestScanner(t *testing.T) { createScanner := func(input string) *specification.Scanner { return specification.NewScanner(strings.NewReader(input)) } t.Run("Scan()", func(t *testing.T) { t.Run("should handle end of input", func(t *testing.T) { scanner := createScanner("=") tok, val := scanner.Scan() assert.Equal(t, specification.EQUALS, tok) assert.Equal(t, "=", val) tok, val = scanner.Scan() assert.Equal(t, specification.EOF, tok) assert.Equal(t, "", val) }) t.Run("should be able to scan left-brackets ([)", func(t *testing.T) { scanner := createScanner("[") tok, val := scanner.Scan() assert.Equal(t, specification.LBRACK, tok) assert.Equal(t, "[", val) }) t.Run("should be able to scan right-brackets (])", func(t *testing.T) { scanner := createScanner("]") tok, val := scanner.Scan() assert.Equal(t, specification.RBRACK, tok) assert.Equal(t, "]", val) }) t.Run("should be able to scan commas (,)", func(t *testing.T) { scanner := createScanner(",") tok, val := scanner.Scan() assert.Equal(t, specification.COMMA, tok) assert.Equal(t, ",", val) }) t.Run("should be able to scan equals (=)", func(t *testing.T) { scanner := createScanner("=") tok, val := scanner.Scan() assert.Equal(t, specification.EQUALS, tok) assert.Equal(t, "=", val) }) t.Run("should be able to scan hyphens (-)", func(t *testing.T) { scanner := createScanner("-") tok, val := scanner.Scan() assert.Equal(t, specification.HYPHEN, tok) assert.Equal(t, "-", val) }) t.Run("should be able to scan whitespace", func(t *testing.T) { scanner := createScanner(" ") tok, val := scanner.Scan() assert.Equal(t, specification.WS, tok) assert.Equal(t, " ", val) }) t.Run("should only scan up to available whitespace characters", func(t *testing.T) { scanner := createScanner(" hello") tok, val := scanner.Scan() assert.Equal(t, specification.WS, tok) assert.Equal(t, " ", val) }) t.Run("should be able to scan identifiers", func(t *testing.T) { scanner := createScanner("I_am_an_identifier-scanner") tok, val := scanner.Scan() assert.Equal(t, specification.IDENTIFIER, tok) assert.Equal(t, "I_am_an_identifier-scanner", val) }) t.Run("should only scan up to available identifier characters", func(t *testing.T) { scanner := createScanner("SOME_IDENTIFIER=") tok, val := scanner.Scan() assert.Equal(t, specification.IDENTIFIER, tok) assert.Equal(t, "SOME_IDENTIFIER", val) tok, val = scanner.Scan() assert.Equal(t, specification.EQUALS, tok) assert.Equal(t, "=", val) }) t.Run("should handle illegal characters", func(t *testing.T) { input := "£$%" scanner := createScanner(input) tok, val := scanner.Scan() assert.Equal(t, specification.ILLEGAL, tok) assert.Equal(t, "£", val) tok, val = scanner.Scan() assert.Equal(t, specification.ILLEGAL, tok) assert.Equal(t, "$", val) tok, val = scanner.Scan() assert.Equal(t, specification.ILLEGAL, tok) assert.Equal(t, "%", val) }) }) }
func TestMapInput(t *testing.T) { createInput := func(params []string) *console.Input { return console.ParseInput(params) } t.Run("should map arguments to their reference values", func(t *testing.T) { var s1 string var s2 string assert.Equal(t, "", s1) assert.Equal(t, "", s2) input := createInput([]string{"hello", "world"}) definition := console.NewDefinition() definition.AddArgument(parameters.NewStringValue(&s1), "S1", "") definition.AddArgument(parameters.NewStringValue(&s2), "S2", "") err := console.MapInput(definition, input) assert.OK(t, err) assert.Equal(t, "hello", s1) assert.Equal(t, "world", s2) }) t.Run("should error parsing arguments with invalid values", func(t *testing.T) { var i1 int assert.Equal(t, 0, i1) input := createInput([]string{"foo"}) definition := console.NewDefinition() definition.AddArgument(parameters.NewIntValue(&i1), "I1", "") err := console.MapInput(definition, input) assert.NotOK(t, err) }) t.Run("should error when required arguments are missing from input", func(t *testing.T) { var s1 string var s2 string assert.Equal(t, "", s1) assert.Equal(t, "", s2) input := createInput([]string{"foo"}) definition := console.NewDefinition() definition.AddArgument(parameters.NewStringValue(&s1), "S1", "") definition.AddArgument(parameters.NewStringValue(&s1), "S2", "") err := console.MapInput(definition, input) assert.NotOK(t, err) }) t.Run("should not error when optional arguments are missing from input", func(t *testing.T) { var s1 string var s2 string assert.Equal(t, "", s1) assert.Equal(t, "", s2) input := createInput([]string{"foo"}) definition := console.NewDefinition() definition.AddArgument(parameters.NewStringValue(&s1), "S1", "") definition.AddArgument(parameters.NewStringValue(&s1), "[S2]", "") err := console.MapInput(definition, input) assert.OK(t, err) assert.Equal(t, "foo", s1) assert.Equal(t, "", s2) }) t.Run("should map short options to their reference values", func(t *testing.T) { var s1 string var s2 string assert.Equal(t, "", s1) assert.Equal(t, "", s2) input := createInput([]string{"-a=foo", "-b=bar"}) definition := console.NewDefinition() definition.AddOption(parameters.NewStringValue(&s1), "-a=S1", "") definition.AddOption(parameters.NewStringValue(&s2), "-b=S2", "") err := console.MapInput(definition, input) assert.OK(t, err) assert.Equal(t, "foo", s1) assert.Equal(t, "bar", s2) }) t.Run("should map long options to their reference values", func(t *testing.T) { var s1 string var s2 string assert.Equal(t, "", s1) assert.Equal(t, "", s2) input := createInput([]string{"--foo=bar", "--baz=qux"}) definition := console.NewDefinition() definition.AddOption(parameters.NewStringValue(&s1), "--foo=S1", "") definition.AddOption(parameters.NewStringValue(&s2), "--baz=S2", "") err := console.MapInput(definition, input) assert.OK(t, err) assert.Equal(t, "bar", s1) assert.Equal(t, "qux", s2) }) t.Run("should ignore options that don't exist in the definition", func(t *testing.T) { var s2 string input := createInput([]string{"--foo=bar"}) definition := console.NewDefinition() definition.AddOption(parameters.NewStringValue(&s2), "--baz=S2", "") err := console.MapInput(definition, input) assert.OK(t, err) }) t.Run("should error parsing an option that requires a value with no value", func(t *testing.T) { var s1 string input := createInput([]string{"--foo"}) definition := console.NewDefinition() definition.AddOption(parameters.NewStringValue(&s1), "--foo=s1", "") err := console.MapInput(definition, input) assert.NotOK(t, err) }) t.Run("should not error parsing an option that doesn't require a value", func(t *testing.T) { var s1 string input := createInput([]string{"--foo"}) definition := console.NewDefinition() definition.AddOption(parameters.NewStringValue(&s1), "--foo=s1", "") err := console.MapInput(definition, input) assert.NotOK(t, err) }) t.Run("should set flag option values where applicable", func(t *testing.T) { var b1 bool assert.Equal(t, false, b1) input := createInput([]string{"--foo"}) definition := console.NewDefinition() definition.AddOption(parameters.NewBoolValue(&b1), "--foo", "") err := console.MapInput(definition, input) assert.OK(t, err) assert.Equal(t, true, b1) }) t.Run("should error parsing options with invalid values", func(t *testing.T) { var i1 int assert.Equal(t, 0, i1) input := createInput([]string{"--foo=hello"}) definition := console.NewDefinition() definition.AddOption(parameters.NewIntValue(&i1), "--foo=I1", "") err := console.MapInput(definition, input) assert.NotOK(t, err) }) }
func TestIPValue(t *testing.T) { t.Run("NewIPValue()", func(t *testing.T) { ipRef := net.ParseIP("127.0.0.1") ipValue := parameters.NewIPValue(&ipRef) assert.Equal(t, "127.0.0.1", ipValue.String()) }) t.Run("Set()", func(t *testing.T) { t.Run("should not error for valid values", func(t *testing.T) { var value parameters.IPValue valid := []string{ "127.0.0.1", "192.168.0.1", "10.0.0.1", "255.255.255.0", "8.8.8.8", "8.8.4.4", } for _, item := range valid { err := value.Set(item) assert.OK(t, err) } }) t.Run("should error for invalid values", func(t *testing.T) { var value parameters.IPValue invalid := []string{ "", "Not an IP adddress", "Hello, World!", "123 Fake Street", "127 0 0 1", } for _, item := range invalid { err := value.Set(item) assert.NotOK(t, err) } }) t.Run("should modify the IP that it references", func(t *testing.T) { ref := net.ParseIP("127.0.0.1") value := parameters.NewIPValue(&ref) assert.Equal(t, value.String(), ref.String()) value.Set("192.168.0.1") assert.Equal(t, value.String(), ref.String()) value.Set("10.0.0.1") assert.Equal(t, value.String(), ref.String()) }) }) t.Run("String()", func(t *testing.T) { inOut := map[string]string{ "127.0.0.1": "127.0.0.1", "192.168.0.1": "192.168.0.1", "10.0.0.1": "10.0.0.1", } for in, expected := range inOut { value := new(parameters.IPValue) value.Set(in) actual := value.String() assert.Equal(t, expected, actual) } }) }
func TestIntValue(t *testing.T) { t.Run("NewIntValue()", func(t *testing.T) { intRef := 3 intValue := parameters.NewIntValue(&intRef) assert.Equal(t, "3", intValue.String()) }) t.Run("Set()", func(t *testing.T) { t.Run("should not error for valid values", func(t *testing.T) { var value parameters.Float64Value valid := []string{ "3", "10", "25", "100000", } for _, item := range valid { err := value.Set(item) assert.OK(t, err) } }) t.Run("should error for invalid values", func(t *testing.T) { var value parameters.IntValue invalid := []string{ "", "Hello, World!", "Three point one four", "92233720368547758070", } for _, item := range invalid { err := value.Set(item) assert.NotOK(t, err) } }) t.Run("should modify the int that it references", func(t *testing.T) { ref := 5 value := parameters.NewIntValue(&ref) assert.Equal(t, 5, ref) value.Set("10") assert.Equal(t, 10, ref) value.Set("25") assert.Equal(t, 25, ref) }) }) t.Run("String()", func(t *testing.T) { inOut := map[string]string{ "3": "3", "10": "10", "1000": "1000", } for in, expected := range inOut { value := new(parameters.IntValue) value.Set(in) actual := value.String() assert.Equal(t, expected, actual) } }) }
func TestFloat64Value(t *testing.T) { t.Run("NewFloat64Value()", func(t *testing.T) { float := float64(3.14) floatValue := parameters.NewFloat64Value(&float) assert.Equal(t, "3.14", floatValue.String()) }) t.Run("Set()", func(t *testing.T) { t.Run("should not error for valid values", func(t *testing.T) { var value parameters.Float64Value valid := []string{ "3", "3.1", "3.14", "314.159e-2", } for _, item := range valid { err := value.Set(item) assert.OK(t, err) } }) t.Run("should error for invalid values", func(t *testing.T) { var value parameters.Float64Value invalid := []string{ "", "Hello, World!", "Three point one four", } for _, item := range invalid { err := value.Set(item) assert.NotOK(t, err) } }) t.Run("should modify the float64 that it references", func(t *testing.T) { ref := float64(3.14) value := parameters.NewFloat64Value(&ref) assert.Equal(t, float64(3.14), ref) value.Set("3.14159") assert.Equal(t, float64(3.14159), ref) value.Set("10") assert.Equal(t, float64(10), ref) }) }) t.Run("String()", func(t *testing.T) { inOut := map[string]string{ "3": "3", "3.14": "3.14", "3.14159": "3.14159", "314.159e-2": "3.14159", } for in, expected := range inOut { value := new(parameters.Float64Value) value.Set(in) actual := value.String() assert.Equal(t, expected, actual) } }) }
func TestBoolValue(t *testing.T) { t.Run("NewBoolValue()", func(t *testing.T) { truthy := true falsey := false truthyValue := parameters.NewBoolValue(&truthy) falseyValue := parameters.NewBoolValue(&falsey) assert.Equal(t, truthyValue.String(), "true") assert.Equal(t, falseyValue.String(), "false") }) t.Run("Set()", func(t *testing.T) { t.Run("should not error for valid values", func(t *testing.T) { var value parameters.BoolValue valid := []string{ "1", "t", "T", "TRUE", "true", "True", "0", "f", "F", "FALSE", "false", "False", } for _, item := range valid { err := value.Set(item) assert.OK(t, err) } }) t.Run("should error for invalid values", func(t *testing.T) { var value parameters.BoolValue invalid := []string{ "", "yes", "no", "Y", "N", } for _, item := range invalid { err := value.Set(item) assert.NotOK(t, err) } }) t.Run("should modify the bool that it references", func(t *testing.T) { ref := true value := parameters.NewBoolValue(&ref) assert.Equal(t, true, ref) value.Set("false") assert.Equal(t, false, ref) value.Set("true") assert.Equal(t, true, ref) }) }) t.Run("String()", func(t *testing.T) { inOut := map[string]string{ "1": "true", "t": "true", "T": "true", "TRUE": "true", "true": "true", "True": "true", "0": "false", "f": "false", "F": "false", "FALSE": "false", "false": "false", "False": "false", } for in, expected := range inOut { value := new(parameters.BoolValue) value.Set(in) actual := value.String() assert.Equal(t, expected, actual) } }) t.Run("FlagValue()", func(t *testing.T) { var value parameters.BoolValue assert.Equal(t, "true", value.FlagValue()) }) }
func TestDurationValue(t *testing.T) { t.Run("NewDurationValue()", func(t *testing.T) { duration := time.Second durationValue := parameters.NewDurationValue(&duration) assert.Equal(t, "1s", durationValue.String()) }) t.Run("Set()", func(t *testing.T) { t.Run("should not error for valid values", func(t *testing.T) { var value parameters.DurationValue valid := []string{ "5us", "999ns", "1s", "3m", "1h33m2s", "5h", "365h", } for _, item := range valid { err := value.Set(item) assert.OK(t, err) } }) t.Run("should error for invalid values", func(t *testing.T) { var value parameters.DurationValue invalid := []string{ "", "1d", "20y", "20 decades", } for _, item := range invalid { err := value.Set(item) assert.NotOK(t, err) } }) t.Run("should modify the bool that it references", func(t *testing.T) { ref := time.Second value := parameters.NewDurationValue(&ref) assert.Equal(t, time.Second, ref) value.Set("1m") assert.Equal(t, time.Minute, ref) value.Set("1h") assert.Equal(t, ref, time.Hour) }) }) t.Run("String()", func(t *testing.T) { inOut := map[string]string{ "1us": "1µs", "1ns": "1ns", "1s": "1s", "1m": "1m0s", "1h": "1h0m0s", "5s": "5s", "10h": "10h0m0s", } for in, expected := range inOut { value := new(parameters.DurationValue) value.Set(in) actual := value.String() assert.Equal(t, expected, actual) } }) }
func TestApplication(t *testing.T) { createApplication := func(writer io.Writer) *console.Application { application := console.NewApplication("eidolon/console", "1.2.3.+testing") application.Writer = writer return application } createTestCommand := func(a *string, b *int) console.Command { return console.Command{ Name: "test", Configure: func(definition *console.Definition) { definition.AddArgument(parameters.NewStringValue(a), "STRINGARG", "") definition.AddOption(parameters.NewIntValue(b), "--int-opt=VALUE", "") }, Execute: func(input *console.Input, output *console.Output) error { output.Printf("STRINGARG = %s", *a) output.Printf("--int-opt = %v", *b) return nil }, } } t.Run("Run()", func(t *testing.T) { t.Run("should return exit code 2 if no command was asked for", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) code := application.Run([]string{}) assert.Equal(t, 100, code) }) t.Run("should return exit code 2 if no command was found", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) code := application.Run([]string{"foo"}) assert.Equal(t, 100, code) }) t.Run("should return exit code 100 if the help flag is set", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) code := application.Run([]string{"--help"}) assert.Equal(t, 100, code) }) t.Run("should show application help if the help flag is set", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) application.Run([]string{"--help"}) output := writer.String() containsUsage := strings.Contains(output, "USAGE:") containsArguments := strings.Contains(output, "ARGUMENTS:") containsOptions := strings.Contains(output, "OPTIONS:") containsHelp := containsUsage && containsOptions && !containsArguments assert.True(t, containsHelp, "Expected help output.") }) t.Run("should show command help if the help flag is set when running a command", func(t *testing.T) { var a string var b int writer := bytes.Buffer{} application := createApplication(&writer) application.AddCommand(createTestCommand(&a, &b)) application.Run([]string{"test", "--help"}) output := writer.String() containsUsage := strings.Contains(output, "USAGE:") containsArguments := strings.Contains(output, "ARGUMENTS:") containsOptions := strings.Contains(output, "OPTIONS:") containsHelp := containsUsage && containsOptions && containsArguments assert.True(t, containsHelp, "Expected help output.") }) t.Run("should return exit code 0 if a command was found, and ran OK", func(t *testing.T) { var a string var b int writer := bytes.Buffer{} application := createApplication(&writer) application.AddCommand(createTestCommand(&a, &b)) code := application.Run([]string{"test", "aval", "--int-opt=384"}) assert.Equal(t, 0, code) }) t.Run("should return exit code 101 if mapping input fails", func(t *testing.T) { var a string var b int writer := bytes.Buffer{} application := createApplication(&writer) application.AddCommand(createTestCommand(&a, &b)) code := application.Run([]string{"test", "aval", "--int-opt=hello"}) assert.Equal(t, 101, code) }) t.Run("should return exit code 102 if the command execution fails", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) application.AddCommand(console.Command{ Name: "test", Execute: func(input *console.Input, output *console.Output) error { return errors.New("Testing errors") }, }) code := application.Run([]string{"test", "aval", "--int-opt=hello"}) assert.Equal(t, 102, code) }) t.Run("should configure the application definition", func(t *testing.T) { var a string var b int var foo string writer := bytes.Buffer{} application := createApplication(&writer) application.Configure = func(definition *console.Definition) { definition.AddOption(parameters.NewStringValue(&foo), "--foo=FOO", "") } application.AddCommand(createTestCommand(&a, &b)) application.Run([]string{"test", "aval", "--foo=bar"}) assert.Equal(t, "bar", foo) }) }) t.Run("AddCommands()", func(t *testing.T) { t.Run("should work when adding 1 command", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) assert.Equal(t, 0, len(application.Commands)) application.AddCommands([]console.Command{ { Name: "test1", }, }) assert.Equal(t, 1, len(application.Commands)) }) t.Run("should work when adding no commands", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) assert.Equal(t, 0, len(application.Commands)) application.AddCommands([]console.Command{}) assert.Equal(t, 0, len(application.Commands)) }) t.Run("should work when adding more than 1 command", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) assert.Equal(t, 0, len(application.Commands)) application.AddCommands([]console.Command{ { Name: "test1", }, { Name: "test2", }, { Name: "test3", }, }) assert.Equal(t, 3, len(application.Commands)) }) }) t.Run("AddCommand()", func(t *testing.T) { writer := bytes.Buffer{} application := createApplication(&writer) assert.Equal(t, 0, len(application.Commands)) application.AddCommand(console.Command{ Name: "test1", }) assert.Equal(t, 1, len(application.Commands)) }) }
func TestDefinition(t *testing.T) { t.Run("Arguments()", func(t *testing.T) { t.Run("should return an empty slice if no arguments have been added", func(t *testing.T) { definition := console.NewDefinition() assert.True(t, len(definition.Arguments()) == 0, "Arguments() length should be 0") }) t.Run("should return an ordered slice of arguments", func(t *testing.T) { var s1 string var s2 string var s3 string definition := console.NewDefinition() definition.AddArgument(parameters.NewStringValue(&s1), "S1", "") definition.AddArgument(parameters.NewStringValue(&s2), "S2", "") definition.AddArgument(parameters.NewStringValue(&s3), "S3", "") arguments := definition.Arguments() assert.True(t, len(arguments) == 3, "Arguments() length should be 3") assert.Equal(t, "S1", arguments[0].Name) assert.Equal(t, "S2", arguments[1].Name) assert.Equal(t, "S3", arguments[2].Name) }) }) t.Run("Options()", func(t *testing.T) { t.Run("should return an empty slice if no options have been added", func(t *testing.T) { definition := console.NewDefinition() assert.True(t, len(definition.Options()) == 0, "Options() length should be 0") }) t.Run("should return a slice of options", func(t *testing.T) { var s1 string var s2 string var s3 string definition := console.NewDefinition() definition.AddOption(parameters.NewStringValue(&s1), "--s1", "") definition.AddOption(parameters.NewStringValue(&s2), "--s2", "") definition.AddOption(parameters.NewStringValue(&s3), "--s3", "") options := definition.Options() assert.Equal(t, 3, len(options)) }) }) t.Run("AddArgument()", func(t *testing.T) { t.Run("should error if an invalid option specification is given", func(t *testing.T) { defer func() { r := recover() assert.False(t, r == nil, "We should be recovering from a panic.") }() var s1 string definition := console.NewDefinition() definition.AddArgument(parameters.NewStringValue(&s1), "!!! S1", "") }) t.Run("should error if an argument with the same name exists", func(t *testing.T) { defer func() { r := recover() assert.False(t, r == nil, "We should be recovering from a panic.") }() var s1 string var s2 string definition := console.NewDefinition() definition.AddArgument(parameters.NewStringValue(&s1), "S1", "") definition.AddArgument(parameters.NewStringValue(&s2), "S1", "") }) t.Run("should add an argument", func(t *testing.T) { var s1 string definition := console.NewDefinition() assert.Equal(t, 0, len(definition.Arguments())) definition.AddArgument(parameters.NewStringValue(&s1), "S1", "") assert.Equal(t, 1, len(definition.Arguments())) }) }) t.Run("AddOption()", func(t *testing.T) { t.Run("should error if an invalid option specification is given", func(t *testing.T) { defer func() { r := recover() assert.False(t, r == nil, "We should be recovering from a panic.") }() var s1 string definition := console.NewDefinition() definition.AddOption(parameters.NewStringValue(&s1), "!!! S1", "") }) t.Run("should error if an option with the same name exists", func(t *testing.T) { defer func() { r := recover() assert.False(t, r == nil, "We should be recovering from a panic.") }() var s1 string var s2 string definition := console.NewDefinition() definition.AddOption(parameters.NewStringValue(&s1), "--s1", "") definition.AddOption(parameters.NewStringValue(&s2), "--s1", "") }) t.Run("should add an option", func(t *testing.T) { var s1 string definition := console.NewDefinition() assert.Equal(t, 0, len(definition.Options())) definition.AddOption(parameters.NewStringValue(&s1), "--s1", "") assert.Equal(t, 1, len(definition.Options())) }) }) }