use of io.github.microcks.domain.TestReturn in project microcks by microcks.
the class SoapUITestStepsRunner method runOperationTestSteps.
/**
* Run all the Operation test steps defined into the SoapUI project and having the name
* contained into testStepNames (if not null nor empty).
* @param operation The operation to run tests for
* @param testResult TestResults that aggregate results within.
* @param endpointUrl The URL of the endpoint to use for request test steps.
* @param testStepNames A list of test step names to execute
* @return A list of TestReturn wrapper objects (one by executed test step)
*/
public List<TestReturn> runOperationTestSteps(Operation operation, TestResult testResult, String endpointUrl, List<String> testStepNames) {
// Remember to force no proxy otherwise SoapUI will use system settings and will
// make them generally applied to everything going out through Apache Http Client
// (and maybe also JDK HttpURLConnection ?).
ProxyUtils.setProxyEnabled(false);
String operationName = operation.getName();
List<TestReturn> results = new ArrayList<TestReturn>();
for (TestSuite testSuite : project.getTestSuiteList()) {
for (TestCase testCase : testSuite.getTestCaseList()) {
// Depending on testCase type build an accurate runner.
TestCaseRunner testCaseRunner = buildTestCaseRunner(testCase);
if (testCaseRunner != null) {
for (TestStep testStep : testCase.getTestStepList()) {
if (testStep instanceof HttpRequestTestStep && testStep instanceof OperationTestStep && (testStepNames == null || testStepNames.contains(testStep.getName()))) {
log.debug("Looking up for testStep for operation '{}'", operationName);
if (operationName.equals(((OperationTestStep) testStep).getOperation().getName())) {
log.debug("Picking up step '{}' for running SoapUI test", testStep.getName());
// Set the endpointUrl using this common interface for Soap and Rest requests.
((HttpRequestTestStep) testStep).getHttpRequest().setEndpoint(endpointUrl);
// Add or override existing headers with test specific ones for operation and globals.
if (testResult.getOperationsHeaders() != null) {
Set<Header> headers = new HashSet<>();
if (testResult.getOperationsHeaders().getGlobals() != null) {
headers.addAll(testResult.getOperationsHeaders().getGlobals());
}
if (testResult.getOperationsHeaders().get(operationName) != null) {
headers.addAll(testResult.getOperationsHeaders().get(operationName));
}
if (headers.size() > 0) {
StringToStringsMap headersMap = new StringToStringsMap();
for (Header header : headers) {
headersMap.put(header.getName(), new ArrayList<>(header.getValues()));
}
((HttpRequestTestStep) testStep).getHttpRequest().setRequestHeaders(headersMap);
}
}
// Running tests also checks linked assertions.
TestStepResult result = testStep.run(testCaseRunner, testCaseRunner.getRunContext());
log.debug("SoapUI test result is " + result.getStatus());
results.add(extractTestReturn(testStep.getName(), result));
}
}
}
}
}
}
return results;
}
use of io.github.microcks.domain.TestReturn in project microcks by microcks.
the class SoapUITestStepsRunner method extractTestReturn.
/**
*/
private TestReturn extractTestReturn(String testStepName, TestStepResult result) {
int code = TestReturn.FAILURE_CODE;
if (result.getStatus() == TestStepStatus.OK) {
code = TestReturn.SUCCESS_CODE;
}
String message = null;
// Re-build request and response.
Request request = new Request();
request.setName(testStepName);
Response response = new Response();
// SoapUI step result class do not implement a common interface...
if (result instanceof WsdlTestRequestStepResult) {
WsdlTestRequestStepResult wtrsr = (WsdlTestRequestStepResult) result;
request.setContent(wtrsr.getRequestContent());
request.setHeaders(buildHeaders(wtrsr.getRequestHeaders()));
response.setContent(wtrsr.getResponseContent());
response.setHeaders(buildHeaders(wtrsr.getResponseHeaders()));
message = buildConsolidatedMessage(wtrsr.getMessages());
}
if (result instanceof RestRequestStepResult) {
RestRequestStepResult rrsr = (RestRequestStepResult) result;
request.setContent(rrsr.getRequestContent());
request.setHeaders(buildHeaders(rrsr.getRequestHeaders()));
response.setContent(rrsr.getResponseContent());
response.setHeaders(buildHeaders(rrsr.getResponseHeaders()));
message = buildConsolidatedMessage(rrsr.getMessages());
// or if endpoint is not reached. Consider 404 as a failure in our case.
if (result.getStatus() == TestStepStatus.UNKNOWN) {
if (rrsr.getResponse().getStatusCode() == 404) {
code = TestReturn.FAILURE_CODE;
} else {
code = TestReturn.SUCCESS_CODE;
}
}
}
return new TestReturn(code, result.getTimeTaken(), message, request, response);
}
use of io.github.microcks.domain.TestReturn in project microcks by microcks.
the class HttpTestRunner method runTest.
@Override
public List<TestReturn> runTest(Service service, Operation operation, TestResult testResult, List<Request> requests, String endpointUrl, HttpMethod method) throws URISyntaxException, IOException {
if (log.isDebugEnabled()) {
log.debug("Launching test run on " + endpointUrl + " for " + requests.size() + " request(s)");
}
if (requests.isEmpty()) {
return null;
}
// Initialize result container.
List<TestReturn> result = new ArrayList<TestReturn>();
for (Request request : requests) {
// Reset status code, message and request each time.
int code = TestReturn.SUCCESS_CODE;
String message = null;
String customizedEndpointUrl = endpointUrl;
if (service.getType().equals(ServiceType.REST)) {
String operationName = operation.getName();
// Name may start with verb, remove it if present.
if (operationName.indexOf(' ') > 0 && operationName.indexOf(' ') < operationName.length()) {
operationName = operationName.split(" ")[1];
}
customizedEndpointUrl += URIBuilder.buildURIFromPattern(operationName, request.getQueryParameters());
log.debug("Using customized endpoint url: " + customizedEndpointUrl);
}
ClientHttpRequest httpRequest = clientHttpRequestFactory.createRequest(new URI(customizedEndpointUrl), method);
// Set headers to request if any. Start with those coming from request itself.
// Add or override existing headers with test specific ones for operation and globals.
Set<Header> headers = new HashSet<>();
if (request.getHeaders() != null) {
headers.addAll(request.getHeaders());
}
if (testResult.getOperationsHeaders() != null) {
if (testResult.getOperationsHeaders().getGlobals() != null) {
headers.addAll(testResult.getOperationsHeaders().getGlobals());
}
if (testResult.getOperationsHeaders().get(operation.getName()) != null) {
headers.addAll(testResult.getOperationsHeaders().get(operation.getName()));
}
}
if (headers.size() > 0) {
for (Header header : headers) {
log.debug("Adding header " + header.getName() + " to request");
httpRequest.getHeaders().add(header.getName(), buildValue(header.getValues()));
}
// Update request headers for traceability of possibly added ones.
request.setHeaders(headers);
}
// Now manage specific authorization headers if there's a secret.
if (secret != null) {
addAuthorizationHeadersFromSecret(httpRequest, request, secret);
}
// Allow extensions to realize some pre-processing of request.
prepareRequest(request);
// If there's input content, add it to request.
if (request.getContent() != null) {
// Update request content with rendered body if necessary.
request.setContent(TestRunnerCommons.renderRequestContent(request, headers));
log.trace("Sending following request content: " + request.getContent());
httpRequest.getBody().write(request.getContent().getBytes());
}
// Actually execute request.
long startTime = System.currentTimeMillis();
ClientHttpResponse httpResponse = null;
try {
httpResponse = httpRequest.execute();
} catch (IOException ioe) {
log.error("IOException while executing request " + request.getName() + " on " + endpointUrl, ioe);
code = TestReturn.FAILURE_CODE;
message = ioe.getMessage();
}
long duration = System.currentTimeMillis() - startTime;
// Extract and store response body so that stream may not be consumed more than o1 time ;-)
String responseContent = null;
if (httpResponse != null) {
StringWriter writer = new StringWriter();
IOUtils.copy(httpResponse.getBody(), writer);
responseContent = writer.toString();
}
// If still in success, check if http code is out of correct ranges (20x and 30x).
if (code == TestReturn.SUCCESS_CODE) {
code = extractTestReturnCode(service, operation, request, httpResponse, responseContent);
message = extractTestReturnMessage(service, operation, request, httpResponse);
}
// Create a Response object for returning.
Response response = new Response();
if (httpResponse != null) {
response.setContent(responseContent);
response.setStatus(String.valueOf(httpResponse.getRawStatusCode()));
log.debug("Response Content-Type: " + httpResponse.getHeaders().getContentType());
if (httpResponse.getHeaders().getContentType() != null) {
response.setMediaType(httpResponse.getHeaders().getContentType().toString());
}
headers = buildHeaders(httpResponse);
if (headers != null) {
response.setHeaders(headers);
}
httpResponse.close();
}
result.add(new TestReturn(code, duration, message, request, response));
}
return result;
}
use of io.github.microcks.domain.TestReturn in project microcks by microcks.
the class GrpcTestRunner method runTest.
@Override
public List<TestReturn> runTest(Service service, Operation operation, TestResult testResult, List<Request> requests, String endpointUrl, HttpMethod method) throws URISyntaxException, IOException {
log.debug("Launching test run on {} for {} request(s)", endpointUrl, requests.size());
if (requests.isEmpty()) {
return null;
}
// Initialize results.
List<TestReturn> results = new ArrayList<>();
// Rebuild the GRPC fullMethodName.
String fullMethodName = service.getXmlNS() + "." + service.getName() + "/" + operation.getName();
// Build a new GRPC Channel from endpoint URL.
URL endpoint = new URL(endpointUrl);
ManagedChannel channel;
if (endpointUrl.startsWith("https://") || endpoint.getPort() == 443) {
TlsChannelCredentials.Builder tlsBuilder = TlsChannelCredentials.newBuilder();
if (secret != null && secret.getCaCertPem() != null) {
// Install a trust manager with custom CA certificate.
tlsBuilder.trustManager(new ByteArrayInputStream(secret.getCaCertPem().getBytes(StandardCharsets.UTF_8)));
} else {
// Install a trust manager that accepts everything and does not validate certificate chains.
tlsBuilder.trustManager(new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} });
}
// Build a Channel using the TLS Builder.
channel = Grpc.newChannelBuilderForAddress(endpoint.getHost(), endpoint.getPort(), tlsBuilder.build()).build();
} else {
// Build a simple Channel using plain text.
channel = Grpc.newChannelBuilderForAddress(endpoint.getHost(), endpoint.getPort(), null).usePlaintext().build();
}
// In order to produce outgoing byte array, we need the Protobuf binary descriptor that should
// have been processed while importing the .proto schema for the service.
List<Resource> resources = resourceRepository.findByServiceIdAndType(service.getId(), ResourceType.PROTOBUF_DESCRIPTOR);
if (resources == null || resources.size() != 1) {
log.error("Could not found any pre-processed Protobuf binary descriptor...");
results.add(new TestReturn(TestReturn.FAILURE_CODE, 0, "Could not found any pre-processed Protobuf binary descriptor...", null, null));
return results;
}
Resource pbResource = resources.get(0);
Descriptors.MethodDescriptor md = null;
try {
md = GrpcUtil.findMethodDescriptor(pbResource.getContent(), service.getName(), operation.getName());
} catch (Exception e) {
log.error("Protobuf descriptor cannot be read or parsed: " + e.getMessage());
results.add(new TestReturn(TestReturn.FAILURE_CODE, 0, "Protobuf descriptor cannot be read or parsed: " + e.getMessage(), null, null));
return results;
}
// Use a builder for out type with a Json parser to merge content and build outMsg.
DynamicMessage.Builder reqBuilder = DynamicMessage.newBuilder(md.getInputType());
DynamicMessage.Builder resBuilder = DynamicMessage.newBuilder(md.getOutputType());
JsonFormat.Parser parser = JsonFormat.parser();
JsonFormat.Printer printer = JsonFormat.printer();
for (Request request : requests) {
// Reset status code, message and request each time.
int code = TestReturn.SUCCESS_CODE;
String message = null;
reqBuilder.clear();
resBuilder.clear();
// Now produce the request message byte array.
parser.merge(request.getContent(), reqBuilder);
byte[] requestBytes = reqBuilder.build().toByteArray();
CallOptions callOptions = CallOptions.DEFAULT.withDeadline(Deadline.after(timeout, TimeUnit.MILLISECONDS));
if (secret != null && secret.getToken() != null) {
log.debug("Secret contains token and maybe token header, adding them as call credentials");
callOptions.withCallCredentials(new TokenCallCredentials(secret.getToken(), secret.getTokenHeader()));
}
// Actually execute request.
long startTime = System.currentTimeMillis();
byte[] responseBytes = ClientCalls.blockingUnaryCall(channel, GrpcUtil.buildGenericUnaryMethodDescriptor(fullMethodName), callOptions, requestBytes);
long duration = System.currentTimeMillis() - startTime;
// Create a Response object for returning.
Response response = new Response();
response.setStatus("200");
response.setMediaType("application/x-protobuf");
response.setContent(new String(responseBytes, "UTF-8"));
try {
// Validate incoming message parsing a DynamicMessage.
DynamicMessage respMsg = DynamicMessage.parseFrom(md.getOutputType(), responseBytes);
// Now update response content with readable content.
String respJson = printer.print(respMsg);
response.setContent(respJson);
results.add(new TestReturn(code, duration, message, request, response));
} catch (InvalidProtocolBufferException ipbe) {
log.error("Received bytes cannot be transformed in " + md.getOutputType().getFullName());
results.add(new TestReturn(TestReturn.FAILURE_CODE, duration, "Received bytes cannot be transformed in \" + md.getOutputType().getFullName()", request, response));
}
}
return results;
}
use of io.github.microcks.domain.TestReturn in project microcks by microcks.
the class TestRunnerService method launchTestsInternal.
/**
* Launch tests using asynchronous/completable future pattern.
* @param testResult TestResults to aggregate results within
* @param service Service to test
* @param runnerType Type of runner for launching the tests
* @return A Future wrapping test results
*/
@Async
public CompletableFuture<TestResult> launchTestsInternal(TestResult testResult, Service service, TestRunnerType runnerType) {
// Found next build number for this test.
List<TestResult> older = testResultRepository.findByServiceId(service.getId(), PageRequest.of(0, 2, Sort.Direction.DESC, "testNumber"));
if (older != null && !older.isEmpty() && older.get(0).getTestNumber() != null) {
testResult.setTestNumber(older.get(0).getTestNumber() + 1L);
} else {
testResult.setTestNumber(1L);
}
Secret secret = null;
if (testResult.getSecretRef() != null) {
secret = secretRepository.findById(testResult.getSecretRef().getSecretId()).orElse(null);
log.debug("Using a secret to test endpoint? '{}'", secret != null ? secret.getName() : "none");
}
// Initialize runner once as it is shared for each test.
AbstractTestRunner<HttpMethod> testRunner = retrieveRunner(runnerType, secret, testResult.getTimeout(), service.getId());
if (testRunner == null) {
// Set failure and stopped flags and save before exiting.
testResult.setSuccess(false);
testResult.setInProgress(false);
testResult.setElapsedTime(0);
testResultRepository.save(testResult);
return CompletableFuture.completedFuture(testResult);
}
for (TestCaseResult testCaseResult : testResult.getTestCaseResults()) {
// Retrieve operation corresponding to testCase.
Operation operation = service.getOperations().stream().filter(o -> o.getName().equals(testCaseResult.getOperationName())).findFirst().get();
String testCaseId = IdBuilder.buildTestCaseId(testResult, operation);
// Prepare collection of requests to launch.
List<Request> requests = requestRepository.findByOperationId(IdBuilder.buildOperationId(service, operation));
requests = cloneRequestsForTestCase(requests, testCaseId);
List<TestReturn> results = new ArrayList<>();
try {
HttpMethod method = testRunner.buildMethod(operation.getMethod());
results = testRunner.runTest(service, operation, testResult, requests, testResult.getTestedEndpoint(), method);
} catch (URISyntaxException use) {
log.error("URISyntaxException on endpoint {}, aborting current tests", testResult.getTestedEndpoint(), use);
// Set flags and add to results before exiting loop.
testCaseResult.setSuccess(false);
testCaseResult.setElapsedTime(0);
testResultRepository.save(testResult);
break;
} catch (Throwable t) {
log.error("Throwable while testing operation {}", operation.getName(), t);
}
// sample request for that operation -> mark it as failed.
if (results == null) {
testCaseResult.setSuccess(false);
testCaseResult.setElapsedTime(0);
testResultRepository.save(testResult);
} else if (!results.isEmpty()) {
updateTestCaseResultWithReturns(testCaseResult, results, testCaseId);
testResultRepository.save(testResult);
}
}
// Update success, progress indicators and total time before saving and returning.
updateTestResult(testResult);
return CompletableFuture.completedFuture(testResult);
}
Aggregations