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.spi;
015
016import static org.junit.Assert.assertNotNull;
017import static org.junit.Assert.assertTrue;
018
019import java.net.MalformedURLException;
020import java.net.URL;
021import java.net.URLClassLoader;
022
023import org.junit.Ignore;
024import org.junit.Test;
025
026import ch.qos.logback.classic.util.TestHelper;
027import ch.qos.logback.core.util.SystemInfo;
028
029public class PackagingDataCalculatorTest {
030
031    public void verify(ThrowableProxy tp) {
032        for (StackTraceElementProxy step : tp.getStackTraceElementProxyArray()) {
033            if (step != null) {
034                assertNotNull(step.getClassPackagingData());
035            }
036        }
037    }
038
039    @Test
040    public void smoke() throws Exception {
041        Throwable t = new Throwable("x");
042        ThrowableProxy tp = new ThrowableProxy(t);
043        PackagingDataCalculator pdc = tp.getPackagingDataCalculator();
044        pdc.calculate(tp);
045        verify(tp);
046        tp.fullDump();
047    }
048
049    @Test
050    public void nested() throws Exception {
051        Throwable t = TestHelper.makeNestedException(3);
052        ThrowableProxy tp = new ThrowableProxy(t);
053        PackagingDataCalculator pdc = tp.getPackagingDataCalculator();
054        pdc.calculate(tp);
055        verify(tp);
056    }
057
058    public void doCalculateClassPackagingData(boolean withClassPackagingCalculation) {
059        try {
060            throw new Exception("testing");
061        } catch (Throwable e) {
062            ThrowableProxy tp = new ThrowableProxy(e);
063            if (withClassPackagingCalculation) {
064                PackagingDataCalculator pdc = tp.getPackagingDataCalculator();
065                pdc.calculate(tp);
066            }
067        }
068    }
069
070    double loop(int len, boolean withClassPackagingCalculation) {
071        long start = System.nanoTime();
072        for (int i = 0; i < len; i++) {
073            doCalculateClassPackagingData(withClassPackagingCalculation);
074        }
075        return (1.0 * System.nanoTime() - start) / len / 1000;
076    }
077
078    @Ignore
079    @Test
080    public void perfTest() {
081        int len = 1000;
082        loop(len, false);
083        loop(len, true);
084
085        double d0 = loop(len, false);
086        System.out.println("without packaging info " + d0 + " microseconds");
087
088        double d1 = loop(len, true);
089        System.out.println("with    packaging info " + d1 + " microseconds");
090
091        int slackFactor = 8;
092        if (!SystemInfo.getJavaVendor().contains("Sun")) {
093            // be more lenient with other JDKs
094            slackFactor = 15;
095        }
096        assertTrue("computing class packaging data (" + d1 + ") should have been less than " + slackFactor
097                        + " times the time it takes to process an exception " + (d0 * slackFactor), d0 * slackFactor > d1);
098
099    }
100
101    private ClassLoader makeBogusClassLoader() throws MalformedURLException {
102        ClassLoader currentClassLoader = this.getClass().getClassLoader();
103        return new BogusClassLoader(new URL[] {}, currentClassLoader);
104    }
105
106    @Test
107    // Test http://jira.qos.ch/browse/LBCLASSIC-125
108    public void noClassDefFoundError_LBCLASSIC_125Test() throws MalformedURLException {
109        ClassLoader cl = (URLClassLoader) makeBogusClassLoader();
110        Thread.currentThread().setContextClassLoader(cl);
111        Throwable t = new Throwable("x");
112        ThrowableProxy tp = new ThrowableProxy(t);
113        StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray();
114        StackTraceElement bogusSTE = new StackTraceElement("com.Bogus", "myMethod", "myFile", 12);
115        stepArray[0] = new StackTraceElementProxy(bogusSTE);
116        PackagingDataCalculator pdc = tp.getPackagingDataCalculator();
117        // NoClassDefFoundError should be caught
118        pdc.calculate(tp);
119
120    }
121
122}