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 }