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

     1  package exec_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  
     7  	"github.com/pf-qiu/concourse/v6/atc/exec"
     8  	"github.com/pf-qiu/concourse/v6/atc/exec/build"
     9  	"github.com/pf-qiu/concourse/v6/atc/exec/execfakes"
    10  	. "github.com/onsi/ginkgo"
    11  	. "github.com/onsi/gomega"
    12  )
    13  
    14  var _ = Describe("Ensure Step", func() {
    15  	var (
    16  		ctx    context.Context
    17  		cancel func()
    18  
    19  		step *execfakes.FakeStep
    20  		hook *execfakes.FakeStep
    21  
    22  		repo  *build.Repository
    23  		state *execfakes.FakeRunState
    24  
    25  		ensure exec.Step
    26  
    27  		stepOk  bool
    28  		stepErr error
    29  	)
    30  
    31  	BeforeEach(func() {
    32  		ctx, cancel = context.WithCancel(context.Background())
    33  
    34  		step = &execfakes.FakeStep{}
    35  		hook = &execfakes.FakeStep{}
    36  
    37  		step = &execfakes.FakeStep{}
    38  		hook = &execfakes.FakeStep{}
    39  
    40  		step.RunStub = func(ctx context.Context, state exec.RunState) (bool, error) {
    41  			return true, ctx.Err()
    42  		}
    43  
    44  		hook.RunStub = func(ctx context.Context, state exec.RunState) (bool, error) {
    45  			return true, ctx.Err()
    46  		}
    47  
    48  		repo = build.NewRepository()
    49  		state = new(execfakes.FakeRunState)
    50  		state.ArtifactRepositoryReturns(repo)
    51  
    52  		ensure = exec.Ensure(step, hook)
    53  	})
    54  
    55  	JustBeforeEach(func() {
    56  		stepOk, stepErr = ensure.Run(ctx, state)
    57  	})
    58  
    59  	Context("when the step succeeds", func() {
    60  		BeforeEach(func() {
    61  			step.RunReturns(true, nil)
    62  		})
    63  
    64  		It("returns nil", func() {
    65  			Expect(stepErr).ToNot(HaveOccurred())
    66  		})
    67  
    68  		It("runs the ensure hook", func() {
    69  			Expect(step.RunCallCount()).To(Equal(1))
    70  			Expect(hook.RunCallCount()).To(Equal(1))
    71  		})
    72  	})
    73  
    74  	Context("when the step fails", func() {
    75  		BeforeEach(func() {
    76  			step.RunReturns(false, nil)
    77  		})
    78  
    79  		It("returns nil", func() {
    80  			Expect(stepErr).ToNot(HaveOccurred())
    81  		})
    82  
    83  		It("runs the ensure hook", func() {
    84  			Expect(step.RunCallCount()).To(Equal(1))
    85  			Expect(hook.RunCallCount()).To(Equal(1))
    86  		})
    87  	})
    88  
    89  	Context("when the step errors", func() {
    90  		disaster := errors.New("disaster")
    91  
    92  		BeforeEach(func() {
    93  			step.RunReturns(false, disaster)
    94  		})
    95  
    96  		It("returns the error", func() {
    97  			Expect(stepErr).To(HaveOccurred())
    98  			Expect(stepErr.Error()).To(ContainSubstring("disaster"))
    99  		})
   100  
   101  		It("runs the ensure hook", func() {
   102  			Expect(step.RunCallCount()).To(Equal(1))
   103  			Expect(hook.RunCallCount()).To(Equal(1))
   104  		})
   105  	})
   106  
   107  	Context("when the context is canceled during the first step", func() {
   108  		BeforeEach(func() {
   109  			cancel()
   110  		})
   111  
   112  		It("returns context.Canceled", func() {
   113  			Expect(stepErr).To(Equal(context.Canceled))
   114  		})
   115  
   116  		It("cancels the first step and runs the hook (without canceling it)", func() {
   117  			Expect(step.RunCallCount()).To(Equal(1))
   118  			Expect(hook.RunCallCount()).To(Equal(1))
   119  
   120  			stepCtx, _ := step.RunArgsForCall(0)
   121  			Expect(stepCtx.Err()).To(Equal(context.Canceled))
   122  
   123  			hookCtx, _ := hook.RunArgsForCall(0)
   124  			Expect(hookCtx.Err()).ToNot(HaveOccurred())
   125  		})
   126  	})
   127  
   128  	Context("when the context is canceled during the hook", func() {
   129  		BeforeEach(func() {
   130  			hook.RunStub = func(context.Context, exec.RunState) (bool, error) {
   131  				cancel()
   132  				return false, ctx.Err()
   133  			}
   134  		})
   135  
   136  		It("returns context.Canceled", func() {
   137  			Expect(stepErr).To(Equal(context.Canceled))
   138  		})
   139  
   140  		It("allows canceling the hook if the first step has not been canceled", func() {
   141  			Expect(step.RunCallCount()).To(Equal(1))
   142  			Expect(hook.RunCallCount()).To(Equal(1))
   143  
   144  			stepCtx, _ := step.RunArgsForCall(0)
   145  			Expect(stepCtx.Err()).To(Equal(context.Canceled))
   146  
   147  			hookCtx, _ := hook.RunArgsForCall(0)
   148  			Expect(hookCtx.Err()).To(Equal(context.Canceled))
   149  		})
   150  	})
   151  
   152  	Context("when both step and hook succeed", func() {
   153  		BeforeEach(func() {
   154  			step.RunReturns(true, nil)
   155  			hook.RunReturns(true, nil)
   156  		})
   157  
   158  		It("succeeds", func() {
   159  			Expect(stepOk).To(BeTrue())
   160  		})
   161  	})
   162  
   163  	Context("when step succeeds and hook fails", func() {
   164  		BeforeEach(func() {
   165  			step.RunReturns(true, nil)
   166  			hook.RunReturns(false, nil)
   167  		})
   168  
   169  		It("does not succeed", func() {
   170  			Expect(stepOk).To(BeFalse())
   171  		})
   172  	})
   173  
   174  	Context("when step fails and hook succeeds", func() {
   175  		BeforeEach(func() {
   176  			step.RunReturns(false, nil)
   177  			hook.RunReturns(true, nil)
   178  		})
   179  
   180  		It("does not succeed", func() {
   181  			Expect(stepOk).To(BeFalse())
   182  		})
   183  	})
   184  
   185  	Context("when step succeeds and hook fails", func() {
   186  		BeforeEach(func() {
   187  			step.RunReturns(false, nil)
   188  			hook.RunReturns(false, nil)
   189  		})
   190  
   191  		It("does not succeed", func() {
   192  			Expect(stepOk).To(BeFalse())
   193  		})
   194  	})
   195  })