github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/qrm-plugins/cpu/util/util_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 util
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  	v1 "k8s.io/api/core/v1"
    25  	pluginapi "k8s.io/kubelet/pkg/apis/resourceplugin/v1alpha1"
    26  
    27  	"github.com/kubewharf/katalyst-api/pkg/consts"
    28  	"github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/cpu/dynamicpolicy/state"
    29  	"github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/util"
    30  	"github.com/kubewharf/katalyst-core/pkg/config"
    31  	"github.com/kubewharf/katalyst-core/pkg/config/agent"
    32  	"github.com/kubewharf/katalyst-core/pkg/config/agent/qrm"
    33  	"github.com/kubewharf/katalyst-core/pkg/metaserver"
    34  	"github.com/kubewharf/katalyst-core/pkg/util/machine"
    35  )
    36  
    37  func TestGetCoresReservedForSystem(t *testing.T) {
    38  	t.Parallel()
    39  
    40  	topology, err := machine.GenerateDummyCPUTopology(16, 2, 4)
    41  	assert.Nil(t, err)
    42  	machineInfo := &machine.KatalystMachineInfo{
    43  		CPUTopology: topology,
    44  	}
    45  
    46  	type args struct {
    47  		conf        *config.Configuration
    48  		metaServer  *metaserver.MetaServer
    49  		machineInfo *machine.KatalystMachineInfo
    50  		allCPUs     machine.CPUSet
    51  	}
    52  	tests := []struct {
    53  		name    string
    54  		args    args
    55  		want    machine.CPUSet
    56  		wantErr bool
    57  	}{
    58  		{
    59  			name:    "GetCoresReservedForSystem with nil conf",
    60  			want:    machine.NewCPUSet(),
    61  			wantErr: true,
    62  		},
    63  		{
    64  			name: "GetCoresReservedForSystem with nil metaServer",
    65  			args: args{
    66  				conf: &config.Configuration{
    67  					AgentConfiguration: &agent.AgentConfiguration{
    68  						GenericAgentConfiguration: &agent.GenericAgentConfiguration{
    69  							GenericQRMPluginConfiguration: &qrm.GenericQRMPluginConfiguration{},
    70  						},
    71  					},
    72  				},
    73  				machineInfo: &machine.KatalystMachineInfo{},
    74  			},
    75  			want:    machine.NewCPUSet(),
    76  			wantErr: true,
    77  		},
    78  		{
    79  			name: "GetCoresReservedForSystem with nil machineInfo",
    80  			args: args{
    81  				conf: &config.Configuration{
    82  					AgentConfiguration: &agent.AgentConfiguration{
    83  						GenericAgentConfiguration: &agent.GenericAgentConfiguration{
    84  							GenericQRMPluginConfiguration: &qrm.GenericQRMPluginConfiguration{},
    85  						},
    86  					},
    87  				},
    88  				metaServer: &metaserver.MetaServer{},
    89  			},
    90  			want:    machine.NewCPUSet(),
    91  			wantErr: true,
    92  		},
    93  		{
    94  			name: "GetCoresReservedForSystem with conf",
    95  			args: args{
    96  				allCPUs: topology.CPUDetails.CPUs(),
    97  				conf: &config.Configuration{
    98  					AgentConfiguration: &agent.AgentConfiguration{
    99  						GenericAgentConfiguration: &agent.GenericAgentConfiguration{
   100  							GenericQRMPluginConfiguration: &qrm.GenericQRMPluginConfiguration{},
   101  						},
   102  						StaticAgentConfiguration: &agent.StaticAgentConfiguration{
   103  							QRMPluginsConfiguration: &qrm.QRMPluginsConfiguration{
   104  								CPUQRMPluginConfig: &qrm.CPUQRMPluginConfig{
   105  									ReservedCPUCores: 4,
   106  								},
   107  							},
   108  						},
   109  					},
   110  				},
   111  				metaServer:  &metaserver.MetaServer{},
   112  				machineInfo: machineInfo,
   113  			},
   114  			want:    machine.NewCPUSet(0, 2, 4, 6),
   115  			wantErr: false,
   116  		},
   117  	}
   118  	for _, tt := range tests {
   119  		tt := tt
   120  		t.Run(tt.name, func(t *testing.T) {
   121  			t.Parallel()
   122  
   123  			got, err := GetCoresReservedForSystem(tt.args.conf, tt.args.metaServer, tt.args.machineInfo, tt.args.allCPUs)
   124  			if (err != nil) != tt.wantErr {
   125  				t.Errorf("GetCoresReservedForSystem() error = %v, wantErr %v", err, tt.wantErr)
   126  				return
   127  			}
   128  			if !reflect.DeepEqual(got, tt.want) {
   129  				t.Errorf("GetCoresReservedForSystem() = %v, want %v", got, tt.want)
   130  			}
   131  		})
   132  	}
   133  }
   134  
   135  func TestRegenerateHints(t *testing.T) {
   136  	t.Parallel()
   137  
   138  	type args struct {
   139  		allocationInfo *state.AllocationInfo
   140  		reqInt         int
   141  	}
   142  	tests := []struct {
   143  		name string
   144  		args args
   145  		want map[string]*pluginapi.ListOfTopologyHints
   146  	}{
   147  		{
   148  			name: "test RegenerateHints",
   149  			args: args{
   150  				allocationInfo: &state.AllocationInfo{
   151  					PodUid:                   "test",
   152  					PodNamespace:             "test",
   153  					PodName:                  "test",
   154  					ContainerName:            "test",
   155  					ContainerType:            pluginapi.ContainerType_MAIN.String(),
   156  					ContainerIndex:           0,
   157  					RampUp:                   false,
   158  					OwnerPoolName:            state.PoolNameDedicated,
   159  					AllocationResult:         machine.NewCPUSet(1, 3, 8, 9, 10, 11),
   160  					OriginalAllocationResult: machine.NewCPUSet(1, 3, 8, 9, 10, 11),
   161  					TopologyAwareAssignments: map[int]machine.CPUSet{
   162  						0: machine.NewCPUSet(1, 8, 9),
   163  						1: machine.NewCPUSet(3, 10, 11),
   164  					},
   165  					OriginalTopologyAwareAssignments: map[int]machine.CPUSet{
   166  						0: machine.NewCPUSet(1, 8, 9),
   167  						1: machine.NewCPUSet(3, 10, 11),
   168  					},
   169  					Labels: map[string]string{
   170  						consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores,
   171  					},
   172  					Annotations: map[string]string{
   173  						consts.PodAnnotationQoSLevelKey:                  consts.PodAnnotationQoSLevelDedicatedCores,
   174  						consts.PodAnnotationMemoryEnhancementNumaBinding: consts.PodAnnotationMemoryEnhancementNumaBindingEnable,
   175  					},
   176  					QoSLevel:        consts.PodAnnotationQoSLevelDedicatedCores,
   177  					RequestQuantity: 2,
   178  				},
   179  				reqInt: 2,
   180  			},
   181  			want: map[string]*pluginapi.ListOfTopologyHints{
   182  				string(v1.ResourceCPU): {
   183  					Hints: []*pluginapi.TopologyHint{
   184  						{
   185  							Nodes:     []uint64{0, 1},
   186  							Preferred: true,
   187  						},
   188  					},
   189  				},
   190  			},
   191  		},
   192  	}
   193  	for _, tt := range tests {
   194  		tt := tt
   195  		t.Run(tt.name, func(t *testing.T) {
   196  			t.Parallel()
   197  			if got := RegenerateHints(tt.args.allocationInfo, tt.args.reqInt); !reflect.DeepEqual(got, tt.want) {
   198  				t.Errorf("RegenerateHints() = %v, want %v", got, tt.want)
   199  			}
   200  		})
   201  	}
   202  }
   203  
   204  func TestPackAllocationResponse(t *testing.T) {
   205  	t.Parallel()
   206  
   207  	type args struct {
   208  		allocationInfo   *state.AllocationInfo
   209  		resourceName     string
   210  		ociPropertyName  string
   211  		isNodeResource   bool
   212  		isScalarResource bool
   213  		req              *pluginapi.ResourceRequest
   214  	}
   215  	tests := []struct {
   216  		name    string
   217  		args    args
   218  		want    *pluginapi.ResourceAllocationResponse
   219  		wantErr bool
   220  	}{
   221  		{
   222  			name:    "test PackAllocationResponse with nil allocationInfo",
   223  			args:    args{},
   224  			want:    nil,
   225  			wantErr: true,
   226  		},
   227  		{
   228  			name: "test PackAllocationResponse with nil req",
   229  			args: args{
   230  				allocationInfo: &state.AllocationInfo{},
   231  			},
   232  			want:    nil,
   233  			wantErr: true,
   234  		},
   235  		{
   236  			name: "test PackAllocationResponse",
   237  			args: args{
   238  				allocationInfo: &state.AllocationInfo{
   239  					PodUid:                   "test",
   240  					PodNamespace:             "test",
   241  					PodName:                  "test",
   242  					ContainerName:            "test",
   243  					ContainerType:            pluginapi.ContainerType_MAIN.String(),
   244  					ContainerIndex:           0,
   245  					RampUp:                   false,
   246  					OwnerPoolName:            state.PoolNameDedicated,
   247  					AllocationResult:         machine.NewCPUSet(1, 3, 8, 9, 10, 11),
   248  					OriginalAllocationResult: machine.NewCPUSet(1, 3, 8, 9, 10, 11),
   249  					TopologyAwareAssignments: map[int]machine.CPUSet{
   250  						0: machine.NewCPUSet(1, 8, 9),
   251  						1: machine.NewCPUSet(3, 10, 11),
   252  					},
   253  					OriginalTopologyAwareAssignments: map[int]machine.CPUSet{
   254  						0: machine.NewCPUSet(1, 8, 9),
   255  						1: machine.NewCPUSet(3, 10, 11),
   256  					},
   257  					Labels: map[string]string{
   258  						consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores,
   259  					},
   260  					Annotations: map[string]string{
   261  						consts.PodAnnotationQoSLevelKey:                  consts.PodAnnotationQoSLevelDedicatedCores,
   262  						consts.PodAnnotationMemoryEnhancementNumaBinding: consts.PodAnnotationMemoryEnhancementNumaBindingEnable,
   263  					},
   264  					QoSLevel:        consts.PodAnnotationQoSLevelDedicatedCores,
   265  					RequestQuantity: 2,
   266  				},
   267  				resourceName:     string(v1.ResourceCPU),
   268  				ociPropertyName:  util.OCIPropertyNameCPUSetCPUs,
   269  				isNodeResource:   false,
   270  				isScalarResource: true,
   271  				req: &pluginapi.ResourceRequest{
   272  					PodUid:         "test",
   273  					PodNamespace:   "test",
   274  					PodName:        "test",
   275  					ContainerName:  "test",
   276  					ContainerType:  pluginapi.ContainerType_MAIN,
   277  					ContainerIndex: 0,
   278  				},
   279  			},
   280  			want: &pluginapi.ResourceAllocationResponse{
   281  				PodUid:         "test",
   282  				PodNamespace:   "test",
   283  				PodName:        "test",
   284  				ContainerName:  "test",
   285  				ContainerType:  pluginapi.ContainerType_MAIN,
   286  				ContainerIndex: 0,
   287  				ResourceName:   string(v1.ResourceCPU),
   288  				AllocationResult: &pluginapi.ResourceAllocation{
   289  					ResourceAllocation: map[string]*pluginapi.ResourceAllocationInfo{
   290  						string(v1.ResourceCPU): {
   291  							OciPropertyName:   util.OCIPropertyNameCPUSetCPUs,
   292  							IsNodeResource:    false,
   293  							IsScalarResource:  true,
   294  							AllocatedQuantity: float64(6),
   295  							AllocationResult:  machine.NewCPUSet(1, 3, 8, 9, 10, 11).String(),
   296  							ResourceHints: &pluginapi.ListOfTopologyHints{
   297  								Hints: []*pluginapi.TopologyHint{
   298  									nil,
   299  								},
   300  							},
   301  						},
   302  					},
   303  				},
   304  			},
   305  			wantErr: false,
   306  		},
   307  	}
   308  	for _, tt := range tests {
   309  		tt := tt
   310  		t.Run(tt.name, func(t *testing.T) {
   311  			t.Parallel()
   312  
   313  			got, err := PackAllocationResponse(tt.args.allocationInfo, tt.args.resourceName, tt.args.ociPropertyName, tt.args.isNodeResource, tt.args.isScalarResource, tt.args.req)
   314  			if (err != nil) != tt.wantErr {
   315  				t.Errorf("PackAllocationResponse() error = %v, wantErr %v", err, tt.wantErr)
   316  				return
   317  			}
   318  			if !reflect.DeepEqual(got, tt.want) {
   319  				t.Errorf("PackAllocationResponse() = %v, want %v", got, tt.want)
   320  			}
   321  		})
   322  	}
   323  }