github.com/Aoi-hosizora/ahlib-more@v1.5.1-0.20230404072844-256112befaf6/xpflag/xpflag_test.go (about) 1 package xpflag 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/Aoi-hosizora/ahlib/xtesting" 7 "github.com/spf13/pflag" 8 "log" 9 "os" 10 "strings" 11 "testing" 12 ) 13 14 func TestParse(t *testing.T) { 15 saved := _cmd 16 defer func() { _cmd = saved }() 17 saved2 := os.Args 18 defer func() { os.Args = saved2 }() 19 saved3 := _osStderr 20 defer func() { _osStderr = saved3 }() 21 saved4 := _osExit 22 defer func() { _osExit = saved4 }() 23 24 var pHelp *bool 25 var pConfig *string 26 define := func(includeError bool) { 27 _cmd = pflag.NewFlagSet("application", pflag.ContinueOnError) // avoid to influence global _cmd 28 _cmd.Usage = func() { DefaultUsage(_cmd) } 29 if includeError { 30 pHelp = Cmd().BoolP("help", "h", false, "show help message") 31 } 32 pConfig = Cmd().StringP("config", "c", "./config.json", "config file path") 33 } 34 sb := &strings.Builder{} 35 _osStderr = sb 36 exitCode := -1 37 _osExit = func(code int) { 38 exitCode = code 39 } 40 41 // 1. PrintUsage 42 xtesting.EmptyCollection(t, strings.TrimSpace(Cmd().FlagUsages())) 43 PrintUsage() 44 define(false) 45 xtesting.Equal(t, len(strings.Split(strings.TrimSpace(Cmd().FlagUsages()), "\n")), 1) 46 PrintUsage() 47 define(true) 48 xtesting.Equal(t, len(strings.Split(strings.TrimSpace(Cmd().FlagUsages()), "\n")), 2) 49 PrintUsage() 50 51 // => test normal parse 52 for _, tc := range []struct { 53 giveArgs []string 54 wantError bool 55 checkFn func() 56 }{ 57 {[]string{}, false, func() { 58 xtesting.Equal(t, *pHelp, false) 59 xtesting.Equal(t, *pConfig, "./config.json") 60 }}, 61 {[]string{"-x"}, true, nil}, 62 {[]string{"-xxx"}, true, nil}, 63 {[]string{"--xxx"}, true, nil}, 64 {[]string{"-h", "-1"}, true, nil}, 65 {[]string{"-x", "-c"}, true, nil}, 66 {[]string{"-h", "123"}, false, func() { 67 xtesting.Equal(t, *pHelp, true) 68 xtesting.Equal(t, *pConfig, "./config.json") 69 }}, 70 {[]string{"--help", "-h", "-c", "xxx"}, false, func() { 71 xtesting.Equal(t, *pHelp, true) 72 xtesting.Equal(t, *pConfig, "xxx") 73 }}, 74 {[]string{"-c", "--help"}, false, func() { 75 xtesting.Equal(t, *pHelp, false) 76 xtesting.Equal(t, *pConfig, "--help") 77 }}, 78 } { 79 t.Run(strings.Join(tc.giveArgs, " "), func(t *testing.T) { 80 os.Args = append([]string{"application"}, tc.giveArgs...) 81 define(true) 82 83 // 2. Parse 84 err := Parse() 85 xtesting.Equal(t, err != nil, tc.wantError) 86 if err == nil && tc.checkFn != nil { 87 tc.checkFn() 88 } 89 90 // 3. MustParse 91 sb.Reset() 92 exitCode = -1 93 MustParse() 94 if !tc.wantError { 95 xtesting.Equal(t, sb.String(), "") 96 xtesting.Equal(t, exitCode, -1) // success 97 } else { 98 log.Println(err) 99 firstLine := strings.Split(sb.String(), "\n")[0] 100 xtesting.Equal(t, firstLine, fmt.Sprintf("Error: %v", err)) 101 xtesting.Equal(t, exitCode, 2) 102 } 103 }) 104 } 105 106 // => test parse without help flag 107 for _, tc := range []struct { 108 giveArgs []string 109 wantHelpError bool 110 }{ 111 {[]string{""}, false}, 112 {[]string{"-h"}, true}, 113 {[]string{"--help"}, true}, 114 {[]string{"-c -h"}, false}, 115 {[]string{"-h -c"}, true}, 116 } { 117 t.Run(strings.Join(tc.giveArgs, " "), func(t *testing.T) { 118 os.Args = append([]string{"application"}, tc.giveArgs...) 119 define(false) 120 121 // 4. Parse (for help) 122 err := Parse() 123 xtesting.Equal(t, errors.Is(err, pflag.ErrHelp), tc.wantHelpError) 124 log.Println(err) // may be "pflag: help requested" 125 126 // 5. MustParse (for help) 127 sb.Reset() 128 exitCode = -1 129 MustParse() 130 if !tc.wantHelpError { 131 xtesting.Equal(t, exitCode, -1) // success 132 } else { 133 xtesting.Equal(t, exitCode, 0) 134 xtesting.Equal(t, strings.Contains(sb.String(), pflag.ErrHelp.Error()), false) 135 } 136 }) 137 } 138 }