Skip to content

Commit 908089e

Browse files
Add log coverage for error response (#190)
* Add log coverage for error response * Use factory method to warp a DebugException to CompletionException * Move the factory method to utility * Move variable exceptionMessage to the closest code block where it's used * Log error message throwed by evaluatable breakpoint * Keep the overload method with the consistent arguments order * Restrict travis ci to jdk8 * latest osx uses jdk10 and the plugin build failed, so roll back to an old osx image
1 parent 17b5024 commit 908089e

File tree

16 files changed

+110
-80
lines changed

16 files changed

+110
-80
lines changed

.project

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<projectDescription>
3-
<name>java-debug</name>
3+
<name>java-debug-parent</name>
44
<comment></comment>
55
<projects>
66
</projects>

.travis.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
language: java
22

3-
os:
4-
- linux
5-
- osx
3+
matrix:
4+
include:
5+
- os: linux
6+
- os: osx
7+
osx_image: xcode9.2
68

79
script:
810
- ./mvnw clean verify

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/AdapterUtils.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
import java.security.MessageDigest;
2525
import java.security.NoSuchAlgorithmException;
2626
import java.util.concurrent.CompletableFuture;
27+
import java.util.concurrent.CompletionException;
2728
import java.util.regex.Matcher;
2829
import java.util.regex.Pattern;
2930

3031
import org.apache.commons.lang3.StringUtils;
3132

33+
import com.microsoft.java.debug.core.DebugException;
3234
import com.microsoft.java.debug.core.protocol.Messages.Response;
3335
import com.microsoft.java.debug.core.protocol.Responses;
3436
import com.microsoft.java.debug.core.protocol.Types;
@@ -221,6 +223,14 @@ public static CompletableFuture<Response> createAsyncErrorResponse(Response resp
221223
return CompletableFuture.completedFuture(setErrorResponse(response, errorCode, e));
222224
}
223225

226+
public static CompletionException createCompletionException(String message, ErrorCode errorCode, Throwable cause) {
227+
return new CompletionException(new DebugException(message, cause, errorCode.getId()));
228+
}
229+
230+
public static CompletionException createCompletionException(String message, ErrorCode errorCode) {
231+
return new CompletionException(new DebugException(message, errorCode.getId()));
232+
}
233+
224234
/**
225235
* Calculate SHA-256 Digest of given string.
226236
* @param content

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/ProtocolServer.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ protected void dispatchRequest(Messages.Request request) {
8383
sendResponse(response);
8484
future.complete(null);
8585
} else {
86-
logger.log(Level.SEVERE, "The request dispatcher should not return null response.");
8786
future.completeExceptionally(new DebugException("The request dispatcher should not return null response.",
8887
ErrorCode.UNKNOWN_FAILURE.getId()));
8988
}
@@ -98,14 +97,13 @@ protected void dispatchRequest(Messages.Request request) {
9897
// mark it success to avoid reporting error on VSCode.
9998
response.success = true;
10099
sendResponse(response);
101-
} else if (ex instanceof DebugException) {
102-
sendResponse(AdapterUtils.setErrorResponse(response,
103-
ErrorCode.parse(((DebugException) ex).getErrorCode()),
104-
ex.getMessage() != null ? ex.getMessage() : ex.toString()));
105100
} else {
101+
String exceptionMessage = ex.getMessage() != null ? ex.getMessage() : ex.toString();
102+
ErrorCode errorCode = ex instanceof DebugException ? ErrorCode.parse(((DebugException) ex).getErrorCode()) : ErrorCode.UNKNOWN_FAILURE;
103+
logger.log(Level.SEVERE, String.format("[error response][%s]: %s", request.command, exceptionMessage), ex);
106104
sendResponse(AdapterUtils.setErrorResponse(response,
107-
ErrorCode.UNKNOWN_FAILURE,
108-
ex.getMessage() != null ? ex.getMessage() : ex.toString()));
105+
errorCode,
106+
exceptionMessage));
109107
}
110108
return null;
111109
}).join();

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/AttachRequestHandler.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,10 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
7979
}
8080
}
8181
} catch (IOException | IllegalConnectorArgumentsException e) {
82-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.ATTACH_FAILURE,
83-
String.format("Failed to attach to remote debuggee VM. Reason: %s", e.toString()));
82+
throw AdapterUtils.createCompletionException(
83+
String.format("Failed to attach to remote debuggee VM. Reason: %s", e.toString()),
84+
ErrorCode.ATTACH_FAILURE,
85+
e);
8486
}
8587

8688
Map<String, Object> options = new HashMap<>();

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/CompletionsHandler.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@
1414
import java.util.Arrays;
1515
import java.util.List;
1616
import java.util.concurrent.CompletableFuture;
17-
import java.util.concurrent.CompletionException;
18-
import java.util.logging.Level;
19-
import java.util.logging.Logger;
2017

21-
import com.microsoft.java.debug.core.Configuration;
2218
import com.microsoft.java.debug.core.adapter.AdapterUtils;
2319
import com.microsoft.java.debug.core.adapter.ErrorCode;
2420
import com.microsoft.java.debug.core.adapter.ICompletionsProvider;
@@ -37,8 +33,6 @@
3733

3834
public class CompletionsHandler implements IDebugRequestHandler {
3935

40-
private static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME);
41-
4236
@Override
4337
public List<Command> getTargetCommands() {
4438
return Arrays.asList(Requests.Command.COMPLETIONS);
@@ -50,8 +44,10 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
5044
StackFrameReference stackFrameReference = (StackFrameReference) context.getRecyclableIdPool().getObjectById(completionsArgs.frameId);
5145

5246
if (stackFrameReference == null) {
53-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.COMPLETIONS_FAILURE,
54-
String.format("Completions: cannot find the stack frame with frameID %s", completionsArgs.frameId));
47+
throw AdapterUtils.createCompletionException(
48+
String.format("Completions: cannot find the stack frame with frameID %s", completionsArgs.frameId),
49+
ErrorCode.COMPLETIONS_FAILURE
50+
);
5551
}
5652

5753
return CompletableFuture.supplyAsync(() -> {
@@ -66,8 +62,11 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
6662
}
6763
return response;
6864
} catch (IncompatibleThreadStateException e) {
69-
logger.log(Level.WARNING, String.format("Cannot provide code completions because of %s.", e.toString()), e);
70-
throw new CompletionException(e);
65+
throw AdapterUtils.createCompletionException(
66+
String.format("Cannot provide code completions because of %s.", e.toString()),
67+
ErrorCode.COMPLETIONS_FAILURE,
68+
e
69+
);
7170
}
7271
});
7372
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/EvaluateRequestHandler.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
import java.util.List;
1616
import java.util.Map;
1717
import java.util.concurrent.CompletableFuture;
18-
import java.util.concurrent.CompletionException;
1918
import java.util.concurrent.ExecutionException;
20-
import java.util.logging.Level;
2119
import java.util.logging.Logger;
2220

2321
import org.apache.commons.lang3.StringUtils;
@@ -60,14 +58,16 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
6058
String expression = evalArguments.expression;
6159

6260
if (StringUtils.isBlank(expression)) {
63-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.EVALUATE_FAILURE,
64-
"Failed to evaluate. Reason: Empty expression cannot be evaluated.");
61+
throw AdapterUtils.createCompletionException(
62+
"Failed to evaluate. Reason: Empty expression cannot be evaluated.",
63+
ErrorCode.EVALUATE_FAILURE);
6564
}
6665
StackFrameReference stackFrameReference = (StackFrameReference) context.getRecyclableIdPool().getObjectById(evalArguments.frameId);
6766
if (stackFrameReference == null) {
6867
// stackFrameReference is null means the stackframe is continued by user manually,
69-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.EVALUATE_FAILURE,
70-
"Failed to evaluate. Reason: Cannot evaluate because the thread is resumed.");
68+
throw AdapterUtils.createCompletionException(
69+
"Failed to evaluate. Reason: Cannot evaluate because the thread is resumed.",
70+
ErrorCode.EVALUATE_FAILURE);
7171
}
7272

7373
return CompletableFuture.supplyAsync(() -> {
@@ -100,8 +100,10 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
100100
cause = e.getCause();
101101
}
102102
// TODO: distinguish user error of wrong expression(eg: compilation error)
103-
logger.log(Level.WARNING, String.format("Cannot evalution expression because of %s.", cause.toString()), cause);
104-
throw new CompletionException(cause);
103+
throw AdapterUtils.createCompletionException(
104+
String.format("Cannot evalution expression because of %s.", cause.toString()),
105+
ErrorCode.EVALUATE_FAILURE,
106+
cause);
105107
}
106108
});
107109
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/LaunchRequestHandler.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.util.Map.Entry;
2424
import java.util.concurrent.CompletableFuture;
2525
import java.util.concurrent.CompletionException;
26-
import java.util.logging.Level;
2726
import java.util.logging.Logger;
2827
import java.util.regex.Matcher;
2928
import java.util.regex.Pattern;
@@ -79,8 +78,9 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
7978
LaunchArguments launchArguments = (LaunchArguments) arguments;
8079
if (StringUtils.isBlank(launchArguments.mainClass)
8180
|| ArrayUtils.isEmpty(launchArguments.modulePaths) && ArrayUtils.isEmpty(launchArguments.classPaths)) {
82-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.ARGUMENT_MISSING,
83-
String.format("Failed to launch debuggee VM. Missing mainClass or modulePaths/classPaths options in launch configuration"));
81+
throw AdapterUtils.createCompletionException(
82+
"Failed to launch debuggee VM. Missing mainClass or modulePaths/classPaths options in launch configuration.",
83+
ErrorCode.ARGUMENT_MISSING);
8484
}
8585

8686
context.setAttached(false);
@@ -93,8 +93,9 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
9393
context.setDebuggeeEncoding(StandardCharsets.UTF_8);
9494
} else {
9595
if (!Charset.isSupported(launchArguments.encoding)) {
96-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.INVALID_ENCODING,
97-
String.format("Failed to launch debuggee VM. 'encoding' options in the launch configuration is not recognized."));
96+
throw AdapterUtils.createCompletionException(
97+
"Failed to launch debuggee VM. 'encoding' options in the launch configuration is not recognized.",
98+
ErrorCode.INVALID_ENCODING);
9899
}
99100

100101
context.setDebuggeeEncoding(Charset.forName(launchArguments.encoding));
@@ -197,7 +198,6 @@ private CompletableFuture<Response> launchInTerminal(LaunchArguments launchArgum
197198
logger.info("Launching debuggee in terminal console succeeded.");
198199
resultFuture.complete(response);
199200
} catch (IOException | IllegalConnectorArgumentsException e) {
200-
logger.log(Level.SEVERE, String.format(launchInTerminalErrorFormat, e.toString()));
201201
resultFuture.completeExceptionally(
202202
new DebugException(
203203
String.format(launchInTerminalErrorFormat, e.toString()),
@@ -206,7 +206,6 @@ private CompletableFuture<Response> launchInTerminal(LaunchArguments launchArgum
206206
);
207207
}
208208
} else {
209-
logger.log(Level.SEVERE, String.format(launchInTerminalErrorFormat, runResponse.message));
210209
resultFuture.completeExceptionally(
211210
new DebugException(
212211
String.format(launchInTerminalErrorFormat, runResponse.message),
@@ -219,7 +218,6 @@ private CompletableFuture<Response> launchInTerminal(LaunchArguments launchArgum
219218
ex = ex.getCause();
220219
}
221220
String errorMessage = String.format(launchInTerminalErrorFormat, ex != null ? ex.toString() : "Null response");
222-
logger.log(Level.SEVERE, errorMessage);
223221
resultFuture.completeExceptionally(
224222
new DebugException(
225223
String.format(launchInTerminalErrorFormat, errorMessage),
@@ -229,7 +227,6 @@ private CompletableFuture<Response> launchInTerminal(LaunchArguments launchArgum
229227
}
230228
});
231229
} catch (IOException | IllegalConnectorArgumentsException e) {
232-
logger.log(Level.SEVERE, String.format(launchInTerminalErrorFormat, e.toString()));
233230
resultFuture.completeExceptionally(
234231
new DebugException(
235232
String.format(launchInTerminalErrorFormat, e.toString()),
@@ -298,7 +295,6 @@ private CompletableFuture<Response> launchInternally(LaunchArguments launchArgum
298295

299296
resultFuture.complete(response);
300297
} catch (IOException | IllegalConnectorArgumentsException | VMStartException e) {
301-
logger.log(Level.SEVERE, String.format("Failed to launch debuggee VM. Reason: %s", e.toString()));
302298
resultFuture.completeExceptionally(
303299
new DebugException(
304300
String.format("Failed to launch debuggee VM. Reason: %s", e.toString()),

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/RestartFrameHandler.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
5151
StackFrameReference stackFrameReference = (StackFrameReference) context.getRecyclableIdPool().getObjectById(restartFrameArgs.frameId);
5252

5353
if (stackFrameReference == null) {
54-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.RESTARTFRAME_FAILURE,
55-
String.format("RestartFrame: cannot find the stack frame with frameID %s", restartFrameArgs.frameId));
54+
throw AdapterUtils.createCompletionException(
55+
String.format("RestartFrame: cannot find the stack frame with frameID %s", restartFrameArgs.frameId),
56+
ErrorCode.RESTARTFRAME_FAILURE);
5657
}
5758

5859
if (canRestartFrame(context, stackFrameReference)) {
@@ -62,11 +63,15 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
6263
stepInto(context, reference);
6364
} catch (DebugException de) {
6465
context.getProtocolServer().sendEvent(new Events.UserNotificationEvent(NotificationType.ERROR, de.getMessage()));
66+
throw AdapterUtils.createCompletionException(
67+
String.format("Failed to restart stack frame. Reason: %s", de.getMessage()),
68+
ErrorCode.RESTARTFRAME_FAILURE,
69+
de);
6570
}
6671
return CompletableFuture.completedFuture(response);
6772
} else {
6873
context.getProtocolServer().sendEvent(new Events.UserNotificationEvent(NotificationType.ERROR, "Current stack frame doesn't support restart."));
69-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.RESTARTFRAME_FAILURE, "Failed to restart the selected stack frame.");
74+
throw AdapterUtils.createCompletionException("Current stack frame doesn't support restart.", ErrorCode.RESTARTFRAME_FAILURE);
7075
}
7176
}
7277

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetBreakpointsRequestHandler.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
117117

118118
// When breakpoint source path is null or an invalid file path, send an ErrorResponse back.
119119
if (StringUtils.isBlank(sourcePath)) {
120-
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.SET_BREAKPOINT_FAILURE,
121-
String.format("Failed to setBreakpoint. Reason: '%s' is an invalid path.", bpArguments.source.path));
120+
throw AdapterUtils.createCompletionException(
121+
String.format("Failed to setBreakpoint. Reason: '%s' is an invalid path.", bpArguments.source.path),
122+
ErrorCode.SET_BREAKPOINT_FAILURE);
122123
}
123124

124125
try {
@@ -154,9 +155,9 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
154155
response.body = new Responses.SetBreakpointsResponseBody(res);
155156
return CompletableFuture.completedFuture(response);
156157
} catch (DebugException e) {
157-
return AdapterUtils.createAsyncErrorResponse(response,
158-
ErrorCode.SET_BREAKPOINT_FAILURE,
159-
String.format("Failed to setBreakpoint. Reason: '%s'", e.toString()));
158+
throw AdapterUtils.createCompletionException(
159+
String.format("Failed to setBreakpoint. Reason: '%s'", e.toString()),
160+
ErrorCode.SET_BREAKPOINT_FAILURE);
160161
}
161162
}
162163

@@ -211,6 +212,7 @@ private void registerBreakpointHandler(IDebugAdapterContext context) {
211212
private boolean handleEvaluationResult(IDebugAdapterContext context, ThreadReference bpThread, IBreakpoint breakpoint, Value value, Throwable ex) {
212213
if (StringUtils.isNotBlank(breakpoint.getLogMessage())) {
213214
if (ex != null) {
215+
logger.log(Level.SEVERE, String.format("[Logpoint]: %s", ex.getMessage() != null ? ex.getMessage() : ex.toString()), ex);
214216
context.getProtocolServer().sendEvent(new Events.UserNotificationEvent(
215217
Events.UserNotificationEvent.NotificationType.ERROR,
216218
String.format("[Logpoint] Log message '%s' error: %s", breakpoint.getLogMessage(), ex.getMessage())));
@@ -236,6 +238,7 @@ private boolean handleEvaluationResult(IDebugAdapterContext context, ThreadRefer
236238
} else {
237239
context.getProtocolServer().sendEvent(new Events.StoppedEvent("breakpoint", bpThread.uniqueID()));
238240
if (ex != null) {
241+
logger.log(Level.SEVERE, String.format("[ConditionalBreakpoint]: %s", ex.getMessage() != null ? ex.getMessage() : ex.toString()), ex);
239242
context.getProtocolServer().sendEvent(new Events.UserNotificationEvent(
240243
Events.UserNotificationEvent.NotificationType.ERROR,
241244
String.format("Breakpoint condition '%s' error: %s", breakpoint.getCondition(), ex.getMessage())));

0 commit comments

Comments
 (0)