From: Alexandre Montplaisir Date: Wed, 20 Jan 2016 20:01:47 +0000 (-0500) Subject: Add tests for application context retrieval X-Git-Url: http://git.liburcu.org/?a=commitdiff_plain;h=73fb67850f841baaa164b86a2e739917da4247e2;p=lttng-ust-java-tests.git Add tests for application context retrieval Signed-off-by: Alexandre Montplaisir --- diff --git a/lttng-tools-java/src/main/java/org/lttng/tools/ILttngSession.java b/lttng-tools-java/src/main/java/org/lttng/tools/ILttngSession.java index a28a4aa..704705f 100644 --- a/lttng-tools-java/src/main/java/org/lttng/tools/ILttngSession.java +++ b/lttng-tools-java/src/main/java/org/lttng/tools/ILttngSession.java @@ -158,6 +158,20 @@ public interface ILttngSession extends AutoCloseable { */ Set listEvents(); + /** + * Enable an application context with the provided retriever/context names. + * + * There is currently no direct command to remove an existing context, the + * session has to be destroyed and re-created to do so. + * + * @param retrieverName + * The name of the retriever (or "namespace" of the context) + * @param contextName + * The name of the context + * @return If the command executed successfully (return code = 0) + */ + boolean enableAppContext(String retrieverName, String contextName); + /** * Start tracing * diff --git a/lttng-tools-java/src/main/java/org/lttng/tools/LttngCommandLineSession.java b/lttng-tools-java/src/main/java/org/lttng/tools/LttngCommandLineSession.java index 171cffb..3859e2f 100644 --- a/lttng-tools-java/src/main/java/org/lttng/tools/LttngCommandLineSession.java +++ b/lttng-tools-java/src/main/java/org/lttng/tools/LttngCommandLineSession.java @@ -147,6 +147,14 @@ class LttngCommandLineSession implements ILttngSession { .collect(Collectors.toSet()); } + @Override + public boolean enableAppContext(String retrieverName, String contextName) { + return executeCommand(Arrays.asList( + "lttng", "add-context", domain.flag(), + "-t", "$app." + retrieverName + ':' + contextName, + "-s", sessionName)); + } + @Override public boolean start() { /* diff --git a/lttng-ust-java-tests-common/.settings/org.eclipse.core.resources.prefs b/lttng-ust-java-tests-common/.settings/org.eclipse.core.resources.prefs index 8dd9b1d..f9fe345 100644 --- a/lttng-ust-java-tests-common/.settings/org.eclipse.core.resources.prefs +++ b/lttng-ust-java-tests-common/.settings/org.eclipse.core.resources.prefs @@ -1,3 +1,4 @@ eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 encoding//src/test/java=UTF-8 encoding/=UTF-8 diff --git a/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/AppContextITBase.java b/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/AppContextITBase.java new file mode 100644 index 0000000..721b619 --- /dev/null +++ b/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/AppContextITBase.java @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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.lttng.ust.agent.integration.context; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.lttng.tools.ILttngSession; +import org.lttng.tools.ILttngSession.Domain; +import org.lttng.ust.agent.ILttngHandler; +import org.lttng.ust.agent.context.ContextInfoManager; +import org.lttng.ust.agent.utils.TestPrintRunner; + +/** + * Base abstract class to implement all sorts of integration tests verifying the + * presence of enabled application contexts in resulting traces. + */ +@RunWith(TestPrintRunner.class) +public abstract class AppContextITBase { + + protected static final String EVENT_NAME = "EventName"; + + protected static final String RETRIEVER_NAME_1 = "Retriever1"; + protected static final String RETRIEVER_NAME_2 = "Retriever2"; + + private static final String CONTEXT_NAME = ContextInfoRetrieverStubs.CONTEXT_NAME; + + private ContextInfoManager cim; + private ILttngSession session; + + /* Field defined by the sub-class */ + protected ILttngHandler logHandler; + + protected abstract Domain getDomain(); + + protected abstract void sendEventsToLoggers(); + + /** + * Base test setup + */ + @Before + public void testSetup() { + try { + cim = ContextInfoManager.getInstance(); + } catch (SecurityException | IOException e) { + /* The native library is not available! */ + fail(); + } + session = ILttngSession.createSession(null, getDomain()); + } + + /** + * Base test teardown + */ + @After + public void testTeardown() { + session.close(); + + logHandler.close(); + logHandler = null; + + /* In case some tests fail or forget to unregister their retrievers */ + cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1); + cim.unregisterContextInfoRetriever(RETRIEVER_NAME_2); + } + + // ------------------------------------------------------------------------ + // Context enabled/disabled tests + // ------------------------------------------------------------------------ + + /** + * Utility method to check that a context is present in all events of a + * trace output. + */ + private static void testContextPresentInTrace(List traceOutput, String retrieverName, String contextName, String contextValue) { + String fullString = "_app_" + retrieverName + "_" + contextName + " = " + contextValue; + traceOutput.forEach(line -> assertTrue(line.contains(fullString))); + } + + /** + * Utility method to check that a context is *absent* from all events of a + * trace output + */ + private static void testContextNotPresentInTrace(List traceOutput, String retrieverName, String contextName) { + String fullString = "_app_" + retrieverName + "_" + contextName; + traceOutput.forEach(line -> assertFalse(line.contains(fullString))); + } + + /** + * Test that if no retrievers are declared, no context info is passed at + * all. + */ + @Test + public void testNoContexts() { + assertTrue(session.enableAllEvents()); + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + /* Test that there is no "_app" contexts in the output */ + output.forEach(line -> assertFalse(line.contains("_app"))); + } + + /** + * Test that if a retriever is registered and provides a context, but this + * context is not enabled in the tracing session, that it is not present in + * the trace. + */ + @Test + public void testContextAvailableButNotEnabled() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.STRING_RETRIEVER)); + + assertTrue(session.enableAllEvents()); + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + /* Test that there is no "_app" contexts in the output */ + output.forEach(line -> assertFalse(line.contains("_app"))); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test that if a context is enabled, but no retriever provides it, that the + * retriever/context names are still mentioned in the event but no value is + * provided. + */ + @Test + public void testContextNotAvailableButEnabled() { + assertTrue(session.enableAllEvents()); + assertTrue(session.enableAppContext(RETRIEVER_NAME_1, CONTEXT_NAME)); + + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + /* Test that context name is there but value is not */ + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, "{ none = { } } }"); + } + + /** + * Test that if a context is enabled and provided by a retriever that it is + * correctly present in the tracing session. + */ + @Test + public void testContextAvailableAndEnabled() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.STRING_RETRIEVER)); + + assertTrue(session.enableAllEvents()); + assertTrue(session.enableAppContext(RETRIEVER_NAME_1, CONTEXT_NAME)); + + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + /* Test that context name + value are present */ + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ string = \"" + ContextInfoRetrieverStubs.STRING_VALUE + "\" }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test that one context is available by a retriever, but another is is + * enabled in the session. Only the latter should be mentioned in events, + * with no value. + */ + @Test + public void testContextsOneAvailableOtherEnabled() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.STRING_RETRIEVER)); + + assertTrue(session.enableAllEvents()); + assertTrue(session.enableAppContext(RETRIEVER_NAME_2, CONTEXT_NAME)); + + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + /* Test that only retriever-name-2 is present, with no value */ + testContextNotPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME); + testContextPresentInTrace(output, RETRIEVER_NAME_2, CONTEXT_NAME, "{ none = { } } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test with two contexts provided in the application, but only one of them + * is enabled in the session. Only that one should be present in the trace, + * name and value. + */ + @Test + public void testContextsTwoAvailableOneEnabled() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.STRING_RETRIEVER)); + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_2, ContextInfoRetrieverStubs.INTEGER_RETRIEVER)); + + assertTrue(session.enableAllEvents()); + assertTrue(session.enableAppContext(RETRIEVER_NAME_1, CONTEXT_NAME)); + + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + /* Test that only retriever-name-1 is present, name + value */ + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ string = \"" + ContextInfoRetrieverStubs.STRING_VALUE + "\" }"); + testContextNotPresentInTrace(output, RETRIEVER_NAME_2, CONTEXT_NAME); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_2)); + } + + /** + * Test with two contexts enabled in the session but only one of them is + * provided by the application. Both should be mentioned in the trace, but + * only the provided one will have a value. + */ + @Test + public void testContextsOneAvailableTwoEnabled() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.STRING_RETRIEVER)); + + assertTrue(session.enableAllEvents()); + assertTrue(session.enableAppContext(RETRIEVER_NAME_1, CONTEXT_NAME)); + assertTrue(session.enableAppContext(RETRIEVER_NAME_2, CONTEXT_NAME)); + + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + /* Test that both contexts are present, but only retriever-1's has a value */ + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ string = \"" + ContextInfoRetrieverStubs.STRING_VALUE + "\" }"); + testContextPresentInTrace(output, RETRIEVER_NAME_2, CONTEXT_NAME, "{ none = { } } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + // ------------------------------------------------------------------------ + // Context types tests + // ------------------------------------------------------------------------ + + /** + * Utility method to enable all events, add the one context we are looking + * for, take a trace, and return the trace output. + */ + private List enableContextAndTrace() { + assertTrue(session.enableAllEvents()); + assertTrue(session.enableAppContext(RETRIEVER_NAME_1, CONTEXT_NAME)); + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + return output; + } + + /** + * Test a "null" context value. + */ + @Test + public void testContextValueNull() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.NULL_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, "{ none = { } } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test an integer (int32) context value. + */ + @Test + public void testContextValueInteger() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.INTEGER_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ int32 = " + ContextInfoRetrieverStubs.INTEGER_VALUE + " } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a long (int64) context value. + */ + @Test + public void testContextValueLong() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.LONG_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ int64 = " + ContextInfoRetrieverStubs.LONG_VALUE + " } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a double context value. + */ + @Test + public void testContextValueDouble() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.DOUBLE_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ double = " + ContextInfoRetrieverStubs.DOUBLE_VALUE + " } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a character context value (should get converted to a string). + */ + @Test + public void testContextValueCharacter() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.CHARACTER_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ string = \"" + ContextInfoRetrieverStubs.CHARACTER_VALUE + "\" } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a float context value. + */ + @Test + public void testContextValueFloat() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.FLOAT_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ float = " + ContextInfoRetrieverStubs.FLOAT_VALUE + " } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a byte (int8) context value. + */ + @Test + public void testContextValueByte() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.BYTE_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ int8 = " + ContextInfoRetrieverStubs.BYTE_VALUE + " } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a short (int16) context value. + */ + @Test + public void testContextValueShort() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.SHORT_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ int16 = " + ContextInfoRetrieverStubs.SHORT_VALUE + " } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a "true" boolean context value (gets converted to a int8 of value 1). + */ + @Test + public void testContextValueBooleanTrue() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.BOOLEAN_TRUE_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, "{ int8 = 1 } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a "false" boolean context value (gets converted to a int8 of value 0). + */ + @Test + public void testContextValueBooleanFalse() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.BOOLEAN_FALSE_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, "{ int8 = 0 } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a string context value. + */ + @Test + public void testContextValueString() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.STRING_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ string = \"" + ContextInfoRetrieverStubs.STRING_VALUE + "\" } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } + + /** + * Test a Object context value (should be converted to a String via .toString()). + */ + @Test + public void testContextValueObject() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME_1, ContextInfoRetrieverStubs.OBJECT_RETRIEVER)); + + List output = enableContextAndTrace(); + testContextPresentInTrace(output, RETRIEVER_NAME_1, CONTEXT_NAME, + "{ string = \"" + ContextInfoRetrieverStubs.OBJECT_VALUE.toString() + "\" } }"); + + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME_1)); + } +} diff --git a/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/AppContextOrderingITBase.java b/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/AppContextOrderingITBase.java new file mode 100644 index 0000000..d0acca3 --- /dev/null +++ b/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/AppContextOrderingITBase.java @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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.lttng.ust.agent.integration.context; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.List; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.lttng.tools.ILttngSession; +import org.lttng.tools.LttngToolsHelper; +import org.lttng.tools.ILttngSession.Domain; +import org.lttng.ust.agent.ILttngHandler; +import org.lttng.ust.agent.context.ContextInfoManager; +import org.lttng.ust.agent.context.IContextInfoRetriever; +import org.lttng.ust.agent.utils.TestPrintRunner; + +/** + * To obtain application contexts in a trace, three steps are required: + * + *
    + *
  • Having the Java agent register to the sessiond (Agent)
  • + *
  • Registering the application-provided context info retriever (Retriever)
  • + *
  • Enabling the contexts in the tracing session (Session)
  • + *
