...

Source file src/sigs.k8s.io/kustomize/api/hasher/hasher_test.go

Documentation: sigs.k8s.io/kustomize/api/hasher

     1  // Copyright 2019 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package hasher
     5  
     6  import (
     7  	"strings"
     8  	"testing"
     9  
    10  	"sigs.k8s.io/kustomize/kyaml/yaml"
    11  )
    12  
    13  func TestSortArrayAndComputeHash(t *testing.T) {
    14  	array1 := []string{"a", "b", "c", "d"}
    15  	array2 := []string{"c", "b", "d", "a"}
    16  	h1, err := SortArrayAndComputeHash(array1)
    17  	if err != nil {
    18  		t.Errorf("unexpected error %v", err)
    19  	}
    20  	if h1 == "" {
    21  		t.Errorf("failed to hash %v", array1)
    22  	}
    23  	h2, err := SortArrayAndComputeHash(array2)
    24  	if err != nil {
    25  		t.Errorf("unexpected error %v", err)
    26  	}
    27  	if h2 == "" {
    28  		t.Errorf("failed to hash %v", array2)
    29  	}
    30  	if h1 != h2 {
    31  		t.Errorf("hash is not consistent with reordered list: %s %s", h1, h2)
    32  	}
    33  }
    34  
    35  func Test_hex256(t *testing.T) {
    36  	// hash the empty string to be sure that sha256 is being used
    37  	expect := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
    38  	sum := hex256("")
    39  	if expect != sum {
    40  		t.Errorf("expected hash %q but got %q", expect, sum)
    41  	}
    42  }
    43  
    44  func TestConfigMapHash(t *testing.T) {
    45  	cases := []struct {
    46  		desc   string
    47  		cmYaml string
    48  		hash   string
    49  		err    string
    50  	}{
    51  		// empty map
    52  		{"empty data", `
    53  apiVersion: v1
    54  kind: ConfigMap`, "6ct58987ht", ""},
    55  		// one key
    56  		{"one key", `
    57  apiVersion: v1
    58  kind: ConfigMap
    59  data:
    60    one: ""`, "9g67k2htb6", ""},
    61  		// three keys (tests sorting order)
    62  		{"three keys", `
    63  apiVersion: v1
    64  kind: ConfigMap
    65  data:
    66    two: 2
    67    one: ""
    68    three: 3`, "7757f9kkct", ""},
    69  		// empty binary data map
    70  		{"empty binary data", `
    71  apiVersion: v1
    72  kind: ConfigMap`, "6ct58987ht", ""},
    73  		// one key with binary data
    74  		{"one key with binary data", `
    75  apiVersion: v1
    76  kind: ConfigMap
    77  binaryData:
    78    one: ""`, "6mtk2m274t", ""},
    79  		// three keys with binary data (tests sorting order)
    80  		{"three keys with binary data", `
    81  apiVersion: v1
    82  kind: ConfigMap
    83  binaryData:
    84    two: 2
    85    one: ""
    86    three: 3`, "9th7kc28dg", ""},
    87  		// two keys, one with string and another with binary data
    88  		{"two keys with one each", `
    89  apiVersion: v1
    90  kind: ConfigMap
    91  data:
    92    one: ""
    93  binaryData:
    94    two: ""`, "698h7c7t9m", ""},
    95  	}
    96  	h := &Hasher{}
    97  	for _, c := range cases {
    98  		node, err := yaml.Parse(c.cmYaml)
    99  		if err != nil {
   100  			t.Fatal(err)
   101  		}
   102  		hashed, err := h.Hash(node)
   103  		if SkipRest(t, c.desc, err, c.err) {
   104  			continue
   105  		}
   106  		if c.hash != hashed {
   107  			t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h)
   108  		}
   109  	}
   110  }
   111  
   112  func TestSecretHash(t *testing.T) {
   113  	cases := []struct {
   114  		desc       string
   115  		secretYaml string
   116  		hash       string
   117  		err        string
   118  	}{
   119  		// empty map
   120  		{"empty data", `
   121  apiVersion: v1
   122  kind: Secret
   123  type: my-type`, "5gmgkf8578", ""},
   124  		// one key
   125  		{"one key", `
   126  apiVersion: v1
   127  kind: Secret
   128  type: my-type
   129  data:
   130    one: ""`, "74bd68bm66", ""},
   131  		// three keys (tests sorting order)
   132  		{"three keys", `
   133  apiVersion: v1
   134  kind: Secret
   135  type: my-type
   136  data:
   137    two: 2
   138    one: ""
   139    three: 3`, "4gf75c7476", ""},
   140  		// with stringdata
   141  		{"stringdata", `
   142  apiVersion: v1
   143  kind: Secret
   144  type: my-type
   145  data:
   146    one: ""
   147  stringData:
   148    two: 2`, "c4h4264gdb", ""},
   149  		// empty stringdata
   150  		{"empty stringdata", `
   151  apiVersion: v1
   152  kind: Secret
   153  type: my-type
   154  data:
   155    one: ""`, "74bd68bm66", ""},
   156  	}
   157  	h := &Hasher{}
   158  	for _, c := range cases {
   159  		node, err := yaml.Parse(c.secretYaml)
   160  		if err != nil {
   161  			t.Fatal(err)
   162  		}
   163  		hashed, err := h.Hash(node)
   164  		if SkipRest(t, c.desc, err, c.err) {
   165  			continue
   166  		}
   167  		if c.hash != hashed {
   168  			t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h)
   169  		}
   170  	}
   171  }
   172  
   173  func TestBasicHash(t *testing.T) {
   174  	cases := map[string]struct {
   175  		res  string
   176  		hash string
   177  		err  string
   178  	}{
   179  		"minimal": {`
   180  apiVersion: test/v1
   181  kind: TestResource
   182  metadata:
   183    name: my-resource`, "244782mkb7", ""},
   184  		"with spec": {`
   185  apiVersion: test/v1
   186  kind: TestResource
   187  metadata:
   188    name: my-resource
   189  spec:
   190    foo: 1
   191    bar: abc`, "59m2mdccg4", ""},
   192  	}
   193  	h := &Hasher{}
   194  	for n := range cases {
   195  		c := cases[n]
   196  		t.Run(n, func(t *testing.T) {
   197  			node, err := yaml.Parse(c.res)
   198  			if err != nil {
   199  				t.Fatal(err)
   200  			}
   201  			hashed, err := h.Hash(node)
   202  			if SkipRest(t, n, err, c.err) {
   203  				return
   204  			}
   205  			if c.hash != hashed {
   206  				t.Errorf("case %q, expect hash %q but got %q", n, c.hash, h)
   207  			}
   208  		})
   209  	}
   210  }
   211  
   212  func TestEncodeConfigMap(t *testing.T) {
   213  	cases := []struct {
   214  		desc   string
   215  		cmYaml string
   216  		expect string
   217  		err    string
   218  	}{
   219  		// empty map
   220  		{"empty data", `
   221  apiVersion: v1
   222  kind: ConfigMap`, `{"data":"","kind":"ConfigMap","name":""}`, ""},
   223  		// one key
   224  		{"one key", `
   225  apiVersion: v1
   226  kind: ConfigMap
   227  data:
   228    one: ""`, `{"data":{"one":""},"kind":"ConfigMap","name":""}`, ""},
   229  		// three keys (tests sorting order)
   230  		{"three keys", `
   231  apiVersion: v1
   232  kind: ConfigMap
   233  data:
   234    two: 2
   235    one: ""
   236    three: 3`, `{"data":{"one":"","three":3,"two":2},"kind":"ConfigMap","name":""}`, ""},
   237  		// empty binary map
   238  		{"empty data", `
   239  apiVersion: v1
   240  kind: ConfigMap`, `{"data":"","kind":"ConfigMap","name":""}`, ""},
   241  		// one key with binary data
   242  		{"one key", `
   243  apiVersion: v1
   244  kind: ConfigMap
   245  binaryData:
   246    one: ""`, `{"binaryData":{"one":""},"data":"","kind":"ConfigMap","name":""}`, ""},
   247  		// three keys with binary data (tests sorting order)
   248  		{"three keys", `
   249  apiVersion: v1
   250  kind: ConfigMap
   251  binaryData:
   252    two: 2
   253    one: ""
   254    three: 3`, `{"binaryData":{"one":"","three":3,"two":2},"data":"","kind":"ConfigMap","name":""}`, ""},
   255  		// two keys, one string and one binary values
   256  		{"two keys with one each", `
   257  apiVersion: v1
   258  kind: ConfigMap
   259  data:
   260    one: ""
   261  binaryData:
   262    two: ""`, `{"binaryData":{"two":""},"data":{"one":""},"kind":"ConfigMap","name":""}`, ""},
   263  	}
   264  	for _, c := range cases {
   265  		node, err := yaml.Parse(c.cmYaml)
   266  		if err != nil {
   267  			t.Fatal(err)
   268  		}
   269  		s, err := encodeConfigMap(node)
   270  		if SkipRest(t, c.desc, err, c.err) {
   271  			continue
   272  		}
   273  		if s != c.expect {
   274  			t.Errorf("case %q, expect %q but got %q from encode %#v", c.desc, c.expect, s, c.cmYaml)
   275  		}
   276  	}
   277  }
   278  
   279  func TestEncodeSecret(t *testing.T) {
   280  	cases := []struct {
   281  		desc       string
   282  		secretYaml string
   283  		expect     string
   284  		err        string
   285  	}{
   286  		// empty map
   287  		{"empty data", `
   288  apiVersion: v1
   289  kind: Secret
   290  type: my-type`, `{"data":"","kind":"Secret","name":"","type":"my-type"}`, ""},
   291  		// one key
   292  		{"one key", `
   293  apiVersion: v1
   294  kind: Secret
   295  type: my-type
   296  data:
   297    one: ""`, `{"data":{"one":""},"kind":"Secret","name":"","type":"my-type"}`, ""},
   298  		// three keys (tests sorting order) - note json.Marshal base64 encodes the values because they come in as []byte
   299  		{"three keys", `
   300  apiVersion: v1
   301  kind: Secret
   302  type: my-type
   303  data:
   304    two: 2
   305    one: ""
   306    three: 3`, `{"data":{"one":"","three":3,"two":2},"kind":"Secret","name":"","type":"my-type"}`, ""},
   307  		// with stringdata
   308  		{"stringdata", `
   309  apiVersion: v1
   310  kind: Secret
   311  type: my-type
   312  data:
   313    one: ""
   314  stringData:
   315    two: 2`, `{"data":{"one":""},"kind":"Secret","name":"","stringData":{"two":2},"type":"my-type"}`, ""},
   316  		// empty stringdata
   317  		{"empty stringdata", `
   318  apiVersion: v1
   319  kind: Secret
   320  type: my-type
   321  data:
   322    one: ""`, `{"data":{"one":""},"kind":"Secret","name":"","type":"my-type"}`, ""},
   323  	}
   324  	for _, c := range cases {
   325  		node, err := yaml.Parse(c.secretYaml)
   326  		if err != nil {
   327  			t.Fatal(err)
   328  		}
   329  		s, err := encodeSecret(node)
   330  		if SkipRest(t, c.desc, err, c.err) {
   331  			continue
   332  		}
   333  		if s != c.expect {
   334  			t.Errorf("case %q, expect %q but got %q from encode %#v", c.desc, c.expect, s, c.secretYaml)
   335  		}
   336  	}
   337  }
   338  
   339  // SkipRest returns true if there was a non-nil error or if we expected an
   340  // error that didn't happen, and logs the appropriate error on the test object.
   341  // The return value indicates whether we should skip the rest of the test case
   342  // due to the error result.
   343  func SkipRest(t *testing.T, desc string, err error, contains string) bool {
   344  	t.Helper()
   345  	if err != nil {
   346  		if len(contains) == 0 {
   347  			t.Errorf("case %q, expect nil error but got %q", desc, err.Error())
   348  		} else if !strings.Contains(err.Error(), contains) {
   349  			t.Errorf("case %q, expect error to contain %q but got %q", desc, contains, err.Error())
   350  		}
   351  		return true
   352  	} else if len(contains) > 0 {
   353  		t.Errorf("case %q, expect error to contain %q but got nil error", desc, contains)
   354  		return true
   355  	}
   356  	return false
   357  }
   358  

View as plain text