From 46c185e3ce8f545adc002a96dc246fc9f2242214 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 5 Apr 2013 09:40:13 +0200 Subject: [PATCH] [#2373] ExecuteListener may have an unbalanced life-cycle - Added LifecycleWatcherListener that collects start() and end() event counts for display in integration tests --- .../jooq/test/_/LifecycleWatcherListener.java | 116 ++++++++++++++++++ .../src/org/jooq/test/jOOQAbstractTest.java | 20 +++ 2 files changed, 136 insertions(+) create mode 100644 jOOQ-test/src/org/jooq/test/_/LifecycleWatcherListener.java diff --git a/jOOQ-test/src/org/jooq/test/_/LifecycleWatcherListener.java b/jOOQ-test/src/org/jooq/test/_/LifecycleWatcherListener.java new file mode 100644 index 0000000000..e033ea7009 --- /dev/null +++ b/jOOQ-test/src/org/jooq/test/_/LifecycleWatcherListener.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.test._; + +import java.lang.reflect.Method; +import java.util.Comparator; +import java.util.Map; +import java.util.TreeMap; + +import org.jooq.ExecuteContext; +import org.jooq.impl.DefaultExecuteListener; + +import org.junit.Test; + +/** + * An ExecuteListener that collects data about the lifecycle of + * execute listeners in all integration tests. + * + * @author Lukas Eder + */ +public class LifecycleWatcherListener extends DefaultExecuteListener { + + /** + * Generated UID + */ + private static final long serialVersionUID = -2283264126211556442L; + + private static Comparator METHOD_COMPARATOR = new Comparator() { + + @Override + public int compare(Method o1, Method o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + public static final Map START_COUNT = new TreeMap(METHOD_COMPARATOR); + public static final Map END_COUNT = new TreeMap(METHOD_COMPARATOR); + private static final Object INCREMENT_MONITOR = new Object(); + + @Override + public void start(ExecuteContext ctx) { + super.start(ctx); + increment(START_COUNT); + } + + @Override + public void end(ExecuteContext ctx) { + super.end(ctx); + increment(END_COUNT); + } + + private void increment(Map map) { + synchronized (INCREMENT_MONITOR) { + Method m = testMethod(); + + if (m != null) { + Integer count = map.get(m); + + if (count == null) { + count = 0; + } + + count = count + 1; + map.put(m, count); + } + } + } + + private static Method testMethod() { + for (StackTraceElement e : Thread.currentThread().getStackTrace()) { + try { + for (Method m : Class.forName(e.getClassName()).getMethods()) { + if (m.getAnnotation(Test.class) != null) { + return m; + } + } + } + catch (Exception ignore) {} + } + + return null; + } +} diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index 634b8fec3a..aca1352875 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -42,6 +42,7 @@ import static org.jooq.tools.reflect.Reflect.on; import java.io.File; import java.io.InputStream; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Connection; @@ -88,6 +89,7 @@ import org.jooq.debug.Debugger; import org.jooq.debug.console.Console; import org.jooq.debug.impl.DebuggerFactory; import org.jooq.impl.Executor; +import org.jooq.test._.LifecycleWatcherListener; import org.jooq.test._.PrettyPrinter; import org.jooq.test._.TestStatisticsListener; import org.jooq.test._.converters.Boolean_10; @@ -452,6 +454,23 @@ public abstract class jOOQAbstractTest< log.info("---------------"); log.info("Total", total); + + log.info(""); + log.info("EXECUTE LIFECYCLE STATS"); + log.info("-----------------------"); + + for (Method m : LifecycleWatcherListener.START_COUNT.keySet()) { + Integer starts = LifecycleWatcherListener.START_COUNT.get(m); + Integer ends = LifecycleWatcherListener.END_COUNT.get(m); + + if (!StringUtils.equals(starts, ends)) { + log.info( + "Unbalanced", String.format("(start, end): (%1$3s, %2$3s) at %3$s", + starts, + ends == null ? 0 : ends, + m.toString().replace("public void ", "").replaceAll("( throws.*)?", ""))); + } + } } @SuppressWarnings("unused") @@ -851,6 +870,7 @@ public abstract class jOOQAbstractTest< Executor create = create(settings); create.configuration().getExecuteListeners().add(new TestStatisticsListener()); create.configuration().getExecuteListeners().add(new PrettyPrinter()); + create.configuration().getExecuteListeners().add(new LifecycleWatcherListener()); return create; }