github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/utils/argparser/args_test.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package argparser 16 17 import ( 18 "reflect" 19 "testing" 20 21 "github.com/stretchr/testify/assert" 22 "github.com/stretchr/testify/require" 23 ) 24 25 var forceOpt = &Option{"force", "f", "", OptionalFlag, "force desc", nil} 26 var messageOpt = &Option{"message", "m", "msg", OptionalValue, "msg desc", nil} 27 var fileTypeOpt = &Option{"file-type", "", "", OptionalValue, "file type", nil} 28 29 func TestParsing(t *testing.T) { 30 tests := []struct { 31 name string 32 options []*Option 33 args []string 34 expectedOpts map[string]string 35 expectedArgs []string 36 expectedErr string 37 }{ 38 { 39 name: "empty", 40 options: []*Option{}, 41 args: []string{}, 42 expectedOpts: map[string]string{}, 43 expectedArgs: []string{}, 44 }, 45 { 46 name: "no options", 47 options: []*Option{}, 48 args: []string{"a", "b", "c"}, 49 expectedOpts: map[string]string{}, 50 expectedArgs: []string{"a", "b", "c"}, 51 }, 52 { 53 name: "-h", 54 options: []*Option{}, 55 args: []string{"a", "-h", "c"}, 56 expectedErr: "Help", 57 }, 58 { 59 name: "--help", 60 options: []*Option{}, 61 args: []string{"a", "--help", "c"}, 62 expectedErr: "Help", 63 }, 64 { 65 name: "force", 66 options: []*Option{forceOpt}, 67 args: []string{"--force", "b", "c"}, 68 expectedOpts: map[string]string{"force": ""}, 69 expectedArgs: []string{"b", "c"}, 70 }, 71 { 72 name: "force abbrev", 73 options: []*Option{forceOpt}, 74 args: []string{"b", "-f", "c"}, 75 expectedOpts: map[string]string{"force": ""}, 76 expectedArgs: []string{"b", "c"}, 77 }, 78 { 79 name: "message", 80 options: []*Option{forceOpt, messageOpt}, 81 args: []string{"-m", "b", "c"}, 82 expectedOpts: map[string]string{"message": "b"}, 83 expectedArgs: []string{"c"}, 84 }, 85 { 86 name: "message equals value", 87 options: []*Option{forceOpt, messageOpt}, 88 args: []string{"b", "--message=value", "c"}, 89 expectedOpts: map[string]string{"message": "value"}, 90 expectedArgs: []string{"b", "c"}, 91 }, 92 { 93 name: "message colon value", 94 options: []*Option{forceOpt, messageOpt}, 95 args: []string{"b", "--message:value", "c"}, 96 expectedOpts: map[string]string{"message": "value"}, 97 expectedArgs: []string{"b", "c"}, 98 }, 99 { 100 name: "empty string", 101 options: []*Option{forceOpt, messageOpt}, 102 args: []string{"b", "--message=value", ""}, 103 expectedOpts: map[string]string{"message": "value"}, 104 expectedArgs: []string{"b", ""}, 105 }, 106 { 107 name: "value attached to flag", 108 options: []*Option{forceOpt}, 109 args: []string{"-fvalue"}, 110 expectedOpts: map[string]string{"force": ""}, 111 expectedArgs: []string{"value"}, 112 }, 113 { 114 name: "-mvalue", 115 options: []*Option{forceOpt, messageOpt}, 116 args: []string{"b", "-mvalue", "c"}, 117 expectedOpts: map[string]string{"message": "value"}, 118 expectedArgs: []string{"b", "c"}, 119 }, 120 { 121 name: "--messagevalue", 122 options: []*Option{forceOpt, messageOpt}, 123 args: []string{"b", "-messagevalue", "c"}, 124 expectedOpts: map[string]string{"message": "value"}, 125 expectedArgs: []string{"b", "c"}, 126 }, 127 { 128 name: "-fmfootball", 129 options: []*Option{forceOpt, messageOpt}, 130 args: []string{"-fmfootball"}, 131 expectedOpts: map[string]string{"message": "football", "force": ""}, 132 expectedArgs: []string{}, 133 }, 134 { 135 name: "-ffootball", 136 options: []*Option{forceOpt, messageOpt}, 137 args: []string{"-ffootball"}, 138 expectedOpts: map[string]string{"force": ""}, 139 expectedArgs: []string{"football"}, 140 }, 141 { 142 name: "-mf", 143 options: []*Option{forceOpt, messageOpt}, 144 args: []string{"-mf"}, 145 expectedOpts: map[string]string{"message": "f"}, 146 expectedArgs: []string{}, 147 }, 148 { 149 name: "-fm", 150 options: []*Option{forceOpt, messageOpt}, 151 args: []string{"-fm"}, 152 expectedErr: "error: no value for option `m'", 153 }, 154 { 155 name: "-mf value", 156 options: []*Option{forceOpt, messageOpt}, 157 args: []string{"-mf", "value"}, 158 expectedOpts: map[string]string{"message": "f"}, 159 expectedArgs: []string{"value"}, 160 }, 161 { 162 name: "-fm value", 163 options: []*Option{forceOpt, messageOpt}, 164 args: []string{"-fm", "value"}, 165 expectedOpts: map[string]string{"message": "value", "force": ""}, 166 expectedArgs: []string{}, 167 }, 168 { 169 name: "file-type not force", 170 options: []*Option{forceOpt, messageOpt, fileTypeOpt}, 171 args: []string{"--file-type=csv"}, 172 expectedOpts: map[string]string{"file-type": "csv"}, 173 expectedArgs: []string{}, 174 }, 175 { 176 name: "unsupported arg", 177 options: []*Option{forceOpt, messageOpt}, 178 args: []string{"-v"}, 179 expectedErr: "error: unknown option `v'", 180 }, 181 { 182 name: "duplicate arg", 183 options: []*Option{forceOpt, messageOpt}, 184 args: []string{"-f", "-f"}, 185 expectedErr: "error: multiple values provided for `force'", 186 }, 187 } 188 189 for _, test := range tests { 190 t.Run(test.name, func(t *testing.T) { 191 parser := NewArgParser() 192 193 for _, opt := range test.options { 194 parser.SupportOption(opt) 195 } 196 197 exp := &ArgParseResults{test.expectedOpts, test.expectedArgs, parser} 198 199 res, err := parser.Parse(test.args) 200 if test.expectedErr != "" { 201 require.Error(t, err, test.expectedErr) 202 } else { 203 require.NoError(t, err) 204 assert.Equal(t, exp, res) 205 } 206 }) 207 } 208 } 209 210 func TestValidation(t *testing.T) { 211 ap := NewArgParser() 212 ap.SupportsString("string", "s", "string_value", "A string") 213 ap.SupportsString("string2", "", "string_value", "Another string") 214 ap.SupportsFlag("flag", "f", "A flag") 215 ap.SupportsFlag("flag2", "", "Another flag") 216 ap.SupportsInt("integer", "n", "num", "A number") 217 ap.SupportsInt("integer2", "", "num", "Another number") 218 apr, err := ap.Parse([]string{"-s", "string", "--flag", "--n", "1234", "a", "b", "c"}) 219 220 if err != nil { 221 t.Fatal(err.Error()) 222 } 223 224 if !apr.ContainsAll("string", "flag", "integer") { 225 t.Error("Missing expected parameter(s)") 226 } 227 228 if apr.ContainsAny("string2", "flag2", "integer2") { 229 t.Error("Contains unexpected parameter(s)") 230 } 231 232 if val := apr.MustGetValue("string"); val != "string" { 233 t.Error("Bad val for -string") 234 } 235 236 if val := apr.GetValueOrDefault("string2", "default"); val != "default" { 237 t.Error("Bad val for -string2") 238 } 239 240 if _, ok := apr.GetValue("string2"); ok { 241 t.Error("Should not be able to get missing parameter string2") 242 } 243 244 if val, ok := apr.GetValue("string"); !ok || val != "string" { 245 t.Error("Bad val for --string") 246 } 247 248 if val, ok := apr.GetInt("integer"); !ok || val != 1234 { 249 t.Error("Bad val for --integer") 250 } 251 252 if val := apr.GetIntOrDefault("integer2", 5678); val != 5678 { 253 t.Error("Bad val for --integer2") 254 } 255 256 trueFlags := apr.AnyFlagsEqualTo(true) 257 falseFlags := apr.AnyFlagsEqualTo(false) 258 259 if trueFlags.Size() != 1 || falseFlags.Size() != 1 { 260 t.Error("AnyFlagsEqualTo error") 261 } 262 263 trueSet := apr.FlagsEqualTo([]string{"flag"}, true) 264 falseSet := apr.FlagsEqualTo([]string{"flag"}, false) 265 266 if trueSet.Size() != 1 && falseSet.Size() != 0 { 267 t.Error("FlagsEqualTo error") 268 } 269 270 expectedArgs := []string{"a", "b", "c"} 271 272 if apr.NArg() != 3 || apr.Arg(0) != "a" || !reflect.DeepEqual(apr.args, expectedArgs) { 273 t.Error("Arg list issues") 274 } 275 }