github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/f/death_windows_test.go (about)

     1  // +build windows
     2  
     3  package f_test
     4  
     5  import (
     6  	"bytes"
     7  	"io/ioutil"
     8  	"os"
     9  	"os/exec"
    10  	"path/filepath"
    11  	"syscall"
    12  	"testing"
    13  	"time"
    14  
    15  	. "github.com/smartystreets/goconvey/convey"
    16  )
    17  
    18  func TestDeath(t *testing.T) {
    19  	Convey("Validate death happens cleanly on windows with ctrl-c event", t, func() {
    20  		// create source file
    21  		const source = `
    22  package main
    23  import (
    24  	"syscall"
    25  	"github.com/vrecan/death"
    26  )
    27  func main() {
    28  	death := death.NewDeath(syscall.SIGINT)
    29  	death.WaitForDeath()
    30  }
    31  `
    32  		tmp, err := ioutil.TempDir("", "TestCtrlBreak")
    33  		if err != nil {
    34  			t.Fatal("TempDir failed: ", err)
    35  		}
    36  		defer os.RemoveAll(tmp)
    37  
    38  		// write ctrlbreak.go
    39  		name := filepath.Join(tmp, "ctlbreak")
    40  		src := name + ".go"
    41  		f, err := os.Create(src)
    42  		if err != nil {
    43  			t.Fatalf("Failed to create %v: %v", src, err)
    44  		}
    45  		defer f.Close()
    46  		f.Write([]byte(source))
    47  
    48  		// compile it
    49  		exe := name + ".exe"
    50  		defer os.Remove(exe)
    51  		o, err := exec.Command("go", "build", "-o", exe, src).CombinedOutput()
    52  		if err != nil {
    53  			t.Fatalf("Failed to compile: %v\n%v", err, string(o))
    54  		}
    55  
    56  		// run it
    57  		cmd := exec.Command(exe)
    58  		var b bytes.Buffer
    59  		cmd.Stdout = &b
    60  		cmd.Stderr = &b
    61  		cmd.SysProcAttr = &syscall.SysProcAttr{
    62  			CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
    63  		}
    64  		err = cmd.Start()
    65  		if err != nil {
    66  			t.Fatalf("Start failed: %v", err)
    67  		}
    68  		go func() {
    69  			time.Sleep(1 * time.Second)
    70  			sendCtrlBreak(t, cmd.Process.Pid)
    71  		}()
    72  		err = cmd.Wait()
    73  		if err != nil {
    74  			t.Fatalf("Program exited with error: %v\n%v", err, string(b.Bytes()))
    75  		}
    76  	})
    77  }
    78  
    79  func sendCtrlBreak(t *testing.T, pid int) {
    80  	d, e := syscall.LoadDLL("kernel32.dll")
    81  	if e != nil {
    82  		t.Fatalf("LoadDLL: %v\n", e)
    83  	}
    84  	p, e := d.FindProc("GenerateConsoleCtrlEvent")
    85  	if e != nil {
    86  		t.Fatalf("FindProc: %v\n", e)
    87  	}
    88  	r, _, e := p.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid))
    89  	if r == 0 {
    90  		t.Fatalf("GenerateConsoleCtrlEvent: %v\n", e)
    91  	}
    92  }