github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/syscall/exec_unix_test.go (about)

     1  // Copyright 2015 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  // +build darwin dragonfly freebsd linux netbsd openbsd solaris
     6  
     7  package syscall_test
     8  
     9  import (
    10  	"internal/testenv"
    11  	"io"
    12  	"os"
    13  	"os/exec"
    14  	"os/signal"
    15  	"syscall"
    16  	"testing"
    17  	"unsafe"
    18  )
    19  
    20  type command struct {
    21  	pipe io.WriteCloser
    22  	proc *exec.Cmd
    23  	test *testing.T
    24  }
    25  
    26  func (c *command) Info() (pid, pgrp int) {
    27  	pid = c.proc.Process.Pid
    28  
    29  	pgrp, err := syscall.Getpgid(pid)
    30  	if err != nil {
    31  		c.test.Fatal(err)
    32  	}
    33  
    34  	return
    35  }
    36  
    37  func (c *command) Start() {
    38  	if err := c.proc.Start(); err != nil {
    39  		c.test.Fatal(err)
    40  	}
    41  }
    42  
    43  func (c *command) Stop() {
    44  	c.pipe.Close()
    45  	if err := c.proc.Wait(); err != nil {
    46  		c.test.Fatal(err)
    47  	}
    48  }
    49  
    50  func create(t *testing.T) *command {
    51  	testenv.MustHaveExec(t)
    52  
    53  	proc := exec.Command("cat")
    54  	stdin, err := proc.StdinPipe()
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  
    59  	return &command{stdin, proc, t}
    60  }
    61  
    62  func parent() (pid, pgrp int) {
    63  	return syscall.Getpid(), syscall.Getpgrp()
    64  }
    65  
    66  func TestZeroSysProcAttr(t *testing.T) {
    67  	ppid, ppgrp := parent()
    68  
    69  	cmd := create(t)
    70  
    71  	cmd.Start()
    72  	defer cmd.Stop()
    73  
    74  	cpid, cpgrp := cmd.Info()
    75  
    76  	if cpid == ppid {
    77  		t.Fatalf("Parent and child have the same process ID")
    78  	}
    79  
    80  	if cpgrp != ppgrp {
    81  		t.Fatalf("Child is not in parent's process group")
    82  	}
    83  }
    84  
    85  func TestSetpgid(t *testing.T) {
    86  	ppid, ppgrp := parent()
    87  
    88  	cmd := create(t)
    89  
    90  	cmd.proc.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
    91  	cmd.Start()
    92  	defer cmd.Stop()
    93  
    94  	cpid, cpgrp := cmd.Info()
    95  
    96  	if cpid == ppid {
    97  		t.Fatalf("Parent and child have the same process ID")
    98  	}
    99  
   100  	if cpgrp == ppgrp {
   101  		t.Fatalf("Parent and child are in the same process group")
   102  	}
   103  
   104  	if cpid != cpgrp {
   105  		t.Fatalf("Child's process group is not the child's process ID")
   106  	}
   107  }
   108  
   109  func TestPgid(t *testing.T) {
   110  	ppid, ppgrp := parent()
   111  
   112  	cmd1 := create(t)
   113  
   114  	cmd1.proc.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
   115  	cmd1.Start()
   116  	defer cmd1.Stop()
   117  
   118  	cpid1, cpgrp1 := cmd1.Info()
   119  
   120  	if cpid1 == ppid {
   121  		t.Fatalf("Parent and child 1 have the same process ID")
   122  	}
   123  
   124  	if cpgrp1 == ppgrp {
   125  		t.Fatalf("Parent and child 1 are in the same process group")
   126  	}
   127  
   128  	if cpid1 != cpgrp1 {
   129  		t.Fatalf("Child 1's process group is not its process ID")
   130  	}
   131  
   132  	cmd2 := create(t)
   133  
   134  	cmd2.proc.SysProcAttr = &syscall.SysProcAttr{
   135  		Setpgid: true,
   136  		Pgid:    cpgrp1,
   137  	}
   138  	cmd2.Start()
   139  	defer cmd2.Stop()
   140  
   141  	cpid2, cpgrp2 := cmd2.Info()
   142  
   143  	if cpid2 == ppid {
   144  		t.Fatalf("Parent and child 2 have the same process ID")
   145  	}
   146  
   147  	if cpgrp2 == ppgrp {
   148  		t.Fatalf("Parent and child 2 are in the same process group")
   149  	}
   150  
   151  	if cpid2 == cpgrp2 {
   152  		t.Fatalf("Child 2's process group is its process ID")
   153  	}
   154  
   155  	if cpid1 == cpid2 {
   156  		t.Fatalf("Child 1 and 2 have the same process ID")
   157  	}
   158  
   159  	if cpgrp1 != cpgrp2 {
   160  		t.Fatalf("Child 1 and 2 are not in the same process group")
   161  	}
   162  }
   163  
   164  func TestForeground(t *testing.T) {
   165  	signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU)
   166  
   167  	tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
   168  	if err != nil {
   169  		t.Skipf("Can't test Foreground. Couldn't open /dev/tty: %s", err)
   170  	}
   171  
   172  	fpgrp := 0
   173  
   174  	errno := syscall.Ioctl(tty.Fd(), syscall.TIOCGPGRP, uintptr(unsafe.Pointer(&fpgrp)))
   175  	if errno != 0 {
   176  		t.Fatalf("TIOCGPGRP failed with error code: %s", errno)
   177  	}
   178  
   179  	if fpgrp == 0 {
   180  		t.Fatalf("Foreground process group is zero")
   181  	}
   182  
   183  	ppid, ppgrp := parent()
   184  
   185  	cmd := create(t)
   186  
   187  	cmd.proc.SysProcAttr = &syscall.SysProcAttr{
   188  		Ctty:       int(tty.Fd()),
   189  		Foreground: true,
   190  	}
   191  	cmd.Start()
   192  
   193  	cpid, cpgrp := cmd.Info()
   194  
   195  	if cpid == ppid {
   196  		t.Fatalf("Parent and child have the same process ID")
   197  	}
   198  
   199  	if cpgrp == ppgrp {
   200  		t.Fatalf("Parent and child are in the same process group")
   201  	}
   202  
   203  	if cpid != cpgrp {
   204  		t.Fatalf("Child's process group is not the child's process ID")
   205  	}
   206  
   207  	cmd.Stop()
   208  
   209  	errno = syscall.Ioctl(tty.Fd(), syscall.TIOCSPGRP, uintptr(unsafe.Pointer(&fpgrp)))
   210  	if errno != 0 {
   211  		t.Fatalf("TIOCSPGRP failed with error code: %s", errno)
   212  	}
   213  
   214  	signal.Reset()
   215  }