github.com/google/cadvisor@v0.49.1/info/v2/conversion_test.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package v2 16 17 import ( 18 "reflect" 19 "testing" 20 "time" 21 22 "github.com/stretchr/testify/assert" 23 24 v1 "github.com/google/cadvisor/info/v1" 25 ) 26 27 var ( 28 timestamp = time.Date(1987, time.August, 10, 0, 0, 0, 0, time.UTC) 29 labels = map[string]string{"foo": "bar"} 30 envs = map[string]string{"foo": "bar"} 31 ) 32 33 func TestContainerSpecFromV1(t *testing.T) { 34 v1Spec := v1.ContainerSpec{ 35 CreationTime: timestamp, 36 Labels: labels, 37 Envs: envs, 38 HasCpu: true, 39 Cpu: v1.CpuSpec{ 40 Limit: 2048, 41 MaxLimit: 4096, 42 Mask: "cpu_mask", 43 }, 44 HasMemory: true, 45 Memory: v1.MemorySpec{ 46 Limit: 2048, 47 Reservation: 1024, 48 SwapLimit: 8192, 49 }, 50 HasHugetlb: true, 51 HasNetwork: true, 52 HasProcesses: true, 53 HasFilesystem: true, 54 HasDiskIo: true, 55 HasCustomMetrics: true, 56 CustomMetrics: []v1.MetricSpec{{ 57 Name: "foo", 58 Type: v1.MetricGauge, 59 Format: v1.IntType, 60 Units: "bars", 61 }}, 62 Image: "gcr.io/kubernetes/kubernetes:v1", 63 } 64 65 aliases := []string{"baz", "oof"} 66 namespace := "foo_bar_baz" 67 68 expectedV2Spec := ContainerSpec{ 69 CreationTime: timestamp, 70 Labels: labels, 71 Envs: envs, 72 HasCpu: true, 73 Cpu: CpuSpec{ 74 Limit: 2048, 75 MaxLimit: 4096, 76 Mask: "cpu_mask", 77 }, 78 HasMemory: true, 79 Memory: MemorySpec{ 80 Limit: 2048, 81 Reservation: 1024, 82 SwapLimit: 8192, 83 }, 84 HasHugetlb: true, 85 HasNetwork: true, 86 HasProcesses: true, 87 HasFilesystem: true, 88 HasDiskIo: true, 89 HasCustomMetrics: true, 90 CustomMetrics: []v1.MetricSpec{{ 91 Name: "foo", 92 Type: v1.MetricGauge, 93 Format: v1.IntType, 94 Units: "bars", 95 }}, 96 Image: "gcr.io/kubernetes/kubernetes:v1", 97 Aliases: aliases, 98 Namespace: namespace, 99 } 100 101 v2Spec := ContainerSpecFromV1(&v1Spec, aliases, namespace) 102 if !reflect.DeepEqual(v2Spec, expectedV2Spec) { 103 t.Errorf("Converted spec differs from expectation!\nExpected: %+v\n Got: %+v\n", expectedV2Spec, v2Spec) 104 } 105 } 106 107 func TestContainerStatsFromV1(t *testing.T) { 108 v1Spec := v1.ContainerSpec{ 109 CreationTime: timestamp, 110 Labels: labels, 111 HasCpu: true, 112 Cpu: v1.CpuSpec{ 113 Limit: 2048, 114 MaxLimit: 4096, 115 Mask: "cpu_mask", 116 }, 117 HasMemory: true, 118 Memory: v1.MemorySpec{ 119 Limit: 2048, 120 Reservation: 1024, 121 SwapLimit: 8192, 122 }, 123 HasHugetlb: true, 124 HasNetwork: true, 125 HasProcesses: true, 126 HasFilesystem: true, 127 HasDiskIo: true, 128 HasCustomMetrics: true, 129 CustomMetrics: []v1.MetricSpec{{ 130 Name: "foo", 131 Type: v1.MetricGauge, 132 Format: v1.IntType, 133 Units: "bars", 134 }}, 135 Image: "gcr.io/kubernetes/kubernetes:v1", 136 } 137 v1Stats := v1.ContainerStats{ 138 Timestamp: timestamp, 139 Memory: v1.MemoryStats{ 140 Usage: 1, 141 Cache: 2, 142 RSS: 3, 143 WorkingSet: 4, 144 Failcnt: 5, 145 ContainerData: v1.MemoryStatsMemoryData{ 146 Pgfault: 1, 147 Pgmajfault: 2, 148 }, 149 HierarchicalData: v1.MemoryStatsMemoryData{ 150 Pgfault: 10, 151 Pgmajfault: 20, 152 }, 153 }, 154 Network: v1.NetworkStats{ 155 InterfaceStats: v1.InterfaceStats{ 156 Name: "", 157 RxBytes: 1, 158 RxPackets: 2, 159 RxErrors: 3, 160 RxDropped: 4, 161 TxBytes: 5, 162 TxPackets: 6, 163 TxErrors: 7, 164 TxDropped: 8, 165 }, 166 Interfaces: []v1.InterfaceStats{{ 167 Name: "eth0", 168 RxBytes: 10, 169 RxPackets: 20, 170 RxErrors: 30, 171 RxDropped: 40, 172 TxBytes: 50, 173 TxPackets: 60, 174 TxErrors: 70, 175 TxDropped: 80, 176 }}, 177 }, 178 Processes: v1.ProcessStats{ 179 ProcessCount: 5, 180 FdCount: 1, 181 ThreadsCurrent: 66, 182 ThreadsMax: 6000, 183 }, 184 Filesystem: []v1.FsStats{{ 185 Device: "dev0", 186 Limit: 500, 187 Usage: 100, 188 BaseUsage: 50, 189 Available: 300, 190 InodesFree: 100, 191 }}, 192 Accelerators: []v1.AcceleratorStats{{ 193 Make: "nvidia", 194 Model: "tesla-p100", 195 ID: "GPU-deadbeef-1234-5678-90ab-feedfacecafe", 196 MemoryTotal: 20304050607, 197 MemoryUsed: 2030405060, 198 DutyCycle: 12, 199 }}, 200 PerfStats: []v1.PerfStat{ 201 { 202 PerfValue: v1.PerfValue{ 203 ScalingRatio: 1, 204 Value: 123, 205 Name: "instructions", 206 }, 207 }, 208 { 209 PerfValue: v1.PerfValue{ 210 ScalingRatio: 0.3333333, 211 Value: 123456, 212 Name: "cycles", 213 }, 214 }, 215 }, 216 PerfUncoreStats: []v1.PerfUncoreStat{ 217 { 218 PerfValue: v1.PerfValue{ 219 ScalingRatio: 1.0, 220 Value: 123456, 221 Name: "uncore_imc_0/cas_count_write", 222 }, 223 Socket: 0, 224 PMU: "17", 225 }, 226 { 227 PerfValue: v1.PerfValue{ 228 ScalingRatio: 1.0, 229 Value: 654321, 230 Name: "uncore_imc_0/cas_count_write", 231 }, 232 Socket: 1, 233 PMU: "17", 234 }, 235 }, 236 ReferencedMemory: uint64(1234), 237 Resctrl: v1.ResctrlStats{ 238 MemoryBandwidth: []v1.MemoryBandwidthStats{ 239 { 240 TotalBytes: 72312331, 241 LocalBytes: 1233311, 242 }, 243 { 244 TotalBytes: 32312331, 245 LocalBytes: 2233311, 246 }, 247 }, 248 Cache: []v1.CacheStats{ 249 { 250 LLCOccupancy: 123123441, 251 }, 252 { 253 LLCOccupancy: 123313111, 254 }, 255 }, 256 }, 257 } 258 expectedV2Stats := ContainerStats{ 259 Timestamp: timestamp, 260 Cpu: &v1Stats.Cpu, 261 DiskIo: &v1Stats.DiskIo, 262 Memory: &v1Stats.Memory, 263 Hugetlb: &v1Stats.Hugetlb, 264 Processes: &v1Stats.Processes, 265 Network: &NetworkStats{ 266 Interfaces: v1Stats.Network.Interfaces, 267 }, 268 Filesystem: &FilesystemStats{ 269 TotalUsageBytes: &v1Stats.Filesystem[0].Usage, 270 BaseUsageBytes: &v1Stats.Filesystem[0].BaseUsage, 271 InodeUsage: &v1Stats.Filesystem[0].Inodes, 272 }, 273 Accelerators: v1Stats.Accelerators, 274 PerfStats: v1Stats.PerfStats, 275 PerfUncoreStats: v1Stats.PerfUncoreStats, 276 ReferencedMemory: v1Stats.ReferencedMemory, 277 Resctrl: v1Stats.Resctrl, 278 } 279 280 v2Stats := ContainerStatsFromV1("test", &v1Spec, []*v1.ContainerStats{&v1Stats}) 281 actualV2Stats := *v2Stats[0] 282 283 if !reflect.DeepEqual(expectedV2Stats, actualV2Stats) { 284 t.Errorf("Converted stats differs from expectation!\nExpected: %+v\n Got: %+v\n", expectedV2Stats, actualV2Stats) 285 } 286 } 287 288 func TestInstCpuStats(t *testing.T) { 289 tests := []struct { 290 last *v1.ContainerStats 291 cur *v1.ContainerStats 292 want *CpuInstStats 293 }{ 294 // Last is missing 295 { 296 nil, 297 &v1.ContainerStats{}, 298 nil, 299 }, 300 // Goes back in time 301 { 302 &v1.ContainerStats{ 303 Timestamp: time.Unix(100, 0).Add(time.Second), 304 }, 305 &v1.ContainerStats{ 306 Timestamp: time.Unix(100, 0), 307 }, 308 nil, 309 }, 310 // Zero time delta 311 { 312 &v1.ContainerStats{ 313 Timestamp: time.Unix(100, 0), 314 }, 315 &v1.ContainerStats{ 316 Timestamp: time.Unix(100, 0), 317 }, 318 nil, 319 }, 320 // Different number of cpus 321 { 322 &v1.ContainerStats{ 323 Timestamp: time.Unix(100, 0), 324 Cpu: v1.CpuStats{ 325 Usage: v1.CpuUsage{ 326 PerCpu: []uint64{100, 200}, 327 }, 328 }, 329 }, 330 &v1.ContainerStats{ 331 Timestamp: time.Unix(100, 0).Add(time.Second), 332 Cpu: v1.CpuStats{ 333 Usage: v1.CpuUsage{ 334 PerCpu: []uint64{100, 200, 300}, 335 }, 336 }, 337 }, 338 nil, 339 }, 340 // Stat numbers decrease 341 { 342 &v1.ContainerStats{ 343 Timestamp: time.Unix(100, 0), 344 Cpu: v1.CpuStats{ 345 Usage: v1.CpuUsage{ 346 Total: 300, 347 PerCpu: []uint64{100, 200}, 348 User: 250, 349 System: 50, 350 }, 351 }, 352 }, 353 &v1.ContainerStats{ 354 Timestamp: time.Unix(100, 0).Add(time.Second), 355 Cpu: v1.CpuStats{ 356 Usage: v1.CpuUsage{ 357 Total: 200, 358 PerCpu: []uint64{100, 100}, 359 User: 150, 360 System: 50, 361 }, 362 }, 363 }, 364 nil, 365 }, 366 // One second elapsed 367 { 368 &v1.ContainerStats{ 369 Timestamp: time.Unix(100, 0), 370 Cpu: v1.CpuStats{ 371 Usage: v1.CpuUsage{ 372 Total: 300, 373 PerCpu: []uint64{100, 200}, 374 User: 250, 375 System: 50, 376 }, 377 }, 378 }, 379 &v1.ContainerStats{ 380 Timestamp: time.Unix(100, 0).Add(time.Second), 381 Cpu: v1.CpuStats{ 382 Usage: v1.CpuUsage{ 383 Total: 500, 384 PerCpu: []uint64{200, 300}, 385 User: 400, 386 System: 100, 387 }, 388 }, 389 }, 390 &CpuInstStats{ 391 Usage: CpuInstUsage{ 392 Total: 200, 393 PerCpu: []uint64{100, 100}, 394 User: 150, 395 System: 50, 396 }, 397 }, 398 }, 399 // Two seconds elapsed 400 { 401 &v1.ContainerStats{ 402 Timestamp: time.Unix(100, 0), 403 Cpu: v1.CpuStats{ 404 Usage: v1.CpuUsage{ 405 Total: 300, 406 PerCpu: []uint64{100, 200}, 407 User: 250, 408 System: 50, 409 }, 410 }, 411 }, 412 &v1.ContainerStats{ 413 Timestamp: time.Unix(100, 0).Add(2 * time.Second), 414 Cpu: v1.CpuStats{ 415 Usage: v1.CpuUsage{ 416 Total: 500, 417 PerCpu: []uint64{200, 300}, 418 User: 400, 419 System: 100, 420 }, 421 }, 422 }, 423 &CpuInstStats{ 424 Usage: CpuInstUsage{ 425 Total: 100, 426 PerCpu: []uint64{50, 50}, 427 User: 75, 428 System: 25, 429 }, 430 }, 431 }, 432 } 433 for _, c := range tests { 434 got, err := InstCpuStats(c.last, c.cur) 435 if err != nil { 436 if c.want == nil { 437 continue 438 } 439 t.Errorf("Unexpected error: %v", err) 440 } 441 assert.Equal(t, c.want, got) 442 } 443 }