]> source.dussan.org Git - sonarqube.git/commitdiff
Add a JUnit 5 version of LogTester
authorJulien HENRY <julien.henry@sonarsource.com>
Fri, 15 Nov 2019 13:56:14 +0000 (14:56 +0100)
committerSonarTech <sonartech@sonarsource.com>
Thu, 21 Nov 2019 19:21:09 +0000 (20:21 +0100)
build.gradle
sonar-plugin-api/build.gradle
sonar-plugin-api/src/main/java/org/sonar/api/utils/log/AbstractLogTester.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTester.java
sonar-plugin-api/src/main/java/org/sonar/api/utils/log/LogTesterJUnit5.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterJUnit5Test.java [new file with mode: 0644]

index a7a3a0b8fce8575b2a66396fb6e44a2a039ef05d..339f4e24d7c2aab37268ab81443f35b3256feca5 100644 (file)
@@ -212,6 +212,7 @@ subprojects {
       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'
index 580f068d29e3d3949f83ab919068bf9dcea7ba5e..37ee4e5521ea6b287998cbbda3a9dcb872a501c1 100644 (file)
@@ -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 (file)
index 0000000..e6b8ad4
--- /dev/null
@@ -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;
+  }
+}
index 6ad69b11135266320e4ff8e42a3cfa81934d2cf6..0a85da680a42d901a5ec008ca0b82315f0354b37 100644 (file)
@@ -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 (file)
index 0000000..7ed6a71
--- /dev/null
@@ -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 {
+ *   &#064;org.junit.jupiter.api.extension.RegisterExtension
+ *   LogTesterJUnit5 logTester = new LogTesterJUnit5();
+ *
+ *   &#064;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 (file)
index 0000000..939799c
--- /dev/null
@@ -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();
+  }
+}