istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/util/util_test.go (about)

     1  // Copyright Istio Authors
     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 util
    16  
    17  import (
    18  	"errors"
    19  	"testing"
    20  )
    21  
    22  func TestParseValue(t *testing.T) {
    23  	tests := []struct {
    24  		desc string
    25  		in   string
    26  		want any
    27  	}{
    28  		{
    29  			desc: "empty",
    30  			in:   "",
    31  			want: "",
    32  		},
    33  		{
    34  			desc: "true",
    35  			in:   "true",
    36  			want: true,
    37  		},
    38  		{
    39  			desc: "false",
    40  			in:   "false",
    41  			want: false,
    42  		},
    43  		{
    44  			desc: "numeric-one",
    45  			in:   "1",
    46  			want: 1,
    47  		},
    48  		{
    49  			desc: "numeric-zero",
    50  			in:   "0",
    51  			want: 0,
    52  		},
    53  		{
    54  			desc: "numeric-large",
    55  			in:   "12345678",
    56  			want: 12345678,
    57  		},
    58  		{
    59  			desc: "numeric-negative",
    60  			in:   "-12345678",
    61  			want: -12345678,
    62  		},
    63  		{
    64  			desc: "float",
    65  			in:   "1.23456",
    66  			want: 1.23456,
    67  		},
    68  		{
    69  			desc: "float-zero",
    70  			in:   "0.00",
    71  			want: 0.00,
    72  		},
    73  		{
    74  			desc: "float-negative",
    75  			in:   "-6.54321",
    76  			want: -6.54321,
    77  		},
    78  		{
    79  			desc: "string",
    80  			in:   "foobar",
    81  			want: "foobar",
    82  		},
    83  		{
    84  			desc: "string-number-prefix",
    85  			in:   "123foobar",
    86  			want: "123foobar",
    87  		},
    88  	}
    89  	for _, tt := range tests {
    90  		t.Run(tt.desc, func(t *testing.T) {
    91  			if got, want := ParseValue(tt.in), tt.want; !(got == want) {
    92  				t.Errorf("%s: got:%v, want:%v", tt.desc, got, want)
    93  			}
    94  		})
    95  	}
    96  }
    97  
    98  func TestConsolidateLog(t *testing.T) {
    99  	tests := []struct {
   100  		desc string
   101  		in   string
   102  		want string
   103  	}{
   104  		{
   105  			desc: "empty",
   106  			in:   "",
   107  			want: "",
   108  		},
   109  		{
   110  			desc: "2 errors once",
   111  			in:   "err1\nerr2\n",
   112  			want: "err1 (repeated 1 times)\nerr2 (repeated 1 times)\n",
   113  		},
   114  		{
   115  			desc: "3 errors multiple times",
   116  			in:   "err1\nerr2\nerr3\nerr1\nerr2\nerr3\nerr3\nerr3\n",
   117  			want: "err1 (repeated 2 times)\nerr2 (repeated 2 times)\nerr3 (repeated 4 times)\n",
   118  		},
   119  	}
   120  	for _, tt := range tests {
   121  		t.Run(tt.desc, func(t *testing.T) {
   122  			if got, want := ConsolidateLog(tt.in), tt.want; !(got == want) {
   123  				t.Errorf("%s: got:%s, want:%s", tt.desc, got, want)
   124  			}
   125  		})
   126  	}
   127  }
   128  
   129  func TestStringBoolMapToSlice(t *testing.T) {
   130  	tests := []struct {
   131  		desc string
   132  		in   map[string]bool
   133  		want []string
   134  	}{
   135  		{
   136  			desc: "empty",
   137  			in:   make(map[string]bool),
   138  			want: make([]string, 0),
   139  		},
   140  		{
   141  			desc: "",
   142  			in: map[string]bool{
   143  				"yo":           true,
   144  				"yolo":         false,
   145  				"test1":        true,
   146  				"water bottle": false,
   147  				"baseball hat": true,
   148  			},
   149  			want: []string{
   150  				"yo",
   151  				"test1",
   152  				"baseball hat",
   153  			},
   154  		},
   155  	}
   156  	for _, tt := range tests {
   157  		t.Run(tt.desc, func(t *testing.T) {
   158  			if got, want := StringBoolMapToSlice(tt.in), tt.want; !(sameStringSlice(got, want)) {
   159  				t.Errorf("%s: got:%s, want: %s", tt.desc, got, want)
   160  			}
   161  		})
   162  	}
   163  }
   164  
   165  // Helper function to check if values in 2 slices are the same,
   166  // no correspondence to order
   167  func sameStringSlice(x, y []string) bool {
   168  	if len(x) != len(y) {
   169  		return false
   170  	}
   171  	diff := make(map[string]int, len(x))
   172  	for _, _x := range x {
   173  		diff[_x]++
   174  	}
   175  	for _, _y := range y {
   176  		if _, ok := diff[_y]; !ok {
   177  			return false
   178  		}
   179  		diff[_y]--
   180  		if diff[_y] == 0 {
   181  			delete(diff, _y)
   182  		}
   183  	}
   184  	return len(diff) == 0
   185  }
   186  
   187  func TestRenderTemplate(t *testing.T) {
   188  	type tmplValue struct {
   189  		Name  string
   190  		Proxy string
   191  	}
   192  	tests := []struct {
   193  		desc     string
   194  		template string
   195  		in       tmplValue
   196  		want     string
   197  		err      error
   198  	}{
   199  		{
   200  			desc:     "valid-template",
   201  			template: "{{.Name}} uses {{.Proxy}} as sidecar",
   202  			in: tmplValue{
   203  				Name:  "istio",
   204  				Proxy: "envoy",
   205  			},
   206  			want: "istio uses envoy as sidecar",
   207  			err:  nil,
   208  		},
   209  		{
   210  			desc:     "empty-template",
   211  			template: "",
   212  			in: tmplValue{
   213  				Name:  "istio",
   214  				Proxy: "envoy",
   215  			},
   216  			want: "",
   217  			err:  nil,
   218  		},
   219  		{
   220  			desc:     "template with no template strings",
   221  			template: "this template is without handlebar expressions",
   222  			in: tmplValue{
   223  				Name:  "istio",
   224  				Proxy: "envoy",
   225  			},
   226  			want: "this template is without handlebar expressions",
   227  			err:  nil,
   228  		},
   229  		{
   230  			desc:     "template with missing variable",
   231  			template: "{{ .Name }} has replaced its control plane with {{ .Istiod }} component",
   232  			in: tmplValue{
   233  				Name:  "istio",
   234  				Proxy: "envoy",
   235  			},
   236  			want: "",
   237  			err:  errors.New(""),
   238  		},
   239  	}
   240  	for _, tt := range tests {
   241  		t.Run(tt.desc, func(t *testing.T) {
   242  			got, err := RenderTemplate(tt.template, tt.in)
   243  			if got != tt.want {
   244  				t.Errorf("%s: got :%v, wanted output: %v", tt.desc, got, tt.want)
   245  			}
   246  
   247  			if (err == nil && tt.err != nil) || (err != nil && tt.err == nil) {
   248  				t.Errorf("%s: got error :%v, wanted error: %v", tt.desc, err, tt.err)
   249  			}
   250  		})
   251  	}
   252  }