diff --git a/pom.xml b/pom.xml index 832fd901..a0b073ff 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.skyflow skyflow-java - 2.0.0-beta.2 + 2.0.0-beta.2-dev.cc7223a jar ${project.groupId}:${project.artifactId} diff --git a/src/main/java/com/skyflow/errors/SkyflowException.java b/src/main/java/com/skyflow/errors/SkyflowException.java index 32c71f39..868b6609 100644 --- a/src/main/java/com/skyflow/errors/SkyflowException.java +++ b/src/main/java/com/skyflow/errors/SkyflowException.java @@ -75,17 +75,20 @@ private void setRequestId(Map> responseHeaders) { } private void setMessage() { - JsonElement messageElement = ((JsonObject) responseBody.get("error")).get("message"); + JsonObject errorObj = ((JsonObject) responseBody.get("error")); + JsonElement messageElement = errorObj.has("message") ? errorObj.get("message") : null; this.message = messageElement == null ? null : messageElement.getAsString(); } private void setGrpcCode() { - JsonElement grpcElement = ((JsonObject) responseBody.get("error")).get("grpc_code"); + JsonObject errorObj = ((JsonObject) responseBody.get("error")); + JsonElement grpcElement = errorObj.has("grpc_code") ? errorObj.get("grpc_code") : errorObj.has("grpcCode") ? errorObj.get("grpcCode") : null; this.grpcCode = grpcElement == null ? null : grpcElement.getAsInt(); } private void setHttpStatus() { - JsonElement statusElement = ((JsonObject) responseBody.get("error")).get("http_status"); + JsonObject errorObj = ((JsonObject) responseBody.get("error")); + JsonElement statusElement = errorObj.has("http_status") ? errorObj.get("http_status") : errorObj.has("httpStatus") ? errorObj.get("httpStatus") : null; this.httpStatus = statusElement == null ? null : statusElement.getAsString(); } @@ -98,11 +101,38 @@ public JsonArray getDetails() { } private void setDetails(Map> responseHeaders) { - JsonElement detailsElement = ((JsonObject) responseBody.get("error")).get("details"); + JsonObject errorObj = ((JsonObject) responseBody.get("error")); + JsonElement detailsElement = errorObj.has("details") ? errorObj.get("details") : null; List errorFromClientHeader = responseHeaders.get(Constants.ERROR_FROM_CLIENT_HEADER_KEY); + if (detailsElement != null) { - this.details = detailsElement.getAsJsonArray(); + if (detailsElement.isJsonArray()) { + this.details = detailsElement.getAsJsonArray(); + if (this.details.isEmpty()) this.details = new JsonArray(); + } else if (detailsElement.isJsonObject()) { + JsonObject obj = detailsElement.getAsJsonObject(); + boolean allEmpty = true; + for (String key : obj.keySet()) { + if (obj.get(key).isJsonArray() && !obj.get(key).getAsJsonArray().isEmpty()) { + allEmpty = false; + break; + } else if (!obj.get(key).isJsonArray() && !obj.get(key).isJsonNull()) { + allEmpty = false; + break; + } + } + if (obj.isEmpty() || allEmpty) { + this.details = new JsonArray(); + } else { + JsonArray arr = new JsonArray(); + arr.add(obj); + this.details = arr; + } + } + } else { + this.details = new JsonArray(); } + if (errorFromClientHeader != null) { this.details = this.details == null ? new JsonArray() : this.details; String errorFromClient = errorFromClientHeader.get(0); diff --git a/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokenResponse.java b/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokenResponse.java index 7c9f4674..5a92603c 100644 --- a/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokenResponse.java +++ b/src/main/java/com/skyflow/serviceaccount/util/SignedDataTokenResponse.java @@ -23,7 +23,7 @@ public String getSignedToken() { @Override public String toString() { - Gson gson = new Gson(); + Gson gson = new Gson().newBuilder().serializeNulls().create(); return gson.toJson(this); } } diff --git a/src/main/java/com/skyflow/utils/Constants.java b/src/main/java/com/skyflow/utils/Constants.java index b9264a22..f12e6a48 100644 --- a/src/main/java/com/skyflow/utils/Constants.java +++ b/src/main/java/com/skyflow/utils/Constants.java @@ -26,6 +26,6 @@ public final class Constants { public static final String SDK_METRICS_HEADER_KEY = "sky-metadata"; public static final String REQUEST_ID_HEADER_KEY = "x-request-id"; public static final String PROCESSED_FILE_NAME_PREFIX = "processed-"; - public static final String ERROR_FROM_CLIENT_HEADER_KEY = "eror-from-client"; - public static final String DEIDENTIFIED_FILE_PREFIX = "deidentified";; + public static final String ERROR_FROM_CLIENT_HEADER_KEY = "error-from-client"; + public static final String DEIDENTIFIED_FILE_PREFIX = "deidentified"; } diff --git a/src/main/java/com/skyflow/vault/connection/InvokeConnectionResponse.java b/src/main/java/com/skyflow/vault/connection/InvokeConnectionResponse.java index a2d44d99..1a81eca0 100644 --- a/src/main/java/com/skyflow/vault/connection/InvokeConnectionResponse.java +++ b/src/main/java/com/skyflow/vault/connection/InvokeConnectionResponse.java @@ -3,15 +3,18 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import java.util.ArrayList; import java.util.HashMap; public class InvokeConnectionResponse { private final Object data; private final HashMap metadata; + private final ArrayList> errors; - public InvokeConnectionResponse(Object data, HashMap metadata) { + public InvokeConnectionResponse(Object data, HashMap metadata, ArrayList> errors) { this.data = data; this.metadata = metadata; + this.errors = errors; } public Object getData() { @@ -22,9 +25,13 @@ public HashMap getMetadata() { return metadata; } + public ArrayList> getErrors() { + return errors; + } + @Override public String toString() { - Gson gson = new GsonBuilder().serializeNulls().create(); + Gson gson = new Gson().newBuilder().serializeNulls().create(); return gson.toJson(this); } } diff --git a/src/main/java/com/skyflow/vault/controller/ConnectionController.java b/src/main/java/com/skyflow/vault/controller/ConnectionController.java index 68a39751..4a9334d4 100644 --- a/src/main/java/com/skyflow/vault/controller/ConnectionController.java +++ b/src/main/java/com/skyflow/vault/controller/ConnectionController.java @@ -67,7 +67,7 @@ public InvokeConnectionResponse invoke(InvokeConnectionRequest invokeConnectionR JsonObject data = JsonParser.parseString(response).getAsJsonObject(); HashMap metadata = new HashMap<>(); metadata.put("requestId", HttpUtility.getRequestID()); - connectionResponse = new InvokeConnectionResponse(data, metadata); + connectionResponse = new InvokeConnectionResponse(data, metadata, null); LogUtil.printInfoLog(InfoLogs.INVOKE_CONNECTION_REQUEST_RESOLVED.getLog()); } catch (IOException e) { LogUtil.printErrorLog(ErrorLogs.INVOKE_CONNECTION_REQUEST_REJECTED.getLog()); diff --git a/src/main/java/com/skyflow/vault/controller/DetectController.java b/src/main/java/com/skyflow/vault/controller/DetectController.java index 411658ae..c06b9a9d 100644 --- a/src/main/java/com/skyflow/vault/controller/DetectController.java +++ b/src/main/java/com/skyflow/vault/controller/DetectController.java @@ -28,7 +28,11 @@ import java.util.*; public final class DetectController extends VaultClient { - private static final Gson gson = new GsonBuilder().serializeNulls().create(); + Gson gson = new GsonBuilder() + .registerTypeAdapter(Optional.class, (JsonSerializer>) (src, typeOfSrc, context) -> + src.map(context::serialize).orElse(null)) + .serializeNulls() + .create(); public DetectController(VaultConfig vaultConfig, Credentials credentials) { super(vaultConfig, credentials); @@ -55,7 +59,7 @@ public DeidentifyTextResponse deidentifyText(DeidentifyTextRequest deidentifyTex deidentifyTextResponse = getDeIdentifyTextResponse(deidentifyStringResponse); LogUtil.printInfoLog(InfoLogs.DEIDENTIFY_TEXT_REQUEST_RESOLVED.getLog()); } catch (ApiClientApiException ex) { - String bodyString = gson.toJson(ex.body()); + String bodyString = extractBodyAsString(ex.body()); LogUtil.printErrorLog(ErrorLogs.DEIDENTIFY_TEXT_REQUEST_REJECTED.getLog()); throw new SkyflowException(ex.statusCode(), ex, ex.headers(), bodyString); } @@ -82,7 +86,7 @@ public ReidentifyTextResponse reidentifyText(ReidentifyTextRequest reidentifyTex reidentifyTextResponse = new ReidentifyTextResponse(reidentifyStringResponse.getText().orElse(null)); LogUtil.printInfoLog(InfoLogs.REIDENTIFY_TEXT_REQUEST_RESOLVED.getLog()); } catch (ApiClientApiException ex) { - String bodyString = gson.toJson(ex.body()); + String bodyString = extractBodyAsString(ex.body()); LogUtil.printErrorLog(ErrorLogs.REIDENTIFY_TEXT_REQUEST_REJECTED.getLog()); throw new SkyflowException(ex.statusCode(), ex, ex.headers(), bodyString); } @@ -145,7 +149,7 @@ public DeidentifyFileResponse deidentifyFile(DeidentifyFileRequest request) thro } } } catch (ApiClientApiException e) { - String bodyString = gson.toJson(e.body()); + String bodyString = extractBodyAsString(e.body()); LogUtil.printErrorLog(ErrorLogs.DEIDENTIFY_FILE_REQUEST_REJECTED.getLog()); throw new SkyflowException(e.statusCode(), e, e.headers(), bodyString); } @@ -287,6 +291,14 @@ private static synchronized List getEntities(DeidentifyStatusRes return entities; } + private String extractBodyAsString(Object body) { + if (body instanceof String) { + return (String) body; + } else { + return gson.toJson(body); + } + } + private com.skyflow.generated.rest.types.DeidentifyFileResponse processFileByType(String fileExtension, String base64Content, DeidentifyFileRequest request, String vaultId) throws SkyflowException { switch (fileExtension.toLowerCase()) { case "txt": @@ -367,7 +379,7 @@ public DeidentifyFileResponse getDetectRun(GetDetectRunRequest request) throws S return parseDeidentifyFileResponse(apiResponse, runId, apiResponse.getStatus().toString()); } catch (ApiClientApiException e) { - String bodyString = gson.toJson(e.body()); + String bodyString = extractBodyAsString(e.body()); LogUtil.printErrorLog(ErrorLogs.GET_DETECT_RUN_REQUEST_REJECTED.getLog()); throw new SkyflowException(e.statusCode(), e, e.headers(), bodyString); } diff --git a/src/main/java/com/skyflow/vault/controller/VaultController.java b/src/main/java/com/skyflow/vault/controller/VaultController.java index 84e528b0..3c307c29 100644 --- a/src/main/java/com/skyflow/vault/controller/VaultController.java +++ b/src/main/java/com/skyflow/vault/controller/VaultController.java @@ -31,7 +31,7 @@ public VaultController(VaultConfig vaultConfig, Credentials credentials) { super(vaultConfig, credentials); } - private static synchronized HashMap getFormattedBatchInsertRecord(Object record, int requestIndex) { + private static synchronized HashMap getFormattedBatchInsertRecord(Object record, Integer requestIndex) { HashMap insertRecord = new HashMap<>(); String jsonString = gson.toJson(record); JsonObject bodyObject = JsonParser.parseString(jsonString).getAsJsonObject().get("Body").getAsJsonObject(); @@ -95,11 +95,9 @@ private static synchronized HashMap getFormattedUpdateRecord(V1U private static synchronized HashMap getFormattedQueryRecord(V1FieldRecords record) { HashMap queryRecord = new HashMap<>(); - Object fields = record.getFields(); - if (fields != null) { - String fieldsString = gson.toJson(fields); - JsonObject fieldsObject = JsonParser.parseString(fieldsString).getAsJsonObject(); - queryRecord.putAll(fieldsObject.asMap()); + Optional> fieldsOpt = record.getFields(); + if (fieldsOpt.isPresent()) { + queryRecord.putAll(fieldsOpt.get()); } return queryRecord; } @@ -124,7 +122,7 @@ public InsertResponse insert(InsertRequest insertRequest) throws SkyflowExceptio if (records.isPresent()) { List> recordList = records.get(); - for (int index = 0; index < recordList.size(); index++) { + for (Integer index = (Integer) 0; index < recordList.size(); index++) { Map record = recordList.get(index); HashMap insertRecord = getFormattedBatchInsertRecord(record, index); @@ -132,6 +130,7 @@ public InsertResponse insert(InsertRequest insertRequest) throws SkyflowExceptio insertedFields.add(insertRecord); } else { insertRecord.put("requestId", batchInsertResult.headers().get("x-request-id").get(0)); + insertRecord.put("httpCode", 400); errorFields.add(insertRecord); } } @@ -232,6 +231,7 @@ public GetResponse get(GetRequest getRequest) throws SkyflowException { .downloadUrl(getRequest.getDownloadURL()) .columnName(getRequest.getColumnName()) .columnValues(getRequest.getColumnValues()) + .fields(getRequest.getFields()) .orderBy(RecordServiceBulkGetRecordRequestOrderBy.valueOf(getRequest.getOrderBy())) .build(); diff --git a/src/main/java/com/skyflow/vault/data/GetRequest.java b/src/main/java/com/skyflow/vault/data/GetRequest.java index 04626e35..e705cd9a 100644 --- a/src/main/java/com/skyflow/vault/data/GetRequest.java +++ b/src/main/java/com/skyflow/vault/data/GetRequest.java @@ -63,7 +63,7 @@ public String getOrderBy() { public static final class GetRequestBuilder { private String table; private ArrayList ids; - private RedactionType redactionType; + private RedactionType redactionType = RedactionType.PLAIN_TEXT; private Boolean returnTokens; private ArrayList fields; private String offset; diff --git a/src/main/java/com/skyflow/vault/data/GetResponse.java b/src/main/java/com/skyflow/vault/data/GetResponse.java index 41821969..34a01303 100644 --- a/src/main/java/com/skyflow/vault/data/GetResponse.java +++ b/src/main/java/com/skyflow/vault/data/GetResponse.java @@ -24,7 +24,7 @@ public ArrayList> getErrors() { @Override public String toString() { - Gson gson = new Gson(); + Gson gson = new Gson().newBuilder().serializeNulls().create(); return gson.toJson(this); } } diff --git a/src/main/java/com/skyflow/vault/data/InsertResponse.java b/src/main/java/com/skyflow/vault/data/InsertResponse.java index a4f97967..3d311525 100644 --- a/src/main/java/com/skyflow/vault/data/InsertResponse.java +++ b/src/main/java/com/skyflow/vault/data/InsertResponse.java @@ -24,7 +24,7 @@ public ArrayList> getErrors() { @Override public String toString() { - Gson gson = new Gson(); + Gson gson = new Gson().newBuilder().serializeNulls().create(); return gson.toJson(this); } } diff --git a/src/main/java/com/skyflow/vault/tokens/DetokenizeData.java b/src/main/java/com/skyflow/vault/tokens/DetokenizeData.java index 33bba2b9..7fcf3e5e 100644 --- a/src/main/java/com/skyflow/vault/tokens/DetokenizeData.java +++ b/src/main/java/com/skyflow/vault/tokens/DetokenizeData.java @@ -8,7 +8,7 @@ public class DetokenizeData { public DetokenizeData(String token) { this.token = token; - this.redactionType = RedactionType.PLAIN_TEXT; + this.redactionType = RedactionType.MASKED; } public DetokenizeData(String token, RedactionType redactionType) { diff --git a/src/main/java/com/skyflow/vault/tokens/DetokenizeResponse.java b/src/main/java/com/skyflow/vault/tokens/DetokenizeResponse.java index 31ff64b2..b826c501 100644 --- a/src/main/java/com/skyflow/vault/tokens/DetokenizeResponse.java +++ b/src/main/java/com/skyflow/vault/tokens/DetokenizeResponse.java @@ -1,6 +1,9 @@ package com.skyflow.vault.tokens; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import java.util.ArrayList; @@ -23,7 +26,33 @@ public ArrayList getErrors() { @Override public String toString() { - Gson gson = new Gson(); + Gson gson = new GsonBuilder() + .serializeNulls() + .registerTypeAdapter( + DetokenizeRecordResponse.class, + (com.google.gson.JsonSerializer) (src, typeOfSrc, context) -> { + com.google.gson.JsonObject obj = new com.google.gson.JsonObject(); + obj.addProperty("token", src.getToken()); + // Only include value if not null + if (src.getValue() != null) { + obj.addProperty("value", src.getValue()); + } + // Only include type if not null + if (src.getType() != null) { + obj.addProperty("type", src.getType()); + } + // Only include error if not null + if (src.getError() != null) { + obj.add("error", context.serialize(src.getError())); + } + // Only include requestId if not null + if (src.getRequestId() != null) { + obj.addProperty("requestId", src.getRequestId()); + } + return obj; + } + ) + .create(); return gson.toJson(this); } } diff --git a/src/test/java/com/skyflow/errors/SkyflowExceptionTest.java b/src/test/java/com/skyflow/errors/SkyflowExceptionTest.java index 89e0643b..8151ff5f 100644 --- a/src/test/java/com/skyflow/errors/SkyflowExceptionTest.java +++ b/src/test/java/com/skyflow/errors/SkyflowExceptionTest.java @@ -3,10 +3,7 @@ import org.junit.Assert; import org.junit.Test; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class SkyflowExceptionTest { @@ -38,6 +35,8 @@ public void testConstructorWithCodeAndMessage() { Assert.assertEquals(Integer.valueOf(400), Integer.valueOf(ex.getHttpCode())); Assert.assertEquals("Bad Request", ex.getMessage()); Assert.assertEquals("Bad Request", ex.toString().contains("Bad Request") ? "Bad Request" : null); + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(0, ex.getDetails().size()); } @Test @@ -49,7 +48,7 @@ public void testToStringFormat() { } @Test - public void testConstructorWithJsonErrorBody() { + public void testConstructorWithJsonErrorBodyArrayDetailsNonEmpty() { String json = "{\"error\":{\"message\":\"json error\",\"grpc_code\":7,\"http_status\":\"NOT_FOUND\",\"details\":[{\"info\":\"detail1\"}]}}"; Map> headers = new HashMap<>(); headers.put("x-request-id", Collections.singletonList("req-123")); @@ -62,21 +61,90 @@ public void testConstructorWithJsonErrorBody() { Assert.assertTrue(ex.getDetails().size() > 0); } + @Test + public void testConstructorWithJsonErrorBodyArrayDetailsEmpty() { + String json = "{\"error\":{\"message\":\"json error\",\"grpc_code\":7,\"http_status\":\"NOT_FOUND\",\"details\":[]}}"; + Map> headers = new HashMap<>(); + SkyflowException ex = new SkyflowException(404, new RuntimeException("fail"), headers, json); + Assert.assertEquals("json error", ex.getMessage()); + Assert.assertEquals(Integer.valueOf(7), ex.getGrpcCode()); + Assert.assertEquals("NOT_FOUND", ex.getHttpStatus()); + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(0, ex.getDetails().size()); + } + + @Test + public void testConstructorWithJsonErrorBodyObjectDetailsEmpty() { + String json = "{\"error\":{\"message\":\"json error\",\"grpc_code\":7,\"http_status\":\"NOT_FOUND\",\"details\":{}}}"; + Map> headers = new HashMap<>(); + SkyflowException ex = new SkyflowException(404, new RuntimeException("fail"), headers, json); + Assert.assertEquals("json error", ex.getMessage()); + Assert.assertEquals(Integer.valueOf(7), ex.getGrpcCode()); + Assert.assertEquals("NOT_FOUND", ex.getHttpStatus()); + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(0, ex.getDetails().size()); + } + + @Test + public void testConstructorWithJsonErrorBodyObjectDetailsAllEmptyArrays() { + String json = "{\"error\":{\"message\":\"json error\",\"grpc_code\":7,\"http_status\":\"NOT_FOUND\",\"details\":{\"a\":[],\"b\":[]}}}"; + Map> headers = new HashMap<>(); + SkyflowException ex = new SkyflowException(404, new RuntimeException("fail"), headers, json); + Assert.assertEquals("json error", ex.getMessage()); + Assert.assertEquals(Integer.valueOf(7), ex.getGrpcCode()); + Assert.assertEquals("NOT_FOUND", ex.getHttpStatus()); + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(0, ex.getDetails().size()); + } + + @Test + public void testConstructorWithJsonErrorBodyObjectDetailsAllNulls() { + String json = "{\"error\":{\"message\":\"json error\",\"grpc_code\":7,\"http_status\":\"NOT_FOUND\",\"details\":{\"a\":null,\"b\":null}}}"; + Map> headers = new HashMap<>(); + SkyflowException ex = new SkyflowException(404, new RuntimeException("fail"), headers, json); + Assert.assertEquals("json error", ex.getMessage()); + Assert.assertEquals(Integer.valueOf(7), ex.getGrpcCode()); + Assert.assertEquals("NOT_FOUND", ex.getHttpStatus()); + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(0, ex.getDetails().size()); + } + + @Test + public void testConstructorWithJsonErrorBodyObjectDetailsNonEmpty() { + String json = "{\"error\":{\"message\":\"json error\",\"grpc_code\":7,\"http_status\":\"NOT_FOUND\",\"details\":{\"a\":[1],\"b\":null}}}"; + Map> headers = new HashMap<>(); + SkyflowException ex = new SkyflowException(404, new RuntimeException("fail"), headers, json); + Assert.assertEquals("json error", ex.getMessage()); + Assert.assertEquals(Integer.valueOf(7), ex.getGrpcCode()); + Assert.assertEquals("NOT_FOUND", ex.getHttpStatus()); + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(1, ex.getDetails().size()); + Assert.assertTrue(ex.getDetails().get(0).getAsJsonObject().has("a")); + } + + @Test + public void testConstructorWithJsonErrorBodyNullDetails() { + String json = "{\"error\":{\"message\":\"json error\",\"grpc_code\":7,\"http_status\":\"NOT_FOUND\"}}"; + Map> headers = new HashMap<>(); + SkyflowException ex = new SkyflowException(404, new RuntimeException("fail"), headers, json); + Assert.assertEquals("json error", ex.getMessage()); + Assert.assertEquals(Integer.valueOf(7), ex.getGrpcCode()); + Assert.assertEquals("NOT_FOUND", ex.getHttpStatus()); + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(0, ex.getDetails().size()); + } @Test public void testConstructorWithNullErrorBody() { Map> headers = new HashMap<>(); SkyflowException ex = new SkyflowException(500, new RuntimeException("fail"), headers, null); - Assert.assertNull(ex.getMessage()); + Assert.assertEquals("fail", ex.getMessage()); Assert.assertNull(ex.getGrpcCode()); - Assert.assertNull(ex.getHttpStatus()); } @Test public void testGettersAndSetters() { SkyflowException ex = new SkyflowException("msg"); - // Simulate setting fields via reflection or constructor - // (getters are already tested above) Assert.assertNull(ex.getRequestId()); Assert.assertNull(ex.getDetails()); Assert.assertNull(ex.getGrpcCode()); @@ -95,4 +163,50 @@ public void testSetDetailsWithErrorFromClientHeader() { Assert.assertEquals(1, ex.getDetails().size()); Assert.assertEquals("client error", ex.getDetails().get(0).getAsJsonObject().get("errorFromClient").getAsString()); } + + @Test + public void testSetDetailsWithErrorFromClientHeaderAndNullDetails() { + String json = "{\"error\":{\"message\":\"test error\",\"grpc_code\":13}}"; + Map> headers = new HashMap<>(); + headers.put("error-from-client", Collections.singletonList("client error")); + + SkyflowException ex = new SkyflowException(500, new RuntimeException("fail"), headers, json); + + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(1, ex.getDetails().size()); + Assert.assertEquals("client error", ex.getDetails().get(0).getAsJsonObject().get("errorFromClient").getAsString()); + } + + @Test + public void testSetDetailsWithNoErrorFromClientHeaderAndNullDetails() { + String json = "{\"error\":{\"message\":\"test error\",\"grpc_code\":13}}"; + Map> headers = new HashMap<>(); + + SkyflowException ex = new SkyflowException(500, new RuntimeException("fail"), headers, json); + + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(0, ex.getDetails().size()); + } + + @Test + public void testSetDetailsWithNoErrorFromClientHeaderAndEmptyDetails() { + String json = "{\"error\":{\"message\":\"test error\",\"grpc_code\":13,\"details\":[]}}"; + Map> headers = new HashMap<>(); + + SkyflowException ex = new SkyflowException(500, new RuntimeException("fail"), headers, json); + + Assert.assertNotNull(ex.getDetails()); + Assert.assertEquals(0, ex.getDetails().size()); + } + + @Test + public void testToStringWithNullFields() { + SkyflowException ex = new SkyflowException("msg"); + String str = ex.toString(); + Assert.assertTrue(str.contains("requestId: null")); + Assert.assertTrue(str.contains("grpcCode: null")); + Assert.assertTrue(str.contains("httpCode: null")); + Assert.assertTrue(str.contains("httpStatus: null")); + Assert.assertTrue(str.contains("details: null")); + } } \ No newline at end of file diff --git a/src/test/java/com/skyflow/vault/connection/InvokeConnectionTests.java b/src/test/java/com/skyflow/vault/connection/InvokeConnectionTests.java index a29a3335..70dc6fd8 100644 --- a/src/test/java/com/skyflow/vault/connection/InvokeConnectionTests.java +++ b/src/test/java/com/skyflow/vault/connection/InvokeConnectionTests.java @@ -425,7 +425,7 @@ public void testInvokeConnectionResponse() { data.addProperty("test_key_2", "test_value_2"); HashMap metadata = new HashMap<>(); metadata.put("requestId", "12345"); - InvokeConnectionResponse connectionResponse = new InvokeConnectionResponse(data, metadata); + InvokeConnectionResponse connectionResponse = new InvokeConnectionResponse(data, metadata, null); String responseString = "{\"data\":{\"test_key_1\":\"test_value_1\",\"test_key_2\":\"test_value_2\"}," + "\"metadata\":{\"requestId\":\"12345\"}}"; Assert.assertNotNull(connectionResponse.getData());