telegraf/plugins/inputs/processes/processes_test.go

248 lines
5.0 KiB
Go

// +build !windows
package processes
import (
"fmt"
"runtime"
"testing"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestProcesses(t *testing.T) {
processes := &Processes{
Log: testutil.Logger{},
execPS: execPS,
readProcFile: readProcFile,
}
var acc testutil.Accumulator
err := processes.Gather(&acc)
require.NoError(t, err)
assert.True(t, acc.HasInt64Field("processes", "running"))
assert.True(t, acc.HasInt64Field("processes", "sleeping"))
assert.True(t, acc.HasInt64Field("processes", "stopped"))
assert.True(t, acc.HasInt64Field("processes", "total"))
total, ok := acc.Get("processes")
require.True(t, ok)
assert.True(t, total.Fields["total"].(int64) > 0)
}
func TestFromPS(t *testing.T) {
processes := &Processes{
Log: testutil.Logger{},
execPS: testExecPS,
forcePS: true,
}
var acc testutil.Accumulator
err := processes.Gather(&acc)
require.NoError(t, err)
fields := getEmptyFields()
fields["blocked"] = int64(4)
fields["zombies"] = int64(1)
fields["running"] = int64(4)
fields["sleeping"] = int64(34)
fields["idle"] = int64(2)
fields["total"] = int64(45)
acc.AssertContainsTaggedFields(t, "processes", fields, map[string]string{})
}
func TestFromPSError(t *testing.T) {
processes := &Processes{
Log: testutil.Logger{},
execPS: testExecPSError,
forcePS: true,
}
var acc testutil.Accumulator
err := processes.Gather(&acc)
require.Error(t, err)
}
func TestFromProcFiles(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("This test only runs on linux")
}
tester := tester{}
processes := &Processes{
Log: testutil.Logger{},
readProcFile: tester.testProcFile,
forceProc: true,
}
var acc testutil.Accumulator
err := processes.Gather(&acc)
require.NoError(t, err)
fields := getEmptyFields()
fields["sleeping"] = tester.calls
fields["total_threads"] = tester.calls * 2
fields["total"] = tester.calls
acc.AssertContainsTaggedFields(t, "processes", fields, map[string]string{})
}
func TestFromProcFilesWithSpaceInCmd(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("This test only runs on linux")
}
tester := tester{}
processes := &Processes{
Log: testutil.Logger{},
readProcFile: tester.testProcFile2,
forceProc: true,
}
var acc testutil.Accumulator
err := processes.Gather(&acc)
require.NoError(t, err)
fields := getEmptyFields()
fields["sleeping"] = tester.calls
fields["total_threads"] = tester.calls * 2
fields["total"] = tester.calls
acc.AssertContainsTaggedFields(t, "processes", fields, map[string]string{})
}
// Based on `man 5 proc`, parked processes an be found in a
// limited range of Linux versions:
//
// > P Parked (Linux 3.9 to 3.13 only)
//
// However, we have had reports of this process state on Ubuntu
// Bionic w/ Linux 4.15 (#6270)
func TestParkedProcess(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("Parked process test only relevant on linux")
}
procstat := `88 (watchdog/13) P 2 0 0 0 -1 69238848 0 0 0 0 0 0 0 0 20 0 1 0 20 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 1 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0
`
plugin := &Processes{
Log: testutil.Logger{},
readProcFile: func(string) ([]byte, error) {
return []byte(procstat), nil
},
forceProc: true,
}
var acc testutil.Accumulator
err := plugin.Gather(&acc)
require.NoError(t, err)
expected := []telegraf.Metric{
testutil.MustMetric(
"processes",
map[string]string{},
map[string]interface{}{
"blocked": 0,
"dead": 0,
"idle": 0,
"paging": 0,
"parked": 1,
"running": 0,
"sleeping": 0,
"stopped": 0,
"unknown": 0,
"zombies": 0,
},
time.Unix(0, 0),
telegraf.Gauge,
),
}
actual := acc.GetTelegrafMetrics()
for _, a := range actual {
a.RemoveField("total")
a.RemoveField("total_threads")
}
testutil.RequireMetricsEqual(t, expected, actual,
testutil.IgnoreTime())
}
func testExecPS() ([]byte, error) {
return []byte(testPSOut), nil
}
// struct for counting calls to testProcFile
type tester struct {
calls int64
}
func (t *tester) testProcFile(_ string) ([]byte, error) {
t.calls++
return []byte(fmt.Sprintf(testProcStat, "S", "2")), nil
}
func (t *tester) testProcFile2(_ string) ([]byte, error) {
t.calls++
return []byte(fmt.Sprintf(testProcStat2, "S", "2")), nil
}
func testExecPSError() ([]byte, error) {
return []byte(testPSOut), fmt.Errorf("ERROR!")
}
const testPSOut = `
STAT
S
S
S
S
R
R
S
S
Ss
Ss
S
SNs
Ss
Ss
S
R+
S
U
S
S
S
S
Ss
S+
Ss
S
S+
S+
Ss
S+
Ss
S
R+
Ss
S
S+
S+
Ss
L
U
Z
D
S+
I
I
`
const testProcStat = `10 (rcuob/0) %s 2 0 0 0 -1 2129984 0 0 0 0 0 0 0 0 20 0 %s 0 11 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0
`
const testProcStat2 = `10 (rcuob 0) %s 2 0 0 0 -1 2129984 0 0 0 0 0 0 0 0 20 0 %s 0 11 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0
`