github.com/facebookincubator/ttpforge@v1.0.13-0.20240405153150-5ae801628835/pkg/args/spec_test.go (about)

     1  /*
     2  Copyright © 2023-present, Meta Platforms, Inc. and affiliates
     3  Permission is hereby granted, free of charge, to any person obtaining a copy
     4  of this software and associated documentation files (the "Software"), to deal
     5  in the Software without restriction, including without limitation the rights
     6  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  copies of the Software, and to permit persons to whom the Software is
     8  furnished to do so, subject to the following conditions:
     9  The above copyright notice and this permission notice shall be included in
    10  all copies or substantial portions of the Software.
    11  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    12  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    13  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    14  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    15  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    16  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    17  THE SOFTWARE.
    18  */
    19  
    20  package args
    21  
    22  import (
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  	"github.com/stretchr/testify/require"
    27  )
    28  
    29  type validateTestCase struct {
    30  	name           string
    31  	specs          []Spec
    32  	argKvStrs      []string
    33  	expectedResult map[string]any
    34  	wantError      bool
    35  }
    36  
    37  func checkValidateTestCase(t *testing.T, tc validateTestCase) {
    38  	args, err := ParseAndValidate(tc.specs, tc.argKvStrs)
    39  	if tc.wantError {
    40  		require.Error(t, err)
    41  		return
    42  	}
    43  	require.NoError(t, err)
    44  	assert.Equal(t, tc.expectedResult, args)
    45  }
    46  
    47  func TestValidateArgs(t *testing.T) {
    48  
    49  	testCases := []validateTestCase{
    50  		{
    51  			name: "Parse String and Integer Arguments",
    52  			specs: []Spec{
    53  				{
    54  					Name: "alpha",
    55  				},
    56  				{
    57  					Name: "beta",
    58  					Type: "int",
    59  				},
    60  			},
    61  			argKvStrs: []string{
    62  				"alpha=foo",
    63  				"beta=3",
    64  			},
    65  			expectedResult: map[string]any{
    66  				"alpha": "foo",
    67  				"beta":  3,
    68  			},
    69  			wantError: false,
    70  		},
    71  		{
    72  			name: "Parse String and Integer Argument (Default Value)",
    73  			specs: []Spec{
    74  				{
    75  					Name: "alpha",
    76  				},
    77  				{
    78  					Name:    "beta",
    79  					Type:    "int",
    80  					Default: "1337",
    81  				},
    82  			},
    83  			argKvStrs: []string{
    84  				"alpha=foo",
    85  			},
    86  			expectedResult: map[string]any{
    87  				"alpha": "foo",
    88  				"beta":  1337,
    89  			},
    90  			wantError: false,
    91  		},
    92  		{
    93  			name: "Handle Extra Equals",
    94  			specs: []Spec{
    95  				{
    96  					Name: "alpha",
    97  				},
    98  				{
    99  					Name: "beta",
   100  				},
   101  			},
   102  			argKvStrs: []string{
   103  				"alpha=foo",
   104  				"beta=bar=baz",
   105  			},
   106  			expectedResult: map[string]any{
   107  				"alpha": "foo",
   108  				"beta":  "bar=baz",
   109  			},
   110  			wantError: false,
   111  		},
   112  		{
   113  			name: "Invalid Inputs (no '=')",
   114  			specs: []Spec{
   115  				{
   116  					Name: "alpha",
   117  				},
   118  				{
   119  					Name: "beta",
   120  				},
   121  			},
   122  			argKvStrs: []string{
   123  				"alpha=foo",
   124  				"wut",
   125  			},
   126  			wantError: true,
   127  		},
   128  		{
   129  			name: "Invalid Inputs (Missing Required Argument)",
   130  			specs: []Spec{
   131  				{
   132  					Name: "alpha",
   133  				},
   134  				{
   135  					Name: "beta",
   136  				},
   137  			},
   138  			argKvStrs: []string{
   139  				"alpha=foo",
   140  			},
   141  			wantError: true,
   142  		},
   143  		{
   144  			name: "Argument Name Not In Specs",
   145  			specs: []Spec{
   146  				{
   147  					Name: "alpha",
   148  				},
   149  				{
   150  					Name: "beta",
   151  				},
   152  			},
   153  			argKvStrs: []string{
   154  				"alpha=foo",
   155  				"gamma=bar",
   156  			},
   157  			wantError: true,
   158  		},
   159  		{
   160  			name: "Duplicate Name in Specs",
   161  			specs: []Spec{
   162  				{
   163  					Name: "alpha",
   164  				},
   165  				{
   166  					Name: "alpha",
   167  				},
   168  			},
   169  			argKvStrs: []string{
   170  				"alpha=foo",
   171  			},
   172  			wantError: true,
   173  		},
   174  		{
   175  			name: "Wrong Type (string instead of int)",
   176  			specs: []Spec{
   177  				{
   178  					Name: "alpha",
   179  				},
   180  				{
   181  					Name: "beta",
   182  					Type: "int",
   183  				},
   184  			},
   185  			argKvStrs: []string{
   186  				"alpha=foo",
   187  				"beta=bar",
   188  			},
   189  			wantError: true,
   190  		},
   191  		{
   192  			name: "Default Value Wrong Type (string instead of int)",
   193  			specs: []Spec{
   194  				{
   195  					Name:    "alpha",
   196  					Type:    "int",
   197  					Default: "wut",
   198  				},
   199  			},
   200  			argKvStrs: []string{
   201  				"alpha=1337",
   202  			},
   203  			wantError: true,
   204  		},
   205  		{
   206  			name: "Format with valid value",
   207  			specs: []Spec{
   208  				{
   209  					Name:   "alpha",
   210  					Type:   "string",
   211  					Format: "[A-Z_]+",
   212  				},
   213  			},
   214  			argKvStrs: []string{
   215  				"alpha=CECI_NEST_PAS_UNE_INT",
   216  			},
   217  			expectedResult: map[string]any{
   218  				"alpha": "CECI_NEST_PAS_UNE_INT",
   219  			},
   220  			wantError: false,
   221  		},
   222  		{
   223  			name: "Format (Flexible Match; No Error)",
   224  			specs: []Spec{
   225  				{
   226  					Name:   "alpha",
   227  					Type:   "string",
   228  					Format: "ab",
   229  				},
   230  			},
   231  			argKvStrs: []string{
   232  				"alpha=xabyabz",
   233  			},
   234  			expectedResult: map[string]any{
   235  				"alpha": "xabyabz",
   236  			},
   237  		},
   238  		{
   239  			name: "Format (Strict Match; No Error)",
   240  			specs: []Spec{
   241  				{
   242  					Name:   "alpha",
   243  					Type:   "string",
   244  					Format: "^ab$",
   245  				},
   246  			},
   247  			argKvStrs: []string{
   248  				"alpha=ab",
   249  			},
   250  			expectedResult: map[string]any{
   251  				"alpha": "ab",
   252  			},
   253  		},
   254  		{
   255  			name: "Format (Strict Match; Error)",
   256  			specs: []Spec{
   257  				{
   258  					Name:   "alpha",
   259  					Type:   "string",
   260  					Format: "^ab$",
   261  				},
   262  			},
   263  			argKvStrs: []string{
   264  				"alpha=xaby",
   265  			},
   266  			wantError: true,
   267  		},
   268  		{
   269  			name: "Format with proper end and beginning tags",
   270  			specs: []Spec{
   271  				{
   272  					Name:   "alpha",
   273  					Type:   "string",
   274  					Format: "^[A-Z_-]+$",
   275  				},
   276  			},
   277  			argKvStrs: []string{
   278  				"alpha=CECI_NEST_PAS_UNE_INT-",
   279  			},
   280  			expectedResult: map[string]any{
   281  				"alpha": "CECI_NEST_PAS_UNE_INT-",
   282  			},
   283  			wantError: false,
   284  		},
   285  		{
   286  			name: "Format with improper regex",
   287  			specs: []Spec{
   288  				{
   289  					Name:   "alpha",
   290  					Type:   "string",
   291  					Format: "^[A-Z_-]+[$$",
   292  				},
   293  			},
   294  			argKvStrs: []string{
   295  				"alpha=CECI_NEST_PAS_UNE_INT-",
   296  			},
   297  			wantError: true,
   298  		},
   299  	}
   300  
   301  	for _, tc := range testCases {
   302  		t.Run(tc.name, func(t *testing.T) {
   303  			checkValidateTestCase(t, tc)
   304  		})
   305  	}
   306  
   307  }