/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.testing.server;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.eclipse.che.api.testing.server.framework.TestFrameworkRegistry;
import org.eclipse.che.api.testing.server.framework.TestRunner;
import org.eclipse.che.api.testing.shared.TestResult;
import org.eclipse.core.resources.ResourcesPlugin;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
/**
* Service for handling Che unit test frameworks.
*
* @author Mirage Abeysekara
*/
@Api(value = "/che-testing")
@Path("che/testing")
public class TestingService {
private final TestFrameworkRegistry frameworkRegistry;
@Inject
public TestingService(TestFrameworkRegistry frameworkRegistry) {
this.frameworkRegistry = frameworkRegistry;
}
/**
* Execute the Java test cases and return the test result.
*
* <pre>
* Required request parameters.
* <em>projectPath</em> : Relative path to the project directory.
* <em>testFramework</em> : Name of the test framework where the tests should be run on. This should match with
* the name returned by {@link TestRunner#getName()} implementation.
* </pre>
*
* @param uriInfo JAX-RS implementation of UrlInfo with set of query parameters.
* @return the test result of test case
* @throws Exception when the test runner failed to execute test cases.
*/
@GET
@Path("run")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Execute Java tests and return results",
notes = "The GET parameters are passed to the test framework implementation.")
@ApiResponses({@ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Server error")})
public TestResult run(@Context UriInfo uriInfo) throws Exception {
try {
Map<String, String> queryParameters = getMap(uriInfo.getQueryParameters());
String projectPath = queryParameters.get("projectPath");
String absoluteProjectPath = ResourcesPlugin.getPathToWorkspace() + projectPath;
queryParameters.put("absoluteProjectPath", absoluteProjectPath);
String testFramework = queryParameters.get("testFramework");
TestRunner runner = frameworkRegistry.getTestRunner(testFramework);
if (runner == null) {
throw new WebApplicationException("No test frameworks found: " + testFramework);
}
TestResult result = frameworkRegistry.getTestRunner(testFramework).execute(queryParameters);
return result;
} catch (Throwable e) {
throw translateException(e);
}
}
private WebApplicationException translateException(Throwable e) {
if (e instanceof WebApplicationException) {
return (WebApplicationException)e;
}
Throwable cause = null;
if (e instanceof InvocationTargetException) {
cause = e.getCause();
}
if (e instanceof RuntimeException) {
cause = e.getCause();
}
if (cause != null && cause != e) {
return translateException(cause);
}
return new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("An unexpected error occured during test execution: " + e.toString()).build());
}
private Map<String, String> getMap(MultivaluedMap<String, String> queryParameters) {
Map<String, String> map = new HashMap<>();
if (queryParameters == null) {
return map;
}
for (Map.Entry<String, List<String>> entry : queryParameters.entrySet()) {
StringBuilder sb = new StringBuilder();
for (String s : entry.getValue()) {
if (sb.length() > 0) {
sb.append(',');
}
sb.append(s);
}
map.put(entry.getKey(), sb.toString());
}
return map;
}
}