...

Source file src/k8s.io/kubernetes/pkg/kubelet/cm/memorymanager/policy_static_test.go

Documentation: k8s.io/kubernetes/pkg/kubelet/cm/memorymanager

     1  /*
     2  Copyright 2020 The Kubernetes 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 memorymanager
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"k8s.io/klog/v2"
    25  
    26  	cadvisorapi "github.com/google/cadvisor/info/v1"
    27  	"github.com/google/go-cmp/cmp"
    28  
    29  	v1 "k8s.io/api/core/v1"
    30  	"k8s.io/apimachinery/pkg/api/resource"
    31  	"k8s.io/kubernetes/pkg/kubelet/cm/memorymanager/state"
    32  	"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager"
    33  	"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager/bitmask"
    34  )
    35  
    36  const (
    37  	mb           = 1024 * 1024
    38  	gb           = mb * 1024
    39  	pageSize1Gb  = 1048576
    40  	hugepages1Gi = v1.ResourceName(v1.ResourceHugePagesPrefix + "1Gi")
    41  )
    42  
    43  var (
    44  	containerRestartPolicyAlways = v1.ContainerRestartPolicyAlways
    45  
    46  	requirementsGuaranteed = &v1.ResourceRequirements{
    47  		Limits: v1.ResourceList{
    48  			v1.ResourceCPU:    resource.MustParse("1000Mi"),
    49  			v1.ResourceMemory: resource.MustParse("1Gi"),
    50  			hugepages1Gi:      resource.MustParse("1Gi"),
    51  		},
    52  		Requests: v1.ResourceList{
    53  			v1.ResourceCPU:    resource.MustParse("1000Mi"),
    54  			v1.ResourceMemory: resource.MustParse("1Gi"),
    55  			hugepages1Gi:      resource.MustParse("1Gi"),
    56  		},
    57  	}
    58  	requirementsBurstable = &v1.ResourceRequirements{
    59  		Limits: v1.ResourceList{
    60  			v1.ResourceCPU:    resource.MustParse("1000Mi"),
    61  			v1.ResourceMemory: resource.MustParse("2Gi"),
    62  			hugepages1Gi:      resource.MustParse("2Gi"),
    63  		},
    64  		Requests: v1.ResourceList{
    65  			v1.ResourceCPU:    resource.MustParse("1000Mi"),
    66  			v1.ResourceMemory: resource.MustParse("1Gi"),
    67  			hugepages1Gi:      resource.MustParse("1Gi"),
    68  		},
    69  	}
    70  )
    71  
    72  func areMemoryBlocksEqual(mb1, mb2 []state.Block) bool {
    73  	if len(mb1) != len(mb2) {
    74  		return false
    75  	}
    76  
    77  	copyMemoryBlocks := make([]state.Block, len(mb2))
    78  	copy(copyMemoryBlocks, mb2)
    79  	for _, block := range mb1 {
    80  		for i, copyBlock := range copyMemoryBlocks {
    81  			if reflect.DeepEqual(block, copyBlock) {
    82  				// move the element that equals to the block to the end of the slice
    83  				copyMemoryBlocks[i] = copyMemoryBlocks[len(copyMemoryBlocks)-1]
    84  
    85  				// remove the last element from our slice
    86  				copyMemoryBlocks = copyMemoryBlocks[:len(copyMemoryBlocks)-1]
    87  
    88  				break
    89  			}
    90  		}
    91  	}
    92  
    93  	return len(copyMemoryBlocks) == 0
    94  }
    95  
    96  func areContainerMemoryAssignmentsEqual(t *testing.T, cma1, cma2 state.ContainerMemoryAssignments) bool {
    97  	if len(cma1) != len(cma2) {
    98  		return false
    99  	}
   100  
   101  	for podUID, container := range cma1 {
   102  		if _, ok := cma2[podUID]; !ok {
   103  			t.Logf("[memorymanager_tests] the assignment does not have pod UID %s", podUID)
   104  			return false
   105  		}
   106  
   107  		for containerName, memoryBlocks := range container {
   108  			if _, ok := cma2[podUID][containerName]; !ok {
   109  				t.Logf("[memorymanager_tests] the assignment does not have container name %s", containerName)
   110  				return false
   111  			}
   112  
   113  			if !areMemoryBlocksEqual(memoryBlocks, cma2[podUID][containerName]) {
   114  				t.Logf("[memorymanager_tests] assignments memory blocks are different: %v != %v", memoryBlocks, cma2[podUID][containerName])
   115  				return false
   116  			}
   117  		}
   118  	}
   119  	return true
   120  }
   121  
   122  type testStaticPolicy struct {
   123  	description                  string
   124  	assignments                  state.ContainerMemoryAssignments
   125  	expectedAssignments          state.ContainerMemoryAssignments
   126  	machineState                 state.NUMANodeMap
   127  	expectedMachineState         state.NUMANodeMap
   128  	systemReserved               systemReservedMemory
   129  	expectedError                error
   130  	machineInfo                  *cadvisorapi.MachineInfo
   131  	pod                          *v1.Pod
   132  	topologyHint                 *topologymanager.TopologyHint
   133  	expectedTopologyHints        map[string][]topologymanager.TopologyHint
   134  	initContainersReusableMemory reusableMemory
   135  }
   136  
   137  func initTests(t *testing.T, testCase *testStaticPolicy, hint *topologymanager.TopologyHint, initContainersReusableMemory reusableMemory) (Policy, state.State, error) {
   138  	manager := topologymanager.NewFakeManager()
   139  	if hint != nil {
   140  		manager = topologymanager.NewFakeManagerWithHint(hint)
   141  	}
   142  
   143  	p, err := NewPolicyStatic(testCase.machineInfo, testCase.systemReserved, manager)
   144  	if err != nil {
   145  		return nil, nil, err
   146  	}
   147  	if initContainersReusableMemory != nil {
   148  		p.(*staticPolicy).initContainersReusableMemory = initContainersReusableMemory
   149  	}
   150  	s := state.NewMemoryState()
   151  	s.SetMachineState(testCase.machineState)
   152  	s.SetMemoryAssignments(testCase.assignments)
   153  	return p, s, nil
   154  }
   155  
   156  func newNUMAAffinity(bits ...int) bitmask.BitMask {
   157  	affinity, err := bitmask.NewBitMask(bits...)
   158  	if err != nil {
   159  		panic(err)
   160  	}
   161  	return affinity
   162  }
   163  
   164  func TestStaticPolicyNew(t *testing.T) {
   165  	testCases := []testStaticPolicy{
   166  		{
   167  			description:   "should fail, when machine does not have reserved memory for the system workloads",
   168  			expectedError: fmt.Errorf("[memorymanager] you should specify the system reserved memory"),
   169  		},
   170  		{
   171  			description: "should succeed, when at least one NUMA node has reserved memory",
   172  			systemReserved: systemReservedMemory{
   173  				0: map[v1.ResourceName]uint64{},
   174  				1: map[v1.ResourceName]uint64{
   175  					v1.ResourceMemory: 512 * mb,
   176  				},
   177  			},
   178  		},
   179  	}
   180  
   181  	for _, testCase := range testCases {
   182  		t.Run(testCase.description, func(t *testing.T) {
   183  			_, _, err := initTests(t, &testCase, nil, nil)
   184  			if !reflect.DeepEqual(err, testCase.expectedError) {
   185  				t.Fatalf("The actual error: %v is different from the expected one: %v", err, testCase.expectedError)
   186  			}
   187  		})
   188  	}
   189  }
   190  
   191  func TestStaticPolicyName(t *testing.T) {
   192  	testCases := []testStaticPolicy{
   193  		{
   194  			description: "should return the correct policy name",
   195  			systemReserved: systemReservedMemory{
   196  				0: map[v1.ResourceName]uint64{
   197  					v1.ResourceMemory: 512 * mb,
   198  				},
   199  			},
   200  		},
   201  	}
   202  	for _, testCase := range testCases {
   203  		t.Run(testCase.description, func(t *testing.T) {
   204  			p, _, err := initTests(t, &testCase, nil, nil)
   205  			if err != nil {
   206  				t.Fatalf("Unexpected error: %v", err)
   207  			}
   208  			if p.Name() != string(policyTypeStatic) {
   209  				t.Errorf("policy name is different, expected: %q, actual: %q", p.Name(), policyTypeStatic)
   210  			}
   211  		})
   212  	}
   213  }
   214  
   215  func TestStaticPolicyStart(t *testing.T) {
   216  	testCases := []testStaticPolicy{
   217  		{
   218  			description: "should fail, if machine state is empty, but it has memory assignments",
   219  			assignments: state.ContainerMemoryAssignments{
   220  				"pod": map[string][]state.Block{
   221  					"container1": {
   222  						{
   223  							NUMAAffinity: []int{0},
   224  							Type:         v1.ResourceMemory,
   225  							Size:         512 * mb,
   226  						},
   227  					},
   228  				},
   229  			},
   230  			systemReserved: systemReservedMemory{
   231  				0: map[v1.ResourceName]uint64{
   232  					v1.ResourceMemory: 512 * mb,
   233  				},
   234  			},
   235  			expectedError: fmt.Errorf("[memorymanager] machine state can not be empty when it has memory assignments"),
   236  		},
   237  		{
   238  			description:         "should fill the state with default values, when the state is empty",
   239  			expectedAssignments: state.ContainerMemoryAssignments{},
   240  			expectedMachineState: state.NUMANodeMap{
   241  				0: &state.NUMANodeState{
   242  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   243  						v1.ResourceMemory: {
   244  							Allocatable:    1536 * mb,
   245  							Free:           1536 * mb,
   246  							Reserved:       0,
   247  							SystemReserved: 512 * mb,
   248  							TotalMemSize:   3 * gb,
   249  						},
   250  						hugepages1Gi: {
   251  							Allocatable:    gb,
   252  							Free:           gb,
   253  							Reserved:       0,
   254  							SystemReserved: 0,
   255  							TotalMemSize:   gb,
   256  						},
   257  					},
   258  					NumberOfAssignments: 0,
   259  					Cells:               []int{0},
   260  				},
   261  			},
   262  			systemReserved: systemReservedMemory{
   263  				0: map[v1.ResourceName]uint64{
   264  					v1.ResourceMemory: 512 * mb,
   265  				},
   266  			},
   267  			machineInfo: &cadvisorapi.MachineInfo{
   268  				Topology: []cadvisorapi.Node{
   269  					{
   270  						Id:     0,
   271  						Memory: 3 * gb,
   272  						HugePages: []cadvisorapi.HugePagesInfo{
   273  							{
   274  								// size in KB
   275  								PageSize: pageSize1Gb,
   276  								NumPages: 1,
   277  							},
   278  						},
   279  					},
   280  				},
   281  			},
   282  		},
   283  		{
   284  			description: "should fail when machine state does not have all NUMA nodes",
   285  			machineState: state.NUMANodeMap{
   286  				0: &state.NUMANodeState{
   287  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   288  						v1.ResourceMemory: {
   289  							Allocatable:    1536 * mb,
   290  							Free:           1536 * mb,
   291  							Reserved:       0,
   292  							SystemReserved: 512 * mb,
   293  							TotalMemSize:   2 * gb,
   294  						},
   295  						hugepages1Gi: {
   296  							Allocatable:    gb,
   297  							Free:           gb,
   298  							Reserved:       0,
   299  							SystemReserved: 0,
   300  							TotalMemSize:   gb,
   301  						},
   302  					},
   303  					Cells:               []int{0},
   304  					NumberOfAssignments: 0,
   305  				},
   306  			},
   307  			systemReserved: systemReservedMemory{
   308  				0: map[v1.ResourceName]uint64{
   309  					v1.ResourceMemory: 512 * mb,
   310  				},
   311  			},
   312  			machineInfo: &cadvisorapi.MachineInfo{
   313  				Topology: []cadvisorapi.Node{
   314  					{
   315  						Id:     0,
   316  						Memory: 2 * gb,
   317  						HugePages: []cadvisorapi.HugePagesInfo{
   318  							{
   319  								// size in KB
   320  								PageSize: pageSize1Gb,
   321  								NumPages: 1,
   322  							},
   323  						},
   324  					},
   325  					{
   326  						Id:     1,
   327  						Memory: 2 * gb,
   328  						HugePages: []cadvisorapi.HugePagesInfo{
   329  							{
   330  								// size in KB
   331  								PageSize: pageSize1Gb,
   332  								NumPages: 1,
   333  							},
   334  						},
   335  					},
   336  				},
   337  			},
   338  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   339  		},
   340  		{
   341  			description: "should fail when machine state does not have memory resource",
   342  			machineState: state.NUMANodeMap{
   343  				0: &state.NUMANodeState{
   344  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   345  						hugepages1Gi: {
   346  							Allocatable:    gb,
   347  							Free:           gb,
   348  							Reserved:       0,
   349  							SystemReserved: 0,
   350  							TotalMemSize:   gb,
   351  						},
   352  					},
   353  					Cells:               []int{0},
   354  					NumberOfAssignments: 0,
   355  				},
   356  			},
   357  			machineInfo: &cadvisorapi.MachineInfo{
   358  				Topology: []cadvisorapi.Node{
   359  					{
   360  						Id:     0,
   361  						Memory: 2 * gb,
   362  						HugePages: []cadvisorapi.HugePagesInfo{
   363  							{
   364  								// size in KB
   365  								PageSize: pageSize1Gb,
   366  								NumPages: 1,
   367  							},
   368  						},
   369  					},
   370  				},
   371  			},
   372  			systemReserved: systemReservedMemory{
   373  				0: map[v1.ResourceName]uint64{
   374  					v1.ResourceMemory: 512 * mb,
   375  				},
   376  			},
   377  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   378  		},
   379  		{
   380  			description: "should fail when machine state has wrong size of total memory",
   381  			machineState: state.NUMANodeMap{
   382  				0: &state.NUMANodeState{
   383  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   384  						v1.ResourceMemory: {
   385  							Allocatable:    1536 * mb,
   386  							Free:           1536 * mb,
   387  							Reserved:       0,
   388  							SystemReserved: 512 * mb,
   389  							TotalMemSize:   1536 * mb,
   390  						},
   391  					},
   392  					Cells:               []int{0},
   393  					NumberOfAssignments: 0,
   394  				},
   395  			},
   396  			systemReserved: systemReservedMemory{
   397  				0: map[v1.ResourceName]uint64{
   398  					v1.ResourceMemory: 512 * mb,
   399  				},
   400  			},
   401  			machineInfo: &cadvisorapi.MachineInfo{
   402  				Topology: []cadvisorapi.Node{
   403  					{
   404  						Id:     0,
   405  						Memory: 2 * gb,
   406  						HugePages: []cadvisorapi.HugePagesInfo{
   407  							{
   408  								// size in KB
   409  								PageSize: pageSize1Gb,
   410  								NumPages: 1,
   411  							},
   412  						},
   413  					},
   414  				},
   415  			},
   416  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   417  		},
   418  		{
   419  			description: "should fail when machine state has wrong size of system reserved memory",
   420  			machineState: state.NUMANodeMap{
   421  				0: &state.NUMANodeState{
   422  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   423  						v1.ResourceMemory: {
   424  							Allocatable:    1536 * mb,
   425  							Free:           1536 * mb,
   426  							Reserved:       0,
   427  							SystemReserved: 1024,
   428  							TotalMemSize:   2 * gb,
   429  						},
   430  					},
   431  					Cells:               []int{0},
   432  					NumberOfAssignments: 0,
   433  				},
   434  			},
   435  			systemReserved: systemReservedMemory{
   436  				0: map[v1.ResourceName]uint64{
   437  					v1.ResourceMemory: 512 * mb,
   438  				},
   439  			},
   440  			machineInfo: &cadvisorapi.MachineInfo{
   441  				Topology: []cadvisorapi.Node{
   442  					{
   443  						Id:     0,
   444  						Memory: 2 * gb,
   445  						HugePages: []cadvisorapi.HugePagesInfo{
   446  							{
   447  								// size in KB
   448  								PageSize: pageSize1Gb,
   449  								NumPages: 1,
   450  							},
   451  						},
   452  					},
   453  				},
   454  			},
   455  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   456  		},
   457  		{
   458  			description: "should fail when machine state reserved memory is different from the memory of all containers memory assignments",
   459  			assignments: state.ContainerMemoryAssignments{
   460  				"pod": map[string][]state.Block{
   461  					"container1": {
   462  						{
   463  							NUMAAffinity: []int{0},
   464  							Type:         v1.ResourceMemory,
   465  							Size:         512 * mb,
   466  						},
   467  					},
   468  				},
   469  			},
   470  			machineState: state.NUMANodeMap{
   471  				0: &state.NUMANodeState{
   472  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   473  						v1.ResourceMemory: {
   474  							Allocatable:    1536 * mb,
   475  							Free:           1536 * mb,
   476  							Reserved:       0,
   477  							SystemReserved: 512 * mb,
   478  							TotalMemSize:   2 * gb,
   479  						},
   480  					},
   481  					Cells:               []int{0},
   482  					NumberOfAssignments: 1,
   483  				},
   484  			},
   485  			systemReserved: systemReservedMemory{
   486  				0: map[v1.ResourceName]uint64{
   487  					v1.ResourceMemory: 512 * mb,
   488  				},
   489  			},
   490  			machineInfo: &cadvisorapi.MachineInfo{
   491  				Topology: []cadvisorapi.Node{
   492  					{
   493  						Id:     0,
   494  						Memory: 2 * gb,
   495  						HugePages: []cadvisorapi.HugePagesInfo{
   496  							{
   497  								// size in KB
   498  								PageSize: pageSize1Gb,
   499  								NumPages: 1,
   500  							},
   501  						},
   502  					},
   503  				},
   504  			},
   505  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   506  		},
   507  		{
   508  			description: "should fail when machine state has wrong size of hugepages",
   509  			machineState: state.NUMANodeMap{
   510  				0: &state.NUMANodeState{
   511  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   512  						v1.ResourceMemory: {
   513  							Allocatable:    1536 * mb,
   514  							Free:           1536 * mb,
   515  							Reserved:       0,
   516  							SystemReserved: 512 * mb,
   517  							TotalMemSize:   2 * gb,
   518  						},
   519  						hugepages1Gi: {
   520  							Allocatable:    gb,
   521  							Free:           gb,
   522  							Reserved:       0,
   523  							SystemReserved: 0,
   524  							TotalMemSize:   gb,
   525  						},
   526  					},
   527  					Cells:               []int{0},
   528  					NumberOfAssignments: 0,
   529  				},
   530  			},
   531  			systemReserved: systemReservedMemory{
   532  				0: map[v1.ResourceName]uint64{
   533  					v1.ResourceMemory: 512 * mb,
   534  				},
   535  			},
   536  			machineInfo: &cadvisorapi.MachineInfo{
   537  				Topology: []cadvisorapi.Node{
   538  					{
   539  						Id:     0,
   540  						Memory: 2 * gb,
   541  						HugePages: []cadvisorapi.HugePagesInfo{
   542  							{
   543  								// size in KB
   544  								PageSize: pageSize1Gb,
   545  								NumPages: 2,
   546  							},
   547  						},
   548  					},
   549  				},
   550  			},
   551  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   552  		},
   553  		{
   554  			description: "should fail when machine state has wrong size of system reserved hugepages",
   555  			machineState: state.NUMANodeMap{
   556  				0: &state.NUMANodeState{
   557  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   558  						v1.ResourceMemory: {
   559  							Allocatable:    1536 * mb,
   560  							Free:           1536 * mb,
   561  							Reserved:       0,
   562  							SystemReserved: 512 * mb,
   563  							TotalMemSize:   2 * gb,
   564  						},
   565  						hugepages1Gi: {
   566  							Allocatable:    gb,
   567  							Free:           gb,
   568  							Reserved:       0,
   569  							SystemReserved: gb,
   570  							TotalMemSize:   2 * gb,
   571  						},
   572  					},
   573  					Cells:               []int{0},
   574  					NumberOfAssignments: 0,
   575  				},
   576  			},
   577  			systemReserved: systemReservedMemory{
   578  				0: map[v1.ResourceName]uint64{
   579  					v1.ResourceMemory: 512 * mb,
   580  				},
   581  			},
   582  			machineInfo: &cadvisorapi.MachineInfo{
   583  				Topology: []cadvisorapi.Node{
   584  					{
   585  						Id:     0,
   586  						Memory: 2 * gb,
   587  						HugePages: []cadvisorapi.HugePagesInfo{
   588  							{
   589  								// size in KB
   590  								PageSize: pageSize1Gb,
   591  								NumPages: 2,
   592  							},
   593  						},
   594  					},
   595  				},
   596  			},
   597  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   598  		},
   599  		{
   600  			description: "should fail when the hugepages reserved machine state is different from the hugepages of all containers memory assignments",
   601  			assignments: state.ContainerMemoryAssignments{
   602  				"pod1": map[string][]state.Block{
   603  					"container1": {
   604  						{
   605  							NUMAAffinity: []int{0},
   606  							Type:         hugepages1Gi,
   607  							Size:         gb,
   608  						},
   609  					},
   610  				},
   611  				"pod2": map[string][]state.Block{
   612  					"container2": {
   613  						{
   614  							NUMAAffinity: []int{0},
   615  							Type:         hugepages1Gi,
   616  							Size:         gb,
   617  						},
   618  					},
   619  				},
   620  			},
   621  			machineState: state.NUMANodeMap{
   622  				0: &state.NUMANodeState{
   623  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   624  						v1.ResourceMemory: {
   625  							Allocatable:    1536 * mb,
   626  							Free:           1536 * mb,
   627  							Reserved:       0,
   628  							SystemReserved: 512 * mb,
   629  							TotalMemSize:   2 * gb,
   630  						},
   631  						hugepages1Gi: {
   632  							Allocatable:    4 * gb,
   633  							Free:           gb,
   634  							Reserved:       3 * gb,
   635  							SystemReserved: 0,
   636  							TotalMemSize:   4 * gb,
   637  						},
   638  					},
   639  					Cells:               []int{0},
   640  					NumberOfAssignments: 2,
   641  				},
   642  			},
   643  			systemReserved: systemReservedMemory{
   644  				0: map[v1.ResourceName]uint64{
   645  					v1.ResourceMemory: 512 * mb,
   646  				},
   647  			},
   648  			machineInfo: &cadvisorapi.MachineInfo{
   649  				Topology: []cadvisorapi.Node{
   650  					{
   651  						Id:     0,
   652  						Memory: 2 * gb,
   653  						HugePages: []cadvisorapi.HugePagesInfo{
   654  							{
   655  								// size in KB
   656  								PageSize: pageSize1Gb,
   657  								NumPages: 4,
   658  							},
   659  						},
   660  					},
   661  				},
   662  			},
   663  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   664  		},
   665  		{
   666  			description: "should fail when machine state does not have NUMA node that used under the memory assignment",
   667  			assignments: state.ContainerMemoryAssignments{
   668  				"pod1": map[string][]state.Block{
   669  					"container1": {
   670  						{
   671  							NUMAAffinity: []int{1},
   672  							Type:         v1.ResourceMemory,
   673  							Size:         gb,
   674  						},
   675  					},
   676  				},
   677  			},
   678  			machineState: state.NUMANodeMap{
   679  				0: &state.NUMANodeState{
   680  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   681  						v1.ResourceMemory: {
   682  							Allocatable:    1536 * mb,
   683  							Free:           1536 * mb,
   684  							Reserved:       0,
   685  							SystemReserved: 512 * mb,
   686  							TotalMemSize:   2 * gb,
   687  						},
   688  						hugepages1Gi: {
   689  							Allocatable:    gb,
   690  							Free:           gb,
   691  							Reserved:       0,
   692  							SystemReserved: 0,
   693  							TotalMemSize:   gb,
   694  						},
   695  					},
   696  					Cells:               []int{0},
   697  					NumberOfAssignments: 0,
   698  				},
   699  			},
   700  			systemReserved: systemReservedMemory{
   701  				0: map[v1.ResourceName]uint64{
   702  					v1.ResourceMemory: 512 * mb,
   703  				},
   704  			},
   705  			machineInfo: &cadvisorapi.MachineInfo{
   706  				Topology: []cadvisorapi.Node{
   707  					{
   708  						Id:     0,
   709  						Memory: 2 * gb,
   710  						HugePages: []cadvisorapi.HugePagesInfo{
   711  							{
   712  								// size in KB
   713  								PageSize: pageSize1Gb,
   714  								NumPages: 1,
   715  							},
   716  						},
   717  					},
   718  				},
   719  			},
   720  			expectedError: fmt.Errorf("[memorymanager] (pod: pod1, container: container1) the memory assignment uses the NUMA that does not exist"),
   721  		},
   722  		{
   723  			description: "should fail when machine state does not have resource that used under the memory assignment",
   724  			assignments: state.ContainerMemoryAssignments{
   725  				"pod1": map[string][]state.Block{
   726  					"container1": {
   727  						{
   728  							NUMAAffinity: []int{0},
   729  							Type:         v1.ResourceMemory,
   730  							Size:         gb,
   731  						},
   732  						{
   733  							NUMAAffinity: []int{0},
   734  							Type:         hugepages2M,
   735  							Size:         gb,
   736  						},
   737  					},
   738  				},
   739  			},
   740  			machineState: state.NUMANodeMap{
   741  				0: &state.NUMANodeState{
   742  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   743  						v1.ResourceMemory: {
   744  							Allocatable:    1536 * mb,
   745  							Free:           1536 * mb,
   746  							Reserved:       0,
   747  							SystemReserved: 512 * mb,
   748  							TotalMemSize:   2 * gb,
   749  						},
   750  						hugepages1Gi: {
   751  							Allocatable:    gb,
   752  							Free:           gb,
   753  							Reserved:       0,
   754  							SystemReserved: 0,
   755  							TotalMemSize:   gb,
   756  						},
   757  					},
   758  					Cells:               []int{0},
   759  					NumberOfAssignments: 2,
   760  				},
   761  			},
   762  			systemReserved: systemReservedMemory{
   763  				0: map[v1.ResourceName]uint64{
   764  					v1.ResourceMemory: 512 * mb,
   765  				},
   766  			},
   767  			machineInfo: &cadvisorapi.MachineInfo{
   768  				Topology: []cadvisorapi.Node{
   769  					{
   770  						Id:     0,
   771  						Memory: 2 * gb,
   772  						HugePages: []cadvisorapi.HugePagesInfo{
   773  							{
   774  								// size in KB
   775  								PageSize: pageSize1Gb,
   776  								NumPages: 1,
   777  							},
   778  						},
   779  					},
   780  				},
   781  			},
   782  			expectedError: fmt.Errorf("[memorymanager] (pod: pod1, container: container1) the memory assignment uses memory resource that does not exist"),
   783  		},
   784  		{
   785  			description: "should fail when machine state number of assignments is different from the expected one",
   786  			assignments: state.ContainerMemoryAssignments{
   787  				"pod1": map[string][]state.Block{
   788  					"container1": {
   789  						{
   790  							NUMAAffinity: []int{0},
   791  							Type:         v1.ResourceMemory,
   792  							Size:         gb,
   793  						},
   794  						{
   795  							NUMAAffinity: []int{0},
   796  							Type:         hugepages1Gi,
   797  							Size:         gb,
   798  						},
   799  					},
   800  				},
   801  			},
   802  			machineState: state.NUMANodeMap{
   803  				0: &state.NUMANodeState{
   804  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   805  						v1.ResourceMemory: {
   806  							Allocatable:    1536 * mb,
   807  							Free:           1536 * mb,
   808  							Reserved:       0,
   809  							SystemReserved: 512 * mb,
   810  							TotalMemSize:   2 * gb,
   811  						},
   812  						hugepages1Gi: {
   813  							Allocatable:    gb,
   814  							Free:           gb,
   815  							Reserved:       0,
   816  							SystemReserved: 0,
   817  							TotalMemSize:   gb,
   818  						},
   819  					},
   820  					Cells:               []int{0},
   821  					NumberOfAssignments: 1,
   822  				},
   823  			},
   824  			systemReserved: systemReservedMemory{
   825  				0: map[v1.ResourceName]uint64{
   826  					v1.ResourceMemory: 512 * mb,
   827  				},
   828  			},
   829  			machineInfo: &cadvisorapi.MachineInfo{
   830  				Topology: []cadvisorapi.Node{
   831  					{
   832  						Id:     0,
   833  						Memory: 2 * gb,
   834  						HugePages: []cadvisorapi.HugePagesInfo{
   835  							{
   836  								// size in KB
   837  								PageSize: pageSize1Gb,
   838  								NumPages: 1,
   839  							},
   840  						},
   841  					},
   842  				},
   843  			},
   844  			expectedError: fmt.Errorf("[memorymanager] the expected machine state is different from the real one"),
   845  		},
   846  		{
   847  			description: "should validate cross NUMA reserved memory vs container assignments",
   848  			assignments: state.ContainerMemoryAssignments{
   849  				"pod1": map[string][]state.Block{
   850  					"container1": {
   851  						{
   852  							NUMAAffinity: []int{0, 1},
   853  							Type:         v1.ResourceMemory,
   854  							Size:         768 * mb,
   855  						},
   856  						{
   857  							NUMAAffinity: []int{0, 1},
   858  							Type:         hugepages1Gi,
   859  							Size:         gb,
   860  						},
   861  					},
   862  				},
   863  				"pod2": map[string][]state.Block{
   864  					"container2": {
   865  						{
   866  							NUMAAffinity: []int{0, 1},
   867  							Type:         v1.ResourceMemory,
   868  							Size:         256 * mb,
   869  						},
   870  						{
   871  							NUMAAffinity: []int{0, 1},
   872  							Type:         hugepages1Gi,
   873  							Size:         gb,
   874  						},
   875  					},
   876  				},
   877  			},
   878  			expectedAssignments: state.ContainerMemoryAssignments{
   879  				"pod1": map[string][]state.Block{
   880  					"container1": {
   881  						{
   882  							NUMAAffinity: []int{0, 1},
   883  							Type:         v1.ResourceMemory,
   884  							Size:         768 * mb,
   885  						},
   886  						{
   887  							NUMAAffinity: []int{0, 1},
   888  							Type:         hugepages1Gi,
   889  							Size:         gb,
   890  						},
   891  					},
   892  				},
   893  				"pod2": map[string][]state.Block{
   894  					"container2": {
   895  						{
   896  							NUMAAffinity: []int{0, 1},
   897  							Type:         v1.ResourceMemory,
   898  							Size:         256 * mb,
   899  						},
   900  						{
   901  							NUMAAffinity: []int{0, 1},
   902  							Type:         hugepages1Gi,
   903  							Size:         gb,
   904  						},
   905  					},
   906  				},
   907  			},
   908  			machineState: state.NUMANodeMap{
   909  				0: &state.NUMANodeState{
   910  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   911  						v1.ResourceMemory: {
   912  							Allocatable:    640 * mb,
   913  							Free:           0,
   914  							Reserved:       640 * mb,
   915  							SystemReserved: 512 * mb,
   916  							TotalMemSize:   2176 * mb,
   917  						},
   918  						hugepages1Gi: {
   919  							Allocatable:    gb,
   920  							Free:           0,
   921  							Reserved:       gb,
   922  							SystemReserved: 0,
   923  							TotalMemSize:   gb,
   924  						},
   925  					},
   926  					Cells:               []int{0, 1},
   927  					NumberOfAssignments: 4,
   928  				},
   929  				1: &state.NUMANodeState{
   930  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   931  						v1.ResourceMemory: {
   932  							Allocatable:    640 * mb,
   933  							Free:           256 * mb,
   934  							Reserved:       384 * mb,
   935  							SystemReserved: 512 * mb,
   936  							TotalMemSize:   2176 * mb,
   937  						},
   938  						hugepages1Gi: {
   939  							Allocatable:    gb,
   940  							Free:           0,
   941  							Reserved:       gb,
   942  							SystemReserved: 0,
   943  							TotalMemSize:   gb,
   944  						},
   945  					},
   946  					Cells:               []int{0, 1},
   947  					NumberOfAssignments: 4,
   948  				},
   949  			},
   950  			expectedMachineState: state.NUMANodeMap{
   951  				0: &state.NUMANodeState{
   952  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   953  						v1.ResourceMemory: {
   954  							Allocatable:    640 * mb,
   955  							Free:           0,
   956  							Reserved:       640 * mb,
   957  							SystemReserved: 512 * mb,
   958  							TotalMemSize:   2176 * mb,
   959  						},
   960  						hugepages1Gi: {
   961  							Allocatable:    gb,
   962  							Free:           0,
   963  							Reserved:       gb,
   964  							SystemReserved: 0,
   965  							TotalMemSize:   gb,
   966  						},
   967  					},
   968  					Cells:               []int{0, 1},
   969  					NumberOfAssignments: 4,
   970  				},
   971  				1: &state.NUMANodeState{
   972  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   973  						v1.ResourceMemory: {
   974  							Allocatable:    640 * mb,
   975  							Free:           256 * mb,
   976  							Reserved:       384 * mb,
   977  							SystemReserved: 512 * mb,
   978  							TotalMemSize:   2176 * mb,
   979  						},
   980  						hugepages1Gi: {
   981  							Allocatable:    gb,
   982  							Free:           0,
   983  							Reserved:       gb,
   984  							SystemReserved: 0,
   985  							TotalMemSize:   gb,
   986  						},
   987  					},
   988  					Cells:               []int{0, 1},
   989  					NumberOfAssignments: 4,
   990  				},
   991  			},
   992  			systemReserved: systemReservedMemory{
   993  				0: map[v1.ResourceName]uint64{
   994  					v1.ResourceMemory: 512 * mb,
   995  				},
   996  				1: map[v1.ResourceName]uint64{
   997  					v1.ResourceMemory: 512 * mb,
   998  				},
   999  			},
  1000  			machineInfo: &cadvisorapi.MachineInfo{
  1001  				Topology: []cadvisorapi.Node{
  1002  					{
  1003  						Id:     0,
  1004  						Memory: 2176 * mb,
  1005  						HugePages: []cadvisorapi.HugePagesInfo{
  1006  							{
  1007  								// size in KB
  1008  								PageSize: pageSize1Gb,
  1009  								NumPages: 1,
  1010  							},
  1011  						},
  1012  					},
  1013  					{
  1014  						Id:     1,
  1015  						Memory: 2176 * mb,
  1016  						HugePages: []cadvisorapi.HugePagesInfo{
  1017  							{
  1018  								// size in KB
  1019  								PageSize: pageSize1Gb,
  1020  								NumPages: 1,
  1021  							},
  1022  						},
  1023  					},
  1024  				},
  1025  			},
  1026  		},
  1027  	}
  1028  
  1029  	for _, testCase := range testCases {
  1030  		t.Run(testCase.description, func(t *testing.T) {
  1031  			t.Logf("[Start] %s", testCase.description)
  1032  			p, s, err := initTests(t, &testCase, nil, nil)
  1033  			if err != nil {
  1034  				t.Fatalf("Unexpected error: %v", err)
  1035  			}
  1036  
  1037  			err = p.Start(s)
  1038  			if !reflect.DeepEqual(err, testCase.expectedError) {
  1039  				t.Fatalf("The actual error: %v is different from the expected one: %v", err, testCase.expectedError)
  1040  			}
  1041  
  1042  			if err != nil {
  1043  				return
  1044  			}
  1045  
  1046  			assignments := s.GetMemoryAssignments()
  1047  			if !areContainerMemoryAssignmentsEqual(t, assignments, testCase.expectedAssignments) {
  1048  				t.Fatalf("Actual assignments: %v is different from the expected one: %v", assignments, testCase.expectedAssignments)
  1049  			}
  1050  
  1051  			machineState := s.GetMachineState()
  1052  			if !areMachineStatesEqual(machineState, testCase.expectedMachineState) {
  1053  				t.Fatalf("The actual machine state: %v is different from the expected one: %v", machineState, testCase.expectedMachineState)
  1054  			}
  1055  		})
  1056  	}
  1057  }
  1058  
  1059  func TestStaticPolicyAllocate(t *testing.T) {
  1060  	testCases := []testStaticPolicy{
  1061  		{
  1062  			description:         "should do nothing for non-guaranteed pods",
  1063  			expectedAssignments: state.ContainerMemoryAssignments{},
  1064  			machineState: state.NUMANodeMap{
  1065  				0: &state.NUMANodeState{
  1066  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1067  						v1.ResourceMemory: {
  1068  							Allocatable:    1536 * mb,
  1069  							Free:           1536 * mb,
  1070  							Reserved:       0,
  1071  							SystemReserved: 512 * mb,
  1072  							TotalMemSize:   2 * gb,
  1073  						},
  1074  						hugepages1Gi: {
  1075  							Allocatable:    gb,
  1076  							Free:           gb,
  1077  							Reserved:       0,
  1078  							SystemReserved: 0,
  1079  							TotalMemSize:   gb,
  1080  						},
  1081  					},
  1082  					Cells: []int{},
  1083  				},
  1084  			},
  1085  			expectedMachineState: state.NUMANodeMap{
  1086  				0: &state.NUMANodeState{
  1087  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1088  						v1.ResourceMemory: {
  1089  							Allocatable:    1536 * mb,
  1090  							Free:           1536 * mb,
  1091  							Reserved:       0,
  1092  							SystemReserved: 512 * mb,
  1093  							TotalMemSize:   2 * gb,
  1094  						},
  1095  						hugepages1Gi: {
  1096  							Allocatable:    gb,
  1097  							Free:           gb,
  1098  							Reserved:       0,
  1099  							SystemReserved: 0,
  1100  							TotalMemSize:   gb,
  1101  						},
  1102  					},
  1103  					Cells: []int{},
  1104  				},
  1105  			},
  1106  			systemReserved: systemReservedMemory{
  1107  				0: map[v1.ResourceName]uint64{
  1108  					v1.ResourceMemory: 512 * mb,
  1109  				},
  1110  			},
  1111  			pod:                   getPod("pod1", "container1", requirementsBurstable),
  1112  			expectedTopologyHints: nil,
  1113  			topologyHint:          &topologymanager.TopologyHint{},
  1114  		},
  1115  		{
  1116  			description: "should do nothing once container already exists under the state file",
  1117  			assignments: state.ContainerMemoryAssignments{
  1118  				"pod1": map[string][]state.Block{
  1119  					"container1": {
  1120  						{
  1121  							NUMAAffinity: []int{0},
  1122  							Type:         v1.ResourceMemory,
  1123  							Size:         gb,
  1124  						},
  1125  					},
  1126  				},
  1127  			},
  1128  			expectedAssignments: state.ContainerMemoryAssignments{
  1129  				"pod1": map[string][]state.Block{
  1130  					"container1": {
  1131  						{
  1132  							NUMAAffinity: []int{0},
  1133  							Type:         v1.ResourceMemory,
  1134  							Size:         gb,
  1135  						},
  1136  					},
  1137  				},
  1138  			},
  1139  			machineState: state.NUMANodeMap{
  1140  				0: &state.NUMANodeState{
  1141  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1142  						v1.ResourceMemory: {
  1143  							Allocatable:    1536 * mb,
  1144  							Free:           512 * mb,
  1145  							Reserved:       1024 * mb,
  1146  							SystemReserved: 512 * mb,
  1147  							TotalMemSize:   2 * gb,
  1148  						},
  1149  						hugepages1Gi: {
  1150  							Allocatable:    gb,
  1151  							Free:           gb,
  1152  							Reserved:       0,
  1153  							SystemReserved: 0,
  1154  							TotalMemSize:   gb,
  1155  						},
  1156  					},
  1157  					Cells: []int{},
  1158  				},
  1159  			},
  1160  			expectedMachineState: state.NUMANodeMap{
  1161  				0: &state.NUMANodeState{
  1162  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1163  						v1.ResourceMemory: {
  1164  							Allocatable:    1536 * mb,
  1165  							Free:           512 * mb,
  1166  							Reserved:       1024 * mb,
  1167  							SystemReserved: 512 * mb,
  1168  							TotalMemSize:   2 * gb,
  1169  						},
  1170  						hugepages1Gi: {
  1171  							Allocatable:    gb,
  1172  							Free:           gb,
  1173  							Reserved:       0,
  1174  							SystemReserved: 0,
  1175  							TotalMemSize:   gb,
  1176  						},
  1177  					},
  1178  					Cells: []int{},
  1179  				},
  1180  			},
  1181  			systemReserved: systemReservedMemory{
  1182  				0: map[v1.ResourceName]uint64{
  1183  					v1.ResourceMemory: 512 * mb,
  1184  				},
  1185  			},
  1186  			pod:                   getPod("pod1", "container1", requirementsGuaranteed),
  1187  			expectedTopologyHints: nil,
  1188  			topologyHint:          &topologymanager.TopologyHint{},
  1189  		},
  1190  		{
  1191  			description: "should calculate a default topology hint when no NUMA affinity was provided by the topology manager hint",
  1192  			assignments: state.ContainerMemoryAssignments{},
  1193  			expectedAssignments: state.ContainerMemoryAssignments{
  1194  				"pod1": map[string][]state.Block{
  1195  					"container1": {
  1196  						{
  1197  							NUMAAffinity: []int{0},
  1198  							Type:         v1.ResourceMemory,
  1199  							Size:         gb,
  1200  						},
  1201  						{
  1202  							NUMAAffinity: []int{0},
  1203  							Type:         hugepages1Gi,
  1204  							Size:         gb,
  1205  						},
  1206  					},
  1207  				},
  1208  			},
  1209  			machineState: state.NUMANodeMap{
  1210  				0: &state.NUMANodeState{
  1211  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1212  						v1.ResourceMemory: {
  1213  							Allocatable:    1536 * mb,
  1214  							Free:           1536 * mb,
  1215  							Reserved:       0,
  1216  							SystemReserved: 512 * mb,
  1217  							TotalMemSize:   2 * gb,
  1218  						},
  1219  						hugepages1Gi: {
  1220  							Allocatable:    gb,
  1221  							Free:           gb,
  1222  							Reserved:       0,
  1223  							SystemReserved: 0,
  1224  							TotalMemSize:   gb,
  1225  						},
  1226  					},
  1227  					Cells: []int{0},
  1228  				},
  1229  			},
  1230  			expectedMachineState: state.NUMANodeMap{
  1231  				0: &state.NUMANodeState{
  1232  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1233  						v1.ResourceMemory: {
  1234  							Allocatable:    1536 * mb,
  1235  							Free:           512 * mb,
  1236  							Reserved:       1024 * mb,
  1237  							SystemReserved: 512 * mb,
  1238  							TotalMemSize:   2 * gb,
  1239  						},
  1240  						hugepages1Gi: {
  1241  							Allocatable:    gb,
  1242  							Free:           0,
  1243  							Reserved:       gb,
  1244  							SystemReserved: 0,
  1245  							TotalMemSize:   gb,
  1246  						},
  1247  					},
  1248  					Cells:               []int{0},
  1249  					NumberOfAssignments: 2,
  1250  				},
  1251  			},
  1252  			systemReserved: systemReservedMemory{
  1253  				0: map[v1.ResourceName]uint64{
  1254  					v1.ResourceMemory: 512 * mb,
  1255  				},
  1256  			},
  1257  			pod:          getPod("pod1", "container1", requirementsGuaranteed),
  1258  			topologyHint: &topologymanager.TopologyHint{},
  1259  		},
  1260  		{
  1261  			description: "should fail when no NUMA affinity was provided under the topology manager hint and calculation of the default hint failed",
  1262  			assignments: state.ContainerMemoryAssignments{
  1263  				"pod1": map[string][]state.Block{
  1264  					"container1": {
  1265  						{
  1266  							NUMAAffinity: []int{0},
  1267  							Type:         v1.ResourceMemory,
  1268  							Size:         gb,
  1269  						},
  1270  						{
  1271  							NUMAAffinity: []int{0},
  1272  							Type:         hugepages1Gi,
  1273  							Size:         gb,
  1274  						},
  1275  					},
  1276  				},
  1277  			},
  1278  			machineState: state.NUMANodeMap{
  1279  				0: &state.NUMANodeState{
  1280  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1281  						v1.ResourceMemory: {
  1282  							Allocatable:    1536 * mb,
  1283  							Free:           512 * mb,
  1284  							Reserved:       1024 * mb,
  1285  							SystemReserved: 512 * mb,
  1286  							TotalMemSize:   2 * gb,
  1287  						},
  1288  						hugepages1Gi: {
  1289  							Allocatable:    gb,
  1290  							Free:           0,
  1291  							Reserved:       gb,
  1292  							SystemReserved: 0,
  1293  							TotalMemSize:   gb,
  1294  						},
  1295  					},
  1296  					Cells:               []int{0},
  1297  					NumberOfAssignments: 2,
  1298  				},
  1299  			},
  1300  			systemReserved: systemReservedMemory{
  1301  				0: map[v1.ResourceName]uint64{
  1302  					v1.ResourceMemory: 512 * mb,
  1303  				},
  1304  			},
  1305  			pod:           getPod("pod2", "container2", requirementsGuaranteed),
  1306  			expectedError: fmt.Errorf("[memorymanager] failed to get the default NUMA affinity, no NUMA nodes with enough memory is available"),
  1307  			topologyHint:  &topologymanager.TopologyHint{},
  1308  		},
  1309  		{
  1310  			description: "should fail when no NUMA affinity was provided under the topology manager preferred hint and default hint has preferred false",
  1311  			assignments: state.ContainerMemoryAssignments{
  1312  				"pod1": map[string][]state.Block{
  1313  					"container1": {
  1314  						{
  1315  							NUMAAffinity: []int{0},
  1316  							Type:         v1.ResourceMemory,
  1317  							Size:         512 * mb,
  1318  						},
  1319  					},
  1320  				},
  1321  			},
  1322  			machineState: state.NUMANodeMap{
  1323  				0: &state.NUMANodeState{
  1324  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1325  						v1.ResourceMemory: {
  1326  							Allocatable:    gb,
  1327  							Free:           512 * mb,
  1328  							Reserved:       512 * mb,
  1329  							SystemReserved: 512 * mb,
  1330  							TotalMemSize:   1536 * mb,
  1331  						},
  1332  						hugepages1Gi: {
  1333  							Allocatable:    gb,
  1334  							Free:           gb,
  1335  							Reserved:       0,
  1336  							SystemReserved: 0,
  1337  							TotalMemSize:   gb,
  1338  						},
  1339  					},
  1340  					Cells:               []int{0},
  1341  					NumberOfAssignments: 1,
  1342  				},
  1343  				1: &state.NUMANodeState{
  1344  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1345  						v1.ResourceMemory: {
  1346  							Allocatable:    512 * mb,
  1347  							Free:           512 * mb,
  1348  							Reserved:       0,
  1349  							SystemReserved: 512 * mb,
  1350  							TotalMemSize:   1536 * mb,
  1351  						},
  1352  						hugepages1Gi: {
  1353  							Allocatable:    gb,
  1354  							Free:           gb,
  1355  							Reserved:       0,
  1356  							SystemReserved: 0,
  1357  							TotalMemSize:   gb,
  1358  						},
  1359  					},
  1360  					Cells:               []int{1},
  1361  					NumberOfAssignments: 0,
  1362  				},
  1363  				2: &state.NUMANodeState{
  1364  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1365  						v1.ResourceMemory: {
  1366  							Allocatable:    512 * mb,
  1367  							Free:           512 * mb,
  1368  							Reserved:       0,
  1369  							SystemReserved: 512 * mb,
  1370  							TotalMemSize:   1536 * mb,
  1371  						},
  1372  						hugepages1Gi: {
  1373  							Allocatable:    gb,
  1374  							Free:           gb,
  1375  							Reserved:       0,
  1376  							SystemReserved: 0,
  1377  							TotalMemSize:   gb,
  1378  						},
  1379  					},
  1380  					Cells:               []int{2},
  1381  					NumberOfAssignments: 0,
  1382  				},
  1383  			},
  1384  			systemReserved: systemReservedMemory{
  1385  				0: map[v1.ResourceName]uint64{
  1386  					v1.ResourceMemory: 512 * mb,
  1387  				},
  1388  				1: map[v1.ResourceName]uint64{
  1389  					v1.ResourceMemory: 512 * mb,
  1390  				},
  1391  				2: map[v1.ResourceName]uint64{
  1392  					v1.ResourceMemory: 512 * mb,
  1393  				},
  1394  			},
  1395  			pod:           getPod("pod2", "container2", requirementsGuaranteed),
  1396  			expectedError: fmt.Errorf("[memorymanager] failed to find the default preferred hint"),
  1397  			topologyHint:  &topologymanager.TopologyHint{Preferred: true},
  1398  		},
  1399  		{
  1400  			description: "should fail when NUMA affinity provided under the topology manager hint did not satisfy container requirements and extended hint generation failed",
  1401  			machineState: state.NUMANodeMap{
  1402  				0: &state.NUMANodeState{
  1403  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1404  						v1.ResourceMemory: {
  1405  							Allocatable:    512 * mb,
  1406  							Free:           512 * mb,
  1407  							Reserved:       0,
  1408  							SystemReserved: 512 * mb,
  1409  							TotalMemSize:   gb,
  1410  						},
  1411  						hugepages1Gi: {
  1412  							Allocatable:    gb,
  1413  							Free:           gb,
  1414  							Reserved:       0,
  1415  							SystemReserved: 0,
  1416  							TotalMemSize:   gb,
  1417  						},
  1418  					},
  1419  					Cells:               []int{0},
  1420  					NumberOfAssignments: 0,
  1421  				},
  1422  				1: &state.NUMANodeState{
  1423  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1424  						v1.ResourceMemory: {
  1425  							Allocatable:    1536 * mb,
  1426  							Free:           512 * mb,
  1427  							Reserved:       gb,
  1428  							SystemReserved: 512 * mb,
  1429  							TotalMemSize:   2 * gb,
  1430  						},
  1431  						hugepages1Gi: {
  1432  							Allocatable:    gb,
  1433  							Free:           gb,
  1434  							Reserved:       0,
  1435  							SystemReserved: 0,
  1436  							TotalMemSize:   gb,
  1437  						},
  1438  					},
  1439  					Cells:               []int{1, 2},
  1440  					NumberOfAssignments: 1,
  1441  				},
  1442  				2: &state.NUMANodeState{
  1443  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1444  						v1.ResourceMemory: {
  1445  							Allocatable:    1536 * mb,
  1446  							Free:           512 * mb,
  1447  							Reserved:       gb,
  1448  							SystemReserved: 512 * mb,
  1449  							TotalMemSize:   2 * gb,
  1450  						},
  1451  						hugepages1Gi: {
  1452  							Allocatable:    gb,
  1453  							Free:           gb,
  1454  							Reserved:       0,
  1455  							SystemReserved: 0,
  1456  							TotalMemSize:   gb,
  1457  						},
  1458  					},
  1459  					Cells:               []int{1, 2},
  1460  					NumberOfAssignments: 1,
  1461  				},
  1462  			},
  1463  			systemReserved: systemReservedMemory{
  1464  				0: map[v1.ResourceName]uint64{
  1465  					v1.ResourceMemory: 512 * mb,
  1466  				},
  1467  				1: map[v1.ResourceName]uint64{
  1468  					v1.ResourceMemory: 512 * mb,
  1469  				},
  1470  				2: map[v1.ResourceName]uint64{
  1471  					v1.ResourceMemory: 512 * mb,
  1472  				},
  1473  			},
  1474  			pod:           getPod("pod1", "container1", requirementsGuaranteed),
  1475  			expectedError: fmt.Errorf("[memorymanager] failed to find NUMA nodes to extend the current topology hint"),
  1476  			topologyHint:  &topologymanager.TopologyHint{NUMANodeAffinity: newNUMAAffinity(0), Preferred: false},
  1477  		},
  1478  		{
  1479  			description: "should fail when the topology manager provided the preferred hint and extended hint has preferred false",
  1480  			assignments: state.ContainerMemoryAssignments{
  1481  				"pod1": map[string][]state.Block{
  1482  					"container1": {
  1483  						{
  1484  							NUMAAffinity: []int{0},
  1485  							Type:         v1.ResourceMemory,
  1486  							Size:         512 * mb,
  1487  						},
  1488  					},
  1489  				},
  1490  			},
  1491  			machineState: state.NUMANodeMap{
  1492  				0: &state.NUMANodeState{
  1493  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1494  						v1.ResourceMemory: {
  1495  							Allocatable:    gb,
  1496  							Free:           512 * mb,
  1497  							Reserved:       512 * mb,
  1498  							SystemReserved: 512 * mb,
  1499  							TotalMemSize:   1536 * mb,
  1500  						},
  1501  						hugepages1Gi: {
  1502  							Allocatable:    gb,
  1503  							Free:           gb,
  1504  							Reserved:       0,
  1505  							SystemReserved: 0,
  1506  							TotalMemSize:   gb,
  1507  						},
  1508  					},
  1509  					Cells:               []int{0},
  1510  					NumberOfAssignments: 1,
  1511  				},
  1512  				1: &state.NUMANodeState{
  1513  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1514  						v1.ResourceMemory: {
  1515  							Allocatable:    512 * mb,
  1516  							Free:           512 * mb,
  1517  							Reserved:       0,
  1518  							SystemReserved: 512 * mb,
  1519  							TotalMemSize:   1536 * mb,
  1520  						},
  1521  						hugepages1Gi: {
  1522  							Allocatable:    gb,
  1523  							Free:           gb,
  1524  							Reserved:       0,
  1525  							SystemReserved: 0,
  1526  							TotalMemSize:   gb,
  1527  						},
  1528  					},
  1529  					Cells:               []int{1},
  1530  					NumberOfAssignments: 0,
  1531  				},
  1532  				2: &state.NUMANodeState{
  1533  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1534  						v1.ResourceMemory: {
  1535  							Allocatable:    512 * mb,
  1536  							Free:           512 * mb,
  1537  							Reserved:       0,
  1538  							SystemReserved: 512 * mb,
  1539  							TotalMemSize:   1536 * mb,
  1540  						},
  1541  						hugepages1Gi: {
  1542  							Allocatable:    gb,
  1543  							Free:           gb,
  1544  							Reserved:       0,
  1545  							SystemReserved: 0,
  1546  							TotalMemSize:   gb,
  1547  						},
  1548  					},
  1549  					Cells:               []int{2},
  1550  					NumberOfAssignments: 0,
  1551  				},
  1552  			},
  1553  			systemReserved: systemReservedMemory{
  1554  				0: map[v1.ResourceName]uint64{
  1555  					v1.ResourceMemory: 512 * mb,
  1556  				},
  1557  				1: map[v1.ResourceName]uint64{
  1558  					v1.ResourceMemory: 512 * mb,
  1559  				},
  1560  				2: map[v1.ResourceName]uint64{
  1561  					v1.ResourceMemory: 512 * mb,
  1562  				},
  1563  			},
  1564  			pod:           getPod("pod2", "container2", requirementsGuaranteed),
  1565  			expectedError: fmt.Errorf("[memorymanager] failed to find the extended preferred hint"),
  1566  			topologyHint:  &topologymanager.TopologyHint{NUMANodeAffinity: newNUMAAffinity(1), Preferred: true},
  1567  		},
  1568  		{
  1569  			description: "should succeed to allocate memory from multiple NUMA nodes",
  1570  			assignments: state.ContainerMemoryAssignments{},
  1571  			expectedAssignments: state.ContainerMemoryAssignments{
  1572  				"pod1": map[string][]state.Block{
  1573  					"container1": {
  1574  						{
  1575  							NUMAAffinity: []int{0, 1},
  1576  							Type:         v1.ResourceMemory,
  1577  							Size:         gb,
  1578  						},
  1579  						{
  1580  							NUMAAffinity: []int{0, 1},
  1581  							Type:         hugepages1Gi,
  1582  							Size:         gb,
  1583  						},
  1584  					},
  1585  				},
  1586  			},
  1587  			machineState: state.NUMANodeMap{
  1588  				0: &state.NUMANodeState{
  1589  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1590  						v1.ResourceMemory: {
  1591  							Allocatable:    512 * mb,
  1592  							Free:           512 * mb,
  1593  							Reserved:       0,
  1594  							SystemReserved: 512 * mb,
  1595  							TotalMemSize:   gb,
  1596  						},
  1597  						hugepages1Gi: {
  1598  							Allocatable:    gb,
  1599  							Free:           gb,
  1600  							Reserved:       0,
  1601  							SystemReserved: 0,
  1602  							TotalMemSize:   gb,
  1603  						},
  1604  					},
  1605  					Cells:               []int{0},
  1606  					NumberOfAssignments: 0,
  1607  				},
  1608  				1: &state.NUMANodeState{
  1609  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1610  						v1.ResourceMemory: {
  1611  							Allocatable:    512 * mb,
  1612  							Free:           512 * mb,
  1613  							Reserved:       0,
  1614  							SystemReserved: 512 * mb,
  1615  							TotalMemSize:   gb,
  1616  						},
  1617  						hugepages1Gi: {
  1618  							Allocatable:    gb,
  1619  							Free:           gb,
  1620  							Reserved:       0,
  1621  							SystemReserved: 0,
  1622  							TotalMemSize:   gb,
  1623  						},
  1624  					},
  1625  					Cells:               []int{1},
  1626  					NumberOfAssignments: 0,
  1627  				},
  1628  				2: &state.NUMANodeState{
  1629  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1630  						v1.ResourceMemory: {
  1631  							Allocatable:    512 * mb,
  1632  							Free:           512 * mb,
  1633  							Reserved:       0,
  1634  							SystemReserved: 512 * mb,
  1635  							TotalMemSize:   gb,
  1636  						},
  1637  						hugepages1Gi: {
  1638  							Allocatable:    gb,
  1639  							Free:           gb,
  1640  							Reserved:       0,
  1641  							SystemReserved: 0,
  1642  							TotalMemSize:   gb,
  1643  						},
  1644  					},
  1645  					Cells:               []int{2},
  1646  					NumberOfAssignments: 0,
  1647  				},
  1648  				3: &state.NUMANodeState{
  1649  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1650  						v1.ResourceMemory: {
  1651  							Allocatable:    512 * mb,
  1652  							Free:           512 * mb,
  1653  							Reserved:       0,
  1654  							SystemReserved: 512 * mb,
  1655  							TotalMemSize:   gb,
  1656  						},
  1657  						hugepages1Gi: {
  1658  							Allocatable:    gb,
  1659  							Free:           gb,
  1660  							Reserved:       0,
  1661  							SystemReserved: 0,
  1662  							TotalMemSize:   gb,
  1663  						},
  1664  					},
  1665  					Cells:               []int{3},
  1666  					NumberOfAssignments: 0,
  1667  				},
  1668  			},
  1669  			expectedMachineState: state.NUMANodeMap{
  1670  				0: &state.NUMANodeState{
  1671  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1672  						v1.ResourceMemory: {
  1673  							Allocatable:    512 * mb,
  1674  							Free:           0,
  1675  							Reserved:       512 * mb,
  1676  							SystemReserved: 512 * mb,
  1677  							TotalMemSize:   gb,
  1678  						},
  1679  						hugepages1Gi: {
  1680  							Allocatable:    gb,
  1681  							Free:           0,
  1682  							Reserved:       gb,
  1683  							SystemReserved: 0,
  1684  							TotalMemSize:   gb,
  1685  						},
  1686  					},
  1687  					Cells:               []int{0, 1},
  1688  					NumberOfAssignments: 2,
  1689  				},
  1690  				1: &state.NUMANodeState{
  1691  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1692  						v1.ResourceMemory: {
  1693  							Allocatable:    512 * mb,
  1694  							Free:           0,
  1695  							Reserved:       512 * mb,
  1696  							SystemReserved: 512 * mb,
  1697  							TotalMemSize:   gb,
  1698  						},
  1699  						hugepages1Gi: {
  1700  							Allocatable:    gb,
  1701  							Free:           gb,
  1702  							Reserved:       0,
  1703  							SystemReserved: 0,
  1704  							TotalMemSize:   gb,
  1705  						},
  1706  					},
  1707  					Cells:               []int{0, 1},
  1708  					NumberOfAssignments: 2,
  1709  				},
  1710  				2: &state.NUMANodeState{
  1711  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1712  						v1.ResourceMemory: {
  1713  							Allocatable:    512 * mb,
  1714  							Free:           512 * mb,
  1715  							Reserved:       0,
  1716  							SystemReserved: 512 * mb,
  1717  							TotalMemSize:   gb,
  1718  						},
  1719  						hugepages1Gi: {
  1720  							Allocatable:    gb,
  1721  							Free:           gb,
  1722  							Reserved:       0,
  1723  							SystemReserved: 0,
  1724  							TotalMemSize:   gb,
  1725  						},
  1726  					},
  1727  					Cells:               []int{2},
  1728  					NumberOfAssignments: 0,
  1729  				},
  1730  				3: &state.NUMANodeState{
  1731  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1732  						v1.ResourceMemory: {
  1733  							Allocatable:    512 * mb,
  1734  							Free:           512 * mb,
  1735  							Reserved:       0,
  1736  							SystemReserved: 512 * mb,
  1737  							TotalMemSize:   gb,
  1738  						},
  1739  						hugepages1Gi: {
  1740  							Allocatable:    gb,
  1741  							Free:           gb,
  1742  							Reserved:       0,
  1743  							SystemReserved: 0,
  1744  							TotalMemSize:   gb,
  1745  						},
  1746  					},
  1747  					Cells:               []int{3},
  1748  					NumberOfAssignments: 0,
  1749  				},
  1750  			},
  1751  			systemReserved: systemReservedMemory{
  1752  				0: map[v1.ResourceName]uint64{
  1753  					v1.ResourceMemory: 512 * mb,
  1754  				},
  1755  				1: map[v1.ResourceName]uint64{
  1756  					v1.ResourceMemory: 512 * mb,
  1757  				},
  1758  				2: map[v1.ResourceName]uint64{
  1759  					v1.ResourceMemory: 512 * mb,
  1760  				},
  1761  				3: map[v1.ResourceName]uint64{
  1762  					v1.ResourceMemory: 512 * mb,
  1763  				},
  1764  			},
  1765  			pod:          getPod("pod1", "container1", requirementsGuaranteed),
  1766  			topologyHint: &topologymanager.TopologyHint{Preferred: true},
  1767  		},
  1768  	}
  1769  
  1770  	for _, testCase := range testCases {
  1771  		t.Run(testCase.description, func(t *testing.T) {
  1772  			t.Logf("TestStaticPolicyAllocate %s", testCase.description)
  1773  			p, s, err := initTests(t, &testCase, testCase.topologyHint, nil)
  1774  			if err != nil {
  1775  				t.Fatalf("Unexpected error: %v", err)
  1776  			}
  1777  
  1778  			err = p.Allocate(s, testCase.pod, &testCase.pod.Spec.Containers[0])
  1779  			if !reflect.DeepEqual(err, testCase.expectedError) {
  1780  				t.Fatalf("The actual error %v is different from the expected one %v", err, testCase.expectedError)
  1781  			}
  1782  
  1783  			if err != nil {
  1784  				return
  1785  			}
  1786  
  1787  			assignments := s.GetMemoryAssignments()
  1788  			if !areContainerMemoryAssignmentsEqual(t, assignments, testCase.expectedAssignments) {
  1789  				t.Fatalf("Actual assignments %v are different from the expected %v", assignments, testCase.expectedAssignments)
  1790  			}
  1791  
  1792  			machineState := s.GetMachineState()
  1793  			if !areMachineStatesEqual(machineState, testCase.expectedMachineState) {
  1794  				t.Fatalf("The actual machine state %v is different from the expected %v", machineState, testCase.expectedMachineState)
  1795  			}
  1796  		})
  1797  	}
  1798  }
  1799  
  1800  func TestStaticPolicyAllocateWithInitContainers(t *testing.T) {
  1801  	testCases := []testStaticPolicy{
  1802  		{
  1803  			description: "should re-use init containers memory, init containers requests 1Gi and 2Gi, apps containers 3Gi and 4Gi",
  1804  			assignments: state.ContainerMemoryAssignments{},
  1805  			expectedAssignments: state.ContainerMemoryAssignments{
  1806  				"pod1": map[string][]state.Block{
  1807  					"initContainer1": {
  1808  						{
  1809  							NUMAAffinity: []int{0},
  1810  							Type:         v1.ResourceMemory,
  1811  							Size:         0,
  1812  						},
  1813  						{
  1814  							NUMAAffinity: []int{0},
  1815  							Type:         hugepages1Gi,
  1816  							Size:         0,
  1817  						},
  1818  					},
  1819  					"initContainer2": {
  1820  						{
  1821  							NUMAAffinity: []int{0},
  1822  							Type:         v1.ResourceMemory,
  1823  							Size:         0,
  1824  						},
  1825  						{
  1826  							NUMAAffinity: []int{0},
  1827  							Type:         hugepages1Gi,
  1828  							Size:         0,
  1829  						},
  1830  					},
  1831  					"container1": {
  1832  						{
  1833  							NUMAAffinity: []int{0},
  1834  							Type:         v1.ResourceMemory,
  1835  							Size:         3 * gb,
  1836  						},
  1837  						{
  1838  							NUMAAffinity: []int{0},
  1839  							Type:         hugepages1Gi,
  1840  							Size:         3 * gb,
  1841  						},
  1842  					},
  1843  					"container2": {
  1844  						{
  1845  							NUMAAffinity: []int{0},
  1846  							Type:         v1.ResourceMemory,
  1847  							Size:         4 * gb,
  1848  						},
  1849  						{
  1850  							NUMAAffinity: []int{0},
  1851  							Type:         hugepages1Gi,
  1852  							Size:         4 * gb,
  1853  						},
  1854  					},
  1855  				},
  1856  			},
  1857  			machineState: state.NUMANodeMap{
  1858  				0: &state.NUMANodeState{
  1859  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1860  						v1.ResourceMemory: {
  1861  							Allocatable:    7680 * mb,
  1862  							Free:           7680 * mb,
  1863  							Reserved:       0,
  1864  							SystemReserved: 512 * mb,
  1865  							TotalMemSize:   8 * gb,
  1866  						},
  1867  						hugepages1Gi: {
  1868  							Allocatable:    8 * gb,
  1869  							Free:           8 * gb,
  1870  							Reserved:       0,
  1871  							SystemReserved: 0,
  1872  							TotalMemSize:   8 * gb,
  1873  						},
  1874  					},
  1875  					Cells: []int{0},
  1876  				},
  1877  			},
  1878  			expectedMachineState: state.NUMANodeMap{
  1879  				0: &state.NUMANodeState{
  1880  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1881  						v1.ResourceMemory: {
  1882  							Allocatable:    7680 * mb,
  1883  							Free:           512 * mb,
  1884  							Reserved:       7 * gb,
  1885  							SystemReserved: 512 * mb,
  1886  							TotalMemSize:   8 * gb,
  1887  						},
  1888  						hugepages1Gi: {
  1889  							Allocatable:    8 * gb,
  1890  							Free:           1 * gb,
  1891  							Reserved:       7 * gb,
  1892  							SystemReserved: 0,
  1893  							TotalMemSize:   8 * gb,
  1894  						},
  1895  					},
  1896  					Cells:               []int{0},
  1897  					NumberOfAssignments: 8,
  1898  				},
  1899  			},
  1900  			systemReserved: systemReservedMemory{
  1901  				0: map[v1.ResourceName]uint64{
  1902  					v1.ResourceMemory: 512 * mb,
  1903  				},
  1904  			},
  1905  			pod: getPodWithInitContainers(
  1906  				"pod1",
  1907  				[]v1.Container{
  1908  					{
  1909  						Name: "container1",
  1910  						Resources: v1.ResourceRequirements{
  1911  							Limits: v1.ResourceList{
  1912  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1913  								v1.ResourceMemory: resource.MustParse("3Gi"),
  1914  								hugepages1Gi:      resource.MustParse("3Gi"),
  1915  							},
  1916  							Requests: v1.ResourceList{
  1917  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1918  								v1.ResourceMemory: resource.MustParse("3Gi"),
  1919  								hugepages1Gi:      resource.MustParse("3Gi"),
  1920  							},
  1921  						},
  1922  					},
  1923  					{
  1924  						Name: "container2",
  1925  						Resources: v1.ResourceRequirements{
  1926  							Limits: v1.ResourceList{
  1927  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1928  								v1.ResourceMemory: resource.MustParse("4Gi"),
  1929  								hugepages1Gi:      resource.MustParse("4Gi"),
  1930  							},
  1931  							Requests: v1.ResourceList{
  1932  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1933  								v1.ResourceMemory: resource.MustParse("4Gi"),
  1934  								hugepages1Gi:      resource.MustParse("4Gi"),
  1935  							},
  1936  						},
  1937  					},
  1938  				},
  1939  				[]v1.Container{
  1940  					{
  1941  						Name: "initContainer1",
  1942  						Resources: v1.ResourceRequirements{
  1943  							Limits: v1.ResourceList{
  1944  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1945  								v1.ResourceMemory: resource.MustParse("1Gi"),
  1946  								hugepages1Gi:      resource.MustParse("1Gi"),
  1947  							},
  1948  							Requests: v1.ResourceList{
  1949  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1950  								v1.ResourceMemory: resource.MustParse("1Gi"),
  1951  								hugepages1Gi:      resource.MustParse("1Gi"),
  1952  							},
  1953  						},
  1954  					},
  1955  					{
  1956  						Name: "initContainer2",
  1957  						Resources: v1.ResourceRequirements{
  1958  							Limits: v1.ResourceList{
  1959  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1960  								v1.ResourceMemory: resource.MustParse("2Gi"),
  1961  								hugepages1Gi:      resource.MustParse("2Gi"),
  1962  							},
  1963  							Requests: v1.ResourceList{
  1964  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1965  								v1.ResourceMemory: resource.MustParse("2Gi"),
  1966  								hugepages1Gi:      resource.MustParse("2Gi"),
  1967  							},
  1968  						},
  1969  					},
  1970  				},
  1971  			),
  1972  			topologyHint: &topologymanager.TopologyHint{},
  1973  		},
  1974  		{
  1975  			description: "should re-use init containers memory, init containers requests 4Gi and 3Gi, apps containers 2Gi and 1Gi",
  1976  			assignments: state.ContainerMemoryAssignments{},
  1977  			expectedAssignments: state.ContainerMemoryAssignments{
  1978  				"pod1": map[string][]state.Block{
  1979  					"initContainer1": {
  1980  						{
  1981  							NUMAAffinity: []int{0},
  1982  							Type:         v1.ResourceMemory,
  1983  							Size:         0,
  1984  						},
  1985  						{
  1986  							NUMAAffinity: []int{0},
  1987  							Type:         hugepages1Gi,
  1988  							Size:         0,
  1989  						},
  1990  					},
  1991  					"initContainer2": {
  1992  						{
  1993  							NUMAAffinity: []int{0},
  1994  							Type:         v1.ResourceMemory,
  1995  							Size:         gb,
  1996  						},
  1997  						{
  1998  							NUMAAffinity: []int{0},
  1999  							Type:         hugepages1Gi,
  2000  							Size:         gb,
  2001  						},
  2002  					},
  2003  					"container1": {
  2004  						{
  2005  							NUMAAffinity: []int{0},
  2006  							Type:         v1.ResourceMemory,
  2007  							Size:         2 * gb,
  2008  						},
  2009  						{
  2010  							NUMAAffinity: []int{0},
  2011  							Type:         hugepages1Gi,
  2012  							Size:         2 * gb,
  2013  						},
  2014  					},
  2015  					"container2": {
  2016  						{
  2017  							NUMAAffinity: []int{0},
  2018  							Type:         v1.ResourceMemory,
  2019  							Size:         gb,
  2020  						},
  2021  						{
  2022  							NUMAAffinity: []int{0},
  2023  							Type:         hugepages1Gi,
  2024  							Size:         gb,
  2025  						},
  2026  					},
  2027  				},
  2028  			},
  2029  			machineState: state.NUMANodeMap{
  2030  				0: &state.NUMANodeState{
  2031  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2032  						v1.ResourceMemory: {
  2033  							Allocatable:    7680 * mb,
  2034  							Free:           7680 * mb,
  2035  							Reserved:       0,
  2036  							SystemReserved: 512 * mb,
  2037  							TotalMemSize:   8 * gb,
  2038  						},
  2039  						hugepages1Gi: {
  2040  							Allocatable:    8 * gb,
  2041  							Free:           8 * gb,
  2042  							Reserved:       0,
  2043  							SystemReserved: 0,
  2044  							TotalMemSize:   8 * gb,
  2045  						},
  2046  					},
  2047  					Cells: []int{0},
  2048  				},
  2049  			},
  2050  			expectedMachineState: state.NUMANodeMap{
  2051  				0: &state.NUMANodeState{
  2052  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2053  						v1.ResourceMemory: {
  2054  							Allocatable:    7680 * mb,
  2055  							Free:           3584 * mb,
  2056  							Reserved:       4 * gb,
  2057  							SystemReserved: 512 * mb,
  2058  							TotalMemSize:   8 * gb,
  2059  						},
  2060  						hugepages1Gi: {
  2061  							Allocatable:    8 * gb,
  2062  							Free:           4 * gb,
  2063  							Reserved:       4 * gb,
  2064  							SystemReserved: 0,
  2065  							TotalMemSize:   8 * gb,
  2066  						},
  2067  					},
  2068  					Cells:               []int{0},
  2069  					NumberOfAssignments: 8,
  2070  				},
  2071  			},
  2072  			systemReserved: systemReservedMemory{
  2073  				0: map[v1.ResourceName]uint64{
  2074  					v1.ResourceMemory: 512 * mb,
  2075  				},
  2076  			},
  2077  			pod: getPodWithInitContainers(
  2078  				"pod1",
  2079  				[]v1.Container{
  2080  					{
  2081  						Name: "container1",
  2082  						Resources: v1.ResourceRequirements{
  2083  							Limits: v1.ResourceList{
  2084  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2085  								v1.ResourceMemory: resource.MustParse("2Gi"),
  2086  								hugepages1Gi:      resource.MustParse("2Gi"),
  2087  							},
  2088  							Requests: v1.ResourceList{
  2089  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2090  								v1.ResourceMemory: resource.MustParse("2Gi"),
  2091  								hugepages1Gi:      resource.MustParse("2Gi"),
  2092  							},
  2093  						},
  2094  					},
  2095  					{
  2096  						Name: "container2",
  2097  						Resources: v1.ResourceRequirements{
  2098  							Limits: v1.ResourceList{
  2099  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2100  								v1.ResourceMemory: resource.MustParse("1Gi"),
  2101  								hugepages1Gi:      resource.MustParse("1Gi"),
  2102  							},
  2103  							Requests: v1.ResourceList{
  2104  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2105  								v1.ResourceMemory: resource.MustParse("1Gi"),
  2106  								hugepages1Gi:      resource.MustParse("1Gi"),
  2107  							},
  2108  						},
  2109  					},
  2110  				},
  2111  				[]v1.Container{
  2112  					{
  2113  						Name: "initContainer1",
  2114  						Resources: v1.ResourceRequirements{
  2115  							Limits: v1.ResourceList{
  2116  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2117  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2118  								hugepages1Gi:      resource.MustParse("4Gi"),
  2119  							},
  2120  							Requests: v1.ResourceList{
  2121  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2122  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2123  								hugepages1Gi:      resource.MustParse("4Gi"),
  2124  							},
  2125  						},
  2126  					},
  2127  					{
  2128  						Name: "initContainer2",
  2129  						Resources: v1.ResourceRequirements{
  2130  							Limits: v1.ResourceList{
  2131  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2132  								v1.ResourceMemory: resource.MustParse("3Gi"),
  2133  								hugepages1Gi:      resource.MustParse("3Gi"),
  2134  							},
  2135  							Requests: v1.ResourceList{
  2136  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2137  								v1.ResourceMemory: resource.MustParse("3Gi"),
  2138  								hugepages1Gi:      resource.MustParse("3Gi"),
  2139  							},
  2140  						},
  2141  					},
  2142  				},
  2143  			),
  2144  			topologyHint: &topologymanager.TopologyHint{},
  2145  		},
  2146  		{
  2147  			description: "should re-use init containers memory, init containers requests 7Gi and 4Gi, apps containers 4Gi and 3Gi",
  2148  			assignments: state.ContainerMemoryAssignments{},
  2149  			expectedAssignments: state.ContainerMemoryAssignments{
  2150  				"pod1": map[string][]state.Block{
  2151  					"initContainer1": {
  2152  						{
  2153  							NUMAAffinity: []int{0},
  2154  							Type:         v1.ResourceMemory,
  2155  							Size:         0,
  2156  						},
  2157  						{
  2158  							NUMAAffinity: []int{0},
  2159  							Type:         hugepages1Gi,
  2160  							Size:         0,
  2161  						},
  2162  					},
  2163  					"initContainer2": {
  2164  						{
  2165  							NUMAAffinity: []int{0},
  2166  							Type:         v1.ResourceMemory,
  2167  							Size:         0,
  2168  						},
  2169  						{
  2170  							NUMAAffinity: []int{0},
  2171  							Type:         hugepages1Gi,
  2172  							Size:         0,
  2173  						},
  2174  					},
  2175  					"container1": {
  2176  						{
  2177  							NUMAAffinity: []int{0},
  2178  							Type:         v1.ResourceMemory,
  2179  							Size:         4 * gb,
  2180  						},
  2181  						{
  2182  							NUMAAffinity: []int{0},
  2183  							Type:         hugepages1Gi,
  2184  							Size:         4 * gb,
  2185  						},
  2186  					},
  2187  					"container2": {
  2188  						{
  2189  							NUMAAffinity: []int{0},
  2190  							Type:         v1.ResourceMemory,
  2191  							Size:         3 * gb,
  2192  						},
  2193  						{
  2194  							NUMAAffinity: []int{0},
  2195  							Type:         hugepages1Gi,
  2196  							Size:         3 * gb,
  2197  						},
  2198  					},
  2199  				},
  2200  			},
  2201  			machineState: state.NUMANodeMap{
  2202  				0: &state.NUMANodeState{
  2203  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2204  						v1.ResourceMemory: {
  2205  							Allocatable:    7680 * mb,
  2206  							Free:           7680 * mb,
  2207  							Reserved:       0,
  2208  							SystemReserved: 512 * mb,
  2209  							TotalMemSize:   8 * gb,
  2210  						},
  2211  						hugepages1Gi: {
  2212  							Allocatable:    8 * gb,
  2213  							Free:           8 * gb,
  2214  							Reserved:       0,
  2215  							SystemReserved: 0,
  2216  							TotalMemSize:   8 * gb,
  2217  						},
  2218  					},
  2219  					Cells: []int{0},
  2220  				},
  2221  			},
  2222  			expectedMachineState: state.NUMANodeMap{
  2223  				0: &state.NUMANodeState{
  2224  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2225  						v1.ResourceMemory: {
  2226  							Allocatable:    7680 * mb,
  2227  							Free:           512 * mb,
  2228  							Reserved:       7 * gb,
  2229  							SystemReserved: 512 * mb,
  2230  							TotalMemSize:   8 * gb,
  2231  						},
  2232  						hugepages1Gi: {
  2233  							Allocatable:    8 * gb,
  2234  							Free:           1 * gb,
  2235  							Reserved:       7 * gb,
  2236  							SystemReserved: 0,
  2237  							TotalMemSize:   8 * gb,
  2238  						},
  2239  					},
  2240  					Cells:               []int{0},
  2241  					NumberOfAssignments: 8,
  2242  				},
  2243  			},
  2244  			systemReserved: systemReservedMemory{
  2245  				0: map[v1.ResourceName]uint64{
  2246  					v1.ResourceMemory: 512 * mb,
  2247  				},
  2248  			},
  2249  			pod: getPodWithInitContainers(
  2250  				"pod1",
  2251  				[]v1.Container{
  2252  					{
  2253  						Name: "container1",
  2254  						Resources: v1.ResourceRequirements{
  2255  							Limits: v1.ResourceList{
  2256  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2257  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2258  								hugepages1Gi:      resource.MustParse("4Gi"),
  2259  							},
  2260  							Requests: v1.ResourceList{
  2261  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2262  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2263  								hugepages1Gi:      resource.MustParse("4Gi"),
  2264  							},
  2265  						},
  2266  					},
  2267  					{
  2268  						Name: "container2",
  2269  						Resources: v1.ResourceRequirements{
  2270  							Limits: v1.ResourceList{
  2271  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2272  								v1.ResourceMemory: resource.MustParse("3Gi"),
  2273  								hugepages1Gi:      resource.MustParse("3Gi"),
  2274  							},
  2275  							Requests: v1.ResourceList{
  2276  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2277  								v1.ResourceMemory: resource.MustParse("3Gi"),
  2278  								hugepages1Gi:      resource.MustParse("3Gi"),
  2279  							},
  2280  						},
  2281  					},
  2282  				},
  2283  				[]v1.Container{
  2284  					{
  2285  						Name: "initContainer1",
  2286  						Resources: v1.ResourceRequirements{
  2287  							Limits: v1.ResourceList{
  2288  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2289  								v1.ResourceMemory: resource.MustParse("7Gi"),
  2290  								hugepages1Gi:      resource.MustParse("7Gi"),
  2291  							},
  2292  							Requests: v1.ResourceList{
  2293  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2294  								v1.ResourceMemory: resource.MustParse("7Gi"),
  2295  								hugepages1Gi:      resource.MustParse("7Gi"),
  2296  							},
  2297  						},
  2298  					},
  2299  					{
  2300  						Name: "initContainer2",
  2301  						Resources: v1.ResourceRequirements{
  2302  							Limits: v1.ResourceList{
  2303  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2304  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2305  								hugepages1Gi:      resource.MustParse("4Gi"),
  2306  							},
  2307  							Requests: v1.ResourceList{
  2308  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2309  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2310  								hugepages1Gi:      resource.MustParse("4Gi"),
  2311  							},
  2312  						},
  2313  					},
  2314  				},
  2315  			),
  2316  			topologyHint: &topologymanager.TopologyHint{},
  2317  		},
  2318  		{
  2319  			description:                  "should re-use init containers memory, init containers requests 7Gi and 4Gi, apps containers 5Gi and 2Gi",
  2320  			assignments:                  state.ContainerMemoryAssignments{},
  2321  			initContainersReusableMemory: reusableMemory{"pod0": map[string]map[v1.ResourceName]uint64{}},
  2322  			expectedAssignments: state.ContainerMemoryAssignments{
  2323  				"pod1": map[string][]state.Block{
  2324  					"initContainer1": {
  2325  						{
  2326  							NUMAAffinity: []int{0},
  2327  							Type:         v1.ResourceMemory,
  2328  							Size:         0,
  2329  						},
  2330  						{
  2331  							NUMAAffinity: []int{0},
  2332  							Type:         hugepages1Gi,
  2333  							Size:         0,
  2334  						},
  2335  					},
  2336  					"initContainer2": {
  2337  						{
  2338  							NUMAAffinity: []int{0},
  2339  							Type:         v1.ResourceMemory,
  2340  							Size:         0,
  2341  						},
  2342  						{
  2343  							NUMAAffinity: []int{0},
  2344  							Type:         hugepages1Gi,
  2345  							Size:         0,
  2346  						},
  2347  					},
  2348  					"container1": {
  2349  						{
  2350  							NUMAAffinity: []int{0},
  2351  							Type:         v1.ResourceMemory,
  2352  							Size:         5 * gb,
  2353  						},
  2354  						{
  2355  							NUMAAffinity: []int{0},
  2356  							Type:         hugepages1Gi,
  2357  							Size:         5 * gb,
  2358  						},
  2359  					},
  2360  					"container2": {
  2361  						{
  2362  							NUMAAffinity: []int{0},
  2363  							Type:         v1.ResourceMemory,
  2364  							Size:         2 * gb,
  2365  						},
  2366  						{
  2367  							NUMAAffinity: []int{0},
  2368  							Type:         hugepages1Gi,
  2369  							Size:         2 * gb,
  2370  						},
  2371  					},
  2372  				},
  2373  			},
  2374  			machineState: state.NUMANodeMap{
  2375  				0: &state.NUMANodeState{
  2376  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2377  						v1.ResourceMemory: {
  2378  							Allocatable:    10240 * mb,
  2379  							Free:           10240 * mb,
  2380  							Reserved:       0,
  2381  							SystemReserved: 512 * mb,
  2382  							TotalMemSize:   10 * gb,
  2383  						},
  2384  						hugepages1Gi: {
  2385  							Allocatable:    10 * gb,
  2386  							Free:           10 * gb,
  2387  							Reserved:       0,
  2388  							SystemReserved: 0,
  2389  							TotalMemSize:   10 * gb,
  2390  						},
  2391  					},
  2392  					Cells: []int{0},
  2393  				},
  2394  			},
  2395  			expectedMachineState: state.NUMANodeMap{
  2396  				0: &state.NUMANodeState{
  2397  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2398  						v1.ResourceMemory: {
  2399  							Allocatable:    10240 * mb,
  2400  							Free:           3072 * mb,
  2401  							Reserved:       7 * gb,
  2402  							SystemReserved: 512 * mb,
  2403  							TotalMemSize:   10 * gb,
  2404  						},
  2405  						hugepages1Gi: {
  2406  							Allocatable:    10 * gb,
  2407  							Free:           3 * gb,
  2408  							Reserved:       7 * gb,
  2409  							SystemReserved: 0,
  2410  							TotalMemSize:   10 * gb,
  2411  						},
  2412  					},
  2413  					Cells:               []int{0},
  2414  					NumberOfAssignments: 8,
  2415  				},
  2416  			},
  2417  			systemReserved: systemReservedMemory{
  2418  				0: map[v1.ResourceName]uint64{
  2419  					v1.ResourceMemory: 512 * mb,
  2420  				},
  2421  			},
  2422  			pod: getPodWithInitContainers(
  2423  				"pod1",
  2424  				[]v1.Container{
  2425  					{
  2426  						Name: "container1",
  2427  						Resources: v1.ResourceRequirements{
  2428  							Limits: v1.ResourceList{
  2429  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2430  								v1.ResourceMemory: resource.MustParse("5Gi"),
  2431  								hugepages1Gi:      resource.MustParse("5Gi"),
  2432  							},
  2433  							Requests: v1.ResourceList{
  2434  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2435  								v1.ResourceMemory: resource.MustParse("5Gi"),
  2436  								hugepages1Gi:      resource.MustParse("5Gi"),
  2437  							},
  2438  						},
  2439  					},
  2440  					{
  2441  						Name: "container2",
  2442  						Resources: v1.ResourceRequirements{
  2443  							Limits: v1.ResourceList{
  2444  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2445  								v1.ResourceMemory: resource.MustParse("2Gi"),
  2446  								hugepages1Gi:      resource.MustParse("2Gi"),
  2447  							},
  2448  							Requests: v1.ResourceList{
  2449  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2450  								v1.ResourceMemory: resource.MustParse("2Gi"),
  2451  								hugepages1Gi:      resource.MustParse("2Gi"),
  2452  							},
  2453  						},
  2454  					},
  2455  				},
  2456  				[]v1.Container{
  2457  					{
  2458  						Name: "initContainer1",
  2459  						Resources: v1.ResourceRequirements{
  2460  							Limits: v1.ResourceList{
  2461  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2462  								v1.ResourceMemory: resource.MustParse("7Gi"),
  2463  								hugepages1Gi:      resource.MustParse("7Gi"),
  2464  							},
  2465  							Requests: v1.ResourceList{
  2466  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2467  								v1.ResourceMemory: resource.MustParse("7Gi"),
  2468  								hugepages1Gi:      resource.MustParse("7Gi"),
  2469  							},
  2470  						},
  2471  					},
  2472  					{
  2473  						Name: "initContainer2",
  2474  						Resources: v1.ResourceRequirements{
  2475  							Limits: v1.ResourceList{
  2476  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2477  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2478  								hugepages1Gi:      resource.MustParse("4Gi"),
  2479  							},
  2480  							Requests: v1.ResourceList{
  2481  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2482  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2483  								hugepages1Gi:      resource.MustParse("4Gi"),
  2484  							},
  2485  						},
  2486  					},
  2487  				},
  2488  			),
  2489  			topologyHint: &topologymanager.TopologyHint{},
  2490  		},
  2491  	}
  2492  
  2493  	for _, testCase := range testCases {
  2494  		t.Run(testCase.description, func(t *testing.T) {
  2495  			klog.InfoS("TestStaticPolicyAllocateWithInitContainers", "name", testCase.description)
  2496  			p, s, err := initTests(t, &testCase, testCase.topologyHint, testCase.initContainersReusableMemory)
  2497  			if err != nil {
  2498  				t.Fatalf("Unexpected error: %v", err)
  2499  			}
  2500  
  2501  			for i := range testCase.pod.Spec.InitContainers {
  2502  				err = p.Allocate(s, testCase.pod, &testCase.pod.Spec.InitContainers[i])
  2503  				if !reflect.DeepEqual(err, testCase.expectedError) {
  2504  					t.Fatalf("The actual error %v is different from the expected one %v", err, testCase.expectedError)
  2505  				}
  2506  			}
  2507  
  2508  			for i := range testCase.pod.Spec.Containers {
  2509  				err = p.Allocate(s, testCase.pod, &testCase.pod.Spec.Containers[i])
  2510  				if !reflect.DeepEqual(err, testCase.expectedError) {
  2511  					t.Fatalf("The actual error %v is different from the expected one %v", err, testCase.expectedError)
  2512  				}
  2513  			}
  2514  
  2515  			assignments := s.GetMemoryAssignments()
  2516  			if !areContainerMemoryAssignmentsEqual(t, assignments, testCase.expectedAssignments) {
  2517  				t.Fatalf("Actual assignments %v are different from the expected %v", assignments, testCase.expectedAssignments)
  2518  			}
  2519  
  2520  			machineState := s.GetMachineState()
  2521  			if !areMachineStatesEqual(machineState, testCase.expectedMachineState) {
  2522  				t.Fatalf("The actual machine state %v is different from the expected %v", machineState, testCase.expectedMachineState)
  2523  			}
  2524  		})
  2525  	}
  2526  }
  2527  
  2528  func TestStaticPolicyAllocateWithRestartableInitContainers(t *testing.T) {
  2529  	testCases := []testStaticPolicy{
  2530  		{
  2531  			description: "should do nothing once containers already exist under the state file",
  2532  			assignments: state.ContainerMemoryAssignments{
  2533  				"pod1": map[string][]state.Block{
  2534  					"initContainer1": {
  2535  						{
  2536  							NUMAAffinity: []int{0},
  2537  							Type:         v1.ResourceMemory,
  2538  							Size:         gb,
  2539  						},
  2540  					},
  2541  					"container1": {
  2542  						{
  2543  							NUMAAffinity: []int{0},
  2544  							Type:         v1.ResourceMemory,
  2545  							Size:         gb,
  2546  						},
  2547  					},
  2548  				},
  2549  			},
  2550  			expectedAssignments: state.ContainerMemoryAssignments{
  2551  				"pod1": map[string][]state.Block{
  2552  					"initContainer1": {
  2553  						{
  2554  							NUMAAffinity: []int{0},
  2555  							Type:         v1.ResourceMemory,
  2556  							Size:         gb,
  2557  						},
  2558  					},
  2559  					"container1": {
  2560  						{
  2561  							NUMAAffinity: []int{0},
  2562  							Type:         v1.ResourceMemory,
  2563  							Size:         gb,
  2564  						},
  2565  					},
  2566  				},
  2567  			},
  2568  			machineState: state.NUMANodeMap{
  2569  				0: &state.NUMANodeState{
  2570  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2571  						v1.ResourceMemory: {
  2572  							Allocatable:    2560 * mb,
  2573  							Free:           512 * mb,
  2574  							Reserved:       2048 * mb,
  2575  							SystemReserved: 512 * mb,
  2576  							TotalMemSize:   3 * gb,
  2577  						},
  2578  						hugepages1Gi: {
  2579  							Allocatable:    2 * gb,
  2580  							Free:           2 * gb,
  2581  							Reserved:       0,
  2582  							SystemReserved: 0,
  2583  							TotalMemSize:   2 * gb,
  2584  						},
  2585  					},
  2586  					Cells: []int{},
  2587  				},
  2588  			},
  2589  			expectedMachineState: state.NUMANodeMap{
  2590  				0: &state.NUMANodeState{
  2591  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2592  						v1.ResourceMemory: {
  2593  							Allocatable:    2560 * mb,
  2594  							Free:           512 * mb,
  2595  							Reserved:       2048 * mb,
  2596  							SystemReserved: 512 * mb,
  2597  							TotalMemSize:   3 * gb,
  2598  						},
  2599  						hugepages1Gi: {
  2600  							Allocatable:    2 * gb,
  2601  							Free:           2 * gb,
  2602  							Reserved:       0,
  2603  							SystemReserved: 0,
  2604  							TotalMemSize:   2 * gb,
  2605  						},
  2606  					},
  2607  					Cells: []int{},
  2608  				},
  2609  			},
  2610  			systemReserved: systemReservedMemory{
  2611  				0: map[v1.ResourceName]uint64{
  2612  					v1.ResourceMemory: 512 * mb,
  2613  				},
  2614  			},
  2615  			pod: getPodWithInitContainers(
  2616  				"pod1",
  2617  				[]v1.Container{
  2618  					{
  2619  						Name:      "container1",
  2620  						Resources: *requirementsGuaranteed,
  2621  					},
  2622  				},
  2623  				[]v1.Container{
  2624  					{
  2625  						Name:          "initContainer1",
  2626  						Resources:     *requirementsGuaranteed,
  2627  						RestartPolicy: &containerRestartPolicyAlways,
  2628  					},
  2629  				},
  2630  			),
  2631  			expectedTopologyHints: nil,
  2632  			topologyHint:          &topologymanager.TopologyHint{},
  2633  		},
  2634  		{
  2635  			description: "should not re-use restartable init containers memory",
  2636  			assignments: state.ContainerMemoryAssignments{},
  2637  			expectedAssignments: state.ContainerMemoryAssignments{
  2638  				"pod1": map[string][]state.Block{
  2639  					"initContainer1": {
  2640  						{
  2641  							NUMAAffinity: []int{0},
  2642  							Type:         v1.ResourceMemory,
  2643  							Size:         0,
  2644  						},
  2645  						{
  2646  							NUMAAffinity: []int{0},
  2647  							Type:         hugepages1Gi,
  2648  							Size:         0,
  2649  						},
  2650  					},
  2651  					"restartableInitContainer2": {
  2652  						{
  2653  							NUMAAffinity: []int{0},
  2654  							Type:         v1.ResourceMemory,
  2655  							Size:         2 * gb,
  2656  						},
  2657  						{
  2658  							NUMAAffinity: []int{0},
  2659  							Type:         hugepages1Gi,
  2660  							Size:         2 * gb,
  2661  						},
  2662  					},
  2663  					"initContainer3": {
  2664  						{
  2665  							NUMAAffinity: []int{0},
  2666  							Type:         v1.ResourceMemory,
  2667  							Size:         0,
  2668  						},
  2669  						{
  2670  							NUMAAffinity: []int{0},
  2671  							Type:         hugepages1Gi,
  2672  							Size:         0,
  2673  						},
  2674  					},
  2675  					"restartableInitContainer4": {
  2676  						{
  2677  							NUMAAffinity: []int{0},
  2678  							Type:         v1.ResourceMemory,
  2679  							Size:         4 * gb,
  2680  						},
  2681  						{
  2682  							NUMAAffinity: []int{0},
  2683  							Type:         hugepages1Gi,
  2684  							Size:         4 * gb,
  2685  						},
  2686  					},
  2687  					"container1": {
  2688  						{
  2689  							NUMAAffinity: []int{0},
  2690  							Type:         v1.ResourceMemory,
  2691  							Size:         1 * gb,
  2692  						},
  2693  						{
  2694  							NUMAAffinity: []int{0},
  2695  							Type:         hugepages1Gi,
  2696  							Size:         1 * gb,
  2697  						},
  2698  					},
  2699  				},
  2700  			},
  2701  			machineState: state.NUMANodeMap{
  2702  				0: &state.NUMANodeState{
  2703  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2704  						v1.ResourceMemory: {
  2705  							Allocatable:    7 * gb,
  2706  							Free:           7 * gb,
  2707  							Reserved:       0,
  2708  							SystemReserved: 512 * mb,
  2709  							TotalMemSize:   7680 * mb,
  2710  						},
  2711  						hugepages1Gi: {
  2712  							Allocatable:    7 * gb,
  2713  							Free:           7 * gb,
  2714  							Reserved:       0,
  2715  							SystemReserved: 0,
  2716  							TotalMemSize:   7 * gb,
  2717  						},
  2718  					},
  2719  					Cells: []int{0},
  2720  				},
  2721  			},
  2722  			expectedMachineState: state.NUMANodeMap{
  2723  				0: &state.NUMANodeState{
  2724  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2725  						v1.ResourceMemory: {
  2726  							Allocatable:    7 * gb,
  2727  							Free:           0,
  2728  							Reserved:       7 * gb,
  2729  							SystemReserved: 512 * mb,
  2730  							TotalMemSize:   7680 * mb,
  2731  						},
  2732  						hugepages1Gi: {
  2733  							Allocatable:    7 * gb,
  2734  							Free:           0,
  2735  							Reserved:       7 * gb,
  2736  							SystemReserved: 0,
  2737  							TotalMemSize:   7 * gb,
  2738  						},
  2739  					},
  2740  					Cells:               []int{0},
  2741  					NumberOfAssignments: 10,
  2742  				},
  2743  			},
  2744  			systemReserved: systemReservedMemory{
  2745  				0: map[v1.ResourceName]uint64{
  2746  					v1.ResourceMemory: 512 * mb,
  2747  				},
  2748  			},
  2749  			pod: getPodWithInitContainers(
  2750  				"pod1",
  2751  				[]v1.Container{
  2752  					{
  2753  						Name:      "container1",
  2754  						Resources: *requirementsGuaranteed,
  2755  					},
  2756  				},
  2757  				[]v1.Container{
  2758  					{
  2759  						Name: "initContainer1",
  2760  						Resources: v1.ResourceRequirements{
  2761  							Limits: v1.ResourceList{
  2762  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2763  								v1.ResourceMemory: resource.MustParse("1Gi"),
  2764  								hugepages1Gi:      resource.MustParse("1Gi"),
  2765  							},
  2766  							Requests: v1.ResourceList{
  2767  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2768  								v1.ResourceMemory: resource.MustParse("1Gi"),
  2769  								hugepages1Gi:      resource.MustParse("1Gi"),
  2770  							},
  2771  						},
  2772  					},
  2773  					{
  2774  						Name: "restartableInitContainer2",
  2775  						Resources: v1.ResourceRequirements{
  2776  							Limits: v1.ResourceList{
  2777  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2778  								v1.ResourceMemory: resource.MustParse("2Gi"),
  2779  								hugepages1Gi:      resource.MustParse("2Gi"),
  2780  							},
  2781  							Requests: v1.ResourceList{
  2782  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2783  								v1.ResourceMemory: resource.MustParse("2Gi"),
  2784  								hugepages1Gi:      resource.MustParse("2Gi"),
  2785  							},
  2786  						},
  2787  						RestartPolicy: &containerRestartPolicyAlways,
  2788  					},
  2789  					{
  2790  						Name: "initContainer3",
  2791  						Resources: v1.ResourceRequirements{
  2792  							Limits: v1.ResourceList{
  2793  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2794  								v1.ResourceMemory: resource.MustParse("3Gi"),
  2795  								hugepages1Gi:      resource.MustParse("3Gi"),
  2796  							},
  2797  							Requests: v1.ResourceList{
  2798  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2799  								v1.ResourceMemory: resource.MustParse("3Gi"),
  2800  								hugepages1Gi:      resource.MustParse("3Gi"),
  2801  							},
  2802  						},
  2803  					},
  2804  					{
  2805  						Name: "restartableInitContainer4",
  2806  						Resources: v1.ResourceRequirements{
  2807  							Limits: v1.ResourceList{
  2808  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2809  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2810  								hugepages1Gi:      resource.MustParse("4Gi"),
  2811  							},
  2812  							Requests: v1.ResourceList{
  2813  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2814  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2815  								hugepages1Gi:      resource.MustParse("4Gi"),
  2816  							},
  2817  						},
  2818  						RestartPolicy: &containerRestartPolicyAlways,
  2819  					},
  2820  				},
  2821  			),
  2822  			topologyHint: &topologymanager.TopologyHint{},
  2823  		},
  2824  	}
  2825  
  2826  	for _, testCase := range testCases {
  2827  		t.Run(testCase.description, func(t *testing.T) {
  2828  			klog.InfoS("TestStaticPolicyAllocateWithRestartableInitContainers", "name", testCase.description)
  2829  			p, s, err := initTests(t, &testCase, testCase.topologyHint, testCase.initContainersReusableMemory)
  2830  			if err != nil {
  2831  				t.Fatalf("Unexpected error: %v", err)
  2832  			}
  2833  
  2834  			for i := range testCase.pod.Spec.InitContainers {
  2835  				err = p.Allocate(s, testCase.pod, &testCase.pod.Spec.InitContainers[i])
  2836  				if !reflect.DeepEqual(err, testCase.expectedError) {
  2837  					t.Fatalf("The actual error %v is different from the expected one %v", err, testCase.expectedError)
  2838  				}
  2839  			}
  2840  
  2841  			if err != nil {
  2842  				return
  2843  			}
  2844  
  2845  			for i := range testCase.pod.Spec.Containers {
  2846  				err = p.Allocate(s, testCase.pod, &testCase.pod.Spec.Containers[i])
  2847  				if err != nil {
  2848  					t.Fatalf("Unexpected error: %v", err)
  2849  				}
  2850  			}
  2851  
  2852  			assignments := s.GetMemoryAssignments()
  2853  			if !areContainerMemoryAssignmentsEqual(t, assignments, testCase.expectedAssignments) {
  2854  				t.Fatalf("Actual assignments %v are different from the expected %v", assignments, testCase.expectedAssignments)
  2855  			}
  2856  
  2857  			machineState := s.GetMachineState()
  2858  			if !areMachineStatesEqual(machineState, testCase.expectedMachineState) {
  2859  				t.Fatalf("The actual machine state %v is different from the expected %v", machineState, testCase.expectedMachineState)
  2860  			}
  2861  		})
  2862  	}
  2863  }
  2864  
  2865  func TestStaticPolicyRemoveContainer(t *testing.T) {
  2866  	testCases := []testStaticPolicy{
  2867  		{
  2868  			description:         "should do nothing when the container does not exist under the state",
  2869  			expectedAssignments: state.ContainerMemoryAssignments{},
  2870  			machineState: state.NUMANodeMap{
  2871  				0: &state.NUMANodeState{
  2872  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2873  						v1.ResourceMemory: {
  2874  							Allocatable:    1536 * mb,
  2875  							Free:           1536 * mb,
  2876  							Reserved:       0,
  2877  							SystemReserved: 512 * mb,
  2878  							TotalMemSize:   2 * gb,
  2879  						},
  2880  						hugepages1Gi: {
  2881  							Allocatable:    gb,
  2882  							Free:           gb,
  2883  							Reserved:       0,
  2884  							SystemReserved: 0,
  2885  							TotalMemSize:   gb,
  2886  						},
  2887  					},
  2888  					Cells: []int{},
  2889  				},
  2890  			},
  2891  			expectedMachineState: state.NUMANodeMap{
  2892  				0: &state.NUMANodeState{
  2893  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2894  						v1.ResourceMemory: {
  2895  							Allocatable:    1536 * mb,
  2896  							Free:           1536 * mb,
  2897  							Reserved:       0,
  2898  							SystemReserved: 512 * mb,
  2899  							TotalMemSize:   2 * gb,
  2900  						},
  2901  						hugepages1Gi: {
  2902  							Allocatable:    gb,
  2903  							Free:           gb,
  2904  							Reserved:       0,
  2905  							SystemReserved: 0,
  2906  							TotalMemSize:   gb,
  2907  						},
  2908  					},
  2909  					Cells: []int{},
  2910  				},
  2911  			},
  2912  			systemReserved: systemReservedMemory{
  2913  				0: map[v1.ResourceName]uint64{
  2914  					v1.ResourceMemory: 512 * mb,
  2915  				},
  2916  			},
  2917  		},
  2918  		{
  2919  			description: "should delete the container assignment and update the machine state",
  2920  			assignments: state.ContainerMemoryAssignments{
  2921  				"pod1": map[string][]state.Block{
  2922  					"container1": {
  2923  						{
  2924  							NUMAAffinity: []int{0},
  2925  							Type:         v1.ResourceMemory,
  2926  							Size:         gb,
  2927  						},
  2928  						{
  2929  							NUMAAffinity: []int{0},
  2930  							Type:         hugepages1Gi,
  2931  							Size:         gb,
  2932  						},
  2933  					},
  2934  				},
  2935  			},
  2936  			expectedAssignments: state.ContainerMemoryAssignments{},
  2937  			machineState: state.NUMANodeMap{
  2938  				0: &state.NUMANodeState{
  2939  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2940  						v1.ResourceMemory: {
  2941  							Allocatable:    1536 * mb,
  2942  							Free:           512 * mb,
  2943  							Reserved:       1024 * mb,
  2944  							SystemReserved: 512 * mb,
  2945  							TotalMemSize:   2 * gb,
  2946  						},
  2947  						hugepages1Gi: {
  2948  							Allocatable:    gb,
  2949  							Free:           0,
  2950  							Reserved:       gb,
  2951  							SystemReserved: 0,
  2952  							TotalMemSize:   gb,
  2953  						},
  2954  					},
  2955  					NumberOfAssignments: 2,
  2956  					Cells:               []int{0},
  2957  				},
  2958  			},
  2959  			expectedMachineState: state.NUMANodeMap{
  2960  				0: &state.NUMANodeState{
  2961  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2962  						v1.ResourceMemory: {
  2963  							Allocatable:    1536 * mb,
  2964  							Free:           1536 * mb,
  2965  							Reserved:       0,
  2966  							SystemReserved: 512 * mb,
  2967  							TotalMemSize:   2 * gb,
  2968  						},
  2969  						hugepages1Gi: {
  2970  							Allocatable:    gb,
  2971  							Free:           gb,
  2972  							Reserved:       0,
  2973  							SystemReserved: 0,
  2974  							TotalMemSize:   gb,
  2975  						},
  2976  					},
  2977  					Cells:               []int{0},
  2978  					NumberOfAssignments: 0,
  2979  				},
  2980  			},
  2981  			systemReserved: systemReservedMemory{
  2982  				0: map[v1.ResourceName]uint64{
  2983  					v1.ResourceMemory: 512 * mb,
  2984  				},
  2985  			},
  2986  		},
  2987  		{
  2988  			description: "should delete the cross NUMA container assignment and update the machine state",
  2989  			assignments: state.ContainerMemoryAssignments{
  2990  				"pod1": map[string][]state.Block{
  2991  					"container1": {
  2992  						{
  2993  							NUMAAffinity: []int{0, 1},
  2994  							Type:         v1.ResourceMemory,
  2995  							Size:         gb,
  2996  						},
  2997  						{
  2998  							NUMAAffinity: []int{0, 1},
  2999  							Type:         hugepages1Gi,
  3000  							Size:         gb,
  3001  						},
  3002  					},
  3003  				},
  3004  			},
  3005  			expectedAssignments: state.ContainerMemoryAssignments{},
  3006  			machineState: state.NUMANodeMap{
  3007  				0: &state.NUMANodeState{
  3008  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3009  						v1.ResourceMemory: {
  3010  							Allocatable:    512 * mb,
  3011  							Free:           0,
  3012  							Reserved:       512 * mb,
  3013  							SystemReserved: 512 * mb,
  3014  							TotalMemSize:   gb,
  3015  						},
  3016  						hugepages1Gi: {
  3017  							Allocatable:    gb,
  3018  							Free:           0,
  3019  							Reserved:       gb,
  3020  							SystemReserved: 0,
  3021  							TotalMemSize:   gb,
  3022  						},
  3023  					},
  3024  					NumberOfAssignments: 2,
  3025  					Cells:               []int{0, 1},
  3026  				},
  3027  				1: &state.NUMANodeState{
  3028  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3029  						v1.ResourceMemory: {
  3030  							Allocatable:    512 * mb,
  3031  							Free:           0,
  3032  							Reserved:       512 * mb,
  3033  							SystemReserved: 512 * mb,
  3034  							TotalMemSize:   gb,
  3035  						},
  3036  						hugepages1Gi: {
  3037  							Allocatable:    gb,
  3038  							Free:           gb,
  3039  							Reserved:       0,
  3040  							SystemReserved: 0,
  3041  							TotalMemSize:   gb,
  3042  						},
  3043  					},
  3044  					NumberOfAssignments: 2,
  3045  					Cells:               []int{0, 1},
  3046  				},
  3047  			},
  3048  			expectedMachineState: state.NUMANodeMap{
  3049  				0: &state.NUMANodeState{
  3050  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3051  						v1.ResourceMemory: {
  3052  							Allocatable:    512 * mb,
  3053  							Free:           512 * mb,
  3054  							Reserved:       0,
  3055  							SystemReserved: 512 * mb,
  3056  							TotalMemSize:   gb,
  3057  						},
  3058  						hugepages1Gi: {
  3059  							Allocatable:    gb,
  3060  							Free:           gb,
  3061  							Reserved:       0,
  3062  							SystemReserved: 0,
  3063  							TotalMemSize:   gb,
  3064  						},
  3065  					},
  3066  					NumberOfAssignments: 0,
  3067  					Cells:               []int{0},
  3068  				},
  3069  				1: &state.NUMANodeState{
  3070  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3071  						v1.ResourceMemory: {
  3072  							Allocatable:    512 * mb,
  3073  							Free:           512 * mb,
  3074  							Reserved:       0,
  3075  							SystemReserved: 512 * mb,
  3076  							TotalMemSize:   gb,
  3077  						},
  3078  						hugepages1Gi: {
  3079  							Allocatable:    gb,
  3080  							Free:           gb,
  3081  							Reserved:       0,
  3082  							SystemReserved: 0,
  3083  							TotalMemSize:   gb,
  3084  						},
  3085  					},
  3086  					NumberOfAssignments: 0,
  3087  					Cells:               []int{1},
  3088  				},
  3089  			},
  3090  			systemReserved: systemReservedMemory{
  3091  				0: map[v1.ResourceName]uint64{
  3092  					v1.ResourceMemory: 512 * mb,
  3093  				},
  3094  				1: map[v1.ResourceName]uint64{
  3095  					v1.ResourceMemory: 512 * mb,
  3096  				},
  3097  			},
  3098  		},
  3099  	}
  3100  
  3101  	for _, testCase := range testCases {
  3102  		t.Run(testCase.description, func(t *testing.T) {
  3103  			p, s, err := initTests(t, &testCase, nil, nil)
  3104  			if err != nil {
  3105  				t.Fatalf("Unexpected error: %v", err)
  3106  			}
  3107  
  3108  			p.RemoveContainer(s, "pod1", "container1")
  3109  			assignments := s.GetMemoryAssignments()
  3110  			if !areContainerMemoryAssignmentsEqual(t, assignments, testCase.expectedAssignments) {
  3111  				t.Fatalf("Actual assignments %v are different from the expected %v", assignments, testCase.expectedAssignments)
  3112  			}
  3113  
  3114  			machineState := s.GetMachineState()
  3115  			if !areMachineStatesEqual(machineState, testCase.expectedMachineState) {
  3116  				t.Fatalf("The actual machine state %v is different from the expected %v", machineState, testCase.expectedMachineState)
  3117  			}
  3118  		})
  3119  	}
  3120  }
  3121  
  3122  func TestStaticPolicyGetTopologyHints(t *testing.T) {
  3123  	testCases := []testStaticPolicy{
  3124  		{
  3125  			description: "should not provide topology hints for non-guaranteed pods",
  3126  			pod:         getPod("pod1", "container1", requirementsBurstable),
  3127  			systemReserved: systemReservedMemory{
  3128  				0: map[v1.ResourceName]uint64{
  3129  					v1.ResourceMemory: 512 * mb,
  3130  				},
  3131  			},
  3132  			expectedTopologyHints: nil,
  3133  		},
  3134  		{
  3135  			description: "should provide topology hints based on the existent memory assignment",
  3136  			assignments: state.ContainerMemoryAssignments{
  3137  				"pod1": map[string][]state.Block{
  3138  					"container1": {
  3139  						{
  3140  							NUMAAffinity: []int{0},
  3141  							Type:         v1.ResourceMemory,
  3142  							Size:         gb,
  3143  						},
  3144  						{
  3145  							NUMAAffinity: []int{0},
  3146  							Type:         hugepages1Gi,
  3147  							Size:         gb,
  3148  						},
  3149  					},
  3150  				},
  3151  			},
  3152  			pod: getPod("pod1", "container1", requirementsGuaranteed),
  3153  			systemReserved: systemReservedMemory{
  3154  				0: map[v1.ResourceName]uint64{
  3155  					v1.ResourceMemory: 512 * mb,
  3156  				},
  3157  			},
  3158  			expectedTopologyHints: map[string][]topologymanager.TopologyHint{
  3159  				string(v1.ResourceMemory): {
  3160  					{
  3161  						NUMANodeAffinity: newNUMAAffinity(0),
  3162  						Preferred:        true,
  3163  					},
  3164  				},
  3165  				string(hugepages1Gi): {
  3166  					{
  3167  						NUMANodeAffinity: newNUMAAffinity(0),
  3168  						Preferred:        true,
  3169  					},
  3170  				},
  3171  			},
  3172  		},
  3173  		{
  3174  			description: "should calculate new topology hints, when the container does not exist under assignments",
  3175  			assignments: state.ContainerMemoryAssignments{
  3176  				"pod1": map[string][]state.Block{
  3177  					"container1": {
  3178  						{
  3179  							NUMAAffinity: []int{0, 1},
  3180  							Type:         v1.ResourceMemory,
  3181  							Size:         2 * gb,
  3182  						},
  3183  						{
  3184  							NUMAAffinity: []int{0, 1},
  3185  							Type:         hugepages1Gi,
  3186  							Size:         2 * gb,
  3187  						},
  3188  					},
  3189  				},
  3190  			},
  3191  			machineState: state.NUMANodeMap{
  3192  				0: &state.NUMANodeState{
  3193  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3194  						v1.ResourceMemory: {
  3195  							Allocatable:    1536 * mb,
  3196  							Free:           0,
  3197  							Reserved:       1536 * mb,
  3198  							SystemReserved: 512 * mb,
  3199  							TotalMemSize:   2 * gb,
  3200  						},
  3201  						hugepages1Gi: {
  3202  							Allocatable:    gb,
  3203  							Free:           0,
  3204  							Reserved:       gb,
  3205  							SystemReserved: 0,
  3206  							TotalMemSize:   gb,
  3207  						},
  3208  					},
  3209  					Cells:               []int{0, 1},
  3210  					NumberOfAssignments: 2,
  3211  				},
  3212  				1: &state.NUMANodeState{
  3213  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3214  						v1.ResourceMemory: {
  3215  							Allocatable:    1536 * mb,
  3216  							Free:           gb,
  3217  							Reserved:       512 * mb,
  3218  							SystemReserved: 512 * mb,
  3219  							TotalMemSize:   2 * gb,
  3220  						},
  3221  						hugepages1Gi: {
  3222  							Allocatable:    gb,
  3223  							Free:           0,
  3224  							Reserved:       gb,
  3225  							SystemReserved: 0,
  3226  							TotalMemSize:   gb,
  3227  						},
  3228  					},
  3229  					Cells:               []int{0, 1},
  3230  					NumberOfAssignments: 2,
  3231  				},
  3232  				2: &state.NUMANodeState{
  3233  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3234  						v1.ResourceMemory: {
  3235  							Allocatable:    1536 * mb,
  3236  							Free:           1536 * mb,
  3237  							Reserved:       0,
  3238  							SystemReserved: 512 * mb,
  3239  							TotalMemSize:   2 * gb,
  3240  						},
  3241  						hugepages1Gi: {
  3242  							Allocatable:    gb,
  3243  							Free:           gb,
  3244  							Reserved:       0,
  3245  							SystemReserved: 0,
  3246  							TotalMemSize:   gb,
  3247  						},
  3248  					},
  3249  					Cells:               []int{2},
  3250  					NumberOfAssignments: 0,
  3251  				},
  3252  				3: &state.NUMANodeState{
  3253  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3254  						v1.ResourceMemory: {
  3255  							Allocatable:    1536 * mb,
  3256  							Free:           1536 * mb,
  3257  							Reserved:       0,
  3258  							SystemReserved: 512 * mb,
  3259  							TotalMemSize:   2 * gb,
  3260  						},
  3261  						hugepages1Gi: {
  3262  							Allocatable:    gb,
  3263  							Free:           gb,
  3264  							Reserved:       0,
  3265  							SystemReserved: 0,
  3266  							TotalMemSize:   gb,
  3267  						},
  3268  					},
  3269  					Cells:               []int{3},
  3270  					NumberOfAssignments: 0,
  3271  				},
  3272  			},
  3273  			pod: getPod("pod2", "container2", requirementsGuaranteed),
  3274  			systemReserved: systemReservedMemory{
  3275  				0: map[v1.ResourceName]uint64{
  3276  					v1.ResourceMemory: 512 * mb,
  3277  				},
  3278  				1: map[v1.ResourceName]uint64{
  3279  					v1.ResourceMemory: 512 * mb,
  3280  				},
  3281  				2: map[v1.ResourceName]uint64{
  3282  					v1.ResourceMemory: 512 * mb,
  3283  				},
  3284  				3: map[v1.ResourceName]uint64{
  3285  					v1.ResourceMemory: 512 * mb,
  3286  				},
  3287  			},
  3288  			expectedTopologyHints: map[string][]topologymanager.TopologyHint{
  3289  				string(v1.ResourceMemory): {
  3290  					{
  3291  						NUMANodeAffinity: newNUMAAffinity(2),
  3292  						Preferred:        true,
  3293  					},
  3294  					{
  3295  						NUMANodeAffinity: newNUMAAffinity(3),
  3296  						Preferred:        true,
  3297  					},
  3298  					{
  3299  						NUMANodeAffinity: newNUMAAffinity(2, 3),
  3300  						Preferred:        false,
  3301  					},
  3302  				},
  3303  				string(hugepages1Gi): {
  3304  					{
  3305  						NUMANodeAffinity: newNUMAAffinity(2),
  3306  						Preferred:        true,
  3307  					},
  3308  					{
  3309  						NUMANodeAffinity: newNUMAAffinity(3),
  3310  						Preferred:        true,
  3311  					},
  3312  					{
  3313  						NUMANodeAffinity: newNUMAAffinity(2, 3),
  3314  						Preferred:        false,
  3315  					},
  3316  				},
  3317  			},
  3318  		},
  3319  		{
  3320  			description: "should fail when number of existing memory assignment resources are different from resources requested by container",
  3321  			assignments: state.ContainerMemoryAssignments{
  3322  				"pod1": map[string][]state.Block{
  3323  					"container1": {
  3324  						{
  3325  							NUMAAffinity: []int{0},
  3326  							Type:         v1.ResourceMemory,
  3327  							Size:         gb,
  3328  						},
  3329  					},
  3330  				},
  3331  			},
  3332  			pod: getPod("pod1", "container1", requirementsGuaranteed),
  3333  			systemReserved: systemReservedMemory{
  3334  				0: map[v1.ResourceName]uint64{
  3335  					v1.ResourceMemory: 512 * mb,
  3336  				},
  3337  			},
  3338  			expectedTopologyHints: nil,
  3339  		},
  3340  		{
  3341  			description: "should fail when existing memory assignment resources are different from resources requested by container",
  3342  			assignments: state.ContainerMemoryAssignments{
  3343  				"pod1": map[string][]state.Block{
  3344  					"container1": {
  3345  						{
  3346  							NUMAAffinity: []int{0},
  3347  							Type:         v1.ResourceMemory,
  3348  							Size:         gb,
  3349  						},
  3350  						{
  3351  							NUMAAffinity: []int{0},
  3352  							Type:         hugepages2M,
  3353  							Size:         gb,
  3354  						},
  3355  					},
  3356  				},
  3357  			},
  3358  			pod: getPod("pod1", "container1", requirementsGuaranteed),
  3359  			systemReserved: systemReservedMemory{
  3360  				0: map[v1.ResourceName]uint64{
  3361  					v1.ResourceMemory: 512 * mb,
  3362  				},
  3363  			},
  3364  			expectedTopologyHints: nil,
  3365  		},
  3366  		{
  3367  			description: "should fail when existing memory assignment size is different from one requested by the container",
  3368  			assignments: state.ContainerMemoryAssignments{
  3369  				"pod1": map[string][]state.Block{
  3370  					"container1": {
  3371  						{
  3372  							NUMAAffinity: []int{0},
  3373  							Type:         v1.ResourceMemory,
  3374  							Size:         512 * mb,
  3375  						},
  3376  						{
  3377  							NUMAAffinity: []int{0},
  3378  							Type:         hugepages1Gi,
  3379  							Size:         gb,
  3380  						},
  3381  					},
  3382  				},
  3383  			},
  3384  			pod: getPod("pod1", "container1", requirementsGuaranteed),
  3385  			systemReserved: systemReservedMemory{
  3386  				0: map[v1.ResourceName]uint64{
  3387  					v1.ResourceMemory: 512 * mb,
  3388  				},
  3389  			},
  3390  			expectedTopologyHints: nil,
  3391  		},
  3392  		{
  3393  			description: "should not return preferred hints with multiple NUMA nodes for the pod with resources satisfied by a single NUMA node",
  3394  			assignments: state.ContainerMemoryAssignments{
  3395  				"pod1": map[string][]state.Block{
  3396  					"container1": {
  3397  						{
  3398  							NUMAAffinity: []int{0, 1},
  3399  							Type:         v1.ResourceMemory,
  3400  							Size:         2 * gb,
  3401  						},
  3402  						{
  3403  							NUMAAffinity: []int{0, 1},
  3404  							Type:         hugepages2M,
  3405  							Size:         24 * mb,
  3406  						},
  3407  					},
  3408  				},
  3409  			},
  3410  			machineState: state.NUMANodeMap{
  3411  				0: &state.NUMANodeState{
  3412  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3413  						v1.ResourceMemory: {
  3414  							Allocatable:    1536 * mb,
  3415  							Free:           0,
  3416  							Reserved:       1536 * mb,
  3417  							SystemReserved: 512 * mb,
  3418  							TotalMemSize:   2 * gb,
  3419  						},
  3420  						hugepages2M: {
  3421  							Allocatable:    20 * mb,
  3422  							Free:           0,
  3423  							Reserved:       20 * mb,
  3424  							SystemReserved: 0,
  3425  							TotalMemSize:   20 * mb,
  3426  						},
  3427  					},
  3428  					Cells:               []int{0, 1},
  3429  					NumberOfAssignments: 2,
  3430  				},
  3431  				1: &state.NUMANodeState{
  3432  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  3433  						v1.ResourceMemory: {
  3434  							Allocatable:    1536 * mb,
  3435  							Free:           gb,
  3436  							Reserved:       512 * mb,
  3437  							SystemReserved: 512 * mb,
  3438  							TotalMemSize:   2 * gb,
  3439  						},
  3440  						hugepages2M: {
  3441  							Allocatable:    20 * mb,
  3442  							Free:           16 * mb,
  3443  							Reserved:       4 * mb,
  3444  							SystemReserved: 0,
  3445  							TotalMemSize:   20 * mb,
  3446  						},
  3447  					},
  3448  					Cells:               []int{0, 1},
  3449  					NumberOfAssignments: 2,
  3450  				},
  3451  			},
  3452  			pod: getPod("pod2",
  3453  				"container2",
  3454  				&v1.ResourceRequirements{
  3455  					Limits: v1.ResourceList{
  3456  						v1.ResourceCPU:    resource.MustParse("1000Mi"),
  3457  						v1.ResourceMemory: resource.MustParse("1Gi"),
  3458  						hugepages2M:       resource.MustParse("16Mi"),
  3459  					},
  3460  					Requests: v1.ResourceList{
  3461  						v1.ResourceCPU:    resource.MustParse("1000Mi"),
  3462  						v1.ResourceMemory: resource.MustParse("1Gi"),
  3463  						hugepages2M:       resource.MustParse("16Mi"),
  3464  					},
  3465  				},
  3466  			),
  3467  			systemReserved: systemReservedMemory{
  3468  				0: map[v1.ResourceName]uint64{
  3469  					v1.ResourceMemory: 512 * mb,
  3470  				},
  3471  				1: map[v1.ResourceName]uint64{
  3472  					v1.ResourceMemory: 512 * mb,
  3473  				},
  3474  			},
  3475  			expectedTopologyHints: map[string][]topologymanager.TopologyHint{
  3476  				string(v1.ResourceMemory): {
  3477  					{
  3478  						NUMANodeAffinity: newNUMAAffinity(0, 1),
  3479  						Preferred:        false,
  3480  					},
  3481  				},
  3482  				hugepages2M: {
  3483  					{
  3484  						NUMANodeAffinity: newNUMAAffinity(0, 1),
  3485  						Preferred:        false,
  3486  					},
  3487  				},
  3488  			},
  3489  		},
  3490  	}
  3491  
  3492  	for _, testCase := range testCases {
  3493  		t.Run(testCase.description, func(t *testing.T) {
  3494  			p, s, err := initTests(t, &testCase, nil, nil)
  3495  			if err != nil {
  3496  				t.Fatalf("Unexpected error: %v", err)
  3497  			}
  3498  
  3499  			topologyHints := p.GetTopologyHints(s, testCase.pod, &testCase.pod.Spec.Containers[0])
  3500  			if !reflect.DeepEqual(topologyHints, testCase.expectedTopologyHints) {
  3501  				t.Fatalf("The actual topology hints: '%+v' are different from the expected one: '%+v'", topologyHints, testCase.expectedTopologyHints)
  3502  			}
  3503  		})
  3504  	}
  3505  }
  3506  
  3507  func Test_getPodRequestedResources(t *testing.T) {
  3508  	testCases := []struct {
  3509  		description string
  3510  		pod         *v1.Pod
  3511  		expected    map[v1.ResourceName]uint64
  3512  	}{
  3513  		{
  3514  			description: "maximum resources of init containers > total resources of containers",
  3515  			pod: getPodWithInitContainers(
  3516  				"",
  3517  				[]v1.Container{
  3518  					{
  3519  						Name: "container1",
  3520  						Resources: v1.ResourceRequirements{
  3521  							Requests: v1.ResourceList{
  3522  								v1.ResourceMemory: resource.MustParse("1Gi"),
  3523  								hugepages1Gi:      resource.MustParse("1Gi"),
  3524  							},
  3525  						},
  3526  					},
  3527  					{
  3528  						Name: "container2",
  3529  						Resources: v1.ResourceRequirements{
  3530  							Requests: v1.ResourceList{
  3531  								v1.ResourceMemory: resource.MustParse("2Gi"),
  3532  								hugepages1Gi:      resource.MustParse("2Gi"),
  3533  							},
  3534  						},
  3535  					},
  3536  				},
  3537  				[]v1.Container{
  3538  					{
  3539  						Name: "initContainer1",
  3540  						Resources: v1.ResourceRequirements{
  3541  							Requests: v1.ResourceList{
  3542  								v1.ResourceMemory: resource.MustParse("1Gi"),
  3543  								hugepages1Gi:      resource.MustParse("1Gi"),
  3544  							},
  3545  						},
  3546  					},
  3547  					{
  3548  						Name: "initContainer2",
  3549  						Resources: v1.ResourceRequirements{
  3550  							Requests: v1.ResourceList{
  3551  								v1.ResourceMemory: resource.MustParse("4Gi"),
  3552  								hugepages1Gi:      resource.MustParse("4Gi"),
  3553  							},
  3554  						},
  3555  					},
  3556  				},
  3557  			),
  3558  			expected: map[v1.ResourceName]uint64{
  3559  				v1.ResourceMemory: 4 * gb,
  3560  				hugepages1Gi:      4 * gb,
  3561  			},
  3562  		},
  3563  		{
  3564  			description: "maximum resources of init containers < total resources of containers",
  3565  			pod: getPodWithInitContainers(
  3566  				"",
  3567  				[]v1.Container{
  3568  					{
  3569  						Name: "container1",
  3570  						Resources: v1.ResourceRequirements{
  3571  							Requests: v1.ResourceList{
  3572  								v1.ResourceMemory: resource.MustParse("2Gi"),
  3573  								hugepages1Gi:      resource.MustParse("2Gi"),
  3574  							},
  3575  						},
  3576  					},
  3577  					{
  3578  						Name: "container2",
  3579  						Resources: v1.ResourceRequirements{
  3580  							Requests: v1.ResourceList{
  3581  								v1.ResourceMemory: resource.MustParse("3Gi"),
  3582  								hugepages1Gi:      resource.MustParse("3Gi"),
  3583  							},
  3584  						},
  3585  					},
  3586  				},
  3587  				[]v1.Container{
  3588  					{
  3589  						Name: "initContainer1",
  3590  						Resources: v1.ResourceRequirements{
  3591  							Requests: v1.ResourceList{
  3592  								v1.ResourceMemory: resource.MustParse("1Gi"),
  3593  								hugepages1Gi:      resource.MustParse("1Gi"),
  3594  							},
  3595  						},
  3596  					},
  3597  					{
  3598  						Name: "initContainer2",
  3599  						Resources: v1.ResourceRequirements{
  3600  							Requests: v1.ResourceList{
  3601  								v1.ResourceMemory: resource.MustParse("3Gi"),
  3602  								hugepages1Gi:      resource.MustParse("3Gi"),
  3603  							},
  3604  						},
  3605  					},
  3606  				},
  3607  			),
  3608  			expected: map[v1.ResourceName]uint64{
  3609  				v1.ResourceMemory: 5 * gb,
  3610  				hugepages1Gi:      5 * gb,
  3611  			},
  3612  		},
  3613  		{
  3614  			description: "calculate different resources independently",
  3615  			pod: getPodWithInitContainers(
  3616  				"",
  3617  				[]v1.Container{
  3618  					{
  3619  						Name: "container1",
  3620  						Resources: v1.ResourceRequirements{
  3621  							Requests: v1.ResourceList{
  3622  								v1.ResourceMemory: resource.MustParse("2Gi"),
  3623  								hugepages1Gi:      resource.MustParse("1Gi"),
  3624  							},
  3625  						},
  3626  					},
  3627  					{
  3628  						Name: "container2",
  3629  						Resources: v1.ResourceRequirements{
  3630  							Requests: v1.ResourceList{
  3631  								v1.ResourceMemory: resource.MustParse("3Gi"),
  3632  								hugepages1Gi:      resource.MustParse("2Gi"),
  3633  							},
  3634  						},
  3635  					},
  3636  				},
  3637  				[]v1.Container{
  3638  					{
  3639  						Name: "initContainer1",
  3640  						Resources: v1.ResourceRequirements{
  3641  							Requests: v1.ResourceList{
  3642  								v1.ResourceMemory: resource.MustParse("1Gi"),
  3643  								hugepages1Gi:      resource.MustParse("1Gi"),
  3644  							},
  3645  						},
  3646  					},
  3647  					{
  3648  						Name: "initContainer2",
  3649  						Resources: v1.ResourceRequirements{
  3650  							Requests: v1.ResourceList{
  3651  								v1.ResourceMemory: resource.MustParse("3Gi"),
  3652  								hugepages1Gi:      resource.MustParse("4Gi"),
  3653  							},
  3654  						},
  3655  					},
  3656  				},
  3657  			),
  3658  			expected: map[v1.ResourceName]uint64{
  3659  				v1.ResourceMemory: 5 * gb,
  3660  				hugepages1Gi:      4 * gb,
  3661  			},
  3662  		},
  3663  		{
  3664  			description: "maximum resources of init containers > total resources of long running containers, including restartable init containers",
  3665  			pod: getPodWithInitContainers(
  3666  				"",
  3667  				[]v1.Container{
  3668  					{
  3669  						Name: "container1",
  3670  						Resources: v1.ResourceRequirements{
  3671  							Requests: v1.ResourceList{
  3672  								v1.ResourceMemory: resource.MustParse("1Gi"),
  3673  								hugepages1Gi:      resource.MustParse("1Gi"),
  3674  							},
  3675  						},
  3676  					},
  3677  					{
  3678  						Name: "container2",
  3679  						Resources: v1.ResourceRequirements{
  3680  							Requests: v1.ResourceList{
  3681  								v1.ResourceMemory: resource.MustParse("2Gi"),
  3682  								hugepages1Gi:      resource.MustParse("2Gi"),
  3683  							},
  3684  						},
  3685  					},
  3686  				},
  3687  				[]v1.Container{
  3688  					{
  3689  						Name: "restartableInit1",
  3690  						Resources: v1.ResourceRequirements{
  3691  							Requests: v1.ResourceList{
  3692  								v1.ResourceMemory: resource.MustParse("2Gi"),
  3693  								hugepages1Gi:      resource.MustParse("2Gi"),
  3694  							},
  3695  						},
  3696  						RestartPolicy: &containerRestartPolicyAlways,
  3697  					},
  3698  					{
  3699  						Name: "initContainer2",
  3700  						Resources: v1.ResourceRequirements{
  3701  							Requests: v1.ResourceList{
  3702  								v1.ResourceMemory: resource.MustParse("4Gi"),
  3703  								hugepages1Gi:      resource.MustParse("4Gi"),
  3704  							},
  3705  						},
  3706  					},
  3707  				},
  3708  			),
  3709  			expected: map[v1.ResourceName]uint64{
  3710  				v1.ResourceMemory: 6 * gb,
  3711  				hugepages1Gi:      6 * gb,
  3712  			},
  3713  		},
  3714  		{
  3715  			description: "maximum resources of init containers < total resources of long running containers, including restartable init containers",
  3716  			pod: getPodWithInitContainers(
  3717  				"",
  3718  				[]v1.Container{
  3719  					{
  3720  						Name: "container1",
  3721  						Resources: v1.ResourceRequirements{
  3722  							Requests: v1.ResourceList{
  3723  								v1.ResourceMemory: resource.MustParse("2Gi"),
  3724  								hugepages1Gi:      resource.MustParse("2Gi"),
  3725  							},
  3726  						},
  3727  					},
  3728  					{
  3729  						Name: "container2",
  3730  						Resources: v1.ResourceRequirements{
  3731  							Requests: v1.ResourceList{
  3732  								v1.ResourceMemory: resource.MustParse("3Gi"),
  3733  								hugepages1Gi:      resource.MustParse("3Gi"),
  3734  							},
  3735  						},
  3736  					},
  3737  				},
  3738  				[]v1.Container{
  3739  					{
  3740  						Name: "restartableInit1",
  3741  						Resources: v1.ResourceRequirements{
  3742  							Requests: v1.ResourceList{
  3743  								v1.ResourceMemory: resource.MustParse("2Gi"),
  3744  								hugepages1Gi:      resource.MustParse("2Gi"),
  3745  							},
  3746  						},
  3747  						RestartPolicy: &containerRestartPolicyAlways,
  3748  					},
  3749  					{
  3750  						Name: "initContainer2",
  3751  						Resources: v1.ResourceRequirements{
  3752  							Requests: v1.ResourceList{
  3753  								v1.ResourceMemory: resource.MustParse("4Gi"),
  3754  								hugepages1Gi:      resource.MustParse("4Gi"),
  3755  							},
  3756  						},
  3757  					},
  3758  				},
  3759  			),
  3760  			expected: map[v1.ResourceName]uint64{
  3761  				v1.ResourceMemory: 7 * gb,
  3762  				hugepages1Gi:      7 * gb,
  3763  			},
  3764  		},
  3765  	}
  3766  
  3767  	for _, tc := range testCases {
  3768  		t.Run(tc.description, func(t *testing.T) {
  3769  			actual, err := getPodRequestedResources(tc.pod)
  3770  			if err != nil {
  3771  				t.Fatalf("Unexpected error: %v", err)
  3772  			}
  3773  			if diff := cmp.Diff(actual, tc.expected); diff != "" {
  3774  				t.Errorf("getPodRequestedResources() mismatch (-want +got):\n%s", diff)
  3775  			}
  3776  		})
  3777  	}
  3778  }
  3779  

View as plain text