github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/configs/parsing_helpers_test.go (about)

     1  package configs
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	v1 "k8s.io/api/core/v1"
     8  	"k8s.io/api/networking/v1beta1"
     9  	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  )
    11  
    12  var configMap = v1.ConfigMap{
    13  	ObjectMeta: meta_v1.ObjectMeta{
    14  		Name:      "test",
    15  		Namespace: "default",
    16  	},
    17  	TypeMeta: meta_v1.TypeMeta{
    18  		Kind:       "ConfigMap",
    19  		APIVersion: "v1",
    20  	},
    21  }
    22  var ingress = v1beta1.Ingress{
    23  	ObjectMeta: meta_v1.ObjectMeta{
    24  		Name:      "test",
    25  		Namespace: "kube-system",
    26  	},
    27  	TypeMeta: meta_v1.TypeMeta{
    28  		Kind:       "Ingress",
    29  		APIVersion: "extensions/v1beta1",
    30  	},
    31  }
    32  
    33  func TestGetMapKeyAsBool(t *testing.T) {
    34  	configMap := configMap
    35  	configMap.Data = map[string]string{
    36  		"key": "True",
    37  	}
    38  
    39  	b, exists, err := GetMapKeyAsBool(configMap.Data, "key", &configMap)
    40  	if !exists {
    41  		t.Errorf("The key 'key' must exist in the configMap")
    42  	}
    43  	if err != nil {
    44  		t.Errorf("Unexpected error: %v", err)
    45  	}
    46  	if b != true {
    47  		t.Errorf("Result should be true")
    48  	}
    49  }
    50  
    51  func TestGetMapKeyAsBoolNotFound(t *testing.T) {
    52  	configMap := configMap
    53  	configMap.Data = map[string]string{}
    54  
    55  	_, exists, _ := GetMapKeyAsBool(configMap.Data, "key", &configMap)
    56  	if exists {
    57  		t.Errorf("The key 'key' must not exist in the configMap")
    58  	}
    59  }
    60  
    61  func TestGetMapKeyAsBoolErrorMessage(t *testing.T) {
    62  	cfgm := configMap
    63  	cfgm.Data = map[string]string{
    64  		"key": "string",
    65  	}
    66  
    67  	// Test with configmap
    68  	_, _, err := GetMapKeyAsBool(cfgm.Data, "key", &cfgm)
    69  	if err == nil {
    70  		t.Error("An error was expected")
    71  	}
    72  	expected := `ConfigMap default/test 'key' contains invalid bool: strconv.ParseBool: parsing "string": invalid syntax, ignoring`
    73  	if err.Error() != expected {
    74  		t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected)
    75  	}
    76  
    77  	// Test with ingress object
    78  	ingress := ingress
    79  	ingress.Annotations = map[string]string{
    80  		"key": "other_string",
    81  	}
    82  
    83  	_, _, err = GetMapKeyAsBool(ingress.Annotations, "key", &ingress)
    84  	if err == nil {
    85  		t.Error("An error was expected")
    86  	}
    87  	expected = `Ingress kube-system/test 'key' contains invalid bool: strconv.ParseBool: parsing "other_string": invalid syntax, ignoring`
    88  	if err.Error() != expected {
    89  		t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected)
    90  	}
    91  }
    92  
    93  func TestGetMapKeyAsInt(t *testing.T) {
    94  	configMap := configMap
    95  	configMap.Data = map[string]string{
    96  		"key": "123456789",
    97  	}
    98  
    99  	i, exists, err := GetMapKeyAsInt(configMap.Data, "key", &configMap)
   100  	if err != nil {
   101  		t.Errorf("Unexpected error: %v", err)
   102  	}
   103  	if !exists {
   104  		t.Errorf("The key 'key' must exist in the configMap")
   105  	}
   106  	expected := 123456789
   107  	if i != expected {
   108  		t.Errorf("Unexpected return value:\nGot: %v\nExpected: %v", i, expected)
   109  	}
   110  }
   111  
   112  func TestGetMapKeyAsIntNotFound(t *testing.T) {
   113  	configMap := configMap
   114  	configMap.Data = map[string]string{}
   115  
   116  	_, exists, _ := GetMapKeyAsInt(configMap.Data, "key", &configMap)
   117  	if exists {
   118  		t.Errorf("The key 'key' must not exist in the configMap")
   119  	}
   120  }
   121  
   122  func TestGetMapKeyAsIntErrorMessage(t *testing.T) {
   123  	cfgm := configMap
   124  	cfgm.Data = map[string]string{
   125  		"key": "string",
   126  	}
   127  
   128  	// Test with configmap
   129  	_, _, err := GetMapKeyAsInt(cfgm.Data, "key", &cfgm)
   130  	if err == nil {
   131  		t.Error("An error was expected")
   132  	}
   133  	expected := `ConfigMap default/test 'key' contains invalid integer: strconv.Atoi: parsing "string": invalid syntax, ignoring`
   134  	if err.Error() != expected {
   135  		t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected)
   136  	}
   137  
   138  	// Test with ingress object
   139  	ingress := ingress
   140  	ingress.Annotations = map[string]string{
   141  		"key": "other_string",
   142  	}
   143  
   144  	_, _, err = GetMapKeyAsInt(ingress.Annotations, "key", &ingress)
   145  	if err == nil {
   146  		t.Error("An error was expected")
   147  	}
   148  	expected = `Ingress kube-system/test 'key' contains invalid integer: strconv.Atoi: parsing "other_string": invalid syntax, ignoring`
   149  	if err.Error() != expected {
   150  		t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected)
   151  	}
   152  }
   153  
   154  func TestGetMapKeyAsInt64(t *testing.T) {
   155  	configMap := configMap
   156  	configMap.Data = map[string]string{
   157  		"key": "123456789",
   158  	}
   159  
   160  	i, exists, err := GetMapKeyAsInt64(configMap.Data, "key", &configMap)
   161  	if err != nil {
   162  		t.Errorf("Unexpected error: %v", err)
   163  	}
   164  	if !exists {
   165  		t.Errorf("The key 'key' must exist in the configMap")
   166  	}
   167  	var expected int64 = 123456789
   168  	if i != expected {
   169  		t.Errorf("Unexpected return value:\nGot: %v\nExpected: %v", i, expected)
   170  	}
   171  }
   172  
   173  func TestGetMapKeyAsInt64NotFound(t *testing.T) {
   174  	configMap := configMap
   175  	configMap.Data = map[string]string{}
   176  
   177  	_, exists, _ := GetMapKeyAsInt64(configMap.Data, "key", &configMap)
   178  	if exists {
   179  		t.Errorf("The key 'key' must not exist in the configMap")
   180  	}
   181  }
   182  
   183  func TestGetMapKeyAsInt64ErrorMessage(t *testing.T) {
   184  	cfgm := configMap
   185  	cfgm.Data = map[string]string{
   186  		"key": "string",
   187  	}
   188  
   189  	// Test with configmap
   190  	_, _, err := GetMapKeyAsInt64(cfgm.Data, "key", &cfgm)
   191  	if err == nil {
   192  		t.Error("An error was expected")
   193  	}
   194  	expected := `ConfigMap default/test 'key' contains invalid integer: strconv.ParseInt: parsing "string": invalid syntax, ignoring`
   195  	if err.Error() != expected {
   196  		t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected)
   197  	}
   198  
   199  	// Test with ingress object
   200  	ingress := ingress
   201  	ingress.Annotations = map[string]string{
   202  		"key": "other_string",
   203  	}
   204  
   205  	_, _, err = GetMapKeyAsInt64(ingress.Annotations, "key", &ingress)
   206  	if err == nil {
   207  		t.Error("An error was expected")
   208  	}
   209  	expected = `Ingress kube-system/test 'key' contains invalid integer: strconv.ParseInt: parsing "other_string": invalid syntax, ignoring`
   210  	if err.Error() != expected {
   211  		t.Errorf("The error message does not match expectations:\nGot: %v\nExpected: %v", err, expected)
   212  	}
   213  }
   214  
   215  func TestGetMapKeyAsStringSlice(t *testing.T) {
   216  	configMap := configMap
   217  	configMap.Data = map[string]string{
   218  		"key": "1.String,2.String,3.String",
   219  	}
   220  
   221  	slice, exists, err := GetMapKeyAsStringSlice(configMap.Data, "key", &configMap, ",")
   222  	if err != nil {
   223  		t.Errorf("Unexpected error: %v", err)
   224  	}
   225  	if !exists {
   226  		t.Errorf("The key 'key' must exist in the configMap")
   227  	}
   228  	expected := []string{"1.String", "2.String", "3.String"}
   229  	t.Log(expected)
   230  	if !reflect.DeepEqual(expected, slice) {
   231  		t.Errorf("Unexpected return value:\nGot: %#v\nExpected: %#v", slice, expected)
   232  	}
   233  
   234  }
   235  
   236  func TestGetMapKeyAsStringSliceMultilineSnippets(t *testing.T) {
   237  	configMap := configMap
   238  	configMap.Data = map[string]string{
   239  		"server-snippets": `
   240  			if ($new_uri) {
   241  				rewrite ^ $new_uri permanent;
   242  			}`,
   243  	}
   244  
   245  	slice, exists, err := GetMapKeyAsStringSlice(configMap.Data, "server-snippets", &configMap, "\n")
   246  	if err != nil {
   247  		t.Errorf("Unexpected error: %v", err)
   248  	}
   249  	if !exists {
   250  		t.Errorf("The key 'server-snippets' must exist in the configMap")
   251  	}
   252  	expected := []string{"", "\t\t\tif ($new_uri) {", "\t\t\t\trewrite ^ $new_uri permanent;", "\t\t\t}"}
   253  	t.Log(expected)
   254  	if !reflect.DeepEqual(expected, slice) {
   255  		t.Errorf("Unexpected return value:\nGot: %#v\nExpected: %#v", slice, expected)
   256  	}
   257  }
   258  
   259  func TestGetMapKeyAsStringSliceNotFound(t *testing.T) {
   260  	configMap := configMap
   261  	configMap.Data = map[string]string{}
   262  
   263  	_, exists, _ := GetMapKeyAsStringSlice(configMap.Data, "key", &configMap, ",")
   264  	if exists {
   265  		t.Errorf("The key 'key' must not exist in the configMap")
   266  	}
   267  }
   268  
   269  func TestParseLBMethod(t *testing.T) {
   270  	var testsWithValidInput = []struct {
   271  		input    string
   272  		expected string
   273  	}{
   274  		{"least_conn", "least_conn"},
   275  		{"round_robin", ""},
   276  		{"ip_hash", "ip_hash"},
   277  		{"random", "random"},
   278  		{"random two", "random two"},
   279  		{"random two least_conn", "random two least_conn"},
   280  		{"hash $request_id", "hash $request_id"},
   281  		{"hash $request_id consistent", "hash $request_id consistent"},
   282  	}
   283  
   284  	var invalidInput = []string{
   285  		"",
   286  		"blabla",
   287  		"least_time header",
   288  		"hash123",
   289  		"hash $request_id conwrongspelling",
   290  		"random one",
   291  		"random two least_time=header",
   292  		"random two least_time=last_byte",
   293  		"random two ip_hash",
   294  	}
   295  
   296  	for _, test := range testsWithValidInput {
   297  		result, err := ParseLBMethod(test.input)
   298  		if err != nil {
   299  			t.Errorf("TestParseLBMethod(%q) returned an error for valid input", test.input)
   300  		}
   301  
   302  		if result != test.expected {
   303  			t.Errorf("TestParseLBMethod(%q) returned %q expected %q", test.input, result, test.expected)
   304  		}
   305  	}
   306  
   307  	for _, input := range invalidInput {
   308  		_, err := ParseLBMethod(input)
   309  		if err == nil {
   310  			t.Errorf("TestParseLBMethod(%q) does not return an error for invalid input", input)
   311  		}
   312  	}
   313  }
   314  
   315  func TestParseLBMethodForPlus(t *testing.T) {
   316  	var testsWithValidInput = []struct {
   317  		input    string
   318  		expected string
   319  	}{
   320  		{"least_conn", "least_conn"},
   321  		{"round_robin", ""},
   322  		{"ip_hash", "ip_hash"},
   323  		{"random", "random"},
   324  		{"random two", "random two"},
   325  		{"random two least_conn", "random two least_conn"},
   326  		{"random two least_time=header", "random two least_time=header"},
   327  		{"random two least_time=last_byte", "random two least_time=last_byte"},
   328  		{"hash $request_id", "hash $request_id"},
   329  		{"least_time header", "least_time header"},
   330  		{"least_time last_byte", "least_time last_byte"},
   331  		{"least_time header inflight", "least_time header inflight"},
   332  		{"least_time last_byte inflight", "least_time last_byte inflight"},
   333  	}
   334  
   335  	var invalidInput = []string{
   336  		"",
   337  		"blabla",
   338  		"hash123",
   339  		"least_time",
   340  		"last_byte",
   341  		"least_time inflight header",
   342  		"random one",
   343  		"random two ip_hash",
   344  		"random two least_time",
   345  	}
   346  
   347  	for _, test := range testsWithValidInput {
   348  		result, err := ParseLBMethodForPlus(test.input)
   349  		if err != nil {
   350  			t.Errorf("TestParseLBMethod(%q) returned an error for valid input", test.input)
   351  		}
   352  
   353  		if result != test.expected {
   354  			t.Errorf("TestParseLBMethod(%q) returned %q expected %q", test.input, result, test.expected)
   355  		}
   356  	}
   357  
   358  	for _, input := range invalidInput {
   359  		_, err := ParseLBMethodForPlus(input)
   360  		if err == nil {
   361  			t.Errorf("TestParseLBMethod(%q) does not return an error for invalid input", input)
   362  		}
   363  	}
   364  }
   365  
   366  func TestParseTime(t *testing.T) {
   367  	var testsWithValidInput = []struct {
   368  		input    string
   369  		expected string
   370  	}{
   371  		{"1h30m 5 100ms", "1h30m5s100ms"},
   372  		{"10ms", "10ms"},
   373  		{"1", "1s"},
   374  		{"5m 30s", "5m30s"},
   375  		{"1s", "1s"},
   376  		{"100m", "100m"},
   377  		{"5w", "5w"},
   378  		{"15m", "15m"},
   379  		{"11M", "11M"},
   380  		{"3h", "3h"},
   381  		{"100y", "100y"},
   382  		{"600", "600s"},
   383  	}
   384  	var invalidInput = []string{"5s 5s", "ss", "rM", "m0m", "s1s", "-5s", "", "1L", "11 11", " ", "   "}
   385  
   386  	for _, test := range testsWithValidInput {
   387  		result, err := ParseTime(test.input)
   388  		if err != nil {
   389  			t.Errorf("TestparseTime(%q) returned an error for valid input", test.input)
   390  		}
   391  
   392  		if result != test.expected {
   393  			t.Errorf("TestparseTime(%q) returned %q expected %q", test.input, result, test.expected)
   394  		}
   395  	}
   396  
   397  	for _, test := range invalidInput {
   398  		result, err := ParseTime(test)
   399  		if err == nil {
   400  			t.Errorf("TestparseTime(%q) didn't return error. Returned: %q", test, result)
   401  		}
   402  	}
   403  }
   404  
   405  func TestParseOffset(t *testing.T) {
   406  	var testsWithValidInput = []string{"1", "2k", "2K", "3m", "3M", "4g", "4G"}
   407  	var invalidInput = []string{"-1", "", "blah"}
   408  	for _, test := range testsWithValidInput {
   409  		result, err := ParseOffset(test)
   410  		if err != nil {
   411  			t.Errorf("TestParseOffset(%q) returned an error for valid input", test)
   412  		}
   413  		if test != result {
   414  			t.Errorf("TestParseOffset(%q) returned %q expected %q", test, result, test)
   415  		}
   416  	}
   417  	for _, test := range invalidInput {
   418  		result, err := ParseOffset(test)
   419  		if err == nil {
   420  			t.Errorf("TestParseOffset(%q) didn't return error. Returned: %q", test, result)
   421  		}
   422  	}
   423  }
   424  
   425  func TestParseSize(t *testing.T) {
   426  	var testsWithValidInput = []string{"1", "2k", "2K", "3m", "3M"}
   427  	var invalidInput = []string{"-1", "", "blah", "4g", "4G"}
   428  	for _, test := range testsWithValidInput {
   429  		result, err := ParseSize(test)
   430  		if err != nil {
   431  			t.Errorf("TestParseSize(%q) returned an error for valid input", test)
   432  		}
   433  		if test != result {
   434  			t.Errorf("TestParseSize(%q) returned %q expected %q", test, result, test)
   435  		}
   436  	}
   437  	for _, test := range invalidInput {
   438  		result, err := ParseSize(test)
   439  		if err == nil {
   440  			t.Errorf("TestParseSize(%q) didn't return error. Returned: %q", test, result)
   441  		}
   442  	}
   443  }
   444  
   445  func TestParseProxyBuffersSpec(t *testing.T) {
   446  	var testsWithValidInput = []string{"1 1k", "10 24k", "2 2K", "6 3m", "128 3M"}
   447  	var invalidInput = []string{"-1", "-6 2k", "", "blah", "16k", "10M", "2 4g", "3 4G"}
   448  	for _, test := range testsWithValidInput {
   449  		result, err := ParseProxyBuffersSpec(test)
   450  		if err != nil {
   451  			t.Errorf("ParseProxyBuffersSpec(%q) returned an error for valid input", test)
   452  		}
   453  		if test != result {
   454  			t.Errorf("TestParseProxyBuffersSpec(%q) returned %q expected %q", test, result, test)
   455  		}
   456  	}
   457  	for _, test := range invalidInput {
   458  		result, err := ParseProxyBuffersSpec(test)
   459  		if err == nil {
   460  			t.Errorf("TestParseProxyBuffersSpec(%q) didn't return error. Returned: %q", test, result)
   461  		}
   462  	}
   463  }
   464  
   465  func TestVerifyThresholds(t *testing.T) {
   466  	validInput := []string{
   467  		"high=3 low=1",
   468  		"high=12 low=2",
   469  		"high=100 low=3",
   470  		"high=12 low=10",
   471  		"high=100 low=11",
   472  		"low=1 high=3",
   473  		"low=2 high=12",
   474  		"low=3 high=100",
   475  		"low=10 high=12",
   476  		"low=11 high=100",
   477  	}
   478  	invalidInput := []string{
   479  		"high=101 low=10",
   480  		"high=101 low=999",
   481  		"high=1 high=1",
   482  		"low=1 low=20",
   483  		"low=",
   484  		"high=12",
   485  		"a string",
   486  	}
   487  	for _, input := range validInput {
   488  		if !VerifyAppProtectThresholds(input) {
   489  			t.Errorf("VerifyAppProtectThresholds(%s) returned false,expected true", input)
   490  		}
   491  	}
   492  	for _, input := range invalidInput {
   493  		if VerifyAppProtectThresholds(input) {
   494  			t.Errorf("VerifyAppProtectThresholds(%s) returned true,expected false", input)
   495  		}
   496  	}
   497  }
   498  
   499  func TestParseBool(t *testing.T) {
   500  	var testsWithValidInput = []struct {
   501  		input    string
   502  		expected bool
   503  	}{
   504  		{"0", false},
   505  		{"1", true},
   506  		{"true", true},
   507  		{"false", false},
   508  	}
   509  
   510  	var invalidInput = []string{
   511  		"",
   512  		"blablah",
   513  		"-100",
   514  		"-1",
   515  	}
   516  
   517  	for _, test := range testsWithValidInput {
   518  		result, err := ParseBool(test.input)
   519  		if err != nil {
   520  			t.Errorf("TestParseBool(%q) returned an error for valid input", test.input)
   521  		}
   522  
   523  		if result != test.expected {
   524  			t.Errorf("TestParseBool(%q) returned %t expected %t", test.input, result, test.expected)
   525  		}
   526  	}
   527  
   528  	for _, input := range invalidInput {
   529  		_, err := ParseBool(input)
   530  		if err == nil {
   531  			t.Errorf("TestParseBool(%q) does not return an error for invalid input", input)
   532  		}
   533  	}
   534  }
   535  
   536  func TestParseInt(t *testing.T) {
   537  	var testsWithValidInput = []struct {
   538  		input    string
   539  		expected int
   540  	}{
   541  		{"0", 0},
   542  		{"1", 1},
   543  		{"-100", -100},
   544  		{"123456789", 123456789},
   545  	}
   546  
   547  	var invalidInput = []string{
   548  		"",
   549  		"blablah",
   550  		"10000000000000000000000000000000000000000000000000000000000000000",
   551  		"1,000",
   552  	}
   553  
   554  	for _, test := range testsWithValidInput {
   555  		result, err := ParseInt(test.input)
   556  		if err != nil {
   557  			t.Errorf("TestParseInt(%q) returned an error for valid input", test.input)
   558  		}
   559  
   560  		if result != test.expected {
   561  			t.Errorf("TestParseInt(%q) returned %d expected %d", test.input, result, test.expected)
   562  		}
   563  	}
   564  
   565  	for _, input := range invalidInput {
   566  		_, err := ParseInt(input)
   567  		if err == nil {
   568  			t.Errorf("TestParseInt(%q) does not return an error for invalid input", input)
   569  		}
   570  	}
   571  }
   572  
   573  func TestParseInt64(t *testing.T) {
   574  	var testsWithValidInput = []struct {
   575  		input    string
   576  		expected int64
   577  	}{
   578  		{"0", 0},
   579  		{"1", 1},
   580  		{"-100", -100},
   581  		{"123456789", 123456789},
   582  	}
   583  
   584  	var invalidInput = []string{
   585  		"",
   586  		"blablah",
   587  		"10000000000000000000000000000000000000000000000000000000000000000",
   588  		"1,000",
   589  	}
   590  
   591  	for _, test := range testsWithValidInput {
   592  		result, err := ParseInt64(test.input)
   593  		if err != nil {
   594  			t.Errorf("TestParseInt64(%q) returned an error for valid input", test.input)
   595  		}
   596  
   597  		if result != test.expected {
   598  			t.Errorf("TestParseInt64(%q) returned %d expected %d", test.input, result, test.expected)
   599  		}
   600  	}
   601  
   602  	for _, input := range invalidInput {
   603  		_, err := ParseInt64(input)
   604  		if err == nil {
   605  			t.Errorf("TestParseInt64(%q) does not return an error for invalid input", input)
   606  		}
   607  	}
   608  }
   609  
   610  func TestParseUint64(t *testing.T) {
   611  	var testsWithValidInput = []struct {
   612  		input    string
   613  		expected uint64
   614  	}{
   615  		{"0", 0},
   616  		{"1", 1},
   617  		{"100", 100},
   618  		{"123456789", 123456789},
   619  	}
   620  
   621  	var invalidInput = []string{
   622  		"",
   623  		"blablah",
   624  		"10000000000000000000000000000000000000000000000000000000000000000",
   625  		"1,000",
   626  		"-1023",
   627  	}
   628  
   629  	for _, test := range testsWithValidInput {
   630  		result, err := ParseUint64(test.input)
   631  		if err != nil {
   632  			t.Errorf("TestParseUint64(%q) returned an error for valid input", test.input)
   633  		}
   634  
   635  		if result != test.expected {
   636  			t.Errorf("TestParseUint64(%q) returned %d expected %d", test.input, result, test.expected)
   637  		}
   638  	}
   639  
   640  	for _, input := range invalidInput {
   641  		_, err := ParseUint64(input)
   642  		if err == nil {
   643  			t.Errorf("TestParseUint64(%q) does not return an error for invalid input", input)
   644  		}
   645  	}
   646  }