/* * SonarQube * Copyright (C) 2009-2017 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.core.util.logs; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.List; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; import org.sonar.api.utils.log.Loggers; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; @RunWith(DataProviderRunner.class) public class DefaultProfilerTest { @Rule public LogTester tester = new LogTester(); Profiler underTest = Profiler.create(Loggers.get("DefaultProfilerTest")); @DataProvider public static Object[][] logTimeLastValues() { return new Object[][] { {true}, {false} }; } @Test public void test_levels() throws Exception { // info by default assertThat(underTest.isDebugEnabled()).isFalse(); assertThat(underTest.isTraceEnabled()).isFalse(); tester.setLevel(LoggerLevel.DEBUG); assertThat(underTest.isDebugEnabled()).isTrue(); assertThat(underTest.isTraceEnabled()).isFalse(); tester.setLevel(LoggerLevel.TRACE); assertThat(underTest.isDebugEnabled()).isTrue(); assertThat(underTest.isTraceEnabled()).isTrue(); } @Test @UseDataProvider("logTimeLastValues") public void stop_reuses_start_message(boolean logTimeLast) throws InterruptedException { underTest.logTimeLast(logTimeLast); tester.setLevel(LoggerLevel.TRACE); // trace underTest.startTrace("Register rules {}", 1); Thread.sleep(2); assertThat(tester.logs()).containsOnly("Register rules 1"); long timing = underTest.stopTrace(); assertThat(timing).isGreaterThan(0); assertThat(tester.logs()).hasSize(2); assertThat(tester.logs().get(1)).startsWith("Register rules 1 (done) | time=" + timing); tester.clear(); // debug underTest.startDebug("Register rules"); Thread.sleep(2); assertThat(tester.logs()).containsOnly("Register rules"); timing = underTest.stopTrace(); assertThat(timing).isGreaterThan(0); assertThat(tester.logs()).hasSize(2); assertThat(tester.logs().get(1)).startsWith("Register rules (done) | time=" + timing); tester.clear(); // info underTest.startInfo("Register rules"); Thread.sleep(2); assertThat(tester.logs()).containsOnly("Register rules"); timing = underTest.stopTrace(); assertThat(timing).isGreaterThan(0); assertThat(tester.logs()).hasSize(2); assertThat(tester.logs().get(1)).startsWith("Register rules (done) | time=" + timing); } @Test @UseDataProvider("logTimeLastValues") public void different_start_and_stop_messages(boolean logTimeLast) { underTest.logTimeLast(logTimeLast); tester.setLevel(LoggerLevel.TRACE); // start TRACE and stop DEBUG underTest.startTrace("Register rules"); underTest.stopDebug("Rules registered"); assertThat(tester.logs()).hasSize(2); assertThat(tester.logs().get(0)).contains("Register rules"); assertThat(tester.logs().get(1)).startsWith("Rules registered | time="); tester.clear(); // start DEBUG and stop INFO underTest.startDebug("Register rules {}", 10); underTest.stopInfo("Rules registered"); assertThat(tester.logs()).hasSize(2); assertThat(tester.logs().get(0)).contains("Register rules 10"); assertThat(tester.logs().get(1)).startsWith("Rules registered | time="); tester.clear(); // start INFO and stop TRACE underTest.startInfo("Register rules"); underTest.stopTrace("Rules registered"); assertThat(tester.logs()).hasSize(2); assertThat(tester.logs().get(0)).contains("Register rules"); assertThat(tester.logs().get(1)).startsWith("Rules registered | time="); } @Test @UseDataProvider("logTimeLastValues") public void log_on_at_stop(boolean logTimeLast) { underTest.logTimeLast(logTimeLast); tester.setLevel(LoggerLevel.TRACE); // trace underTest.start(); underTest.stopTrace("Rules registered"); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs().get(0)).startsWith("Rules registered | time="); tester.clear(); // debug underTest.start(); underTest.stopDebug("Rules registered {} on {}", 6, 10); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs().get(0)).startsWith("Rules registered 6 on 10 | time="); tester.clear(); // info underTest.start(); underTest.stopInfo("Rules registered"); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs().get(0)).startsWith("Rules registered | time="); } @Test public void start_writes_no_log_even_if_there_is_context() { underTest.addContext("a_string", "bar"); underTest.addContext("null_value", null); underTest.addContext("an_int", 42); underTest.start(); // do not write context as there's no message assertThat(tester.logs()).isEmpty(); } @Test public void startInfo_writes_log_with_context_appended_when_there_is_a_message() { addSomeContext(underTest); underTest.startInfo("Foo"); assertThat(tester.logs(LoggerLevel.INFO)).containsOnly("Foo | a_string=bar | an_int=42 | after_start=true"); } @Test public void startDebug_writes_log_with_context_appended_when_there_is_a_message() { tester.setLevel(LoggerLevel.DEBUG); addSomeContext(underTest); underTest.startDebug("Foo"); assertThat(tester.logs(LoggerLevel.DEBUG)).containsOnly("Foo | a_string=bar | an_int=42 | after_start=true"); } @Test public void startTrace_writes_log_with_context_appended_when_there_is_a_message() { tester.setLevel(LoggerLevel.TRACE); addSomeContext(underTest); underTest.startTrace("Foo"); assertThat(tester.logs(LoggerLevel.TRACE)).containsOnly("Foo | a_string=bar | an_int=42 | after_start=true"); } @Test public void stopError_adds_context_after_time_by_default() { addSomeContext(underTest); underTest.start().stopError("Rules registered"); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs(LoggerLevel.ERROR).get(0)) .startsWith("Rules registered | time=") .endsWith("ms | a_string=bar | an_int=42 | after_start=true"); } @Test public void stopInfo_adds_context_after_time_by_default() { addSomeContext(underTest); underTest.start().stopInfo("Rules registered"); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs(LoggerLevel.INFO).get(0)) .startsWith("Rules registered | time=") .endsWith("ms | a_string=bar | an_int=42 | after_start=true"); } @Test public void stopTrace_adds_context_after_time_by_default() { tester.setLevel(LoggerLevel.TRACE); addSomeContext(underTest); underTest.start().stopTrace("Rules registered"); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs(LoggerLevel.TRACE).get(0)) .startsWith("Rules registered | time=") .endsWith("ms | a_string=bar | an_int=42 | after_start=true"); } @Test public void stopError_adds_context_before_time_if_logTimeLast_is_true() { addSomeContext(underTest); underTest.logTimeLast(true); underTest.start().stopError("Rules registered"); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs(LoggerLevel.ERROR).get(0)) .startsWith("Rules registered | a_string=bar | an_int=42 | after_start=true | time=") .endsWith("ms"); } @Test public void stopInfo_adds_context_before_time_if_logTimeLast_is_true() { addSomeContext(underTest); underTest.logTimeLast(true); underTest.start().stopInfo("Rules registered"); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs(LoggerLevel.INFO).get(0)) .startsWith("Rules registered | a_string=bar | an_int=42 | after_start=true | time=") .endsWith("ms"); } @Test public void stopTrace_adds_context_before_time_if_logTimeLast_is_true() { tester.setLevel(LoggerLevel.TRACE); addSomeContext(underTest); underTest.logTimeLast(true); underTest.start().stopTrace("Rules registered"); assertThat(tester.logs()).hasSize(1); assertThat(tester.logs(LoggerLevel.TRACE).get(0)) .startsWith("Rules registered | a_string=bar | an_int=42 | after_start=true | time=") .endsWith("ms"); } @Test public void stopInfo_clears_context() { addSomeContext(underTest); underTest.logTimeLast(true); underTest.start().stopInfo("Foo"); underTest.start().stopInfo("Bar"); assertThat(tester.logs()).hasSize(2); List<String> logs = tester.logs(LoggerLevel.INFO); assertThat(logs.get(0)) .startsWith("Foo | a_string=bar | an_int=42 | after_start=true | time=") .endsWith("ms"); assertThat(logs.get(1)) .startsWith("Bar | time=") .endsWith("ms"); } @Test public void stopDebug_clears_context() { tester.setLevel(LoggerLevel.DEBUG); addSomeContext(underTest); underTest.logTimeLast(true); underTest.start().stopDebug("Foo"); underTest.start().stopDebug("Bar"); assertThat(tester.logs()).hasSize(2); List<String> logs = tester.logs(LoggerLevel.DEBUG); assertThat(logs.get(0)) .startsWith("Foo | a_string=bar | an_int=42 | after_start=true | time=") .endsWith("ms"); assertThat(logs.get(1)) .startsWith("Bar | time=") .endsWith("ms"); } @Test public void stopTrace_clears_context() { tester.setLevel(LoggerLevel.TRACE); addSomeContext(underTest); underTest.logTimeLast(true); underTest.start().stopTrace("Foo"); underTest.start().stopTrace("Bar"); assertThat(tester.logs()).hasSize(2); List<String> logs = tester.logs(LoggerLevel.TRACE); assertThat(logs.get(0)) .startsWith("Foo | a_string=bar | an_int=42 | after_start=true | time=") .endsWith("ms"); assertThat(logs.get(1)) .startsWith("Bar | time=") .endsWith("ms"); } private static void addSomeContext(Profiler profiler) { profiler.addContext("a_string", "bar"); profiler.addContext("null_value", null); profiler.addContext("an_int", 42); profiler.addContext("after_start", true); } @Test public void empty_message() { underTest.addContext("foo", "bar"); underTest.startInfo(""); assertThat(tester.logs()).containsOnly("foo=bar"); underTest.addContext("after_start", true); underTest.stopInfo(""); assertThat(tester.logs()).hasSize(2); assertThat(tester.logs().get(1)) .startsWith("time=") .endsWith("ms | foo=bar | after_start=true"); } @Test public void fail_if_stop_without_message() { underTest.start(); try { underTest.stopInfo(); fail(); } catch (IllegalStateException e) { assertThat(e).hasMessage("Profiler#stopXXX() can't be called without any message defined in start methods"); } } @Test public void fail_if_stop_without_start() { try { underTest.stopDebug("foo"); fail(); } catch (IllegalStateException e) { assertThat(e).hasMessage("Profiler must be started before being stopped"); } } }