Improve /proc/net/dev parsing to include all edge cases

This commit is contained in:
Alexander Blagoev 2017-04-29 18:57:54 +03:00
parent 70693b6a3d
commit f7dd4f97c7
2 changed files with 74 additions and 2 deletions

View File

@ -32,15 +32,20 @@ func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
return nil, err
}
parts := make([]string, 2)
statlen := len(lines) - 1
ret := make([]IOCountersStat, 0, statlen)
for _, line := range lines[2:] {
parts := strings.SplitN(line, ": ", 2)
if len(parts) != 2 {
separatorPos := strings.LastIndex(line, ":")
if separatorPos == -1 {
continue
}
parts[0] = line[0:separatorPos]
parts[1] = line[separatorPos+1:]
interfaceName := strings.TrimSpace(parts[0])
if interfaceName == "" {
continue

View File

@ -1,7 +1,10 @@
package net
import (
"fmt"
"io/ioutil"
"os"
"strings"
"syscall"
"testing"
@ -9,6 +12,70 @@ import (
"github.com/stretchr/testify/assert"
)
func TestIOCountersByFileParsing(t *testing.T) {
// Prpare a temporary file, which will be read during the test
tmpfile, err := ioutil.TempFile("", "proc_dev_net")
defer os.Remove(tmpfile.Name()) // clean up
assert.Nil(t, err, "Temporary file creation failed: ", err)
cases := [4][2]string{
[2]string{"eth0: ", "eth1: "},
[2]string{"eth0:0: ", "eth1:0: "},
[2]string{"eth0:", "eth1:"},
[2]string{"eth0:0:", "eth1:0:"},
}
for _, testCase := range cases {
err = tmpfile.Truncate(0)
assert.Nil(t, err, "Temporary file truncating problem: ", err)
// Parse interface name for assertion
interface0 := strings.TrimSpace(testCase[0])
interface0 = interface0[:len(interface0)-1]
interface1 := strings.TrimSpace(testCase[1])
interface1 = interface1[:len(interface1)-1]
// Replace the interfaces from the test case
proc := []byte(fmt.Sprintf("Inter-| Receive | Transmit\n face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n %s1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16\n %s100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500 1600\n", testCase[0], testCase[1]))
// Write /proc/net/dev sample output
_, err = tmpfile.Write(proc)
assert.Nil(t, err, "Temporary file writing failed: ", err)
counters, err := IOCountersByFile(true, tmpfile.Name())
assert.Nil(t, err)
assert.NotEmpty(t, counters)
assert.Equal(t, 2, len(counters))
assert.Equal(t, interface0, counters[0].Name)
assert.Equal(t, 1, int(counters[0].BytesRecv))
assert.Equal(t, 2, int(counters[0].PacketsRecv))
assert.Equal(t, 3, int(counters[0].Errin))
assert.Equal(t, 4, int(counters[0].Dropin))
assert.Equal(t, 5, int(counters[0].Fifoin))
assert.Equal(t, 9, int(counters[0].BytesSent))
assert.Equal(t, 10, int(counters[0].PacketsSent))
assert.Equal(t, 11, int(counters[0].Errout))
assert.Equal(t, 12, int(counters[0].Dropout))
assert.Equal(t, 13, int(counters[0].Fifoout))
assert.Equal(t, interface1, counters[1].Name)
assert.Equal(t, 100, int(counters[1].BytesRecv))
assert.Equal(t, 200, int(counters[1].PacketsRecv))
assert.Equal(t, 300, int(counters[1].Errin))
assert.Equal(t, 400, int(counters[1].Dropin))
assert.Equal(t, 500, int(counters[1].Fifoin))
assert.Equal(t, 900, int(counters[1].BytesSent))
assert.Equal(t, 1000, int(counters[1].PacketsSent))
assert.Equal(t, 1100, int(counters[1].Errout))
assert.Equal(t, 1200, int(counters[1].Dropout))
assert.Equal(t, 1300, int(counters[1].Fifoout))
}
err = tmpfile.Close()
assert.Nil(t, err, "Temporary file closing failed: ", err)
}
func TestGetProcInodesAll(t *testing.T) {
if os.Getenv("CIRCLECI") == "true" {
t.Skip("Skip CI")