| /* |
| Copyright 2018 The Kubernetes Authors. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| package kubeadm |
| |
| import ( |
| "encoding/json" |
| "reflect" |
| "testing" |
| |
| "github.com/pkg/errors" |
| ) |
| |
| func TestMarshalJSON(t *testing.T) { |
| var tests = []struct { |
| bts BootstrapTokenString |
| expected string |
| }{ |
| {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`}, |
| {BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`}, |
| {BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`}, |
| } |
| for _, rt := range tests { |
| b, err := json.Marshal(rt.bts) |
| if err != nil { |
| t.Fatalf("json.Marshal returned an unexpected error: %v", err) |
| } |
| if string(b) != rt.expected { |
| t.Errorf( |
| "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", |
| rt.expected, |
| string(b), |
| ) |
| } |
| } |
| } |
| |
| func TestUnmarshalJSON(t *testing.T) { |
| var tests = []struct { |
| input string |
| bts *BootstrapTokenString |
| expectedError bool |
| }{ |
| {`"f.s"`, &BootstrapTokenString{}, true}, |
| {`"abcdef."`, &BootstrapTokenString{}, true}, |
| {`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true}, |
| {`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, |
| {`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, |
| {`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true}, |
| {`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false}, |
| {`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false}, |
| } |
| for _, rt := range tests { |
| newbts := &BootstrapTokenString{} |
| err := json.Unmarshal([]byte(rt.input), newbts) |
| if (err != nil) != rt.expectedError { |
| t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) |
| } else if !reflect.DeepEqual(rt.bts, newbts) { |
| t.Errorf( |
| "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", |
| rt.bts, |
| newbts, |
| ) |
| } |
| } |
| } |
| |
| func TestJSONRoundtrip(t *testing.T) { |
| var tests = []struct { |
| input string |
| bts *BootstrapTokenString |
| }{ |
| {`"abcdef.abcdef0123456789"`, nil}, |
| {"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, |
| } |
| for _, rt := range tests { |
| if err := roundtrip(rt.input, rt.bts); err != nil { |
| t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) |
| } |
| } |
| } |
| |
| func roundtrip(input string, bts *BootstrapTokenString) error { |
| var b []byte |
| var err error |
| newbts := &BootstrapTokenString{} |
| // If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string |
| if len(input) > 0 { |
| if err := json.Unmarshal([]byte(input), newbts); err != nil { |
| return errors.Wrap(err, "expected no unmarshal error, got error") |
| } |
| if b, err = json.Marshal(newbts); err != nil { |
| return errors.Wrap(err, "expected no marshal error, got error") |
| } |
| if input != string(b) { |
| return errors.Errorf( |
| "expected token: %s\n\t actual: %s", |
| input, |
| string(b), |
| ) |
| } |
| } else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object |
| if b, err = json.Marshal(bts); err != nil { |
| return errors.Wrap(err, "expected no marshal error, got error") |
| } |
| if err := json.Unmarshal(b, newbts); err != nil { |
| return errors.Wrap(err, "expected no unmarshal error, got error") |
| } |
| if !reflect.DeepEqual(bts, newbts) { |
| return errors.Errorf( |
| "expected object: %v\n\t actual: %v", |
| bts, |
| newbts, |
| ) |
| } |
| } |
| return nil |
| } |
| |
| func TestTokenFromIDAndSecret(t *testing.T) { |
| var tests = []struct { |
| bts BootstrapTokenString |
| expected string |
| }{ |
| {BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"}, |
| {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"}, |
| {BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"}, |
| } |
| for _, rt := range tests { |
| actual := rt.bts.String() |
| if actual != rt.expected { |
| t.Errorf( |
| "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", |
| rt.expected, |
| actual, |
| ) |
| } |
| } |
| } |
| |
| func TestNewBootstrapTokenString(t *testing.T) { |
| var tests = []struct { |
| token string |
| expectedError bool |
| bts *BootstrapTokenString |
| }{ |
| {token: "", expectedError: true, bts: nil}, |
| {token: ".", expectedError: true, bts: nil}, |
| {token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size |
| {token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size |
| {token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size |
| {token: "123456.", expectedError: true, bts: nil}, // invalid parcel size |
| {token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation |
| {token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation |
| {token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id |
| {token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret |
| {token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character |
| {token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character |
| {token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, |
| {token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, |
| {token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, |
| {token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, |
| } |
| for _, rt := range tests { |
| actual, err := NewBootstrapTokenString(rt.token) |
| if (err != nil) != rt.expectedError { |
| t.Errorf( |
| "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", |
| rt.token, |
| rt.expectedError, |
| err, |
| ) |
| } else if !reflect.DeepEqual(actual, rt.bts) { |
| t.Errorf( |
| "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", |
| rt.token, |
| rt.bts, |
| actual, |
| ) |
| } |
| } |
| } |
| |
| func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { |
| var tests = []struct { |
| id, secret string |
| expectedError bool |
| bts *BootstrapTokenString |
| }{ |
| {id: "", secret: "", expectedError: true, bts: nil}, |
| {id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size |
| {id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size |
| {id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size |
| {id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size |
| {id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id |
| {id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret |
| {id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character |
| {id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character |
| {id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, |
| {id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, |
| {id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, |
| {id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, |
| } |
| for _, rt := range tests { |
| actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) |
| if (err != nil) != rt.expectedError { |
| t.Errorf( |
| "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", |
| rt.id, |
| rt.secret, |
| rt.expectedError, |
| err, |
| ) |
| } else if !reflect.DeepEqual(actual, rt.bts) { |
| t.Errorf( |
| "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", |
| rt.id, |
| rt.secret, |
| rt.bts, |
| actual, |
| ) |
| } |
| } |
| } |