github.com/kubewharf/katalyst-core@v0.5.3/pkg/metaserver/kcc/manager_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 kcc
    18  
    19  import (
    20  	"context"
    21  	"os"
    22  	"reflect"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/stretchr/testify/require"
    27  	v1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    30  	"k8s.io/apimachinery/pkg/runtime/schema"
    31  	"k8s.io/klog/v2"
    32  	"k8s.io/kubernetes/pkg/kubelet/checkpointmanager"
    33  
    34  	"github.com/kubewharf/katalyst-api/pkg/apis/config/v1alpha1"
    35  	"github.com/kubewharf/katalyst-core/cmd/katalyst-agent/app/options"
    36  	pkgconfig "github.com/kubewharf/katalyst-core/pkg/config"
    37  	"github.com/kubewharf/katalyst-core/pkg/config/agent"
    38  	"github.com/kubewharf/katalyst-core/pkg/config/agent/dynamic"
    39  	evictionconfig "github.com/kubewharf/katalyst-core/pkg/config/agent/dynamic/adminqos/eviction"
    40  	"github.com/kubewharf/katalyst-core/pkg/config/agent/dynamic/crd"
    41  	"github.com/kubewharf/katalyst-core/pkg/metaserver/agent/cnc"
    42  	"github.com/kubewharf/katalyst-core/pkg/metrics"
    43  	"github.com/kubewharf/katalyst-core/pkg/util"
    44  	"github.com/kubewharf/katalyst-core/pkg/util/native"
    45  )
    46  
    47  var (
    48  	defaultEnableNumaLevelDetection                = true
    49  	defaultEnableSystemLevelDetection              = true
    50  	defaultNumaFreeBelowWatermarkTimesThreshold    = 4
    51  	defaultSystemKswapdRateThreshold               = 2000
    52  	defaultSystemKswapdRateExceedDurationThreshold = 120
    53  
    54  	nonDefaultEnableNumaLevelEviction                       = false
    55  	nonDefaultEnableSystemLevelEviction                     = false
    56  	nonDefaultNumaFreeBelowWatermarkTimesThreshold          = 5
    57  	nonDefaultSystemKswapdRateThreshold                     = 3000
    58  	nonDefaultSystemKswapdRateExceedDurationThreshold       = 130
    59  	nonDefaultNumaEvictionRankingMetrics                    = []string{"metric1", "metric2"}
    60  	nonDefaultSystemEvictionRankingMetrics                  = []string{"metric3"}
    61  	nonDefaultGracePeriod                             int64 = 30
    62  
    63  	nonDefaultMemoryEvictionPluginConfig = v1alpha1.MemoryPressureEvictionConfig{
    64  		EnableNumaLevelEviction:                 &nonDefaultEnableNumaLevelEviction,
    65  		EnableSystemLevelEviction:               &nonDefaultEnableSystemLevelEviction,
    66  		NumaFreeBelowWatermarkTimesThreshold:    &nonDefaultNumaFreeBelowWatermarkTimesThreshold,
    67  		SystemKswapdRateThreshold:               &nonDefaultSystemKswapdRateThreshold,
    68  		SystemKswapdRateExceedDurationThreshold: &nonDefaultSystemKswapdRateExceedDurationThreshold,
    69  		NumaEvictionRankingMetrics:              util.ConvertStringListToNumaEvictionRankingMetrics(nonDefaultNumaEvictionRankingMetrics),
    70  		SystemEvictionRankingMetrics:            util.ConvertStringListToSystemEvictionRankingMetrics(nonDefaultSystemEvictionRankingMetrics),
    71  		GracePeriod:                             &nonDefaultGracePeriod,
    72  	}
    73  )
    74  
    75  func generateTestConfiguration(t *testing.T, nodeName string, dir string) *pkgconfig.Configuration {
    76  	testConfiguration, err := options.NewOptions().Config()
    77  	require.NoError(t, err)
    78  	require.NotNil(t, testConfiguration)
    79  
    80  	testConfiguration.NodeName = nodeName
    81  	testConfiguration.CheckpointManagerDir = dir
    82  	return testConfiguration
    83  }
    84  
    85  func generateTestCNC(nodeName string) *v1alpha1.CustomNodeConfig {
    86  	return &v1alpha1.CustomNodeConfig{
    87  		ObjectMeta: metav1.ObjectMeta{
    88  			Name: nodeName,
    89  		},
    90  		Status: v1alpha1.CustomNodeConfigStatus{
    91  			KatalystCustomConfigList: []v1alpha1.TargetConfig{
    92  				{
    93  					ConfigName:      "default",
    94  					ConfigNamespace: "test-namespace",
    95  					ConfigType:      testTargetGVR,
    96  					Hash:            "e39c2dd73aac",
    97  				},
    98  			},
    99  		},
   100  	}
   101  }
   102  
   103  func generateTestEvictionConfiguration(evictionThreshold map[v1.ResourceName]float64) *v1alpha1.AdminQoSConfiguration {
   104  	return &v1alpha1.AdminQoSConfiguration{
   105  		ObjectMeta: metav1.ObjectMeta{
   106  			Name:      "default",
   107  			Namespace: "test-namespace",
   108  		},
   109  		Spec: v1alpha1.AdminQoSConfigurationSpec{
   110  			Config: v1alpha1.AdminQoSConfig{
   111  				EvictionConfig: &v1alpha1.EvictionConfig{
   112  					ReclaimedResourcesEvictionConfig: &v1alpha1.ReclaimedResourcesEvictionConfig{
   113  						EvictionThreshold: evictionThreshold,
   114  					},
   115  					MemoryPressureEvictionConfig: &v1alpha1.MemoryPressureEvictionConfig{
   116  						NumaFreeBelowWatermarkTimesThreshold:    &defaultNumaFreeBelowWatermarkTimesThreshold,
   117  						SystemKswapdRateThreshold:               &defaultSystemKswapdRateThreshold,
   118  						SystemKswapdRateExceedDurationThreshold: &defaultSystemKswapdRateExceedDurationThreshold,
   119  						NumaEvictionRankingMetrics:              util.ConvertStringListToNumaEvictionRankingMetrics(evictionconfig.DefaultNumaEvictionRankingMetrics),
   120  						SystemEvictionRankingMetrics:            util.ConvertStringListToSystemEvictionRankingMetrics(evictionconfig.DefaultSystemEvictionRankingMetrics),
   121  					},
   122  				},
   123  			},
   124  		},
   125  	}
   126  }
   127  
   128  func constructTestDynamicConfigManager(t *testing.T, nodeName, dir string, evictionConfiguration *v1alpha1.AdminQoSConfiguration) *DynamicConfigManager {
   129  	clientSet := generateTestGenericClientSet(generateTestCNC(nodeName), evictionConfiguration)
   130  	conf := generateTestConfiguration(t, nodeName, dir)
   131  	cncFetcher := cnc.NewCachedCNCFetcher(conf.BaseConfiguration, conf.CNCConfiguration,
   132  		clientSet.InternalClient.ConfigV1alpha1().CustomNodeConfigs())
   133  
   134  	err := os.MkdirAll(dir, os.FileMode(0o755))
   135  	require.NoError(t, err)
   136  
   137  	checkpointManager, err := checkpointmanager.NewCheckpointManager(conf.CheckpointManagerDir)
   138  	require.NoError(t, err)
   139  
   140  	configLoader := NewKatalystCustomConfigLoader(clientSet, 1*time.Second, cncFetcher)
   141  	manager := &DynamicConfigManager{
   142  		conf:                conf.AgentConfiguration,
   143  		defaultConfig:       deepCopy(conf.GetDynamicConfiguration()),
   144  		configLoader:        configLoader,
   145  		emitter:             &metrics.DummyMetrics{},
   146  		resourceGVRMap:      make(map[string]metav1.GroupVersionResource),
   147  		checkpointGraceTime: conf.ConfigCheckpointGraceTime,
   148  		checkpointManager:   checkpointManager,
   149  	}
   150  
   151  	err = manager.AddConfigWatcher(testTargetGVR)
   152  	require.NoError(t, err)
   153  	return manager
   154  }
   155  
   156  func TestNewDynamicConfigManager(t *testing.T) {
   157  	t.Parallel()
   158  
   159  	nodeName := "test-node"
   160  	evictionConfiguration := generateTestEvictionConfiguration(map[v1.ResourceName]float64{
   161  		v1.ResourceCPU:    1.2,
   162  		v1.ResourceMemory: 1.3,
   163  	})
   164  	clientSet := generateTestGenericClientSet(generateTestCNC(nodeName), evictionConfiguration)
   165  	conf := generateTestConfiguration(t, nodeName, "/tmp/metaserver1/TestNewDynamicConfigManager")
   166  	cncFetcher := cnc.NewCachedCNCFetcher(conf.BaseConfiguration, conf.CNCConfiguration,
   167  		clientSet.InternalClient.ConfigV1alpha1().CustomNodeConfigs())
   168  	defer os.RemoveAll(conf.CheckpointManagerDir)
   169  
   170  	err := os.MkdirAll("/tmp/metaserver1/TestNewDynamicConfigManager", os.FileMode(0o755))
   171  	require.NoError(t, err)
   172  
   173  	manager, err := NewDynamicConfigManager(clientSet, &metrics.DummyMetrics{}, cncFetcher, conf)
   174  	require.NoError(t, err)
   175  	require.NotNil(t, manager)
   176  
   177  	err = manager.AddConfigWatcher(testTargetGVR)
   178  	require.NoError(t, err)
   179  
   180  	err = manager.InitializeConfig(context.TODO())
   181  	require.NoError(t, err)
   182  	go manager.Run(context.TODO())
   183  }
   184  
   185  func TestDynamicConfigManager_getConfig(t *testing.T) {
   186  	t.Parallel()
   187  
   188  	type fields struct {
   189  		manager *DynamicConfigManager
   190  	}
   191  	type args struct {
   192  		ctx context.Context
   193  	}
   194  	tests := []struct {
   195  		name   string
   196  		fields fields
   197  		args   args
   198  		want   func(got *agent.AgentConfiguration) bool
   199  	}{
   200  		{
   201  			name: "test-1",
   202  			fields: fields{
   203  				manager: constructTestDynamicConfigManager(t, "test-node", "/tmp/metaserver1/TestDynamicConfigManager_test-node",
   204  					generateTestEvictionConfiguration(map[v1.ResourceName]float64{
   205  						v1.ResourceCPU:    1.2,
   206  						v1.ResourceMemory: 1.3,
   207  					})),
   208  			},
   209  			args: args{
   210  				ctx: context.TODO(),
   211  			},
   212  			want: func(got *agent.AgentConfiguration) bool {
   213  				return got.GetDynamicConfiguration().EvictionThreshold[v1.ResourceCPU] == 1.2 &&
   214  					got.GetDynamicConfiguration().EvictionThreshold[v1.ResourceMemory] == 1.3
   215  			},
   216  		},
   217  		{
   218  			name: "test-no-change",
   219  			fields: fields{
   220  				manager: constructTestDynamicConfigManager(t, "test-node", "/tmp/metaserver1/TestDynamicConfigManager_test-no-change",
   221  					generateTestEvictionConfiguration(generateTestConfiguration(t, "test-node", "/tmp/metaserver1/TestDynamicConfigManager_test-no-change").
   222  						GetDynamicConfiguration().EvictionThreshold)),
   223  			},
   224  			args: args{
   225  				ctx: context.TODO(),
   226  			},
   227  			want: func(got *agent.AgentConfiguration) bool {
   228  				return reflect.DeepEqual(got.GetDynamicConfiguration().EvictionThreshold,
   229  					generateTestConfiguration(t, "test-node", "/tmp/metaserver1/TestDynamicConfigManager_test-no-change").
   230  						GetDynamicConfiguration().EvictionThreshold)
   231  			},
   232  		},
   233  	}
   234  	for _, tt := range tests {
   235  		tt := tt
   236  		t.Run(tt.name, func(t *testing.T) {
   237  			t.Parallel()
   238  
   239  			c := tt.fields.manager
   240  			defer os.RemoveAll(c.conf.CheckpointManagerDir)
   241  			err := c.updateConfig(tt.args.ctx)
   242  			require.NoError(t, err)
   243  			require.True(t, tt.want(c.conf))
   244  		})
   245  	}
   246  }
   247  
   248  func Test_applyDynamicConfig(t *testing.T) {
   249  	t.Parallel()
   250  
   251  	type args struct {
   252  		currentConfig *dynamic.Configuration
   253  		dynamicConf   *crd.DynamicConfigCRD
   254  	}
   255  	tests := []struct {
   256  		name string
   257  		args args
   258  		want func(got *dynamic.Configuration) bool
   259  	}{
   260  		{
   261  			name: "test-1",
   262  			args: args{
   263  				currentConfig: func() *dynamic.Configuration {
   264  					d := dynamic.NewConfiguration()
   265  					d.EvictionThreshold = map[v1.ResourceName]float64{
   266  						"cpu": 1.5,
   267  					}
   268  
   269  					d.EnableNumaLevelEviction = defaultEnableNumaLevelDetection
   270  					d.EnableSystemLevelEviction = defaultEnableSystemLevelDetection
   271  					d.NumaFreeBelowWatermarkTimesThreshold = defaultNumaFreeBelowWatermarkTimesThreshold
   272  					d.SystemKswapdRateThreshold = defaultSystemKswapdRateThreshold
   273  					d.SystemKswapdRateExceedDurationThreshold = defaultSystemKswapdRateExceedDurationThreshold
   274  					d.NumaEvictionRankingMetrics = evictionconfig.DefaultNumaEvictionRankingMetrics
   275  					d.SystemEvictionRankingMetrics = evictionconfig.DefaultSystemEvictionRankingMetrics
   276  					d.MemoryPressureEvictionConfiguration.GracePeriod = evictionconfig.DefaultGracePeriod
   277  					return d
   278  				}(),
   279  				dynamicConf: &crd.DynamicConfigCRD{
   280  					AdminQoSConfiguration: &v1alpha1.AdminQoSConfiguration{
   281  						Spec: v1alpha1.AdminQoSConfigurationSpec{
   282  							Config: v1alpha1.AdminQoSConfig{
   283  								EvictionConfig: &v1alpha1.EvictionConfig{
   284  									ReclaimedResourcesEvictionConfig: &v1alpha1.ReclaimedResourcesEvictionConfig{
   285  										EvictionThreshold: map[v1.ResourceName]float64{
   286  											"cpu": 1.3,
   287  										},
   288  									},
   289  									MemoryPressureEvictionConfig: &nonDefaultMemoryEvictionPluginConfig,
   290  								},
   291  							},
   292  						},
   293  					},
   294  				},
   295  			},
   296  			want: func(got *dynamic.Configuration) bool {
   297  				return got.EvictionThreshold["cpu"] == 1.3 &&
   298  					got.EnableNumaLevelEviction == nonDefaultEnableNumaLevelEviction &&
   299  					got.EnableSystemLevelEviction == nonDefaultEnableSystemLevelEviction &&
   300  					got.NumaFreeBelowWatermarkTimesThreshold == nonDefaultNumaFreeBelowWatermarkTimesThreshold &&
   301  					got.SystemKswapdRateThreshold == nonDefaultSystemKswapdRateThreshold &&
   302  					got.SystemKswapdRateExceedDurationThreshold == nonDefaultSystemKswapdRateExceedDurationThreshold &&
   303  					reflect.DeepEqual(got.NumaEvictionRankingMetrics, nonDefaultNumaEvictionRankingMetrics) &&
   304  					reflect.DeepEqual(got.SystemEvictionRankingMetrics, nonDefaultSystemEvictionRankingMetrics) &&
   305  					got.MemoryPressureEvictionConfiguration.GracePeriod == nonDefaultGracePeriod
   306  			},
   307  		},
   308  		{
   309  			name: "test-2",
   310  			args: args{
   311  				currentConfig: func() *dynamic.Configuration {
   312  					d := dynamic.NewConfiguration()
   313  					d.EvictionThreshold = map[v1.ResourceName]float64{
   314  						"cpu": 1.3,
   315  					}
   316  
   317  					d.EnableNumaLevelEviction = nonDefaultEnableNumaLevelEviction
   318  					d.EnableSystemLevelEviction = nonDefaultEnableSystemLevelEviction
   319  					d.NumaFreeBelowWatermarkTimesThreshold = nonDefaultNumaFreeBelowWatermarkTimesThreshold
   320  					d.SystemKswapdRateThreshold = nonDefaultSystemKswapdRateThreshold
   321  					d.SystemKswapdRateExceedDurationThreshold = nonDefaultSystemKswapdRateExceedDurationThreshold
   322  					d.NumaEvictionRankingMetrics = nonDefaultNumaEvictionRankingMetrics
   323  					d.SystemEvictionRankingMetrics = nonDefaultSystemEvictionRankingMetrics
   324  					d.MemoryPressureEvictionConfiguration.GracePeriod = nonDefaultGracePeriod
   325  					return d
   326  				}(),
   327  				dynamicConf: &crd.DynamicConfigCRD{
   328  					AdminQoSConfiguration: &v1alpha1.AdminQoSConfiguration{
   329  						Spec: v1alpha1.AdminQoSConfigurationSpec{
   330  							Config: v1alpha1.AdminQoSConfig{
   331  								EvictionConfig: &v1alpha1.EvictionConfig{
   332  									ReclaimedResourcesEvictionConfig: &v1alpha1.ReclaimedResourcesEvictionConfig{
   333  										EvictionThreshold: map[v1.ResourceName]float64{
   334  											"cpu": 1.3,
   335  										},
   336  									},
   337  									MemoryPressureEvictionConfig: &nonDefaultMemoryEvictionPluginConfig,
   338  								},
   339  							},
   340  						},
   341  					},
   342  				},
   343  			},
   344  			want: func(got *dynamic.Configuration) bool {
   345  				return got.EvictionThreshold["cpu"] == 1.3 &&
   346  					got.EnableNumaLevelEviction == nonDefaultEnableNumaLevelEviction &&
   347  					got.EnableSystemLevelEviction == nonDefaultEnableSystemLevelEviction &&
   348  					got.NumaFreeBelowWatermarkTimesThreshold == nonDefaultNumaFreeBelowWatermarkTimesThreshold &&
   349  					got.SystemKswapdRateThreshold == nonDefaultSystemKswapdRateThreshold &&
   350  					got.SystemKswapdRateExceedDurationThreshold == nonDefaultSystemKswapdRateExceedDurationThreshold &&
   351  					reflect.DeepEqual(got.NumaEvictionRankingMetrics, nonDefaultNumaEvictionRankingMetrics) &&
   352  					reflect.DeepEqual(got.SystemEvictionRankingMetrics, nonDefaultSystemEvictionRankingMetrics) &&
   353  					got.MemoryPressureEvictionConfiguration.GracePeriod == nonDefaultGracePeriod
   354  			},
   355  		},
   356  	}
   357  	for _, tt := range tests {
   358  		tt := tt
   359  		t.Run(tt.name, func(t *testing.T) {
   360  			t.Parallel()
   361  			applyDynamicConfig(tt.args.currentConfig, tt.args.dynamicConf)
   362  			got := tt.args.currentConfig
   363  			require.True(t, tt.want(got))
   364  		})
   365  	}
   366  }
   367  
   368  func Test_getGVRToKindMap(t *testing.T) {
   369  	t.Parallel()
   370  
   371  	tests := []struct {
   372  		name    string
   373  		wantGVR schema.GroupVersionResource
   374  		wantGVK schema.GroupVersionKind
   375  	}{
   376  		{
   377  			name:    "aqc",
   378  			wantGVR: schema.GroupVersionResource(crd.AdminQoSConfigurationGVR),
   379  			wantGVK: schema.GroupVersionKind{
   380  				Group:   v1alpha1.SchemeGroupVersion.Group,
   381  				Version: v1alpha1.SchemeGroupVersion.Version,
   382  				Kind:    crd.ResourceKindAdminQoSConfiguration,
   383  			},
   384  		},
   385  	}
   386  
   387  	for _, tt := range tests {
   388  		tt := tt
   389  		t.Run(tt.name, func(t *testing.T) {
   390  			t.Parallel()
   391  			if got := getGVRToGVKMap(); !checkGVRToGVKMap(tt.wantGVR, tt.wantGVK, got) {
   392  				t.Errorf("getGVRToGVKMap() = %v, wantGVR %v wantGVK %v", got, tt.wantGVR, tt.wantGVK)
   393  			}
   394  		})
   395  	}
   396  }
   397  
   398  func checkGVRToGVKMap(gvr schema.GroupVersionResource, wantGVK schema.GroupVersionKind,
   399  	m map[schema.GroupVersionResource]schema.GroupVersionKind,
   400  ) bool {
   401  	gvk, ok := m[gvr]
   402  	if ok && gvk == wantGVK {
   403  		return true
   404  	}
   405  	return false
   406  }
   407  
   408  func Test_updateDynamicConf(t *testing.T) {
   409  	t.Parallel()
   410  
   411  	type args struct {
   412  		resourceGVRMap map[string]metav1.GroupVersionResource
   413  		gvrToKind      map[schema.GroupVersionResource]schema.GroupVersionKind
   414  		loader         func(gvr metav1.GroupVersionResource, conf interface{}) error
   415  	}
   416  	tests := []struct {
   417  		name  string
   418  		args  args
   419  		want  *crd.DynamicConfigCRD
   420  		want1 bool
   421  	}{
   422  		{
   423  			name: "test-1",
   424  			args: args{
   425  				resourceGVRMap: generateTestResourceGVRMap(),
   426  				gvrToKind:      getGVRToGVKMap(),
   427  				loader: generateTestLoader(toTestUnstructured(&v1alpha1.AdminQoSConfiguration{
   428  					ObjectMeta: metav1.ObjectMeta{
   429  						Name: "config-1",
   430  					},
   431  					Spec: v1alpha1.AdminQoSConfigurationSpec{
   432  						GenericConfigSpec: v1alpha1.GenericConfigSpec{
   433  							NodeLabelSelector: "aa=bb",
   434  						},
   435  						Config: v1alpha1.AdminQoSConfig{
   436  							EvictionConfig: &v1alpha1.EvictionConfig{
   437  								ReclaimedResourcesEvictionConfig: &v1alpha1.ReclaimedResourcesEvictionConfig{
   438  									EvictionThreshold: map[v1.ResourceName]float64{
   439  										v1.ResourceCPU:    1.3,
   440  										v1.ResourceMemory: 1.5,
   441  									},
   442  								},
   443  							},
   444  						},
   445  					},
   446  				})),
   447  			},
   448  			want: &crd.DynamicConfigCRD{
   449  				AdminQoSConfiguration: &v1alpha1.AdminQoSConfiguration{
   450  					ObjectMeta: metav1.ObjectMeta{
   451  						Name: "config-1",
   452  					},
   453  					Spec: v1alpha1.AdminQoSConfigurationSpec{
   454  						GenericConfigSpec: v1alpha1.GenericConfigSpec{
   455  							NodeLabelSelector: "aa=bb",
   456  						},
   457  						Config: v1alpha1.AdminQoSConfig{
   458  							EvictionConfig: &v1alpha1.EvictionConfig{
   459  								ReclaimedResourcesEvictionConfig: &v1alpha1.ReclaimedResourcesEvictionConfig{
   460  									EvictionThreshold: map[v1.ResourceName]float64{
   461  										v1.ResourceCPU:    1.3,
   462  										v1.ResourceMemory: 1.5,
   463  									},
   464  								},
   465  							},
   466  						},
   467  					},
   468  				},
   469  			},
   470  			want1: true,
   471  		},
   472  	}
   473  	for _, tt := range tests {
   474  		tt := tt
   475  		t.Run(tt.name, func(t *testing.T) {
   476  			t.Parallel()
   477  
   478  			ec := generateTestEvictionConfiguration(map[v1.ResourceName]float64{
   479  				v1.ResourceCPU:    1.2,
   480  				v1.ResourceMemory: 1.3,
   481  			})
   482  			manager := constructTestDynamicConfigManager(t, "node-name", "Test_updateDynamicConf", ec)
   483  			defer os.RemoveAll(manager.conf.CheckpointManagerDir)
   484  			got, got1, _ := manager.updateDynamicConfig(tt.args.resourceGVRMap, tt.args.gvrToKind, tt.args.loader)
   485  			if !reflect.DeepEqual(got, tt.want) {
   486  				t.Errorf("updateDynamicConfig() got = %v, want %v", got, tt.want)
   487  			}
   488  			if got1 != tt.want1 {
   489  				t.Errorf("updateDynamicConfig() got1 = %v, want %v", got1, tt.want1)
   490  			}
   491  		})
   492  	}
   493  }
   494  
   495  func generateTestResourceGVRMap() map[string]metav1.GroupVersionResource {
   496  	return map[string]metav1.GroupVersionResource{
   497  		v1alpha1.ResourceNameAdminQoSConfigurations: crd.AdminQoSConfigurationGVR,
   498  	}
   499  }
   500  
   501  func generateTestLoader(unstructured *unstructured.Unstructured) func(gvr metav1.GroupVersionResource, conf interface{}) error {
   502  	return func(gvr metav1.GroupVersionResource, conf interface{}) error {
   503  		return util.ToKCCTargetResource(unstructured).Unmarshal(conf)
   504  	}
   505  }
   506  
   507  func toTestUnstructured(obj interface{}) *unstructured.Unstructured {
   508  	ret, err := native.ToUnstructured(obj)
   509  	if err != nil {
   510  		klog.Error(err)
   511  	}
   512  	return ret
   513  }