Author: chetanm
Date: Tue Apr 7 09:32:22 2015
New Revision: 1671773
URL: http://svn.apache.org/r1671773
Log:
OAK-2721 - LogDumper rule to dump logs as part of system out in case of test
failure
Added:
jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/junit/
jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/junit/LogDumper.java
(with props)
Added:
jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/junit/LogDumper.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/junit/LogDumper.java?rev=1671773&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/junit/LogDumper.java
(added)
+++
jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/junit/LogDumper.java
Tue Apr 7 09:32:22 2015
@@ -0,0 +1,147 @@
+/*
+ * 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.jackrabbit.oak.commons.junit;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.PatternLayout;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.read.CyclicBufferAppender;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The LogDumper Rule collects logs which are generated due to execution of
test and dumps them
+ * locally upon test failure. This simplifies determining failure
+ * cause by providing all required data locally. This would be specially
useful when running test
+ * in CI server where server logs gets cluttered with all other test executions
+ * <p/>
+ * <pre>
+ * public class LoginTestIT {
+ *
+ * @Rule
+ * public TestRule logDumper = new LogDumper();
+ *
+ * @Test
+ * public void remoteLogin() {
+ * //test stuff
+ * assertEquals("testA", name.getMethodName());
+ * }
+ *
+ * }
+ * </pre>
+ */
+public class LogDumper extends TestWatcher {
+ /**
+ * Number of log entries to keep in memory
+ */
+ private static final int LOG_BUFFER_SIZE = 1000;
+
+ /**
+ * Message pattern used to render logs
+ */
+ private static final String DEFAULT_PATTERN = "%d{dd.MM.yyyy HH:mm:ss.SSS}
*%level* [%thread] %logger %msg%n";
+
+ private CyclicBufferAppender<ILoggingEvent> appender;
+
+ @Override
+ protected void finished(Description description) {
+ deregisterAppender();
+ }
+
+ @Override
+ protected void starting(Description description) {
+ registerAppender();
+ }
+
+ @Override
+ protected void failed(Throwable e, Description description) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+
+ try {
+ String msg = e.getMessage();
+ if (msg != null) {
+ pw.println(msg);
+ }
+
+ pw.printf("=============== Logs for [%s#%s]===================%n",
+ description.getClassName(), description.getMethodName());
+ pw.print(getLogs());
+
pw.println("========================================================");
+
+
+ } catch (Throwable t) {
+ System.err.println("Error occurred while fetching test logs");
+ t.printStackTrace(System.err);
+ }
+
+ System.err.print(sw.toString());
+ }
+
+ private String getLogs() {
+ if (appender == null) {
+ return "<Logs cannot be determined>";
+ }
+ PatternLayout layout = createLayout();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < appender.getLength(); i++) {
+ sb.append(layout.doLayout(appender.get(i)));
+ }
+ return sb.toString();
+ }
+
+ private void registerAppender() {
+ appender = new CyclicBufferAppender<ILoggingEvent>();
+ appender.setMaxSize(LOG_BUFFER_SIZE);
+ appender.setContext(getContext());
+ appender.setName("TestLogCollector");
+ appender.start();
+ rootLogger().addAppender(appender);
+ }
+
+ private void deregisterAppender() {
+ if (appender != null) {
+ rootLogger().detachAppender(appender);
+ appender.stop();
+ appender = null;
+ }
+ }
+
+ private static PatternLayout createLayout() {
+ PatternLayout pl = new PatternLayout();
+ pl.setPattern(DEFAULT_PATTERN);
+ pl.setOutputPatternAsHeader(false);
+ pl.setContext(getContext());
+ pl.start();
+ return pl;
+ }
+
+ private static LoggerContext getContext() {
+ return (LoggerContext) LoggerFactory.getILoggerFactory();
+ }
+
+ private static ch.qos.logback.classic.Logger rootLogger() {
+ return
getContext().getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/junit/LogDumper.java
------------------------------------------------------------------------------
svn:eol-style = native