// Copyright 2016 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 v2 import ( "reflect" "testing" "time" "github.com/google/cadvisor/info/v1" "github.com/stretchr/testify/assert" ) var ( timestamp = time.Date(1987, time.August, 10, 0, 0, 0, 0, time.UTC) labels = map[string]string{"foo": "bar"} ) func TestContanierSpecFromV1(t *testing.T) { v1Spec := v1.ContainerSpec{ CreationTime: timestamp, Labels: labels, HasCpu: true, Cpu: v1.CpuSpec{ Limit: 2048, MaxLimit: 4096, Mask: "cpu_mask", }, HasMemory: true, Memory: v1.MemorySpec{ Limit: 2048, Reservation: 1024, SwapLimit: 8192, }, HasNetwork: true, HasFilesystem: true, HasDiskIo: true, HasCustomMetrics: true, CustomMetrics: []v1.MetricSpec{{ Name: "foo", Type: v1.MetricGauge, Format: v1.IntType, Units: "bars", }}, Image: "gcr.io/kubernetes/kubernetes:v1", } aliases := []string{"baz", "oof"} namespace := "foo_bar_baz" expectedV2Spec := ContainerSpec{ CreationTime: timestamp, Labels: labels, HasCpu: true, Cpu: CpuSpec{ Limit: 2048, MaxLimit: 4096, Mask: "cpu_mask", }, HasMemory: true, Memory: MemorySpec{ Limit: 2048, Reservation: 1024, SwapLimit: 8192, }, HasNetwork: true, HasFilesystem: true, HasDiskIo: true, HasCustomMetrics: true, CustomMetrics: []v1.MetricSpec{{ Name: "foo", Type: v1.MetricGauge, Format: v1.IntType, Units: "bars", }}, Image: "gcr.io/kubernetes/kubernetes:v1", Aliases: aliases, Namespace: namespace, } v2Spec := ContainerSpecFromV1(&v1Spec, aliases, namespace) if !reflect.DeepEqual(v2Spec, expectedV2Spec) { t.Errorf("Converted spec differs from expectation!\nExpected: %+v\n Got: %+v\n", expectedV2Spec, v2Spec) } } func TestContainerStatsFromV1(t *testing.T) { v1Spec := v1.ContainerSpec{ CreationTime: timestamp, Labels: labels, HasCpu: true, Cpu: v1.CpuSpec{ Limit: 2048, MaxLimit: 4096, Mask: "cpu_mask", }, HasMemory: true, Memory: v1.MemorySpec{ Limit: 2048, Reservation: 1024, SwapLimit: 8192, }, HasNetwork: true, HasFilesystem: true, HasDiskIo: true, HasCustomMetrics: true, CustomMetrics: []v1.MetricSpec{{ Name: "foo", Type: v1.MetricGauge, Format: v1.IntType, Units: "bars", }}, Image: "gcr.io/kubernetes/kubernetes:v1", } v1Stats := v1.ContainerStats{ Timestamp: timestamp, Memory: v1.MemoryStats{ Usage: 1, Cache: 2, RSS: 3, WorkingSet: 4, Failcnt: 5, ContainerData: v1.MemoryStatsMemoryData{ Pgfault: 1, Pgmajfault: 2, }, HierarchicalData: v1.MemoryStatsMemoryData{ Pgfault: 10, Pgmajfault: 20, }, }, Network: v1.NetworkStats{ InterfaceStats: v1.InterfaceStats{ Name: "", RxBytes: 1, RxPackets: 2, RxErrors: 3, RxDropped: 4, TxBytes: 5, TxPackets: 6, TxErrors: 7, TxDropped: 8, }, Interfaces: []v1.InterfaceStats{{ Name: "eth0", RxBytes: 10, RxPackets: 20, RxErrors: 30, RxDropped: 40, TxBytes: 50, TxPackets: 60, TxErrors: 70, TxDropped: 80, }}, }, Filesystem: []v1.FsStats{{ Device: "dev0", Limit: 500, Usage: 100, BaseUsage: 50, Available: 300, InodesFree: 100, }}, } expectedV2Stats := ContainerStats{ Timestamp: timestamp, Cpu: &v1Stats.Cpu, DiskIo: &v1Stats.DiskIo, Memory: &v1Stats.Memory, Network: &NetworkStats{ Interfaces: v1Stats.Network.Interfaces, }, Filesystem: &FilesystemStats{ TotalUsageBytes: &v1Stats.Filesystem[0].Usage, BaseUsageBytes: &v1Stats.Filesystem[0].BaseUsage, }, } v2Stats := ContainerStatsFromV1(&v1Spec, []*v1.ContainerStats{&v1Stats}) actualV2Stats := *v2Stats[0] if !reflect.DeepEqual(expectedV2Stats, actualV2Stats) { t.Errorf("Converted stats differs from expectation!\nExpected: %+v\n Got: %+v\n", expectedV2Stats, actualV2Stats) } } func TestInstCpuStats(t *testing.T) { tests := []struct { last *v1.ContainerStats cur *v1.ContainerStats want *CpuInstStats }{ // Last is missing { nil, &v1.ContainerStats{}, nil, }, // Goes back in time { &v1.ContainerStats{ Timestamp: time.Unix(100, 0).Add(time.Second), }, &v1.ContainerStats{ Timestamp: time.Unix(100, 0), }, nil, }, // Zero time delta { &v1.ContainerStats{ Timestamp: time.Unix(100, 0), }, &v1.ContainerStats{ Timestamp: time.Unix(100, 0), }, nil, }, // Unexpectedly small time delta { &v1.ContainerStats{ Timestamp: time.Unix(100, 0), }, &v1.ContainerStats{ Timestamp: time.Unix(100, 0).Add(30 * time.Millisecond), }, nil, }, // Different number of cpus { &v1.ContainerStats{ Timestamp: time.Unix(100, 0), Cpu: v1.CpuStats{ Usage: v1.CpuUsage{ PerCpu: []uint64{100, 200}, }, }, }, &v1.ContainerStats{ Timestamp: time.Unix(100, 0).Add(time.Second), Cpu: v1.CpuStats{ Usage: v1.CpuUsage{ PerCpu: []uint64{100, 200, 300}, }, }, }, nil, }, // Stat numbers decrease { &v1.ContainerStats{ Timestamp: time.Unix(100, 0), Cpu: v1.CpuStats{ Usage: v1.CpuUsage{ Total: 300, PerCpu: []uint64{100, 200}, User: 250, System: 50, }, }, }, &v1.ContainerStats{ Timestamp: time.Unix(100, 0).Add(time.Second), Cpu: v1.CpuStats{ Usage: v1.CpuUsage{ Total: 200, PerCpu: []uint64{100, 100}, User: 150, System: 50, }, }, }, nil, }, // One second elapsed { &v1.ContainerStats{ Timestamp: time.Unix(100, 0), Cpu: v1.CpuStats{ Usage: v1.CpuUsage{ Total: 300, PerCpu: []uint64{100, 200}, User: 250, System: 50, }, }, }, &v1.ContainerStats{ Timestamp: time.Unix(100, 0).Add(time.Second), Cpu: v1.CpuStats{ Usage: v1.CpuUsage{ Total: 500, PerCpu: []uint64{200, 300}, User: 400, System: 100, }, }, }, &CpuInstStats{ Usage: CpuInstUsage{ Total: 200, PerCpu: []uint64{100, 100}, User: 150, System: 50, }, }, }, // Two seconds elapsed { &v1.ContainerStats{ Timestamp: time.Unix(100, 0), Cpu: v1.CpuStats{ Usage: v1.CpuUsage{ Total: 300, PerCpu: []uint64{100, 200}, User: 250, System: 50, }, }, }, &v1.ContainerStats{ Timestamp: time.Unix(100, 0).Add(2 * time.Second), Cpu: v1.CpuStats{ Usage: v1.CpuUsage{ Total: 500, PerCpu: []uint64{200, 300}, User: 400, System: 100, }, }, }, &CpuInstStats{ Usage: CpuInstUsage{ Total: 100, PerCpu: []uint64{50, 50}, User: 75, System: 25, }, }, }, } for _, c := range tests { got, err := InstCpuStats(c.last, c.cur) if err != nil { if c.want == nil { continue } t.Errorf("Unexpected error: %v", err) } assert.Equal(t, c.want, got) } }