From eb46332fe0ec0640e0f19d89e4a92f3485126b96 Mon Sep 17 00:00:00 2001
From: Pierre Charton
Date: Fri, 20 Dec 2024 17:40:06 +0100
Subject: [PATCH] UT + refactoring to test
---
.../backup/BackrollBackupProvider.java | 4 +-
.../utils/BackrollHttpClientProvider.java | 22 +--
.../backup/BackrollBackupProviderTest.java | 16 +-
.../utils/BackrollHttpClientProviderTest.java | 153 ++++++++++++++++++
4 files changed, 180 insertions(+), 15 deletions(-)
create mode 100644 plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/backroll/utils/BackrollHttpClientProviderTest.java
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java
index 0386bd437c7..6a112895a77 100644
--- a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java
@@ -377,11 +377,11 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
throw new CloudRuntimeException("You can't delete a backup while it still BackingUp");
} else {
logger.debug("backroll - try delete backup");
- VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(backup.getVmId());
if (backup.getStatus().equals(Backup.Status.Removed) || backup.getStatus().equals(Backup.Status.Failed)){
return deleteBackupInDb(backup);
} else {
+ VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(backup.getVmId());
try {
if (getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup))) {
logger.debug("Backup deletion for backup {} complete on backroll side.", backup.getUuid());
@@ -411,7 +411,7 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
try {
if (backrollClient == null) {
logger.debug("backroll client null - instantiation of new one ");
- BackrollHttpClientProvider provider = new BackrollHttpClientProvider(BackrollUrlConfigKey.valueIn(zoneId), BackrollAppNameConfigKey.valueIn(zoneId), BackrollPasswordConfigKey.valueIn(zoneId), true, 300, 600);
+ BackrollHttpClientProvider provider = BackrollHttpClientProvider.createProvider(new BackrollHttpClientProvider(), BackrollUrlConfigKey.valueIn(zoneId), BackrollAppNameConfigKey.valueIn(zoneId), BackrollPasswordConfigKey.valueIn(zoneId), true, 300, 600);
backrollClient = new BackrollClient(provider);
}
return backrollClient;
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/utils/BackrollHttpClientProvider.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/utils/BackrollHttpClientProvider.java
index 401d0454f02..852f281ce34 100644
--- a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/utils/BackrollHttpClientProvider.java
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/utils/BackrollHttpClientProvider.java
@@ -60,7 +60,7 @@ import com.cloud.utils.nio.TrustAllManager;
import com.fasterxml.jackson.databind.ObjectMapper;
public class BackrollHttpClientProvider {
- private final URI apiURI;
+ private URI apiURI;;
private String backrollToken = null;
private String appname = null;
private String password = null;
@@ -69,23 +69,25 @@ public class BackrollHttpClientProvider {
private Logger logger = LogManager.getLogger(BackrollClient.class);
- public BackrollHttpClientProvider(final String url, final String appname, final String password,
+ public static BackrollHttpClientProvider createProvider(BackrollHttpClientProvider backrollHttpClientProvider, final String url, final String appname, final String password,
final boolean validateCertificate, final int timeout,
- final int restoreTimeout)
- throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException {
- this.apiURI = new URI(url);
- this.appname = appname;
- this.password = password;
- this.validateCertificate = validateCertificate;
+ final int restoreTimeout) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException {
- this.config = RequestConfig.custom()
+ backrollHttpClientProvider.apiURI = new URI(url);
+ backrollHttpClientProvider.appname = appname;
+ backrollHttpClientProvider.password = password;
+ backrollHttpClientProvider.validateCertificate = validateCertificate;
+
+ backrollHttpClientProvider.config = RequestConfig.custom()
.setConnectTimeout(timeout * 1000)
.setConnectionRequestTimeout(timeout * 1000)
.setSocketTimeout(timeout * 1000)
.build();
+
+ return backrollHttpClientProvider;
}
- private CloseableHttpClient createHttpClient() throws BackrollApiException {
+ protected CloseableHttpClient createHttpClient() throws BackrollApiException {
if(!validateCertificate) {
SSLContext sslContext;
try {
diff --git a/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java b/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java
index 7e6177185d7..5b66ac5a4f8 100644
--- a/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java
+++ b/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java
@@ -50,9 +50,8 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.VirtualMachine;
-
-
import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
public class BackrollBackupProviderTest {
@Mock
@@ -68,6 +67,15 @@ public class BackrollBackupProviderTest {
@Mock
VMInstanceDao vmInstanceDao;
+ @Mock
+ private ConfigKey BackrollUrlConfigKey;
+
+ @Mock
+ private ConfigKey BackrollAppNameConfigKey;
+
+ @Mock
+ private ConfigKey BackrollPasswordConfigKey;
+
@Mock
BackupDao backupDao;
@@ -76,8 +84,10 @@ public class BackrollBackupProviderTest {
vmInstanceDao = mock(VMInstanceDao.class);
clientMock = mock(BackrollClient.class);
backupDao = mock(BackupDao.class);
- backupProviderMock = mock(BackrollBackupProvider.class);
backupProvider = new BackrollBackupProvider(backupDao, vmInstanceDao, clientMock, Mockito.mock(Logger.class));
+ backupProvider.BackrollAppNameConfigKey = BackrollAppNameConfigKey;
+ backupProvider.BackrollPasswordConfigKey = BackrollPasswordConfigKey;
+ backupProvider.BackrollUrlConfigKey = BackrollUrlConfigKey;
}
@Test
diff --git a/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/backroll/utils/BackrollHttpClientProviderTest.java b/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/backroll/utils/BackrollHttpClientProviderTest.java
new file mode 100644
index 00000000000..cfdf05d7577
--- /dev/null
+++ b/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/backroll/utils/BackrollHttpClientProviderTest.java
@@ -0,0 +1,153 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.backup.backroll.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.http.HttpResponse;
+
+import org.apache.cloudstack.backup.BackrollBackupProvider;
+import org.apache.cloudstack.backup.backroll.BackrollClient;
+import org.apache.cloudstack.backup.backroll.model.response.api.LoginApiResponse;
+import org.apache.cloudstack.backup.backroll.model.response.metrics.virtualMachineBackups.VirtualMachineBackupsResponse;
+import org.apache.cloudstack.backup.backroll.utils.BackrollHttpClientProvider.NotOkBodyException;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpStatus;
+import org.apache.http.ParseException;
+import org.apache.http.StatusLine;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.logging.log4j.Logger;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class BackrollHttpClientProviderTest {
+ @Spy
+ @InjectMocks
+ BackrollHttpClientProvider backupHttpClientProvider;
+
+ @Mock
+ private CloseableHttpClient httpClient;
+
+ @Mock
+ private CloseableHttpResponse response;
+
+ @Before
+ public void setUp() throws Exception {
+ Long zoneId = 2L;
+ MockitoAnnotations.openMocks(this);
+ backupHttpClientProvider = BackrollHttpClientProvider.createProvider(backupHttpClientProvider,
+ "http://api.backup.demo.ccc:5050/api/v1", "backroll-api", "VviX8dALauSyYJMqVYJqf3UyZOpO3joS", false,
+ 300, 600);
+ }
+
+ private void defaultTestHttpClient(String path) throws BackrollApiException, ClientProtocolException, IOException, NotOkBodyException {
+
+ LoginApiResponse responseLogin = new LoginApiResponse();
+ responseLogin.accessToken = "dummyToken";
+ responseLogin.expiresIn = 3600;
+ responseLogin.notBeforePolicy = "dummyNotBeforePolicy";
+ responseLogin.refreshExpiresIn = "7200";
+ responseLogin.scope = "dummyScope";
+
+ String virtualMachineResponseString = "{ \"state\": \"SUCCESS\", \"info\": { \"archives\": [ { \"archive\": \"ROOT-00000\", \"barchive\": \"ROOT-00000\", \"id\": \"25d55ad283aa400af464c76d713c07ad7d163abdd3b8fbcdbdc46b827e5e0457\", \"name\": \"ROOT-00000\", \"start\": \"2024-11-08T18:24:48.000000\", \"time\": \"2024-11-08T18:24:48.000000\" } ], \"encryption\": { \"mode\": \"none\" }, \"repository\": { \"id\": \"36a11ebc0775a097c927735cc7015d19be7309be69fc15b896c5b1fd87fcbd79\", \"last_modified\": \"2024-11-29T09:53:09.000000\", \"location\": \"/mnt/backup/backup1\" } } }";
+
+ CloseableHttpResponse response2 = mock(CloseableHttpResponse.class);
+
+ StatusLine statusLine = mock(StatusLine.class);
+
+ doReturn(httpClient).when(backupHttpClientProvider).createHttpClient();
+
+ doReturn(response).when(httpClient)
+ .execute(argThat(argument -> argument != null && argument.getURI().toString().contains("login")));
+
+ doReturn(response2).when(httpClient)
+ .execute(argThat(argument -> argument != null && argument.getURI().toString().contains(path)));
+
+ doReturn(new ObjectMapper().writeValueAsString(responseLogin)).when(backupHttpClientProvider).okBody(response);
+ doReturn(virtualMachineResponseString).when(backupHttpClientProvider).okBody(response2);
+
+ doReturn(statusLine).when(response).getStatusLine();
+ doReturn(HttpStatus.SC_OK).when(statusLine).getStatusCode();
+
+ doNothing().when(response).close();
+
+ doReturn(new StringEntity("{\"mockKey\": \"mockValue\"}", ContentType.APPLICATION_JSON)).when(response).getEntity();
+ }
+
+ @Test
+ public void testGet_success() throws Exception, BackrollApiException, IOException {
+ // Arrange
+ String path = "/test";
+ defaultTestHttpClient(path);
+
+ // Act
+ VirtualMachineBackupsResponse result = backupHttpClientProvider.get(path,
+ VirtualMachineBackupsResponse.class);
+
+ // Assert
+ assertNotNull(result);
+ verify(backupHttpClientProvider, times(2)).okBody(Mockito.any(CloseableHttpResponse.class));
+ verify(httpClient, times(1)).execute(Mockito.any(HttpPost.class));
+ verify(httpClient, times(1)).execute(Mockito.any(HttpGet.class));
+ verify(response, times(1)).close();
+ }
+
+ @Test
+ public void testPost_success() throws Exception, BackrollApiException, IOException {
+ // Arrange
+ String path = "/test";
+ JSONObject json = new JSONObject();
+
+ defaultTestHttpClient(path);
+ // Act
+ VirtualMachineBackupsResponse result = backupHttpClientProvider.post(path, json,
+ VirtualMachineBackupsResponse.class);
+
+ // Assert
+ assertNotNull(result);
+ verify(backupHttpClientProvider, times(2)).okBody(Mockito.any(CloseableHttpResponse.class));
+ verify(httpClient, times(2)).execute(Mockito.any(HttpPost.class));
+ verify(response, times(1)).close();
+ }
+
+}