blob: d0b2738b41f3d828a23d8102609ace34563a55ba [file] [log] [blame]
/*
* 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.apache.sling.tracer.internal;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.zip.GZIPInputStream;
import javax.json.Json;
import javax.json.JsonObject;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
import org.jetbrains.annotations.NotNull;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import static org.apache.sling.tracer.internal.TestUtil.createTracker;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class TracerLogServletTest {
@Rule
public final OsgiContext context = new OsgiContext();
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Mock
private HttpServletRequest request;
@Mock
private HttpServletResponse response;
@Test
public void noRecordingByDefault() throws Exception{
TracerLogServlet logServlet = newLogServlet();
assertSame(Recording.NOOP, logServlet.startRecording(request, response));
assertSame(Recording.NOOP, logServlet.getRecordingForRequest(request));
}
@Test
public void recordingWhenRequested() throws Exception{
TracerLogServlet logServlet = newLogServlet();
request = new MockSlingHttpServletRequest(context.bundleContext());
Recording recording = logServlet.startRecording(request, response);
assertNotNull(recording);
//Once recording is created then it should be returned
Recording recording2 = logServlet.getRecordingForRequest(request);
assertSame(recording, recording2);
//Repeated call should return same recording instance
Recording recording3 = logServlet.startRecording(request, response);
assertSame(recording, recording3);
logServlet.resetCache();
//If recording gets lost then NOOP must be returned
Recording recording4 = logServlet.getRecordingForRequest(request);
assertSame(Recording.NOOP, recording4);
}
@Test
public void jsonRendering() throws Exception{
TracerLogServlet logServlet = newLogServlet();
when(request.getMethod()).thenReturn("GET");
when(request.getHeader(TracerLogServlet.HEADER_TRACER_RECORDING)).thenReturn("true");
Recording recording = logServlet.startRecording(request, response);
recording.registerTracker(createTracker("x" ,"y"));
logServlet.endRecording(request, recording);
ArgumentCaptor<String> requestIdCaptor = ArgumentCaptor.forClass(String.class);
verify(response).setHeader(eq(TracerLogServlet.HEADER_TRACER_REQUEST_ID), requestIdCaptor.capture());
verify(response).setHeader(TracerLogServlet.HEADER_TRACER_PROTOCOL_VERSION,
String.valueOf(TracerLogServlet.TRACER_PROTOCOL_VERSION));
ByteArrayServletOutputStream sos = new ByteArrayServletOutputStream();
when(response.getOutputStream()).thenReturn(sos);
when(request.getRequestURI()).thenReturn("/system/console/" + requestIdCaptor.getValue() + ".json" );
logServlet.renderContent(request, response);
JsonObject json = Json.createReader(new StringReader(sos.baos.toString("UTF-8"))).readObject();
assertEquals("GET", json.getString("method"));
assertEquals(2, json.getJsonArray("requestProgressLogs").size());
}
@Test
public void gzipResponse() throws Exception{
TracerLogServlet logServlet = newLogServlet();
when(request.getMethod()).thenReturn("GET");
when(request.getHeader(TracerLogServlet.HEADER_TRACER_RECORDING)).thenReturn("true");
when(request.getHeader("Accept-Encoding")).thenReturn("gzip, deflate");
Recording recording = logServlet.startRecording(request, response);
recording.registerTracker(createTracker("x" ,"y"));
logServlet.endRecording(request, recording);
ArgumentCaptor<String> requestIdCaptor = ArgumentCaptor.forClass(String.class);
verify(response).setHeader(eq(TracerLogServlet.HEADER_TRACER_REQUEST_ID), requestIdCaptor.capture());
verify(response).setHeader(TracerLogServlet.HEADER_TRACER_PROTOCOL_VERSION,
String.valueOf(TracerLogServlet.TRACER_PROTOCOL_VERSION));
ByteArrayServletOutputStream sos = new ByteArrayServletOutputStream();
when(response.getOutputStream()).thenReturn(sos);
when(request.getRequestURI()).thenReturn("/system/console/" + requestIdCaptor.getValue() + ".json" );
logServlet.renderContent(request, response);
byte[] data = IOUtils.toByteArray(new GZIPInputStream(new ByteArrayInputStream(sos.baos.toByteArray())));
JsonObject json = Json.createReader(new StringReader(new String(data, "UTF-8"))).readObject();
assertEquals("GET", json.getString("method"));
assertEquals(2, json.getJsonArray("requestProgressLogs").size());
verify(response).setHeader("Content-Encoding" , "gzip");
}
private TracerLogServlet newLogServlet() {
return new TracerLogServlet(context.bundleContext(), 50, 60*15, true, true);
}
@Test
public void pluginRendering() throws Exception{
TracerLogServlet logServlet = newLogServlet();
when(request.getRequestURI()).thenReturn("/system/console/tracer" );
StringWriter sw = new StringWriter();
when(response.getWriter()).thenReturn(new PrintWriter(sw));
logServlet.renderContent(request, response);
assertTrue(sw.toString().contains("Log Tracer"));
}
private static class ByteArrayServletOutputStream extends ServletOutputStream {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
@Override
public void write(int b) throws IOException {
baos.write(b);
}
@Override
public void write(@NotNull byte[] b, int off, int len) throws IOException {
baos.write(b, off, len);
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
}
}