@@ -22,6 +22,7 @@ import (
2222"runtime"
2323"strconv"
2424"strings"
25+ "syscall"
2526"testing"
2627"time"
2728
@@ -1292,7 +1293,7 @@ func TestCompiledFlags(t *testing.T) {
12921293if err == nil {
12931294t .Fatalf ("expected an error because of timeout" )
12941295}
1295- got = stdout .String ()
1296+ got = stderr .String ()
12961297want = "context deadline exceeded"
12971298if strings .Contains (got , want ) == false {
12981299t .Errorf ("got %q, does not contain %q" , got , want )
@@ -1384,7 +1385,7 @@ func TestCompiledEnvironmentVars(t *testing.T) {
13841385if err == nil {
13851386t .Fatalf ("expected an error because of timeout" )
13861387}
1387- got = stdout .String ()
1388+ got = stderr .String ()
13881389want = "context deadline exceeded"
13891390if strings .Contains (got , want ) == false {
13901391t .Errorf ("got %q, does not contain %q" , got , want )
@@ -1457,6 +1458,111 @@ func TestCompiledVerboseFlag(t *testing.T) {
14571458}
14581459}
14591460
1461+ func TestSignals (t * testing.T ) {
1462+ stderr := & bytes.Buffer {}
1463+ stdout := & bytes.Buffer {}
1464+ dir := "./testdata/signals"
1465+ compileDir , err := ioutil .TempDir (dir , "" )
1466+ if err != nil {
1467+ t .Fatal (err )
1468+ }
1469+ name := filepath .Join (compileDir , "mage_out" )
1470+ // The CompileOut directory is relative to the
1471+ // invocation directory, so chop off the invocation dir.
1472+ outName := "./" + name [len (dir )- 1 :]
1473+ defer os .RemoveAll (compileDir )
1474+ inv := Invocation {
1475+ Dir : dir ,
1476+ Stdout : stdout ,
1477+ Stderr : stderr ,
1478+ CompileOut : outName ,
1479+ }
1480+ code := Invoke (inv )
1481+ if code != 0 {
1482+ t .Errorf ("expected to exit with code 0, but got %v, stderr: %s" , code , stderr )
1483+ }
1484+
1485+ run := func (stdout , stderr * bytes.Buffer , filename string , target string , signals ... syscall.Signal ) error {
1486+ stderr .Reset ()
1487+ stdout .Reset ()
1488+ cmd := exec .Command (filename , target )
1489+ cmd .Stderr = stderr
1490+ cmd .Stdout = stdout
1491+ if err := cmd .Start (); err != nil {
1492+ return fmt .Errorf ("running '%s %s' failed with: %v\n stdout: %s\n stderr: %s" ,
1493+ filename , target , err , stdout , stderr )
1494+ }
1495+ pid := cmd .Process .Pid
1496+ go func () {
1497+ time .Sleep (time .Millisecond * 500 )
1498+ for _ , s := range signals {
1499+ syscall .Kill (pid , s )
1500+ time .Sleep (time .Millisecond * 50 )
1501+ }
1502+ }()
1503+ if err := cmd .Wait (); err != nil {
1504+ return fmt .Errorf ("running '%s %s' failed with: %v\n stdout: %s\n stderr: %s" ,
1505+ filename , target , err , stdout , stderr )
1506+ }
1507+ return nil
1508+ }
1509+
1510+ if err := run (stdout , stderr , name , "exitsAfterSighup" , syscall .SIGHUP ); err != nil {
1511+ t .Fatal (err )
1512+ }
1513+ got := stdout .String ()
1514+ want := "received sighup\n "
1515+ if strings .Contains (got , want ) == false {
1516+ t .Errorf ("got %q, does not contain %q" , got , want )
1517+ }
1518+
1519+ if err := run (stdout , stderr , name , "exitsAfterSigint" , syscall .SIGINT ); err != nil {
1520+ t .Fatal (err )
1521+ }
1522+ got = stdout .String ()
1523+ want = "exiting...done\n "
1524+ if strings .Contains (got , want ) == false {
1525+ t .Errorf ("got %q, does not contain %q" , got , want )
1526+ }
1527+ got = stderr .String ()
1528+ want = "cancelling mage targets, waiting up to 5 seconds for cleanup...\n "
1529+ if strings .Contains (got , want ) == false {
1530+ t .Errorf ("got %q, does not contain %q" , got , want )
1531+ }
1532+
1533+ if err := run (stdout , stderr , name , "exitsAfterCancel" , syscall .SIGINT ); err != nil {
1534+ t .Fatal (err )
1535+ }
1536+ got = stdout .String ()
1537+ want = "exiting...done\n deferred cleanup\n "
1538+ if strings .Contains (got , want ) == false {
1539+ t .Errorf ("got %q, does not contain %q" , got , want )
1540+ }
1541+ got = stderr .String ()
1542+ want = "cancelling mage targets, waiting up to 5 seconds for cleanup...\n "
1543+ if strings .Contains (got , want ) == false {
1544+ t .Errorf ("got %q, does not contain %q" , got , want )
1545+ }
1546+
1547+ if err := run (stdout , stderr , name , "ignoresSignals" , syscall .SIGINT , syscall .SIGINT ); err == nil {
1548+ t .Fatalf ("expected an error because of force kill" )
1549+ }
1550+ got = stderr .String ()
1551+ want = "cancelling mage targets, waiting up to 5 seconds for cleanup...\n exiting mage\n Error: exit forced\n "
1552+ if strings .Contains (got , want ) == false {
1553+ t .Errorf ("got %q, does not contain %q" , got , want )
1554+ }
1555+
1556+ if err := run (stdout , stderr , name , "ignoresSignals" , syscall .SIGINT ); err == nil {
1557+ t .Fatalf ("expected an error because of force kill" )
1558+ }
1559+ got = stderr .String ()
1560+ want = "cancelling mage targets, waiting up to 5 seconds for cleanup...\n Error: cleanup timeout exceeded\n "
1561+ if strings .Contains (got , want ) == false {
1562+ t .Errorf ("got %q, does not contain %q" , got , want )
1563+ }
1564+ }
1565+
14601566func TestCompiledDeterministic (t * testing.T ) {
14611567dir := "./testdata/compiled"
14621568compileDir , err := ioutil .TempDir (dir , "" )
0 commit comments