2 * Copyright (C) 2016, EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 package org
.lttng
.ust
.agent
.integration
.context
;
21 import static org
.junit
.Assert
.assertFalse
;
22 import static org
.junit
.Assert
.assertNotNull
;
23 import static org
.junit
.Assert
.assertTrue
;
24 import static org
.junit
.Assert
.fail
;
26 import java
.io
.IOException
;
27 import java
.util
.List
;
29 import org
.junit
.After
;
30 import org
.junit
.Before
;
31 import org
.junit
.Test
;
32 import org
.junit
.runner
.RunWith
;
33 import org
.lttng
.tools
.ILttngSession
;
34 import org
.lttng
.tools
.ILttngSession
.Domain
;
35 import org
.lttng
.ust
.agent
.ILttngHandler
;
36 import org
.lttng
.ust
.agent
.context
.ContextInfoManager
;
37 import org
.lttng
.ust
.agent
.utils
.TestPrintRunner
;
40 * Base abstract class to implement all sorts of integration tests verifying the
41 * presence of enabled application contexts in resulting traces.
43 @RunWith(TestPrintRunner
.class)
44 public abstract class AppContextITBase
{
46 protected static final String EVENT_NAME
= "EventName";
48 protected static final String RETRIEVER_NAME_1
= "Retriever1";
49 protected static final String RETRIEVER_NAME_2
= "some.retriever_2";
51 private static final String CONTEXT_NAME
= ContextInfoRetrieverStubs
.CONTEXT_NAME
;
53 private ContextInfoManager cim
;
54 private ILttngSession session
;
56 /* Field defined by the sub-class */
57 protected ILttngHandler logHandler
;
59 protected abstract Domain
getDomain();
61 protected abstract boolean closeHandlers();
63 protected abstract void sendEventsToLoggers();
69 public void testSetup() {
71 cim
= ContextInfoManager
.getInstance();
72 } catch (SecurityException
| IOException e
) {
73 /* The native library is not available! */
76 session
= ILttngSession
.createSession(null, getDomain());
83 public void testTeardown() {
86 if (closeHandlers()) {
91 /* In case some tests fail or forget to unregister their retrievers */
92 cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
);
93 cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_2
);
96 // ------------------------------------------------------------------------
97 // Context enabled/disabled tests
98 // ------------------------------------------------------------------------
101 * Utility method to check that a context is present in all events of a
104 private static void testContextPresentInTrace(List
<String
> traceOutput
, String retrieverName
, String contextName
, String contextValue
) {
105 String traceRetrieverName
= convertToNameInTrace(retrieverName
);
106 String traceContextName
= convertToNameInTrace(contextName
);
108 String fullString
= "_app_" + traceRetrieverName
+ "_" + traceContextName
+ " = " + contextValue
;
109 traceOutput
.forEach(line
-> assertTrue(line
.contains(fullString
)));
113 * Utility method to check that a context is *absent* from all events of a
116 private static void testContextNotPresentInTrace(List
<String
> traceOutput
, String retrieverName
, String contextName
) {
117 String traceRetrieverName
= convertToNameInTrace(retrieverName
);
118 String traceContextName
= convertToNameInTrace(contextName
);
120 String fullString
= "_app_" + traceRetrieverName
+ "_" + traceContextName
;
121 traceOutput
.forEach(line
-> assertFalse(line
.contains(fullString
)));
125 * LTTng accepts periods in context names, but ends up printing them as
126 * underscores in the trace, so the metadata grammar remains valid.
128 private static String
convertToNameInTrace(String name
) {
129 return name
.replace('.', '_');
133 * Test that if no retrievers are declared, no context info is passed at
137 public void testNoContexts() {
138 assertTrue(session
.enableAllEvents());
139 assertTrue(session
.start());
140 sendEventsToLoggers();
141 assertTrue(session
.stop());
143 List
<String
> output
= session
.view();
144 assertNotNull(output
);
145 assertFalse(output
.isEmpty());
147 /* Test that there is no "_app" contexts in the output */
148 output
.forEach(line
-> assertFalse(line
.contains("_app")));
152 * Test that if a retriever is registered and provides a context, but this
153 * context is not enabled in the tracing session, that it is not present in
157 public void testContextAvailableButNotEnabled() {
158 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
160 assertTrue(session
.enableAllEvents());
161 assertTrue(session
.start());
162 sendEventsToLoggers();
163 assertTrue(session
.stop());
165 List
<String
> output
= session
.view();
166 assertNotNull(output
);
167 assertFalse(output
.isEmpty());
169 /* Test that there is no "_app" contexts in the output */
170 output
.forEach(line
-> assertFalse(line
.contains("_app")));
172 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
176 * Test that if a context is enabled, but no retriever provides it, that the
177 * retriever/context names are still mentioned in the event but no value is
181 public void testContextNotAvailableButEnabled() {
182 assertTrue(session
.enableAllEvents());
183 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
185 assertTrue(session
.start());
186 sendEventsToLoggers();
187 assertTrue(session
.stop());
189 List
<String
> output
= session
.view();
190 assertNotNull(output
);
191 assertFalse(output
.isEmpty());
193 /* Test that context name is there but value is not */
194 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
, "{ { } } }");
198 * Test that if a context is enabled and provided by a retriever that it is
199 * correctly present in the tracing session.
202 public void testContextAvailableAndEnabled() {
203 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
205 assertTrue(session
.enableAllEvents());
206 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
208 assertTrue(session
.start());
209 sendEventsToLoggers();
210 assertTrue(session
.stop());
212 List
<String
> output
= session
.view();
213 assertNotNull(output
);
214 assertFalse(output
.isEmpty());
216 /* Test that context name + value are present */
217 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
218 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" }");
220 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
224 * Test that one context is available by a retriever, but another is is
225 * enabled in the session. Only the latter should be mentioned in events,
229 public void testContextsOneAvailableOtherEnabled() {
230 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
232 assertTrue(session
.enableAllEvents());
233 assertTrue(session
.enableAppContext(RETRIEVER_NAME_2
, CONTEXT_NAME
));
235 assertTrue(session
.start());
236 sendEventsToLoggers();
237 assertTrue(session
.stop());
239 List
<String
> output
= session
.view();
240 assertNotNull(output
);
241 assertFalse(output
.isEmpty());
243 /* Test that only retriever-name-2 is present, with no value */
244 testContextNotPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
);
245 testContextPresentInTrace(output
, RETRIEVER_NAME_2
, CONTEXT_NAME
, "{ { } } }");
247 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
251 * Test with two contexts provided in the application, but only one of them
252 * is enabled in the session. Only that one should be present in the trace,
256 public void testContextsTwoAvailableOneEnabled() {
257 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
258 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_2
, ContextInfoRetrieverStubs
.INTEGER_RETRIEVER
));
260 assertTrue(session
.enableAllEvents());
261 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
263 assertTrue(session
.start());
264 sendEventsToLoggers();
265 assertTrue(session
.stop());
267 List
<String
> output
= session
.view();
268 assertNotNull(output
);
269 assertFalse(output
.isEmpty());
271 /* Test that only retriever-name-1 is present, name + value */
272 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
273 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" }");
274 testContextNotPresentInTrace(output
, RETRIEVER_NAME_2
, CONTEXT_NAME
);
276 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
277 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_2
));
281 * Test with two contexts enabled in the session but only one of them is
282 * provided by the application. Both should be mentioned in the trace, but
283 * only the provided one will have a value.
286 public void testContextsOneAvailableTwoEnabled() {
287 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
289 assertTrue(session
.enableAllEvents());
290 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
291 assertTrue(session
.enableAppContext(RETRIEVER_NAME_2
, CONTEXT_NAME
));
293 assertTrue(session
.start());
294 sendEventsToLoggers();
295 assertTrue(session
.stop());
297 List
<String
> output
= session
.view();
298 assertNotNull(output
);
299 assertFalse(output
.isEmpty());
301 /* Test that both contexts are present, but only retriever-1's has a value */
302 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
303 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" }");
304 testContextPresentInTrace(output
, RETRIEVER_NAME_2
, CONTEXT_NAME
, "{ { } } }");
306 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
309 // ------------------------------------------------------------------------
310 // Context types tests
311 // ------------------------------------------------------------------------
314 * Utility method to enable all events, add the one context we are looking
315 * for, take a trace, and return the trace output.
317 private List
<String
> enableContextAndTrace() {
318 assertTrue(session
.enableAllEvents());
319 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
320 assertTrue(session
.start());
321 sendEventsToLoggers();
322 assertTrue(session
.stop());
324 List
<String
> output
= session
.view();
325 assertNotNull(output
);
326 assertFalse(output
.isEmpty());
332 * Test a "null" context value.
335 public void testContextValueNull() {
336 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.NULL_RETRIEVER
));
338 List
<String
> output
= enableContextAndTrace();
339 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
, "{ { } } }");
341 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
345 * Test an integer (int32) context value.
348 public void testContextValueInteger() {
349 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.INTEGER_RETRIEVER
));
351 List
<String
> output
= enableContextAndTrace();
352 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
353 "{ " + ContextInfoRetrieverStubs
.INTEGER_VALUE
+ " } }");
355 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
359 * Test a long (int64) context value.
362 public void testContextValueLong() {
363 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.LONG_RETRIEVER
));
365 List
<String
> output
= enableContextAndTrace();
366 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
367 "{ " + ContextInfoRetrieverStubs
.LONG_VALUE
+ " } }");
369 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
373 * Test a double context value.
376 public void testContextValueDouble() {
377 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.DOUBLE_RETRIEVER
));
379 List
<String
> output
= enableContextAndTrace();
380 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
381 "{ " + ContextInfoRetrieverStubs
.DOUBLE_VALUE
+ " } }");
383 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
387 * Test a character context value (should get converted to a string).
390 public void testContextValueCharacter() {
391 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.CHARACTER_RETRIEVER
));
393 List
<String
> output
= enableContextAndTrace();
394 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
395 "{ \"" + ContextInfoRetrieverStubs
.CHARACTER_VALUE
+ "\" } }");
397 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
401 * Test a float context value.
404 public void testContextValueFloat() {
405 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.FLOAT_RETRIEVER
));
407 List
<String
> output
= enableContextAndTrace();
408 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
409 "{ " + ContextInfoRetrieverStubs
.FLOAT_VALUE
+ " } }");
411 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
415 * Test a byte (int8) context value.
418 public void testContextValueByte() {
419 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.BYTE_RETRIEVER
));
421 List
<String
> output
= enableContextAndTrace();
422 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
423 "{ " + ContextInfoRetrieverStubs
.BYTE_VALUE
+ " } }");
425 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
429 * Test a short (int16) context value.
432 public void testContextValueShort() {
433 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.SHORT_RETRIEVER
));
435 List
<String
> output
= enableContextAndTrace();
436 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
437 "{ " + ContextInfoRetrieverStubs
.SHORT_VALUE
+ " } }");
439 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
443 * Test a "true" boolean context value (gets converted to a int8 of value 1).
446 public void testContextValueBooleanTrue() {
447 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.BOOLEAN_TRUE_RETRIEVER
));
449 List
<String
> output
= enableContextAndTrace();
450 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
, "{ 1 } }");
452 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
456 * Test a "false" boolean context value (gets converted to a int8 of value 0).
459 public void testContextValueBooleanFalse() {
460 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.BOOLEAN_FALSE_RETRIEVER
));
462 List
<String
> output
= enableContextAndTrace();
463 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
, "{ 0 } }");
465 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
469 * Test a string context value.
472 public void testContextValueString() {
473 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
475 List
<String
> output
= enableContextAndTrace();
476 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
477 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" } }");
479 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
483 * Test a Object context value (should be converted to a String via .toString()).
486 public void testContextValueObject() {
487 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.OBJECT_RETRIEVER
));
489 List
<String
> output
= enableContextAndTrace();
490 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
491 "{ \"" + ContextInfoRetrieverStubs
.OBJECT_VALUE
.toString() + "\" } }");
493 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
496 // ------------------------------------------------------------------------
497 // Tests related to filtering
498 // ------------------------------------------------------------------------
501 * Test with a filter expression using a context, but not having the actual
504 * The JNI should still send the context so UST can use it for filtering,
505 * but it should not be present in the resulting trace.
508 public void testContextFilterExpressionNotEnabled() {
509 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
511 assertTrue(session
.enableEvent(EVENT_NAME
, null, false,
512 "$app." + RETRIEVER_NAME_1
+ ':' + CONTEXT_NAME
+ "==\"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ '\"'));
514 assertTrue(session
.start());
515 sendEventsToLoggers();
516 assertTrue(session
.stop());
518 List
<String
> output
= session
.view();
519 assertNotNull(output
);
520 assertFalse(output
.isEmpty());
522 testContextNotPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
);
524 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
528 * Test with a filter expression and an enabled context. The filter however
529 * should *exclude* the events, so no events should be present in the
533 public void testContextFilterExpressionEnabledNotMatching() {
534 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
536 assertTrue(session
.enableEvent(EVENT_NAME
, null, false,
537 "$app." + RETRIEVER_NAME_1
+ ':' + CONTEXT_NAME
+ "!=\"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ '\"'));
539 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
540 assertTrue(session
.start());
541 sendEventsToLoggers();
542 assertTrue(session
.stop());
544 List
<String
> output
= session
.view();
545 assertNotNull(output
);
546 assertTrue(output
.isEmpty());
548 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
552 * Test with a filter expression and an enabled context. The filter however
553 * should match the events, so events with the context info should be
554 * present in the resulting trace.
557 public void testContextFilterExpressionEnabledMatching() {
558 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
560 assertTrue(session
.enableEvent(EVENT_NAME
, null, false,
561 "$app." + RETRIEVER_NAME_1
+ ':' + CONTEXT_NAME
+ "==\"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ '\"'));
563 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
564 assertTrue(session
.start());
565 sendEventsToLoggers();
566 assertTrue(session
.stop());
568 List
<String
> output
= session
.view();
569 assertNotNull(output
);
570 assertFalse(output
.isEmpty());
572 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
573 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" } }");
575 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));