package org.lttng.ust.agent.integration.client;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
import org.lttng.tools.ILttngSession;
import org.lttng.tools.LttngToolsHelper;
import org.lttng.ust.agent.ILttngAgent;
import org.lttng.ust.agent.session.LogLevelSelector.LogLevelType;
import org.lttng.ust.agent.utils.EventRuleFactory;
import org.lttng.ust.agent.utils.ILogLevelStrings;
-import org.lttng.ust.agent.utils.TestPrintRunner;
+import org.lttng.ust.agent.utils.TestPrintExtension;
/**
* Tests for the TCP client only, without using an agent.
*
* @author Alexandre Montplaisir
*/
-@RunWith(TestPrintRunner.class)
+@ExtendWith(TestPrintExtension.class)
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;
- private static final boolean ROOT_SESSIOND = true;
private static TcpClientDebugListener clientListener;
private static LttngTcpSessiondClient client;
/**
* Class setup
*/
- @BeforeClass
+ @BeforeAll
public static void setupClass() {
LttngToolsHelper.destroyAllSessions();
clientListener = new TcpClientDebugListener();
- client = new LttngTcpSessiondClient(clientListener, DOMAIN_VALUE, ROOT_SESSIOND);
+ /* Try connecting to a root sessiond first */
+ client = new LttngTcpSessiondClient(clientListener, DOMAIN_VALUE, true);
clientThread = new Thread(client);
clientThread.start();
- assumeTrue("Timed out waiting for root sessiond", client.waitForConnection(5));
+ if (client.waitForConnection(5)) {
+ return;
+ }
+
+ /* Connection was not established, try a user sessiond instead */
+ client.close();
+ try {
+ clientThread.join();
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+
+ client = new LttngTcpSessiondClient(clientListener, DOMAIN_VALUE, false);
+ clientThread = new Thread(client);
+ clientThread.start();
+
+ assertTrue(client.waitForConnection(5), "Timed out waiting for a sessiond");
}
/**
* Class teardown
*/
- @AfterClass
+ @AfterAll
public static void teardownClass() {
if (client != null) {
client.close();
/**
* Test setup
*/
- @Before
+ @BeforeEach
public void setup() {
session = ILttngSession.createSession(null, SESSION_DOMAIN);
clientListener.clearAllCommands();
/**
* Test teardown
*/
- @After
+ @AfterEach
public void teardown() {
session.close();
}
}
// ------------------------------------------------------------------------
- // Test cases
+ // Event enabling/disabling test cases
// ------------------------------------------------------------------------
/**
List<String> expectedDisabledCommands = Arrays.asList(EVENT_NAME_A, EVENT_NAME_B);
assertEquals(expectedEnabledCommands, clientListener.getEnabledEventCommands());
- assertEquals(expectedDisabledCommands, clientListener.getDisabledEventCommands());
+ assertTrue(clientListener.getDisabledEventCommands().containsAll(expectedDisabledCommands));
}
/**
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<String> expectedCommands = Collections.singletonList(
+ CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+
+ List<String> 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<String> expectedCommands = Arrays.asList(
+ CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A,
+ CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_B);
+
+ List<String> 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<String> expectedCommands = Arrays.asList(
+ CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A,
+ CONTEXT_RETRIEVER_NAME_B + ':' + CONTEXT_NAME_A);
+
+ List<String> 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<String> expectedEnabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+ List<String> expectedDisabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+ List<String> actualEnabledCommands = clientListener.getEnabledAppContextCommands();
+ List<String> 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<String> expectedEnabledCommands = Arrays.asList(
+ CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A,
+ CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+ List<String> 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<String> expectedDisabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+ List<String> 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<String> expectedEnabledCommands = Arrays.asList(
+ CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A,
+ CONTEXT_RETRIEVER_NAME_B + ':' + CONTEXT_NAME_B);
+ List<String> 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<String> expectedDisabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_B + ':' + CONTEXT_NAME_B);
+ List<String> actualDisabledCommands = clientListener.getDisabledAppContextCommands();
+
+ assertEquals(expectedDisabledCommands, actualDisabledCommands);
+ }
+
+ // ------------------------------------------------------------------------
+ // Application context filtering
+ // ------------------------------------------------------------------------
+
+ /**
+ * Test that enabling an event with a filter string referring to a context
+ * should send an agent message about this context now being "enabled".
+ *
+ * This is because we will pass the context information to UST for the
+ * filtering step, even if the actual context won't be present in the trace.
+ */
+ @SuppressWarnings("static-method")
+ @Test
+ public void testContextInFilterString() {
+ try (ILttngSession session2 = ILttngSession.createSession(null, SESSION_DOMAIN);) {
+ session2.enableEvent(EVENT_NAME_A, null, false, "$app." + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A + "==\"bozo\"");
+
+ List<String> expectedEnabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+ assertEquals(expectedEnabledCommands, clientListener.getEnabledAppContextCommands());
+ } // close(), aka destroy the session, sending "disable context" messages
+
+ List<String> expectedDisabledCommands = Collections.singletonList(CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+ assertEquals(expectedDisabledCommands, clientListener.getDisabledAppContextCommands());
+ }
+
+ /**
+ * Test that if we the context is both referred to by a filter string *and*
+ * enabled directly, we receive *2* messages about this context being
+ * enabled (and disabled on session teardown).
+ */
+ @SuppressWarnings("static-method")
+ @Test
+ public void testContextEnabledAndInFilterString() {
+ try (ILttngSession session2 = ILttngSession.createSession(null, SESSION_DOMAIN);) {
+ session2.enableEvent(EVENT_NAME_A, null, false, "$app." + CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A + "==\"bozo\"");
+ session2.enableAppContext(CONTEXT_RETRIEVER_NAME_A, CONTEXT_NAME_A);
+
+ List<String> expectedEnabledCommands = Collections.nCopies(2, CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+ assertEquals(expectedEnabledCommands, clientListener.getEnabledAppContextCommands());
+ } // close(), aka destroy the session, sending "disable context" messages
+
+ List<String> expectedDisabledCommands = Collections.nCopies(2, CONTEXT_RETRIEVER_NAME_A + ':' + CONTEXT_NAME_A);
+ assertEquals(expectedDisabledCommands, clientListener.getDisabledAppContextCommands());
+ }
}