Update go dependencies

This commit is contained in:
Manuel de Brito Fontes 2018-05-26 11:27:53 -04:00 committed by Manuel Alejandro de Brito Fontes
parent 15ffb51394
commit bb4d483837
No known key found for this signature in database
GPG key ID: 786136016A8BA02A
1621 changed files with 86368 additions and 284392 deletions

View file

@ -1,32 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["semantic.go"],
importpath = "k8s.io/apimachinery/pkg/api/equality",
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,47 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["errors_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"errors.go",
],
importpath = "k8s.io/apimachinery/pkg/api/errors",
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,222 +0,0 @@
/*
Copyright 2014 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 errors
import (
"errors"
"fmt"
"reflect"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
)
func resource(resource string) schema.GroupResource {
return schema.GroupResource{Group: "", Resource: resource}
}
func kind(kind string) schema.GroupKind {
return schema.GroupKind{Group: "", Kind: kind}
}
func TestErrorNew(t *testing.T) {
err := NewAlreadyExists(resource("tests"), "1")
if !IsAlreadyExists(err) {
t.Errorf("expected to be %s", metav1.StatusReasonAlreadyExists)
}
if IsConflict(err) {
t.Errorf("expected to not be %s", metav1.StatusReasonConflict)
}
if IsNotFound(err) {
t.Errorf(fmt.Sprintf("expected to not be %s", metav1.StatusReasonNotFound))
}
if IsInvalid(err) {
t.Errorf("expected to not be %s", metav1.StatusReasonInvalid)
}
if IsBadRequest(err) {
t.Errorf("expected to not be %s", metav1.StatusReasonBadRequest)
}
if IsForbidden(err) {
t.Errorf("expected to not be %s", metav1.StatusReasonForbidden)
}
if IsServerTimeout(err) {
t.Errorf("expected to not be %s", metav1.StatusReasonServerTimeout)
}
if IsMethodNotSupported(err) {
t.Errorf("expected to not be %s", metav1.StatusReasonMethodNotAllowed)
}
if !IsConflict(NewConflict(resource("tests"), "2", errors.New("message"))) {
t.Errorf("expected to be conflict")
}
if !IsNotFound(NewNotFound(resource("tests"), "3")) {
t.Errorf("expected to be %s", metav1.StatusReasonNotFound)
}
if !IsInvalid(NewInvalid(kind("Test"), "2", nil)) {
t.Errorf("expected to be %s", metav1.StatusReasonInvalid)
}
if !IsBadRequest(NewBadRequest("reason")) {
t.Errorf("expected to be %s", metav1.StatusReasonBadRequest)
}
if !IsForbidden(NewForbidden(resource("tests"), "2", errors.New("reason"))) {
t.Errorf("expected to be %s", metav1.StatusReasonForbidden)
}
if !IsUnauthorized(NewUnauthorized("reason")) {
t.Errorf("expected to be %s", metav1.StatusReasonUnauthorized)
}
if !IsServerTimeout(NewServerTimeout(resource("tests"), "reason", 0)) {
t.Errorf("expected to be %s", metav1.StatusReasonServerTimeout)
}
if !IsMethodNotSupported(NewMethodNotSupported(resource("foos"), "delete")) {
t.Errorf("expected to be %s", metav1.StatusReasonMethodNotAllowed)
}
if time, ok := SuggestsClientDelay(NewServerTimeout(resource("tests"), "doing something", 10)); time != 10 || !ok {
t.Errorf("unexpected %d", time)
}
if time, ok := SuggestsClientDelay(NewServerTimeout(resource("tests"), "doing something", 0)); time != 0 || !ok {
t.Errorf("unexpected %d", time)
}
if time, ok := SuggestsClientDelay(NewTimeoutError("test reason", 10)); time != 10 || !ok {
t.Errorf("unexpected %d", time)
}
if time, ok := SuggestsClientDelay(NewTooManyRequests("doing something", 10)); time != 10 || !ok {
t.Errorf("unexpected %d", time)
}
if time, ok := SuggestsClientDelay(NewTooManyRequests("doing something", 1)); time != 1 || !ok {
t.Errorf("unexpected %d", time)
}
if time, ok := SuggestsClientDelay(NewGenericServerResponse(429, "get", resource("tests"), "test", "doing something", 10, true)); time != 10 || !ok {
t.Errorf("unexpected %d", time)
}
if time, ok := SuggestsClientDelay(NewGenericServerResponse(500, "get", resource("tests"), "test", "doing something", 10, true)); time != 10 || !ok {
t.Errorf("unexpected %d", time)
}
if time, ok := SuggestsClientDelay(NewGenericServerResponse(429, "get", resource("tests"), "test", "doing something", 0, true)); time != 0 || ok {
t.Errorf("unexpected %d", time)
}
}
func TestNewInvalid(t *testing.T) {
testCases := []struct {
Err *field.Error
Details *metav1.StatusDetails
}{
{
field.Duplicate(field.NewPath("field[0].name"), "bar"),
&metav1.StatusDetails{
Kind: "Kind",
Name: "name",
Causes: []metav1.StatusCause{{
Type: metav1.CauseTypeFieldValueDuplicate,
Field: "field[0].name",
}},
},
},
{
field.Invalid(field.NewPath("field[0].name"), "bar", "detail"),
&metav1.StatusDetails{
Kind: "Kind",
Name: "name",
Causes: []metav1.StatusCause{{
Type: metav1.CauseTypeFieldValueInvalid,
Field: "field[0].name",
}},
},
},
{
field.NotFound(field.NewPath("field[0].name"), "bar"),
&metav1.StatusDetails{
Kind: "Kind",
Name: "name",
Causes: []metav1.StatusCause{{
Type: metav1.CauseTypeFieldValueNotFound,
Field: "field[0].name",
}},
},
},
{
field.NotSupported(field.NewPath("field[0].name"), "bar", nil),
&metav1.StatusDetails{
Kind: "Kind",
Name: "name",
Causes: []metav1.StatusCause{{
Type: metav1.CauseTypeFieldValueNotSupported,
Field: "field[0].name",
}},
},
},
{
field.Required(field.NewPath("field[0].name"), ""),
&metav1.StatusDetails{
Kind: "Kind",
Name: "name",
Causes: []metav1.StatusCause{{
Type: metav1.CauseTypeFieldValueRequired,
Field: "field[0].name",
}},
},
},
}
for i, testCase := range testCases {
vErr, expected := testCase.Err, testCase.Details
expected.Causes[0].Message = vErr.ErrorBody()
err := NewInvalid(kind("Kind"), "name", field.ErrorList{vErr})
status := err.ErrStatus
if status.Code != 422 || status.Reason != metav1.StatusReasonInvalid {
t.Errorf("%d: unexpected status: %#v", i, status)
}
if !reflect.DeepEqual(expected, status.Details) {
t.Errorf("%d: expected %#v, got %#v", i, expected, status.Details)
}
}
}
func TestReasonForError(t *testing.T) {
if e, a := metav1.StatusReasonUnknown, ReasonForError(nil); e != a {
t.Errorf("unexpected reason type: %#v", a)
}
}
type TestType struct{}
func (obj *TestType) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func (obj *TestType) DeepCopyObject() runtime.Object {
if obj == nil {
return nil
}
clone := *obj
return &clone
}
func TestFromObject(t *testing.T) {
table := []struct {
obj runtime.Object
message string
}{
{&metav1.Status{Message: "foobar"}, "foobar"},
{&TestType{}, "unexpected object: &{}"},
}
for _, item := range table {
if e, a := item.message, FromObject(item.obj).Error(); e != a {
t.Errorf("Expected %v, got %v", e, a)
}
}
}

View file

@ -1,72 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"meta_test.go",
"multirestmapper_test.go",
"priority_test.go",
"restmapper_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"errors.go",
"firsthit_restmapper.go",
"help.go",
"interfaces.go",
"lazy.go",
"meta.go",
"multirestmapper.go",
"priority.go",
"restmapper.go",
"unstructured.go",
],
importpath = "k8s.io/apimachinery/pkg/api/meta",
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/api/meta/table:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,51 +0,0 @@
/*
Copyright 2017 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 meta
import (
"math/rand"
"reflect"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/util/diff"
fuzz "github.com/google/gofuzz"
)
func TestAsPartialObjectMetadata(t *testing.T) {
f := fuzz.New().NilChance(.5).NumElements(0, 1).RandSource(rand.NewSource(1))
for i := 0; i < 100; i++ {
m := &metav1.ObjectMeta{}
f.Fuzz(m)
partial := AsPartialObjectMetadata(m)
if !reflect.DeepEqual(&partial.ObjectMeta, m) {
t.Fatalf("incomplete partial object metadata: %s", diff.ObjectReflectDiff(&partial.ObjectMeta, m))
}
}
for i := 0; i < 100; i++ {
m := &metav1beta1.PartialObjectMetadata{}
f.Fuzz(&m.ObjectMeta)
partial := AsPartialObjectMetadata(m)
if !reflect.DeepEqual(&partial.ObjectMeta, &m.ObjectMeta) {
t.Fatalf("incomplete partial object metadata: %s", diff.ObjectReflectDiff(&partial.ObjectMeta, &m.ObjectMeta))
}
}
}

View file

@ -1,391 +0,0 @@
/*
Copyright 2014 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 meta
import (
"errors"
"reflect"
"testing"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func TestMultiRESTMapperResourceFor(t *testing.T) {
tcs := []struct {
name string
mapper MultiRESTMapper
input schema.GroupVersionResource
result schema.GroupVersionResource
err error
}{
{
name: "empty",
mapper: MultiRESTMapper{},
input: schema.GroupVersionResource{Resource: "foo"},
result: schema.GroupVersionResource{},
err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "foo"}},
},
{
name: "ignore not found",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "IGNORE_THIS"}}}},
input: schema.GroupVersionResource{Resource: "foo"},
result: schema.GroupVersionResource{},
err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "foo"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "unused"}}}},
input: schema.GroupVersionResource{Resource: "foo"},
result: schema.GroupVersionResource{},
err: errors.New("fail on this"),
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.ResourceFor(tc.input)
if e, a := tc.result, actualResult; e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
switch {
case tc.err == nil && actualErr == nil:
case tc.err == nil:
t.Errorf("%s: unexpected error: %v", tc.name, actualErr)
case actualErr == nil:
t.Errorf("%s: expected error: %v got nil", tc.name, tc.err)
case tc.err.Error() != actualErr.Error():
t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
}
}
}
func TestMultiRESTMapperResourcesFor(t *testing.T) {
tcs := []struct {
name string
mapper MultiRESTMapper
input schema.GroupVersionResource
result []schema.GroupVersionResource
err error
}{
{
name: "empty",
mapper: MultiRESTMapper{},
input: schema.GroupVersionResource{Resource: "foo"},
result: nil,
err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "foo"}},
},
{
name: "ignore not found",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "IGNORE_THIS"}}}},
input: schema.GroupVersionResource{Resource: "foo"},
result: nil,
err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "foo"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "unused"}}}},
input: schema.GroupVersionResource{Resource: "foo"},
result: nil,
err: errors.New("fail on this"),
},
{
name: "union and dedup",
mapper: MultiRESTMapper{
fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "dupe"}, {Resource: "first"}}},
fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "dupe"}, {Resource: "second"}}},
},
input: schema.GroupVersionResource{Resource: "foo"},
result: []schema.GroupVersionResource{{Resource: "dupe"}, {Resource: "first"}, {Resource: "second"}},
},
{
name: "skip not and continue",
mapper: MultiRESTMapper{
fixedRESTMapper{err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "IGNORE_THIS"}}},
fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "first"}, {Resource: "second"}}},
},
input: schema.GroupVersionResource{Resource: "foo"},
result: []schema.GroupVersionResource{{Resource: "first"}, {Resource: "second"}},
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.ResourcesFor(tc.input)
if e, a := tc.result, actualResult; !reflect.DeepEqual(e, a) {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
switch {
case tc.err == nil && actualErr == nil:
case tc.err == nil:
t.Errorf("%s: unexpected error: %v", tc.name, actualErr)
case actualErr == nil:
t.Errorf("%s: expected error: %v got nil", tc.name, tc.err)
case tc.err.Error() != actualErr.Error():
t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
}
}
}
func TestMultiRESTMapperKindsFor(t *testing.T) {
tcs := []struct {
name string
mapper MultiRESTMapper
input schema.GroupVersionResource
result []schema.GroupVersionKind
err error
}{
{
name: "empty",
mapper: MultiRESTMapper{},
input: schema.GroupVersionResource{Resource: "foo"},
result: nil,
err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "foo"}},
},
{
name: "ignore not found",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "IGNORE_THIS"}}}},
input: schema.GroupVersionResource{Resource: "foo"},
result: nil,
err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "foo"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "unused"}}}},
input: schema.GroupVersionResource{Resource: "foo"},
result: nil,
err: errors.New("fail on this"),
},
{
name: "union and dedup",
mapper: MultiRESTMapper{
fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "dupe"}, {Kind: "first"}}},
fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "dupe"}, {Kind: "second"}}},
},
input: schema.GroupVersionResource{Resource: "foo"},
result: []schema.GroupVersionKind{{Kind: "dupe"}, {Kind: "first"}, {Kind: "second"}},
},
{
name: "skip not and continue",
mapper: MultiRESTMapper{
fixedRESTMapper{err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "IGNORE_THIS"}}},
fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "first"}, {Kind: "second"}}},
},
input: schema.GroupVersionResource{Resource: "foo"},
result: []schema.GroupVersionKind{{Kind: "first"}, {Kind: "second"}},
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.KindsFor(tc.input)
if e, a := tc.result, actualResult; !reflect.DeepEqual(e, a) {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
switch {
case tc.err == nil && actualErr == nil:
case tc.err == nil:
t.Errorf("%s: unexpected error: %v", tc.name, actualErr)
case actualErr == nil:
t.Errorf("%s: expected error: %v got nil", tc.name, tc.err)
case tc.err.Error() != actualErr.Error():
t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
}
}
}
func TestMultiRESTMapperKindFor(t *testing.T) {
tcs := []struct {
name string
mapper MultiRESTMapper
input schema.GroupVersionResource
result schema.GroupVersionKind
err error
}{
{
name: "empty",
mapper: MultiRESTMapper{},
input: schema.GroupVersionResource{Resource: "foo"},
result: schema.GroupVersionKind{},
err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "foo"}},
},
{
name: "ignore not found",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "IGNORE_THIS"}}}},
input: schema.GroupVersionResource{Resource: "foo"},
result: schema.GroupVersionKind{},
err: &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Resource: "foo"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "unused"}}}},
input: schema.GroupVersionResource{Resource: "foo"},
result: schema.GroupVersionKind{},
err: errors.New("fail on this"),
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.KindFor(tc.input)
if e, a := tc.result, actualResult; e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
switch {
case tc.err == nil && actualErr == nil:
case tc.err == nil:
t.Errorf("%s: unexpected error: %v", tc.name, actualErr)
case actualErr == nil:
t.Errorf("%s: expected error: %v got nil", tc.name, tc.err)
case tc.err.Error() != actualErr.Error():
t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
}
}
}
func TestMultiRESTMapperRESTMappings(t *testing.T) {
mapping1, mapping2 := &RESTMapping{}, &RESTMapping{}
tcs := []struct {
name string
mapper MultiRESTMapper
groupKind schema.GroupKind
versions []string
result []*RESTMapping
err error
}{
{
name: "empty with no versions",
mapper: MultiRESTMapper{},
groupKind: schema.GroupKind{Kind: "Foo"},
result: nil,
err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}},
},
{
name: "empty with one version",
mapper: MultiRESTMapper{},
groupKind: schema.GroupKind{Kind: "Foo"},
versions: []string{"v1beta"},
result: nil,
err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}, SearchedVersions: []string{"v1beta"}},
},
{
name: "empty with multi(two) vesions",
mapper: MultiRESTMapper{},
groupKind: schema.GroupKind{Kind: "Foo"},
versions: []string{"v1beta", "v2"},
result: nil,
err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}, SearchedVersions: []string{"v1beta", "v2"}},
},
{
name: "ignore not found with kind not exist",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "IGNORE_THIS"}}}},
groupKind: schema.GroupKind{Kind: "Foo"},
versions: nil,
result: nil,
err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}},
},
{
name: "ignore not found with version not exist",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}, SearchedVersions: []string{"v1"}}}},
groupKind: schema.GroupKind{Kind: "Foo"},
versions: []string{"v1beta"},
result: nil,
err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}, SearchedVersions: []string{"v1beta"}},
},
{
name: "ignore not found with multi versions not exist",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}, SearchedVersions: []string{"v1"}}}},
groupKind: schema.GroupKind{Kind: "Foo"},
versions: []string{"v1beta", "v2"},
result: nil,
err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}, SearchedVersions: []string{"v1beta", "v2"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{mappings: []*RESTMapping{mapping1}}},
groupKind: schema.GroupKind{Kind: "Foo"},
versions: []string{"v1beta"},
result: nil,
err: errors.New("fail on this"),
},
{
name: "return both",
mapper: MultiRESTMapper{fixedRESTMapper{mappings: []*RESTMapping{mapping1}}, fixedRESTMapper{mappings: []*RESTMapping{mapping2}}},
groupKind: schema.GroupKind{Kind: "Foo"},
versions: []string{"v1beta"},
result: []*RESTMapping{mapping1, mapping2},
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.RESTMappings(tc.groupKind, tc.versions...)
if e, a := tc.result, actualResult; !reflect.DeepEqual(e, a) {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
switch {
case tc.err == nil && actualErr == nil:
case tc.err == nil:
t.Errorf("%s: unexpected error: %v", tc.name, actualErr)
case actualErr == nil:
t.Errorf("%s: expected error: %v got nil", tc.name, tc.err)
case tc.err.Error() != actualErr.Error():
t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
}
}
}
type fixedRESTMapper struct {
resourcesFor []schema.GroupVersionResource
kindsFor []schema.GroupVersionKind
resourceFor schema.GroupVersionResource
kindFor schema.GroupVersionKind
mappings []*RESTMapping
err error
}
func (m fixedRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
return "", m.err
}
func (m fixedRESTMapper) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) {
return m.resourcesFor, m.err
}
func (m fixedRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvk []schema.GroupVersionKind, err error) {
return m.kindsFor, m.err
}
func (m fixedRESTMapper) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) {
return m.resourceFor, m.err
}
func (m fixedRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
return m.kindFor, m.err
}
func (m fixedRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (mapping *RESTMapping, err error) {
return nil, m.err
}
func (m fixedRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (mappings []*RESTMapping, err error) {
return m.mappings, m.err
}
func (m fixedRESTMapper) ResourceIsValid(resource schema.GroupVersionResource) bool {
return false
}

View file

@ -1,346 +0,0 @@
/*
Copyright 2016 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 meta
import (
"errors"
"reflect"
"strings"
"testing"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) {
tcs := []struct {
name string
delegate RESTMapper
resourcePatterns []schema.GroupVersionResource
result schema.GroupVersionResource
err string
}{
{
name: "single hit",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "single-hit"}}},
result: schema.GroupVersionResource{Resource: "single-hit"},
},
{
name: "ambiguous match",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{
{Group: "one", Version: "a", Resource: "first"},
{Group: "two", Version: "b", Resource: "second"},
}},
err: "matches multiple resources",
},
{
name: "group selection",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{
{Group: "one", Version: "a", Resource: "first"},
{Group: "two", Version: "b", Resource: "second"},
}},
resourcePatterns: []schema.GroupVersionResource{
{Group: "one", Version: AnyVersion, Resource: AnyResource},
},
result: schema.GroupVersionResource{Group: "one", Version: "a", Resource: "first"},
},
{
name: "empty match continues",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{
{Group: "one", Version: "a", Resource: "first"},
{Group: "two", Version: "b", Resource: "second"},
}},
resourcePatterns: []schema.GroupVersionResource{
{Group: "fail", Version: AnyVersion, Resource: AnyResource},
{Group: "one", Version: AnyVersion, Resource: AnyResource},
},
result: schema.GroupVersionResource{Group: "one", Version: "a", Resource: "first"},
},
{
name: "group followed by version selection",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{
{Group: "one", Version: "a", Resource: "first"},
{Group: "two", Version: "b", Resource: "second"},
{Group: "one", Version: "c", Resource: "third"},
}},
resourcePatterns: []schema.GroupVersionResource{
{Group: "one", Version: AnyVersion, Resource: AnyResource},
{Group: AnyGroup, Version: "a", Resource: AnyResource},
},
result: schema.GroupVersionResource{Group: "one", Version: "a", Resource: "first"},
},
{
name: "resource selection",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{
{Group: "one", Version: "a", Resource: "first"},
{Group: "one", Version: "a", Resource: "second"},
}},
resourcePatterns: []schema.GroupVersionResource{
{Group: AnyGroup, Version: AnyVersion, Resource: "second"},
},
result: schema.GroupVersionResource{Group: "one", Version: "a", Resource: "second"},
},
}
for _, tc := range tcs {
mapper := PriorityRESTMapper{Delegate: tc.delegate, ResourcePriority: tc.resourcePatterns}
actualResult, actualErr := mapper.ResourceFor(schema.GroupVersionResource{})
if e, a := tc.result, actualResult; e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
if len(tc.err) == 0 && actualErr == nil {
continue
}
if len(tc.err) > 0 && actualErr == nil {
t.Errorf("%s: missing expected err: %v", tc.name, tc.err)
continue
}
if !strings.Contains(actualErr.Error(), tc.err) {
t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
}
}
}
func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) {
tcs := []struct {
name string
delegate RESTMapper
kindPatterns []schema.GroupVersionKind
result schema.GroupVersionKind
err string
}{
{
name: "single hit",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "single-hit"}}},
result: schema.GroupVersionKind{Kind: "single-hit"},
},
{
name: "ambiguous match",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{
{Group: "one", Version: "a", Kind: "first"},
{Group: "two", Version: "b", Kind: "second"},
}},
err: "matches multiple kinds",
},
{
name: "group selection",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{
{Group: "one", Version: "a", Kind: "first"},
{Group: "two", Version: "b", Kind: "second"},
}},
kindPatterns: []schema.GroupVersionKind{
{Group: "one", Version: AnyVersion, Kind: AnyKind},
},
result: schema.GroupVersionKind{Group: "one", Version: "a", Kind: "first"},
},
{
name: "empty match continues",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{
{Group: "one", Version: "a", Kind: "first"},
{Group: "two", Version: "b", Kind: "second"},
}},
kindPatterns: []schema.GroupVersionKind{
{Group: "fail", Version: AnyVersion, Kind: AnyKind},
{Group: "one", Version: AnyVersion, Kind: AnyKind},
},
result: schema.GroupVersionKind{Group: "one", Version: "a", Kind: "first"},
},
{
name: "group followed by version selection",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{
{Group: "one", Version: "a", Kind: "first"},
{Group: "two", Version: "b", Kind: "second"},
{Group: "one", Version: "c", Kind: "third"},
}},
kindPatterns: []schema.GroupVersionKind{
{Group: "one", Version: AnyVersion, Kind: AnyKind},
{Group: AnyGroup, Version: "a", Kind: AnyKind},
},
result: schema.GroupVersionKind{Group: "one", Version: "a", Kind: "first"},
},
{
name: "kind selection",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{
{Group: "one", Version: "a", Kind: "first"},
{Group: "one", Version: "a", Kind: "second"},
}},
kindPatterns: []schema.GroupVersionKind{
{Group: AnyGroup, Version: AnyVersion, Kind: "second"},
},
result: schema.GroupVersionKind{Group: "one", Version: "a", Kind: "second"},
},
}
for _, tc := range tcs {
mapper := PriorityRESTMapper{Delegate: tc.delegate, KindPriority: tc.kindPatterns}
actualResult, actualErr := mapper.KindFor(schema.GroupVersionResource{})
if e, a := tc.result, actualResult; e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
if len(tc.err) == 0 && actualErr == nil {
continue
}
if len(tc.err) > 0 && actualErr == nil {
t.Errorf("%s: missing expected err: %v", tc.name, tc.err)
continue
}
if !strings.Contains(actualErr.Error(), tc.err) {
t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
}
}
}
func TestPriorityRESTMapperRESTMapping(t *testing.T) {
mapping1 := &RESTMapping{
GroupVersionKind: schema.GroupVersionKind{Kind: "Foo", Version: "v1alpha1"},
}
mapping2 := &RESTMapping{
GroupVersionKind: schema.GroupVersionKind{Kind: "Foo", Version: "v1"},
}
mapping3 := &RESTMapping{
GroupVersionKind: schema.GroupVersionKind{Group: "other", Kind: "Foo", Version: "v1"},
}
allMappers := MultiRESTMapper{
fixedRESTMapper{mappings: []*RESTMapping{mapping1}},
fixedRESTMapper{mappings: []*RESTMapping{mapping2}},
fixedRESTMapper{mappings: []*RESTMapping{mapping3}},
}
tcs := []struct {
name string
mapper PriorityRESTMapper
input schema.GroupKind
result *RESTMapping
err error
}{
{
name: "empty",
mapper: PriorityRESTMapper{Delegate: MultiRESTMapper{}},
input: schema.GroupKind{Kind: "Foo"},
err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}},
},
{
name: "ignore not found",
mapper: PriorityRESTMapper{Delegate: MultiRESTMapper{fixedRESTMapper{err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "IGNORE_THIS"}}}}},
input: schema.GroupKind{Kind: "Foo"},
err: &NoKindMatchError{GroupKind: schema.GroupKind{Kind: "Foo"}},
},
{
name: "accept first failure",
mapper: PriorityRESTMapper{Delegate: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{mappings: []*RESTMapping{mapping1}}}},
input: schema.GroupKind{Kind: "Foo"},
err: errors.New("fail on this"),
},
{
name: "return error for ambiguous",
mapper: PriorityRESTMapper{
Delegate: allMappers,
},
input: schema.GroupKind{Kind: "Foo"},
err: &AmbiguousKindError{
PartialKind: schema.GroupVersionKind{Kind: "Foo"},
MatchingKinds: []schema.GroupVersionKind{
{Kind: "Foo", Version: "v1alpha1"},
{Kind: "Foo", Version: "v1"},
{Group: "other", Kind: "Foo", Version: "v1"},
},
},
},
{
name: "accept only item",
mapper: PriorityRESTMapper{
Delegate: fixedRESTMapper{mappings: []*RESTMapping{mapping1}},
},
input: schema.GroupKind{Kind: "Foo"},
result: mapping1,
},
{
name: "return single priority",
mapper: PriorityRESTMapper{
Delegate: allMappers,
KindPriority: []schema.GroupVersionKind{{Version: "v1", Kind: AnyKind}, {Version: "v1alpha1", Kind: AnyKind}},
},
input: schema.GroupKind{Kind: "Foo"},
result: mapping2,
},
{
name: "return out of group match",
mapper: PriorityRESTMapper{
Delegate: allMappers,
KindPriority: []schema.GroupVersionKind{{Group: AnyGroup, Version: "v1", Kind: AnyKind}, {Group: "other", Version: AnyVersion, Kind: AnyKind}},
},
input: schema.GroupKind{Kind: "Foo"},
result: mapping3,
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.RESTMapping(tc.input)
if e, a := tc.result, actualResult; !reflect.DeepEqual(e, a) {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
switch {
case tc.err == nil && actualErr == nil:
case tc.err == nil:
t.Errorf("%s: unexpected error: %v", tc.name, actualErr)
case actualErr == nil:
t.Errorf("%s: expected error: %v got nil", tc.name, tc.err)
case tc.err.Error() != actualErr.Error():
t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr)
}
}
}
func TestPriorityRESTMapperRESTMappingHonorsUserVersion(t *testing.T) {
mappingV2alpha1 := &RESTMapping{
GroupVersionKind: schema.GroupVersionKind{Group: "Bar", Kind: "Foo", Version: "v2alpha1"},
}
mappingV1 := &RESTMapping{
GroupVersionKind: schema.GroupVersionKind{Group: "Bar", Kind: "Foo", Version: "v1"},
}
allMappers := MultiRESTMapper{
fixedRESTMapper{mappings: []*RESTMapping{mappingV2alpha1}},
fixedRESTMapper{mappings: []*RESTMapping{mappingV1}},
}
mapper := PriorityRESTMapper{
Delegate: allMappers,
KindPriority: []schema.GroupVersionKind{{Group: "Bar", Version: "v2alpha1", Kind: AnyKind}, {Group: "Bar", Version: AnyVersion, Kind: AnyKind}},
}
outMapping1, err := mapper.RESTMapping(schema.GroupKind{Group: "Bar", Kind: "Foo"}, "v1")
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if outMapping1 != mappingV1 {
t.Errorf("asked for version %v, expected mapping for %v, got mapping for %v", "v1", mappingV1.GroupVersionKind, outMapping1.GroupVersionKind)
}
outMapping2, err := mapper.RESTMapping(schema.GroupKind{Group: "Bar", Kind: "Foo"}, "v2alpha1")
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if outMapping2 != mappingV2alpha1 {
t.Errorf("asked for version %v, expected mapping for %v, got mapping for %v", "v2alpha1", mappingV2alpha1.GroupVersionKind, outMapping2.GroupVersionKind)
}
}

View file

@ -1,751 +0,0 @@
/*
Copyright 2014 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 meta
import (
"errors"
"reflect"
"strings"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
type fakeConvertor struct{}
func (fakeConvertor) Convert(in, out, context interface{}) error {
return nil
}
func (fakeConvertor) ConvertToVersion(in runtime.Object, _ runtime.GroupVersioner) (runtime.Object, error) {
return in, nil
}
func (fakeConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
return label, value, nil
}
var validAccessor = resourceAccessor{}
var validConvertor = fakeConvertor{}
func fakeInterfaces(version schema.GroupVersion) (*VersionInterfaces, error) {
return &VersionInterfaces{ObjectConvertor: validConvertor, MetadataAccessor: validAccessor}, nil
}
var unmatchedErr = errors.New("no version")
func unmatchedVersionInterfaces(version schema.GroupVersion) (*VersionInterfaces, error) {
return nil, unmatchedErr
}
func TestRESTMapperVersionAndKindForResource(t *testing.T) {
testGroup := "test.group"
testVersion := "test"
testGroupVersion := schema.GroupVersion{Group: testGroup, Version: testVersion}
testCases := []struct {
Resource schema.GroupVersionResource
GroupVersionToRegister schema.GroupVersion
ExpectedGVK schema.GroupVersionKind
Err bool
}{
{Resource: schema.GroupVersionResource{Resource: "internalobjec"}, Err: true},
{Resource: schema.GroupVersionResource{Resource: "internalObjec"}, Err: true},
{Resource: schema.GroupVersionResource{Resource: "internalobject"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
{Resource: schema.GroupVersionResource{Resource: "internalobjects"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}, fakeInterfaces)
if len(testCase.ExpectedGVK.Kind) != 0 {
mapper.Add(testCase.ExpectedGVK, RESTScopeNamespace)
}
actualGVK, err := mapper.KindFor(testCase.Resource)
hasErr := err != nil
if hasErr != testCase.Err {
t.Errorf("%d: unexpected error behavior %t: %v", i, testCase.Err, err)
continue
}
if err != nil {
continue
}
if actualGVK != testCase.ExpectedGVK {
t.Errorf("%d: unexpected version and kind: e=%s a=%s", i, testCase.ExpectedGVK, actualGVK)
}
}
}
func TestRESTMapperGroupForResource(t *testing.T) {
testCases := []struct {
Resource schema.GroupVersionResource
GroupVersionKind schema.GroupVersionKind
Err bool
}{
{Resource: schema.GroupVersionResource{Resource: "myObject"}, GroupVersionKind: schema.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
{Resource: schema.GroupVersionResource{Resource: "myobject"}, GroupVersionKind: schema.GroupVersionKind{Group: "testapi2", Version: "test", Kind: "MyObject"}},
{Resource: schema.GroupVersionResource{Resource: "myObje"}, Err: true, GroupVersionKind: schema.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
{Resource: schema.GroupVersionResource{Resource: "myobje"}, Err: true, GroupVersionKind: schema.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces)
mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace)
actualGVK, err := mapper.KindFor(testCase.Resource)
if testCase.Err {
if err == nil {
t.Errorf("%d: expected error", i)
}
} else if err != nil {
t.Errorf("%d: unexpected error: %v", i, err)
} else if actualGVK != testCase.GroupVersionKind {
t.Errorf("%d: expected group %q, got %q", i, testCase.GroupVersionKind, actualGVK)
}
}
}
func TestRESTMapperKindsFor(t *testing.T) {
testCases := []struct {
Name string
PreferredOrder []schema.GroupVersion
KindsToRegister []schema.GroupVersionKind
PartialResourceToRequest schema.GroupVersionResource
ExpectedKinds []schema.GroupVersionKind
ExpectedKindErr string
}{
{
// exact matches are preferred
Name: "groups, with group exact",
PreferredOrder: []schema.GroupVersion{
{Group: "first-group-1", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group-1", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
PartialResourceToRequest: schema.GroupVersionResource{Group: "first-group", Resource: "my-kind"},
ExpectedKinds: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
},
{
// group prefixes work
Name: "groups, with group prefix",
PreferredOrder: []schema.GroupVersion{
{Group: "second-group", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
},
PartialResourceToRequest: schema.GroupVersionResource{Group: "first", Resource: "my-kind"},
ExpectedKinds: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
},
{
// group prefixes can be ambiguous
Name: "groups, with ambiguous group prefix",
PreferredOrder: []schema.GroupVersion{
{Group: "first-group-1", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group-1", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
PartialResourceToRequest: schema.GroupVersionResource{Group: "first", Resource: "my-kind"},
ExpectedKinds: []schema.GroupVersionKind{
{Group: "first-group-1", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
ExpectedKindErr: " matches multiple kinds ",
},
{
Name: "ambiguous groups, with preference order",
PreferredOrder: []schema.GroupVersion{
{Group: "second-group", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
},
PartialResourceToRequest: schema.GroupVersionResource{Resource: "my-kinds"},
ExpectedKinds: []schema.GroupVersionKind{
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
ExpectedKindErr: " matches multiple kinds ",
},
{
Name: "ambiguous groups, with explicit group match",
PreferredOrder: []schema.GroupVersion{
{Group: "second-group", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
},
PartialResourceToRequest: schema.GroupVersionResource{Group: "first-group", Resource: "my-kinds"},
ExpectedKinds: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
},
{
Name: "ambiguous groups, with ambiguous version match",
PreferredOrder: []schema.GroupVersion{
{Group: "first-group", Version: "first-version"},
{Group: "second-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
},
PartialResourceToRequest: schema.GroupVersionResource{Version: "first-version", Resource: "my-kinds"},
ExpectedKinds: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
},
ExpectedKindErr: " matches multiple kinds ",
},
}
for _, testCase := range testCases {
tcName := testCase.Name
mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces)
for _, kind := range testCase.KindsToRegister {
mapper.Add(kind, RESTScopeNamespace)
}
actualKinds, err := mapper.KindsFor(testCase.PartialResourceToRequest)
if err != nil {
t.Errorf("%s: unexpected error: %v", tcName, err)
continue
}
if !reflect.DeepEqual(testCase.ExpectedKinds, actualKinds) {
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKinds, actualKinds)
}
singleKind, err := mapper.KindFor(testCase.PartialResourceToRequest)
if err == nil && len(testCase.ExpectedKindErr) != 0 {
t.Errorf("%s: expected error: %v", tcName, testCase.ExpectedKindErr)
continue
}
if err != nil {
if len(testCase.ExpectedKindErr) == 0 {
t.Errorf("%s: unexpected error: %v", tcName, err)
continue
} else {
if !strings.Contains(err.Error(), testCase.ExpectedKindErr) {
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKindErr, err)
continue
}
}
} else {
if testCase.ExpectedKinds[0] != singleKind {
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKinds[0], singleKind)
}
}
}
}
func TestRESTMapperResourcesFor(t *testing.T) {
testCases := []struct {
Name string
PreferredOrder []schema.GroupVersion
KindsToRegister []schema.GroupVersionKind
PluralPartialResourceToRequest schema.GroupVersionResource
SingularPartialResourceToRequest schema.GroupVersionResource
ExpectedResources []schema.GroupVersionResource
ExpectedResourceErr string
}{
{
// exact matches are preferred
Name: "groups, with group exact",
PreferredOrder: []schema.GroupVersion{
{Group: "first-group-1", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group-1", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
PluralPartialResourceToRequest: schema.GroupVersionResource{Group: "first-group", Resource: "my-kinds"},
SingularPartialResourceToRequest: schema.GroupVersionResource{Group: "first-group", Resource: "my-kind"},
ExpectedResources: []schema.GroupVersionResource{
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
},
},
{
// group prefixes work
Name: "groups, with group prefix",
PreferredOrder: []schema.GroupVersion{
{Group: "second-group", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
},
PluralPartialResourceToRequest: schema.GroupVersionResource{Group: "first", Resource: "my-kinds"},
SingularPartialResourceToRequest: schema.GroupVersionResource{Group: "first", Resource: "my-kind"},
ExpectedResources: []schema.GroupVersionResource{
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
},
},
{
// group prefixes can be ambiguous
Name: "groups, with ambiguous group prefix",
PreferredOrder: []schema.GroupVersion{
{Group: "first-group-1", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group-1", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
PluralPartialResourceToRequest: schema.GroupVersionResource{Group: "first", Resource: "my-kinds"},
SingularPartialResourceToRequest: schema.GroupVersionResource{Group: "first", Resource: "my-kind"},
ExpectedResources: []schema.GroupVersionResource{
{Group: "first-group-1", Version: "first-version", Resource: "my-kinds"},
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
},
ExpectedResourceErr: " matches multiple resources ",
},
{
Name: "ambiguous groups, with preference order",
PreferredOrder: []schema.GroupVersion{
{Group: "second-group", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
},
PluralPartialResourceToRequest: schema.GroupVersionResource{Resource: "my-kinds"},
SingularPartialResourceToRequest: schema.GroupVersionResource{Resource: "my-kind"},
ExpectedResources: []schema.GroupVersionResource{
{Group: "second-group", Version: "first-version", Resource: "my-kinds"},
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
},
ExpectedResourceErr: " matches multiple resources ",
},
{
Name: "ambiguous groups, with explicit group match",
PreferredOrder: []schema.GroupVersion{
{Group: "second-group", Version: "first-version"},
{Group: "first-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
},
PluralPartialResourceToRequest: schema.GroupVersionResource{Group: "first-group", Resource: "my-kinds"},
SingularPartialResourceToRequest: schema.GroupVersionResource{Group: "first-group", Resource: "my-kind"},
ExpectedResources: []schema.GroupVersionResource{
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
},
},
{
Name: "ambiguous groups, with ambiguous version match",
PreferredOrder: []schema.GroupVersion{
{Group: "first-group", Version: "first-version"},
{Group: "second-group", Version: "first-version"},
},
KindsToRegister: []schema.GroupVersionKind{
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
},
PluralPartialResourceToRequest: schema.GroupVersionResource{Version: "first-version", Resource: "my-kinds"},
SingularPartialResourceToRequest: schema.GroupVersionResource{Version: "first-version", Resource: "my-kind"},
ExpectedResources: []schema.GroupVersionResource{
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
{Group: "second-group", Version: "first-version", Resource: "my-kinds"},
},
ExpectedResourceErr: " matches multiple resources ",
},
}
for _, testCase := range testCases {
tcName := testCase.Name
for _, partialResource := range []schema.GroupVersionResource{testCase.PluralPartialResourceToRequest, testCase.SingularPartialResourceToRequest} {
mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces)
for _, kind := range testCase.KindsToRegister {
mapper.Add(kind, RESTScopeNamespace)
}
actualResources, err := mapper.ResourcesFor(partialResource)
if err != nil {
t.Errorf("%s: unexpected error: %v", tcName, err)
continue
}
if !reflect.DeepEqual(testCase.ExpectedResources, actualResources) {
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResources, actualResources)
}
singleResource, err := mapper.ResourceFor(partialResource)
if err == nil && len(testCase.ExpectedResourceErr) != 0 {
t.Errorf("%s: expected error: %v", tcName, testCase.ExpectedResourceErr)
continue
}
if err != nil {
if len(testCase.ExpectedResourceErr) == 0 {
t.Errorf("%s: unexpected error: %v", tcName, err)
continue
} else {
if !strings.Contains(err.Error(), testCase.ExpectedResourceErr) {
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResourceErr, err)
continue
}
}
} else {
if testCase.ExpectedResources[0] != singleResource {
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResources[0], singleResource)
}
}
}
}
}
func TestKindToResource(t *testing.T) {
testCases := []struct {
Kind string
Plural, Singular string
}{
{Kind: "Pod", Plural: "pods", Singular: "pod"},
{Kind: "ReplicationController", Plural: "replicationcontrollers", Singular: "replicationcontroller"},
// Add "ies" when ending with "y"
{Kind: "ImageRepository", Plural: "imagerepositories", Singular: "imagerepository"},
// Add "es" when ending with "s"
{Kind: "miss", Plural: "misses", Singular: "miss"},
// Add "s" otherwise
{Kind: "lowercase", Plural: "lowercases", Singular: "lowercase"},
}
for i, testCase := range testCases {
version := schema.GroupVersion{}
plural, singular := UnsafeGuessKindToResource(version.WithKind(testCase.Kind))
if singular != version.WithResource(testCase.Singular) || plural != version.WithResource(testCase.Plural) {
t.Errorf("%d: unexpected plural and singular: %v %v", i, plural, singular)
}
}
}
func TestRESTMapperResourceSingularizer(t *testing.T) {
testGroupVersion := schema.GroupVersion{Group: "tgroup", Version: "test"}
testCases := []struct {
Kind string
Plural string
Singular string
}{
{Kind: "Pod", Plural: "pods", Singular: "pod"},
{Kind: "ReplicationController", Plural: "replicationcontrollers", Singular: "replicationcontroller"},
{Kind: "ImageRepository", Plural: "imagerepositories", Singular: "imagerepository"},
{Kind: "Status", Plural: "statuses", Singular: "status"},
{Kind: "lowercase", Plural: "lowercases", Singular: "lowercase"},
// TODO this test is broken. This updates to reflect actual behavior. Kinds are expected to be singular
// old (incorrect), comment: Don't add extra s if the original object is already plural
{Kind: "lowercases", Plural: "lowercaseses", Singular: "lowercases"},
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}, fakeInterfaces)
// create singular/plural mapping
mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace)
singular, err := mapper.ResourceSingularizer(testCase.Plural)
if err != nil {
t.Errorf("%d: unexpected error: %v", i, err)
}
if singular != testCase.Singular {
t.Errorf("%d: mismatched singular: got %v, expected %v", i, singular, testCase.Singular)
}
}
}
func TestRESTMapperRESTMapping(t *testing.T) {
testGroup := "tgroup"
testGroupVersion := schema.GroupVersion{Group: testGroup, Version: "test"}
internalGroupVersion := schema.GroupVersion{Group: testGroup, Version: "test"}
testCases := []struct {
Kind string
APIGroupVersions []schema.GroupVersion
DefaultVersions []schema.GroupVersion
Resource string
ExpectedGroupVersion *schema.GroupVersion
Err bool
}{
{Kind: "Unknown", Err: true},
{Kind: "InternalObject", Err: true},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "Unknown", Err: true},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &schema.GroupVersion{Group: testGroup, Version: "test"}},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
// TODO: add test for a resource that exists in one version but not another
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces)
mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace)
preferredVersions := []string{}
for _, gv := range testCase.APIGroupVersions {
preferredVersions = append(preferredVersions, gv.Version)
}
gk := schema.GroupKind{Group: testGroup, Kind: testCase.Kind}
mapping, err := mapper.RESTMapping(gk, preferredVersions...)
hasErr := err != nil
if hasErr != testCase.Err {
t.Errorf("%d: unexpected error behavior %t: %v", i, testCase.Err, err)
}
if hasErr {
continue
}
if mapping.Resource != testCase.Resource {
t.Errorf("%d: unexpected resource: %#v", i, mapping)
}
if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil {
t.Errorf("%d: missing codec and accessor: %#v", i, mapping)
}
groupVersion := testCase.ExpectedGroupVersion
if groupVersion == nil {
groupVersion = &testCase.APIGroupVersions[0]
}
if mapping.GroupVersionKind.GroupVersion() != *groupVersion {
t.Errorf("%d: unexpected version: %#v", i, mapping)
}
}
}
func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) {
expectedGroupVersion1 := schema.GroupVersion{Group: "tgroup", Version: "test1"}
expectedGroupVersion2 := schema.GroupVersion{Group: "tgroup", Version: "test2"}
expectedGroupVersion3 := schema.GroupVersion{Group: "tgroup", Version: "test3"}
internalObjectGK := schema.GroupKind{Group: "tgroup", Kind: "InternalObject"}
otherObjectGK := schema.GroupKind{Group: "tgroup", Kind: "OtherObject"}
mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, fakeInterfaces)
mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace)
mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace)
// pick default matching object kind based on search order
mapping, err := mapper.RESTMapping(otherObjectGK)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 {
t.Errorf("unexpected mapping: %#v", mapping)
}
mapping, err = mapper.RESTMapping(internalObjectGK)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if mapping.Resource != "internalobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 {
t.Errorf("unexpected mapping: %#v", mapping)
}
// mismatch of version
mapping, err = mapper.RESTMapping(internalObjectGK, expectedGroupVersion2.Version)
if err == nil {
t.Errorf("unexpected non-error")
}
mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion1.Version)
if err == nil {
t.Errorf("unexpected non-error")
}
// not in the search versions
mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version)
if err == nil {
t.Errorf("unexpected non-error")
}
// explicit search order
mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version, expectedGroupVersion1.Version)
if err == nil {
t.Errorf("unexpected non-error")
}
mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version, expectedGroupVersion2.Version)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 {
t.Errorf("unexpected mapping: %#v", mapping)
}
}
func TestRESTMapperRESTMappings(t *testing.T) {
testGroup := "tgroup"
testGroupVersion := schema.GroupVersion{Group: testGroup, Version: "v1"}
testCases := []struct {
Kind string
APIGroupVersions []schema.GroupVersion
DefaultVersions []schema.GroupVersion
AddGroupVersionKind []schema.GroupVersionKind
ExpectedRESTMappings []*RESTMapping
Err bool
}{
{Kind: "Unknown", Err: true},
{Kind: "InternalObject", Err: true},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "Unknown", Err: true},
// ask for specific version - not available - thus error
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v2"}}, Err: true},
// ask for specific version - available - check ExpectedRESTMappings
{
DefaultVersions: []schema.GroupVersion{testGroupVersion},
Kind: "InternalObject",
APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v2"}},
AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")},
ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}},
},
// ask for specific versions - only one available - check ExpectedRESTMappings
{
DefaultVersions: []schema.GroupVersion{testGroupVersion},
Kind: "InternalObject",
APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v3"}, {Group: testGroup, Version: "v2"}},
AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")},
ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}},
},
// do not ask for specific version - search through default versions - check ExpectedRESTMappings
{
DefaultVersions: []schema.GroupVersion{testGroupVersion, {Group: testGroup, Version: "v2"}},
Kind: "InternalObject",
AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v1"}.WithKind("InternalObject"), schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")},
ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v1", Kind: "InternalObject"}}, {Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}},
},
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces)
for _, gvk := range testCase.AddGroupVersionKind {
mapper.Add(gvk, RESTScopeNamespace)
}
preferredVersions := []string{}
for _, gv := range testCase.APIGroupVersions {
preferredVersions = append(preferredVersions, gv.Version)
}
gk := schema.GroupKind{Group: testGroup, Kind: testCase.Kind}
mappings, err := mapper.RESTMappings(gk, preferredVersions...)
hasErr := err != nil
if hasErr != testCase.Err {
t.Errorf("%d: unexpected error behavior %t: %v", i, testCase.Err, err)
}
if hasErr {
continue
}
if len(mappings) != len(testCase.ExpectedRESTMappings) {
t.Errorf("%d: unexpected number = %d of rest mappings was returned, expected = %d", i, len(mappings), len(testCase.ExpectedRESTMappings))
}
for j, mapping := range mappings {
exp := testCase.ExpectedRESTMappings[j]
if mapping.Resource != exp.Resource {
t.Errorf("%d - %d: unexpected resource: %#v", i, j, mapping)
}
if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil {
t.Errorf("%d - %d: missing codec and accessor: %#v", i, j, mapping)
}
if mapping.GroupVersionKind != exp.GroupVersionKind {
t.Errorf("%d - %d: unexpected GroupVersionKind: %#v", i, j, mapping)
}
}
}
}
func TestRESTMapperReportsErrorOnBadVersion(t *testing.T) {
expectedGroupVersion1 := schema.GroupVersion{Group: "tgroup", Version: "test1"}
expectedGroupVersion2 := schema.GroupVersion{Group: "tgroup", Version: "test2"}
internalObjectGK := schema.GroupKind{Group: "tgroup", Kind: "InternalObject"}
mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, unmatchedVersionInterfaces)
mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace)
_, err := mapper.RESTMapping(internalObjectGK, expectedGroupVersion1.Version)
if err == nil {
t.Errorf("unexpected non-error")
}
}

View file

@ -1,69 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"amount_test.go",
"math_test.go",
"quantity_proto_test.go",
"quantity_test.go",
"scale_int_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/gopkg.in/inf.v0:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"amount.go",
"generated.pb.go",
"math.go",
"quantity.go",
"quantity_proto.go",
"scale_int.go",
"suffix.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apimachinery/pkg/api/resource",
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/gopkg.in/inf.v0:go_default_library",
],
)
go_test(
name = "go_default_xtest",
srcs = ["quantity_example_test.go"],
deps = ["//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)

View file

@ -1,133 +0,0 @@
/*
Copyright 2014 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 resource
import (
"testing"
)
func TestInt64AmountAsInt64(t *testing.T) {
for _, test := range []struct {
value int64
scale Scale
result int64
ok bool
}{
{100, 0, 100, true},
{100, 1, 1000, true},
{100, -5, 0, false},
{100, 100, 0, false},
} {
r, ok := int64Amount{value: test.value, scale: test.scale}.AsInt64()
if r != test.result {
t.Errorf("%v: unexpected result: %d", test, r)
}
if ok != test.ok {
t.Errorf("%v: unexpected ok: %t", test, ok)
}
}
}
func TestInt64AmountAdd(t *testing.T) {
for _, test := range []struct {
a, b, c int64Amount
ok bool
}{
{int64Amount{value: 100, scale: 1}, int64Amount{value: 10, scale: 2}, int64Amount{value: 200, scale: 1}, true},
{int64Amount{value: 100, scale: 1}, int64Amount{value: 1, scale: 2}, int64Amount{value: 110, scale: 1}, true},
{int64Amount{value: 100, scale: 1}, int64Amount{value: 1, scale: 100}, int64Amount{value: 1, scale: 100}, false},
{int64Amount{value: -5, scale: 2}, int64Amount{value: 50, scale: 1}, int64Amount{value: 0, scale: 1}, true},
{int64Amount{value: -5, scale: 2}, int64Amount{value: 5, scale: 2}, int64Amount{value: 0, scale: 2}, true},
{int64Amount{value: mostPositive, scale: -1}, int64Amount{value: 1, scale: -1}, int64Amount{value: 0, scale: -1}, false},
{int64Amount{value: mostPositive, scale: -1}, int64Amount{value: 0, scale: -1}, int64Amount{value: mostPositive, scale: -1}, true},
{int64Amount{value: mostPositive / 10, scale: 1}, int64Amount{value: 10, scale: 0}, int64Amount{value: mostPositive, scale: -1}, false},
} {
c := test.a
ok := c.Add(test.b)
if ok != test.ok {
t.Errorf("%v: unexpected ok: %t", test, ok)
}
if ok {
if c != test.c {
t.Errorf("%v: unexpected result: %d", test, c)
}
} else {
if c != test.a {
t.Errorf("%v: overflow addition mutated source: %d", test, c)
}
}
// addition is commutative
c = test.b
if ok := c.Add(test.a); ok != test.ok {
t.Errorf("%v: unexpected ok: %t", test, ok)
}
if ok {
if c != test.c {
t.Errorf("%v: unexpected result: %d", test, c)
}
} else {
if c != test.b {
t.Errorf("%v: overflow addition mutated source: %d", test, c)
}
}
}
}
func TestInt64AsCanonicalString(t *testing.T) {
for _, test := range []struct {
value int64
scale Scale
result string
exponent int32
}{
{100, 0, "100", 0},
{100, 1, "1", 3},
{100, -1, "10", 0},
{10800, -10, "1080", -9},
} {
r, exp := int64Amount{value: test.value, scale: test.scale}.AsCanonicalBytes(nil)
if string(r) != test.result {
t.Errorf("%v: unexpected result: %s", test, r)
}
if exp != test.exponent {
t.Errorf("%v: unexpected exponent: %d", test, exp)
}
}
}
func TestAmountSign(t *testing.T) {
table := []struct {
i int64Amount
expect int
}{
{int64Amount{value: -50, scale: 1}, -1},
{int64Amount{value: 0, scale: 1}, 0},
{int64Amount{value: 300, scale: 1}, 1},
{int64Amount{value: -50, scale: -8}, -1},
{int64Amount{value: 50, scale: -8}, 1},
{int64Amount{value: 0, scale: -8}, 0},
{int64Amount{value: -50, scale: 0}, -1},
{int64Amount{value: 50, scale: 0}, 1},
{int64Amount{value: 0, scale: 0}, 0},
}
for _, testCase := range table {
if result := testCase.i.Sign(); result != testCase.expect {
t.Errorf("i: %v, Expected: %v, Actual: %v", testCase.i, testCase.expect, result)
}
}
}

View file

@ -1,211 +0,0 @@
/*
Copyright 2014 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 resource
import (
"testing"
)
func TestDetectOverflowAdd(t *testing.T) {
for _, test := range []struct {
a, b int64
c int64
ok bool
}{
{0, 0, 0, true},
{-1, 1, 0, true},
{0, 1, 1, true},
{2, 2, 4, true},
{2, -2, 0, true},
{-2, -2, -4, true},
{mostNegative, -1, 0, false},
{mostNegative, 1, mostNegative + 1, true},
{mostPositive, -1, mostPositive - 1, true},
{mostPositive, 1, 0, false},
{mostNegative, mostPositive, -1, true},
{mostPositive, mostNegative, -1, true},
{mostPositive, mostPositive, 0, false},
{mostNegative, mostNegative, 0, false},
{-mostPositive, mostNegative, 0, false},
{mostNegative, -mostPositive, 0, false},
{-mostPositive, -mostPositive, 0, false},
} {
c, ok := int64Add(test.a, test.b)
if c != test.c {
t.Errorf("%v: unexpected result: %d", test, c)
}
if ok != test.ok {
t.Errorf("%v: unexpected overflow: %t", test, ok)
}
// addition is commutative
d, ok2 := int64Add(test.b, test.a)
if c != d || ok != ok2 {
t.Errorf("%v: not commutative: %d %t", test, d, ok2)
}
}
}
func TestDetectOverflowMultiply(t *testing.T) {
for _, test := range []struct {
a, b int64
c int64
ok bool
}{
{0, 0, 0, true},
{-1, 1, -1, true},
{-1, -1, 1, true},
{1, 1, 1, true},
{0, 1, 0, true},
{1, 0, 0, true},
{2, 2, 4, true},
{2, -2, -4, true},
{-2, -2, 4, true},
{mostNegative, -1, 0, false},
{mostNegative, 1, mostNegative, true},
{mostPositive, -1, -mostPositive, true},
{mostPositive, 1, mostPositive, true},
{mostNegative, mostPositive, 0, false},
{mostPositive, mostNegative, 0, false},
{mostPositive, mostPositive, 1, false},
{mostNegative, mostNegative, 0, false},
{-mostPositive, mostNegative, 0, false},
{mostNegative, -mostPositive, 0, false},
{-mostPositive, -mostPositive, 1, false},
} {
c, ok := int64Multiply(test.a, test.b)
if c != test.c {
t.Errorf("%v: unexpected result: %d", test, c)
}
if ok != test.ok {
t.Errorf("%v: unexpected overflow: %t", test, ok)
}
// multiplication is commutative
d, ok2 := int64Multiply(test.b, test.a)
if c != d || ok != ok2 {
t.Errorf("%v: not commutative: %d %t", test, d, ok2)
}
}
}
func TestDetectOverflowScale(t *testing.T) {
for _, a := range []int64{0, -1, 1, 10, -10, mostPositive, mostNegative, -mostPositive} {
for _, b := range []int64{1, 2, 10, 100, 1000, mostPositive} {
expect, expectOk := int64Multiply(a, b)
c, ok := int64MultiplyScale(a, b)
if c != expect {
t.Errorf("%d*%d: unexpected result: %d", a, b, c)
}
if ok != expectOk {
t.Errorf("%d*%d: unexpected overflow: %t", a, b, ok)
}
}
for _, test := range []struct {
base int64
fn func(a int64) (int64, bool)
}{
{10, int64MultiplyScale10},
{100, int64MultiplyScale100},
{1000, int64MultiplyScale1000},
} {
expect, expectOk := int64Multiply(a, test.base)
c, ok := test.fn(a)
if c != expect {
t.Errorf("%d*%d: unexpected result: %d", a, test.base, c)
}
if ok != expectOk {
t.Errorf("%d*%d: unexpected overflow: %t", a, test.base, ok)
}
}
}
}
func TestRemoveInt64Factors(t *testing.T) {
for _, test := range []struct {
value int64
max int64
result int64
scale int32
}{
{100, 10, 1, 2},
{100, 10, 1, 2},
{100, 100, 1, 1},
{1, 10, 1, 0},
} {
r, s := removeInt64Factors(test.value, test.max)
if r != test.result {
t.Errorf("%v: unexpected result: %d", test, r)
}
if s != test.scale {
t.Errorf("%v: unexpected scale: %d", test, s)
}
}
}
func TestNegativeScaleInt64(t *testing.T) {
for _, test := range []struct {
base int64
scale Scale
result int64
exact bool
}{
{1234567, 0, 1234567, true},
{1234567, 1, 123457, false},
{1234567, 2, 12346, false},
{1234567, 3, 1235, false},
{1234567, 4, 124, false},
{-1234567, 0, -1234567, true},
{-1234567, 1, -123457, false},
{-1234567, 2, -12346, false},
{-1234567, 3, -1235, false},
{-1234567, 4, -124, false},
{1000, 0, 1000, true},
{1000, 1, 100, true},
{1000, 2, 10, true},
{1000, 3, 1, true},
{1000, 4, 1, false},
{-1000, 0, -1000, true},
{-1000, 1, -100, true},
{-1000, 2, -10, true},
{-1000, 3, -1, true},
{-1000, 4, -1, false},
{0, 0, 0, true},
{0, 1, 0, true},
{0, 2, 0, true},
// negative scale is undefined behavior
{1000, -1, 1000, true},
} {
result, exact := negativeScaleInt64(test.base, test.scale)
if result != test.result {
t.Errorf("%v: unexpected result: %d", test, result)
}
if exact != test.exact {
t.Errorf("%v: unexpected exact: %t", test, exact)
}
}
}

View file

@ -1,59 +0,0 @@
/*
Copyright 2014 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 resource_test
import (
"fmt"
"k8s.io/apimachinery/pkg/api/resource"
)
func ExampleFormat() {
memorySize := resource.NewQuantity(5*1024*1024*1024, resource.BinarySI)
fmt.Printf("memorySize = %v\n", memorySize)
diskSize := resource.NewQuantity(5*1000*1000*1000, resource.DecimalSI)
fmt.Printf("diskSize = %v\n", diskSize)
cores := resource.NewMilliQuantity(5300, resource.DecimalSI)
fmt.Printf("cores = %v\n", cores)
// Output:
// memorySize = 5Gi
// diskSize = 5G
// cores = 5300m
}
func ExampleMustParse() {
memorySize := resource.MustParse("5Gi")
fmt.Printf("memorySize = %v (%v)\n", memorySize.Value(), memorySize.Format)
diskSize := resource.MustParse("5G")
fmt.Printf("diskSize = %v (%v)\n", diskSize.Value(), diskSize.Format)
cores := resource.MustParse("5300m")
fmt.Printf("milliCores = %v (%v)\n", cores.MilliValue(), cores.Format)
cores2 := resource.MustParse("5.4")
fmt.Printf("milliCores = %v (%v)\n", cores2.MilliValue(), cores2.Format)
// Output:
// memorySize = 5368709120 (BinarySI)
// diskSize = 5000000000 (DecimalSI)
// milliCores = 5300 (DecimalSI)
// milliCores = 5400 (DecimalSI)
}

View file

@ -1,103 +0,0 @@
/*
Copyright 2017 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 resource
import (
"testing"
inf "gopkg.in/inf.v0"
)
func TestQuantityProtoMarshal(t *testing.T) {
// Test when d is nil
table := []struct {
quantity string
expect Quantity
}{
{"0", Quantity{i: int64Amount{value: 0, scale: 0}, s: "0", Format: DecimalSI}},
{"100m", Quantity{i: int64Amount{value: 100, scale: -3}, s: "100m", Format: DecimalSI}},
{"50m", Quantity{i: int64Amount{value: 50, scale: -3}, s: "50m", Format: DecimalSI}},
{"10000T", Quantity{i: int64Amount{value: 10000, scale: 12}, s: "10000T", Format: DecimalSI}},
}
for _, testCase := range table {
q := MustParse(testCase.quantity)
// Won't currently get an error as MarshalTo can't return one
result, _ := q.Marshal()
q.MarshalTo(result)
if q.Cmp(testCase.expect) != 0 {
t.Errorf("Expected: %v, Actual: %v", testCase.expect, q)
}
}
// Test when i is {0,0}
table2 := []struct {
dec *inf.Dec
expect Quantity
}{
{dec(0, 0).Dec, Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(0, 0).Dec}, s: "0", Format: DecimalSI}},
{dec(10, 0).Dec, Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(10, 0).Dec}, s: "10", Format: DecimalSI}},
{dec(-10, 0).Dec, Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(-10, 0).Dec}, s: "-10", Format: DecimalSI}},
}
for _, testCase := range table2 {
q := Quantity{d: infDecAmount{testCase.dec}, Format: DecimalSI}
// Won't currently get an error as MarshalTo can't return one
result, _ := q.Marshal()
q.Unmarshal(result)
if q.Cmp(testCase.expect) != 0 {
t.Errorf("Expected: %v, Actual: %v", testCase.expect, q)
}
}
}
func TestQuantityProtoUnmarshal(t *testing.T) {
// Test when d is nil
table := []struct {
input Quantity
expect string
}{
{Quantity{i: int64Amount{value: 0, scale: 0}, s: "0", Format: DecimalSI}, "0"},
{Quantity{i: int64Amount{value: 100, scale: -3}, s: "100m", Format: DecimalSI}, "100m"},
{Quantity{i: int64Amount{value: 50, scale: -3}, s: "50m", Format: DecimalSI}, "50m"},
{Quantity{i: int64Amount{value: 10000, scale: 12}, s: "10000T", Format: DecimalSI}, "10000T"},
}
for _, testCase := range table {
var inputQ Quantity
expectQ := MustParse(testCase.expect)
inputByteArray, _ := testCase.input.Marshal()
inputQ.Unmarshal(inputByteArray)
if inputQ.Cmp(expectQ) != 0 {
t.Errorf("Expected: %v, Actual: %v", inputQ, expectQ)
}
}
// Test when i is {0,0}
table2 := []struct {
input Quantity
expect *inf.Dec
}{
{Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(0, 0).Dec}, s: "0", Format: DecimalSI}, dec(0, 0).Dec},
{Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(10, 0).Dec}, s: "10", Format: DecimalSI}, dec(10, 0).Dec},
{Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(-10, 0).Dec}, s: "-10", Format: DecimalSI}, dec(-10, 0).Dec},
}
for _, testCase := range table2 {
var inputQ Quantity
expectQ := Quantity{d: infDecAmount{testCase.expect}, Format: DecimalSI}
inputByteArray, _ := testCase.input.Marshal()
inputQ.Unmarshal(inputByteArray)
if inputQ.Cmp(expectQ) != 0 {
t.Errorf("Expected: %v, Actual: %v", inputQ, expectQ)
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,85 +0,0 @@
/*
Copyright 2015 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 resource
import (
"math"
"math/big"
"testing"
)
func TestScaledValueInternal(t *testing.T) {
tests := []struct {
unscaled *big.Int
scale int
newScale int
want int64
}{
// remain scale
{big.NewInt(1000), 0, 0, 1000},
// scale down
{big.NewInt(1000), 0, -3, 1},
{big.NewInt(1000), 3, 0, 1},
{big.NewInt(0), 3, 0, 0},
// always round up
{big.NewInt(999), 3, 0, 1},
{big.NewInt(500), 3, 0, 1},
{big.NewInt(499), 3, 0, 1},
{big.NewInt(1), 3, 0, 1},
// large scaled value does not lose precision
{big.NewInt(0).Sub(maxInt64, bigOne), 1, 0, (math.MaxInt64-1)/10 + 1},
// large intermediate result.
{big.NewInt(1).Exp(big.NewInt(10), big.NewInt(100), nil), 100, 0, 1},
// scale up
{big.NewInt(0), 0, 3, 0},
{big.NewInt(1), 0, 3, 1000},
{big.NewInt(1), -3, 0, 1000},
{big.NewInt(1000), -3, 2, 100000000},
{big.NewInt(0).Div(big.NewInt(math.MaxInt64), bigThousand), 0, 3,
(math.MaxInt64 / 1000) * 1000},
}
for i, tt := range tests {
old := (&big.Int{}).Set(tt.unscaled)
got := scaledValue(tt.unscaled, tt.scale, tt.newScale)
if got != tt.want {
t.Errorf("#%d: got = %v, want %v", i, got, tt.want)
}
if tt.unscaled.Cmp(old) != 0 {
t.Errorf("#%d: unscaled = %v, want %v", i, tt.unscaled, old)
}
}
}
func BenchmarkScaledValueSmall(b *testing.B) {
s := big.NewInt(1000)
for i := 0; i < b.N; i++ {
scaledValue(s, 3, 0)
}
}
func BenchmarkScaledValueLarge(b *testing.B) {
s := big.NewInt(math.MaxInt64)
s.Mul(s, big.NewInt(1000))
for i := 0; i < b.N; i++ {
scaledValue(s, 10, 0)
}
}

View file

@ -1,53 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["objectmeta_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"generic.go",
"objectmeta.go",
],
importpath = "k8s.io/apimachinery/pkg/api/validation",
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/api/validation/path:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,500 +0,0 @@
/*
Copyright 2017 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 validation
import (
"math/rand"
"reflect"
"strings"
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
)
const (
maxLengthErrMsg = "must be no more than"
namePartErrMsg = "name part must consist of"
nameErrMsg = "a qualified name must consist of"
)
// Ensure custom name functions are allowed
func TestValidateObjectMetaCustomName(t *testing.T) {
errs := ValidateObjectMeta(
&metav1.ObjectMeta{Name: "test", GenerateName: "foo"},
false,
func(s string, prefix bool) []string {
if s == "test" {
return nil
}
return []string{"name-gen"}
},
field.NewPath("field"))
if len(errs) != 1 {
t.Fatalf("unexpected errors: %v", errs)
}
if !strings.Contains(errs[0].Error(), "name-gen") {
t.Errorf("unexpected error message: %v", errs)
}
}
// Ensure namespace names follow dns label format
func TestValidateObjectMetaNamespaces(t *testing.T) {
errs := ValidateObjectMeta(
&metav1.ObjectMeta{Name: "test", Namespace: "foo.bar"},
true,
func(s string, prefix bool) []string {
return nil
},
field.NewPath("field"))
if len(errs) != 1 {
t.Fatalf("unexpected errors: %v", errs)
}
if !strings.Contains(errs[0].Error(), `Invalid value: "foo.bar"`) {
t.Errorf("unexpected error message: %v", errs)
}
maxLength := 63
letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
b := make([]rune, maxLength+1)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
errs = ValidateObjectMeta(
&metav1.ObjectMeta{Name: "test", Namespace: string(b)},
true,
func(s string, prefix bool) []string {
return nil
},
field.NewPath("field"))
if len(errs) != 2 {
t.Fatalf("unexpected errors: %v", errs)
}
if !strings.Contains(errs[0].Error(), "Invalid value") || !strings.Contains(errs[1].Error(), "Invalid value") {
t.Errorf("unexpected error message: %v", errs)
}
}
func TestValidateObjectMetaOwnerReferences(t *testing.T) {
trueVar := true
falseVar := false
testCases := []struct {
description string
ownerReferences []metav1.OwnerReference
expectError bool
expectedErrorMessage string
}{
{
description: "simple success - third party extension.",
ownerReferences: []metav1.OwnerReference{
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "1",
},
},
expectError: false,
expectedErrorMessage: "",
},
{
description: "simple failures - event shouldn't be set as an owner",
ownerReferences: []metav1.OwnerReference{
{
APIVersion: "v1",
Kind: "Event",
Name: "name",
UID: "1",
},
},
expectError: true,
expectedErrorMessage: "is disallowed from being an owner",
},
{
description: "simple controller ref success - one reference with Controller set",
ownerReferences: []metav1.OwnerReference{
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "1",
Controller: &falseVar,
},
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "2",
Controller: &trueVar,
},
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "3",
Controller: &falseVar,
},
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "4",
},
},
expectError: false,
expectedErrorMessage: "",
},
{
description: "simple controller ref failure - two references with Controller set",
ownerReferences: []metav1.OwnerReference{
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "1",
Controller: &falseVar,
},
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "2",
Controller: &trueVar,
},
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "3",
Controller: &trueVar,
},
{
APIVersion: "customresourceVersion",
Kind: "customresourceKind",
Name: "name",
UID: "4",
},
},
expectError: true,
expectedErrorMessage: "Only one reference can have Controller set to true",
},
}
for _, tc := range testCases {
errs := ValidateObjectMeta(
&metav1.ObjectMeta{Name: "test", Namespace: "test", OwnerReferences: tc.ownerReferences},
true,
func(s string, prefix bool) []string {
return nil
},
field.NewPath("field"))
if len(errs) != 0 && !tc.expectError {
t.Errorf("unexpected error: %v in test case %v", errs, tc.description)
}
if len(errs) == 0 && tc.expectError {
t.Errorf("expect error in test case %v", tc.description)
}
if len(errs) != 0 && !strings.Contains(errs[0].Error(), tc.expectedErrorMessage) {
t.Errorf("unexpected error message: %v in test case %v", errs, tc.description)
}
}
}
func TestValidateObjectMetaUpdateIgnoresCreationTimestamp(t *testing.T) {
if errs := ValidateObjectMetaUpdate(
&metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
&metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))},
field.NewPath("field"),
); len(errs) != 0 {
t.Fatalf("unexpected errors: %v", errs)
}
if errs := ValidateObjectMetaUpdate(
&metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))},
&metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
field.NewPath("field"),
); len(errs) != 0 {
t.Fatalf("unexpected errors: %v", errs)
}
if errs := ValidateObjectMetaUpdate(
&metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(10, 0))},
&metav1.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: metav1.NewTime(time.Unix(11, 0))},
field.NewPath("field"),
); len(errs) != 0 {
t.Fatalf("unexpected errors: %v", errs)
}
}
func TestValidateFinalizersUpdate(t *testing.T) {
testcases := map[string]struct {
Old metav1.ObjectMeta
New metav1.ObjectMeta
ExpectedErr string
}{
"invalid adding finalizers": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a"}},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a", "y/b"}},
ExpectedErr: "y/b",
},
"invalid changing finalizers": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a"}},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/b"}},
ExpectedErr: "x/b",
},
"valid removing finalizers": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a", "y/b"}},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &metav1.Time{}, Finalizers: []string{"x/a"}},
ExpectedErr: "",
},
"valid adding finalizers for objects not being deleted": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{"x/a"}},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{"x/a", "y/b"}},
ExpectedErr: "",
},
}
for name, tc := range testcases {
errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field"))
if len(errs) == 0 {
if len(tc.ExpectedErr) != 0 {
t.Errorf("case: %q, expected error to contain %q", name, tc.ExpectedErr)
}
} else if e, a := tc.ExpectedErr, errs.ToAggregate().Error(); !strings.Contains(a, e) {
t.Errorf("case: %q, expected error to contain %q, got error %q", name, e, a)
}
}
}
func TestValidateFinalizersPreventConflictingFinalizers(t *testing.T) {
testcases := map[string]struct {
ObjectMeta metav1.ObjectMeta
ExpectedErr string
}{
"conflicting finalizers": {
ObjectMeta: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{metav1.FinalizerOrphanDependents, metav1.FinalizerDeleteDependents}},
ExpectedErr: "cannot be both set",
},
}
for name, tc := range testcases {
errs := ValidateObjectMeta(&tc.ObjectMeta, false, NameIsDNSSubdomain, field.NewPath("field"))
if len(errs) == 0 {
if len(tc.ExpectedErr) != 0 {
t.Errorf("case: %q, expected error to contain %q", name, tc.ExpectedErr)
}
} else if e, a := tc.ExpectedErr, errs.ToAggregate().Error(); !strings.Contains(a, e) {
t.Errorf("case: %q, expected error to contain %q, got error %q", name, e, a)
}
}
}
func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) {
now := metav1.NewTime(time.Unix(1000, 0).UTC())
later := metav1.NewTime(time.Unix(2000, 0).UTC())
gracePeriodShort := int64(30)
gracePeriodLong := int64(40)
testcases := map[string]struct {
Old metav1.ObjectMeta
New metav1.ObjectMeta
ExpectedNew metav1.ObjectMeta
ExpectedErrs []string
}{
"valid without deletion fields": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
ExpectedErrs: []string{},
},
"valid with deletion fields": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort},
ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort},
ExpectedErrs: []string{},
},
"invalid set deletionTimestamp": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: 1970-01-01 00:16:40 +0000 UTC: field is immutable; may only be changed via deletion"},
},
"invalid clear deletionTimestamp": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
ExpectedErrs: []string{}, // no errors, validation copies the old value
},
"invalid change deletionTimestamp": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &later},
ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now},
ExpectedErrs: []string{}, // no errors, validation copies the old value
},
"invalid set deletionGracePeriodSeconds": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 30: field is immutable; may only be changed via deletion"},
},
"invalid clear deletionGracePeriodSeconds": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1"},
ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
ExpectedErrs: []string{}, // no errors, validation copies the old value
},
"invalid change deletionGracePeriodSeconds": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong},
ExpectedNew: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong},
ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 40: field is immutable; may only be changed via deletion"},
},
}
for k, tc := range testcases {
errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field"))
if len(errs) != len(tc.ExpectedErrs) {
t.Logf("%s: Expected: %#v", k, tc.ExpectedErrs)
t.Logf("%s: Got: %#v", k, errs)
t.Errorf("%s: expected %d errors, got %d", k, len(tc.ExpectedErrs), len(errs))
continue
}
for i := range errs {
if errs[i].Error() != tc.ExpectedErrs[i] {
t.Errorf("%s: error #%d: expected %q, got %q", k, i, tc.ExpectedErrs[i], errs[i].Error())
}
}
if !reflect.DeepEqual(tc.New, tc.ExpectedNew) {
t.Errorf("%s: Expected after validation:\n%#v\ngot\n%#v", k, tc.ExpectedNew, tc.New)
}
}
}
func TestObjectMetaGenerationUpdate(t *testing.T) {
testcases := map[string]struct {
Old metav1.ObjectMeta
New metav1.ObjectMeta
ExpectedErrs []string
}{
"invalid generation change - decremented": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 4},
ExpectedErrs: []string{"field.generation: Invalid value: 4: must not be decremented"},
},
"valid generation change - incremented by one": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 1},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 2},
ExpectedErrs: []string{},
},
"valid generation field - not updated": {
Old: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
New: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Generation: 5},
ExpectedErrs: []string{},
},
}
for k, tc := range testcases {
errList := []string{}
errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field"))
if len(errs) != len(tc.ExpectedErrs) {
t.Logf("%s: Expected: %#v", k, tc.ExpectedErrs)
for _, err := range errs {
errList = append(errList, err.Error())
}
t.Logf("%s: Got: %#v", k, errList)
t.Errorf("%s: expected %d errors, got %d", k, len(tc.ExpectedErrs), len(errs))
continue
}
for i := range errList {
if errList[i] != tc.ExpectedErrs[i] {
t.Errorf("%s: error #%d: expected %q, got %q", k, i, tc.ExpectedErrs[i], errList[i])
}
}
}
}
// Ensure trailing slash is allowed in generate name
func TestValidateObjectMetaTrimsTrailingSlash(t *testing.T) {
errs := ValidateObjectMeta(
&metav1.ObjectMeta{Name: "test", GenerateName: "foo-"},
false,
NameIsDNSSubdomain,
field.NewPath("field"))
if len(errs) != 0 {
t.Fatalf("unexpected errors: %v", errs)
}
}
func TestValidateAnnotations(t *testing.T) {
successCases := []map[string]string{
{"simple": "bar"},
{"now-with-dashes": "bar"},
{"1-starts-with-num": "bar"},
{"1234": "bar"},
{"simple/simple": "bar"},
{"now-with-dashes/simple": "bar"},
{"now-with-dashes/now-with-dashes": "bar"},
{"now.with.dots/simple": "bar"},
{"now-with.dashes-and.dots/simple": "bar"},
{"1-num.2-num/3-num": "bar"},
{"1234/5678": "bar"},
{"1.2.3.4/5678": "bar"},
{"UpperCase123": "bar"},
{"a": strings.Repeat("b", totalAnnotationSizeLimitB-1)},
{
"a": strings.Repeat("b", totalAnnotationSizeLimitB/2-1),
"c": strings.Repeat("d", totalAnnotationSizeLimitB/2-1),
},
}
for i := range successCases {
errs := ValidateAnnotations(successCases[i], field.NewPath("field"))
if len(errs) != 0 {
t.Errorf("case[%d] expected success, got %#v", i, errs)
}
}
nameErrorCases := []struct {
annotations map[string]string
expect string
}{
{map[string]string{"nospecialchars^=@": "bar"}, namePartErrMsg},
{map[string]string{"cantendwithadash-": "bar"}, namePartErrMsg},
{map[string]string{"only/one/slash": "bar"}, nameErrMsg},
{map[string]string{strings.Repeat("a", 254): "bar"}, maxLengthErrMsg},
}
for i := range nameErrorCases {
errs := ValidateAnnotations(nameErrorCases[i].annotations, field.NewPath("field"))
if len(errs) != 1 {
t.Errorf("case[%d]: expected failure", i)
} else {
if !strings.Contains(errs[0].Detail, nameErrorCases[i].expect) {
t.Errorf("case[%d]: error details do not include %q: %q", i, nameErrorCases[i].expect, errs[0].Detail)
}
}
}
totalSizeErrorCases := []map[string]string{
{"a": strings.Repeat("b", totalAnnotationSizeLimitB)},
{
"a": strings.Repeat("b", totalAnnotationSizeLimitB/2),
"c": strings.Repeat("d", totalAnnotationSizeLimitB/2),
},
}
for i := range totalSizeErrorCases {
errs := ValidateAnnotations(totalSizeErrorCases[i], field.NewPath("field"))
if len(errs) != 1 {
t.Errorf("case[%d] expected failure", i)
}
}
}

View file

@ -1,45 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["types_test.go"],
embed = [":go_default_library"],
deps = ["//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"types.go",
],
importpath = "k8s.io/apimachinery/pkg/apimachinery",
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/apimachinery/announced:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/apimachinery/registered:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,45 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["announced_test.go"],
embed = [":go_default_library"],
deps = ["//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"announced.go",
"group_factory.go",
],
importpath = "k8s.io/apimachinery/pkg/apimachinery/announced",
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,64 +0,0 @@
/*
Copyright 2016 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 announced
import (
"reflect"
"testing"
"k8s.io/apimachinery/pkg/util/sets"
)
func TestFactoryRegistry(t *testing.T) {
regA := make(APIGroupFactoryRegistry)
regB := make(APIGroupFactoryRegistry)
if err := regA.AnnounceGroup(&GroupMetaFactoryArgs{
GroupName: "foo",
VersionPreferenceOrder: []string{"v2", "v1"},
RootScopedKinds: sets.NewString("namespaces"),
}); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if err := regA.AnnounceGroupVersion(&GroupVersionFactoryArgs{
GroupName: "foo",
VersionName: "v1",
}); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if err := regA.AnnounceGroupVersion(&GroupVersionFactoryArgs{
GroupName: "foo",
VersionName: "v2",
}); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if err := regB.AnnouncePreconstructedFactory(NewGroupMetaFactory(
&GroupMetaFactoryArgs{
GroupName: "foo",
VersionPreferenceOrder: []string{"v2", "v1"},
RootScopedKinds: sets.NewString("namespaces"),
},
VersionToSchemeFunc{"v1": nil, "v2": nil},
)); err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if !reflect.DeepEqual(regA, regB) {
t.Errorf("Expected both ways of registering to be equivalent, but they were not.\n\n%#v\n\n%#v\n", regA, regB)
}
}

View file

@ -1,43 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["registered_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["registered.go"],
importpath = "k8s.io/apimachinery/pkg/apimachinery/registered",
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,71 +0,0 @@
/*
Copyright 2015 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 registered
import (
"testing"
"k8s.io/apimachinery/pkg/apimachinery"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func TestAllPreferredGroupVersions(t *testing.T) {
testCases := []struct {
groupMetas []apimachinery.GroupMeta
expect string
}{
{
groupMetas: []apimachinery.GroupMeta{
{
GroupVersion: schema.GroupVersion{Group: "group1", Version: "v1"},
},
{
GroupVersion: schema.GroupVersion{Group: "group2", Version: "v2"},
},
{
GroupVersion: schema.GroupVersion{Group: "", Version: "v1"},
},
},
expect: "group1/v1,group2/v2,v1",
},
{
groupMetas: []apimachinery.GroupMeta{
{
GroupVersion: schema.GroupVersion{Group: "", Version: "v1"},
},
},
expect: "v1",
},
{
groupMetas: []apimachinery.GroupMeta{},
expect: "",
},
}
for _, testCase := range testCases {
m, err := NewAPIRegistrationManager("")
if err != nil {
t.Fatalf("Unexpected failure to make a manager: %v", err)
}
for _, groupMeta := range testCase.groupMetas {
m.RegisterGroup(groupMeta)
}
output := m.AllPreferredGroupVersions()
if testCase.expect != output {
t.Errorf("Error. expect: %s, got: %s", testCase.expect, output)
}
}
}

View file

@ -1,43 +0,0 @@
/*
Copyright 2016 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 apimachinery
import (
"testing"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func TestAdd(t *testing.T) {
gm := GroupMeta{
GroupVersion: schema.GroupVersion{
Group: "test",
Version: "v1",
},
GroupVersions: []schema.GroupVersion{{Group: "test", Version: "v1"}},
}
gm.AddVersionInterfaces(schema.GroupVersion{Group: "test", Version: "v1"}, nil)
if e, a := 1, len(gm.InterfacesByVersion); e != a {
t.Errorf("expected %v, got %v", e, a)
}
// GroupVersions is unchanged
if e, a := 1, len(gm.GroupVersions); e != a {
t.Errorf("expected %v, got %v", e, a)
}
}

View file

@ -1,59 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"register_test.go",
"roundtrip_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"conversion.go",
"doc.go",
"register.go",
"types.go",
"zz_generated.conversion.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apimachinery/pkg/apis/meta/internalversion",
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,89 +0,0 @@
/*
Copyright 2017 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 internalversion
import (
"net/url"
"reflect"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/diff"
)
func TestListOptions(t *testing.T) {
// verify round trip conversion
ten := int64(10)
in := &metav1.ListOptions{
LabelSelector: "a=1",
FieldSelector: "b=1",
ResourceVersion: "10",
TimeoutSeconds: &ten,
Watch: true,
}
out := &ListOptions{}
if err := scheme.Convert(in, out, nil); err != nil {
t.Fatal(err)
}
actual := &metav1.ListOptions{}
if err := scheme.Convert(out, actual, nil); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(in, actual) {
t.Errorf("unexpected: %s", diff.ObjectReflectDiff(in, actual))
}
// verify failing conversion
for i, failingObject := range []*metav1.ListOptions{
{LabelSelector: "a!!!"},
{FieldSelector: "a!!!"},
} {
out = &ListOptions{}
if err := scheme.Convert(failingObject, out, nil); err == nil {
t.Errorf("%d: unexpected conversion: %#v", i, out)
}
}
// verify kind registration
if gvks, unversioned, err := scheme.ObjectKinds(in); err != nil || unversioned || gvks[0] != metav1.SchemeGroupVersion.WithKind("ListOptions") {
t.Errorf("unexpected: %v %v %v", gvks[0], unversioned, err)
}
if gvks, unversioned, err := scheme.ObjectKinds(out); err != nil || unversioned || gvks[0] != SchemeGroupVersion.WithKind("ListOptions") {
t.Errorf("unexpected: %v %v %v", gvks[0], unversioned, err)
}
actual = &metav1.ListOptions{}
if err := ParameterCodec.DecodeParameters(url.Values{"watch": []string{"1"}}, metav1.SchemeGroupVersion, actual); err != nil {
t.Fatal(err)
}
if !actual.Watch {
t.Errorf("unexpected watch decode: %#v", actual)
}
// check ParameterCodec
query, err := ParameterCodec.EncodeParameters(in, metav1.SchemeGroupVersion)
if err != nil {
t.Fatal(err)
}
actual = &metav1.ListOptions{}
if err := ParameterCodec.DecodeParameters(query, metav1.SchemeGroupVersion, actual); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(in, actual) {
t.Errorf("unexpected: %s", diff.ObjectReflectDiff(in, actual))
}
}

View file

@ -1,28 +0,0 @@
/*
Copyright 2017 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 internalversion
import (
"testing"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
"k8s.io/apimachinery/pkg/apis/meta/fuzzer"
)
func TestRoundTrip(t *testing.T) {
roundtrip.RoundTripTestForScheme(t, scheme, fuzzer.Funcs)
}

View file

@ -1,101 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"controller_ref_test.go",
"duration_test.go",
"group_version_test.go",
"helpers_test.go",
"labels_test.go",
"micro_time_test.go",
"time_test.go",
"types_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/json-iterator/go:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"controller_ref.go",
"conversion.go",
"doc.go",
"duration.go",
"generated.pb.go",
"group_version.go",
"helpers.go",
"labels.go",
"meta.go",
"micro_time.go",
"micro_time_proto.go",
"register.go",
"time.go",
"time_proto.go",
"types.go",
"types_swagger_doc_generated.go",
"watch.go",
"zz_generated.deepcopy.go",
"zz_generated.defaults.go",
],
importpath = "k8s.io/apimachinery/pkg/apis/meta/v1",
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/gogo/protobuf/sortkeys:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/selection:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:all-srcs",
],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_xtest",
srcs = ["conversion_test.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
],
)

View file

@ -1,133 +0,0 @@
/*
Copyright 2017 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 v1
import (
"testing"
"k8s.io/apimachinery/pkg/runtime/schema"
)
type metaObj struct {
ObjectMeta
TypeMeta
}
func TestNewControllerRef(t *testing.T) {
gvk := schema.GroupVersionKind{
Group: "group",
Version: "v1",
Kind: "Kind",
}
obj1 := &metaObj{
ObjectMeta: ObjectMeta{
Name: "name",
UID: "uid1",
},
}
controllerRef := NewControllerRef(obj1, gvk)
if controllerRef.UID != obj1.UID {
t.Errorf("Incorrect UID: %s", controllerRef.UID)
}
if controllerRef.Controller == nil || *controllerRef.Controller != true {
t.Error("Controller must be set to true")
}
if controllerRef.BlockOwnerDeletion == nil || *controllerRef.BlockOwnerDeletion != true {
t.Error("BlockOwnerDeletion must be set to true")
}
if controllerRef.APIVersion == "" ||
controllerRef.Kind == "" ||
controllerRef.Name == "" {
t.Errorf("All controllerRef fields must be set: %v", controllerRef)
}
}
func TestGetControllerOf(t *testing.T) {
gvk := schema.GroupVersionKind{
Group: "group",
Version: "v1",
Kind: "Kind",
}
obj1 := &metaObj{
ObjectMeta: ObjectMeta{
UID: "uid1",
Name: "name1",
},
}
controllerRef := NewControllerRef(obj1, gvk)
var falseRef = false
obj2 := &metaObj{
ObjectMeta: ObjectMeta{
UID: "uid2",
Name: "name1",
OwnerReferences: []OwnerReference{
{
Name: "owner1",
Controller: &falseRef,
},
*controllerRef,
{
Name: "owner2",
Controller: &falseRef,
},
},
},
}
if GetControllerOf(obj1) != nil {
t.Error("GetControllerOf must return null")
}
c := GetControllerOf(obj2)
if c.Name != controllerRef.Name || c.UID != controllerRef.UID {
t.Errorf("Incorrect result of GetControllerOf: %v", c)
}
}
func TestIsControlledBy(t *testing.T) {
gvk := schema.GroupVersionKind{
Group: "group",
Version: "v1",
Kind: "Kind",
}
obj1 := &metaObj{
ObjectMeta: ObjectMeta{
UID: "uid1",
},
}
obj2 := &metaObj{
ObjectMeta: ObjectMeta{
UID: "uid2",
OwnerReferences: []OwnerReference{
*NewControllerRef(obj1, gvk),
},
},
}
obj3 := &metaObj{
ObjectMeta: ObjectMeta{
UID: "uid3",
OwnerReferences: []OwnerReference{
*NewControllerRef(obj2, gvk),
},
},
}
if !IsControlledBy(obj2, obj1) || !IsControlledBy(obj3, obj2) {
t.Error("Incorrect IsControlledBy result: false")
}
if IsControlledBy(obj3, obj1) {
t.Error("Incorrect IsControlledBy result: true")
}
}

View file

@ -1,49 +0,0 @@
/*
Copyright 2017 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 v1_test
import (
"testing"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestMapToLabelSelectorRoundTrip(t *testing.T) {
// We should be able to round-trip a map-only selector through LabelSelector.
inputs := []map[string]string{
nil,
{},
{"one": "foo"},
{"one": "foo", "two": "bar"},
}
for _, in := range inputs {
ls := &v1.LabelSelector{}
if err := v1.Convert_map_to_unversioned_LabelSelector(&in, ls, nil); err != nil {
t.Errorf("Convert_map_to_unversioned_LabelSelector(%#v): %v", in, err)
continue
}
out := map[string]string{}
if err := v1.Convert_unversioned_LabelSelector_to_map(ls, &out, nil); err != nil {
t.Errorf("Convert_unversioned_LabelSelector_to_map(%#v): %v", ls, err)
continue
}
if !apiequality.Semantic.DeepEqual(in, out) {
t.Errorf("map-selector conversion round-trip failed: got %v; want %v", out, in)
}
}
}

View file

@ -1,153 +0,0 @@
/*
Copyright 2014 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 v1
import (
"encoding/json"
"testing"
"time"
"github.com/ghodss/yaml"
)
type DurationHolder struct {
D Duration `json:"d"`
}
func TestDurationMarshalYAML(t *testing.T) {
cases := []struct {
input Duration
result string
}{
{Duration{5 * time.Second}, "d: 5s\n"},
{Duration{2 * time.Minute}, "d: 2m0s\n"},
{Duration{time.Hour + 3*time.Millisecond}, "d: 1h0m0.003s\n"},
}
for _, c := range cases {
input := DurationHolder{c.input}
result, err := yaml.Marshal(&input)
if err != nil {
t.Errorf("Failed to marshal input: %q: %v", input, err)
}
if string(result) != c.result {
t.Errorf("Failed to marshal input: %q: expected %q, got %q", input, c.result, string(result))
}
}
}
func TestDurationUnmarshalYAML(t *testing.T) {
cases := []struct {
input string
result Duration
}{
{"d: 0s\n", Duration{}},
{"d: 5s\n", Duration{5 * time.Second}},
{"d: 2m0s\n", Duration{2 * time.Minute}},
{"d: 1h0m0.003s\n", Duration{time.Hour + 3*time.Millisecond}},
// Units with zero values can optionally be dropped
{"d: 2m\n", Duration{2 * time.Minute}},
{"d: 1h0.003s\n", Duration{time.Hour + 3*time.Millisecond}},
}
for _, c := range cases {
var result DurationHolder
if err := yaml.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("Failed to unmarshal input %q: %v", c.input, err)
}
if result.D != c.result {
t.Errorf("Failed to unmarshal input %q: expected %q, got %q", c.input, c.result, result)
}
}
}
func TestDurationMarshalJSON(t *testing.T) {
cases := []struct {
input Duration
result string
}{
{Duration{5 * time.Second}, `{"d":"5s"}`},
{Duration{2 * time.Minute}, `{"d":"2m0s"}`},
{Duration{time.Hour + 3*time.Millisecond}, `{"d":"1h0m0.003s"}`},
}
for _, c := range cases {
input := DurationHolder{c.input}
result, err := json.Marshal(&input)
if err != nil {
t.Errorf("Failed to marshal input: %q: %v", input, err)
}
if string(result) != c.result {
t.Errorf("Failed to marshal input: %q: expected %q, got %q", input, c.result, string(result))
}
}
}
func TestDurationUnmarshalJSON(t *testing.T) {
cases := []struct {
input string
result Duration
}{
{`{"d":"0s"}`, Duration{}},
{`{"d":"5s"}`, Duration{5 * time.Second}},
{`{"d":"2m0s"}`, Duration{2 * time.Minute}},
{`{"d":"1h0m0.003s"}`, Duration{time.Hour + 3*time.Millisecond}},
// Units with zero values can optionally be dropped
{`{"d":"2m"}`, Duration{2 * time.Minute}},
{`{"d":"1h0.003s"}`, Duration{time.Hour + 3*time.Millisecond}},
}
for _, c := range cases {
var result DurationHolder
if err := json.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("Failed to unmarshal input %q: %v", c.input, err)
}
if result.D != c.result {
t.Errorf("Failed to unmarshal input %q: expected %q, got %q", c.input, c.result, result)
}
}
}
func TestDurationMarshalJSONUnmarshalYAML(t *testing.T) {
cases := []struct {
input Duration
}{
{Duration{}},
{Duration{5 * time.Second}},
{Duration{2 * time.Minute}},
{Duration{time.Hour + 3*time.Millisecond}},
}
for i, c := range cases {
input := DurationHolder{c.input}
jsonMarshalled, err := json.Marshal(&input)
if err != nil {
t.Errorf("%d-1: Failed to marshal input: '%v': %v", i, input, err)
}
var result DurationHolder
if err := yaml.Unmarshal(jsonMarshalled, &result); err != nil {
t.Errorf("%d-2: Failed to unmarshal '%+v': %v", i, string(jsonMarshalled), err)
}
if input.D != result.D {
t.Errorf("%d-4: Failed to marshal input '%#v': got %#v", i, input, result)
}
}
}

View file

@ -1,78 +0,0 @@
/*
Copyright 2015 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 v1
import (
"encoding/json"
"reflect"
"testing"
jsoniter "github.com/json-iterator/go"
)
type GroupVersionHolder struct {
GV GroupVersion `json:"val"`
}
func TestGroupVersionUnmarshalJSON(t *testing.T) {
cases := []struct {
input []byte
expect GroupVersion
}{
{[]byte(`{"val": "v1"}`), GroupVersion{"", "v1"}},
{[]byte(`{"val": "extensions/v1beta1"}`), GroupVersion{"extensions", "v1beta1"}},
}
for _, c := range cases {
var result GroupVersionHolder
// test golang lib's JSON codec
if err := json.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("JSON codec failed to unmarshal input '%v': %v", c.input, err)
}
if !reflect.DeepEqual(result.GV, c.expect) {
t.Errorf("JSON codec failed to unmarshal input '%s': expected %+v, got %+v", c.input, c.expect, result.GV)
}
// test the json-iterator codec
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(c.input, &result); err != nil {
t.Errorf("json-iterator codec failed to unmarshal input '%v': %v", c.input, err)
}
if !reflect.DeepEqual(result.GV, c.expect) {
t.Errorf("json-iterator codec failed to unmarshal input '%s': expected %+v, got %+v", c.input, c.expect, result.GV)
}
}
}
func TestGroupVersionMarshalJSON(t *testing.T) {
cases := []struct {
input GroupVersion
expect []byte
}{
{GroupVersion{"", "v1"}, []byte(`{"val":"v1"}`)},
{GroupVersion{"extensions", "v1beta1"}, []byte(`{"val":"extensions/v1beta1"}`)},
}
for _, c := range cases {
input := GroupVersionHolder{c.input}
result, err := json.Marshal(&input)
if err != nil {
t.Errorf("Failed to marshal input '%v': %v", input, err)
}
if !reflect.DeepEqual(result, c.expect) {
t.Errorf("Failed to marshal input '%+v': expected: %s, got: %s", input, c.expect, result)
}
}
}

View file

@ -1,154 +0,0 @@
/*
Copyright 2016 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 v1
import (
"reflect"
"strings"
"testing"
"k8s.io/apimachinery/pkg/labels"
)
func TestLabelSelectorAsSelector(t *testing.T) {
matchLabels := map[string]string{"foo": "bar"}
matchExpressions := []LabelSelectorRequirement{{
Key: "baz",
Operator: LabelSelectorOpIn,
Values: []string{"qux", "norf"},
}}
mustParse := func(s string) labels.Selector {
out, e := labels.Parse(s)
if e != nil {
panic(e)
}
return out
}
tc := []struct {
in *LabelSelector
out labels.Selector
expectErr bool
}{
{in: nil, out: labels.Nothing()},
{in: &LabelSelector{}, out: labels.Everything()},
{
in: &LabelSelector{MatchLabels: matchLabels},
out: mustParse("foo=bar"),
},
{
in: &LabelSelector{MatchExpressions: matchExpressions},
out: mustParse("baz in (norf,qux)"),
},
{
in: &LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions},
out: mustParse("baz in (norf,qux),foo=bar"),
},
{
in: &LabelSelector{
MatchExpressions: []LabelSelectorRequirement{{
Key: "baz",
Operator: LabelSelectorOpExists,
Values: []string{"qux", "norf"},
}},
},
expectErr: true,
},
}
for i, tc := range tc {
out, err := LabelSelectorAsSelector(tc.in)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
if !reflect.DeepEqual(out, tc.out) {
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
}
}
}
func TestLabelSelectorAsMap(t *testing.T) {
matchLabels := map[string]string{"foo": "bar"}
matchExpressions := func(operator LabelSelectorOperator, values []string) []LabelSelectorRequirement {
return []LabelSelectorRequirement{{
Key: "baz",
Operator: operator,
Values: values,
}}
}
tests := []struct {
in *LabelSelector
out map[string]string
errString string
}{
{in: nil, out: nil},
{
in: &LabelSelector{MatchLabels: matchLabels},
out: map[string]string{"foo": "bar"},
},
{
in: &LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(LabelSelectorOpIn, []string{"norf"})},
out: map[string]string{"foo": "bar", "baz": "norf"},
},
{
in: &LabelSelector{MatchExpressions: matchExpressions(LabelSelectorOpIn, []string{"norf"})},
out: map[string]string{"baz": "norf"},
},
{
in: &LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(LabelSelectorOpIn, []string{"norf", "qux"})},
out: map[string]string{"foo": "bar"},
errString: "without a single value cannot be converted",
},
{
in: &LabelSelector{MatchExpressions: matchExpressions(LabelSelectorOpNotIn, []string{"norf", "qux"})},
out: map[string]string{},
errString: "cannot be converted",
},
{
in: &LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(LabelSelectorOpExists, []string{})},
out: map[string]string{"foo": "bar"},
errString: "cannot be converted",
},
{
in: &LabelSelector{MatchExpressions: matchExpressions(LabelSelectorOpDoesNotExist, []string{})},
out: map[string]string{},
errString: "cannot be converted",
},
}
for i, tc := range tests {
out, err := LabelSelectorAsMap(tc.in)
if err == nil && len(tc.errString) > 0 {
t.Errorf("[%v]expected error but got none.", i)
continue
}
if err != nil && len(tc.errString) == 0 {
t.Errorf("[%v]did not expect error but got: %v", i, err)
continue
}
if err != nil && len(tc.errString) > 0 && !strings.Contains(err.Error(), tc.errString) {
t.Errorf("[%v]expected error with %q but got: %v", i, tc.errString, err)
continue
}
if !reflect.DeepEqual(out, tc.out) {
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
}
}
}

View file

@ -1,123 +0,0 @@
/*
Copyright 2016 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 v1
import (
"reflect"
"testing"
)
func TestCloneSelectorAndAddLabel(t *testing.T) {
labels := map[string]string{
"foo1": "bar1",
"foo2": "bar2",
"foo3": "bar3",
}
matchExpressions := []LabelSelectorRequirement{
{Key: "foo", Operator: LabelSelectorOpIn, Values: []string{"foo"}},
}
cases := []struct {
labels map[string]string
labelKey string
labelValue string
want map[string]string
}{
{
labels: labels,
want: labels,
},
{
labels: labels,
labelKey: "foo4",
labelValue: "89",
want: map[string]string{
"foo1": "bar1",
"foo2": "bar2",
"foo3": "bar3",
"foo4": "89",
},
},
{
labels: nil,
labelKey: "foo4",
labelValue: "12",
want: map[string]string{
"foo4": "12",
},
},
}
for _, tc := range cases {
ls_in := LabelSelector{MatchLabels: tc.labels, MatchExpressions: matchExpressions}
ls_out := LabelSelector{MatchLabels: tc.want, MatchExpressions: matchExpressions}
got := CloneSelectorAndAddLabel(&ls_in, tc.labelKey, tc.labelValue)
if !reflect.DeepEqual(got, &ls_out) {
t.Errorf("got %v, want %v", got, tc.want)
}
}
}
func TestAddLabelToSelector(t *testing.T) {
labels := map[string]string{
"foo1": "bar1",
"foo2": "bar2",
"foo3": "bar3",
}
cases := []struct {
labels map[string]string
labelKey string
labelValue string
want map[string]string
}{
{
labels: labels,
want: labels,
},
{
labels: labels,
labelKey: "foo4",
labelValue: "89",
want: map[string]string{
"foo1": "bar1",
"foo2": "bar2",
"foo3": "bar3",
"foo4": "89",
},
},
{
labels: nil,
labelKey: "foo4",
labelValue: "12",
want: map[string]string{
"foo4": "12",
},
},
}
for _, tc := range cases {
ls_in := LabelSelector{MatchLabels: tc.labels}
ls_out := LabelSelector{MatchLabels: tc.want}
got := AddLabelToSelector(&ls_in, tc.labelKey, tc.labelValue)
if !reflect.DeepEqual(got, &ls_out) {
t.Errorf("got %v, want %v", got, tc.want)
}
}
}

View file

@ -1,139 +0,0 @@
/*
Copyright 2016 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 v1
import (
"encoding/json"
"reflect"
"testing"
"time"
"github.com/ghodss/yaml"
)
type MicroTimeHolder struct {
T MicroTime `json:"t"`
}
func TestMicroTimeMarshalYAML(t *testing.T) {
cases := []struct {
input MicroTime
result string
}{
{MicroTime{}, "t: null\n"},
{DateMicro(1998, time.May, 5, 1, 5, 5, 50, time.FixedZone("test", -4*60*60)), "t: 1998-05-05T05:05:05.000000Z\n"},
{DateMicro(1998, time.May, 5, 5, 5, 5, 0, time.UTC), "t: 1998-05-05T05:05:05.000000Z\n"},
}
for _, c := range cases {
input := MicroTimeHolder{c.input}
result, err := yaml.Marshal(&input)
if err != nil {
t.Errorf("Failed to marshal input: '%v': %v", input, err)
}
if string(result) != c.result {
t.Errorf("Failed to marshal input: '%v': expected %+v, got %q", input, c.result, string(result))
}
}
}
func TestMicroTimeUnmarshalYAML(t *testing.T) {
cases := []struct {
input string
result MicroTime
}{
{"t: null\n", MicroTime{}},
{"t: 1998-05-05T05:05:05.000000Z\n", MicroTime{Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC).Local()}},
}
for _, c := range cases {
var result MicroTimeHolder
if err := yaml.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("Failed to unmarshal input '%v': %v", c.input, err)
}
if result.T != c.result {
t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result)
}
}
}
func TestMicroTimeMarshalJSON(t *testing.T) {
cases := []struct {
input MicroTime
result string
}{
{MicroTime{}, "{\"t\":null}"},
{DateMicro(1998, time.May, 5, 5, 5, 5, 50, time.UTC), "{\"t\":\"1998-05-05T05:05:05.000000Z\"}"},
{DateMicro(1998, time.May, 5, 5, 5, 5, 0, time.UTC), "{\"t\":\"1998-05-05T05:05:05.000000Z\"}"},
}
for _, c := range cases {
input := MicroTimeHolder{c.input}
result, err := json.Marshal(&input)
if err != nil {
t.Errorf("Failed to marshal input: '%v': %v", input, err)
}
if string(result) != c.result {
t.Errorf("Failed to marshal input: '%v': expected %+v, got %q", input, c.result, string(result))
}
}
}
func TestMicroTimeUnmarshalJSON(t *testing.T) {
cases := []struct {
input string
result MicroTime
}{
{"{\"t\":null}", MicroTime{}},
{"{\"t\":\"1998-05-05T05:05:05.000000Z\"}", MicroTime{Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC).Local()}},
}
for _, c := range cases {
var result MicroTimeHolder
if err := json.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("Failed to unmarshal input '%v': %v", c.input, err)
}
if result.T != c.result {
t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result)
}
}
}
func TestMicroTimeProto(t *testing.T) {
cases := []struct {
input MicroTime
}{
{MicroTime{}},
{DateMicro(1998, time.May, 5, 1, 5, 5, 50, time.Local)},
{DateMicro(1998, time.May, 5, 5, 5, 5, 0, time.Local)},
}
for _, c := range cases {
input := c.input
data, err := input.Marshal()
if err != nil {
t.Fatalf("Failed to marshal input: '%v': %v", input, err)
}
time := MicroTime{}
if err := time.Unmarshal(data); err != nil {
t.Fatalf("Failed to unmarshal output: '%v': %v", input, err)
}
if !reflect.DeepEqual(input, time) {
t.Errorf("Marshal->Unmarshal is not idempotent: '%v' vs '%v'", input, time)
}
}
}

View file

@ -1,197 +0,0 @@
/*
Copyright 2014 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 v1
import (
"encoding/json"
"reflect"
"testing"
"time"
"github.com/ghodss/yaml"
)
type TimeHolder struct {
T Time `json:"t"`
}
func TestTimeMarshalYAML(t *testing.T) {
cases := []struct {
input Time
result string
}{
{Time{}, "t: null\n"},
{Date(1998, time.May, 5, 1, 5, 5, 50, time.FixedZone("test", -4*60*60)), "t: 1998-05-05T05:05:05Z\n"},
{Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC), "t: 1998-05-05T05:05:05Z\n"},
}
for _, c := range cases {
input := TimeHolder{c.input}
result, err := yaml.Marshal(&input)
if err != nil {
t.Errorf("Failed to marshal input: '%v': %v", input, err)
}
if string(result) != c.result {
t.Errorf("Failed to marshal input: '%v': expected %+v, got %q", input, c.result, string(result))
}
}
}
func TestTimeUnmarshalYAML(t *testing.T) {
cases := []struct {
input string
result Time
}{
{"t: null\n", Time{}},
{"t: 1998-05-05T05:05:05Z\n", Time{Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC).Local()}},
}
for _, c := range cases {
var result TimeHolder
if err := yaml.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("Failed to unmarshal input '%v': %v", c.input, err)
}
if result.T != c.result {
t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result)
}
}
}
func TestTimeMarshalJSON(t *testing.T) {
cases := []struct {
input Time
result string
}{
{Time{}, "{\"t\":null}"},
{Date(1998, time.May, 5, 5, 5, 5, 50, time.UTC), "{\"t\":\"1998-05-05T05:05:05Z\"}"},
{Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC), "{\"t\":\"1998-05-05T05:05:05Z\"}"},
}
for _, c := range cases {
input := TimeHolder{c.input}
result, err := json.Marshal(&input)
if err != nil {
t.Errorf("Failed to marshal input: '%v': %v", input, err)
}
if string(result) != c.result {
t.Errorf("Failed to marshal input: '%v': expected %+v, got %q", input, c.result, string(result))
}
}
}
func TestTimeUnmarshalJSON(t *testing.T) {
cases := []struct {
input string
result Time
}{
{"{\"t\":null}", Time{}},
{"{\"t\":\"1998-05-05T05:05:05Z\"}", Time{Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC).Local()}},
}
for _, c := range cases {
var result TimeHolder
if err := json.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("Failed to unmarshal input '%v': %v", c.input, err)
}
if result.T != c.result {
t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result)
}
}
}
func TestTimeMarshalJSONUnmarshalYAML(t *testing.T) {
cases := []struct {
input Time
}{
{Time{}},
{Date(1998, time.May, 5, 5, 5, 5, 50, time.Local).Rfc3339Copy()},
{Date(1998, time.May, 5, 5, 5, 5, 0, time.Local).Rfc3339Copy()},
}
for i, c := range cases {
input := TimeHolder{c.input}
jsonMarshalled, err := json.Marshal(&input)
if err != nil {
t.Errorf("%d-1: Failed to marshal input: '%v': %v", i, input, err)
}
var result TimeHolder
err = yaml.Unmarshal(jsonMarshalled, &result)
if err != nil {
t.Errorf("%d-2: Failed to unmarshal '%+v': %v", i, string(jsonMarshalled), err)
}
iN, iO := input.T.Zone()
oN, oO := result.T.Zone()
if iN != oN || iO != oO {
t.Errorf("%d-3: Time zones differ before and after serialization %s:%d %s:%d", i, iN, iO, oN, oO)
}
if input.T.UnixNano() != result.T.UnixNano() {
t.Errorf("%d-4: Failed to marshal input '%#v': got %#v", i, input, result)
}
}
}
func TestTimeProto(t *testing.T) {
cases := []struct {
input Time
}{
{Time{}},
{Date(1998, time.May, 5, 1, 5, 5, 0, time.Local)},
{Date(1998, time.May, 5, 5, 5, 5, 0, time.Local)},
}
for _, c := range cases {
input := c.input
data, err := input.Marshal()
if err != nil {
t.Fatalf("Failed to marshal input: '%v': %v", input, err)
}
time := Time{}
if err := time.Unmarshal(data); err != nil {
t.Fatalf("Failed to unmarshal output: '%v': %v", input, err)
}
if !reflect.DeepEqual(input, time) {
t.Errorf("Marshal->Unmarshal is not idempotent: '%v' vs '%v'", input, time)
}
}
}
func TestTimeEqual(t *testing.T) {
t1 := NewTime(time.Now())
cases := []struct {
name string
x *Time
y *Time
result bool
}{
{"nil =? nil", nil, nil, true},
{"!nil =? !nil", &t1, &t1, true},
{"nil =? !nil", nil, &t1, false},
{"!nil =? nil", &t1, nil, false},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
result := c.x.Equal(c.y)
if result != c.result {
t.Errorf("Failed equality test for '%v', '%v': expected %+v, got %+v", c.x, c.y, c.result, result)
}
})
}
}

View file

@ -1,134 +0,0 @@
/*
Copyright 2016 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 v1
import (
"encoding/json"
"reflect"
"testing"
jsoniter "github.com/json-iterator/go"
)
func TestVerbsUgorjiMarshalJSON(t *testing.T) {
cases := []struct {
input APIResource
result string
}{
{APIResource{}, `{"name":"","singularName":"","namespaced":false,"kind":"","verbs":null}`},
{APIResource{Verbs: Verbs([]string{})}, `{"name":"","singularName":"","namespaced":false,"kind":"","verbs":[]}`},
{APIResource{Verbs: Verbs([]string{"delete"})}, `{"name":"","singularName":"","namespaced":false,"kind":"","verbs":["delete"]}`},
}
for i, c := range cases {
result, err := json.Marshal(&c.input)
if err != nil {
t.Errorf("[%d] Failed to marshal input: '%v': %v", i, c.input, err)
}
if string(result) != c.result {
t.Errorf("[%d] Failed to marshal input: '%v': expected '%v', got '%v'", i, c.input, c.result, string(result))
}
}
}
func TestVerbsUgorjiUnmarshalJSON(t *testing.T) {
cases := []struct {
input string
result APIResource
}{
{`{}`, APIResource{}},
{`{"verbs":null}`, APIResource{}},
{`{"verbs":[]}`, APIResource{Verbs: Verbs([]string{})}},
{`{"verbs":["delete"]}`, APIResource{Verbs: Verbs([]string{"delete"})}},
}
for i, c := range cases {
var result APIResource
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("[%d] Failed to unmarshal input '%v': %v", i, c.input, err)
}
if !reflect.DeepEqual(result, c.result) {
t.Errorf("[%d] Failed to unmarshal input '%v': expected %+v, got %+v", i, c.input, c.result, result)
}
}
}
// TestUgorjiMarshalJSONWithOmit tests that we don't have regressions regarding nil and empty slices with "omit"
func TestUgorjiMarshalJSONWithOmit(t *testing.T) {
cases := []struct {
input LabelSelector
result string
}{
{LabelSelector{}, `{}`},
{LabelSelector{MatchExpressions: []LabelSelectorRequirement{}}, `{}`},
{LabelSelector{MatchExpressions: []LabelSelectorRequirement{{}}}, `{"matchExpressions":[{"key":"","operator":""}]}`},
}
for i, c := range cases {
result, err := json.Marshal(&c.input)
if err != nil {
t.Errorf("[%d] Failed to marshal input: '%v': %v", i, c.input, err)
}
if string(result) != c.result {
t.Errorf("[%d] Failed to marshal input: '%v': expected '%v', got '%v'", i, c.input, c.result, string(result))
}
}
}
func TestVerbsUnmarshalJSON(t *testing.T) {
cases := []struct {
input string
result APIResource
}{
{`{}`, APIResource{}},
{`{"verbs":null}`, APIResource{}},
{`{"verbs":[]}`, APIResource{Verbs: Verbs([]string{})}},
{`{"verbs":["delete"]}`, APIResource{Verbs: Verbs([]string{"delete"})}},
}
for i, c := range cases {
var result APIResource
if err := json.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("[%d] Failed to unmarshal input '%v': %v", i, c.input, err)
}
if !reflect.DeepEqual(result, c.result) {
t.Errorf("[%d] Failed to unmarshal input '%v': expected %+v, got %+v", i, c.input, c.result, result)
}
}
}
func TestVerbsProto(t *testing.T) {
cases := []APIResource{
{},
{Verbs: Verbs([]string{})},
{Verbs: Verbs([]string{"delete"})},
}
for _, input := range cases {
data, err := input.Marshal()
if err != nil {
t.Fatalf("Failed to marshal input: '%v': %v", input, err)
}
resource := APIResource{}
if err := resource.Unmarshal(data); err != nil {
t.Fatalf("Failed to unmarshal output: '%v': %v", input, err)
}
if !reflect.DeepEqual(input, resource) {
t.Errorf("Marshal->Unmarshal is not idempotent: '%v' vs '%v'", input, resource)
}
}
}

View file

@ -1,53 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"helpers_test.go",
"unstructured_list_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"helpers.go",
"unstructured.go",
"unstructured_list.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,60 +0,0 @@
/*
Copyright 2017 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 unstructured
import (
"io/ioutil"
"sync"
"testing"
"github.com/stretchr/testify/assert"
)
// TestCodecOfUnstructuredList tests that there are no data races in Encode().
// i.e. that it does not mutate the object being encoded.
func TestCodecOfUnstructuredList(t *testing.T) {
var wg sync.WaitGroup
concurrency := 10
list := UnstructuredList{
Object: map[string]interface{}{},
}
wg.Add(concurrency)
for i := 0; i < concurrency; i++ {
go func() {
defer wg.Done()
assert.NoError(t, UnstructuredJSONScheme.Encode(&list, ioutil.Discard))
}()
}
wg.Wait()
}
func TestRemoveNestedField(t *testing.T) {
obj := map[string]interface{}{
"x": map[string]interface{}{
"y": 1,
"a": "foo",
},
}
RemoveNestedField(obj, "x", "a")
assert.Len(t, obj["x"], 1)
RemoveNestedField(obj, "x", "y")
assert.Empty(t, obj["x"])
RemoveNestedField(obj, "x")
assert.Empty(t, obj)
RemoveNestedField(obj, "x") // Remove of a non-existent field
assert.Empty(t, obj)
}

View file

@ -1,86 +0,0 @@
/*
Copyright 2017 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 unstructured
import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUnstructuredList(t *testing.T) {
list := &UnstructuredList{
Object: map[string]interface{}{"kind": "List", "apiVersion": "v1"},
Items: []Unstructured{
{Object: map[string]interface{}{"kind": "Pod", "apiVersion": "v1", "metadata": map[string]interface{}{"name": "test"}}},
},
}
content := list.UnstructuredContent()
items := content["items"].([]interface{})
require.Len(t, items, 1)
val, found, err := NestedFieldCopy(items[0].(map[string]interface{}), "metadata", "name")
require.True(t, found)
require.NoError(t, err)
assert.Equal(t, "test", val)
}
func TestNilDeletionTimestamp(t *testing.T) {
var u Unstructured
del := u.GetDeletionTimestamp()
if del != nil {
t.Errorf("unexpected non-nil deletion timestamp: %v", del)
}
u.SetDeletionTimestamp(u.GetDeletionTimestamp())
del = u.GetDeletionTimestamp()
if del != nil {
t.Errorf("unexpected non-nil deletion timestamp: %v", del)
}
_, ok := u.Object["metadata"]
assert.False(t, ok)
now := metav1.Now()
u.SetDeletionTimestamp(&now)
assert.Equal(t, now.Unix(), u.GetDeletionTimestamp().Unix())
u.SetDeletionTimestamp(nil)
metadata := u.Object["metadata"].(map[string]interface{})
_, ok = metadata["deletionTimestamp"]
assert.False(t, ok)
}
func TestEmptyCreationTimestampIsOmitted(t *testing.T) {
var u Unstructured
now := metav1.Now()
// set an initial creationTimestamp and ensure the field exists
u.SetCreationTimestamp(now)
metadata := u.Object["metadata"].(map[string]interface{})
creationTimestamp, exists := metadata["creationTimestamp"]
if !exists {
t.Fatalf("unexpected missing creationTimestamp")
}
// set an empty timestamp and ensure the field no longer exists
u.SetCreationTimestamp(metav1.Time{})
metadata = u.Object["metadata"].(map[string]interface{})
creationTimestamp, exists = metadata["creationTimestamp"]
if exists {
t.Errorf("unexpected creation timestamp field: %q", creationTimestamp)
}
}

View file

@ -1,38 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["validation_test.go"],
embed = [":go_default_library"],
deps = ["//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["validation.go"],
importpath = "k8s.io/apimachinery/pkg/apis/meta/v1/validation",
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,94 +0,0 @@
/*
Copyright 2016 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 validation
import (
"strings"
"testing"
"k8s.io/apimachinery/pkg/util/validation/field"
)
func TestValidateLabels(t *testing.T) {
successCases := []map[string]string{
{"simple": "bar"},
{"now-with-dashes": "bar"},
{"1-starts-with-num": "bar"},
{"1234": "bar"},
{"simple/simple": "bar"},
{"now-with-dashes/simple": "bar"},
{"now-with-dashes/now-with-dashes": "bar"},
{"now.with.dots/simple": "bar"},
{"now-with.dashes-and.dots/simple": "bar"},
{"1-num.2-num/3-num": "bar"},
{"1234/5678": "bar"},
{"1.2.3.4/5678": "bar"},
{"UpperCaseAreOK123": "bar"},
{"goodvalue": "123_-.BaR"},
}
for i := range successCases {
errs := ValidateLabels(successCases[i], field.NewPath("field"))
if len(errs) != 0 {
t.Errorf("case[%d] expected success, got %#v", i, errs)
}
}
namePartErrMsg := "name part must consist of"
nameErrMsg := "a qualified name must consist of"
labelErrMsg := "a valid label must be an empty string or consist of"
maxLengthErrMsg := "must be no more than"
labelNameErrorCases := []struct {
labels map[string]string
expect string
}{
{map[string]string{"nospecialchars^=@": "bar"}, namePartErrMsg},
{map[string]string{"cantendwithadash-": "bar"}, namePartErrMsg},
{map[string]string{"only/one/slash": "bar"}, nameErrMsg},
{map[string]string{strings.Repeat("a", 254): "bar"}, maxLengthErrMsg},
}
for i := range labelNameErrorCases {
errs := ValidateLabels(labelNameErrorCases[i].labels, field.NewPath("field"))
if len(errs) != 1 {
t.Errorf("case[%d]: expected failure", i)
} else {
if !strings.Contains(errs[0].Detail, labelNameErrorCases[i].expect) {
t.Errorf("case[%d]: error details do not include %q: %q", i, labelNameErrorCases[i].expect, errs[0].Detail)
}
}
}
labelValueErrorCases := []struct {
labels map[string]string
expect string
}{
{map[string]string{"toolongvalue": strings.Repeat("a", 64)}, maxLengthErrMsg},
{map[string]string{"backslashesinvalue": "some\\bad\\value"}, labelErrMsg},
{map[string]string{"nocommasallowed": "bad,value"}, labelErrMsg},
{map[string]string{"strangecharsinvalue": "?#$notsogood"}, labelErrMsg},
}
for i := range labelValueErrorCases {
errs := ValidateLabels(labelValueErrorCases[i].labels, field.NewPath("field"))
if len(errs) != 1 {
t.Errorf("case[%d]: expected failure", i)
} else {
if !strings.Contains(errs[0].Detail, labelValueErrorCases[i].expect) {
t.Errorf("case[%d]: error details do not include %q: %q", i, labelValueErrorCases[i].expect, errs[0].Detail)
}
}
}
}

View file

@ -1,45 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
srcs = [
"conversion.go",
"deepcopy.go",
"doc.go",
"generated.pb.go",
"register.go",
"types.go",
"types_swagger_doc_generated.go",
"zz_generated.deepcopy.go",
"zz_generated.defaults.go",
],
importpath = "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View file

@ -1,49 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"converter_test.go",
"helper_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"converter.go",
"deep_equal.go",
"doc.go",
"helper.go",
],
importpath = "k8s.io/apimachinery/pkg/conversion",
deps = ["//vendor/k8s.io/apimachinery/third_party/forked/golang/reflect:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/conversion/queryparams:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,826 +0,0 @@
/*
Copyright 2014 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 conversion
import (
"fmt"
"reflect"
"strconv"
"strings"
"testing"
"github.com/google/gofuzz"
flag "github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/diff"
)
var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.")
// Test a weird version/kind embedding format.
type MyWeirdCustomEmbeddedVersionKindField struct {
ID string `json:"ID,omitempty"`
APIVersion string `json:"myVersionKey,omitempty"`
ObjectKind string `json:"myKindKey,omitempty"`
Z string `json:"Z,omitempty"`
Y uint64 `json:"Y,omitempty"`
}
type TestType1 struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
C int8 `json:"C,omitempty"`
D int16 `json:"D,omitempty"`
E int32 `json:"E,omitempty"`
F int64 `json:"F,omitempty"`
G uint `json:"G,omitempty"`
H uint8 `json:"H,omitempty"`
I uint16 `json:"I,omitempty"`
J uint32 `json:"J,omitempty"`
K uint64 `json:"K,omitempty"`
L bool `json:"L,omitempty"`
M map[string]int `json:"M,omitempty"`
N map[string]TestType2 `json:"N,omitempty"`
O *TestType2 `json:"O,omitempty"`
P []TestType2 `json:"Q,omitempty"`
}
type TestType2 struct {
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
}
type ExternalTestType2 struct {
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
}
type ExternalTestType1 struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
C int8 `json:"C,omitempty"`
D int16 `json:"D,omitempty"`
E int32 `json:"E,omitempty"`
F int64 `json:"F,omitempty"`
G uint `json:"G,omitempty"`
H uint8 `json:"H,omitempty"`
I uint16 `json:"I,omitempty"`
J uint32 `json:"J,omitempty"`
K uint64 `json:"K,omitempty"`
L bool `json:"L,omitempty"`
M map[string]int `json:"M,omitempty"`
N map[string]ExternalTestType2 `json:"N,omitempty"`
O *ExternalTestType2 `json:"O,omitempty"`
P []ExternalTestType2 `json:"Q,omitempty"`
}
func testLogger(t *testing.T) DebugLogger {
// We don't set logger to eliminate rubbish logs in tests.
// If you want to switch it, simply switch it to: "return t"
return nil
}
func TestConverter_byteSlice(t *testing.T) {
c := NewConverter(DefaultNameFunc)
src := []byte{1, 2, 3}
dest := []byte{}
err := c.Convert(&src, &dest, 0, nil)
if err != nil {
t.Fatalf("expected no error")
}
if e, a := src, dest; !reflect.DeepEqual(e, a) {
t.Errorf("expected %#v, got %#v", e, a)
}
}
func TestConverter_MismatchedTypes(t *testing.T) {
c := NewConverter(DefaultNameFunc)
err := c.RegisterConversionFunc(
func(in *[]string, out *int, s Scope) error {
if str, err := strconv.Atoi((*in)[0]); err != nil {
return err
} else {
*out = str
return nil
}
},
)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
src := []string{"5"}
var dest *int
err = c.Convert(&src, &dest, 0, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if e, a := 5, *dest; e != a {
t.Errorf("expected %#v, got %#v", e, a)
}
}
func TestConverter_DefaultConvert(t *testing.T) {
type A struct {
Foo string
Baz int
}
type B struct {
Bar string
Baz int
}
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
c.nameFunc = func(t reflect.Type) string { return "MyType" }
// Ensure conversion funcs can call DefaultConvert to get default behavior,
// then fixup remaining fields manually
err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
if err := s.DefaultConvert(in, out, IgnoreMissingFields); err != nil {
return err
}
out.Bar = in.Foo
return nil
})
if err != nil {
t.Fatalf("unexpected error %v", err)
}
x := A{"hello, intrepid test reader!", 3}
y := B{}
err = c.Convert(&x, &y, 0, nil)
if err != nil {
t.Fatalf("unexpected error %v", err)
}
if e, a := x.Foo, y.Bar; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := x.Baz, y.Baz; e != a {
t.Errorf("expected %v, got %v", e, a)
}
}
func TestConverter_DeepCopy(t *testing.T) {
type A struct {
Foo *string
Bar []string
Baz interface{}
Qux map[string]string
}
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
foo, baz := "foo", "baz"
x := A{
Foo: &foo,
Bar: []string{"bar"},
Baz: &baz,
Qux: map[string]string{"qux": "qux"},
}
y := A{}
if err := c.Convert(&x, &y, 0, nil); err != nil {
t.Fatalf("unexpected error %v", err)
}
*x.Foo = "foo2"
x.Bar[0] = "bar2"
*x.Baz.(*string) = "baz2"
x.Qux["qux"] = "qux2"
if e, a := *x.Foo, *y.Foo; e == a {
t.Errorf("expected difference between %v and %v", e, a)
}
if e, a := x.Bar, y.Bar; reflect.DeepEqual(e, a) {
t.Errorf("expected difference between %v and %v", e, a)
}
if e, a := *x.Baz.(*string), *y.Baz.(*string); e == a {
t.Errorf("expected difference between %v and %v", e, a)
}
if e, a := x.Qux, y.Qux; reflect.DeepEqual(e, a) {
t.Errorf("expected difference between %v and %v", e, a)
}
}
func TestConverter_CallsRegisteredFunctions(t *testing.T) {
type A struct {
Foo string
Baz int
}
type B struct {
Bar string
Baz int
}
type C struct{}
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
out.Bar = in.Foo
return s.Convert(&in.Baz, &out.Baz, 0)
})
if err != nil {
t.Fatalf("unexpected error %v", err)
}
err = c.RegisterConversionFunc(func(in *B, out *A, s Scope) error {
out.Foo = in.Bar
return s.Convert(&in.Baz, &out.Baz, 0)
})
if err != nil {
t.Fatalf("unexpected error %v", err)
}
x := A{"hello, intrepid test reader!", 3}
y := B{}
err = c.Convert(&x, &y, 0, nil)
if err != nil {
t.Fatalf("unexpected error %v", err)
}
if e, a := x.Foo, y.Bar; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := x.Baz, y.Baz; e != a {
t.Errorf("expected %v, got %v", e, a)
}
z := B{"all your test are belong to us", 42}
w := A{}
err = c.Convert(&z, &w, 0, nil)
if err != nil {
t.Fatalf("unexpected error %v", err)
}
if e, a := z.Bar, w.Foo; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := z.Baz, w.Baz; e != a {
t.Errorf("expected %v, got %v", e, a)
}
err = c.RegisterConversionFunc(func(in *A, out *C, s Scope) error {
return fmt.Errorf("C can't store an A, silly")
})
if err != nil {
t.Fatalf("unexpected error %v", err)
}
err = c.Convert(&A{}, &C{}, 0, nil)
if err == nil {
t.Errorf("unexpected non-error")
}
}
func TestConverter_IgnoredConversion(t *testing.T) {
type A struct{}
type B struct{}
count := 0
c := NewConverter(DefaultNameFunc)
if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
count++
return nil
}); err != nil {
t.Fatalf("unexpected error %v", err)
}
if err := c.RegisterIgnoredConversion(&A{}, &B{}); err != nil {
t.Fatal(err)
}
a := A{}
b := B{}
if err := c.Convert(&a, &b, 0, nil); err != nil {
t.Errorf("%v", err)
}
if count != 0 {
t.Errorf("unexpected number of conversion invocations")
}
}
func TestConverter_IgnoredConversionNested(t *testing.T) {
type C string
type A struct {
C C
}
type B struct {
C C
}
c := NewConverter(DefaultNameFunc)
typed := C("")
if err := c.RegisterIgnoredConversion(&typed, &typed); err != nil {
t.Fatal(err)
}
a := A{C: C("test")}
b := B{C: C("other")}
if err := c.Convert(&a, &b, AllowDifferentFieldTypeNames, nil); err != nil {
t.Errorf("%v", err)
}
if b.C != C("other") {
t.Errorf("expected no conversion of field C: %#v", b)
}
}
func TestConverter_GeneratedConversionOverriden(t *testing.T) {
type A struct{}
type B struct{}
c := NewConverter(DefaultNameFunc)
if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
return nil
}); err != nil {
t.Fatalf("unexpected error %v", err)
}
if err := c.RegisterGeneratedConversionFunc(func(in *A, out *B, s Scope) error {
return fmt.Errorf("generated function should be overridden")
}); err != nil {
t.Fatalf("unexpected error %v", err)
}
a := A{}
b := B{}
if err := c.Convert(&a, &b, 0, nil); err != nil {
t.Errorf("%v", err)
}
}
func TestConverter_WithConversionOverriden(t *testing.T) {
type A struct{}
type B struct{}
c := NewConverter(DefaultNameFunc)
if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
return fmt.Errorf("conversion function should be overridden")
}); err != nil {
t.Fatalf("unexpected error %v", err)
}
if err := c.RegisterGeneratedConversionFunc(func(in *A, out *B, s Scope) error {
return fmt.Errorf("generated function should be overridden")
}); err != nil {
t.Fatalf("unexpected error %v", err)
}
ext := NewConversionFuncs()
ext.Add(func(in *A, out *B, s Scope) error {
return nil
})
newc := c.WithConversions(ext)
a := A{}
b := B{}
if err := c.Convert(&a, &b, 0, nil); err == nil || err.Error() != "conversion function should be overridden" {
t.Errorf("unexpected error: %v", err)
}
if err := newc.Convert(&a, &b, 0, nil); err != nil {
t.Errorf("%v", err)
}
}
func TestConverter_MapsStringArrays(t *testing.T) {
type A struct {
Foo string
Baz int
Other string
}
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
if err := c.RegisterConversionFunc(func(input *[]string, out *string, s Scope) error {
if len(*input) == 0 {
*out = ""
}
*out = (*input)[0]
return nil
}); err != nil {
t.Fatalf("unexpected error %v", err)
}
x := map[string][]string{
"Foo": {"bar"},
"Baz": {"1"},
"Other": {"", "test"},
"other": {"wrong"},
}
y := A{"test", 2, "something"}
if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames, nil); err == nil {
t.Error("unexpected non-error")
}
if err := c.RegisterConversionFunc(func(input *[]string, out *int, s Scope) error {
if len(*input) == 0 {
*out = 0
}
str := (*input)[0]
i, err := strconv.Atoi(str)
if err != nil {
return err
}
*out = i
return nil
}); err != nil {
t.Fatalf("unexpected error %v", err)
}
if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames, nil); err != nil {
t.Fatalf("unexpected error %v", err)
}
if !reflect.DeepEqual(y, A{"bar", 1, ""}) {
t.Errorf("unexpected result: %#v", y)
}
}
func TestConverter_MapsStringArraysWithMappingKey(t *testing.T) {
type A struct {
Foo string `json:"test"`
Baz int
Other string
}
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
if err := c.RegisterConversionFunc(func(input *[]string, out *string, s Scope) error {
if len(*input) == 0 {
*out = ""
}
*out = (*input)[0]
return nil
}); err != nil {
t.Fatalf("unexpected error %v", err)
}
x := map[string][]string{
"Foo": {"bar"},
"test": {"baz"},
}
y := A{"", 0, ""}
if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames|IgnoreMissingFields, &Meta{}); err != nil {
t.Fatalf("unexpected error %v", err)
}
if !reflect.DeepEqual(y, A{"bar", 0, ""}) {
t.Errorf("unexpected result: %#v", y)
}
mapping := func(key string, sourceTag, destTag reflect.StructTag) (source string, dest string) {
if s := destTag.Get("json"); len(s) > 0 {
return strings.SplitN(s, ",", 2)[0], key
}
return key, key
}
if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames|IgnoreMissingFields, &Meta{KeyNameMapping: mapping}); err != nil {
t.Fatalf("unexpected error %v", err)
}
if !reflect.DeepEqual(y, A{"baz", 0, ""}) {
t.Errorf("unexpected result: %#v", y)
}
}
func TestConverter_fuzz(t *testing.T) {
// Use the same types from the scheme test.
table := []struct {
from, to, check interface{}
}{
{&TestType1{}, &ExternalTestType1{}, &TestType1{}},
{&ExternalTestType1{}, &TestType1{}, &ExternalTestType1{}},
}
f := fuzz.New().NilChance(.5).NumElements(0, 100)
c := NewConverter(DefaultNameFunc)
c.nameFunc = func(t reflect.Type) string {
// Hide the fact that we don't have separate packages for these things.
return map[reflect.Type]string{
reflect.TypeOf(TestType1{}): "TestType1",
reflect.TypeOf(ExternalTestType1{}): "TestType1",
reflect.TypeOf(TestType2{}): "TestType2",
reflect.TypeOf(ExternalTestType2{}): "TestType2",
}[t]
}
c.Debug = testLogger(t)
for i, item := range table {
for j := 0; j < *fuzzIters; j++ {
f.Fuzz(item.from)
err := c.Convert(item.from, item.to, 0, nil)
if err != nil {
t.Errorf("(%v, %v): unexpected error: %v", i, j, err)
continue
}
err = c.Convert(item.to, item.check, 0, nil)
if err != nil {
t.Errorf("(%v, %v): unexpected error: %v", i, j, err)
continue
}
if e, a := item.from, item.check; !reflect.DeepEqual(e, a) {
t.Errorf("(%v, %v): unexpected diff: %v", i, j, diff.ObjectDiff(e, a))
}
}
}
}
func TestConverter_MapElemAddr(t *testing.T) {
type Foo struct {
A map[int]int
}
type Bar struct {
A map[string]string
}
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
err := c.RegisterConversionFunc(
func(in *int, out *string, s Scope) error {
*out = fmt.Sprintf("%v", *in)
return nil
},
)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
err = c.RegisterConversionFunc(
func(in *string, out *int, s Scope) error {
if str, err := strconv.Atoi(*in); err != nil {
return err
} else {
*out = str
return nil
}
},
)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
f := fuzz.New().NilChance(0).NumElements(3, 3)
first := Foo{}
second := Bar{}
f.Fuzz(&first)
err = c.Convert(&first, &second, AllowDifferentFieldTypeNames, nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
third := Foo{}
err = c.Convert(&second, &third, AllowDifferentFieldTypeNames, nil)
if e, a := first, third; !reflect.DeepEqual(e, a) {
t.Errorf("Unexpected diff: %v", diff.ObjectDiff(e, a))
}
}
func TestConverter_tags(t *testing.T) {
type Foo struct {
A string `test:"foo"`
}
type Bar struct {
A string `test:"bar"`
}
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
err := c.RegisterConversionFunc(
func(in *string, out *string, s Scope) error {
if e, a := "foo", s.SrcTag().Get("test"); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "bar", s.DestTag().Get("test"); e != a {
t.Errorf("expected %v, got %v", e, a)
}
return nil
},
)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
err = c.Convert(&Foo{}, &Bar{}, AllowDifferentFieldTypeNames, nil)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
}
func TestConverter_meta(t *testing.T) {
type Foo struct{ A string }
type Bar struct{ A string }
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
checks := 0
err := c.RegisterConversionFunc(
func(in *Foo, out *Bar, s Scope) error {
if s.Meta() == nil {
t.Errorf("Meta did not get passed!")
}
checks++
s.Convert(&in.A, &out.A, 0)
return nil
},
)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
err = c.RegisterConversionFunc(
func(in *string, out *string, s Scope) error {
if s.Meta() == nil {
t.Errorf("Meta did not get passed a second time!")
}
checks++
return nil
},
)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
err = c.Convert(&Foo{}, &Bar{}, 0, &Meta{})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if checks != 2 {
t.Errorf("Registered functions did not get called.")
}
}
func TestConverter_flags(t *testing.T) {
type Foo struct{ A string }
type Bar struct{ A string }
table := []struct {
from, to interface{}
flags FieldMatchingFlags
shouldSucceed bool
}{
// Check that DestFromSource allows extra fields only in source.
{
from: &struct{ A string }{},
to: &struct{ A, B string }{},
flags: DestFromSource,
shouldSucceed: false,
}, {
from: &struct{ A, B string }{},
to: &struct{ A string }{},
flags: DestFromSource,
shouldSucceed: true,
},
// Check that SourceToDest allows for extra fields only in dest.
{
from: &struct{ A string }{},
to: &struct{ A, B string }{},
flags: SourceToDest,
shouldSucceed: true,
}, {
from: &struct{ A, B string }{},
to: &struct{ A string }{},
flags: SourceToDest,
shouldSucceed: false,
},
// Check that IgnoreMissingFields makes the above failure cases pass.
{
from: &struct{ A string }{},
to: &struct{ A, B string }{},
flags: DestFromSource | IgnoreMissingFields,
shouldSucceed: true,
}, {
from: &struct{ A, B string }{},
to: &struct{ A string }{},
flags: SourceToDest | IgnoreMissingFields,
shouldSucceed: true,
},
// Check that the field type name must match unless
// AllowDifferentFieldTypeNames is specified.
{
from: &struct{ A, B Foo }{},
to: &struct{ A Bar }{},
flags: DestFromSource,
shouldSucceed: false,
}, {
from: &struct{ A Foo }{},
to: &struct{ A, B Bar }{},
flags: SourceToDest,
shouldSucceed: false,
}, {
from: &struct{ A, B Foo }{},
to: &struct{ A Bar }{},
flags: DestFromSource | AllowDifferentFieldTypeNames,
shouldSucceed: true,
}, {
from: &struct{ A Foo }{},
to: &struct{ A, B Bar }{},
flags: SourceToDest | AllowDifferentFieldTypeNames,
shouldSucceed: true,
},
}
f := fuzz.New().NilChance(.5).NumElements(0, 100)
c := NewConverter(DefaultNameFunc)
c.Debug = testLogger(t)
for i, item := range table {
for j := 0; j < *fuzzIters; j++ {
f.Fuzz(item.from)
err := c.Convert(item.from, item.to, item.flags, nil)
if item.shouldSucceed && err != nil {
t.Errorf("(%v, %v): unexpected error: %v", i, j, err)
continue
}
if !item.shouldSucceed && err == nil {
t.Errorf("(%v, %v): unexpected non-error", i, j)
continue
}
}
}
}
func TestConverter_FieldRename(t *testing.T) {
type WeirdMeta struct {
Name string
Type string
}
type NameMeta struct {
Name string
}
type TypeMeta struct {
Type string
}
type A struct {
WeirdMeta
}
type B struct {
TypeMeta
NameMeta
}
c := NewConverter(DefaultNameFunc)
err := c.SetStructFieldCopy(WeirdMeta{}, "WeirdMeta", TypeMeta{}, "TypeMeta")
if err != nil {
t.Fatalf("unexpected error %v", err)
}
err = c.SetStructFieldCopy(WeirdMeta{}, "WeirdMeta", NameMeta{}, "NameMeta")
if err != nil {
t.Fatalf("unexpected error %v", err)
}
err = c.SetStructFieldCopy(TypeMeta{}, "TypeMeta", WeirdMeta{}, "WeirdMeta")
if err != nil {
t.Fatalf("unexpected error %v", err)
}
err = c.SetStructFieldCopy(NameMeta{}, "NameMeta", WeirdMeta{}, "WeirdMeta")
if err != nil {
t.Fatalf("unexpected error %v", err)
}
c.Debug = testLogger(t)
aVal := &A{
WeirdMeta: WeirdMeta{
Name: "Foo",
Type: "Bar",
},
}
bVal := &B{
TypeMeta: TypeMeta{"Bar"},
NameMeta: NameMeta{"Foo"},
}
table := map[string]struct {
from, to, expect interface{}
flags FieldMatchingFlags
}{
"to": {
aVal,
&B{},
bVal,
AllowDifferentFieldTypeNames | SourceToDest | IgnoreMissingFields,
},
"from": {
bVal,
&A{},
aVal,
AllowDifferentFieldTypeNames | SourceToDest,
},
"toDestFirst": {
aVal,
&B{},
bVal,
AllowDifferentFieldTypeNames,
},
"fromDestFirst": {
bVal,
&A{},
aVal,
AllowDifferentFieldTypeNames | IgnoreMissingFields,
},
}
for name, item := range table {
err := c.Convert(item.from, item.to, item.flags, nil)
if err != nil {
t.Errorf("%v: unexpected error: %v", name, err)
continue
}
if e, a := item.expect, item.to; !reflect.DeepEqual(e, a) {
t.Errorf("%v: unexpected diff: %v", name, diff.ObjectDiff(e, a))
}
}
}

View file

@ -1,38 +0,0 @@
/*
Copyright 2014 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 conversion
import "testing"
func TestInvalidPtrValueKind(t *testing.T) {
var simple interface{}
switch obj := simple.(type) {
default:
_, err := EnforcePtr(obj)
if err == nil {
t.Errorf("Expected error on invalid kind")
}
}
}
func TestEnforceNilPtr(t *testing.T) {
var nilPtr *struct{}
_, err := EnforcePtr(nilPtr)
if err == nil {
t.Errorf("Expected error on nil pointer")
}
}

View file

@ -1,39 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"convert.go",
"doc.go",
],
importpath = "k8s.io/apimachinery/pkg/conversion/queryparams",
)
go_test(
name = "go_default_xtest",
srcs = ["convert_test.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion/queryparams:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,215 +0,0 @@
/*
Copyright 2014 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 queryparams_test
import (
"net/url"
"reflect"
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion/queryparams"
"k8s.io/apimachinery/pkg/runtime/schema"
)
type namedString string
type namedBool bool
type bar struct {
Float1 float32 `json:"float1"`
Float2 float64 `json:"float2"`
Int1 int64 `json:"int1,omitempty"`
Int2 int32 `json:"int2,omitempty"`
Int3 int16 `json:"int3,omitempty"`
Str1 string `json:"str1,omitempty"`
Ignored int
Ignored2 string
}
func (obj *bar) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
type foo struct {
Str string `json:"str"`
Integer int `json:"integer,omitempty"`
Slice []string `json:"slice,omitempty"`
Boolean bool `json:"boolean,omitempty"`
NamedStr namedString `json:"namedStr,omitempty"`
NamedBool namedBool `json:"namedBool,omitempty"`
Foobar bar `json:"foobar,omitempty"`
Testmap map[string]string `json:"testmap,omitempty"`
}
func (obj *foo) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
type baz struct {
Ptr *int `json:"ptr"`
Bptr *bool `json:"bptr,omitempty"`
}
func (obj *baz) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
// childStructs tests some of the types we serialize to query params for log API calls
// notably, the nested time struct
type childStructs struct {
Container string `json:"container,omitempty"`
Follow bool `json:"follow,omitempty"`
Previous bool `json:"previous,omitempty"`
SinceSeconds *int64 `json:"sinceSeconds,omitempty"`
SinceTime *metav1.Time `json:"sinceTime,omitempty"`
EmptyTime *metav1.Time `json:"emptyTime"`
NonPointerTime metav1.Time `json:"nonPointerTime"`
}
func (obj *childStructs) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func validateResult(t *testing.T, input interface{}, actual, expected url.Values) {
local := url.Values{}
for k, v := range expected {
local[k] = v
}
for k, v := range actual {
if ev, ok := local[k]; !ok || !reflect.DeepEqual(ev, v) {
if !ok {
t.Errorf("%#v: actual value key %s not found in expected map", input, k)
} else {
t.Errorf("%#v: values don't match: actual: %#v, expected: %#v", input, v, ev)
}
}
delete(local, k)
}
if len(local) > 0 {
t.Errorf("%#v: expected map has keys that were not found in actual map: %#v", input, local)
}
}
func TestConvert(t *testing.T) {
sinceSeconds := int64(123)
sinceTime := metav1.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC)
tests := []struct {
input interface{}
expected url.Values
}{
{
input: &foo{
Str: "hello",
},
expected: url.Values{"str": {"hello"}},
},
{
input: &foo{
Str: "test string",
Slice: []string{"one", "two", "three"},
Integer: 234,
Boolean: true,
},
expected: url.Values{"str": {"test string"}, "slice": {"one", "two", "three"}, "integer": {"234"}, "boolean": {"true"}},
},
{
input: &foo{
Str: "named types",
NamedStr: "value1",
NamedBool: true,
},
expected: url.Values{"str": {"named types"}, "namedStr": {"value1"}, "namedBool": {"true"}},
},
{
input: &foo{
Str: "don't ignore embedded struct",
Foobar: bar{
Float1: 5.0,
},
},
expected: url.Values{"str": {"don't ignore embedded struct"}, "float1": {"5"}, "float2": {"0"}},
},
{
// Ignore untagged fields
input: &bar{
Float1: 23.5,
Float2: 100.7,
Int1: 1,
Int2: 2,
Int3: 3,
Ignored: 1,
Ignored2: "ignored",
},
expected: url.Values{"float1": {"23.5"}, "float2": {"100.7"}, "int1": {"1"}, "int2": {"2"}, "int3": {"3"}},
},
{
// include fields that are not tagged omitempty
input: &foo{
NamedStr: "named str",
},
expected: url.Values{"str": {""}, "namedStr": {"named str"}},
},
{
input: &baz{
Ptr: intp(5),
Bptr: boolp(true),
},
expected: url.Values{"ptr": {"5"}, "bptr": {"true"}},
},
{
input: &baz{
Bptr: boolp(true),
},
expected: url.Values{"ptr": {""}, "bptr": {"true"}},
},
{
input: &baz{
Ptr: intp(5),
},
expected: url.Values{"ptr": {"5"}},
},
{
input: &childStructs{
Container: "mycontainer",
Follow: true,
Previous: true,
SinceSeconds: &sinceSeconds,
SinceTime: &sinceTime, // test a custom marshaller
EmptyTime: nil, // test a nil custom marshaller without omitempty
NonPointerTime: sinceTime,
},
expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "sinceTime": {"2000-01-01T12:34:56Z"}, "emptyTime": {""}, "nonPointerTime": {"2000-01-01T12:34:56Z"}},
},
{
input: &childStructs{
Container: "mycontainer",
Follow: true,
Previous: true,
SinceSeconds: &sinceSeconds,
SinceTime: nil, // test a nil custom marshaller with omitempty
NonPointerTime: sinceTime,
},
expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "emptyTime": {""}, "nonPointerTime": {"2000-01-01T12:34:56Z"}},
},
}
for _, test := range tests {
result, err := queryparams.Convert(test.input)
if err != nil {
t.Errorf("Unexpected error while converting %#v: %v", test.input, err)
}
validateResult(t, test.input, result, test.expected)
}
}
func intp(n int) *int { return &n }
func boolp(b bool) *bool { return &b }

View file

@ -1,41 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"fields_test.go",
"selector_test.go",
],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"fields.go",
"requirements.go",
"selector.go",
],
importpath = "k8s.io/apimachinery/pkg/fields",
deps = ["//vendor/k8s.io/apimachinery/pkg/selection:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,57 +0,0 @@
/*
Copyright 2015 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 fields
import (
"testing"
)
func matches(t *testing.T, ls Set, want string) {
if ls.String() != want {
t.Errorf("Expected '%s', but got '%s'", want, ls.String())
}
}
func TestSetString(t *testing.T) {
matches(t, Set{"x": "y"}, "x=y")
matches(t, Set{"foo": "bar"}, "foo=bar")
matches(t, Set{"foo": "bar", "baz": "qup"}, "baz=qup,foo=bar")
}
func TestFieldHas(t *testing.T) {
fieldHasTests := []struct {
Ls Fields
Key string
Has bool
}{
{Set{"x": "y"}, "x", true},
{Set{"x": ""}, "x", true},
{Set{"x": "y"}, "foo", false},
}
for _, lh := range fieldHasTests {
if has := lh.Ls.Has(lh.Key); has != lh.Has {
t.Errorf("%#v.Has(%#v) => %v, expected %v", lh.Ls, lh.Key, has, lh.Has)
}
}
}
func TestFieldGet(t *testing.T) {
ls := Set{"x": "y"}
if ls.Get("x") != "y" {
t.Errorf("Set.Get is broken")
}
}

View file

@ -1,397 +0,0 @@
/*
Copyright 2015 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 fields
import (
"reflect"
"testing"
)
func TestSplitTerms(t *testing.T) {
testcases := map[string][]string{
// Simple selectors
`a`: {`a`},
`a=avalue`: {`a=avalue`},
`a=avalue,b=bvalue`: {`a=avalue`, `b=bvalue`},
`a=avalue,b==bvalue,c!=cvalue`: {`a=avalue`, `b==bvalue`, `c!=cvalue`},
// Empty terms
``: nil,
`a=a,`: {`a=a`, ``},
`,a=a`: {``, `a=a`},
// Escaped values
`k=\,,k2=v2`: {`k=\,`, `k2=v2`}, // escaped comma in value
`k=\\,k2=v2`: {`k=\\`, `k2=v2`}, // escaped backslash, unescaped comma
`k=\\\,,k2=v2`: {`k=\\\,`, `k2=v2`}, // escaped backslash and comma
`k=\a\b\`: {`k=\a\b\`}, // non-escape sequences
`k=\`: {`k=\`}, // orphan backslash
// Multi-byte
`함=수,목=록`: {`함=수`, `목=록`},
}
for selector, expectedTerms := range testcases {
if terms := splitTerms(selector); !reflect.DeepEqual(terms, expectedTerms) {
t.Errorf("splitSelectors(`%s`): Expected\n%#v\ngot\n%#v", selector, expectedTerms, terms)
}
}
}
func TestSplitTerm(t *testing.T) {
testcases := map[string]struct {
lhs string
op string
rhs string
ok bool
}{
// Simple terms
`a=value`: {lhs: `a`, op: `=`, rhs: `value`, ok: true},
`b==value`: {lhs: `b`, op: `==`, rhs: `value`, ok: true},
`c!=value`: {lhs: `c`, op: `!=`, rhs: `value`, ok: true},
// Empty or invalid terms
``: {lhs: ``, op: ``, rhs: ``, ok: false},
`a`: {lhs: ``, op: ``, rhs: ``, ok: false},
// Escaped values
`k=\,`: {lhs: `k`, op: `=`, rhs: `\,`, ok: true},
`k=\=`: {lhs: `k`, op: `=`, rhs: `\=`, ok: true},
`k=\\\a\b\=\,\`: {lhs: `k`, op: `=`, rhs: `\\\a\b\=\,\`, ok: true},
// Multi-byte
`함=수`: {lhs: ``, op: `=`, rhs: ``, ok: true},
}
for term, expected := range testcases {
lhs, op, rhs, ok := splitTerm(term)
if lhs != expected.lhs || op != expected.op || rhs != expected.rhs || ok != expected.ok {
t.Errorf(
"splitTerm(`%s`): Expected\n%s,%s,%s,%v\nGot\n%s,%s,%s,%v",
term,
expected.lhs, expected.op, expected.rhs, expected.ok,
lhs, op, rhs, ok,
)
}
}
}
func TestEscapeValue(t *testing.T) {
// map values to their normalized escaped values
testcases := map[string]string{
``: ``,
`a`: `a`,
`=`: `\=`,
`,`: `\,`,
`\`: `\\`,
`\=\,\`: `\\\=\\\,\\`,
}
for unescapedValue, escapedValue := range testcases {
actualEscaped := EscapeValue(unescapedValue)
if actualEscaped != escapedValue {
t.Errorf("EscapeValue(%s): expected %s, got %s", unescapedValue, escapedValue, actualEscaped)
}
actualUnescaped, err := UnescapeValue(escapedValue)
if err != nil {
t.Errorf("UnescapeValue(%s): unexpected error %v", escapedValue, err)
}
if actualUnescaped != unescapedValue {
t.Errorf("UnescapeValue(%s): expected %s, got %s", escapedValue, unescapedValue, actualUnescaped)
}
}
// test invalid escape sequences
invalidTestcases := []string{
`\`, // orphan slash is invalid
`\\\`, // orphan slash is invalid
`\a`, // unrecognized escape sequence is invalid
}
for _, invalidValue := range invalidTestcases {
_, err := UnescapeValue(invalidValue)
if _, ok := err.(InvalidEscapeSequence); !ok || err == nil {
t.Errorf("UnescapeValue(%s): expected invalid escape sequence error, got %#v", invalidValue, err)
}
}
}
func TestSelectorParse(t *testing.T) {
testGoodStrings := []string{
"x=a,y=b,z=c",
"",
"x!=a,y=b",
`x=a||y\=b`,
`x=a\=\=b`,
}
testBadStrings := []string{
"x=a||y=b",
"x==a==b",
"x=a,b",
"x in (a)",
"x in (a,b,c)",
"x",
}
for _, test := range testGoodStrings {
lq, err := ParseSelector(test)
if err != nil {
t.Errorf("%v: error %v (%#v)\n", test, err, err)
}
if test != lq.String() {
t.Errorf("%v restring gave: %v\n", test, lq.String())
}
}
for _, test := range testBadStrings {
_, err := ParseSelector(test)
if err == nil {
t.Errorf("%v: did not get expected error\n", test)
}
}
}
func TestDeterministicParse(t *testing.T) {
s1, err := ParseSelector("x=a,a=x")
s2, err2 := ParseSelector("a=x,x=a")
if err != nil || err2 != nil {
t.Errorf("Unexpected parse error")
}
if s1.String() != s2.String() {
t.Errorf("Non-deterministic parse")
}
}
func expectMatch(t *testing.T, selector string, ls Set) {
lq, err := ParseSelector(selector)
if err != nil {
t.Errorf("Unable to parse %v as a selector\n", selector)
return
}
if !lq.Matches(ls) {
t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
}
}
func expectNoMatch(t *testing.T, selector string, ls Set) {
lq, err := ParseSelector(selector)
if err != nil {
t.Errorf("Unable to parse %v as a selector\n", selector)
return
}
if lq.Matches(ls) {
t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
}
}
func TestEverything(t *testing.T) {
if !Everything().Matches(Set{"x": "y"}) {
t.Errorf("Nil selector didn't match")
}
if !Everything().Empty() {
t.Errorf("Everything was not empty")
}
}
func TestSelectorMatches(t *testing.T) {
expectMatch(t, "", Set{"x": "y"})
expectMatch(t, "x=y", Set{"x": "y"})
expectMatch(t, "x=y,z=w", Set{"x": "y", "z": "w"})
expectMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "a"})
expectMatch(t, "notin=in", Set{"notin": "in"}) // in and notin in exactMatch
expectNoMatch(t, "x=y", Set{"x": "z"})
expectNoMatch(t, "x=y,z=w", Set{"x": "w", "z": "w"})
expectNoMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "w"})
fieldset := Set{
"foo": "bar",
"baz": "blah",
"complex": `=value\,\`,
}
expectMatch(t, "foo=bar", fieldset)
expectMatch(t, "baz=blah", fieldset)
expectMatch(t, "foo=bar,baz=blah", fieldset)
expectMatch(t, `foo=bar,baz=blah,complex=\=value\\\,\\`, fieldset)
expectNoMatch(t, "foo=blah", fieldset)
expectNoMatch(t, "baz=bar", fieldset)
expectNoMatch(t, "foo=bar,foobar=bar,baz=blah", fieldset)
}
func TestOneTermEqualSelector(t *testing.T) {
if !OneTermEqualSelector("x", "y").Matches(Set{"x": "y"}) {
t.Errorf("No match when match expected.")
}
if OneTermEqualSelector("x", "y").Matches(Set{"x": "z"}) {
t.Errorf("Match when none expected.")
}
}
func expectMatchDirect(t *testing.T, selector, ls Set) {
if !SelectorFromSet(selector).Matches(ls) {
t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
}
}
func expectNoMatchDirect(t *testing.T, selector, ls Set) {
if SelectorFromSet(selector).Matches(ls) {
t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
}
}
func TestSetMatches(t *testing.T) {
labelset := Set{
"foo": "bar",
"baz": "blah",
}
expectMatchDirect(t, Set{}, labelset)
expectMatchDirect(t, Set{"foo": "bar"}, labelset)
expectMatchDirect(t, Set{"baz": "blah"}, labelset)
expectMatchDirect(t, Set{"foo": "bar", "baz": "blah"}, labelset)
expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset)
expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset)
expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset)
}
func TestNilMapIsValid(t *testing.T) {
selector := Set(nil).AsSelector()
if selector == nil {
t.Errorf("Selector for nil set should be Everything")
}
if !selector.Empty() {
t.Errorf("Selector for nil set should be Empty")
}
}
func TestSetIsEmpty(t *testing.T) {
if !(Set{}).AsSelector().Empty() {
t.Errorf("Empty set should be empty")
}
if !(andTerm(nil)).Empty() {
t.Errorf("Nil andTerm should be empty")
}
if (&hasTerm{}).Empty() {
t.Errorf("hasTerm should not be empty")
}
if (&notHasTerm{}).Empty() {
t.Errorf("notHasTerm should not be empty")
}
if !(andTerm{andTerm{}}).Empty() {
t.Errorf("Nested andTerm should be empty")
}
if (andTerm{&hasTerm{"a", "b"}}).Empty() {
t.Errorf("Nested andTerm should not be empty")
}
}
func TestRequiresExactMatch(t *testing.T) {
testCases := map[string]struct {
S Selector
Label string
Value string
Found bool
}{
"empty set": {Set{}.AsSelector(), "test", "", false},
"empty hasTerm": {&hasTerm{}, "test", "", false},
"skipped hasTerm": {&hasTerm{"a", "b"}, "test", "", false},
"valid hasTerm": {&hasTerm{"test", "b"}, "test", "b", true},
"valid hasTerm no value": {&hasTerm{"test", ""}, "test", "", true},
"valid notHasTerm": {&notHasTerm{"test", "b"}, "test", "", false},
"valid notHasTerm no value": {&notHasTerm{"test", ""}, "test", "", false},
"nil andTerm": {andTerm(nil), "test", "", false},
"empty andTerm": {andTerm{}, "test", "", false},
"nested andTerm": {andTerm{andTerm{}}, "test", "", false},
"nested andTerm matches": {andTerm{&hasTerm{"test", "b"}}, "test", "b", true},
"andTerm with non-match": {andTerm{&hasTerm{}, &hasTerm{"test", "b"}}, "test", "b", true},
}
for k, v := range testCases {
value, found := v.S.RequiresExactMatch(v.Label)
if value != v.Value {
t.Errorf("%s: expected value %s, got %s", k, v.Value, value)
}
if found != v.Found {
t.Errorf("%s: expected found %t, got %t", k, v.Found, found)
}
}
}
func TestTransform(t *testing.T) {
testCases := []struct {
name string
selector string
transform func(field, value string) (string, string, error)
result string
isEmpty bool
}{
{
name: "empty selector",
selector: "",
transform: func(field, value string) (string, string, error) { return field, value, nil },
result: "",
isEmpty: true,
},
{
name: "no-op transform",
selector: "a=b,c=d",
transform: func(field, value string) (string, string, error) { return field, value, nil },
result: "a=b,c=d",
isEmpty: false,
},
{
name: "transform one field",
selector: "a=b,c=d",
transform: func(field, value string) (string, string, error) {
if field == "a" {
return "e", "f", nil
}
return field, value, nil
},
result: "e=f,c=d",
isEmpty: false,
},
{
name: "remove field to make empty",
selector: "a=b",
transform: func(field, value string) (string, string, error) { return "", "", nil },
result: "",
isEmpty: true,
},
{
name: "remove only one field",
selector: "a=b,c=d,e=f",
transform: func(field, value string) (string, string, error) {
if field == "c" {
return "", "", nil
}
return field, value, nil
},
result: "a=b,e=f",
isEmpty: false,
},
}
for i, tc := range testCases {
result, err := ParseAndTransformSelector(tc.selector, tc.transform)
if err != nil {
t.Errorf("[%d] unexpected error during Transform: %v", i, err)
}
if result.Empty() != tc.isEmpty {
t.Errorf("[%d] expected empty: %t, got: %t", i, tc.isEmpty, result.Empty())
}
if result.String() != tc.result {
t.Errorf("[%d] unexpected result: %s", i, result.String())
}
}
}

View file

@ -1,50 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"labels_test.go",
"selector_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/selection:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"labels.go",
"selector.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apimachinery/pkg/labels",
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/selection:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,231 +0,0 @@
/*
Copyright 2014 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 labels
import (
"testing"
)
func matches(t *testing.T, ls Set, want string) {
if ls.String() != want {
t.Errorf("Expected '%s', but got '%s'", want, ls.String())
}
}
func TestSetString(t *testing.T) {
matches(t, Set{"x": "y"}, "x=y")
matches(t, Set{"foo": "bar"}, "foo=bar")
matches(t, Set{"foo": "bar", "baz": "qup"}, "baz=qup,foo=bar")
// TODO: Make our label representation robust enough to handle labels
// with ",=!" characters in their names.
}
func TestLabelHas(t *testing.T) {
labelHasTests := []struct {
Ls Labels
Key string
Has bool
}{
{Set{"x": "y"}, "x", true},
{Set{"x": ""}, "x", true},
{Set{"x": "y"}, "foo", false},
}
for _, lh := range labelHasTests {
if has := lh.Ls.Has(lh.Key); has != lh.Has {
t.Errorf("%#v.Has(%#v) => %v, expected %v", lh.Ls, lh.Key, has, lh.Has)
}
}
}
func TestLabelGet(t *testing.T) {
ls := Set{"x": "y"}
if ls.Get("x") != "y" {
t.Errorf("Set.Get is broken")
}
}
func TestLabelConflict(t *testing.T) {
tests := []struct {
labels1 map[string]string
labels2 map[string]string
conflict bool
}{
{
labels1: map[string]string{},
labels2: map[string]string{},
conflict: false,
},
{
labels1: map[string]string{"env": "test"},
labels2: map[string]string{"infra": "true"},
conflict: false,
},
{
labels1: map[string]string{"env": "test"},
labels2: map[string]string{"infra": "true", "env": "test"},
conflict: false,
},
{
labels1: map[string]string{"env": "test"},
labels2: map[string]string{"env": "dev"},
conflict: true,
},
{
labels1: map[string]string{"env": "test", "infra": "false"},
labels2: map[string]string{"infra": "true", "color": "blue"},
conflict: true,
},
}
for _, test := range tests {
conflict := Conflicts(Set(test.labels1), Set(test.labels2))
if conflict != test.conflict {
t.Errorf("expected: %v but got: %v", test.conflict, conflict)
}
}
}
func TestLabelMerge(t *testing.T) {
tests := []struct {
labels1 map[string]string
labels2 map[string]string
mergedLabels map[string]string
}{
{
labels1: map[string]string{},
labels2: map[string]string{},
mergedLabels: map[string]string{},
},
{
labels1: map[string]string{"infra": "true"},
labels2: map[string]string{},
mergedLabels: map[string]string{"infra": "true"},
},
{
labels1: map[string]string{"infra": "true"},
labels2: map[string]string{"env": "test", "color": "blue"},
mergedLabels: map[string]string{"infra": "true", "env": "test", "color": "blue"},
},
}
for _, test := range tests {
mergedLabels := Merge(Set(test.labels1), Set(test.labels2))
if !Equals(mergedLabels, test.mergedLabels) {
t.Errorf("expected: %v but got: %v", test.mergedLabels, mergedLabels)
}
}
}
func TestLabelSelectorParse(t *testing.T) {
tests := []struct {
selector string
labels map[string]string
valid bool
}{
{
selector: "",
labels: map[string]string{},
valid: true,
},
{
selector: "x=a",
labels: map[string]string{"x": "a"},
valid: true,
},
{
selector: "x=a,y=b,z=c",
labels: map[string]string{"x": "a", "y": "b", "z": "c"},
valid: true,
},
{
selector: " x = a , y = b , z = c ",
labels: map[string]string{"x": "a", "y": "b", "z": "c"},
valid: true,
},
{
selector: "color=green,env=test,service=front",
labels: map[string]string{"color": "green", "env": "test", "service": "front"},
valid: true,
},
{
selector: "color=green, env=test, service=front",
labels: map[string]string{"color": "green", "env": "test", "service": "front"},
valid: true,
},
{
selector: ",",
labels: map[string]string{},
valid: false,
},
{
selector: "x",
labels: map[string]string{},
valid: false,
},
{
selector: "x,y",
labels: map[string]string{},
valid: false,
},
{
selector: "x=$y",
labels: map[string]string{},
valid: false,
},
{
selector: "x!=y",
labels: map[string]string{},
valid: false,
},
{
selector: "x==y",
labels: map[string]string{},
valid: false,
},
{
selector: "x=a||y=b",
labels: map[string]string{},
valid: false,
},
{
selector: "x in (y)",
labels: map[string]string{},
valid: false,
},
{
selector: "x notin (y)",
labels: map[string]string{},
valid: false,
},
{
selector: "x y",
labels: map[string]string{},
valid: false,
},
}
for _, test := range tests {
labels, err := ConvertSelectorToLabelsMap(test.selector)
if test.valid && err != nil {
t.Errorf("selector: %s, expected no error but got: %s", test.selector, err)
} else if !test.valid && err == nil {
t.Errorf("selector: %s, expected an error", test.selector)
}
if !Equals(Set(labels), test.labels) {
t.Errorf("expected: %s but got: %s", test.labels, labels)
}
}
}

View file

@ -1,575 +0,0 @@
/*
Copyright 2014 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 labels
import (
"reflect"
"strings"
"testing"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/apimachinery/pkg/util/sets"
)
func TestSelectorParse(t *testing.T) {
testGoodStrings := []string{
"x=a,y=b,z=c",
"",
"x!=a,y=b",
"x=",
"x= ",
"x=,z= ",
"x= ,z= ",
"!x",
"x>1",
"x>1,z<5",
}
testBadStrings := []string{
"x=a||y=b",
"x==a==b",
"!x=a",
"x<a",
}
for _, test := range testGoodStrings {
lq, err := Parse(test)
if err != nil {
t.Errorf("%v: error %v (%#v)\n", test, err, err)
}
if strings.Replace(test, " ", "", -1) != lq.String() {
t.Errorf("%v restring gave: %v\n", test, lq.String())
}
}
for _, test := range testBadStrings {
_, err := Parse(test)
if err == nil {
t.Errorf("%v: did not get expected error\n", test)
}
}
}
func TestDeterministicParse(t *testing.T) {
s1, err := Parse("x=a,a=x")
s2, err2 := Parse("a=x,x=a")
if err != nil || err2 != nil {
t.Errorf("Unexpected parse error")
}
if s1.String() != s2.String() {
t.Errorf("Non-deterministic parse")
}
}
func expectMatch(t *testing.T, selector string, ls Set) {
lq, err := Parse(selector)
if err != nil {
t.Errorf("Unable to parse %v as a selector\n", selector)
return
}
if !lq.Matches(ls) {
t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
}
}
func expectNoMatch(t *testing.T, selector string, ls Set) {
lq, err := Parse(selector)
if err != nil {
t.Errorf("Unable to parse %v as a selector\n", selector)
return
}
if lq.Matches(ls) {
t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
}
}
func TestEverything(t *testing.T) {
if !Everything().Matches(Set{"x": "y"}) {
t.Errorf("Nil selector didn't match")
}
if !Everything().Empty() {
t.Errorf("Everything was not empty")
}
}
func TestSelectorMatches(t *testing.T) {
expectMatch(t, "", Set{"x": "y"})
expectMatch(t, "x=y", Set{"x": "y"})
expectMatch(t, "x=y,z=w", Set{"x": "y", "z": "w"})
expectMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "a"})
expectMatch(t, "notin=in", Set{"notin": "in"}) // in and notin in exactMatch
expectMatch(t, "x", Set{"x": "z"})
expectMatch(t, "!x", Set{"y": "z"})
expectMatch(t, "x>1", Set{"x": "2"})
expectMatch(t, "x<1", Set{"x": "0"})
expectNoMatch(t, "x=z", Set{})
expectNoMatch(t, "x=y", Set{"x": "z"})
expectNoMatch(t, "x=y,z=w", Set{"x": "w", "z": "w"})
expectNoMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "w"})
expectNoMatch(t, "x", Set{"y": "z"})
expectNoMatch(t, "!x", Set{"x": "z"})
expectNoMatch(t, "x>1", Set{"x": "0"})
expectNoMatch(t, "x<1", Set{"x": "2"})
labelset := Set{
"foo": "bar",
"baz": "blah",
}
expectMatch(t, "foo=bar", labelset)
expectMatch(t, "baz=blah", labelset)
expectMatch(t, "foo=bar,baz=blah", labelset)
expectNoMatch(t, "foo=blah", labelset)
expectNoMatch(t, "baz=bar", labelset)
expectNoMatch(t, "foo=bar,foobar=bar,baz=blah", labelset)
}
func expectMatchDirect(t *testing.T, selector, ls Set) {
if !SelectorFromSet(selector).Matches(ls) {
t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls)
}
}
func expectNoMatchDirect(t *testing.T, selector, ls Set) {
if SelectorFromSet(selector).Matches(ls) {
t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls)
}
}
func TestSetMatches(t *testing.T) {
labelset := Set{
"foo": "bar",
"baz": "blah",
}
expectMatchDirect(t, Set{}, labelset)
expectMatchDirect(t, Set{"foo": "bar"}, labelset)
expectMatchDirect(t, Set{"baz": "blah"}, labelset)
expectMatchDirect(t, Set{"foo": "bar", "baz": "blah"}, labelset)
//TODO: bad values not handled for the moment in SelectorFromSet
//expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset)
//expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset)
//expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset)
}
func TestNilMapIsValid(t *testing.T) {
selector := Set(nil).AsSelector()
if selector == nil {
t.Errorf("Selector for nil set should be Everything")
}
if !selector.Empty() {
t.Errorf("Selector for nil set should be Empty")
}
}
func TestSetIsEmpty(t *testing.T) {
if !(Set{}).AsSelector().Empty() {
t.Errorf("Empty set should be empty")
}
if !(NewSelector()).Empty() {
t.Errorf("Nil Selector should be empty")
}
}
func TestLexer(t *testing.T) {
testcases := []struct {
s string
t Token
}{
{"", EndOfStringToken},
{",", CommaToken},
{"notin", NotInToken},
{"in", InToken},
{"=", EqualsToken},
{"==", DoubleEqualsToken},
{">", GreaterThanToken},
{"<", LessThanToken},
//Note that Lex returns the longest valid token found
{"!", DoesNotExistToken},
{"!=", NotEqualsToken},
{"(", OpenParToken},
{")", ClosedParToken},
//Non-"special" characters are considered part of an identifier
{"~", IdentifierToken},
{"||", IdentifierToken},
}
for _, v := range testcases {
l := &Lexer{s: v.s, pos: 0}
token, lit := l.Lex()
if token != v.t {
t.Errorf("Got %d it should be %d for '%s'", token, v.t, v.s)
}
if v.t != ErrorToken && lit != v.s {
t.Errorf("Got '%s' it should be '%s'", lit, v.s)
}
}
}
func min(l, r int) (m int) {
m = r
if l < r {
m = l
}
return m
}
func TestLexerSequence(t *testing.T) {
testcases := []struct {
s string
t []Token
}{
{"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken}},
{"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken}},
{"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken}},
{"key", []Token{IdentifierToken}},
{"!key", []Token{DoesNotExistToken, IdentifierToken}},
{"()", []Token{OpenParToken, ClosedParToken}},
{"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken}},
{"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken}},
{"key>2", []Token{IdentifierToken, GreaterThanToken, IdentifierToken}},
{"key<1", []Token{IdentifierToken, LessThanToken, IdentifierToken}},
}
for _, v := range testcases {
var literals []string
var tokens []Token
l := &Lexer{s: v.s, pos: 0}
for {
token, lit := l.Lex()
if token == EndOfStringToken {
break
}
tokens = append(tokens, token)
literals = append(literals, lit)
}
if len(tokens) != len(v.t) {
t.Errorf("Bad number of tokens for '%s %d, %d", v.s, len(tokens), len(v.t))
}
for i := 0; i < min(len(tokens), len(v.t)); i++ {
if tokens[i] != v.t[i] {
t.Errorf("Test '%s': Mismatching in token type found '%v' it should be '%v'", v.s, tokens[i], v.t[i])
}
}
}
}
func TestParserLookahead(t *testing.T) {
testcases := []struct {
s string
t []Token
}{
{"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
{"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
{"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken, EndOfStringToken}},
{"key", []Token{IdentifierToken, EndOfStringToken}},
{"!key", []Token{DoesNotExistToken, IdentifierToken, EndOfStringToken}},
{"()", []Token{OpenParToken, ClosedParToken, EndOfStringToken}},
{"", []Token{EndOfStringToken}},
{"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken, EndOfStringToken}},
{"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken, EndOfStringToken}},
{"key>2", []Token{IdentifierToken, GreaterThanToken, IdentifierToken, EndOfStringToken}},
{"key<1", []Token{IdentifierToken, LessThanToken, IdentifierToken, EndOfStringToken}},
}
for _, v := range testcases {
p := &Parser{l: &Lexer{s: v.s, pos: 0}, position: 0}
p.scan()
if len(p.scannedItems) != len(v.t) {
t.Errorf("Expected %d items found %d", len(v.t), len(p.scannedItems))
}
for {
token, lit := p.lookahead(KeyAndOperator)
token2, lit2 := p.consume(KeyAndOperator)
if token == EndOfStringToken {
break
}
if token != token2 || lit != lit2 {
t.Errorf("Bad values")
}
}
}
}
func TestRequirementConstructor(t *testing.T) {
requirementConstructorTests := []struct {
Key string
Op selection.Operator
Vals sets.String
Success bool
}{
{"x", selection.In, nil, false},
{"x", selection.NotIn, sets.NewString(), false},
{"x", selection.In, sets.NewString("foo"), true},
{"x", selection.NotIn, sets.NewString("foo"), true},
{"x", selection.Exists, nil, true},
{"x", selection.DoesNotExist, nil, true},
{"1foo", selection.In, sets.NewString("bar"), true},
{"1234", selection.In, sets.NewString("bar"), true},
{"y", selection.GreaterThan, sets.NewString("1"), true},
{"z", selection.LessThan, sets.NewString("6"), true},
{"foo", selection.GreaterThan, sets.NewString("bar"), false},
{"barz", selection.LessThan, sets.NewString("blah"), false},
{strings.Repeat("a", 254), selection.Exists, nil, false}, //breaks DNS rule that len(key) <= 253
}
for _, rc := range requirementConstructorTests {
if _, err := NewRequirement(rc.Key, rc.Op, rc.Vals.List()); err == nil && !rc.Success {
t.Errorf("expected error with key:%#v op:%v vals:%v, got no error", rc.Key, rc.Op, rc.Vals)
} else if err != nil && rc.Success {
t.Errorf("expected no error with key:%#v op:%v vals:%v, got:%v", rc.Key, rc.Op, rc.Vals, err)
}
}
}
func TestToString(t *testing.T) {
var req Requirement
toStringTests := []struct {
In *internalSelector
Out string
Valid bool
}{
{&internalSelector{
getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
getRequirement("y", selection.NotIn, sets.NewString("jkl"), t),
getRequirement("z", selection.Exists, nil, t)},
"x in (abc,def),y notin (jkl),z", true},
{&internalSelector{
getRequirement("x", selection.NotIn, sets.NewString("abc", "def"), t),
getRequirement("y", selection.NotEquals, sets.NewString("jkl"), t),
getRequirement("z", selection.DoesNotExist, nil, t)},
"x notin (abc,def),y!=jkl,!z", true},
{&internalSelector{
getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
req}, // adding empty req for the trailing ','
"x in (abc,def),", false},
{&internalSelector{
getRequirement("x", selection.NotIn, sets.NewString("abc"), t),
getRequirement("y", selection.In, sets.NewString("jkl", "mno"), t),
getRequirement("z", selection.NotIn, sets.NewString(""), t)},
"x notin (abc),y in (jkl,mno),z notin ()", true},
{&internalSelector{
getRequirement("x", selection.Equals, sets.NewString("abc"), t),
getRequirement("y", selection.DoubleEquals, sets.NewString("jkl"), t),
getRequirement("z", selection.NotEquals, sets.NewString("a"), t),
getRequirement("z", selection.Exists, nil, t)},
"x=abc,y==jkl,z!=a,z", true},
{&internalSelector{
getRequirement("x", selection.GreaterThan, sets.NewString("2"), t),
getRequirement("y", selection.LessThan, sets.NewString("8"), t),
getRequirement("z", selection.Exists, nil, t)},
"x>2,y<8,z", true},
}
for _, ts := range toStringTests {
if out := ts.In.String(); out == "" && ts.Valid {
t.Errorf("%#v.String() => '%v' expected no error", ts.In, out)
} else if out != ts.Out {
t.Errorf("%#v.String() => '%v' want '%v'", ts.In, out, ts.Out)
}
}
}
func TestRequirementSelectorMatching(t *testing.T) {
var req Requirement
labelSelectorMatchingTests := []struct {
Set Set
Sel Selector
Match bool
}{
{Set{"x": "foo", "y": "baz"}, &internalSelector{
req,
}, false},
{Set{"x": "foo", "y": "baz"}, &internalSelector{
getRequirement("x", selection.In, sets.NewString("foo"), t),
getRequirement("y", selection.NotIn, sets.NewString("alpha"), t),
}, true},
{Set{"x": "foo", "y": "baz"}, &internalSelector{
getRequirement("x", selection.In, sets.NewString("foo"), t),
getRequirement("y", selection.In, sets.NewString("alpha"), t),
}, false},
{Set{"y": ""}, &internalSelector{
getRequirement("x", selection.NotIn, sets.NewString(""), t),
getRequirement("y", selection.Exists, nil, t),
}, true},
{Set{"y": ""}, &internalSelector{
getRequirement("x", selection.DoesNotExist, nil, t),
getRequirement("y", selection.Exists, nil, t),
}, true},
{Set{"y": ""}, &internalSelector{
getRequirement("x", selection.NotIn, sets.NewString(""), t),
getRequirement("y", selection.DoesNotExist, nil, t),
}, false},
{Set{"y": "baz"}, &internalSelector{
getRequirement("x", selection.In, sets.NewString(""), t),
}, false},
{Set{"z": "2"}, &internalSelector{
getRequirement("z", selection.GreaterThan, sets.NewString("1"), t),
}, true},
{Set{"z": "v2"}, &internalSelector{
getRequirement("z", selection.GreaterThan, sets.NewString("1"), t),
}, false},
}
for _, lsm := range labelSelectorMatchingTests {
if match := lsm.Sel.Matches(lsm.Set); match != lsm.Match {
t.Errorf("%+v.Matches(%#v) => %v, want %v", lsm.Sel, lsm.Set, match, lsm.Match)
}
}
}
func TestSetSelectorParser(t *testing.T) {
setSelectorParserTests := []struct {
In string
Out Selector
Match bool
Valid bool
}{
{"", NewSelector(), true, true},
{"\rx", internalSelector{
getRequirement("x", selection.Exists, nil, t),
}, true, true},
{"this-is-a-dns.domain.com/key-with-dash", internalSelector{
getRequirement("this-is-a-dns.domain.com/key-with-dash", selection.Exists, nil, t),
}, true, true},
{"this-is-another-dns.domain.com/key-with-dash in (so,what)", internalSelector{
getRequirement("this-is-another-dns.domain.com/key-with-dash", selection.In, sets.NewString("so", "what"), t),
}, true, true},
{"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", internalSelector{
getRequirement("0.1.2.domain/99", selection.NotIn, sets.NewString("10.10.100.1", "tick.tack.clock"), t),
}, true, true},
{"foo in (abc)", internalSelector{
getRequirement("foo", selection.In, sets.NewString("abc"), t),
}, true, true},
{"x notin\n (abc)", internalSelector{
getRequirement("x", selection.NotIn, sets.NewString("abc"), t),
}, true, true},
{"x notin \t (abc,def)", internalSelector{
getRequirement("x", selection.NotIn, sets.NewString("abc", "def"), t),
}, true, true},
{"x in (abc,def)", internalSelector{
getRequirement("x", selection.In, sets.NewString("abc", "def"), t),
}, true, true},
{"x in (abc,)", internalSelector{
getRequirement("x", selection.In, sets.NewString("abc", ""), t),
}, true, true},
{"x in ()", internalSelector{
getRequirement("x", selection.In, sets.NewString(""), t),
}, true, true},
{"x notin (abc,,def),bar,z in (),w", internalSelector{
getRequirement("bar", selection.Exists, nil, t),
getRequirement("w", selection.Exists, nil, t),
getRequirement("x", selection.NotIn, sets.NewString("abc", "", "def"), t),
getRequirement("z", selection.In, sets.NewString(""), t),
}, true, true},
{"x,y in (a)", internalSelector{
getRequirement("y", selection.In, sets.NewString("a"), t),
getRequirement("x", selection.Exists, nil, t),
}, false, true},
{"x=a", internalSelector{
getRequirement("x", selection.Equals, sets.NewString("a"), t),
}, true, true},
{"x>1", internalSelector{
getRequirement("x", selection.GreaterThan, sets.NewString("1"), t),
}, true, true},
{"x<7", internalSelector{
getRequirement("x", selection.LessThan, sets.NewString("7"), t),
}, true, true},
{"x=a,y!=b", internalSelector{
getRequirement("x", selection.Equals, sets.NewString("a"), t),
getRequirement("y", selection.NotEquals, sets.NewString("b"), t),
}, true, true},
{"x=a,y!=b,z in (h,i,j)", internalSelector{
getRequirement("x", selection.Equals, sets.NewString("a"), t),
getRequirement("y", selection.NotEquals, sets.NewString("b"), t),
getRequirement("z", selection.In, sets.NewString("h", "i", "j"), t),
}, true, true},
{"x=a||y=b", internalSelector{}, false, false},
{"x,,y", nil, true, false},
{",x,y", nil, true, false},
{"x nott in (y)", nil, true, false},
{"x notin ( )", internalSelector{
getRequirement("x", selection.NotIn, sets.NewString(""), t),
}, true, true},
{"x notin (, a)", internalSelector{
getRequirement("x", selection.NotIn, sets.NewString("", "a"), t),
}, true, true},
{"a in (xyz),", nil, true, false},
{"a in (xyz)b notin ()", nil, true, false},
{"a ", internalSelector{
getRequirement("a", selection.Exists, nil, t),
}, true, true},
{"a in (x,y,notin, z,in)", internalSelector{
getRequirement("a", selection.In, sets.NewString("in", "notin", "x", "y", "z"), t),
}, true, true}, // operator 'in' inside list of identifiers
{"a in (xyz abc)", nil, false, false}, // no comma
{"a notin(", nil, true, false}, // bad formed
{"a (", nil, false, false}, // cpar
{"(", nil, false, false}, // opar
}
for _, ssp := range setSelectorParserTests {
if sel, err := Parse(ssp.In); err != nil && ssp.Valid {
t.Errorf("Parse(%s) => %v expected no error", ssp.In, err)
} else if err == nil && !ssp.Valid {
t.Errorf("Parse(%s) => %+v expected error", ssp.In, sel)
} else if ssp.Match && !reflect.DeepEqual(sel, ssp.Out) {
t.Errorf("Parse(%s) => parse output '%#v' doesn't match '%#v' expected match", ssp.In, sel, ssp.Out)
}
}
}
func getRequirement(key string, op selection.Operator, vals sets.String, t *testing.T) Requirement {
req, err := NewRequirement(key, op, vals.List())
if err != nil {
t.Errorf("NewRequirement(%v, %v, %v) resulted in error:%v", key, op, vals, err)
return Requirement{}
}
return *req
}
func TestAdd(t *testing.T) {
testCases := []struct {
name string
sel Selector
key string
operator selection.Operator
values []string
refSelector Selector
}{
{
"keyInOperator",
internalSelector{},
"key",
selection.In,
[]string{"value"},
internalSelector{Requirement{"key", selection.In, []string{"value"}}},
},
{
"keyEqualsOperator",
internalSelector{Requirement{"key", selection.In, []string{"value"}}},
"key2",
selection.Equals,
[]string{"value2"},
internalSelector{
Requirement{"key", selection.In, []string{"value"}},
Requirement{"key2", selection.Equals, []string{"value2"}},
},
},
}
for _, ts := range testCases {
req, err := NewRequirement(ts.key, ts.operator, ts.values)
if err != nil {
t.Errorf("%s - Unable to create labels.Requirement", ts.name)
}
ts.sel = ts.sel.Add(*req)
if !reflect.DeepEqual(ts.sel, ts.refSelector) {
t.Errorf("%s - Expected %v found %v", ts.name, ts.refSelector, ts.sel)
}
}
}

View file

@ -1,98 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["swagger_doc_generator_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"codec.go",
"codec_check.go",
"conversion.go",
"converter.go",
"doc.go",
"embedded.go",
"error.go",
"extension.go",
"generated.pb.go",
"helper.go",
"interfaces.go",
"register.go",
"scheme.go",
"scheme_builder.go",
"swagger_doc_generator.go",
"types.go",
"types_proto.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime",
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion/queryparams:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
],
)
go_test(
name = "go_default_xtest",
srcs = [
"conversion_test.go",
"converter_test.go",
"embedded_test.go",
"extension_test.go",
"scheme_test.go",
],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/testing:all-srcs",
],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)

View file

@ -1,115 +0,0 @@
/*
Copyright 2014 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 runtime_test
import (
"reflect"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
runtimetesting "k8s.io/apimachinery/pkg/runtime/testing"
)
func TestStringMapConversion(t *testing.T) {
internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Group: "test.group", Version: "external"}
scheme := runtime.NewScheme()
scheme.Log(t)
scheme.AddKnownTypeWithName(internalGV.WithKind("Complex"), &runtimetesting.InternalComplex{})
scheme.AddKnownTypeWithName(externalGV.WithKind("Complex"), &runtimetesting.ExternalComplex{})
testCases := map[string]struct {
input map[string][]string
errFn func(error) bool
expected runtime.Object
}{
"ignores omitempty": {
input: map[string][]string{
"String": {"not_used"},
"string": {"value"},
"int": {"1"},
"Integer64": {"2"},
},
expected: &runtimetesting.ExternalComplex{String: "value", Integer: 1},
},
"returns error on bad int": {
input: map[string][]string{
"int": {"a"},
},
errFn: func(err error) bool { return err != nil },
expected: &runtimetesting.ExternalComplex{},
},
"parses int64": {
input: map[string][]string{
"Int64": {"-1"},
},
expected: &runtimetesting.ExternalComplex{Int64: -1},
},
"returns error on bad int64": {
input: map[string][]string{
"Int64": {"a"},
},
errFn: func(err error) bool { return err != nil },
expected: &runtimetesting.ExternalComplex{},
},
"parses boolean true": {
input: map[string][]string{
"bool": {"true"},
},
expected: &runtimetesting.ExternalComplex{Bool: true},
},
"parses boolean any value": {
input: map[string][]string{
"bool": {"foo"},
},
expected: &runtimetesting.ExternalComplex{Bool: true},
},
"parses boolean false": {
input: map[string][]string{
"bool": {"false"},
},
expected: &runtimetesting.ExternalComplex{Bool: false},
},
"parses boolean empty value": {
input: map[string][]string{
"bool": {""},
},
expected: &runtimetesting.ExternalComplex{Bool: true},
},
"parses boolean no value": {
input: map[string][]string{
"bool": {},
},
expected: &runtimetesting.ExternalComplex{Bool: false},
},
}
for k, tc := range testCases {
out := &runtimetesting.ExternalComplex{}
if err := scheme.Convert(&tc.input, out, nil); (tc.errFn == nil && err != nil) || (tc.errFn != nil && !tc.errFn(err)) {
t.Errorf("%s: unexpected error: %v", k, err)
continue
} else if err != nil {
continue
}
if !reflect.DeepEqual(out, tc.expected) {
t.Errorf("%s: unexpected output: %#v", k, out)
}
}
}

View file

@ -1,597 +0,0 @@
/*
Copyright 2015 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.
*/
// These tests are in a separate package to break cyclic dependency in tests.
// Unstructured type depends on unstructured converter package but we want to test how the converter handles
// the Unstructured type so we need to import both.
package runtime_test
import (
encodingjson "encoding/json"
"fmt"
"reflect"
"strconv"
"testing"
"time"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/json"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var simpleEquality = conversion.EqualitiesOrDie(
func(a, b time.Time) bool {
return a.UTC() == b.UTC()
},
)
// Definte a number of test types.
type A struct {
A int `json:"aa,omitempty"`
B string `json:"ab,omitempty"`
C bool `json:"ac,omitempty"`
}
type B struct {
A A `json:"ba"`
B string `json:"bb"`
C map[string]string `json:"bc"`
D []string `json:"bd"`
}
type C struct {
A []A `json:"ca"`
B `json:",inline"`
C string `json:"cc"`
D *int64 `json:"cd"`
E map[string]int `json:"ce"`
F []bool `json:"cf"`
G []int `json:"cg"`
H float32 `json:"ch"`
I []interface{} `json:"ci"`
}
type D struct {
A []interface{} `json:"da"`
}
type E struct {
A interface{} `json:"ea"`
}
type F struct {
A string `json:"fa"`
B map[string]string `json:"fb"`
C []A `json:"fc"`
D int `json:"fd"`
E float32 `json:"fe"`
F []string `json:"ff"`
G []int `json:"fg"`
H []bool `json:"fh"`
I []float32 `json:"fi"`
}
type G struct {
CustomValue1 CustomValue `json:"customValue1"`
CustomValue2 *CustomValue `json:"customValue2"`
CustomPointer1 CustomPointer `json:"customPointer1"`
CustomPointer2 *CustomPointer `json:"customPointer2"`
}
type CustomValue struct {
data []byte
}
// MarshalJSON has a value receiver on this type.
func (c CustomValue) MarshalJSON() ([]byte, error) {
return c.data, nil
}
type CustomPointer struct {
data []byte
}
// MarshalJSON has a pointer receiver on this type.
func (c *CustomPointer) MarshalJSON() ([]byte, error) {
return c.data, nil
}
func doRoundTrip(t *testing.T, item interface{}) {
data, err := json.Marshal(item)
if err != nil {
t.Errorf("Error when marshaling object: %v", err)
return
}
unstr := make(map[string]interface{})
err = json.Unmarshal(data, &unstr)
if err != nil {
t.Errorf("Error when unmarshaling to unstructured: %v", err)
return
}
data, err = json.Marshal(unstr)
if err != nil {
t.Errorf("Error when marshaling unstructured: %v", err)
return
}
unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = json.Unmarshal(data, unmarshalledObj)
if err != nil {
t.Errorf("Error when unmarshaling to object: %v", err)
return
}
if !reflect.DeepEqual(item, unmarshalledObj) {
t.Errorf("Object changed during JSON operations, diff: %v", diff.ObjectReflectDiff(item, unmarshalledObj))
return
}
// TODO: should be using mismatch detection but fails due to another error
newUnstr, err := runtime.DefaultUnstructuredConverter.ToUnstructured(item)
if err != nil {
t.Errorf("ToUnstructured failed: %v", err)
return
}
newObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = runtime.NewTestUnstructuredConverter(simpleEquality).FromUnstructured(newUnstr, newObj)
if err != nil {
t.Errorf("FromUnstructured failed: %v", err)
return
}
if !reflect.DeepEqual(item, newObj) {
t.Errorf("Object changed, diff: %v", diff.ObjectReflectDiff(item, newObj))
}
}
func TestRoundTrip(t *testing.T) {
intVal := int64(42)
testCases := []struct {
obj interface{}
}{
{
obj: &unstructured.UnstructuredList{
Object: map[string]interface{}{
"kind": "List",
},
// Not testing a list with nil Items because items is a non-optional field and hence
// is always marshaled into an empty array which is not equal to nil when unmarshalled and will fail.
// That is expected.
Items: []unstructured.Unstructured{},
},
},
{
obj: &unstructured.UnstructuredList{
Object: map[string]interface{}{
"kind": "List",
},
Items: []unstructured.Unstructured{
{
Object: map[string]interface{}{
"kind": "Pod",
},
},
},
},
},
{
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "Pod",
},
},
},
{
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "foo1",
},
},
},
},
{
// This (among others) tests nil map, slice and pointer.
obj: &C{
C: "ccc",
},
},
{
// This (among others) tests empty map and slice.
obj: &C{
A: []A{},
C: "ccc",
E: map[string]int{},
I: []interface{}{},
},
},
{
obj: &C{
A: []A{
{
A: 1,
B: "11",
C: true,
},
{
A: 2,
B: "22",
C: false,
},
},
B: B{
A: A{
A: 3,
B: "33",
},
B: "bbb",
C: map[string]string{
"k1": "v1",
"k2": "v2",
},
D: []string{"s1", "s2"},
},
C: "ccc",
D: &intVal,
E: map[string]int{
"k1": 1,
"k2": 2,
},
F: []bool{true, false, false},
G: []int{1, 2, 5},
H: 3.3,
I: []interface{}{nil, nil, nil},
},
},
{
// Test slice of interface{} with empty slices.
obj: &D{
A: []interface{}{[]interface{}{}, []interface{}{}},
},
},
{
// Test slice of interface{} with different values.
obj: &D{
A: []interface{}{3.0, "3.0", nil},
},
},
}
for i := range testCases {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
doRoundTrip(t, testCases[i].obj)
})
}
}
// Verifies that:
// 1) serialized json -> object
// 2) serialized json -> map[string]interface{} -> object
// produces the same object.
func doUnrecognized(t *testing.T, jsonData string, item interface{}, expectedErr error) {
unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err := json.Unmarshal([]byte(jsonData), unmarshalledObj)
if (err != nil) != (expectedErr != nil) {
t.Errorf("Unexpected error when unmarshaling to object: %v, expected: %v", err, expectedErr)
return
}
unstr := make(map[string]interface{})
err = json.Unmarshal([]byte(jsonData), &unstr)
if err != nil {
t.Errorf("Error when unmarshaling to unstructured: %v", err)
return
}
newObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = runtime.NewTestUnstructuredConverter(simpleEquality).FromUnstructured(unstr, newObj)
if (err != nil) != (expectedErr != nil) {
t.Errorf("Unexpected error in FromUnstructured: %v, expected: %v", err, expectedErr)
}
if expectedErr == nil && !reflect.DeepEqual(unmarshalledObj, newObj) {
t.Errorf("Object changed, diff: %v", diff.ObjectReflectDiff(unmarshalledObj, newObj))
}
}
func TestUnrecognized(t *testing.T) {
testCases := []struct {
data string
obj interface{}
err error
}{
{
data: "{\"da\":[3.0,\"3.0\",null]}",
obj: &D{},
},
{
data: "{\"ea\":[3.0,\"3.0\",null]}",
obj: &E{},
},
{
data: "{\"ea\":[null,null,null]}",
obj: &E{},
},
{
data: "{\"ea\":[[],[null]]}",
obj: &E{},
},
{
data: "{\"ea\":{\"a\":[],\"b\":null}}",
obj: &E{},
},
{
data: "{\"fa\":\"fa\",\"fb\":{\"a\":\"a\"}}",
obj: &F{},
},
{
data: "{\"fa\":\"fa\",\"fb\":{\"a\":null}}",
obj: &F{},
},
{
data: "{\"fc\":[null]}",
obj: &F{},
},
{
data: "{\"fc\":[{\"aa\":123,\"ab\":\"bbb\"}]}",
obj: &F{},
},
{
// Only unknown fields
data: "{\"fx\":[{\"aa\":123,\"ab\":\"bbb\"}],\"fz\":123}",
obj: &F{},
},
{
data: "{\"fc\":[{\"aa\":\"aaa\",\"ab\":\"bbb\"}]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type int"),
},
{
data: "{\"fd\":123,\"fe\":3.5}",
obj: &F{},
},
{
data: "{\"ff\":[\"abc\"],\"fg\":[123],\"fh\":[true,false]}",
obj: &F{},
},
{
// Invalid string data
data: "{\"fa\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type string"),
},
{
// Invalid string data
data: "{\"fa\":13.5}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type string"),
},
{
// Invalid string data
data: "{\"fa\":true}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal bool into Go value of type string"),
},
{
// Invalid []string data
data: "{\"ff\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []string"),
},
{
// Invalid []string data
data: "{\"ff\":3.5}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []string"),
},
{
// Invalid []string data
data: "{\"ff\":[123,345]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type string"),
},
{
// Invalid []int data
data: "{\"fg\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []int"),
},
{
// Invalid []int data
data: "{\"fg\":\"abc\"}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type []int"),
},
{
// Invalid []int data
data: "{\"fg\":[\"abc\"]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type int"),
},
{
// Invalid []int data
data: "{\"fg\":[3.5]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number 3.5 into Go value of type int"),
},
{
// Invalid []int data
data: "{\"fg\":[true,false]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number 3.5 into Go value of type int"),
},
{
// Invalid []bool data
data: "{\"fh\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []bool"),
},
{
// Invalid []bool data
data: "{\"fh\":\"abc\"}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type []bool"),
},
{
// Invalid []bool data
data: "{\"fh\":[\"abc\"]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type bool"),
},
{
// Invalid []bool data
data: "{\"fh\":[3.5]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type bool"),
},
{
// Invalid []bool data
data: "{\"fh\":[123]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type bool"),
},
{
// Invalid []float data
data: "{\"fi\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []float32"),
},
{
// Invalid []float data
data: "{\"fi\":\"abc\"}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type []float32"),
},
{
// Invalid []float data
data: "{\"fi\":[\"abc\"]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type float32"),
},
{
// Invalid []float data
data: "{\"fi\":[true]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal bool into Go value of type float32"),
},
}
for _, tc := range testCases {
t.Run(tc.data, func(t *testing.T) {
doUnrecognized(t, tc.data, tc.obj, tc.err)
})
}
}
func TestDeepCopyJSON(t *testing.T) {
src := map[string]interface{}{
"a": nil,
"b": int64(123),
"c": map[string]interface{}{
"a": "b",
},
"d": []interface{}{
int64(1), int64(2),
},
"e": "estr",
"f": true,
"g": encodingjson.Number("123"),
}
deepCopy := runtime.DeepCopyJSON(src)
assert.Equal(t, src, deepCopy)
}
func TestFloatIntConversion(t *testing.T) {
unstr := map[string]interface{}{"fd": float64(3)}
var obj F
if err := runtime.NewTestUnstructuredConverter(simpleEquality).FromUnstructured(unstr, &obj); err != nil {
t.Errorf("Unexpected error in FromUnstructured: %v", err)
}
data, err := json.Marshal(unstr)
if err != nil {
t.Fatalf("Error when marshaling unstructured: %v", err)
}
var unmarshalled F
if err := json.Unmarshal(data, &unmarshalled); err != nil {
t.Fatalf("Error when unmarshaling to object: %v", err)
}
if !reflect.DeepEqual(obj, unmarshalled) {
t.Errorf("Incorrect conversion, diff: %v", diff.ObjectReflectDiff(obj, unmarshalled))
}
}
func TestCustomToUnstructured(t *testing.T) {
testcases := []struct {
Data string
Expected interface{}
}{
{Data: `null`, Expected: nil},
{Data: `true`, Expected: true},
{Data: `false`, Expected: false},
{Data: `[]`, Expected: []interface{}{}},
{Data: `[1]`, Expected: []interface{}{int64(1)}},
{Data: `{}`, Expected: map[string]interface{}{}},
{Data: `{"a":1}`, Expected: map[string]interface{}{"a": int64(1)}},
{Data: `0`, Expected: int64(0)},
{Data: `0.0`, Expected: float64(0)},
}
for _, tc := range testcases {
tc := tc
t.Run(tc.Data, func(t *testing.T) {
t.Parallel()
result, err := runtime.NewTestUnstructuredConverter(simpleEquality).ToUnstructured(&G{
CustomValue1: CustomValue{data: []byte(tc.Data)},
CustomValue2: &CustomValue{data: []byte(tc.Data)},
CustomPointer1: CustomPointer{data: []byte(tc.Data)},
CustomPointer2: &CustomPointer{data: []byte(tc.Data)},
})
require.NoError(t, err)
for field, fieldResult := range result {
assert.Equal(t, tc.Expected, fieldResult, field)
}
})
}
}
func TestCustomToUnstructuredTopLevel(t *testing.T) {
// Only objects are supported at the top level
topLevelCases := []interface{}{
&CustomValue{data: []byte(`{"a":1}`)},
&CustomPointer{data: []byte(`{"a":1}`)},
}
expected := map[string]interface{}{"a": int64(1)}
for i, obj := range topLevelCases {
obj := obj
t.Run(strconv.Itoa(i), func(t *testing.T) {
t.Parallel()
result, err := runtime.NewTestUnstructuredConverter(simpleEquality).ToUnstructured(obj)
require.NoError(t, err)
assert.Equal(t, expected, result)
})
}
}

View file

@ -1,256 +0,0 @@
/*
Copyright 2014 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 runtime_test
import (
"encoding/json"
"reflect"
"testing"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
runtimetesting "k8s.io/apimachinery/pkg/runtime/testing"
"k8s.io/apimachinery/pkg/util/diff"
)
func TestDecodeEmptyRawExtensionAsObject(t *testing.T) {
internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Group: "test.group", Version: "v1test"}
externalGVK := externalGV.WithKind("ObjectTest")
s := runtime.NewScheme()
s.AddKnownTypes(internalGV, &runtimetesting.ObjectTest{})
s.AddKnownTypeWithName(externalGVK, &runtimetesting.ObjectTestExternal{})
codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV)
obj, gvk, err := codec.Decode([]byte(`{"kind":"`+externalGVK.Kind+`","apiVersion":"`+externalGV.String()+`","items":[{}]}`), nil, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
test := obj.(*runtimetesting.ObjectTest)
if unk, ok := test.Items[0].(*runtime.Unknown); !ok || unk.Kind != "" || unk.APIVersion != "" || string(unk.Raw) != "{}" || unk.ContentType != runtime.ContentTypeJSON {
t.Fatalf("unexpected object: %#v", test.Items[0])
}
if *gvk != externalGVK {
t.Fatalf("unexpected kind: %#v", gvk)
}
obj, gvk, err = codec.Decode([]byte(`{"kind":"`+externalGVK.Kind+`","apiVersion":"`+externalGV.String()+`","items":[{"kind":"Other","apiVersion":"v1"}]}`), nil, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
test = obj.(*runtimetesting.ObjectTest)
if unk, ok := test.Items[0].(*runtime.Unknown); !ok || unk.Kind != "" || unk.APIVersion != "" || string(unk.Raw) != `{"kind":"Other","apiVersion":"v1"}` || unk.ContentType != runtime.ContentTypeJSON {
t.Fatalf("unexpected object: %#v", test.Items[0])
}
if *gvk != externalGVK {
t.Fatalf("unexpected kind: %#v", gvk)
}
}
func TestArrayOfRuntimeObject(t *testing.T) {
internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Group: "test.group", Version: "v1test"}
s := runtime.NewScheme()
s.AddKnownTypes(internalGV, &runtimetesting.EmbeddedTest{})
s.AddKnownTypeWithName(externalGV.WithKind("EmbeddedTest"), &runtimetesting.EmbeddedTestExternal{})
s.AddKnownTypes(internalGV, &runtimetesting.ObjectTest{})
s.AddKnownTypeWithName(externalGV.WithKind("ObjectTest"), &runtimetesting.ObjectTestExternal{})
codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV)
innerItems := []runtime.Object{
&runtimetesting.EmbeddedTest{ID: "baz"},
}
items := []runtime.Object{
&runtimetesting.EmbeddedTest{ID: "foo"},
&runtimetesting.EmbeddedTest{ID: "bar"},
// TODO: until YAML is removed, this JSON must be in ascending key order to ensure consistent roundtrip serialization
&runtime.Unknown{
Raw: []byte(`{"apiVersion":"unknown.group/unknown","foo":"bar","kind":"OtherTest"}`),
ContentType: runtime.ContentTypeJSON,
},
&runtimetesting.ObjectTest{
Items: runtime.NewEncodableList(codec, innerItems),
},
}
internal := &runtimetesting.ObjectTest{
Items: runtime.NewEncodableList(codec, items),
}
wire, err := runtime.Encode(codec, internal)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
t.Logf("Wire format is:\n%s\n", string(wire))
obj := &runtimetesting.ObjectTestExternal{}
if err := json.Unmarshal(wire, obj); err != nil {
t.Fatalf("unexpected error: %v", err)
}
t.Logf("exact wire is: %s", string(obj.Items[0].Raw))
items[3] = &runtimetesting.ObjectTest{Items: innerItems}
internal.Items = items
decoded, err := runtime.Decode(codec, wire)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
list, err := meta.ExtractList(decoded)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if errs := runtime.DecodeList(list, codec); len(errs) > 0 {
t.Fatalf("unexpected error: %v", errs)
}
list2, err := meta.ExtractList(list[3])
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if errs := runtime.DecodeList(list2, codec); len(errs) > 0 {
t.Fatalf("unexpected error: %v", errs)
}
if err := meta.SetList(list[3], list2); err != nil {
t.Fatalf("unexpected error: %v", err)
}
// we want DecodeList to set type meta if possible, even on runtime.Unknown objects
internal.Items[2].(*runtime.Unknown).TypeMeta = runtime.TypeMeta{Kind: "OtherTest", APIVersion: "unknown.group/unknown"}
if e, a := internal.Items, list; !reflect.DeepEqual(e, a) {
t.Errorf("mismatched decoded: %s", diff.ObjectGoPrintSideBySide(e, a))
}
}
func TestNestedObject(t *testing.T) {
internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Group: "test.group", Version: "v1test"}
embeddedTestExternalGVK := externalGV.WithKind("EmbeddedTest")
s := runtime.NewScheme()
s.AddKnownTypes(internalGV, &runtimetesting.EmbeddedTest{})
s.AddKnownTypeWithName(embeddedTestExternalGVK, &runtimetesting.EmbeddedTestExternal{})
codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV)
inner := &runtimetesting.EmbeddedTest{
ID: "inner",
}
outer := &runtimetesting.EmbeddedTest{
ID: "outer",
Object: runtime.NewEncodable(codec, inner),
}
wire, err := runtime.Encode(codec, outer)
if err != nil {
t.Fatalf("Unexpected encode error '%v'", err)
}
t.Logf("Wire format is:\n%v\n", string(wire))
decoded, err := runtime.Decode(codec, wire)
if err != nil {
t.Fatalf("Unexpected decode error %v", err)
}
// for later tests
outer.Object = inner
if e, a := outer, decoded; reflect.DeepEqual(e, a) {
t.Errorf("Expected unequal %#v %#v", e, a)
}
obj, err := runtime.Decode(codec, decoded.(*runtimetesting.EmbeddedTest).Object.(*runtime.Unknown).Raw)
if err != nil {
t.Fatal(err)
}
decoded.(*runtimetesting.EmbeddedTest).Object = obj
if e, a := outer, decoded; !reflect.DeepEqual(e, a) {
t.Errorf("Expected equal %#v %#v", e, a)
}
// test JSON decoding of the external object, which should preserve
// raw bytes
var externalViaJSON runtimetesting.EmbeddedTestExternal
err = json.Unmarshal(wire, &externalViaJSON)
if err != nil {
t.Fatalf("Unexpected decode error %v", err)
}
if externalViaJSON.Kind == "" || externalViaJSON.APIVersion == "" || externalViaJSON.ID != "outer" {
t.Errorf("Expected objects to have type info set, got %#v", externalViaJSON)
}
if len(externalViaJSON.EmptyObject.Raw) > 0 {
t.Errorf("Expected deserialization of empty nested objects into empty bytes, got %#v", externalViaJSON)
}
// test JSON decoding, too, since Decode uses yaml unmarshalling.
// Generic Unmarshalling of JSON cannot load the nested objects because there is
// no default schema set. Consumers wishing to get direct JSON decoding must use
// the external representation
var decodedViaJSON runtimetesting.EmbeddedTest
err = json.Unmarshal(wire, &decodedViaJSON)
if err == nil {
t.Fatal("Expeceted decode error")
}
if _, ok := err.(*json.UnmarshalTypeError); !ok {
t.Fatalf("Unexpected decode error: %v", err)
}
if a := decodedViaJSON; a.Object != nil || a.EmptyObject != nil {
t.Errorf("Expected embedded objects to be nil: %#v", a)
}
}
// TestDeepCopyOfRuntimeObject checks to make sure that runtime.Objects's can be passed through DeepCopy with fidelity
func TestDeepCopyOfRuntimeObject(t *testing.T) {
internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Group: "test.group", Version: "v1test"}
embeddedTestExternalGVK := externalGV.WithKind("EmbeddedTest")
s := runtime.NewScheme()
s.AddKnownTypes(internalGV, &runtimetesting.EmbeddedTest{})
s.AddKnownTypeWithName(embeddedTestExternalGVK, &runtimetesting.EmbeddedTestExternal{})
original := &runtimetesting.EmbeddedTest{
ID: "outer",
Object: &runtimetesting.EmbeddedTest{
ID: "inner",
},
}
codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV)
originalData, err := runtime.Encode(codec, original)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
t.Logf("originalRole = %v\n", string(originalData))
copyOfOriginal := original.DeepCopy()
copiedData, err := runtime.Encode(codec, copyOfOriginal)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
t.Logf("copyOfRole = %v\n", string(copiedData))
if !reflect.DeepEqual(original, copyOfOriginal) {
t.Errorf("expected \n%v\n, got \n%v", string(originalData), string(copiedData))
}
}

View file

@ -1,113 +0,0 @@
/*
Copyright 2014 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 runtime_test
import (
"bytes"
"encoding/json"
"reflect"
"testing"
"k8s.io/apimachinery/pkg/runtime"
)
func TestEmbeddedRawExtensionMarshal(t *testing.T) {
type test struct {
Ext runtime.RawExtension
}
extension := test{Ext: runtime.RawExtension{Raw: []byte(`{"foo":"bar"}`)}}
data, err := json.Marshal(extension)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if string(data) != `{"Ext":{"foo":"bar"}}` {
t.Errorf("unexpected data: %s", string(data))
}
}
func TestEmbeddedRawExtensionUnmarshal(t *testing.T) {
type test struct {
Ext runtime.RawExtension
}
testCases := map[string]struct {
orig test
}{
"non-empty object": {
orig: test{Ext: runtime.RawExtension{Raw: []byte(`{"foo":"bar"}`)}},
},
"empty object": {
orig: test{Ext: runtime.RawExtension{}},
},
}
for k, tc := range testCases {
new := test{}
data, _ := json.Marshal(tc.orig)
if err := json.Unmarshal(data, &new); err != nil {
t.Errorf("%s: umarshal error: %v", k, err)
}
if !reflect.DeepEqual(tc.orig, new) {
t.Errorf("%s: unmarshaled struct differs from original: %v %v", k, tc.orig, new)
}
}
}
func TestEmbeddedRawExtensionRoundTrip(t *testing.T) {
type test struct {
Ext runtime.RawExtension
}
testCases := map[string]struct {
orig test
}{
"non-empty object": {
orig: test{Ext: runtime.RawExtension{Raw: []byte(`{"foo":"bar"}`)}},
},
"empty object": {
orig: test{Ext: runtime.RawExtension{}},
},
}
for k, tc := range testCases {
new1 := test{}
new2 := test{}
data, err := json.Marshal(tc.orig)
if err != nil {
t.Errorf("1st marshal error: %v", err)
}
if err = json.Unmarshal(data, &new1); err != nil {
t.Errorf("1st unmarshal error: %v", err)
}
newData, err := json.Marshal(new1)
if err != nil {
t.Errorf("2st marshal error: %v", err)
}
if err = json.Unmarshal(newData, &new2); err != nil {
t.Errorf("2nd unmarshal error: %v", err)
}
if !bytes.Equal(data, newData) {
t.Errorf("%s: re-marshaled data differs from original: %v %v", k, data, newData)
}
if !reflect.DeepEqual(tc.orig, new1) {
t.Errorf("%s: unmarshaled struct differs from original: %v %v", k, tc.orig, new1)
}
if !reflect.DeepEqual(new1, new2) {
t.Errorf("%s: re-unmarshaled struct differs from original: %v %v", k, new1, new2)
}
}
}

View file

@ -1,43 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["group_version_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"generated.pb.go",
"group_version.go",
"interfaces.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/schema",
deps = ["//vendor/github.com/gogo/protobuf/proto:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)

View file

@ -1,136 +0,0 @@
/*
Copyright 2015 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 schema
import (
"testing"
)
func TestGroupVersionParse(t *testing.T) {
tests := []struct {
input string
out GroupVersion
err func(error) bool
}{
{input: "v1", out: GroupVersion{Version: "v1"}},
{input: "v2", out: GroupVersion{Version: "v2"}},
{input: "/v1", out: GroupVersion{Version: "v1"}},
{input: "v1/", out: GroupVersion{Group: "v1"}},
{input: "/v1/", err: func(err error) bool { return err.Error() == "unexpected GroupVersion string: /v1/" }},
{input: "v1/a", out: GroupVersion{Group: "v1", Version: "a"}},
}
for i, test := range tests {
out, err := ParseGroupVersion(test.input)
if test.err == nil && err != nil || err == nil && test.err != nil {
t.Errorf("%d: unexpected error: %v", i, err)
continue
}
if test.err != nil && !test.err(err) {
t.Errorf("%d: unexpected error: %v", i, err)
continue
}
if out != test.out {
t.Errorf("%d: unexpected output: %#v", i, out)
}
}
}
func TestGroupResourceParse(t *testing.T) {
tests := []struct {
input string
out GroupResource
}{
{input: "v1", out: GroupResource{Resource: "v1"}},
{input: ".v1", out: GroupResource{Group: "v1"}},
{input: "v1.", out: GroupResource{Resource: "v1"}},
{input: "v1.a", out: GroupResource{Group: "a", Resource: "v1"}},
{input: "b.v1.a", out: GroupResource{Group: "v1.a", Resource: "b"}},
}
for i, test := range tests {
out := ParseGroupResource(test.input)
if out != test.out {
t.Errorf("%d: unexpected output: %#v", i, out)
}
}
}
func TestParseResourceArg(t *testing.T) {
tests := []struct {
input string
gvr *GroupVersionResource
gr GroupResource
}{
{input: "v1", gr: GroupResource{Resource: "v1"}},
{input: ".v1", gr: GroupResource{Group: "v1"}},
{input: "v1.", gr: GroupResource{Resource: "v1"}},
{input: "v1.a", gr: GroupResource{Group: "a", Resource: "v1"}},
{input: "b.v1.a", gvr: &GroupVersionResource{Group: "a", Version: "v1", Resource: "b"}, gr: GroupResource{Group: "v1.a", Resource: "b"}},
}
for i, test := range tests {
gvr, gr := ParseResourceArg(test.input)
if (gvr != nil && test.gvr == nil) || (gvr == nil && test.gvr != nil) || (test.gvr != nil && *gvr != *test.gvr) {
t.Errorf("%d: unexpected output: %#v", i, gvr)
}
if gr != test.gr {
t.Errorf("%d: unexpected output: %#v", i, gr)
}
}
}
func TestKindForGroupVersionKinds(t *testing.T) {
gvks := GroupVersions{
GroupVersion{Group: "batch", Version: "v1"},
GroupVersion{Group: "batch", Version: "v2alpha1"},
GroupVersion{Group: "policy", Version: "v1beta1"},
}
cases := []struct {
input []GroupVersionKind
target GroupVersionKind
ok bool
}{
{
input: []GroupVersionKind{{Group: "batch", Version: "v2alpha1", Kind: "ScheduledJob"}},
target: GroupVersionKind{Group: "batch", Version: "v2alpha1", Kind: "ScheduledJob"},
ok: true,
},
{
input: []GroupVersionKind{{Group: "batch", Version: "v3alpha1", Kind: "CronJob"}},
target: GroupVersionKind{Group: "batch", Version: "v1", Kind: "CronJob"},
ok: true,
},
{
input: []GroupVersionKind{{Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"}},
target: GroupVersionKind{Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"},
ok: true,
},
{
input: []GroupVersionKind{{Group: "apps", Version: "v1alpha1", Kind: "StatefulSet"}},
target: GroupVersionKind{},
ok: false,
},
}
for i, c := range cases {
target, ok := gvks.KindForGroupVersionKinds(c.input)
if c.target != target {
t.Errorf("%d: unexpected target: %v, expected %v", i, target, c.target)
}
if c.ok != ok {
t.Errorf("%d: unexpected ok: %v, expected %v", i, ok, c.ok)
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,64 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["codec_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"codec_factory.go",
"negotiated_codec.go",
"protobuf_extension.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/testing:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/yaml:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,339 +0,0 @@
/*
Copyright 2014 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 serializer
import (
"encoding/json"
"fmt"
"log"
"os"
"reflect"
"strings"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
serializertesting "k8s.io/apimachinery/pkg/runtime/serializer/testing"
"k8s.io/apimachinery/pkg/util/diff"
"github.com/ghodss/yaml"
"github.com/google/gofuzz"
flag "github.com/spf13/pflag"
)
var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.")
type testMetaFactory struct{}
func (testMetaFactory) Interpret(data []byte) (*schema.GroupVersionKind, error) {
findKind := struct {
APIVersion string `json:"myVersionKey,omitempty"`
ObjectKind string `json:"myKindKey,omitempty"`
}{}
// yaml is a superset of json, so we use it to decode here. That way,
// we understand both.
if err := yaml.Unmarshal(data, &findKind); err != nil {
return nil, fmt.Errorf("couldn't get version/kind: %v", err)
}
gv, err := schema.ParseGroupVersion(findKind.APIVersion)
if err != nil {
return nil, err
}
return &schema.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: findKind.ObjectKind}, nil
}
// TestObjectFuzzer can randomly populate all the above objects.
var TestObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 100).Funcs(
func(j *serializertesting.MyWeirdCustomEmbeddedVersionKindField, c fuzz.Continue) {
c.FuzzNoCustom(j)
j.APIVersion = ""
j.ObjectKind = ""
},
)
// Returns a new Scheme set up with the test objects.
func GetTestScheme() (*runtime.Scheme, runtime.Codec) {
internalGV := schema.GroupVersion{Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Version: "v1"}
externalGV2 := schema.GroupVersion{Version: "v2"}
s := runtime.NewScheme()
// Ordinarily, we wouldn't add TestType2, but because this is a test and
// both types are from the same package, we need to get it into the system
// so that converter will match it with ExternalType2.
s.AddKnownTypes(internalGV, &serializertesting.TestType1{}, &serializertesting.TestType2{}, &serializertesting.ExternalInternalSame{})
s.AddKnownTypes(externalGV, &serializertesting.ExternalInternalSame{})
s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &serializertesting.ExternalTestType1{})
s.AddKnownTypeWithName(externalGV.WithKind("TestType2"), &serializertesting.ExternalTestType2{})
s.AddKnownTypeWithName(internalGV.WithKind("TestType3"), &serializertesting.TestType1{})
s.AddKnownTypeWithName(externalGV.WithKind("TestType3"), &serializertesting.ExternalTestType1{})
s.AddKnownTypeWithName(externalGV2.WithKind("TestType1"), &serializertesting.ExternalTestType1{})
s.AddUnversionedTypes(externalGV, &metav1.Status{})
cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{}))
codec := cf.LegacyCodec(schema.GroupVersion{Version: "v1"})
return s, codec
}
var semantic = conversion.EqualitiesOrDie(
func(a, b serializertesting.MyWeirdCustomEmbeddedVersionKindField) bool {
a.APIVersion, a.ObjectKind = "", ""
b.APIVersion, b.ObjectKind = "", ""
return a == b
},
)
func runTest(t *testing.T, source interface{}) {
name := reflect.TypeOf(source).Elem().Name()
TestObjectFuzzer.Fuzz(source)
_, codec := GetTestScheme()
data, err := runtime.Encode(codec, source.(runtime.Object))
if err != nil {
t.Errorf("%v: %v (%#v)", name, err, source)
return
}
obj2, err := runtime.Decode(codec, data)
if err != nil {
t.Errorf("%v: %v (%v)", name, err, string(data))
return
}
if !semantic.DeepEqual(source, obj2) {
t.Errorf("1: %v: diff: %v", name, diff.ObjectGoPrintSideBySide(source, obj2))
return
}
obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface()
if err := runtime.DecodeInto(codec, data, obj3.(runtime.Object)); err != nil {
t.Errorf("2: %v: %v", name, err)
return
}
if !semantic.DeepEqual(source, obj3) {
t.Errorf("3: %v: diff: %v", name, diff.ObjectDiff(source, obj3))
return
}
}
func TestTypes(t *testing.T) {
table := []interface{}{
&serializertesting.TestType1{},
&serializertesting.ExternalInternalSame{},
}
for _, item := range table {
// Try a few times, since runTest uses random values.
for i := 0; i < *fuzzIters; i++ {
runTest(t, item)
}
}
}
func TestVersionedEncoding(t *testing.T) {
s, _ := GetTestScheme()
cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{}))
info, _ := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON)
encoder := info.Serializer
codec := cf.CodecForVersions(encoder, nil, schema.GroupVersion{Version: "v2"}, nil)
out, err := runtime.Encode(codec, &serializertesting.TestType1{})
if err != nil {
t.Fatal(err)
}
if string(out) != `{"myVersionKey":"v2","myKindKey":"TestType1"}`+"\n" {
t.Fatal(string(out))
}
codec = cf.CodecForVersions(encoder, nil, schema.GroupVersion{Version: "v3"}, nil)
_, err = runtime.Encode(codec, &serializertesting.TestType1{})
if err == nil {
t.Fatal(err)
}
// unversioned encode with no versions is written directly to wire
codec = cf.CodecForVersions(encoder, nil, runtime.InternalGroupVersioner, nil)
out, err = runtime.Encode(codec, &serializertesting.TestType1{})
if err != nil {
t.Fatal(err)
}
if string(out) != `{}`+"\n" {
t.Fatal(string(out))
}
}
func TestMultipleNames(t *testing.T) {
_, codec := GetTestScheme()
obj, _, err := codec.Decode([]byte(`{"myKindKey":"TestType3","myVersionKey":"v1","A":"value"}`), nil, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
internal := obj.(*serializertesting.TestType1)
if internal.A != "value" {
t.Fatalf("unexpected decoded object: %#v", internal)
}
out, err := runtime.Encode(codec, internal)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !strings.Contains(string(out), `"myKindKey":"TestType1"`) {
t.Errorf("unexpected encoded output: %s", string(out))
}
}
func TestConvertTypesWhenDefaultNamesMatch(t *testing.T) {
internalGV := schema.GroupVersion{Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Version: "v1"}
s := runtime.NewScheme()
// create two names internally, with TestType1 being preferred
s.AddKnownTypeWithName(internalGV.WithKind("TestType1"), &serializertesting.TestType1{})
s.AddKnownTypeWithName(internalGV.WithKind("OtherType1"), &serializertesting.TestType1{})
// create two names externally, with TestType1 being preferred
s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &serializertesting.ExternalTestType1{})
s.AddKnownTypeWithName(externalGV.WithKind("OtherType1"), &serializertesting.ExternalTestType1{})
ext := &serializertesting.ExternalTestType1{}
ext.APIVersion = "v1"
ext.ObjectKind = "OtherType1"
ext.A = "test"
data, err := json.Marshal(ext)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expect := &serializertesting.TestType1{A: "test"}
codec := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})).LegacyCodec(schema.GroupVersion{Version: "v1"})
obj, err := runtime.Decode(codec, data)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !semantic.DeepEqual(expect, obj) {
t.Errorf("unexpected object: %#v", obj)
}
into := &serializertesting.TestType1{}
if err := runtime.DecodeInto(codec, data, into); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !semantic.DeepEqual(expect, into) {
t.Errorf("unexpected object: %#v", obj)
}
}
func TestEncode_Ptr(t *testing.T) {
_, codec := GetTestScheme()
tt := &serializertesting.TestType1{A: "I am a pointer object"}
data, err := runtime.Encode(codec, tt)
obj2, err2 := runtime.Decode(codec, data)
if err != nil || err2 != nil {
t.Fatalf("Failure: '%v' '%v'\n%s", err, err2, data)
}
if _, ok := obj2.(*serializertesting.TestType1); !ok {
t.Fatalf("Got wrong type")
}
if !semantic.DeepEqual(obj2, tt) {
t.Errorf("Expected:\n %#v,\n Got:\n %#v", tt, obj2)
}
}
func TestBadJSONRejection(t *testing.T) {
log.SetOutput(os.Stderr)
_, codec := GetTestScheme()
badJSONs := [][]byte{
[]byte(`{"myVersionKey":"v1"}`), // Missing kind
[]byte(`{"myVersionKey":"v1","myKindKey":"bar"}`), // Unknown kind
[]byte(`{"myVersionKey":"bar","myKindKey":"TestType1"}`), // Unknown version
[]byte(`{"myKindKey":"TestType1"}`), // Missing version
}
for _, b := range badJSONs {
if _, err := runtime.Decode(codec, b); err == nil {
t.Errorf("Did not reject bad json: %s", string(b))
}
}
badJSONKindMismatch := []byte(`{"myVersionKey":"v1","myKindKey":"ExternalInternalSame"}`)
if err := runtime.DecodeInto(codec, badJSONKindMismatch, &serializertesting.TestType1{}); err == nil {
t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch)
}
if err := runtime.DecodeInto(codec, []byte(``), &serializertesting.TestType1{}); err != nil {
t.Errorf("Should allow empty decode: %v", err)
}
if _, _, err := codec.Decode([]byte(``), &schema.GroupVersionKind{Kind: "ExternalInternalSame"}, nil); err == nil {
t.Errorf("Did not give error for empty data with only kind default")
}
if _, _, err := codec.Decode([]byte(`{"myVersionKey":"v1"}`), &schema.GroupVersionKind{Kind: "ExternalInternalSame"}, nil); err != nil {
t.Errorf("Gave error for version and kind default")
}
if _, _, err := codec.Decode([]byte(`{"myKindKey":"ExternalInternalSame"}`), &schema.GroupVersionKind{Version: "v1"}, nil); err != nil {
t.Errorf("Gave error for version and kind default")
}
if _, _, err := codec.Decode([]byte(``), &schema.GroupVersionKind{Kind: "ExternalInternalSame", Version: "v1"}, nil); err != nil {
t.Errorf("Gave error for version and kind defaulted: %v", err)
}
if _, err := runtime.Decode(codec, []byte(``)); err == nil {
t.Errorf("Did not give error for empty data")
}
}
// Returns a new Scheme set up with the test objects needed by TestDirectCodec.
func GetDirectCodecTestScheme() *runtime.Scheme {
internalGV := schema.GroupVersion{Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Version: "v1"}
s := runtime.NewScheme()
// Ordinarily, we wouldn't add TestType2, but because this is a test and
// both types are from the same package, we need to get it into the system
// so that converter will match it with ExternalType2.
s.AddKnownTypes(internalGV, &serializertesting.TestType1{})
s.AddKnownTypes(externalGV, &serializertesting.ExternalTestType1{})
s.AddUnversionedTypes(externalGV, &metav1.Status{})
return s
}
func TestDirectCodec(t *testing.T) {
s := GetDirectCodecTestScheme()
cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{}))
info, _ := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON)
serializer := info.Serializer
df := DirectCodecFactory{cf}
ignoredGV, err := schema.ParseGroupVersion("ignored group/ignored version")
if err != nil {
t.Fatal(err)
}
directEncoder := df.EncoderForVersion(serializer, ignoredGV)
directDecoder := df.DecoderToVersion(serializer, ignoredGV)
out, err := runtime.Encode(directEncoder, &serializertesting.ExternalTestType1{})
if err != nil {
t.Fatal(err)
}
if string(out) != `{"myVersionKey":"v1","myKindKey":"ExternalTestType1"}`+"\n" {
t.Fatal(string(out))
}
a, _, err := directDecoder.Decode(out, nil, nil)
e := &serializertesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: serializertesting.MyWeirdCustomEmbeddedVersionKindField{
APIVersion: "v1",
ObjectKind: "ExternalTestType1",
},
}
if !semantic.DeepEqual(e, a) {
t.Fatalf("expect %v, got %v", e, a)
}
}

View file

@ -1,55 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["meta_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"json.go",
"meta.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/json",
deps = [
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/json-iterator/go:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/framer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
],
)
go_test(
name = "go_default_xtest",
srcs = ["json_test.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,293 +0,0 @@
/*
Copyright 2015 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 json_test
import (
"fmt"
"reflect"
"strings"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/util/diff"
)
type testDecodable struct {
Other string
Value int `json:"value"`
gvk schema.GroupVersionKind
}
func (d *testDecodable) GetObjectKind() schema.ObjectKind { return d }
func (d *testDecodable) SetGroupVersionKind(gvk schema.GroupVersionKind) { d.gvk = gvk }
func (d *testDecodable) GroupVersionKind() schema.GroupVersionKind { return d.gvk }
func (d *testDecodable) DeepCopyObject() runtime.Object {
panic("testDecodable does not support DeepCopy")
}
func TestDecode(t *testing.T) {
testCases := []struct {
creater runtime.ObjectCreater
typer runtime.ObjectTyper
yaml bool
pretty bool
data []byte
defaultGVK *schema.GroupVersionKind
into runtime.Object
errFn func(error) bool
expectedObject runtime.Object
expectedGVK *schema.GroupVersionKind
}{
{
data: []byte("{}"),
expectedGVK: &schema.GroupVersionKind{},
errFn: func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") },
},
{
data: []byte("{}"),
defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
creater: &mockCreater{err: fmt.Errorf("fake error")},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
errFn: func(err error) bool { return err.Error() == "fake error" },
},
{
data: []byte("{}"),
defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
creater: &mockCreater{obj: &testDecodable{}},
expectedObject: &testDecodable{},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
},
// version without group is not defaulted
{
data: []byte(`{"apiVersion":"blah"}`),
defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
creater: &mockCreater{obj: &testDecodable{}},
expectedObject: &testDecodable{},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "", Version: "blah"},
},
// group without version is defaulted
{
data: []byte(`{"apiVersion":"other/"}`),
defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
creater: &mockCreater{obj: &testDecodable{}},
expectedObject: &testDecodable{},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
},
// group version, kind is defaulted
{
data: []byte(`{"apiVersion":"other1/blah1"}`),
defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
creater: &mockCreater{obj: &testDecodable{}},
expectedObject: &testDecodable{},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other1", Version: "blah1"},
},
// gvk all provided then not defaulted at all
{
data: []byte(`{"kind":"Test","apiVersion":"other/blah"}`),
defaultGVK: &schema.GroupVersionKind{Kind: "Test1", Group: "other1", Version: "blah1"},
creater: &mockCreater{obj: &testDecodable{}},
expectedObject: &testDecodable{},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
},
//gvk defaulting if kind not provided in data and defaultGVK use into's kind
{
data: []byte(`{"apiVersion":"b1/c1"}`),
into: &testDecodable{gvk: schema.GroupVersionKind{Kind: "a3", Group: "b1", Version: "c1"}},
typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "a3", Group: "b1", Version: "c1"}},
defaultGVK: nil,
creater: &mockCreater{obj: &testDecodable{}},
expectedObject: &testDecodable{gvk: schema.GroupVersionKind{Kind: "a3", Group: "b1", Version: "c1"}},
expectedGVK: &schema.GroupVersionKind{Kind: "a3", Group: "b1", Version: "c1"},
},
// accept runtime.Unknown as into and bypass creator
{
data: []byte(`{}`),
into: &runtime.Unknown{},
expectedGVK: &schema.GroupVersionKind{},
expectedObject: &runtime.Unknown{
Raw: []byte(`{}`),
ContentType: runtime.ContentTypeJSON,
},
},
{
data: []byte(`{"test":"object"}`),
into: &runtime.Unknown{},
expectedGVK: &schema.GroupVersionKind{},
expectedObject: &runtime.Unknown{
Raw: []byte(`{"test":"object"}`),
ContentType: runtime.ContentTypeJSON,
},
},
{
data: []byte(`{"test":"object"}`),
into: &runtime.Unknown{},
defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
expectedObject: &runtime.Unknown{
TypeMeta: runtime.TypeMeta{APIVersion: "other/blah", Kind: "Test"},
Raw: []byte(`{"test":"object"}`),
ContentType: runtime.ContentTypeJSON,
},
},
// unregistered objects can be decoded into directly
{
data: []byte(`{"kind":"Test","apiVersion":"other/blah","value":1,"Other":"test"}`),
into: &testDecodable{},
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
expectedObject: &testDecodable{
Other: "test",
Value: 1,
},
},
// registered types get defaulted by the into object kind
{
data: []byte(`{"value":1,"Other":"test"}`),
into: &testDecodable{},
typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
expectedObject: &testDecodable{
Other: "test",
Value: 1,
},
},
// registered types get defaulted by the into object kind even without version, but return an error
{
data: []byte(`{"value":1,"Other":"test"}`),
into: &testDecodable{},
typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: ""}},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: ""},
errFn: func(err error) bool { return strings.Contains(err.Error(), "Object 'apiVersion' is missing in") },
expectedObject: &testDecodable{
Other: "test",
Value: 1,
},
},
// runtime.VersionedObjects are decoded
{
data: []byte(`{"value":1,"Other":"test"}`),
into: &runtime.VersionedObjects{Objects: []runtime.Object{}},
creater: &mockCreater{obj: &testDecodable{}},
typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
defaultGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
expectedObject: &runtime.VersionedObjects{
Objects: []runtime.Object{
&testDecodable{
Other: "test",
Value: 1,
},
},
},
},
// runtime.VersionedObjects with an object are decoded into
{
data: []byte(`{"Other":"test"}`),
into: &runtime.VersionedObjects{Objects: []runtime.Object{&testDecodable{Value: 2}}},
typer: &mockTyper{gvk: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
expectedObject: &runtime.VersionedObjects{
Objects: []runtime.Object{
&testDecodable{
Other: "test",
Value: 2,
},
},
},
},
}
for i, test := range testCases {
var s runtime.Serializer
if test.yaml {
s = json.NewYAMLSerializer(json.DefaultMetaFactory, test.creater, test.typer)
} else {
s = json.NewSerializer(json.DefaultMetaFactory, test.creater, test.typer, test.pretty)
}
obj, gvk, err := s.Decode([]byte(test.data), test.defaultGVK, test.into)
if !reflect.DeepEqual(test.expectedGVK, gvk) {
t.Errorf("%d: unexpected GVK: %v", i, gvk)
}
switch {
case err == nil && test.errFn != nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil && test.errFn == nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil:
if !test.errFn(err) {
t.Errorf("%d: failed: %v", i, err)
}
if obj != nil {
t.Errorf("%d: should have returned nil object", i)
}
continue
}
if test.into != nil && test.into != obj {
t.Errorf("%d: expected into to be returned: %v", i, obj)
continue
}
if !reflect.DeepEqual(test.expectedObject, obj) {
t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintSideBySide(test.expectedObject, obj))
}
}
}
type mockCreater struct {
apiVersion string
kind string
err error
obj runtime.Object
}
func (c *mockCreater) New(kind schema.GroupVersionKind) (runtime.Object, error) {
c.apiVersion, c.kind = kind.GroupVersion().String(), kind.Kind
return c.obj, c.err
}
type mockTyper struct {
gvk *schema.GroupVersionKind
err error
}
func (t *mockTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
if t.gvk == nil {
return nil, false, t.err
}
return []schema.GroupVersionKind{*t.gvk}, false, t.err
}
func (t *mockTyper) Recognizes(_ schema.GroupVersionKind) bool {
return false
}

View file

@ -1,45 +0,0 @@
/*
Copyright 2014 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 json
import "testing"
func TestSimpleMetaFactoryInterpret(t *testing.T) {
factory := SimpleMetaFactory{}
gvk, err := factory.Interpret([]byte(`{"apiVersion":"1","kind":"object"}`))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if gvk.Version != "1" || gvk.Kind != "object" {
t.Errorf("unexpected interpret: %#v", gvk)
}
// no kind or version
gvk, err = factory.Interpret([]byte(`{}`))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if gvk.Version != "" || gvk.Kind != "" {
t.Errorf("unexpected interpret: %#v", gvk)
}
// unparsable
gvk, err = factory.Interpret([]byte(`{`))
if err == nil {
t.Errorf("unexpected non-error")
}
}

View file

@ -1,35 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"protobuf.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/framer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,32 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["recognizer.go"],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/recognizer/testing:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,41 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["streaming_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/framer:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["streaming.go"],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,84 +0,0 @@
/*
Copyright 2016 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 streaming
import (
"bytes"
"io"
"io/ioutil"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/framer"
)
type fakeDecoder struct {
got []byte
obj runtime.Object
err error
}
func (d *fakeDecoder) Decode(data []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
d.got = data
return d.obj, nil, d.err
}
func TestEmptyDecoder(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
d := &fakeDecoder{}
_, _, err := NewDecoder(ioutil.NopCloser(buf), d).Decode(nil, nil)
if err != io.EOF {
t.Fatal(err)
}
}
func TestDecoder(t *testing.T) {
frames := [][]byte{
make([]byte, 1025),
make([]byte, 1024*5),
make([]byte, 1024*1024*5),
make([]byte, 1025),
}
pr, pw := io.Pipe()
fw := framer.NewLengthDelimitedFrameWriter(pw)
go func() {
for i := range frames {
fw.Write(frames[i])
}
pw.Close()
}()
r := framer.NewLengthDelimitedFrameReader(pr)
d := &fakeDecoder{}
dec := NewDecoder(r, d)
if _, _, err := dec.Decode(nil, nil); err != nil || !bytes.Equal(d.got, frames[0]) {
t.Fatalf("unexpected %v %v", err, len(d.got))
}
if _, _, err := dec.Decode(nil, nil); err != nil || !bytes.Equal(d.got, frames[1]) {
t.Fatalf("unexpected %v %v", err, len(d.got))
}
if _, _, err := dec.Decode(nil, nil); err != ErrObjectTooLarge || !bytes.Equal(d.got, frames[1]) {
t.Fatalf("unexpected %v %v", err, len(d.got))
}
if _, _, err := dec.Decode(nil, nil); err != nil || !bytes.Equal(d.got, frames[3]) {
t.Fatalf("unexpected %v %v", err, len(d.got))
}
if _, _, err := dec.Decode(nil, nil); err != io.EOF {
t.Fatalf("unexpected %v %v", err, len(d.got))
}
}

View file

@ -1,41 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["versioning_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["versioning.go"],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,381 +0,0 @@
/*
Copyright 2015 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 versioning
import (
"fmt"
"io"
"io/ioutil"
"reflect"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
)
type testDecodable struct {
Other string
Value int `json:"value"`
gvk schema.GroupVersionKind
}
func (d *testDecodable) GetObjectKind() schema.ObjectKind { return d }
func (d *testDecodable) SetGroupVersionKind(gvk schema.GroupVersionKind) { d.gvk = gvk }
func (d *testDecodable) GroupVersionKind() schema.GroupVersionKind { return d.gvk }
func (d *testDecodable) DeepCopyObject() runtime.Object {
// no real deepcopy because these tests check for pointer equality
return d
}
type testNestedDecodable struct {
Other string
Value int `json:"value"`
gvk schema.GroupVersionKind
nestedCalled bool
nestedErr error
}
func (d *testNestedDecodable) GetObjectKind() schema.ObjectKind { return d }
func (d *testNestedDecodable) SetGroupVersionKind(gvk schema.GroupVersionKind) { d.gvk = gvk }
func (d *testNestedDecodable) GroupVersionKind() schema.GroupVersionKind { return d.gvk }
func (d *testNestedDecodable) DeepCopyObject() runtime.Object {
// no real deepcopy because these tests check for pointer equality
return d
}
func (d *testNestedDecodable) EncodeNestedObjects(e runtime.Encoder) error {
d.nestedCalled = true
return d.nestedErr
}
func (d *testNestedDecodable) DecodeNestedObjects(_ runtime.Decoder) error {
d.nestedCalled = true
return d.nestedErr
}
func TestNestedDecode(t *testing.T) {
n := &testNestedDecodable{nestedErr: fmt.Errorf("unable to decode")}
decoder := &mockSerializer{obj: n}
codec := NewCodec(nil, decoder, nil, nil, nil, nil, nil, nil)
if _, _, err := codec.Decode([]byte(`{}`), nil, n); err != n.nestedErr {
t.Errorf("unexpected error: %v", err)
}
if !n.nestedCalled {
t.Errorf("did not invoke nested decoder")
}
}
func TestNestedEncode(t *testing.T) {
n := &testNestedDecodable{nestedErr: fmt.Errorf("unable to decode")}
n2 := &testNestedDecodable{nestedErr: fmt.Errorf("unable to decode 2")}
encoder := &mockSerializer{obj: n}
codec := NewCodec(
encoder, nil,
&checkConvertor{obj: n2, groupVersion: schema.GroupVersion{Group: "other"}},
nil,
&mockTyper{gvks: []schema.GroupVersionKind{{Kind: "test"}}},
nil,
schema.GroupVersion{Group: "other"}, nil,
)
if err := codec.Encode(n, ioutil.Discard); err != n2.nestedErr {
t.Errorf("unexpected error: %v", err)
}
if n.nestedCalled || !n2.nestedCalled {
t.Errorf("did not invoke correct nested decoder")
}
}
func TestDecode(t *testing.T) {
gvk1 := &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}
decodable1 := &testDecodable{}
decodable2 := &testDecodable{}
decodable3 := &testDecodable{}
versionedDecodable1 := &runtime.VersionedObjects{Objects: []runtime.Object{decodable1}}
testCases := []struct {
serializer runtime.Serializer
convertor runtime.ObjectConvertor
creater runtime.ObjectCreater
typer runtime.ObjectTyper
defaulter runtime.ObjectDefaulter
yaml bool
pretty bool
encodes, decodes runtime.GroupVersioner
defaultGVK *schema.GroupVersionKind
into runtime.Object
errFn func(error) bool
expectedObject runtime.Object
sameObject runtime.Object
expectedGVK *schema.GroupVersionKind
}{
{
serializer: &mockSerializer{actual: gvk1},
convertor: &checkConvertor{groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}},
expectedGVK: gvk1,
decodes: schema.GroupVersion{Group: "other", Version: "__internal"},
},
{
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}},
expectedGVK: gvk1,
sameObject: decodable2,
decodes: schema.GroupVersion{Group: "other", Version: "__internal"},
},
// defaultGVK.Group is allowed to force a conversion to the destination group
{
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
defaultGVK: &schema.GroupVersionKind{Group: "force"},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "force", Version: "__internal"}},
expectedGVK: gvk1,
sameObject: decodable2,
decodes: schema.GroupVersion{Group: "force", Version: "__internal"},
},
// uses direct conversion for into when objects differ
{
into: decodable3,
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable3, directConvert: true},
expectedGVK: gvk1,
sameObject: decodable3,
},
{
into: versionedDecodable1,
serializer: &mockSerializer{actual: gvk1, obj: decodable3},
convertor: &checkConvertor{in: decodable3, obj: decodable1, directConvert: true},
expectedGVK: gvk1,
sameObject: versionedDecodable1,
},
// returns directly when serializer returns into
{
into: decodable3,
serializer: &mockSerializer{actual: gvk1, obj: decodable3},
expectedGVK: gvk1,
sameObject: decodable3,
},
// returns directly when serializer returns into
{
into: versionedDecodable1,
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
expectedGVK: gvk1,
sameObject: versionedDecodable1,
},
// runtime.VersionedObjects are decoded
{
into: &runtime.VersionedObjects{Objects: []runtime.Object{}},
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}},
expectedGVK: gvk1,
expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1, decodable2}},
decodes: schema.GroupVersion{Group: "other", Version: "__internal"},
},
// decode into the same version as the serialized object
{
decodes: schema.GroupVersions{gvk1.GroupVersion()},
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable1, groupVersion: schema.GroupVersions{{Group: "other", Version: "blah"}}},
expectedGVK: gvk1,
expectedObject: decodable1,
},
{
into: &runtime.VersionedObjects{Objects: []runtime.Object{}},
decodes: schema.GroupVersions{gvk1.GroupVersion()},
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable1, groupVersion: schema.GroupVersions{{Group: "other", Version: "blah"}}},
expectedGVK: gvk1,
expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1}},
},
// codec with non matching version skips conversion altogether
{
decodes: schema.GroupVersions{{Group: "something", Version: "else"}},
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable1, groupVersion: schema.GroupVersions{{Group: "something", Version: "else"}}},
expectedGVK: gvk1,
expectedObject: decodable1,
},
{
into: &runtime.VersionedObjects{Objects: []runtime.Object{}},
decodes: schema.GroupVersions{{Group: "something", Version: "else"}},
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable1, groupVersion: schema.GroupVersions{{Group: "something", Version: "else"}}},
expectedGVK: gvk1,
expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1}},
},
}
for i, test := range testCases {
t.Logf("%d", i)
s := NewCodec(test.serializer, test.serializer, test.convertor, test.creater, test.typer, test.defaulter, test.encodes, test.decodes)
obj, gvk, err := s.Decode([]byte(`{}`), test.defaultGVK, test.into)
if !reflect.DeepEqual(test.expectedGVK, gvk) {
t.Errorf("%d: unexpected GVK: %v", i, gvk)
}
switch {
case err == nil && test.errFn != nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil && test.errFn == nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil:
if !test.errFn(err) {
t.Errorf("%d: failed: %v", i, err)
}
if obj != nil {
t.Errorf("%d: should have returned nil object", i)
}
continue
}
if test.into != nil && test.into != obj {
t.Errorf("%d: expected into to be returned: %v", i, obj)
continue
}
switch {
case test.expectedObject != nil:
if !reflect.DeepEqual(test.expectedObject, obj) {
t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintSideBySide(test.expectedObject, obj))
}
case test.sameObject != nil:
if test.sameObject != obj {
t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintSideBySide(test.sameObject, obj))
}
case obj != nil:
t.Errorf("%d: unexpected object: %#v", i, obj)
}
}
}
type checkConvertor struct {
err error
in, obj runtime.Object
groupVersion runtime.GroupVersioner
directConvert bool
}
func (c *checkConvertor) Convert(in, out, context interface{}) error {
if !c.directConvert {
return fmt.Errorf("unexpected call to Convert")
}
if c.in != nil && c.in != in {
return fmt.Errorf("unexpected in: %s", in)
}
if c.obj != nil && c.obj != out {
return fmt.Errorf("unexpected out: %s", out)
}
return c.err
}
func (c *checkConvertor) ConvertToVersion(in runtime.Object, outVersion runtime.GroupVersioner) (out runtime.Object, err error) {
if c.directConvert {
return nil, fmt.Errorf("unexpected call to ConvertToVersion")
}
if c.in != nil && c.in != in {
return nil, fmt.Errorf("unexpected in: %s", in)
}
if !reflect.DeepEqual(c.groupVersion, outVersion) {
return nil, fmt.Errorf("unexpected outversion: %s (%s)", outVersion, c.groupVersion)
}
return c.obj, c.err
}
func (c *checkConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
return "", "", fmt.Errorf("unexpected call to ConvertFieldLabel")
}
type mockSerializer struct {
err error
obj runtime.Object
encodingObjGVK schema.GroupVersionKind
defaults, actual *schema.GroupVersionKind
into runtime.Object
}
func (s *mockSerializer) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
s.defaults = defaults
s.into = into
return s.obj, s.actual, s.err
}
func (s *mockSerializer) Encode(obj runtime.Object, w io.Writer) error {
s.obj = obj
s.encodingObjGVK = obj.GetObjectKind().GroupVersionKind()
return s.err
}
type mockCreater struct {
err error
obj runtime.Object
}
func (c *mockCreater) New(kind schema.GroupVersionKind) (runtime.Object, error) {
return c.obj, c.err
}
type mockTyper struct {
gvks []schema.GroupVersionKind
unversioned bool
err error
}
func (t *mockTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
return t.gvks, t.unversioned, t.err
}
func (t *mockTyper) Recognizes(_ schema.GroupVersionKind) bool {
return true
}
func TestDirectCodecEncode(t *testing.T) {
serializer := mockSerializer{}
typer := mockTyper{
gvks: []schema.GroupVersionKind{
{
Group: "wrong_group",
Kind: "some_kind",
},
{
Group: "expected_group",
Kind: "some_kind",
},
},
}
c := DirectEncoder{
Version: schema.GroupVersion{Group: "expected_group"},
Encoder: &serializer,
ObjectTyper: &typer,
}
c.Encode(&testDecodable{}, ioutil.Discard)
if e, a := "expected_group", serializer.encodingObjGVK.Group; e != a {
t.Errorf("expected group to be %v, got %v", e, a)
}
}

View file

@ -1,43 +0,0 @@
/*
Copyright 2015 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 runtime
import (
"testing"
)
func TestFmtRawDoc(t *testing.T) {
tests := []struct {
t, expected string
}{
{"aaa\n --- asd\n TODO: tooooodo\n toooodoooooo\n", "aaa"},
{"aaa\nasd\n TODO: tooooodo\nbbbb\n --- toooodoooooo\n", "aaa asd bbbb"},
{" TODO: tooooodo\n", ""},
{"Par1\n\nPar2\n\n", "Par1\\n\\nPar2"},
{"", ""},
{" ", ""},
{" \n", ""},
{" \n\n ", ""},
{"Example:\n\tl1\n\t\tl2\n", "Example:\\n\\tl1\\n\\t\\tl2"},
}
for _, test := range tests {
if o := fmtRawDoc(test.t); o != test.expected {
t.Fatalf("Expected: %q, got %q", test.expected, o)
}
}
}

View file

@ -1,25 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["operator.go"],
importpath = "k8s.io/apimachinery/pkg/selection",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,31 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"namespacedname.go",
"nodename.go",
"patch.go",
"uid.go",
],
importpath = "k8s.io/apimachinery/pkg/types",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,43 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"cache_test.go",
"lruexpirecache_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/golang/groupcache/lru:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"lruexpirecache.go",
],
importpath = "k8s.io/apimachinery/pkg/util/cache",
deps = ["//vendor/github.com/hashicorp/golang-lru:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,90 +0,0 @@
/*
Copyright 2014 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 cache
import (
"testing"
)
const (
maxTestCacheSize int = shardsCount * 2
)
func ExpectEntry(t *testing.T, cache Cache, index uint64, expectedValue interface{}) bool {
elem, found := cache.Get(index)
if !found {
t.Errorf("Expected to find entry with key %d", index)
return false
} else if elem != expectedValue {
t.Errorf("Expected to find %v, got %v", expectedValue, elem)
return false
}
return true
}
func TestBasic(t *testing.T) {
cache := NewCache(maxTestCacheSize)
cache.Add(1, "xxx")
ExpectEntry(t, cache, 1, "xxx")
}
func TestOverflow(t *testing.T) {
cache := NewCache(maxTestCacheSize)
for i := 0; i < maxTestCacheSize+1; i++ {
cache.Add(uint64(i), "xxx")
}
foundIndexes := make([]uint64, 0)
for i := 0; i < maxTestCacheSize+1; i++ {
_, found := cache.Get(uint64(i))
if found {
foundIndexes = append(foundIndexes, uint64(i))
}
}
if len(foundIndexes) != maxTestCacheSize {
t.Errorf("Expect to find %d elements, got %d %v", maxTestCacheSize, len(foundIndexes), foundIndexes)
}
}
func TestOverwrite(t *testing.T) {
cache := NewCache(maxTestCacheSize)
cache.Add(1, "xxx")
ExpectEntry(t, cache, 1, "xxx")
cache.Add(1, "yyy")
ExpectEntry(t, cache, 1, "yyy")
}
// TestEvict this test will fail sporatically depending on what add()
// selects for the randomKey to be evicted. Ensure that randomKey
// is never the key we most recently added. Since the chance of failure
// on each evict is 50%, if we do it 7 times, it should catch the problem
// if it exists >99% of the time.
func TestEvict(t *testing.T) {
cache := NewCache(shardsCount)
var found bool
for retry := 0; retry < 7; retry++ {
cache.Add(uint64(shardsCount), "xxx")
found = ExpectEntry(t, cache, uint64(shardsCount), "xxx")
if !found {
break
}
cache.Add(0, "xxx")
found = ExpectEntry(t, cache, 0, "xxx")
if !found {
break
}
}
}

View file

@ -1,68 +0,0 @@
/*
Copyright 2016 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 cache
import (
"testing"
"time"
"k8s.io/apimachinery/pkg/util/clock"
"github.com/golang/groupcache/lru"
)
func expectEntry(t *testing.T, c *LRUExpireCache, key lru.Key, value interface{}) {
result, ok := c.Get(key)
if !ok || result != value {
t.Errorf("Expected cache[%v]: %v, got %v", key, value, result)
}
}
func expectNotEntry(t *testing.T, c *LRUExpireCache, key lru.Key) {
if result, ok := c.Get(key); ok {
t.Errorf("Expected cache[%v] to be empty, got %v", key, result)
}
}
func TestSimpleGet(t *testing.T) {
c := NewLRUExpireCache(10)
c.Add("long-lived", "12345", 10*time.Hour)
expectEntry(t, c, "long-lived", "12345")
}
func TestExpiredGet(t *testing.T) {
fakeClock := clock.NewFakeClock(time.Now())
c := NewLRUExpireCacheWithClock(10, fakeClock)
c.Add("short-lived", "12345", 1*time.Millisecond)
// ensure the entry expired
fakeClock.Step(2 * time.Millisecond)
expectNotEntry(t, c, "short-lived")
}
func TestLRUOverflow(t *testing.T) {
c := NewLRUExpireCache(4)
c.Add("elem1", "1", 10*time.Hour)
c.Add("elem2", "2", 10*time.Hour)
c.Add("elem3", "3", 10*time.Hour)
c.Add("elem4", "4", 10*time.Hour)
c.Add("elem5", "5", 10*time.Hour)
expectNotEntry(t, c, "elem1")
expectEntry(t, c, "elem2", "2")
expectEntry(t, c, "elem3", "3")
expectEntry(t, c, "elem4", "4")
expectEntry(t, c, "elem5", "5")
}

View file

@ -1,32 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["clock_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["clock.go"],
importpath = "k8s.io/apimachinery/pkg/util/clock",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,184 +0,0 @@
/*
Copyright 2015 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 clock
import (
"testing"
"time"
)
func TestFakeClock(t *testing.T) {
startTime := time.Now()
tc := NewFakeClock(startTime)
tc.Step(time.Second)
now := tc.Now()
if now.Sub(startTime) != time.Second {
t.Errorf("input: %s now=%s gap=%s expected=%s", startTime, now, now.Sub(startTime), time.Second)
}
tt := tc.Now()
tc.SetTime(tt.Add(time.Hour))
if tc.Now().Sub(tt) != time.Hour {
t.Errorf("input: %s now=%s gap=%s expected=%s", tt, tc.Now(), tc.Now().Sub(tt), time.Hour)
}
}
func TestFakeClockSleep(t *testing.T) {
startTime := time.Now()
tc := NewFakeClock(startTime)
tc.Sleep(time.Duration(1) * time.Hour)
now := tc.Now()
if now.Sub(startTime) != time.Hour {
t.Errorf("Fake sleep failed, expected time to advance by one hour, instead, its %v", now.Sub(startTime))
}
}
func TestFakeAfter(t *testing.T) {
tc := NewFakeClock(time.Now())
if tc.HasWaiters() {
t.Errorf("unexpected waiter?")
}
oneSec := tc.After(time.Second)
if !tc.HasWaiters() {
t.Errorf("unexpected lack of waiter?")
}
oneOhOneSec := tc.After(time.Second + time.Millisecond)
twoSec := tc.After(2 * time.Second)
select {
case <-oneSec:
t.Errorf("unexpected channel read")
case <-oneOhOneSec:
t.Errorf("unexpected channel read")
case <-twoSec:
t.Errorf("unexpected channel read")
default:
}
tc.Step(999 * time.Millisecond)
select {
case <-oneSec:
t.Errorf("unexpected channel read")
case <-oneOhOneSec:
t.Errorf("unexpected channel read")
case <-twoSec:
t.Errorf("unexpected channel read")
default:
}
tc.Step(time.Millisecond)
select {
case <-oneSec:
// Expected!
case <-oneOhOneSec:
t.Errorf("unexpected channel read")
case <-twoSec:
t.Errorf("unexpected channel read")
default:
t.Errorf("unexpected non-channel read")
}
tc.Step(time.Millisecond)
select {
case <-oneSec:
// should not double-trigger!
t.Errorf("unexpected channel read")
case <-oneOhOneSec:
// Expected!
case <-twoSec:
t.Errorf("unexpected channel read")
default:
t.Errorf("unexpected non-channel read")
}
}
func TestFakeTick(t *testing.T) {
tc := NewFakeClock(time.Now())
if tc.HasWaiters() {
t.Errorf("unexpected waiter?")
}
oneSec := tc.Tick(time.Second)
if !tc.HasWaiters() {
t.Errorf("unexpected lack of waiter?")
}
oneOhOneSec := tc.Tick(time.Second + time.Millisecond)
twoSec := tc.Tick(2 * time.Second)
select {
case <-oneSec:
t.Errorf("unexpected channel read")
case <-oneOhOneSec:
t.Errorf("unexpected channel read")
case <-twoSec:
t.Errorf("unexpected channel read")
default:
}
tc.Step(999 * time.Millisecond) // t=.999
select {
case <-oneSec:
t.Errorf("unexpected channel read")
case <-oneOhOneSec:
t.Errorf("unexpected channel read")
case <-twoSec:
t.Errorf("unexpected channel read")
default:
}
tc.Step(time.Millisecond) // t=1.000
select {
case <-oneSec:
// Expected!
case <-oneOhOneSec:
t.Errorf("unexpected channel read")
case <-twoSec:
t.Errorf("unexpected channel read")
default:
t.Errorf("unexpected non-channel read")
}
tc.Step(time.Millisecond) // t=1.001
select {
case <-oneSec:
// should not double-trigger!
t.Errorf("unexpected channel read")
case <-oneOhOneSec:
// Expected!
case <-twoSec:
t.Errorf("unexpected channel read")
default:
t.Errorf("unexpected non-channel read")
}
tc.Step(time.Second) // t=2.001
tc.Step(time.Second) // t=3.001
tc.Step(time.Second) // t=4.001
tc.Step(time.Second) // t=5.001
// The one second ticker should not accumulate ticks
accumulatedTicks := 0
drained := false
for !drained {
select {
case <-oneSec:
accumulatedTicks++
default:
drained = true
}
}
if accumulatedTicks != 1 {
t.Errorf("unexpected number of accumulated ticks: %d", accumulatedTicks)
}
}

View file

@ -1,36 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["diff_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["diff.go"],
importpath = "k8s.io/apimachinery/pkg/util/diff",
deps = [
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,96 +0,0 @@
/*
Copyright 2016 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 diff
import (
"testing"
)
func TestObjectReflectDiff(t *testing.T) {
type struct1 struct{ A []int }
testCases := map[string]struct {
a, b interface{}
out string
}{
"map": {
a: map[string]int{},
b: map[string]int{},
},
"detect nil map": {
a: map[string]int(nil),
b: map[string]int{},
out: `
object:
a: map[string]int(nil)
b: map[string]int{}`,
},
"detect map changes": {
a: map[string]int{"test": 1, "other": 2},
b: map[string]int{"test": 2, "third": 3},
out: `
object[other]:
a: 2
b: <nil>
object[test]:
a: 1
b: 2
object[third]:
a: <nil>
b: 3`,
},
"nil slice": {a: struct1{A: nil}, b: struct1{A: nil}},
"empty slice": {a: struct1{A: []int{}}, b: struct1{A: []int{}}},
"detect slice changes 1": {a: struct1{A: []int{1}}, b: struct1{A: []int{2}}, out: `
object.A[0]:
a: 1
b: 2`,
},
"detect slice changes 2": {a: struct1{A: []int{}}, b: struct1{A: []int{2}}, out: `
object.A[0]:
a: <nil>
b: 2`,
},
"detect slice changes 3": {a: struct1{A: []int{1}}, b: struct1{A: []int{}}, out: `
object.A[0]:
a: 1
b: <nil>`,
},
"detect nil vs empty slices": {a: struct1{A: nil}, b: struct1{A: []int{}}, out: `
object.A:
a: []int(nil)
b: []int{}`,
},
}
for name, test := range testCases {
expect := test.out
if len(expect) == 0 {
expect = "<no diffs>"
}
if actual := ObjectReflectDiff(test.a, test.b); actual != expect {
t.Errorf("%s: unexpected output: %s", name, actual)
}
}
}
func TestStringDiff(t *testing.T) {
diff := StringDiff("aaabb", "aaacc")
expect := "aaa\n\nA: bb\n\nB: cc\n\n"
if diff != expect {
t.Errorf("diff returned %v", diff)
}
}

View file

@ -1,35 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["errors_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"errors.go",
],
importpath = "k8s.io/apimachinery/pkg/util/errors",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,368 +0,0 @@
/*
Copyright 2015 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 errors
import (
"fmt"
"reflect"
"sort"
"testing"
)
func TestEmptyAggregate(t *testing.T) {
var slice []error
var agg Aggregate
var err error
agg = NewAggregate(slice)
if agg != nil {
t.Errorf("expected nil, got %#v", agg)
}
err = NewAggregate(slice)
if err != nil {
t.Errorf("expected nil, got %#v", err)
}
// This is not normally possible, but pedantry demands I test it.
agg = aggregate(slice) // empty aggregate
if s := agg.Error(); s != "" {
t.Errorf("expected empty string, got %q", s)
}
if s := agg.Errors(); len(s) != 0 {
t.Errorf("expected empty slice, got %#v", s)
}
err = agg.(error)
if s := err.Error(); s != "" {
t.Errorf("expected empty string, got %q", s)
}
}
func TestAggregateWithNil(t *testing.T) {
var slice []error
slice = []error{nil}
var agg Aggregate
var err error
agg = NewAggregate(slice)
if agg != nil {
t.Errorf("expected nil, got %#v", agg)
}
err = NewAggregate(slice)
if err != nil {
t.Errorf("expected nil, got %#v", err)
}
// Append a non-nil error
slice = append(slice, fmt.Errorf("err"))
agg = NewAggregate(slice)
if agg == nil {
t.Errorf("expected non-nil")
}
if s := agg.Error(); s != "err" {
t.Errorf("expected 'err', got %q", s)
}
if s := agg.Errors(); len(s) != 1 {
t.Errorf("expected one-element slice, got %#v", s)
}
if s := agg.Errors()[0].Error(); s != "err" {
t.Errorf("expected 'err', got %q", s)
}
err = agg.(error)
if err == nil {
t.Errorf("expected non-nil")
}
if s := err.Error(); s != "err" {
t.Errorf("expected 'err', got %q", s)
}
}
func TestSingularAggregate(t *testing.T) {
var slice []error = []error{fmt.Errorf("err")}
var agg Aggregate
var err error
agg = NewAggregate(slice)
if agg == nil {
t.Errorf("expected non-nil")
}
if s := agg.Error(); s != "err" {
t.Errorf("expected 'err', got %q", s)
}
if s := agg.Errors(); len(s) != 1 {
t.Errorf("expected one-element slice, got %#v", s)
}
if s := agg.Errors()[0].Error(); s != "err" {
t.Errorf("expected 'err', got %q", s)
}
err = agg.(error)
if err == nil {
t.Errorf("expected non-nil")
}
if s := err.Error(); s != "err" {
t.Errorf("expected 'err', got %q", s)
}
}
func TestPluralAggregate(t *testing.T) {
var slice []error = []error{fmt.Errorf("abc"), fmt.Errorf("123")}
var agg Aggregate
var err error
agg = NewAggregate(slice)
if agg == nil {
t.Errorf("expected non-nil")
}
if s := agg.Error(); s != "[abc, 123]" {
t.Errorf("expected '[abc, 123]', got %q", s)
}
if s := agg.Errors(); len(s) != 2 {
t.Errorf("expected two-elements slice, got %#v", s)
}
if s := agg.Errors()[0].Error(); s != "abc" {
t.Errorf("expected '[abc, 123]', got %q", s)
}
err = agg.(error)
if err == nil {
t.Errorf("expected non-nil")
}
if s := err.Error(); s != "[abc, 123]" {
t.Errorf("expected '[abc, 123]', got %q", s)
}
}
func TestFilterOut(t *testing.T) {
testCases := []struct {
err error
filter []Matcher
expected error
}{
{
nil,
[]Matcher{},
nil,
},
{
aggregate{},
[]Matcher{},
nil,
},
{
aggregate{fmt.Errorf("abc")},
[]Matcher{},
aggregate{fmt.Errorf("abc")},
},
{
aggregate{fmt.Errorf("abc")},
[]Matcher{func(err error) bool { return false }},
aggregate{fmt.Errorf("abc")},
},
{
aggregate{fmt.Errorf("abc")},
[]Matcher{func(err error) bool { return true }},
nil,
},
{
aggregate{fmt.Errorf("abc")},
[]Matcher{func(err error) bool { return false }, func(err error) bool { return false }},
aggregate{fmt.Errorf("abc")},
},
{
aggregate{fmt.Errorf("abc")},
[]Matcher{func(err error) bool { return false }, func(err error) bool { return true }},
nil,
},
{
aggregate{fmt.Errorf("abc"), fmt.Errorf("def"), fmt.Errorf("ghi")},
[]Matcher{func(err error) bool { return err.Error() == "def" }},
aggregate{fmt.Errorf("abc"), fmt.Errorf("ghi")},
},
{
aggregate{aggregate{fmt.Errorf("abc")}},
[]Matcher{},
aggregate{aggregate{fmt.Errorf("abc")}},
},
{
aggregate{aggregate{fmt.Errorf("abc"), aggregate{fmt.Errorf("def")}}},
[]Matcher{},
aggregate{aggregate{fmt.Errorf("abc"), aggregate{fmt.Errorf("def")}}},
},
{
aggregate{aggregate{fmt.Errorf("abc"), aggregate{fmt.Errorf("def")}}},
[]Matcher{func(err error) bool { return err.Error() == "def" }},
aggregate{aggregate{fmt.Errorf("abc")}},
},
}
for i, testCase := range testCases {
err := FilterOut(testCase.err, testCase.filter...)
if !reflect.DeepEqual(testCase.expected, err) {
t.Errorf("%d: expected %v, got %v", i, testCase.expected, err)
}
}
}
func TestFlatten(t *testing.T) {
testCases := []struct {
agg Aggregate
expected Aggregate
}{
{
nil,
nil,
},
{
aggregate{},
nil,
},
{
aggregate{fmt.Errorf("abc")},
aggregate{fmt.Errorf("abc")},
},
{
aggregate{fmt.Errorf("abc"), fmt.Errorf("def"), fmt.Errorf("ghi")},
aggregate{fmt.Errorf("abc"), fmt.Errorf("def"), fmt.Errorf("ghi")},
},
{
aggregate{aggregate{fmt.Errorf("abc")}},
aggregate{fmt.Errorf("abc")},
},
{
aggregate{aggregate{aggregate{fmt.Errorf("abc")}}},
aggregate{fmt.Errorf("abc")},
},
{
aggregate{aggregate{fmt.Errorf("abc"), aggregate{fmt.Errorf("def")}}},
aggregate{fmt.Errorf("abc"), fmt.Errorf("def")},
},
{
aggregate{aggregate{aggregate{fmt.Errorf("abc")}, fmt.Errorf("def"), aggregate{fmt.Errorf("ghi")}}},
aggregate{fmt.Errorf("abc"), fmt.Errorf("def"), fmt.Errorf("ghi")},
},
}
for i, testCase := range testCases {
agg := Flatten(testCase.agg)
if !reflect.DeepEqual(testCase.expected, agg) {
t.Errorf("%d: expected %v, got %v", i, testCase.expected, agg)
}
}
}
func TestCreateAggregateFromMessageCountMap(t *testing.T) {
testCases := []struct {
name string
mcm MessageCountMap
expected Aggregate
}{
{
"input has single instance of one message",
MessageCountMap{"abc": 1},
aggregate{fmt.Errorf("abc")},
},
{
"input has multiple messages",
MessageCountMap{"abc": 2, "ghi": 1},
aggregate{fmt.Errorf("abc (repeated 2 times)"), fmt.Errorf("ghi")},
},
{
"input has multiple messages",
MessageCountMap{"ghi": 1, "abc": 2},
aggregate{fmt.Errorf("abc (repeated 2 times)"), fmt.Errorf("ghi")},
},
}
var expected, agg []error
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
if testCase.expected != nil {
expected = testCase.expected.Errors()
sort.Slice(expected, func(i, j int) bool { return expected[i].Error() < expected[j].Error() })
}
if testCase.mcm != nil {
agg = CreateAggregateFromMessageCountMap(testCase.mcm).Errors()
sort.Slice(agg, func(i, j int) bool { return agg[i].Error() < agg[j].Error() })
}
if !reflect.DeepEqual(expected, agg) {
t.Errorf("expected %v, got %v", expected, agg)
}
})
}
}
func TestAggregateGoroutines(t *testing.T) {
testCases := []struct {
errs []error
expected map[string]bool // can't compare directly to Aggregate due to non-deterministic ordering
}{
{
[]error{},
nil,
},
{
[]error{nil},
nil,
},
{
[]error{nil, nil},
nil,
},
{
[]error{fmt.Errorf("1")},
map[string]bool{"1": true},
},
{
[]error{fmt.Errorf("1"), nil},
map[string]bool{"1": true},
},
{
[]error{fmt.Errorf("1"), fmt.Errorf("267")},
map[string]bool{"1": true, "267": true},
},
{
[]error{fmt.Errorf("1"), nil, fmt.Errorf("1234")},
map[string]bool{"1": true, "1234": true},
},
{
[]error{nil, fmt.Errorf("1"), nil, fmt.Errorf("1234"), fmt.Errorf("22")},
map[string]bool{"1": true, "1234": true, "22": true},
},
}
for i, testCase := range testCases {
funcs := make([]func() error, len(testCase.errs))
for i := range testCase.errs {
err := testCase.errs[i]
funcs[i] = func() error { return err }
}
agg := AggregateGoroutines(funcs...)
if agg == nil {
if len(testCase.expected) > 0 {
t.Errorf("%d: expected %v, got nil", i, testCase.expected)
}
continue
}
if len(agg.Errors()) != len(testCase.expected) {
t.Errorf("%d: expected %d errors in aggregate, got %v", i, len(testCase.expected), agg)
continue
}
for _, err := range agg.Errors() {
if !testCase.expected[err.Error()] {
t.Errorf("%d: expected %v, got aggregate containing %v", i, testCase.expected, err)
}
}
}
}

View file

@ -1,32 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["framer_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["framer.go"],
importpath = "k8s.io/apimachinery/pkg/util/framer",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,176 +0,0 @@
/*
Copyright 2016 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 framer
import (
"bytes"
"io"
"io/ioutil"
"testing"
)
func TestRead(t *testing.T) {
data := []byte{
0x00, 0x00, 0x00, 0x04,
0x01, 0x02, 0x03, 0x04,
0x00, 0x00, 0x00, 0x03,
0x05, 0x06, 0x07,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x08,
}
b := bytes.NewBuffer(data)
r := NewLengthDelimitedFrameReader(ioutil.NopCloser(b))
buf := make([]byte, 1)
if n, err := r.Read(buf); err != io.ErrShortBuffer && n != 1 && bytes.Equal(buf, []byte{0x01}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
if n, err := r.Read(buf); err != io.ErrShortBuffer && n != 1 && bytes.Equal(buf, []byte{0x02}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
// read the remaining frame
buf = make([]byte, 2)
if n, err := r.Read(buf); err != nil && n != 2 && bytes.Equal(buf, []byte{0x03, 0x04}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
// read with buffer equal to frame
buf = make([]byte, 3)
if n, err := r.Read(buf); err != nil && n != 3 && bytes.Equal(buf, []byte{0x05, 0x06, 0x07}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
// read empty frame
buf = make([]byte, 3)
if n, err := r.Read(buf); err != nil && n != 0 && bytes.Equal(buf, []byte{}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
// read with larger buffer than frame
buf = make([]byte, 3)
if n, err := r.Read(buf); err != nil && n != 1 && bytes.Equal(buf, []byte{0x08}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
// read EOF
if n, err := r.Read(buf); err != io.EOF && n != 0 {
t.Fatalf("unexpected: %v %d", err, n)
}
}
func TestReadLarge(t *testing.T) {
data := []byte{
0x00, 0x00, 0x00, 0x04,
0x01, 0x02, 0x03, 0x04,
0x00, 0x00, 0x00, 0x03,
0x05, 0x06, 0x07,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x08,
}
b := bytes.NewBuffer(data)
r := NewLengthDelimitedFrameReader(ioutil.NopCloser(b))
buf := make([]byte, 40)
if n, err := r.Read(buf); err != nil && n != 4 && bytes.Equal(buf, []byte{0x01, 0x02, 0x03, 0x04}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
if n, err := r.Read(buf); err != nil && n != 3 && bytes.Equal(buf, []byte{0x05, 0x06, 0x7}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
if n, err := r.Read(buf); err != nil && n != 0 && bytes.Equal(buf, []byte{}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
if n, err := r.Read(buf); err != nil && n != 1 && bytes.Equal(buf, []byte{0x08}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
// read EOF
if n, err := r.Read(buf); err != io.EOF && n != 0 {
t.Fatalf("unexpected: %v %d", err, n)
}
}
func TestReadInvalidFrame(t *testing.T) {
data := []byte{
0x00, 0x00, 0x00, 0x04,
0x01, 0x02,
}
b := bytes.NewBuffer(data)
r := NewLengthDelimitedFrameReader(ioutil.NopCloser(b))
buf := make([]byte, 1)
if n, err := r.Read(buf); err != io.ErrShortBuffer && n != 1 && bytes.Equal(buf, []byte{0x01}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
// read the remaining frame
buf = make([]byte, 3)
if n, err := r.Read(buf); err != io.ErrUnexpectedEOF && n != 1 && bytes.Equal(buf, []byte{0x02}) {
t.Fatalf("unexpected: %v %d %v", err, n, buf)
}
// read EOF
if n, err := r.Read(buf); err != io.EOF && n != 0 {
t.Fatalf("unexpected: %v %d", err, n)
}
}
func TestJSONFrameReader(t *testing.T) {
b := bytes.NewBufferString("{\"test\":true}\n1\n[\"a\"]")
r := NewJSONFramedReader(ioutil.NopCloser(b))
buf := make([]byte, 20)
if n, err := r.Read(buf); err != nil || n != 13 || string(buf[:n]) != `{"test":true}` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != nil || n != 1 || string(buf[:n]) != `1` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != nil || n != 5 || string(buf[:n]) != `["a"]` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != io.EOF || n != 0 {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
}
func TestJSONFrameReaderShortBuffer(t *testing.T) {
b := bytes.NewBufferString("{\"test\":true}\n1\n[\"a\"]")
r := NewJSONFramedReader(ioutil.NopCloser(b))
buf := make([]byte, 3)
if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `{"t` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `est` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `":t` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `rue` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != nil || n != 1 || string(buf[:n]) != `}` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != nil || n != 1 || string(buf[:n]) != `1` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `["a` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != nil || n != 2 || string(buf[:n]) != `"]` {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
if n, err := r.Read(buf); err != io.EOF || n != 0 {
t.Fatalf("unexpected: %v %d %q", err, n, buf)
}
}

View file

@ -1,38 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["httpstream_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"httpstream.go",
],
importpath = "k8s.io/apimachinery/pkg/util/httpstream",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/util/httpstream/spdy:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,125 +0,0 @@
/*
Copyright 2015 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 httpstream
import (
"net/http"
"reflect"
"testing"
)
type responseWriter struct {
header http.Header
statusCode *int
}
func newResponseWriter() *responseWriter {
return &responseWriter{
header: make(http.Header),
}
}
func (r *responseWriter) Header() http.Header {
return r.header
}
func (r *responseWriter) WriteHeader(code int) {
r.statusCode = &code
}
func (r *responseWriter) Write([]byte) (int, error) {
return 0, nil
}
func TestHandshake(t *testing.T) {
tests := map[string]struct {
clientProtocols []string
serverProtocols []string
expectedProtocol string
expectError bool
}{
"no client protocols": {
clientProtocols: []string{},
serverProtocols: []string{"a", "b"},
expectedProtocol: "",
},
"no common protocol": {
clientProtocols: []string{"c"},
serverProtocols: []string{"a", "b"},
expectedProtocol: "",
expectError: true,
},
"common protocol": {
clientProtocols: []string{"b"},
serverProtocols: []string{"a", "b"},
expectedProtocol: "b",
},
}
for name, test := range tests {
req, err := http.NewRequest("GET", "http://www.example.com/", nil)
if err != nil {
t.Fatalf("%s: error creating request: %v", name, err)
}
for _, p := range test.clientProtocols {
req.Header.Add(HeaderProtocolVersion, p)
}
w := newResponseWriter()
negotiated, err := Handshake(req, w, test.serverProtocols)
// verify negotiated protocol
if e, a := test.expectedProtocol, negotiated; e != a {
t.Errorf("%s: protocol: expected %q, got %q", name, e, a)
}
if test.expectError {
if err == nil {
t.Errorf("%s: expected error but did not get one", name)
}
if w.statusCode == nil {
t.Errorf("%s: expected w.statusCode to be set", name)
} else if e, a := http.StatusForbidden, *w.statusCode; e != a {
t.Errorf("%s: w.statusCode: expected %d, got %d", name, e, a)
}
if e, a := test.serverProtocols, w.Header()[HeaderAcceptedProtocolVersions]; !reflect.DeepEqual(e, a) {
t.Errorf("%s: accepted server protocols: expected %v, got %v", name, e, a)
}
continue
}
if !test.expectError && err != nil {
t.Errorf("%s: unexpected error: %v", name, err)
continue
}
if w.statusCode != nil {
t.Errorf("%s: unexpected non-nil w.statusCode: %d", name, w.statusCode)
}
if len(test.expectedProtocol) == 0 {
if len(w.Header()[HeaderProtocolVersion]) > 0 {
t.Errorf("%s: unexpected protocol version response header: %s", name, w.Header()[HeaderProtocolVersion])
}
continue
}
// verify response headers
if e, a := []string{test.expectedProtocol}, w.Header()[HeaderProtocolVersion]; !reflect.DeepEqual(e, a) {
t.Errorf("%s: protocol response header: expected %v, got %v", name, e, a)
}
}
}

View file

@ -1,56 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"connection_test.go",
"roundtripper_test.go",
"upgrade_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/elazarl/goproxy:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"connection.go",
"roundtripper.go",
"upgrade.go",
],
importpath = "k8s.io/apimachinery/pkg/util/httpstream/spdy",
deps = [
"//vendor/github.com/docker/spdystream:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/third_party/forked/golang/netutil:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,164 +0,0 @@
/*
Copyright 2016 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 spdy
import (
"io"
"net"
"net/http"
"sync"
"testing"
"time"
"k8s.io/apimachinery/pkg/util/httpstream"
)
func runProxy(t *testing.T, backendUrl string, proxyUrl chan<- string, proxyDone chan<- struct{}) {
listener, err := net.Listen("tcp4", "localhost:0")
if err != nil {
t.Fatalf("error listening: %v", err)
}
defer listener.Close()
proxyUrl <- listener.Addr().String()
clientConn, err := listener.Accept()
if err != nil {
t.Errorf("proxy: error accepting client connection: %v", err)
return
}
backendConn, err := net.Dial("tcp4", backendUrl)
if err != nil {
t.Errorf("proxy: error dialing backend: %v", err)
return
}
defer backendConn.Close()
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
io.Copy(backendConn, clientConn)
}()
go func() {
defer wg.Done()
io.Copy(clientConn, backendConn)
}()
wg.Wait()
proxyDone <- struct{}{}
}
func runServer(t *testing.T, backendUrl chan<- string, serverDone chan<- struct{}) {
listener, err := net.Listen("tcp4", "localhost:0")
if err != nil {
t.Fatalf("server: error listening: %v", err)
}
defer listener.Close()
backendUrl <- listener.Addr().String()
conn, err := listener.Accept()
if err != nil {
t.Errorf("server: error accepting connection: %v", err)
return
}
streamChan := make(chan httpstream.Stream)
replySentChan := make(chan (<-chan struct{}))
spdyConn, err := NewServerConnection(conn, func(stream httpstream.Stream, replySent <-chan struct{}) error {
streamChan <- stream
replySentChan <- replySent
return nil
})
if err != nil {
t.Errorf("server: error creating spdy connection: %v", err)
return
}
stream := <-streamChan
replySent := <-replySentChan
<-replySent
buf := make([]byte, 1)
_, err = stream.Read(buf)
if err != io.EOF {
t.Errorf("server: unexpected read error: %v", err)
return
}
<-spdyConn.CloseChan()
raw := spdyConn.(*connection).conn
if err := raw.Wait(15 * time.Second); err != nil {
t.Errorf("server: timed out waiting for connection closure: %v", err)
}
serverDone <- struct{}{}
}
func TestConnectionCloseIsImmediateThroughAProxy(t *testing.T) {
serverDone := make(chan struct{})
backendUrlChan := make(chan string)
go runServer(t, backendUrlChan, serverDone)
backendUrl := <-backendUrlChan
proxyDone := make(chan struct{})
proxyUrlChan := make(chan string)
go runProxy(t, backendUrl, proxyUrlChan, proxyDone)
proxyUrl := <-proxyUrlChan
conn, err := net.Dial("tcp4", proxyUrl)
if err != nil {
t.Fatalf("client: error connecting to proxy: %v", err)
}
spdyConn, err := NewClientConnection(conn)
if err != nil {
t.Fatalf("client: error creating spdy connection: %v", err)
}
if _, err := spdyConn.CreateStream(http.Header{}); err != nil {
t.Fatalf("client: error creating stream: %v", err)
}
spdyConn.Close()
raw := spdyConn.(*connection).conn
if err := raw.Wait(15 * time.Second); err != nil {
t.Fatalf("client: timed out waiting for connection closure: %v", err)
}
expired := time.NewTimer(15 * time.Second)
defer expired.Stop()
i := 0
for {
select {
case <-expired.C:
t.Fatalf("timed out waiting for proxy and/or server closure")
case <-serverDone:
i++
case <-proxyDone:
i++
}
if i == 2 {
break
}
}
}

View file

@ -1,529 +0,0 @@
/*
Copyright 2015 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 spdy
import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"sync/atomic"
"testing"
"github.com/elazarl/goproxy"
"k8s.io/apimachinery/pkg/util/httpstream"
)
// be sure to unset environment variable https_proxy (if exported) before testing, otherwise the testing will fail unexpectedly.
func TestRoundTripAndNewConnection(t *testing.T) {
for _, redirect := range []bool{false, true} {
t.Run(fmt.Sprintf("redirect = %t", redirect), func(t *testing.T) {
localhostPool := x509.NewCertPool()
if !localhostPool.AppendCertsFromPEM(localhostCert) {
t.Errorf("error setting up localhostCert pool")
}
httpsServerInvalidHostname := func(h http.Handler) *httptest.Server {
cert, err := tls.X509KeyPair(exampleCert, exampleKey)
if err != nil {
t.Errorf("https (invalid hostname): proxy_test: %v", err)
}
ts := httptest.NewUnstartedServer(h)
ts.TLS = &tls.Config{
Certificates: []tls.Certificate{cert},
}
ts.StartTLS()
return ts
}
httpsServerValidHostname := func(h http.Handler) *httptest.Server {
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
if err != nil {
t.Errorf("https (valid hostname): proxy_test: %v", err)
}
ts := httptest.NewUnstartedServer(h)
ts.TLS = &tls.Config{
Certificates: []tls.Certificate{cert},
}
ts.StartTLS()
return ts
}
testCases := map[string]struct {
serverFunc func(http.Handler) *httptest.Server
proxyServerFunc func(http.Handler) *httptest.Server
proxyAuth *url.Userinfo
clientTLS *tls.Config
serverConnectionHeader string
serverUpgradeHeader string
serverStatusCode int
shouldError bool
}{
"no headers": {
serverFunc: httptest.NewServer,
serverConnectionHeader: "",
serverUpgradeHeader: "",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: true,
},
"no upgrade header": {
serverFunc: httptest.NewServer,
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: true,
},
"no connection header": {
serverFunc: httptest.NewServer,
serverConnectionHeader: "",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: true,
},
"no switching protocol status code": {
serverFunc: httptest.NewServer,
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusForbidden,
shouldError: true,
},
"http": {
serverFunc: httptest.NewServer,
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"https (invalid hostname + InsecureSkipVerify)": {
serverFunc: httpsServerInvalidHostname,
clientTLS: &tls.Config{InsecureSkipVerify: true},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"https (invalid hostname + hostname verification)": {
serverFunc: httpsServerInvalidHostname,
clientTLS: &tls.Config{InsecureSkipVerify: false},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: true,
},
"https (valid hostname + RootCAs)": {
serverFunc: httpsServerValidHostname,
clientTLS: &tls.Config{RootCAs: localhostPool},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"proxied http->http": {
serverFunc: httptest.NewServer,
proxyServerFunc: httptest.NewServer,
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"proxied https (invalid hostname + InsecureSkipVerify) -> http": {
serverFunc: httptest.NewServer,
proxyServerFunc: httpsServerInvalidHostname,
clientTLS: &tls.Config{InsecureSkipVerify: true},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"proxied https with auth (invalid hostname + InsecureSkipVerify) -> http": {
serverFunc: httptest.NewServer,
proxyServerFunc: httpsServerInvalidHostname,
proxyAuth: url.UserPassword("proxyuser", "proxypasswd"),
clientTLS: &tls.Config{InsecureSkipVerify: true},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"proxied https (invalid hostname + hostname verification) -> http": {
serverFunc: httptest.NewServer,
proxyServerFunc: httpsServerInvalidHostname,
clientTLS: &tls.Config{InsecureSkipVerify: false},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: true, // fails because the client doesn't trust the proxy
},
"proxied https (valid hostname + RootCAs) -> http": {
serverFunc: httptest.NewServer,
proxyServerFunc: httpsServerValidHostname,
clientTLS: &tls.Config{RootCAs: localhostPool},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"proxied https with auth (valid hostname + RootCAs) -> http": {
serverFunc: httptest.NewServer,
proxyServerFunc: httpsServerValidHostname,
proxyAuth: url.UserPassword("proxyuser", "proxypasswd"),
clientTLS: &tls.Config{RootCAs: localhostPool},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"proxied https (invalid hostname + InsecureSkipVerify) -> https (invalid hostname)": {
serverFunc: httpsServerInvalidHostname,
proxyServerFunc: httpsServerInvalidHostname,
clientTLS: &tls.Config{InsecureSkipVerify: true},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false, // works because the test proxy ignores TLS errors
},
"proxied https with auth (invalid hostname + InsecureSkipVerify) -> https (invalid hostname)": {
serverFunc: httpsServerInvalidHostname,
proxyServerFunc: httpsServerInvalidHostname,
proxyAuth: url.UserPassword("proxyuser", "proxypasswd"),
clientTLS: &tls.Config{InsecureSkipVerify: true},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false, // works because the test proxy ignores TLS errors
},
"proxied https (invalid hostname + hostname verification) -> https (invalid hostname)": {
serverFunc: httpsServerInvalidHostname,
proxyServerFunc: httpsServerInvalidHostname,
clientTLS: &tls.Config{InsecureSkipVerify: false},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: true, // fails because the client doesn't trust the proxy
},
"proxied https (valid hostname + RootCAs) -> https (valid hostname + RootCAs)": {
serverFunc: httpsServerValidHostname,
proxyServerFunc: httpsServerValidHostname,
clientTLS: &tls.Config{RootCAs: localhostPool},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
"proxied https with auth (valid hostname + RootCAs) -> https (valid hostname + RootCAs)": {
serverFunc: httpsServerValidHostname,
proxyServerFunc: httpsServerValidHostname,
proxyAuth: url.UserPassword("proxyuser", "proxypasswd"),
clientTLS: &tls.Config{RootCAs: localhostPool},
serverConnectionHeader: "Upgrade",
serverUpgradeHeader: "SPDY/3.1",
serverStatusCode: http.StatusSwitchingProtocols,
shouldError: false,
},
}
for k, testCase := range testCases {
server := testCase.serverFunc(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if testCase.shouldError {
if e, a := httpstream.HeaderUpgrade, req.Header.Get(httpstream.HeaderConnection); e != a {
t.Fatalf("%s: Expected connection=upgrade header, got '%s", k, a)
}
w.Header().Set(httpstream.HeaderConnection, testCase.serverConnectionHeader)
w.Header().Set(httpstream.HeaderUpgrade, testCase.serverUpgradeHeader)
w.WriteHeader(testCase.serverStatusCode)
return
}
streamCh := make(chan httpstream.Stream)
responseUpgrader := NewResponseUpgrader()
spdyConn := responseUpgrader.UpgradeResponse(w, req, func(s httpstream.Stream, replySent <-chan struct{}) error {
streamCh <- s
return nil
})
if spdyConn == nil {
t.Fatalf("%s: unexpected nil spdyConn", k)
}
defer spdyConn.Close()
stream := <-streamCh
io.Copy(stream, stream)
}))
defer server.Close()
serverURL, err := url.Parse(server.URL)
if err != nil {
t.Fatalf("%s: Error creating request: %s", k, err)
}
req, err := http.NewRequest("GET", server.URL, nil)
if err != nil {
t.Fatalf("%s: Error creating request: %s", k, err)
}
spdyTransport := NewSpdyRoundTripper(testCase.clientTLS, redirect)
var proxierCalled bool
var proxyCalledWithHost string
var proxyCalledWithAuth bool
var proxyCalledWithAuthHeader string
if testCase.proxyServerFunc != nil {
proxyHandler := goproxy.NewProxyHttpServer()
proxyHandler.OnRequest().HandleConnectFunc(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
proxyCalledWithHost = host
proxyAuthHeaderName := "Proxy-Authorization"
_, proxyCalledWithAuth = ctx.Req.Header[proxyAuthHeaderName]
proxyCalledWithAuthHeader = ctx.Req.Header.Get(proxyAuthHeaderName)
return goproxy.OkConnect, host
})
proxy := testCase.proxyServerFunc(proxyHandler)
spdyTransport.proxier = func(proxierReq *http.Request) (*url.URL, error) {
proxierCalled = true
proxyURL, err := url.Parse(proxy.URL)
if err != nil {
return nil, err
}
proxyURL.User = testCase.proxyAuth
return proxyURL, nil
}
defer proxy.Close()
}
client := &http.Client{Transport: spdyTransport}
resp, err := client.Do(req)
var conn httpstream.Connection
if err == nil {
conn, err = spdyTransport.NewConnection(resp)
}
haveErr := err != nil
if e, a := testCase.shouldError, haveErr; e != a {
t.Fatalf("%s: shouldError=%t, got %t: %v", k, e, a, err)
}
if testCase.shouldError {
continue
}
defer conn.Close()
if resp.StatusCode != http.StatusSwitchingProtocols {
t.Fatalf("%s: expected http 101 switching protocols, got %d", k, resp.StatusCode)
}
stream, err := conn.CreateStream(http.Header{})
if err != nil {
t.Fatalf("%s: error creating client stream: %s", k, err)
}
n, err := stream.Write([]byte("hello"))
if err != nil {
t.Fatalf("%s: error writing to stream: %s", k, err)
}
if n != 5 {
t.Fatalf("%s: Expected to write 5 bytes, but actually wrote %d", k, n)
}
b := make([]byte, 5)
n, err = stream.Read(b)
if err != nil {
t.Fatalf("%s: error reading from stream: %s", k, err)
}
if n != 5 {
t.Fatalf("%s: Expected to read 5 bytes, but actually read %d", k, n)
}
if e, a := "hello", string(b[0:n]); e != a {
t.Fatalf("%s: expected '%s', got '%s'", k, e, a)
}
if testCase.proxyServerFunc != nil {
if !proxierCalled {
t.Fatalf("%s: Expected to use a proxy but proxier in SpdyRoundTripper wasn't called", k)
}
if proxyCalledWithHost != serverURL.Host {
t.Fatalf("%s: Expected to see a call to the proxy for backend %q, got %q", k, serverURL.Host, proxyCalledWithHost)
}
}
var expectedProxyAuth string
if testCase.proxyAuth != nil {
encodedCredentials := base64.StdEncoding.EncodeToString([]byte(testCase.proxyAuth.String()))
expectedProxyAuth = "Basic " + encodedCredentials
}
if len(expectedProxyAuth) == 0 && proxyCalledWithAuth {
t.Fatalf("%s: Proxy authorization unexpected, got %q", k, proxyCalledWithAuthHeader)
}
if proxyCalledWithAuthHeader != expectedProxyAuth {
t.Fatalf("%s: Expected to see a call to the proxy with credentials %q, got %q", k, testCase.proxyAuth, proxyCalledWithAuthHeader)
}
}
})
}
}
func TestRoundTripRedirects(t *testing.T) {
tests := []struct {
redirects int32
expectSuccess bool
}{
{0, true},
{1, true},
{10, true},
{11, false},
}
for _, test := range tests {
t.Run(fmt.Sprintf("with %d redirects", test.redirects), func(t *testing.T) {
var redirects int32 = 0
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if redirects < test.redirects {
redirects = atomic.AddInt32(&redirects, 1)
http.Redirect(w, req, "redirect", http.StatusFound)
return
}
streamCh := make(chan httpstream.Stream)
responseUpgrader := NewResponseUpgrader()
spdyConn := responseUpgrader.UpgradeResponse(w, req, func(s httpstream.Stream, replySent <-chan struct{}) error {
streamCh <- s
return nil
})
if spdyConn == nil {
t.Fatalf("unexpected nil spdyConn")
}
defer spdyConn.Close()
stream := <-streamCh
io.Copy(stream, stream)
}))
defer server.Close()
req, err := http.NewRequest("GET", server.URL, nil)
if err != nil {
t.Fatalf("Error creating request: %s", err)
}
spdyTransport := NewSpdyRoundTripper(nil, true)
client := &http.Client{Transport: spdyTransport}
resp, err := client.Do(req)
if test.expectSuccess {
if err != nil {
t.Fatalf("error calling Do: %v", err)
}
} else {
if err == nil {
t.Fatalf("expecting an error")
} else if !strings.Contains(err.Error(), "too many redirects") {
t.Fatalf("expecting too many redirects, got %v", err)
}
return
}
conn, err := spdyTransport.NewConnection(resp)
if err != nil {
t.Fatalf("error calling NewConnection: %v", err)
}
defer conn.Close()
if resp.StatusCode != http.StatusSwitchingProtocols {
t.Fatalf("expected http 101 switching protocols, got %d", resp.StatusCode)
}
stream, err := conn.CreateStream(http.Header{})
if err != nil {
t.Fatalf("error creating client stream: %s", err)
}
n, err := stream.Write([]byte("hello"))
if err != nil {
t.Fatalf("error writing to stream: %s", err)
}
if n != 5 {
t.Fatalf("Expected to write 5 bytes, but actually wrote %d", n)
}
b := make([]byte, 5)
n, err = stream.Read(b)
if err != nil {
t.Fatalf("error reading from stream: %s", err)
}
if n != 5 {
t.Fatalf("Expected to read 5 bytes, but actually read %d", n)
}
if e, a := "hello", string(b[0:n]); e != a {
t.Fatalf("expected '%s', got '%s'", e, a)
}
})
}
}
// exampleCert was generated from crypto/tls/generate_cert.go with the following command:
// go run generate_cert.go --rsa-bits 512 --host example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var exampleCert = []byte(`-----BEGIN CERTIFICATE-----
MIIBdzCCASGgAwIBAgIRAOVTAdPnfbS5V85mfS90TfIwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2
MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
QQCoVSqeu8TBvF+70T7Jm4340YQNhds6IxjRoifenYodAO1dnKGrcbF266DJGunh
nIjQH7B12tduhl0fLK4Ezf7/AgMBAAGjUDBOMA4GA1UdDwEB/wQEAwICpDATBgNV
HSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBYGA1UdEQQPMA2CC2V4
YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA0EAk1kVa5uZ/AzwYDVcS9bpM/czwjjV
xq3VeSCfmNa2uNjbFvodmCRwZOHUvipAMGCUCV6j5vMrJ8eMj8tCQ36W9A==
-----END CERTIFICATE-----`)
var exampleKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAKhVKp67xMG8X7vRPsmbjfjRhA2F2zojGNGiJ96dih0A7V2coatx
sXbroMka6eGciNAfsHXa126GXR8srgTN/v8CAwEAAQJASdzdD7vKsUwMIejGCUb1
fAnLTPfAY3lFCa+CmR89nE22dAoRDv+5RbnBsZ58BazPNJHrsVPRlfXB3OQmSQr0
SQIhANoJhs+xOJE/i8nJv0uAbzKyiD1YkvRkta0GpUOULyAVAiEAxaQus3E/SuqD
P7y5NeJnE7X6XkyC35zrsJRkz7orE8MCIHdDjsI8pjyNDeGqwUCDWE/a6DrmIDwe
emHSqMN2YvChAiEAnxLCM9NWaenOsaIoP+J1rDuvw+4499nJKVqGuVrSCRkCIEqK
4KSchPMc3x8M/uhw9oWTtKFmjA/PPh0FsWCdKrEy
-----END RSA PRIVATE KEY-----`)
// localhostCert was generated from crypto/tls/generate_cert.go with the following command:
// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
MIIBjzCCATmgAwIBAgIRAKpi2WmTcFrVjxrl5n5YDUEwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2
MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
QQC9fEbRszP3t14Gr4oahV7zFObBI4TfA5i7YnlMXeLinb7MnvT4bkfOJzE6zktn
59zP7UiHs3l4YOuqrjiwM413AgMBAAGjaDBmMA4GA1UdDwEB/wQEAwICpDATBgNV
HSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MC4GA1UdEQQnMCWCC2V4
YW1wbGUuY29thwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUA
A0EAUsVE6KMnza/ZbodLlyeMzdo7EM/5nb5ywyOxgIOCf0OOLHsPS9ueGLQX9HEG
//yjTXuhNcUugExIjM/AIwAZPQ==
-----END CERTIFICATE-----`)
// localhostKey is the private key for localhostCert.
var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBAL18RtGzM/e3XgavihqFXvMU5sEjhN8DmLtieUxd4uKdvsye9Phu
R84nMTrOS2fn3M/tSIezeXhg66quOLAzjXcCAwEAAQJBAKcRxH9wuglYLBdI/0OT
BLzfWPZCEw1vZmMR2FF1Fm8nkNOVDPleeVGTWoOEcYYlQbpTmkGSxJ6ya+hqRi6x
goECIQDx3+X49fwpL6B5qpJIJMyZBSCuMhH4B7JevhGGFENi3wIhAMiNJN5Q3UkL
IuSvv03kaPR5XVQ99/UeEetUgGvBcABpAiBJSBzVITIVCGkGc7d+RCf49KTCIklv
bGWObufAR8Ni4QIgWpILjW8dkGg8GOUZ0zaNA6Nvt6TIv2UWGJ4v5PoV98kCIQDx
rIiZs5QbKdycsv9gQJzwQAogC8o04X3Zz3dsoX+h4A==
-----END RSA PRIVATE KEY-----`)

View file

@ -1,93 +0,0 @@
/*
Copyright 2015 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 spdy
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestUpgradeResponse(t *testing.T) {
testCases := []struct {
connectionHeader string
upgradeHeader string
shouldError bool
}{
{
connectionHeader: "",
upgradeHeader: "",
shouldError: true,
},
{
connectionHeader: "Upgrade",
upgradeHeader: "",
shouldError: true,
},
{
connectionHeader: "",
upgradeHeader: "SPDY/3.1",
shouldError: true,
},
{
connectionHeader: "Upgrade",
upgradeHeader: "SPDY/3.1",
shouldError: false,
},
}
for i, testCase := range testCases {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
upgrader := NewResponseUpgrader()
conn := upgrader.UpgradeResponse(w, req, nil)
haveErr := conn == nil
if e, a := testCase.shouldError, haveErr; e != a {
t.Fatalf("%d: expected shouldErr=%t, got %t", i, testCase.shouldError, haveErr)
}
if haveErr {
return
}
if conn == nil {
t.Fatalf("%d: unexpected nil conn", i)
}
defer conn.Close()
}))
defer server.Close()
req, err := http.NewRequest("GET", server.URL, nil)
if err != nil {
t.Fatalf("%d: error creating request: %s", i, err)
}
req.Header.Set("Connection", testCase.connectionHeader)
req.Header.Set("Upgrade", testCase.upgradeHeader)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
t.Fatalf("%d: unexpected non-nil err from client.Do: %s", i, err)
}
if testCase.shouldError {
continue
}
if resp.StatusCode != http.StatusSwitchingProtocols {
t.Fatalf("%d: expected status 101 switching protocols, got %d", i, resp.StatusCode)
}
}
}

View file

@ -1,47 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["intstr_test.go"],
embed = [":go_default_library"],
deps = ["//vendor/github.com/ghodss/yaml:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"generated.pb.go",
"intstr.go",
],
importpath = "k8s.io/apimachinery/pkg/util/intstr",
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)

View file

@ -1,176 +0,0 @@
/*
Copyright 2014 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 intstr
import (
"encoding/json"
"reflect"
"testing"
"github.com/ghodss/yaml"
)
func TestFromInt(t *testing.T) {
i := FromInt(93)
if i.Type != Int || i.IntVal != 93 {
t.Errorf("Expected IntVal=93, got %+v", i)
}
}
func TestFromString(t *testing.T) {
i := FromString("76")
if i.Type != String || i.StrVal != "76" {
t.Errorf("Expected StrVal=\"76\", got %+v", i)
}
}
type IntOrStringHolder struct {
IOrS IntOrString `json:"val"`
}
func TestIntOrStringUnmarshalJSON(t *testing.T) {
cases := []struct {
input string
result IntOrString
}{
{"{\"val\": 123}", FromInt(123)},
{"{\"val\": \"123\"}", FromString("123")},
}
for _, c := range cases {
var result IntOrStringHolder
if err := json.Unmarshal([]byte(c.input), &result); err != nil {
t.Errorf("Failed to unmarshal input '%v': %v", c.input, err)
}
if result.IOrS != c.result {
t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result)
}
}
}
func TestIntOrStringMarshalJSON(t *testing.T) {
cases := []struct {
input IntOrString
result string
}{
{FromInt(123), "{\"val\":123}"},
{FromString("123"), "{\"val\":\"123\"}"},
}
for _, c := range cases {
input := IntOrStringHolder{c.input}
result, err := json.Marshal(&input)
if err != nil {
t.Errorf("Failed to marshal input '%v': %v", input, err)
}
if string(result) != c.result {
t.Errorf("Failed to marshal input '%v': expected: %+v, got %q", input, c.result, string(result))
}
}
}
func TestIntOrStringMarshalJSONUnmarshalYAML(t *testing.T) {
cases := []struct {
input IntOrString
}{
{FromInt(123)},
{FromString("123")},
}
for _, c := range cases {
input := IntOrStringHolder{c.input}
jsonMarshalled, err := json.Marshal(&input)
if err != nil {
t.Errorf("1: Failed to marshal input: '%v': %v", input, err)
}
var result IntOrStringHolder
err = yaml.Unmarshal(jsonMarshalled, &result)
if err != nil {
t.Errorf("2: Failed to unmarshal '%+v': %v", string(jsonMarshalled), err)
}
if !reflect.DeepEqual(input, result) {
t.Errorf("3: Failed to marshal input '%+v': got %+v", input, result)
}
}
}
func TestGetValueFromIntOrPercent(t *testing.T) {
tests := []struct {
input IntOrString
total int
roundUp bool
expectErr bool
expectVal int
}{
{
input: FromInt(123),
expectErr: false,
expectVal: 123,
},
{
input: FromString("90%"),
total: 100,
roundUp: true,
expectErr: false,
expectVal: 90,
},
{
input: FromString("90%"),
total: 95,
roundUp: true,
expectErr: false,
expectVal: 86,
},
{
input: FromString("90%"),
total: 95,
roundUp: false,
expectErr: false,
expectVal: 85,
},
{
input: FromString("%"),
expectErr: true,
},
{
input: FromString("90#"),
expectErr: true,
},
{
input: FromString("#%"),
expectErr: true,
},
}
for i, test := range tests {
t.Logf("test case %d", i)
value, err := GetValueFromIntOrPercent(&test.input, test.total, test.roundUp)
if test.expectErr && err == nil {
t.Errorf("expected error, but got none")
continue
}
if !test.expectErr && err != nil {
t.Errorf("unexpected err: %v", err)
continue
}
if test.expectVal != value {
t.Errorf("expected %v, but got %v", test.expectVal, value)
}
}
}

View file

@ -1,32 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["json.go"],
importpath = "k8s.io/apimachinery/pkg/util/json",
)
go_test(
name = "go_default_test",
srcs = ["json_test.go"],
embed = [":go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,319 +0,0 @@
// +build go1.8
/*
Copyright 2015 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 json
import (
"fmt"
"math"
"reflect"
"strconv"
"strings"
"testing"
)
func TestEvaluateTypes(t *testing.T) {
testCases := []struct {
In string
Data interface{}
Out string
Err bool
}{
// Invalid syntaxes
{
In: `x`,
Err: true,
},
{
In: ``,
Err: true,
},
// Null
{
In: `null`,
Data: nil,
Out: `null`,
},
// Booleans
{
In: `true`,
Data: true,
Out: `true`,
},
{
In: `false`,
Data: false,
Out: `false`,
},
// Integers
{
In: `0`,
Data: int64(0),
Out: `0`,
},
{
In: `-0`,
Data: int64(-0),
Out: `0`,
},
{
In: `1`,
Data: int64(1),
Out: `1`,
},
{
In: `2147483647`,
Data: int64(math.MaxInt32),
Out: `2147483647`,
},
{
In: `-2147483648`,
Data: int64(math.MinInt32),
Out: `-2147483648`,
},
{
In: `9223372036854775807`,
Data: int64(math.MaxInt64),
Out: `9223372036854775807`,
},
{
In: `-9223372036854775808`,
Data: int64(math.MinInt64),
Out: `-9223372036854775808`,
},
// Int overflow
{
In: `9223372036854775808`, // MaxInt64 + 1
Data: float64(9223372036854775808),
Out: `9223372036854776000`,
},
{
In: `-9223372036854775809`, // MinInt64 - 1
Data: float64(math.MinInt64),
Out: `-9223372036854776000`,
},
// Floats
{
In: `0.0`,
Data: float64(0),
Out: `0`,
},
{
In: `-0.0`,
Data: float64(-0.0),
Out: `-0`,
},
{
In: `0.5`,
Data: float64(0.5),
Out: `0.5`,
},
{
In: `1e3`,
Data: float64(1e3),
Out: `1000`,
},
{
In: `1.5`,
Data: float64(1.5),
Out: `1.5`,
},
{
In: `-0.3`,
Data: float64(-.3),
Out: `-0.3`,
},
{
// Largest representable float32
In: `3.40282346638528859811704183484516925440e+38`,
Data: float64(math.MaxFloat32),
Out: strconv.FormatFloat(math.MaxFloat32, 'g', -1, 64),
},
{
// Smallest float32 without losing precision
In: `1.175494351e-38`,
Data: float64(1.175494351e-38),
Out: `1.175494351e-38`,
},
{
// float32 closest to zero
In: `1.401298464324817070923729583289916131280e-45`,
Data: float64(math.SmallestNonzeroFloat32),
Out: strconv.FormatFloat(math.SmallestNonzeroFloat32, 'g', -1, 64),
},
{
// Largest representable float64
In: `1.797693134862315708145274237317043567981e+308`,
Data: float64(math.MaxFloat64),
Out: strconv.FormatFloat(math.MaxFloat64, 'g', -1, 64),
},
{
// Closest to zero without losing precision
In: `2.2250738585072014e-308`,
Data: float64(2.2250738585072014e-308),
Out: `2.2250738585072014e-308`,
},
{
// float64 closest to zero
In: `4.940656458412465441765687928682213723651e-324`,
Data: float64(math.SmallestNonzeroFloat64),
Out: strconv.FormatFloat(math.SmallestNonzeroFloat64, 'g', -1, 64),
},
{
// math.MaxFloat64 + 2 overflow
In: `1.7976931348623159e+308`,
Err: true,
},
// Strings
{
In: `""`,
Data: string(""),
Out: `""`,
},
{
In: `"0"`,
Data: string("0"),
Out: `"0"`,
},
{
In: `"A"`,
Data: string("A"),
Out: `"A"`,
},
{
In: `"Iñtërnâtiônàlizætiøn"`,
Data: string("Iñtërnâtiônàlizætiøn"),
Out: `"Iñtërnâtiônàlizætiøn"`,
},
// Arrays
{
In: `[]`,
Data: []interface{}{},
Out: `[]`,
},
{
In: `[` + strings.Join([]string{
`null`,
`true`,
`false`,
`0`,
`9223372036854775807`,
`0.0`,
`0.5`,
`1.0`,
`1.797693134862315708145274237317043567981e+308`,
`"0"`,
`"A"`,
`"Iñtërnâtiônàlizætiøn"`,
`[null,true,1,1.0,1.5]`,
`{"boolkey":true,"floatkey":1.0,"intkey":1,"nullkey":null}`,
}, ",") + `]`,
Data: []interface{}{
nil,
true,
false,
int64(0),
int64(math.MaxInt64),
float64(0.0),
float64(0.5),
float64(1.0),
float64(math.MaxFloat64),
string("0"),
string("A"),
string("Iñtërnâtiônàlizætiøn"),
[]interface{}{nil, true, int64(1), float64(1.0), float64(1.5)},
map[string]interface{}{"nullkey": nil, "boolkey": true, "intkey": int64(1), "floatkey": float64(1.0)},
},
Out: `[` + strings.Join([]string{
`null`,
`true`,
`false`,
`0`,
`9223372036854775807`,
`0`,
`0.5`,
`1`,
strconv.FormatFloat(math.MaxFloat64, 'g', -1, 64),
`"0"`,
`"A"`,
`"Iñtërnâtiônàlizætiøn"`,
`[null,true,1,1,1.5]`,
`{"boolkey":true,"floatkey":1,"intkey":1,"nullkey":null}`, // gets alphabetized by Marshal
}, ",") + `]`,
},
// Maps
{
In: `{}`,
Data: map[string]interface{}{},
Out: `{}`,
},
{
In: `{"boolkey":true,"floatkey":1.0,"intkey":1,"nullkey":null}`,
Data: map[string]interface{}{"nullkey": nil, "boolkey": true, "intkey": int64(1), "floatkey": float64(1.0)},
Out: `{"boolkey":true,"floatkey":1,"intkey":1,"nullkey":null}`, // gets alphabetized by Marshal
},
}
for _, tc := range testCases {
inputJSON := fmt.Sprintf(`{"data":%s}`, tc.In)
expectedJSON := fmt.Sprintf(`{"data":%s}`, tc.Out)
m := map[string]interface{}{}
err := Unmarshal([]byte(inputJSON), &m)
if tc.Err && err != nil {
// Expected error
continue
}
if err != nil {
t.Errorf("%s: error decoding: %v", tc.In, err)
continue
}
if tc.Err {
t.Errorf("%s: expected error, got none", tc.In)
continue
}
data, ok := m["data"]
if !ok {
t.Errorf("%s: decoded object missing data key: %#v", tc.In, m)
continue
}
if !reflect.DeepEqual(tc.Data, data) {
t.Errorf("%s: expected\n\t%#v (%v), got\n\t%#v (%v)", tc.In, tc.Data, reflect.TypeOf(tc.Data), data, reflect.TypeOf(data))
continue
}
outputJSON, err := Marshal(m)
if err != nil {
t.Errorf("%s: error encoding: %v", tc.In, err)
continue
}
if expectedJSON != string(outputJSON) {
t.Errorf("%s: expected\n\t%s, got\n\t%s", tc.In, expectedJSON, string(outputJSON))
continue
}
}
}

View file

@ -1,39 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"errors.go",
"util.go",
],
importpath = "k8s.io/apimachinery/pkg/util/mergepatch",
deps = [
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,138 +0,0 @@
/*
Copyright 2017 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 mergepatch
import (
"fmt"
"testing"
)
func TestHasConflicts(t *testing.T) {
testCases := []struct {
A interface{}
B interface{}
Ret bool
}{
{A: "hello", B: "hello", Ret: false},
{A: "hello", B: "hell", Ret: true},
{A: "hello", B: nil, Ret: true},
{A: "hello", B: 1, Ret: true},
{A: "hello", B: float64(1.0), Ret: true},
{A: "hello", B: false, Ret: true},
{A: 1, B: 1, Ret: false},
{A: nil, B: nil, Ret: false},
{A: false, B: false, Ret: false},
{A: float64(3), B: float64(3), Ret: false},
{A: "hello", B: []interface{}{}, Ret: true},
{A: []interface{}{1}, B: []interface{}{}, Ret: true},
{A: []interface{}{}, B: []interface{}{}, Ret: false},
{A: []interface{}{1}, B: []interface{}{1}, Ret: false},
{A: map[string]interface{}{}, B: []interface{}{1}, Ret: true},
{A: map[string]interface{}{}, B: map[string]interface{}{"a": 1}, Ret: false},
{A: map[string]interface{}{"a": 1}, B: map[string]interface{}{"a": 1}, Ret: false},
{A: map[string]interface{}{"a": 1}, B: map[string]interface{}{"a": 2}, Ret: true},
{A: map[string]interface{}{"a": 1}, B: map[string]interface{}{"b": 2}, Ret: false},
{
A: map[string]interface{}{"a": []interface{}{1}},
B: map[string]interface{}{"a": []interface{}{1}},
Ret: false,
},
{
A: map[string]interface{}{"a": []interface{}{1}},
B: map[string]interface{}{"a": []interface{}{}},
Ret: true,
},
{
A: map[string]interface{}{"a": []interface{}{1}},
B: map[string]interface{}{"a": 1},
Ret: true,
},
// Maps and lists with multiple entries.
{
A: map[string]interface{}{"a": 1, "b": 2},
B: map[string]interface{}{"a": 1, "b": 0},
Ret: true,
},
{
A: map[string]interface{}{"a": 1, "b": 2},
B: map[string]interface{}{"a": 1, "b": 2},
Ret: false,
},
{
A: map[string]interface{}{"a": 1, "b": 2},
B: map[string]interface{}{"a": 1, "b": 0, "c": 3},
Ret: true,
},
{
A: map[string]interface{}{"a": 1, "b": 2},
B: map[string]interface{}{"a": 1, "b": 2, "c": 3},
Ret: false,
},
{
A: map[string]interface{}{"a": []interface{}{1, 2}},
B: map[string]interface{}{"a": []interface{}{1, 0}},
Ret: true,
},
{
A: map[string]interface{}{"a": []interface{}{1, 2}},
B: map[string]interface{}{"a": []interface{}{1, 2}},
Ret: false,
},
// Numeric types are not interchangeable.
// Callers are expected to ensure numeric types are consistent in 'left' and 'right'.
{A: int(0), B: int64(0), Ret: true},
{A: int(0), B: float64(0), Ret: true},
{A: int64(0), B: float64(0), Ret: true},
// Other types are not interchangeable.
{A: int(0), B: "0", Ret: true},
{A: int(0), B: nil, Ret: true},
{A: int(0), B: false, Ret: true},
{A: "true", B: true, Ret: true},
{A: "null", B: nil, Ret: true},
}
for _, testCase := range testCases {
testStr := fmt.Sprintf("A = %#v, B = %#v", testCase.A, testCase.B)
// Run each test case multiple times if it passes because HasConflicts()
// uses map iteration, which returns keys in nondeterministic order.
for try := 0; try < 10; try++ {
out, err := HasConflicts(testCase.A, testCase.B)
if err != nil {
t.Errorf("%v: unexpected error: %v", testStr, err)
break
}
if out != testCase.Ret {
t.Errorf("%v: expected %t got %t", testStr, testCase.Ret, out)
break
}
out, err = HasConflicts(testCase.B, testCase.A)
if err != nil {
t.Errorf("%v: unexpected error: %v", testStr, err)
break
}
if out != testCase.Ret {
t.Errorf("%v: expected reversed %t got %t", testStr, testCase.Ret, out)
break
}
}
}
}

View file

@ -1,50 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"http_test.go",
"interface_test.go",
"port_range_test.go",
"port_split_test.go",
"util_test.go",
],
embed = [":go_default_library"],
deps = ["//vendor/github.com/spf13/pflag:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"http.go",
"interface.go",
"port_range.go",
"port_split.go",
"util.go",
],
importpath = "k8s.io/apimachinery/pkg/util/net",
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/net/http2:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -61,6 +61,9 @@ func JoinPreservingTrailingSlash(elem ...string) string {
// differentiate probable errors in connection behavior between normal "this is
// disconnected" should use the method.
func IsProbableEOF(err error) bool {
if err == nil {
return false
}
if uerr, ok := err.(*url.Error); ok {
err = uerr.Err
}

Some files were not shown because too many files have changed in this diff Show more