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 void sendEventsToLoggers();
67 public void testSetup() {
69 cim
= ContextInfoManager
.getInstance();
70 } catch (SecurityException
| IOException e
) {
71 /* The native library is not available! */
74 session
= ILttngSession
.createSession(null, getDomain());
81 public void testTeardown() {
87 /* In case some tests fail or forget to unregister their retrievers */
88 cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
);
89 cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_2
);
92 // ------------------------------------------------------------------------
93 // Context enabled/disabled tests
94 // ------------------------------------------------------------------------
97 * Utility method to check that a context is present in all events of a
100 private static void testContextPresentInTrace(List
<String
> traceOutput
, String retrieverName
, String contextName
, String contextValue
) {
101 String traceRetrieverName
= convertToNameInTrace(retrieverName
);
102 String traceContextName
= convertToNameInTrace(contextName
);
104 String fullString
= "_app_" + traceRetrieverName
+ "_" + traceContextName
+ " = " + contextValue
;
105 traceOutput
.forEach(line
-> assertTrue(line
.contains(fullString
)));
109 * Utility method to check that a context is *absent* from all events of a
112 private static void testContextNotPresentInTrace(List
<String
> traceOutput
, String retrieverName
, String contextName
) {
113 String traceRetrieverName
= convertToNameInTrace(retrieverName
);
114 String traceContextName
= convertToNameInTrace(contextName
);
116 String fullString
= "_app_" + traceRetrieverName
+ "_" + traceContextName
;
117 traceOutput
.forEach(line
-> assertFalse(line
.contains(fullString
)));
121 * LTTng accepts periods in context names, but ends up printing them as
122 * underscores in the trace, so the metadata grammar remains valid.
124 private static String
convertToNameInTrace(String name
) {
125 return name
.replace('.', '_');
129 * Test that if no retrievers are declared, no context info is passed at
133 public void testNoContexts() {
134 assertTrue(session
.enableAllEvents());
135 assertTrue(session
.start());
136 sendEventsToLoggers();
137 assertTrue(session
.stop());
139 List
<String
> output
= session
.view();
140 assertNotNull(output
);
141 assertFalse(output
.isEmpty());
143 /* Test that there is no "_app" contexts in the output */
144 output
.forEach(line
-> assertFalse(line
.contains("_app")));
148 * Test that if a retriever is registered and provides a context, but this
149 * context is not enabled in the tracing session, that it is not present in
153 public void testContextAvailableButNotEnabled() {
154 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
156 assertTrue(session
.enableAllEvents());
157 assertTrue(session
.start());
158 sendEventsToLoggers();
159 assertTrue(session
.stop());
161 List
<String
> output
= session
.view();
162 assertNotNull(output
);
163 assertFalse(output
.isEmpty());
165 /* Test that there is no "_app" contexts in the output */
166 output
.forEach(line
-> assertFalse(line
.contains("_app")));
168 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
172 * Test that if a context is enabled, but no retriever provides it, that the
173 * retriever/context names are still mentioned in the event but no value is
177 public void testContextNotAvailableButEnabled() {
178 assertTrue(session
.enableAllEvents());
179 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
181 assertTrue(session
.start());
182 sendEventsToLoggers();
183 assertTrue(session
.stop());
185 List
<String
> output
= session
.view();
186 assertNotNull(output
);
187 assertFalse(output
.isEmpty());
189 /* Test that context name is there but value is not */
190 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
, "{ { } } }");
194 * Test that if a context is enabled and provided by a retriever that it is
195 * correctly present in the tracing session.
198 public void testContextAvailableAndEnabled() {
199 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
201 assertTrue(session
.enableAllEvents());
202 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
204 assertTrue(session
.start());
205 sendEventsToLoggers();
206 assertTrue(session
.stop());
208 List
<String
> output
= session
.view();
209 assertNotNull(output
);
210 assertFalse(output
.isEmpty());
212 /* Test that context name + value are present */
213 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
214 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" }");
216 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
220 * Test that one context is available by a retriever, but another is is
221 * enabled in the session. Only the latter should be mentioned in events,
225 public void testContextsOneAvailableOtherEnabled() {
226 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
228 assertTrue(session
.enableAllEvents());
229 assertTrue(session
.enableAppContext(RETRIEVER_NAME_2
, CONTEXT_NAME
));
231 assertTrue(session
.start());
232 sendEventsToLoggers();
233 assertTrue(session
.stop());
235 List
<String
> output
= session
.view();
236 assertNotNull(output
);
237 assertFalse(output
.isEmpty());
239 /* Test that only retriever-name-2 is present, with no value */
240 testContextNotPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
);
241 testContextPresentInTrace(output
, RETRIEVER_NAME_2
, CONTEXT_NAME
, "{ { } } }");
243 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
247 * Test with two contexts provided in the application, but only one of them
248 * is enabled in the session. Only that one should be present in the trace,
252 public void testContextsTwoAvailableOneEnabled() {
253 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
254 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_2
, ContextInfoRetrieverStubs
.INTEGER_RETRIEVER
));
256 assertTrue(session
.enableAllEvents());
257 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
259 assertTrue(session
.start());
260 sendEventsToLoggers();
261 assertTrue(session
.stop());
263 List
<String
> output
= session
.view();
264 assertNotNull(output
);
265 assertFalse(output
.isEmpty());
267 /* Test that only retriever-name-1 is present, name + value */
268 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
269 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" }");
270 testContextNotPresentInTrace(output
, RETRIEVER_NAME_2
, CONTEXT_NAME
);
272 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
273 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_2
));
277 * Test with two contexts enabled in the session but only one of them is
278 * provided by the application. Both should be mentioned in the trace, but
279 * only the provided one will have a value.
282 public void testContextsOneAvailableTwoEnabled() {
283 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
285 assertTrue(session
.enableAllEvents());
286 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
287 assertTrue(session
.enableAppContext(RETRIEVER_NAME_2
, CONTEXT_NAME
));
289 assertTrue(session
.start());
290 sendEventsToLoggers();
291 assertTrue(session
.stop());
293 List
<String
> output
= session
.view();
294 assertNotNull(output
);
295 assertFalse(output
.isEmpty());
297 /* Test that both contexts are present, but only retriever-1's has a value */
298 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
299 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" }");
300 testContextPresentInTrace(output
, RETRIEVER_NAME_2
, CONTEXT_NAME
, "{ { } } }");
302 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
305 // ------------------------------------------------------------------------
306 // Context types tests
307 // ------------------------------------------------------------------------
310 * Utility method to enable all events, add the one context we are looking
311 * for, take a trace, and return the trace output.
313 private List
<String
> enableContextAndTrace() {
314 assertTrue(session
.enableAllEvents());
315 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
316 assertTrue(session
.start());
317 sendEventsToLoggers();
318 assertTrue(session
.stop());
320 List
<String
> output
= session
.view();
321 assertNotNull(output
);
322 assertFalse(output
.isEmpty());
328 * Test a "null" context value.
331 public void testContextValueNull() {
332 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.NULL_RETRIEVER
));
334 List
<String
> output
= enableContextAndTrace();
335 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
, "{ { } } }");
337 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
341 * Test an integer (int32) context value.
344 public void testContextValueInteger() {
345 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.INTEGER_RETRIEVER
));
347 List
<String
> output
= enableContextAndTrace();
348 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
349 "{ " + ContextInfoRetrieverStubs
.INTEGER_VALUE
+ " } }");
351 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
355 * Test a long (int64) context value.
358 public void testContextValueLong() {
359 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.LONG_RETRIEVER
));
361 List
<String
> output
= enableContextAndTrace();
362 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
363 "{ " + ContextInfoRetrieverStubs
.LONG_VALUE
+ " } }");
365 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
369 * Test a double context value.
372 public void testContextValueDouble() {
373 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.DOUBLE_RETRIEVER
));
375 List
<String
> output
= enableContextAndTrace();
376 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
377 "{ " + ContextInfoRetrieverStubs
.DOUBLE_VALUE
+ " } }");
379 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
383 * Test a character context value (should get converted to a string).
386 public void testContextValueCharacter() {
387 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.CHARACTER_RETRIEVER
));
389 List
<String
> output
= enableContextAndTrace();
390 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
391 "{ \"" + ContextInfoRetrieverStubs
.CHARACTER_VALUE
+ "\" } }");
393 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
397 * Test a float context value.
400 public void testContextValueFloat() {
401 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.FLOAT_RETRIEVER
));
403 List
<String
> output
= enableContextAndTrace();
404 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
405 "{ " + ContextInfoRetrieverStubs
.FLOAT_VALUE
+ " } }");
407 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
411 * Test a byte (int8) context value.
414 public void testContextValueByte() {
415 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.BYTE_RETRIEVER
));
417 List
<String
> output
= enableContextAndTrace();
418 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
419 "{ " + ContextInfoRetrieverStubs
.BYTE_VALUE
+ " } }");
421 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
425 * Test a short (int16) context value.
428 public void testContextValueShort() {
429 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.SHORT_RETRIEVER
));
431 List
<String
> output
= enableContextAndTrace();
432 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
433 "{ " + ContextInfoRetrieverStubs
.SHORT_VALUE
+ " } }");
435 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
439 * Test a "true" boolean context value (gets converted to a int8 of value 1).
442 public void testContextValueBooleanTrue() {
443 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.BOOLEAN_TRUE_RETRIEVER
));
445 List
<String
> output
= enableContextAndTrace();
446 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
, "{ 1 } }");
448 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
452 * Test a "false" boolean context value (gets converted to a int8 of value 0).
455 public void testContextValueBooleanFalse() {
456 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.BOOLEAN_FALSE_RETRIEVER
));
458 List
<String
> output
= enableContextAndTrace();
459 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
, "{ 0 } }");
461 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
465 * Test a string context value.
468 public void testContextValueString() {
469 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
471 List
<String
> output
= enableContextAndTrace();
472 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
473 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" } }");
475 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
479 * Test a Object context value (should be converted to a String via .toString()).
482 public void testContextValueObject() {
483 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.OBJECT_RETRIEVER
));
485 List
<String
> output
= enableContextAndTrace();
486 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
487 "{ \"" + ContextInfoRetrieverStubs
.OBJECT_VALUE
.toString() + "\" } }");
489 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
492 // ------------------------------------------------------------------------
493 // Tests related to filtering
494 // ------------------------------------------------------------------------
497 * Test with a filter expression using a context, but not having the actual
500 * The JNI should still send the context so UST can use it for filtering,
501 * but it should not be present in the resulting trace.
504 public void testContextFilterExpressionNotEnabled() {
505 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
507 assertTrue(session
.enableEvent(EVENT_NAME
, null, false,
508 "$app." + RETRIEVER_NAME_1
+ ':' + CONTEXT_NAME
+ "==\"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ '\"'));
510 assertTrue(session
.start());
511 sendEventsToLoggers();
512 assertTrue(session
.stop());
514 List
<String
> output
= session
.view();
515 assertNotNull(output
);
516 assertFalse(output
.isEmpty());
518 testContextNotPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
);
520 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
524 * Test with a filter expression and an enabled context. The filter however
525 * should *exclude* the events, so no events should be present in the
529 public void testContextFilterExpressionEnabledNotMatching() {
530 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
532 assertTrue(session
.enableEvent(EVENT_NAME
, null, false,
533 "$app." + RETRIEVER_NAME_1
+ ':' + CONTEXT_NAME
+ "!=\"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ '\"'));
535 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
536 assertTrue(session
.start());
537 sendEventsToLoggers();
538 assertTrue(session
.stop());
540 List
<String
> output
= session
.view();
541 assertNotNull(output
);
542 assertTrue(output
.isEmpty());
544 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));
548 * Test with a filter expression and an enabled context. The filter however
549 * should match the events, so events with the context info should be
550 * present in the resulting trace.
553 public void testContextFilterExpressionEnabledMatching() {
554 assertTrue(cim
.registerContextInfoRetriever(RETRIEVER_NAME_1
, ContextInfoRetrieverStubs
.STRING_RETRIEVER
));
556 assertTrue(session
.enableEvent(EVENT_NAME
, null, false,
557 "$app." + RETRIEVER_NAME_1
+ ':' + CONTEXT_NAME
+ "==\"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ '\"'));
559 assertTrue(session
.enableAppContext(RETRIEVER_NAME_1
, CONTEXT_NAME
));
560 assertTrue(session
.start());
561 sendEventsToLoggers();
562 assertTrue(session
.stop());
564 List
<String
> output
= session
.view();
565 assertNotNull(output
);
566 assertFalse(output
.isEmpty());
568 testContextPresentInTrace(output
, RETRIEVER_NAME_1
, CONTEXT_NAME
,
569 "{ \"" + ContextInfoRetrieverStubs
.STRING_VALUE
+ "\" } }");
571 assertTrue(cim
.unregisterContextInfoRetriever(RETRIEVER_NAME_1
));