From fc5d4050b1db8cecd9bc37f1d7edd144091936df Mon Sep 17 00:00:00 2001 From: Gareth Smith Date: Wed, 22 Nov 2017 12:19:15 +0000 Subject: [PATCH] Add Fixtures struct, which can start+stop everything Create a new set of test fixtures by doing: ``` f := test.NewFixtures("/path/to/etcd", "/path/to/apiserver") ``` Before running your integration tests, start all your fixtures: ``` err := f.Start() Expect(err).NotTo(HaveOccurred()) ``` Now that you have started your etcd and apiserver, you'll find the apiserver listening locally on the default port. When you're done with your testing, stop and clean up: ``` err := f.Stop() Expect(err).NotTo(HaveOccurred()) ``` --- pkg/framework/test/apiserver.go | 27 +++- pkg/framework/test/apiserver_test.go | 27 ++-- pkg/framework/test/etcd.go | 29 +++- pkg/framework/test/etcd_test.go | 27 ++-- pkg/framework/test/fixtures.go | 83 +++++++++++ pkg/framework/test/fixtures_test.go | 96 ++++++++++++ .../testfakes/fake_apiserver_start_stopper.go | 119 +++++++++++++++ .../test/testfakes/fake_etcd_start_stopper.go | 121 +++++++++++++++ .../test/testfakes/fake_temp_dir_manager.go | 139 ++++++++++++++++++ 9 files changed, 641 insertions(+), 27 deletions(-) create mode 100644 pkg/framework/test/fixtures.go create mode 100644 pkg/framework/test/fixtures_test.go create mode 100644 pkg/framework/test/testfakes/fake_apiserver_start_stopper.go create mode 100644 pkg/framework/test/testfakes/fake_etcd_start_stopper.go create mode 100644 pkg/framework/test/testfakes/fake_temp_dir_manager.go diff --git a/pkg/framework/test/apiserver.go b/pkg/framework/test/apiserver.go index a32daf311..e39ea96a4 100644 --- a/pkg/framework/test/apiserver.go +++ b/pkg/framework/test/apiserver.go @@ -6,17 +6,19 @@ import ( "fmt" "github.com/onsi/ginkgo" + "github.com/onsi/gomega/gbytes" "github.com/onsi/gomega/gexec" ) // APIServer knows how to run a kubernetes apiserver. Set it up with the path to a precompiled binary. type APIServer struct { // The path to the apiserver binary - Path string + Path string + session *gexec.Session } // Start starts the apiserver, and returns a gexec.Session. To stop it again, call Terminate and Wait on that session. -func (s APIServer) Start(etcdURL string) (*gexec.Session, error) { +func (s *APIServer) Start(etcdURL string) error { args := []string{ "--authorization-mode=Node,RBAC", "--runtime-config=admissionregistration.k8s.io/v1alpha1", @@ -31,5 +33,24 @@ func (s APIServer) Start(etcdURL string) (*gexec.Session, error) { } command := exec.Command(s.Path, args...) - return gexec.Start(command, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter) + var err error + s.session, err = gexec.Start(command, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter) + return err +} + +// Stop stops this process gracefully. +func (s *APIServer) Stop() { + if s.session != nil { + s.session.Terminate() + } +} + +// ExitCode returns the exit code of the process, if it has exited. If it hasn't exited yet, ExitCode returns -1. +func (s *APIServer) ExitCode() int { + return s.session.ExitCode() +} + +// Buffer implements the gbytes.BufferProvider interface and returns the stdout of the process +func (s *APIServer) Buffer() *gbytes.Buffer { + return s.session.Buffer() } diff --git a/pkg/framework/test/apiserver_test.go b/pkg/framework/test/apiserver_test.go index 71dfacd7a..17b8fbbe8 100644 --- a/pkg/framework/test/apiserver_test.go +++ b/pkg/framework/test/apiserver_test.go @@ -15,37 +15,44 @@ var _ = Describe("Apiserver", func() { It("can start and stop that binary", func() { pathToFakeAPIServer, err := gexec.Build("k8s.io/kubectl/pkg/framework/test/assets/fakeapiserver") Expect(err).NotTo(HaveOccurred()) - apiServer := APIServer{Path: pathToFakeAPIServer} + apiServer := &APIServer{Path: pathToFakeAPIServer} By("Starting the API Server") - session, err := apiServer.Start("the etcd url") + err = apiServer.Start("the etcd url") Expect(err).NotTo(HaveOccurred()) - Eventually(session.Out).Should(gbytes.Say("Everything is fine")) - Expect(session).NotTo(gexec.Exit()) + Eventually(apiServer).Should(gbytes.Say("Everything is fine")) + Expect(apiServer).NotTo(gexec.Exit()) By("Stopping the API Server") - session.Terminate() - Eventually(session).Should(gexec.Exit(143)) + apiServer.Stop() + Eventually(apiServer).Should(gexec.Exit(143)) }) }) Context("when no path is given", func() { It("fails with a helpful error", func() { - apiServer := APIServer{} - _, err := apiServer.Start("the etcd url") + apiServer := &APIServer{} + err := apiServer.Start("the etcd url") Expect(err).To(MatchError(ContainSubstring("no such file or directory"))) }) }) Context("when given a path to a non-executable", func() { It("fails with a helpful error", func() { - apiServer := APIServer{ + apiServer := &APIServer{ Path: "./apiserver.go", } - _, err := apiServer.Start("the etcd url") + err := apiServer.Start("the etcd url") Expect(err).To(MatchError(ContainSubstring("./apiserver.go: permission denied"))) }) }) + + Context("when we try to stop a server that hasn't been started", func() { + It("does not panic", func() { + server := &APIServer{} + server.Stop() + }) + }) }) diff --git a/pkg/framework/test/etcd.go b/pkg/framework/test/etcd.go index 4fb23749d..5e448af71 100644 --- a/pkg/framework/test/etcd.go +++ b/pkg/framework/test/etcd.go @@ -4,17 +4,19 @@ import ( "os/exec" "github.com/onsi/ginkgo" + "github.com/onsi/gomega/gbytes" "github.com/onsi/gomega/gexec" ) // Etcd knows how to run an etcd server. Set it up with the path to a precompiled binary. type Etcd struct { // The path to the etcd binary - Path string + Path string + session *gexec.Session } // Start starts the etcd, and returns a gexec.Session. To stop it again, call Terminate and Wait on that session. -func (s Etcd) Start(etcdURL string, datadir string) (*gexec.Session, error) { +func (e *Etcd) Start(etcdURL string, datadir string) error { args := []string{ "--advertise-client-urls", etcdURL, @@ -25,6 +27,25 @@ func (s Etcd) Start(etcdURL string, datadir string) (*gexec.Session, error) { "--debug", } - command := exec.Command(s.Path, args...) - return gexec.Start(command, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter) + command := exec.Command(e.Path, args...) + var err error + e.session, err = gexec.Start(command, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter) + return err +} + +// Stop stops this process gracefully. +func (e *Etcd) Stop() { + if e.session != nil { + e.session.Terminate() + } +} + +// ExitCode returns the exit code of the process, if it has exited. If it hasn't exited yet, ExitCode returns -1. +func (e *Etcd) ExitCode() int { + return e.session.ExitCode() +} + +// Buffer implements the gbytes.BufferProvider interface and returns the stdout of the process +func (e *Etcd) Buffer() *gbytes.Buffer { + return e.session.Buffer() } diff --git a/pkg/framework/test/etcd_test.go b/pkg/framework/test/etcd_test.go index bbb379796..9b13cbdfc 100644 --- a/pkg/framework/test/etcd_test.go +++ b/pkg/framework/test/etcd_test.go @@ -15,37 +15,44 @@ var _ = Describe("Etcd", func() { It("can start and stop that binary", func() { pathToFakeEtcd, err := gexec.Build("k8s.io/kubectl/pkg/framework/test/assets/fakeetcd") Expect(err).NotTo(HaveOccurred()) - etcd := Etcd{Path: pathToFakeEtcd} + etcd := &Etcd{Path: pathToFakeEtcd} By("Starting the Etcd Server") - session, err := etcd.Start("our etcd url", "our data directory") + err = etcd.Start("our etcd url", "our data directory") Expect(err).NotTo(HaveOccurred()) - Eventually(session.Out).Should(gbytes.Say("Everything is dandy")) - Expect(session).NotTo(gexec.Exit()) + Eventually(etcd).Should(gbytes.Say("Everything is dandy")) + Expect(etcd).NotTo(gexec.Exit()) By("Stopping the Etcd Server") - session.Terminate() - Eventually(session).Should(gexec.Exit(143)) + etcd.Stop() + Eventually(etcd).Should(gexec.Exit(143)) }) }) Context("when no path is given", func() { It("fails with a helpful error", func() { - etcd := Etcd{} - _, err := etcd.Start("our etcd url", "") + etcd := &Etcd{} + err := etcd.Start("our etcd url", "") Expect(err).To(MatchError(ContainSubstring("no such file or directory"))) }) }) Context("when given a path to a non-executable", func() { It("fails with a helpful error", func() { - apiServer := Etcd{ + etcd := &Etcd{ Path: "./etcd.go", } - _, err := apiServer.Start("our etcd url", "") + err := etcd.Start("our etcd url", "") Expect(err).To(MatchError(ContainSubstring("./etcd.go: permission denied"))) }) }) + + Context("when we try to stop a server that hasn't been started", func() { + It("does not panic", func() { + etcd := &Etcd{} + etcd.Stop() + }) + }) }) diff --git a/pkg/framework/test/fixtures.go b/pkg/framework/test/fixtures.go new file mode 100644 index 000000000..8f15e94c5 --- /dev/null +++ b/pkg/framework/test/fixtures.go @@ -0,0 +1,83 @@ +package test + +import ( + "fmt" + "os" +) + +// Fixtures is a struct that knows how to start all your test fixtures. +// +// Right now, that means Etcd and your APIServer. This is likely to increase in future. +type Fixtures struct { + Etcd EtcdStartStopper + APIServer APIServerStartStopper + TempDirManager TempDirManager +} + +// EtcdStartStopper knows how to start an Etcd. One good implementation is Etcd. +type EtcdStartStopper interface { + Start(etcdURL, datadir string) error + Stop() +} + +//go:generate counterfeiter . EtcdStartStopper + +// APIServerStartStopper knows how to start an APIServer. One good implementation is APIServer. +type APIServerStartStopper interface { + Start(etcdURL string) error + Stop() +} + +//go:generate counterfeiter . APIServerStartStopper + +// TempDirManager knows how to create and destroy temporary directories. +type TempDirManager interface { + Create() string + Destroy() error +} + +//go:generate counterfeiter . TempDirManager + +// NewFixtures will give you a Fixtures struct that's properly wired together. +func NewFixtures(pathToEtcd, pathToAPIServer string) *Fixtures { + return &Fixtures{ + Etcd: &Etcd{Path: pathToEtcd}, + APIServer: &APIServer{Path: pathToAPIServer}, + TempDirManager: &tempDirManager{}, + } +} + +type tempDirManager struct { + dir string +} + +func (t *tempDirManager) Create() string { + t.dir = os.TempDir() + return t.dir +} + +func (t *tempDirManager) Destroy() error { + if t.dir != "" { + return os.RemoveAll(t.dir) + } + return nil +} + +// Start will start all your fixtures. To stop them, call Stop(). +func (f *Fixtures) Start() error { + tmpDir := f.TempDirManager.Create() + if err := f.Etcd.Start("tcp://127.0.0.1:2379", tmpDir); err != nil { + return fmt.Errorf("Error starting etcd: %s", err) + } + if err := f.APIServer.Start("tcp://127.0.0.1:2379"); err != nil { + return fmt.Errorf("Error starting apiserver: %s", err) + } + return nil +} + +// Stop will stop all your fixtures, and clean up their data. +func (f *Fixtures) Stop() error { + f.APIServer.Stop() + f.Etcd.Stop() + return f.TempDirManager.Destroy() +} diff --git a/pkg/framework/test/fixtures_test.go b/pkg/framework/test/fixtures_test.go new file mode 100644 index 000000000..ad19f04d0 --- /dev/null +++ b/pkg/framework/test/fixtures_test.go @@ -0,0 +1,96 @@ +package test_test + +import ( + . "k8s.io/kubectl/pkg/framework/test" + + "fmt" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/kubectl/pkg/framework/test/testfakes" +) + +var _ = Describe("Fixtures", func() { + It("can construct a properly wired Fixtures struct", func() { + f := NewFixtures("path to etcd", "path to apiserver") + Expect(f.Etcd.(*Etcd).Path).To(Equal("path to etcd")) + Expect(f.APIServer.(*APIServer).Path).To(Equal("path to apiserver")) + }) + + Context("with a properly configured set of Fixtures", func() { + var ( + fakeEtcdStartStopper *testfakes.FakeEtcdStartStopper + fakeAPIServerStartStopper *testfakes.FakeAPIServerStartStopper + fakeTempDirManager *testfakes.FakeTempDirManager + fixtures Fixtures + ) + BeforeEach(func() { + fakeEtcdStartStopper = &testfakes.FakeEtcdStartStopper{} + fakeAPIServerStartStopper = &testfakes.FakeAPIServerStartStopper{} + fakeTempDirManager = &testfakes.FakeTempDirManager{} + fixtures = Fixtures{ + Etcd: fakeEtcdStartStopper, + APIServer: fakeAPIServerStartStopper, + TempDirManager: fakeTempDirManager, + } + }) + + It("can start them", func() { + fakeTempDirManager.CreateReturns("some temp dir") + + err := fixtures.Start() + Expect(err).NotTo(HaveOccurred()) + + By("creating a temporary directory") + Expect(fakeTempDirManager.CreateCallCount()).To(Equal(1), + "the TempDirManager should be called exactly once") + + By("starting Etcd") + Expect(fakeEtcdStartStopper.StartCallCount()).To(Equal(1), + "the EtcdStartStopper should be called exactly once") + url, datadir := fakeEtcdStartStopper.StartArgsForCall(0) + Expect(url).To(Equal("tcp://127.0.0.1:2379")) + Expect(datadir).To(Equal("some temp dir")) + + By("starting APIServer") + Expect(fakeAPIServerStartStopper.StartCallCount()).To(Equal(1), + "the APIServerStartStopper should be called exactly once") + url = fakeAPIServerStartStopper.StartArgsForCall(0) + Expect(url).To(Equal("tcp://127.0.0.1:2379")) + }) + + Context("when starting etcd fails", func() { + It("wraps the error", func() { + fakeEtcdStartStopper.StartReturns(fmt.Errorf("some error")) + err := fixtures.Start() + Expect(err).To(MatchError(ContainSubstring("some error"))) + }) + }) + + Context("when starting APIServer fails", func() { + It("wraps the error", func() { + fakeAPIServerStartStopper.StartReturns(fmt.Errorf("another error")) + err := fixtures.Start() + Expect(err).To(MatchError(ContainSubstring("another error"))) + }) + }) + + It("can can clean up the temporary directory and stop", func() { + fixtures.Stop() + Expect(fakeEtcdStartStopper.StopCallCount()).To(Equal(1)) + Expect(fakeAPIServerStartStopper.StopCallCount()).To(Equal(1)) + Expect(fakeTempDirManager.DestroyCallCount()).To(Equal(1)) + }) + + Context("when cleanup fails", func() { + It("still stops the services, and it bubbles up the error", func() { + fakeTempDirManager.DestroyReturns(fmt.Errorf("deletion failed")) + err := fixtures.Stop() + Expect(err).To(MatchError(ContainSubstring("deletion failed"))) + + Expect(fakeEtcdStartStopper.StopCallCount()).To(Equal(1)) + Expect(fakeAPIServerStartStopper.StopCallCount()).To(Equal(1)) + }) + }) + }) +}) diff --git a/pkg/framework/test/testfakes/fake_apiserver_start_stopper.go b/pkg/framework/test/testfakes/fake_apiserver_start_stopper.go new file mode 100644 index 000000000..7a792e542 --- /dev/null +++ b/pkg/framework/test/testfakes/fake_apiserver_start_stopper.go @@ -0,0 +1,119 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package testfakes + +import ( + "sync" + + "k8s.io/kubectl/pkg/framework/test" +) + +type FakeAPIServerStartStopper struct { + StartStub func(etcdURL string) error + startMutex sync.RWMutex + startArgsForCall []struct { + etcdURL string + } + startReturns struct { + result1 error + } + startReturnsOnCall map[int]struct { + result1 error + } + StopStub func() + stopMutex sync.RWMutex + stopArgsForCall []struct{} + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeAPIServerStartStopper) Start(etcdURL string) error { + fake.startMutex.Lock() + ret, specificReturn := fake.startReturnsOnCall[len(fake.startArgsForCall)] + fake.startArgsForCall = append(fake.startArgsForCall, struct { + etcdURL string + }{etcdURL}) + fake.recordInvocation("Start", []interface{}{etcdURL}) + fake.startMutex.Unlock() + if fake.StartStub != nil { + return fake.StartStub(etcdURL) + } + if specificReturn { + return ret.result1 + } + return fake.startReturns.result1 +} + +func (fake *FakeAPIServerStartStopper) StartCallCount() int { + fake.startMutex.RLock() + defer fake.startMutex.RUnlock() + return len(fake.startArgsForCall) +} + +func (fake *FakeAPIServerStartStopper) StartArgsForCall(i int) string { + fake.startMutex.RLock() + defer fake.startMutex.RUnlock() + return fake.startArgsForCall[i].etcdURL +} + +func (fake *FakeAPIServerStartStopper) StartReturns(result1 error) { + fake.StartStub = nil + fake.startReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeAPIServerStartStopper) StartReturnsOnCall(i int, result1 error) { + fake.StartStub = nil + if fake.startReturnsOnCall == nil { + fake.startReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.startReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeAPIServerStartStopper) Stop() { + fake.stopMutex.Lock() + fake.stopArgsForCall = append(fake.stopArgsForCall, struct{}{}) + fake.recordInvocation("Stop", []interface{}{}) + fake.stopMutex.Unlock() + if fake.StopStub != nil { + fake.StopStub() + } +} + +func (fake *FakeAPIServerStartStopper) StopCallCount() int { + fake.stopMutex.RLock() + defer fake.stopMutex.RUnlock() + return len(fake.stopArgsForCall) +} + +func (fake *FakeAPIServerStartStopper) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.startMutex.RLock() + defer fake.startMutex.RUnlock() + fake.stopMutex.RLock() + defer fake.stopMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeAPIServerStartStopper) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ test.APIServerStartStopper = new(FakeAPIServerStartStopper) diff --git a/pkg/framework/test/testfakes/fake_etcd_start_stopper.go b/pkg/framework/test/testfakes/fake_etcd_start_stopper.go new file mode 100644 index 000000000..b59e89b81 --- /dev/null +++ b/pkg/framework/test/testfakes/fake_etcd_start_stopper.go @@ -0,0 +1,121 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package testfakes + +import ( + "sync" + + "k8s.io/kubectl/pkg/framework/test" +) + +type FakeEtcdStartStopper struct { + StartStub func(etcdURL, datadir string) error + startMutex sync.RWMutex + startArgsForCall []struct { + etcdURL string + datadir string + } + startReturns struct { + result1 error + } + startReturnsOnCall map[int]struct { + result1 error + } + StopStub func() + stopMutex sync.RWMutex + stopArgsForCall []struct{} + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeEtcdStartStopper) Start(etcdURL string, datadir string) error { + fake.startMutex.Lock() + ret, specificReturn := fake.startReturnsOnCall[len(fake.startArgsForCall)] + fake.startArgsForCall = append(fake.startArgsForCall, struct { + etcdURL string + datadir string + }{etcdURL, datadir}) + fake.recordInvocation("Start", []interface{}{etcdURL, datadir}) + fake.startMutex.Unlock() + if fake.StartStub != nil { + return fake.StartStub(etcdURL, datadir) + } + if specificReturn { + return ret.result1 + } + return fake.startReturns.result1 +} + +func (fake *FakeEtcdStartStopper) StartCallCount() int { + fake.startMutex.RLock() + defer fake.startMutex.RUnlock() + return len(fake.startArgsForCall) +} + +func (fake *FakeEtcdStartStopper) StartArgsForCall(i int) (string, string) { + fake.startMutex.RLock() + defer fake.startMutex.RUnlock() + return fake.startArgsForCall[i].etcdURL, fake.startArgsForCall[i].datadir +} + +func (fake *FakeEtcdStartStopper) StartReturns(result1 error) { + fake.StartStub = nil + fake.startReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeEtcdStartStopper) StartReturnsOnCall(i int, result1 error) { + fake.StartStub = nil + if fake.startReturnsOnCall == nil { + fake.startReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.startReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeEtcdStartStopper) Stop() { + fake.stopMutex.Lock() + fake.stopArgsForCall = append(fake.stopArgsForCall, struct{}{}) + fake.recordInvocation("Stop", []interface{}{}) + fake.stopMutex.Unlock() + if fake.StopStub != nil { + fake.StopStub() + } +} + +func (fake *FakeEtcdStartStopper) StopCallCount() int { + fake.stopMutex.RLock() + defer fake.stopMutex.RUnlock() + return len(fake.stopArgsForCall) +} + +func (fake *FakeEtcdStartStopper) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.startMutex.RLock() + defer fake.startMutex.RUnlock() + fake.stopMutex.RLock() + defer fake.stopMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeEtcdStartStopper) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ test.EtcdStartStopper = new(FakeEtcdStartStopper) diff --git a/pkg/framework/test/testfakes/fake_temp_dir_manager.go b/pkg/framework/test/testfakes/fake_temp_dir_manager.go new file mode 100644 index 000000000..0f848099f --- /dev/null +++ b/pkg/framework/test/testfakes/fake_temp_dir_manager.go @@ -0,0 +1,139 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package testfakes + +import ( + "sync" + + "k8s.io/kubectl/pkg/framework/test" +) + +type FakeTempDirManager struct { + CreateStub func() string + createMutex sync.RWMutex + createArgsForCall []struct{} + createReturns struct { + result1 string + } + createReturnsOnCall map[int]struct { + result1 string + } + DestroyStub func() error + destroyMutex sync.RWMutex + destroyArgsForCall []struct{} + destroyReturns struct { + result1 error + } + destroyReturnsOnCall map[int]struct { + result1 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeTempDirManager) Create() string { + fake.createMutex.Lock() + ret, specificReturn := fake.createReturnsOnCall[len(fake.createArgsForCall)] + fake.createArgsForCall = append(fake.createArgsForCall, struct{}{}) + fake.recordInvocation("Create", []interface{}{}) + fake.createMutex.Unlock() + if fake.CreateStub != nil { + return fake.CreateStub() + } + if specificReturn { + return ret.result1 + } + return fake.createReturns.result1 +} + +func (fake *FakeTempDirManager) CreateCallCount() int { + fake.createMutex.RLock() + defer fake.createMutex.RUnlock() + return len(fake.createArgsForCall) +} + +func (fake *FakeTempDirManager) CreateReturns(result1 string) { + fake.CreateStub = nil + fake.createReturns = struct { + result1 string + }{result1} +} + +func (fake *FakeTempDirManager) CreateReturnsOnCall(i int, result1 string) { + fake.CreateStub = nil + if fake.createReturnsOnCall == nil { + fake.createReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.createReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *FakeTempDirManager) Destroy() error { + fake.destroyMutex.Lock() + ret, specificReturn := fake.destroyReturnsOnCall[len(fake.destroyArgsForCall)] + fake.destroyArgsForCall = append(fake.destroyArgsForCall, struct{}{}) + fake.recordInvocation("Destroy", []interface{}{}) + fake.destroyMutex.Unlock() + if fake.DestroyStub != nil { + return fake.DestroyStub() + } + if specificReturn { + return ret.result1 + } + return fake.destroyReturns.result1 +} + +func (fake *FakeTempDirManager) DestroyCallCount() int { + fake.destroyMutex.RLock() + defer fake.destroyMutex.RUnlock() + return len(fake.destroyArgsForCall) +} + +func (fake *FakeTempDirManager) DestroyReturns(result1 error) { + fake.DestroyStub = nil + fake.destroyReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeTempDirManager) DestroyReturnsOnCall(i int, result1 error) { + fake.DestroyStub = nil + if fake.destroyReturnsOnCall == nil { + fake.destroyReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.destroyReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeTempDirManager) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.createMutex.RLock() + defer fake.createMutex.RUnlock() + fake.destroyMutex.RLock() + defer fake.destroyMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeTempDirManager) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ test.TempDirManager = new(FakeTempDirManager)