/* * Copyright (C) 2011-2014 Chris Vest (mr.chrisvest@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package stormpot; import org.junit.internal.AssumptionViolatedException; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; import java.lang.management.*; import java.util.List; /** * A TestRule that ensures that any failing tests have their stack-trace * printed to stderr. * * This is useful for when the tests are running on a build-server, and you'd * like the details of any failure to be printed to the build-log. A nice thing * if the build system does not make the build artifacts with the test failures * available. * * @author cvh */ public class FailurePrinterTestRule implements TestRule { @Override public Statement apply(final Statement base, final Description description) { return new Statement() { @Override public void evaluate() throws Throwable { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean(); List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans(); OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); if (threadMXBean.isCurrentThreadCpuTimeSupported()) { threadMXBean.setThreadCpuTimeEnabled(true); } long startCpuTimeNs = getCpuTimeNs(threadMXBean); long startUserTimeNs = getUserTimeNs(threadMXBean); int startThreadCount = threadMXBean.getThreadCount(); long startCompilationTimeMs = getCompilationTimeMs(compilationMXBean); long startCollectionTimeMs = collectionTimeMs(garbageCollectorMXBeans); double loadAverage = operatingSystemMXBean.getSystemLoadAverage(); int cores = operatingSystemMXBean.getAvailableProcessors(); try { base.evaluate(); } catch (AssumptionViolatedException ignore) { // This is fine. } catch (Throwable th) { long cpuTimeNs = getCpuTimeNs(threadMXBean) - startCpuTimeNs; long userTimeNs = getUserTimeNs(threadMXBean) - startUserTimeNs; int threadCount = threadMXBean.getThreadCount(); long compilationTimeMs = getCompilationTimeMs(compilationMXBean) - startCompilationTimeMs; long collectionTimeMs = collectionTimeMs(garbageCollectorMXBeans) - startCollectionTimeMs; double newLoadAverage = operatingSystemMXBean.getSystemLoadAverage(); System.err.printf("Failed test:%n" + "\tcpu-cores = %s%n" + "\tcpuTimeNs = %s%n" + "\tuserTimeNs = %s%n" + "\tcompilationTimeMs = %s%n" + "\tcollectionTimeMs = %s%n" + "\tload average = %s -> %s%n" + "\tthreads = %s -> %s%n", cores, cpuTimeNs, userTimeNs, compilationTimeMs, collectionTimeMs, loadAverage, newLoadAverage, startThreadCount, threadCount); th.printStackTrace(); System.err.flush(); throw th; } } }; } private long collectionTimeMs(List<GarbageCollectorMXBean> garbageCollectorMXBeans) { long sum = 0L; for (GarbageCollectorMXBean gc : garbageCollectorMXBeans) { long collectionTime = gc.getCollectionTime(); if (collectionTime != -1) { sum += collectionTime; } } return sum; } private long getCompilationTimeMs(CompilationMXBean compilationMXBean) { return compilationMXBean.isCompilationTimeMonitoringSupported()? compilationMXBean.getTotalCompilationTime() : 0; } private long getUserTimeNs(ThreadMXBean threadMXBean) { return threadMXBean.isCurrentThreadCpuTimeSupported()? threadMXBean.getCurrentThreadUserTime() : 0; } private long getCpuTimeNs(ThreadMXBean threadMXBean) { return threadMXBean.isCurrentThreadCpuTimeSupported()? threadMXBean.getCurrentThreadCpuTime() : 0; } }