org.codehaus.jstestrunner.jetty.JSTestResultHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jstestrunner-junit Show documentation
Show all versions of jstestrunner-junit Show documentation
Runs JavaScript headlessly and reports details of the test back through JUnit.
/*
* 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.codehaus.jstestrunner.jetty;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jstestrunner.TestResultProducer;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
/**
* Receive test results and store them in an internal cache.
*/
public class JSTestResultHandler extends AbstractHandler {
/**
* Captures a test result.
*/
public static class JSTestResult {
public int failures;
public int passes;
public String message;
}
/**
* Store a mapping of test results.
*/
private final Map jsTestResults = new HashMap();
private final Lock jsTestResultsLock = new ReentrantLock();
private final Condition newJsTestResults = jsTestResultsLock.newCondition();
/**
* Get the test result associated with the given url and block until it
* becomes available, or we timeout.
*
* @param url
* the url of the test.
* @param testResultProducer
* Used to determine whether we are in a position to wait for
* results.
* @param time
* the time to wait.
* @param unit
* the unit of time to wait.
* @return the test result or null if it cannot be obtained.
*/
public JSTestResult getJsTestResult(URL url,
TestResultProducer testResultProducer, long time, TimeUnit unit) {
JSTestResult jsTestResult = null;
jsTestResultsLock.lock();
try {
do {
jsTestResult = jsTestResults.get(url.toString());
if (jsTestResult == null) {
boolean newJsTestResult;
try {
if (testResultProducer.isAvailable()) {
newJsTestResult = newJsTestResults
.await(time, unit);
} else {
newJsTestResult = false;
}
} catch (InterruptedException e) {
newJsTestResult = false;
}
if (!newJsTestResult) {
break;
}
}
} while (jsTestResult == null);
} finally {
jsTestResultsLock.unlock();
}
return jsTestResult;
}
/**
* Handle a test result.
*/
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
if (target.equals("/testResults") && request.getMethod().equals("POST")
&& request.getContentType().contains("application/json")) {
JSTestResult jsTestResult = null;
JsonFactory f = new JsonFactory();
JsonParser jp = f.createJsonParser(request.getReader());
String testUrl = null;
Integer failures = null;
Integer passes = null;
String message = null;
try {
jp.nextToken(); // will return JsonToken.START_OBJECT (verify?)
while (jp.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jp.getCurrentName();
jp.nextToken(); // move to value, or
// START_OBJECT/START_ARRAY
if (fieldname.equals("testUrl")) { // contains an object
testUrl = jp.getText();
} else if (fieldname.equals("failures")) {
failures = jp.getIntValue();
} else if (fieldname.equals("passes")) {
passes = jp.getIntValue();
} else if (fieldname.equals("message")) {
message = jp.getText();
}
}
} finally {
jp.close();
}
// Store any failures.
if (testUrl != null && failures != null && passes != null
&& message != null) {
jsTestResult = new JSTestResult();
jsTestResult.failures = failures;
jsTestResult.message = message;
jsTestResult.passes = passes;
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
} else {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
response.setContentType("application/json");
baseRequest.setHandled(true);
// Minimally signal any threads to re-look at things. Store results
// if we received them.
jsTestResultsLock.lock();
try {
if (jsTestResult != null) {
jsTestResults.put(testUrl, jsTestResult);
}
newJsTestResults.signalAll();
} finally {
jsTestResultsLock.unlock();
}
}
}
}