...

Source file src/k8s.io/kubernetes/pkg/kubelet/cm/memorymanager/memory_manager_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  	"context"
    21  	"fmt"
    22  	"os"
    23  	"reflect"
    24  	"strings"
    25  	"testing"
    26  
    27  	"k8s.io/klog/v2"
    28  
    29  	cadvisorapi "github.com/google/cadvisor/info/v1"
    30  	"github.com/stretchr/testify/assert"
    31  
    32  	v1 "k8s.io/api/core/v1"
    33  	"k8s.io/apimachinery/pkg/api/resource"
    34  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    35  	"k8s.io/apimachinery/pkg/types"
    36  	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
    37  	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
    38  	"k8s.io/kubernetes/pkg/kubelet/cm/containermap"
    39  	"k8s.io/kubernetes/pkg/kubelet/cm/memorymanager/state"
    40  	"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager"
    41  )
    42  
    43  const (
    44  	hugepages2M = "hugepages-2Mi"
    45  	hugepages1G = "hugepages-1Gi"
    46  )
    47  
    48  const policyTypeMock policyType = "mock"
    49  
    50  type testMemoryManager struct {
    51  	description                string
    52  	machineInfo                cadvisorapi.MachineInfo
    53  	assignments                state.ContainerMemoryAssignments
    54  	expectedAssignments        state.ContainerMemoryAssignments
    55  	machineState               state.NUMANodeMap
    56  	expectedMachineState       state.NUMANodeMap
    57  	expectedError              error
    58  	expectedAllocateError      error
    59  	expectedAddContainerError  error
    60  	updateError                error
    61  	removeContainerID          string
    62  	nodeAllocatableReservation v1.ResourceList
    63  	policyName                 policyType
    64  	affinity                   topologymanager.Store
    65  	systemReservedMemory       []kubeletconfig.MemoryReservation
    66  	expectedHints              map[string][]topologymanager.TopologyHint
    67  	expectedReserved           systemReservedMemory
    68  	reserved                   systemReservedMemory
    69  	podAllocate                *v1.Pod
    70  	firstPod                   *v1.Pod
    71  	activePods                 []*v1.Pod
    72  }
    73  
    74  func returnPolicyByName(testCase testMemoryManager) Policy {
    75  	switch testCase.policyName {
    76  	case policyTypeMock:
    77  		return &mockPolicy{
    78  			err: fmt.Errorf("fake reg error"),
    79  		}
    80  	case policyTypeStatic:
    81  		policy, _ := NewPolicyStatic(&testCase.machineInfo, testCase.reserved, topologymanager.NewFakeManager())
    82  		return policy
    83  	case policyTypeNone:
    84  		return NewPolicyNone()
    85  	}
    86  	return nil
    87  }
    88  
    89  type mockPolicy struct {
    90  	err error
    91  }
    92  
    93  func (p *mockPolicy) Name() string {
    94  	return string(policyTypeMock)
    95  }
    96  
    97  func (p *mockPolicy) Start(s state.State) error {
    98  	return p.err
    99  }
   100  
   101  func (p *mockPolicy) Allocate(s state.State, pod *v1.Pod, container *v1.Container) error {
   102  	return p.err
   103  }
   104  
   105  func (p *mockPolicy) RemoveContainer(s state.State, podUID string, containerName string) {
   106  }
   107  
   108  func (p *mockPolicy) GetTopologyHints(s state.State, pod *v1.Pod, container *v1.Container) map[string][]topologymanager.TopologyHint {
   109  	return nil
   110  }
   111  
   112  func (p *mockPolicy) GetPodTopologyHints(s state.State, pod *v1.Pod) map[string][]topologymanager.TopologyHint {
   113  	return nil
   114  }
   115  
   116  // GetAllocatableMemory returns the amount of allocatable memory for each NUMA node
   117  func (p *mockPolicy) GetAllocatableMemory(s state.State) []state.Block {
   118  	return []state.Block{}
   119  }
   120  
   121  type mockRuntimeService struct {
   122  	err error
   123  }
   124  
   125  func (rt mockRuntimeService) UpdateContainerResources(_ context.Context, id string, resources *runtimeapi.ContainerResources) error {
   126  	return rt.err
   127  }
   128  
   129  type mockPodStatusProvider struct {
   130  	podStatus v1.PodStatus
   131  	found     bool
   132  }
   133  
   134  func (psp mockPodStatusProvider) GetPodStatus(uid types.UID) (v1.PodStatus, bool) {
   135  	return psp.podStatus, psp.found
   136  }
   137  
   138  func getPod(podUID string, containerName string, requirements *v1.ResourceRequirements) *v1.Pod {
   139  	return &v1.Pod{
   140  		ObjectMeta: metav1.ObjectMeta{
   141  			UID: types.UID(podUID),
   142  		},
   143  		Spec: v1.PodSpec{
   144  			Containers: []v1.Container{
   145  				{
   146  					Name:      containerName,
   147  					Resources: *requirements,
   148  				},
   149  			},
   150  		},
   151  	}
   152  }
   153  
   154  func getPodWithInitContainers(podUID string, containers []v1.Container, initContainers []v1.Container) *v1.Pod {
   155  	return &v1.Pod{
   156  		ObjectMeta: metav1.ObjectMeta{
   157  			UID: types.UID(podUID),
   158  		},
   159  		Spec: v1.PodSpec{
   160  			InitContainers: initContainers,
   161  			Containers:     containers,
   162  		},
   163  	}
   164  }
   165  
   166  func TestValidateReservedMemory(t *testing.T) {
   167  	machineInfo := &cadvisorapi.MachineInfo{
   168  		Topology: []cadvisorapi.Node{
   169  			{Id: 0},
   170  			{Id: 1},
   171  		},
   172  	}
   173  	const msgNotEqual = "the total amount %q of type %q is not equal to the value %q determined by Node Allocatable feature"
   174  	testCases := []struct {
   175  		description                string
   176  		nodeAllocatableReservation v1.ResourceList
   177  		machineInfo                *cadvisorapi.MachineInfo
   178  		systemReservedMemory       []kubeletconfig.MemoryReservation
   179  		expectedError              string
   180  	}{
   181  		{
   182  			"Node Allocatable not set, reserved not set",
   183  			v1.ResourceList{},
   184  			machineInfo,
   185  			[]kubeletconfig.MemoryReservation{},
   186  			"",
   187  		},
   188  		{
   189  			"Node Allocatable set to zero, reserved set to zero",
   190  			v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(0, resource.DecimalSI)},
   191  			machineInfo,
   192  			[]kubeletconfig.MemoryReservation{
   193  				{
   194  					NumaNode: 0,
   195  					Limits: v1.ResourceList{
   196  						v1.ResourceMemory: *resource.NewQuantity(0, resource.DecimalSI),
   197  					},
   198  				},
   199  			},
   200  			"",
   201  		},
   202  		{
   203  			"Node Allocatable not set (equal zero), reserved set",
   204  			v1.ResourceList{},
   205  			machineInfo,
   206  			[]kubeletconfig.MemoryReservation{
   207  				{
   208  					NumaNode: 0,
   209  					Limits: v1.ResourceList{
   210  						v1.ResourceMemory: *resource.NewQuantity(12, resource.DecimalSI),
   211  					},
   212  				},
   213  			},
   214  			fmt.Sprintf(msgNotEqual, "12", v1.ResourceMemory, "0"),
   215  		},
   216  		{
   217  			"Node Allocatable set, reserved not set",
   218  			v1.ResourceList{hugepages2M: *resource.NewQuantity(5, resource.DecimalSI)},
   219  			machineInfo,
   220  			[]kubeletconfig.MemoryReservation{},
   221  			fmt.Sprintf(msgNotEqual, "0", hugepages2M, "5"),
   222  		},
   223  		{
   224  			"Reserved not equal to Node Allocatable",
   225  			v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(5, resource.DecimalSI)},
   226  			machineInfo,
   227  			[]kubeletconfig.MemoryReservation{
   228  				{
   229  					NumaNode: 0,
   230  					Limits: v1.ResourceList{
   231  						v1.ResourceMemory: *resource.NewQuantity(12, resource.DecimalSI),
   232  					},
   233  				},
   234  			},
   235  			fmt.Sprintf(msgNotEqual, "12", v1.ResourceMemory, "5"),
   236  		},
   237  		{
   238  			"Reserved contains the NUMA node that does not exist under the machine",
   239  			v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(17, resource.DecimalSI)},
   240  			machineInfo,
   241  			[]kubeletconfig.MemoryReservation{
   242  				{
   243  					NumaNode: 0,
   244  					Limits: v1.ResourceList{
   245  						v1.ResourceMemory: *resource.NewQuantity(12, resource.DecimalSI),
   246  					},
   247  				},
   248  				{
   249  					NumaNode: 2,
   250  					Limits: v1.ResourceList{
   251  						v1.ResourceMemory: *resource.NewQuantity(5, resource.DecimalSI),
   252  					},
   253  				},
   254  			},
   255  			"the reserved memory configuration references a NUMA node 2 that does not exist on this machine",
   256  		},
   257  		{
   258  			"Reserved total equal to Node Allocatable",
   259  			v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(17, resource.DecimalSI),
   260  				hugepages2M: *resource.NewQuantity(77, resource.DecimalSI),
   261  				hugepages1G: *resource.NewQuantity(13, resource.DecimalSI)},
   262  			machineInfo,
   263  			[]kubeletconfig.MemoryReservation{
   264  				{
   265  					NumaNode: 0,
   266  					Limits: v1.ResourceList{
   267  						v1.ResourceMemory: *resource.NewQuantity(12, resource.DecimalSI),
   268  						hugepages2M:       *resource.NewQuantity(70, resource.DecimalSI),
   269  						hugepages1G:       *resource.NewQuantity(13, resource.DecimalSI),
   270  					},
   271  				},
   272  				{
   273  					NumaNode: 1,
   274  					Limits: v1.ResourceList{
   275  						v1.ResourceMemory: *resource.NewQuantity(5, resource.DecimalSI),
   276  						hugepages2M:       *resource.NewQuantity(7, resource.DecimalSI),
   277  					},
   278  				},
   279  			},
   280  			"",
   281  		},
   282  		{
   283  			"Reserved total hugapages-2M not equal to Node Allocatable",
   284  			v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(17, resource.DecimalSI),
   285  				hugepages2M: *resource.NewQuantity(14, resource.DecimalSI),
   286  				hugepages1G: *resource.NewQuantity(13, resource.DecimalSI)},
   287  			machineInfo,
   288  			[]kubeletconfig.MemoryReservation{
   289  				{
   290  					NumaNode: 0,
   291  					Limits: v1.ResourceList{
   292  						v1.ResourceMemory: *resource.NewQuantity(12, resource.DecimalSI),
   293  						hugepages2M:       *resource.NewQuantity(70, resource.DecimalSI),
   294  						hugepages1G:       *resource.NewQuantity(13, resource.DecimalSI),
   295  					},
   296  				},
   297  				{
   298  					NumaNode: 1,
   299  					Limits: v1.ResourceList{
   300  						v1.ResourceMemory: *resource.NewQuantity(5, resource.DecimalSI),
   301  						hugepages2M:       *resource.NewQuantity(7, resource.DecimalSI),
   302  					},
   303  				},
   304  			},
   305  
   306  			fmt.Sprintf(msgNotEqual, "77", hugepages2M, "14"),
   307  		},
   308  	}
   309  
   310  	for _, tc := range testCases {
   311  		t.Run(tc.description, func(t *testing.T) {
   312  			err := validateReservedMemory(tc.machineInfo, tc.nodeAllocatableReservation, tc.systemReservedMemory)
   313  			if strings.TrimSpace(tc.expectedError) != "" {
   314  				assert.Error(t, err)
   315  				assert.Equal(t, tc.expectedError, err.Error())
   316  			}
   317  		})
   318  	}
   319  }
   320  
   321  func TestConvertPreReserved(t *testing.T) {
   322  	machineInfo := cadvisorapi.MachineInfo{
   323  		Topology: []cadvisorapi.Node{
   324  			{Id: 0},
   325  			{Id: 1},
   326  		},
   327  	}
   328  
   329  	testCases := []struct {
   330  		description            string
   331  		systemReserved         []kubeletconfig.MemoryReservation
   332  		systemReservedExpected systemReservedMemory
   333  		expectedError          string
   334  	}{
   335  		{
   336  			"Empty",
   337  			[]kubeletconfig.MemoryReservation{},
   338  			systemReservedMemory{
   339  				0: map[v1.ResourceName]uint64{},
   340  				1: map[v1.ResourceName]uint64{},
   341  			},
   342  			"",
   343  		},
   344  		{
   345  			"Single NUMA node is reserved",
   346  			[]kubeletconfig.MemoryReservation{
   347  				{
   348  					NumaNode: 0,
   349  					Limits: v1.ResourceList{
   350  						v1.ResourceMemory: *resource.NewQuantity(12, resource.DecimalSI),
   351  						hugepages2M:       *resource.NewQuantity(70, resource.DecimalSI),
   352  						hugepages1G:       *resource.NewQuantity(13, resource.DecimalSI),
   353  					},
   354  				},
   355  			},
   356  			systemReservedMemory{
   357  				0: map[v1.ResourceName]uint64{
   358  					v1.ResourceMemory: 12,
   359  					hugepages2M:       70,
   360  					hugepages1G:       13,
   361  				},
   362  				1: map[v1.ResourceName]uint64{},
   363  			},
   364  			"",
   365  		},
   366  		{
   367  			"Both NUMA nodes are reserved",
   368  			[]kubeletconfig.MemoryReservation{
   369  				{
   370  					NumaNode: 0,
   371  					Limits: v1.ResourceList{
   372  						v1.ResourceMemory: *resource.NewQuantity(12, resource.DecimalSI),
   373  						hugepages2M:       *resource.NewQuantity(70, resource.DecimalSI),
   374  						hugepages1G:       *resource.NewQuantity(13, resource.DecimalSI),
   375  					},
   376  				},
   377  				{
   378  					NumaNode: 1,
   379  					Limits: v1.ResourceList{
   380  						v1.ResourceMemory: *resource.NewQuantity(5, resource.DecimalSI),
   381  						hugepages2M:       *resource.NewQuantity(7, resource.DecimalSI),
   382  					},
   383  				},
   384  			},
   385  			systemReservedMemory{
   386  				0: map[v1.ResourceName]uint64{
   387  					v1.ResourceMemory: 12,
   388  					hugepages2M:       70,
   389  					hugepages1G:       13,
   390  				},
   391  				1: map[v1.ResourceName]uint64{
   392  					v1.ResourceMemory: 5,
   393  					hugepages2M:       7,
   394  				},
   395  			},
   396  			"",
   397  		},
   398  	}
   399  
   400  	for _, tc := range testCases {
   401  		t.Run(tc.description, func(t *testing.T) {
   402  			reserved, _ := convertReserved(&machineInfo, tc.systemReserved)
   403  			if !reflect.DeepEqual(reserved, tc.systemReservedExpected) {
   404  				t.Errorf("got %v, expected %v", reserved, tc.systemReservedExpected)
   405  			}
   406  		})
   407  	}
   408  }
   409  
   410  func TestGetSystemReservedMemory(t *testing.T) {
   411  	machineInfo := returnMachineInfo()
   412  	testCases := []testMemoryManager{
   413  		{
   414  			description:                "Should return empty map when reservation is not done",
   415  			nodeAllocatableReservation: v1.ResourceList{},
   416  			systemReservedMemory:       []kubeletconfig.MemoryReservation{},
   417  			expectedReserved: systemReservedMemory{
   418  				0: {},
   419  				1: {},
   420  			},
   421  			expectedError: nil,
   422  			machineInfo:   machineInfo,
   423  		},
   424  		{
   425  			description:                "Should return error when Allocatable reservation is not equal to the reserved memory",
   426  			nodeAllocatableReservation: v1.ResourceList{},
   427  			systemReservedMemory: []kubeletconfig.MemoryReservation{
   428  				{
   429  					NumaNode: 0,
   430  					Limits: v1.ResourceList{
   431  						v1.ResourceMemory: *resource.NewQuantity(gb, resource.BinarySI),
   432  					},
   433  				},
   434  			},
   435  			expectedReserved: nil,
   436  			expectedError:    fmt.Errorf("the total amount \"1Gi\" of type \"memory\" is not equal to the value \"0\" determined by Node Allocatable feature"),
   437  			machineInfo:      machineInfo,
   438  		},
   439  		{
   440  			description:                "Reserved should be equal to systemReservedMemory",
   441  			nodeAllocatableReservation: v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(2*gb, resource.BinarySI)},
   442  			systemReservedMemory: []kubeletconfig.MemoryReservation{
   443  				{
   444  					NumaNode: 0,
   445  					Limits: v1.ResourceList{
   446  						v1.ResourceMemory: *resource.NewQuantity(gb, resource.BinarySI),
   447  					},
   448  				},
   449  				{
   450  					NumaNode: 1,
   451  					Limits: v1.ResourceList{
   452  						v1.ResourceMemory: *resource.NewQuantity(gb, resource.BinarySI),
   453  					},
   454  				},
   455  			},
   456  			expectedReserved: systemReservedMemory{
   457  				0: map[v1.ResourceName]uint64{
   458  					v1.ResourceMemory: 1 * gb,
   459  				},
   460  				1: map[v1.ResourceName]uint64{
   461  					v1.ResourceMemory: 1 * gb,
   462  				},
   463  			},
   464  			expectedError: nil,
   465  			machineInfo:   machineInfo,
   466  		},
   467  	}
   468  
   469  	for _, testCase := range testCases {
   470  		t.Run(testCase.description, func(t *testing.T) {
   471  			res, err := getSystemReservedMemory(&testCase.machineInfo, testCase.nodeAllocatableReservation, testCase.systemReservedMemory)
   472  
   473  			if !reflect.DeepEqual(res, testCase.expectedReserved) {
   474  				t.Errorf("Memory Manager getReservedMemory() error, expected reserved %+v, but got: %+v",
   475  					testCase.expectedReserved, res)
   476  			}
   477  			if !reflect.DeepEqual(err, testCase.expectedError) {
   478  				t.Errorf("Memory Manager getReservedMemory() error, expected error %v, but got: %v",
   479  					testCase.expectedError, err)
   480  			}
   481  
   482  		})
   483  	}
   484  }
   485  
   486  func TestRemoveStaleState(t *testing.T) {
   487  	machineInfo := returnMachineInfo()
   488  	testCases := []testMemoryManager{
   489  		{
   490  			description: "Should fail - policy returns an error",
   491  			policyName:  policyTypeMock,
   492  			machineInfo: machineInfo,
   493  			reserved: systemReservedMemory{
   494  				0: map[v1.ResourceName]uint64{
   495  					v1.ResourceMemory: 1 * gb,
   496  				},
   497  				1: map[v1.ResourceName]uint64{
   498  					v1.ResourceMemory: 1 * gb,
   499  				},
   500  			},
   501  			assignments: state.ContainerMemoryAssignments{
   502  				"fakePod1": map[string][]state.Block{
   503  					"fakeContainer1": {
   504  						{
   505  							NUMAAffinity: []int{0},
   506  							Type:         v1.ResourceMemory,
   507  							Size:         1 * gb,
   508  						},
   509  						{
   510  							NUMAAffinity: []int{0},
   511  							Type:         hugepages1Gi,
   512  							Size:         1 * gb,
   513  						},
   514  					},
   515  					"fakeContainer2": {
   516  						{
   517  							NUMAAffinity: []int{0},
   518  							Type:         v1.ResourceMemory,
   519  							Size:         1 * gb,
   520  						},
   521  						{
   522  							NUMAAffinity: []int{0},
   523  							Type:         hugepages1Gi,
   524  							Size:         1 * gb,
   525  						},
   526  					},
   527  				},
   528  			},
   529  			expectedAssignments: state.ContainerMemoryAssignments{
   530  				"fakePod1": map[string][]state.Block{
   531  					"fakeContainer1": {
   532  						{
   533  							NUMAAffinity: []int{0},
   534  							Type:         v1.ResourceMemory,
   535  							Size:         1 * gb,
   536  						},
   537  						{
   538  							NUMAAffinity: []int{0},
   539  							Type:         hugepages1Gi,
   540  							Size:         1 * gb,
   541  						},
   542  					},
   543  					"fakeContainer2": {
   544  						{
   545  							NUMAAffinity: []int{0},
   546  							Type:         v1.ResourceMemory,
   547  							Size:         1 * gb,
   548  						},
   549  						{
   550  							NUMAAffinity: []int{0},
   551  							Type:         hugepages1Gi,
   552  							Size:         1 * gb,
   553  						},
   554  					},
   555  				},
   556  			},
   557  			machineState: state.NUMANodeMap{
   558  				0: &state.NUMANodeState{
   559  					Cells:               []int{0},
   560  					NumberOfAssignments: 4,
   561  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   562  						v1.ResourceMemory: {
   563  							Allocatable:    9 * gb,
   564  							Free:           7 * gb,
   565  							Reserved:       2 * gb,
   566  							SystemReserved: 1 * gb,
   567  							TotalMemSize:   10 * gb,
   568  						},
   569  						hugepages1Gi: {
   570  							Allocatable:    5 * gb,
   571  							Free:           3 * gb,
   572  							Reserved:       2 * gb,
   573  							SystemReserved: 0 * gb,
   574  							TotalMemSize:   5 * gb,
   575  						},
   576  					},
   577  				},
   578  				1: &state.NUMANodeState{
   579  					Cells:               []int{1},
   580  					NumberOfAssignments: 0,
   581  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   582  						v1.ResourceMemory: {
   583  							Allocatable:    9 * gb,
   584  							Free:           9 * gb,
   585  							Reserved:       0 * gb,
   586  							SystemReserved: 1 * gb,
   587  							TotalMemSize:   10 * gb,
   588  						},
   589  						hugepages1Gi: {
   590  							Allocatable:    5 * gb,
   591  							Free:           5 * gb,
   592  							Reserved:       0,
   593  							SystemReserved: 0,
   594  							TotalMemSize:   5 * gb,
   595  						},
   596  					},
   597  				},
   598  			},
   599  			expectedMachineState: state.NUMANodeMap{
   600  				0: &state.NUMANodeState{
   601  					Cells:               []int{0},
   602  					NumberOfAssignments: 4,
   603  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   604  						v1.ResourceMemory: {
   605  							Allocatable:    9 * gb,
   606  							Free:           7 * gb,
   607  							Reserved:       2 * gb,
   608  							SystemReserved: 1 * gb,
   609  							TotalMemSize:   10 * gb,
   610  						},
   611  						hugepages1Gi: {
   612  							Allocatable:    5 * gb,
   613  							Free:           3 * gb,
   614  							Reserved:       2 * gb,
   615  							SystemReserved: 0 * gb,
   616  							TotalMemSize:   5 * gb,
   617  						},
   618  					},
   619  				},
   620  				1: &state.NUMANodeState{
   621  					Cells:               []int{1},
   622  					NumberOfAssignments: 0,
   623  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   624  						v1.ResourceMemory: {
   625  							Allocatable:    9 * gb,
   626  							Free:           9 * gb,
   627  							Reserved:       0 * gb,
   628  							SystemReserved: 1 * gb,
   629  							TotalMemSize:   10 * gb,
   630  						},
   631  						hugepages1Gi: {
   632  							Allocatable:    5 * gb,
   633  							Free:           5 * gb,
   634  							Reserved:       0,
   635  							SystemReserved: 0,
   636  							TotalMemSize:   5 * gb,
   637  						},
   638  					},
   639  				},
   640  			},
   641  		},
   642  		{
   643  			description: "Stale state successfully removed, without multi NUMA assignments",
   644  			policyName:  policyTypeStatic,
   645  			machineInfo: machineInfo,
   646  			reserved: systemReservedMemory{
   647  				0: map[v1.ResourceName]uint64{
   648  					v1.ResourceMemory: 1 * gb,
   649  				},
   650  				1: map[v1.ResourceName]uint64{
   651  					v1.ResourceMemory: 1 * gb,
   652  				},
   653  			},
   654  			assignments: state.ContainerMemoryAssignments{
   655  				"fakePod1": map[string][]state.Block{
   656  					"fakeContainer1": {
   657  						{
   658  							NUMAAffinity: []int{0},
   659  							Type:         v1.ResourceMemory,
   660  							Size:         1 * gb,
   661  						},
   662  						{
   663  							NUMAAffinity: []int{0},
   664  							Type:         hugepages1Gi,
   665  							Size:         1 * gb,
   666  						},
   667  					},
   668  					"fakeContainer2": {
   669  						{
   670  							NUMAAffinity: []int{0},
   671  							Type:         v1.ResourceMemory,
   672  							Size:         1 * gb,
   673  						},
   674  						{
   675  							NUMAAffinity: []int{0},
   676  							Type:         hugepages1Gi,
   677  							Size:         1 * gb,
   678  						},
   679  					},
   680  				},
   681  			},
   682  			expectedAssignments: state.ContainerMemoryAssignments{},
   683  			machineState: state.NUMANodeMap{
   684  				0: &state.NUMANodeState{
   685  					Cells:               []int{0},
   686  					NumberOfAssignments: 4,
   687  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   688  						v1.ResourceMemory: {
   689  							Allocatable:    9 * gb,
   690  							Free:           7 * gb,
   691  							Reserved:       2 * gb,
   692  							SystemReserved: 1 * gb,
   693  							TotalMemSize:   10 * gb,
   694  						},
   695  						hugepages1Gi: {
   696  							Allocatable:    5 * gb,
   697  							Free:           3 * gb,
   698  							Reserved:       2 * gb,
   699  							SystemReserved: 0 * gb,
   700  							TotalMemSize:   5 * gb,
   701  						},
   702  					},
   703  				},
   704  				1: &state.NUMANodeState{
   705  					Cells:               []int{1},
   706  					NumberOfAssignments: 0,
   707  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   708  						v1.ResourceMemory: {
   709  							Allocatable:    9 * gb,
   710  							Free:           9 * gb,
   711  							Reserved:       0 * gb,
   712  							SystemReserved: 1 * gb,
   713  							TotalMemSize:   10 * gb,
   714  						},
   715  						hugepages1Gi: {
   716  							Allocatable:    5 * gb,
   717  							Free:           5 * gb,
   718  							Reserved:       0,
   719  							SystemReserved: 0,
   720  							TotalMemSize:   5 * gb,
   721  						},
   722  					},
   723  				},
   724  			},
   725  			expectedMachineState: state.NUMANodeMap{
   726  				0: &state.NUMANodeState{
   727  					Cells:               []int{0},
   728  					NumberOfAssignments: 0,
   729  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   730  						v1.ResourceMemory: {
   731  							Allocatable:    9 * gb,
   732  							Free:           9 * gb,
   733  							Reserved:       0 * gb,
   734  							SystemReserved: 1 * gb,
   735  							TotalMemSize:   10 * gb,
   736  						},
   737  						hugepages1Gi: {
   738  							Allocatable:    5 * gb,
   739  							Free:           5 * gb,
   740  							Reserved:       0,
   741  							SystemReserved: 0,
   742  							TotalMemSize:   5 * gb,
   743  						},
   744  					},
   745  				},
   746  				1: &state.NUMANodeState{
   747  					Cells:               []int{1},
   748  					NumberOfAssignments: 0,
   749  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   750  						v1.ResourceMemory: {
   751  							Allocatable:    9 * gb,
   752  							Free:           9 * gb,
   753  							Reserved:       0 * gb,
   754  							SystemReserved: 1 * gb,
   755  							TotalMemSize:   10 * gb,
   756  						},
   757  						hugepages1Gi: {
   758  							Allocatable:    5 * gb,
   759  							Free:           5 * gb,
   760  							Reserved:       0,
   761  							SystemReserved: 0,
   762  							TotalMemSize:   5 * gb,
   763  						},
   764  					},
   765  				},
   766  			},
   767  		},
   768  		{
   769  			description: "Stale state successfully removed, with multi NUMA assignments",
   770  			policyName:  policyTypeStatic,
   771  			machineInfo: machineInfo,
   772  			reserved: systemReservedMemory{
   773  				0: map[v1.ResourceName]uint64{
   774  					v1.ResourceMemory: 1 * gb,
   775  				},
   776  				1: map[v1.ResourceName]uint64{
   777  					v1.ResourceMemory: 1 * gb,
   778  				},
   779  			},
   780  			assignments: state.ContainerMemoryAssignments{
   781  				"fakePod1": map[string][]state.Block{
   782  					"fakeContainer1": {
   783  						{
   784  							NUMAAffinity: []int{0, 1},
   785  							Type:         v1.ResourceMemory,
   786  							Size:         12 * gb,
   787  						},
   788  						{
   789  							NUMAAffinity: []int{0, 1},
   790  							Type:         hugepages1Gi,
   791  							Size:         1 * gb,
   792  						},
   793  					},
   794  					"fakeContainer2": {
   795  						{
   796  							NUMAAffinity: []int{0, 1},
   797  							Type:         v1.ResourceMemory,
   798  							Size:         1 * gb,
   799  						},
   800  						{
   801  							NUMAAffinity: []int{0, 1},
   802  							Type:         hugepages1Gi,
   803  							Size:         1 * gb,
   804  						},
   805  					},
   806  				},
   807  			},
   808  			expectedAssignments: state.ContainerMemoryAssignments{},
   809  			machineState: state.NUMANodeMap{
   810  				0: &state.NUMANodeState{
   811  					Cells:               []int{0, 1},
   812  					NumberOfAssignments: 4,
   813  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   814  						v1.ResourceMemory: {
   815  							Allocatable:    9 * gb,
   816  							Free:           0 * gb,
   817  							Reserved:       9 * gb,
   818  							SystemReserved: 1 * gb,
   819  							TotalMemSize:   10 * gb,
   820  						},
   821  						hugepages1Gi: {
   822  							Allocatable:    5 * gb,
   823  							Free:           4 * gb,
   824  							Reserved:       1 * gb,
   825  							SystemReserved: 0 * gb,
   826  							TotalMemSize:   5 * gb,
   827  						},
   828  					},
   829  				},
   830  				1: &state.NUMANodeState{
   831  					Cells:               []int{0, 1},
   832  					NumberOfAssignments: 4,
   833  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   834  						v1.ResourceMemory: {
   835  							Allocatable:    9 * gb,
   836  							Free:           5 * gb,
   837  							Reserved:       4 * gb,
   838  							SystemReserved: 1 * gb,
   839  							TotalMemSize:   10 * gb,
   840  						},
   841  						hugepages1Gi: {
   842  							Allocatable:    5 * gb,
   843  							Free:           4 * gb,
   844  							Reserved:       1 * gb,
   845  							SystemReserved: 0,
   846  							TotalMemSize:   5 * gb,
   847  						},
   848  					},
   849  				},
   850  			},
   851  			expectedMachineState: state.NUMANodeMap{
   852  				0: &state.NUMANodeState{
   853  					Cells:               []int{0},
   854  					NumberOfAssignments: 0,
   855  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   856  						v1.ResourceMemory: {
   857  							Allocatable:    9 * gb,
   858  							Free:           9 * gb,
   859  							Reserved:       0 * gb,
   860  							SystemReserved: 1 * gb,
   861  							TotalMemSize:   10 * gb,
   862  						},
   863  						hugepages1Gi: {
   864  							Allocatable:    5 * gb,
   865  							Free:           5 * gb,
   866  							Reserved:       0,
   867  							SystemReserved: 0,
   868  							TotalMemSize:   5 * gb,
   869  						},
   870  					},
   871  				},
   872  				1: &state.NUMANodeState{
   873  					Cells:               []int{1},
   874  					NumberOfAssignments: 0,
   875  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   876  						v1.ResourceMemory: {
   877  							Allocatable:    9 * gb,
   878  							Free:           9 * gb,
   879  							Reserved:       0 * gb,
   880  							SystemReserved: 1 * gb,
   881  							TotalMemSize:   10 * gb,
   882  						},
   883  						hugepages1Gi: {
   884  							Allocatable:    5 * gb,
   885  							Free:           5 * gb,
   886  							Reserved:       0,
   887  							SystemReserved: 0,
   888  							TotalMemSize:   5 * gb,
   889  						},
   890  					},
   891  				},
   892  			},
   893  		},
   894  	}
   895  	for _, testCase := range testCases {
   896  		t.Run(testCase.description, func(t *testing.T) {
   897  			mgr := &manager{
   898  				policy:       returnPolicyByName(testCase),
   899  				state:        state.NewMemoryState(),
   900  				containerMap: containermap.NewContainerMap(),
   901  				containerRuntime: mockRuntimeService{
   902  					err: nil,
   903  				},
   904  				activePods:        func() []*v1.Pod { return nil },
   905  				podStatusProvider: mockPodStatusProvider{},
   906  			}
   907  			mgr.sourcesReady = &sourcesReadyStub{}
   908  			mgr.state.SetMemoryAssignments(testCase.assignments)
   909  			mgr.state.SetMachineState(testCase.machineState)
   910  
   911  			mgr.removeStaleState()
   912  
   913  			if !areContainerMemoryAssignmentsEqual(t, mgr.state.GetMemoryAssignments(), testCase.expectedAssignments) {
   914  				t.Errorf("Memory Manager removeStaleState() error, expected assignments %v, but got: %v",
   915  					testCase.expectedAssignments, mgr.state.GetMemoryAssignments())
   916  			}
   917  			if !areMachineStatesEqual(mgr.state.GetMachineState(), testCase.expectedMachineState) {
   918  				t.Fatalf("The actual machine state: %v is different from the expected one: %v", mgr.state.GetMachineState(), testCase.expectedMachineState)
   919  			}
   920  		})
   921  
   922  	}
   923  }
   924  
   925  func TestAddContainer(t *testing.T) {
   926  	machineInfo := returnMachineInfo()
   927  	reserved := systemReservedMemory{
   928  		0: map[v1.ResourceName]uint64{
   929  			v1.ResourceMemory: 1 * gb,
   930  		},
   931  		1: map[v1.ResourceName]uint64{
   932  			v1.ResourceMemory: 1 * gb,
   933  		},
   934  	}
   935  	pod := getPod("fakePod1", "fakeContainer1", requirementsGuaranteed)
   936  	testCases := []testMemoryManager{
   937  		{
   938  			description: "Correct allocation and adding container on NUMA 0",
   939  			policyName:  policyTypeStatic,
   940  			machineInfo: machineInfo,
   941  			reserved:    reserved,
   942  			machineState: state.NUMANodeMap{
   943  				0: &state.NUMANodeState{
   944  					Cells:               []int{0},
   945  					NumberOfAssignments: 0,
   946  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   947  						v1.ResourceMemory: {
   948  							Allocatable:    9 * gb,
   949  							Free:           9 * gb,
   950  							Reserved:       0 * gb,
   951  							SystemReserved: 1 * gb,
   952  							TotalMemSize:   10 * gb,
   953  						},
   954  						hugepages1Gi: {
   955  							Allocatable:    5 * gb,
   956  							Free:           5 * gb,
   957  							Reserved:       0,
   958  							SystemReserved: 0,
   959  							TotalMemSize:   5 * gb,
   960  						},
   961  					},
   962  				},
   963  				1: &state.NUMANodeState{
   964  					Cells:               []int{1},
   965  					NumberOfAssignments: 0,
   966  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   967  						v1.ResourceMemory: {
   968  							Allocatable:    9 * gb,
   969  							Free:           9 * gb,
   970  							Reserved:       0 * gb,
   971  							SystemReserved: 1 * gb,
   972  							TotalMemSize:   10 * gb,
   973  						},
   974  						hugepages1Gi: {
   975  							Allocatable:    5 * gb,
   976  							Free:           5 * gb,
   977  							Reserved:       0,
   978  							SystemReserved: 0,
   979  							TotalMemSize:   5 * gb,
   980  						},
   981  					},
   982  				},
   983  			},
   984  			expectedMachineState: state.NUMANodeMap{
   985  				0: &state.NUMANodeState{
   986  					Cells:               []int{0},
   987  					NumberOfAssignments: 2,
   988  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
   989  						v1.ResourceMemory: {
   990  							Allocatable:    9 * gb,
   991  							Free:           8 * gb,
   992  							Reserved:       1 * gb,
   993  							SystemReserved: 1 * gb,
   994  							TotalMemSize:   10 * gb,
   995  						},
   996  						hugepages1Gi: {
   997  							Allocatable:    5 * gb,
   998  							Free:           4 * gb,
   999  							Reserved:       1 * gb,
  1000  							SystemReserved: 0,
  1001  							TotalMemSize:   5 * gb,
  1002  						},
  1003  					},
  1004  				},
  1005  				1: &state.NUMANodeState{
  1006  					Cells:               []int{1},
  1007  					NumberOfAssignments: 0,
  1008  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1009  						v1.ResourceMemory: {
  1010  							Allocatable:    9 * gb,
  1011  							Free:           9 * gb,
  1012  							Reserved:       0 * gb,
  1013  							SystemReserved: 1 * gb,
  1014  							TotalMemSize:   10 * gb,
  1015  						},
  1016  						hugepages1Gi: {
  1017  							Allocatable:    5 * gb,
  1018  							Free:           5 * gb,
  1019  							Reserved:       0,
  1020  							SystemReserved: 0,
  1021  							TotalMemSize:   5 * gb,
  1022  						},
  1023  					},
  1024  				},
  1025  			},
  1026  			expectedAllocateError:     nil,
  1027  			expectedAddContainerError: nil,
  1028  			updateError:               nil,
  1029  			podAllocate:               pod,
  1030  			assignments:               state.ContainerMemoryAssignments{},
  1031  			activePods:                nil,
  1032  		},
  1033  		{
  1034  			description:               "Shouldn't return any error when policy is set as None",
  1035  			updateError:               nil,
  1036  			policyName:                policyTypeNone,
  1037  			machineInfo:               machineInfo,
  1038  			reserved:                  reserved,
  1039  			machineState:              state.NUMANodeMap{},
  1040  			expectedMachineState:      state.NUMANodeMap{},
  1041  			expectedAllocateError:     nil,
  1042  			expectedAddContainerError: nil,
  1043  			podAllocate:               pod,
  1044  			assignments:               state.ContainerMemoryAssignments{},
  1045  			activePods:                nil,
  1046  		},
  1047  		{
  1048  			description: "Allocation should fail if policy returns an error",
  1049  			updateError: nil,
  1050  			policyName:  policyTypeMock,
  1051  			machineInfo: machineInfo,
  1052  			reserved:    reserved,
  1053  			machineState: state.NUMANodeMap{
  1054  				0: &state.NUMANodeState{
  1055  					Cells:               []int{0},
  1056  					NumberOfAssignments: 0,
  1057  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1058  						v1.ResourceMemory: {
  1059  							Allocatable:    9 * gb,
  1060  							Free:           9 * gb,
  1061  							Reserved:       0 * gb,
  1062  							SystemReserved: 1 * gb,
  1063  							TotalMemSize:   10 * gb,
  1064  						},
  1065  						hugepages1Gi: {
  1066  							Allocatable:    5 * gb,
  1067  							Free:           5 * gb,
  1068  							Reserved:       0,
  1069  							SystemReserved: 0,
  1070  							TotalMemSize:   5 * gb,
  1071  						},
  1072  					},
  1073  				},
  1074  				1: &state.NUMANodeState{
  1075  					Cells:               []int{1},
  1076  					NumberOfAssignments: 0,
  1077  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1078  						v1.ResourceMemory: {
  1079  							Allocatable:    9 * gb,
  1080  							Free:           9 * gb,
  1081  							Reserved:       0 * gb,
  1082  							SystemReserved: 1 * gb,
  1083  							TotalMemSize:   10 * gb,
  1084  						},
  1085  						hugepages1Gi: {
  1086  							Allocatable:    5 * gb,
  1087  							Free:           5 * gb,
  1088  							Reserved:       0,
  1089  							SystemReserved: 0,
  1090  							TotalMemSize:   5 * gb,
  1091  						},
  1092  					},
  1093  				},
  1094  			},
  1095  			expectedMachineState: state.NUMANodeMap{
  1096  				0: &state.NUMANodeState{
  1097  					Cells:               []int{0},
  1098  					NumberOfAssignments: 0,
  1099  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1100  						v1.ResourceMemory: {
  1101  							Allocatable:    9 * gb,
  1102  							Free:           9 * gb,
  1103  							Reserved:       0 * gb,
  1104  							SystemReserved: 1 * gb,
  1105  							TotalMemSize:   10 * gb,
  1106  						},
  1107  						hugepages1Gi: {
  1108  							Allocatable:    5 * gb,
  1109  							Free:           5 * gb,
  1110  							Reserved:       0,
  1111  							SystemReserved: 0,
  1112  							TotalMemSize:   5 * gb,
  1113  						},
  1114  					},
  1115  				},
  1116  				1: &state.NUMANodeState{
  1117  					Cells:               []int{1},
  1118  					NumberOfAssignments: 0,
  1119  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1120  						v1.ResourceMemory: {
  1121  							Allocatable:    9 * gb,
  1122  							Free:           9 * gb,
  1123  							Reserved:       0 * gb,
  1124  							SystemReserved: 1 * gb,
  1125  							TotalMemSize:   10 * gb,
  1126  						},
  1127  						hugepages1Gi: {
  1128  							Allocatable:    5 * gb,
  1129  							Free:           5 * gb,
  1130  							Reserved:       0,
  1131  							SystemReserved: 0,
  1132  							TotalMemSize:   5 * gb,
  1133  						},
  1134  					},
  1135  				},
  1136  			},
  1137  			expectedAllocateError:     fmt.Errorf("fake reg error"),
  1138  			expectedAddContainerError: nil,
  1139  			podAllocate:               pod,
  1140  			assignments:               state.ContainerMemoryAssignments{},
  1141  			activePods:                nil,
  1142  		},
  1143  		{
  1144  			description: "Correct allocation of container requiring amount of memory higher than capacity of one NUMA node",
  1145  			policyName:  policyTypeStatic,
  1146  			machineInfo: machineInfo,
  1147  			reserved:    reserved,
  1148  			machineState: state.NUMANodeMap{
  1149  				0: &state.NUMANodeState{
  1150  					Cells:               []int{0},
  1151  					NumberOfAssignments: 0,
  1152  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1153  						v1.ResourceMemory: {
  1154  							Allocatable:    9 * gb,
  1155  							Free:           9 * gb,
  1156  							Reserved:       0 * gb,
  1157  							SystemReserved: 1 * gb,
  1158  							TotalMemSize:   10 * gb,
  1159  						},
  1160  						hugepages1Gi: {
  1161  							Allocatable:    5 * gb,
  1162  							Free:           5 * gb,
  1163  							Reserved:       0,
  1164  							SystemReserved: 0,
  1165  							TotalMemSize:   5 * gb,
  1166  						},
  1167  					},
  1168  				},
  1169  				1: &state.NUMANodeState{
  1170  					Cells:               []int{1},
  1171  					NumberOfAssignments: 0,
  1172  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1173  						v1.ResourceMemory: {
  1174  							Allocatable:    9 * gb,
  1175  							Free:           9 * gb,
  1176  							Reserved:       0 * gb,
  1177  							SystemReserved: 1 * gb,
  1178  							TotalMemSize:   10 * gb,
  1179  						},
  1180  						hugepages1Gi: {
  1181  							Allocatable:    5 * gb,
  1182  							Free:           5 * gb,
  1183  							Reserved:       0,
  1184  							SystemReserved: 0,
  1185  							TotalMemSize:   5 * gb,
  1186  						},
  1187  					},
  1188  				},
  1189  			},
  1190  			expectedMachineState: state.NUMANodeMap{
  1191  				0: &state.NUMANodeState{
  1192  					Cells:               []int{0, 1},
  1193  					NumberOfAssignments: 2,
  1194  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1195  						v1.ResourceMemory: {
  1196  							Allocatable:    9 * gb,
  1197  							Free:           0 * gb,
  1198  							Reserved:       9 * gb,
  1199  							SystemReserved: 1 * gb,
  1200  							TotalMemSize:   10 * gb,
  1201  						},
  1202  						hugepages1Gi: {
  1203  							Allocatable:    5 * gb,
  1204  							Free:           1 * gb,
  1205  							Reserved:       4 * gb,
  1206  							SystemReserved: 0,
  1207  							TotalMemSize:   5 * gb,
  1208  						},
  1209  					},
  1210  				},
  1211  				1: &state.NUMANodeState{
  1212  					Cells:               []int{0, 1},
  1213  					NumberOfAssignments: 2,
  1214  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1215  						v1.ResourceMemory: {
  1216  							Allocatable:    9 * gb,
  1217  							Free:           6 * gb,
  1218  							Reserved:       3 * gb,
  1219  							SystemReserved: 1 * gb,
  1220  							TotalMemSize:   10 * gb,
  1221  						},
  1222  						hugepages1Gi: {
  1223  							Allocatable:    5 * gb,
  1224  							Free:           5 * gb,
  1225  							Reserved:       0,
  1226  							SystemReserved: 0,
  1227  							TotalMemSize:   5 * gb,
  1228  						},
  1229  					},
  1230  				},
  1231  			},
  1232  			expectedAllocateError:     nil,
  1233  			expectedAddContainerError: nil,
  1234  			podAllocate: getPod("fakePod1", "fakeContainer1", &v1.ResourceRequirements{
  1235  				Limits: v1.ResourceList{
  1236  					v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1237  					v1.ResourceMemory: resource.MustParse("12Gi"),
  1238  					hugepages1Gi:      resource.MustParse("4Gi"),
  1239  				},
  1240  				Requests: v1.ResourceList{
  1241  					v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1242  					v1.ResourceMemory: resource.MustParse("12Gi"),
  1243  					hugepages1Gi:      resource.MustParse("4Gi"),
  1244  				},
  1245  			}),
  1246  			assignments: state.ContainerMemoryAssignments{},
  1247  			activePods:  nil,
  1248  		},
  1249  		{
  1250  			description: "Should fail if try to allocate container requiring amount of memory higher than capacity of one NUMA node but a small pod is already allocated",
  1251  			policyName:  policyTypeStatic,
  1252  			machineInfo: machineInfo,
  1253  			firstPod:    pod,
  1254  			reserved:    reserved,
  1255  			machineState: state.NUMANodeMap{
  1256  				0: &state.NUMANodeState{
  1257  					Cells:               []int{0},
  1258  					NumberOfAssignments: 2,
  1259  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1260  						v1.ResourceMemory: {
  1261  							Allocatable:    9 * gb,
  1262  							Free:           8 * gb,
  1263  							Reserved:       1 * gb,
  1264  							SystemReserved: 1 * gb,
  1265  							TotalMemSize:   10 * gb,
  1266  						},
  1267  						hugepages1Gi: {
  1268  							Allocatable:    5 * gb,
  1269  							Free:           4 * gb,
  1270  							Reserved:       1 * gb,
  1271  							SystemReserved: 0,
  1272  							TotalMemSize:   5 * gb,
  1273  						},
  1274  					},
  1275  				},
  1276  				1: &state.NUMANodeState{
  1277  					Cells:               []int{1},
  1278  					NumberOfAssignments: 0,
  1279  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1280  						v1.ResourceMemory: {
  1281  							Allocatable:    9 * gb,
  1282  							Free:           9 * gb,
  1283  							Reserved:       0 * gb,
  1284  							SystemReserved: 1 * gb,
  1285  							TotalMemSize:   10 * gb,
  1286  						},
  1287  						hugepages1Gi: {
  1288  							Allocatable:    5 * gb,
  1289  							Free:           5 * gb,
  1290  							Reserved:       0,
  1291  							SystemReserved: 0,
  1292  							TotalMemSize:   5 * gb,
  1293  						},
  1294  					},
  1295  				},
  1296  			},
  1297  			assignments: state.ContainerMemoryAssignments{
  1298  				"fakePod1": map[string][]state.Block{
  1299  					"fakeContainer1": {
  1300  						{
  1301  							NUMAAffinity: []int{0},
  1302  							Type:         v1.ResourceMemory,
  1303  							Size:         1 * gb,
  1304  						},
  1305  						{
  1306  							NUMAAffinity: []int{0},
  1307  							Type:         hugepages1Gi,
  1308  							Size:         1 * gb,
  1309  						},
  1310  					},
  1311  				},
  1312  			},
  1313  			expectedMachineState: state.NUMANodeMap{
  1314  				0: &state.NUMANodeState{
  1315  					Cells:               []int{0},
  1316  					NumberOfAssignments: 2,
  1317  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1318  						v1.ResourceMemory: {
  1319  							Allocatable:    9 * gb,
  1320  							Free:           8 * gb,
  1321  							Reserved:       1 * gb,
  1322  							SystemReserved: 1 * gb,
  1323  							TotalMemSize:   10 * gb,
  1324  						},
  1325  						hugepages1Gi: {
  1326  							Allocatable:    5 * gb,
  1327  							Free:           4 * gb,
  1328  							Reserved:       1 * gb,
  1329  							SystemReserved: 0,
  1330  							TotalMemSize:   5 * gb,
  1331  						},
  1332  					},
  1333  				},
  1334  				1: &state.NUMANodeState{
  1335  					Cells:               []int{1},
  1336  					NumberOfAssignments: 0,
  1337  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1338  						v1.ResourceMemory: {
  1339  							Allocatable:    9 * gb,
  1340  							Free:           9 * gb,
  1341  							Reserved:       0 * gb,
  1342  							SystemReserved: 1 * gb,
  1343  							TotalMemSize:   10 * gb,
  1344  						},
  1345  						hugepages1Gi: {
  1346  							Allocatable:    5 * gb,
  1347  							Free:           5 * gb,
  1348  							Reserved:       0,
  1349  							SystemReserved: 0,
  1350  							TotalMemSize:   5 * gb,
  1351  						},
  1352  					},
  1353  				},
  1354  			},
  1355  			expectedAllocateError:     fmt.Errorf("[memorymanager] failed to get the default NUMA affinity, no NUMA nodes with enough memory is available"),
  1356  			expectedAddContainerError: nil,
  1357  			podAllocate: getPod("fakePod2", "fakeContainer2", &v1.ResourceRequirements{
  1358  				Limits: v1.ResourceList{
  1359  					v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1360  					v1.ResourceMemory: resource.MustParse("12Gi"),
  1361  					hugepages1Gi:      resource.MustParse("4Gi"),
  1362  				},
  1363  				Requests: v1.ResourceList{
  1364  					v1.ResourceCPU:    resource.MustParse("1000Mi"),
  1365  					v1.ResourceMemory: resource.MustParse("12Gi"),
  1366  					hugepages1Gi:      resource.MustParse("4Gi"),
  1367  				},
  1368  			}),
  1369  			activePods: []*v1.Pod{
  1370  				{
  1371  					ObjectMeta: metav1.ObjectMeta{
  1372  						UID: types.UID("fakePod1"),
  1373  					},
  1374  					Spec: v1.PodSpec{
  1375  						Containers: []v1.Container{
  1376  							{
  1377  								Name:      "fakeContainer1",
  1378  								Resources: *requirementsGuaranteed,
  1379  							},
  1380  						},
  1381  					},
  1382  				},
  1383  			},
  1384  		},
  1385  	}
  1386  
  1387  	for _, testCase := range testCases {
  1388  		t.Run(testCase.description, func(t *testing.T) {
  1389  			mgr := &manager{
  1390  				policy:       returnPolicyByName(testCase),
  1391  				state:        state.NewMemoryState(),
  1392  				containerMap: containermap.NewContainerMap(),
  1393  				containerRuntime: mockRuntimeService{
  1394  					err: testCase.updateError,
  1395  				},
  1396  				activePods:        func() []*v1.Pod { return testCase.activePods },
  1397  				podStatusProvider: mockPodStatusProvider{},
  1398  			}
  1399  			mgr.sourcesReady = &sourcesReadyStub{}
  1400  			mgr.state.SetMachineState(testCase.machineState)
  1401  			mgr.state.SetMemoryAssignments(testCase.assignments)
  1402  			if testCase.firstPod != nil {
  1403  				mgr.containerMap.Add(testCase.firstPod.Name, testCase.firstPod.Spec.Containers[0].Name, "fakeID0")
  1404  			}
  1405  			pod := testCase.podAllocate
  1406  			container := &pod.Spec.Containers[0]
  1407  			err := mgr.Allocate(pod, container)
  1408  			if !reflect.DeepEqual(err, testCase.expectedAllocateError) {
  1409  				t.Errorf("Memory Manager Allocate() error (%v), expected error: %v, but got: %v",
  1410  					testCase.description, testCase.expectedAllocateError, err)
  1411  			}
  1412  			mgr.AddContainer(pod, container, "fakeID")
  1413  			_, _, err = mgr.containerMap.GetContainerRef("fakeID")
  1414  			if !reflect.DeepEqual(err, testCase.expectedAddContainerError) {
  1415  				t.Errorf("Memory Manager AddContainer() error (%v), expected error: %v, but got: %v",
  1416  					testCase.description, testCase.expectedAddContainerError, err)
  1417  			}
  1418  
  1419  			if !areMachineStatesEqual(mgr.state.GetMachineState(), testCase.expectedMachineState) {
  1420  				t.Errorf("[test] %+v", mgr.state.GetMemoryAssignments())
  1421  				t.Fatalf("The actual machine state: %v is different from the expected one: %v", mgr.state.GetMachineState(), testCase.expectedMachineState)
  1422  			}
  1423  
  1424  		})
  1425  	}
  1426  }
  1427  
  1428  func TestRemoveContainer(t *testing.T) {
  1429  	machineInfo := returnMachineInfo()
  1430  	reserved := systemReservedMemory{
  1431  		0: map[v1.ResourceName]uint64{
  1432  			v1.ResourceMemory: 1 * gb,
  1433  		},
  1434  		1: map[v1.ResourceName]uint64{
  1435  			v1.ResourceMemory: 1 * gb,
  1436  		},
  1437  	}
  1438  	testCases := []testMemoryManager{
  1439  		{
  1440  			description:       "Correct removing of a container",
  1441  			removeContainerID: "fakeID2",
  1442  			policyName:        policyTypeStatic,
  1443  			machineInfo:       machineInfo,
  1444  			reserved:          reserved,
  1445  			assignments: state.ContainerMemoryAssignments{
  1446  				"fakePod1": map[string][]state.Block{
  1447  					"fakeContainer1": {
  1448  						{
  1449  							NUMAAffinity: []int{0},
  1450  							Type:         v1.ResourceMemory,
  1451  							Size:         1 * gb,
  1452  						},
  1453  						{
  1454  							NUMAAffinity: []int{0},
  1455  							Type:         hugepages1Gi,
  1456  							Size:         1 * gb,
  1457  						},
  1458  					},
  1459  					"fakeContainer2": {
  1460  						{
  1461  							NUMAAffinity: []int{0},
  1462  							Type:         v1.ResourceMemory,
  1463  							Size:         1 * gb,
  1464  						},
  1465  						{
  1466  							NUMAAffinity: []int{0},
  1467  							Type:         hugepages1Gi,
  1468  							Size:         1 * gb,
  1469  						},
  1470  					},
  1471  				},
  1472  			},
  1473  			expectedAssignments: state.ContainerMemoryAssignments{
  1474  				"fakePod1": map[string][]state.Block{
  1475  					"fakeContainer1": {
  1476  						{
  1477  							NUMAAffinity: []int{0},
  1478  							Type:         v1.ResourceMemory,
  1479  							Size:         1 * gb,
  1480  						},
  1481  						{
  1482  							NUMAAffinity: []int{0},
  1483  							Type:         hugepages1Gi,
  1484  							Size:         1 * gb,
  1485  						},
  1486  					},
  1487  				},
  1488  			},
  1489  			machineState: state.NUMANodeMap{
  1490  				0: &state.NUMANodeState{
  1491  					Cells:               []int{0},
  1492  					NumberOfAssignments: 4,
  1493  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1494  						v1.ResourceMemory: {
  1495  							Allocatable:    9 * gb,
  1496  							Free:           7 * gb,
  1497  							Reserved:       2 * gb,
  1498  							SystemReserved: 1 * gb,
  1499  							TotalMemSize:   10 * gb,
  1500  						},
  1501  						hugepages1Gi: {
  1502  							Allocatable:    5 * gb,
  1503  							Free:           3 * gb,
  1504  							Reserved:       2 * gb,
  1505  							SystemReserved: 0 * gb,
  1506  							TotalMemSize:   5 * gb,
  1507  						},
  1508  					},
  1509  				},
  1510  				1: &state.NUMANodeState{
  1511  					Cells:               []int{1},
  1512  					NumberOfAssignments: 0,
  1513  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1514  						v1.ResourceMemory: {
  1515  							Allocatable:    9 * gb,
  1516  							Free:           9 * gb,
  1517  							Reserved:       0 * gb,
  1518  							SystemReserved: 1 * gb,
  1519  							TotalMemSize:   10 * gb,
  1520  						},
  1521  						hugepages1Gi: {
  1522  							Allocatable:    5 * gb,
  1523  							Free:           5 * gb,
  1524  							Reserved:       0,
  1525  							SystemReserved: 0,
  1526  							TotalMemSize:   5 * gb,
  1527  						},
  1528  					},
  1529  				},
  1530  			},
  1531  			expectedMachineState: state.NUMANodeMap{
  1532  				0: &state.NUMANodeState{
  1533  					Cells:               []int{0},
  1534  					NumberOfAssignments: 2,
  1535  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1536  						v1.ResourceMemory: {
  1537  							Allocatable:    9 * gb,
  1538  							Free:           8 * gb,
  1539  							Reserved:       1 * gb,
  1540  							SystemReserved: 1 * gb,
  1541  							TotalMemSize:   10 * gb,
  1542  						},
  1543  						hugepages1Gi: {
  1544  							Allocatable:    5 * gb,
  1545  							Free:           4 * gb,
  1546  							Reserved:       1 * gb,
  1547  							SystemReserved: 0,
  1548  							TotalMemSize:   5 * gb,
  1549  						},
  1550  					},
  1551  				},
  1552  				1: &state.NUMANodeState{
  1553  					Cells:               []int{1},
  1554  					NumberOfAssignments: 0,
  1555  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1556  						v1.ResourceMemory: {
  1557  							Allocatable:    9 * gb,
  1558  							Free:           9 * gb,
  1559  							Reserved:       0 * gb,
  1560  							SystemReserved: 1 * gb,
  1561  							TotalMemSize:   10 * gb,
  1562  						},
  1563  						hugepages1Gi: {
  1564  							Allocatable:    5 * gb,
  1565  							Free:           5 * gb,
  1566  							Reserved:       0,
  1567  							SystemReserved: 0,
  1568  							TotalMemSize:   5 * gb,
  1569  						},
  1570  					},
  1571  				},
  1572  			},
  1573  			expectedError: nil,
  1574  		},
  1575  		{
  1576  			description:       "Correct removing of a multi NUMA container",
  1577  			removeContainerID: "fakeID2",
  1578  			policyName:        policyTypeStatic,
  1579  			machineInfo:       machineInfo,
  1580  			reserved:          reserved,
  1581  			assignments: state.ContainerMemoryAssignments{
  1582  				"fakePod1": map[string][]state.Block{
  1583  					"fakeContainer1": {
  1584  						{
  1585  							NUMAAffinity: []int{0, 1},
  1586  							Type:         v1.ResourceMemory,
  1587  							Size:         1 * gb,
  1588  						},
  1589  						{
  1590  							NUMAAffinity: []int{0, 1},
  1591  							Type:         hugepages1Gi,
  1592  							Size:         1 * gb,
  1593  						},
  1594  					},
  1595  					"fakeContainer2": {
  1596  						{
  1597  							NUMAAffinity: []int{0, 1},
  1598  							Type:         v1.ResourceMemory,
  1599  							Size:         12 * gb,
  1600  						},
  1601  						{
  1602  							NUMAAffinity: []int{0, 1},
  1603  							Type:         hugepages1Gi,
  1604  							Size:         1 * gb,
  1605  						},
  1606  					},
  1607  				},
  1608  			},
  1609  			expectedAssignments: state.ContainerMemoryAssignments{
  1610  				"fakePod1": map[string][]state.Block{
  1611  					"fakeContainer1": {
  1612  						{
  1613  							NUMAAffinity: []int{0, 1},
  1614  							Type:         v1.ResourceMemory,
  1615  							Size:         1 * gb,
  1616  						},
  1617  						{
  1618  							NUMAAffinity: []int{0, 1},
  1619  							Type:         hugepages1Gi,
  1620  							Size:         1 * gb,
  1621  						},
  1622  					},
  1623  				},
  1624  			},
  1625  			machineState: state.NUMANodeMap{
  1626  				0: &state.NUMANodeState{
  1627  					Cells:               []int{0, 1},
  1628  					NumberOfAssignments: 4,
  1629  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1630  						v1.ResourceMemory: {
  1631  							Allocatable:    9 * gb,
  1632  							Free:           0 * gb,
  1633  							Reserved:       9 * gb,
  1634  							SystemReserved: 1 * gb,
  1635  							TotalMemSize:   10 * gb,
  1636  						},
  1637  						hugepages1Gi: {
  1638  							Allocatable:    5 * gb,
  1639  							Free:           3 * gb,
  1640  							Reserved:       2 * gb,
  1641  							SystemReserved: 0 * gb,
  1642  							TotalMemSize:   5 * gb,
  1643  						},
  1644  					},
  1645  				},
  1646  				1: &state.NUMANodeState{
  1647  					Cells:               []int{0, 1},
  1648  					NumberOfAssignments: 4,
  1649  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1650  						v1.ResourceMemory: {
  1651  							Allocatable:    9 * gb,
  1652  							Free:           5 * gb,
  1653  							Reserved:       4 * gb,
  1654  							SystemReserved: 1 * gb,
  1655  							TotalMemSize:   10 * gb,
  1656  						},
  1657  						hugepages1Gi: {
  1658  							Allocatable:    5 * gb,
  1659  							Free:           5 * gb,
  1660  							Reserved:       0,
  1661  							SystemReserved: 0,
  1662  							TotalMemSize:   5 * gb,
  1663  						},
  1664  					},
  1665  				},
  1666  			},
  1667  			expectedMachineState: state.NUMANodeMap{
  1668  				0: &state.NUMANodeState{
  1669  					Cells:               []int{0, 1},
  1670  					NumberOfAssignments: 2,
  1671  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1672  						v1.ResourceMemory: {
  1673  							Allocatable:    9 * gb,
  1674  							Free:           9 * gb,
  1675  							Reserved:       0 * gb,
  1676  							SystemReserved: 1 * gb,
  1677  							TotalMemSize:   10 * gb,
  1678  						},
  1679  						hugepages1Gi: {
  1680  							Allocatable:    5 * gb,
  1681  							Free:           4 * gb,
  1682  							Reserved:       1 * gb,
  1683  							SystemReserved: 0,
  1684  							TotalMemSize:   5 * gb,
  1685  						},
  1686  					},
  1687  				},
  1688  				1: &state.NUMANodeState{
  1689  					Cells:               []int{0, 1},
  1690  					NumberOfAssignments: 2,
  1691  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1692  						v1.ResourceMemory: {
  1693  							Allocatable:    9 * gb,
  1694  							Free:           8 * gb,
  1695  							Reserved:       1 * gb,
  1696  							SystemReserved: 1 * gb,
  1697  							TotalMemSize:   10 * gb,
  1698  						},
  1699  						hugepages1Gi: {
  1700  							Allocatable:    5 * gb,
  1701  							Free:           5 * gb,
  1702  							Reserved:       0,
  1703  							SystemReserved: 0,
  1704  							TotalMemSize:   5 * gb,
  1705  						},
  1706  					},
  1707  				},
  1708  			},
  1709  			expectedError: nil,
  1710  		},
  1711  		{
  1712  			description:       "Should do nothing if container is not in containerMap",
  1713  			removeContainerID: "fakeID3",
  1714  			policyName:        policyTypeStatic,
  1715  			machineInfo:       machineInfo,
  1716  			reserved:          reserved,
  1717  			assignments: state.ContainerMemoryAssignments{
  1718  				"fakePod1": map[string][]state.Block{
  1719  					"fakeContainer1": {
  1720  						{
  1721  							NUMAAffinity: []int{0},
  1722  							Type:         v1.ResourceMemory,
  1723  							Size:         1 * gb,
  1724  						},
  1725  						{
  1726  							NUMAAffinity: []int{0},
  1727  							Type:         hugepages1Gi,
  1728  							Size:         1 * gb,
  1729  						},
  1730  					},
  1731  					"fakeContainer2": {
  1732  						{
  1733  							NUMAAffinity: []int{0},
  1734  							Type:         v1.ResourceMemory,
  1735  							Size:         1 * gb,
  1736  						},
  1737  						{
  1738  							NUMAAffinity: []int{0},
  1739  							Type:         hugepages1Gi,
  1740  							Size:         1 * gb,
  1741  						},
  1742  					},
  1743  				},
  1744  			},
  1745  			expectedAssignments: state.ContainerMemoryAssignments{
  1746  				"fakePod1": map[string][]state.Block{
  1747  					"fakeContainer1": {
  1748  						{
  1749  							NUMAAffinity: []int{0},
  1750  							Type:         v1.ResourceMemory,
  1751  							Size:         1 * gb,
  1752  						},
  1753  						{
  1754  							NUMAAffinity: []int{0},
  1755  							Type:         hugepages1Gi,
  1756  							Size:         1 * gb,
  1757  						},
  1758  					},
  1759  					"fakeContainer2": {
  1760  						{
  1761  							NUMAAffinity: []int{0},
  1762  							Type:         v1.ResourceMemory,
  1763  							Size:         1 * gb,
  1764  						},
  1765  						{
  1766  							NUMAAffinity: []int{0},
  1767  							Type:         hugepages1Gi,
  1768  							Size:         1 * gb,
  1769  						},
  1770  					},
  1771  				},
  1772  			},
  1773  			machineState: state.NUMANodeMap{
  1774  				0: &state.NUMANodeState{
  1775  					Cells:               []int{0},
  1776  					NumberOfAssignments: 4,
  1777  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1778  						v1.ResourceMemory: {
  1779  							Allocatable:    9 * gb,
  1780  							Free:           7 * gb,
  1781  							Reserved:       2 * gb,
  1782  							SystemReserved: 1 * gb,
  1783  							TotalMemSize:   10 * gb,
  1784  						},
  1785  						hugepages1Gi: {
  1786  							Allocatable:    5 * gb,
  1787  							Free:           3 * gb,
  1788  							Reserved:       2 * gb,
  1789  							SystemReserved: 0 * gb,
  1790  							TotalMemSize:   5 * gb,
  1791  						},
  1792  					},
  1793  				},
  1794  				1: &state.NUMANodeState{
  1795  					Cells:               []int{1},
  1796  					NumberOfAssignments: 0,
  1797  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1798  						v1.ResourceMemory: {
  1799  							Allocatable:    9 * gb,
  1800  							Free:           9 * gb,
  1801  							Reserved:       0 * gb,
  1802  							SystemReserved: 1 * gb,
  1803  							TotalMemSize:   10 * gb,
  1804  						},
  1805  						hugepages1Gi: {
  1806  							Allocatable:    5 * gb,
  1807  							Free:           5 * gb,
  1808  							Reserved:       0,
  1809  							SystemReserved: 0,
  1810  							TotalMemSize:   5 * gb,
  1811  						},
  1812  					},
  1813  				},
  1814  			},
  1815  			expectedMachineState: state.NUMANodeMap{
  1816  				0: &state.NUMANodeState{
  1817  					Cells:               []int{0},
  1818  					NumberOfAssignments: 4,
  1819  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1820  						v1.ResourceMemory: {
  1821  							Allocatable:    9 * gb,
  1822  							Free:           7 * gb,
  1823  							Reserved:       2 * gb,
  1824  							SystemReserved: 1 * gb,
  1825  							TotalMemSize:   10 * gb,
  1826  						},
  1827  						hugepages1Gi: {
  1828  							Allocatable:    5 * gb,
  1829  							Free:           3 * gb,
  1830  							Reserved:       2 * gb,
  1831  							SystemReserved: 0 * gb,
  1832  							TotalMemSize:   5 * gb,
  1833  						},
  1834  					},
  1835  				},
  1836  				1: &state.NUMANodeState{
  1837  					Cells:               []int{1},
  1838  					NumberOfAssignments: 0,
  1839  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  1840  						v1.ResourceMemory: {
  1841  							Allocatable:    9 * gb,
  1842  							Free:           9 * gb,
  1843  							Reserved:       0 * gb,
  1844  							SystemReserved: 1 * gb,
  1845  							TotalMemSize:   10 * gb,
  1846  						},
  1847  						hugepages1Gi: {
  1848  							Allocatable:    5 * gb,
  1849  							Free:           5 * gb,
  1850  							Reserved:       0,
  1851  							SystemReserved: 0,
  1852  							TotalMemSize:   5 * gb,
  1853  						},
  1854  					},
  1855  				},
  1856  			},
  1857  			expectedError: nil,
  1858  		},
  1859  	}
  1860  	for _, testCase := range testCases {
  1861  		t.Run(testCase.description, func(t *testing.T) {
  1862  			iniContainerMap := containermap.NewContainerMap()
  1863  			iniContainerMap.Add("fakePod1", "fakeContainer1", "fakeID1")
  1864  			iniContainerMap.Add("fakePod1", "fakeContainer2", "fakeID2")
  1865  			mgr := &manager{
  1866  				policy:       returnPolicyByName(testCase),
  1867  				state:        state.NewMemoryState(),
  1868  				containerMap: iniContainerMap,
  1869  				containerRuntime: mockRuntimeService{
  1870  					err: testCase.expectedError,
  1871  				},
  1872  				activePods:        func() []*v1.Pod { return nil },
  1873  				podStatusProvider: mockPodStatusProvider{},
  1874  			}
  1875  			mgr.sourcesReady = &sourcesReadyStub{}
  1876  			mgr.state.SetMemoryAssignments(testCase.assignments)
  1877  			mgr.state.SetMachineState(testCase.machineState)
  1878  
  1879  			err := mgr.RemoveContainer(testCase.removeContainerID)
  1880  			if !reflect.DeepEqual(err, testCase.expectedError) {
  1881  				t.Errorf("Memory Manager RemoveContainer() error (%v), expected error: %v, but got: %v",
  1882  					testCase.description, testCase.expectedError, err)
  1883  			}
  1884  
  1885  			if !areContainerMemoryAssignmentsEqual(t, mgr.state.GetMemoryAssignments(), testCase.expectedAssignments) {
  1886  				t.Fatalf("Memory Manager RemoveContainer() inconsistent assignment, expected: %+v, but got: %+v, start %+v",
  1887  					testCase.expectedAssignments, mgr.state.GetMemoryAssignments(), testCase.expectedAssignments)
  1888  			}
  1889  
  1890  			if !areMachineStatesEqual(mgr.state.GetMachineState(), testCase.expectedMachineState) {
  1891  				t.Errorf("[test] %+v", mgr.state.GetMemoryAssignments())
  1892  				t.Errorf("[test] %+v, %+v", mgr.state.GetMachineState()[0].MemoryMap["memory"], mgr.state.GetMachineState()[1].MemoryMap["memory"])
  1893  				t.Fatalf("The actual machine state: %v is different from the expected one: %v", mgr.state.GetMachineState(), testCase.expectedMachineState)
  1894  			}
  1895  		})
  1896  	}
  1897  }
  1898  
  1899  func TestNewManager(t *testing.T) {
  1900  	machineInfo := returnMachineInfo()
  1901  	expectedReserved := systemReservedMemory{
  1902  		0: map[v1.ResourceName]uint64{
  1903  			v1.ResourceMemory: 1 * gb,
  1904  		},
  1905  		1: map[v1.ResourceName]uint64{
  1906  			v1.ResourceMemory: 1 * gb,
  1907  		},
  1908  	}
  1909  	testCases := []testMemoryManager{
  1910  		{
  1911  			description:                "Successful creation of Memory Manager instance",
  1912  			policyName:                 policyTypeStatic,
  1913  			machineInfo:                machineInfo,
  1914  			nodeAllocatableReservation: v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(2*gb, resource.BinarySI)},
  1915  			systemReservedMemory: []kubeletconfig.MemoryReservation{
  1916  				{
  1917  					NumaNode: 0,
  1918  					Limits:   v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(gb, resource.BinarySI)},
  1919  				},
  1920  				{
  1921  					NumaNode: 1,
  1922  					Limits:   v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(gb, resource.BinarySI)},
  1923  				},
  1924  			},
  1925  			affinity:         topologymanager.NewFakeManager(),
  1926  			expectedError:    nil,
  1927  			expectedReserved: expectedReserved,
  1928  		},
  1929  		{
  1930  			description:                "Should return an error when systemReservedMemory (configured with kubelet flag) does not comply with Node Allocatable feature values",
  1931  			policyName:                 policyTypeStatic,
  1932  			machineInfo:                machineInfo,
  1933  			nodeAllocatableReservation: v1.ResourceList{v1.ResourceMemory: *resource.NewQuantity(2*gb, resource.BinarySI)},
  1934  			systemReservedMemory: []kubeletconfig.MemoryReservation{
  1935  				{
  1936  					NumaNode: 0,
  1937  					Limits: v1.ResourceList{
  1938  						v1.ResourceMemory: *resource.NewQuantity(gb, resource.BinarySI),
  1939  					},
  1940  				},
  1941  				{
  1942  					NumaNode: 1,
  1943  					Limits: v1.ResourceList{
  1944  						v1.ResourceMemory: *resource.NewQuantity(2*gb, resource.BinarySI),
  1945  					},
  1946  				},
  1947  			},
  1948  			affinity:         topologymanager.NewFakeManager(),
  1949  			expectedError:    fmt.Errorf("the total amount \"3Gi\" of type %q is not equal to the value \"2Gi\" determined by Node Allocatable feature", v1.ResourceMemory),
  1950  			expectedReserved: expectedReserved,
  1951  		},
  1952  		{
  1953  			description:                "Should return an error when memory reserved for system is empty (systemReservedMemory)",
  1954  			policyName:                 policyTypeStatic,
  1955  			machineInfo:                machineInfo,
  1956  			nodeAllocatableReservation: v1.ResourceList{},
  1957  			systemReservedMemory:       []kubeletconfig.MemoryReservation{},
  1958  			affinity:                   topologymanager.NewFakeManager(),
  1959  			expectedError:              fmt.Errorf("[memorymanager] you should specify the system reserved memory"),
  1960  			expectedReserved:           expectedReserved,
  1961  		},
  1962  		{
  1963  			description:                "Should return an error when policy name is not correct",
  1964  			policyName:                 "fake",
  1965  			machineInfo:                machineInfo,
  1966  			nodeAllocatableReservation: v1.ResourceList{},
  1967  			systemReservedMemory:       []kubeletconfig.MemoryReservation{},
  1968  			affinity:                   topologymanager.NewFakeManager(),
  1969  			expectedError:              fmt.Errorf("unknown policy: \"fake\""),
  1970  			expectedReserved:           expectedReserved,
  1971  		},
  1972  		{
  1973  			description:                "Should create manager with \"none\" policy",
  1974  			policyName:                 policyTypeNone,
  1975  			machineInfo:                machineInfo,
  1976  			nodeAllocatableReservation: v1.ResourceList{},
  1977  			systemReservedMemory:       []kubeletconfig.MemoryReservation{},
  1978  			affinity:                   topologymanager.NewFakeManager(),
  1979  			expectedError:              nil,
  1980  			expectedReserved:           expectedReserved,
  1981  		},
  1982  	}
  1983  	for _, testCase := range testCases {
  1984  		t.Run(testCase.description, func(t *testing.T) {
  1985  			stateFileDirectory, err := os.MkdirTemp("", "memory_manager_tests")
  1986  			if err != nil {
  1987  				t.Errorf("Cannot create state file: %s", err.Error())
  1988  			}
  1989  			defer os.RemoveAll(stateFileDirectory)
  1990  
  1991  			mgr, err := NewManager(string(testCase.policyName), &testCase.machineInfo, testCase.nodeAllocatableReservation, testCase.systemReservedMemory, stateFileDirectory, testCase.affinity)
  1992  
  1993  			if !reflect.DeepEqual(err, testCase.expectedError) {
  1994  				t.Errorf("Could not create the Memory Manager. Expected error: '%v', but got: '%v'",
  1995  					testCase.expectedError, err)
  1996  			}
  1997  
  1998  			if testCase.expectedError == nil {
  1999  				if mgr != nil {
  2000  					rawMgr := mgr.(*manager)
  2001  					if !reflect.DeepEqual(rawMgr.policy.Name(), string(testCase.policyName)) {
  2002  						t.Errorf("Could not create the Memory Manager. Expected policy name: %v, but got: %v",
  2003  							testCase.policyName, rawMgr.policy.Name())
  2004  					}
  2005  					if testCase.policyName == policyTypeStatic {
  2006  						if !reflect.DeepEqual(rawMgr.policy.(*staticPolicy).systemReserved, testCase.expectedReserved) {
  2007  							t.Errorf("Could not create the Memory Manager. Expected system reserved: %+v, but got: %+v",
  2008  								testCase.expectedReserved, rawMgr.policy.(*staticPolicy).systemReserved)
  2009  						}
  2010  					}
  2011  				} else {
  2012  					t.Errorf("Could not create the Memory Manager - manager is nil, but it should not be.")
  2013  				}
  2014  
  2015  			}
  2016  		})
  2017  	}
  2018  }
  2019  
  2020  func TestGetTopologyHints(t *testing.T) {
  2021  	testCases := []testMemoryManager{
  2022  		{
  2023  			description: "Successful hint generation",
  2024  			policyName:  policyTypeStatic,
  2025  			machineInfo: returnMachineInfo(),
  2026  			reserved: systemReservedMemory{
  2027  				0: map[v1.ResourceName]uint64{
  2028  					v1.ResourceMemory: 1 * gb,
  2029  				},
  2030  				1: map[v1.ResourceName]uint64{
  2031  					v1.ResourceMemory: 1 * gb,
  2032  				},
  2033  			},
  2034  			assignments: state.ContainerMemoryAssignments{
  2035  				"fakePod1": map[string][]state.Block{
  2036  					"fakeContainer1": {
  2037  						{
  2038  							NUMAAffinity: []int{0},
  2039  							Type:         v1.ResourceMemory,
  2040  							Size:         1 * gb,
  2041  						},
  2042  						{
  2043  							NUMAAffinity: []int{0},
  2044  							Type:         hugepages1Gi,
  2045  							Size:         1 * gb,
  2046  						},
  2047  					},
  2048  					"fakeContainer2": {
  2049  						{
  2050  							NUMAAffinity: []int{0},
  2051  							Type:         v1.ResourceMemory,
  2052  							Size:         1 * gb,
  2053  						},
  2054  						{
  2055  							NUMAAffinity: []int{0},
  2056  							Type:         hugepages1Gi,
  2057  							Size:         1 * gb,
  2058  						},
  2059  					},
  2060  				},
  2061  			},
  2062  			machineState: state.NUMANodeMap{
  2063  				0: &state.NUMANodeState{
  2064  					Cells:               []int{0},
  2065  					NumberOfAssignments: 4,
  2066  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2067  						v1.ResourceMemory: {
  2068  							Allocatable:    9 * gb,
  2069  							Free:           7 * gb,
  2070  							Reserved:       2 * gb,
  2071  							SystemReserved: 1 * gb,
  2072  							TotalMemSize:   10 * gb,
  2073  						},
  2074  						hugepages1Gi: {
  2075  							Allocatable:    5 * gb,
  2076  							Free:           3 * gb,
  2077  							Reserved:       2 * gb,
  2078  							SystemReserved: 0 * gb,
  2079  							TotalMemSize:   5 * gb,
  2080  						},
  2081  					},
  2082  				},
  2083  				1: &state.NUMANodeState{
  2084  					Cells:               []int{1},
  2085  					NumberOfAssignments: 0,
  2086  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2087  						v1.ResourceMemory: {
  2088  							Allocatable:    9 * gb,
  2089  							Free:           9 * gb,
  2090  							Reserved:       0 * gb,
  2091  							SystemReserved: 1 * gb,
  2092  							TotalMemSize:   10 * gb,
  2093  						},
  2094  						hugepages1Gi: {
  2095  							Allocatable:    5 * gb,
  2096  							Free:           5 * gb,
  2097  							Reserved:       0,
  2098  							SystemReserved: 0,
  2099  							TotalMemSize:   5 * gb,
  2100  						},
  2101  					},
  2102  				},
  2103  			},
  2104  			expectedError: nil,
  2105  			expectedHints: map[string][]topologymanager.TopologyHint{
  2106  				string(v1.ResourceMemory): {
  2107  					{
  2108  						NUMANodeAffinity: newNUMAAffinity(0),
  2109  						Preferred:        true,
  2110  					},
  2111  					{
  2112  						NUMANodeAffinity: newNUMAAffinity(1),
  2113  						Preferred:        true,
  2114  					},
  2115  				},
  2116  				string(hugepages1Gi): {
  2117  					{
  2118  						NUMANodeAffinity: newNUMAAffinity(0),
  2119  						Preferred:        true,
  2120  					},
  2121  					{
  2122  						NUMANodeAffinity: newNUMAAffinity(1),
  2123  						Preferred:        true,
  2124  					},
  2125  				},
  2126  			},
  2127  			activePods: []*v1.Pod{
  2128  				{
  2129  					ObjectMeta: metav1.ObjectMeta{
  2130  						UID: "fakePod1",
  2131  					},
  2132  					Spec: v1.PodSpec{
  2133  						Containers: []v1.Container{
  2134  							{
  2135  								Name: "fakeContainer1",
  2136  							},
  2137  							{
  2138  								Name: "fakeContainer2",
  2139  							},
  2140  						},
  2141  					},
  2142  				},
  2143  			},
  2144  		},
  2145  		{
  2146  			description: "Successful hint generation",
  2147  			policyName:  policyTypeStatic,
  2148  			machineInfo: returnMachineInfo(),
  2149  			reserved: systemReservedMemory{
  2150  				0: map[v1.ResourceName]uint64{
  2151  					v1.ResourceMemory: 1 * gb,
  2152  				},
  2153  				1: map[v1.ResourceName]uint64{
  2154  					v1.ResourceMemory: 1 * gb,
  2155  				},
  2156  			},
  2157  			assignments: state.ContainerMemoryAssignments{
  2158  				"fakePod1": map[string][]state.Block{
  2159  					"fakeContainer1": {
  2160  						{
  2161  							NUMAAffinity: []int{0},
  2162  							Type:         v1.ResourceMemory,
  2163  							Size:         1 * gb,
  2164  						},
  2165  						{
  2166  							NUMAAffinity: []int{0},
  2167  							Type:         hugepages1Gi,
  2168  							Size:         1 * gb,
  2169  						},
  2170  					},
  2171  					"fakeContainer2": {
  2172  						{
  2173  							NUMAAffinity: []int{0},
  2174  							Type:         v1.ResourceMemory,
  2175  							Size:         1 * gb,
  2176  						},
  2177  						{
  2178  							NUMAAffinity: []int{0},
  2179  							Type:         hugepages1Gi,
  2180  							Size:         1 * gb,
  2181  						},
  2182  					},
  2183  				},
  2184  			},
  2185  			machineState: state.NUMANodeMap{
  2186  				0: &state.NUMANodeState{
  2187  					Cells:               []int{0},
  2188  					NumberOfAssignments: 4,
  2189  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2190  						v1.ResourceMemory: {
  2191  							Allocatable:    9 * gb,
  2192  							Free:           7 * gb,
  2193  							Reserved:       2 * gb,
  2194  							SystemReserved: 1 * gb,
  2195  							TotalMemSize:   10 * gb,
  2196  						},
  2197  						hugepages1Gi: {
  2198  							Allocatable:    5 * gb,
  2199  							Free:           3 * gb,
  2200  							Reserved:       2 * gb,
  2201  							SystemReserved: 0 * gb,
  2202  							TotalMemSize:   5 * gb,
  2203  						},
  2204  					},
  2205  				},
  2206  				1: &state.NUMANodeState{
  2207  					Cells:               []int{1},
  2208  					NumberOfAssignments: 0,
  2209  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2210  						v1.ResourceMemory: {
  2211  							Allocatable:    9 * gb,
  2212  							Free:           9 * gb,
  2213  							Reserved:       0 * gb,
  2214  							SystemReserved: 1 * gb,
  2215  							TotalMemSize:   10 * gb,
  2216  						},
  2217  						hugepages1Gi: {
  2218  							Allocatable:    5 * gb,
  2219  							Free:           5 * gb,
  2220  							Reserved:       0,
  2221  							SystemReserved: 0,
  2222  							TotalMemSize:   5 * gb,
  2223  						},
  2224  					},
  2225  				},
  2226  			},
  2227  			expectedError: nil,
  2228  			expectedHints: map[string][]topologymanager.TopologyHint{
  2229  				string(v1.ResourceMemory): {
  2230  					{
  2231  						NUMANodeAffinity: newNUMAAffinity(0),
  2232  						Preferred:        true,
  2233  					},
  2234  					{
  2235  						NUMANodeAffinity: newNUMAAffinity(1),
  2236  						Preferred:        true,
  2237  					},
  2238  					{
  2239  						NUMANodeAffinity: newNUMAAffinity(0, 1),
  2240  						Preferred:        false,
  2241  					},
  2242  				},
  2243  				string(hugepages1Gi): {
  2244  					{
  2245  						NUMANodeAffinity: newNUMAAffinity(0),
  2246  						Preferred:        true,
  2247  					},
  2248  					{
  2249  						NUMANodeAffinity: newNUMAAffinity(1),
  2250  						Preferred:        true,
  2251  					},
  2252  					{
  2253  						NUMANodeAffinity: newNUMAAffinity(0, 1),
  2254  						Preferred:        false,
  2255  					},
  2256  				},
  2257  			},
  2258  			activePods: []*v1.Pod{},
  2259  		},
  2260  	}
  2261  
  2262  	for _, testCase := range testCases {
  2263  		t.Run(testCase.description, func(t *testing.T) {
  2264  			mgr := &manager{
  2265  				policy:       returnPolicyByName(testCase),
  2266  				state:        state.NewMemoryState(),
  2267  				containerMap: containermap.NewContainerMap(),
  2268  				containerRuntime: mockRuntimeService{
  2269  					err: nil,
  2270  				},
  2271  				activePods:        func() []*v1.Pod { return testCase.activePods },
  2272  				podStatusProvider: mockPodStatusProvider{},
  2273  			}
  2274  			mgr.sourcesReady = &sourcesReadyStub{}
  2275  			mgr.state.SetMachineState(testCase.machineState.Clone())
  2276  			mgr.state.SetMemoryAssignments(testCase.assignments.Clone())
  2277  
  2278  			pod := getPod("fakePod2", "fakeContainer1", requirementsGuaranteed)
  2279  			container := &pod.Spec.Containers[0]
  2280  			hints := mgr.GetTopologyHints(pod, container)
  2281  			if !reflect.DeepEqual(hints, testCase.expectedHints) {
  2282  				t.Errorf("Hints were not generated correctly. Hints generated: %+v, hints expected: %+v",
  2283  					hints, testCase.expectedHints)
  2284  			}
  2285  		})
  2286  	}
  2287  }
  2288  
  2289  func TestAllocateAndAddPodWithInitContainers(t *testing.T) {
  2290  	testCases := []testMemoryManager{
  2291  		{
  2292  			description: "should remove init containers from the state file, once app container started",
  2293  			policyName:  policyTypeStatic,
  2294  			machineInfo: returnMachineInfo(),
  2295  			assignments: state.ContainerMemoryAssignments{},
  2296  			expectedAssignments: state.ContainerMemoryAssignments{
  2297  				"pod1": map[string][]state.Block{
  2298  					"container1": {
  2299  						{
  2300  							NUMAAffinity: []int{0},
  2301  							Type:         v1.ResourceMemory,
  2302  							Size:         4 * gb,
  2303  						},
  2304  						{
  2305  							NUMAAffinity: []int{0},
  2306  							Type:         hugepages1Gi,
  2307  							Size:         4 * gb,
  2308  						},
  2309  					},
  2310  				},
  2311  			},
  2312  			machineState: state.NUMANodeMap{
  2313  				0: &state.NUMANodeState{
  2314  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2315  						v1.ResourceMemory: {
  2316  							Allocatable:    9728 * mb,
  2317  							Free:           9728 * mb,
  2318  							Reserved:       0,
  2319  							SystemReserved: 512 * mb,
  2320  							TotalMemSize:   10 * gb,
  2321  						},
  2322  						hugepages1Gi: {
  2323  							Allocatable:    5 * gb,
  2324  							Free:           5 * gb,
  2325  							Reserved:       0,
  2326  							SystemReserved: 0,
  2327  							TotalMemSize:   5 * gb,
  2328  						},
  2329  					},
  2330  					Cells: []int{0},
  2331  				},
  2332  				1: &state.NUMANodeState{
  2333  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2334  						v1.ResourceMemory: {
  2335  							Allocatable:    9728 * mb,
  2336  							Free:           9728 * mb,
  2337  							Reserved:       0,
  2338  							SystemReserved: 512 * mb,
  2339  							TotalMemSize:   10 * gb,
  2340  						},
  2341  						hugepages1Gi: {
  2342  							Allocatable:    5 * gb,
  2343  							Free:           5 * gb,
  2344  							Reserved:       0,
  2345  							SystemReserved: 0,
  2346  							TotalMemSize:   5 * gb,
  2347  						},
  2348  					},
  2349  					Cells: []int{1},
  2350  				},
  2351  			},
  2352  			expectedMachineState: state.NUMANodeMap{
  2353  				0: &state.NUMANodeState{
  2354  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2355  						v1.ResourceMemory: {
  2356  							Allocatable:    9728 * mb,
  2357  							Free:           5632 * mb,
  2358  							Reserved:       4 * gb,
  2359  							SystemReserved: 512 * mb,
  2360  							TotalMemSize:   10 * gb,
  2361  						},
  2362  						hugepages1Gi: {
  2363  							Allocatable:    5 * gb,
  2364  							Free:           gb,
  2365  							Reserved:       4 * gb,
  2366  							SystemReserved: 0,
  2367  							TotalMemSize:   5 * gb,
  2368  						},
  2369  					},
  2370  					Cells:               []int{0},
  2371  					NumberOfAssignments: 2,
  2372  				},
  2373  				1: &state.NUMANodeState{
  2374  					MemoryMap: map[v1.ResourceName]*state.MemoryTable{
  2375  						v1.ResourceMemory: {
  2376  							Allocatable:    9728 * mb,
  2377  							Free:           9728 * mb,
  2378  							Reserved:       0,
  2379  							SystemReserved: 512 * mb,
  2380  							TotalMemSize:   10 * gb,
  2381  						},
  2382  						hugepages1Gi: {
  2383  							Allocatable:    5 * gb,
  2384  							Free:           5 * gb,
  2385  							Reserved:       0,
  2386  							SystemReserved: 0,
  2387  							TotalMemSize:   5 * gb,
  2388  						},
  2389  					},
  2390  					Cells: []int{1},
  2391  				},
  2392  			},
  2393  			reserved: systemReservedMemory{
  2394  				0: map[v1.ResourceName]uint64{
  2395  					v1.ResourceMemory: 512 * mb,
  2396  				},
  2397  			},
  2398  			podAllocate: getPodWithInitContainers(
  2399  				"pod1",
  2400  				[]v1.Container{
  2401  					{
  2402  						Name: "container1",
  2403  						Resources: v1.ResourceRequirements{
  2404  							Limits: v1.ResourceList{
  2405  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2406  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2407  								hugepages1Gi:      resource.MustParse("4Gi"),
  2408  							},
  2409  							Requests: v1.ResourceList{
  2410  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2411  								v1.ResourceMemory: resource.MustParse("4Gi"),
  2412  								hugepages1Gi:      resource.MustParse("4Gi"),
  2413  							},
  2414  						},
  2415  					},
  2416  				},
  2417  				[]v1.Container{
  2418  					{
  2419  						Name: "initContainer1",
  2420  						Resources: v1.ResourceRequirements{
  2421  							Limits: v1.ResourceList{
  2422  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2423  								v1.ResourceMemory: resource.MustParse("7Gi"),
  2424  								hugepages1Gi:      resource.MustParse("5Gi"),
  2425  							},
  2426  							Requests: v1.ResourceList{
  2427  								v1.ResourceCPU:    resource.MustParse("1000Mi"),
  2428  								v1.ResourceMemory: resource.MustParse("7Gi"),
  2429  								hugepages1Gi:      resource.MustParse("5Gi"),
  2430  							},
  2431  						},
  2432  					},
  2433  				},
  2434  			),
  2435  		},
  2436  	}
  2437  
  2438  	for _, testCase := range testCases {
  2439  		t.Run(testCase.description, func(t *testing.T) {
  2440  			klog.InfoS("TestAllocateAndAddPodWithInitContainers", "name", testCase.description)
  2441  			mgr := &manager{
  2442  				policy:       returnPolicyByName(testCase),
  2443  				state:        state.NewMemoryState(),
  2444  				containerMap: containermap.NewContainerMap(),
  2445  				containerRuntime: mockRuntimeService{
  2446  					err: nil,
  2447  				},
  2448  				activePods:        func() []*v1.Pod { return []*v1.Pod{testCase.podAllocate} },
  2449  				podStatusProvider: mockPodStatusProvider{},
  2450  			}
  2451  			mgr.sourcesReady = &sourcesReadyStub{}
  2452  			mgr.state.SetMachineState(testCase.machineState.Clone())
  2453  			mgr.state.SetMemoryAssignments(testCase.assignments.Clone())
  2454  
  2455  			// Allocates memory for init containers
  2456  			for i := range testCase.podAllocate.Spec.InitContainers {
  2457  				err := mgr.Allocate(testCase.podAllocate, &testCase.podAllocate.Spec.InitContainers[i])
  2458  				if !reflect.DeepEqual(err, testCase.expectedError) {
  2459  					t.Fatalf("The actual error %v is different from the expected one %v", err, testCase.expectedError)
  2460  				}
  2461  			}
  2462  
  2463  			// Allocates memory for apps containers
  2464  			for i := range testCase.podAllocate.Spec.Containers {
  2465  				err := mgr.Allocate(testCase.podAllocate, &testCase.podAllocate.Spec.Containers[i])
  2466  				if !reflect.DeepEqual(err, testCase.expectedError) {
  2467  					t.Fatalf("The actual error %v is different from the expected one %v", err, testCase.expectedError)
  2468  				}
  2469  			}
  2470  
  2471  			// Calls AddContainer for init containers
  2472  			for i, initContainer := range testCase.podAllocate.Spec.InitContainers {
  2473  				mgr.AddContainer(testCase.podAllocate, &testCase.podAllocate.Spec.InitContainers[i], initContainer.Name)
  2474  			}
  2475  
  2476  			// Calls AddContainer for apps containers
  2477  			for i, appContainer := range testCase.podAllocate.Spec.Containers {
  2478  				mgr.AddContainer(testCase.podAllocate, &testCase.podAllocate.Spec.Containers[i], appContainer.Name)
  2479  			}
  2480  
  2481  			assignments := mgr.state.GetMemoryAssignments()
  2482  			if !areContainerMemoryAssignmentsEqual(t, assignments, testCase.expectedAssignments) {
  2483  				t.Fatalf("Actual assignments %v are different from the expected %v", assignments, testCase.expectedAssignments)
  2484  			}
  2485  
  2486  			machineState := mgr.state.GetMachineState()
  2487  			if !areMachineStatesEqual(machineState, testCase.expectedMachineState) {
  2488  				t.Fatalf("The actual machine state %v is different from the expected %v", machineState, testCase.expectedMachineState)
  2489  			}
  2490  		})
  2491  	}
  2492  }
  2493  
  2494  func returnMachineInfo() cadvisorapi.MachineInfo {
  2495  	return cadvisorapi.MachineInfo{
  2496  		Topology: []cadvisorapi.Node{
  2497  			{
  2498  				Id:     0,
  2499  				Memory: 10 * gb,
  2500  				HugePages: []cadvisorapi.HugePagesInfo{
  2501  					{
  2502  						PageSize: pageSize1Gb,
  2503  						NumPages: 5,
  2504  					},
  2505  				},
  2506  			},
  2507  			{
  2508  				Id:     1,
  2509  				Memory: 10 * gb,
  2510  				HugePages: []cadvisorapi.HugePagesInfo{
  2511  					{
  2512  						PageSize: pageSize1Gb,
  2513  						NumPages: 5,
  2514  					},
  2515  				},
  2516  			},
  2517  		},
  2518  	}
  2519  }
  2520  

View as plain text