Home | History | Annotate | Download | only in signal
      1 // Copyright 2012 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package signal
      6 
      7 import (
      8 	"bytes"
      9 	"io/ioutil"
     10 	"os"
     11 	"os/exec"
     12 	"path/filepath"
     13 	"syscall"
     14 	"testing"
     15 	"time"
     16 )
     17 
     18 func sendCtrlBreak(t *testing.T, pid int) {
     19 	d, e := syscall.LoadDLL("kernel32.dll")
     20 	if e != nil {
     21 		t.Fatalf("LoadDLL: %v\n", e)
     22 	}
     23 	p, e := d.FindProc("GenerateConsoleCtrlEvent")
     24 	if e != nil {
     25 		t.Fatalf("FindProc: %v\n", e)
     26 	}
     27 	r, _, e := p.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid))
     28 	if r == 0 {
     29 		t.Fatalf("GenerateConsoleCtrlEvent: %v\n", e)
     30 	}
     31 }
     32 
     33 func TestCtrlBreak(t *testing.T) {
     34 	// create source file
     35 	const source = `
     36 package main
     37 
     38 import (
     39 	"log"
     40 	"os"
     41 	"os/signal"
     42 	"time"
     43 )
     44 
     45 
     46 func main() {
     47 	c := make(chan os.Signal, 10)
     48 	signal.Notify(c)
     49 	select {
     50 	case s := <-c:
     51 		if s != os.Interrupt {
     52 			log.Fatalf("Wrong signal received: got %q, want %q\n", s, os.Interrupt)
     53 		}
     54 	case <-time.After(3 * time.Second):
     55 		log.Fatalf("Timeout waiting for Ctrl+Break\n")
     56 	}
     57 }
     58 `
     59 	tmp, err := ioutil.TempDir("", "TestCtrlBreak")
     60 	if err != nil {
     61 		t.Fatal("TempDir failed: ", err)
     62 	}
     63 	defer os.RemoveAll(tmp)
     64 
     65 	// write ctrlbreak.go
     66 	name := filepath.Join(tmp, "ctlbreak")
     67 	src := name + ".go"
     68 	f, err := os.Create(src)
     69 	if err != nil {
     70 		t.Fatalf("Failed to create %v: %v", src, err)
     71 	}
     72 	defer f.Close()
     73 	f.Write([]byte(source))
     74 
     75 	// compile it
     76 	exe := name + ".exe"
     77 	defer os.Remove(exe)
     78 	o, err := exec.Command("go", "build", "-o", exe, src).CombinedOutput()
     79 	if err != nil {
     80 		t.Fatalf("Failed to compile: %v\n%v", err, string(o))
     81 	}
     82 
     83 	// run it
     84 	cmd := exec.Command(exe)
     85 	var b bytes.Buffer
     86 	cmd.Stdout = &b
     87 	cmd.Stderr = &b
     88 	cmd.SysProcAttr = &syscall.SysProcAttr{
     89 		CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
     90 	}
     91 	err = cmd.Start()
     92 	if err != nil {
     93 		t.Fatalf("Start failed: %v", err)
     94 	}
     95 	go func() {
     96 		time.Sleep(1 * time.Second)
     97 		sendCtrlBreak(t, cmd.Process.Pid)
     98 	}()
     99 	err = cmd.Wait()
    100 	if err != nil {
    101 		t.Fatalf("Program exited with error: %v\n%v", err, string(b.Bytes()))
    102 	}
    103 }
    104