...

Source file src/github.com/shirou/gopsutil/process/process_test.go

Documentation: github.com/shirou/gopsutil/process

     1  package process
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net"
     7  	"os"
     8  	"os/exec"
     9  	"os/user"
    10  	"path/filepath"
    11  	"reflect"
    12  	"runtime"
    13  	"strconv"
    14  	"strings"
    15  	"sync"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/shirou/gopsutil/internal/common"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  var mu sync.Mutex
    24  
    25  func skipIfNotImplementedErr(t *testing.T, err error) {
    26  	if err == common.ErrNotImplementedError {
    27  		t.Skip("not implemented")
    28  	}
    29  }
    30  
    31  func testGetProcess() Process {
    32  	checkPid := os.Getpid() // process.test
    33  	ret, _ := NewProcess(int32(checkPid))
    34  	return *ret
    35  }
    36  
    37  func Test_Pids(t *testing.T) {
    38  	ret, err := Pids()
    39  	skipIfNotImplementedErr(t, err)
    40  	if err != nil {
    41  		t.Errorf("error %v", err)
    42  	}
    43  	if len(ret) == 0 {
    44  		t.Errorf("could not get pids %v", ret)
    45  	}
    46  }
    47  
    48  func Test_Pids_Fail(t *testing.T) {
    49  	if runtime.GOOS != "darwin" {
    50  		t.Skip("darwin only")
    51  	}
    52  
    53  	mu.Lock()
    54  	defer mu.Unlock()
    55  
    56  	invoke = common.FakeInvoke{Suffix: "fail"}
    57  	ret, err := Pids()
    58  	skipIfNotImplementedErr(t, err)
    59  	invoke = common.Invoke{}
    60  	if err != nil {
    61  		t.Errorf("error %v", err)
    62  	}
    63  	if len(ret) != 9 {
    64  		t.Errorf("wrong getted pid nums: %v/%d", ret, len(ret))
    65  	}
    66  }
    67  func Test_Pid_exists(t *testing.T) {
    68  	checkPid := os.Getpid()
    69  
    70  	ret, err := PidExists(int32(checkPid))
    71  	skipIfNotImplementedErr(t, err)
    72  	if err != nil {
    73  		t.Errorf("error %v", err)
    74  	}
    75  
    76  	if ret == false {
    77  		t.Errorf("could not get process exists: %v", ret)
    78  	}
    79  }
    80  
    81  func Test_NewProcess(t *testing.T) {
    82  	checkPid := os.Getpid()
    83  
    84  	ret, err := NewProcess(int32(checkPid))
    85  	skipIfNotImplementedErr(t, err)
    86  	if err != nil {
    87  		t.Errorf("error %v", err)
    88  	}
    89  	empty := &Process{}
    90  	if runtime.GOOS != "windows" { // Windows pid is 0
    91  		if empty == ret {
    92  			t.Errorf("error %v", ret)
    93  		}
    94  	}
    95  
    96  }
    97  
    98  func Test_Process_memory_maps(t *testing.T) {
    99  	checkPid := os.Getpid()
   100  
   101  	ret, err := NewProcess(int32(checkPid))
   102  	skipIfNotImplementedErr(t, err)
   103  	if err != nil {
   104  		t.Errorf("error %v", err)
   105  	}
   106  
   107  	// ungrouped memory maps
   108  	mmaps, err := ret.MemoryMaps(false)
   109  	skipIfNotImplementedErr(t, err)
   110  	if err != nil {
   111  		t.Errorf("memory map get error %v", err)
   112  	}
   113  	empty := MemoryMapsStat{}
   114  	for _, m := range *mmaps {
   115  		if m == empty {
   116  			t.Errorf("memory map get error %v", m)
   117  		}
   118  	}
   119  
   120  	// grouped memory maps
   121  	mmaps, err = ret.MemoryMaps(true)
   122  	skipIfNotImplementedErr(t, err)
   123  	if err != nil {
   124  		t.Errorf("memory map get error %v", err)
   125  	}
   126  	if len(*mmaps) != 1 {
   127  		t.Errorf("grouped memory maps length (%v) is not equal to 1", len(*mmaps))
   128  	}
   129  	if (*mmaps)[0] == empty {
   130  		t.Errorf("memory map is empty")
   131  	}
   132  }
   133  func Test_Process_MemoryInfo(t *testing.T) {
   134  	p := testGetProcess()
   135  
   136  	v, err := p.MemoryInfo()
   137  	skipIfNotImplementedErr(t, err)
   138  	if err != nil {
   139  		t.Errorf("getting memory info error %v", err)
   140  	}
   141  	empty := MemoryInfoStat{}
   142  	if v == nil || *v == empty {
   143  		t.Errorf("could not get memory info %v", v)
   144  	}
   145  }
   146  
   147  func Test_Process_CmdLine(t *testing.T) {
   148  	p := testGetProcess()
   149  
   150  	v, err := p.Cmdline()
   151  	skipIfNotImplementedErr(t, err)
   152  	if err != nil {
   153  		t.Errorf("getting cmdline error %v", err)
   154  	}
   155  	if !strings.Contains(v, "process.test") {
   156  		t.Errorf("invalid cmd line %v", v)
   157  	}
   158  }
   159  
   160  func Test_Process_CmdLineSlice(t *testing.T) {
   161  	p := testGetProcess()
   162  
   163  	v, err := p.CmdlineSlice()
   164  	skipIfNotImplementedErr(t, err)
   165  	if err != nil {
   166  		t.Fatalf("getting cmdline slice error %v", err)
   167  	}
   168  	if !reflect.DeepEqual(v, os.Args) {
   169  		t.Errorf("returned cmdline slice not as expected:\nexp: %v\ngot: %v", os.Args, v)
   170  	}
   171  }
   172  
   173  func Test_Process_Ppid(t *testing.T) {
   174  	p := testGetProcess()
   175  
   176  	v, err := p.Ppid()
   177  	skipIfNotImplementedErr(t, err)
   178  	if err != nil {
   179  		t.Errorf("getting ppid error %v", err)
   180  	}
   181  	if v == 0 {
   182  		t.Errorf("return value is 0 %v", v)
   183  	}
   184  	expected := os.Getppid()
   185  	if v != int32(expected) {
   186  		t.Errorf("return value is %v, expected %v", v, expected)
   187  	}
   188  }
   189  
   190  func Test_Process_Status(t *testing.T) {
   191  	p := testGetProcess()
   192  
   193  	v, err := p.Status()
   194  	skipIfNotImplementedErr(t, err)
   195  	if err != nil {
   196  		t.Errorf("getting status error %v", err)
   197  	}
   198  	if v != "R" && v != "S" {
   199  		t.Errorf("could not get state %v", v)
   200  	}
   201  }
   202  
   203  func Test_Process_Terminal(t *testing.T) {
   204  	p := testGetProcess()
   205  
   206  	_, err := p.Terminal()
   207  	skipIfNotImplementedErr(t, err)
   208  	if err != nil {
   209  		t.Errorf("getting terminal error %v", err)
   210  	}
   211  }
   212  
   213  func Test_Process_IOCounters(t *testing.T) {
   214  	p := testGetProcess()
   215  
   216  	v, err := p.IOCounters()
   217  	skipIfNotImplementedErr(t, err)
   218  	if err != nil {
   219  		t.Errorf("getting iocounter error %v", err)
   220  		return
   221  	}
   222  	empty := &IOCountersStat{}
   223  	if v == empty {
   224  		t.Errorf("error %v", v)
   225  	}
   226  }
   227  
   228  func Test_Process_NumCtx(t *testing.T) {
   229  	p := testGetProcess()
   230  
   231  	_, err := p.NumCtxSwitches()
   232  	skipIfNotImplementedErr(t, err)
   233  	if err != nil {
   234  		t.Errorf("getting numctx error %v", err)
   235  		return
   236  	}
   237  }
   238  
   239  func Test_Process_Nice(t *testing.T) {
   240  	p := testGetProcess()
   241  
   242  	n, err := p.Nice()
   243  	skipIfNotImplementedErr(t, err)
   244  	if err != nil {
   245  		t.Errorf("getting nice error %v", err)
   246  	}
   247  	if runtime.GOOS != "windows" && n != 0 && n != 20 && n != 8 {
   248  		t.Errorf("invalid nice: %d", n)
   249  	}
   250  }
   251  
   252  func Test_Process_Groups(t *testing.T) {
   253  	p := testGetProcess()
   254  
   255  	v, err := p.Groups()
   256  	skipIfNotImplementedErr(t, err)
   257  	if err != nil {
   258  		t.Errorf("getting groups error %v", err)
   259  	}
   260  	if len(v) == 0 {
   261  		t.Skip("Groups is empty")
   262  	}
   263  	if v[0] < 0 {
   264  		t.Errorf("invalid Groups: %v", v)
   265  	}
   266  }
   267  
   268  func Test_Process_NumThread(t *testing.T) {
   269  	p := testGetProcess()
   270  
   271  	n, err := p.NumThreads()
   272  	skipIfNotImplementedErr(t, err)
   273  	if err != nil {
   274  		t.Errorf("getting NumThread error %v", err)
   275  	}
   276  	if n < 0 {
   277  		t.Errorf("invalid NumThread: %d", n)
   278  	}
   279  }
   280  
   281  func Test_Process_Threads(t *testing.T) {
   282  	p := testGetProcess()
   283  
   284  	n, err := p.NumThreads()
   285  	skipIfNotImplementedErr(t, err)
   286  	if err != nil {
   287  		t.Errorf("getting NumThread error %v", err)
   288  	}
   289  	if n < 0 {
   290  		t.Errorf("invalid NumThread: %d", n)
   291  	}
   292  
   293  	ts, err := p.Threads()
   294  	skipIfNotImplementedErr(t, err)
   295  	if err != nil {
   296  		t.Errorf("getting Threads error %v", err)
   297  	}
   298  	if len(ts) != int(n) {
   299  		t.Errorf("unexpected number of threads: %v vs %v", len(ts), n)
   300  	}
   301  }
   302  
   303  func Test_Process_Name(t *testing.T) {
   304  	p := testGetProcess()
   305  
   306  	n, err := p.Name()
   307  	skipIfNotImplementedErr(t, err)
   308  	if err != nil {
   309  		t.Errorf("getting name error %v", err)
   310  	}
   311  	if !strings.Contains(n, "process.test") {
   312  		t.Errorf("invalid Exe %s", n)
   313  	}
   314  }
   315  
   316  func Test_Process_Long_Name_With_Spaces(t *testing.T) {
   317  	tmpdir, err := ioutil.TempDir("", "")
   318  	if err != nil {
   319  		t.Fatalf("unable to create temp dir %v", err)
   320  	}
   321  	defer os.RemoveAll(tmpdir) // clean up
   322  	tmpfilepath := filepath.Join(tmpdir, "loooong name with spaces.go")
   323  	tmpfile, err := os.Create(tmpfilepath)
   324  	if err != nil {
   325  		t.Fatalf("unable to create temp file %v", err)
   326  	}
   327  
   328  	tmpfilecontent := []byte("package main\nimport(\n\"time\"\n)\nfunc main(){\nfor range time.Tick(time.Second) {}\n}")
   329  	if _, err := tmpfile.Write(tmpfilecontent); err != nil {
   330  		tmpfile.Close()
   331  		t.Fatalf("unable to write temp file %v", err)
   332  	}
   333  	if err := tmpfile.Close(); err != nil {
   334  		t.Fatalf("unable to close temp file %v", err)
   335  	}
   336  
   337  	err = exec.Command("go", "build", "-o", tmpfile.Name()+".exe", tmpfile.Name()).Run()
   338  	if err != nil {
   339  		t.Fatalf("unable to build temp file %v", err)
   340  	}
   341  
   342  	cmd := exec.Command(tmpfile.Name() + ".exe")
   343  
   344  	assert.Nil(t, cmd.Start())
   345  	time.Sleep(100 * time.Millisecond)
   346  	p, err := NewProcess(int32(cmd.Process.Pid))
   347  	skipIfNotImplementedErr(t, err)
   348  	assert.Nil(t, err)
   349  
   350  	n, err := p.Name()
   351  	skipIfNotImplementedErr(t, err)
   352  	if err != nil {
   353  		t.Fatalf("getting name error %v", err)
   354  	}
   355  	basename := filepath.Base(tmpfile.Name() + ".exe")
   356  	if basename != n {
   357  		t.Fatalf("%s != %s", basename, n)
   358  	}
   359  	cmd.Process.Kill()
   360  }
   361  func Test_Process_Long_Name(t *testing.T) {
   362  	tmpdir, err := ioutil.TempDir("", "")
   363  	if err != nil {
   364  		t.Fatalf("unable to create temp dir %v", err)
   365  	}
   366  	defer os.RemoveAll(tmpdir) // clean up
   367  	tmpfilepath := filepath.Join(tmpdir, "looooooooooooooooooooong.go")
   368  	tmpfile, err := os.Create(tmpfilepath)
   369  	if err != nil {
   370  		t.Fatalf("unable to create temp file %v", err)
   371  	}
   372  
   373  	tmpfilecontent := []byte("package main\nimport(\n\"time\"\n)\nfunc main(){\nfor range time.Tick(time.Second) {}\n}")
   374  	if _, err := tmpfile.Write(tmpfilecontent); err != nil {
   375  		tmpfile.Close()
   376  		t.Fatalf("unable to write temp file %v", err)
   377  	}
   378  	if err := tmpfile.Close(); err != nil {
   379  		t.Fatalf("unable to close temp file %v", err)
   380  	}
   381  
   382  	err = exec.Command("go", "build", "-o", tmpfile.Name()+".exe", tmpfile.Name()).Run()
   383  	if err != nil {
   384  		t.Fatalf("unable to build temp file %v", err)
   385  	}
   386  
   387  	cmd := exec.Command(tmpfile.Name() + ".exe")
   388  
   389  	assert.Nil(t, cmd.Start())
   390  	time.Sleep(100 * time.Millisecond)
   391  	p, err := NewProcess(int32(cmd.Process.Pid))
   392  	skipIfNotImplementedErr(t, err)
   393  	assert.Nil(t, err)
   394  
   395  	n, err := p.Name()
   396  	skipIfNotImplementedErr(t, err)
   397  	if err != nil {
   398  		t.Fatalf("getting name error %v", err)
   399  	}
   400  	basename := filepath.Base(tmpfile.Name() + ".exe")
   401  	if basename != n {
   402  		t.Fatalf("%s != %s", basename, n)
   403  	}
   404  	cmd.Process.Kill()
   405  }
   406  func Test_Process_Exe(t *testing.T) {
   407  	p := testGetProcess()
   408  
   409  	n, err := p.Exe()
   410  	skipIfNotImplementedErr(t, err)
   411  	if err != nil {
   412  		t.Errorf("getting Exe error %v", err)
   413  	}
   414  	if !strings.Contains(n, "process.test") {
   415  		t.Errorf("invalid Exe %s", n)
   416  	}
   417  }
   418  
   419  func Test_Process_CpuPercent(t *testing.T) {
   420  	p := testGetProcess()
   421  	_, err := p.Percent(0)
   422  	skipIfNotImplementedErr(t, err)
   423  	if err != nil {
   424  		t.Errorf("error %v", err)
   425  	}
   426  	duration := time.Duration(1000) * time.Microsecond
   427  	time.Sleep(duration)
   428  	percent, err := p.Percent(0)
   429  	if err != nil {
   430  		t.Errorf("error %v", err)
   431  	}
   432  
   433  	numcpu := runtime.NumCPU()
   434  	//	if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
   435  	if percent < 0.0 {
   436  		t.Fatalf("CPUPercent value is invalid: %f, %d", percent, numcpu)
   437  	}
   438  }
   439  
   440  func Test_Process_CpuPercentLoop(t *testing.T) {
   441  	p := testGetProcess()
   442  	numcpu := runtime.NumCPU()
   443  
   444  	for i := 0; i < 2; i++ {
   445  		duration := time.Duration(100) * time.Microsecond
   446  		percent, err := p.Percent(duration)
   447  		skipIfNotImplementedErr(t, err)
   448  		if err != nil {
   449  			t.Errorf("error %v", err)
   450  		}
   451  		//	if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
   452  		if percent < 0.0 {
   453  			t.Fatalf("CPUPercent value is invalid: %f, %d", percent, numcpu)
   454  		}
   455  	}
   456  }
   457  
   458  func Test_Process_CreateTime(t *testing.T) {
   459  	if os.Getenv("CIRCLECI") == "true" {
   460  		t.Skip("Skip CI")
   461  	}
   462  
   463  	p := testGetProcess()
   464  
   465  	c, err := p.CreateTime()
   466  	skipIfNotImplementedErr(t, err)
   467  	if err != nil {
   468  		t.Errorf("error %v", err)
   469  	}
   470  
   471  	if c < 1420000000 {
   472  		t.Errorf("process created time is wrong.")
   473  	}
   474  
   475  	gotElapsed := time.Since(time.Unix(int64(c/1000), 0))
   476  	maxElapsed := time.Duration(20 * time.Second)
   477  
   478  	if gotElapsed >= maxElapsed {
   479  		t.Errorf("this process has not been running for %v", gotElapsed)
   480  	}
   481  }
   482  
   483  func Test_Parent(t *testing.T) {
   484  	p := testGetProcess()
   485  
   486  	c, err := p.Parent()
   487  	skipIfNotImplementedErr(t, err)
   488  	if err != nil {
   489  		t.Fatalf("error %v", err)
   490  	}
   491  	if c == nil {
   492  		t.Fatalf("could not get parent")
   493  	}
   494  	if c.Pid == 0 {
   495  		t.Fatalf("wrong parent pid")
   496  	}
   497  }
   498  
   499  func Test_Connections(t *testing.T) {
   500  	p := testGetProcess()
   501  
   502  	addr, err := net.ResolveTCPAddr("tcp", "localhost:0") // dynamically get a random open port from OS
   503  	if err != nil {
   504  		t.Fatalf("unable to resolve localhost: %v", err)
   505  	}
   506  	l, err := net.ListenTCP(addr.Network(), addr)
   507  	if err != nil {
   508  		t.Fatalf("unable to listen on %v: %v", addr, err)
   509  	}
   510  	defer l.Close()
   511  
   512  	tcpServerAddr := l.Addr().String()
   513  	tcpServerAddrIP := strings.Split(tcpServerAddr, ":")[0]
   514  	tcpServerAddrPort, err := strconv.ParseUint(strings.Split(tcpServerAddr, ":")[1], 10, 32)
   515  	if err != nil {
   516  		t.Fatalf("unable to parse tcpServerAddr port: %v", err)
   517  	}
   518  
   519  	serverEstablished := make(chan struct{})
   520  	go func() { // TCP listening goroutine
   521  		conn, err := l.Accept()
   522  		if err != nil {
   523  			panic(err)
   524  		}
   525  		defer conn.Close()
   526  
   527  		serverEstablished <- struct{}{}
   528  		_, err = ioutil.ReadAll(conn)
   529  		if err != nil {
   530  			panic(err)
   531  		}
   532  	}()
   533  
   534  	conn, err := net.Dial("tcp", tcpServerAddr)
   535  	if err != nil {
   536  		t.Fatalf("unable to dial %v: %v", tcpServerAddr, err)
   537  	}
   538  	defer conn.Close()
   539  
   540  	// Rarely the call to net.Dial returns before the server connection is
   541  	// established. Wait so that the test doesn't fail.
   542  	<-serverEstablished
   543  
   544  	c, err := p.Connections()
   545  	skipIfNotImplementedErr(t, err)
   546  	if err != nil {
   547  		t.Fatalf("error %v", err)
   548  	}
   549  	if len(c) == 0 {
   550  		t.Fatal("no connections found")
   551  	}
   552  
   553  	serverConnections := 0
   554  	for _, connection := range c {
   555  		if connection.Laddr.IP == tcpServerAddrIP && connection.Laddr.Port == uint32(tcpServerAddrPort) && connection.Raddr.Port != 0 {
   556  			if connection.Status != "ESTABLISHED" {
   557  				t.Fatalf("expected server connection to be ESTABLISHED, have %+v", connection)
   558  			}
   559  			serverConnections++
   560  		}
   561  	}
   562  
   563  	clientConnections := 0
   564  	for _, connection := range c {
   565  		if connection.Raddr.IP == tcpServerAddrIP && connection.Raddr.Port == uint32(tcpServerAddrPort) {
   566  			if connection.Status != "ESTABLISHED" {
   567  				t.Fatalf("expected client connection to be ESTABLISHED, have %+v", connection)
   568  			}
   569  			clientConnections++
   570  		}
   571  	}
   572  
   573  	if serverConnections != 1 { // two established connections, one for the server, the other for the client
   574  		t.Fatalf("expected 1 server connection, have %d.\nDetails: %+v", serverConnections, c)
   575  	}
   576  
   577  	if clientConnections != 1 { // two established connections, one for the server, the other for the client
   578  		t.Fatalf("expected 1 server connection, have %d.\nDetails: %+v", clientConnections, c)
   579  	}
   580  }
   581  
   582  func Test_Children(t *testing.T) {
   583  	p := testGetProcess()
   584  
   585  	var cmd *exec.Cmd
   586  	if runtime.GOOS == "windows" {
   587  		cmd = exec.Command("ping", "localhost", "-n", "4")
   588  	} else {
   589  		cmd = exec.Command("sleep", "3")
   590  	}
   591  	assert.Nil(t, cmd.Start())
   592  	time.Sleep(100 * time.Millisecond)
   593  
   594  	c, err := p.Children()
   595  	skipIfNotImplementedErr(t, err)
   596  	if err != nil {
   597  		t.Fatalf("error %v", err)
   598  	}
   599  	if len(c) == 0 {
   600  		t.Fatalf("children is empty")
   601  	}
   602  	found := false
   603  	for _, child := range c {
   604  		if child.Pid == int32(cmd.Process.Pid) {
   605  			found = true
   606  			break
   607  		}
   608  	}
   609  	if !found {
   610  		t.Errorf("could not find child %d", cmd.Process.Pid)
   611  	}
   612  }
   613  
   614  func Test_Username(t *testing.T) {
   615  	myPid := os.Getpid()
   616  	currentUser, _ := user.Current()
   617  	myUsername := currentUser.Username
   618  
   619  	process, _ := NewProcess(int32(myPid))
   620  	pidUsername, err := process.Username()
   621  	skipIfNotImplementedErr(t, err)
   622  	assert.Equal(t, myUsername, pidUsername)
   623  
   624  	t.Log(pidUsername)
   625  }
   626  
   627  func Test_CPUTimes(t *testing.T) {
   628  	pid := os.Getpid()
   629  	process, err := NewProcess(int32(pid))
   630  	skipIfNotImplementedErr(t, err)
   631  	assert.Nil(t, err)
   632  
   633  	spinSeconds := 0.2
   634  	cpuTimes0, err := process.Times()
   635  	skipIfNotImplementedErr(t, err)
   636  	assert.Nil(t, err)
   637  
   638  	// Spin for a duration of spinSeconds
   639  	t0 := time.Now()
   640  	tGoal := t0.Add(time.Duration(spinSeconds*1000) * time.Millisecond)
   641  	assert.Nil(t, err)
   642  	for time.Now().Before(tGoal) {
   643  		// This block intentionally left blank
   644  	}
   645  
   646  	cpuTimes1, err := process.Times()
   647  	assert.Nil(t, err)
   648  
   649  	if cpuTimes0 == nil || cpuTimes1 == nil {
   650  		t.FailNow()
   651  	}
   652  	measuredElapsed := cpuTimes1.Total() - cpuTimes0.Total()
   653  	message := fmt.Sprintf("Measured %fs != spun time of %fs\ncpuTimes0=%v\ncpuTimes1=%v",
   654  		measuredElapsed, spinSeconds, cpuTimes0, cpuTimes1)
   655  	assert.True(t, measuredElapsed > float64(spinSeconds)/5, message)
   656  	assert.True(t, measuredElapsed < float64(spinSeconds)*5, message)
   657  }
   658  
   659  func Test_OpenFiles(t *testing.T) {
   660  	fp, err := os.Open("process_test.go")
   661  	defer fp.Close()
   662  
   663  	pid := os.Getpid()
   664  	p, err := NewProcess(int32(pid))
   665  	skipIfNotImplementedErr(t, err)
   666  	assert.Nil(t, err)
   667  
   668  	v, err := p.OpenFiles()
   669  	skipIfNotImplementedErr(t, err)
   670  	assert.Nil(t, err)
   671  	assert.NotEmpty(t, v) // test always open files.
   672  
   673  	for _, vv := range v {
   674  		assert.NotEqual(t, "", vv.Path)
   675  	}
   676  }
   677  
   678  func Test_Kill(t *testing.T) {
   679  	var cmd *exec.Cmd
   680  	if runtime.GOOS == "windows" {
   681  		cmd = exec.Command("ping", "localhost", "-n", "4")
   682  	} else {
   683  		cmd = exec.Command("sleep", "3")
   684  	}
   685  	assert.Nil(t, cmd.Start())
   686  	time.Sleep(100 * time.Millisecond)
   687  	p, err := NewProcess(int32(cmd.Process.Pid))
   688  	skipIfNotImplementedErr(t, err)
   689  	assert.Nil(t, err)
   690  	err = p.Kill()
   691  	skipIfNotImplementedErr(t, err)
   692  	assert.Nil(t, err)
   693  	cmd.Wait()
   694  }
   695  
   696  func Test_IsRunning(t *testing.T) {
   697  	var cmd *exec.Cmd
   698  	if runtime.GOOS == "windows" {
   699  		cmd = exec.Command("ping", "localhost", "-n", "2")
   700  	} else {
   701  		cmd = exec.Command("sleep", "1")
   702  	}
   703  	cmd.Start()
   704  	p, err := NewProcess(int32(cmd.Process.Pid))
   705  	skipIfNotImplementedErr(t, err)
   706  	assert.Nil(t, err)
   707  	running, err := p.IsRunning()
   708  	skipIfNotImplementedErr(t, err)
   709  	if err != nil {
   710  		t.Fatalf("IsRunning error: %v", err)
   711  	}
   712  	if !running {
   713  		t.Fatalf("process should be found running")
   714  	}
   715  	cmd.Wait()
   716  	running, err = p.IsRunning()
   717  	skipIfNotImplementedErr(t, err)
   718  	if err != nil {
   719  		t.Fatalf("IsRunning error: %v", err)
   720  	}
   721  	if running {
   722  		t.Fatalf("process should NOT be found running")
   723  	}
   724  }
   725  
   726  func Test_Process_Cwd(t *testing.T) {
   727  	myPid := os.Getpid()
   728  	currentWorkingDirectory, _ := os.Getwd()
   729  
   730  	process, _ := NewProcess(int32(myPid))
   731  	pidCwd, err := process.Cwd()
   732  	skipIfNotImplementedErr(t, err)
   733  	if err != nil {
   734  		t.Fatalf("getting cwd error %v", err)
   735  	}
   736  	pidCwd = strings.TrimSuffix(pidCwd, string(os.PathSeparator))
   737  	assert.Equal(t, currentWorkingDirectory, pidCwd)
   738  
   739  	t.Log(pidCwd)
   740  }
   741  
   742  func Test_Process_Environ(t *testing.T) {
   743  	tmpdir, err := ioutil.TempDir("", "")
   744  	if err != nil {
   745  		t.Fatalf("unable to create temp dir %v", err)
   746  	}
   747  	defer os.RemoveAll(tmpdir) // clean up
   748  	tmpfilepath := filepath.Join(tmpdir, "test.go")
   749  	tmpfile, err := os.Create(tmpfilepath)
   750  	if err != nil {
   751  		t.Fatalf("unable to create temp file %v", err)
   752  	}
   753  
   754  	tmpfilecontent := []byte("package main\nimport(\n\"time\"\n)\nfunc main(){\nfor range time.Tick(time.Second) {}\n}")
   755  	if _, err := tmpfile.Write(tmpfilecontent); err != nil {
   756  		tmpfile.Close()
   757  		t.Fatalf("unable to write temp file %v", err)
   758  	}
   759  	if err := tmpfile.Close(); err != nil {
   760  		t.Fatalf("unable to close temp file %v", err)
   761  	}
   762  
   763  	err = exec.Command("go", "build", "-o", tmpfile.Name()+".exe", tmpfile.Name()).Run()
   764  	if err != nil {
   765  		t.Fatalf("unable to build temp file %v", err)
   766  	}
   767  
   768  	cmd := exec.Command(tmpfile.Name() + ".exe")
   769  
   770  	cmd.Env = []string{"testkey=envvalue"}
   771  
   772  	assert.Nil(t, cmd.Start())
   773  	defer cmd.Process.Kill()
   774  	time.Sleep(100 * time.Millisecond)
   775  	p, err := NewProcess(int32(cmd.Process.Pid))
   776  	skipIfNotImplementedErr(t, err)
   777  	assert.Nil(t, err)
   778  
   779  	envs, err := p.Environ()
   780  	skipIfNotImplementedErr(t, err)
   781  	if err != nil {
   782  		t.Errorf("getting environ error %v", err)
   783  	}
   784  	var envvarFound bool
   785  	for _, envvar := range envs {
   786  		if envvar == "testkey=envvalue" {
   787  			envvarFound = true
   788  			break
   789  		}
   790  	}
   791  	if !envvarFound {
   792  		t.Error("environment variable not found")
   793  	}
   794  }
   795  
   796  func Test_AllProcesses_cmdLine(t *testing.T) {
   797  	procs, err := Processes()
   798  	skipIfNotImplementedErr(t, err)
   799  	if err != nil {
   800  		t.Fatalf("getting processes error %v", err)
   801  	}
   802  	for _, proc := range procs {
   803  		var exeName string
   804  		var cmdLine string
   805  
   806  		exeName, _ = proc.Exe()
   807  		cmdLine, err = proc.Cmdline()
   808  		if err != nil {
   809  			cmdLine = "Error: " + err.Error()
   810  		}
   811  
   812  		t.Logf("Process #%v: Name: %v / CmdLine: %v\n", proc.Pid, exeName, cmdLine)
   813  	}
   814  }
   815  
   816  func Test_AllProcesses_environ(t *testing.T) {
   817  	procs, err := Processes()
   818  	skipIfNotImplementedErr(t, err)
   819  	if err != nil {
   820  		t.Fatalf("getting processes error %v", err)
   821  	}
   822  	for _, proc := range procs {
   823  		exeName, _ := proc.Exe()
   824  		environ, err := proc.Environ()
   825  		if err != nil {
   826  			environ = []string{"Error: " + err.Error()}
   827  		}
   828  
   829  		t.Logf("Process #%v: Name: %v / Environment Variables: %v\n", proc.Pid, exeName, environ)
   830  	}
   831  }
   832  
   833  func Test_AllProcesses_Cwd(t *testing.T) {
   834  	procs, err := Processes()
   835  	skipIfNotImplementedErr(t, err)
   836  	if err != nil {
   837  		t.Fatalf("getting processes error %v", err)
   838  	}
   839  	for _, proc := range procs {
   840  		exeName, _ := proc.Exe()
   841  		cwd, err := proc.Cwd()
   842  		if err != nil {
   843  			cwd = "Error: " + err.Error()
   844  		}
   845  
   846  		t.Logf("Process #%v: Name: %v / Current Working Directory: %s\n", proc.Pid, exeName, cwd)
   847  	}
   848  }
   849  
   850  func BenchmarkNewProcess(b *testing.B) {
   851  	checkPid := os.Getpid()
   852  	for i := 0; i < b.N; i++ {
   853  		NewProcess(int32(checkPid))
   854  	}
   855  }
   856  
   857  func BenchmarkProcessName(b *testing.B) {
   858  	p := testGetProcess()
   859  	for i := 0; i < b.N; i++ {
   860  		p.Name()
   861  	}
   862  }
   863  
   864  func BenchmarkProcessPpid(b *testing.B) {
   865  	p := testGetProcess()
   866  	for i := 0; i < b.N; i++ {
   867  		p.Ppid()
   868  	}
   869  }
   870  

View as plain text