dependency 'javax.servlet:javax.servlet-api:3.1.0'
dependency 'javax.xml.bind:jaxb-api:2.3.0'
dependency 'junit:junit:4.12'
+ dependency 'org.junit.jupiter:junit-jupiter-api:5.5.2'
dependency 'net.jpountz.lz4:lz4:1.3.0'
dependency 'net.lightbody.bmp:littleproxy:1.1.0-beta-bmp-17'
dependency 'org.awaitility:awaitility:4.0.1'
compileOnly 'com.google.code.findbugs:jsr305'
compileOnly 'javax.servlet:javax.servlet-api'
compileOnly 'junit:junit'
+ // Used by LogTesterJUnit5
+ compileOnly 'org.junit.jupiter:junit-jupiter-api'
compileOnly 'org.slf4j:slf4j-api'
testCompile 'com.google.guava:guava'
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.utils.log;
+
+import java.util.List;
+
+class AbstractLogTester {
+
+ protected void before() {
+ // this shared instance breaks compatibility with parallel execution of tests
+ LogInterceptors.set(new ListInterceptor());
+ setLevel(LoggerLevel.INFO);
+ }
+
+ protected void after() {
+ LogInterceptors.set(NullInterceptor.NULL_INSTANCE);
+ setLevel(LoggerLevel.INFO);
+ }
+
+ LoggerLevel getLevel() {
+ return Loggers.getFactory().getLevel();
+ }
+
+ /**
+ * Enable/disable debug logs. Info, warn and error logs are always enabled.
+ * By default INFO logs are enabled when LogTester is started.
+ */
+ public AbstractLogTester setLevel(LoggerLevel level) {
+ Loggers.getFactory().setLevel(level);
+ return this;
+ }
+
+ /**
+ * Logs in chronological order (item at index 0 is the oldest one)
+ */
+ public List<String> logs() {
+ return ((ListInterceptor) LogInterceptors.get()).logs();
+ }
+
+ /**
+ * Logs in chronological order (item at index 0 is the oldest one) for
+ * a given level
+ */
+ public List<String> logs(LoggerLevel level) {
+ return ((ListInterceptor) LogInterceptors.get()).logs(level);
+ }
+
+ /**
+ * Logs with arguments in chronological order (item at index 0 is the oldest one)
+ */
+ public List<LogAndArguments> getLogs() {
+ return ((ListInterceptor) LogInterceptors.get()).getLogs();
+ }
+
+ /**
+ * Logs with arguments in chronological order (item at index 0 is the oldest one) for
+ * a given level
+ */
+ public List<LogAndArguments> getLogs(LoggerLevel level) {
+ return ((ListInterceptor) LogInterceptors.get()).getLogs(level);
+ }
+
+ public AbstractLogTester clear() {
+ ((ListInterceptor) LogInterceptors.get()).clear();
+ return this;
+ }
+}
*/
package org.sonar.api.utils.log;
-import java.util.List;
-import org.junit.rules.ExternalResource;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
/**
* <b>For tests only</b>
*
* @since 5.1
*/
-public class LogTester extends ExternalResource {
-
- @Override
- protected void before() throws Throwable {
- // this shared instance breaks compatibility with parallel execution of tests
- LogInterceptors.set(new ListInterceptor());
- setLevel(LoggerLevel.INFO);
- }
-
- @Override
- protected void after() {
- LogInterceptors.set(NullInterceptor.NULL_INSTANCE);
- setLevel(LoggerLevel.INFO);
- }
-
- LoggerLevel getLevel() {
- return Loggers.getFactory().getLevel();
- }
-
- /**
- * Enable/disable debug logs. Info, warn and error logs are always enabled.
- * By default INFO logs are enabled when LogTester is started.
- */
- public LogTester setLevel(LoggerLevel level) {
- Loggers.getFactory().setLevel(level);
- return this;
- }
-
- /**
- * Logs in chronological order (item at index 0 is the oldest one)
- */
- public List<String> logs() {
- return ((ListInterceptor) LogInterceptors.get()).logs();
- }
-
- /**
- * Logs in chronological order (item at index 0 is the oldest one) for
- * a given level
- */
- public List<String> logs(LoggerLevel level) {
- return ((ListInterceptor) LogInterceptors.get()).logs(level);
- }
-
- /**
- * Logs with arguments in chronological order (item at index 0 is the oldest one)
- */
- public List<LogAndArguments> getLogs() {
- return ((ListInterceptor) LogInterceptors.get()).getLogs();
- }
-
- /**
- * Logs with arguments in chronological order (item at index 0 is the oldest one) for
- * a given level
- */
- public List<LogAndArguments> getLogs(LoggerLevel level) {
- return ((ListInterceptor) LogInterceptors.get()).getLogs(level);
+public class LogTester extends AbstractLogTester implements TestRule {
+ public Statement apply(Statement base, Description description) {
+ return statement(base);
}
- public LogTester clear() {
- ((ListInterceptor) LogInterceptors.get()).clear();
- return this;
+ private Statement statement(final Statement base) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ before();
+ try {
+ base.evaluate();
+ } finally {
+ after();
+ }
+ }
+ };
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.utils.log;
+
+import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
+import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+/**
+ * <b>For tests only</b>
+ * <br>
+ * This JUnit 5 extension allows to configure and access logs in tests. By default
+ * trace level is enabled.
+ * <br>
+ * Warning - not compatible with parallel execution of tests in the same JVM fork.
+ * <br>
+ * Example:
+ * <pre>
+ * public class MyClass {
+ * private final Logger logger = Loggers.get("logger_name");
+ *
+ * public void doSomething() {
+ * logger.info("foo");
+ * }
+ * }
+ *
+ * class MyClassTests {
+ * @org.junit.jupiter.api.extension.RegisterExtension
+ * LogTesterJUnit5 logTester = new LogTesterJUnit5();
+ *
+ * @org.junit.jupiter.api.Test
+ * public void test_log() {
+ * new MyClass().doSomething();
+ *
+ * assertThat(logTester.logs()).containsOnly("foo");
+ * }
+ * }
+ * </pre>
+ *
+ * @since 8.1
+ */
+public class LogTesterJUnit5 extends AbstractLogTester implements BeforeTestExecutionCallback, AfterTestExecutionCallback {
+
+ @Override
+ public void beforeTestExecution(ExtensionContext context) throws Exception {
+ before();
+ }
+
+ @Override
+ public void afterTestExecution(ExtensionContext context) throws Exception {
+ after();
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.utils.log;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class LogTesterJUnit5Test {
+
+ LogTesterJUnit5 underTest = new LogTesterJUnit5();
+
+ @Test
+ public void info_level_by_default() throws Throwable {
+ // when LogTester is used, then info logs are enabled by default
+ underTest.beforeTestExecution(null);
+ assertThat(underTest.getLevel()).isEqualTo(LoggerLevel.INFO);
+ assertThat(Loggers.getFactory().getLevel()).isEqualTo(LoggerLevel.INFO);
+
+ // change
+ underTest.setLevel(LoggerLevel.DEBUG);
+ assertThat(underTest.getLevel()).isEqualTo(LoggerLevel.DEBUG);
+ assertThat(Loggers.getFactory().getLevel()).isEqualTo(LoggerLevel.DEBUG);
+
+ // reset to initial level after execution of test
+ underTest.afterTestExecution(null);
+ assertThat(underTest.getLevel()).isEqualTo(LoggerLevel.INFO);
+ assertThat(Loggers.getFactory().getLevel()).isEqualTo(LoggerLevel.INFO);
+ }
+
+ @Test
+ public void intercept_logs() throws Throwable {
+ underTest.beforeTestExecution(null);
+ Loggers.get("logger1").info("an information");
+ Loggers.get("logger2").warn("warning: {}", 42);
+
+ assertThat(underTest.logs()).containsExactly("an information", "warning: 42");
+ assertThat(underTest.logs(LoggerLevel.ERROR)).isEmpty();
+ assertThat(underTest.logs(LoggerLevel.INFO)).containsOnly("an information");
+ assertThat(underTest.logs(LoggerLevel.WARN)).containsOnly("warning: 42");
+
+ underTest.clear();
+ assertThat(underTest.logs()).isEmpty();
+ assertThat(underTest.logs(LoggerLevel.INFO)).isEmpty();
+
+ underTest.afterTestExecution(null);
+ assertThat(LogInterceptors.get()).isSameAs(NullInterceptor.NULL_INSTANCE);
+ }
+
+ @Test
+ public void use_suppliers() throws Throwable {
+ // when LogTester is used, then info logs are enabled by default
+ underTest.beforeTestExecution(null);
+ AtomicBoolean touchedTrace = new AtomicBoolean();
+ AtomicBoolean touchedDebug = new AtomicBoolean();
+ Loggers.get("logger1").trace(() -> {
+ touchedTrace.set(true);
+ return "a trace information";
+ });
+ Loggers.get("logger1").debug(() -> {
+ touchedDebug.set(true);
+ return "a debug information";
+ });
+
+ assertThat(underTest.logs()).isEmpty();
+ assertThat(touchedTrace.get()).isFalse();
+ assertThat(touchedDebug.get()).isFalse();
+
+ // change level to DEBUG
+ underTest.setLevel(LoggerLevel.DEBUG);
+ Loggers.get("logger1").trace(() -> {
+ touchedTrace.set(true);
+ return "a trace information";
+ });
+ Loggers.get("logger1").debug(() -> {
+ touchedDebug.set(true);
+ return "a debug information";
+ });
+
+ assertThat(underTest.logs()).containsOnly("a debug information");
+ assertThat(touchedTrace.get()).isFalse();
+ assertThat(touchedDebug.get()).isTrue();
+ touchedDebug.set(false);
+ underTest.clear();
+
+ // change level to TRACE
+ underTest.setLevel(LoggerLevel.TRACE);
+ Loggers.get("logger1").trace(() -> {
+ touchedTrace.set(true);
+ return "a trace information";
+ });
+ Loggers.get("logger1").debug(() -> {
+ touchedDebug.set(true);
+ return "a debug information";
+ });
+
+ assertThat(underTest.logs()).containsExactly("a trace information", "a debug information");
+ assertThat(touchedTrace.get()).isTrue();
+ assertThat(touchedDebug.get()).isTrue();
+ }
+}