001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.classic.boolex;
015
016import static org.junit.Assert.assertEquals;
017import static org.junit.Assert.assertFalse;
018import static org.junit.Assert.assertTrue;
019import static org.junit.Assert.fail;
020
021import java.io.IOException;
022
023import org.junit.Test;
024import org.slf4j.MDC;
025import org.slf4j.MarkerFactory;
026
027import ch.qos.logback.classic.Level;
028import ch.qos.logback.classic.Logger;
029import ch.qos.logback.classic.LoggerContext;
030import ch.qos.logback.classic.pattern.ConverterTest;
031import ch.qos.logback.classic.spi.ILoggingEvent;
032import ch.qos.logback.classic.spi.LoggingEvent;
033import ch.qos.logback.core.boolex.EvaluationException;
034import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase;
035import ch.qos.logback.core.boolex.Matcher;
036import ch.qos.logback.core.filter.EvaluatorFilter;
037import ch.qos.logback.core.spi.FilterReply;
038import ch.qos.logback.core.testUtil.RandomUtil;
039import ch.qos.logback.core.util.StatusPrinter;
040
041public class JaninoEventEvaluatorTest {
042
043    LoggerContext loggerContext = new LoggerContext();
044    Logger logger = loggerContext.getLogger(ConverterTest.class);
045
046    Matcher matcherX = new Matcher();
047
048    JaninoEventEvaluator jee = new JaninoEventEvaluator();
049
050    int diff = RandomUtil.getPositiveInt();
051
052    public JaninoEventEvaluatorTest() {
053        jee.setContext(loggerContext);
054
055        matcherX.setName("x");
056        matcherX.setRegex("^Some\\s.*");
057        matcherX.start();
058
059    }
060
061    LoggingEvent makeLoggingEvent(Exception ex) {
062        return new LoggingEvent(ch.qos.logback.core.pattern.FormattingConverter.class.getName(), logger, Level.INFO, "Some message", ex, null);
063    }
064
065    @Test
066    public void testBasic() throws Exception {
067        jee.setExpression("message.equals(\"Some message\")");
068        jee.start();
069
070        StatusPrinter.print(loggerContext);
071        ILoggingEvent event = makeLoggingEvent(null);
072        assertTrue(jee.evaluate(event));
073    }
074
075    @Test
076    public void testLevel() throws Exception {
077        jee.setExpression("level > DEBUG");
078        jee.start();
079
080        ILoggingEvent event = makeLoggingEvent(null);
081        assertTrue(jee.evaluate(event));
082    }
083
084    @Test
085    public void testtimeStamp() throws Exception {
086        jee.setExpression("timeStamp > 10");
087        jee.start();
088
089        ILoggingEvent event = makeLoggingEvent(null);
090        assertTrue(jee.evaluate(event));
091    }
092
093    @Test
094    public void testWithMatcher() throws Exception {
095        jee.setExpression("x.matches(message)");
096        jee.addMatcher(matcherX);
097        jee.start();
098
099        ILoggingEvent event = makeLoggingEvent(null);
100        assertTrue(jee.evaluate(event));
101    }
102
103    @Test
104    public void mdcAsString() throws Exception {
105        String k = "key" + diff;
106
107        MDC.put("key" + diff, "value" + diff);
108        jee.setExpression("((String) mdc.get(\"" + k + "\")).contains(\"alue\")");
109        jee.start();
110        StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext);
111
112        LoggingEvent event = makeLoggingEvent(null);
113        assertTrue(jee.evaluate(event));
114        MDC.remove(k);
115    }
116
117    @Test
118    public void marker() throws Exception {
119        jee.setExpression("marker.contains(\"BLUE\")");
120        jee.start();
121
122        LoggingEvent event = makeLoggingEvent(null);
123        event.setMarker(MarkerFactory.getMarker("BLUE"));
124        assertTrue(jee.evaluate(event));
125    }
126
127    @Test
128    public void withNullMarker_LBCORE_118() throws Exception {
129        jee.setExpression("marker.contains(\"BLUE\")");
130        jee.start();
131
132        ILoggingEvent event = makeLoggingEvent(null);
133        try {
134            jee.evaluate(event);
135            fail("We should not reach this point");
136        } catch (EvaluationException ee) {
137            // received an exception as expected
138        }
139    }
140
141    @Test
142    public void evaluatorFilterWithNullMarker_LBCORE_118() throws Exception {
143        EvaluatorFilter<ILoggingEvent> ef = new EvaluatorFilter<ILoggingEvent>();
144        ef.setContext(loggerContext);
145
146        ef.setOnMatch(FilterReply.ACCEPT);
147        ef.setOnMismatch(FilterReply.DENY);
148
149        jee.setExpression("marker.contains(\"BLUE\")");
150        jee.start();
151
152        ef.setEvaluator(jee);
153        ef.start();
154        ILoggingEvent event = makeLoggingEvent(null);
155        assertEquals(FilterReply.NEUTRAL, ef.decide(event));
156
157    }
158
159    @Test
160    public void testComplex() throws Exception {
161        jee.setExpression("level >= INFO && x.matches(message) && marker.contains(\"BLUE\")");
162        jee.addMatcher(matcherX);
163        jee.start();
164
165        LoggingEvent event = makeLoggingEvent(null);
166        event.setMarker(MarkerFactory.getMarker("BLUE"));
167        assertTrue(jee.evaluate(event));
168    }
169
170    /**
171     * check that evaluator with bogus exp does not start
172     * 
173     * @throws Exception
174     */
175    @Test
176    public void testBogusExp1() {
177        jee.setExpression("mzzzz.get(\"key\").equals(null)");
178        jee.setName("bogus");
179        jee.start();
180
181        assertFalse(jee.isStarted());
182    }
183
184    // check that eval stops after errors
185    @Test
186    public void testBogusExp2() {
187        jee.setExpression("mdc.get(\"keyXN89\").equals(null)");
188        jee.setName("bogus");
189        jee.start();
190
191        assertTrue(jee.isStarted());
192
193        ILoggingEvent event = makeLoggingEvent(null);
194
195        for (int i = 0; i < JaninoEventEvaluatorBase.ERROR_THRESHOLD; i++) {
196            try {
197                jee.evaluate(event);
198                fail("should throw an exception");
199            } catch (EvaluationException e) {
200            }
201        }
202        // after a few attempts the evaluator should processPriorToRemoval
203        assertFalse(jee.isStarted());
204
205    }
206
207    static final long LEN = 10 * 1000;
208
209    // with 6 parameters 400 nanos
210    // with 7 parameters 460 nanos (all levels + selected fields from
211    // LoggingEvent)
212    // with 10 parameters 510 nanos (all levels + fields)
213    void loop(JaninoEventEvaluator jee, String msg) throws Exception {
214        ILoggingEvent event = makeLoggingEvent(null);
215        // final long start = System.nanoTime();
216        for (int i = 0; i < LEN; i++) {
217            jee.evaluate(event);
218        }
219        // final long end = System.nanoTime();
220        // System.out.println(msg + (end - start) / LEN + " nanos");
221    }
222
223    @Test
224    public void testLoop1() throws Exception {
225        jee.setExpression("timeStamp > 10");
226        jee.start();
227
228        loop(jee, "timestamp > 10]: ");
229    }
230
231    @Test
232    public void testLoop2() throws Exception {
233        jee.setExpression("x.matches(message)");
234        jee.addMatcher(matcherX);
235        jee.start();
236
237        loop(jee, "x.matches(message): ");
238    }
239
240    @Test
241    public void throwable_LBCLASSIC_155_I() throws EvaluationException {
242        jee.setExpression("throwable instanceof java.io.IOException");
243        jee.start();
244
245        LoggingEvent event = makeLoggingEvent(new IOException(""));
246        assertTrue(jee.evaluate(event));
247    }
248
249    @Test
250    public void throwable_LBCLASSIC_155_II() throws EvaluationException {
251        jee.setExpression("throwableProxy.getClassName().contains(\"IO\")");
252        jee.start();
253
254        LoggingEvent event = makeLoggingEvent(new IOException(""));
255        assertTrue(jee.evaluate(event));
256    }
257
258    @Test
259    public void nullMDC() throws EvaluationException {
260        MDC.clear();
261        jee.setExpression("mdc.isEmpty()");
262        jee.start();
263
264        LoggingEvent event = makeLoggingEvent(null);
265        assertTrue(jee.evaluate(event));
266    }
267}