Merge pull request #758 from Lomanic/process-cleanup

[process] Propagate context internally on linux and improve tests
This commit is contained in:
shirou 2019-09-07 13:32:35 +09:00 committed by GitHub
commit 56ed89e0cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 148 additions and 111 deletions

View File

@ -70,7 +70,7 @@ func (p *Process) Ppid() (int32, error) {
}
func (p *Process) PpidWithContext(ctx context.Context) (int32, error) {
_, ppid, _, _, _, _, _, err := p.fillFromStat()
_, ppid, _, _, _, _, _, err := p.fillFromStatWithContext(ctx)
if err != nil {
return -1, err
}
@ -84,7 +84,7 @@ func (p *Process) Name() (string, error) {
func (p *Process) NameWithContext(ctx context.Context) (string, error) {
if p.name == "" {
if err := p.fillFromStatus(); err != nil {
if err := p.fillFromStatusWithContext(ctx); err != nil {
return "", err
}
}
@ -94,7 +94,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
// Tgid returns tgid, a Linux-synonym for user-space Pid
func (p *Process) Tgid() (int32, error) {
if p.tgid == 0 {
if err := p.fillFromStatus(); err != nil {
if err := p.fillFromStatusWithContext(context.Background()); err != nil {
return 0, err
}
}
@ -107,7 +107,7 @@ func (p *Process) Exe() (string, error) {
}
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
return p.fillFromExe()
return p.fillFromExeWithContext(ctx)
}
// Cmdline returns the command line arguments of the process as a string with
@ -117,7 +117,7 @@ func (p *Process) Cmdline() (string, error) {
}
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
return p.fillFromCmdline()
return p.fillFromCmdlineWithContext(ctx)
}
// CmdlineSlice returns the command line arguments of the process as a slice with each
@ -127,7 +127,7 @@ func (p *Process) CmdlineSlice() ([]string, error) {
}
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
return p.fillSliceFromCmdline()
return p.fillSliceFromCmdlineWithContext(ctx)
}
// CreateTime returns created time of the process in milliseconds since the epoch, in UTC.
@ -136,7 +136,7 @@ func (p *Process) CreateTime() (int64, error) {
}
func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) {
_, _, _, createTime, _, _, _, err := p.fillFromStat()
_, _, _, createTime, _, _, _, err := p.fillFromStatWithContext(ctx)
if err != nil {
return 0, err
}
@ -149,7 +149,7 @@ func (p *Process) Cwd() (string, error) {
}
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
return p.fillFromCwd()
return p.fillFromCwdWithContext(ctx)
}
// Parent returns parent Process of the process.
@ -158,7 +158,7 @@ func (p *Process) Parent() (*Process, error) {
}
func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) {
err := p.fillFromStatus()
err := p.fillFromStatusWithContext(ctx)
if err != nil {
return nil, err
}
@ -178,7 +178,7 @@ func (p *Process) Status() (string, error) {
}
func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
err := p.fillFromStatus()
err := p.fillFromStatusWithContext(ctx)
if err != nil {
return "", err
}
@ -213,7 +213,7 @@ func (p *Process) Uids() ([]int32, error) {
}
func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) {
err := p.fillFromStatus()
err := p.fillFromStatusWithContext(ctx)
if err != nil {
return []int32{}, err
}
@ -226,7 +226,7 @@ func (p *Process) Gids() ([]int32, error) {
}
func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) {
err := p.fillFromStatus()
err := p.fillFromStatusWithContext(ctx)
if err != nil {
return []int32{}, err
}
@ -239,7 +239,7 @@ func (p *Process) Terminal() (string, error) {
}
func (p *Process) TerminalWithContext(ctx context.Context) (string, error) {
t, _, _, _, _, _, _, err := p.fillFromStat()
t, _, _, _, _, _, _, err := p.fillFromStatWithContext(ctx)
if err != nil {
return "", err
}
@ -258,7 +258,7 @@ func (p *Process) Nice() (int32, error) {
}
func (p *Process) NiceWithContext(ctx context.Context) (int32, error) {
_, _, _, _, _, nice, _, err := p.fillFromStat()
_, _, _, _, _, nice, _, err := p.fillFromStatWithContext(ctx)
if err != nil {
return 0, err
}
@ -291,16 +291,16 @@ func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) {
}
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
rlimits, err := p.fillFromLimits()
rlimits, err := p.fillFromLimitsWithContext(ctx)
if !gatherUsed || err != nil {
return rlimits, err
}
_, _, _, _, rtprio, nice, _, err := p.fillFromStat()
_, _, _, _, rtprio, nice, _, err := p.fillFromStatWithContext(ctx)
if err != nil {
return nil, err
}
if err := p.fillFromStatus(); err != nil {
if err := p.fillFromStatusWithContext(ctx); err != nil {
return nil, err
}
@ -351,7 +351,7 @@ func (p *Process) IOCounters() (*IOCountersStat, error) {
}
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
return p.fillFromIO()
return p.fillFromIOWithContext(ctx)
}
// NumCtxSwitches returns the number of the context switches of the process.
@ -360,7 +360,7 @@ func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
}
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
err := p.fillFromStatus()
err := p.fillFromStatusWithContext(ctx)
if err != nil {
return nil, err
}
@ -373,7 +373,7 @@ func (p *Process) NumFDs() (int32, error) {
}
func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) {
_, fnames, err := p.fillFromfdList()
_, fnames, err := p.fillFromfdListWithContext(ctx)
return int32(len(fnames)), err
}
@ -383,7 +383,7 @@ func (p *Process) NumThreads() (int32, error) {
}
func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
err := p.fillFromStatus()
err := p.fillFromStatusWithContext(ctx)
if err != nil {
return 0, err
}
@ -404,7 +404,7 @@ func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesS
}
for _, tid := range tids {
_, _, cpuTimes, _, _, _, _, err := p.fillFromTIDStat(tid)
_, _, cpuTimes, _, _, _, _, err := p.fillFromTIDStatWithContext(ctx, tid)
if err != nil {
return nil, err
}
@ -420,7 +420,7 @@ func (p *Process) Times() (*cpu.TimesStat, error) {
}
func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) {
_, _, cpuTimes, _, _, _, _, err := p.fillFromStat()
_, _, cpuTimes, _, _, _, _, err := p.fillFromStatWithContext(ctx)
if err != nil {
return nil, err
}
@ -444,7 +444,7 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
}
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
meminfo, _, err := p.fillFromStatm()
meminfo, _, err := p.fillFromStatmWithContext(ctx)
if err != nil {
return nil, err
}
@ -457,7 +457,7 @@ func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
}
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
_, memInfoEx, err := p.fillFromStatm()
_, memInfoEx, err := p.fillFromStatmWithContext(ctx)
if err != nil {
return nil, err
}
@ -470,7 +470,7 @@ func (p *Process) PageFaults() (*PageFaultsStat, error) {
}
func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, error) {
_, _, _, _, _, _, pageFaults, err := p.fillFromStat()
_, _, _, _, _, _, pageFaults, err := p.fillFromStatWithContext(ctx)
if err != nil {
return nil, err
}
@ -509,7 +509,7 @@ func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
}
func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) {
_, ofs, err := p.fillFromfd()
_, ofs, err := p.fillFromfdWithContext(ctx)
if err != nil {
return nil, err
}
@ -675,10 +675,6 @@ func limitToInt(val string) (int32, error) {
}
// Get num_fds from /proc/(pid)/limits
func (p *Process) fillFromLimits() ([]RlimitStat, error) {
return p.fillFromLimitsWithContext(context.Background())
}
func (p *Process) fillFromLimitsWithContext(ctx context.Context) ([]RlimitStat, error) {
pid := p.Pid
limitsFile := common.HostProc(strconv.Itoa(int(pid)), "limits")
@ -772,10 +768,6 @@ func (p *Process) fillFromLimitsWithContext(ctx context.Context) ([]RlimitStat,
}
// Get list of /proc/(pid)/fd files
func (p *Process) fillFromfdList() (string, []string, error) {
return p.fillFromfdListWithContext(context.Background())
}
func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) {
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "fd")
@ -789,12 +781,8 @@ func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []stri
}
// Get num_fds from /proc/(pid)/fd
func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) {
return p.fillFromfdWithContext(context.Background())
}
func (p *Process) fillFromfdWithContext(ctx context.Context) (int32, []*OpenFilesStat, error) {
statPath, fnames, err := p.fillFromfdList()
statPath, fnames, err := p.fillFromfdListWithContext(ctx)
if err != nil {
return 0, nil, err
}
@ -822,10 +810,6 @@ func (p *Process) fillFromfdWithContext(ctx context.Context) (int32, []*OpenFile
}
// Get cwd from /proc/(pid)/cwd
func (p *Process) fillFromCwd() (string, error) {
return p.fillFromCwdWithContext(context.Background())
}
func (p *Process) fillFromCwdWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cwdPath := common.HostProc(strconv.Itoa(int(pid)), "cwd")
@ -837,10 +821,6 @@ func (p *Process) fillFromCwdWithContext(ctx context.Context) (string, error) {
}
// Get exe from /proc/(pid)/exe
func (p *Process) fillFromExe() (string, error) {
return p.fillFromExeWithContext(context.Background())
}
func (p *Process) fillFromExeWithContext(ctx context.Context) (string, error) {
pid := p.Pid
exePath := common.HostProc(strconv.Itoa(int(pid)), "exe")
@ -852,10 +832,6 @@ func (p *Process) fillFromExeWithContext(ctx context.Context) (string, error) {
}
// Get cmdline from /proc/(pid)/cmdline
func (p *Process) fillFromCmdline() (string, error) {
return p.fillFromCmdlineWithContext(context.Background())
}
func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
@ -873,10 +849,6 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
return strings.Join(ret, " "), nil
}
func (p *Process) fillSliceFromCmdline() ([]string, error) {
return p.fillSliceFromCmdlineWithContext(context.Background())
}
func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
@ -900,10 +872,6 @@ func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string
}
// Get IO status from /proc/(pid)/io
func (p *Process) fillFromIO() (*IOCountersStat, error) {
return p.fillFromIOWithContext(context.Background())
}
func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, error) {
pid := p.Pid
ioPath := common.HostProc(strconv.Itoa(int(pid)), "io")
@ -943,10 +911,6 @@ func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, e
}
// Get memory info from /proc/(pid)/statm
func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
return p.fillFromStatmWithContext(context.Background())
}
func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat, *MemoryInfoExStat, error) {
pid := p.Pid
memPath := common.HostProc(strconv.Itoa(int(pid)), "statm")
@ -999,10 +963,6 @@ func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat
}
// Get various status from /proc/(pid)/status
func (p *Process) fillFromStatus() error {
return p.fillFromStatusWithContext(context.Background())
}
func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "status")
@ -1172,10 +1132,6 @@ func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
return nil
}
func (p *Process) fillFromTIDStat(tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
return p.fillFromTIDStatWithContext(context.Background(), tid)
}
func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
pid := p.Pid
var statPath string
@ -1272,12 +1228,8 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
return terminal, int32(ppid), cpuTimes, createTime, uint32(rtpriority), nice, faults, nil
}
func (p *Process) fillFromStat() (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
return p.fillFromStatWithContext(context.Background())
}
func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *cpu.TimesStat, int64, uint32, int32, *PageFaultsStat, error) {
return p.fillFromTIDStat(-1)
return p.fillFromTIDStatWithContext(ctx, -1)
}
func pidsWithContext(ctx context.Context) ([]int32, error) {

View File

@ -2,11 +2,13 @@ package process
import (
"fmt"
"net"
"os"
"os/exec"
"os/user"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"testing"
@ -18,6 +20,12 @@ import (
var mu sync.Mutex
func skipIfNotImplementedErr(t *testing.T, err error) {
if err == common.ErrNotImplementedError {
t.Skip("not implemented")
}
}
func testGetProcess() Process {
checkPid := os.Getpid() // process.test
ret, _ := NewProcess(int32(checkPid))
@ -26,6 +34,7 @@ func testGetProcess() Process {
func Test_Pids(t *testing.T) {
ret, err := Pids()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
@ -44,6 +53,7 @@ func Test_Pids_Fail(t *testing.T) {
invoke = common.FakeInvoke{Suffix: "fail"}
ret, err := Pids()
skipIfNotImplementedErr(t, err)
invoke = common.Invoke{}
if err != nil {
t.Errorf("error %v", err)
@ -56,6 +66,7 @@ func Test_Pid_exists(t *testing.T) {
checkPid := os.Getpid()
ret, err := PidExists(int32(checkPid))
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
@ -69,6 +80,7 @@ func Test_NewProcess(t *testing.T) {
checkPid := os.Getpid()
ret, err := NewProcess(int32(checkPid))
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
@ -85,12 +97,14 @@ func Test_Process_memory_maps(t *testing.T) {
checkPid := os.Getpid()
ret, err := NewProcess(int32(checkPid))
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
// ungrouped memory maps
mmaps, err := ret.MemoryMaps(false)
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("memory map get error %v", err)
}
@ -103,6 +117,7 @@ func Test_Process_memory_maps(t *testing.T) {
// grouped memory maps
mmaps, err = ret.MemoryMaps(true)
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("memory map get error %v", err)
}
@ -117,8 +132,9 @@ func Test_Process_MemoryInfo(t *testing.T) {
p := testGetProcess()
v, err := p.MemoryInfo()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting memory info error %v", err)
t.Errorf("getting memory info error %v", err)
}
empty := MemoryInfoStat{}
if v == nil || *v == empty {
@ -130,8 +146,9 @@ func Test_Process_CmdLine(t *testing.T) {
p := testGetProcess()
v, err := p.Cmdline()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting cmdline error %v", err)
t.Errorf("getting cmdline error %v", err)
}
if !strings.Contains(v, "process.test") {
t.Errorf("invalid cmd line %v", v)
@ -142,8 +159,9 @@ func Test_Process_CmdLineSlice(t *testing.T) {
p := testGetProcess()
v, err := p.CmdlineSlice()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Fatalf("geting cmdline slice error %v", err)
t.Fatalf("getting cmdline slice error %v", err)
}
if !reflect.DeepEqual(v, os.Args) {
t.Errorf("returned cmdline slice not as expected:\nexp: %v\ngot: %v", os.Args, v)
@ -154,8 +172,9 @@ func Test_Process_Ppid(t *testing.T) {
p := testGetProcess()
v, err := p.Ppid()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting ppid error %v", err)
t.Errorf("getting ppid error %v", err)
}
if v == 0 {
t.Errorf("return value is 0 %v", v)
@ -166,8 +185,9 @@ func Test_Process_Status(t *testing.T) {
p := testGetProcess()
v, err := p.Status()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting status error %v", err)
t.Errorf("getting status error %v", err)
}
if v != "R" && v != "S" {
t.Errorf("could not get state %v", v)
@ -178,8 +198,9 @@ func Test_Process_Terminal(t *testing.T) {
p := testGetProcess()
_, err := p.Terminal()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting terminal error %v", err)
t.Errorf("getting terminal error %v", err)
}
}
@ -187,8 +208,9 @@ func Test_Process_IOCounters(t *testing.T) {
p := testGetProcess()
v, err := p.IOCounters()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting iocounter error %v", err)
t.Errorf("getting iocounter error %v", err)
return
}
empty := &IOCountersStat{}
@ -201,8 +223,9 @@ func Test_Process_NumCtx(t *testing.T) {
p := testGetProcess()
_, err := p.NumCtxSwitches()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting numctx error %v", err)
t.Errorf("getting numctx error %v", err)
return
}
}
@ -211,8 +234,9 @@ func Test_Process_Nice(t *testing.T) {
p := testGetProcess()
n, err := p.Nice()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting nice error %v", err)
t.Errorf("getting nice error %v", err)
}
if n != 0 && n != 20 && n != 8 {
t.Errorf("invalid nice: %d", n)
@ -222,8 +246,9 @@ func Test_Process_NumThread(t *testing.T) {
p := testGetProcess()
n, err := p.NumThreads()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting NumThread error %v", err)
t.Errorf("getting NumThread error %v", err)
}
if n < 0 {
t.Errorf("invalid NumThread: %d", n)
@ -234,16 +259,18 @@ func Test_Process_Threads(t *testing.T) {
p := testGetProcess()
n, err := p.NumThreads()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting NumThread error %v", err)
t.Errorf("getting NumThread error %v", err)
}
if n < 0 {
t.Errorf("invalid NumThread: %d", n)
}
ts, err := p.Threads()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting Threads error %v", err)
t.Errorf("getting Threads error %v", err)
}
if len(ts) != int(n) {
t.Errorf("unexpected number of threads: %v vs %v", len(ts), n)
@ -254,8 +281,9 @@ func Test_Process_Name(t *testing.T) {
p := testGetProcess()
n, err := p.Name()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting name error %v", err)
t.Errorf("getting name error %v", err)
}
if !strings.Contains(n, "process.test") {
t.Errorf("invalid Exe %s", n)
@ -265,8 +293,9 @@ func Test_Process_Exe(t *testing.T) {
p := testGetProcess()
n, err := p.Exe()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("geting Exe error %v", err)
t.Errorf("getting Exe error %v", err)
}
if !strings.Contains(n, "process.test") {
t.Errorf("invalid Exe %s", n)
@ -276,6 +305,7 @@ func Test_Process_Exe(t *testing.T) {
func Test_Process_CpuPercent(t *testing.T) {
p := testGetProcess()
percent, err := p.Percent(0)
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
@ -300,6 +330,7 @@ func Test_Process_CpuPercentLoop(t *testing.T) {
for i := 0; i < 2; i++ {
duration := time.Duration(100) * time.Microsecond
percent, err := p.Percent(duration)
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
@ -318,6 +349,7 @@ func Test_Process_CreateTime(t *testing.T) {
p := testGetProcess()
c, err := p.CreateTime()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
@ -338,6 +370,7 @@ func Test_Parent(t *testing.T) {
p := testGetProcess()
c, err := p.Parent()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Fatalf("error %v", err)
}
@ -351,32 +384,81 @@ func Test_Parent(t *testing.T) {
func Test_Connections(t *testing.T) {
p := testGetProcess()
ch0 := make(chan string)
ch1 := make(chan string)
go func() { // TCP listening goroutine
addr, err := net.ResolveTCPAddr("tcp", "localhost:0") // dynamically get a random open port from OS
if err != nil {
t.Skip("unable to resolve localhost:", err)
}
l, err := net.ListenTCP(addr.Network(), addr)
if err != nil {
t.Skip(fmt.Sprintf("unable to listen on %v: %v", addr, err))
}
defer l.Close()
ch0 <- l.Addr().String()
for {
conn, err := l.Accept()
if err != nil {
t.Skip("unable to accept connection:", err)
}
ch1 <- l.Addr().String()
defer conn.Close()
}
}()
go func() { // TCP client goroutine
tcpServerAddr := <-ch0
net.Dial("tcp", tcpServerAddr)
}()
c, err := p.Connections()
tcpServerAddr := <-ch1
tcpServerAddrIP := strings.Split(tcpServerAddr, ":")[0]
tcpServerAddrPort, err := strconv.ParseUint(strings.Split(tcpServerAddr, ":")[1], 10, 32)
if err != nil {
t.Fatalf("error %v", err)
t.Errorf("unable to parse tcpServerAddr port: %v", err)
}
// TODO:
// Since go test open no connection, ret is empty.
// should invoke child process or other solutions.
if len(c) != 0 {
t.Fatalf("wrong connections")
c, err := p.Connections()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
if len(c) == 0 {
t.Errorf("no connections found")
}
found := 0
for _, connection := range c {
if connection.Status == "ESTABLISHED" && (connection.Laddr.IP == tcpServerAddrIP && connection.Laddr.Port == uint32(tcpServerAddrPort)) || (connection.Raddr.IP == tcpServerAddrIP && connection.Raddr.Port == uint32(tcpServerAddrPort)) {
found++
}
}
if found != 2 { // two established connections, one for the server, the other for the client
t.Errorf(fmt.Sprintf("wrong connections: %+v", c))
}
}
func Test_Children(t *testing.T) {
p, err := NewProcess(1)
if err != nil {
t.Fatalf("new process error %v", err)
p := testGetProcess()
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("ping", "localhost", "-n", "4")
} else {
cmd = exec.Command("sleep", "3")
}
assert.Nil(t, cmd.Start())
time.Sleep(100 * time.Millisecond)
c, err := p.Children()
skipIfNotImplementedErr(t, err)
if err != nil {
t.Fatalf("error %v", err)
}
if len(c) == 0 {
t.Fatalf("children is empty")
}
if c[0].Pid != int32(cmd.Process.Pid) {
t.Errorf("could not find child %d", cmd.Process.Pid)
}
}
func Test_Username(t *testing.T) {
@ -385,7 +467,8 @@ func Test_Username(t *testing.T) {
myUsername := currentUser.Username
process, _ := NewProcess(int32(myPid))
pidUsername, _ := process.Username()
pidUsername, err := process.Username()
skipIfNotImplementedErr(t, err)
assert.Equal(t, myUsername, pidUsername)
t.Log(pidUsername)
@ -394,10 +477,12 @@ func Test_Username(t *testing.T) {
func Test_CPUTimes(t *testing.T) {
pid := os.Getpid()
process, err := NewProcess(int32(pid))
skipIfNotImplementedErr(t, err)
assert.Nil(t, err)
spinSeconds := 0.2
cpuTimes0, err := process.Times()
skipIfNotImplementedErr(t, err)
assert.Nil(t, err)
// Spin for a duration of spinSeconds
@ -424,9 +509,11 @@ func Test_CPUTimes(t *testing.T) {
func Test_OpenFiles(t *testing.T) {
pid := os.Getpid()
p, err := NewProcess(int32(pid))
skipIfNotImplementedErr(t, err)
assert.Nil(t, err)
v, err := p.OpenFiles()
skipIfNotImplementedErr(t, err)
assert.Nil(t, err)
assert.NotEmpty(t, v) // test always open files.
@ -438,19 +525,17 @@ func Test_OpenFiles(t *testing.T) {
func Test_Kill(t *testing.T) {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("choice", "/C", "YN", "/D", "Y", "/t", "3")
cmd = exec.Command("ping", "localhost", "-n", "4")
} else {
cmd = exec.Command("sleep", "3")
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
assert.NotNil(t, cmd.Run())
wg.Done()
}()
assert.Nil(t, cmd.Start())
time.Sleep(100 * time.Millisecond)
p, err := NewProcess(int32(cmd.Process.Pid))
skipIfNotImplementedErr(t, err)
assert.Nil(t, err)
assert.Nil(t, p.Kill())
wg.Wait()
err = p.Kill()
skipIfNotImplementedErr(t, err)
assert.Nil(t, err)
cmd.Wait()
}