From 9368bd5ec332435ed97717647e9cd3f2df051f4d Mon Sep 17 00:00:00 2001 From: Alexandre Montplaisir Date: Thu, 23 Jul 2015 20:53:57 -0400 Subject: [PATCH] Add some integration tests for JUL as well as more functionality to LttngSessionControl. Signed-off-by: Alexandre Montplaisir --- .../jul/handler/FileHandlerBenchmark.java | 14 +- ...tngJulHandlerTracingDisabledBenchmark.java | 4 +- ...ttngJulHandlerTracingEnabledBenchmark.java | 4 +- ...tngJulHandlerTracingDisabledBenchmark.java | 4 +- ...ttngJulHandlerTracingEnabledBenchmark.java | 4 +- .../integration/jul/JulEnabledEventsTest.java | 219 ++++++++++++++++-- .../ust/agent/utils/LttngSessionControl.java | 165 ++++++++++++- 7 files changed, 372 insertions(+), 42 deletions(-) diff --git a/src/org/lttng/ust/agent/benchmarks/jul/handler/FileHandlerBenchmark.java b/src/org/lttng/ust/agent/benchmarks/jul/handler/FileHandlerBenchmark.java index d6095aa..167c741 100644 --- a/src/org/lttng/ust/agent/benchmarks/jul/handler/FileHandlerBenchmark.java +++ b/src/org/lttng/ust/agent/benchmarks/jul/handler/FileHandlerBenchmark.java @@ -1,16 +1,28 @@ package org.lttng.ust.agent.benchmarks.jul.handler; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.logging.FileHandler; import java.util.logging.SimpleFormatter; +import org.junit.After; import org.junit.Before; public class FileHandlerBenchmark extends AbstractJulBenchmark { + private Path outputFile; + @Before public void testSetup() throws SecurityException, IOException { - handler = new FileHandler("/tmp/log", false); + outputFile = Files.createTempFile(this.getClass().getSimpleName(), null); + + handler = new FileHandler(outputFile.toString(), false); handler.setFormatter(new SimpleFormatter()); } + + @After + public void testTeardown() throws IOException { + Files.deleteIfExists(outputFile); + } } diff --git a/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/LttngJulHandlerTracingDisabledBenchmark.java b/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/LttngJulHandlerTracingDisabledBenchmark.java index 690af1d..562965d 100644 --- a/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/LttngJulHandlerTracingDisabledBenchmark.java +++ b/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/LttngJulHandlerTracingDisabledBenchmark.java @@ -22,7 +22,7 @@ public class LttngJulHandlerTracingDisabledBenchmark extends AbstractJulBenchmar @After public void testTeardown() { - assertTrue(LttngSessionControl.stopSession()); - assertTrue(LttngSessionControl.destroySession()); + assertTrue(LttngSessionControl.stopSession(null)); + assertTrue(LttngSessionControl.destroySession(null)); } } diff --git a/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/LttngJulHandlerTracingEnabledBenchmark.java b/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/LttngJulHandlerTracingEnabledBenchmark.java index eb0514e..38b6aa6 100644 --- a/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/LttngJulHandlerTracingEnabledBenchmark.java +++ b/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/LttngJulHandlerTracingEnabledBenchmark.java @@ -22,7 +22,7 @@ public class LttngJulHandlerTracingEnabledBenchmark extends AbstractJulBenchmark @After public void testTeardown() { - assertTrue(LttngSessionControl.stopSession()); - assertTrue(LttngSessionControl.destroySession()); + assertTrue(LttngSessionControl.stopSession(null)); + assertTrue(LttngSessionControl.destroySession(null)); } } diff --git a/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/old/OldLttngJulHandlerTracingDisabledBenchmark.java b/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/old/OldLttngJulHandlerTracingDisabledBenchmark.java index c8cbe6e..21ab953 100644 --- a/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/old/OldLttngJulHandlerTracingDisabledBenchmark.java +++ b/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/old/OldLttngJulHandlerTracingDisabledBenchmark.java @@ -23,8 +23,8 @@ public class OldLttngJulHandlerTracingDisabledBenchmark extends AbstractJulBench @After public void testTeardown() { - assertTrue(LttngSessionControl.stopSession()); - assertTrue(LttngSessionControl.destroySession()); + assertTrue(LttngSessionControl.stopSession(null)); + assertTrue(LttngSessionControl.destroySession(null)); LTTngAgent.dispose(); } diff --git a/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/old/OldLttngJulHandlerTracingEnabledBenchmark.java b/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/old/OldLttngJulHandlerTracingEnabledBenchmark.java index 3e6636b..29439a0 100644 --- a/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/old/OldLttngJulHandlerTracingEnabledBenchmark.java +++ b/src/org/lttng/ust/agent/benchmarks/jul/handler/lttng/old/OldLttngJulHandlerTracingEnabledBenchmark.java @@ -48,8 +48,8 @@ public class OldLttngJulHandlerTracingEnabledBenchmark extends AbstractJulBenchm @After public void testTeardown() { - assertTrue(LttngSessionControl.stopSession()); - assertTrue(LttngSessionControl.destroySession()); + assertTrue(LttngSessionControl.stopSession(null)); + assertTrue(LttngSessionControl.destroySession(null)); logger.removeHandler(agentHandler); LTTngAgent.dispose(); diff --git a/src/org/lttng/ust/agent/integration/jul/JulEnabledEventsTest.java b/src/org/lttng/ust/agent/integration/jul/JulEnabledEventsTest.java index 27f033e..53fdafe 100644 --- a/src/org/lttng/ust/agent/integration/jul/JulEnabledEventsTest.java +++ b/src/org/lttng/ust/agent/integration/jul/JulEnabledEventsTest.java @@ -7,11 +7,11 @@ import static org.junit.Assume.assumeTrue; import java.io.IOException; import java.util.List; -import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -23,6 +23,8 @@ public class JulEnabledEventsTest { private static final Domain DOMAIN = Domain.JUL; + private static final String SESSION_NAME = JulEnabledEventsTest.class.getSimpleName(); + private static final String EVENT_NAME_A = "EventA"; private static final String EVENT_NAME_B = "EventAB"; private static final String EVENT_NAME_C = "EventABC"; @@ -33,9 +35,9 @@ public class JulEnabledEventsTest { private Logger loggerC; private Logger loggerD; - private Handler handlerA; - private Handler handlerB; - private Handler handlerC; + private LttngLogHandler handlerA; + private LttngLogHandler handlerB; + private LttngLogHandler handlerC; @BeforeClass public static void classSetup() { @@ -48,13 +50,23 @@ public class JulEnabledEventsTest { } boolean ret1 = LttngSessionControl.setupSession(null, DOMAIN); - boolean ret2 = LttngSessionControl.stopSession(); - boolean ret3 = LttngSessionControl.destroySession(); + boolean ret2 = LttngSessionControl.stopSession(null); + /* "lttng view" also tests that Babeltrace is installed and working */ + List contents = LttngSessionControl.viewSession(null); + boolean ret3 = LttngSessionControl.destroySession(null); assumeTrue(ret1 && ret2 && ret3); + assumeTrue(contents.isEmpty()); + } + + @AfterClass + public static void classCleanup() { + LttngSessionControl.deleteAllTracee(); } @Before public void setup() throws SecurityException, IOException { + // TODO Wipe all existing LTTng sessions? + loggerA = Logger.getLogger(EVENT_NAME_A); loggerB = Logger.getLogger(EVENT_NAME_B); loggerC = Logger.getLogger(EVENT_NAME_C); @@ -71,11 +83,14 @@ public class JulEnabledEventsTest { loggerA.addHandler(handlerA); loggerB.addHandler(handlerB); - loggerC.addHandler(handlerB); + loggerC.addHandler(handlerC); } @After public void teardown() { + /* Just in case the test failed */ + LttngSessionControl.tryDestroySession(SESSION_NAME); + loggerA.removeHandler(handlerA); loggerB.removeHandler(handlerB); loggerC.removeHandler(handlerC); @@ -95,24 +110,29 @@ public class JulEnabledEventsTest { /** * Test sending events on the Java side, but no events enabled in the - * tracing session. There should be nothing in the resulting trace. + * tracing session. There should be nothing in the resulting trace, and + * handlers should not have logged anything. */ @Test public void testNoEvents() { - assertTrue(LttngSessionControl.setupSession(null, DOMAIN)); + assertTrue(LttngSessionControl.setupSession(SESSION_NAME, DOMAIN)); send10Events(loggerA); send10Events(loggerB); send10Events(loggerC); send10Events(loggerD); - assertTrue(LttngSessionControl.stopSession()); + assertTrue(LttngSessionControl.stopSession(SESSION_NAME)); - List output = LttngSessionControl.viewSession(); + List output = LttngSessionControl.viewSession(SESSION_NAME); assertNotNull(output); assertTrue(output.isEmpty()); - assertTrue(LttngSessionControl.destroySession()); + assertTrue(LttngSessionControl.destroySession(SESSION_NAME)); + + assertEquals(0, handlerA.getEventCount()); + assertEquals(0, handlerB.getEventCount()); + assertEquals(0, handlerC.getEventCount()); } /** @@ -121,20 +141,24 @@ public class JulEnabledEventsTest { */ @Test public void testAllEvents() { - assertTrue(LttngSessionControl.setupSessionAllEvents(null, DOMAIN)); + assertTrue(LttngSessionControl.setupSessionAllEvents(SESSION_NAME, DOMAIN)); send10Events(loggerA); send10Events(loggerB); send10Events(loggerC); send10Events(loggerD); - assertTrue(LttngSessionControl.stopSession()); + assertTrue(LttngSessionControl.stopSession(SESSION_NAME)); - List output = LttngSessionControl.viewSession(); + List output = LttngSessionControl.viewSession(SESSION_NAME); assertNotNull(output); - assertEquals(20, output.size()); // loggerC has no handler attached + assertEquals(30, output.size()); // loggerD has no handler attached - assertTrue(LttngSessionControl.destroySession()); + assertTrue(LttngSessionControl.destroySession(SESSION_NAME)); + + assertEquals(10, handlerA.getEventCount()); + assertEquals(10, handlerB.getEventCount()); + assertEquals(10, handlerC.getEventCount()); } /** @@ -143,28 +167,173 @@ public class JulEnabledEventsTest { */ @Test public void testSomeEvents() { - assertTrue(LttngSessionControl.setupSession(null, DOMAIN, - EVENT_NAME_A, EVENT_NAME_D)); + assertTrue(LttngSessionControl.setupSession(SESSION_NAME, DOMAIN, + EVENT_NAME_A, EVENT_NAME_C, EVENT_NAME_D)); + + send10Events(loggerA); + send10Events(loggerB); + send10Events(loggerC); + send10Events(loggerD); + + assertTrue(LttngSessionControl.stopSession(SESSION_NAME)); + + List output = LttngSessionControl.viewSession(SESSION_NAME); + assertNotNull(output); + assertEquals(20, output.size()); + + assertTrue(LttngSessionControl.destroySession(SESSION_NAME)); + + assertEquals(10, handlerA.getEventCount()); + assertEquals(0, handlerB.getEventCount()); + assertEquals(10, handlerC.getEventCount()); + } + + /** + * Test with all events enabled (-a), plus some other events added manually. + * Events should still be retained, but there should be no duplicates. + */ + @Test + public void testAllEventsAndSome() { + assertTrue(LttngSessionControl.setupSessionAllEvents(SESSION_NAME, DOMAIN)); + assertTrue(LttngSessionControl.enableEvents(SESSION_NAME, DOMAIN, + EVENT_NAME_A, EVENT_NAME_B)); + + send10Events(loggerA); + send10Events(loggerB); + send10Events(loggerC); + send10Events(loggerD); + + assertTrue(LttngSessionControl.stopSession(SESSION_NAME)); + + List output = LttngSessionControl.viewSession(SESSION_NAME); + assertNotNull(output); + assertEquals(30, output.size()); + + assertTrue(LttngSessionControl.destroySession(SESSION_NAME)); + + assertEquals(10, handlerA.getEventCount()); + assertEquals(10, handlerB.getEventCount()); + assertEquals(10, handlerC.getEventCount()); + } + + /** + * Same as {@link #testSomeEvents()}, but some events were enabled first, + * then disabled. Makes sure the enabled-event refcounting works properly. + */ + @Test + public void testSomeEventsAfterDisabling() { + assertTrue(LttngSessionControl.setupSession(SESSION_NAME, DOMAIN, + EVENT_NAME_A, EVENT_NAME_C, EVENT_NAME_D)); + + assertTrue(LttngSessionControl.disableEvents(SESSION_NAME, DOMAIN, + EVENT_NAME_C)); + + send10Events(loggerA); + send10Events(loggerB); + send10Events(loggerC); + send10Events(loggerD); + + assertTrue(LttngSessionControl.stopSession(SESSION_NAME)); + + List output = LttngSessionControl.viewSession(SESSION_NAME); + assertNotNull(output); + assertEquals(10, output.size()); + + assertTrue(LttngSessionControl.destroySession(SESSION_NAME)); + + assertEquals(10, handlerA.getEventCount()); + assertEquals(0, handlerB.getEventCount()); + assertEquals(0, handlerC.getEventCount()); + } + + /** + * Test enabling an event prefix, which means an event name ending with a *, + * to match all events starting with this name. + */ + @Test + public void testEventPrefix() { + assertTrue(LttngSessionControl.setupSession(SESSION_NAME, DOMAIN, + "EventAB*")); // should match event/loggers B and C, but not A. + + send10Events(loggerA); + send10Events(loggerB); + send10Events(loggerC); + send10Events(loggerD); + + assertTrue(LttngSessionControl.stopSession(SESSION_NAME)); + + List output = LttngSessionControl.viewSession(SESSION_NAME); + assertNotNull(output); + assertEquals(20, output.size()); + + assertTrue(LttngSessionControl.destroySession(SESSION_NAME)); + + assertEquals(0, handlerA.getEventCount()); + assertEquals(10, handlerB.getEventCount()); + assertEquals(10, handlerC.getEventCount()); + } + + /** + * Same as {@link #testEventPrefix()}, but with multiple prefixes that + * overlap. There should not be any duplicate events in the trace or in the + * handlers. + */ + @Test + public void testEventPrefixOverlapping() { + assertTrue(LttngSessionControl.setupSession(SESSION_NAME, DOMAIN, + "EventAB*", "EventABC*")); // should still match B and C send10Events(loggerA); send10Events(loggerB); send10Events(loggerC); send10Events(loggerD); - assertTrue(LttngSessionControl.stopSession()); + assertTrue(LttngSessionControl.stopSession(SESSION_NAME)); - List output = LttngSessionControl.viewSession(); + List output = LttngSessionControl.viewSession(SESSION_NAME); assertNotNull(output); - assertEquals(10, output.size()); // loggerC has no handler attached + assertEquals(20, output.size()); + + assertTrue(LttngSessionControl.destroySession(SESSION_NAME)); + + assertEquals(0, handlerA.getEventCount()); + assertEquals(10, handlerB.getEventCount()); + assertEquals(10, handlerC.getEventCount()); + } + + /** + * Test with all events enabled (-a), plus an event prefix. Once again, + * there should be no duplicates. + */ + @Test + public void testAllEventsAndPrefix() { + assertTrue(LttngSessionControl.setupSessionAllEvents(SESSION_NAME, DOMAIN)); + assertTrue(LttngSessionControl.enableEvents(SESSION_NAME, DOMAIN, + "EventAB*")); // should match B and C + + send10Events(loggerA); + send10Events(loggerB); + send10Events(loggerC); + send10Events(loggerD); + + assertTrue(LttngSessionControl.stopSession(SESSION_NAME)); + + List output = LttngSessionControl.viewSession(SESSION_NAME); + assertNotNull(output); + assertEquals(30, output.size()); + + assertTrue(LttngSessionControl.destroySession(SESSION_NAME)); - assertTrue(LttngSessionControl.destroySession()); + assertEquals(10, handlerA.getEventCount()); + assertEquals(10, handlerB.getEventCount()); + assertEquals(10, handlerC.getEventCount()); } private static void send10Events(Logger logger) { String a = new String("a"); - Object[] params = {a, new String("b"), new Object()}; + Object[] params = { a, new String("b"), new Object() }; - // Levels are FINE, FINER, FINEST, INFO, SEVERE, WARNING + // Levels are FINE, FINER, FINEST, INFO, SEVERE, WARNING logger.fine("A fine level message"); logger.finer("A finer level message"); logger.finest("A finest level message"); diff --git a/src/org/lttng/ust/agent/utils/LttngSessionControl.java b/src/org/lttng/ust/agent/utils/LttngSessionControl.java index 48eacc5..3e10bd5 100644 --- a/src/org/lttng/ust/agent/utils/LttngSessionControl.java +++ b/src/org/lttng/ust/agent/utils/LttngSessionControl.java @@ -2,8 +2,13 @@ package org.lttng.ust.agent.utils; import java.io.IOException; import java.lang.ProcessBuilder.Redirect; +import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -91,26 +96,164 @@ public final class LttngSessionControl { }); } + /** + * Send a separate enable-event command. + * + * @param sessionName + * Name of the session in which to enable events. Use null for + * current session. + * @param domain + * The tracing domain + * @param enabledEvents + * The list of events to enable. Should not be null or empty + * @return If the command executed successfully (return code = 0). + */ + public static boolean enableEvents(String sessionName, Domain domain, String... enabledEvents) { + if (enabledEvents == null || enabledEvents.length == 0) { + throw new IllegalArgumentException(); + } + List command = new ArrayList(); + command.add("lttng"); + command.add("enable-event"); + command.add(domain.flag()); + command.add(Arrays.stream(enabledEvents).collect(Collectors.joining(","))); + if (sessionName != null) { + command.add("-s"); + command.add(sessionName); + } + return executeCommand(command.toArray(new String[0])); + } + + /** + * Send a disable-event command. Used to disable events that were previously + * enabled. + * + * @param sessionName + * Name of the session in which to disable events. Use null for + * current session. + * @param domain + * The tracing domain + * @param disabledEvents + * The list of disabled events. Should not be null or empty + * @return If the command executed successfully (return code = 0). + */ + public static boolean disableEvents(String sessionName, Domain domain, String... disabledEvents) { + if (disabledEvents == null || disabledEvents.length == 0) { + throw new IllegalArgumentException(); + } + List command = new ArrayList(); + command.add("lttng"); + command.add("disable-event"); + command.add(domain.flag()); + command.add(Arrays.stream(disabledEvents).collect(Collectors.joining(","))); + if (sessionName != null) { + command.add("-s"); + command.add(sessionName); + } + return executeCommand(command.toArray(new String[0])); + } + /** * Stop the current tracing session * + * @param sessionName + * The name of the session to stop. Use null for the current + * session. * @return If the command executed successfully (return code = 0). */ - public static boolean stopSession() { - return executeCommand(new String[] { "lttng", "stop" }); + public static boolean stopSession(String sessionName) { + List command = new ArrayList(); + command.add("lttng"); + command.add("stop"); + if (sessionName != null) { + command.add(sessionName); + } + return executeCommand(command.toArray(new String[0])); } - public static List viewSession() { - return getOutputFromCommand(new String[] { "lttng", "view" }); + /** + * Issue a "lttng view" command on the provided session, and returns its + * output. This effectively returns the current content of the trace in text + * form. + * + * @param sessionName + * The name of the session to print. Use null for the current + * session. + * @return The output of Babeltrace on the session's current trace + */ + public static List viewSession(String sessionName) { + List command = new ArrayList(); + command.add("lttng"); + command.add("view"); + if (sessionName != null) { + command.add(sessionName); + } + return getOutputFromCommand(command.toArray(new String[0])); } /** * Destroy the current tracing session * + * @param sessionName + * The name of the session to destroy. Use null for the current + * session. * @return If the command executed successfully (return code = 0). */ - public static boolean destroySession() { - return executeCommand(new String[] { "lttng", "destroy" }); + public static boolean destroySession(String sessionName) { + List command = new ArrayList(); + command.add("lttng"); + command.add("destroy"); + if (sessionName != null) { + command.add(sessionName); + } + return executeCommand(command.toArray(new String[0])); + } + + /** + * Try destroying the given tracing session, fail silently if there is no + * session. + * + * @param sessionName + * The name of the session to destroy. Use null for the current + * session. + */ + public static void tryDestroySession(String sessionName) { + getOutputFromCommand(false, new String[] { "lttng", "destroy" }); + } + + /** + * Outside of the scope of lttng-tools, but this utility method can be used + * to delete all traces currently under ~/lttng-traces/. This can be used by + * tests to cleanup a trace they have created. + * + * @return True if the command completes successfully, false if there was an + * error. + */ + public static boolean deleteAllTracee() { + String tracesDir = new String(System.getProperty("user.home") + "/lttng-traces/"); + return deleteDirectory(Paths.get(tracesDir)); + } + + private static boolean deleteDirectory(Path directory) { + try { + Files.walkFileTree(directory, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + /* At least we tried... */ + return false; + } + return true; } // ------------------------------------------------------------------------ @@ -149,6 +292,10 @@ public final class LttngSessionControl { } private static List getOutputFromCommand(String[] command) { + return getOutputFromCommand(true, command); + } + + private static List getOutputFromCommand(boolean print, String[] command) { try { Path tempFile = Files.createTempFile("test-output", null); @@ -162,8 +309,10 @@ public final class LttngSessionControl { List lines = Files.readAllLines(tempFile); Files.delete(tempFile); - /* Also print the output to the console */ - lines.stream().forEach(s -> System.out.println(s)); + if (print) { + /* Also print the output to the console */ + lines.stream().forEach(s -> System.out.println(s)); + } return lines; -- 2.34.1