sigs.k8s.io/cluster-api@v1.7.1/bootstrap/kubeadm/types/upstreamv1beta3/bootstraptokenstring_test.go (about) 1 /* 2 Copyright 2021 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 upstreamv1beta3 18 19 import ( 20 "encoding/json" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 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 diff := cmp.Diff(rt.bts, newbts); diff != "" { 75 t.Errorf( 76 "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v\n\t diff: %v", 77 rt.bts, 78 newbts, 79 diff, 80 ) 81 } 82 }) 83 } 84 } 85 86 func TestJSONRoundtrip(t *testing.T) { 87 var tests = []struct { 88 input string 89 bts *BootstrapTokenString 90 }{ 91 {`"abcdef.abcdef0123456789"`, nil}, 92 {"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, 93 } 94 for _, rt := range tests { 95 t.Run(rt.input, func(t *testing.T) { 96 if err := roundtrip(rt.input, rt.bts); err != nil { 97 t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) 98 } 99 }) 100 } 101 } 102 103 func roundtrip(input string, bts *BootstrapTokenString) error { 104 var b []byte 105 var err error 106 newbts := &BootstrapTokenString{} 107 // If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string 108 if input != "" { 109 if err := json.Unmarshal([]byte(input), newbts); err != nil { 110 return errors.Wrap(err, "expected no unmarshal error, got error") 111 } 112 if b, err = json.Marshal(newbts); err != nil { 113 return errors.Wrap(err, "expected no marshal error, got error") 114 } 115 if input != string(b) { 116 return errors.Errorf( 117 "expected token: %s\n\t actual: %s", 118 input, 119 string(b), 120 ) 121 } 122 } else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object 123 if b, err = json.Marshal(bts); err != nil { 124 return errors.Wrap(err, "expected no marshal error, got error") 125 } 126 if err := json.Unmarshal(b, newbts); err != nil { 127 return errors.Wrap(err, "expected no unmarshal error, got error") 128 } 129 if diff := cmp.Diff(bts, newbts); diff != "" { 130 return errors.Errorf( 131 "expected object: %v\n\t actual: %v\n\t got diff: %v", 132 bts, 133 newbts, 134 diff, 135 ) 136 } 137 } 138 return nil 139 } 140 141 func TestTokenFromIDAndSecret(t *testing.T) { 142 var tests = []struct { 143 bts BootstrapTokenString 144 expected string 145 }{ 146 {BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"}, 147 {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"}, 148 {BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"}, 149 } 150 for _, rt := range tests { 151 t.Run(rt.bts.ID, func(t *testing.T) { 152 actual := rt.bts.String() 153 if actual != rt.expected { 154 t.Errorf( 155 "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", 156 rt.expected, 157 actual, 158 ) 159 } 160 }) 161 } 162 } 163 164 func TestNewBootstrapTokenString(t *testing.T) { 165 var tests = []struct { 166 token string 167 expectedError bool 168 bts *BootstrapTokenString 169 }{ 170 {token: "", expectedError: true, bts: nil}, 171 {token: ".", expectedError: true, bts: nil}, 172 {token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size 173 {token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size 174 {token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size 175 {token: "123456.", expectedError: true, bts: nil}, // invalid parcel size 176 {token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation 177 {token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation 178 {token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id 179 {token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret 180 {token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character 181 {token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character 182 {token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, 183 {token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, 184 {token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, 185 {token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, 186 } 187 for _, rt := range tests { 188 t.Run(rt.token, func(t *testing.T) { 189 actual, err := NewBootstrapTokenString(rt.token) 190 if (err != nil) != rt.expectedError { 191 t.Errorf( 192 "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", 193 rt.token, 194 rt.expectedError, 195 err, 196 ) 197 } else if diff := cmp.Diff(actual, rt.bts); diff != "" { 198 t.Errorf( 199 "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v\n\t diff: %v", 200 rt.token, 201 rt.bts, 202 actual, 203 diff, 204 ) 205 } 206 }) 207 } 208 } 209 210 func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { 211 var tests = []struct { 212 id, secret string 213 expectedError bool 214 bts *BootstrapTokenString 215 }{ 216 {id: "", secret: "", expectedError: true, bts: nil}, 217 {id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size 218 {id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size 219 {id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size 220 {id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size 221 {id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id 222 {id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret 223 {id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character 224 {id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character 225 {id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, 226 {id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, 227 {id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, 228 {id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, 229 } 230 for _, rt := range tests { 231 t.Run(rt.id, func(t *testing.T) { 232 actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) 233 if (err != nil) != rt.expectedError { 234 t.Errorf( 235 "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", 236 rt.id, 237 rt.secret, 238 rt.expectedError, 239 err, 240 ) 241 } else if diff := cmp.Diff(actual, rt.bts); diff != "" { 242 t.Errorf( 243 "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v\n\t diff: %v", 244 rt.id, 245 rt.secret, 246 rt.bts, 247 actual, 248 diff, 249 ) 250 } 251 }) 252 } 253 }