Author: bdelacretaz
Date: Wed Feb 23 12:00:41 2011
New Revision: 1073712
URL: http://svn.apache.org/viewvc?rev=1073712&view=rev
Log:
SLING-1992 - refactor to simplify JUnitServlet, and Renderers are now OSGi
services
Added:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/Renderer.java
- copied, changed from r1073087,
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/Renderer.java
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/RequestParser.java
- copied, changed from r1073087,
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/RequestInfo.java
Removed:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/Renderer.java
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/RequestInfo.java
Modified:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JUnitServlet.java
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JsonRenderer.java
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/PlainTextRenderer.java
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/XmlRenderer.java
Copied:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/Renderer.java
(from r1073087,
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/Renderer.java)
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/Renderer.java?p2=sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/Renderer.java&p1=sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/Renderer.java&r1=1073087&r2=1073712&rev=1073712&view=diff
==============================================================================
---
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/Renderer.java
(original)
+++
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/Renderer.java
Wed Feb 23 12:00:41 2011
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sling.junit.impl.servlet;
+package org.apache.sling.junit;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -25,10 +25,29 @@ import javax.servlet.http.HttpServletRes
import org.junit.runner.notification.RunListener;
/** Renderer for our servlet output */
-abstract class Renderer extends RunListener {
- abstract void setup(HttpServletResponse response, String pageTitle) throws
IOException, UnsupportedEncodingException;
- abstract void cleanup();
- abstract void list(String cssClass, List<String> data);
- abstract void info(String cssClass, String info);
- abstract void title(int level, String title);
-}
+ public interface Renderer {
+ /** True if this renderer applies to supplied request */
+ boolean appliesTo(RequestParser p);
+
+ /** Called first to setup rendering */
+ void setup(HttpServletResponse response, String pageTitle) throws
IOException, UnsupportedEncodingException;
+
+ /** Called once rendering is done */
+ void cleanup();
+
+ /** Render a list of things
+ * @param describes the role of the list, must be a valid CSS class value
+ */
+ void list(String role, List<String> data);
+
+ /** Render general information
+ * @param describes the role of the list, must be a valid CSS class value
+ */
+ void info(String role, String info);
+
+ /** Render a title of a specified hierarchical level */
+ void title(int level, String title);
+
+ /** Provide a RunListener for JUnit tests */
+ RunListener getRunListener();
+}
\ No newline at end of file
Copied:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/RequestParser.java
(from r1073087,
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/RequestInfo.java)
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/RequestParser.java?p2=sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/RequestParser.java&p1=sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/RequestInfo.java&r1=1073087&r2=1073712&rev=1073712&view=diff
==============================================================================
---
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/RequestInfo.java
(original)
+++
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/RequestParser.java
Wed Feb 23 12:00:41 2011
@@ -14,16 +14,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sling.junit.impl.servlet;
+package org.apache.sling.junit;
import javax.servlet.http.HttpServletRequest;
-/** Parse information from a request */
-public class RequestInfo {
- final String testSelector;
- final String extension;
+/** Parse information from a request, to define which
+ * tests to run and which renderer to select.
+ *
+ * We do not use the Sling API to to that, in order to
+ * keep the junit core module reusable in other OSGi
+ * environments.
+ */
+public class RequestParser {
+ private final String testSelector;
+ private final String extension;
+ private final HttpServletRequest request;
- RequestInfo(HttpServletRequest request) {
+ public RequestParser(HttpServletRequest request) {
+ this.request = request;
String pathinfo = request.getPathInfo();
if (pathinfo == null) {
pathinfo = "";
@@ -34,7 +42,7 @@ public class RequestInfo {
final int pos = pathinfo.lastIndexOf('.');
if (pos >= 0) {
testSelector = pathinfo.substring(0, pos);
- extension = pathinfo.substring(pos);
+ extension = pathinfo.substring(pos+1);
} else {
testSelector = pathinfo;
extension = "";
@@ -42,7 +50,20 @@ public class RequestInfo {
}
public String toString() {
- return getClass().getSimpleName() + ", testSelector=[" + testSelector
+ return getClass().getSimpleName() + ": testSelector=[" + testSelector
+ "], extension=[" + extension + "]";
}
-}
+
+ public String getTestSelector() {
+ return testSelector;
+ }
+
+ public String getExtension() {
+ return extension;
+ }
+
+ public HttpServletRequest getRequest() {
+ return request;
+ }
+
+}
\ No newline at end of file
Modified:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java?rev=1073712&r1=1073711&r2=1073712&view=diff
==============================================================================
---
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java
(original)
+++
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/HtmlRenderer.java
Wed Feb 23 12:00:41 2011
@@ -23,20 +23,37 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.junit.Renderer;
+import org.apache.sling.junit.RequestParser;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
-class HtmlRenderer extends Renderer {
+/** HTML renderer for JUnit servlet */
+@Component(immediate=false)
+@Service
+public class HtmlRenderer extends RunListener implements Renderer {
private PrintWriter output;
+ /** @inheritDoc */
+ public boolean appliesTo(RequestParser p) {
+ // This is our default renderer, applies to the empty
+ // extension as well
+ return "html".equals(p.getExtension()) || "".equals(p.getExtension());
+ }
+
+ /** @inheritDoc */
public void info(String cssClass, String str) {
output.println("<p class='" + cssClass + "'>");
HtmlFilter.escape(output, str);
output.println("</p>");
}
+ /** @inheritDoc */
public void list(String cssClass, List<String> data) {
output.println("<ul class='testNames'>");
for(String str : data) {
@@ -47,12 +64,14 @@ class HtmlRenderer extends Renderer {
output.println("</ul>");
}
+ /** @inheritDoc */
public void title(int level, String title) {
output.print("<h" + level + ">");
HtmlFilter.escape(output, title);
output.print("</h" + level + ">");
}
+ /** @inheritDoc */
public void setup(HttpServletResponse response, String pageTitle) throws
IOException, UnsupportedEncodingException {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
@@ -67,11 +86,17 @@ class HtmlRenderer extends Renderer {
output.println("</h1>");
}
+ /** @inheritDoc */
public void cleanup() {
output.println("</body>");
output.println("</html>");
}
+ /** @inheritDoc */
+ public RunListener getRunListener() {
+ return this;
+ }
+
@Override
public void testFailure(Failure failure) throws Exception {
super.testFailure(failure);
Modified:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JUnitServlet.java
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JUnitServlet.java?rev=1073712&r1=1073711&r2=1073712&view=diff
==============================================================================
---
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JUnitServlet.java
(original)
+++
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JUnitServlet.java
Wed Feb 23 12:00:41 2011
@@ -19,6 +19,7 @@ package org.apache.sling.junit.impl.serv
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
@@ -34,10 +35,15 @@ import org.apache.felix.scr.annotations.
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.junit.JUnitTestsManager;
+import org.apache.sling.junit.Renderer;
+import org.apache.sling.junit.RequestParser;
import org.junit.runner.JUnitCore;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
+import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,7 +71,14 @@ public class JUnitServlet extends HttpSe
@Reference
private HttpService httpService;
+ // Keep track of available Renderer
+ private final List<Renderer> renderers = new ArrayList<Renderer>();
+ private ServiceTracker renderersTracker;
+ private int renderersTrackerTrackingCount = -1;
+ private BundleContext bundleContext;
+
protected void activate(ComponentContext ctx) throws ServletException,
NamespaceException {
+ bundleContext = ctx.getBundleContext();
final Dictionary<?, ?> config = ctx.getProperties();
boolean disabled =
((Boolean)config.get(SERVLET_DISABLED_NAME)).booleanValue();
if(disabled) {
@@ -76,13 +89,21 @@ public class JUnitServlet extends HttpSe
httpService.registerServlet(servletPath, this, null, null);
log.info("Servlet registered at {}", servletPath);
}
+
+ renderersTracker = new ServiceTracker(ctx.getBundleContext(),
Renderer.class.getName(), null);
+ renderersTracker.open();
}
protected void deactivate(ComponentContext ctx) throws ServletException,
NamespaceException {
+ if(renderersTracker != null) {
+ renderersTracker.close();
+ renderersTracker = null;
+ }
if(servletPath != null) {
httpService.unregister(servletPath);
log.info("Servlet unregistered from path {}", servletPath);
}
+ bundleContext = null;
}
/** Return the list of available tests
@@ -104,16 +125,30 @@ public class JUnitServlet extends HttpSe
return testClasses;
}
- private Renderer getRenderer(RequestInfo requestInfo) {
- if(".txt".equals(requestInfo.extension)) {
- return new PlainTextRenderer();
- } else if(".xml".equals(requestInfo.extension)) {
- return new XmlRenderer();
- } else if(".json".equals(requestInfo.extension)) {
- return new JsonRenderer();
- } else {
- return new HtmlRenderer();
+ /** Return a Renderer, null if none found */
+ private Renderer getRenderer(RequestParser rp) {
+ if(renderersTracker.getTrackingCount() !=
renderersTrackerTrackingCount) {
+ log.debug("Rebuilding list of {}", Renderer.class.getSimpleName());
+ renderersTrackerTrackingCount =
renderersTracker.getTrackingCount();
+ final ServiceReference [] refs =
renderersTracker.getServiceReferences();
+ renderers.clear();
+ if(refs != null) {
+ for(ServiceReference ref : refs) {
+ renderers.add( (Renderer)bundleContext.getService(ref) );
+ }
+ }
+ log.info("List of {} rebuilt: {}",
+ Renderer.class.getSimpleName(),
+ renderers);
}
+
+ for(Renderer r : renderers) {
+ if(r.appliesTo(rp)) {
+ return r;
+ }
+ }
+
+ return null;
}
private void sendCss(HttpServletResponse response) throws IOException {
@@ -147,25 +182,28 @@ public class JUnitServlet extends HttpSe
}
}
- final RequestInfo requestInfo = new RequestInfo(request);
- final Renderer renderer = getRenderer(requestInfo);
- log.debug("GET request: {}", requestInfo);
+ final RequestParser requestParser = new RequestParser(request);
+ final Renderer renderer = getRenderer(requestParser);
+ if(renderer == null) {
+ throw new ServletException("No Renderer found for " +
requestParser);
+ }
+ log.debug("GET request: {}", requestParser);
renderer.setup(response, getClass().getSimpleName());
- if(requestInfo.testSelector.length() > 0) {
- renderer.info("info", "Test selector: " +
requestInfo.testSelector);
+ if(requestParser.getTestSelector().length() > 0) {
+ renderer.info("info", "Test selector: " +
requestParser.getTestSelector());
} else {
renderer.info("info", "Test selector is empty: "
+ "add class name prefix + extension at the end of the URL
to select a subset of tests");
}
// Any test classes?
- final List<String> testNames = getTestNames(requestInfo.testSelector);
+ final List<String> testNames =
getTestNames(requestParser.getTestSelector());
if(testNames.isEmpty()) {
renderer.info(
"warning",
- "No test classes found with prefix=" +
requestInfo.testSelector
+ "No test classes found with prefix=" +
requestParser.getTestSelector()
+ ", check the requirements of the active " +
"TestsProvider services for how to supply tests."
);
@@ -175,7 +213,7 @@ public class JUnitServlet extends HttpSe
renderer.title(2, "Running tests");
final JUnitCore junit = new JUnitCore();
- junit.addListener(renderer);
+ junit.addListener(renderer.getRunListener());
try {
for(String className : testNames) {
renderer.title(3, className);
Modified:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JsonRenderer.java
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JsonRenderer.java?rev=1073712&r1=1073711&r2=1073712&view=diff
==============================================================================
---
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JsonRenderer.java
(original)
+++
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/JsonRenderer.java
Wed Feb 23 12:00:41 2011
@@ -22,15 +22,23 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.io.JSONWriter;
+import org.apache.sling.junit.Renderer;
+import org.apache.sling.junit.RequestParser;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-class JsonRenderer extends Renderer {
+/** HTML renderer for JUnit servlet */
+@Component(immediate=false)
+@Service
+public class JsonRenderer extends RunListener implements Renderer {
public static final String INFO_TYPE_KEY = "INFO_TYPE";
public static final String INFO_SUBTYPE_KEY = "INFO_SUBTYPE";
@@ -38,8 +46,13 @@ class JsonRenderer extends Renderer {
private JSONWriter writer;
private int counter;
- @Override
- void setup(HttpServletResponse response, String pageTitle) throws
IOException, UnsupportedEncodingException {
+ /** @inheritDoc */
+ public boolean appliesTo(RequestParser p) {
+ return "json".equals(p.getExtension());
+ }
+
+ /** @inheritDoc */
+ public void setup(HttpServletResponse response, String pageTitle) throws
IOException, UnsupportedEncodingException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
writer = new JSONWriter(response.getWriter());
@@ -51,8 +64,8 @@ class JsonRenderer extends Renderer {
}
}
- @Override
- void cleanup() {
+ /** @inheritDoc */
+ public void cleanup() {
if(writer != null) {
try {
writer.endArray();
@@ -63,8 +76,8 @@ class JsonRenderer extends Renderer {
writer = null;
}
- @Override
- void info(String cssClass, String info) {
+ /** @inheritDoc */
+ public void info(String cssClass, String info) {
try {
startItem("info");
writer.key(INFO_SUBTYPE_KEY).value(cssClass);
@@ -75,8 +88,8 @@ class JsonRenderer extends Renderer {
}
}
- @Override
- void list(String cssClass, List<String> data) {
+ /** @inheritDoc */
+ public void list(String cssClass, List<String> data) {
try {
startItem("list");
writer.key(INFO_SUBTYPE_KEY).value(cssClass);
@@ -92,11 +105,16 @@ class JsonRenderer extends Renderer {
}
}
- @Override
- void title(int level, String title) {
+ /** @inheritDoc */
+ public void title(int level, String title) {
// Titles are not needed
}
+ /** @inheritDoc */
+ public RunListener getRunListener() {
+ return this;
+ }
+
@Override
public void testStarted(Description description) throws Exception {
super.testStarted(description);
Modified:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/PlainTextRenderer.java
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/PlainTextRenderer.java?rev=1073712&r1=1073711&r2=1073712&view=diff
==============================================================================
---
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/PlainTextRenderer.java
(original)
+++
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/PlainTextRenderer.java
Wed Feb 23 12:00:41 2011
@@ -23,13 +23,27 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.junit.Renderer;
+import org.apache.sling.junit.RequestParser;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
-class PlainTextRenderer extends Renderer {
+@Component(immediate=false)
+@Service
+/** Plain text renderer */
+public class PlainTextRenderer extends RunListener implements Renderer {
private PrintWriter output;
+ /** @inheritDoc */
+ public boolean appliesTo(RequestParser p) {
+ return "txt".equals(p.getExtension());
+ }
+
+ /** @inheritDoc */
public void setup(HttpServletResponse response, String pageTitle) throws
IOException, UnsupportedEncodingException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
@@ -37,23 +51,32 @@ class PlainTextRenderer extends Renderer
title(1, pageTitle);
}
+ /** @inheritDoc */
public void cleanup() {
}
+ /** @inheritDoc */
public void info(String cssClass, String str) {
output.println(str);
}
+ /** @inheritDoc */
public void list(String cssClass, List<String> data) {
for(String str : data) {
output.println(str);
}
}
+ /** @inheritDoc */
public void title(int level, String title) {
output.print(title);
output.println(" ****");
}
+
+ /** @inheritDoc */
+ public RunListener getRunListener() {
+ return this;
+ }
@Override
public void testFailure(Failure failure) throws Exception {
Modified:
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/XmlRenderer.java
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/XmlRenderer.java?rev=1073712&r1=1073711&r2=1073712&view=diff
==============================================================================
---
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/XmlRenderer.java
(original)
+++
sling/trunk/testing/junit/core/src/main/java/org/apache/sling/junit/impl/servlet/XmlRenderer.java
Wed Feb 23 12:00:41 2011
@@ -38,14 +38,22 @@ import javax.xml.transform.stream.Stream
import junit.runner.BaseTestRunner;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.junit.Renderer;
+import org.apache.sling.junit.RequestParser;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
-public class XmlRenderer extends Renderer {
+/** XML renderer for JUnit servlet */
+@Component(immediate=false)
+@Service
+public class XmlRenderer extends RunListener implements Renderer {
/**
* Writer used for output.
@@ -97,6 +105,12 @@ public class XmlRenderer extends Rendere
*/
private int testSuiteCount = 0;
+ /** @inheritDoc */
+ public boolean appliesTo(RequestParser p) {
+ return "xml".equals(p.getExtension());
+ }
+
+ /** @inheritDoc */
public void setup(HttpServletResponse response, String pageTitle)
throws IOException, UnsupportedEncodingException {
suiteStartTime = System.currentTimeMillis();
@@ -110,23 +124,32 @@ public class XmlRenderer extends Rendere
}
+ /** @inheritDoc */
public void info(String cssClass, String str) {
}
+ /** @inheritDoc */
public void list(String cssClass, List<String> data) {
}
+ /** @inheritDoc */
public void title(int level, String title) {
if (level == 3)
name = title;
}
+ /** @inheritDoc */
public void cleanup() {
if (testSuiteCount > 1)
output.println(getStringFromElement(suitesElement));
else
output.println(getStringFromElement(rootElement));
}
+
+ /** @inheritDoc */
+ public RunListener getRunListener() {
+ return this;
+ }
@Override
public void testFailure(Failure failure) throws Exception {