github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/orm/topology/policy_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 topology
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  
    25  	"github.com/kubewharf/katalyst-core/pkg/util/bitmask"
    26  )
    27  
    28  type policyMergeTestCase struct {
    29  	name     string
    30  	hp       []HintProvider
    31  	expected map[string]TopologyHint
    32  }
    33  
    34  func commonPolicyMergeTestCases(numaNodes []int) []policyMergeTestCase {
    35  	return []policyMergeTestCase{
    36  		{
    37  			name: "Two providers, 1 hint each, same mask, both preferred 1/2",
    38  			hp: []HintProvider{
    39  				&mockHintProvider{
    40  					map[string][]TopologyHint{
    41  						"resource1": {
    42  							{
    43  								NUMANodeAffinity: NewTestBitMask(0),
    44  								Preferred:        true,
    45  							},
    46  						},
    47  					},
    48  				},
    49  				&mockHintProvider{
    50  					map[string][]TopologyHint{
    51  						"resource2": {
    52  							{
    53  								NUMANodeAffinity: NewTestBitMask(0),
    54  								Preferred:        true,
    55  							},
    56  						},
    57  					},
    58  				},
    59  			},
    60  			expected: map[string]TopologyHint{
    61  				"resource1": {
    62  					NUMANodeAffinity: NewTestBitMask(0),
    63  					Preferred:        true,
    64  				},
    65  				"resource2": {
    66  					NUMANodeAffinity: NewTestBitMask(0),
    67  					Preferred:        true,
    68  				},
    69  			},
    70  		},
    71  		{
    72  			name: "Two providers, 1 hint each, same mask, both preferred 2/2",
    73  			hp: []HintProvider{
    74  				&mockHintProvider{
    75  					map[string][]TopologyHint{
    76  						"resource1": {
    77  							{
    78  								NUMANodeAffinity: NewTestBitMask(1),
    79  								Preferred:        true,
    80  							},
    81  						},
    82  					},
    83  				},
    84  				&mockHintProvider{
    85  					map[string][]TopologyHint{
    86  						"resource2": {
    87  							{
    88  								NUMANodeAffinity: NewTestBitMask(1),
    89  								Preferred:        true,
    90  							},
    91  						},
    92  					},
    93  				},
    94  			},
    95  			expected: map[string]TopologyHint{
    96  				"resource1": {
    97  					NUMANodeAffinity: NewTestBitMask(1),
    98  					Preferred:        true,
    99  				},
   100  				"resource2": {
   101  					NUMANodeAffinity: NewTestBitMask(1),
   102  					Preferred:        true,
   103  				},
   104  			},
   105  		},
   106  		{
   107  			name: "Two providers, 1 no hints, 1 single hint preferred 1/2",
   108  			hp: []HintProvider{
   109  				&mockHintProvider{},
   110  				&mockHintProvider{
   111  					map[string][]TopologyHint{
   112  						"resource": {
   113  							{
   114  								NUMANodeAffinity: NewTestBitMask(0),
   115  								Preferred:        true,
   116  							},
   117  						},
   118  					},
   119  				},
   120  			},
   121  			expected: map[string]TopologyHint{
   122  				defaultResourceKey: {
   123  					NUMANodeAffinity: NewTestBitMask(0),
   124  					Preferred:        true,
   125  				},
   126  				"resource": {
   127  					NUMANodeAffinity: NewTestBitMask(0),
   128  					Preferred:        true,
   129  				},
   130  			},
   131  		},
   132  		{
   133  			name: "Two providers, 1 no hints, 1 single hint preferred 2/2",
   134  			hp: []HintProvider{
   135  				&mockHintProvider{},
   136  				&mockHintProvider{
   137  					map[string][]TopologyHint{
   138  						"resource": {
   139  							{
   140  								NUMANodeAffinity: NewTestBitMask(1),
   141  								Preferred:        true,
   142  							},
   143  						},
   144  					},
   145  				},
   146  			},
   147  			expected: map[string]TopologyHint{
   148  				defaultResourceKey: {
   149  					NUMANodeAffinity: NewTestBitMask(1),
   150  					Preferred:        true,
   151  				},
   152  				"resource": {
   153  					NUMANodeAffinity: NewTestBitMask(1),
   154  					Preferred:        true,
   155  				},
   156  			},
   157  		},
   158  		{
   159  			name: "Two providers, 1 with 2 hints, 1 with single hint matching 1/2",
   160  			hp: []HintProvider{
   161  				&mockHintProvider{
   162  					map[string][]TopologyHint{
   163  						"resource1": {
   164  							{
   165  								NUMANodeAffinity: NewTestBitMask(0),
   166  								Preferred:        true,
   167  							},
   168  							{
   169  								NUMANodeAffinity: NewTestBitMask(1),
   170  								Preferred:        true,
   171  							},
   172  						},
   173  					},
   174  				},
   175  				&mockHintProvider{
   176  					map[string][]TopologyHint{
   177  						"resource2": {
   178  							{
   179  								NUMANodeAffinity: NewTestBitMask(0),
   180  								Preferred:        true,
   181  							},
   182  						},
   183  					},
   184  				},
   185  			},
   186  			expected: map[string]TopologyHint{
   187  				"resource1": {
   188  					NUMANodeAffinity: NewTestBitMask(0),
   189  					Preferred:        true,
   190  				},
   191  				"resource2": {
   192  					NUMANodeAffinity: NewTestBitMask(0),
   193  					Preferred:        true,
   194  				},
   195  			},
   196  		},
   197  		{
   198  			name: "Two providers, 1 with 2 hints, 1 with single hint matching 2/2",
   199  			hp: []HintProvider{
   200  				&mockHintProvider{
   201  					map[string][]TopologyHint{
   202  						"resource1": {
   203  							{
   204  								NUMANodeAffinity: NewTestBitMask(0),
   205  								Preferred:        true,
   206  							},
   207  							{
   208  								NUMANodeAffinity: NewTestBitMask(1),
   209  								Preferred:        true,
   210  							},
   211  						},
   212  					},
   213  				},
   214  				&mockHintProvider{
   215  					map[string][]TopologyHint{
   216  						"resource2": {
   217  							{
   218  								NUMANodeAffinity: NewTestBitMask(1),
   219  								Preferred:        true,
   220  							},
   221  						},
   222  					},
   223  				},
   224  			},
   225  			expected: map[string]TopologyHint{
   226  				"resource1": {
   227  					NUMANodeAffinity: NewTestBitMask(1),
   228  					Preferred:        true,
   229  				},
   230  				"resource2": {
   231  					NUMANodeAffinity: NewTestBitMask(1),
   232  					Preferred:        true,
   233  				},
   234  			},
   235  		},
   236  		{
   237  			name: "Two providers, both with 2 hints, matching narrower preferred hint from both",
   238  			hp: []HintProvider{
   239  				&mockHintProvider{
   240  					map[string][]TopologyHint{
   241  						"resource1": {
   242  							{
   243  								NUMANodeAffinity: NewTestBitMask(0),
   244  								Preferred:        true,
   245  							},
   246  							{
   247  								NUMANodeAffinity: NewTestBitMask(1),
   248  								Preferred:        true,
   249  							},
   250  						},
   251  					},
   252  				},
   253  				&mockHintProvider{
   254  					map[string][]TopologyHint{
   255  						"resource2": {
   256  							{
   257  								NUMANodeAffinity: NewTestBitMask(0),
   258  								Preferred:        true,
   259  							},
   260  							{
   261  								NUMANodeAffinity: NewTestBitMask(0, 1),
   262  								Preferred:        false,
   263  							},
   264  						},
   265  					},
   266  				},
   267  			},
   268  			expected: map[string]TopologyHint{
   269  				"resource1": {
   270  					NUMANodeAffinity: NewTestBitMask(0),
   271  					Preferred:        true,
   272  				},
   273  				"resource2": {
   274  					NUMANodeAffinity: NewTestBitMask(0),
   275  					Preferred:        true,
   276  				},
   277  			},
   278  		},
   279  		{
   280  			name: "Ensure less narrow preferred hints are chosen over narrower non-preferred hints",
   281  			hp: []HintProvider{
   282  				&mockHintProvider{
   283  					map[string][]TopologyHint{
   284  						"resource1": {
   285  							{
   286  								NUMANodeAffinity: NewTestBitMask(1),
   287  								Preferred:        true,
   288  							},
   289  							{
   290  								NUMANodeAffinity: NewTestBitMask(0, 1),
   291  								Preferred:        false,
   292  							},
   293  						},
   294  					},
   295  				},
   296  				&mockHintProvider{
   297  					map[string][]TopologyHint{
   298  						"resource2": {
   299  							{
   300  								NUMANodeAffinity: NewTestBitMask(0),
   301  								Preferred:        true,
   302  							},
   303  							{
   304  								NUMANodeAffinity: NewTestBitMask(1),
   305  								Preferred:        true,
   306  							},
   307  							{
   308  								NUMANodeAffinity: NewTestBitMask(0, 1),
   309  								Preferred:        false,
   310  							},
   311  						},
   312  					},
   313  				},
   314  			},
   315  			expected: map[string]TopologyHint{
   316  				"resource1": {
   317  					NUMANodeAffinity: NewTestBitMask(1),
   318  					Preferred:        true,
   319  				},
   320  				"resource2": {
   321  					NUMANodeAffinity: NewTestBitMask(1),
   322  					Preferred:        true,
   323  				},
   324  			},
   325  		},
   326  		{
   327  			name: "Multiple resources, same provider",
   328  			hp: []HintProvider{
   329  				&mockHintProvider{
   330  					map[string][]TopologyHint{
   331  						"resource1": {
   332  							{
   333  								NUMANodeAffinity: NewTestBitMask(1),
   334  								Preferred:        true,
   335  							},
   336  							{
   337  								NUMANodeAffinity: NewTestBitMask(0, 1),
   338  								Preferred:        false,
   339  							},
   340  						},
   341  						"resource2": {
   342  							{
   343  								NUMANodeAffinity: NewTestBitMask(0),
   344  								Preferred:        true,
   345  							},
   346  							{
   347  								NUMANodeAffinity: NewTestBitMask(1),
   348  								Preferred:        true,
   349  							},
   350  							{
   351  								NUMANodeAffinity: NewTestBitMask(0, 1),
   352  								Preferred:        false,
   353  							},
   354  						},
   355  					},
   356  				},
   357  			},
   358  			expected: map[string]TopologyHint{
   359  				"resource1": {
   360  					NUMANodeAffinity: NewTestBitMask(1),
   361  					Preferred:        true,
   362  				},
   363  				"resource2": {
   364  					NUMANodeAffinity: NewTestBitMask(1),
   365  					Preferred:        true,
   366  				},
   367  			},
   368  		},
   369  	}
   370  }
   371  
   372  func (p *bestEffortPolicy) mergeTestCases(numaNodes []int) []policyMergeTestCase {
   373  	return []policyMergeTestCase{
   374  		{
   375  			name: "Two providers, 2 hints each, same mask (some with different bits), same preferred",
   376  			hp: []HintProvider{
   377  				&mockHintProvider{
   378  					map[string][]TopologyHint{
   379  						"resource1": {
   380  							{
   381  								NUMANodeAffinity: NewTestBitMask(0, 1),
   382  								Preferred:        true,
   383  							},
   384  							{
   385  								NUMANodeAffinity: NewTestBitMask(0, 2),
   386  								Preferred:        true,
   387  							},
   388  						},
   389  					},
   390  				},
   391  				&mockHintProvider{
   392  					map[string][]TopologyHint{
   393  						"resource2": {
   394  							{
   395  								NUMANodeAffinity: NewTestBitMask(0, 1),
   396  								Preferred:        true,
   397  							},
   398  							{
   399  								NUMANodeAffinity: NewTestBitMask(0, 2),
   400  								Preferred:        true,
   401  							},
   402  						},
   403  					},
   404  				},
   405  			},
   406  			expected: map[string]TopologyHint{
   407  				"resource1": {
   408  					NUMANodeAffinity: NewTestBitMask(0, 1),
   409  					Preferred:        true,
   410  				},
   411  				"resource2": {
   412  					NUMANodeAffinity: NewTestBitMask(0, 1),
   413  					Preferred:        true,
   414  				},
   415  			},
   416  		},
   417  		{
   418  			name: "TopologyHint not set",
   419  			hp:   []HintProvider{},
   420  			expected: map[string]TopologyHint{
   421  				defaultResourceKey: {
   422  					NUMANodeAffinity: NewTestBitMask(numaNodes...),
   423  					Preferred:        true,
   424  				},
   425  			},
   426  		},
   427  		{
   428  			name: "HintProvider returns empty non-nil map[string][]TopologyHint",
   429  			hp: []HintProvider{
   430  				&mockHintProvider{
   431  					map[string][]TopologyHint{},
   432  				},
   433  			},
   434  			expected: map[string]TopologyHint{
   435  				defaultResourceKey: {
   436  					NUMANodeAffinity: NewTestBitMask(numaNodes...),
   437  					Preferred:        true,
   438  				},
   439  			},
   440  		},
   441  		{
   442  			name: "HintProvider returns -nil map[string][]TopologyHint from provider",
   443  			hp: []HintProvider{
   444  				&mockHintProvider{
   445  					map[string][]TopologyHint{
   446  						"resource": nil,
   447  					},
   448  				},
   449  			},
   450  			expected: map[string]TopologyHint{
   451  				"resource": {
   452  					NUMANodeAffinity: NewTestBitMask(numaNodes...),
   453  					Preferred:        true,
   454  				},
   455  			},
   456  		},
   457  		{
   458  			name: "HintProvider returns empty non-nil map[string][]TopologyHint from provider", hp: []HintProvider{
   459  				&mockHintProvider{
   460  					map[string][]TopologyHint{
   461  						"resource": {},
   462  					},
   463  				},
   464  			},
   465  			expected: map[string]TopologyHint{
   466  				"resource": {
   467  					NUMANodeAffinity: NewTestBitMask(numaNodes...),
   468  					Preferred:        false,
   469  				},
   470  			},
   471  		},
   472  		{
   473  			name: "Single TopologyHint with Preferred as true and NUMANodeAffinity as nil",
   474  			hp: []HintProvider{
   475  				&mockHintProvider{
   476  					map[string][]TopologyHint{
   477  						"resource": {
   478  							{
   479  								NUMANodeAffinity: nil,
   480  								Preferred:        true,
   481  							},
   482  						},
   483  					},
   484  				},
   485  			},
   486  			expected: map[string]TopologyHint{
   487  				"resource": {
   488  					NUMANodeAffinity: NewTestBitMask(numaNodes...),
   489  					Preferred:        true,
   490  				},
   491  			},
   492  		},
   493  		{
   494  			name: "Single TopologyHint with Preferred as false and NUMANodeAffinity as nil",
   495  			hp: []HintProvider{
   496  				&mockHintProvider{
   497  					map[string][]TopologyHint{
   498  						"resource": {
   499  							{
   500  								NUMANodeAffinity: nil,
   501  								Preferred:        false,
   502  							},
   503  						},
   504  					},
   505  				},
   506  			},
   507  			expected: map[string]TopologyHint{
   508  				"resource": {
   509  					NUMANodeAffinity: NewTestBitMask(numaNodes...),
   510  					Preferred:        false,
   511  				},
   512  			},
   513  		},
   514  		{
   515  			name: "Two providers, 1 hint each, no common mask",
   516  			hp: []HintProvider{
   517  				&mockHintProvider{
   518  					map[string][]TopologyHint{
   519  						"resource1": {
   520  							{
   521  								NUMANodeAffinity: NewTestBitMask(0),
   522  								Preferred:        true,
   523  							},
   524  						},
   525  					},
   526  				},
   527  				&mockHintProvider{
   528  					map[string][]TopologyHint{
   529  						"resource2": {
   530  							{
   531  								NUMANodeAffinity: NewTestBitMask(1),
   532  								Preferred:        true,
   533  							},
   534  						},
   535  					},
   536  				},
   537  			},
   538  			expected: map[string]TopologyHint{
   539  				"resource1": {
   540  					NUMANodeAffinity: NewTestBitMask(numaNodes...),
   541  					Preferred:        false,
   542  				},
   543  				"resource2": {
   544  					NUMANodeAffinity: NewTestBitMask(numaNodes...),
   545  					Preferred:        false,
   546  				},
   547  			},
   548  		},
   549  		{
   550  			name: "Two providers, 1 hint each, same mask, 1 preferred, 1 not 1/2",
   551  			hp: []HintProvider{
   552  				&mockHintProvider{
   553  					map[string][]TopologyHint{
   554  						"resource1": {
   555  							{
   556  								NUMANodeAffinity: NewTestBitMask(0),
   557  								Preferred:        true,
   558  							},
   559  						},
   560  					},
   561  				},
   562  				&mockHintProvider{
   563  					map[string][]TopologyHint{
   564  						"resource2": {
   565  							{
   566  								NUMANodeAffinity: NewTestBitMask(0),
   567  								Preferred:        false,
   568  							},
   569  						},
   570  					},
   571  				},
   572  			},
   573  			expected: map[string]TopologyHint{
   574  				"resource1": {
   575  					NUMANodeAffinity: NewTestBitMask(0),
   576  					Preferred:        false,
   577  				},
   578  				"resource2": {
   579  					NUMANodeAffinity: NewTestBitMask(0),
   580  					Preferred:        false,
   581  				},
   582  			},
   583  		},
   584  		{
   585  			name: "Two providers, 1 hint each, same mask, 1 preferred, 1 not 2/2",
   586  			hp: []HintProvider{
   587  				&mockHintProvider{
   588  					map[string][]TopologyHint{
   589  						"resource1": {
   590  							{
   591  								NUMANodeAffinity: NewTestBitMask(1),
   592  								Preferred:        true,
   593  							},
   594  						},
   595  					},
   596  				},
   597  				&mockHintProvider{
   598  					map[string][]TopologyHint{
   599  						"resource2": {
   600  							{
   601  								NUMANodeAffinity: NewTestBitMask(1),
   602  								Preferred:        false,
   603  							},
   604  						},
   605  					},
   606  				},
   607  			},
   608  			expected: map[string]TopologyHint{
   609  				"resource1": {
   610  					NUMANodeAffinity: NewTestBitMask(1),
   611  					Preferred:        false,
   612  				},
   613  				"resource2": {
   614  					NUMANodeAffinity: NewTestBitMask(1),
   615  					Preferred:        false,
   616  				},
   617  			},
   618  		},
   619  		{
   620  			name: "Two providers, 1 hint each, 1 wider mask, both preferred 1/2",
   621  			hp: []HintProvider{
   622  				&mockHintProvider{
   623  					map[string][]TopologyHint{
   624  						"resource1": {
   625  							{
   626  								NUMANodeAffinity: NewTestBitMask(0),
   627  								Preferred:        true,
   628  							},
   629  						},
   630  					},
   631  				},
   632  				&mockHintProvider{
   633  					map[string][]TopologyHint{
   634  						"resource2": {
   635  							{
   636  								NUMANodeAffinity: NewTestBitMask(0, 1),
   637  								Preferred:        true,
   638  							},
   639  						},
   640  					},
   641  				},
   642  			},
   643  			expected: map[string]TopologyHint{
   644  				"resource1": {
   645  					NUMANodeAffinity: NewTestBitMask(0),
   646  					Preferred:        false,
   647  				},
   648  				"resource2": {
   649  					NUMANodeAffinity: NewTestBitMask(0),
   650  					Preferred:        false,
   651  				},
   652  			},
   653  		},
   654  		{
   655  			name: "Two providers, 1 with 2 hints, 1 with single non-preferred hint matching",
   656  			hp: []HintProvider{
   657  				&mockHintProvider{
   658  					map[string][]TopologyHint{
   659  						"resource1": {
   660  							{
   661  								NUMANodeAffinity: NewTestBitMask(0),
   662  								Preferred:        true,
   663  							},
   664  							{
   665  								NUMANodeAffinity: NewTestBitMask(1),
   666  								Preferred:        true,
   667  							},
   668  						},
   669  					},
   670  				},
   671  				&mockHintProvider{
   672  					map[string][]TopologyHint{
   673  						"resource2": {
   674  							{
   675  								NUMANodeAffinity: NewTestBitMask(0, 1),
   676  								Preferred:        false,
   677  							},
   678  						},
   679  					},
   680  				},
   681  			},
   682  			expected: map[string]TopologyHint{
   683  				"resource1": {
   684  					NUMANodeAffinity: NewTestBitMask(0),
   685  					Preferred:        false,
   686  				},
   687  				"resource2": {
   688  					NUMANodeAffinity: NewTestBitMask(0),
   689  					Preferred:        false,
   690  				},
   691  			},
   692  		},
   693  		{
   694  			name: "Two providers, 1 hint each, 1 wider mask, both preferred 2/2",
   695  			hp: []HintProvider{
   696  				&mockHintProvider{
   697  					map[string][]TopologyHint{
   698  						"resource1": {
   699  							{
   700  								NUMANodeAffinity: NewTestBitMask(1),
   701  								Preferred:        true,
   702  							},
   703  						},
   704  					},
   705  				},
   706  				&mockHintProvider{
   707  					map[string][]TopologyHint{
   708  						"resource2": {
   709  							{
   710  								NUMANodeAffinity: NewTestBitMask(0, 1),
   711  								Preferred:        true,
   712  							},
   713  						},
   714  					},
   715  				},
   716  			},
   717  			expected: map[string]TopologyHint{
   718  				"resource1": {
   719  					NUMANodeAffinity: NewTestBitMask(1),
   720  					Preferred:        false,
   721  				},
   722  				"resource2": {
   723  					NUMANodeAffinity: NewTestBitMask(1),
   724  					Preferred:        false,
   725  				},
   726  			},
   727  		},
   728  		{
   729  			name: "bestNonPreferredAffinityCount (1)",
   730  			hp: []HintProvider{
   731  				&mockHintProvider{
   732  					map[string][]TopologyHint{
   733  						"resource1": {
   734  							{
   735  								NUMANodeAffinity: NewTestBitMask(0, 1, 2, 3),
   736  								Preferred:        false,
   737  							},
   738  							{
   739  								NUMANodeAffinity: NewTestBitMask(0, 1),
   740  								Preferred:        false,
   741  							},
   742  						},
   743  					},
   744  				},
   745  				&mockHintProvider{
   746  					map[string][]TopologyHint{
   747  						"resource2": {
   748  							{
   749  								NUMANodeAffinity: NewTestBitMask(0, 1),
   750  								Preferred:        false,
   751  							},
   752  						},
   753  					},
   754  				},
   755  			},
   756  			expected: map[string]TopologyHint{
   757  				"resource1": {
   758  					NUMANodeAffinity: NewTestBitMask(0, 1),
   759  					Preferred:        false,
   760  				},
   761  				"resource2": {
   762  					NUMANodeAffinity: NewTestBitMask(0, 1),
   763  					Preferred:        false,
   764  				},
   765  			},
   766  		},
   767  		{
   768  			name: "bestNonPreferredAffinityCount (2)",
   769  			hp: []HintProvider{
   770  				&mockHintProvider{
   771  					map[string][]TopologyHint{
   772  						"resource1": {
   773  							{
   774  								NUMANodeAffinity: NewTestBitMask(0, 1, 2, 3),
   775  								Preferred:        false,
   776  							},
   777  							{
   778  								NUMANodeAffinity: NewTestBitMask(0, 1),
   779  								Preferred:        false,
   780  							},
   781  						},
   782  					},
   783  				},
   784  				&mockHintProvider{
   785  					map[string][]TopologyHint{
   786  						"resource2": {
   787  							{
   788  								NUMANodeAffinity: NewTestBitMask(0, 3),
   789  								Preferred:        false,
   790  							},
   791  						},
   792  					},
   793  				},
   794  			},
   795  			expected: map[string]TopologyHint{
   796  				"resource1": {
   797  					NUMANodeAffinity: NewTestBitMask(0, 3),
   798  					Preferred:        false,
   799  				},
   800  				"resource2": {
   801  					NUMANodeAffinity: NewTestBitMask(0, 3),
   802  					Preferred:        false,
   803  				},
   804  			},
   805  		},
   806  		{
   807  			name: "bestNonPreferredAffinityCount (3)",
   808  			hp: []HintProvider{
   809  				&mockHintProvider{
   810  					map[string][]TopologyHint{
   811  						"resource1": {
   812  							{
   813  								NUMANodeAffinity: NewTestBitMask(0, 1, 2, 3),
   814  								Preferred:        false,
   815  							},
   816  							{
   817  								NUMANodeAffinity: NewTestBitMask(0, 1),
   818  								Preferred:        false,
   819  							},
   820  						},
   821  					},
   822  				},
   823  				&mockHintProvider{
   824  					map[string][]TopologyHint{
   825  						"resource2": {
   826  							{
   827  								NUMANodeAffinity: NewTestBitMask(1, 2),
   828  								Preferred:        false,
   829  							},
   830  						},
   831  					},
   832  				},
   833  			},
   834  			expected: map[string]TopologyHint{
   835  				"resource1": {
   836  					NUMANodeAffinity: NewTestBitMask(1, 2),
   837  					Preferred:        false,
   838  				},
   839  				"resource2": {
   840  					NUMANodeAffinity: NewTestBitMask(1, 2),
   841  					Preferred:        false,
   842  				},
   843  			},
   844  		},
   845  		{
   846  			name: "bestNonPreferredAffinityCount (4)",
   847  			hp: []HintProvider{
   848  				&mockHintProvider{
   849  					map[string][]TopologyHint{
   850  						"resource1": {
   851  							{
   852  								NUMANodeAffinity: NewTestBitMask(0, 1, 2, 3),
   853  								Preferred:        false,
   854  							},
   855  							{
   856  								NUMANodeAffinity: NewTestBitMask(0, 1),
   857  								Preferred:        false,
   858  							},
   859  						},
   860  					},
   861  				},
   862  				&mockHintProvider{
   863  					map[string][]TopologyHint{
   864  						"resource2": {
   865  							{
   866  								NUMANodeAffinity: NewTestBitMask(2, 3),
   867  								Preferred:        false,
   868  							},
   869  						},
   870  					},
   871  				},
   872  			},
   873  			expected: map[string]TopologyHint{
   874  				"resource1": {
   875  					NUMANodeAffinity: NewTestBitMask(2, 3),
   876  					Preferred:        false,
   877  				},
   878  				"resource2": {
   879  					NUMANodeAffinity: NewTestBitMask(2, 3),
   880  					Preferred:        false,
   881  				},
   882  			},
   883  		},
   884  		{
   885  			name: "bestNonPreferredAffinityCount (5)",
   886  			hp: []HintProvider{
   887  				&mockHintProvider{
   888  					map[string][]TopologyHint{
   889  						"resource1": {
   890  							{
   891  								NUMANodeAffinity: NewTestBitMask(0, 1, 2, 3),
   892  								Preferred:        false,
   893  							},
   894  							{
   895  								NUMANodeAffinity: NewTestBitMask(0, 1),
   896  								Preferred:        false,
   897  							},
   898  						},
   899  					},
   900  				},
   901  				&mockHintProvider{
   902  					map[string][]TopologyHint{
   903  						"resource2": {
   904  							{
   905  								NUMANodeAffinity: NewTestBitMask(1, 2),
   906  								Preferred:        false,
   907  							},
   908  							{
   909  								NUMANodeAffinity: NewTestBitMask(2, 3),
   910  								Preferred:        false,
   911  							},
   912  						},
   913  					},
   914  				},
   915  			},
   916  			expected: map[string]TopologyHint{
   917  				"resource1": {
   918  					NUMANodeAffinity: NewTestBitMask(1, 2),
   919  					Preferred:        false,
   920  				},
   921  				"resource2": {
   922  					NUMANodeAffinity: NewTestBitMask(1, 2),
   923  					Preferred:        false,
   924  				},
   925  			},
   926  		},
   927  		{
   928  			name: "bestNonPreferredAffinityCount (6)",
   929  			hp: []HintProvider{
   930  				&mockHintProvider{
   931  					map[string][]TopologyHint{
   932  						"resource1": {
   933  							{
   934  								NUMANodeAffinity: NewTestBitMask(0, 1, 2, 3),
   935  								Preferred:        false,
   936  							},
   937  							{
   938  								NUMANodeAffinity: NewTestBitMask(0, 1),
   939  								Preferred:        false,
   940  							},
   941  						},
   942  					},
   943  				},
   944  				&mockHintProvider{
   945  					map[string][]TopologyHint{
   946  						"resource2": {
   947  							{
   948  								NUMANodeAffinity: NewTestBitMask(1, 2, 3),
   949  								Preferred:        false,
   950  							},
   951  							{
   952  								NUMANodeAffinity: NewTestBitMask(1, 2),
   953  								Preferred:        false,
   954  							},
   955  							{
   956  								NUMANodeAffinity: NewTestBitMask(1, 3),
   957  								Preferred:        false,
   958  							},
   959  							{
   960  								NUMANodeAffinity: NewTestBitMask(2, 3),
   961  								Preferred:        false,
   962  							},
   963  						},
   964  					},
   965  				},
   966  			},
   967  			expected: map[string]TopologyHint{
   968  				"resource1": {
   969  					NUMANodeAffinity: NewTestBitMask(1, 2),
   970  					Preferred:        false,
   971  				},
   972  				"resource2": {
   973  					NUMANodeAffinity: NewTestBitMask(1, 2),
   974  					Preferred:        false,
   975  				},
   976  			},
   977  		},
   978  	}
   979  }
   980  
   981  func (p *singleNumaNodePolicy) mergeTestCases(numaNodes []int) []policyMergeTestCase {
   982  	return []policyMergeTestCase{
   983  		{
   984  			name: "TopologyHint not set",
   985  			hp:   []HintProvider{},
   986  			expected: map[string]TopologyHint{
   987  				defaultResourceKey: {
   988  					NUMANodeAffinity: nil,
   989  					Preferred:        true,
   990  				},
   991  			},
   992  		},
   993  		{
   994  			name: "HintProvider returns empty non-nil map[string][]TopologyHint",
   995  			hp: []HintProvider{
   996  				&mockHintProvider{
   997  					map[string][]TopologyHint{},
   998  				},
   999  			},
  1000  			expected: map[string]TopologyHint{
  1001  				defaultResourceKey: {
  1002  					NUMANodeAffinity: nil,
  1003  					Preferred:        true,
  1004  				},
  1005  			},
  1006  		},
  1007  		{
  1008  			name: "HintProvider returns -nil map[string][]TopologyHint from provider",
  1009  			hp: []HintProvider{
  1010  				&mockHintProvider{
  1011  					map[string][]TopologyHint{
  1012  						"resource": nil,
  1013  					},
  1014  				},
  1015  			},
  1016  			expected: map[string]TopologyHint{
  1017  				"resource": {
  1018  					NUMANodeAffinity: nil,
  1019  					Preferred:        true,
  1020  				},
  1021  			},
  1022  		},
  1023  		{
  1024  			name: "HintProvider returns empty non-nil map[string][]TopologyHint from provider", hp: []HintProvider{
  1025  				&mockHintProvider{
  1026  					map[string][]TopologyHint{
  1027  						"resource": {},
  1028  					},
  1029  				},
  1030  			},
  1031  			expected: map[string]TopologyHint{
  1032  				"resource": {
  1033  					NUMANodeAffinity: nil,
  1034  					Preferred:        false,
  1035  				},
  1036  			},
  1037  		},
  1038  		{
  1039  			name: "Single TopologyHint with Preferred as true and NUMANodeAffinity as nil",
  1040  			hp: []HintProvider{
  1041  				&mockHintProvider{
  1042  					map[string][]TopologyHint{
  1043  						"resource": {
  1044  							{
  1045  								NUMANodeAffinity: nil,
  1046  								Preferred:        true,
  1047  							},
  1048  						},
  1049  					},
  1050  				},
  1051  			},
  1052  			expected: map[string]TopologyHint{
  1053  				"resource": {
  1054  					NUMANodeAffinity: nil,
  1055  					Preferred:        true,
  1056  				},
  1057  			},
  1058  		},
  1059  		{
  1060  			name: "Single TopologyHint with Preferred as false and NUMANodeAffinity as nil",
  1061  			hp: []HintProvider{
  1062  				&mockHintProvider{
  1063  					map[string][]TopologyHint{
  1064  						"resource": {
  1065  							{
  1066  								NUMANodeAffinity: nil,
  1067  								Preferred:        false,
  1068  							},
  1069  						},
  1070  					},
  1071  				},
  1072  			},
  1073  			expected: map[string]TopologyHint{
  1074  				"resource": {
  1075  					NUMANodeAffinity: nil,
  1076  					Preferred:        false,
  1077  				},
  1078  			},
  1079  		},
  1080  		{
  1081  			name: "Two providers, 1 hint each, no common mask",
  1082  			hp: []HintProvider{
  1083  				&mockHintProvider{
  1084  					map[string][]TopologyHint{
  1085  						"resource1": {
  1086  							{
  1087  								NUMANodeAffinity: NewTestBitMask(0),
  1088  								Preferred:        true,
  1089  							},
  1090  						},
  1091  					},
  1092  				},
  1093  				&mockHintProvider{
  1094  					map[string][]TopologyHint{
  1095  						"resource2": {
  1096  							{
  1097  								NUMANodeAffinity: NewTestBitMask(1),
  1098  								Preferred:        true,
  1099  							},
  1100  						},
  1101  					},
  1102  				},
  1103  			},
  1104  			expected: map[string]TopologyHint{
  1105  				"resource1": {
  1106  					NUMANodeAffinity: nil,
  1107  					Preferred:        false,
  1108  				},
  1109  				"resource2": {
  1110  					NUMANodeAffinity: nil,
  1111  					Preferred:        false,
  1112  				},
  1113  			},
  1114  		},
  1115  		{
  1116  			name: "Two providers, 1 hint each, same mask, 1 preferred, 1 not 1/2",
  1117  			hp: []HintProvider{
  1118  				&mockHintProvider{
  1119  					map[string][]TopologyHint{
  1120  						"resource1": {
  1121  							{
  1122  								NUMANodeAffinity: NewTestBitMask(0),
  1123  								Preferred:        true,
  1124  							},
  1125  						},
  1126  					},
  1127  				},
  1128  				&mockHintProvider{
  1129  					map[string][]TopologyHint{
  1130  						"resource2": {
  1131  							{
  1132  								NUMANodeAffinity: NewTestBitMask(0),
  1133  								Preferred:        false,
  1134  							},
  1135  						},
  1136  					},
  1137  				},
  1138  			},
  1139  			expected: map[string]TopologyHint{
  1140  				"resource1": {
  1141  					NUMANodeAffinity: nil,
  1142  					Preferred:        false,
  1143  				},
  1144  				"resource2": {
  1145  					NUMANodeAffinity: nil,
  1146  					Preferred:        false,
  1147  				},
  1148  			},
  1149  		},
  1150  		{
  1151  			name: "Two providers, 1 hint each, same mask, 1 preferred, 1 not 2/2",
  1152  			hp: []HintProvider{
  1153  				&mockHintProvider{
  1154  					map[string][]TopologyHint{
  1155  						"resource1": {
  1156  							{
  1157  								NUMANodeAffinity: NewTestBitMask(1),
  1158  								Preferred:        true,
  1159  							},
  1160  						},
  1161  					},
  1162  				},
  1163  				&mockHintProvider{
  1164  					map[string][]TopologyHint{
  1165  						"resource2": {
  1166  							{
  1167  								NUMANodeAffinity: NewTestBitMask(1),
  1168  								Preferred:        false,
  1169  							},
  1170  						},
  1171  					},
  1172  				},
  1173  			},
  1174  			expected: map[string]TopologyHint{
  1175  				"resource1": {
  1176  					NUMANodeAffinity: nil,
  1177  					Preferred:        false,
  1178  				},
  1179  				"resource2": {
  1180  					NUMANodeAffinity: nil,
  1181  					Preferred:        false,
  1182  				},
  1183  			},
  1184  		},
  1185  		{
  1186  			name: "Two providers, 1 with 2 hints, 1 with single non-preferred hint matching",
  1187  			hp: []HintProvider{
  1188  				&mockHintProvider{
  1189  					map[string][]TopologyHint{
  1190  						"resource1": {
  1191  							{
  1192  								NUMANodeAffinity: NewTestBitMask(0),
  1193  								Preferred:        true,
  1194  							},
  1195  							{
  1196  								NUMANodeAffinity: NewTestBitMask(1),
  1197  								Preferred:        true,
  1198  							},
  1199  						},
  1200  					},
  1201  				},
  1202  				&mockHintProvider{
  1203  					map[string][]TopologyHint{
  1204  						"resource2": {
  1205  							{
  1206  								NUMANodeAffinity: NewTestBitMask(0, 1),
  1207  								Preferred:        false,
  1208  							},
  1209  						},
  1210  					},
  1211  				},
  1212  			},
  1213  			expected: map[string]TopologyHint{
  1214  				"resource1": {
  1215  					NUMANodeAffinity: nil,
  1216  					Preferred:        false,
  1217  				},
  1218  				"resource2": {
  1219  					NUMANodeAffinity: nil,
  1220  					Preferred:        false,
  1221  				},
  1222  			},
  1223  		},
  1224  		{
  1225  			name: "Single NUMA hint generation",
  1226  			hp: []HintProvider{
  1227  				&mockHintProvider{
  1228  					map[string][]TopologyHint{
  1229  						"resource1": {
  1230  							{
  1231  								NUMANodeAffinity: NewTestBitMask(0, 1),
  1232  								Preferred:        true,
  1233  							},
  1234  						},
  1235  						"resource2": {
  1236  							{
  1237  								NUMANodeAffinity: NewTestBitMask(0),
  1238  								Preferred:        true,
  1239  							},
  1240  							{
  1241  								NUMANodeAffinity: NewTestBitMask(1),
  1242  								Preferred:        true,
  1243  							},
  1244  							{
  1245  								NUMANodeAffinity: NewTestBitMask(0, 1),
  1246  								Preferred:        false,
  1247  							},
  1248  						},
  1249  					},
  1250  				},
  1251  			},
  1252  			expected: map[string]TopologyHint{
  1253  				"resource1": {
  1254  					NUMANodeAffinity: nil,
  1255  					Preferred:        false,
  1256  				},
  1257  				"resource2": {
  1258  					NUMANodeAffinity: nil,
  1259  					Preferred:        false,
  1260  				},
  1261  			},
  1262  		},
  1263  		{
  1264  			name: "One no-preference provider",
  1265  			hp: []HintProvider{
  1266  				&mockHintProvider{
  1267  					map[string][]TopologyHint{
  1268  						"resource1": {
  1269  							{
  1270  								NUMANodeAffinity: NewTestBitMask(0),
  1271  								Preferred:        true,
  1272  							},
  1273  							{
  1274  								NUMANodeAffinity: NewTestBitMask(1),
  1275  								Preferred:        true,
  1276  							},
  1277  							{
  1278  								NUMANodeAffinity: NewTestBitMask(0, 1),
  1279  								Preferred:        false,
  1280  							},
  1281  						},
  1282  					},
  1283  				},
  1284  				&mockHintProvider{
  1285  					nil,
  1286  				},
  1287  			},
  1288  			expected: map[string]TopologyHint{
  1289  				"resource1": {
  1290  					NUMANodeAffinity: NewTestBitMask(0),
  1291  					Preferred:        true,
  1292  				},
  1293  				defaultResourceKey: {
  1294  					NUMANodeAffinity: NewTestBitMask(0),
  1295  					Preferred:        true,
  1296  				},
  1297  			},
  1298  		},
  1299  	}
  1300  }
  1301  
  1302  func testPolicyMerge(policy Policy, tcases []policyMergeTestCase, t *testing.T) {
  1303  	for _, tc := range tcases {
  1304  		var providersHints []map[string][]TopologyHint
  1305  		for _, provider := range tc.hp {
  1306  			hints := provider.GetTopologyHints(&v1.Pod{}, &v1.Container{})
  1307  			providersHints = append(providersHints, hints)
  1308  		}
  1309  
  1310  		actual, _ := policy.Merge(providersHints)
  1311  		if !reflect.DeepEqual(actual, tc.expected) {
  1312  			t.Errorf("%v: Expected Topology Hint to be %v, got %v:", tc.name, tc.expected, actual)
  1313  		}
  1314  	}
  1315  }
  1316  
  1317  func TestMaxOfMinAffinityCounts(t *testing.T) {
  1318  	t.Parallel()
  1319  
  1320  	tcases := []struct {
  1321  		hints    [][]TopologyHint
  1322  		expected int
  1323  	}{
  1324  		{
  1325  			[][]TopologyHint{},
  1326  			0,
  1327  		},
  1328  		{
  1329  			[][]TopologyHint{
  1330  				{
  1331  					TopologyHint{NewTestBitMask(), true},
  1332  				},
  1333  			},
  1334  			0,
  1335  		},
  1336  		{
  1337  			[][]TopologyHint{
  1338  				{
  1339  					TopologyHint{NewTestBitMask(0), true},
  1340  				},
  1341  			},
  1342  			1,
  1343  		},
  1344  		{
  1345  			[][]TopologyHint{
  1346  				{
  1347  					TopologyHint{NewTestBitMask(0, 1), true},
  1348  				},
  1349  			},
  1350  			2,
  1351  		},
  1352  		{
  1353  			[][]TopologyHint{
  1354  				{
  1355  					TopologyHint{NewTestBitMask(0, 1), true},
  1356  					TopologyHint{NewTestBitMask(0, 1, 2), true},
  1357  				},
  1358  			},
  1359  			2,
  1360  		},
  1361  		{
  1362  			[][]TopologyHint{
  1363  				{
  1364  					TopologyHint{NewTestBitMask(0, 1), true},
  1365  					TopologyHint{NewTestBitMask(0, 1, 2), true},
  1366  				},
  1367  				{
  1368  					TopologyHint{NewTestBitMask(0, 1, 2), true},
  1369  				},
  1370  			},
  1371  			3,
  1372  		},
  1373  		{
  1374  			[][]TopologyHint{
  1375  				{
  1376  					TopologyHint{NewTestBitMask(0, 1), true},
  1377  					TopologyHint{NewTestBitMask(0, 1, 2), true},
  1378  				},
  1379  				{
  1380  					TopologyHint{NewTestBitMask(0, 1, 2), true},
  1381  					TopologyHint{NewTestBitMask(0, 1, 2, 3), true},
  1382  				},
  1383  			},
  1384  			3,
  1385  		},
  1386  	}
  1387  
  1388  	for _, tc := range tcases {
  1389  		tc := tc
  1390  		t.Run("", func(t *testing.T) {
  1391  			t.Parallel()
  1392  			result := maxOfMinAffinityCounts(tc.hints)
  1393  			if result != tc.expected {
  1394  				t.Errorf("Expected result to be %v, got %v", tc.expected, result)
  1395  			}
  1396  		})
  1397  	}
  1398  }
  1399  
  1400  func TestCompareHints(t *testing.T) {
  1401  	t.Parallel()
  1402  
  1403  	tcases := []struct {
  1404  		description                   string
  1405  		bestNonPreferredAffinityCount int
  1406  		current                       *TopologyHint
  1407  		candidate                     *TopologyHint
  1408  		expected                      string
  1409  	}{
  1410  		{
  1411  			"candidate.NUMANodeAffinity.Count() == 0 (1)",
  1412  			-1,
  1413  			nil,
  1414  			&TopologyHint{bitmask.NewEmptyBitMask(), false},
  1415  			"current",
  1416  		},
  1417  		{
  1418  			"candidate.NUMANodeAffinity.Count() == 0 (2)",
  1419  			-1,
  1420  			&TopologyHint{NewTestBitMask(), true},
  1421  			&TopologyHint{NewTestBitMask(), false},
  1422  			"current",
  1423  		},
  1424  		{
  1425  			"current == nil (1)",
  1426  			-1,
  1427  			nil,
  1428  			&TopologyHint{NewTestBitMask(0), true},
  1429  			"candidate",
  1430  		},
  1431  		{
  1432  			"current == nil (2)",
  1433  			-1,
  1434  			nil,
  1435  			&TopologyHint{NewTestBitMask(0), false},
  1436  			"candidate",
  1437  		},
  1438  		{
  1439  			"!current.Preferred && candidate.Preferred",
  1440  			-1,
  1441  			&TopologyHint{NewTestBitMask(0), false},
  1442  			&TopologyHint{NewTestBitMask(0), true},
  1443  			"candidate",
  1444  		},
  1445  		{
  1446  			"current.Preferred && !candidate.Preferred",
  1447  			-1,
  1448  			&TopologyHint{NewTestBitMask(0), true},
  1449  			&TopologyHint{NewTestBitMask(0), false},
  1450  			"current",
  1451  		},
  1452  		{
  1453  			"current.Preferred && candidate.Preferred (1)",
  1454  			-1,
  1455  			&TopologyHint{NewTestBitMask(0), true},
  1456  			&TopologyHint{NewTestBitMask(0), true},
  1457  			"current",
  1458  		},
  1459  		{
  1460  			"current.Preferred && candidate.Preferred (2)",
  1461  			-1,
  1462  			&TopologyHint{NewTestBitMask(0, 1), true},
  1463  			&TopologyHint{NewTestBitMask(0), true},
  1464  			"candidate",
  1465  		},
  1466  		{
  1467  			"current.Preferred && candidate.Preferred (3)",
  1468  			-1,
  1469  			&TopologyHint{NewTestBitMask(0), true},
  1470  			&TopologyHint{NewTestBitMask(0, 1), true},
  1471  			"current",
  1472  		},
  1473  		{
  1474  			"!current.Preferred && !candidate.Preferred (1.1)",
  1475  			1,
  1476  			&TopologyHint{NewTestBitMask(0, 1), false},
  1477  			&TopologyHint{NewTestBitMask(0, 1), false},
  1478  			"current",
  1479  		},
  1480  		{
  1481  			"!current.Preferred && !candidate.Preferred (1.2)",
  1482  			1,
  1483  			&TopologyHint{NewTestBitMask(1, 2), false},
  1484  			&TopologyHint{NewTestBitMask(0, 1), false},
  1485  			"candidate",
  1486  		},
  1487  		{
  1488  			"!current.Preferred && !candidate.Preferred (1.3)",
  1489  			1,
  1490  			&TopologyHint{NewTestBitMask(0, 1), false},
  1491  			&TopologyHint{NewTestBitMask(1, 2), false},
  1492  			"current",
  1493  		},
  1494  		{
  1495  			"!current.Preferred && !candidate.Preferred (2.1)",
  1496  			2,
  1497  			&TopologyHint{NewTestBitMask(0, 1), false},
  1498  			&TopologyHint{NewTestBitMask(0), false},
  1499  			"current",
  1500  		},
  1501  		{
  1502  			"!current.Preferred && !candidate.Preferred (2.2)",
  1503  			2,
  1504  			&TopologyHint{NewTestBitMask(0, 1), false},
  1505  			&TopologyHint{NewTestBitMask(0, 1), false},
  1506  			"current",
  1507  		},
  1508  		{
  1509  			"!current.Preferred && !candidate.Preferred (2.3)",
  1510  			2,
  1511  			&TopologyHint{NewTestBitMask(1, 2), false},
  1512  			&TopologyHint{NewTestBitMask(0, 1), false},
  1513  			"candidate",
  1514  		},
  1515  		{
  1516  			"!current.Preferred && !candidate.Preferred (2.4)",
  1517  			2,
  1518  			&TopologyHint{NewTestBitMask(0, 1), false},
  1519  			&TopologyHint{NewTestBitMask(1, 2), false},
  1520  			"current",
  1521  		},
  1522  		{
  1523  			"!current.Preferred && !candidate.Preferred (3a)",
  1524  			2,
  1525  			&TopologyHint{NewTestBitMask(0), false},
  1526  			&TopologyHint{NewTestBitMask(0, 1, 2), false},
  1527  			"current",
  1528  		},
  1529  		{
  1530  			"!current.Preferred && !candidate.Preferred (3b)",
  1531  			2,
  1532  			&TopologyHint{NewTestBitMask(0), false},
  1533  			&TopologyHint{NewTestBitMask(0, 1), false},
  1534  			"candidate",
  1535  		},
  1536  		{
  1537  			"!current.Preferred && !candidate.Preferred (3ca.1)",
  1538  			3,
  1539  			&TopologyHint{NewTestBitMask(0), false},
  1540  			&TopologyHint{NewTestBitMask(0, 1), false},
  1541  			"candidate",
  1542  		},
  1543  		{
  1544  			"!current.Preferred && !candidate.Preferred (3ca.2)",
  1545  			3,
  1546  			&TopologyHint{NewTestBitMask(0), false},
  1547  			&TopologyHint{NewTestBitMask(1, 2), false},
  1548  			"candidate",
  1549  		},
  1550  		{
  1551  			"!current.Preferred && !candidate.Preferred (3ca.3)",
  1552  			4,
  1553  			&TopologyHint{NewTestBitMask(0, 1), false},
  1554  			&TopologyHint{NewTestBitMask(1, 2, 3), false},
  1555  			"candidate",
  1556  		},
  1557  		{
  1558  			"!current.Preferred && !candidate.Preferred (3cb)",
  1559  			4,
  1560  			&TopologyHint{NewTestBitMask(1, 2, 3), false},
  1561  			&TopologyHint{NewTestBitMask(0, 1), false},
  1562  			"current",
  1563  		},
  1564  		{
  1565  			"!current.Preferred && !candidate.Preferred (3cc.1)",
  1566  			4,
  1567  			&TopologyHint{NewTestBitMask(0, 1, 2), false},
  1568  			&TopologyHint{NewTestBitMask(0, 1, 2), false},
  1569  			"current",
  1570  		},
  1571  		{
  1572  			"!current.Preferred && !candidate.Preferred (3cc.2)",
  1573  			4,
  1574  			&TopologyHint{NewTestBitMask(0, 1, 2), false},
  1575  			&TopologyHint{NewTestBitMask(1, 2, 3), false},
  1576  			"current",
  1577  		},
  1578  		{
  1579  			"!current.Preferred && !candidate.Preferred (3cc.3)",
  1580  			4,
  1581  			&TopologyHint{NewTestBitMask(1, 2, 3), false},
  1582  			&TopologyHint{NewTestBitMask(0, 1, 2), false},
  1583  			"candidate",
  1584  		},
  1585  	}
  1586  
  1587  	for _, tc := range tcases {
  1588  		tc := tc
  1589  		t.Run(tc.description, func(t *testing.T) {
  1590  			t.Parallel()
  1591  
  1592  			result := compareHints(tc.bestNonPreferredAffinityCount, tc.current, tc.candidate)
  1593  			if result != tc.current && result != tc.candidate {
  1594  				t.Errorf("Expected result to be either 'current' or 'candidate' hint")
  1595  			}
  1596  			if tc.expected == "current" && result != tc.current {
  1597  				t.Errorf("Expected result to be %v, got %v", tc.current, result)
  1598  			}
  1599  			if tc.expected == "candidate" && result != tc.candidate {
  1600  				t.Errorf("Expected result to be %v, got %v", tc.candidate, result)
  1601  			}
  1602  		})
  1603  	}
  1604  }