@@ -21,6 +21,7 @@ import (
2121 "errors"
2222 "io/ioutil"
2323 "os"
24+ "strings"
2425 "sync"
2526 "syscall"
2627 "testing"
@@ -287,9 +288,7 @@ func interrupt(ctx context.Context, t *testing.T, started <-chan int) {
287288 }
288289}
289290
290- // dummySleepRunc creates s simple script that just runs `sleep 10` to replace
291- // runc for testing process that are longer running.
292- func dummySleepRunc () (_ string , err error ) {
291+ func createScript (content string ) (_ string , err error ) {
293292 fh , err := ioutil .TempFile ("" , "*.sh" )
294293 if err != nil {
295294 return "" , err
@@ -299,7 +298,7 @@ func dummySleepRunc() (_ string, err error) {
299298 os .Remove (fh .Name ())
300299 }
301300 }()
302- _ , err = fh .Write ([]byte ("#!/bin/sh \n exec /bin/sleep 10" ))
301+ _ , err = fh .Write ([]byte (content ))
303302 if err != nil {
304303 return "" , err
305304 }
@@ -314,6 +313,22 @@ func dummySleepRunc() (_ string, err error) {
314313 return fh .Name (), nil
315314}
316315
316+ // dummySleepRunc creates a simple script that just runs `sleep 10` to replace
317+ // runc for testing process that are longer running.
318+ func dummySleepRunc () (_ string , err error ) {
319+ return createScript ("#!/bin/sh\n exec /bin/sleep 10" )
320+ }
321+
322+ // debugCommand creates a simple script that echos the arguments passed to
323+ // runc, and returns them as part of the error message.
324+ func debugCommand () (string , error ) {
325+ return createScript (`#!/bin/sh
326+ echo "$@"
327+ # force non-zero exit code, so that the error message contains the output
328+ exit 1
329+ ` )
330+ }
331+
317332func TestCreateArgs (t * testing.T ) {
318333 o := & CreateOpts {}
319334 args , err := o .args ()
@@ -336,3 +351,72 @@ func TestCreateArgs(t *testing.T) {
336351 }
337352
338353}
354+
355+ func TestRuncKill (t * testing.T ) {
356+ ctx , timeout := context .WithTimeout (context .Background (), 10 * time .Second )
357+ defer timeout ()
358+
359+ dummyCmd , err := debugCommand ()
360+ if err != nil {
361+ t .Fatalf ("Failed to create dummy debug command: %v" , err )
362+ }
363+ defer os .Remove (dummyCmd )
364+
365+ debugRunc := & Runc {Command : dummyCmd }
366+
367+ type config struct {
368+ name string
369+ rawSignal string
370+ numericalSignal int
371+ expectedSignal string
372+ }
373+ tests := []config {
374+ {
375+ name : "Kill sends raw signal" ,
376+ rawSignal : "SIGTERM" ,
377+ expectedSignal : "SIGTERM" ,
378+ },
379+ {
380+ name : "Kill sends raw signal number" ,
381+ rawSignal : "15" ,
382+ expectedSignal : "15" ,
383+ },
384+ {
385+ name : "Kill prefers raw signal over numerical signal" ,
386+ rawSignal : "SIGTERM" ,
387+ numericalSignal : 9 ,
388+ expectedSignal : "SIGTERM" ,
389+ },
390+ {
391+ name : "Kill prefers raw signal number over numerical signal" ,
392+ rawSignal : "15" ,
393+ numericalSignal : 9 ,
394+ expectedSignal : "15" ,
395+ },
396+ {
397+ name : "Kill sends numerical signal when no raw signal specified" ,
398+ numericalSignal : 9 ,
399+ expectedSignal : "9" ,
400+ },
401+ }
402+ for _ , test := range tests {
403+ t .Run (test .name , func (_ * testing.T ) {
404+ opts := & KillOpts {
405+ RawSignal : test .rawSignal ,
406+ }
407+ err = debugRunc .Kill (ctx , "fake_id" , test .numericalSignal , opts )
408+ if err == nil {
409+ t .Fatal ("expected dummy debug command to return error, instead got nil" )
410+ }
411+ errorMessage := err .Error ()
412+ words := strings .Fields (errorMessage )
413+ if len (words ) < 3 {
414+ t .Fatalf ("expected dummy debug command to error with the kill command sent, instead got %s" , errorMessage )
415+ }
416+ actualSignal := words [len (words )- 1 ]
417+ if actualSignal != test .expectedSignal {
418+ t .Fatalf ("expected kill command to send signal %v, instead got %v" , test .expectedSignal , actualSignal )
419+ }
420+ })
421+ }
422+ }
0 commit comments