diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2019-11-15 14:56:14 +0100 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-11-21 20:21:09 +0100 |
commit | edb900d518a022846a4ac646a4d66b757d6dc1eb (patch) | |
tree | 0d637f4fa5fb0c67c036d4b4165e1a6cbd9bb2fe /sonar-plugin-api | |
parent | afcbb00449f357551be38b3fda8c5d20e659b54e (diff) | |
download | sonarqube-edb900d518a022846a4ac646a4d66b757d6dc1eb.tar.gz sonarqube-edb900d518a022846a4ac646a4d66b757d6dc1eb.zip |
Add a JUnit 5 version of LogTester
Diffstat (limited to 'sonar-plugin-api')
5 files changed, 293 insertions, 61 deletions
diff --git a/sonar-plugin-api/build.gradle b/sonar-plugin-api/build.gradle index 580f068d29e..37ee4e5521e 100644 --- a/sonar-plugin-api/build.gradle +++ b/sonar-plugin-api/build.gradle @@ -25,6 +25,8 @@ dependencies { 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' diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/AbstractLogTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/AbstractLogTester.java new file mode 100644 index 00000000000..e6b8ad41864 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/AbstractLogTester.java @@ -0,0 +1,84 @@ +/* + * 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; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java index 6ad69b11135..0a85da680a4 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java @@ -19,8 +19,9 @@ */ 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> @@ -55,66 +56,22 @@ import org.junit.rules.ExternalResource; * * @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(); + } + } + }; } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTesterJUnit5.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTesterJUnit5.java new file mode 100644 index 00000000000..7ed6a717078 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTesterJUnit5.java @@ -0,0 +1,70 @@ +/* + * 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(); + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterJUnit5Test.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterJUnit5Test.java new file mode 100644 index 00000000000..939799c1d55 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterJUnit5Test.java @@ -0,0 +1,119 @@ +/* + * 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(); + } +} |