Skip to content

Commit

Permalink
Add test to the default error handler on the pipeline error proper ha…
Browse files Browse the repository at this point in the history
…ndling (#26)

Signed-off-by: Clement Escoffier <[email protected]>
  • Loading branch information
cescoffier committed Jun 5, 2014
1 parent 5734387 commit 7757e89
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public class DefaultPageErrorHandler extends DefaultController implements Filter
* The 500 template.
*/
@Requires(filter = "(name=error/pipeline)", proxy = false, optional = true, id = "pipeline")
private Template pipeline;
protected Template pipeline;

/**
* The router.
Expand All @@ -100,11 +100,19 @@ public class DefaultPageErrorHandler extends DefaultController implements Filter
private File pipelineErrorDirectory;


/**
* Methods called when this component is starting. It builds the pipeline error directory from the
* configuration's base directory.
*/
@Validate
public void start() {
pipelineErrorDirectory = new File(configuration.getBaseDir().getParentFile(), "pipeline");
}

/**
* @return the first error file contained in the pipeline error's directory, {@literal null} if none. Notice that
* the returned file may depend on the operating system.
*/
public File getFirstErrorFile() {
if (!pipelineErrorDirectory.isDirectory()) {
return null;
Expand All @@ -127,7 +135,7 @@ public File getFirstErrorFile() {
* @return the HTTP result serving the error page
*/
private Result renderInternalError(Context context, Route route, Throwable e) {
Throwable localException = e;
Throwable localException;

// If the template is not there, just wrap the exception within a JSON Object.
if (internalerror == null) {
Expand All @@ -136,8 +144,10 @@ private Result renderInternalError(Context context, Route route, Throwable e) {


// Manage ITE
if (localException instanceof InvocationTargetException) {
localException = ((InvocationTargetException) localException).getTargetException();
if (e instanceof InvocationTargetException) {
localException = ((InvocationTargetException) e).getTargetException();
} else {
localException = e;
}

// Retrieve the cause if any.
Expand Down Expand Up @@ -370,16 +380,38 @@ public int priority() {
return 1000;
}

/**
* A structure storing the line of an error.
*/
public static class InterestingLines {

/**
* The first line to display (line number).
*/
public final int firstLine;

/**
* The line where the error occurs (line number).
*/
public final int errorLine;

/**
* The set of lines.
*/
public final String[] focus;

public InterestingLines(int firstLine, String[] focus, int errorLine) {
/**
* Creates the interested line instance.
*
* @param firstLine the first line
* @param focus the set of lines
* @param errorLine the error line.
*/
private InterestingLines(int firstLine, String[] focus, int errorLine) {
this.firstLine = firstLine;
this.errorLine = errorLine;
this.focus = focus;
// We keep a copy of the array.
this.focus = focus; //NOSONAR
}

}
Expand All @@ -390,6 +422,7 @@ public InterestingLines(int firstLine, String[] focus, int errorLine) {
* @param source the source
* @param line the line responsible of the error
* @param border number of lines to use as a border
* @return the interested line structure
*/
public InterestingLines extractInterestedLines(String source, int line, int border) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,31 @@
*/
package org.wisdom.error;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.wisdom.api.Controller;
import org.wisdom.api.DefaultController;
import org.wisdom.api.configuration.ApplicationConfiguration;
import org.wisdom.api.http.HttpMethod;
import org.wisdom.api.http.MimeTypes;
import org.wisdom.api.http.Result;
import org.wisdom.api.http.Status;
import org.wisdom.api.content.Json;
import org.wisdom.api.http.*;
import org.wisdom.api.interception.Filter;
import org.wisdom.api.interception.Interceptor;
import org.wisdom.api.interception.RequestContext;
import org.wisdom.api.router.Route;
import org.wisdom.api.router.Router;
import org.wisdom.api.templates.Template;

import java.io.File;
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -105,7 +111,6 @@ public void switchToHeadWhenGetRouteDoesNotExist() throws Exception {
when(handler.configuration.isDev()).thenReturn(false);
handler.router = mock(Router.class);


Route reqRoute = new Route(HttpMethod.HEAD, "/", null, null);

when(handler.router.getRouteFor(HttpMethod.HEAD, "/")).thenReturn(new Route(HttpMethod.HEAD, "/", null, null));
Expand All @@ -120,6 +125,76 @@ public void switchToHeadWhenGetRouteDoesNotExist() throws Exception {
assertThat(result.getRenderable().length()).isEqualTo(0);
}

@Test
public void pipelineErrorWithoutError() throws Exception {
DefaultPageErrorHandler handler = new DefaultPageErrorHandler();
handler.configuration = mock(ApplicationConfiguration.class);
when(handler.configuration.isDev()).thenReturn(true);
when(handler.configuration.getBaseDir()).thenReturn(new File("src/test/resources/wisdom/missing_on_purpose"));
handler.router = mock(Router.class);
handler.pipeline = mock(Template.class);

Request request = mock(Request.class);
when(request.accepts(MimeTypes.HTML)).thenReturn(true);

Context context = mock(Context.class);
when(context.request()).thenReturn(request);

Context.CONTEXT.set(context);
MyController controller = new MyController();
Route route = new Route(HttpMethod.GET, "/", controller, controller.getClass().getMethod("action"));


RequestContext rc = new RequestContext(route, Collections.<Filter>emptyList(),
Collections.<Interceptor<?>, Object>emptyMap(), new Object[0]);

handler.start();
Result result = handler.call(route, rc);
assertThat(result.getStatusCode()).isEqualTo(200);
}

@Test
public void pipelineErrorWithError() throws Exception {
DefaultPageErrorHandler handler = new DefaultPageErrorHandler();
handler.configuration = mock(ApplicationConfiguration.class);
when(handler.configuration.isDev()).thenReturn(true);
when(handler.configuration.getBaseDir()).thenReturn(new File("src/test/resources/wisdom"));

handler.router = mock(Router.class);
handler.pipeline = mock(Template.class);
handler.json = mock(Json.class);
when(handler.json.parse(anyString())).thenAnswer(new Answer<JsonNode>() {
@Override
public JsonNode answer(InvocationOnMock invocation) throws Throwable {
return new ObjectMapper().readValue((String) invocation.getArguments()[0], JsonNode.class);
}
});

handler.start();

Request request = mock(Request.class);
when(request.accepts(MimeTypes.HTML)).thenReturn(true);

Context context = mock(Context.class);
when(context.request()).thenReturn(request);

Context.CONTEXT.set(context);
MyController controller = new MyController();
Route route = new Route(HttpMethod.GET, "/", controller, controller.getClass().getMethod("action"));


RequestContext rc = new RequestContext(route, Collections.<Filter>emptyList(),
Collections.<Interceptor<?>, Object>emptyMap(), new Object[0]);

Result result = handler.call(route, rc);
assertThat(result.getStatusCode()).isEqualTo(500);
}

@After
public void cleanupContext() {
Context.CONTEXT.remove();
}


private class MyController extends DefaultController {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"message" : "This is the error",
"title" : "processing error",
"watcher" : "My Watcher"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This directory is just here to simulate the location of the Wisdom Runtime.

0 comments on commit 7757e89

Please sign in to comment.