View Javadoc
1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2022, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.blackbox.boolex;
15  
16  import java.io.IOException;
17  import java.util.List;
18  
19  import ch.qos.logback.classic.boolex.JaninoEventEvaluator;
20  import ch.qos.logback.classic.util.LogbackMDCAdapter;
21  import org.junit.jupiter.api.BeforeEach;
22  import org.junit.jupiter.api.Disabled;
23  import org.junit.jupiter.api.Test;
24  import org.slf4j.MDC;
25  import org.slf4j.Marker;
26  import org.slf4j.MarkerFactory;
27  
28  import ch.qos.logback.classic.Level;
29  import ch.qos.logback.classic.Logger;
30  import ch.qos.logback.classic.LoggerContext;
31  import ch.qos.logback.classic.spi.ILoggingEvent;
32  import ch.qos.logback.classic.spi.LoggingEvent;
33  import ch.qos.logback.core.boolex.EvaluationException;
34  import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase;
35  import ch.qos.logback.core.boolex.Matcher;
36  import ch.qos.logback.core.filter.EvaluatorFilter;
37  import ch.qos.logback.core.spi.FilterReply;
38  import ch.qos.logback.core.testUtil.RandomUtil;
39  import ch.qos.logback.core.util.StatusPrinter;
40  
41  import static org.junit.jupiter.api.Assertions.assertEquals;
42  import static org.junit.jupiter.api.Assertions.assertFalse;
43  import static org.junit.jupiter.api.Assertions.assertTrue;
44  import static org.junit.jupiter.api.Assertions.fail;
45  
46  public class BlackboxJaninoEventEvaluatorTest {
47  
48      LoggerContext loggerContext = new LoggerContext();
49      LogbackMDCAdapter logbackMDCAdapter = new LogbackMDCAdapter();
50      Logger logger = loggerContext.getLogger(BlackboxJaninoEventEvaluatorTest.class);
51  
52      Matcher matcherX = new Matcher();
53  
54      JaninoEventEvaluator jee = new JaninoEventEvaluator();
55  
56      int diff = RandomUtil.getPositiveInt();
57  
58      @BeforeEach
59      public void setup()  {
60          loggerContext.setMDCAdapter(logbackMDCAdapter);
61          jee.setContext(loggerContext);
62  
63          matcherX.setName("x");
64          matcherX.setRegex("^Some\\s.*");
65          matcherX.start();
66  
67      }
68  
69      LoggingEvent makeLoggingEvent(Exception ex) {
70          return new LoggingEvent(ch.qos.logback.core.pattern.FormattingConverter.class.getName(), logger, Level.INFO,
71                  "Some message", ex, null);
72      }
73  
74      @Test
75      public void testBasic() throws Exception {
76          jee.setExpression("message.equals(\"Some message\")");
77          jee.start();
78  
79          StatusPrinter.print(loggerContext);
80          ILoggingEvent event = makeLoggingEvent(null);
81          assertTrue(jee.evaluate(event));
82      }
83  
84      @Test
85      public void testLevel() throws Exception {
86          jee.setExpression("level > DEBUG");
87          jee.start();
88  
89          ILoggingEvent event = makeLoggingEvent(null);
90          assertTrue(jee.evaluate(event));
91      }
92  
93      @Test
94      public void testtimeStamp() throws Exception {
95          jee.setExpression("timeStamp > 10");
96          jee.start();
97  
98          ILoggingEvent event = makeLoggingEvent(null);
99          assertTrue(jee.evaluate(event));
100     }
101 
102     @Test
103     public void testWithMatcher() throws Exception {
104         jee.setExpression("x.matches(message)");
105         jee.addMatcher(matcherX);
106         jee.start();
107 
108         ILoggingEvent event = makeLoggingEvent(null);
109         assertTrue(jee.evaluate(event));
110     }
111 
112     @Test
113     public void mdcAsString() throws Exception {
114         String k = "key" + diff;
115 
116         logbackMDCAdapter.put("key" + diff, "value" + diff);
117         jee.setExpression("((String) mdc.get(\"" + k + "\")).contains(\"alue\")");
118         jee.start();
119         StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext);
120 
121         LoggingEvent event = makeLoggingEvent(null);
122         assertTrue(jee.evaluate(event));
123         logbackMDCAdapter.remove(k);
124     }
125 
126     @Test
127     public void markerList() throws Exception {
128 
129         jee.setExpression("markerList.contains(\"BLUE\")");
130         jee.start();
131 
132         LoggingEvent event = makeLoggingEvent(null);
133         event.addMarker(MarkerFactory.getMarker("BLUE"));
134         StatusPrinter.print(loggerContext);
135         assertTrue(jee.evaluate(event));
136     }
137 
138     @Test
139     public void marker() throws Exception {
140 
141         jee.setExpression("marker.contains(\"BLUE\")");
142         jee.start();
143 
144         LoggingEvent event = makeLoggingEvent(null);
145         event.addMarker(MarkerFactory.getMarker("BLUE"));
146         StatusPrinter.print(loggerContext);
147         assertTrue(jee.evaluate(event));
148     }
149 
150     // LBCORE_118
151     @Test
152     public void withNullMarker_LOGBACK_63() throws Exception {
153         jee.setExpression("marker.contains(\"BLUE\")");
154         jee.start();
155 
156         ILoggingEvent event = makeLoggingEvent(null);
157         try {
158             jee.evaluate(event);
159             fail("We should not reach this point");
160         } catch (EvaluationException ee) {
161             // received an exception as expected
162         }
163     }
164 
165     @Test
166     public void evaluatorFilterWithNullMarker_LBCORE_118() throws Exception {
167         EvaluatorFilter<ILoggingEvent> ef = new EvaluatorFilter<ILoggingEvent>();
168         ef.setContext(loggerContext);
169 
170         ef.setOnMatch(FilterReply.ACCEPT);
171         ef.setOnMismatch(FilterReply.DENY);
172 
173         jee.setExpression("marker.contains(\"BLUE\")");
174         jee.start();
175 
176         ef.setEvaluator(jee);
177         ef.start();
178         ILoggingEvent event = makeLoggingEvent(null);
179         assertEquals(FilterReply.NEUTRAL, ef.decide(event));
180 
181     }
182 
183     @Test
184     public void testComplex() throws Exception {
185         jee.setExpression("level >= INFO && x.matches(message)");
186         jee.addMatcher(matcherX);
187         jee.start();
188 
189         LoggingEvent event = makeLoggingEvent(null);
190         event.addMarker(MarkerFactory.getMarker("BLUE"));
191         assertTrue(jee.evaluate(event));
192     }
193 
194     /**
195      * check that evaluator with bogus exp does not start
196      * 
197      * @throws Exception
198      */
199     @Test
200     public void testBogusExp1() {
201         jee.setExpression("mzzzz.get(\"key\").equals(null)");
202         jee.setName("bogus");
203         jee.start();
204 
205         assertFalse(jee.isStarted());
206     }
207 
208     // check that eval stops after errors
209     @Test
210     public void testBogusExp2() {
211         jee.setExpression("mdc.get(\"keyXN89\").equals(null)");
212         jee.setName("bogus");
213         jee.start();
214 
215         assertTrue(jee.isStarted());
216 
217         ILoggingEvent event = makeLoggingEvent(null);
218 
219         for (int i = 0; i < JaninoEventEvaluatorBase.ERROR_THRESHOLD; i++) {
220             try {
221                 jee.evaluate(event);
222                 fail("should throw an exception");
223             } catch (EvaluationException e) {
224             }
225         }
226         // after a few attempts the evaluator should processPriorToRemoval
227         assertFalse(jee.isStarted());
228 
229     }
230 
231     static final long LEN = 10 * 1000;
232 
233     // with 6 parameters 400 nanos
234     // with 7 parameters 460 nanos (all levels + selected fields from
235     // LoggingEvent)
236     // with 10 parameters 510 nanos (all levels + fields)
237     void loop(JaninoEventEvaluator jee, String msg) throws Exception {
238         ILoggingEvent event = makeLoggingEvent(null);
239         // final long start = System.nanoTime();
240         for (int i = 0; i < LEN; i++) {
241             jee.evaluate(event);
242         }
243         // final long end = System.nanoTime();
244         // System.out.println(msg + (end - start) / LEN + " nanos");
245     }
246 
247     @Test
248     public void testLoop1() throws Exception {
249         jee.setExpression("timeStamp > 10");
250         jee.start();
251 
252         loop(jee, "timestamp > 10]: ");
253     }
254 
255     @Test
256     public void testLoop2() throws Exception {
257         jee.setExpression("x.matches(message)");
258         jee.addMatcher(matcherX);
259         jee.start();
260 
261         loop(jee, "x.matches(message): ");
262     }
263 
264     @Test
265     public void throwable_LBCLASSIC_155_I() throws EvaluationException {
266         jee.setExpression("throwable instanceof java.io.IOException");
267         jee.start();
268 
269         LoggingEvent event = makeLoggingEvent(new IOException(""));
270         assertTrue(jee.evaluate(event));
271     }
272 
273     @Test
274     public void throwable_LBCLASSIC_155_II() throws EvaluationException {
275         jee.setExpression("throwableProxy.getClassName().contains(\"IO\")");
276         jee.start();
277 
278         LoggingEvent event = makeLoggingEvent(new IOException(""));
279         assertTrue(jee.evaluate(event));
280     }
281 
282     @Test
283     public void nullMDC() throws EvaluationException {
284         MDC.clear();
285         jee.setExpression("mdc.isEmpty()");
286         jee.start();
287 
288         LoggingEvent event = makeLoggingEvent(null);
289         assertTrue(jee.evaluate(event));
290     }
291 }