telegraf/plugins/inputs/ping/ping_test.go

308 lines
9.8 KiB
Go
Raw Normal View History

// +build !windows
2015-09-02 23:16:52 +00:00
package ping
import (
"errors"
"reflect"
"sort"
"testing"
2016-01-20 18:57:35 +00:00
"github.com/influxdata/telegraf/testutil"
2015-09-02 23:16:52 +00:00
"github.com/stretchr/testify/assert"
2018-07-28 01:29:54 +00:00
"github.com/stretchr/testify/require"
2015-09-02 23:16:52 +00:00
)
// BSD/Darwin ping output
var bsdPingOutput = `
PING www.google.com (216.58.217.36): 56 data bytes
64 bytes from 216.58.217.36: icmp_seq=0 ttl=55 time=15.087 ms
64 bytes from 216.58.217.36: icmp_seq=1 ttl=55 time=21.564 ms
64 bytes from 216.58.217.36: icmp_seq=2 ttl=55 time=27.263 ms
64 bytes from 216.58.217.36: icmp_seq=3 ttl=55 time=18.828 ms
64 bytes from 216.58.217.36: icmp_seq=4 ttl=55 time=18.378 ms
--- www.google.com ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 15.087/20.224/27.263/4.076 ms
`
// Linux ping output
var linuxPingOutput = `
PING www.google.com (216.58.218.164) 56(84) bytes of data.
64 bytes from host.net (216.58.218.164): icmp_seq=1 ttl=63 time=35.2 ms
64 bytes from host.net (216.58.218.164): icmp_seq=2 ttl=63 time=42.3 ms
64 bytes from host.net (216.58.218.164): icmp_seq=3 ttl=63 time=45.1 ms
64 bytes from host.net (216.58.218.164): icmp_seq=4 ttl=63 time=43.5 ms
64 bytes from host.net (216.58.218.164): icmp_seq=5 ttl=63 time=51.8 ms
--- www.google.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4010ms
rtt min/avg/max/mdev = 35.225/43.628/51.806/5.325 ms
`
// BusyBox v1.24.1 (2017-02-28 03:28:13 CET) multi-call binary
var busyBoxPingOutput = `
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=56 time=22.559 ms
64 bytes from 8.8.8.8: seq=1 ttl=56 time=15.810 ms
64 bytes from 8.8.8.8: seq=2 ttl=56 time=16.262 ms
64 bytes from 8.8.8.8: seq=3 ttl=56 time=15.815 ms
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 15.810/17.611/22.559 ms
`
2015-09-02 23:16:52 +00:00
// Fatal ping output (invalid argument)
var fatalPingOutput = `
ping: -i interval too short: Operation not permitted
`
// Test that ping command output is processed properly
func TestProcessPingOutput(t *testing.T) {
trans, rec, min, avg, max, stddev, err := processPingOutput(bsdPingOutput)
2015-09-02 23:16:52 +00:00
assert.NoError(t, err)
assert.Equal(t, 5, trans, "5 packets were transmitted")
assert.Equal(t, 5, rec, "5 packets were transmitted")
assert.InDelta(t, 15.087, min, 0.001)
2015-09-02 23:16:52 +00:00
assert.InDelta(t, 20.224, avg, 0.001)
assert.InDelta(t, 27.263, max, 0.001)
assert.InDelta(t, 4.076, stddev, 0.001)
2015-09-02 23:16:52 +00:00
trans, rec, min, avg, max, stddev, err = processPingOutput(linuxPingOutput)
2015-09-02 23:16:52 +00:00
assert.NoError(t, err)
assert.Equal(t, 5, trans, "5 packets were transmitted")
assert.Equal(t, 5, rec, "5 packets were transmitted")
assert.InDelta(t, 35.225, min, 0.001)
2015-09-02 23:16:52 +00:00
assert.InDelta(t, 43.628, avg, 0.001)
assert.InDelta(t, 51.806, max, 0.001)
assert.InDelta(t, 5.325, stddev, 0.001)
trans, rec, min, avg, max, stddev, err = processPingOutput(busyBoxPingOutput)
assert.NoError(t, err)
assert.Equal(t, 4, trans, "4 packets were transmitted")
assert.Equal(t, 4, rec, "4 packets were transmitted")
assert.InDelta(t, 15.810, min, 0.001)
assert.InDelta(t, 17.611, avg, 0.001)
assert.InDelta(t, 22.559, max, 0.001)
assert.InDelta(t, -1.0, stddev, 0.001)
2015-09-02 23:16:52 +00:00
}
// Test that processPingOutput returns an error when 'ping' fails to run, such
// as when an invalid argument is provided
func TestErrorProcessPingOutput(t *testing.T) {
_, _, _, _, _, _, err := processPingOutput(fatalPingOutput)
2015-09-02 23:16:52 +00:00
assert.Error(t, err, "Error was expected from processPingOutput")
}
// Test that arg lists and created correctly
func TestArgs(t *testing.T) {
p := Ping{
2018-07-28 01:29:54 +00:00
Count: 2,
Interface: "eth0",
Timeout: 12.0,
Deadline: 24,
PingInterval: 1.2,
2015-09-02 23:16:52 +00:00
}
2018-07-28 01:29:54 +00:00
var systemCases = []struct {
system string
output []string
}{
{"darwin", []string{"-c", "2", "-n", "-s", "16", "-i", "1.2", "-W", "12000", "-t", "24", "-I", "eth0", "www.google.com"}},
2018-07-28 01:29:54 +00:00
{"linux", []string{"-c", "2", "-n", "-s", "16", "-i", "1.2", "-W", "12", "-w", "24", "-I", "eth0", "www.google.com"}},
{"anything else", []string{"-c", "2", "-n", "-s", "16", "-i", "1.2", "-W", "12", "-w", "24", "-i", "eth0", "www.google.com"}},
}
2018-07-28 01:29:54 +00:00
for i := range systemCases {
actual := p.args("www.google.com", systemCases[i].system)
expected := systemCases[i].output
sort.Strings(actual)
sort.Strings(expected)
require.True(t, reflect.DeepEqual(expected, actual),
"Expected: %s Actual: %s", expected, actual)
}
2015-09-02 23:16:52 +00:00
}
func TestArguments(t *testing.T) {
arguments := []string{"-c", "3"}
expected := append(arguments, "www.google.com")
p := Ping{
Count: 2,
Interface: "eth0",
Timeout: 12.0,
Deadline: 24,
PingInterval: 1.2,
Arguments: arguments,
}
for _, system := range []string{"darwin", "linux", "anything else"} {
actual := p.args("www.google.com", system)
require.True(t, reflect.DeepEqual(actual, expected), "Expected: %s Actual: %s", expected, actual)
}
}
func mockHostPinger(binary string, timeout float64, args ...string) (string, error) {
2015-09-02 23:16:52 +00:00
return linuxPingOutput, nil
}
// Test that Gather function works on a normal ping
func TestPingGather(t *testing.T) {
var acc testutil.Accumulator
p := Ping{
Urls: []string{"www.google.com", "www.reddit.com"},
pingHost: mockHostPinger,
}
2017-04-24 18:13:26 +00:00
acc.GatherError(p.Gather)
2015-09-02 23:16:52 +00:00
tags := map[string]string{"url": "www.google.com"}
fields := map[string]interface{}{
"packets_transmitted": 5,
"packets_received": 5,
"percent_packet_loss": 0.0,
"minimum_response_ms": 35.225,
"average_response_ms": 43.628,
"maximum_response_ms": 51.806,
"standard_deviation_ms": 5.325,
2017-10-26 20:35:37 +00:00
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
2015-09-02 23:16:52 +00:00
tags = map[string]string{"url": "www.reddit.com"}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
2015-09-02 23:16:52 +00:00
}
var lossyPingOutput = `
PING www.google.com (216.58.218.164) 56(84) bytes of data.
64 bytes from host.net (216.58.218.164): icmp_seq=1 ttl=63 time=35.2 ms
64 bytes from host.net (216.58.218.164): icmp_seq=3 ttl=63 time=45.1 ms
64 bytes from host.net (216.58.218.164): icmp_seq=5 ttl=63 time=51.8 ms
--- www.google.com ping statistics ---
5 packets transmitted, 3 received, 40% packet loss, time 4010ms
rtt min/avg/max/mdev = 35.225/44.033/51.806/5.325 ms
`
func mockLossyHostPinger(binary string, timeout float64, args ...string) (string, error) {
2015-09-02 23:16:52 +00:00
return lossyPingOutput, nil
}
// Test that Gather works on a ping with lossy packets
func TestLossyPingGather(t *testing.T) {
var acc testutil.Accumulator
p := Ping{
Urls: []string{"www.google.com"},
pingHost: mockLossyHostPinger,
}
2017-04-24 18:13:26 +00:00
acc.GatherError(p.Gather)
2015-09-02 23:16:52 +00:00
tags := map[string]string{"url": "www.google.com"}
fields := map[string]interface{}{
"packets_transmitted": 5,
"packets_received": 3,
"percent_packet_loss": 40.0,
"minimum_response_ms": 35.225,
"average_response_ms": 44.033,
"maximum_response_ms": 51.806,
"standard_deviation_ms": 5.325,
2017-10-26 20:35:37 +00:00
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
2015-09-02 23:16:52 +00:00
}
var errorPingOutput = `
PING www.amazon.com (176.32.98.166): 56 data bytes
Request timeout for icmp_seq 0
--- www.amazon.com ping statistics ---
2 packets transmitted, 0 packets received, 100.0% packet loss
`
func mockErrorHostPinger(binary string, timeout float64, args ...string) (string, error) {
// This error will not trigger correct error paths
return errorPingOutput, nil
2015-09-02 23:16:52 +00:00
}
// Test that Gather works on a ping with no transmitted packets, even though the
// command returns an error
func TestBadPingGather(t *testing.T) {
var acc testutil.Accumulator
p := Ping{
Urls: []string{"www.amazon.com"},
pingHost: mockErrorHostPinger,
}
2017-04-24 18:13:26 +00:00
acc.GatherError(p.Gather)
2015-09-02 23:16:52 +00:00
tags := map[string]string{"url": "www.amazon.com"}
fields := map[string]interface{}{
"packets_transmitted": 2,
"packets_received": 0,
"percent_packet_loss": 100.0,
2017-10-26 20:35:37 +00:00
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
2015-09-02 23:16:52 +00:00
}
func mockFatalHostPinger(binary string, timeout float64, args ...string) (string, error) {
2015-09-02 23:16:52 +00:00
return fatalPingOutput, errors.New("So very bad")
}
// Test that a fatal ping command does not gather any statistics.
func TestFatalPingGather(t *testing.T) {
var acc testutil.Accumulator
p := Ping{
Urls: []string{"www.amazon.com"},
pingHost: mockFatalHostPinger,
}
2017-04-24 18:13:26 +00:00
acc.GatherError(p.Gather)
2015-09-02 23:16:52 +00:00
assert.False(t, acc.HasMeasurement("packets_transmitted"),
"Fatal ping should not have packet measurements")
assert.False(t, acc.HasMeasurement("packets_received"),
"Fatal ping should not have packet measurements")
assert.False(t, acc.HasMeasurement("percent_packet_loss"),
"Fatal ping should not have packet measurements")
assert.False(t, acc.HasMeasurement("minimum_response_ms"),
"Fatal ping should not have packet measurements")
2015-09-02 23:16:52 +00:00
assert.False(t, acc.HasMeasurement("average_response_ms"),
"Fatal ping should not have packet measurements")
assert.False(t, acc.HasMeasurement("maximum_response_ms"),
"Fatal ping should not have packet measurements")
2015-09-02 23:16:52 +00:00
}
func TestErrorWithHostNamePingGather(t *testing.T) {
params := []struct {
out string
error error
}{
{"", errors.New("host www.amazon.com: So very bad")},
{"so bad", errors.New("host www.amazon.com: so bad, So very bad")},
}
for _, param := range params {
var acc testutil.Accumulator
p := Ping{
Urls: []string{"www.amazon.com"},
pingHost: func(binary string, timeout float64, args ...string) (string, error) {
return param.out, errors.New("So very bad")
},
}
acc.GatherError(p.Gather)
assert.True(t, len(acc.Errors) > 0)
assert.Contains(t, acc.Errors, param.error)
}
}
func TestPingBinary(t *testing.T) {
var acc testutil.Accumulator
p := Ping{
Urls: []string{"www.google.com"},
Binary: "ping6",
pingHost: func(binary string, timeout float64, args ...string) (string, error) {
assert.True(t, binary == "ping6")
return "", nil
},
}
acc.GatherError(p.Gather)
}