github.com/chenbh/concourse/v6@v6.4.2/worker/runtime/killer_test.go (about)

     1  package runtime_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"testing"
     7  
     8  	"github.com/chenbh/concourse/v6/worker/runtime"
     9  	"github.com/chenbh/concourse/v6/worker/runtime/runtimefakes"
    10  	"github.com/chenbh/concourse/v6/worker/runtime/libcontainerd/libcontainerdfakes"
    11  	"github.com/containerd/containerd"
    12  	"github.com/containerd/containerd/runtime/v2/runc/options"
    13  	"github.com/containerd/typeurl"
    14  	"github.com/stretchr/testify/require"
    15  	"github.com/stretchr/testify/suite"
    16  )
    17  
    18  type KillerSuite struct {
    19  	suite.Suite
    20  	*require.Assertions
    21  
    22  	task          *libcontainerdfakes.FakeTask
    23  	processKiller *runtimefakes.FakeProcessKiller
    24  	killer        runtime.Killer
    25  }
    26  
    27  func (s *KillerSuite) SetupTest() {
    28  	s.task = new(libcontainerdfakes.FakeTask)
    29  	s.processKiller = new(runtimefakes.FakeProcessKiller)
    30  	s.killer = runtime.NewKiller(
    31  		runtime.WithProcessKiller(s.processKiller),
    32  	)
    33  }
    34  
    35  func (s *KillerSuite) TestKillTaskWithNoProcs() {
    36  	s.T().Run("graceful", func(_ *testing.T) {
    37  		err := s.killer.Kill(context.Background(), s.task, runtime.KillGracefully)
    38  		s.NoError(err)
    39  
    40  	})
    41  
    42  	s.T().Run("ungraceful", func(_ *testing.T) {
    43  		err := s.killer.Kill(context.Background(), s.task, runtime.KillUngracefully)
    44  		s.NoError(err)
    45  	})
    46  
    47  	s.Equal(2, s.task.PidsCallCount())
    48  	s.Equal(0, s.task.LoadProcessCallCount())
    49  }
    50  
    51  func (s *KillerSuite) TestKillTaskPidsErr() {
    52  	expectedErr := errors.New("pids-err")
    53  	s.task.PidsReturns(nil, expectedErr)
    54  
    55  	s.T().Run("graceful", func(_ *testing.T) {
    56  		err := s.killer.Kill(context.Background(), s.task, runtime.KillGracefully)
    57  		s.True(errors.Is(err, expectedErr))
    58  	})
    59  
    60  	s.T().Run("ungraceful", func(_ *testing.T) {
    61  		err := s.killer.Kill(context.Background(), s.task, runtime.KillUngracefully)
    62  		s.True(errors.Is(err, expectedErr))
    63  	})
    64  }
    65  
    66  func (s *KillerSuite) TestKillTaskWithOnlyInitProc() {
    67  	s.task.PidsReturns([]containerd.ProcessInfo{
    68  		{Pid: 1234, Info: nil}, // the `init` proc returns `info: nil`
    69  	}, nil)
    70  
    71  	s.T().Run("graceful", func(_ *testing.T) {
    72  		err := s.killer.Kill(context.Background(), s.task, runtime.KillUngracefully)
    73  		s.NoError(err)
    74  	})
    75  
    76  	s.T().Run("ungraceful", func(_ *testing.T) {
    77  		err := s.killer.Kill(context.Background(), s.task, runtime.KillUngracefully)
    78  		s.NoError(err)
    79  	})
    80  
    81  	s.Equal(2, s.task.PidsCallCount())
    82  	s.Equal(0, s.task.LoadProcessCallCount())
    83  	s.Equal(0, s.processKiller.KillCallCount())
    84  }
    85  
    86  func (s *KillerSuite) TestKillTaskLoadProcessError() {
    87  	procInfo, err := typeurl.MarshalAny(&options.ProcessDetails{
    88  		ExecID: "execution-1",
    89  	})
    90  	s.NoError(err)
    91  
    92  	s.task.PidsReturns([]containerd.ProcessInfo{
    93  		{Pid: 123, Info: procInfo},
    94  	}, nil)
    95  
    96  	expectedErr := errors.New("load-proc-err")
    97  	s.task.LoadProcessReturns(nil, expectedErr)
    98  
    99  	s.T().Run("graceful", func(_ *testing.T) {
   100  		err = s.killer.Kill(context.Background(), s.task, runtime.KillUngracefully)
   101  		s.True(errors.Is(err, expectedErr))
   102  	})
   103  
   104  	s.T().Run("ungraceful", func(_ *testing.T) {
   105  		err = s.killer.Kill(context.Background(), s.task, runtime.KillUngracefully)
   106  		s.True(errors.Is(err, expectedErr))
   107  	})
   108  }
   109  
   110  func (s *KillerSuite) TestUngracefulKillTaskProcKillError() {
   111  	procInfo, err := typeurl.MarshalAny(&options.ProcessDetails{
   112  		ExecID: "execution-1",
   113  	})
   114  	s.NoError(err)
   115  
   116  	s.task.PidsReturns([]containerd.ProcessInfo{
   117  		{Pid: 123, Info: procInfo},
   118  	}, nil)
   119  
   120  	expectedErr := errors.New("load-proc-err")
   121  	s.processKiller.KillReturns(expectedErr)
   122  
   123  	err = s.killer.Kill(context.Background(), s.task, runtime.KillUngracefully)
   124  	s.True(errors.Is(err, expectedErr))
   125  }
   126  
   127  func (s *KillerSuite) TestGracefulKillTaskProcKillGracePeriodTimeoutError() {
   128  	procInfo, err := typeurl.MarshalAny(&options.ProcessDetails{
   129  		ExecID: "execution-1",
   130  	})
   131  	s.NoError(err)
   132  
   133  	s.task.PidsReturns([]containerd.ProcessInfo{
   134  		{Pid: 123, Info: procInfo},
   135  	}, nil)
   136  
   137  	expectedErr := runtime.ErrGracePeriodTimeout
   138  	s.processKiller.KillReturnsOnCall(0, expectedErr)
   139  
   140  	err = s.killer.Kill(context.Background(), s.task, runtime.KillGracefully)
   141  	s.NoError(err)
   142  
   143  	s.Equal(2, s.processKiller.KillCallCount())
   144  }
   145  
   146  func (s *KillerSuite) TestGracefulKillTaskProcKillUncaughtError() {
   147  	procInfo, err := typeurl.MarshalAny(&options.ProcessDetails{
   148  		ExecID: "execution-1",
   149  	})
   150  	s.NoError(err)
   151  
   152  	s.task.PidsReturns([]containerd.ProcessInfo{
   153  		{Pid: 123, Info: procInfo},
   154  	}, nil)
   155  
   156  	expectedErr := errors.New("kill-err")
   157  	s.processKiller.KillReturnsOnCall(0, expectedErr)
   158  
   159  	err = s.killer.Kill(context.Background(), s.task, runtime.KillGracefully)
   160  	s.True(errors.Is(err, expectedErr))
   161  
   162  	s.Equal(1, s.processKiller.KillCallCount())
   163  }
   164  
   165  func (s *KillerSuite) TestGracefulKillTaskProcKillErrorOnUngracefulTry() {
   166  	procInfo, err := typeurl.MarshalAny(&options.ProcessDetails{
   167  		ExecID: "execution-1",
   168  	})
   169  	s.NoError(err)
   170  
   171  	s.task.PidsReturns([]containerd.ProcessInfo{
   172  		{Pid: 123, Info: procInfo},
   173  	}, nil)
   174  
   175  	s.processKiller.KillReturnsOnCall(0, runtime.ErrGracePeriodTimeout)
   176  	expectedErr := errors.New("ungraceful-kill-err")
   177  	s.processKiller.KillReturnsOnCall(1, expectedErr)
   178  
   179  	err = s.killer.Kill(context.Background(), s.task, runtime.KillGracefully)
   180  	s.True(errors.Is(err, expectedErr))
   181  
   182  	s.Equal(2, s.processKiller.KillCallCount())
   183  }