@@ -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,23 @@ 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+
328+ # force non-zero exit code, so that the error message contains the output
329+ exit 1
330+ ` )
331+ }
332+
317333func TestCreateArgs (t * testing.T ) {
318334 o := & CreateOpts {}
319335 args , err := o .args ()
@@ -336,3 +352,72 @@ func TestCreateArgs(t *testing.T) {
336352 }
337353
338354}
355+
356+ func TestRuncKill (t * testing.T ) {
357+ ctx , timeout := context .WithTimeout (context .Background (), 10 * time .Second )
358+ defer timeout ()
359+
360+ dummyCmd , err := debugCommand ()
361+ if err != nil {
362+ t .Fatalf ("Failed to create dummy debug command: %v" , err )
363+ }
364+ defer os .Remove (dummyCmd )
365+
366+ debugRunc := & Runc {Command : dummyCmd }
367+
368+ type config struct {
369+ name string
370+ rawSignal string
371+ numericalSignal int
372+ expectedSignal string
373+ }
374+ tests := []config {
375+ {
376+ name : "Kill sends raw signal" ,
377+ rawSignal : "SIGTERM" ,
378+ expectedSignal : "SIGTERM" ,
379+ },
380+ {
381+ name : "Kill sends raw signal number" ,
382+ rawSignal : "15" ,
383+ expectedSignal : "15" ,
384+ },
385+ {
386+ name : "Kill prefers raw signal over numerical signal" ,
387+ rawSignal : "SIGTERM" ,
388+ numericalSignal : 9 ,
389+ expectedSignal : "SIGTERM" ,
390+ },
391+ {
392+ name : "Kill prefers raw signal number over numerical signal" ,
393+ rawSignal : "15" ,
394+ numericalSignal : 9 ,
395+ expectedSignal : "15" ,
396+ },
397+ {
398+ name : "Kill sends numerical signal when no raw signal specified" ,
399+ numericalSignal : 9 ,
400+ expectedSignal : "9" ,
401+ },
402+ }
403+ for _ , test := range tests {
404+ t .Run (test .name , func (_ * testing.T ) {
405+ opts := & KillOpts {
406+ RawSignal : test .rawSignal ,
407+ }
408+ err = debugRunc .Kill (ctx , "fake_id" , test .numericalSignal , opts )
409+ if err == nil {
410+ t .Fatal ("expected dummy debug command to return error, instead got nil" )
411+ }
412+ errorMessage := err .Error ()
413+ words := strings .Fields (errorMessage )
414+ if len (words ) < 3 {
415+ t .Fatalf ("expected dummy debug command to error with the kill command sent, instead got %s" , errorMessage )
416+ }
417+ actualSignal := words [len (words )- 1 ]
418+ if actualSignal != test .expectedSignal {
419+ t .Fatalf ("expected kill command to send signal %v, instead got %v" , test .expectedSignal , actualSignal )
420+ }
421+ })
422+ }
423+ }
0 commit comments