+ * + * These three steps however can occur in any order ; this means there are 6 + * possible cases. The goal of this class is to test all these cases. + */ +@RunWith(TestPrintRunner.class) +public abstract class AppContextOrderingITBase { + + protected static final String EVENT_NAME = "EventName"; + + private static final IContextInfoRetriever RETRIEVER = ContextInfoRetrieverStubs.STRING_RETRIEVER; + private static final String RETRIEVER_NAME = "MyRetriever"; + private static final String CONTEXT_NAME = ContextInfoRetrieverStubs.CONTEXT_NAME; + private static final String CONTEXT_VALUE = ContextInfoRetrieverStubs.STRING_VALUE; + + protected ILttngHandler logHandler; + + private ContextInfoManager cim; + private ILttngSession session; + + protected abstract Domain getDomain(); + protected abstract void sendEventsToLoggers(); + + /** + * Base test setup + */ + @Before + public void testSetup() { + try { + cim = ContextInfoManager.getInstance(); + } catch (SecurityException | IOException e) { + /* The native library is not available! */ + fail(); + } + session = ILttngSession.createSession(null, getDomain()); + } + + /** + * Base test cleanup + */ + @After + public void testCleanup() { + session.close(); + assertTrue(cim.unregisterContextInfoRetriever(RETRIEVER_NAME)); + } + + /** + * Base class cleanup + */ + @AfterClass + public static void julClassCleanup() { + LttngToolsHelper.deleteAllTraces(); + } + + // ------------------------------------------------------------------------ + // Utility methods + // ------------------------------------------------------------------------ + + /** + * Instantiate the log handler for the corresponding logging API. This will + * also spawn the agent and have it register to the sessiond, so it + * corresponds to the "Agent" step. + * + * This method should set the 'logHandler' field accordingly. + */ + protected abstract void registerAgent(); + + /** + * Register the context info retriever to UST. This corresponds to the + * "Retriever" step. + */ + private void registerRetriever() { + assertTrue(cim.registerContextInfoRetriever(RETRIEVER_NAME, RETRIEVER)); + } + + /** + * Enable the contexts in the tracing session. This corresponds to the "Session" step. + */ + private void enableContextInSessions() { + assertTrue(session.enableAllEvents()); + assertTrue(session.enableAppContext(RETRIEVER_NAME, CONTEXT_NAME)); + } + + /** + * Start tracing, send events from the application, and verify that the + * output contains the expected context information. + * + * This should be called only after all 3 steps above are done. + */ + private void traceSendEventsAndVerify() { + assertTrue(session.start()); + sendEventsToLoggers(); + assertTrue(session.stop()); + + List output = session.view(); + assertNotNull(output); + assertFalse(output.isEmpty()); + + String expectedString = "_app_" + RETRIEVER_NAME + "_" + CONTEXT_NAME + " = { string = \"" + CONTEXT_VALUE + "\" } }"; + output.forEach(line -> assertTrue(line.contains(expectedString))); + } + + // ------------------------------------------------------------------------ + // Test methods + // ------------------------------------------------------------------------ + + /** + * Test the sequence Agent -> Retriever -> Session + */ + @Test + public void testAgentRetrieverSession() { + registerAgent(); + registerRetriever(); + enableContextInSessions(); + + traceSendEventsAndVerify(); + } + + /** + * Test the sequence Agent -> Session -> Retriever + */ + @Test + public void testAgentSessionRetriever() { + registerAgent(); + enableContextInSessions(); + registerRetriever(); + + traceSendEventsAndVerify(); + } + + /** + * Test the sequence Retriever -> Agent -> Session + */ + @Test + public void testRetrieverAgentSession() { + registerRetriever(); + registerAgent(); + enableContextInSessions(); + + traceSendEventsAndVerify(); + } + + /** + * Test the sequence Retriever -> Session -> Agent + */ + @Test + public void testRetrieverSessionAgent() { + registerAgent(); + registerRetriever(); + enableContextInSessions(); + + traceSendEventsAndVerify(); + } + + /** + * Test the sequence Session -> Agent -> Retriever + */ + @Test + public void testSessionAgentRetriever() { + registerAgent(); + registerRetriever(); + enableContextInSessions(); + + traceSendEventsAndVerify(); + } + + /** + * Test the sequence Session -> Retriever -> Agent + */ + @Test + public void testSessionRetrieverAgent() { + registerAgent(); + registerRetriever(); + enableContextInSessions(); + + traceSendEventsAndVerify(); + } +} diff --git a/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/ContextInfoRetrieverStubs.java b/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/ContextInfoRetrieverStubs.java new file mode 100644 index 0000000..0981f77 --- /dev/null +++ b/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/ContextInfoRetrieverStubs.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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.lttng.ust.agent.integration.context; + +import org.lttng.ust.agent.context.IContextInfoRetriever; + +interface ContextInfoRetrieverStubs { + + String CONTEXT_NAME = "ContextName"; + + Integer INTEGER_VALUE = Integer.valueOf(42); + Long LONG_VALUE = Long.valueOf(9001); + Double DOUBLE_VALUE = Double.valueOf(11.55); + Character CHARACTER_VALUE = Character.valueOf('a'); + Float FLOAT_VALUE = Float.valueOf(2.8f); + Byte BYTE_VALUE = Byte.valueOf((byte) 8); + Short SHORT_VALUE = Short.valueOf((short) 500); + String STRING_VALUE = "ContextValue"; + + String OBJECT_VALUE_STRING = "ValueToString"; + Object OBJECT_VALUE = new Object() { + @Override + public String toString() { + return OBJECT_VALUE_STRING; + } + }; + + + IContextInfoRetriever NULL_RETRIEVER = (key -> null); + IContextInfoRetriever INTEGER_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? INTEGER_VALUE : null)); + IContextInfoRetriever LONG_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? LONG_VALUE : null)); + IContextInfoRetriever DOUBLE_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? DOUBLE_VALUE : null)); + IContextInfoRetriever CHARACTER_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? CHARACTER_VALUE : null)); + IContextInfoRetriever FLOAT_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? FLOAT_VALUE : null)); + IContextInfoRetriever BYTE_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? BYTE_VALUE : null)); + IContextInfoRetriever SHORT_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? SHORT_VALUE : null)); + IContextInfoRetriever BOOLEAN_TRUE_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? Boolean.TRUE : null)); + IContextInfoRetriever BOOLEAN_FALSE_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? Boolean.FALSE : null)); + IContextInfoRetriever STRING_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? STRING_VALUE : null)); + IContextInfoRetriever OBJECT_RETRIEVER = (key -> (CONTEXT_NAME.equals(key) ? OBJECT_VALUE : null)); + +} diff --git a/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/LttngContextValues.java b/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/LttngContextValues.java new file mode 100644 index 0000000..5c9fc92 --- /dev/null +++ b/lttng-ust-java-tests-common/src/main/java/org/lttng/ust/agent/integration/context/LttngContextValues.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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.lttng.ust.agent.integration.context; + +/** + * Values defined by the LTTng tracer related to dynamically-typed contexts + */ +interface LttngContextValues { + + // TODO check that these are all the right values + String NULL_TYPE_NAME = ""; + String INTEGER_TYPE_NAME = "int"; + String LONG_TYPE_NAME = "long"; + String DOUBLE_TYPE_NAME = "double"; + String CHARACTER_TYPE_NAME = "char"; + String FLOAT_TYPE_NAME = "float"; + String BYTE_TYPE_NAME = "byte"; + String SHORT_TYPE_NAME = "short"; + String BOOLEAN_TYPE_NAME = "bool"; + String STRING_TYPE_NAME = "string"; +} diff --git a/lttng-ust-java-tests-common/src/test/java/org/lttng/ust/agent/integration/client/TcpClientDebugListener.java b/lttng-ust-java-tests-common/src/test/java/org/lttng/ust/agent/integration/client/TcpClientDebugListener.java index 1b6ce47..abc9d42 100644 --- a/lttng-ust-java-tests-common/src/test/java/org/lttng/ust/agent/integration/client/TcpClientDebugListener.java +++ b/lttng-ust-java-tests-common/src/test/java/org/lttng/ust/agent/integration/client/TcpClientDebugListener.java @@ -36,6 +36,9 @@ public class TcpClientDebugListener implements ILttngTcpClientListener { private final List enabledEventCommands = Collections.synchronizedList(new ArrayList<>()); private final List disabledEventCommands = Collections.synchronizedList(new ArrayList<>()); + private final List enabledAppContextCommands = Collections.synchronizedList(new ArrayList<>()); + private final List disabledAppContextCommands = Collections.synchronizedList(new ArrayList<>()); + @Override public boolean eventEnabled(EventRule rule) { enabledEventCommands.add(rule); @@ -49,15 +52,15 @@ public class TcpClientDebugListener implements ILttngTcpClientListener { } @Override - public boolean appContextDisabled(String contextRetrieverName, String contextName) { - // TODO NYI - return false; + public boolean appContextEnabled(String contextRetrieverName, String contextName) { + enabledAppContextCommands.add(contextRetrieverName + ':' + contextName); + return true; } @Override - public boolean appContextEnabled(String contextRetrieverName, String contextName) { - // TODO NYI - return false; + public boolean appContextDisabled(String contextRetrieverName, String contextName) { + disabledAppContextCommands.add(contextRetrieverName + ':' + contextName); + return true; } /** @@ -89,12 +92,39 @@ public class TcpClientDebugListener implements ILttngTcpClientListener { } } + /** + * @return The "add-context" commands that were received since instantiation + * or the last {@link #clearAllCommands}. + */ + public List getEnabledAppContextCommands() { + synchronized (enabledAppContextCommands) { + return new ArrayList<>(enabledAppContextCommands); + } + } + + /** + * Return the number of "context disabled" commands received. + * + * There is no equivalent command in the lttng CLI, but the sessiond will + * send such messages through the agent socket when a session is destroyed + * and had contexts enabled. + * + * @return The number of "context disabled" commands received. + */ + public List getDisabledAppContextCommands() { + synchronized (disabledAppContextCommands) { + return new ArrayList<>(disabledAppContextCommands); + } + } + /** * Clear all tracked data. */ public void clearAllCommands() { enabledEventCommands.clear(); disabledEventCommands.clear(); + enabledAppContextCommands.clear(); + disabledAppContextCommands.clear(); } } diff --git a/lttng-ust-java-tests-common/src/test/java/org/lttng/ust/agent/integration/client/TcpClientIT.java b/lttng-ust-java-tests-common/src/test/java/org/lttng/ust/agent/integration/client/TcpClientIT.java index 16c7d01..a86a273 100644 --- a/lttng-ust-java-tests-common/src/test/java/org/lttng/ust/agent/integration/client/TcpClientIT.java +++ b/lttng-ust-java-tests-common/src/test/java/org/lttng/ust/agent/integration/client/TcpClientIT.java @@ -64,6 +64,11 @@ public class TcpClientIT { private static final String EVENT_NAME_B = "eventB"; private static final String EVENT_NAME_C = "eventC"; + private static final String CONTEXT_RETRIEVER_NAME_A = "retrieverA"; + private static final String CONTEXT_RETRIEVER_NAME_B = "retrieverB"; + private static final String CONTEXT_NAME_A = "contextA"; + private static final String CONTEXT_NAME_B = "contextB"; + /* Test configuration */ private static final int DOMAIN_VALUE = ILttngAgent.Domain.JUL.value(); private static final ILttngSession.Domain SESSION_DOMAIN = ILttngSession.Domain.JUL; @@ -147,7 +152,7 @@ public class TcpClientIT { } // ------------------------------------------------------------------------ - // Test cases + // Event enabling/disabling test cases // ------------------------------------------------------------------------ /** @@ -392,4 +397,133 @@ public class TcpClientIT { assertEquals(expectedCommands, actualCommands); } + + // ------------------------------------------------------------------------ + // Application context enabling/disabling test cases + // ------------------------------------------------------------------------ + + /** + * Test enabling one application context. + */ + @Test + public void testEnableAppContext() { + session.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_A); + + List expectedCommands = Collections.singletonList( + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A); + + List actualCommands = clientListener.getEnabledAppContextCommands(); + assertEquals(expectedCommands, actualCommands); + } + + /** + * Test enabling two application contexts sharing the same retriever name. + */ + @Test + public void testEnableAppContextsSameRetriever() { + session.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_A); + session.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_B); + + List expectedCommands = Arrays.asList( + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A, + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_B); + + List actualCommands = clientListener.getEnabledAppContextCommands(); + assertEquals(expectedCommands, actualCommands); + } + + /** + * Test enabling two application contexts sharing the same context name, but + * with different retrievers. Unusual, but they should still be recognized + * separately. + */ + @Test + public void testEnableAppContextsSameContext() { + session.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_A); + session.enableAppContext(CONTEXT_RETRIEVER_NAME_B, CONTEXT_NAME_A); + + List expectedCommands = Arrays.asList( + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A, + CONTEXT_RETRIEVER_NAME_B + ':' + CONTEXT_NAME_A); + + List actualCommands = clientListener.getEnabledAppContextCommands(); + assertEquals(expectedCommands, actualCommands); + } + + /** + * Test enabling one application context, then destroying the session. We + * should receive the corresponding "context removed" message. + */ + @Test + @SuppressWarnings("static-method") + public void testEnableAppContextThenDestroy() { + try (ILttngSession session2 = ILttngSession.createSession(null, SESSION_DOMAIN);) { + session2.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_A); + } // close(), aka destroy the session, sending "disable context" messages + + List expectedEnabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A); + List expectedDisabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A); + List actualEnabledCommands = clientListener.getEnabledAppContextCommands(); + List actualDisabledCommands = clientListener.getDisabledAppContextCommands(); + + assertEquals(expectedEnabledCommands, actualEnabledCommands); + assertEquals(expectedDisabledCommands, actualDisabledCommands); + } + + /** + * Test enabling the same application context in two different sessions. + * Upon destroying one, we should only receive one "destroyed" message. + */ + @Test + public void testEnableSameAppContextTwoSessions() { + List expectedEnabledCommands = Arrays.asList( + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A, + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A); + List actualEnabledCommands; + + try (ILttngSession session2 = ILttngSession.createSession(null, SESSION_DOMAIN);) { + session.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_A); + session2.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_A); + + actualEnabledCommands = clientListener.getEnabledAppContextCommands(); + assertEquals(expectedEnabledCommands, actualEnabledCommands); + } // close/destroy session2 + + actualEnabledCommands = clientListener.getEnabledAppContextCommands(); + assertEquals(expectedEnabledCommands, actualEnabledCommands); + + List expectedDisabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A); + List actualDisabledCommands = clientListener.getDisabledAppContextCommands(); + + assertEquals(expectedDisabledCommands, actualDisabledCommands); + } + + /** + * Test enabling two different application context in two different + * sessions. Upon destroying one, we should receive the correct "destroyed" + * message. + */ + @Test + public void testEnableDiffAppContextTwoSessions() { + List expectedEnabledCommands = Arrays.asList( + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A, + CONTEXT_RETRIEVER_NAME_B + ':' + CONTEXT_NAME_B); + List actualEnabledCommands; + + try (ILttngSession session2 = ILttngSession.createSession(null, SESSION_DOMAIN);) { + session.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_A); + session2.enableAppContext(CONTEXT_RETRIEVER_NAME_B, CONTEXT_NAME_B); + + actualEnabledCommands = clientListener.getEnabledAppContextCommands(); + assertEquals(expectedEnabledCommands, actualEnabledCommands); + } // close/destroy session2 + + actualEnabledCommands = clientListener.getEnabledAppContextCommands(); + assertEquals(expectedEnabledCommands, actualEnabledCommands); + + List expectedDisabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_B + ':' + CONTEXT_NAME_B); + List actualDisabledCommands = clientListener.getDisabledAppContextCommands(); + + assertEquals(expectedDisabledCommands, actualDisabledCommands); + } } diff --git a/lttng-ust-java-tests-jul/src/test/java/org/lttng/ust/agent/integration/context/JulAppContextIT.java b/lttng-ust-java-tests-jul/src/test/java/org/lttng/ust/agent/integration/context/JulAppContextIT.java new file mode 100644 index 0000000..aaecf41 --- /dev/null +++ b/lttng-ust-java-tests-jul/src/test/java/org/lttng/ust/agent/integration/context/JulAppContextIT.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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.lttng.ust.agent.integration.context; + +import static org.junit.Assume.assumeTrue; + +import java.io.IOException; +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.lttng.tools.ILttngSession.Domain; +import org.lttng.tools.LttngToolsHelper; +import org.lttng.ust.agent.jul.LttngLogHandler; +import org.lttng.ust.agent.utils.JulTestUtils; +import org.lttng.ust.agent.utils.LttngUtils; + +/** + * Enabled app contexts test for the LTTng-UST JUL log handler. + */ +public class JulAppContextIT extends AppContextITBase { + + private static final Domain DOMAIN = Domain.JUL; + + private Logger logger; + + /** + * Class setup + */ + @BeforeClass + public static void julClassSetup() { + /* Skip tests if we can't find the JNI library or lttng-tools */ + assumeTrue(JulTestUtils.checkForJulLibrary()); + assumeTrue(LttngUtils.checkForLttngTools(Domain.JUL)); + + LttngToolsHelper.destroyAllSessions(); + } + + /** + * Class cleanup + */ + @AfterClass + public static void julClassCleanup() { + LttngToolsHelper.deleteAllTraces(); + } + + /** + * Test setup + * + * @throws SecurityException + * @throws IOException + */ + @Before + public void julSetup() throws SecurityException, IOException { + logger = Logger.getLogger(EVENT_NAME); + logger.setLevel(Level.ALL); + + logHandler = new LttngLogHandler(); + logger.addHandler((Handler) logHandler); + } + + /** + * Test teardown + */ + @After + public void julTeardown() { + logger.removeHandler((Handler) logHandler); + logger = null; + } + + @Override + protected Domain getDomain() { + return DOMAIN; + } + + @Override + protected void sendEventsToLoggers() { + JulTestUtils.send10EventsTo(logger); + } +} diff --git a/lttng-ust-java-tests-jul/src/test/java/org/lttng/ust/agent/integration/context/JulAppContextOrderingIT.java b/lttng-ust-java-tests-jul/src/test/java/org/lttng/ust/agent/integration/context/JulAppContextOrderingIT.java new file mode 100644 index 0000000..1cef0d4 --- /dev/null +++ b/lttng-ust-java-tests-jul/src/test/java/org/lttng/ust/agent/integration/context/JulAppContextOrderingIT.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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.lttng.ust.agent.integration.context; + +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +import java.io.IOException; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.junit.After; +import org.junit.BeforeClass; +import org.lttng.tools.ILttngSession.Domain; +import org.lttng.tools.LttngToolsHelper; +import org.lttng.ust.agent.jul.LttngLogHandler; +import org.lttng.ust.agent.utils.JulTestUtils; +import org.lttng.ust.agent.utils.LttngUtils; + +/** + * Implementation of {@link AppContextOrderingITBase} for the JUL API. + */ +public class JulAppContextOrderingIT extends AppContextOrderingITBase { + + private Logger logger; + + /** + * Class setup + */ + @BeforeClass + public static void julClassSetup() { + /* Skip tests if we can't find the JNI library or lttng-tools */ + assumeTrue(JulTestUtils.checkForJulLibrary()); + assumeTrue(LttngUtils.checkForLttngTools(Domain.JUL)); + + LttngToolsHelper.destroyAllSessions(); + } + + /** + * Test teardown + */ + @After + public void julTeardown() { + logger.removeHandler((Handler) logHandler); + logger = null; + + logHandler.close(); + logHandler = null; + } + + @Override + protected Domain getDomain() { + return Domain.JUL; + } + + @Override + protected void registerAgent() { + logger = Logger.getLogger(EVENT_NAME); + logger.setLevel(Level.ALL); + + try { + logHandler = new LttngLogHandler(); + } catch (SecurityException | IOException e) { + fail(); + } + logger.addHandler((Handler) logHandler); + } + + @Override + protected void sendEventsToLoggers() { + JulTestUtils.send10EventsTo(logger); + } +} diff --git a/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/integration/context/Log4jAppContextIT.java b/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/integration/context/Log4jAppContextIT.java new file mode 100644 index 0000000..bc8e631 --- /dev/null +++ b/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/integration/context/Log4jAppContextIT.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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.lttng.ust.agent.integration.context; + +import static org.junit.Assume.assumeTrue; + +import java.io.IOException; + +import org.apache.log4j.Appender; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.lttng.tools.ILttngSession.Domain; +import org.lttng.tools.LttngToolsHelper; +import org.lttng.ust.agent.log4j.LttngLogAppender; +import org.lttng.ust.agent.utils.Log4jTestUtils; +import org.lttng.ust.agent.utils.LttngUtils; + +/** + * Enabled app contexts test for the LTTng-UST JUL log handler. + */ +public class Log4jAppContextIT extends AppContextITBase { + + private static final Domain DOMAIN = Domain.LOG4J; + + private Logger logger; + + /** + * Class setup + */ + @BeforeClass + public static void julClassSetup() { + /* Skip tests if we can't find the log4j library or lttng-tools */ + assumeTrue(Log4jTestUtils.checkForLog4jLibrary()); + assumeTrue(LttngUtils.checkForLttngTools(Domain.LOG4J)); + + LttngToolsHelper.destroyAllSessions(); + } + + /** + * Class cleanup + */ + @AfterClass + public static void julClassCleanup() { + LttngToolsHelper.deleteAllTraces(); + } + + /** + * Test setup + * + * @throws SecurityException + * @throws IOException + */ + @Before + public void julSetup() throws SecurityException, IOException { + logger = Logger.getLogger(EVENT_NAME); + logger.setLevel(Level.ALL); + + logHandler = new LttngLogAppender(); + logger.addAppender((Appender) logHandler); + } + + /** + * Test teardown + */ + @After + public void julTeardown() { + logger.removeAppender((Appender) logHandler); + logger = null; + } + + @Override + protected Domain getDomain() { + return DOMAIN; + } + + @Override + protected void sendEventsToLoggers() { + Log4jTestUtils.send10Events(logger); + } +} diff --git a/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/integration/context/Log4jAppContextOrderingIT.java b/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/integration/context/Log4jAppContextOrderingIT.java new file mode 100644 index 0000000..69e45bc --- /dev/null +++ b/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/integration/context/Log4jAppContextOrderingIT.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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.lttng.ust.agent.integration.context; + +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +import java.io.IOException; + +import org.apache.log4j.Appender; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.BeforeClass; +import org.lttng.tools.ILttngSession.Domain; +import org.lttng.tools.LttngToolsHelper; +import org.lttng.ust.agent.log4j.LttngLogAppender; +import org.lttng.ust.agent.utils.Log4jTestUtils; +import org.lttng.ust.agent.utils.LttngUtils; + +/** + * Implementation of {@link AppContextOrderingITBase} for the log4j API. + */ +public class Log4jAppContextOrderingIT extends AppContextOrderingITBase { + + private Logger logger; + + /** + * Class setup + */ + @BeforeClass + public static void log4jClassSetup() { + /* Skip tests if we can't find the JNI library or lttng-tools */ + assumeTrue(Log4jTestUtils.checkForLog4jLibrary()); + assumeTrue(LttngUtils.checkForLttngTools(Domain.LOG4J)); + + LttngToolsHelper.destroyAllSessions(); + } + + /** + * Test teardown + */ + @After + public void log4jTeardown() { + logger.removeAppender((Appender) logHandler); + logger = null; + + logHandler.close(); + logHandler = null; + } + + @Override + protected Domain getDomain() { + return Domain.LOG4J; + } + + @Override + protected void registerAgent() { + logger = Logger.getLogger(EVENT_NAME); + logger.setLevel(Level.ALL); + + try { + logHandler = new LttngLogAppender(); + } catch (SecurityException | IOException e) { + fail(); + } + logger.addAppender((Appender) logHandler); + } + + @Override + protected void sendEventsToLoggers() { + Log4jTestUtils.send10Events(logger); + } +} diff --git a/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/utils/Log4jTestUtils.java b/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/utils/Log4jTestUtils.java index 3e67f1f..b356dbe 100644 --- a/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/utils/Log4jTestUtils.java +++ b/lttng-ust-java-tests-log4j/src/test/java/org/lttng/ust/agent/utils/Log4jTestUtils.java @@ -43,6 +43,7 @@ public final class Log4jTestUtils { LttngLogAppender testAppender = new LttngLogAppender(); testAppender.close(); } catch (SecurityException | IOException e) { + e.printStackTrace(); return false; } return true;