1 //go:build windows 2 3 package uvm 4 5 import ( 6 "context" 7 "testing" 8 9 "github.com/Microsoft/hcsshim/hcn" 10 "github.com/Microsoft/hcsshim/internal/computeagent" 11 hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" 12 "github.com/Microsoft/hcsshim/internal/hns" 13 "github.com/Microsoft/hcsshim/internal/protocol/guestresource" 14 "github.com/containerd/typeurl" 15 "github.com/gogo/protobuf/types" 16 ) 17 18 type testUtilityVM struct{} 19 20 var _ agentComputeSystem = &testUtilityVM{} 21 22 func (t *testUtilityVM) AddEndpointToNSWithID(ctx context.Context, nsID, nicID string, endpoint *hns.HNSEndpoint) error { 23 return nil 24 } 25 26 func (t *testUtilityVM) RemoveEndpointFromNS(ctx context.Context, id string, endpoint *hns.HNSEndpoint) error { 27 return nil 28 } 29 30 func (t *testUtilityVM) UpdateNIC(ctx context.Context, id string, settings *hcsschema.NetworkAdapter) error { 31 return nil 32 } 33 34 func (t *testUtilityVM) AssignDevice(ctx context.Context, deviceID string, index uint16, vmBusGUID string) (*VPCIDevice, error) { 35 return &VPCIDevice{}, nil 36 } 37 38 func (t *testUtilityVM) RemoveDevice(ctx context.Context, deviceID string, index uint16) error { 39 return nil 40 } 41 42 func (t *testUtilityVM) AddNICInGuest(ctx context.Context, cfg *guestresource.LCOWNetworkAdapter) error { 43 return nil 44 } 45 46 func (t *testUtilityVM) RemoveNICInGuest(ctx context.Context, cfg *guestresource.LCOWNetworkAdapter) error { 47 return nil 48 } 49 50 func TestAddNIC(t *testing.T) { 51 ctx := context.Background() 52 53 agent := &computeAgent{ 54 uvm: &testUtilityVM{}, 55 } 56 57 hnsGetHNSEndpointByName = func(endpointName string) (*hns.HNSEndpoint, error) { 58 return &hns.HNSEndpoint{ 59 Namespace: &hns.Namespace{ID: t.Name() + "-namespaceID"}, 60 }, nil 61 } 62 63 var ( 64 testNICID = t.Name() + "-nicID" 65 testEndpointName = t.Name() + "-endpoint" 66 ) 67 68 type config struct { 69 name string 70 nicID string 71 endpointName string 72 errorExpected bool 73 } 74 tests := []config{ 75 { 76 name: "AddNIC returns no error", 77 nicID: testNICID, 78 endpointName: testEndpointName, 79 errorExpected: false, 80 }, 81 { 82 name: "AddNIC returns error with blank nic ID", 83 nicID: "", 84 endpointName: testEndpointName, 85 errorExpected: true, 86 }, 87 { 88 name: "AddNIC returns error with no endpoint", 89 nicID: testNICID, 90 endpointName: "", 91 errorExpected: true, 92 }, 93 } 94 95 for _, test := range tests { 96 t.Run(test.name, func(_ *testing.T) { 97 var err error 98 var anyEndpoint *types.Any 99 if test.endpointName != "" { 100 endpoint := &hcn.HostComputeEndpoint{ 101 Name: test.endpointName, 102 } 103 anyEndpoint, err = typeurl.MarshalAny(endpoint) 104 if err != nil { 105 t.Fatal(err) 106 } 107 } 108 req := &computeagent.AddNICInternalRequest{ 109 NicID: test.nicID, 110 Endpoint: anyEndpoint, 111 } 112 113 _, err = agent.AddNIC(ctx, req) 114 if test.errorExpected && err == nil { 115 t.Fatalf("expected AddNIC to return an error") 116 } 117 if !test.errorExpected && err != nil { 118 t.Fatalf("expected AddNIC to return no error, instead got %v", err) 119 } 120 }) 121 } 122 } 123 124 func TestModifyNIC(t *testing.T) { 125 ctx := context.Background() 126 127 agent := &computeAgent{ 128 uvm: &testUtilityVM{}, 129 } 130 131 hnsGetHNSEndpointByName = func(endpointName string) (*hns.HNSEndpoint, error) { 132 return &hns.HNSEndpoint{ 133 Id: t.Name() + "-endpoint-ID", 134 MacAddress: "00-00-00-00-00-00", 135 }, nil 136 } 137 138 var ( 139 testNICID = t.Name() + "-nicID" 140 testEndpointName = t.Name() + "-endpoint" 141 ) 142 143 iovSettingsOn := &computeagent.IovSettings{ 144 IovOffloadWeight: 100, 145 } 146 147 type config struct { 148 name string 149 nicID string 150 endpointName string 151 iovSettings *computeagent.IovSettings 152 errorExpected bool 153 } 154 tests := []config{ 155 { 156 name: "ModifyNIC returns no error", 157 nicID: testNICID, 158 endpointName: testEndpointName, 159 iovSettings: iovSettingsOn, 160 errorExpected: false, 161 }, 162 { 163 name: "ModifyNIC returns error with blank nic ID", 164 nicID: "", 165 endpointName: testEndpointName, 166 iovSettings: iovSettingsOn, 167 errorExpected: true, 168 }, 169 { 170 name: "ModifyNIC returns error with no endpoint", 171 nicID: testNICID, 172 endpointName: "", 173 iovSettings: iovSettingsOn, 174 errorExpected: true, 175 }, 176 { 177 name: "ModifyNIC returns error with nil IOV settings", 178 nicID: testNICID, 179 endpointName: testEndpointName, 180 iovSettings: nil, 181 errorExpected: true, 182 }, 183 } 184 for _, test := range tests { 185 t.Run(test.name, func(_ *testing.T) { 186 var err error 187 var anyEndpoint *types.Any 188 if test.endpointName != "" { 189 endpoint := &hcn.HostComputeEndpoint{ 190 Name: test.endpointName, 191 } 192 anyEndpoint, err = typeurl.MarshalAny(endpoint) 193 if err != nil { 194 t.Fatal(err) 195 } 196 } 197 req := &computeagent.ModifyNICInternalRequest{ 198 NicID: test.nicID, 199 Endpoint: anyEndpoint, 200 IovPolicySettings: test.iovSettings, 201 } 202 203 _, err = agent.ModifyNIC(ctx, req) 204 if test.errorExpected && err == nil { 205 t.Fatalf("expected ModifyNIC to return an error") 206 } 207 if !test.errorExpected && err != nil { 208 t.Fatalf("expected ModifyNIC to return no error, instead got %v", err) 209 } 210 }) 211 } 212 } 213 214 func TestDeleteNIC(t *testing.T) { 215 ctx := context.Background() 216 217 agent := &computeAgent{ 218 uvm: &testUtilityVM{}, 219 } 220 221 hnsGetHNSEndpointByName = func(endpointName string) (*hns.HNSEndpoint, error) { 222 return &hns.HNSEndpoint{ 223 Namespace: &hns.Namespace{ID: "test-namespace-ID"}, 224 }, nil 225 } 226 227 var ( 228 testNICID = t.Name() + "-nicID" 229 testEndpointName = t.Name() + "-endpoint" 230 ) 231 232 type config struct { 233 name string 234 nicID string 235 endpointName string 236 errorExpected bool 237 } 238 tests := []config{ 239 { 240 name: "DeleteNIC returns no error", 241 nicID: testNICID, 242 endpointName: testEndpointName, 243 errorExpected: false, 244 }, 245 { 246 name: "DeleteNIC returns error with blank nic ID", 247 nicID: "", 248 endpointName: testEndpointName, 249 errorExpected: true, 250 }, 251 { 252 name: "DeleteNIC returns error with no endpoint", 253 nicID: testNICID, 254 endpointName: "", 255 errorExpected: true, 256 }, 257 } 258 for _, test := range tests { 259 t.Run(test.name, func(_ *testing.T) { 260 var err error 261 var anyEndpoint *types.Any 262 if test.endpointName != "" { 263 endpoint := &hcn.HostComputeEndpoint{ 264 Name: test.endpointName, 265 } 266 anyEndpoint, err = typeurl.MarshalAny(endpoint) 267 if err != nil { 268 t.Fatal(err) 269 } 270 } 271 req := &computeagent.DeleteNICInternalRequest{ 272 NicID: test.nicID, 273 Endpoint: anyEndpoint, 274 } 275 276 _, err = agent.DeleteNIC(ctx, req) 277 if test.errorExpected && err == nil { 278 t.Fatalf("expected DeleteNIC to return an error") 279 } 280 if !test.errorExpected && err != nil { 281 t.Fatalf("expected DeleteNIC to return no error, instead got %v", err) 282 } 283 }) 284 } 285 } 286 287 func TestAssignPCI(t *testing.T) { 288 ctx := context.Background() 289 290 agent := &computeAgent{ 291 uvm: &testUtilityVM{}, 292 } 293 294 testDeviceID := "test-device-ID" 295 296 type config struct { 297 name string 298 deviceID string 299 errorExpected bool 300 } 301 tests := []config{ 302 { 303 name: "AssignPCI returns no error", 304 deviceID: testDeviceID, 305 errorExpected: false, 306 }, 307 { 308 name: "AssignPCI returns error with blank device ID", 309 deviceID: "", 310 errorExpected: true, 311 }, 312 } 313 for _, test := range tests { 314 t.Run(test.name, func(_ *testing.T) { 315 req := &computeagent.AssignPCIInternalRequest{ 316 ContainerID: t.Name() + "-container-id", 317 DeviceID: test.deviceID, 318 } 319 320 _, err := agent.AssignPCI(ctx, req) 321 if test.errorExpected && err == nil { 322 t.Fatalf("expected AssignPCI to return an error") 323 } 324 if !test.errorExpected && err != nil { 325 t.Fatalf("expected AssignPCI to return no error, instead got %v", err) 326 } 327 }) 328 } 329 } 330 331 func TestRemovePCI(t *testing.T) { 332 ctx := context.Background() 333 334 agent := &computeAgent{ 335 uvm: &testUtilityVM{}, 336 } 337 338 testDeviceID := "test-device-ID" 339 340 type config struct { 341 name string 342 deviceID string 343 errorExpected bool 344 } 345 tests := []config{ 346 { 347 name: "RemovePCI returns no error", 348 deviceID: testDeviceID, 349 errorExpected: false, 350 }, 351 { 352 name: "RemovePCI returns error with blank device ID", 353 deviceID: "", 354 errorExpected: true, 355 }, 356 } 357 for _, test := range tests { 358 t.Run(test.name, func(_ *testing.T) { 359 req := &computeagent.RemovePCIInternalRequest{ 360 ContainerID: t.Name() + "-container-id", 361 DeviceID: test.deviceID, 362 } 363 364 _, err := agent.RemovePCI(ctx, req) 365 if test.errorExpected && err == nil { 366 t.Fatalf("expected RemovePCI to return an error") 367 } 368 if !test.errorExpected && err != nil { 369 t.Fatalf("expected RemovePCI to return no error, instead got %v", err) 370 } 371 }) 372 } 373 } 374