sigs.k8s.io/cluster-api@v1.7.1/bootstrap/kubeadm/types/upstreamv1beta2/bootstraptokenstring_test.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package upstreamv1beta2
    18  
    19  import (
    20  	"encoding/json"
    21  	"testing"
    22  
    23  	"github.com/google/go-cmp/cmp"
    24  	. "github.com/onsi/gomega"
    25  	"github.com/pkg/errors"
    26  )
    27  
    28  func TestMarshalJSON(t *testing.T) {
    29  	var tests = []struct {
    30  		bts      BootstrapTokenString
    31  		expected string
    32  	}{
    33  		{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`},
    34  		{BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`},
    35  		{BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`},
    36  	}
    37  	for _, rt := range tests {
    38  		t.Run(rt.bts.ID, func(t *testing.T) {
    39  			g := NewWithT(t)
    40  
    41  			b, err := json.Marshal(rt.bts)
    42  			g.Expect(err).ToNot(HaveOccurred())
    43  			g.Expect(string(b)).To(Equal(rt.expected))
    44  		})
    45  	}
    46  }
    47  
    48  func TestUnmarshalJSON(t *testing.T) {
    49  	var tests = []struct {
    50  		input         string
    51  		bts           *BootstrapTokenString
    52  		expectedError bool
    53  	}{
    54  		{`"f.s"`, &BootstrapTokenString{}, true},
    55  		{`"abcdef."`, &BootstrapTokenString{}, true},
    56  		{`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true},
    57  		{`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
    58  		{`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
    59  		{`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true},
    60  		{`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false},
    61  		{`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false},
    62  	}
    63  	for _, rt := range tests {
    64  		t.Run(rt.input, func(t *testing.T) {
    65  			g := NewWithT(t)
    66  
    67  			newbts := &BootstrapTokenString{}
    68  			err := json.Unmarshal([]byte(rt.input), newbts)
    69  			if rt.expectedError {
    70  				g.Expect(err).To(HaveOccurred())
    71  			} else {
    72  				g.Expect(err).ToNot(HaveOccurred())
    73  			}
    74  			g.Expect(newbts).To(BeComparableTo(rt.bts))
    75  		})
    76  	}
    77  }
    78  
    79  func TestJSONRoundtrip(t *testing.T) {
    80  	var tests = []struct {
    81  		input string
    82  		bts   *BootstrapTokenString
    83  	}{
    84  		{`"abcdef.abcdef0123456789"`, nil},
    85  		{"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
    86  	}
    87  	for _, rt := range tests {
    88  		t.Run(rt.input, func(t *testing.T) {
    89  			g := NewWithT(t)
    90  
    91  			g.Expect(roundtrip(rt.input, rt.bts)).To(Succeed())
    92  		})
    93  	}
    94  }
    95  
    96  func roundtrip(input string, bts *BootstrapTokenString) error {
    97  	var b []byte
    98  	var err error
    99  	newbts := &BootstrapTokenString{}
   100  	// If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string
   101  	if input != "" {
   102  		if err := json.Unmarshal([]byte(input), newbts); err != nil {
   103  			return errors.Wrap(err, "expected no unmarshal error, got error")
   104  		}
   105  		if b, err = json.Marshal(newbts); err != nil {
   106  			return errors.Wrap(err, "expected no marshal error, got error")
   107  		}
   108  		if input != string(b) {
   109  			return errors.Errorf(
   110  				"expected token: %s\n\t  actual: %s",
   111  				input,
   112  				string(b),
   113  			)
   114  		}
   115  	} else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object
   116  		if b, err = json.Marshal(bts); err != nil {
   117  			return errors.Wrap(err, "expected no marshal error, got error")
   118  		}
   119  		if err := json.Unmarshal(b, newbts); err != nil {
   120  			return errors.Wrap(err, "expected no unmarshal error, got error")
   121  		}
   122  		if diff := cmp.Diff(bts, newbts); diff != "" {
   123  			return errors.Errorf(
   124  				"expected object: %v\n\t  actual: %v\n\t got diff: %v",
   125  				bts,
   126  				newbts,
   127  				diff,
   128  			)
   129  		}
   130  	}
   131  	return nil
   132  }
   133  
   134  func TestTokenFromIDAndSecret(t *testing.T) {
   135  	var tests = []struct {
   136  		bts      BootstrapTokenString
   137  		expected string
   138  	}{
   139  		{BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"},
   140  		{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"},
   141  		{BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"},
   142  	}
   143  	for _, rt := range tests {
   144  		t.Run(rt.bts.ID, func(t *testing.T) {
   145  			g := NewWithT(t)
   146  
   147  			g.Expect(rt.bts.String()).To(Equal(rt.expected))
   148  		})
   149  	}
   150  }
   151  
   152  func TestNewBootstrapTokenString(t *testing.T) {
   153  	var tests = []struct {
   154  		token         string
   155  		expectedError bool
   156  		bts           *BootstrapTokenString
   157  	}{
   158  		{token: "", expectedError: true, bts: nil},
   159  		{token: ".", expectedError: true, bts: nil},
   160  		{token: "1234567890123456789012", expectedError: true, bts: nil},   // invalid parcel size
   161  		{token: "12345.1234567890123456", expectedError: true, bts: nil},   // invalid parcel size
   162  		{token: ".1234567890123456", expectedError: true, bts: nil},        // invalid parcel size
   163  		{token: "123456.", expectedError: true, bts: nil},                  // invalid parcel size
   164  		{token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation
   165  		{token: "abcdef:1234567890123456", expectedError: true, bts: nil},  // invalid separation
   166  		{token: "Abcdef.1234567890123456", expectedError: true, bts: nil},  // invalid token id
   167  		{token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil},  // invalid token secret
   168  		{token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil},  // invalid character
   169  		{token: "abc*ef.1234567890123456", expectedError: true, bts: nil},  // invalid character
   170  		{token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
   171  		{token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
   172  		{token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
   173  		{token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
   174  	}
   175  	for _, rt := range tests {
   176  		t.Run(rt.token, func(t *testing.T) {
   177  			g := NewWithT(t)
   178  
   179  			actual, err := NewBootstrapTokenString(rt.token)
   180  			if rt.expectedError {
   181  				g.Expect(err).To(HaveOccurred())
   182  			} else {
   183  				g.Expect(err).ToNot(HaveOccurred())
   184  			}
   185  			g.Expect(actual).To(BeComparableTo(rt.bts))
   186  		})
   187  	}
   188  }
   189  
   190  func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) {
   191  	var tests = []struct {
   192  		id, secret    string
   193  		expectedError bool
   194  		bts           *BootstrapTokenString
   195  	}{
   196  		{id: "", secret: "", expectedError: true, bts: nil},
   197  		{id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size
   198  		{id: "12345", secret: "1234567890123456", expectedError: true, bts: nil},  // invalid parcel size
   199  		{id: "", secret: "1234567890123456", expectedError: true, bts: nil},       // invalid parcel size
   200  		{id: "123456", secret: "", expectedError: true, bts: nil},                 // invalid parcel size
   201  		{id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id
   202  		{id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
   203  		{id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
   204  		{id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character
   205  		{id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
   206  		{id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
   207  		{id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
   208  		{id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
   209  	}
   210  	for _, rt := range tests {
   211  		t.Run(rt.id, func(t *testing.T) {
   212  			g := NewWithT(t)
   213  
   214  			actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret)
   215  			if rt.expectedError {
   216  				g.Expect(err).To(HaveOccurred())
   217  			} else {
   218  				g.Expect(err).ToNot(HaveOccurred())
   219  			}
   220  			g.Expect(actual).To(BeComparableTo(rt.bts))
   221  		})
   222  	}
   223  }