sigs.k8s.io/cluster-api/bootstrap/kubeadm@v0.0.0-20191016155141-23a891785b60/kubeadm/v1beta2/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 v1beta2
    18  
    19  import (
    20  	"encoding/json"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/pkg/errors"
    25  )
    26  
    27  func TestMarshalJSON(t *testing.T) {
    28  	var tests = []struct {
    29  		bts      BootstrapTokenString
    30  		expected string
    31  	}{
    32  		{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`},
    33  		{BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`},
    34  		{BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`},
    35  	}
    36  	for _, rt := range tests {
    37  		t.Run(rt.bts.ID, func(t *testing.T) {
    38  			b, err := json.Marshal(rt.bts)
    39  			if err != nil {
    40  				t.Fatalf("json.Marshal returned an unexpected error: %v", err)
    41  			}
    42  			if string(b) != rt.expected {
    43  				t.Errorf(
    44  					"failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t  actual: %s",
    45  					rt.expected,
    46  					string(b),
    47  				)
    48  			}
    49  		})
    50  	}
    51  }
    52  
    53  func TestUnmarshalJSON(t *testing.T) {
    54  	var tests = []struct {
    55  		input         string
    56  		bts           *BootstrapTokenString
    57  		expectedError bool
    58  	}{
    59  		{`"f.s"`, &BootstrapTokenString{}, true},
    60  		{`"abcdef."`, &BootstrapTokenString{}, true},
    61  		{`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true},
    62  		{`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
    63  		{`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true},
    64  		{`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true},
    65  		{`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false},
    66  		{`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false},
    67  	}
    68  	for _, rt := range tests {
    69  		t.Run(rt.input, func(t *testing.T) {
    70  			newbts := &BootstrapTokenString{}
    71  			err := json.Unmarshal([]byte(rt.input), newbts)
    72  			if (err != nil) != rt.expectedError {
    73  				t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t  actual error: %v", rt.expectedError, err)
    74  			} else if !reflect.DeepEqual(rt.bts, newbts) {
    75  				t.Errorf(
    76  					"failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t  actual: %v",
    77  					rt.bts,
    78  					newbts,
    79  				)
    80  			}
    81  		})
    82  	}
    83  }
    84  
    85  func TestJSONRoundtrip(t *testing.T) {
    86  	var tests = []struct {
    87  		input string
    88  		bts   *BootstrapTokenString
    89  	}{
    90  		{`"abcdef.abcdef0123456789"`, nil},
    91  		{"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
    92  	}
    93  	for _, rt := range tests {
    94  		t.Run(rt.input, func(t *testing.T) {
    95  			if err := roundtrip(rt.input, rt.bts); err != nil {
    96  				t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err)
    97  			}
    98  		})
    99  	}
   100  }
   101  
   102  func roundtrip(input string, bts *BootstrapTokenString) error {
   103  	var b []byte
   104  	var err error
   105  	newbts := &BootstrapTokenString{}
   106  	// If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string
   107  	if len(input) > 0 {
   108  		if err := json.Unmarshal([]byte(input), newbts); err != nil {
   109  			return errors.Wrap(err, "expected no unmarshal error, got error")
   110  		}
   111  		if b, err = json.Marshal(newbts); err != nil {
   112  			return errors.Wrap(err, "expected no marshal error, got error")
   113  		}
   114  		if input != string(b) {
   115  			return errors.Errorf(
   116  				"expected token: %s\n\t  actual: %s",
   117  				input,
   118  				string(b),
   119  			)
   120  		}
   121  	} else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object
   122  		if b, err = json.Marshal(bts); err != nil {
   123  			return errors.Wrap(err, "expected no marshal error, got error")
   124  		}
   125  		if err := json.Unmarshal(b, newbts); err != nil {
   126  			return errors.Wrap(err, "expected no unmarshal error, got error")
   127  		}
   128  		if !reflect.DeepEqual(bts, newbts) {
   129  			return errors.Errorf(
   130  				"expected object: %v\n\t  actual: %v",
   131  				bts,
   132  				newbts,
   133  			)
   134  		}
   135  	}
   136  	return nil
   137  }
   138  
   139  func TestTokenFromIDAndSecret(t *testing.T) {
   140  	var tests = []struct {
   141  		bts      BootstrapTokenString
   142  		expected string
   143  	}{
   144  		{BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"},
   145  		{BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"},
   146  		{BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"},
   147  	}
   148  	for _, rt := range tests {
   149  		t.Run(rt.bts.ID, func(t *testing.T) {
   150  			actual := rt.bts.String()
   151  			if actual != rt.expected {
   152  				t.Errorf(
   153  					"failed BootstrapTokenString.String():\n\texpected: %s\n\t  actual: %s",
   154  					rt.expected,
   155  					actual,
   156  				)
   157  			}
   158  		})
   159  	}
   160  }
   161  
   162  func TestNewBootstrapTokenString(t *testing.T) {
   163  	var tests = []struct {
   164  		token         string
   165  		expectedError bool
   166  		bts           *BootstrapTokenString
   167  	}{
   168  		{token: "", expectedError: true, bts: nil},
   169  		{token: ".", expectedError: true, bts: nil},
   170  		{token: "1234567890123456789012", expectedError: true, bts: nil},   // invalid parcel size
   171  		{token: "12345.1234567890123456", expectedError: true, bts: nil},   // invalid parcel size
   172  		{token: ".1234567890123456", expectedError: true, bts: nil},        // invalid parcel size
   173  		{token: "123456.", expectedError: true, bts: nil},                  // invalid parcel size
   174  		{token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation
   175  		{token: "abcdef:1234567890123456", expectedError: true, bts: nil},  // invalid separation
   176  		{token: "Abcdef.1234567890123456", expectedError: true, bts: nil},  // invalid token id
   177  		{token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil},  // invalid token secret
   178  		{token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil},  // invalid character
   179  		{token: "abc*ef.1234567890123456", expectedError: true, bts: nil},  // invalid character
   180  		{token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
   181  		{token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
   182  		{token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
   183  		{token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
   184  	}
   185  	for _, rt := range tests {
   186  		t.Run(rt.token, func(t *testing.T) {
   187  			actual, err := NewBootstrapTokenString(rt.token)
   188  			if (err != nil) != rt.expectedError {
   189  				t.Errorf(
   190  					"failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t  actual error: %v",
   191  					rt.token,
   192  					rt.expectedError,
   193  					err,
   194  				)
   195  			} else if !reflect.DeepEqual(actual, rt.bts) {
   196  				t.Errorf(
   197  					"failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t  actual: %v",
   198  					rt.token,
   199  					rt.bts,
   200  					actual,
   201  				)
   202  			}
   203  		})
   204  	}
   205  }
   206  
   207  func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) {
   208  	var tests = []struct {
   209  		id, secret    string
   210  		expectedError bool
   211  		bts           *BootstrapTokenString
   212  	}{
   213  		{id: "", secret: "", expectedError: true, bts: nil},
   214  		{id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size
   215  		{id: "12345", secret: "1234567890123456", expectedError: true, bts: nil},  // invalid parcel size
   216  		{id: "", secret: "1234567890123456", expectedError: true, bts: nil},       // invalid parcel size
   217  		{id: "123456", secret: "", expectedError: true, bts: nil},                 // invalid parcel size
   218  		{id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id
   219  		{id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret
   220  		{id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character
   221  		{id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character
   222  		{id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}},
   223  		{id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}},
   224  		{id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}},
   225  		{id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}},
   226  	}
   227  	for _, rt := range tests {
   228  		t.Run(rt.id, func(t *testing.T) {
   229  			actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret)
   230  			if (err != nil) != rt.expectedError {
   231  				t.Errorf(
   232  					"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t  actual error: %v",
   233  					rt.id,
   234  					rt.secret,
   235  					rt.expectedError,
   236  					err,
   237  				)
   238  			} else if !reflect.DeepEqual(actual, rt.bts) {
   239  				t.Errorf(
   240  					"failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t  actual: %v",
   241  					rt.id,
   242  					rt.secret,
   243  					rt.bts,
   244  					actual,
   245  				)
   246  			}
   247  		})
   248  	}
   249  }