Example #1
0
	It("runs the ensured hook even if the step errors", func() {
		step.RunReturns(errors.New("disaster"))

		process := ifrit.Background(ensureStep)

		Eventually(step.RunCallCount).Should(Equal(1))
		Eventually(process.Wait()).Should(Receive(errorMatching(ContainSubstring("disaster"))))

		Expect(hook.RunCallCount()).To(Equal(1))
	})

	It("propagates signals to the first step when first step is running", func() {
		step.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
			close(ready)

			<-signals
			return errors.New("interrupted")
		}

		process := ifrit.Background(ensureStep)

		process.Signal(os.Kill)

		Eventually(step.RunCallCount).Should(Equal(1))
		Eventually(process.Wait()).Should(Receive(errorMatching(ContainSubstring("interrupted"))))

		Expect(hook.RunCallCount()).To(Equal(1))
	})

	It("propagates signals to the hook when the hook is running", func() {
		hook.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
Example #2
0
					var foo interface{}
					destination := &foo
					Expect(step.Result(destination)).To(BeTrue())

					Expect(attempt2Step.ResultCallCount()).To(Equal(2))
					Expect(attempt2Step.ResultArgsForCall(1)).To(Equal(destination))
				})
			})
		})
	})

	Context("when attempt 1 errors, and attempt 2 is interrupted", func() {
		BeforeEach(func() {
			attempt1Step.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
				close(ready)
				return errors.New("nope")
			}

			attempt2Step.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
				close(ready)
				<-signals
				return ErrInterrupted
			}
		})

		Describe("Run", func() {
			var process ifrit.Process

			JustBeforeEach(func() {
				process = ifrit.Invoke(step)
				process.Signal(os.Interrupt)
Example #3
0
	JustBeforeEach(func() {
		timeout = Timeout(fakeStepFactoryStep, timeoutDuration)
		step = timeout.Using(nil, nil)
		process = ifrit.Background(step)
	})

	Context("when the process goes beyond the duration", func() {
		BeforeEach(func() {
			runStep.ResultStub = successResult(true)
			timeoutDuration = atc.Duration(1 * time.Second)

			runStep.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
				close(ready)
				select {
				case <-startStep:
					return nil
				case <-signals:
					return ErrInterrupted
				}
			}
		})

		It("should interrupt after timeout duration", func() {
			Eventually(runStep.RunCallCount).Should(Equal(1))

			var receivedError error
			Eventually(process.Wait(), 3*time.Second).Should(Receive(&receivedError))
			Ω(receivedError).Should(Equal(ErrStepTimedOut))
		})

		Context("when the process is signaled", func() {
Example #4
0
				_, _, location := fakeDelegate.InputDelegateArgsForCall(1)
				Ω(location).ShouldNot(BeNil())
			})
		})

		Context("when the steps complete", func() {
			BeforeEach(func() {
				assertNotReleased := func(signals <-chan os.Signal, ready chan<- struct{}) error {
					defer GinkgoRecover()
					Consistently(inputStep.ReleaseCallCount).Should(BeZero())
					Consistently(taskStep.ReleaseCallCount).Should(BeZero())
					Consistently(outputStep.ReleaseCallCount).Should(BeZero())
					return nil
				}

				inputStep.RunStub = assertNotReleased
				taskStep.RunStub = assertNotReleased
				outputStep.RunStub = assertNotReleased
			})

			It("releases all sources", func() {
				Ω(inputStep.ReleaseCallCount()).Should(Equal(1))
				Ω(taskStep.ReleaseCallCount()).Should(Equal(1))
				Ω(outputStep.ReleaseCallCount()).Should(BeNumerically(">", 0))
			})
		})

		Context("when the task is privileged", func() {
			BeforeEach(func() {
				privileged = true
			})
Example #5
0
		Ω(step).Should(Equal(inStep))
		Ω(repo).Should(Equal(repo))
	})

	It("exits successfully", func() {
		Eventually(process.Wait()).Should(Receive(BeNil()))
	})

	Describe("executing each source", func() {
		BeforeEach(func() {
			wg := new(sync.WaitGroup)
			wg.Add(2)

			outStepA.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
				wg.Done()
				wg.Wait()
				close(ready)
				return nil
			}

			outStepB.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
				wg.Done()
				wg.Wait()
				close(ready)
				return nil
			}
		})

		It("happens concurrently", func() {
			Ω(outStepA.RunCallCount()).Should(Equal(1))
			Ω(outStepB.RunCallCount()).Should(Equal(1))
		})
Example #6
0
					Type:    worker.ContainerTypeGet,
					Name:    "some-input",
				}))

				Ω(delegate).Should(Equal(fakeInputDelegate))
				_, _, location := fakeDelegate.InputDelegateArgsForCall(0)
				Ω(location).ShouldNot(BeNil())
			})
		})

		Context("when the step times out", func() {
			BeforeEach(func() {
				inputStep.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
					close(ready)

					time.Sleep(4 * time.Second)

					return nil
				}
			})

			It("does not run the next step", func() {
				plan := atc.Plan{
					OnSuccess: &atc.OnSuccessPlan{
						Step: atc.Plan{
							Timeout: &atc.TimeoutPlan{
								Duration: "2s",
								Step: atc.Plan{
									Location: &atc.Location{},
									Get: &atc.GetPlan{
										Name: "some-input",
Example #7
0
		finishStep = make(chan error, 1)

		startNextStep = make(chan error, 1)
		finishNextStep = make(chan error, 1)

		outStep.ResultStub = successResult(true)
		outStep.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
			select {
			case err := <-startStep:
				if err != nil {
					return err
				}
			case <-signals:
				return ErrInterrupted
			}

			close(ready)

			select {
			case <-signals:
				return ErrInterrupted
			case err := <-finishStep:
				return err
			}
		}

		nextStep.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
			select {
			case err := <-startNextStep:
				if err != nil {
					return err
Example #8
0
					Expect(delegate).To(Equal(fakeInputDelegate))
					_, _, location := fakeDelegate.InputDelegateArgsForCall(0)
					Expect(location).NotTo(BeNil())
					Expect(location.ID).To(Equal(uint(145)))
					Expect(location.ParentID).To(Equal(uint(1)))
					Expect(location.ParallelGroup).To(Equal(uint(1234)))
					Expect(location.SerialGroup).To(Equal(uint(5678)))
					Expect(location.Hook).To(Equal("boring input hook"))

				})

				It("releases inputs correctly", func() {
					inputStep.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
						defer GinkgoRecover()
						Consistently(inputStep.ReleaseCallCount).Should(BeZero())
						return nil
					}
					var err error
					build, err = execEngine.CreateBuild(logger, buildModel, plan)
					Expect(err).NotTo(HaveOccurred())
					build.Resume(logger)

					Expect(inputStep.ReleaseCallCount()).To(Equal(1))
				})
			})

			Context("that contains tasks", func() {
				privileged = false

				taskConfig = &atc.TaskConfig{
Example #9
0
		startA = make(chan error, 1)
		finishA = make(chan error, 1)

		startB = make(chan error, 1)
		finishB = make(chan error, 1)

		outStepA.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
			select {
			case err := <-startA:
				if err != nil {
					return err
				}
			case <-signals:
				return ErrInterrupted
			}

			close(ready)

			select {
			case <-signals:
				return ErrInterrupted
			case err := <-finishA:
				return err
			}
		}

		outStepB.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error {
			select {
			case err := <-startB:
				if err != nil {
					return err