1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-04-26 13:48:59 +08:00
shirou_gopsutil/process/process_test.go
Chris Gilling b8c40ac83c process: add CmdlineSlice function for linux + freebsd
This allows for getting more exact information about each argument
especially if there are arguments that have spaces in them.

This was not implemented for darwin or for windows because they
both currently have not way of properly parsing the cmdline string.
Darwin parses the output of 'ps' which is already whitespace
segmented, and windows just has the cmdline string.
2016-02-27 18:01:49 -08:00

383 lines
7.5 KiB
Go

package process
import (
"fmt"
"os"
"os/user"
"reflect"
"runtime"
"strings"
"sync"
"testing"
"time"
"github.com/shirou/gopsutil/internal/common"
"github.com/stretchr/testify/assert"
)
var mu sync.Mutex
func testGetProcess() Process {
checkPid := os.Getpid() // process.test
ret, _ := NewProcess(int32(checkPid))
return *ret
}
func Test_Pids(t *testing.T) {
ret, err := Pids()
if err != nil {
t.Errorf("error %v", err)
}
if len(ret) == 0 {
t.Errorf("could not get pids %v", ret)
}
}
func Test_Pids_Fail(t *testing.T) {
if runtime.GOOS != "darwin" {
t.Skip("darwin only")
}
mu.Lock()
defer mu.Unlock()
invoke = common.FakeInvoke{Suffix: "fail"}
ret, err := Pids()
invoke = common.Invoke{}
if err != nil {
t.Errorf("error %v", err)
}
if len(ret) != 9 {
t.Errorf("wrong getted pid nums: %v/%d", ret, len(ret))
}
}
func Test_Pid_exists(t *testing.T) {
checkPid := os.Getpid()
ret, err := PidExists(int32(checkPid))
if err != nil {
t.Errorf("error %v", err)
}
if ret == false {
t.Errorf("could not get process exists: %v", ret)
}
}
func Test_NewProcess(t *testing.T) {
checkPid := os.Getpid()
ret, err := NewProcess(int32(checkPid))
if err != nil {
t.Errorf("error %v", err)
}
empty := &Process{}
if runtime.GOOS != "windows" { // Windows pid is 0
if empty == ret {
t.Errorf("error %v", ret)
}
}
}
func Test_Process_memory_maps(t *testing.T) {
checkPid := os.Getpid()
ret, err := NewProcess(int32(checkPid))
mmaps, err := ret.MemoryMaps(false)
if err != nil {
t.Errorf("memory map get error %v", err)
}
empty := MemoryMapsStat{}
for _, m := range *mmaps {
if m == empty {
t.Errorf("memory map get error %v", m)
}
}
}
func Test_Process_MemoryInfo(t *testing.T) {
p := testGetProcess()
v, err := p.MemoryInfo()
if err != nil {
t.Errorf("geting memory info error %v", err)
}
empty := MemoryInfoStat{}
if v == nil || *v == empty {
t.Errorf("could not get memory info %v", v)
}
}
func Test_Process_CmdLine(t *testing.T) {
p := testGetProcess()
v, err := p.Cmdline()
if err != nil {
t.Errorf("geting cmdline error %v", err)
}
if !strings.Contains(v, "process.test") {
t.Errorf("invalid cmd line %v", v)
}
}
func Test_Process_CmdLineSlice(t *testing.T) {
p := testGetProcess()
v, err := p.CmdlineSlice()
if err != nil {
t.Fatalf("geting 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)
}
}
func Test_Process_Ppid(t *testing.T) {
p := testGetProcess()
v, err := p.Ppid()
if err != nil {
t.Errorf("geting ppid error %v", err)
}
if v == 0 {
t.Errorf("return value is 0 %v", v)
}
}
func Test_Process_Status(t *testing.T) {
p := testGetProcess()
v, err := p.Status()
if err != nil {
t.Errorf("geting status error %v", err)
}
if !strings.HasPrefix(v, "S") && v != "running" && v != "sleeping" {
t.Errorf("could not get state %v", v)
}
}
func Test_Process_Terminal(t *testing.T) {
p := testGetProcess()
_, err := p.Terminal()
if err != nil {
t.Errorf("geting terminal error %v", err)
}
/*
if v == "" {
t.Errorf("could not get terminal %v", v)
}
*/
}
func Test_Process_IOCounters(t *testing.T) {
p := testGetProcess()
v, err := p.IOCounters()
if err != nil {
t.Errorf("geting iocounter error %v", err)
return
}
empty := &IOCountersStat{}
if v == empty {
t.Errorf("error %v", v)
}
}
func Test_Process_NumCtx(t *testing.T) {
p := testGetProcess()
_, err := p.NumCtxSwitches()
if err != nil {
t.Errorf("geting numctx error %v", err)
return
}
}
func Test_Process_Nice(t *testing.T) {
p := testGetProcess()
n, err := p.Nice()
if err != nil {
t.Errorf("geting nice error %v", err)
}
if n != 0 && n != 20 && n != 8 {
t.Errorf("invalid nice: %d", n)
}
}
func Test_Process_NumThread(t *testing.T) {
p := testGetProcess()
n, err := p.NumThreads()
if err != nil {
t.Errorf("geting NumThread error %v", err)
}
if n < 0 {
t.Errorf("invalid NumThread: %d", n)
}
}
func Test_Process_Name(t *testing.T) {
p := testGetProcess()
n, err := p.Name()
if err != nil {
t.Errorf("geting name error %v", err)
}
if !strings.Contains(n, "process.test") {
t.Errorf("invalid Exe %s", n)
}
}
func Test_Process_Exe(t *testing.T) {
p := testGetProcess()
n, err := p.Exe()
if err != nil {
t.Errorf("geting Exe error %v", err)
}
if !strings.Contains(n, "process.test") {
t.Errorf("invalid Exe %s", n)
}
}
func Test_Process_CpuPercent(t *testing.T) {
p := testGetProcess()
percent, err := p.CPUPercent(0)
if err != nil {
t.Errorf("error %v", err)
}
duration := time.Duration(1000) * time.Microsecond
time.Sleep(duration)
percent, err = p.CPUPercent(0)
if err != nil {
t.Errorf("error %v", err)
}
numcpu := runtime.NumCPU()
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
if percent < 0.0 {
t.Fatalf("CPUPercent value is invalid: %f, %d", percent, numcpu)
}
}
func Test_Process_CpuPercentLoop(t *testing.T) {
p := testGetProcess()
numcpu := runtime.NumCPU()
for i := 0; i < 2; i++ {
duration := time.Duration(100) * time.Microsecond
percent, err := p.CPUPercent(duration)
if err != nil {
t.Errorf("error %v", err)
}
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
if percent < 0.0 {
t.Fatalf("CPUPercent value is invalid: %f, %d", percent, numcpu)
}
}
}
func Test_Process_CreateTime(t *testing.T) {
p := testGetProcess()
c, err := p.CreateTime()
if err != nil {
t.Errorf("error %v", err)
}
if c < 1420000000 {
t.Errorf("process created time is wrong.")
}
gotElapsed := time.Since(time.Unix(int64(c/1000), 0))
maxElapsed := time.Duration(5 * time.Second)
if gotElapsed >= maxElapsed {
t.Errorf("this process has not been running for %v", gotElapsed)
}
}
func Test_Parent(t *testing.T) {
p := testGetProcess()
c, err := p.Parent()
if err != nil {
t.Fatalf("error %v", err)
}
if c == nil {
t.Fatalf("could not get parent")
}
if c.Pid == 0 {
t.Fatalf("wrong parent pid")
}
}
func Test_Connections(t *testing.T) {
p := testGetProcess()
c, err := p.Connections()
if err != nil {
t.Fatalf("error %v", err)
}
// TODO:
// Since go test open no conneciton, ret is empty.
// should invoke child process or other solutions.
if len(c) != 0 {
t.Fatalf("wrong connections")
}
}
func Test_Children(t *testing.T) {
p, err := NewProcess(1)
if err != nil {
t.Fatalf("new process error %v", err)
}
c, err := p.Children()
if err != nil {
t.Fatalf("error %v", err)
}
if len(c) == 0 {
t.Fatalf("children is empty")
}
}
func Test_Username(t *testing.T) {
myPid := os.Getpid()
currentUser, _ := user.Current()
myUsername := currentUser.Username
process, _ := NewProcess(int32(myPid))
pidUsername, _ := process.Username()
assert.Equal(t, myUsername, pidUsername)
}
func Test_CPUTimes(t *testing.T) {
pid := os.Getpid()
process, err := NewProcess(int32(pid))
assert.Nil(t, err)
spinSeconds := 0.2
cpuTimes0, err := process.CPUTimes()
assert.Nil(t, err)
// Spin for a duration of spinSeconds
t0 := time.Now()
tGoal := t0.Add(time.Duration(spinSeconds*1000) * time.Millisecond)
assert.Nil(t, err)
for time.Now().Before(tGoal) {
// This block intentionally left blank
}
cpuTimes1, err := process.CPUTimes()
assert.Nil(t, err)
measuredElapsed := cpuTimes1.Total() - cpuTimes0.Total()
message := fmt.Sprintf("Measured %fs != spun time of %fs\ncpuTimes0=%v\ncpuTimes1=%v",
measuredElapsed, spinSeconds, cpuTimes0, cpuTimes1)
assert.True(t, measuredElapsed > float64(spinSeconds)/5, message)
assert.True(t, measuredElapsed < float64(spinSeconds)*5, message)
}