Update go dependencies
This commit is contained in:
parent
15ffb51394
commit
bb4d483837
1621 changed files with 86368 additions and 284392 deletions
43
vendor/k8s.io/apimachinery/pkg/util/cache/BUILD
generated
vendored
43
vendor/k8s.io/apimachinery/pkg/util/cache/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
90
vendor/k8s.io/apimachinery/pkg/util/cache/cache_test.go
generated
vendored
90
vendor/k8s.io/apimachinery/pkg/util/cache/cache_test.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
68
vendor/k8s.io/apimachinery/pkg/util/cache/lruexpirecache_test.go
generated
vendored
68
vendor/k8s.io/apimachinery/pkg/util/cache/lruexpirecache_test.go
generated
vendored
|
|
@ -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")
|
||||
}
|
||||
32
vendor/k8s.io/apimachinery/pkg/util/clock/BUILD
generated
vendored
32
vendor/k8s.io/apimachinery/pkg/util/clock/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
184
vendor/k8s.io/apimachinery/pkg/util/clock/clock_test.go
generated
vendored
184
vendor/k8s.io/apimachinery/pkg/util/clock/clock_test.go
generated
vendored
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
36
vendor/k8s.io/apimachinery/pkg/util/diff/BUILD
generated
vendored
36
vendor/k8s.io/apimachinery/pkg/util/diff/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
96
vendor/k8s.io/apimachinery/pkg/util/diff/diff_test.go
generated
vendored
96
vendor/k8s.io/apimachinery/pkg/util/diff/diff_test.go
generated
vendored
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
35
vendor/k8s.io/apimachinery/pkg/util/errors/BUILD
generated
vendored
35
vendor/k8s.io/apimachinery/pkg/util/errors/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
368
vendor/k8s.io/apimachinery/pkg/util/errors/errors_test.go
generated
vendored
368
vendor/k8s.io/apimachinery/pkg/util/errors/errors_test.go
generated
vendored
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
vendor/k8s.io/apimachinery/pkg/util/framer/BUILD
generated
vendored
32
vendor/k8s.io/apimachinery/pkg/util/framer/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
176
vendor/k8s.io/apimachinery/pkg/util/framer/framer_test.go
generated
vendored
176
vendor/k8s.io/apimachinery/pkg/util/framer/framer_test.go
generated
vendored
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
38
vendor/k8s.io/apimachinery/pkg/util/httpstream/BUILD
generated
vendored
38
vendor/k8s.io/apimachinery/pkg/util/httpstream/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
125
vendor/k8s.io/apimachinery/pkg/util/httpstream/httpstream_test.go
generated
vendored
125
vendor/k8s.io/apimachinery/pkg/util/httpstream/httpstream_test.go
generated
vendored
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
56
vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/BUILD
generated
vendored
56
vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
164
vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection_test.go
generated
vendored
164
vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection_test.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
529
vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go
generated
vendored
529
vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper_test.go
generated
vendored
|
|
@ -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-----`)
|
||||
93
vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade_test.go
generated
vendored
93
vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade_test.go
generated
vendored
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
47
vendor/k8s.io/apimachinery/pkg/util/intstr/BUILD
generated
vendored
47
vendor/k8s.io/apimachinery/pkg/util/intstr/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
176
vendor/k8s.io/apimachinery/pkg/util/intstr/intstr_test.go
generated
vendored
176
vendor/k8s.io/apimachinery/pkg/util/intstr/intstr_test.go
generated
vendored
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
32
vendor/k8s.io/apimachinery/pkg/util/json/BUILD
generated
vendored
32
vendor/k8s.io/apimachinery/pkg/util/json/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
319
vendor/k8s.io/apimachinery/pkg/util/json/json_test.go
generated
vendored
319
vendor/k8s.io/apimachinery/pkg/util/json/json_test.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
39
vendor/k8s.io/apimachinery/pkg/util/mergepatch/BUILD
generated
vendored
39
vendor/k8s.io/apimachinery/pkg/util/mergepatch/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
138
vendor/k8s.io/apimachinery/pkg/util/mergepatch/util_test.go
generated
vendored
138
vendor/k8s.io/apimachinery/pkg/util/mergepatch/util_test.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
vendor/k8s.io/apimachinery/pkg/util/net/BUILD
generated
vendored
50
vendor/k8s.io/apimachinery/pkg/util/net/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
3
vendor/k8s.io/apimachinery/pkg/util/net/http.go
generated
vendored
3
vendor/k8s.io/apimachinery/pkg/util/net/http.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
282
vendor/k8s.io/apimachinery/pkg/util/net/http_test.go
generated
vendored
282
vendor/k8s.io/apimachinery/pkg/util/net/http_test.go
generated
vendored
|
|
@ -1,282 +0,0 @@
|
|||
// +build go1.8
|
||||
|
||||
/*
|
||||
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 net
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetClientIP(t *testing.T) {
|
||||
ipString := "10.0.0.1"
|
||||
ip := net.ParseIP(ipString)
|
||||
invalidIPString := "invalidIPString"
|
||||
testCases := []struct {
|
||||
Request http.Request
|
||||
ExpectedIP net.IP
|
||||
}{
|
||||
{
|
||||
Request: http.Request{},
|
||||
},
|
||||
{
|
||||
Request: http.Request{
|
||||
Header: map[string][]string{
|
||||
"X-Real-Ip": {ipString},
|
||||
},
|
||||
},
|
||||
ExpectedIP: ip,
|
||||
},
|
||||
{
|
||||
Request: http.Request{
|
||||
Header: map[string][]string{
|
||||
"X-Real-Ip": {invalidIPString},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Request: http.Request{
|
||||
Header: map[string][]string{
|
||||
"X-Forwarded-For": {ipString},
|
||||
},
|
||||
},
|
||||
ExpectedIP: ip,
|
||||
},
|
||||
{
|
||||
Request: http.Request{
|
||||
Header: map[string][]string{
|
||||
"X-Forwarded-For": {invalidIPString},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Request: http.Request{
|
||||
Header: map[string][]string{
|
||||
"X-Forwarded-For": {invalidIPString + "," + ipString},
|
||||
},
|
||||
},
|
||||
ExpectedIP: ip,
|
||||
},
|
||||
{
|
||||
Request: http.Request{
|
||||
// RemoteAddr is in the form host:port
|
||||
RemoteAddr: ipString + ":1234",
|
||||
},
|
||||
ExpectedIP: ip,
|
||||
},
|
||||
{
|
||||
Request: http.Request{
|
||||
RemoteAddr: invalidIPString,
|
||||
},
|
||||
},
|
||||
{
|
||||
Request: http.Request{
|
||||
Header: map[string][]string{
|
||||
"X-Forwarded-For": {invalidIPString},
|
||||
},
|
||||
// RemoteAddr is in the form host:port
|
||||
RemoteAddr: ipString,
|
||||
},
|
||||
ExpectedIP: ip,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
if a, e := GetClientIP(&test.Request), test.ExpectedIP; reflect.DeepEqual(e, a) != true {
|
||||
t.Fatalf("test case %d failed. expected: %v, actual: %v", i, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendForwardedForHeader(t *testing.T) {
|
||||
testCases := []struct {
|
||||
addr, forwarded, expected string
|
||||
}{
|
||||
{"1.2.3.4:8000", "", "1.2.3.4"},
|
||||
{"1.2.3.4:8000", "8.8.8.8", "8.8.8.8, 1.2.3.4"},
|
||||
{"1.2.3.4:8000", "8.8.8.8, 1.2.3.4", "8.8.8.8, 1.2.3.4, 1.2.3.4"},
|
||||
{"1.2.3.4:8000", "foo,bar", "foo,bar, 1.2.3.4"},
|
||||
}
|
||||
for i, test := range testCases {
|
||||
req := &http.Request{
|
||||
RemoteAddr: test.addr,
|
||||
Header: make(http.Header),
|
||||
}
|
||||
if test.forwarded != "" {
|
||||
req.Header.Set("X-Forwarded-For", test.forwarded)
|
||||
}
|
||||
|
||||
AppendForwardedForHeader(req)
|
||||
actual := req.Header.Get("X-Forwarded-For")
|
||||
if actual != test.expected {
|
||||
t.Errorf("[%d] Expected %q, Got %q", i, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxierWithNoProxyCIDR(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
noProxy string
|
||||
url string
|
||||
|
||||
expectedDelegated bool
|
||||
}{
|
||||
{
|
||||
name: "no env",
|
||||
url: "https://192.168.143.1/api",
|
||||
expectedDelegated: true,
|
||||
},
|
||||
{
|
||||
name: "no cidr",
|
||||
noProxy: "192.168.63.1",
|
||||
url: "https://192.168.143.1/api",
|
||||
expectedDelegated: true,
|
||||
},
|
||||
{
|
||||
name: "hostname",
|
||||
noProxy: "192.168.63.0/24,192.168.143.0/24",
|
||||
url: "https://my-hostname/api",
|
||||
expectedDelegated: true,
|
||||
},
|
||||
{
|
||||
name: "match second cidr",
|
||||
noProxy: "192.168.63.0/24,192.168.143.0/24",
|
||||
url: "https://192.168.143.1/api",
|
||||
expectedDelegated: false,
|
||||
},
|
||||
{
|
||||
name: "match second cidr with host:port",
|
||||
noProxy: "192.168.63.0/24,192.168.143.0/24",
|
||||
url: "https://192.168.143.1:8443/api",
|
||||
expectedDelegated: false,
|
||||
},
|
||||
{
|
||||
name: "IPv6 cidr",
|
||||
noProxy: "2001:db8::/48",
|
||||
url: "https://[2001:db8::1]/api",
|
||||
expectedDelegated: false,
|
||||
},
|
||||
{
|
||||
name: "IPv6+port cidr",
|
||||
noProxy: "2001:db8::/48",
|
||||
url: "https://[2001:db8::1]:8443/api",
|
||||
expectedDelegated: false,
|
||||
},
|
||||
{
|
||||
name: "IPv6, not matching cidr",
|
||||
noProxy: "2001:db8::/48",
|
||||
url: "https://[2001:db8:1::1]/api",
|
||||
expectedDelegated: true,
|
||||
},
|
||||
{
|
||||
name: "IPv6+port, not matching cidr",
|
||||
noProxy: "2001:db8::/48",
|
||||
url: "https://[2001:db8:1::1]:8443/api",
|
||||
expectedDelegated: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
os.Setenv("NO_PROXY", test.noProxy)
|
||||
actualDelegated := false
|
||||
proxyFunc := NewProxierWithNoProxyCIDR(func(req *http.Request) (*url.URL, error) {
|
||||
actualDelegated = true
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
req, err := http.NewRequest("GET", test.url, nil)
|
||||
if err != nil {
|
||||
t.Errorf("%s: unexpected err: %v", test.name, err)
|
||||
continue
|
||||
}
|
||||
if _, err := proxyFunc(req); err != nil {
|
||||
t.Errorf("%s: unexpected err: %v", test.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if test.expectedDelegated != actualDelegated {
|
||||
t.Errorf("%s: expected %v, got %v", test.name, test.expectedDelegated, actualDelegated)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type fakeTLSClientConfigHolder struct {
|
||||
called bool
|
||||
}
|
||||
|
||||
func (f *fakeTLSClientConfigHolder) TLSClientConfig() *tls.Config {
|
||||
f.called = true
|
||||
return nil
|
||||
}
|
||||
func (f *fakeTLSClientConfigHolder) RoundTrip(*http.Request) (*http.Response, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestTLSClientConfigHolder(t *testing.T) {
|
||||
rt := &fakeTLSClientConfigHolder{}
|
||||
TLSClientConfig(rt)
|
||||
|
||||
if !rt.called {
|
||||
t.Errorf("didn't find tls config")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJoinPreservingTrailingSlash(t *testing.T) {
|
||||
tests := []struct {
|
||||
a string
|
||||
b string
|
||||
want string
|
||||
}{
|
||||
// All empty
|
||||
{"", "", ""},
|
||||
|
||||
// Empty a
|
||||
{"", "/", "/"},
|
||||
{"", "foo", "foo"},
|
||||
{"", "/foo", "/foo"},
|
||||
{"", "/foo/", "/foo/"},
|
||||
|
||||
// Empty b
|
||||
{"/", "", "/"},
|
||||
{"foo", "", "foo"},
|
||||
{"/foo", "", "/foo"},
|
||||
{"/foo/", "", "/foo/"},
|
||||
|
||||
// Both populated
|
||||
{"/", "/", "/"},
|
||||
{"foo", "foo", "foo/foo"},
|
||||
{"/foo", "/foo", "/foo/foo"},
|
||||
{"/foo/", "/foo/", "/foo/foo/"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
name := fmt.Sprintf("%q+%q=%q", tt.a, tt.b, tt.want)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if got := JoinPreservingTrailingSlash(tt.a, tt.b); got != tt.want {
|
||||
t.Errorf("JoinPreservingTrailingSlash() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
725
vendor/k8s.io/apimachinery/pkg/util/net/interface_test.go
generated
vendored
725
vendor/k8s.io/apimachinery/pkg/util/net/interface_test.go
generated
vendored
|
|
@ -1,725 +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 net
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const gatewayfirst = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||||
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
|
||||
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
|
||||
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
|
||||
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
|
||||
`
|
||||
const gatewaylast = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||||
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
|
||||
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
|
||||
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
|
||||
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
|
||||
`
|
||||
const gatewaymiddle = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||||
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
|
||||
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
|
||||
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
|
||||
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
|
||||
`
|
||||
const noInternetConnection = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||||
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
|
||||
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
|
||||
`
|
||||
const nothing = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||||
`
|
||||
const badDestination = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||||
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
|
||||
eth3 0000FE0AA1 00000000 0001 0 0 0 0080FFFF 0 0 0
|
||||
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
|
||||
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
|
||||
`
|
||||
const badGateway = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||||
eth3 00000000 0100FE0AA1 0003 0 0 1024 00000000 0 0 0
|
||||
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
|
||||
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
|
||||
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
|
||||
`
|
||||
const route_Invalidhex = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||||
eth3 00000000 0100FE0AA 0003 0 0 1024 00000000 0 0 0
|
||||
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
|
||||
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
|
||||
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
|
||||
`
|
||||
|
||||
const v6gatewayfirst = `00000000000000000000000000000000 00 00000000000000000000000000000000 00 20010001000000000000000000000001 00000064 00000000 00000000 00000003 eth3
|
||||
20010002000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth3
|
||||
00000000000000000000000000000000 60 00000000000000000000000000000000 00 00000000000000000000000000000000 00000400 00000000 00000000 00200200 lo
|
||||
`
|
||||
const v6gatewaylast = `20010002000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth3
|
||||
00000000000000000000000000000000 60 00000000000000000000000000000000 00 00000000000000000000000000000000 00000400 00000000 00000000 00200200 lo
|
||||
00000000000000000000000000000000 00 00000000000000000000000000000000 00 20010001000000000000000000000001 00000064 00000000 00000000 00000003 eth3
|
||||
`
|
||||
const v6gatewaymiddle = `20010002000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth3
|
||||
00000000000000000000000000000000 00 00000000000000000000000000000000 00 20010001000000000000000000000001 00000064 00000000 00000000 00000003 eth3
|
||||
00000000000000000000000000000000 60 00000000000000000000000000000000 00 00000000000000000000000000000000 00000400 00000000 00000000 00200200 lo
|
||||
`
|
||||
const v6noDefaultRoutes = `00000000000000000000000000000000 60 00000000000000000000000000000000 00 00000000000000000000000000000000 00000400 00000000 00000000 00200200 lo
|
||||
20010001000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000400 00000000 00000000 00000001 docker0
|
||||
20010002000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth3
|
||||
fe800000000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth3
|
||||
`
|
||||
const v6nothing = ``
|
||||
const v6badDestination = `2001000200000000 7a 00000000000000000000000000000000 00 00000000000000000000000000000000 00000400 00000000 00000000 00200200 lo
|
||||
`
|
||||
const v6badGateway = `00000000000000000000000000000000 00 00000000000000000000000000000000 00 200100010000000000000000000000000012 00000064 00000000 00000000 00000003 eth3
|
||||
`
|
||||
const v6route_Invalidhex = `000000000000000000000000000000000 00 00000000000000000000000000000000 00 fe80000000000000021fcafffea0ec00 00000064 00000000 00000000 00000003 enp1s0f0
|
||||
|
||||
`
|
||||
|
||||
const (
|
||||
flagUp = net.FlagUp | net.FlagBroadcast | net.FlagMulticast
|
||||
flagDown = net.FlagBroadcast | net.FlagMulticast
|
||||
flagLoopback = net.FlagUp | net.FlagLoopback
|
||||
flagP2P = net.FlagUp | net.FlagPointToPoint
|
||||
)
|
||||
|
||||
func makeIntf(index int, name string, flags net.Flags) net.Interface {
|
||||
mac := net.HardwareAddr{0, 0x32, 0x7d, 0x69, 0xf7, byte(0x30 + index)}
|
||||
return net.Interface{
|
||||
Index: index,
|
||||
MTU: 1500,
|
||||
Name: name,
|
||||
HardwareAddr: mac,
|
||||
Flags: flags}
|
||||
}
|
||||
|
||||
var (
|
||||
downIntf = makeIntf(1, "eth3", flagDown)
|
||||
loopbackIntf = makeIntf(1, "lo", flagLoopback)
|
||||
p2pIntf = makeIntf(1, "lo", flagP2P)
|
||||
upIntf = makeIntf(1, "eth3", flagUp)
|
||||
)
|
||||
|
||||
var (
|
||||
ipv4Route = Route{Interface: "eth3", Destination: net.ParseIP("0.0.0.0"), Gateway: net.ParseIP("10.254.0.1"), Family: familyIPv4}
|
||||
ipv6Route = Route{Interface: "eth3", Destination: net.ParseIP("::"), Gateway: net.ParseIP("2001:1::1"), Family: familyIPv6}
|
||||
)
|
||||
|
||||
var (
|
||||
noRoutes = []Route{}
|
||||
routeV4 = []Route{ipv4Route}
|
||||
routeV6 = []Route{ipv6Route}
|
||||
bothRoutes = []Route{ipv4Route, ipv6Route}
|
||||
)
|
||||
|
||||
func TestGetIPv4Routes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
route string
|
||||
count int
|
||||
expected *Route
|
||||
errStrFrag string
|
||||
}{
|
||||
{"gatewayfirst", gatewayfirst, 1, &ipv4Route, ""},
|
||||
{"gatewaymiddle", gatewaymiddle, 1, &ipv4Route, ""},
|
||||
{"gatewaylast", gatewaylast, 1, &ipv4Route, ""},
|
||||
{"no routes", nothing, 0, nil, ""},
|
||||
{"badDestination", badDestination, 0, nil, "invalid IPv4"},
|
||||
{"badGateway", badGateway, 0, nil, "invalid IPv4"},
|
||||
{"route_Invalidhex", route_Invalidhex, 0, nil, "odd length hex string"},
|
||||
{"no default routes", noInternetConnection, 0, nil, ""},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
r := strings.NewReader(tc.route)
|
||||
routes, err := getIPv4DefaultRoutes(r)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), tc.errStrFrag) {
|
||||
t.Errorf("case[%s]: Error string %q does not contain %q", tc.tcase, err, tc.errStrFrag)
|
||||
}
|
||||
} else if tc.errStrFrag != "" {
|
||||
t.Errorf("case[%s]: Error %q expected, but not seen", tc.tcase, tc.errStrFrag)
|
||||
} else {
|
||||
if tc.count != len(routes) {
|
||||
t.Errorf("case[%s]: expected %d routes, have %v", tc.tcase, tc.count, routes)
|
||||
} else if tc.count == 1 {
|
||||
if !tc.expected.Gateway.Equal(routes[0].Gateway) {
|
||||
t.Errorf("case[%s]: expected %v, got %v .err : %v", tc.tcase, tc.expected, routes, err)
|
||||
}
|
||||
if !routes[0].Destination.Equal(net.IPv4zero) {
|
||||
t.Errorf("case[%s}: destination is not for default route (not zero)", tc.tcase)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIPv6Routes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
route string
|
||||
count int
|
||||
expected *Route
|
||||
errStrFrag string
|
||||
}{
|
||||
{"v6 gatewayfirst", v6gatewayfirst, 1, &ipv6Route, ""},
|
||||
{"v6 gatewaymiddle", v6gatewaymiddle, 1, &ipv6Route, ""},
|
||||
{"v6 gatewaylast", v6gatewaylast, 1, &ipv6Route, ""},
|
||||
{"v6 no routes", v6nothing, 0, nil, ""},
|
||||
{"v6 badDestination", v6badDestination, 0, nil, "invalid IPv6"},
|
||||
{"v6 badGateway", v6badGateway, 0, nil, "invalid IPv6"},
|
||||
{"v6 route_Invalidhex", v6route_Invalidhex, 0, nil, "odd length hex string"},
|
||||
{"v6 no default routes", v6noDefaultRoutes, 0, nil, ""},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
r := strings.NewReader(tc.route)
|
||||
routes, err := getIPv6DefaultRoutes(r)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), tc.errStrFrag) {
|
||||
t.Errorf("case[%s]: Error string %q does not contain %q", tc.tcase, err, tc.errStrFrag)
|
||||
}
|
||||
} else if tc.errStrFrag != "" {
|
||||
t.Errorf("case[%s]: Error %q expected, but not seen", tc.tcase, tc.errStrFrag)
|
||||
} else {
|
||||
if tc.count != len(routes) {
|
||||
t.Errorf("case[%s]: expected %d routes, have %v", tc.tcase, tc.count, routes)
|
||||
} else if tc.count == 1 {
|
||||
if !tc.expected.Gateway.Equal(routes[0].Gateway) {
|
||||
t.Errorf("case[%s]: expected %v, got %v .err : %v", tc.tcase, tc.expected, routes, err)
|
||||
}
|
||||
if !routes[0].Destination.Equal(net.IPv6zero) {
|
||||
t.Errorf("case[%s}: destination is not for default route (not zero)", tc.tcase)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseIP(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
ip string
|
||||
family AddressFamily
|
||||
success bool
|
||||
expected net.IP
|
||||
}{
|
||||
{"empty", "", familyIPv4, false, nil},
|
||||
{"too short", "AA", familyIPv4, false, nil},
|
||||
{"too long", "0011223344", familyIPv4, false, nil},
|
||||
{"invalid", "invalid!", familyIPv4, false, nil},
|
||||
{"zero", "00000000", familyIPv4, true, net.IP{0, 0, 0, 0}},
|
||||
{"ffff", "FFFFFFFF", familyIPv4, true, net.IP{0xff, 0xff, 0xff, 0xff}},
|
||||
{"valid v4", "12345678", familyIPv4, true, net.IP{120, 86, 52, 18}},
|
||||
{"valid v6", "fe800000000000000000000000000000", familyIPv6, true, net.IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"v6 too short", "fe80000000000000021fcafffea0ec0", familyIPv6, false, nil},
|
||||
{"v6 too long", "fe80000000000000021fcafffea0ec002", familyIPv6, false, nil},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ip, err := parseIP(tc.ip, tc.family)
|
||||
if !ip.Equal(tc.expected) {
|
||||
t.Errorf("case[%v]: expected %q, got %q . err : %v", tc.tcase, tc.expected, ip, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInterfaceUp(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
intf *net.Interface
|
||||
expected bool
|
||||
}{
|
||||
{"up", &net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}, true},
|
||||
{"down", &net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: 0}, false},
|
||||
{"no interface", nil, false},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
it := isInterfaceUp(tc.intf)
|
||||
if it != tc.expected {
|
||||
t.Errorf("case[%v]: expected %v, got %v .", tc.tcase, tc.expected, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type addrStruct struct{ val string }
|
||||
|
||||
func (a addrStruct) Network() string {
|
||||
return a.val
|
||||
}
|
||||
func (a addrStruct) String() string {
|
||||
return a.val
|
||||
}
|
||||
|
||||
func TestFinalIP(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
addr []net.Addr
|
||||
family AddressFamily
|
||||
expected net.IP
|
||||
}{
|
||||
{"no ipv4", []net.Addr{addrStruct{val: "2001::5/64"}}, familyIPv4, nil},
|
||||
{"no ipv6", []net.Addr{addrStruct{val: "10.128.0.4/32"}}, familyIPv6, nil},
|
||||
{"invalidV4CIDR", []net.Addr{addrStruct{val: "10.20.30.40.50/24"}}, familyIPv4, nil},
|
||||
{"invalidV6CIDR", []net.Addr{addrStruct{val: "fe80::2f7:67fff:fe6e:2956/64"}}, familyIPv6, nil},
|
||||
{"loopback", []net.Addr{addrStruct{val: "127.0.0.1/24"}}, familyIPv4, nil},
|
||||
{"loopbackv6", []net.Addr{addrStruct{val: "::1/128"}}, familyIPv6, nil},
|
||||
{"link local v4", []net.Addr{addrStruct{val: "169.254.1.10/16"}}, familyIPv4, nil},
|
||||
{"link local v6", []net.Addr{addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}}, familyIPv6, nil},
|
||||
{"ip4", []net.Addr{addrStruct{val: "10.254.12.132/17"}}, familyIPv4, net.ParseIP("10.254.12.132")},
|
||||
{"ip6", []net.Addr{addrStruct{val: "2001::5/64"}}, familyIPv6, net.ParseIP("2001::5")},
|
||||
|
||||
{"no addresses", []net.Addr{}, familyIPv4, nil},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ip, err := getMatchingGlobalIP(tc.addr, tc.family)
|
||||
if !ip.Equal(tc.expected) {
|
||||
t.Errorf("case[%v]: expected %v, got %v .err : %v", tc.tcase, tc.expected, ip, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddrs(t *testing.T) {
|
||||
var nw networkInterfacer = validNetworkInterface{}
|
||||
intf := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: 0}
|
||||
addrs, err := nw.Addrs(&intf)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error got : %v", err)
|
||||
}
|
||||
if len(addrs) != 2 {
|
||||
t.Errorf("expected addrs: 2 got null")
|
||||
}
|
||||
}
|
||||
|
||||
// Has a valid IPv4 address (IPv6 is LLA)
|
||||
type validNetworkInterface struct {
|
||||
}
|
||||
|
||||
func (_ validNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &upIntf, nil
|
||||
}
|
||||
func (_ validNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
ifat = []net.Addr{
|
||||
addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}, addrStruct{val: "10.254.71.145/17"}}
|
||||
return ifat, nil
|
||||
}
|
||||
func (_ validNetworkInterface) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{upIntf}, nil
|
||||
}
|
||||
|
||||
// Both IPv4 and IPv6 addresses (expecting IPv4 to be used)
|
||||
type v4v6NetworkInterface struct {
|
||||
}
|
||||
|
||||
func (_ v4v6NetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &upIntf, nil
|
||||
}
|
||||
func (_ v4v6NetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
ifat = []net.Addr{
|
||||
addrStruct{val: "2001::10/64"}, addrStruct{val: "10.254.71.145/17"}}
|
||||
return ifat, nil
|
||||
}
|
||||
func (_ v4v6NetworkInterface) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{upIntf}, nil
|
||||
}
|
||||
|
||||
// Interface with only IPv6 address
|
||||
type ipv6NetworkInterface struct {
|
||||
}
|
||||
|
||||
func (_ ipv6NetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &upIntf, nil
|
||||
}
|
||||
func (_ ipv6NetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
ifat = []net.Addr{addrStruct{val: "2001::200/64"}}
|
||||
return ifat, nil
|
||||
}
|
||||
|
||||
func (_ ipv6NetworkInterface) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{upIntf}, nil
|
||||
}
|
||||
|
||||
// Only with link local addresses
|
||||
type networkInterfaceWithOnlyLinkLocals struct {
|
||||
}
|
||||
|
||||
func (_ networkInterfaceWithOnlyLinkLocals) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &upIntf, nil
|
||||
}
|
||||
func (_ networkInterfaceWithOnlyLinkLocals) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
ifat = []net.Addr{addrStruct{val: "169.254.162.166/16"}, addrStruct{val: "fe80::200/10"}}
|
||||
return ifat, nil
|
||||
}
|
||||
func (_ networkInterfaceWithOnlyLinkLocals) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{upIntf}, nil
|
||||
}
|
||||
|
||||
// Unable to get interface(s)
|
||||
type failGettingNetworkInterface struct {
|
||||
}
|
||||
|
||||
func (_ failGettingNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return nil, fmt.Errorf("unable get Interface")
|
||||
}
|
||||
func (_ failGettingNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (_ failGettingNetworkInterface) Interfaces() ([]net.Interface, error) {
|
||||
return nil, fmt.Errorf("mock failed getting all interfaces")
|
||||
}
|
||||
|
||||
// No interfaces
|
||||
type noNetworkInterface struct {
|
||||
}
|
||||
|
||||
func (_ noNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return nil, fmt.Errorf("no such network interface")
|
||||
}
|
||||
func (_ noNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (_ noNetworkInterface) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{}, nil
|
||||
}
|
||||
|
||||
// Interface is down
|
||||
type downNetworkInterface struct {
|
||||
}
|
||||
|
||||
func (_ downNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &downIntf, nil
|
||||
}
|
||||
func (_ downNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
ifat = []net.Addr{
|
||||
addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}, addrStruct{val: "10.254.71.145/17"}}
|
||||
return ifat, nil
|
||||
}
|
||||
func (_ downNetworkInterface) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{downIntf}, nil
|
||||
}
|
||||
|
||||
// Loopback interface
|
||||
type loopbackNetworkInterface struct {
|
||||
}
|
||||
|
||||
func (_ loopbackNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &loopbackIntf, nil
|
||||
}
|
||||
func (_ loopbackNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
ifat = []net.Addr{
|
||||
addrStruct{val: "::1/128"}, addrStruct{val: "127.0.0.1/8"}}
|
||||
return ifat, nil
|
||||
}
|
||||
func (_ loopbackNetworkInterface) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{loopbackIntf}, nil
|
||||
}
|
||||
|
||||
// Point to point interface
|
||||
type p2pNetworkInterface struct {
|
||||
}
|
||||
|
||||
func (_ p2pNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &p2pIntf, nil
|
||||
}
|
||||
func (_ p2pNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
ifat = []net.Addr{
|
||||
addrStruct{val: "::1/128"}, addrStruct{val: "127.0.0.1/8"}}
|
||||
return ifat, nil
|
||||
}
|
||||
func (_ p2pNetworkInterface) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{p2pIntf}, nil
|
||||
}
|
||||
|
||||
// Unable to get IP addresses for interface
|
||||
type networkInterfaceFailGetAddrs struct {
|
||||
}
|
||||
|
||||
func (_ networkInterfaceFailGetAddrs) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &upIntf, nil
|
||||
}
|
||||
func (_ networkInterfaceFailGetAddrs) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
return nil, fmt.Errorf("unable to get Addrs")
|
||||
}
|
||||
func (_ networkInterfaceFailGetAddrs) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{upIntf}, nil
|
||||
}
|
||||
|
||||
// No addresses for interface
|
||||
type networkInterfaceWithNoAddrs struct {
|
||||
}
|
||||
|
||||
func (_ networkInterfaceWithNoAddrs) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &upIntf, nil
|
||||
}
|
||||
func (_ networkInterfaceWithNoAddrs) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
ifat := []net.Addr{}
|
||||
return ifat, nil
|
||||
}
|
||||
func (_ networkInterfaceWithNoAddrs) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{upIntf}, nil
|
||||
}
|
||||
|
||||
// Invalid addresses for interface
|
||||
type networkInterfaceWithInvalidAddr struct {
|
||||
}
|
||||
|
||||
func (_ networkInterfaceWithInvalidAddr) InterfaceByName(intfName string) (*net.Interface, error) {
|
||||
return &upIntf, nil
|
||||
}
|
||||
func (_ networkInterfaceWithInvalidAddr) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
var ifat []net.Addr
|
||||
ifat = []net.Addr{addrStruct{val: "10.20.30.40.50/24"}}
|
||||
return ifat, nil
|
||||
}
|
||||
func (_ networkInterfaceWithInvalidAddr) Interfaces() ([]net.Interface, error) {
|
||||
return []net.Interface{upIntf}, nil
|
||||
}
|
||||
|
||||
func TestGetIPFromInterface(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
nwname string
|
||||
family AddressFamily
|
||||
nw networkInterfacer
|
||||
expected net.IP
|
||||
errStrFrag string
|
||||
}{
|
||||
{"ipv4", "eth3", familyIPv4, validNetworkInterface{}, net.ParseIP("10.254.71.145"), ""},
|
||||
{"ipv6", "eth3", familyIPv6, ipv6NetworkInterface{}, net.ParseIP("2001::200"), ""},
|
||||
{"no ipv4", "eth3", familyIPv4, ipv6NetworkInterface{}, nil, ""},
|
||||
{"no ipv6", "eth3", familyIPv6, validNetworkInterface{}, nil, ""},
|
||||
{"I/F down", "eth3", familyIPv4, downNetworkInterface{}, nil, ""},
|
||||
{"I/F get fail", "eth3", familyIPv4, noNetworkInterface{}, nil, "no such network interface"},
|
||||
{"fail get addr", "eth3", familyIPv4, networkInterfaceFailGetAddrs{}, nil, "unable to get Addrs"},
|
||||
{"bad addr", "eth3", familyIPv4, networkInterfaceWithInvalidAddr{}, nil, "invalid CIDR"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ip, err := getIPFromInterface(tc.nwname, tc.family, tc.nw)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), tc.errStrFrag) {
|
||||
t.Errorf("case[%s]: Error string %q does not contain %q", tc.tcase, err, tc.errStrFrag)
|
||||
}
|
||||
} else if tc.errStrFrag != "" {
|
||||
t.Errorf("case[%s]: Error %q expected, but not seen", tc.tcase, tc.errStrFrag)
|
||||
} else if !ip.Equal(tc.expected) {
|
||||
t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestChooseHostInterfaceFromRoute(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
routes []Route
|
||||
nw networkInterfacer
|
||||
expected net.IP
|
||||
}{
|
||||
{"ipv4", routeV4, validNetworkInterface{}, net.ParseIP("10.254.71.145")},
|
||||
{"ipv6", routeV6, ipv6NetworkInterface{}, net.ParseIP("2001::200")},
|
||||
{"prefer ipv4", bothRoutes, v4v6NetworkInterface{}, net.ParseIP("10.254.71.145")},
|
||||
{"all LLA", routeV4, networkInterfaceWithOnlyLinkLocals{}, nil},
|
||||
{"no routes", noRoutes, validNetworkInterface{}, nil},
|
||||
{"fail get IP", routeV4, networkInterfaceFailGetAddrs{}, nil},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
ip, err := chooseHostInterfaceFromRoute(tc.routes, tc.nw)
|
||||
if !ip.Equal(tc.expected) {
|
||||
t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemberOf(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
ip net.IP
|
||||
family AddressFamily
|
||||
expected bool
|
||||
}{
|
||||
{"ipv4 is 4", net.ParseIP("10.20.30.40"), familyIPv4, true},
|
||||
{"ipv4 is 6", net.ParseIP("10.10.10.10"), familyIPv6, false},
|
||||
{"ipv6 is 4", net.ParseIP("2001::100"), familyIPv4, false},
|
||||
{"ipv6 is 6", net.ParseIP("2001::100"), familyIPv6, true},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
if memberOf(tc.ip, tc.family) != tc.expected {
|
||||
t.Errorf("case[%s]: expected %+v", tc.tcase, tc.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIPFromHostInterfaces(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
nw networkInterfacer
|
||||
expected net.IP
|
||||
errStrFrag string
|
||||
}{
|
||||
{"fail get I/Fs", failGettingNetworkInterface{}, nil, "failed getting all interfaces"},
|
||||
{"no interfaces", noNetworkInterface{}, nil, "no interfaces"},
|
||||
{"I/F not up", downNetworkInterface{}, nil, "no acceptable"},
|
||||
{"loopback only", loopbackNetworkInterface{}, nil, "no acceptable"},
|
||||
{"P2P I/F only", p2pNetworkInterface{}, nil, "no acceptable"},
|
||||
{"fail get addrs", networkInterfaceFailGetAddrs{}, nil, "unable to get Addrs"},
|
||||
{"no addresses", networkInterfaceWithNoAddrs{}, nil, "no acceptable"},
|
||||
{"invalid addr", networkInterfaceWithInvalidAddr{}, nil, "invalid CIDR"},
|
||||
{"no matches", networkInterfaceWithOnlyLinkLocals{}, nil, "no acceptable"},
|
||||
{"ipv4", validNetworkInterface{}, net.ParseIP("10.254.71.145"), ""},
|
||||
{"ipv6", ipv6NetworkInterface{}, net.ParseIP("2001::200"), ""},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ip, err := chooseIPFromHostInterfaces(tc.nw)
|
||||
if !ip.Equal(tc.expected) {
|
||||
t.Errorf("case[%s]: expected %+v, got %+v with err : %v", tc.tcase, tc.expected, ip, err)
|
||||
}
|
||||
if err != nil && !strings.Contains(err.Error(), tc.errStrFrag) {
|
||||
t.Errorf("case[%s]: unable to find %q in error string %q", tc.tcase, tc.errStrFrag, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeRouteFile(content string, t *testing.T) (*os.File, error) {
|
||||
routeFile, err := ioutil.TempFile("", "route")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := routeFile.Write([]byte(content)); err != nil {
|
||||
return routeFile, err
|
||||
}
|
||||
err = routeFile.Close()
|
||||
return routeFile, err
|
||||
}
|
||||
|
||||
func TestFailGettingIPv4Routes(t *testing.T) {
|
||||
defer func() { v4File.name = ipv4RouteFile }()
|
||||
|
||||
// Try failure to open file (should not occur, as caller ensures we have IPv4 route file, but being thorough)
|
||||
v4File.name = "no-such-file"
|
||||
errStrFrag := "no such file"
|
||||
_, err := v4File.extract()
|
||||
if err == nil {
|
||||
t.Errorf("Expected error trying to read non-existent v4 route file")
|
||||
}
|
||||
if !strings.Contains(err.Error(), errStrFrag) {
|
||||
t.Errorf("Unable to find %q in error string %q", errStrFrag, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailGettingIPv6Routes(t *testing.T) {
|
||||
defer func() { v6File.name = ipv6RouteFile }()
|
||||
|
||||
// Try failure to open file (this would be ignored by caller)
|
||||
v6File.name = "no-such-file"
|
||||
errStrFrag := "no such file"
|
||||
_, err := v6File.extract()
|
||||
if err == nil {
|
||||
t.Errorf("Expected error trying to read non-existent v6 route file")
|
||||
}
|
||||
if !strings.Contains(err.Error(), errStrFrag) {
|
||||
t.Errorf("Unable to find %q in error string %q", errStrFrag, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllDefaultRoutesFailNoV4RouteFile(t *testing.T) {
|
||||
defer func() { v4File.name = ipv4RouteFile }()
|
||||
|
||||
// Should not occur, as caller ensures we have IPv4 route file, but being thorough
|
||||
v4File.name = "no-such-file"
|
||||
errStrFrag := "no such file"
|
||||
_, err := getAllDefaultRoutes()
|
||||
if err == nil {
|
||||
t.Errorf("Expected error trying to read non-existent v4 route file")
|
||||
}
|
||||
if !strings.Contains(err.Error(), errStrFrag) {
|
||||
t.Errorf("Unable to find %q in error string %q", errStrFrag, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllDefaultRoutes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tcase string
|
||||
v4Info string
|
||||
v6Info string
|
||||
count int
|
||||
expected []Route
|
||||
errStrFrag string
|
||||
}{
|
||||
{"no routes", noInternetConnection, v6noDefaultRoutes, 0, nil, "No default routes"},
|
||||
{"only v4 route", gatewayfirst, v6noDefaultRoutes, 1, routeV4, ""},
|
||||
{"only v6 route", noInternetConnection, v6gatewayfirst, 1, routeV6, ""},
|
||||
{"v4 and v6 routes", gatewayfirst, v6gatewayfirst, 2, bothRoutes, ""},
|
||||
}
|
||||
defer func() {
|
||||
v4File.name = ipv4RouteFile
|
||||
v6File.name = ipv6RouteFile
|
||||
}()
|
||||
|
||||
for _, tc := range testCases {
|
||||
routeFile, err := makeRouteFile(tc.v4Info, t)
|
||||
if routeFile != nil {
|
||||
defer os.Remove(routeFile.Name())
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("case[%s]: test setup failure for IPv4 route file: %v", tc.tcase, err)
|
||||
}
|
||||
v4File.name = routeFile.Name()
|
||||
v6routeFile, err := makeRouteFile(tc.v6Info, t)
|
||||
if v6routeFile != nil {
|
||||
defer os.Remove(v6routeFile.Name())
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("case[%s]: test setup failure for IPv6 route file: %v", tc.tcase, err)
|
||||
}
|
||||
v6File.name = v6routeFile.Name()
|
||||
|
||||
routes, err := getAllDefaultRoutes()
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), tc.errStrFrag) {
|
||||
t.Errorf("case[%s]: Error string %q does not contain %q", tc.tcase, err, tc.errStrFrag)
|
||||
}
|
||||
} else if tc.errStrFrag != "" {
|
||||
t.Errorf("case[%s]: Error %q expected, but not seen", tc.tcase, tc.errStrFrag)
|
||||
} else {
|
||||
if tc.count != len(routes) {
|
||||
t.Errorf("case[%s]: expected %d routes, have %v", tc.tcase, tc.count, routes)
|
||||
}
|
||||
for i, expected := range tc.expected {
|
||||
if !expected.Gateway.Equal(routes[i].Gateway) {
|
||||
t.Errorf("case[%s]: at %d expected %v, got %v .err : %v", tc.tcase, i, tc.expected, routes, err)
|
||||
}
|
||||
zeroIP := net.IPv4zero
|
||||
if expected.Family == familyIPv6 {
|
||||
zeroIP = net.IPv6zero
|
||||
}
|
||||
if !routes[i].Destination.Equal(zeroIP) {
|
||||
t.Errorf("case[%s}: at %d destination is not for default route (not %v)", tc.tcase, i, zeroIP)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
vendor/k8s.io/apimachinery/pkg/util/net/port_range_test.go
generated
vendored
69
vendor/k8s.io/apimachinery/pkg/util/net/port_range_test.go
generated
vendored
|
|
@ -1,69 +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 net
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func TestPortRange(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
success bool
|
||||
expected string
|
||||
included int
|
||||
excluded int
|
||||
}{
|
||||
{"100-200", true, "100-200", 200, 201},
|
||||
{" 100-200 ", true, "100-200", 200, 201},
|
||||
{"0-0", true, "0-0", 0, 1},
|
||||
{"", true, "", -1, 0},
|
||||
{"100", false, "", -1, -1},
|
||||
{"100 - 200", false, "", -1, -1},
|
||||
{"-100", false, "", -1, -1},
|
||||
{"100-", false, "", -1, -1},
|
||||
{"200-100", false, "", -1, -1},
|
||||
{"60000-70000", false, "", -1, -1},
|
||||
{"70000-80000", false, "", -1, -1},
|
||||
}
|
||||
|
||||
for i := range testCases {
|
||||
tc := &testCases[i]
|
||||
pr := &PortRange{}
|
||||
var f flag.Value = pr
|
||||
err := f.Set(tc.input)
|
||||
if err != nil && tc.success == true {
|
||||
t.Errorf("expected success, got %q", err)
|
||||
continue
|
||||
} else if err == nil && tc.success == false {
|
||||
t.Errorf("expected failure")
|
||||
continue
|
||||
} else if tc.success {
|
||||
if f.String() != tc.expected {
|
||||
t.Errorf("expected %q, got %q", tc.expected, f.String())
|
||||
}
|
||||
if tc.included >= 0 && !pr.Contains(tc.included) {
|
||||
t.Errorf("expected %q to include %d", f.String(), tc.included)
|
||||
}
|
||||
if tc.excluded >= 0 && pr.Contains(tc.excluded) {
|
||||
t.Errorf("expected %q to exclude %d", f.String(), tc.excluded)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
121
vendor/k8s.io/apimachinery/pkg/util/net/port_split_test.go
generated
vendored
121
vendor/k8s.io/apimachinery/pkg/util/net/port_split_test.go
generated
vendored
|
|
@ -1,121 +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 net
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSplitSchemeNamePort(t *testing.T) {
|
||||
table := []struct {
|
||||
in string
|
||||
name, port, scheme string
|
||||
valid bool
|
||||
normalized bool
|
||||
}{
|
||||
{
|
||||
in: "aoeu:asdf",
|
||||
name: "aoeu",
|
||||
port: "asdf",
|
||||
valid: true,
|
||||
normalized: true,
|
||||
}, {
|
||||
in: "http:aoeu:asdf",
|
||||
scheme: "http",
|
||||
name: "aoeu",
|
||||
port: "asdf",
|
||||
valid: true,
|
||||
normalized: true,
|
||||
}, {
|
||||
in: "https:aoeu:",
|
||||
scheme: "https",
|
||||
name: "aoeu",
|
||||
port: "",
|
||||
valid: true,
|
||||
normalized: false,
|
||||
}, {
|
||||
in: "https:aoeu:asdf",
|
||||
scheme: "https",
|
||||
name: "aoeu",
|
||||
port: "asdf",
|
||||
valid: true,
|
||||
normalized: true,
|
||||
}, {
|
||||
in: "aoeu:",
|
||||
name: "aoeu",
|
||||
valid: true,
|
||||
normalized: false,
|
||||
}, {
|
||||
in: "aoeu",
|
||||
name: "aoeu",
|
||||
valid: true,
|
||||
normalized: true,
|
||||
}, {
|
||||
in: ":asdf",
|
||||
valid: false,
|
||||
}, {
|
||||
in: "aoeu:asdf:htns",
|
||||
valid: false,
|
||||
}, {
|
||||
in: "http::asdf",
|
||||
valid: false,
|
||||
}, {
|
||||
in: "http::",
|
||||
valid: false,
|
||||
}, {
|
||||
in: "",
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, item := range table {
|
||||
scheme, name, port, valid := SplitSchemeNamePort(item.in)
|
||||
if e, a := item.scheme, scheme; e != a {
|
||||
t.Errorf("%q: Wanted %q, got %q", item.in, e, a)
|
||||
}
|
||||
if e, a := item.name, name; e != a {
|
||||
t.Errorf("%q: Wanted %q, got %q", item.in, e, a)
|
||||
}
|
||||
if e, a := item.port, port; e != a {
|
||||
t.Errorf("%q: Wanted %q, got %q", item.in, e, a)
|
||||
}
|
||||
if e, a := item.valid, valid; e != a {
|
||||
t.Errorf("%q: Wanted %t, got %t", item.in, e, a)
|
||||
}
|
||||
|
||||
// Make sure valid items round trip through JoinSchemeNamePort
|
||||
if item.valid {
|
||||
out := JoinSchemeNamePort(scheme, name, port)
|
||||
if item.normalized && out != item.in {
|
||||
t.Errorf("%q: Wanted %s, got %s", item.in, item.in, out)
|
||||
}
|
||||
scheme, name, port, valid := SplitSchemeNamePort(out)
|
||||
if e, a := item.scheme, scheme; e != a {
|
||||
t.Errorf("%q: Wanted %q, got %q", item.in, e, a)
|
||||
}
|
||||
if e, a := item.name, name; e != a {
|
||||
t.Errorf("%q: Wanted %q, got %q", item.in, e, a)
|
||||
}
|
||||
if e, a := item.port, port; e != a {
|
||||
t.Errorf("%q: Wanted %q, got %q", item.in, e, a)
|
||||
}
|
||||
if e, a := item.valid, valid; e != a {
|
||||
t.Errorf("%q: Wanted %t, got %t", item.in, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
68
vendor/k8s.io/apimachinery/pkg/util/net/util_test.go
generated
vendored
68
vendor/k8s.io/apimachinery/pkg/util/net/util_test.go
generated
vendored
|
|
@ -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 net
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func getIPNet(cidr string) *net.IPNet {
|
||||
_, ipnet, _ := net.ParseCIDR(cidr)
|
||||
return ipnet
|
||||
}
|
||||
|
||||
func TestIPNetEqual(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ipnet1 *net.IPNet
|
||||
ipnet2 *net.IPNet
|
||||
expect bool
|
||||
}{
|
||||
//null case
|
||||
{
|
||||
getIPNet("10.0.0.1/24"),
|
||||
getIPNet(""),
|
||||
false,
|
||||
},
|
||||
{
|
||||
getIPNet("10.0.0.0/24"),
|
||||
getIPNet("10.0.0.0/24"),
|
||||
true,
|
||||
},
|
||||
{
|
||||
getIPNet("10.0.0.0/24"),
|
||||
getIPNet("10.0.0.1/24"),
|
||||
true,
|
||||
},
|
||||
{
|
||||
getIPNet("10.0.0.0/25"),
|
||||
getIPNet("10.0.0.0/24"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
getIPNet("10.0.1.0/24"),
|
||||
getIPNet("10.0.0.0/24"),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
if tc.expect != IPNetEqual(tc.ipnet1, tc.ipnet2) {
|
||||
t.Errorf("Expect equality of %s and %s be to %v", tc.ipnet1.String(), tc.ipnet2.String(), tc.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
26
vendor/k8s.io/apimachinery/pkg/util/remotecommand/BUILD
generated
vendored
26
vendor/k8s.io/apimachinery/pkg/util/remotecommand/BUILD
generated
vendored
|
|
@ -1,26 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["constants.go"],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/remotecommand",
|
||||
deps = ["//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
33
vendor/k8s.io/apimachinery/pkg/util/runtime/BUILD
generated
vendored
33
vendor/k8s.io/apimachinery/pkg/util/runtime/BUILD
generated
vendored
|
|
@ -1,33 +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 = ["runtime_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["runtime.go"],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/runtime",
|
||||
deps = ["//vendor/github.com/golang/glog:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
71
vendor/k8s.io/apimachinery/pkg/util/runtime/runtime_test.go
generated
vendored
71
vendor/k8s.io/apimachinery/pkg/util/runtime/runtime_test.go
generated
vendored
|
|
@ -1,71 +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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandleCrash(t *testing.T) {
|
||||
defer func() {
|
||||
if x := recover(); x == nil {
|
||||
t.Errorf("Expected a panic to recover from")
|
||||
}
|
||||
}()
|
||||
defer HandleCrash()
|
||||
panic("Test Panic")
|
||||
}
|
||||
|
||||
func TestCustomHandleCrash(t *testing.T) {
|
||||
old := PanicHandlers
|
||||
defer func() { PanicHandlers = old }()
|
||||
var result interface{}
|
||||
PanicHandlers = []func(interface{}){
|
||||
func(r interface{}) {
|
||||
result = r
|
||||
},
|
||||
}
|
||||
func() {
|
||||
defer func() {
|
||||
if x := recover(); x == nil {
|
||||
t.Errorf("Expected a panic to recover from")
|
||||
}
|
||||
}()
|
||||
defer HandleCrash()
|
||||
panic("test")
|
||||
}()
|
||||
if result != "test" {
|
||||
t.Errorf("did not receive custom handler")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomHandleError(t *testing.T) {
|
||||
old := ErrorHandlers
|
||||
defer func() { ErrorHandlers = old }()
|
||||
var result error
|
||||
ErrorHandlers = []func(error){
|
||||
func(err error) {
|
||||
result = err
|
||||
},
|
||||
}
|
||||
err := fmt.Errorf("test")
|
||||
HandleError(err)
|
||||
if result != err {
|
||||
t.Errorf("did not receive custom handler")
|
||||
}
|
||||
}
|
||||
71
vendor/k8s.io/apimachinery/pkg/util/sets/BUILD
generated
vendored
71
vendor/k8s.io/apimachinery/pkg/util/sets/BUILD
generated
vendored
|
|
@ -1,71 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@io_kubernetes_build//defs:go.bzl", "go_genrule")
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"byte.go",
|
||||
"doc.go",
|
||||
"empty.go",
|
||||
"int.go",
|
||||
"int64.go",
|
||||
"string.go",
|
||||
],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/sets",
|
||||
)
|
||||
|
||||
go_genrule(
|
||||
name = "set-gen",
|
||||
srcs = [
|
||||
"//hack/boilerplate:boilerplate.go.txt",
|
||||
],
|
||||
outs = [
|
||||
"byte.go",
|
||||
"doc.go",
|
||||
"empty.go",
|
||||
"int.go",
|
||||
"int64.go",
|
||||
"string.go",
|
||||
],
|
||||
cmd = """
|
||||
$(location //vendor/k8s.io/code-generator/cmd/set-gen) \
|
||||
--input-dirs ./vendor/k8s.io/apimachinery/pkg/util/sets/types \
|
||||
--output-base $$(dirname $$(dirname $(location :byte.go))) \
|
||||
--go-header-file $(location //hack/boilerplate:boilerplate.go.txt) \
|
||||
--output-package sets
|
||||
""",
|
||||
go_deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets/types:go_default_library",
|
||||
],
|
||||
tools = [
|
||||
"//vendor/k8s.io/code-generator/cmd/set-gen",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["set_test.go"],
|
||||
embed = [":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/util/sets/types:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
270
vendor/k8s.io/apimachinery/pkg/util/sets/set_test.go
generated
vendored
270
vendor/k8s.io/apimachinery/pkg/util/sets/set_test.go
generated
vendored
|
|
@ -1,270 +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 sets
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStringSet(t *testing.T) {
|
||||
s := String{}
|
||||
s2 := String{}
|
||||
if len(s) != 0 {
|
||||
t.Errorf("Expected len=0: %d", len(s))
|
||||
}
|
||||
s.Insert("a", "b")
|
||||
if len(s) != 2 {
|
||||
t.Errorf("Expected len=2: %d", len(s))
|
||||
}
|
||||
s.Insert("c")
|
||||
if s.Has("d") {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
if !s.Has("a") {
|
||||
t.Errorf("Missing contents: %#v", s)
|
||||
}
|
||||
s.Delete("a")
|
||||
if s.Has("a") {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
s.Insert("a")
|
||||
if s.HasAll("a", "b", "d") {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
if !s.HasAll("a", "b") {
|
||||
t.Errorf("Missing contents: %#v", s)
|
||||
}
|
||||
s2.Insert("a", "b", "d")
|
||||
if s.IsSuperset(s2) {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
s2.Delete("d")
|
||||
if !s.IsSuperset(s2) {
|
||||
t.Errorf("Missing contents: %#v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSetDeleteMultiples(t *testing.T) {
|
||||
s := String{}
|
||||
s.Insert("a", "b", "c")
|
||||
if len(s) != 3 {
|
||||
t.Errorf("Expected len=3: %d", len(s))
|
||||
}
|
||||
|
||||
s.Delete("a", "c")
|
||||
if len(s) != 1 {
|
||||
t.Errorf("Expected len=1: %d", len(s))
|
||||
}
|
||||
if s.Has("a") {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
if s.Has("c") {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
if !s.Has("b") {
|
||||
t.Errorf("Missing contents: %#v", s)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNewStringSet(t *testing.T) {
|
||||
s := NewString("a", "b", "c")
|
||||
if len(s) != 3 {
|
||||
t.Errorf("Expected len=3: %d", len(s))
|
||||
}
|
||||
if !s.Has("a") || !s.Has("b") || !s.Has("c") {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSetList(t *testing.T) {
|
||||
s := NewString("z", "y", "x", "a")
|
||||
if !reflect.DeepEqual(s.List(), []string{"a", "x", "y", "z"}) {
|
||||
t.Errorf("List gave unexpected result: %#v", s.List())
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSetDifference(t *testing.T) {
|
||||
a := NewString("1", "2", "3")
|
||||
b := NewString("1", "2", "4", "5")
|
||||
c := a.Difference(b)
|
||||
d := b.Difference(a)
|
||||
if len(c) != 1 {
|
||||
t.Errorf("Expected len=1: %d", len(c))
|
||||
}
|
||||
if !c.Has("3") {
|
||||
t.Errorf("Unexpected contents: %#v", c.List())
|
||||
}
|
||||
if len(d) != 2 {
|
||||
t.Errorf("Expected len=2: %d", len(d))
|
||||
}
|
||||
if !d.Has("4") || !d.Has("5") {
|
||||
t.Errorf("Unexpected contents: %#v", d.List())
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSetHasAny(t *testing.T) {
|
||||
a := NewString("1", "2", "3")
|
||||
|
||||
if !a.HasAny("1", "4") {
|
||||
t.Errorf("expected true, got false")
|
||||
}
|
||||
|
||||
if a.HasAny("0", "4") {
|
||||
t.Errorf("expected false, got true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSetEquals(t *testing.T) {
|
||||
// Simple case (order doesn't matter)
|
||||
a := NewString("1", "2")
|
||||
b := NewString("2", "1")
|
||||
if !a.Equal(b) {
|
||||
t.Errorf("Expected to be equal: %v vs %v", a, b)
|
||||
}
|
||||
|
||||
// It is a set; duplicates are ignored
|
||||
b = NewString("2", "2", "1")
|
||||
if !a.Equal(b) {
|
||||
t.Errorf("Expected to be equal: %v vs %v", a, b)
|
||||
}
|
||||
|
||||
// Edge cases around empty sets / empty strings
|
||||
a = NewString()
|
||||
b = NewString()
|
||||
if !a.Equal(b) {
|
||||
t.Errorf("Expected to be equal: %v vs %v", a, b)
|
||||
}
|
||||
|
||||
b = NewString("1", "2", "3")
|
||||
if a.Equal(b) {
|
||||
t.Errorf("Expected to be not-equal: %v vs %v", a, b)
|
||||
}
|
||||
|
||||
b = NewString("1", "2", "")
|
||||
if a.Equal(b) {
|
||||
t.Errorf("Expected to be not-equal: %v vs %v", a, b)
|
||||
}
|
||||
|
||||
// Check for equality after mutation
|
||||
a = NewString()
|
||||
a.Insert("1")
|
||||
if a.Equal(b) {
|
||||
t.Errorf("Expected to be not-equal: %v vs %v", a, b)
|
||||
}
|
||||
|
||||
a.Insert("2")
|
||||
if a.Equal(b) {
|
||||
t.Errorf("Expected to be not-equal: %v vs %v", a, b)
|
||||
}
|
||||
|
||||
a.Insert("")
|
||||
if !a.Equal(b) {
|
||||
t.Errorf("Expected to be equal: %v vs %v", a, b)
|
||||
}
|
||||
|
||||
a.Delete("")
|
||||
if a.Equal(b) {
|
||||
t.Errorf("Expected to be not-equal: %v vs %v", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringUnion(t *testing.T) {
|
||||
tests := []struct {
|
||||
s1 String
|
||||
s2 String
|
||||
expected String
|
||||
}{
|
||||
{
|
||||
NewString("1", "2", "3", "4"),
|
||||
NewString("3", "4", "5", "6"),
|
||||
NewString("1", "2", "3", "4", "5", "6"),
|
||||
},
|
||||
{
|
||||
NewString("1", "2", "3", "4"),
|
||||
NewString(),
|
||||
NewString("1", "2", "3", "4"),
|
||||
},
|
||||
{
|
||||
NewString(),
|
||||
NewString("1", "2", "3", "4"),
|
||||
NewString("1", "2", "3", "4"),
|
||||
},
|
||||
{
|
||||
NewString(),
|
||||
NewString(),
|
||||
NewString(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
union := test.s1.Union(test.s2)
|
||||
if union.Len() != test.expected.Len() {
|
||||
t.Errorf("Expected union.Len()=%d but got %d", test.expected.Len(), union.Len())
|
||||
}
|
||||
|
||||
if !union.Equal(test.expected) {
|
||||
t.Errorf("Expected union.Equal(expected) but not true. union:%v expected:%v", union.List(), test.expected.List())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringIntersection(t *testing.T) {
|
||||
tests := []struct {
|
||||
s1 String
|
||||
s2 String
|
||||
expected String
|
||||
}{
|
||||
{
|
||||
NewString("1", "2", "3", "4"),
|
||||
NewString("3", "4", "5", "6"),
|
||||
NewString("3", "4"),
|
||||
},
|
||||
{
|
||||
NewString("1", "2", "3", "4"),
|
||||
NewString("1", "2", "3", "4"),
|
||||
NewString("1", "2", "3", "4"),
|
||||
},
|
||||
{
|
||||
NewString("1", "2", "3", "4"),
|
||||
NewString(),
|
||||
NewString(),
|
||||
},
|
||||
{
|
||||
NewString(),
|
||||
NewString("1", "2", "3", "4"),
|
||||
NewString(),
|
||||
},
|
||||
{
|
||||
NewString(),
|
||||
NewString(),
|
||||
NewString(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
intersection := test.s1.Intersection(test.s2)
|
||||
if intersection.Len() != test.expected.Len() {
|
||||
t.Errorf("Expected intersection.Len()=%d but got %d", test.expected.Len(), intersection.Len())
|
||||
}
|
||||
|
||||
if !intersection.Equal(test.expected) {
|
||||
t.Errorf("Expected intersection.Equal(expected) but not true. intersection:%v expected:%v", intersection.List(), test.expected.List())
|
||||
}
|
||||
}
|
||||
}
|
||||
60
vendor/k8s.io/apimachinery/pkg/util/strategicpatch/BUILD
generated
vendored
60
vendor/k8s.io/apimachinery/pkg/util/strategicpatch/BUILD
generated
vendored
|
|
@ -1,60 +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 = ["patch_test.go"],
|
||||
data = [
|
||||
"testdata/swagger-merge-item.json",
|
||||
"testdata/swagger-precision-item.json",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
|
||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/strategicpatch/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"errors.go",
|
||||
"meta.go",
|
||||
"patch.go",
|
||||
"types.go",
|
||||
],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/strategicpatch",
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/third_party/forked/golang/json:go_default_library",
|
||||
"//vendor/k8s.io/kube-openapi/pkg/util/proto: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/util/strategicpatch/testing:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
6763
vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go
generated
vendored
6763
vendor/k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
29
vendor/k8s.io/apimachinery/pkg/util/uuid/BUILD
generated
vendored
29
vendor/k8s.io/apimachinery/pkg/util/uuid/BUILD
generated
vendored
|
|
@ -1,29 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["uuid.go"],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/uuid",
|
||||
deps = [
|
||||
"//vendor/github.com/pborman/uuid:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
37
vendor/k8s.io/apimachinery/pkg/util/validation/BUILD
generated
vendored
37
vendor/k8s.io/apimachinery/pkg/util/validation/BUILD
generated
vendored
|
|
@ -1,37 +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/util/validation",
|
||||
deps = ["//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/util/validation/field:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
42
vendor/k8s.io/apimachinery/pkg/util/validation/field/BUILD
generated
vendored
42
vendor/k8s.io/apimachinery/pkg/util/validation/field/BUILD
generated
vendored
|
|
@ -1,42 +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",
|
||||
"path_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"errors.go",
|
||||
"path.go",
|
||||
],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/validation/field",
|
||||
deps = [
|
||||
"//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"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
175
vendor/k8s.io/apimachinery/pkg/util/validation/field/errors_test.go
generated
vendored
175
vendor/k8s.io/apimachinery/pkg/util/validation/field/errors_test.go
generated
vendored
|
|
@ -1,175 +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 field
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMakeFuncs(t *testing.T) {
|
||||
testCases := []struct {
|
||||
fn func() *Error
|
||||
expected ErrorType
|
||||
}{
|
||||
{
|
||||
func() *Error { return Invalid(NewPath("f"), "v", "d") },
|
||||
ErrorTypeInvalid,
|
||||
},
|
||||
{
|
||||
func() *Error { return NotSupported(NewPath("f"), "v", nil) },
|
||||
ErrorTypeNotSupported,
|
||||
},
|
||||
{
|
||||
func() *Error { return Duplicate(NewPath("f"), "v") },
|
||||
ErrorTypeDuplicate,
|
||||
},
|
||||
{
|
||||
func() *Error { return NotFound(NewPath("f"), "v") },
|
||||
ErrorTypeNotFound,
|
||||
},
|
||||
{
|
||||
func() *Error { return Required(NewPath("f"), "d") },
|
||||
ErrorTypeRequired,
|
||||
},
|
||||
{
|
||||
func() *Error { return InternalError(NewPath("f"), fmt.Errorf("e")) },
|
||||
ErrorTypeInternal,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
err := testCase.fn()
|
||||
if err.Type != testCase.expected {
|
||||
t.Errorf("expected Type %q, got %q", testCase.expected, err.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorUsefulMessage(t *testing.T) {
|
||||
{
|
||||
s := Invalid(nil, nil, "").Error()
|
||||
t.Logf("message: %v", s)
|
||||
if !strings.Contains(s, "null") {
|
||||
t.Errorf("error message did not contain 'null': %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
s := Invalid(NewPath("foo"), "bar", "deet").Error()
|
||||
t.Logf("message: %v", s)
|
||||
for _, part := range []string{"foo", "bar", "deet", ErrorTypeInvalid.String()} {
|
||||
if !strings.Contains(s, part) {
|
||||
t.Errorf("error message did not contain expected part '%v'", part)
|
||||
}
|
||||
}
|
||||
|
||||
type complicated struct {
|
||||
Baz int
|
||||
Qux string
|
||||
Inner interface{}
|
||||
KV map[string]int
|
||||
}
|
||||
s = Invalid(
|
||||
NewPath("foo"),
|
||||
&complicated{
|
||||
Baz: 1,
|
||||
Qux: "aoeu",
|
||||
Inner: &complicated{Qux: "asdf"},
|
||||
KV: map[string]int{"Billy": 2},
|
||||
},
|
||||
"detail",
|
||||
).Error()
|
||||
t.Logf("message: %v", s)
|
||||
for _, part := range []string{
|
||||
"foo", ErrorTypeInvalid.String(),
|
||||
"Baz", "Qux", "Inner", "KV", "detail",
|
||||
"1", "aoeu", "Billy", "2",
|
||||
// "asdf", TODO: re-enable once we have a better nested printer
|
||||
} {
|
||||
if !strings.Contains(s, part) {
|
||||
t.Errorf("error message did not contain expected part '%v'", part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestToAggregate(t *testing.T) {
|
||||
testCases := struct {
|
||||
ErrList []ErrorList
|
||||
NumExpectedErrs []int
|
||||
}{
|
||||
[]ErrorList{
|
||||
nil,
|
||||
{},
|
||||
{Invalid(NewPath("f"), "v", "d")},
|
||||
{Invalid(NewPath("f"), "v", "d"), Invalid(NewPath("f"), "v", "d")},
|
||||
{Invalid(NewPath("f"), "v", "d"), InternalError(NewPath(""), fmt.Errorf("e"))},
|
||||
},
|
||||
[]int{
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
},
|
||||
}
|
||||
|
||||
if len(testCases.ErrList) != len(testCases.NumExpectedErrs) {
|
||||
t.Errorf("Mismatch: length of NumExpectedErrs does not match length of ErrList")
|
||||
}
|
||||
for i, tc := range testCases.ErrList {
|
||||
agg := tc.ToAggregate()
|
||||
numErrs := 0
|
||||
|
||||
if agg != nil {
|
||||
numErrs = len(agg.Errors())
|
||||
}
|
||||
if numErrs != testCases.NumExpectedErrs[i] {
|
||||
t.Errorf("[%d] Expected %d, got %d", i, testCases.NumExpectedErrs[i], numErrs)
|
||||
}
|
||||
|
||||
if len(tc) == 0 {
|
||||
if agg != nil {
|
||||
t.Errorf("[%d] Expected nil, got %#v", i, agg)
|
||||
}
|
||||
} else if agg == nil {
|
||||
t.Errorf("[%d] Expected non-nil", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrListFilter(t *testing.T) {
|
||||
list := ErrorList{
|
||||
Invalid(NewPath("test.field"), "", ""),
|
||||
Invalid(NewPath("field.test"), "", ""),
|
||||
Duplicate(NewPath("test"), "value"),
|
||||
}
|
||||
if len(list.Filter(NewErrorTypeMatcher(ErrorTypeDuplicate))) != 2 {
|
||||
t.Errorf("should not filter")
|
||||
}
|
||||
if len(list.Filter(NewErrorTypeMatcher(ErrorTypeInvalid))) != 1 {
|
||||
t.Errorf("should filter")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotSupported(t *testing.T) {
|
||||
notSupported := NotSupported(NewPath("f"), "v", []string{"a", "b", "c"})
|
||||
expected := `Unsupported value: "v": supported values: "a", "b", "c"`
|
||||
if notSupported.ErrorBody() != expected {
|
||||
t.Errorf("Expected: %s\n, but got: %s\n", expected, notSupported.ErrorBody())
|
||||
}
|
||||
}
|
||||
123
vendor/k8s.io/apimachinery/pkg/util/validation/field/path_test.go
generated
vendored
123
vendor/k8s.io/apimachinery/pkg/util/validation/field/path_test.go
generated
vendored
|
|
@ -1,123 +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 field
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestPath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
op func(*Path) *Path
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
func(p *Path) *Path { return p },
|
||||
"root",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.Child("first") },
|
||||
"root.first",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.Child("second") },
|
||||
"root.first.second",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.Index(0) },
|
||||
"root.first.second[0]",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.Child("third") },
|
||||
"root.first.second[0].third",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.Index(93) },
|
||||
"root.first.second[0].third[93]",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.parent },
|
||||
"root.first.second[0].third",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.parent },
|
||||
"root.first.second[0]",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.Key("key") },
|
||||
"root.first.second[0][key]",
|
||||
},
|
||||
}
|
||||
|
||||
root := NewPath("root")
|
||||
p := root
|
||||
for i, tc := range testCases {
|
||||
p = tc.op(p)
|
||||
if p.String() != tc.expected {
|
||||
t.Errorf("[%d] Expected %q, got %q", i, tc.expected, p.String())
|
||||
}
|
||||
if p.Root() != root {
|
||||
t.Errorf("[%d] Wrong root: %#v", i, p.Root())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathMultiArg(t *testing.T) {
|
||||
testCases := []struct {
|
||||
op func(*Path) *Path
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
func(p *Path) *Path { return p },
|
||||
"root.first",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.Child("second", "third") },
|
||||
"root.first.second.third",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.Index(0) },
|
||||
"root.first.second.third[0]",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.parent },
|
||||
"root.first.second.third",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.parent },
|
||||
"root.first.second",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.parent },
|
||||
"root.first",
|
||||
},
|
||||
{
|
||||
func(p *Path) *Path { return p.parent },
|
||||
"root",
|
||||
},
|
||||
}
|
||||
|
||||
root := NewPath("root", "first")
|
||||
p := root
|
||||
for i, tc := range testCases {
|
||||
p = tc.op(p)
|
||||
if p.String() != tc.expected {
|
||||
t.Errorf("[%d] Expected %q, got %q", i, tc.expected, p.String())
|
||||
}
|
||||
if p.Root() != root.Root() {
|
||||
t.Errorf("[%d] Wrong root: %#v", i, p.Root())
|
||||
}
|
||||
}
|
||||
}
|
||||
513
vendor/k8s.io/apimachinery/pkg/util/validation/validation_test.go
generated
vendored
513
vendor/k8s.io/apimachinery/pkg/util/validation/validation_test.go
generated
vendored
|
|
@ -1,513 +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 validation
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func TestIsDNS1123Label(t *testing.T) {
|
||||
goodValues := []string{
|
||||
"a", "ab", "abc", "a1", "a-1", "a--1--2--b",
|
||||
"0", "01", "012", "1a", "1-a", "1--a--b--2",
|
||||
strings.Repeat("a", 63),
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsDNS1123Label(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for '%s': %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"", "A", "ABC", "aBc", "A1", "A-1", "1-A",
|
||||
"-", "a-", "-a", "1-", "-1",
|
||||
"_", "a_", "_a", "a_b", "1_", "_1", "1_2",
|
||||
".", "a.", ".a", "a.b", "1.", ".1", "1.2",
|
||||
" ", "a ", " a", "a b", "1 ", " 1", "1 2",
|
||||
strings.Repeat("a", 64),
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsDNS1123Label(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for '%s'", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsDNS1123Subdomain(t *testing.T) {
|
||||
goodValues := []string{
|
||||
"a", "ab", "abc", "a1", "a-1", "a--1--2--b",
|
||||
"0", "01", "012", "1a", "1-a", "1--a--b--2",
|
||||
"a.a", "ab.a", "abc.a", "a1.a", "a-1.a", "a--1--2--b.a",
|
||||
"a.1", "ab.1", "abc.1", "a1.1", "a-1.1", "a--1--2--b.1",
|
||||
"0.a", "01.a", "012.a", "1a.a", "1-a.a", "1--a--b--2",
|
||||
"0.1", "01.1", "012.1", "1a.1", "1-a.1", "1--a--b--2.1",
|
||||
"a.b.c.d.e", "aa.bb.cc.dd.ee", "1.2.3.4.5", "11.22.33.44.55",
|
||||
strings.Repeat("a", 253),
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsDNS1123Subdomain(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for '%s': %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"", "A", "ABC", "aBc", "A1", "A-1", "1-A",
|
||||
"-", "a-", "-a", "1-", "-1",
|
||||
"_", "a_", "_a", "a_b", "1_", "_1", "1_2",
|
||||
".", "a.", ".a", "a..b", "1.", ".1", "1..2",
|
||||
" ", "a ", " a", "a b", "1 ", " 1", "1 2",
|
||||
"A.a", "aB.a", "ab.A", "A1.a", "a1.A",
|
||||
"A.1", "aB.1", "A1.1", "1A.1",
|
||||
"0.A", "01.A", "012.A", "1A.a", "1a.A",
|
||||
"A.B.C.D.E", "AA.BB.CC.DD.EE", "a.B.c.d.e", "aa.bB.cc.dd.ee",
|
||||
"a@b", "a,b", "a_b", "a;b",
|
||||
"a:b", "a%b", "a?b", "a$b",
|
||||
strings.Repeat("a", 254),
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsDNS1123Subdomain(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for '%s'", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsDNS1035Label(t *testing.T) {
|
||||
goodValues := []string{
|
||||
"a", "ab", "abc", "a1", "a-1", "a--1--2--b",
|
||||
strings.Repeat("a", 63),
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsDNS1035Label(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for '%s': %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"0", "01", "012", "1a", "1-a", "1--a--b--2",
|
||||
"", "A", "ABC", "aBc", "A1", "A-1", "1-A",
|
||||
"-", "a-", "-a", "1-", "-1",
|
||||
"_", "a_", "_a", "a_b", "1_", "_1", "1_2",
|
||||
".", "a.", ".a", "a.b", "1.", ".1", "1.2",
|
||||
" ", "a ", " a", "a b", "1 ", " 1", "1 2",
|
||||
strings.Repeat("a", 64),
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsDNS1035Label(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for '%s'", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsCIdentifier(t *testing.T) {
|
||||
goodValues := []string{
|
||||
"a", "ab", "abc", "a1", "_a", "a_", "a_b", "a_1", "a__1__2__b", "__abc_123",
|
||||
"A", "AB", "AbC", "A1", "_A", "A_", "A_B", "A_1", "A__1__2__B", "__123_ABC",
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsCIdentifier(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for '%s': %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"", "1", "123", "1a",
|
||||
"-", "a-", "-a", "1-", "-1", "1_", "1_2",
|
||||
".", "a.", ".a", "a.b", "1.", ".1", "1.2",
|
||||
" ", "a ", " a", "a b", "1 ", " 1", "1 2",
|
||||
"#a#",
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsCIdentifier(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for '%s'", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidPortNum(t *testing.T) {
|
||||
goodValues := []int{1, 2, 1000, 16384, 32768, 65535}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsValidPortNum(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for %d, got %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []int{0, -1, 65536, 100000}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsValidPortNum(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for %d", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInRange(t *testing.T) {
|
||||
goodValues := []struct {
|
||||
value int
|
||||
min int
|
||||
max int
|
||||
}{{1, 0, 10}, {5, 5, 20}, {25, 10, 25}}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsInRange(val.value, val.min, val.max); len(msgs) > 0 {
|
||||
t.Errorf("expected no errors for %#v, but got %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []struct {
|
||||
value int
|
||||
min int
|
||||
max int
|
||||
}{{1, 2, 10}, {5, -4, 2}, {25, 100, 120}}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsInRange(val.value, val.min, val.max); len(msgs) == 0 {
|
||||
t.Errorf("expected errors for %#v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createGroupIDs(ids ...int64) []int64 {
|
||||
var output []int64
|
||||
for _, id := range ids {
|
||||
output = append(output, int64(id))
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func createUserIDs(ids ...int64) []int64 {
|
||||
var output []int64
|
||||
for _, id := range ids {
|
||||
output = append(output, int64(id))
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func TestIsValidGroupID(t *testing.T) {
|
||||
goodValues := createGroupIDs(0, 1, 1000, 65535, 2147483647)
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsValidGroupID(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for '%d': %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := createGroupIDs(-1, -1003, 2147483648, 4147483647)
|
||||
for _, val := range badValues {
|
||||
if msgs := IsValidGroupID(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for '%d'", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidUserID(t *testing.T) {
|
||||
goodValues := createUserIDs(0, 1, 1000, 65535, 2147483647)
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsValidUserID(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for '%d': %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := createUserIDs(-1, -1003, 2147483648, 4147483647)
|
||||
for _, val := range badValues {
|
||||
if msgs := IsValidUserID(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for '%d'", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidPortName(t *testing.T) {
|
||||
goodValues := []string{"telnet", "re-mail-ck", "pop3", "a", "a-1", "1-a", "a-1-b-2-c", "1-a-2-b-3"}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsValidPortName(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for %q: %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{"longerthan15characters", "", strings.Repeat("a", 16), "12345", "1-2-3-4", "-begin", "end-", "two--hyphens", "whois++"}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsValidPortName(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for %q", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsQualifiedName(t *testing.T) {
|
||||
successCases := []string{
|
||||
"simple",
|
||||
"now-with-dashes",
|
||||
"1-starts-with-num",
|
||||
"1234",
|
||||
"simple/simple",
|
||||
"now-with-dashes/simple",
|
||||
"now-with-dashes/now-with-dashes",
|
||||
"now.with.dots/simple",
|
||||
"now-with.dashes-and.dots/simple",
|
||||
"1-num.2-num/3-num",
|
||||
"1234/5678",
|
||||
"1.2.3.4/5678",
|
||||
"Uppercase_Is_OK_123",
|
||||
"example.com/Uppercase_Is_OK_123",
|
||||
"requests.storage-foo",
|
||||
strings.Repeat("a", 63),
|
||||
strings.Repeat("a", 253) + "/" + strings.Repeat("b", 63),
|
||||
}
|
||||
for i := range successCases {
|
||||
if errs := IsQualifiedName(successCases[i]); len(errs) != 0 {
|
||||
t.Errorf("case[%d]: %q: expected success: %v", i, successCases[i], errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := []string{
|
||||
"nospecialchars%^=@",
|
||||
"cantendwithadash-",
|
||||
"-cantstartwithadash-",
|
||||
"only/one/slash",
|
||||
"Example.com/abc",
|
||||
"example_com/abc",
|
||||
"example.com/",
|
||||
"/simple",
|
||||
strings.Repeat("a", 64),
|
||||
strings.Repeat("a", 254) + "/abc",
|
||||
}
|
||||
for i := range errorCases {
|
||||
if errs := IsQualifiedName(errorCases[i]); len(errs) == 0 {
|
||||
t.Errorf("case[%d]: %q: expected failure", i, errorCases[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidLabelValue(t *testing.T) {
|
||||
successCases := []string{
|
||||
"simple",
|
||||
"now-with-dashes",
|
||||
"1-starts-with-num",
|
||||
"end-with-num-1",
|
||||
"1234", // only num
|
||||
strings.Repeat("a", 63), // to the limit
|
||||
"", // empty value
|
||||
}
|
||||
for i := range successCases {
|
||||
if errs := IsValidLabelValue(successCases[i]); len(errs) != 0 {
|
||||
t.Errorf("case %s expected success: %v", successCases[i], errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := []string{
|
||||
"nospecialchars%^=@",
|
||||
"Tama-nui-te-rā.is.Māori.sun",
|
||||
"\\backslashes\\are\\bad",
|
||||
"-starts-with-dash",
|
||||
"ends-with-dash-",
|
||||
".starts.with.dot",
|
||||
"ends.with.dot.",
|
||||
strings.Repeat("a", 64), // over the limit
|
||||
}
|
||||
for i := range errorCases {
|
||||
if errs := IsValidLabelValue(errorCases[i]); len(errs) == 0 {
|
||||
t.Errorf("case[%d] expected failure", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidIP(t *testing.T) {
|
||||
goodValues := []string{
|
||||
"::1",
|
||||
"2a00:79e0:2:0:f1c3:e797:93c1:df80",
|
||||
"::",
|
||||
"2001:4860:4860::8888",
|
||||
"::fff:1.1.1.1",
|
||||
"1.1.1.1",
|
||||
"1.1.1.01",
|
||||
"255.0.0.1",
|
||||
"1.0.0.0",
|
||||
"0.0.0.0",
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsValidIP(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for %q: %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"[2001:db8:0:1]:80",
|
||||
"myhost.mydomain",
|
||||
"-1.0.0.0",
|
||||
"[2001:db8:0:1]",
|
||||
"a",
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsValidIP(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for %q", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsHTTPHeaderName(t *testing.T) {
|
||||
goodValues := []string{
|
||||
// Common ones
|
||||
"Accept-Encoding", "Host", "If-Modified-Since", "X-Forwarded-For",
|
||||
// Weirdo, but still conforming names
|
||||
"a", "ab", "abc", "a1", "-a", "a-", "a-b", "a-1", "a--1--2--b", "--abc-123",
|
||||
"A", "AB", "AbC", "A1", "-A", "A-", "A-B", "A-1", "A--1--2--B", "--123-ABC",
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsHTTPHeaderName(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for '%s': %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"Host:", "X-Forwarded-For:", "X-@Home",
|
||||
"", "_", "a_", "_a", "1_", "1_2", ".", "a.", ".a", "a.b", "1.", ".1", "1.2",
|
||||
" ", "a ", " a", "a b", "1 ", " 1", "1 2", "#a#", "^", ",", ";", "=", "<",
|
||||
"?", "@", "{",
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsHTTPHeaderName(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for '%s'", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidPercent(t *testing.T) {
|
||||
goodValues := []string{
|
||||
"0%",
|
||||
"00000%",
|
||||
"1%",
|
||||
"01%",
|
||||
"99%",
|
||||
"100%",
|
||||
"101%",
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if msgs := IsValidPercent(val); len(msgs) != 0 {
|
||||
t.Errorf("expected true for %q: %v", val, msgs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"",
|
||||
"0",
|
||||
"100",
|
||||
"0.0%",
|
||||
"99.9%",
|
||||
"hundred",
|
||||
" 1%",
|
||||
"1% ",
|
||||
"-0%",
|
||||
"-1%",
|
||||
"+1%",
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if msgs := IsValidPercent(val); len(msgs) == 0 {
|
||||
t.Errorf("expected false for %q", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsConfigMapKey(t *testing.T) {
|
||||
successCases := []string{
|
||||
"a",
|
||||
"good",
|
||||
"good-good",
|
||||
"still.good",
|
||||
"this.is.also.good",
|
||||
".so.is.this",
|
||||
"THIS_IS_GOOD",
|
||||
"so_is_this_17",
|
||||
}
|
||||
|
||||
for i := range successCases {
|
||||
if errs := IsConfigMapKey(successCases[i]); len(errs) != 0 {
|
||||
t.Errorf("[%d] expected success: %v", i, errs)
|
||||
}
|
||||
}
|
||||
|
||||
failureCases := []string{
|
||||
".",
|
||||
"..",
|
||||
"..bad",
|
||||
"b*d",
|
||||
"bad!&bad",
|
||||
}
|
||||
|
||||
for i := range failureCases {
|
||||
if errs := IsConfigMapKey(failureCases[i]); len(errs) == 0 {
|
||||
t.Errorf("[%d] expected failure", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsWildcardDNS1123Subdomain(t *testing.T) {
|
||||
goodValues := []string{
|
||||
"*.example.com",
|
||||
"*.bar.com",
|
||||
"*.foo.bar.com",
|
||||
}
|
||||
for _, val := range goodValues {
|
||||
if errs := IsWildcardDNS1123Subdomain(val); len(errs) != 0 {
|
||||
t.Errorf("expected no errors for %q: %v", val, errs)
|
||||
}
|
||||
}
|
||||
|
||||
badValues := []string{
|
||||
"*.*.bar.com",
|
||||
"*.foo.*.com",
|
||||
"*bar.com",
|
||||
"f*.bar.com",
|
||||
"*",
|
||||
}
|
||||
for _, val := range badValues {
|
||||
if errs := IsWildcardDNS1123Subdomain(val); len(errs) == 0 {
|
||||
t.Errorf("expected errors for %q", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsFullyQualifiedName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
targetName string
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "name needs to be fully qualified, i.e., contains at least 2 dots",
|
||||
targetName: "k8s.io",
|
||||
err: "should be a domain with at least three segments separated by dots",
|
||||
},
|
||||
{
|
||||
name: "name cannot be empty",
|
||||
targetName: "",
|
||||
err: "Required value",
|
||||
},
|
||||
{
|
||||
name: "name must conform to RFC 1123",
|
||||
targetName: "A.B.C",
|
||||
err: "a DNS-1123 subdomain must consist of lower case alphanumeric characters",
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
err := IsFullyQualifiedName(field.NewPath(""), tc.targetName).ToAggregate()
|
||||
switch {
|
||||
case tc.err == "" && err != nil:
|
||||
t.Errorf("%q: unexpected error: %v", tc.name, err)
|
||||
case tc.err != "" && err == nil:
|
||||
t.Errorf("%q: unexpected no error, expected %s", tc.name, tc.err)
|
||||
case tc.err != "" && err != nil && !strings.Contains(err.Error(), tc.err):
|
||||
t.Errorf("%q: expected %s, got %v", tc.name, tc.err, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
37
vendor/k8s.io/apimachinery/pkg/util/wait/BUILD
generated
vendored
37
vendor/k8s.io/apimachinery/pkg/util/wait/BUILD
generated
vendored
|
|
@ -1,37 +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 = ["wait_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"wait.go",
|
||||
],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/wait",
|
||||
deps = ["//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"],
|
||||
)
|
||||
501
vendor/k8s.io/apimachinery/pkg/util/wait/wait_test.go
generated
vendored
501
vendor/k8s.io/apimachinery/pkg/util/wait/wait_test.go
generated
vendored
|
|
@ -1,501 +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 wait
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
func TestUntil(t *testing.T) {
|
||||
ch := make(chan struct{})
|
||||
close(ch)
|
||||
Until(func() {
|
||||
t.Fatal("should not have been invoked")
|
||||
}, 0, ch)
|
||||
|
||||
ch = make(chan struct{})
|
||||
called := make(chan struct{})
|
||||
go func() {
|
||||
Until(func() {
|
||||
called <- struct{}{}
|
||||
}, 0, ch)
|
||||
close(called)
|
||||
}()
|
||||
<-called
|
||||
close(ch)
|
||||
<-called
|
||||
}
|
||||
|
||||
func TestNonSlidingUntil(t *testing.T) {
|
||||
ch := make(chan struct{})
|
||||
close(ch)
|
||||
NonSlidingUntil(func() {
|
||||
t.Fatal("should not have been invoked")
|
||||
}, 0, ch)
|
||||
|
||||
ch = make(chan struct{})
|
||||
called := make(chan struct{})
|
||||
go func() {
|
||||
NonSlidingUntil(func() {
|
||||
called <- struct{}{}
|
||||
}, 0, ch)
|
||||
close(called)
|
||||
}()
|
||||
<-called
|
||||
close(ch)
|
||||
<-called
|
||||
}
|
||||
|
||||
func TestUntilReturnsImmediately(t *testing.T) {
|
||||
now := time.Now()
|
||||
ch := make(chan struct{})
|
||||
Until(func() {
|
||||
close(ch)
|
||||
}, 30*time.Second, ch)
|
||||
if now.Add(25 * time.Second).Before(time.Now()) {
|
||||
t.Errorf("Until did not return immediately when the stop chan was closed inside the func")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJitterUntil(t *testing.T) {
|
||||
ch := make(chan struct{})
|
||||
// if a channel is closed JitterUntil never calls function f
|
||||
// and returns immediately
|
||||
close(ch)
|
||||
JitterUntil(func() {
|
||||
t.Fatal("should not have been invoked")
|
||||
}, 0, 1.0, true, ch)
|
||||
|
||||
ch = make(chan struct{})
|
||||
called := make(chan struct{})
|
||||
go func() {
|
||||
JitterUntil(func() {
|
||||
called <- struct{}{}
|
||||
}, 0, 1.0, true, ch)
|
||||
close(called)
|
||||
}()
|
||||
<-called
|
||||
close(ch)
|
||||
<-called
|
||||
}
|
||||
|
||||
func TestJitterUntilReturnsImmediately(t *testing.T) {
|
||||
now := time.Now()
|
||||
ch := make(chan struct{})
|
||||
JitterUntil(func() {
|
||||
close(ch)
|
||||
}, 30*time.Second, 1.0, true, ch)
|
||||
if now.Add(25 * time.Second).Before(time.Now()) {
|
||||
t.Errorf("JitterUntil did not return immediately when the stop chan was closed inside the func")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJitterUntilRecoversPanic(t *testing.T) {
|
||||
// Save and restore crash handlers
|
||||
originalReallyCrash := runtime.ReallyCrash
|
||||
originalHandlers := runtime.PanicHandlers
|
||||
defer func() {
|
||||
runtime.ReallyCrash = originalReallyCrash
|
||||
runtime.PanicHandlers = originalHandlers
|
||||
}()
|
||||
|
||||
called := 0
|
||||
handled := 0
|
||||
|
||||
// Hook up a custom crash handler to ensure it is called when a jitter function panics
|
||||
runtime.ReallyCrash = false
|
||||
runtime.PanicHandlers = []func(interface{}){
|
||||
func(p interface{}) {
|
||||
handled++
|
||||
},
|
||||
}
|
||||
|
||||
ch := make(chan struct{})
|
||||
JitterUntil(func() {
|
||||
called++
|
||||
if called > 2 {
|
||||
close(ch)
|
||||
return
|
||||
}
|
||||
panic("TestJitterUntilRecoversPanic")
|
||||
}, time.Millisecond, 1.0, true, ch)
|
||||
|
||||
if called != 3 {
|
||||
t.Errorf("Expected panic recovers")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJitterUntilNegativeFactor(t *testing.T) {
|
||||
now := time.Now()
|
||||
ch := make(chan struct{})
|
||||
called := make(chan struct{})
|
||||
received := make(chan struct{})
|
||||
go func() {
|
||||
JitterUntil(func() {
|
||||
called <- struct{}{}
|
||||
<-received
|
||||
}, time.Second, -30.0, true, ch)
|
||||
}()
|
||||
// first loop
|
||||
<-called
|
||||
received <- struct{}{}
|
||||
// second loop
|
||||
<-called
|
||||
close(ch)
|
||||
received <- struct{}{}
|
||||
|
||||
// it should take at most 2 seconds + some overhead, not 3
|
||||
if now.Add(3 * time.Second).Before(time.Now()) {
|
||||
t.Errorf("JitterUntil did not returned after predefined period with negative jitter factor when the stop chan was closed inside the func")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestExponentialBackoff(t *testing.T) {
|
||||
opts := Backoff{Factor: 1.0, Steps: 3}
|
||||
|
||||
// waits up to steps
|
||||
i := 0
|
||||
err := ExponentialBackoff(opts, func() (bool, error) {
|
||||
i++
|
||||
return false, nil
|
||||
})
|
||||
if err != ErrWaitTimeout || i != opts.Steps {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// returns immediately
|
||||
i = 0
|
||||
err = ExponentialBackoff(opts, func() (bool, error) {
|
||||
i++
|
||||
return true, nil
|
||||
})
|
||||
if err != nil || i != 1 {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// returns immediately on error
|
||||
testErr := fmt.Errorf("some other error")
|
||||
err = ExponentialBackoff(opts, func() (bool, error) {
|
||||
return false, testErr
|
||||
})
|
||||
if err != testErr {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// invoked multiple times
|
||||
i = 1
|
||||
err = ExponentialBackoff(opts, func() (bool, error) {
|
||||
if i < opts.Steps {
|
||||
i++
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
if err != nil || i != opts.Steps {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoller(t *testing.T) {
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
w := poller(time.Millisecond, 2*time.Millisecond)
|
||||
ch := w(done)
|
||||
count := 0
|
||||
DRAIN:
|
||||
for {
|
||||
select {
|
||||
case _, open := <-ch:
|
||||
if !open {
|
||||
break DRAIN
|
||||
}
|
||||
count++
|
||||
case <-time.After(ForeverTestTimeout):
|
||||
t.Errorf("unexpected timeout after poll")
|
||||
}
|
||||
}
|
||||
if count > 3 {
|
||||
t.Errorf("expected up to three values, got %d", count)
|
||||
}
|
||||
}
|
||||
|
||||
type fakePoller struct {
|
||||
max int
|
||||
used int32 // accessed with atomics
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
func fakeTicker(max int, used *int32, doneFunc func()) WaitFunc {
|
||||
return func(done <-chan struct{}) <-chan struct{} {
|
||||
ch := make(chan struct{})
|
||||
go func() {
|
||||
defer doneFunc()
|
||||
defer close(ch)
|
||||
for i := 0; i < max; i++ {
|
||||
select {
|
||||
case ch <- struct{}{}:
|
||||
case <-done:
|
||||
return
|
||||
}
|
||||
if used != nil {
|
||||
atomic.AddInt32(used, 1)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
}
|
||||
|
||||
func (fp *fakePoller) GetWaitFunc() WaitFunc {
|
||||
fp.wg.Add(1)
|
||||
return fakeTicker(fp.max, &fp.used, fp.wg.Done)
|
||||
}
|
||||
|
||||
func TestPoll(t *testing.T) {
|
||||
invocations := 0
|
||||
f := ConditionFunc(func() (bool, error) {
|
||||
invocations++
|
||||
return true, nil
|
||||
})
|
||||
fp := fakePoller{max: 1}
|
||||
if err := pollInternal(fp.GetWaitFunc(), f); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
fp.wg.Wait()
|
||||
if invocations != 1 {
|
||||
t.Errorf("Expected exactly one invocation, got %d", invocations)
|
||||
}
|
||||
used := atomic.LoadInt32(&fp.used)
|
||||
if used != 1 {
|
||||
t.Errorf("Expected exactly one tick, got %d", used)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPollError(t *testing.T) {
|
||||
expectedError := errors.New("Expected error")
|
||||
f := ConditionFunc(func() (bool, error) {
|
||||
return false, expectedError
|
||||
})
|
||||
fp := fakePoller{max: 1}
|
||||
if err := pollInternal(fp.GetWaitFunc(), f); err == nil || err != expectedError {
|
||||
t.Fatalf("Expected error %v, got none %v", expectedError, err)
|
||||
}
|
||||
fp.wg.Wait()
|
||||
used := atomic.LoadInt32(&fp.used)
|
||||
if used != 1 {
|
||||
t.Errorf("Expected exactly one tick, got %d", used)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPollImmediate(t *testing.T) {
|
||||
invocations := 0
|
||||
f := ConditionFunc(func() (bool, error) {
|
||||
invocations++
|
||||
return true, nil
|
||||
})
|
||||
fp := fakePoller{max: 0}
|
||||
if err := pollImmediateInternal(fp.GetWaitFunc(), f); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
// We don't need to wait for fp.wg, as pollImmediate shouldn't call WaitFunc at all.
|
||||
if invocations != 1 {
|
||||
t.Errorf("Expected exactly one invocation, got %d", invocations)
|
||||
}
|
||||
used := atomic.LoadInt32(&fp.used)
|
||||
if used != 0 {
|
||||
t.Errorf("Expected exactly zero ticks, got %d", used)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPollImmediateError(t *testing.T) {
|
||||
expectedError := errors.New("Expected error")
|
||||
f := ConditionFunc(func() (bool, error) {
|
||||
return false, expectedError
|
||||
})
|
||||
fp := fakePoller{max: 0}
|
||||
if err := pollImmediateInternal(fp.GetWaitFunc(), f); err == nil || err != expectedError {
|
||||
t.Fatalf("Expected error %v, got none %v", expectedError, err)
|
||||
}
|
||||
// We don't need to wait for fp.wg, as pollImmediate shouldn't call WaitFunc at all.
|
||||
used := atomic.LoadInt32(&fp.used)
|
||||
if used != 0 {
|
||||
t.Errorf("Expected exactly zero ticks, got %d", used)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPollForever(t *testing.T) {
|
||||
ch := make(chan struct{})
|
||||
done := make(chan struct{}, 1)
|
||||
complete := make(chan struct{})
|
||||
go func() {
|
||||
f := ConditionFunc(func() (bool, error) {
|
||||
ch <- struct{}{}
|
||||
select {
|
||||
case <-done:
|
||||
return true, nil
|
||||
default:
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
if err := PollInfinite(time.Microsecond, f); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
close(ch)
|
||||
complete <- struct{}{}
|
||||
}()
|
||||
|
||||
// ensure the condition is opened
|
||||
<-ch
|
||||
|
||||
// ensure channel sends events
|
||||
for i := 0; i < 10; i++ {
|
||||
select {
|
||||
case _, open := <-ch:
|
||||
if !open {
|
||||
t.Fatalf("did not expect channel to be closed")
|
||||
}
|
||||
case <-time.After(ForeverTestTimeout):
|
||||
t.Fatalf("channel did not return at least once within the poll interval")
|
||||
}
|
||||
}
|
||||
|
||||
// at most one poll notification should be sent once we return from the condition
|
||||
done <- struct{}{}
|
||||
go func() {
|
||||
for i := 0; i < 2; i++ {
|
||||
_, open := <-ch
|
||||
if !open {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatalf("expected closed channel after two iterations")
|
||||
}()
|
||||
<-complete
|
||||
}
|
||||
|
||||
func TestWaitFor(t *testing.T) {
|
||||
var invocations int
|
||||
testCases := map[string]struct {
|
||||
F ConditionFunc
|
||||
Ticks int
|
||||
Invoked int
|
||||
Err bool
|
||||
}{
|
||||
"invoked once": {
|
||||
ConditionFunc(func() (bool, error) {
|
||||
invocations++
|
||||
return true, nil
|
||||
}),
|
||||
2,
|
||||
1,
|
||||
false,
|
||||
},
|
||||
"invoked and returns a timeout": {
|
||||
ConditionFunc(func() (bool, error) {
|
||||
invocations++
|
||||
return false, nil
|
||||
}),
|
||||
2,
|
||||
3, // the contract of WaitFor() says the func is called once more at the end of the wait
|
||||
true,
|
||||
},
|
||||
"returns immediately on error": {
|
||||
ConditionFunc(func() (bool, error) {
|
||||
invocations++
|
||||
return false, errors.New("test")
|
||||
}),
|
||||
2,
|
||||
1,
|
||||
true,
|
||||
},
|
||||
}
|
||||
for k, c := range testCases {
|
||||
invocations = 0
|
||||
ticker := fakeTicker(c.Ticks, nil, func() {})
|
||||
err := func() error {
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
return WaitFor(ticker, c.F, done)
|
||||
}()
|
||||
switch {
|
||||
case c.Err && err == nil:
|
||||
t.Errorf("%s: Expected error, got nil", k)
|
||||
continue
|
||||
case !c.Err && err != nil:
|
||||
t.Errorf("%s: Expected no error, got: %#v", k, err)
|
||||
continue
|
||||
}
|
||||
if invocations != c.Invoked {
|
||||
t.Errorf("%s: Expected %d invocations, got %d", k, c.Invoked, invocations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWaitForWithDelay(t *testing.T) {
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
WaitFor(poller(time.Millisecond, ForeverTestTimeout), func() (bool, error) {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
return true, nil
|
||||
}, done)
|
||||
// If polling goroutine doesn't see the done signal it will leak timers.
|
||||
select {
|
||||
case done <- struct{}{}:
|
||||
case <-time.After(ForeverTestTimeout):
|
||||
t.Errorf("expected an ack of the done signal.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPollUntil(t *testing.T) {
|
||||
stopCh := make(chan struct{})
|
||||
called := make(chan bool)
|
||||
pollDone := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
PollUntil(time.Microsecond, ConditionFunc(func() (bool, error) {
|
||||
called <- true
|
||||
return false, nil
|
||||
}), stopCh)
|
||||
|
||||
close(pollDone)
|
||||
}()
|
||||
|
||||
// make sure we're called once
|
||||
<-called
|
||||
// this should trigger a "done"
|
||||
close(stopCh)
|
||||
|
||||
go func() {
|
||||
// release the condition func if needed
|
||||
for {
|
||||
<-called
|
||||
}
|
||||
}()
|
||||
|
||||
// make sure we finished the poll
|
||||
<-pollDone
|
||||
}
|
||||
36
vendor/k8s.io/apimachinery/pkg/util/yaml/BUILD
generated
vendored
36
vendor/k8s.io/apimachinery/pkg/util/yaml/BUILD
generated
vendored
|
|
@ -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 = ["decoder_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["decoder.go"],
|
||||
importpath = "k8s.io/apimachinery/pkg/util/yaml",
|
||||
deps = [
|
||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
405
vendor/k8s.io/apimachinery/pkg/util/yaml/decoder_test.go
generated
vendored
405
vendor/k8s.io/apimachinery/pkg/util/yaml/decoder_test.go
generated
vendored
|
|
@ -1,405 +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 yaml
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestYAMLDecoderReadBytesLength(t *testing.T) {
|
||||
d := `---
|
||||
stuff: 1
|
||||
test-foo: 1
|
||||
`
|
||||
testCases := []struct {
|
||||
bufLen int
|
||||
expectLen int
|
||||
expectErr error
|
||||
}{
|
||||
{len(d), len(d), nil},
|
||||
{len(d) + 10, len(d), nil},
|
||||
{len(d) - 10, len(d) - 10, io.ErrShortBuffer},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
r := NewDocumentDecoder(ioutil.NopCloser(bytes.NewReader([]byte(d))))
|
||||
b := make([]byte, testCase.bufLen)
|
||||
n, err := r.Read(b)
|
||||
if err != testCase.expectErr || n != testCase.expectLen {
|
||||
t.Fatalf("%d: unexpected body: %d / %v", i, n, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestYAMLDecoderCallsAfterErrShortBufferRestOfFrame(t *testing.T) {
|
||||
d := `---
|
||||
stuff: 1
|
||||
test-foo: 1`
|
||||
r := NewDocumentDecoder(ioutil.NopCloser(bytes.NewReader([]byte(d))))
|
||||
b := make([]byte, 12)
|
||||
n, err := r.Read(b)
|
||||
if err != io.ErrShortBuffer || n != 12 {
|
||||
t.Fatalf("expected ErrShortBuffer: %d / %v", n, err)
|
||||
}
|
||||
expected := "---\nstuff: 1"
|
||||
if string(b) != expected {
|
||||
t.Fatalf("expected bytes read to be: %s got: %s", expected, string(b))
|
||||
}
|
||||
b = make([]byte, 13)
|
||||
n, err = r.Read(b)
|
||||
if err != nil || n != 13 {
|
||||
t.Fatalf("expected nil: %d / %v", n, err)
|
||||
}
|
||||
expected = "\n\ttest-foo: 1"
|
||||
if string(b) != expected {
|
||||
t.Fatalf("expected bytes read to be: '%s' got: '%s'", expected, string(b))
|
||||
}
|
||||
b = make([]byte, 15)
|
||||
n, err = r.Read(b)
|
||||
if err != io.EOF || n != 0 {
|
||||
t.Fatalf("expected EOF: %d / %v", n, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitYAMLDocument(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
atEOF bool
|
||||
expect string
|
||||
adv int
|
||||
}{
|
||||
{"foo", true, "foo", 3},
|
||||
{"fo", false, "", 0},
|
||||
|
||||
{"---", true, "---", 3},
|
||||
{"---\n", true, "---\n", 4},
|
||||
{"---\n", false, "", 0},
|
||||
|
||||
{"\n---\n", false, "", 5},
|
||||
{"\n---\n", true, "", 5},
|
||||
|
||||
{"abc\n---\ndef", true, "abc", 8},
|
||||
{"def", true, "def", 3},
|
||||
{"", true, "", 0},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
adv, token, err := splitYAMLDocument([]byte(testCase.input), testCase.atEOF)
|
||||
if err != nil {
|
||||
t.Errorf("%d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if adv != testCase.adv {
|
||||
t.Errorf("%d: advance did not match: %d %d", i, testCase.adv, adv)
|
||||
}
|
||||
if testCase.expect != string(token) {
|
||||
t.Errorf("%d: token did not match: %q %q", i, testCase.expect, string(token))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGuessJSON(t *testing.T) {
|
||||
if r, _, isJSON := GuessJSONStream(bytes.NewReader([]byte(" \n{}")), 100); !isJSON {
|
||||
t.Fatalf("expected stream to be JSON")
|
||||
} else {
|
||||
b := make([]byte, 30)
|
||||
n, err := r.Read(b)
|
||||
if err != nil || n != 4 {
|
||||
t.Fatalf("unexpected body: %d / %v", n, err)
|
||||
}
|
||||
if string(b[:n]) != " \n{}" {
|
||||
t.Fatalf("unexpected body: %q", string(b[:n]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanYAML(t *testing.T) {
|
||||
s := bufio.NewScanner(bytes.NewReader([]byte(`---
|
||||
stuff: 1
|
||||
|
||||
---
|
||||
`)))
|
||||
s.Split(splitYAMLDocument)
|
||||
if !s.Scan() {
|
||||
t.Fatalf("should have been able to scan")
|
||||
}
|
||||
t.Logf("scan: %s", s.Text())
|
||||
if !s.Scan() {
|
||||
t.Fatalf("should have been able to scan")
|
||||
}
|
||||
t.Logf("scan: %s", s.Text())
|
||||
if s.Scan() {
|
||||
t.Fatalf("scan should have been done")
|
||||
}
|
||||
if s.Err() != nil {
|
||||
t.Fatalf("err should have been nil: %v", s.Err())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeYAML(t *testing.T) {
|
||||
s := NewYAMLToJSONDecoder(bytes.NewReader([]byte(`---
|
||||
stuff: 1
|
||||
|
||||
---
|
||||
`)))
|
||||
obj := generic{}
|
||||
if err := s.Decode(&obj); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if fmt.Sprintf("%#v", obj) != `yaml.generic{"stuff":1}` {
|
||||
t.Errorf("unexpected object: %#v", obj)
|
||||
}
|
||||
obj = generic{}
|
||||
if err := s.Decode(&obj); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(obj) != 0 {
|
||||
t.Fatalf("unexpected object: %#v", obj)
|
||||
}
|
||||
obj = generic{}
|
||||
if err := s.Decode(&obj); err != io.EOF {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeBrokenYAML(t *testing.T) {
|
||||
s := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`---
|
||||
stuff: 1
|
||||
test-foo: 1
|
||||
|
||||
---
|
||||
`)), 100)
|
||||
obj := generic{}
|
||||
err := s.Decode(&obj)
|
||||
if err == nil {
|
||||
t.Fatal("expected error with yaml: violate, got no error")
|
||||
}
|
||||
fmt.Printf("err: %s\n", err.Error())
|
||||
if !strings.Contains(err.Error(), "yaml: line 2:") {
|
||||
t.Fatalf("expected %q to have 'yaml: line 2:' found a tab character", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeBrokenJSON(t *testing.T) {
|
||||
s := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`{
|
||||
"foo": {
|
||||
"stuff": 1
|
||||
"otherStuff": 2
|
||||
}
|
||||
}
|
||||
`)), 100)
|
||||
obj := generic{}
|
||||
err := s.Decode(&obj)
|
||||
if err == nil {
|
||||
t.Fatal("expected error with json: prefix, got no error")
|
||||
}
|
||||
if !strings.HasPrefix(err.Error(), "json: line 3:") {
|
||||
t.Fatalf("expected %q to have 'json: line 3:' prefix", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type generic map[string]interface{}
|
||||
|
||||
func TestYAMLOrJSONDecoder(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
buffer int
|
||||
isJSON bool
|
||||
err bool
|
||||
out []generic
|
||||
}{
|
||||
{` {"1":2}{"3":4}`, 2, true, false, []generic{
|
||||
{"1": 2},
|
||||
{"3": 4},
|
||||
}},
|
||||
{" \n{}", 3, true, false, []generic{
|
||||
{},
|
||||
}},
|
||||
{" \na: b", 2, false, false, []generic{
|
||||
{"a": "b"},
|
||||
}},
|
||||
{" \n{\"a\": \"b\"}", 2, false, true, []generic{
|
||||
{"a": "b"},
|
||||
}},
|
||||
{" \n{\"a\": \"b\"}", 3, true, false, []generic{
|
||||
{"a": "b"},
|
||||
}},
|
||||
{` {"a":"b"}`, 100, true, false, []generic{
|
||||
{"a": "b"},
|
||||
}},
|
||||
{"", 1, false, false, []generic{}},
|
||||
{"foo: bar\n---\nbaz: biz", 100, false, false, []generic{
|
||||
{"foo": "bar"},
|
||||
{"baz": "biz"},
|
||||
}},
|
||||
{"foo: bar\n---\n", 100, false, false, []generic{
|
||||
{"foo": "bar"},
|
||||
}},
|
||||
{"foo: bar\n---", 100, false, false, []generic{
|
||||
{"foo": "bar"},
|
||||
}},
|
||||
{"foo: bar\n--", 100, false, true, []generic{
|
||||
{"foo": "bar"},
|
||||
}},
|
||||
{"foo: bar\n-", 100, false, true, []generic{
|
||||
{"foo": "bar"},
|
||||
}},
|
||||
{"foo: bar\n", 100, false, false, []generic{
|
||||
{"foo": "bar"},
|
||||
}},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
decoder := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(testCase.input)), testCase.buffer)
|
||||
objs := []generic{}
|
||||
|
||||
var err error
|
||||
for {
|
||||
out := make(generic)
|
||||
err = decoder.Decode(&out)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
objs = append(objs, out)
|
||||
}
|
||||
if err != io.EOF {
|
||||
switch {
|
||||
case testCase.err && err == nil:
|
||||
t.Errorf("%d: unexpected non-error", i)
|
||||
continue
|
||||
case !testCase.err && err != nil:
|
||||
t.Errorf("%d: unexpected error: %v", i, err)
|
||||
continue
|
||||
case err != nil:
|
||||
continue
|
||||
}
|
||||
}
|
||||
switch decoder.decoder.(type) {
|
||||
case *YAMLToJSONDecoder:
|
||||
if testCase.isJSON {
|
||||
t.Errorf("%d: expected JSON decoder, got YAML", i)
|
||||
}
|
||||
case *json.Decoder:
|
||||
if !testCase.isJSON {
|
||||
t.Errorf("%d: expected YAML decoder, got JSON", i)
|
||||
}
|
||||
}
|
||||
if fmt.Sprintf("%#v", testCase.out) != fmt.Sprintf("%#v", objs) {
|
||||
t.Errorf("%d: objects were not equal: \n%#v\n%#v", i, testCase.out, objs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadSingleLongLine(t *testing.T) {
|
||||
testReadLines(t, []int{128 * 1024})
|
||||
}
|
||||
|
||||
func TestReadRandomLineLengths(t *testing.T) {
|
||||
minLength := 100
|
||||
maxLength := 96 * 1024
|
||||
maxLines := 100
|
||||
|
||||
lineLengths := make([]int, maxLines)
|
||||
for i := 0; i < maxLines; i++ {
|
||||
lineLengths[i] = rand.Intn(maxLength-minLength) + minLength
|
||||
}
|
||||
|
||||
testReadLines(t, lineLengths)
|
||||
}
|
||||
|
||||
func testReadLines(t *testing.T, lineLengths []int) {
|
||||
var (
|
||||
lines [][]byte
|
||||
inputStream []byte
|
||||
)
|
||||
for _, lineLength := range lineLengths {
|
||||
inputLine := make([]byte, lineLength+1)
|
||||
for i := 0; i < lineLength; i++ {
|
||||
char := rand.Intn('z'-'A') + 'A'
|
||||
inputLine[i] = byte(char)
|
||||
}
|
||||
inputLine[len(inputLine)-1] = '\n'
|
||||
lines = append(lines, inputLine)
|
||||
}
|
||||
for _, line := range lines {
|
||||
inputStream = append(inputStream, line...)
|
||||
}
|
||||
|
||||
// init Reader
|
||||
reader := bufio.NewReader(bytes.NewReader(inputStream))
|
||||
lineReader := &LineReader{reader: reader}
|
||||
|
||||
// read lines
|
||||
var readLines [][]byte
|
||||
for range lines {
|
||||
bytes, err := lineReader.Read()
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatalf("failed to read lines: %v", err)
|
||||
}
|
||||
readLines = append(readLines, bytes)
|
||||
}
|
||||
|
||||
// validate
|
||||
for i := range lines {
|
||||
if len(lines[i]) != len(readLines[i]) {
|
||||
t.Fatalf("expected line length: %d, but got %d", len(lines[i]), len(readLines[i]))
|
||||
}
|
||||
if !reflect.DeepEqual(lines[i], readLines[i]) {
|
||||
t.Fatalf("expected line: %v, but got %v", lines[i], readLines[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypedJSONOrYamlErrors(t *testing.T) {
|
||||
s := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`{
|
||||
"foo": {
|
||||
"stuff": 1
|
||||
"otherStuff": 2
|
||||
}
|
||||
}
|
||||
`)), 100)
|
||||
obj := generic{}
|
||||
err := s.Decode(&obj)
|
||||
if err == nil {
|
||||
t.Fatal("expected error with json: prefix, got no error")
|
||||
}
|
||||
if _, ok := err.(JSONSyntaxError); !ok {
|
||||
t.Fatalf("expected %q to be of type JSONSyntaxError", err.Error())
|
||||
}
|
||||
|
||||
s = NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`---
|
||||
stuff: 1
|
||||
test-foo: 1
|
||||
|
||||
---
|
||||
`)), 100)
|
||||
obj = generic{}
|
||||
err = s.Decode(&obj)
|
||||
if err == nil {
|
||||
t.Fatal("expected error with yaml: prefix, got no error")
|
||||
}
|
||||
if _, ok := err.(YAMLSyntaxError); !ok {
|
||||
t.Fatalf("expected %q to be of type YAMLSyntaxError", err.Error())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue