github.com/google/cadvisor@v0.49.1/container/common/helpers_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 common
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"math"
    21  	"os"
    22  	"path/filepath"
    23  	"reflect"
    24  	"testing"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  
    28  	"github.com/google/cadvisor/container"
    29  	info "github.com/google/cadvisor/info/v1"
    30  	v2 "github.com/google/cadvisor/info/v2"
    31  )
    32  
    33  func BenchmarkListDirectories(b *testing.B) {
    34  	for i := 0; i < b.N; i++ {
    35  		output := make(map[string]struct{})
    36  		if err := ListDirectories("/sys/fs/cgroup", "", true, output); err != nil {
    37  			b.Fatal(err)
    38  		}
    39  	}
    40  }
    41  
    42  func TestConvertCpuWeightToCpuLimit(t *testing.T) {
    43  	limit, err := convertCPUWeightToCPULimit(1)
    44  	if err != nil {
    45  		t.Fatalf("Error in convertCPUWeightToCPULimit: %s", err)
    46  	}
    47  	if limit != 2 {
    48  		t.Fatalf("convertCPUWeightToCPULimit(1) != 2")
    49  	}
    50  	limit, err = convertCPUWeightToCPULimit(10000)
    51  	if err != nil {
    52  		t.Fatalf("Error in convertCPUWeightToCPULimit: %s", err)
    53  	}
    54  	if limit != 262144 {
    55  		t.Fatalf("convertCPUWeightToCPULimit(10000) != 262144")
    56  	}
    57  	_, err = convertCPUWeightToCPULimit(0)
    58  	if err == nil {
    59  		t.Fatalf("convertCPUWeightToCPULimit(0) must raise an error")
    60  	}
    61  	_, err = convertCPUWeightToCPULimit(10001)
    62  	if err == nil {
    63  		t.Fatalf("convertCPUWeightToCPULimit(10001) must raise an error")
    64  	}
    65  }
    66  
    67  func TestParseUint64String(t *testing.T) {
    68  	if parseUint64String("1000") != 1000 {
    69  		t.Fatalf("parseUint64String(\"1000\") != 1000")
    70  	}
    71  	if parseUint64String("-1") != 0 {
    72  		t.Fatalf("parseUint64String(\"-1\") != 0")
    73  	}
    74  	if parseUint64String("0") != 0 {
    75  		t.Fatalf("parseUint64String(\"0\") != 0")
    76  	}
    77  	if parseUint64String("not-a-number") != 0 {
    78  		t.Fatalf("parseUint64String(\"not-a-number\") != 0")
    79  	}
    80  	if parseUint64String(" 1000 ") != 0 {
    81  		t.Fatalf("parseUint64String(\" 1000 \") != 0")
    82  	}
    83  	if parseUint64String("18446744073709551615") != 18446744073709551615 {
    84  		t.Fatalf("parseUint64String(\"18446744073709551615\") != 18446744073709551615")
    85  	}
    86  }
    87  
    88  type mockInfoProvider struct {
    89  	options v2.RequestOptions
    90  }
    91  
    92  func (m *mockInfoProvider) GetRequestedContainersInfo(containerName string, options v2.RequestOptions) (map[string]*info.ContainerInfo, error) {
    93  	m.options = options
    94  	return map[string]*info.ContainerInfo{}, nil
    95  }
    96  
    97  func (m *mockInfoProvider) GetVersionInfo() (*info.VersionInfo, error) {
    98  	return nil, errors.New("not supported")
    99  }
   100  
   101  func (m *mockInfoProvider) GetMachineInfo() (*info.MachineInfo, error) {
   102  	return &info.MachineInfo{
   103  		NumCores: 7,
   104  	}, nil
   105  }
   106  
   107  func TestGetSpecCgroupV1(t *testing.T) {
   108  	root, err := os.Getwd()
   109  	if err != nil {
   110  		t.Fatalf("getwd: %s", err)
   111  	}
   112  
   113  	cgroupPaths := map[string]string{
   114  		"memory": filepath.Join(root, "test_resources/cgroup_v1/test1/memory"),
   115  		"cpu":    filepath.Join(root, "test_resources/cgroup_v1/test1/cpu"),
   116  		"cpuset": filepath.Join(root, "test_resources/cgroup_v1/test1/cpuset"),
   117  		"pids":   filepath.Join(root, "test_resources/cgroup_v1/test1/pids"),
   118  	}
   119  
   120  	spec, err := getSpecInternal(cgroupPaths, &mockInfoProvider{}, false, false, false)
   121  	assert.Nil(t, err)
   122  
   123  	assert.True(t, spec.HasMemory)
   124  	assert.EqualValues(t, spec.Memory.Limit, 123456789)
   125  	assert.EqualValues(t, spec.Memory.SwapLimit, 13579)
   126  	assert.EqualValues(t, spec.Memory.Reservation, 24680)
   127  
   128  	assert.True(t, spec.HasCpu)
   129  	assert.EqualValues(t, spec.Cpu.Limit, 1025)
   130  	assert.EqualValues(t, spec.Cpu.Period, 100010)
   131  	assert.EqualValues(t, spec.Cpu.Quota, 20000)
   132  
   133  	assert.EqualValues(t, spec.Cpu.Mask, "0-5")
   134  
   135  	assert.True(t, spec.HasProcesses)
   136  	assert.EqualValues(t, spec.Processes.Limit, 1027)
   137  
   138  	assert.False(t, spec.HasHugetlb)
   139  	assert.False(t, spec.HasDiskIo)
   140  }
   141  
   142  func TestGetSpecCgroupV2(t *testing.T) {
   143  	root, err := os.Getwd()
   144  	if err != nil {
   145  		t.Fatalf("getwd: %s", err)
   146  	}
   147  
   148  	cgroupPaths := map[string]string{
   149  		"": filepath.Join(root, "test_resources/cgroup_v2/test1"),
   150  	}
   151  
   152  	spec, err := getSpecInternal(cgroupPaths, &mockInfoProvider{}, false, false, true)
   153  	assert.Nil(t, err)
   154  
   155  	assert.True(t, spec.HasMemory)
   156  	assert.EqualValues(t, spec.Memory.Limit, 123456789)
   157  	assert.EqualValues(t, spec.Memory.SwapLimit, 13579)
   158  	assert.EqualValues(t, spec.Memory.Reservation, 24680)
   159  
   160  	assert.True(t, spec.HasCpu)
   161  	assert.EqualValues(t, spec.Cpu.Limit, 1286)
   162  	assert.EqualValues(t, spec.Cpu.Period, 100010)
   163  	assert.EqualValues(t, spec.Cpu.Quota, 20000)
   164  
   165  	assert.EqualValues(t, spec.Cpu.Mask, "0-5")
   166  
   167  	assert.True(t, spec.HasProcesses)
   168  	assert.EqualValues(t, spec.Processes.Limit, 1027)
   169  
   170  	assert.False(t, spec.HasHugetlb)
   171  	assert.True(t, spec.HasDiskIo)
   172  }
   173  
   174  func TestGetSpecCgroupV2Max(t *testing.T) {
   175  	root, err := os.Getwd()
   176  	assert.Nil(t, err)
   177  
   178  	cgroupPaths := map[string]string{
   179  		"": filepath.Join(root, "test_resources/cgroup_v2/test2"),
   180  	}
   181  
   182  	spec, err := getSpecInternal(cgroupPaths, &mockInfoProvider{}, false, false, true)
   183  	assert.Nil(t, err)
   184  
   185  	max := uint64(math.MaxUint64)
   186  
   187  	assert.True(t, spec.HasMemory)
   188  	assert.EqualValues(t, spec.Memory.Limit, max)
   189  	assert.EqualValues(t, spec.Memory.SwapLimit, max)
   190  	assert.EqualValues(t, spec.Memory.Reservation, max)
   191  
   192  	assert.True(t, spec.HasCpu)
   193  	assert.EqualValues(t, spec.Cpu.Limit, 1286)
   194  	assert.EqualValues(t, spec.Cpu.Period, 100010)
   195  	assert.EqualValues(t, spec.Cpu.Quota, 0)
   196  
   197  	assert.EqualValues(t, spec.Processes.Limit, max)
   198  }
   199  
   200  func TestRemoveNetMetrics(t *testing.T) {
   201  	for _, ts := range []struct {
   202  		desc    string
   203  		in, out container.MetricSet
   204  	}{
   205  		{
   206  			desc: "nil set",
   207  			in:   nil,
   208  		},
   209  		{
   210  			desc: "empty set",
   211  			in:   container.MetricSet{},
   212  		},
   213  		{
   214  			desc: "nothing to remove",
   215  			in:   container.MetricSet{container.MemoryUsageMetrics: struct{}{}, container.PerfMetrics: struct{}{}},
   216  		},
   217  		{
   218  			desc: "also nothing to remove",
   219  			in:   container.AllMetrics.Difference(container.AllNetworkMetrics),
   220  		},
   221  		{
   222  			desc: "remove net from all",
   223  			in:   container.AllMetrics,
   224  			out:  container.AllMetrics.Difference(container.AllNetworkMetrics),
   225  		},
   226  		{
   227  			desc: "remove net from some",
   228  			in:   container.MetricSet{container.MemoryUsageMetrics: struct{}{}, container.NetworkTcpUsageMetrics: struct{}{}},
   229  			out:  container.MetricSet{container.MemoryUsageMetrics: struct{}{}},
   230  		},
   231  	} {
   232  		for _, remove := range []bool{true, false} {
   233  			ts, remove := ts, remove
   234  			desc := fmt.Sprintf("%s, remove: %v", ts.desc, remove)
   235  			t.Run(desc, func(t *testing.T) {
   236  				out := RemoveNetMetrics(ts.in, remove)
   237  				if !remove || ts.out == nil {
   238  					// Compare the actual underlying pointers. Can't use assert.Same
   239  					// because it checks for pointer type, and these are maps.
   240  					if reflect.ValueOf(ts.in) != reflect.ValueOf(out) {
   241  						t.Errorf("expected original map %p, got %p", ts.in, out)
   242  					}
   243  				} else {
   244  					assert.Equal(t, ts.out, out)
   245  				}
   246  			})
   247  		}
   248  	}
   249  }
   250  
   251  func BenchmarkGetSpecCgroupV2(b *testing.B) {
   252  	root, err := os.Getwd()
   253  	if err != nil {
   254  		b.Fatalf("getwd: %s", err)
   255  	}
   256  
   257  	cgroupPaths := map[string]string{
   258  		"": filepath.Join(root, "test_resources/cgroup_v2/test1"),
   259  	}
   260  
   261  	for i := 0; i < b.N; i++ {
   262  		_, err := getSpecInternal(cgroupPaths, &mockInfoProvider{}, false, false, true)
   263  		assert.Nil(b, err)
   264  	}
   265  
   266  }
   267  
   268  func BenchmarkGetSpecCgroupV1(b *testing.B) {
   269  	root, err := os.Getwd()
   270  	if err != nil {
   271  		b.Fatalf("getwd: %s", err)
   272  	}
   273  
   274  	cgroupPaths := map[string]string{
   275  		"memory": filepath.Join(root, "test_resources/cgroup_v1/test1/memory"),
   276  		"cpu":    filepath.Join(root, "test_resources/cgroup_v1/test1/cpu"),
   277  		"cpuset": filepath.Join(root, "test_resources/cgroup_v1/test1/cpuset"),
   278  		"pids":   filepath.Join(root, "test_resources/cgroup_v1/test1/pids"),
   279  	}
   280  
   281  	for i := 0; i < b.N; i++ {
   282  		_, err := getSpecInternal(cgroupPaths, &mockInfoProvider{}, false, false, false)
   283  		assert.Nil(b, err)
   284  	}
   285  
   286  }