vendor files

This commit is contained in:
Serguei Bezverkhi
2018-01-09 13:57:14 -05:00
parent 558bc6c02a
commit 7b24313bd6
16547 changed files with 4527373 additions and 0 deletions

9
vendor/k8s.io/utils/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,9 @@
language: go
go:
- 1.8.x
- 1.9.x
go_import_path: k8s.io/utils
script:
- diff -u <(echo -n) <(gofmt -d .)
- go tool vet .
- go test -v -race ./...

31
vendor/k8s.io/utils/HOWTOMOVE.md generated vendored Normal file
View File

@ -0,0 +1,31 @@
# How to move a utility pkg from other kubernetes repos
It has 2 steps to move a pkg from other Kubernetes repos to `k8s.io/utils` repo:
- copy the pkg to `k8s.io/utils` repo
- update the import paths and `vendor/` in the repos that refer this pkg
## Copy the pkg to `k8s.io/utils` repo
Copying should preserve all the git history associated with it.
[Here](http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/) is a working approach.
Note: You may need to use `--allow-unrelated-histories` if you get error when running `git pull` following the post above.
Then, you may need to restructure the package to make sure it has the following structure.
.
├── doc.go # Description for this package
├── <utilname1>.go # utility go file
├── <utilname>_test.go # go unit tests
└── testing # All the testing framework
└── fake_<utilname>.go # Testing framework go file
[#5](https://github.com/kubernetes/utils/pull/5) is an example for this step.
## Update the repos that refer the pkg
You should update the import paths.
Then follow [this doc](https://github.com/kubernetes/community/blob/master/contributors/devel/godep.md) to update `vendor/` and `Godeps/`.
You may want to run `make bazel-test` to make sure all new references work.
[kubernetes/kubernetes#49234](https://github.com/kubernetes/kubernetes/pull/49234) is an example for this step.

202
vendor/k8s.io/utils/LICENSE generated vendored Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

57
vendor/k8s.io/utils/README.md generated vendored Normal file
View File

@ -0,0 +1,57 @@
# Utils
[![Build Status]](https://travis-ci.org/kubernetes/utils) [![GoDoc](https://godoc.org/k8s.io/utils?status.svg)](https://godoc.org/k8s.io/utils)
A set of Go libraries that provide low-level,
kubernetes-independent packages supplementing the [Go
standard libs].
## Purpose
As Kubernetes grows and spins functionality out of its
[core] and into cooperating repositories like
[apiserver], [kubectl], [kubeadm], etc., the need
arises for leaf repositories to house shared code and
avoid cycles in repository relationships.
This repository is intended to hold shared utilities
with no Kubernetes dependence that may be of interest
to any Go project. See these [instructions for moving]
an existing package to this repository.
## Criteria for adding code here
- Used by multiple Kubernetes repositories.
- Full unit test coverage.
- Go tools compliant (`go get`, `go test`, etc.).
- Complex enough to be worth vendoring, rather than copying.
- Stable, or backward compatible, API.
- _No dependence on any Kubernetes repository_.
## Libraries
- [Exec](/exec) provides an interface for `os/exec`. It makes it easier
to mock and replace in tests, especially with
the [FakeExec](exec/testing/fake_exec.go) struct.
- [Temp](/temp) provides an interface to create temporary directories. It also
provides a [FakeDir](temp/temptesting) implementation to replace in tests.
- [Clock](/clock) provides an interface for time-based operations. It allows
mocking time for testing.
[Build Status]: https://travis-ci.org/kubernetes/utils.svg?branch=master
[Go standard libs]: https://golang.org/pkg/#stdlib
[api]: https://github.com/kubernetes/api
[apiserver]: https://github.com/kubernetes/apiserver
[core]: https://github.com/kubernetes/kubernetes
[ingress]: https://github.com/kubernetes/ingress
[kubeadm]: https://github.com/kubernetes/kubeadm
[kubectl]: https://github.com/kubernetes/kubectl
[instructions for moving]: ./HOWTOMOVE.md

94
vendor/k8s.io/utils/clock/clock.go generated vendored Normal file
View File

@ -0,0 +1,94 @@
/*
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 clock
import "time"
// Clock allows for injecting fake or real clocks into code that
// needs to do arbitrary things based on time.
type Clock interface {
Now() time.Time
Since(time.Time) time.Duration
After(d time.Duration) <-chan time.Time
NewTimer(d time.Duration) Timer
Sleep(d time.Duration)
Tick(d time.Duration) <-chan time.Time
}
var _ = Clock(RealClock{})
// RealClock really calls time.Now()
type RealClock struct{}
// Now returns the current time.
func (RealClock) Now() time.Time {
return time.Now()
}
// Since returns time since the specified timestamp.
func (RealClock) Since(ts time.Time) time.Duration {
return time.Since(ts)
}
// Same as time.After(d).
func (RealClock) After(d time.Duration) <-chan time.Time {
return time.After(d)
}
func (RealClock) NewTimer(d time.Duration) Timer {
return &realTimer{
timer: time.NewTimer(d),
}
}
func (RealClock) Tick(d time.Duration) <-chan time.Time {
return time.Tick(d)
}
func (RealClock) Sleep(d time.Duration) {
time.Sleep(d)
}
// Timer allows for injecting fake or real timers into code that
// needs to do arbitrary things based on time.
type Timer interface {
C() <-chan time.Time
Stop() bool
Reset(d time.Duration) bool
}
var _ = Timer(&realTimer{})
// realTimer is backed by an actual time.Timer.
type realTimer struct {
timer *time.Timer
}
// C returns the underlying timer's channel.
func (r *realTimer) C() <-chan time.Time {
return r.timer.C
}
// Stop calls Stop() on the underlying timer.
func (r *realTimer) Stop() bool {
return r.timer.Stop()
}
// Reset calls Reset() on the underlying timer.
func (r *realTimer) Reset(d time.Duration) bool {
return r.timer.Reset(d)
}

254
vendor/k8s.io/utils/clock/testing/fake_clock.go generated vendored Normal file
View File

@ -0,0 +1,254 @@
/*
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 testing
import (
"sync"
"time"
"k8s.io/utils/clock"
)
var (
_ = clock.Clock(&FakeClock{})
_ = clock.Clock(&IntervalClock{})
)
// FakeClock implements clock.Clock, but returns an arbitrary time.
type FakeClock struct {
lock sync.RWMutex
time time.Time
// waiters are waiting for the fake time to pass their specified time
waiters []fakeClockWaiter
}
type fakeClockWaiter struct {
targetTime time.Time
stepInterval time.Duration
skipIfBlocked bool
destChan chan time.Time
fired bool
}
func NewFakeClock(t time.Time) *FakeClock {
return &FakeClock{
time: t,
}
}
// Now returns f's time.
func (f *FakeClock) Now() time.Time {
f.lock.RLock()
defer f.lock.RUnlock()
return f.time
}
// Since returns time since the time in f.
func (f *FakeClock) Since(ts time.Time) time.Duration {
f.lock.RLock()
defer f.lock.RUnlock()
return f.time.Sub(ts)
}
// Fake version of time.After(d).
func (f *FakeClock) After(d time.Duration) <-chan time.Time {
f.lock.Lock()
defer f.lock.Unlock()
stopTime := f.time.Add(d)
ch := make(chan time.Time, 1) // Don't block!
f.waiters = append(f.waiters, fakeClockWaiter{
targetTime: stopTime,
destChan: ch,
})
return ch
}
// Fake version of time.NewTimer(d).
func (f *FakeClock) NewTimer(d time.Duration) clock.Timer {
f.lock.Lock()
defer f.lock.Unlock()
stopTime := f.time.Add(d)
ch := make(chan time.Time, 1) // Don't block!
timer := &fakeTimer{
fakeClock: f,
waiter: fakeClockWaiter{
targetTime: stopTime,
destChan: ch,
},
}
f.waiters = append(f.waiters, timer.waiter)
return timer
}
func (f *FakeClock) Tick(d time.Duration) <-chan time.Time {
f.lock.Lock()
defer f.lock.Unlock()
tickTime := f.time.Add(d)
ch := make(chan time.Time, 1) // hold one tick
f.waiters = append(f.waiters, fakeClockWaiter{
targetTime: tickTime,
stepInterval: d,
skipIfBlocked: true,
destChan: ch,
})
return ch
}
// Move clock by Duration, notify anyone that's called After, Tick, or NewTimer
func (f *FakeClock) Step(d time.Duration) {
f.lock.Lock()
defer f.lock.Unlock()
f.setTimeLocked(f.time.Add(d))
}
// Sets the time.
func (f *FakeClock) SetTime(t time.Time) {
f.lock.Lock()
defer f.lock.Unlock()
f.setTimeLocked(t)
}
// Actually changes the time and checks any waiters. f must be write-locked.
func (f *FakeClock) setTimeLocked(t time.Time) {
f.time = t
newWaiters := make([]fakeClockWaiter, 0, len(f.waiters))
for i := range f.waiters {
w := &f.waiters[i]
if !w.targetTime.After(t) {
if w.skipIfBlocked {
select {
case w.destChan <- t:
w.fired = true
default:
}
} else {
w.destChan <- t
w.fired = true
}
if w.stepInterval > 0 {
for !w.targetTime.After(t) {
w.targetTime = w.targetTime.Add(w.stepInterval)
}
newWaiters = append(newWaiters, *w)
}
} else {
newWaiters = append(newWaiters, f.waiters[i])
}
}
f.waiters = newWaiters
}
// Returns true if After has been called on f but not yet satisfied (so you can
// write race-free tests).
func (f *FakeClock) HasWaiters() bool {
f.lock.RLock()
defer f.lock.RUnlock()
return len(f.waiters) > 0
}
func (f *FakeClock) Sleep(d time.Duration) {
f.Step(d)
}
// IntervalClock implements clock.Clock, but each invocation of Now steps the clock forward the specified duration
type IntervalClock struct {
Time time.Time
Duration time.Duration
}
// Now returns i's time.
func (i *IntervalClock) Now() time.Time {
i.Time = i.Time.Add(i.Duration)
return i.Time
}
// Since returns time since the time in i.
func (i *IntervalClock) Since(ts time.Time) time.Duration {
return i.Time.Sub(ts)
}
// Unimplemented, will panic.
// TODO: make interval clock use FakeClock so this can be implemented.
func (*IntervalClock) After(d time.Duration) <-chan time.Time {
panic("IntervalClock doesn't implement After")
}
// Unimplemented, will panic.
// TODO: make interval clock use FakeClock so this can be implemented.
func (*IntervalClock) NewTimer(d time.Duration) clock.Timer {
panic("IntervalClock doesn't implement NewTimer")
}
// Unimplemented, will panic.
// TODO: make interval clock use FakeClock so this can be implemented.
func (*IntervalClock) Tick(d time.Duration) <-chan time.Time {
panic("IntervalClock doesn't implement Tick")
}
func (*IntervalClock) Sleep(d time.Duration) {
panic("IntervalClock doesn't implement Sleep")
}
var _ = clock.Timer(&fakeTimer{})
// fakeTimer implements clock.Timer based on a FakeClock.
type fakeTimer struct {
fakeClock *FakeClock
waiter fakeClockWaiter
}
// C returns the channel that notifies when this timer has fired.
func (f *fakeTimer) C() <-chan time.Time {
return f.waiter.destChan
}
// Stop stops the timer and returns true if the timer has not yet fired, or false otherwise.
func (f *fakeTimer) Stop() bool {
f.fakeClock.lock.Lock()
defer f.fakeClock.lock.Unlock()
newWaiters := make([]fakeClockWaiter, 0, len(f.fakeClock.waiters))
for i := range f.fakeClock.waiters {
w := &f.fakeClock.waiters[i]
if w != &f.waiter {
newWaiters = append(newWaiters, *w)
}
}
f.fakeClock.waiters = newWaiters
return !f.waiter.fired
}
// Reset resets the timer to the fake clock's "now" + d. It returns true if the timer has not yet
// fired, or false otherwise.
func (f *fakeTimer) Reset(d time.Duration) bool {
f.fakeClock.lock.Lock()
defer f.fakeClock.lock.Unlock()
active := !f.waiter.fired
f.waiter.fired = false
f.waiter.targetTime = f.fakeClock.time.Add(d)
return active
}

184
vendor/k8s.io/utils/clock/testing/fake_clock_test.go generated vendored Normal file
View File

@ -0,0 +1,184 @@
/*
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 testing
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)
}
}

3
vendor/k8s.io/utils/code-of-conduct.md generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Kubernetes Community Code of Conduct
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)

18
vendor/k8s.io/utils/exec/doc.go generated vendored Normal file
View File

@ -0,0 +1,18 @@
/*
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 exec provides an injectable interface and implementations for running commands.
package exec // import "k8s.io/utils/exec"

215
vendor/k8s.io/utils/exec/exec.go generated vendored Normal file
View File

@ -0,0 +1,215 @@
/*
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 exec
import (
"context"
"io"
osexec "os/exec"
"syscall"
"time"
)
// ErrExecutableNotFound is returned if the executable is not found.
var ErrExecutableNotFound = osexec.ErrNotFound
// Interface is an interface that presents a subset of the os/exec API. Use this
// when you want to inject fakeable/mockable exec behavior.
type Interface interface {
// Command returns a Cmd instance which can be used to run a single command.
// This follows the pattern of package os/exec.
Command(cmd string, args ...string) Cmd
// CommandContext returns a Cmd instance which can be used to run a single command.
//
// The provided context is used to kill the process if the context becomes done
// before the command completes on its own. For example, a timeout can be set in
// the context.
CommandContext(ctx context.Context, cmd string, args ...string) Cmd
// LookPath wraps os/exec.LookPath
LookPath(file string) (string, error)
}
// Cmd is an interface that presents an API that is very similar to Cmd from os/exec.
// As more functionality is needed, this can grow. Since Cmd is a struct, we will have
// to replace fields with get/set method pairs.
type Cmd interface {
// Run runs the command to the completion.
Run() error
// CombinedOutput runs the command and returns its combined standard output
// and standard error. This follows the pattern of package os/exec.
CombinedOutput() ([]byte, error)
// Output runs the command and returns standard output, but not standard err
Output() ([]byte, error)
SetDir(dir string)
SetStdin(in io.Reader)
SetStdout(out io.Writer)
SetStderr(out io.Writer)
// Stops the command by sending SIGTERM. It is not guaranteed the
// process will stop before this function returns. If the process is not
// responding, an internal timer function will send a SIGKILL to force
// terminate after 10 seconds.
Stop()
}
// ExitError is an interface that presents an API similar to os.ProcessState, which is
// what ExitError from os/exec is. This is designed to make testing a bit easier and
// probably loses some of the cross-platform properties of the underlying library.
type ExitError interface {
String() string
Error() string
Exited() bool
ExitStatus() int
}
// Implements Interface in terms of really exec()ing.
type executor struct{}
// New returns a new Interface which will os/exec to run commands.
func New() Interface {
return &executor{}
}
// Command is part of the Interface interface.
func (executor *executor) Command(cmd string, args ...string) Cmd {
return (*cmdWrapper)(osexec.Command(cmd, args...))
}
// CommandContext is part of the Interface interface.
func (executor *executor) CommandContext(ctx context.Context, cmd string, args ...string) Cmd {
return (*cmdWrapper)(osexec.CommandContext(ctx, cmd, args...))
}
// LookPath is part of the Interface interface
func (executor *executor) LookPath(file string) (string, error) {
return osexec.LookPath(file)
}
// Wraps exec.Cmd so we can capture errors.
type cmdWrapper osexec.Cmd
var _ Cmd = &cmdWrapper{}
func (cmd *cmdWrapper) SetDir(dir string) {
cmd.Dir = dir
}
func (cmd *cmdWrapper) SetStdin(in io.Reader) {
cmd.Stdin = in
}
func (cmd *cmdWrapper) SetStdout(out io.Writer) {
cmd.Stdout = out
}
func (cmd *cmdWrapper) SetStderr(out io.Writer) {
cmd.Stderr = out
}
// Run is part of the Cmd interface.
func (cmd *cmdWrapper) Run() error {
err := (*osexec.Cmd)(cmd).Run()
return handleError(err)
}
// CombinedOutput is part of the Cmd interface.
func (cmd *cmdWrapper) CombinedOutput() ([]byte, error) {
out, err := (*osexec.Cmd)(cmd).CombinedOutput()
return out, handleError(err)
}
func (cmd *cmdWrapper) Output() ([]byte, error) {
out, err := (*osexec.Cmd)(cmd).Output()
return out, handleError(err)
}
// Stop is part of the Cmd interface.
func (cmd *cmdWrapper) Stop() {
c := (*osexec.Cmd)(cmd)
if c.Process == nil {
return
}
c.Process.Signal(syscall.SIGTERM)
time.AfterFunc(10*time.Second, func() {
if !c.ProcessState.Exited() {
c.Process.Signal(syscall.SIGKILL)
}
})
}
func handleError(err error) error {
if err == nil {
return nil
}
switch e := err.(type) {
case *osexec.ExitError:
return &ExitErrorWrapper{e}
case *osexec.Error:
if e.Err == osexec.ErrNotFound {
return ErrExecutableNotFound
}
}
return err
}
// ExitErrorWrapper is an implementation of ExitError in terms of os/exec ExitError.
// Note: standard exec.ExitError is type *os.ProcessState, which already implements Exited().
type ExitErrorWrapper struct {
*osexec.ExitError
}
var _ ExitError = &ExitErrorWrapper{}
// ExitStatus is part of the ExitError interface.
func (eew ExitErrorWrapper) ExitStatus() int {
ws, ok := eew.Sys().(syscall.WaitStatus)
if !ok {
panic("can't call ExitStatus() on a non-WaitStatus exitErrorWrapper")
}
return ws.ExitStatus()
}
// CodeExitError is an implementation of ExitError consisting of an error object
// and an exit code (the upper bits of os.exec.ExitStatus).
type CodeExitError struct {
Err error
Code int
}
var _ ExitError = CodeExitError{}
func (e CodeExitError) Error() string {
return e.Err.Error()
}
func (e CodeExitError) String() string {
return e.Err.Error()
}
func (e CodeExitError) Exited() bool {
return true
}
func (e CodeExitError) ExitStatus() int {
return e.Code
}

141
vendor/k8s.io/utils/exec/exec_test.go generated vendored Normal file
View File

@ -0,0 +1,141 @@
/*
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 exec
import (
"context"
osexec "os/exec"
"testing"
"time"
)
func TestExecutorNoArgs(t *testing.T) {
ex := New()
cmd := ex.Command("true")
out, err := cmd.CombinedOutput()
if err != nil {
t.Errorf("expected success, got %v", err)
}
if len(out) != 0 {
t.Errorf("expected no output, got %q", string(out))
}
cmd = ex.Command("false")
out, err = cmd.CombinedOutput()
if err == nil {
t.Errorf("expected failure, got nil error")
}
if len(out) != 0 {
t.Errorf("expected no output, got %q", string(out))
}
ee, ok := err.(ExitError)
if !ok {
t.Errorf("expected an ExitError, got %+v", err)
}
if ee.Exited() {
if code := ee.ExitStatus(); code != 1 {
t.Errorf("expected exit status 1, got %d", code)
}
}
cmd = ex.Command("/does/not/exist")
out, err = cmd.CombinedOutput()
if err == nil {
t.Errorf("expected failure, got nil error")
}
if ee, ok := err.(ExitError); ok {
t.Errorf("expected non-ExitError, got %+v", ee)
}
}
func TestExecutorWithArgs(t *testing.T) {
ex := New()
cmd := ex.Command("echo", "stdout")
out, err := cmd.CombinedOutput()
if err != nil {
t.Errorf("expected success, got %+v", err)
}
if string(out) != "stdout\n" {
t.Errorf("unexpected output: %q", string(out))
}
cmd = ex.Command("/bin/sh", "-c", "echo stderr > /dev/stderr")
out, err = cmd.CombinedOutput()
if err != nil {
t.Errorf("expected success, got %+v", err)
}
if string(out) != "stderr\n" {
t.Errorf("unexpected output: %q", string(out))
}
}
func TestLookPath(t *testing.T) {
ex := New()
shExpected, _ := osexec.LookPath("sh")
sh, _ := ex.LookPath("sh")
if sh != shExpected {
t.Errorf("unexpected result for LookPath: got %s, expected %s", sh, shExpected)
}
}
func TestExecutableNotFound(t *testing.T) {
exec := New()
cmd := exec.Command("fake_executable_name")
_, err := cmd.CombinedOutput()
if err != ErrExecutableNotFound {
t.Errorf("cmd.CombinedOutput(): Expected error ErrExecutableNotFound but got %v", err)
}
cmd = exec.Command("fake_executable_name")
_, err = cmd.Output()
if err != ErrExecutableNotFound {
t.Errorf("cmd.Output(): Expected error ErrExecutableNotFound but got %v", err)
}
cmd = exec.Command("fake_executable_name")
err = cmd.Run()
if err != ErrExecutableNotFound {
t.Errorf("cmd.Run(): Expected error ErrExecutableNotFound but got %v", err)
}
}
func TestStopBeforeStart(t *testing.T) {
cmd := New().Command("echo", "hello")
// no panic calling Stop before calling Run
cmd.Stop()
cmd.Run()
// no panic calling Stop after command is done
cmd.Stop()
}
func TestTimeout(t *testing.T) {
exec := New()
ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond)
defer cancel()
err := exec.CommandContext(ctx, "sleep", "2").Run()
if err != context.DeadlineExceeded {
t.Errorf("expected %v but got %v", context.DeadlineExceeded, err)
}
}

37
vendor/k8s.io/utils/exec/new_test.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
/*
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 exec_test
import (
"bytes"
"fmt"
"k8s.io/utils/exec"
)
func ExampleNew() {
exec := exec.New()
cmd := exec.Command("echo", "Bonjour!")
buff := bytes.Buffer{}
cmd.SetStdout(&buff)
if err := cmd.Run(); err != nil {
panic(err)
}
fmt.Println(buff.String())
// Output: Bonjour!
}

158
vendor/k8s.io/utils/exec/testing/fake_exec.go generated vendored Normal file
View File

@ -0,0 +1,158 @@
/*
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 testingexec
import (
"context"
"fmt"
"io"
"k8s.io/utils/exec"
)
// A simple scripted Interface type.
type FakeExec struct {
CommandScript []FakeCommandAction
CommandCalls int
LookPathFunc func(string) (string, error)
}
var _ exec.Interface = &FakeExec{}
type FakeCommandAction func(cmd string, args ...string) exec.Cmd
func (fake *FakeExec) Command(cmd string, args ...string) exec.Cmd {
if fake.CommandCalls > len(fake.CommandScript)-1 {
panic(fmt.Sprintf("ran out of Command() actions. Could not handle command [%d]: %s args: %v", fake.CommandCalls, cmd, args))
}
i := fake.CommandCalls
fake.CommandCalls++
return fake.CommandScript[i](cmd, args...)
}
func (fake *FakeExec) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd {
return fake.Command(cmd, args...)
}
func (fake *FakeExec) LookPath(file string) (string, error) {
return fake.LookPathFunc(file)
}
// A simple scripted Cmd type.
type FakeCmd struct {
Argv []string
CombinedOutputScript []FakeCombinedOutputAction
CombinedOutputCalls int
CombinedOutputLog [][]string
RunScript []FakeRunAction
RunCalls int
RunLog [][]string
Dirs []string
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
var _ exec.Cmd = &FakeCmd{}
func InitFakeCmd(fake *FakeCmd, cmd string, args ...string) exec.Cmd {
fake.Argv = append([]string{cmd}, args...)
return fake
}
type FakeCombinedOutputAction func() ([]byte, error)
type FakeRunAction func() ([]byte, []byte, error)
func (fake *FakeCmd) SetDir(dir string) {
fake.Dirs = append(fake.Dirs, dir)
}
func (fake *FakeCmd) SetStdin(in io.Reader) {
fake.Stdin = in
}
func (fake *FakeCmd) SetStdout(out io.Writer) {
fake.Stdout = out
}
func (fake *FakeCmd) SetStderr(out io.Writer) {
fake.Stderr = out
}
func (fake *FakeCmd) Run() error {
if fake.RunCalls > len(fake.RunScript)-1 {
panic("ran out of Run() actions")
}
if fake.RunLog == nil {
fake.RunLog = [][]string{}
}
i := fake.RunCalls
fake.RunLog = append(fake.RunLog, append([]string{}, fake.Argv...))
fake.RunCalls++
stdout, stderr, err := fake.RunScript[i]()
if stdout != nil {
fake.Stdout.Write(stdout)
}
if stderr != nil {
fake.Stderr.Write(stderr)
}
return err
}
func (fake *FakeCmd) CombinedOutput() ([]byte, error) {
if fake.CombinedOutputCalls > len(fake.CombinedOutputScript)-1 {
panic("ran out of CombinedOutput() actions")
}
if fake.CombinedOutputLog == nil {
fake.CombinedOutputLog = [][]string{}
}
i := fake.CombinedOutputCalls
fake.CombinedOutputLog = append(fake.CombinedOutputLog, append([]string{}, fake.Argv...))
fake.CombinedOutputCalls++
return fake.CombinedOutputScript[i]()
}
func (fake *FakeCmd) Output() ([]byte, error) {
return nil, fmt.Errorf("unimplemented")
}
func (fake *FakeCmd) Stop() {
// no-op
}
// A simple fake ExitError type.
type FakeExitError struct {
Status int
}
var _ exec.ExitError = FakeExitError{}
func (fake FakeExitError) String() string {
return fmt.Sprintf("exit %d", fake.Status)
}
func (fake FakeExitError) Error() string {
return fake.String()
}
func (fake FakeExitError) Exited() bool {
return true
}
func (fake FakeExitError) ExitStatus() int {
return fake.Status
}

70
vendor/k8s.io/utils/temp/dir.go generated vendored Normal file
View File

@ -0,0 +1,70 @@
/*
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 temp
import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
)
// Directory is an interface to a temporary directory, in which you can
// create new files.
type Directory interface {
// NewFile creates a new file in that directory. Calling NewFile
// with the same filename twice will result in an error.
NewFile(name string) (io.WriteCloser, error)
// Delete removes the directory and its content.
Delete() error
}
// TempDir is wrapping an temporary directory on disk.
type TempDir struct {
// Name is the name (full path) of the created directory.
Name string
}
var _ Directory = &TempDir{}
// CreateTempDir returns a new Directory wrapping a temporary directory
// on disk.
func CreateTempDir(prefix string) (*TempDir, error) {
name, err := ioutil.TempDir("", fmt.Sprintf("%s-", prefix))
if err != nil {
return nil, err
}
return &TempDir{
Name: name,
}, nil
}
// NewFile creates a new file in the specified directory.
func (d *TempDir) NewFile(name string) (io.WriteCloser, error) {
return os.OpenFile(
filepath.Join(d.Name, name),
os.O_WRONLY|os.O_CREATE|os.O_TRUNC|os.O_EXCL,
0700,
)
}
// Delete the underlying directory, and all of its content.
func (d *TempDir) Delete() error {
return os.RemoveAll(d.Name)
}

90
vendor/k8s.io/utils/temp/dir_test.go generated vendored Normal file
View File

@ -0,0 +1,90 @@
/*
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 temp
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
)
func TestTempDir(t *testing.T) {
dir, err := CreateTempDir("prefix")
if err != nil {
t.Fatal(err)
}
// Delete the directory no matter what.
defer dir.Delete()
// Make sure we have created the dir, with the proper name
_, err = os.Stat(dir.Name)
if err != nil {
t.Fatal(err)
}
if !strings.HasPrefix(filepath.Base(dir.Name), "prefix") {
t.Fatalf(`Directory doesn't start with "prefix": %q`,
dir.Name)
}
// Verify that the directory is empty
entries, err := ioutil.ReadDir(dir.Name)
if err != nil {
t.Fatal(err)
}
if len(entries) != 0 {
t.Fatalf("Directory should be empty, has %d elements",
len(entries))
}
// Create a couple of files
_, err = dir.NewFile("ONE")
if err != nil {
t.Fatal(err)
}
_, err = dir.NewFile("TWO")
if err != nil {
t.Fatal(err)
}
// We can't create the same file twice
_, err = dir.NewFile("TWO")
if err == nil {
t.Fatal("NewFile should fail to create the same file twice")
}
// We have created only two files
entries, err = ioutil.ReadDir(dir.Name)
if err != nil {
t.Fatal(err)
}
if len(entries) != 2 {
t.Fatalf("ReadDir should have two elements, has %d elements",
len(entries))
}
// Verify that deletion works
err = dir.Delete()
if err != nil {
t.Fatal(err)
}
_, err = os.Stat(dir.Name)
if err == nil {
t.Fatal("Directory should be gone, still present.")
}
}

19
vendor/k8s.io/utils/temp/doc.go generated vendored Normal file
View File

@ -0,0 +1,19 @@
/*
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 temp provides an interface to handle temporary files and
// directories.
package temp // import "k8s.io/utils/temp"

66
vendor/k8s.io/utils/temp/temptest/dir.go generated vendored Normal file
View File

@ -0,0 +1,66 @@
/*
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 temptest
import (
"errors"
"fmt"
"io"
"k8s.io/utils/temp"
)
// FakeDir implements a Directory that is not backed on the
// filesystem. This is useful for testing since the created "files" are
// simple bytes.Buffer that can be inspected.
type FakeDir struct {
Files map[string]*FakeFile
Deleted bool
}
var _ temp.Directory = &FakeDir{}
// NewFile returns a new FakeFile if the filename doesn't exist already.
// This function will fail if the directory has already been deleted.
func (d *FakeDir) NewFile(name string) (io.WriteCloser, error) {
if d.Deleted {
return nil, errors.New("can't create file in deleted FakeDir")
}
if d.Files == nil {
d.Files = map[string]*FakeFile{}
}
f := d.Files[name]
if f != nil {
return nil, fmt.Errorf(
"FakeDir already has file named %q",
name,
)
}
f = &FakeFile{}
d.Files[name] = f
return f, nil
}
// Delete doesn't remove anything, but records that the directory has
// been deleted.
func (d *FakeDir) Delete() error {
if d.Deleted {
return errors.New("failed to re-delete FakeDir")
}
d.Deleted = true
return nil
}

67
vendor/k8s.io/utils/temp/temptest/dir_test.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
/*
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 temptest
import (
"io"
"testing"
)
func TestFakeDir(t *testing.T) {
d := &FakeDir{}
f, err := d.NewFile("ONE")
if err != nil {
t.Fatal(err)
}
n, err := io.WriteString(f, "Bonjour!")
if n != 8 || err != nil {
t.Fatalf(
`WriteString(f, "Bonjour!") = (%v, %v), expected (%v, %v)`,
n, err,
0, nil,
)
}
if got := d.Files["ONE"].Buffer.String(); got != "Bonjour!" {
t.Fatalf(`file content is %q, expected "Bonjour!"`, got)
}
f, err = d.NewFile("ONE")
if err == nil {
t.Fatal("Same file could be created twice.")
}
err = d.Delete()
if err != nil {
t.Fatal(err)
}
err = d.Delete()
if err == nil {
t.Fatal("FakeDir could be deleted twice.")
}
f, err = d.NewFile("TWO")
if err == nil {
t.Fatal("NewFile could be created in deleted dir")
}
if !d.Deleted {
t.Fatal("FakeDir should be deleted.")
}
}

19
vendor/k8s.io/utils/temp/temptest/doc.go generated vendored Normal file
View File

@ -0,0 +1,19 @@
/*
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 temptest provides utilities for testing temp
// files/directories testing.
package temptest

57
vendor/k8s.io/utils/temp/temptest/example_test.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
/*
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 temptest
import (
"errors"
"fmt"
"io"
"k8s.io/utils/temp"
)
func TestedCode(dir temp.Directory) error {
f, err := dir.NewFile("filename")
if err != nil {
return err
}
_, err = io.WriteString(f, "Bonjour!")
if err != nil {
return err
}
return dir.Delete()
}
func Example() {
dir := FakeDir{}
err := TestedCode(&dir)
if err != nil {
panic(err)
}
if dir.Deleted == false {
panic(errors.New("Directory should have been deleted."))
}
if dir.Files["filename"] == nil {
panic(errors.New(`"filename" should have been created.`))
}
fmt.Println(dir.Files["filename"].Buffer.String())
// Output: Bonjour!
}

52
vendor/k8s.io/utils/temp/temptest/file.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
/*
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 temptest
import (
"bytes"
"errors"
"io"
)
// FakeFile is an implementation of a WriteCloser, that records what has
// been written in the file (in a bytes.Buffer) and if the file has been
// closed.
type FakeFile struct {
Buffer bytes.Buffer
Closed bool
}
var _ io.WriteCloser = &FakeFile{}
// Write appends the contents of p to the Buffer. If the file has
// already been closed, an error is returned.
func (f *FakeFile) Write(p []byte) (n int, err error) {
if f.Closed {
return 0, errors.New("can't write to closed FakeFile")
}
return f.Buffer.Write(p)
}
// Close records that the file has been closed. If the file has already
// been closed, an error is returned.
func (f *FakeFile) Close() error {
if f.Closed {
return errors.New("FakeFile was closed multiple times")
}
f.Closed = true
return nil
}

56
vendor/k8s.io/utils/temp/temptest/file_test.go generated vendored Normal file
View File

@ -0,0 +1,56 @@
/*
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 temptest
import (
"io"
"testing"
)
func TestFakeFile(t *testing.T) {
f := &FakeFile{}
n, err := io.WriteString(f, "Bonjour!")
if n != 8 || err != nil {
t.Fatalf(
`WriteString(f, "Bonjour!") = (%v, %v), expected (%v, %v)`,
n, err,
8, nil,
)
}
err = f.Close()
if err != nil {
t.Fatal(err)
}
// File can't be closed twice.
err = f.Close()
if err == nil {
t.Fatal("FakeFile could be closed twice")
}
// File is not writable after close.
n, err = io.WriteString(f, "Bonjour!")
if n != 0 || err == nil {
t.Fatalf(
`WriteString(f, "Bonjour!") = (%v, %v), expected (%v, %v)`,
n, err,
0, "non-nil",
)
}
}