package org.geotools.gce.geotiff; import static org.junit.Assert.*; import java.io.File; import java.io.FilenameFilter; import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.geotools.test.TestData; import org.junit.Test; public class GeoTiffDeadlockTest { /** * Increase this value to get more threads than files */ int multiplier = 1; @Test public void testForDeadlock() throws Exception { // grab all the test data files (but not those that contain known errors) final File dir = TestData.file(GeoTiffReaderTest.class, ""); final File files[] = dir.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { if(name.startsWith("no_crs_no_envelope")) { return false; } return true; } }); final int numFiles = files.length; // prepare the loaders final AtomicInteger ai = new AtomicInteger(numFiles); // start them // System.out.println("Testing with " + numFiles + " files"); final List<Thread> threads = new ArrayList<Thread>(); final int total = numFiles * multiplier; //System.out.println("Testing with " + total + " threads"); for (int index = 0; index < total; index++) { final File file = files[index % multiplier]; Runnable testRunner = new Runnable() { public void run() { try { GeoTiffReader reader = new GeoTiffReader(file); reader.read(null); } catch (Exception e) { throw new RuntimeException("Exception opening file " + file, e); } finally { ai.decrementAndGet(); } } }; final Thread thread = new Thread(testRunner); thread.start(); threads.add(thread); } // use jmx to do deadlock detection try { final ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); while (ai.get() > 0) { long[] deadlockedThreads = mbean.findMonitorDeadlockedThreads(); if (deadlockedThreads != null && deadlockedThreads.length > 0) { fail("Deadlock detected between the following threads: " + Arrays.toString(deadlockedThreads)); } // sleep for a bit Thread.currentThread().sleep(10); } } finally { // kill all the threads for (final Thread thread : threads) { if(thread.isAlive()) { thread.interrupt(); } } } } }