github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/exec/aggregate_test.go (about)

     1  package exec_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"sync"
     7  
     8  	"github.com/pf-qiu/concourse/v6/atc/exec"
     9  	. "github.com/pf-qiu/concourse/v6/atc/exec"
    10  	"github.com/pf-qiu/concourse/v6/atc/exec/build"
    11  	"github.com/pf-qiu/concourse/v6/atc/exec/execfakes"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("Aggregate", func() {
    17  	var (
    18  		ctx    context.Context
    19  		cancel func()
    20  
    21  		fakeStepA *execfakes.FakeStep
    22  		fakeStepB *execfakes.FakeStep
    23  
    24  		repo  *build.Repository
    25  		state *execfakes.FakeRunState
    26  
    27  		step    Step
    28  		stepOk  bool
    29  		stepErr error
    30  	)
    31  
    32  	BeforeEach(func() {
    33  		ctx, cancel = context.WithCancel(context.Background())
    34  
    35  		fakeStepA = new(execfakes.FakeStep)
    36  		fakeStepB = new(execfakes.FakeStep)
    37  
    38  		step = AggregateStep{
    39  			fakeStepA,
    40  			fakeStepB,
    41  		}
    42  
    43  		repo = build.NewRepository()
    44  		state = new(execfakes.FakeRunState)
    45  		state.ArtifactRepositoryReturns(repo)
    46  	})
    47  
    48  	AfterEach(func() {
    49  		cancel()
    50  	})
    51  
    52  	JustBeforeEach(func() {
    53  		stepOk, stepErr = step.Run(ctx, state)
    54  	})
    55  
    56  	It("succeeds", func() {
    57  		Expect(stepErr).ToNot(HaveOccurred())
    58  	})
    59  
    60  	It("passes the artifact repo to all steps", func() {
    61  		Expect(fakeStepA.RunCallCount()).To(Equal(1))
    62  		_, repo := fakeStepA.RunArgsForCall(0)
    63  		Expect(repo).To(Equal(repo))
    64  
    65  		Expect(fakeStepB.RunCallCount()).To(Equal(1))
    66  		_, repo = fakeStepB.RunArgsForCall(0)
    67  		Expect(repo).To(Equal(repo))
    68  	})
    69  
    70  	Describe("executing each source", func() {
    71  		BeforeEach(func() {
    72  			wg := new(sync.WaitGroup)
    73  			wg.Add(2)
    74  
    75  			fakeStepA.RunStub = func(context.Context, RunState) (bool, error) {
    76  				wg.Done()
    77  				wg.Wait()
    78  				return true, nil
    79  			}
    80  
    81  			fakeStepB.RunStub = func(context.Context, RunState) (bool, error) {
    82  				wg.Done()
    83  				wg.Wait()
    84  				return true, nil
    85  			}
    86  		})
    87  
    88  		It("happens concurrently", func() {
    89  			Expect(fakeStepA.RunCallCount()).To(Equal(1))
    90  			Expect(fakeStepB.RunCallCount()).To(Equal(1))
    91  		})
    92  	})
    93  
    94  	Describe("canceling", func() {
    95  		BeforeEach(func() {
    96  			cancel()
    97  		})
    98  
    99  		It("cancels each substep", func() {
   100  			ctx, _ := fakeStepA.RunArgsForCall(0)
   101  			Expect(ctx.Err()).To(Equal(context.Canceled))
   102  			ctx, _ = fakeStepB.RunArgsForCall(0)
   103  			Expect(ctx.Err()).To(Equal(context.Canceled))
   104  		})
   105  
   106  		It("returns ctx.Err()", func() {
   107  			Expect(stepErr).To(Equal(context.Canceled))
   108  		})
   109  	})
   110  
   111  	Context("when sources fail", func() {
   112  		disasterA := errors.New("nope A")
   113  		disasterB := errors.New("nope B")
   114  
   115  		BeforeEach(func() {
   116  			fakeStepA.RunReturns(false, disasterA)
   117  			fakeStepB.RunReturns(false, disasterB)
   118  		})
   119  
   120  		It("exits with an error including the original message", func() {
   121  			Expect(stepErr.Error()).To(ContainSubstring("nope A"))
   122  			Expect(stepErr.Error()).To(ContainSubstring("nope B"))
   123  		})
   124  	})
   125  
   126  	Context("when all sources are successful", func() {
   127  		BeforeEach(func() {
   128  			fakeStepA.RunReturns(true, nil)
   129  			fakeStepB.RunReturns(true, nil)
   130  		})
   131  
   132  		It("succeeds", func() {
   133  			Expect(stepOk).To(BeTrue())
   134  		})
   135  	})
   136  
   137  	Context("and some branches are not successful", func() {
   138  		BeforeEach(func() {
   139  			fakeStepA.RunReturns(true, nil)
   140  			fakeStepB.RunReturns(false, nil)
   141  		})
   142  
   143  		It("fails", func() {
   144  			Expect(stepOk).To(BeFalse())
   145  		})
   146  	})
   147  
   148  	Context("when no branches indicate success", func() {
   149  		BeforeEach(func() {
   150  			fakeStepA.RunReturns(false, nil)
   151  			fakeStepB.RunReturns(false, nil)
   152  		})
   153  
   154  		It("fails", func() {
   155  			Expect(stepOk).To(BeFalse())
   156  		})
   157  	})
   158  
   159  	Context("when there are no branches", func() {
   160  		BeforeEach(func() {
   161  			step = AggregateStep{}
   162  		})
   163  
   164  		It("returns true", func() {
   165  			Expect(stepOk).To(BeTrue())
   166  		})
   167  	})
   168  
   169  	Describe("Panic", func() {
   170  		Context("when one step panic", func() {
   171  			BeforeEach(func() {
   172  				fakeStepB.RunStub = func(_ context.Context, _ exec.RunState) (bool, error) {
   173  					panic("something terrible")
   174  				}
   175  			})
   176  
   177  			It("recover from panic and yields false", func() {
   178  				Expect(stepOk).To(BeFalse())
   179  				Expect(stepErr.Error()).To(ContainSubstring("something terrible"))
   180  			})
   181  		})
   182  	})
   183  })