github.com/wangyougui/gf/v2@v2.6.5/os/gcmd/gcmd_z_unit_test.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 // go test *.go -bench=".*" -benchmem 8 9 package gcmd_test 10 11 import ( 12 "context" 13 "fmt" 14 "os" 15 "strings" 16 "testing" 17 18 "github.com/wangyougui/gf/v2/errors/gcode" 19 "github.com/wangyougui/gf/v2/errors/gerror" 20 "github.com/wangyougui/gf/v2/frame/g" 21 "github.com/wangyougui/gf/v2/os/gcmd" 22 "github.com/wangyougui/gf/v2/os/gctx" 23 "github.com/wangyougui/gf/v2/os/genv" 24 "github.com/wangyougui/gf/v2/test/gtest" 25 ) 26 27 func Test_Default(t *testing.T) { 28 gtest.C(t, func(t *gtest.T) { 29 gcmd.Init([]string{"gf", "--force", "remove", "-fq", "-p=www", "path", "-n", "root"}...) 30 t.Assert(len(gcmd.GetArgAll()), 2) 31 t.Assert(gcmd.GetArg(1), "path") 32 t.Assert(gcmd.GetArg(100, "test"), "test") 33 t.Assert(gcmd.GetOpt("force"), "remove") 34 t.Assert(gcmd.GetOpt("n"), "root") 35 t.Assert(gcmd.GetOpt("fq").IsNil(), false) 36 t.Assert(gcmd.GetOpt("p").IsNil(), false) 37 t.Assert(gcmd.GetOpt("none").IsNil(), true) 38 t.Assert(gcmd.GetOpt("none", "value"), "value") 39 }) 40 gtest.C(t, func(t *gtest.T) { 41 gcmd.Init([]string{"gf", "gen", "-h"}...) 42 t.Assert(len(gcmd.GetArgAll()), 2) 43 t.Assert(gcmd.GetOpt("h"), "") 44 t.Assert(gcmd.GetOpt("h").IsNil(), false) 45 }) 46 } 47 48 func Test_BuildOptions(t *testing.T) { 49 gtest.C(t, func(t *gtest.T) { 50 s := gcmd.BuildOptions(g.MapStrStr{ 51 "n": "john", 52 }) 53 t.Assert(s, "-n=john") 54 }) 55 56 gtest.C(t, func(t *gtest.T) { 57 s := gcmd.BuildOptions(g.MapStrStr{ 58 "n": "john", 59 }, "-test") 60 t.Assert(s, "-testn=john") 61 }) 62 63 gtest.C(t, func(t *gtest.T) { 64 s := gcmd.BuildOptions(g.MapStrStr{ 65 "n1": "john", 66 "n2": "huang", 67 }) 68 t.Assert(strings.Contains(s, "-n1=john"), true) 69 t.Assert(strings.Contains(s, "-n2=huang"), true) 70 }) 71 } 72 73 func Test_GetWithEnv(t *testing.T) { 74 gtest.C(t, func(t *gtest.T) { 75 genv.Set("TEST", "1") 76 defer genv.Remove("TEST") 77 t.Assert(gcmd.GetOptWithEnv("test"), 1) 78 }) 79 gtest.C(t, func(t *gtest.T) { 80 genv.Set("TEST", "1") 81 defer genv.Remove("TEST") 82 gcmd.Init("-test", "2") 83 t.Assert(gcmd.GetOptWithEnv("test"), 2) 84 }) 85 } 86 87 func Test_Command(t *testing.T) { 88 gtest.C(t, func(t *gtest.T) { 89 var ( 90 ctx = gctx.New() 91 err error 92 ) 93 commandRoot := &gcmd.Command{ 94 Name: "gf", 95 } 96 // env 97 commandEnv := &gcmd.Command{ 98 Name: "env", 99 Func: func(ctx context.Context, parser *gcmd.Parser) error { 100 fmt.Println("env") 101 return nil 102 }, 103 } 104 // test 105 commandTest := &gcmd.Command{ 106 Name: "test", 107 Brief: "test brief", 108 Description: "test description current Golang environment variables", 109 Examples: ` 110 gf get github.com/wangyougui/gf 111 gf get github.com/wangyougui/gf@latest 112 gf get github.com/wangyougui/gf@master 113 gf get golang.org/x/sys 114 `, 115 Arguments: []gcmd.Argument{ 116 { 117 Name: "my-option", 118 Short: "o", 119 Brief: "It's my custom option", 120 Orphan: true, 121 }, 122 { 123 Name: "another", 124 Short: "a", 125 Brief: "It's my another custom option", 126 Orphan: true, 127 }, 128 }, 129 Func: func(ctx context.Context, parser *gcmd.Parser) error { 130 fmt.Println("test") 131 return nil 132 }, 133 } 134 err = commandRoot.AddCommand( 135 commandEnv, 136 ) 137 if err != nil { 138 g.Log().Fatal(ctx, err) 139 } 140 err = commandRoot.AddObject( 141 commandTest, 142 ) 143 if err != nil { 144 g.Log().Fatal(ctx, err) 145 } 146 147 if err = commandRoot.RunWithError(ctx); err != nil { 148 if gerror.Code(err) == gcode.CodeNotFound { 149 commandRoot.Print() 150 } 151 } 152 }) 153 } 154 155 func Test_Command_Print(t *testing.T) { 156 gtest.C(t, func(t *gtest.T) { 157 var ( 158 ctx = gctx.New() 159 err error 160 ) 161 c := &gcmd.Command{ 162 Name: "gf", 163 Description: `GoFrame Command Line Interface, which is your helpmate for building GoFrame application with convenience.`, 164 Additional: ` 165 Use 'gf help COMMAND' or 'gf COMMAND -h' for detail about a command, which has '...' in the tail of their comments.`, 166 } 167 // env 168 commandEnv := &gcmd.Command{ 169 Name: "env", 170 Brief: "show current Golang environment variables, long brief.long brief.long brief.long brief.long brief.long brief.long brief.long brief.", 171 Description: "show current Golang environment variables", 172 Func: func(ctx context.Context, parser *gcmd.Parser) error { 173 return nil 174 }, 175 } 176 if err = c.AddCommand(commandEnv); err != nil { 177 g.Log().Fatal(ctx, err) 178 } 179 // get 180 commandGet := &gcmd.Command{ 181 Name: "get", 182 Brief: "install or update GF to system in default...", 183 Description: "show current Golang environment variables", 184 185 Examples: ` 186 gf get github.com/wangyougui/gf 187 gf get github.com/wangyougui/gf@latest 188 gf get github.com/wangyougui/gf@master 189 gf get golang.org/x/sys 190 `, 191 Func: func(ctx context.Context, parser *gcmd.Parser) error { 192 return nil 193 }, 194 } 195 if err = c.AddCommand(commandGet); err != nil { 196 g.Log().Fatal(ctx, err) 197 } 198 // build 199 //-n, --name output binary name 200 //-v, --version output binary version 201 //-a, --arch output binary architecture, multiple arch separated with ',' 202 //-s, --system output binary system, multiple os separated with ',' 203 //-o, --output output binary path, used when building single binary file 204 //-p, --path output binary directory path, default is './bin' 205 //-e, --extra extra custom "go build" options 206 //-m, --mod like "-mod" option of "go build", use "-m none" to disable go module 207 //-c, --cgo enable or disable cgo feature, it's disabled in default 208 209 commandBuild := gcmd.Command{ 210 Name: "build", 211 Usage: "gf build FILE [OPTION]", 212 Brief: "cross-building go project for lots of platforms...", 213 Description: ` 214 The "build" command is most commonly used command, which is designed as a powerful wrapper for 215 "go build" command for convenience cross-compiling usage. 216 It provides much more features for building binary: 217 1. Cross-Compiling for many platforms and architectures. 218 2. Configuration file support for compiling. 219 3. Build-In Variables. 220 `, 221 Examples: ` 222 gf build main.go 223 gf build main.go --swagger 224 gf build main.go --pack public,template 225 gf build main.go --cgo 226 gf build main.go -m none 227 gf build main.go -n my-app -a all -s all 228 gf build main.go -n my-app -a amd64,386 -s linux -p . 229 gf build main.go -n my-app -v 1.0 -a amd64,386 -s linux,windows,darwin -p ./docker/bin 230 `, 231 Func: func(ctx context.Context, parser *gcmd.Parser) error { 232 return nil 233 }, 234 } 235 if err = c.AddCommand(&commandBuild); err != nil { 236 g.Log().Fatal(ctx, err) 237 } 238 _ = c.RunWithError(ctx) 239 }) 240 } 241 242 func Test_Command_NotFound(t *testing.T) { 243 gtest.C(t, func(t *gtest.T) { 244 c0 := &gcmd.Command{ 245 Name: "c0", 246 } 247 c1 := &gcmd.Command{ 248 Name: "c1", 249 FuncWithValue: func(ctx context.Context, parser *gcmd.Parser) (interface{}, error) { 250 return nil, nil 251 }, 252 } 253 c21 := &gcmd.Command{ 254 Name: "c21", 255 FuncWithValue: func(ctx context.Context, parser *gcmd.Parser) (interface{}, error) { 256 return nil, nil 257 }, 258 } 259 c22 := &gcmd.Command{ 260 Name: "c22", 261 FuncWithValue: func(ctx context.Context, parser *gcmd.Parser) (interface{}, error) { 262 return nil, nil 263 }, 264 } 265 t.AssertNil(c0.AddCommand(c1)) 266 t.AssertNil(c1.AddCommand(c21, c22)) 267 268 os.Args = []string{"c0", "c1", "c23", `--test="abc"`} 269 err := c0.RunWithError(gctx.New()) 270 t.Assert(err.Error(), `command "c1 c23" not found for command "c0", command line: c0 c1 c23 --test="abc"`) 271 }) 272 }