Skip to content

Commit ec65be7

Browse files
committed
add more unit test coverage
1 parent 5ff6419 commit ec65be7

File tree

2 files changed

+308
-4
lines changed

2 files changed

+308
-4
lines changed

src/main/java/com/datastax/cdm/data/AstraDevOpsClient.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,7 @@ private String extractDownloadUrl(String jsonResponse, String scbType, PKFactory
284284

285285
if (rootNode.has("customDomainBundles") && rootNode.get("customDomainBundles").isArray()) {
286286
for (JsonNode customNode : rootNode.get("customDomainBundles")) {
287-
if (customNode.has("sniDomain")
288-
&& customDomain.equalsIgnoreCase(customNode.get("sniDomain").asText())
287+
if (customNode.has("domain") && customDomain.equalsIgnoreCase(customNode.get("domain").asText())
289288
&& customNode.has("downloadURL")) {
290289

291290
return customNode.get("downloadURL").asText();

src/test/java/com/datastax/cdm/data/AstraDevOpsClientTest.java

Lines changed: 307 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,23 @@
1616
package com.datastax.cdm.data;
1717

1818
import static org.junit.jupiter.api.Assertions.*;
19+
import static org.mockito.ArgumentMatchers.*;
1920
import static org.mockito.Mockito.*;
2021

22+
import java.io.ByteArrayInputStream;
2123
import java.io.IOException;
24+
import java.io.InputStream;
2225
import java.lang.reflect.Field;
2326
import java.lang.reflect.Method;
27+
import java.net.URI;
2428
import java.net.http.HttpClient;
29+
import java.net.http.HttpRequest;
2530
import java.net.http.HttpResponse;
2631

2732
import org.junit.jupiter.api.BeforeEach;
2833
import org.junit.jupiter.api.Test;
2934
import org.junit.jupiter.api.extension.ExtendWith;
35+
import org.mockito.ArgumentCaptor;
3036
import org.mockito.Mock;
3137
import org.mockito.junit.jupiter.MockitoExtension;
3238

@@ -46,6 +52,9 @@ class AstraDevOpsClientTest {
4652
@Mock
4753
private HttpResponse<String> httpResponse;
4854

55+
@Mock
56+
private HttpResponse<InputStream> httpResponseStream;
57+
4958
private AstraDevOpsClient client;
5059

5160
@BeforeEach
@@ -197,5 +206,301 @@ void testExtractDownloadUrlDefaultType() throws Exception {
197206
assertEquals("https://example.com/bundle.zip", url);
198207
}
199208

200-
// More tests for extractDownloadUrl with different SCB types can be added here
201-
}
209+
@Test
210+
void testExtractDownloadUrlRegionType() throws Exception {
211+
// Setup
212+
String jsonResponse = "{ \"downloadURLs\": ["
213+
+ "{ \"region\": \"us-east-1\", \"downloadURL\": \"https://us-east-1.example.com/bundle.zip\" },"
214+
+ "{ \"region\": \"us-west-2\", \"downloadURL\": \"https://us-west-2.example.com/bundle.zip\" },"
215+
+ "{ \"region\": \"eu-central-1\", \"downloadURL\": \"https://eu-central-1.example.com/bundle.zip\" }"
216+
+ "]}";
217+
218+
when(propertyHelper.getAsString(KnownProperties.ORIGIN_ASTRA_SCB_REGION)).thenReturn("us-west-2");
219+
220+
// Use reflection to access the private method
221+
Method extractDownloadUrlMethod = AstraDevOpsClient.class.getDeclaredMethod("extractDownloadUrl", String.class,
222+
String.class, PKFactory.Side.class);
223+
extractDownloadUrlMethod.setAccessible(true);
224+
225+
// Test
226+
String url = (String) extractDownloadUrlMethod.invoke(client, jsonResponse, "region", PKFactory.Side.ORIGIN);
227+
228+
// Verify
229+
assertEquals("https://us-west-2.example.com/bundle.zip", url);
230+
}
231+
232+
@Test
233+
void testExtractDownloadUrlRegionTypeWithMissingRegion() throws Exception {
234+
// Setup
235+
String jsonResponse = "{ \"downloadURLs\": ["
236+
+ "{ \"region\": \"us-east-1\", \"downloadURL\": \"https://us-east-1.example.com/bundle.zip\" },"
237+
+ "{ \"region\": \"us-west-2\", \"downloadURL\": \"https://us-west-2.example.com/bundle.zip\" }" + "]}";
238+
239+
when(propertyHelper.getAsString(KnownProperties.ORIGIN_ASTRA_SCB_REGION)).thenReturn(null);
240+
241+
// Use reflection to access the private method
242+
Method extractDownloadUrlMethod = AstraDevOpsClient.class.getDeclaredMethod("extractDownloadUrl", String.class,
243+
String.class, PKFactory.Side.class);
244+
extractDownloadUrlMethod.setAccessible(true);
245+
246+
// Test
247+
String url = (String) extractDownloadUrlMethod.invoke(client, jsonResponse, "region", PKFactory.Side.ORIGIN);
248+
249+
// Verify
250+
assertNull(url);
251+
}
252+
253+
@Test
254+
void testExtractDownloadUrlRegionTypeWithNoMatchingRegion() throws Exception {
255+
// Setup
256+
String jsonResponse = "{ \"downloadURLs\": ["
257+
+ "{ \"region\": \"us-east-1\", \"downloadURL\": \"https://us-east-1.example.com/bundle.zip\" },"
258+
+ "{ \"region\": \"us-west-2\", \"downloadURL\": \"https://us-west-2.example.com/bundle.zip\" }" + "]}";
259+
260+
when(propertyHelper.getAsString(KnownProperties.ORIGIN_ASTRA_SCB_REGION)).thenReturn("ap-south-1");
261+
262+
// Use reflection to access the private method
263+
Method extractDownloadUrlMethod = AstraDevOpsClient.class.getDeclaredMethod("extractDownloadUrl", String.class,
264+
String.class, PKFactory.Side.class);
265+
extractDownloadUrlMethod.setAccessible(true);
266+
267+
// Test
268+
String url = (String) extractDownloadUrlMethod.invoke(client, jsonResponse, "region", PKFactory.Side.ORIGIN);
269+
270+
// Verify
271+
assertNull(url);
272+
}
273+
274+
@Test
275+
void testExtractDownloadUrlCustomDomainType() throws Exception {
276+
// Setup
277+
String jsonResponse = "{ \"customDomainBundles\": ["
278+
+ "{ \"domain\": \"db1.example.com\", \"downloadURL\": \"https://db1.example.com/bundle.zip\" },"
279+
+ "{ \"domain\": \"db2.example.com\", \"downloadURL\": \"https://db2.example.com/bundle.zip\" }" + "]}";
280+
281+
when(propertyHelper.getAsString(KnownProperties.TARGET_ASTRA_SCB_CUSTOM_DOMAIN)).thenReturn("db2.example.com");
282+
283+
// Use reflection to access the private method
284+
Method extractDownloadUrlMethod = AstraDevOpsClient.class.getDeclaredMethod("extractDownloadUrl", String.class,
285+
String.class, PKFactory.Side.class);
286+
extractDownloadUrlMethod.setAccessible(true);
287+
288+
// Test
289+
String url = (String) extractDownloadUrlMethod.invoke(client, jsonResponse, "custom", PKFactory.Side.TARGET);
290+
291+
// Verify
292+
assertEquals("https://db2.example.com/bundle.zip", url);
293+
}
294+
295+
@Test
296+
void testExtractDownloadUrlCustomDomainTypeWithMissingDomain() throws Exception {
297+
// Setup
298+
String jsonResponse = "{ \"customDomainBundles\": ["
299+
+ "{ \"domain\": \"db1.example.com\", \"downloadURL\": \"https://db1.example.com/bundle.zip\" },"
300+
+ "{ \"domain\": \"db2.example.com\", \"downloadURL\": \"https://db2.example.com/bundle.zip\" }" + "]}";
301+
302+
when(propertyHelper.getAsString(KnownProperties.TARGET_ASTRA_SCB_CUSTOM_DOMAIN)).thenReturn(null);
303+
304+
// Use reflection to access the private method
305+
Method extractDownloadUrlMethod = AstraDevOpsClient.class.getDeclaredMethod("extractDownloadUrl", String.class,
306+
String.class, PKFactory.Side.class);
307+
extractDownloadUrlMethod.setAccessible(true);
308+
309+
// Test
310+
String url = (String) extractDownloadUrlMethod.invoke(client, jsonResponse, "custom", PKFactory.Side.TARGET);
311+
312+
// Verify
313+
assertNull(url);
314+
}
315+
316+
@Test
317+
void testExtractDownloadUrlUnknownType() throws Exception {
318+
// Setup
319+
String jsonResponse = "{ \"downloadURL\": \"https://example.com/bundle.zip\" }";
320+
321+
// Use reflection to access the private method
322+
Method extractDownloadUrlMethod = AstraDevOpsClient.class.getDeclaredMethod("extractDownloadUrl", String.class,
323+
String.class, PKFactory.Side.class);
324+
extractDownloadUrlMethod.setAccessible(true);
325+
326+
// Test
327+
String url = (String) extractDownloadUrlMethod.invoke(client, jsonResponse, "unknown", PKFactory.Side.ORIGIN);
328+
329+
// Verify
330+
assertNull(url);
331+
}
332+
333+
@Test
334+
void testFetchSecureBundleUrlInfo() throws Exception {
335+
// Mock the HTTP response
336+
when(httpResponse.statusCode()).thenReturn(200);
337+
when(httpResponse.body()).thenReturn("{ \"downloadURL\": \"https://example.com/bundle.zip\" }");
338+
339+
// Mock the HTTP client to return our mocked response
340+
when(httpClient.send(any(), eq(HttpResponse.BodyHandlers.ofString()))).thenReturn(httpResponse);
341+
342+
// Use reflection to access the private method
343+
Method fetchSecureBundleUrlInfoMethod = AstraDevOpsClient.class.getDeclaredMethod(
344+
"fetchSecureBundleUrlInfo", String.class, String.class, boolean.class);
345+
fetchSecureBundleUrlInfoMethod.setAccessible(true);
346+
347+
// Test
348+
String jsonResponse = (String) fetchSecureBundleUrlInfoMethod.invoke(client, "test-token", "test-db-id", false);
349+
350+
// Verify
351+
assertEquals("{ \"downloadURL\": \"https://example.com/bundle.zip\" }", jsonResponse);
352+
353+
// Verify the correct URL was used
354+
ArgumentCaptor<HttpRequest> requestCaptor = ArgumentCaptor.forClass(HttpRequest.class);
355+
verify(httpClient).send(requestCaptor.capture(), eq(HttpResponse.BodyHandlers.ofString()));
356+
357+
HttpRequest capturedRequest = requestCaptor.getValue();
358+
assertEquals(URI.create("https://api.astra.datastax.com/v2/databases/test-db-id/secureBundleURL"),
359+
capturedRequest.uri());
360+
assertTrue(capturedRequest.headers().firstValue("Authorization").isPresent());
361+
assertEquals("Bearer test-token", capturedRequest.headers().firstValue("Authorization").get());
362+
}
363+
364+
@Test
365+
void testFetchSecureBundleUrlInfoWithRegionalFlag() throws Exception {
366+
// Mock the HTTP response
367+
when(httpResponse.statusCode()).thenReturn(200);
368+
when(httpResponse.body()).thenReturn("{ \"downloadURLs\": [] }");
369+
370+
// Mock the HTTP client to return our mocked response
371+
when(httpClient.send(any(), eq(HttpResponse.BodyHandlers.ofString()))).thenReturn(httpResponse);
372+
373+
// Use reflection to access the private method
374+
Method fetchSecureBundleUrlInfoMethod = AstraDevOpsClient.class.getDeclaredMethod(
375+
"fetchSecureBundleUrlInfo", String.class, String.class, boolean.class);
376+
fetchSecureBundleUrlInfoMethod.setAccessible(true);
377+
378+
// Test
379+
String jsonResponse = (String) fetchSecureBundleUrlInfoMethod.invoke(client, "test-token", "test-db-id", true);
380+
381+
// Verify
382+
assertEquals("{ \"downloadURLs\": [] }", jsonResponse);
383+
384+
// Verify the correct URL was used with all=true parameter
385+
ArgumentCaptor<HttpRequest> requestCaptor = ArgumentCaptor.forClass(HttpRequest.class);
386+
verify(httpClient).send(requestCaptor.capture(), eq(HttpResponse.BodyHandlers.ofString()));
387+
388+
HttpRequest capturedRequest = requestCaptor.getValue();
389+
assertEquals(URI.create("https://api.astra.datastax.com/v2/databases/test-db-id/secureBundleURL?all=true"),
390+
capturedRequest.uri());
391+
}
392+
393+
@Test
394+
void testFetchSecureBundleUrlInfoError() throws Exception {
395+
// Mock the HTTP response for an error
396+
when(httpResponse.statusCode()).thenReturn(401);
397+
when(httpResponse.body()).thenReturn("{ \"error\": \"Unauthorized\" }");
398+
399+
// Mock the HTTP client to return our mocked response
400+
when(httpClient.send(any(), eq(HttpResponse.BodyHandlers.ofString()))).thenReturn(httpResponse);
401+
402+
// Use reflection to access the private method
403+
Method fetchSecureBundleUrlInfoMethod = AstraDevOpsClient.class.getDeclaredMethod(
404+
"fetchSecureBundleUrlInfo", String.class, String.class, boolean.class);
405+
fetchSecureBundleUrlInfoMethod.setAccessible(true);
406+
407+
// Test
408+
String jsonResponse = (String) fetchSecureBundleUrlInfoMethod.invoke(client, "invalid-token", "test-db-id", false);
409+
410+
// Verify
411+
assertNull(jsonResponse);
412+
}
413+
414+
@Test
415+
void testDownloadBundleFile() throws Exception {
416+
// Setup
417+
byte[] mockData = new byte[100]; // Mock some binary data
418+
ByteArrayInputStream inputStream = new ByteArrayInputStream(mockData);
419+
420+
// Mock the HTTP response
421+
when(httpResponseStream.statusCode()).thenReturn(200);
422+
when(httpResponseStream.body()).thenReturn(inputStream);
423+
424+
// Mock the HTTP client to return our mocked response
425+
when(httpClient.send(any(), eq(HttpResponse.BodyHandlers.ofInputStream()))).thenReturn(httpResponseStream);
426+
427+
// Use reflection to access the private method
428+
Method downloadBundleFileMethod = AstraDevOpsClient.class.getDeclaredMethod("downloadBundleFile", String.class,
429+
PKFactory.Side.class);
430+
downloadBundleFileMethod.setAccessible(true);
431+
432+
// Test
433+
String filePath = (String) downloadBundleFileMethod.invoke(client, "https://example.com/bundle.zip",
434+
PKFactory.Side.ORIGIN);
435+
436+
// Verify
437+
assertNotNull(filePath);
438+
assertTrue(filePath.contains("origin-secure-bundle.zip"));
439+
440+
// Verify the correct URL was used
441+
ArgumentCaptor<HttpRequest> requestCaptor = ArgumentCaptor.forClass(HttpRequest.class);
442+
verify(httpClient).send(requestCaptor.capture(), eq(HttpResponse.BodyHandlers.ofInputStream()));
443+
444+
HttpRequest capturedRequest = requestCaptor.getValue();
445+
assertEquals(URI.create("https://example.com/bundle.zip"), capturedRequest.uri());
446+
}
447+
448+
@Test
449+
void testDownloadBundleFileHttpError() throws Exception {
450+
// Setup
451+
452+
// Mock the HTTP response with an error status
453+
when(httpResponseStream.statusCode()).thenReturn(404);
454+
455+
// Mock the HTTP client to return our mocked response
456+
when(httpClient.send(any(), eq(HttpResponse.BodyHandlers.ofInputStream()))).thenReturn(httpResponseStream);
457+
458+
// Use reflection to access the private method
459+
Method downloadBundleFileMethod = AstraDevOpsClient.class.getDeclaredMethod(
460+
"downloadBundleFile", String.class, PKFactory.Side.class);
461+
downloadBundleFileMethod.setAccessible(true);
462+
463+
try {
464+
downloadBundleFileMethod.invoke(client, "https://example.com/not-found.zip", PKFactory.Side.ORIGIN);
465+
fail("Expected an exception to be thrown");
466+
} catch (java.lang.reflect.InvocationTargetException e) {
467+
// Extract the actual exception that was wrapped
468+
assertTrue(e.getCause() instanceof IOException);
469+
assertEquals("Failed to download secure bundle. Status code: 404", e.getCause().getMessage());
470+
}
471+
}
472+
473+
@Test
474+
void testDownloadSecureBundleSuccess() throws Exception {
475+
// Setup - mock all the components for a successful download
476+
477+
// Step 1: Mock the API response for fetching the SCB URL
478+
when(httpResponse.statusCode()).thenReturn(200);
479+
when(httpResponse.body()).thenReturn("{ \"downloadURL\": \"https://example.com/bundle.zip\" }");
480+
481+
// Step 2: Mock the binary download
482+
byte[] mockData = new byte[100]; // Mock some binary data
483+
ByteArrayInputStream inputStream = new ByteArrayInputStream(mockData);
484+
485+
// Mock the HTTP response
486+
when(httpResponseStream.statusCode()).thenReturn(200);
487+
when(httpResponseStream.body()).thenReturn(inputStream);
488+
489+
// Configure the HTTP client to return responses based on different handler types
490+
// We need to use doReturn().when() syntax here to avoid NullPointerException in the matcher
491+
doReturn(httpResponse).when(httpClient).send(any(), eq(HttpResponse.BodyHandlers.ofString()));
492+
doReturn(httpResponseStream).when(httpClient).send(any(), eq(HttpResponse.BodyHandlers.ofInputStream()));
493+
494+
// Mock the property helper
495+
when(propertyHelper.getAsString(KnownProperties.ORIGIN_ASTRA_TOKEN)).thenReturn("test-token");
496+
when(propertyHelper.getAsString(KnownProperties.ORIGIN_ASTRA_DATABASE_ID)).thenReturn("test-db-id");
497+
when(propertyHelper.getAsString(KnownProperties.ORIGIN_ASTRA_SCB_TYPE)).thenReturn("default");
498+
499+
// Test
500+
String filePath = client.downloadSecureBundle(PKFactory.Side.ORIGIN);
501+
502+
// Verify
503+
assertNotNull(filePath);
504+
assertTrue(filePath.contains("origin-secure-bundle.zip"));
505+
}
506+
}

0 commit comments

Comments
 (0)