<commit_before>package steps_test

import (
	"errors"
	"sync"

	"github.com/hashicorp/go-multierror"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/cloudfoundry-incubator/executor/depot/steps"
	"github.com/cloudfoundry-incubator/executor/depot/steps/fakes"
)

var _ = Describe("CodependentStep", func() {
	var step steps.Step
	var subStep1 *fakes.FakeStep
	var subStep2 *fakes.FakeStep

	var thingHappened chan bool
	var cancelled chan bool

	var errorOnExit bool

	BeforeEach(func() {
		errorOnExit = false

		thingHappened = make(chan bool, 2)
		cancelled = make(chan bool, 2)

		running := new(sync.WaitGroup)
		running.Add(2)

		subStep1 = &fakes.FakeStep{
			PerformStub: func() error {
				running.Done()
				running.Wait()
				thingHappened <- true
				return nil
			},
			CancelStub: func() {
				cancelled <- true
			},
		}

		subStep2 = &fakes.FakeStep{
			PerformStub: func() error {
				running.Done()
				running.Wait()
				thingHappened <- true
				return nil
			},
			CancelStub: func() {
				cancelled <- true
			},
		}
	})

	JustBeforeEach(func() {
		step = steps.NewCodependent([]steps.Step{subStep1, subStep2}, errorOnExit)
	})

	Describe("Perform", func() {
		It("performs its substeps in parallel", func() {
			err := step.Perform()
			Expect(err).NotTo(HaveOccurred())

			Eventually(thingHappened).Should(Receive())
			Eventually(thingHappened).Should(Receive())
		})

		Context("when one of the substeps fails", func() {
			disaster := errors.New("oh no!")

			BeforeEach(func() {
				subStep1 = &fakes.FakeStep{
					PerformStub: func() error {
						return disaster
					},
				}

				subStep2 = &fakes.FakeStep{
					PerformStub: func() error {
						return nil
					},
				}
			})

			It("returns an aggregate of the failures", func() {
				err := step.Perform()
				Expect(err.(*multierror.Error).WrappedErrors()).To(ConsistOf(disaster))
			})

			It("cancels all the steps", func() {
				step.Perform()

				Expect(subStep1.CancelCallCount()).To(Equal(1))
				Expect(subStep2.CancelCallCount()).To(Equal(1))
			})
		})

		Context("when one of the substeps exits without failure", func() {
			var (
				cancelledError, err error
				errCh               chan error
			)

			BeforeEach(func() {
				cancelledError = errors.New("I was cancelled yo.")
				cancelled2 := make(chan bool)

				subStep1.PerformStub = func() error {
					return nil
				}

				subStep2.PerformStub = func() error {
					<-cancelled2
					return cancelledError
				}

				subStep2.CancelStub = func() {
					cancelled2 <- true
				}
			})

			JustBeforeEach(func() {
				errCh = make(chan error)

				go func() {
					errCh <- step.Perform()
				}()
			})

			It("continues to performe the other step", func() {
				Eventually(errCh).ShouldNot(Receive())
			})

			Context("when errorOnExit is set to true", func() {
				BeforeEach(func() {
					errorOnExit = true
				})

				It("returns an aggregate of the failures", func() {
					Eventually(errCh).Should(Receive(&err))
					Expect(err.(*multierror.Error).WrappedErrors()).To(ConsistOf(cancelledError, steps.CodependentStepExitedError))
				})

				It("cancels all the steps", func() {
					Eventually(errCh).Should(Receive())

					Expect(subStep1.CancelCallCount()).To(Equal(1))
					Expect(subStep2.CancelCallCount()).To(Equal(1))
				})
			})
		})<commit_msg>Wait until all steps are finished<commit_after>package steps_test

import (
	"errors"
	"sync"

	"github.com/hashicorp/go-multierror"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/cloudfoundry-incubator/executor/depot/steps"
	"github.com/cloudfoundry-incubator/executor/depot/steps/fakes"
)

var _ = Describe("CodependentStep", func() {
	var step steps.Step
	var subStep1 *fakes.FakeStep
	var subStep2 *fakes.FakeStep

	var thingHappened chan bool
	var cancelled chan bool

	var errorOnExit bool

	BeforeEach(func() {
		errorOnExit = false

		thingHappened = make(chan bool, 2)
		cancelled = make(chan bool, 2)

		running := new(sync.WaitGroup)
		running.Add(2)

		subStep1 = &fakes.FakeStep{
			PerformStub: func() error {
				running.Done()
				running.Wait()
				thingHappened <- true
				return nil
			},
			CancelStub: func() {
				cancelled <- true
			},
		}

		subStep2 = &fakes.FakeStep{
			PerformStub: func() error {
				running.Done()
				running.Wait()
				thingHappened <- true
				return nil
			},
			CancelStub: func() {
				cancelled <- true
			},
		}
	})

	Describe("Perform", func() {
		JustBeforeEach(func() {
			step = steps.NewCodependent([]steps.Step{subStep1, subStep2}, errorOnExit)
		})

		It("performs its substeps in parallel", func() {
			err := step.Perform()
			Expect(err).NotTo(HaveOccurred())

			Eventually(thingHappened).Should(Receive())
			Eventually(thingHappened).Should(Receive())
		})

		Context("when one of the substeps fails", func() {
			disaster := errors.New("oh no!")

			BeforeEach(func() {
				subStep1 = &fakes.FakeStep{
					PerformStub: func() error {
						return disaster
					},
				}

				subStep2 = &fakes.FakeStep{
					PerformStub: func() error {
						return nil
					},
				}
			})

			It("returns an aggregate of the failures", func() {
				err := step.Perform()
				Expect(err.(*multierror.Error).WrappedErrors()).To(ConsistOf(disaster))
			})

			It("cancels all the steps", func() {
				step.Perform()

				Expect(subStep1.CancelCallCount()).To(Equal(1))
				Expect(subStep2.CancelCallCount()).To(Equal(1))
			})
		})

		Context("when one of the substeps exits without failure", func() {
			var (
				cancelledError, err error
				errCh               chan error
			)

			BeforeEach(func() {
				cancelledError = errors.New("I was cancelled yo.")
				cancelled2 := make(chan bool, 1)

				subStep1.PerformStub = func() error {
					return nil
				}

				subStep2.PerformStub = func() error {
					<-cancelled2
					return cancelledError
				}

				subStep2.CancelStub = func() {
					cancelled2 <- true
				}
			})

			JustBeforeEach(func() {
				errCh = make(chan error)

				go func() {
					errCh <- step.Perform()
				}()
			})

			It("continues to perform the other step", func() {
				Consistently(errCh).ShouldNot(Receive())

				By("cancelling, it should return")
				step.Cancel()
				Eventually(errCh).Should(Receive())
			})

			Context("when errorOnExit is set to true", func() {
				BeforeEach(func() {
					errorOnExit = true
				})

				It("returns an aggregate of the failures", func() {
					Eventually(errCh).Should(Receive(&err))
					Expect(err.(*multierror.Error).WrappedErrors()).To(ConsistOf(cancelledError, steps.CodependentStepExitedError))
				})

				It("cancels all the steps", func() {
					Eventually(errCh).Should(Receive())

					Expect(subStep1.CancelCallCount()).To(Equal(1))
					Expect(subStep2.CancelCallCount()).To(Equal(1))
				})
			})
		})
{'fraction_non_alphanumeric': 0.14094846571722214, 'fraction_numerical': 0.007487887241227426, 'mean_word_length': 3.0962116656644616, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6702139', 'n_tokens_mistral': 2935, 'n_tokens_neox': 2311, 'n_words': 456}