All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.cq.testing.junit.rules.LogTracerRule Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017 Adobe Systems Incorporated
 *
 * Licensed 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 com.adobe.cq.testing.junit.rules;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.apache.sling.testing.clients.ClientException;
import org.apache.sling.testing.clients.SlingClient;
import org.apache.sling.testing.clients.SlingHttpResponse;
import org.apache.sling.testing.clients.osgi.OsgiConsoleClient;
import org.apache.sling.testing.clients.osgi.OsgiInstanceConfig;
import org.apache.sling.testing.clients.util.JsonUtils;
import org.apache.sling.testing.clients.util.config.InstanceConfigException;
import org.apache.sling.testing.clients.util.config.impl.InstanceConfigCacheImpl;
import org.apache.sling.testing.clients.util.poller.Polling;
import org.apache.sling.testing.junit.rules.instance.Instance;

import org.junit.Assert;
import org.junit.rules.ExternalResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import static org.apache.http.HttpStatus.SC_MOVED_TEMPORARILY;
import static org.apache.http.HttpStatus.SC_OK;

public class LogTracerRule extends ExternalResource {

    private final Logger logger = LoggerFactory.getLogger(OsgiConfigRestoreRule.class);
    private final String pid = "org.apache.sling.tracer.internal.LogTracer";
    private final Instance quickstartRule;
    private OsgiConsoleClient client;
    private InstanceConfigCacheImpl configs;

    private int recordingCacheSizeInMB = 50;
    private int recordingCacheDurationInSecs = 900;

    // Request headers required to configure log tracer for each request
    private List
tracerHeaders = Arrays.
asList( new BasicHeader("Sling-Tracer-Record", "true"), new BasicHeader("Sling-Tracer-Config", "com.day;level=error,com.adobe;level=error,org.apache;level=error") ); public LogTracerRule(Instance quickstartRule) { super(); this.quickstartRule = quickstartRule; } public LogTracerRule(Instance quickstartRule, int recordingCacheSizeInMB, int recordingCacheDurationInSecs) { super(); this.quickstartRule = quickstartRule; this.recordingCacheSizeInMB = recordingCacheSizeInMB; this.recordingCacheDurationInSecs = recordingCacheDurationInSecs; } public List
getTracerHeaders() { return this.tracerHeaders; } public void setTracerHeaders(List
headers) { this.tracerHeaders = headers; } /** * Store the state of the log tracer configuration and enable it. */ @Override protected void before() throws ClientException, InstanceConfigException, InterruptedException { // Store existing config this.client = this.quickstartRule.getAdminClient(OsgiConsoleClient.class); this.configs = new InstanceConfigCacheImpl(); this.configs.add(new OsgiInstanceConfig(this.client, this.pid)); // Update config Map config = new HashMap<>(); config.put("enabled", "true"); config.put("servletEnabled", "true"); config.put("recordingCacheSizeInMB", String.valueOf(this.recordingCacheSizeInMB)); config.put("recordingCacheDurationInSecs", String.valueOf(this.recordingCacheDurationInSecs)); try { this.client.waitEditConfiguration(30000, this.pid, null, config, SC_MOVED_TEMPORARILY); config = this.client.waitGetConfiguration(30000, this.pid, SC_OK); } catch (TimeoutException e) { throw new ClientException("Failed editing configuration for " + this.pid, e); } Assert.assertEquals(config.get("enabled"), "true"); Assert.assertEquals(config.get("servletEnabled"), "true"); } /** * Restore the original configuration state of the log tracer. */ @Override protected void after() { try { this.configs.restore(); } catch (InstanceConfigException | InterruptedException e) { logger.error("Could not restore OSGi config.", e); } } /** * Parse the tracer request id from the given response object and return the corresponding tracer report from the tracer servlet as * JSON object. * * @param response SlingHttpResponse object * @return Request report as JSONObject * @throws ClientException if the request fails * @throws InterruptedException to mark this method as waiting */ public JsonNode getTracerReport(SlingHttpResponse response) throws ClientException, InterruptedException { // Parse tracer request id Header requestIdHeader = response.getFirstHeader("Sling-Tracer-Request-Id"); // TODO: Don't fail for flaky behaviour // Assert.assertNotNull(requestIdHeader); if(requestIdHeader == null) { logger.warn("Request did not include Sling-Tracer-Request-Id header."); return new ObjectMapper().createObjectNode(); } String requestId = requestIdHeader.getValue(); // Parse log data from tracer servlet using the request id LogReportPoller poller = new LogReportPoller(requestId, this.client); try { poller.poll(2000, 100); } catch (TimeoutException e) { throw new ClientException("Failed to retrieve logs", e); } return poller.logJson; } /** * Parse the tracer request id from the given response object and return the corresponding logs from the tracer servlet as * JSON array. * * @param response SlingHttpResponse object * @return Request logs as JSONArray * @throws ClientException if the request fails * @throws InterruptedException to mark this method as waiting */ public JsonNode getLogs(SlingHttpResponse response) throws ClientException, InterruptedException { JsonNode report = this.getTracerReport(response); if (report.get("logs") == null) { return new ObjectMapper().createObjectNode(); } return report.get("logs"); } /** * Parse the tracer request id from the given response object and check if there are any entries in the corresponding log. * Marks the test case from which this method was called as failed if there are any log entries. * * @param response SlingHttpResponse object * @throws ClientException if the request fails * @throws InterruptedException to mark this method as waiting */ public void verifyLog(SlingHttpResponse response) throws ClientException, InterruptedException { JsonNode report = this.getTracerReport(response); // TODO: Don't fail for flaky behaviour if (report.get("logs") == null) { return; } JsonNode logs = report.get("logs"); if (logs.isArray() && logs.size() > 0) { Assert.fail("Found error in log: " + logs.get(0)); } } private class LogReportPoller extends Polling { public String requestId; public SlingClient client; public JsonNode logJson; public LogReportPoller(String requestId, SlingClient client) { super(); this.requestId = requestId; this.client = client; } @Override public Boolean call() throws ClientException { SlingHttpResponse logResponse = this.client.doGet("/system/console/tracer/" + requestId + ".json", SC_OK); this.logJson = JsonUtils.getJsonNodeFromString(logResponse.getContent()); return this.logJson.get("logs") != null; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy