github.com/google/cadvisor@v0.49.1/container/libcontainer/handler_test.go (about) 1 // Copyright 2018 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 libcontainer 16 17 import ( 18 "os" 19 "reflect" 20 "testing" 21 22 "github.com/opencontainers/runc/libcontainer/cgroups" 23 "github.com/stretchr/testify/assert" 24 25 info "github.com/google/cadvisor/info/v1" 26 ) 27 28 func TestScanInterfaceStats(t *testing.T) { 29 stats, err := scanInterfaceStats("testdata/procnetdev") 30 if err != nil { 31 t.Error(err) 32 } 33 34 netdevstats := []info.InterfaceStats{ 35 { 36 Name: "wlp4s0", 37 RxBytes: 1, 38 RxPackets: 2, 39 RxErrors: 3, 40 RxDropped: 4, 41 TxBytes: 9, 42 TxPackets: 10, 43 TxErrors: 11, 44 TxDropped: 12, 45 }, 46 { 47 Name: "em1", 48 RxBytes: 315849, 49 RxPackets: 1172, 50 RxErrors: 0, 51 RxDropped: 0, 52 TxBytes: 315850, 53 TxPackets: 1173, 54 TxErrors: 0, 55 TxDropped: 0, 56 }, 57 } 58 59 if len(stats) != len(netdevstats) { 60 t.Errorf("Expected 2 net stats, got %d", len(stats)) 61 } 62 63 for i, v := range netdevstats { 64 if v != stats[i] { 65 t.Errorf("Expected %#v, got %#v", v, stats[i]) 66 } 67 } 68 } 69 70 func TestScanUDPStats(t *testing.T) { 71 udpStatsFile := "testdata/procnetudp" 72 r, err := os.Open(udpStatsFile) 73 if err != nil { 74 t.Errorf("failure opening %s: %v", udpStatsFile, err) 75 } 76 77 stats, err := scanUDPStats(r) 78 if err != nil { 79 t.Error(err) 80 } 81 82 udpstats := info.UdpStat{ 83 Listen: 2, 84 Dropped: 4, 85 RxQueued: 10, 86 TxQueued: 11, 87 } 88 89 if stats != udpstats { 90 t.Errorf("Expected %#v, got %#v", udpstats, stats) 91 } 92 } 93 94 // https://github.com/docker/libcontainer/blob/v2.2.1/cgroups/fs/cpuacct.go#L19 95 const nanosecondsInSeconds = 1000000000 96 97 // https://github.com/containerd/cgroups/pull/12 98 const clockTicks = 100 99 100 func TestSetCPUStats(t *testing.T) { 101 perCPUUsage := make([]uint64, 31) 102 for i := uint32(0); i < 31; i++ { 103 perCPUUsage[i] = 8562955455524 104 } 105 s := &cgroups.Stats{ 106 CpuStats: cgroups.CpuStats{ 107 CpuUsage: cgroups.CpuUsage{ 108 PercpuUsage: perCPUUsage, 109 TotalUsage: 33802947350272, 110 UsageInKernelmode: 734746 * nanosecondsInSeconds / clockTicks, 111 UsageInUsermode: 2767637 * nanosecondsInSeconds / clockTicks, 112 }, 113 }, 114 } 115 var ret info.ContainerStats 116 setCPUStats(s, &ret, true) 117 118 expected := info.ContainerStats{ 119 Cpu: info.CpuStats{ 120 Usage: info.CpuUsage{ 121 PerCpu: perCPUUsage, 122 User: s.CpuStats.CpuUsage.UsageInUsermode, 123 System: s.CpuStats.CpuUsage.UsageInKernelmode, 124 Total: 33802947350272, 125 }, 126 }, 127 } 128 129 if !ret.Eq(&expected) { 130 t.Fatalf("expected %+v == %+v", ret, expected) 131 } 132 } 133 134 func TestSetProcessesStats(t *testing.T) { 135 ret := info.ContainerStats{ 136 Processes: info.ProcessStats{ 137 ProcessCount: 1, 138 FdCount: 2, 139 }, 140 } 141 s := &cgroups.Stats{ 142 PidsStats: cgroups.PidsStats{ 143 Current: 5, 144 Limit: 100, 145 }, 146 } 147 setThreadsStats(s, &ret) 148 149 expected := info.ContainerStats{ 150 151 Processes: info.ProcessStats{ 152 ProcessCount: 1, 153 FdCount: 2, 154 ThreadsCurrent: s.PidsStats.Current, 155 ThreadsMax: s.PidsStats.Limit, 156 }, 157 } 158 159 if expected.Processes.ProcessCount != ret.Processes.ProcessCount { 160 t.Fatalf("expected ProcessCount: %d == %d", ret.Processes.ProcessCount, expected.Processes.ProcessCount) 161 } 162 if expected.Processes.FdCount != ret.Processes.FdCount { 163 t.Fatalf("expected FdCount: %d == %d", ret.Processes.FdCount, expected.Processes.FdCount) 164 } 165 166 if expected.Processes.ThreadsCurrent != ret.Processes.ThreadsCurrent { 167 t.Fatalf("expected current threads: %d == %d", ret.Processes.ThreadsCurrent, expected.Processes.ThreadsCurrent) 168 } 169 if expected.Processes.ThreadsMax != ret.Processes.ThreadsMax { 170 t.Fatalf("expected max threads: %d == %d", ret.Processes.ThreadsMax, expected.Processes.ThreadsMax) 171 } 172 } 173 174 func TestParseLimitsFile(t *testing.T) { 175 testData := []struct { 176 limitLine string 177 expected []info.UlimitSpec 178 }{ 179 { 180 "Limit Soft Limit Hard Limit Units \n", 181 []info.UlimitSpec{}, 182 }, 183 { 184 "Max open files 8192 8192 files \n", 185 []info.UlimitSpec{{Name: "max_open_files", SoftLimit: 8192, HardLimit: 8192}}, 186 }, 187 { 188 "Max open files 85899345920 85899345920 files \n", 189 []info.UlimitSpec{{Name: "max_open_files", SoftLimit: 85899345920, HardLimit: 85899345920}}, 190 }, 191 { 192 "Max open files gibberish1 8192 files \n", 193 []info.UlimitSpec{}, 194 }, 195 { 196 "Max open files 8192 0xbaddata files \n", 197 []info.UlimitSpec{}, 198 }, 199 { 200 "Max stack size 8192 8192 files \n", 201 []info.UlimitSpec{}, 202 }, 203 } 204 205 for _, testItem := range testData { 206 actual := processLimitsFile(testItem.limitLine) 207 if reflect.DeepEqual(actual, testItem.expected) == false { 208 t.Fatalf("Parsed ulimit doesn't match expected values for line: %s", testItem.limitLine) 209 } 210 } 211 } 212 213 func TestReferencedBytesStat(t *testing.T) { 214 // overwrite package variables 215 smapsFilePathPattern = "testdata/smaps%d" 216 clearRefsFilePathPattern = "testdata/clear_refs%d" 217 218 pids := []int{4, 6, 8} 219 stat, err := referencedBytesStat(pids, 1, 3) 220 assert.Nil(t, err) 221 assert.Equal(t, uint64(416*1024), stat) 222 223 clearRefsFiles := []string{ 224 "testdata/clear_refs4", 225 "testdata/clear_refs6", 226 "testdata/clear_refs8", 227 } 228 229 // check if clear_refs files have proper values 230 assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[0])) 231 assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[1])) 232 assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[2])) 233 } 234 235 func TestReferencedBytesStatWhenNeverCleared(t *testing.T) { 236 // overwrite package variables 237 smapsFilePathPattern = "testdata/smaps%d" 238 clearRefsFilePathPattern = "testdata/clear_refs%d" 239 240 pids := []int{4, 6, 8} 241 stat, err := referencedBytesStat(pids, 1, 0) 242 assert.Nil(t, err) 243 assert.Equal(t, uint64(416*1024), stat) 244 245 clearRefsFiles := []string{ 246 "testdata/clear_refs4", 247 "testdata/clear_refs6", 248 "testdata/clear_refs8", 249 } 250 251 // check if clear_refs files have proper values 252 assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[0])) 253 assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[1])) 254 assert.Equal(t, "0\n", getFileContent(t, clearRefsFiles[2])) 255 } 256 257 func TestReferencedBytesStatWhenResetIsNeeded(t *testing.T) { 258 // overwrite package variables 259 smapsFilePathPattern = "testdata/smaps%d" 260 clearRefsFilePathPattern = "testdata/clear_refs%d" 261 262 pids := []int{4, 6, 8} 263 stat, err := referencedBytesStat(pids, 1, 1) 264 assert.Nil(t, err) 265 assert.Equal(t, uint64(416*1024), stat) 266 267 clearRefsFiles := []string{ 268 "testdata/clear_refs4", 269 "testdata/clear_refs6", 270 "testdata/clear_refs8", 271 } 272 273 // check if clear_refs files have proper values 274 assert.Equal(t, "1\n", getFileContent(t, clearRefsFiles[0])) 275 assert.Equal(t, "1\n", getFileContent(t, clearRefsFiles[1])) 276 assert.Equal(t, "1\n", getFileContent(t, clearRefsFiles[2])) 277 278 clearTestData(t, clearRefsFiles) 279 } 280 281 func TestGetReferencedKBytesWhenSmapsMissing(t *testing.T) { 282 // overwrite package variable 283 smapsFilePathPattern = "testdata/smaps%d" 284 285 pids := []int{10} 286 referenced, err := getReferencedKBytes(pids) 287 assert.Nil(t, err) 288 assert.Equal(t, uint64(0), referenced) 289 } 290 291 func TestClearReferencedBytesWhenClearRefsMissing(t *testing.T) { 292 // overwrite package variable 293 clearRefsFilePathPattern = "testdata/clear_refs%d" 294 295 pids := []int{10} 296 err := clearReferencedBytes(pids, 0, 1) 297 assert.Nil(t, err) 298 } 299 300 var ulimits []info.UlimitSpec 301 302 func BenchmarkProcessLimitsFile(b *testing.B) { 303 content, err := os.ReadFile("testdata/limits") 304 assert.Nil(b, err) 305 306 b.ResetTimer() 307 for i := 0; i < b.N; i++ { 308 ulimits = processLimitsFile(string(content)) 309 } 310 311 // Ensure the compiler doesn't optimize away the benchmark 312 _ = ulimits 313 } 314 315 func TestProcessMaxOpenFileLimitLine(t *testing.T) { 316 line := " 1073741816 1073741816 files " 317 318 ulimit, err := processMaxOpenFileLimitLine("max_open_files", line) 319 assert.Nil(t, err) 320 assert.Equal(t, "max_open_files", ulimit.Name) 321 assert.Equal(t, int64(1073741816), ulimit.SoftLimit) 322 assert.Equal(t, int64(1073741816), ulimit.HardLimit) 323 }