diff --git a/server/pom.xml b/server/pom.xml
index 2b35a0f42ac8..fc27f97fbd43 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -118,6 +118,24 @@
test-jar
test
+
+ org.junit.jupiter
+ junit-jupiter
+ ${cs.junit.jupiter.version}
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+ ${cs.junit.jupiter.version}
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${cs.mockito.version}
+ test
+
org.reflections
reflections
diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
index 8c51d9926841..f309196442ea 100644
--- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
@@ -4184,474 +4184,584 @@ public UsageRecordResponse createUsageResponse(Usage usageRecord, Map ignored = Mockito.mockStatic(ApiDBUtils.class)) {
when(ApiDBUtils.getResourceIconByResourceUUID(uuid, ResourceTag.ResourceObjectType.GuestOsCategory)).thenReturn(null);
GuestOSCategoryResponse response = apiResponseHelper.createGuestOSCategoryResponse(guestOsCategory);
- Assert.assertNotNull(response);
- Assert.assertEquals(uuid, response.getId());
- Assert.assertEquals(name, response.getName());
+ Assertions.assertNotNull(response);
+ Assertions.assertEquals(uuid, response.getId());
+ Assertions.assertEquals(name, response.getName());
Object obj = ReflectionTestUtils.getField(response, "featured");
if (obj == null) {
- Assert.fail("Invalid featured value");
+ Assertions.fail("Invalid featured value");
}
- Assert.assertFalse((Boolean)obj);
+ Assertions.assertFalse((Boolean)obj);
obj = ReflectionTestUtils.getField(response, "resourceIconResponse");
- Assert.assertNull(obj);
- Assert.assertEquals("oscategory", response.getObjectName());
+ Assertions.assertNull(obj);
+ Assertions.assertEquals("oscategory", response.getObjectName());
}
}
@@ -621,7 +649,7 @@ public void testCreateGuestOSCategoryResponse_WithShowIconFalse() {
Mockito.when(guestOsCategory.getUuid()).thenReturn(UUID.randomUUID().toString());
try (MockedStatic mockedStatic = Mockito.mockStatic(ApiDBUtils.class)) {
GuestOSCategoryResponse response = apiResponseHelper.createGuestOSCategoryResponse(guestOsCategory, false);
- Assert.assertNotNull(response);
+ Assertions.assertNotNull(response);
mockedStatic.verify(() -> ApiDBUtils.getResourceIconByResourceUUID(Mockito.any(), Mockito.any()),
Mockito.never());
}
@@ -732,12 +760,12 @@ public void createConsoleSessionResponseTestShouldReturnRestrictedResponse() {
ConsoleSessionResponse response = apiResponseHelper.createConsoleSessionResponse(consoleSessionMock, ResponseObject.ResponseView.Restricted);
- Assert.assertEquals(expected.getId(), response.getId());
- Assert.assertEquals(expected.getCreated(), response.getCreated());
- Assert.assertEquals(expected.getAcquired(), response.getAcquired());
- Assert.assertEquals(expected.getRemoved(), response.getRemoved());
- Assert.assertEquals(expected.getConsoleEndpointCreatorAddress(), response.getConsoleEndpointCreatorAddress());
- Assert.assertEquals(expected.getClientAddress(), response.getClientAddress());
+ Assertions.assertEquals(expected.getId(), response.getId());
+ Assertions.assertEquals(expected.getCreated(), response.getCreated());
+ Assertions.assertEquals(expected.getAcquired(), response.getAcquired());
+ Assertions.assertEquals(expected.getRemoved(), response.getRemoved());
+ Assertions.assertEquals(expected.getConsoleEndpointCreatorAddress(), response.getConsoleEndpointCreatorAddress());
+ Assertions.assertEquals(expected.getClientAddress(), response.getClientAddress());
}
}
@@ -781,23 +809,664 @@ public void createConsoleSessionResponseTestShouldReturnFullResponse() {
ConsoleSessionResponse response = apiResponseHelper.createConsoleSessionResponse(consoleSessionMock, ResponseObject.ResponseView.Full);
- Assert.assertEquals(expected.getId(), response.getId());
- Assert.assertEquals(expected.getCreated(), response.getCreated());
- Assert.assertEquals(expected.getAcquired(), response.getAcquired());
- Assert.assertEquals(expected.getRemoved(), response.getRemoved());
- Assert.assertEquals(expected.getConsoleEndpointCreatorAddress(), response.getConsoleEndpointCreatorAddress());
- Assert.assertEquals(expected.getClientAddress(), response.getClientAddress());
- Assert.assertEquals(expected.getDomain(), response.getDomain());
- Assert.assertEquals(expected.getDomainPath(), response.getDomainPath());
- Assert.assertEquals(expected.getDomainId(), response.getDomainId());
- Assert.assertEquals(expected.getUser(), response.getUser());
- Assert.assertEquals(expected.getUserId(), response.getUserId());
- Assert.assertEquals(expected.getAccount(), response.getAccount());
- Assert.assertEquals(expected.getAccountId(), response.getAccountId());
- Assert.assertEquals(expected.getHostId(), response.getHostId());
- Assert.assertEquals(expected.getHostName(), response.getHostName());
- Assert.assertEquals(expected.getVmId(), response.getVmId());
- Assert.assertEquals(expected.getVmName(), response.getVmName());
+ Assertions.assertEquals(expected.getId(), response.getId());
+ Assertions.assertEquals(expected.getCreated(), response.getCreated());
+ Assertions.assertEquals(expected.getAcquired(), response.getAcquired());
+ Assertions.assertEquals(expected.getRemoved(), response.getRemoved());
+ Assertions.assertEquals(expected.getConsoleEndpointCreatorAddress(), response.getConsoleEndpointCreatorAddress());
+ Assertions.assertEquals(expected.getClientAddress(), response.getClientAddress());
+ Assertions.assertEquals(expected.getDomain(), response.getDomain());
+ Assertions.assertEquals(expected.getDomainPath(), response.getDomainPath());
+ Assertions.assertEquals(expected.getDomainId(), response.getDomainId());
+ Assertions.assertEquals(expected.getUser(), response.getUser());
+ Assertions.assertEquals(expected.getUserId(), response.getUserId());
+ Assertions.assertEquals(expected.getAccount(), response.getAccount());
+ Assertions.assertEquals(expected.getAccountId(), response.getAccountId());
+ Assertions.assertEquals(expected.getHostId(), response.getHostId());
+ Assertions.assertEquals(expected.getHostName(), response.getHostName());
+ Assertions.assertEquals(expected.getVmId(), response.getVmId());
+ Assertions.assertEquals(expected.getVmName(), response.getVmName());
}
}
+
+ @Test
+ @DisplayName("RUNNING_VM usage populates service offering, VM and OS details")
+ public void populateRunningVmUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
+ VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+ VMTemplateVO template = mock(VMTemplateVO.class);
+ GuestOSVO guestOS = mock(GuestOSVO.class);
+ GuestOSCategoryVO guestOSCategory = mock(GuestOSCategoryVO.class);
+ Long usageId = 11L;
+ Long offeringId = 21L;
+ Long guestOSId = 31L;
+ Long guestOSCategoryId = 41L;
+
+ when(usageRecord.getUsageType()).thenReturn(UsageTypes.RUNNING_VM);
+ when(usageRecord.getOfferingId()).thenReturn(offeringId);
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getVmInstanceId()).thenReturn(usageId);
+ when(usageRecord.getType()).thenReturn("KVM");
+ when(usageRecord.getCpuCores()).thenReturn(null);
+ when(usageRecord.getCpuSpeed()).thenReturn(2400L);
+ when(usageRecord.getMemory()).thenReturn(8192L);
+ when(entityManagerMock.findByIdIncludingRemoved(ServiceOfferingVO.class, offeringId.toString())).thenReturn(serviceOffering);
+ when(serviceOffering.getUuid()).thenReturn("service-offering-uuid");
+ when(serviceOffering.getName()).thenReturn("Small Instance");
+ when(serviceOffering.getCpu()).thenReturn(4);
+ when(vmInstance.getUuid()).thenReturn("vm-uuid");
+ when(vmInstance.getId()).thenReturn(usageId);
+ when(vmInstance.getHostName()).thenReturn("vm-host");
+ when(vmInstance.getInstanceName()).thenReturn("i-2-11-VM");
+ when(vmInstance.getGuestOSId()).thenReturn(guestOSId);
+ when(guestOSDaoMock.findById(guestOSId)).thenReturn(guestOS);
+ when(guestOS.getUuid()).thenReturn("guest-os-uuid");
+ when(guestOS.getDisplayName()).thenReturn("Ubuntu 22.04");
+ when(guestOS.getCategoryId()).thenReturn(guestOSCategoryId);
+ when(guestOSCategoryDaoMock.findById(guestOSCategoryId)).thenReturn(guestOSCategory);
+ when(guestOSCategory.getUuid()).thenReturn("guest-os-category-uuid");
+ when(guestOSCategory.getName()).thenReturn("Linux");
+ when(template.getUuid()).thenReturn("template-uuid");
+ when(template.getName()).thenReturn("Ubuntu Template");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateRunningOrAllocatedVmUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class, VMTemplateVO.class},
+ usageRecord, response, false, vmInstance, template);
+
+ // Assert
+ assertResponseField(response, "offeringId", "service-offering-uuid");
+ assertResponseField(response, "usageId", "vm-uuid");
+ assertResponseField(response, "type", "KVM");
+ assertResponseField(response, "cpuNumber", 4L);
+ assertResponseField(response, "cpuSpeed", 2400L);
+ assertResponseField(response, "memory", 8192L);
+ assertResponseField(response, "osTypeId", "guest-os-uuid");
+ assertResponseField(response, "osDisplayName", "Ubuntu 22.04");
+ assertResponseField(response, "osCategoryId", "guest-os-category-uuid");
+ assertResponseField(response, "osCategoryName", "Linux");
+ assertDescriptionContains(response, "Running VM usage for vm-host (i-2-11-VM) (vm-uuid)");
+ assertDescriptionContains(response, "using service offering Small Instance (service-offering-uuid)");
+ assertDescriptionContains(response, "and template Ubuntu Template (template-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.UserVm, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(ServiceOfferingVO.class, offeringId.toString());
+ verify(guestOSDaoMock).findById(guestOSId);
+ }
+
+ @Test
+ @DisplayName("ALLOCATED_VM usage falls back to service offering compute details")
+ public void populateAllocatedVmUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
+ VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+ Long usageId = 12L;
+ Long vmInstanceId = 22L;
+ Long offeringId = 32L;
+
+ when(usageRecord.getUsageType()).thenReturn(UsageTypes.ALLOCATED_VM);
+ when(usageRecord.getOfferingId()).thenReturn(offeringId);
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getVmInstanceId()).thenReturn(vmInstanceId);
+ when(usageRecord.getType()).thenReturn("KVM");
+ when(usageRecord.getCpuCores()).thenReturn(null);
+ when(usageRecord.getCpuSpeed()).thenReturn(null);
+ when(usageRecord.getMemory()).thenReturn(null);
+ when(entityManagerMock.findByIdIncludingRemoved(ServiceOfferingVO.class, offeringId.toString())).thenReturn(serviceOffering);
+ when(entityManagerMock.findByIdIncludingRemoved(VMInstanceVO.class, usageId.toString())).thenReturn(vmInstance);
+ when(serviceOffering.getUuid()).thenReturn("allocated-service-offering-uuid");
+ when(serviceOffering.getName()).thenReturn("Medium Instance");
+ when(serviceOffering.getCpu()).thenReturn(2);
+ when(serviceOffering.getSpeed()).thenReturn(1800);
+ when(serviceOffering.getRamSize()).thenReturn(4096);
+ when(vmInstance.getUuid()).thenReturn("allocated-vm-uuid");
+ when(vmInstance.getId()).thenReturn(usageId);
+ when(vmInstance.getHostName()).thenReturn("allocated-vm-host");
+ when(vmInstance.getInstanceName()).thenReturn("i-2-12-VM");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateRunningOrAllocatedVmUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class, VMTemplateVO.class},
+ usageRecord, response, false, null, null);
+
+ // Assert
+ assertResponseField(response, "offeringId", "allocated-service-offering-uuid");
+ assertResponseField(response, "usageId", "allocated-vm-uuid");
+ assertResponseField(response, "type", "KVM");
+ assertResponseField(response, "cpuNumber", 2L);
+ assertResponseField(response, "cpuSpeed", 1800L);
+ assertResponseField(response, "memory", 4096L);
+ assertDescriptionContains(response, "Allocated VM usage for allocated-vm-host (i-2-12-VM) (allocated-vm-uuid)");
+ assertDescriptionContains(response, "using service offering Medium Instance (allocated-service-offering-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.UserVm, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(ServiceOfferingVO.class, offeringId.toString());
+ verify(entityManagerMock).findByIdIncludingRemoved(VMInstanceVO.class, usageId.toString());
+ }
+
+ @Test
+ @DisplayName("IP_ADDRESS usage populates public IP flags")
+ public void populateIpAddressUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ IPAddressVO ipAddress = mock(IPAddressVO.class);
+ Long usageId = 13L;
+
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getType()).thenReturn("SourceNat");
+ when(usageRecord.getSize()).thenReturn(1L);
+ when(entityManagerMock.findByIdIncludingRemoved(IPAddressVO.class, usageId.toString())).thenReturn(ipAddress);
+ when(ipAddress.getUuid()).thenReturn("ip-address-uuid");
+ when(ipAddress.getId()).thenReturn(usageId);
+ when(ipAddress.getAssociatedWithNetworkId()).thenReturn(null);
+ when(ipAddress.getSourceNetworkId()).thenReturn(23L);
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateIpAddressUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class}, usageRecord, response);
+
+ // Assert
+ assertResponseField(response, "usageId", "ip-address-uuid");
+ assertResponseField(response, "isSourceNat", Boolean.TRUE);
+ assertResponseField(response, "isSystem", Boolean.TRUE);
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.PublicIpAddress, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(IPAddressVO.class, usageId.toString());
+ verify(ipAddress).getSourceNetworkId();
+ }
+
+ @Test
+ @DisplayName("NETWORK_BYTES_SENT usage populates VM and network details")
+ public void populateNetworkBytesSentUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+ NetworkVO network = mock(NetworkVO.class);
+ Long usageId = 14L;
+ Long networkId = 24L;
+
+ when(usageRecord.getUsageType()).thenReturn(UsageTypes.NETWORK_BYTES_SENT);
+ when(usageRecord.getType()).thenReturn("UserVm");
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getNetworkId()).thenReturn(networkId);
+ when(usageRecord.getRawUsage()).thenReturn(1024D);
+ when(entityManagerMock.findByIdIncludingRemoved(VMInstanceVO.class, usageId.toString())).thenReturn(vmInstance);
+ when(entityManagerMock.findByIdIncludingRemoved(NetworkVO.class, networkId.toString())).thenReturn(network);
+ when(vmInstance.getUuid()).thenReturn("network-vm-uuid");
+ when(vmInstance.getId()).thenReturn(usageId);
+ when(vmInstance.getInstanceName()).thenReturn("r-14-VM");
+ when(network.getUuid()).thenReturn("network-uuid");
+ when(network.getId()).thenReturn(networkId);
+ when(network.getName()).thenReturn("guest-network");
+ when(network.getTrafficType()).thenReturn(Networks.TrafficType.Guest);
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateNetworkBytesUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class}, usageRecord, response, false);
+
+ // Assert
+ assertResponseField(response, "type", "UserVm");
+ assertResponseField(response, "usageId", "network-vm-uuid");
+ assertResponseField(response, "networkId", "network-uuid");
+ assertResponseField(response, "resourceName", "guest-network");
+ assertDescriptionContains(response, "Bytes sent by network guest-network (network-uuid)");
+ assertDescriptionContains(response, "using router r-14-VM (network-vm-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.Network, networkId);
+ verify(entityManagerMock).findByIdIncludingRemoved(VMInstanceVO.class, usageId.toString());
+ verify(entityManagerMock).findByIdIncludingRemoved(NetworkVO.class, networkId.toString());
+ }
+
+ @Test
+ @DisplayName("NETWORK_BYTES_RECEIVED usage populates VM and network details")
+ public void populateNetworkBytesReceivedUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+ NetworkVO network = mock(NetworkVO.class);
+ Long usageId = 15L;
+ Long networkId = 25L;
+
+ when(usageRecord.getUsageType()).thenReturn(UsageTypes.NETWORK_BYTES_RECEIVED);
+ when(usageRecord.getType()).thenReturn("DomainRouter");
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getNetworkId()).thenReturn(networkId);
+ when(usageRecord.getRawUsage()).thenReturn(2048D);
+ when(entityManagerMock.findByIdIncludingRemoved(VMInstanceVO.class, usageId.toString())).thenReturn(vmInstance);
+ when(entityManagerMock.findByIdIncludingRemoved(NetworkVO.class, networkId.toString())).thenReturn(network);
+ when(vmInstance.getUuid()).thenReturn("network-router-uuid");
+ when(vmInstance.getId()).thenReturn(usageId);
+ when(vmInstance.getInstanceName()).thenReturn("r-15-VM");
+ when(network.getUuid()).thenReturn("received-network-uuid");
+ when(network.getId()).thenReturn(networkId);
+ when(network.getName()).thenReturn("received-network");
+ when(network.getTrafficType()).thenReturn(Networks.TrafficType.Guest);
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateNetworkBytesUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class}, usageRecord, response, false);
+
+ // Assert
+ assertResponseField(response, "type", "DomainRouter");
+ assertResponseField(response, "usageId", "network-router-uuid");
+ assertResponseField(response, "networkId", "received-network-uuid");
+ assertResponseField(response, "resourceName", "received-network");
+ assertDescriptionContains(response, "Bytes received by network received-network (received-network-uuid)");
+ assertDescriptionContains(response, "using router r-15-VM (network-router-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.Network, networkId);
+ verify(entityManagerMock).findByIdIncludingRemoved(VMInstanceVO.class, usageId.toString());
+ verify(entityManagerMock).findByIdIncludingRemoved(NetworkVO.class, networkId.toString());
+ }
+
+ @Test
+ @DisplayName("VOLUME usage populates volume size and offering details")
+ public void populateVolumeUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+ VMTemplateVO template = mock(VMTemplateVO.class);
+ VolumeVO volume = mock(VolumeVO.class);
+ DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
+ Long usageId = 16L;
+ Long offeringId = 26L;
+
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getOfferingId()).thenReturn(offeringId);
+ when(usageRecord.getSize()).thenReturn(4096L);
+ when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, usageId.toString())).thenReturn(volume);
+ when(entityManagerMock.findByIdIncludingRemoved(DiskOfferingVO.class, offeringId.toString())).thenReturn(diskOffering);
+ when(volume.getUuid()).thenReturn("volume-uuid");
+ when(volume.getId()).thenReturn(usageId);
+ when(volume.getName()).thenReturn("data-volume");
+ when(diskOffering.getUuid()).thenReturn("disk-offering-uuid");
+ when(diskOffering.getName()).thenReturn("Small Disk");
+ when(vmInstance.getUuid()).thenReturn("volume-vm-uuid");
+ when(vmInstance.getHostName()).thenReturn("volume-vm");
+ when(template.getUuid()).thenReturn("volume-template-uuid");
+ when(template.getName()).thenReturn("Volume Template");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateVolumeUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class, VMTemplateVO.class},
+ usageRecord, response, false, vmInstance, template);
+
+ // Assert
+ assertResponseField(response, "usageId", "volume-uuid");
+ assertResponseField(response, "size", 4096L);
+ assertResponseField(response, "offeringId", "disk-offering-uuid");
+ assertDescriptionContains(response, "Volume usage for data-volume (volume-uuid)");
+ assertDescriptionContains(response, "attached to VM volume-vm (volume-vm-uuid)");
+ assertDescriptionContains(response, "with disk offering Small Disk (disk-offering-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.Volume, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, usageId.toString());
+ verify(entityManagerMock).findByIdIncludingRemoved(DiskOfferingVO.class, offeringId.toString());
+ }
+
+ @Test
+ @DisplayName("TEMPLATE usage populates template size details")
+ public void populateTemplateUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMTemplateVO template = mock(VMTemplateVO.class);
+ Long usageId = 17L;
+
+ when(usageRecord.getUsageType()).thenReturn(UsageTypes.TEMPLATE);
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getSize()).thenReturn(8192L);
+ when(usageRecord.getVirtualSize()).thenReturn(16384L);
+ when(entityManagerMock.findByIdIncludingRemoved(VMTemplateVO.class, usageId.toString())).thenReturn(template);
+ when(template.getUuid()).thenReturn("template-usage-uuid");
+ when(template.getId()).thenReturn(usageId);
+ when(template.getName()).thenReturn("CentOS Template");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateTemplateOrIsoUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class}, usageRecord, response, false);
+
+ // Assert
+ assertResponseField(response, "usageId", "template-usage-uuid");
+ assertResponseField(response, "size", 8192L);
+ assertResponseField(response, "virtualSize", 16384L);
+ assertDescriptionContains(response, "Template usage for CentOS Template (template-usage-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.Template, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(VMTemplateVO.class, usageId.toString());
+ }
+
+ @Test
+ @DisplayName("ISO usage populates ISO size details")
+ public void populateIsoUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMTemplateVO iso = mock(VMTemplateVO.class);
+ Long usageId = 18L;
+
+ when(usageRecord.getUsageType()).thenReturn(UsageTypes.ISO);
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getSize()).thenReturn(2048L);
+ when(usageRecord.getVirtualSize()).thenReturn(4096L);
+ when(entityManagerMock.findByIdIncludingRemoved(VMTemplateVO.class, usageId.toString())).thenReturn(iso);
+ when(iso.getUuid()).thenReturn("iso-usage-uuid");
+ when(iso.getId()).thenReturn(usageId);
+ when(iso.getName()).thenReturn("Installer ISO");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateTemplateOrIsoUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class}, usageRecord, response, false);
+
+ // Assert
+ assertResponseField(response, "usageId", "iso-usage-uuid");
+ assertResponseField(response, "size", 2048L);
+ assertResponseField(response, "virtualSize", 2048L);
+ assertDescriptionContains(response, "ISO usage for Installer ISO (iso-usage-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.ISO, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(VMTemplateVO.class, usageId.toString());
+ }
+
+ @Test
+ @DisplayName("SNAPSHOT usage populates snapshot size details")
+ public void populateSnapshotUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ SnapshotVO snapshot = mock(SnapshotVO.class);
+ Long usageId = 19L;
+
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getSize()).thenReturn(1024L);
+ when(entityManagerMock.findByIdIncludingRemoved(SnapshotVO.class, usageId.toString())).thenReturn(snapshot);
+ when(snapshot.getUuid()).thenReturn("snapshot-uuid");
+ when(snapshot.getId()).thenReturn(usageId);
+ when(snapshot.getName()).thenReturn("daily-snapshot");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateSnapshotUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class}, usageRecord, response, false);
+
+ // Assert
+ assertResponseField(response, "usageId", "snapshot-uuid");
+ assertResponseField(response, "size", 1024L);
+ assertDescriptionContains(response, "Snapshot usage for daily-snapshot (snapshot-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.Snapshot, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(SnapshotVO.class, usageId.toString());
+ }
+
+ @Test
+ @DisplayName("SECURITY_GROUP usage populates security group details")
+ public void populateSecurityGroupUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ SecurityGroupVO securityGroup = mock(SecurityGroupVO.class);
+ VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+ Long usageId = 20L;
+
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(entityManagerMock.findByIdIncludingRemoved(SecurityGroupVO.class, usageId.toString())).thenReturn(securityGroup);
+ when(securityGroup.getUuid()).thenReturn("security-group-uuid");
+ when(securityGroup.getId()).thenReturn(usageId);
+ when(securityGroup.getName()).thenReturn("web-tier");
+ when(vmInstance.getUuid()).thenReturn("security-group-vm-uuid");
+ when(vmInstance.getHostName()).thenReturn("security-group-vm");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateSecurityGroupUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class},
+ usageRecord, response, false, vmInstance);
+
+ // Assert
+ assertResponseField(response, "usageId", "security-group-uuid");
+ assertDescriptionContains(response, "Security group web-tier (security-group-uuid) usage");
+ assertDescriptionContains(response, "for VM security-group-vm (security-group-vm-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.SecurityGroup, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(SecurityGroupVO.class, usageId.toString());
+ }
+
+ @Test
+ @DisplayName("LOAD_BALANCER_POLICY usage populates load balancer details")
+ public void populateLoadBalancerPolicyUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ LoadBalancerVO loadBalancer = mock(LoadBalancerVO.class);
+ Long usageId = 21L;
+
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(entityManagerMock.findByIdIncludingRemoved(LoadBalancerVO.class, usageId.toString())).thenReturn(loadBalancer);
+ when(loadBalancer.getUuid()).thenReturn("load-balancer-uuid");
+ when(loadBalancer.getId()).thenReturn(usageId);
+ when(loadBalancer.getName()).thenReturn("public-lb");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateLoadBalancerPolicyUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class}, usageRecord, response, false);
+
+ // Assert
+ assertResponseField(response, "usageId", "load-balancer-uuid");
+ assertDescriptionContains(response, "Loadbalancer policy usage public-lb (load-balancer-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.LoadBalancer, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(LoadBalancerVO.class, usageId.toString());
+ }
+
+ @Test
+ @DisplayName("PORT_FORWARDING_RULE usage populates port forwarding rule details")
+ public void populatePortForwardingRuleUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ PortForwardingRuleVO portForwardingRule = mock(PortForwardingRuleVO.class);
+ Long usageId = 22L;
+
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(entityManagerMock.findByIdIncludingRemoved(PortForwardingRuleVO.class, usageId.toString())).thenReturn(portForwardingRule);
+ when(portForwardingRule.getUuid()).thenReturn("port-forwarding-rule-uuid");
+ when(portForwardingRule.getId()).thenReturn(usageId);
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populatePortForwardingRuleUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class}, usageRecord, response, false);
+
+ // Assert
+ assertResponseField(response, "usageId", "port-forwarding-rule-uuid");
+ assertDescriptionContains(response, "Port forwarding rule usage (port-forwarding-rule-uuid)");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.PortForwardingRule, usageId);
+ verify(entityManagerMock).findByIdIncludingRemoved(PortForwardingRuleVO.class, usageId.toString());
+ }
+
+ @Test
+ @DisplayName("NETWORK_OFFERING usage populates offering and default flag")
+ public void populateNetworkOfferingUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ NetworkOfferingVO networkOffering = mock(NetworkOfferingVO.class);
+ VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+ Long offeringId = 23L;
+
+ when(usageRecord.getOfferingId()).thenReturn(offeringId);
+ when(usageRecord.getUsageId()).thenReturn(1L);
+ when(entityManagerMock.findByIdIncludingRemoved(NetworkOfferingVO.class, offeringId.toString())).thenReturn(networkOffering);
+ when(networkOffering.getUuid()).thenReturn("network-offering-uuid");
+ when(networkOffering.getName()).thenReturn("Default Isolated Network");
+ when(vmInstance.getUuid()).thenReturn("network-offering-vm-uuid");
+ when(vmInstance.getHostName()).thenReturn("network-offering-vm");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateNetworkOfferingUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class},
+ usageRecord, response, false, vmInstance);
+
+ // Assert
+ assertResponseField(response, "offeringId", "network-offering-uuid");
+ assertResponseField(response, "isDefault", Boolean.TRUE);
+ assertDescriptionContains(response, "Network offering Default Isolated Network (network-offering-uuid) usage");
+ assertDescriptionContains(response, "for VM network-offering-vm (network-offering-vm-uuid)");
+ assertUsageResourceDetails(resourceDetails, null, null);
+ verify(entityManagerMock).findByIdIncludingRemoved(NetworkOfferingVO.class, offeringId.toString());
+ }
+
+ @Test
+ @DisplayName("VPN_USERS usage populates VPN user details")
+ public void populateVpnUsersUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mock(UsageVO.class);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VpnUserVO vpnUser = mock(VpnUserVO.class);
+ Long usageId = 24L;
+
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(entityManagerMock.findByIdIncludingRemoved(VpnUserVO.class, usageId.toString())).thenReturn(vpnUser);
+ when(vpnUser.getUuid()).thenReturn("vpn-user-uuid");
+ when(vpnUser.getUsername()).thenReturn("vpn-user");
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateVpnUsersUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class}, usageRecord, response, false);
+
+ // Assert
+ assertResponseField(response, "usageId", "vpn-user-uuid");
+ assertDescriptionContains(response, "VPN usage for user vpn-user (vpn-user-uuid)");
+ assertUsageResourceDetails(resourceDetails, null, null);
+ verify(entityManagerMock).findByIdIncludingRemoved(VpnUserVO.class, usageId.toString());
+ }
+
+ @Test
+ @DisplayName("VM_DISK_IO_READ usage populates disk read request details")
+ public void populateVmDiskIoReadUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mockVmDiskUsageRecord(UsageTypes.VM_DISK_IO_READ, 25L, 512D);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMInstanceVO vmInstance = mockVmInstance("vm-disk-read-vm", "vm-disk-read-vm-uuid");
+ VolumeVO volume = mockVolume(25L, "vm-disk-read-volume-uuid", "vm-disk-read-volume");
+ when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, "25")).thenReturn(volume);
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateVmDiskUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class},
+ usageRecord, response, false, vmInstance);
+
+ // Assert
+ assertVmDiskUsageResponse(response, resourceDetails, "Disk I/O read requests", "vm-disk-read-volume-uuid", "vm-disk-read-volume", 25L);
+ verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, "25");
+ }
+
+ @Test
+ @DisplayName("VM_DISK_IO_WRITE usage populates disk write request details")
+ public void populateVmDiskIoWriteUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mockVmDiskUsageRecord(UsageTypes.VM_DISK_IO_WRITE, 26L, 1024D);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMInstanceVO vmInstance = mockVmInstance("vm-disk-write-vm", "vm-disk-write-vm-uuid");
+ VolumeVO volume = mockVolume(26L, "vm-disk-write-volume-uuid", "vm-disk-write-volume");
+ when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, "26")).thenReturn(volume);
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateVmDiskUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class},
+ usageRecord, response, false, vmInstance);
+
+ // Assert
+ assertVmDiskUsageResponse(response, resourceDetails, "Disk I/O write requests", "vm-disk-write-volume-uuid", "vm-disk-write-volume", 26L);
+ verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, "26");
+ }
+
+ @Test
+ @DisplayName("VM_DISK_BYTES_READ usage populates disk read byte details")
+ public void populateVmDiskBytesReadUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mockVmDiskUsageRecord(UsageTypes.VM_DISK_BYTES_READ, 27L, 2048D);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMInstanceVO vmInstance = mockVmInstance("vm-disk-bytes-read-vm", "vm-disk-bytes-read-vm-uuid");
+ VolumeVO volume = mockVolume(27L, "vm-disk-bytes-read-volume-uuid", "vm-disk-bytes-read-volume");
+ when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, "27")).thenReturn(volume);
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateVmDiskUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class},
+ usageRecord, response, false, vmInstance);
+
+ // Assert
+ assertVmDiskUsageResponse(response, resourceDetails, "Disk I/O read bytes", "vm-disk-bytes-read-volume-uuid", "vm-disk-bytes-read-volume", 27L);
+ verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, "27");
+ }
+
+ @Test
+ @DisplayName("VM_DISK_BYTES_WRITE usage populates disk write byte details")
+ public void populateVmDiskBytesWriteUsageResponseTest() throws Exception {
+ // Arrange
+ UsageVO usageRecord = mockVmDiskUsageRecord(UsageTypes.VM_DISK_BYTES_WRITE, 28L, 4096D);
+ UsageRecordResponse response = new UsageRecordResponse();
+ VMInstanceVO vmInstance = mockVmInstance("vm-disk-bytes-write-vm", "vm-disk-bytes-write-vm-uuid");
+ VolumeVO volume = mockVolume(28L, "vm-disk-bytes-write-volume-uuid", "vm-disk-bytes-write-volume");
+ when(entityManagerMock.findByIdIncludingRemoved(VolumeVO.class, "28")).thenReturn(volume);
+
+ // Act
+ Object resourceDetails = invokeUsageDetailsHelper("populateVmDiskUsageResponse",
+ new Class>[] {Usage.class, UsageRecordResponse.class, boolean.class, VMInstanceVO.class},
+ usageRecord, response, false, vmInstance);
+
+ // Assert
+ assertVmDiskUsageResponse(response, resourceDetails, "Disk I/O write bytes", "vm-disk-bytes-write-volume-uuid", "vm-disk-bytes-write-volume", 28L);
+ verify(entityManagerMock).findByIdIncludingRemoved(VolumeVO.class, "28");
+ }
+
+ private Object invokeUsageDetailsHelper(String methodName, Class>[] parameterTypes, Object... args) throws Exception {
+ Method method = ApiResponseHelper.class.getDeclaredMethod(methodName, parameterTypes);
+ method.setAccessible(true);
+ return method.invoke(helper, args);
+ }
+
+ private void assertResponseField(UsageRecordResponse response, String fieldName, Object expectedValue) {
+ assertEquals(expectedValue, ReflectionTestUtils.getField(response, fieldName));
+ }
+
+ private void assertDescriptionContains(UsageRecordResponse response, String expectedText) {
+ Object description = ReflectionTestUtils.getField(response, "description");
+ Assertions.assertNotNull(description);
+ assertTrue(description.toString().contains(expectedText),
+ String.format("Expected description [%s] to contain [%s]", description, expectedText));
+ }
+
+ private void assertUsageResourceDetails(Object resourceDetails, ResourceTag.ResourceObjectType expectedResourceType, Long expectedResourceId) {
+ assertEquals(expectedResourceType, ReflectionTestUtils.getField(resourceDetails, "resourceType"));
+ assertEquals(expectedResourceId, ReflectionTestUtils.getField(resourceDetails, "resourceId"));
+ }
+
+ private UsageVO mockVmDiskUsageRecord(int usageType, Long usageId, Double rawUsage) {
+ UsageVO usageRecord = mock(UsageVO.class);
+ when(usageRecord.getUsageType()).thenReturn(usageType);
+ when(usageRecord.getUsageId()).thenReturn(usageId);
+ when(usageRecord.getType()).thenReturn("UserVm");
+ when(usageRecord.getRawUsage()).thenReturn(rawUsage);
+ return usageRecord;
+ }
+
+ private VMInstanceVO mockVmInstance(String hostName, String uuid) {
+ VMInstanceVO vmInstance = mock(VMInstanceVO.class);
+ when(vmInstance.getHostName()).thenReturn(hostName);
+ when(vmInstance.getUuid()).thenReturn(uuid);
+ return vmInstance;
+ }
+
+ private VolumeVO mockVolume(Long id, String uuid, String name) {
+ VolumeVO volume = mock(VolumeVO.class);
+ when(volume.getId()).thenReturn(id);
+ when(volume.getUuid()).thenReturn(uuid);
+ when(volume.getName()).thenReturn(name);
+ return volume;
+ }
+
+ private void assertVmDiskUsageResponse(UsageRecordResponse response, Object resourceDetails, String descriptionPrefix, String volumeUuid, String volumeName, Long volumeId) {
+ assertResponseField(response, "type", "UserVm");
+ assertResponseField(response, "usageId", volumeUuid);
+ assertDescriptionContains(response, descriptionPrefix);
+ assertDescriptionContains(response, "volume " + volumeName + " (" + volumeUuid + ")");
+ assertUsageResourceDetails(resourceDetails, ResourceTag.ResourceObjectType.Volume, volumeId);
+ }
}