* Use golangci-lint to add lint presubmit test, and fix linter errors Signed-off-by: Maciej "Iwan" Iwanowski <maciej.iwanowski@intel.com>
303 lines
7.9 KiB
Go
303 lines
7.9 KiB
Go
// Copyright 2018 Google Inc. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package libcontainer
|
|
|
|
import (
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
|
|
info "github.com/google/cadvisor/info/v1"
|
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
|
"github.com/opencontainers/runc/libcontainer/system"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestScanInterfaceStats(t *testing.T) {
|
|
stats, err := scanInterfaceStats("testdata/procnetdev")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
var netdevstats = []info.InterfaceStats{
|
|
{
|
|
Name: "wlp4s0",
|
|
RxBytes: 1,
|
|
RxPackets: 2,
|
|
RxErrors: 3,
|
|
RxDropped: 4,
|
|
TxBytes: 9,
|
|
TxPackets: 10,
|
|
TxErrors: 11,
|
|
TxDropped: 12,
|
|
},
|
|
{
|
|
Name: "em1",
|
|
RxBytes: 315849,
|
|
RxPackets: 1172,
|
|
RxErrors: 0,
|
|
RxDropped: 0,
|
|
TxBytes: 315850,
|
|
TxPackets: 1173,
|
|
TxErrors: 0,
|
|
TxDropped: 0,
|
|
},
|
|
}
|
|
|
|
if len(stats) != len(netdevstats) {
|
|
t.Errorf("Expected 2 net stats, got %d", len(stats))
|
|
}
|
|
|
|
for i, v := range netdevstats {
|
|
if v != stats[i] {
|
|
t.Errorf("Expected %#v, got %#v", v, stats[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestScanUDPStats(t *testing.T) {
|
|
udpStatsFile := "testdata/procnetudp"
|
|
r, err := os.Open(udpStatsFile)
|
|
if err != nil {
|
|
t.Errorf("failure opening %s: %v", udpStatsFile, err)
|
|
}
|
|
|
|
stats, err := scanUDPStats(r)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
var udpstats = info.UdpStat{
|
|
Listen: 2,
|
|
Dropped: 4,
|
|
RxQueued: 10,
|
|
TxQueued: 11,
|
|
}
|
|
|
|
if stats != udpstats {
|
|
t.Errorf("Expected %#v, got %#v", udpstats, stats)
|
|
}
|
|
}
|
|
|
|
// https://github.com/docker/libcontainer/blob/v2.2.1/cgroups/fs/cpuacct.go#L19
|
|
const nanosecondsInSeconds = 1000000000
|
|
|
|
var clockTicks = uint64(system.GetClockTicks())
|
|
|
|
func TestMorePossibleCPUs(t *testing.T) {
|
|
realNumCPUs := uint32(8)
|
|
numCpusFunc = func() (uint32, error) {
|
|
return realNumCPUs, nil
|
|
}
|
|
possibleCPUs := uint32(31)
|
|
|
|
perCPUUsage := make([]uint64, possibleCPUs)
|
|
for i := uint32(0); i < realNumCPUs; i++ {
|
|
perCPUUsage[i] = 8562955455524
|
|
}
|
|
|
|
s := &cgroups.Stats{
|
|
CpuStats: cgroups.CpuStats{
|
|
CpuUsage: cgroups.CpuUsage{
|
|
PercpuUsage: perCPUUsage,
|
|
TotalUsage: 33802947350272,
|
|
UsageInKernelmode: 734746 * nanosecondsInSeconds / clockTicks,
|
|
UsageInUsermode: 2767637 * nanosecondsInSeconds / clockTicks,
|
|
},
|
|
},
|
|
}
|
|
var ret info.ContainerStats
|
|
setCPUStats(s, &ret, true)
|
|
|
|
expected := info.ContainerStats{
|
|
Cpu: info.CpuStats{
|
|
Usage: info.CpuUsage{
|
|
PerCpu: perCPUUsage[0:realNumCPUs],
|
|
User: s.CpuStats.CpuUsage.UsageInUsermode,
|
|
System: s.CpuStats.CpuUsage.UsageInKernelmode,
|
|
Total: 33802947350272,
|
|
},
|
|
},
|
|
}
|
|
|
|
if !ret.Eq(&expected) {
|
|
t.Fatalf("expected %+v == %+v", ret, expected)
|
|
}
|
|
}
|
|
|
|
func TestSetProcessesStats(t *testing.T) {
|
|
ret := info.ContainerStats{
|
|
Processes: info.ProcessStats{
|
|
ProcessCount: 1,
|
|
FdCount: 2,
|
|
},
|
|
}
|
|
s := &cgroups.Stats{
|
|
PidsStats: cgroups.PidsStats{
|
|
Current: 5,
|
|
Limit: 100,
|
|
},
|
|
}
|
|
setThreadsStats(s, &ret)
|
|
|
|
expected := info.ContainerStats{
|
|
|
|
Processes: info.ProcessStats{
|
|
ProcessCount: 1,
|
|
FdCount: 2,
|
|
ThreadsCurrent: s.PidsStats.Current,
|
|
ThreadsMax: s.PidsStats.Limit,
|
|
},
|
|
}
|
|
|
|
if expected.Processes.ProcessCount != ret.Processes.ProcessCount {
|
|
t.Fatalf("expected ProcessCount: %d == %d", ret.Processes.ProcessCount, expected.Processes.ProcessCount)
|
|
}
|
|
if expected.Processes.FdCount != ret.Processes.FdCount {
|
|
t.Fatalf("expected FdCount: %d == %d", ret.Processes.FdCount, expected.Processes.FdCount)
|
|
}
|
|
|
|
if expected.Processes.ThreadsCurrent != ret.Processes.ThreadsCurrent {
|
|
t.Fatalf("expected current threads: %d == %d", ret.Processes.ThreadsCurrent, expected.Processes.ThreadsCurrent)
|
|
}
|
|
if expected.Processes.ThreadsMax != ret.Processes.ThreadsMax {
|
|
t.Fatalf("expected max threads: %d == %d", ret.Processes.ThreadsMax, expected.Processes.ThreadsMax)
|
|
}
|
|
|
|
}
|
|
|
|
func TestParseLimitsFile(t *testing.T) {
|
|
var testData = []struct {
|
|
limitLine string
|
|
expected []info.UlimitSpec
|
|
}{
|
|
{
|
|
"Limit Soft Limit Hard Limit Units \n",
|
|
[]info.UlimitSpec{},
|
|
},
|
|
{
|
|
"Max open files 8192 8192 files \n",
|
|
[]info.UlimitSpec{{Name: "max_open_files", SoftLimit: 8192, HardLimit: 8192}},
|
|
},
|
|
{
|
|
"Max open files 85899345920 85899345920 files \n",
|
|
[]info.UlimitSpec{{Name: "max_open_files", SoftLimit: 85899345920, HardLimit: 85899345920}},
|
|
},
|
|
{
|
|
"Max open files gibberish1 8192 files \n",
|
|
[]info.UlimitSpec{},
|
|
},
|
|
{
|
|
"Max open files 8192 0xbaddata files \n",
|
|
[]info.UlimitSpec{},
|
|
},
|
|
{
|
|
"Max stack size 8192 8192 files \n",
|
|
[]info.UlimitSpec{},
|
|
},
|
|
}
|
|
|
|
for _, testItem := range testData {
|
|
actual := processLimitsFile(testItem.limitLine)
|
|
if reflect.DeepEqual(actual, testItem.expected) == false {
|
|
t.Fatalf("Parsed ulimit doesn't match expected values for line: %s", testItem.limitLine)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestReferencedBytesStat(t *testing.T) {
|
|
//overwrite package variables
|
|
smapsFilePathPattern = "testdata/smaps%d"
|
|
clearRefsFilePathPattern = "testdata/clear_refs%d"
|
|
|
|
pids := []int{4, 6, 8}
|
|
stat, err := referencedBytesStat(pids, 1, 3)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, uint64(416*1024), stat)
|
|
|
|
clearRefsFiles := []string{
|
|
"testdata/clear_refs4",
|
|
"testdata/clear_refs6",
|
|
"testdata/clear_refs8"}
|
|
|
|
//check if clear_refs files have proper values
|
|
assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[0]))
|
|
assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[1]))
|
|
assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[2]))
|
|
}
|
|
|
|
func TestReferencedBytesStatWhenNeverCleared(t *testing.T) {
|
|
//overwrite package variables
|
|
smapsFilePathPattern = "testdata/smaps%d"
|
|
clearRefsFilePathPattern = "testdata/clear_refs%d"
|
|
|
|
pids := []int{4, 6, 8}
|
|
stat, err := referencedBytesStat(pids, 1, 0)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, uint64(416*1024), stat)
|
|
|
|
clearRefsFiles := []string{
|
|
"testdata/clear_refs4",
|
|
"testdata/clear_refs6",
|
|
"testdata/clear_refs8"}
|
|
|
|
//check if clear_refs files have proper values
|
|
assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[0]))
|
|
assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[1]))
|
|
assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[2]))
|
|
}
|
|
|
|
func TestReferencedBytesStatWhenResetIsNeeded(t *testing.T) {
|
|
//overwrite package variables
|
|
smapsFilePathPattern = "testdata/smaps%d"
|
|
clearRefsFilePathPattern = "testdata/clear_refs%d"
|
|
|
|
pids := []int{4, 6, 8}
|
|
stat, err := referencedBytesStat(pids, 1, 1)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, uint64(416*1024), stat)
|
|
|
|
clearRefsFiles := []string{
|
|
"testdata/clear_refs4",
|
|
"testdata/clear_refs6",
|
|
"testdata/clear_refs8"}
|
|
|
|
//check if clear_refs files have proper values
|
|
assert.Equal(t, "1\n", getFileContent(t, clearRefsFiles[0]))
|
|
assert.Equal(t, "1\n", getFileContent(t, clearRefsFiles[1]))
|
|
assert.Equal(t, "1\n", getFileContent(t, clearRefsFiles[2]))
|
|
|
|
clearTestData(t, clearRefsFiles)
|
|
}
|
|
|
|
func TestGetReferencedKBytesWhenSmapsMissing(t *testing.T) {
|
|
//overwrite package variable
|
|
smapsFilePathPattern = "testdata/smaps%d"
|
|
|
|
pids := []int{10}
|
|
referenced, err := getReferencedKBytes(pids)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, uint64(0), referenced)
|
|
}
|
|
|
|
func TestClearReferencedBytesWhenClearRefsMissing(t *testing.T) {
|
|
//overwrite package variable
|
|
clearRefsFilePathPattern = "testdata/clear_refs%d"
|
|
|
|
pids := []int{10}
|
|
err := clearReferencedBytes(pids, 0, 1)
|
|
assert.Nil(t, err)
|
|
}
|