github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/native/resources_test.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package native
    18  
    19  import (
    20  	"testing"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  	v1 "k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/api/resource"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  )
    27  
    28  var makePod = func(name string, request, limits v1.ResourceList) *v1.Pod {
    29  	pod := &v1.Pod{
    30  		ObjectMeta: metav1.ObjectMeta{Name: name},
    31  		Spec: v1.PodSpec{
    32  			Containers: []v1.Container{
    33  				{
    34  					Name: "c1",
    35  					Resources: v1.ResourceRequirements{
    36  						Limits:   limits,
    37  						Requests: request,
    38  					},
    39  				},
    40  			},
    41  		},
    42  	}
    43  	return pod
    44  }
    45  
    46  func TestNeedUpdateResources(t *testing.T) {
    47  	t.Parallel()
    48  
    49  	for _, tc := range []struct {
    50  		name                       string
    51  		pod                        *v1.Pod
    52  		containerResourcesToUpdate map[string]v1.ResourceRequirements
    53  		want                       bool
    54  	}{
    55  		{
    56  			name: "same resource",
    57  			pod: makePod("pod1",
    58  				map[v1.ResourceName]resource.Quantity{
    59  					v1.ResourceCPU: *resource.NewQuantity(2, resource.DecimalSI),
    60  				},
    61  				nil),
    62  			containerResourcesToUpdate: map[string]v1.ResourceRequirements{
    63  				"c1": {
    64  					Requests: map[v1.ResourceName]resource.Quantity{
    65  						v1.ResourceCPU: *resource.NewQuantity(2, resource.DecimalSI),
    66  					},
    67  				},
    68  			},
    69  			want: false,
    70  		},
    71  		{
    72  			name: "same resource2",
    73  			pod: makePod("pod1",
    74  				map[v1.ResourceName]resource.Quantity{
    75  					v1.ResourceCPU:    *resource.NewQuantity(2, resource.DecimalSI),
    76  					v1.ResourceMemory: *resource.NewQuantity(2, resource.DecimalSI),
    77  				},
    78  				nil),
    79  			containerResourcesToUpdate: map[string]v1.ResourceRequirements{
    80  				"c1": {
    81  					Requests: map[v1.ResourceName]resource.Quantity{
    82  						v1.ResourceCPU: *resource.NewQuantity(2, resource.DecimalSI),
    83  					},
    84  				},
    85  			},
    86  			want: false,
    87  		},
    88  		{
    89  			name: "diff resource",
    90  			pod: makePod("pod1",
    91  				map[v1.ResourceName]resource.Quantity{
    92  					v1.ResourceCPU: *resource.NewQuantity(2, resource.DecimalSI),
    93  				},
    94  				nil),
    95  			containerResourcesToUpdate: map[string]v1.ResourceRequirements{
    96  				"c1": {
    97  					Requests: map[v1.ResourceName]resource.Quantity{
    98  						v1.ResourceCPU: *resource.NewQuantity(1, resource.DecimalSI),
    99  					},
   100  				},
   101  			},
   102  			want: true,
   103  		},
   104  		{
   105  			name: "new resource",
   106  			pod: makePod("pod1",
   107  				map[v1.ResourceName]resource.Quantity{
   108  					v1.ResourceCPU: *resource.NewQuantity(2, resource.DecimalSI),
   109  				},
   110  				nil),
   111  			containerResourcesToUpdate: map[string]v1.ResourceRequirements{
   112  				"c1": {
   113  					Requests: map[v1.ResourceName]resource.Quantity{
   114  						v1.ResourceMemory: *resource.NewQuantity(2, resource.DecimalSI),
   115  					},
   116  				},
   117  			},
   118  			want: true,
   119  		},
   120  		{
   121  			name: "pod not match",
   122  			pod: makePod("pod1",
   123  				map[v1.ResourceName]resource.Quantity{
   124  					v1.ResourceCPU: *resource.NewQuantity(2, resource.DecimalSI),
   125  				},
   126  				nil),
   127  			containerResourcesToUpdate: map[string]v1.ResourceRequirements{
   128  				"c2": {
   129  					Requests: map[v1.ResourceName]resource.Quantity{
   130  						v1.ResourceMemory: *resource.NewQuantity(2, resource.DecimalSI),
   131  					},
   132  				},
   133  			},
   134  			want: false,
   135  		},
   136  	} {
   137  		tc := tc
   138  		t.Run(tc.name, func(t *testing.T) {
   139  			t.Parallel()
   140  			assert.Equal(t, tc.want, PodResourceDiff(tc.pod, tc.containerResourcesToUpdate))
   141  		})
   142  	}
   143  }
   144  
   145  func TestMultiplyResourceQuantity(t *testing.T) {
   146  	t.Parallel()
   147  
   148  	cases := []struct {
   149  		name         string
   150  		resourceName v1.ResourceName
   151  		quant        resource.Quantity
   152  		factor       float64
   153  		res          resource.Quantity
   154  		want         bool
   155  	}{
   156  		{
   157  			name:         "resource CPU",
   158  			resourceName: v1.ResourceCPU,
   159  			quant:        *resource.NewQuantity(2, resource.DecimalSI),
   160  			factor:       1.5,
   161  			res:          *resource.NewQuantity(3, resource.DecimalSI),
   162  			want:         true,
   163  		},
   164  		{
   165  			name:         "resource memory Gi",
   166  			resourceName: v1.ResourceCPU,
   167  			quant:        resource.MustParse("200Gi"),
   168  			factor:       1.5,
   169  			res:          resource.MustParse("300Gi"),
   170  			want:         true,
   171  		},
   172  		{
   173  			name:         "resource memory ki",
   174  			resourceName: v1.ResourceMemory,
   175  			quant:        resource.MustParse("32612508Ki"),
   176  			factor:       1.5,
   177  			res:          resource.MustParse("48918762Ki"),
   178  			want:         true,
   179  		},
   180  		{
   181  			name:         "resource memory m",
   182  			resourceName: v1.ResourceMemory,
   183  			quant:        resource.MustParse("29258114498560m"),
   184  			factor:       1.5,
   185  			res:          resource.MustParse("43887171747840m"),
   186  			want:         true,
   187  		},
   188  		{
   189  			name:         "zero value",
   190  			resourceName: v1.ResourceCPU,
   191  			quant:        *resource.NewQuantity(0, resource.DecimalSI),
   192  			factor:       2,
   193  			res:          *resource.NewQuantity(0, resource.DecimalSI),
   194  			want:         true,
   195  		},
   196  		{
   197  			name:         "zero factor",
   198  			resourceName: v1.ResourceCPU,
   199  			quant:        *resource.NewQuantity(2, resource.DecimalSI),
   200  			factor:       0,
   201  			res:          *resource.NewQuantity(0, resource.DecimalSI),
   202  			want:         true,
   203  		},
   204  		{
   205  			name:         "round down",
   206  			resourceName: v1.ResourceCPU,
   207  			quant:        *resource.NewQuantity(2, resource.DecimalSI),
   208  			factor:       1.23456,
   209  			res:          *resource.NewMilliQuantity(2469, resource.DecimalSI),
   210  			want:         true,
   211  		},
   212  	}
   213  	for _, c := range cases {
   214  		c := c
   215  		t.Run(c.name, func(t *testing.T) {
   216  			t.Parallel()
   217  			quant := MultiplyMilliQuantity(c.quant, c.factor)
   218  			t.Log(quant.String())
   219  			assert.Equal(t, c.want, quant.Equal(c.res))
   220  		})
   221  	}
   222  }
   223  
   224  func TestAggregateAvgQuantities(t *testing.T) {
   225  	t.Parallel()
   226  
   227  	type args struct {
   228  		quantities []resource.Quantity
   229  	}
   230  	tests := []struct {
   231  		name string
   232  		args args
   233  		want *resource.Quantity
   234  	}{
   235  		{
   236  			name: "default",
   237  			args: args{
   238  				quantities: []resource.Quantity{
   239  					resource.MustParse("10"),
   240  					resource.MustParse("20"),
   241  				},
   242  			},
   243  			want: resource.NewQuantity(15, resource.DecimalSI),
   244  		},
   245  		{
   246  			name: "empty",
   247  			args: args{
   248  				quantities: []resource.Quantity{},
   249  			},
   250  			want: nil,
   251  		},
   252  	}
   253  	for _, tt := range tests {
   254  		tt := tt
   255  		t.Run(tt.name, func(t *testing.T) {
   256  			t.Parallel()
   257  
   258  			assert.Equalf(t, tt.want, AggregateAvgQuantities(tt.args.quantities), "AggregateAvgQuantities(%v)", tt.args.quantities)
   259  		})
   260  	}
   261  }