github.com/vmware/govmomi@v0.37.1/vim25/types/json_test.go (about) 1 /* 2 Copyright (c) 2022-2023 VMware, Inc. All Rights Reserved. 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 types 18 19 import ( 20 "bytes" 21 "os" 22 "reflect" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/google/go-cmp/cmp" 28 "github.com/stretchr/testify/assert" 29 ) 30 31 var serializationTests = []struct { 32 name string 33 file string 34 data interface{} 35 goType reflect.Type 36 expDecErr string 37 }{ 38 { 39 name: "vminfo", 40 file: "./testdata/vminfo.json", 41 data: &vmInfoObjForTests, 42 goType: reflect.TypeOf(VirtualMachineConfigInfo{}), 43 }, 44 { 45 name: "retrieveResult", 46 file: "./testdata/retrieveResult.json", 47 data: &retrieveResultForTests, 48 goType: reflect.TypeOf(RetrieveResult{}), 49 }, 50 { 51 name: "vminfo-invalid-type-name-value", 52 file: "./testdata/vminfo-invalid-type-name-value.json", 53 data: &vmInfoObjForTests, 54 goType: reflect.TypeOf(VirtualMachineConfigInfo{}), 55 expDecErr: `json: cannot unmarshal bool into Go struct field VirtualMachineConfigInfo.extraConfig of type string`, 56 }, 57 } 58 59 func TestSerialization(t *testing.T) { 60 for _, test := range serializationTests { 61 t.Run(test.name+" Decode", func(t *testing.T) { 62 f, err := os.Open(test.file) 63 if err != nil { 64 t.Fatal(err) 65 } 66 defer f.Close() 67 68 dec := NewJSONDecoder(f) 69 70 ee := test.expDecErr 71 data := reflect.New(test.goType).Interface() 72 if err := dec.Decode(data); err != nil { 73 if ee != err.Error() { 74 t.Errorf("expected error mismatch: e=%v, a=%v", ee, err) 75 } else if ee == "" { 76 t.Errorf("unexpected error: %v", err) 77 } 78 } else if ee != "" { 79 t.Errorf("expected error did not occur: %v", ee) 80 } else { 81 a, e := data, test.data 82 if diff := cmp.Diff(a, e); diff != "" { 83 t.Errorf("mismatched %v: %s", test.name, diff) 84 } 85 } 86 }) 87 88 t.Run(test.name+" Encode", func(t *testing.T) { 89 if test.expDecErr != "" { 90 t.Skip("skipping due to expected decode error") 91 } 92 93 expJSON, err := os.ReadFile(test.file) 94 if err != nil { 95 t.Fatal(err) 96 } 97 98 var w bytes.Buffer 99 _ = w 100 enc := NewJSONEncoder(&w) 101 102 if err := enc.Encode(test.data); err != nil { 103 t.Fatal(err) 104 } 105 106 expected, actual := string(expJSON), w.String() 107 assert.JSONEq(t, expected, actual) 108 }) 109 } 110 } 111 112 func TestOptionValueSerialization(t *testing.T) { 113 tv, e := time.Parse(time.RFC3339Nano, "2022-12-12T11:48:35.473645Z") 114 if e != nil { 115 t.Log("Cannot parse test timestamp. This is coding error.") 116 t.Fail() 117 return 118 } 119 options := []struct { 120 name string 121 wire string 122 binding OptionValue 123 }{ 124 { 125 name: "boolean", 126 wire: `{"_typeName": "OptionValue","key": "option1", 127 "value": {"_typeName": "boolean","_value": true} 128 }`, 129 binding: OptionValue{Key: "option1", Value: true}, 130 }, 131 { 132 name: "byte", 133 wire: `{"_typeName": "OptionValue","key": "option1", 134 "value": {"_typeName": "byte","_value": 16} 135 }`, 136 binding: OptionValue{Key: "option1", Value: uint8(16)}, 137 }, 138 { 139 name: "short", 140 wire: `{"_typeName": "OptionValue","key": "option1", 141 "value": {"_typeName": "short","_value": 300} 142 }`, 143 binding: OptionValue{Key: "option1", Value: int16(300)}, 144 }, 145 { 146 name: "int", 147 wire: `{"_typeName": "OptionValue","key": "option1", 148 "value": {"_typeName": "int","_value": 300}}`, 149 binding: OptionValue{Key: "option1", Value: int32(300)}, 150 }, 151 { 152 name: "long", 153 wire: `{"_typeName": "OptionValue","key": "option1", 154 "value": {"_typeName": "long","_value": 300}}`, 155 binding: OptionValue{Key: "option1", Value: int64(300)}, 156 }, 157 { 158 name: "float", 159 wire: `{"_typeName": "OptionValue","key": "option1", 160 "value": {"_typeName": "float","_value": 30.5}}`, 161 binding: OptionValue{Key: "option1", Value: float32(30.5)}, 162 }, 163 { 164 name: "double", 165 wire: `{"_typeName": "OptionValue","key": "option1", 166 "value": {"_typeName": "double","_value": 12.2}}`, 167 binding: OptionValue{Key: "option1", Value: float64(12.2)}, 168 }, 169 { 170 name: "string", 171 wire: `{"_typeName": "OptionValue","key": "option1", 172 "value": {"_typeName": "string","_value": "test"}}`, 173 binding: OptionValue{Key: "option1", Value: "test"}, 174 }, 175 { 176 name: "dateTime", // time.Time 177 wire: `{"_typeName": "OptionValue","key": "option1", 178 "value": {"_typeName": "dateTime","_value": "2022-12-12T11:48:35.473645Z"}}`, 179 binding: OptionValue{Key: "option1", Value: tv}, 180 }, 181 { 182 name: "binary", // []byte 183 wire: `{"_typeName": "OptionValue","key": "option1", 184 "value": {"_typeName": "binary","_value": "SGVsbG8="}}`, 185 binding: OptionValue{Key: "option1", Value: []byte("Hello")}, 186 }, 187 // during serialization we have no way to guess that a string is to be 188 // converted to uri. Using net.URL solves this. It is a breaking change. 189 // See https://github.com/vmware/govmomi/pull/3123 190 // { 191 // name: "anyURI", // string 192 // wire: `{"_typeName": "OptionValue","key": "option1", 193 // "value": {"_typeName": "anyURI","_value": "http://hello"}}`, 194 // binding: OptionValue{Key: "option1", Value: "test"}, 195 // }, 196 { 197 name: "enum", 198 wire: `{"_typeName": "OptionValue","key": "option1", 199 "value": {"_typeName": "CustomizationNetBIOSMode","_value": "enableNetBIOS"}}`, 200 binding: OptionValue{Key: "option1", Value: CustomizationNetBIOSModeEnableNetBIOS}, 201 }, 202 // There is no ArrayOfCustomizationNetBIOSMode type emitted i.e. no enum 203 // array types are emitted in govmomi. 204 // We can process these in the serialization logic i.e. discover or 205 // prepend the "ArrayOf" prefix 206 // { 207 // name: "array of enum", 208 // wire: `{ 209 // "_typeName": "OptionValue", 210 // "key": "option1", 211 // "value": {"_typeName": "ArrayOfCustomizationNetBIOSMode", 212 // "_value": ["enableNetBIOS"]}}`, 213 // binding: OptionValue{Key: "option1", 214 // Value: []CustomizationNetBIOSMode{ 215 // CustomizationNetBIOSModeEnableNetBIOS 216 // }}, 217 // }, 218 219 // array of struct is weird. Do we want to unmarshal this as 220 // []ClusterHostRecommendation directly? Why do we want to use 221 // ArrayOfClusterHostRecommendation wrapper? 222 // if SOAP does it then I guess back compat is a big reason. 223 { 224 name: "array of struct", 225 wire: `{"_typeName": "OptionValue","key": "option1", 226 "value": {"_typeName": "ArrayOfClusterHostRecommendation","_value": [ 227 { 228 "_typeName":"ClusterHostRecommendation", 229 "host": { 230 "_typeName": "ManagedObjectReference", 231 "type": "HostSystem", 232 "value": "host-42" 233 }, 234 "rating":42 235 }]}}`, 236 binding: OptionValue{ 237 Key: "option1", 238 Value: ArrayOfClusterHostRecommendation{ 239 ClusterHostRecommendation: []ClusterHostRecommendation{ 240 { 241 Host: ManagedObjectReference{ 242 Type: "HostSystem", 243 Value: "host-42", 244 }, 245 Rating: 42, 246 }, 247 }, 248 }, 249 }, 250 }, 251 } 252 253 for _, opt := range options { 254 t.Run("Serialize "+opt.name, func(t *testing.T) { 255 r := strings.NewReader(opt.wire) 256 dec := NewJSONDecoder(r) 257 v := OptionValue{} 258 e := dec.Decode(&v) 259 if e != nil { 260 assert.Fail(t, "Cannot read json", "json %v err %v", opt.wire, e) 261 return 262 } 263 assert.Equal(t, opt.binding, v) 264 }) 265 266 t.Run("De-serialize "+opt.name, func(t *testing.T) { 267 var w bytes.Buffer 268 enc := NewJSONEncoder(&w) 269 enc.Encode(opt.binding) 270 s := w.String() 271 assert.JSONEq(t, opt.wire, s) 272 }) 273 } 274 } 275 276 var vmInfoObjForTests = VirtualMachineConfigInfo{ 277 ChangeVersion: "2022-12-12T11:48:35.473645Z", 278 Modified: mustParseTime(time.RFC3339, "1970-01-01T00:00:00Z"), 279 Name: "test", 280 GuestFullName: "VMware Photon OS (64-bit)", 281 Version: "vmx-20", 282 Uuid: "422ca90b-853b-1101-3350-759f747730cc", 283 CreateDate: addrOfMustParseTime(time.RFC3339, "2022-12-12T11:47:24.685785Z"), 284 InstanceUuid: "502cc2a5-1f06-2890-6d70-ba2c55c5c2b7", 285 NpivTemporaryDisabled: NewBool(true), 286 LocationId: "Earth", 287 Template: false, 288 GuestId: "vmwarePhoton64Guest", 289 AlternateGuestName: "", 290 Annotation: "Hello, world.", 291 Files: VirtualMachineFileInfo{ 292 VmPathName: "[datastore1] test/test.vmx", 293 SnapshotDirectory: "[datastore1] test/", 294 SuspendDirectory: "[datastore1] test/", 295 LogDirectory: "[datastore1] test/", 296 }, 297 Tools: &ToolsConfigInfo{ 298 ToolsVersion: 1, 299 AfterPowerOn: NewBool(true), 300 AfterResume: NewBool(true), 301 BeforeGuestStandby: NewBool(true), 302 BeforeGuestShutdown: NewBool(true), 303 BeforeGuestReboot: nil, 304 ToolsUpgradePolicy: "manual", 305 SyncTimeWithHostAllowed: NewBool(true), 306 SyncTimeWithHost: NewBool(false), 307 LastInstallInfo: &ToolsConfigInfoToolsLastInstallInfo{ 308 Counter: 0, 309 }, 310 }, 311 Flags: VirtualMachineFlagInfo{ 312 EnableLogging: NewBool(true), 313 UseToe: NewBool(false), 314 RunWithDebugInfo: NewBool(false), 315 MonitorType: "release", 316 HtSharing: "any", 317 SnapshotDisabled: NewBool(false), 318 SnapshotLocked: NewBool(false), 319 DiskUuidEnabled: NewBool(false), 320 SnapshotPowerOffBehavior: "powerOff", 321 RecordReplayEnabled: NewBool(false), 322 FaultToleranceType: "unset", 323 CbrcCacheEnabled: NewBool(false), 324 VvtdEnabled: NewBool(false), 325 VbsEnabled: NewBool(false), 326 }, 327 DefaultPowerOps: VirtualMachineDefaultPowerOpInfo{ 328 PowerOffType: "soft", 329 SuspendType: "hard", 330 ResetType: "soft", 331 DefaultPowerOffType: "soft", 332 DefaultSuspendType: "hard", 333 DefaultResetType: "soft", 334 StandbyAction: "checkpoint", 335 }, 336 RebootPowerOff: NewBool(false), 337 Hardware: VirtualHardware{ 338 NumCPU: 1, 339 NumCoresPerSocket: 1, 340 AutoCoresPerSocket: NewBool(true), 341 MemoryMB: 2048, 342 VirtualICH7MPresent: NewBool(false), 343 VirtualSMCPresent: NewBool(false), 344 Device: []BaseVirtualDevice{ 345 &VirtualIDEController{ 346 VirtualController: VirtualController{ 347 VirtualDevice: VirtualDevice{ 348 Key: 200, 349 DeviceInfo: &Description{ 350 Label: "IDE 0", 351 Summary: "IDE 0", 352 }, 353 }, 354 BusNumber: 0, 355 }, 356 }, 357 &VirtualIDEController{ 358 VirtualController: VirtualController{ 359 VirtualDevice: VirtualDevice{ 360 Key: 201, 361 DeviceInfo: &Description{ 362 Label: "IDE 1", 363 Summary: "IDE 1", 364 }, 365 }, 366 BusNumber: 1, 367 }, 368 }, 369 &VirtualPS2Controller{ 370 VirtualController: VirtualController{ 371 VirtualDevice: VirtualDevice{ 372 Key: 300, 373 DeviceInfo: &Description{ 374 Label: "PS2 controller 0", 375 Summary: "PS2 controller 0", 376 }, 377 }, 378 BusNumber: 0, 379 Device: []int32{600, 700}, 380 }, 381 }, 382 &VirtualPCIController{ 383 VirtualController: VirtualController{ 384 VirtualDevice: VirtualDevice{ 385 Key: 100, 386 DeviceInfo: &Description{ 387 Label: "PCI controller 0", 388 Summary: "PCI controller 0", 389 }, 390 }, 391 BusNumber: 0, 392 Device: []int32{500, 12000, 14000, 1000, 15000, 4000}, 393 }, 394 }, 395 &VirtualSIOController{ 396 VirtualController: VirtualController{ 397 VirtualDevice: VirtualDevice{ 398 Key: 400, 399 DeviceInfo: &Description{ 400 Label: "SIO controller 0", 401 Summary: "SIO controller 0", 402 }, 403 }, 404 BusNumber: 0, 405 }, 406 }, 407 &VirtualKeyboard{ 408 VirtualDevice: VirtualDevice{ 409 Key: 600, 410 DeviceInfo: &Description{ 411 Label: "Keyboard", 412 Summary: "Keyboard", 413 }, 414 ControllerKey: 300, 415 UnitNumber: NewInt32(0), 416 }, 417 }, 418 &VirtualPointingDevice{ 419 VirtualDevice: VirtualDevice{ 420 Key: 700, 421 DeviceInfo: &Description{Label: "Pointing device", Summary: "Pointing device; Device"}, 422 Backing: &VirtualPointingDeviceDeviceBackingInfo{ 423 VirtualDeviceDeviceBackingInfo: VirtualDeviceDeviceBackingInfo{ 424 UseAutoDetect: NewBool(false), 425 }, 426 HostPointingDevice: "autodetect", 427 }, 428 ControllerKey: 300, 429 UnitNumber: NewInt32(1), 430 }, 431 }, 432 &VirtualMachineVideoCard{ 433 VirtualDevice: VirtualDevice{ 434 Key: 500, 435 DeviceInfo: &Description{Label: "Video card ", Summary: "Video card"}, 436 ControllerKey: 100, 437 UnitNumber: NewInt32(0), 438 }, 439 VideoRamSizeInKB: 4096, 440 NumDisplays: 1, 441 UseAutoDetect: NewBool(false), 442 Enable3DSupport: NewBool(false), 443 Use3dRenderer: "automatic", 444 GraphicsMemorySizeInKB: 262144, 445 }, 446 &VirtualMachineVMCIDevice{ 447 VirtualDevice: VirtualDevice{ 448 Key: 12000, 449 DeviceInfo: &Description{ 450 Label: "VMCI device", 451 Summary: "Device on the virtual machine PCI " + 452 "bus that provides support for the " + 453 "virtual machine communication interface", 454 }, 455 ControllerKey: 100, 456 UnitNumber: NewInt32(17), 457 }, 458 Id: -1, 459 AllowUnrestrictedCommunication: NewBool(false), 460 FilterEnable: NewBool(true), 461 }, 462 &ParaVirtualSCSIController{ 463 VirtualSCSIController: VirtualSCSIController{ 464 VirtualController: VirtualController{ 465 VirtualDevice: VirtualDevice{ 466 Key: 1000, 467 DeviceInfo: &Description{ 468 Label: "SCSI controller 0", 469 Summary: "VMware paravirtual SCSI", 470 }, 471 ControllerKey: 100, 472 UnitNumber: NewInt32(3), 473 }, 474 Device: []int32{2000}, 475 }, 476 HotAddRemove: NewBool(true), 477 SharedBus: "noSharing", 478 ScsiCtlrUnitNumber: 7, 479 }, 480 }, 481 &VirtualAHCIController{ 482 VirtualSATAController: VirtualSATAController{ 483 VirtualController: VirtualController{ 484 VirtualDevice: VirtualDevice{ 485 Key: 15000, 486 DeviceInfo: &Description{ 487 Label: "SATA controller 0", 488 Summary: "AHCI", 489 }, 490 ControllerKey: 100, 491 UnitNumber: NewInt32(24), 492 }, 493 Device: []int32{16000}, 494 }, 495 }, 496 }, 497 &VirtualCdrom{ 498 VirtualDevice: VirtualDevice{ 499 Key: 16000, 500 DeviceInfo: &Description{ 501 Label: "CD/DVD drive 1", 502 Summary: "Remote device", 503 }, 504 Backing: &VirtualCdromRemotePassthroughBackingInfo{ 505 VirtualDeviceRemoteDeviceBackingInfo: VirtualDeviceRemoteDeviceBackingInfo{ 506 UseAutoDetect: NewBool(false), 507 }, 508 }, 509 Connectable: &VirtualDeviceConnectInfo{AllowGuestControl: true, Status: "untried"}, 510 ControllerKey: 15000, 511 UnitNumber: NewInt32(0), 512 }, 513 }, 514 &VirtualDisk{ 515 VirtualDevice: VirtualDevice{ 516 Key: 2000, 517 DeviceInfo: &Description{ 518 Label: "Hard disk 1", 519 Summary: "4,194,304 KB", 520 }, 521 Backing: &VirtualDiskFlatVer2BackingInfo{ 522 VirtualDeviceFileBackingInfo: VirtualDeviceFileBackingInfo{ 523 BackingObjectId: "1", 524 FileName: "[datastore1] test/test.vmdk", 525 Datastore: &ManagedObjectReference{ 526 Type: "Datastore", 527 Value: "datastore-21", 528 }, 529 }, 530 DiskMode: "persistent", 531 Split: NewBool(false), 532 WriteThrough: NewBool(false), 533 ThinProvisioned: NewBool(false), 534 EagerlyScrub: NewBool(false), 535 Uuid: "6000C298-df15-fe89-ddcb-8ea33329595d", 536 ContentId: "e4e1a794c6307ce7906a3973fffffffe", 537 ChangeId: "", 538 Parent: nil, 539 DeltaDiskFormat: "", 540 DigestEnabled: NewBool(false), 541 DeltaGrainSize: 0, 542 DeltaDiskFormatVariant: "", 543 Sharing: "sharingNone", 544 KeyId: nil, 545 }, 546 ControllerKey: 1000, 547 UnitNumber: NewInt32(0), 548 }, 549 CapacityInKB: 4194304, 550 CapacityInBytes: 4294967296, 551 Shares: &SharesInfo{Shares: 1000, Level: "normal"}, 552 StorageIOAllocation: &StorageIOAllocationInfo{ 553 Limit: NewInt64(-1), 554 Shares: &SharesInfo{Shares: 1000, Level: "normal"}, 555 Reservation: NewInt32(0), 556 }, 557 DiskObjectId: "1-2000", 558 NativeUnmanagedLinkedClone: NewBool(false), 559 }, 560 &VirtualVmxnet3{ 561 VirtualVmxnet: VirtualVmxnet{ 562 VirtualEthernetCard: VirtualEthernetCard{ 563 VirtualDevice: VirtualDevice{ 564 Key: 4000, 565 DeviceInfo: &Description{ 566 Label: "Network adapter 1", 567 Summary: "VM Network", 568 }, 569 Backing: &VirtualEthernetCardNetworkBackingInfo{ 570 VirtualDeviceDeviceBackingInfo: VirtualDeviceDeviceBackingInfo{ 571 DeviceName: "VM Network", 572 UseAutoDetect: NewBool(false), 573 }, 574 Network: &ManagedObjectReference{ 575 Type: "Network", 576 Value: "network-27", 577 }, 578 }, 579 Connectable: &VirtualDeviceConnectInfo{ 580 MigrateConnect: "unset", 581 StartConnected: true, 582 Status: "untried", 583 }, 584 ControllerKey: 100, 585 UnitNumber: NewInt32(7), 586 }, 587 AddressType: "assigned", 588 MacAddress: "00:50:56:ac:4d:ed", 589 WakeOnLanEnabled: NewBool(true), 590 ResourceAllocation: &VirtualEthernetCardResourceAllocation{ 591 Reservation: NewInt64(0), 592 Share: SharesInfo{ 593 Shares: 50, 594 Level: "normal", 595 }, 596 Limit: NewInt64(-1), 597 }, 598 UptCompatibilityEnabled: NewBool(true), 599 }, 600 }, 601 Uptv2Enabled: NewBool(false), 602 }, 603 &VirtualUSBXHCIController{ 604 VirtualController: VirtualController{ 605 VirtualDevice: VirtualDevice{ 606 Key: 14000, 607 DeviceInfo: &Description{ 608 Label: "USB xHCI controller ", 609 Summary: "USB xHCI controller", 610 }, 611 SlotInfo: &VirtualDevicePciBusSlotInfo{ 612 PciSlotNumber: -1, 613 }, 614 ControllerKey: 100, 615 UnitNumber: NewInt32(23), 616 }, 617 }, 618 619 AutoConnectDevices: NewBool(false), 620 }, 621 }, 622 MotherboardLayout: "i440bxHostBridge", 623 SimultaneousThreads: 1, 624 }, 625 CpuAllocation: &ResourceAllocationInfo{ 626 Reservation: NewInt64(0), 627 ExpandableReservation: NewBool(false), 628 Limit: NewInt64(-1), 629 Shares: &SharesInfo{ 630 Shares: 1000, 631 Level: SharesLevelNormal, 632 }, 633 }, 634 MemoryAllocation: &ResourceAllocationInfo{ 635 Reservation: NewInt64(0), 636 ExpandableReservation: NewBool(false), 637 Limit: NewInt64(-1), 638 Shares: &SharesInfo{ 639 Shares: 20480, 640 Level: SharesLevelNormal, 641 }, 642 }, 643 LatencySensitivity: &LatencySensitivity{ 644 Level: LatencySensitivitySensitivityLevelNormal, 645 }, 646 MemoryHotAddEnabled: NewBool(false), 647 CpuHotAddEnabled: NewBool(false), 648 CpuHotRemoveEnabled: NewBool(false), 649 ExtraConfig: []BaseOptionValue{ 650 &OptionValue{Key: "nvram", Value: "test.nvram"}, 651 &OptionValue{Key: "svga.present", Value: "TRUE"}, 652 &OptionValue{Key: "pciBridge0.present", Value: "TRUE"}, 653 &OptionValue{Key: "pciBridge4.present", Value: "TRUE"}, 654 &OptionValue{Key: "pciBridge4.virtualDev", Value: "pcieRootPort"}, 655 &OptionValue{Key: "pciBridge4.functions", Value: "8"}, 656 &OptionValue{Key: "pciBridge5.present", Value: "TRUE"}, 657 &OptionValue{Key: "pciBridge5.virtualDev", Value: "pcieRootPort"}, 658 &OptionValue{Key: "pciBridge5.functions", Value: "8"}, 659 &OptionValue{Key: "pciBridge6.present", Value: "TRUE"}, 660 &OptionValue{Key: "pciBridge6.virtualDev", Value: "pcieRootPort"}, 661 &OptionValue{Key: "pciBridge6.functions", Value: "8"}, 662 &OptionValue{Key: "pciBridge7.present", Value: "TRUE"}, 663 &OptionValue{Key: "pciBridge7.virtualDev", Value: "pcieRootPort"}, 664 &OptionValue{Key: "pciBridge7.functions", Value: "8"}, 665 &OptionValue{Key: "hpet0.present", Value: "TRUE"}, 666 &OptionValue{Key: "RemoteDisplay.maxConnections", Value: "-1"}, 667 &OptionValue{Key: "sched.cpu.latencySensitivity", Value: "normal"}, 668 &OptionValue{Key: "vmware.tools.internalversion", Value: "0"}, 669 &OptionValue{Key: "vmware.tools.requiredversion", Value: "12352"}, 670 &OptionValue{Key: "migrate.hostLogState", Value: "none"}, 671 &OptionValue{Key: "migrate.migrationId", Value: "0"}, 672 &OptionValue{Key: "migrate.hostLog", Value: "test-36f94569.hlog"}, 673 &OptionValue{ 674 Key: "viv.moid", 675 Value: "c5b34aa9-d962-4a74-b7d2-b83ec683ba1b:vm-28:lIgQ2t7v24n2nl3N7K3m6IHW2OoPF4CFrJd5N+Tdfio=", 676 }, 677 }, 678 DatastoreUrl: []VirtualMachineConfigInfoDatastoreUrlPair{ 679 { 680 Name: "datastore1", 681 Url: "/vmfs/volumes/63970ed8-4abddd2a-62d7-02003f49c37d", 682 }, 683 }, 684 SwapPlacement: "inherit", 685 BootOptions: &VirtualMachineBootOptions{ 686 EnterBIOSSetup: NewBool(false), 687 EfiSecureBootEnabled: NewBool(false), 688 BootDelay: 1, 689 BootRetryEnabled: NewBool(false), 690 BootRetryDelay: 10000, 691 NetworkBootProtocol: "ipv4", 692 }, 693 FtInfo: nil, 694 RepConfig: nil, 695 VAppConfig: nil, 696 VAssertsEnabled: NewBool(false), 697 ChangeTrackingEnabled: NewBool(false), 698 Firmware: "bios", 699 MaxMksConnections: -1, 700 GuestAutoLockEnabled: NewBool(true), 701 ManagedBy: nil, 702 MemoryReservationLockedToMax: NewBool(false), 703 InitialOverhead: &VirtualMachineConfigInfoOverheadInfo{ 704 InitialMemoryReservation: 214446080, 705 InitialSwapReservation: 2541883392, 706 }, 707 NestedHVEnabled: NewBool(false), 708 VPMCEnabled: NewBool(false), 709 ScheduledHardwareUpgradeInfo: &ScheduledHardwareUpgradeInfo{ 710 UpgradePolicy: "never", 711 ScheduledHardwareUpgradeStatus: "none", 712 }, 713 ForkConfigInfo: nil, 714 VFlashCacheReservation: 0, 715 VmxConfigChecksum: []uint8{ 716 0x69, 0xf7, 0xa7, 0x9e, 717 0xd1, 0xc2, 0x21, 0x4b, 718 0x6c, 0x20, 0x77, 0x0a, 719 0x94, 0x94, 0x99, 0xee, 720 0x17, 0x5d, 0xdd, 0xa3, 721 }, 722 MessageBusTunnelEnabled: NewBool(false), 723 GuestIntegrityInfo: &VirtualMachineGuestIntegrityInfo{ 724 Enabled: NewBool(false), 725 }, 726 MigrateEncryption: "opportunistic", 727 SgxInfo: &VirtualMachineSgxInfo{ 728 FlcMode: "unlocked", 729 RequireAttestation: NewBool(false), 730 }, 731 ContentLibItemInfo: nil, 732 FtEncryptionMode: "ftEncryptionOpportunistic", 733 GuestMonitoringModeInfo: &VirtualMachineGuestMonitoringModeInfo{}, 734 SevEnabled: NewBool(false), 735 NumaInfo: &VirtualMachineVirtualNumaInfo{ 736 AutoCoresPerNumaNode: NewBool(true), 737 VnumaOnCpuHotaddExposed: NewBool(false), 738 }, 739 PmemFailoverEnabled: NewBool(false), 740 VmxStatsCollectionEnabled: NewBool(true), 741 VmOpNotificationToAppEnabled: NewBool(false), 742 VmOpNotificationTimeout: -1, 743 DeviceSwap: &VirtualMachineVirtualDeviceSwap{ 744 LsiToPvscsi: &VirtualMachineVirtualDeviceSwapDeviceSwapInfo{ 745 Enabled: NewBool(true), 746 Applicable: NewBool(false), 747 Status: "none", 748 }, 749 }, 750 Pmem: nil, 751 DeviceGroups: &VirtualMachineVirtualDeviceGroups{}, 752 } 753 754 var retrieveResultForTests = RetrieveResult{ 755 Token: "", 756 Objects: []ObjectContent{ 757 758 { 759 760 DynamicData: DynamicData{}, 761 Obj: ManagedObjectReference{ 762 763 Type: "Folder", 764 Value: "group-d1", 765 }, 766 PropSet: []DynamicProperty{ 767 { 768 769 Name: "alarmActionsEnabled", 770 Val: true, 771 }, 772 { 773 774 Name: "availableField", 775 Val: ArrayOfCustomFieldDef{ 776 777 CustomFieldDef: []CustomFieldDef{}, 778 }, 779 }, 780 781 { 782 783 Name: "childEntity", 784 Val: ArrayOfManagedObjectReference{ 785 ManagedObjectReference: []ManagedObjectReference{}, 786 }, 787 }, 788 { 789 Name: "childType", 790 Val: ArrayOfString{ 791 String: []string{ 792 "Folder", 793 "Datacenter"}, 794 }, 795 }, 796 { 797 Name: "configIssue", 798 Val: ArrayOfEvent{ 799 Event: []BaseEvent{}, 800 }, 801 }, 802 { 803 Name: "configStatus", 804 Val: ManagedEntityStatusGray}, 805 { 806 Name: "customValue", 807 Val: ArrayOfCustomFieldValue{ 808 CustomFieldValue: []BaseCustomFieldValue{}, 809 }, 810 }, 811 { 812 Name: "declaredAlarmState", 813 Val: ArrayOfAlarmState{ 814 AlarmState: []AlarmState{ 815 { 816 Key: "alarm-328.group-d1", 817 Entity: ManagedObjectReference{ 818 Type: "Folder", 819 Value: "group-d1"}, 820 Alarm: ManagedObjectReference{ 821 Type: "Alarm", 822 Value: "alarm-328"}, 823 OverallStatus: "gray", 824 Time: time.Date(2023, time.January, 14, 8, 57, 35, 279575000, time.UTC), 825 Acknowledged: NewBool(false), 826 }, 827 { 828 Key: "alarm-327.group-d1", 829 Entity: ManagedObjectReference{ 830 Type: "Folder", 831 Value: "group-d1"}, 832 Alarm: ManagedObjectReference{ 833 Type: "Alarm", 834 Value: "alarm-327"}, 835 OverallStatus: "green", 836 Time: time.Date(2023, time.January, 14, 8, 56, 40, 83607000, time.UTC), 837 Acknowledged: NewBool(false), 838 EventKey: 756, 839 }, 840 { 841 DynamicData: DynamicData{}, 842 Key: "alarm-326.group-d1", 843 Entity: ManagedObjectReference{ 844 Type: "Folder", 845 Value: "group-d1"}, 846 Alarm: ManagedObjectReference{ 847 Type: "Alarm", 848 Value: "alarm-326"}, 849 OverallStatus: "green", 850 Time: time.Date(2023, 851 time.January, 852 14, 853 8, 854 56, 855 35, 856 82616000, 857 time.UTC), 858 Acknowledged: NewBool(false), 859 EventKey: 751, 860 }, 861 }, 862 }, 863 }, 864 { 865 Name: "disabledMethod", 866 Val: ArrayOfString{ 867 String: []string{}, 868 }, 869 }, 870 { 871 Name: "effectiveRole", 872 Val: ArrayOfInt{ 873 Int: []int32{-1}, 874 }, 875 }, 876 { 877 Name: "name", 878 Val: "Datacenters"}, 879 { 880 Name: "overallStatus", 881 Val: ManagedEntityStatusGray}, 882 { 883 Name: "permission", 884 Val: ArrayOfPermission{ 885 Permission: []Permission{ 886 { 887 Entity: &ManagedObjectReference{ 888 Value: "group-d1", 889 Type: "Folder", 890 }, 891 Principal: "VSPHERE.LOCAL\\vmware-vsm-2bd917c6-e084-4d1f-988d-a68f7525cc94", 892 Group: false, 893 RoleId: 1034, 894 Propagate: true}, 895 { 896 Entity: &ManagedObjectReference{ 897 Value: "group-d1", 898 Type: "Folder", 899 }, 900 Principal: "VSPHERE.LOCAL\\topologysvc-2bd917c6-e084-4d1f-988d-a68f7525cc94", 901 Group: false, 902 RoleId: 1024, 903 Propagate: true}, 904 { 905 Entity: &ManagedObjectReference{ 906 Value: "group-d1", 907 Type: "Folder", 908 }, 909 Principal: "VSPHERE.LOCAL\\vpxd-extension-2bd917c6-e084-4d1f-988d-a68f7525cc94", 910 Group: false, 911 RoleId: -1, 912 Propagate: true}, 913 }, 914 }, 915 }, 916 { 917 Name: "recentTask", 918 Val: ArrayOfManagedObjectReference{ 919 ManagedObjectReference: []ManagedObjectReference{ 920 { 921 Type: "Task", 922 Value: "task-186"}, 923 { 924 Type: "Task", 925 Value: "task-187"}, 926 { 927 Type: "Task", 928 Value: "task-188"}, 929 }, 930 }, 931 }, 932 { 933 Name: "tag", 934 Val: ArrayOfTag{ 935 Tag: []Tag{}, 936 }, 937 }, 938 { 939 Name: "triggeredAlarmState", 940 Val: ArrayOfAlarmState{ 941 AlarmState: []AlarmState{}, 942 }, 943 }, 944 { 945 Name: "value", 946 Val: ArrayOfCustomFieldValue{ 947 CustomFieldValue: []BaseCustomFieldValue{}, 948 }, 949 }, 950 }, 951 MissingSet: nil, 952 }, 953 }, 954 } 955 956 func mustParseTime(layout, value string) time.Time { 957 t, err := time.Parse(layout, value) 958 if err != nil { 959 panic(err) 960 } 961 return t 962 } 963 964 func addrOfMustParseTime(layout, value string) *time.Time { 965 t := mustParseTime(layout, value) 966 return &t 967 }