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  }