Compress the heap dump after tests are finished
Motivation: Tests sometimes time out because it took too long to compress the generated heap dump. Modifications: - Move the compression logic to a new method 'compressHeapDumps()' - Call TestUtils.compressHeapDumps() at the end of the tests, so that the tests do not fail because of timeout Result: JUnit reports the real cause of the test failure instead of timeout exception.
This commit is contained in:
parent
9ee75126eb
commit
c7b407e288
@ -26,7 +26,10 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.testsuite.util.TestUtils;
|
import io.netty.testsuite.util.TestUtils;
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.Timeout;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@ -36,6 +39,9 @@ import static org.junit.Assert.*;
|
|||||||
|
|
||||||
public class SocketGatheringWriteTest extends AbstractSocketTest {
|
public class SocketGatheringWriteTest extends AbstractSocketTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final Timeout globalTimeout = new Timeout(60000);
|
||||||
|
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
static final byte[] data = new byte[1048576];
|
static final byte[] data = new byte[1048576];
|
||||||
|
|
||||||
@ -43,7 +49,12 @@ public class SocketGatheringWriteTest extends AbstractSocketTest {
|
|||||||
random.nextBytes(data);
|
random.nextBytes(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 60000)
|
@AfterClass
|
||||||
|
public static void compressHeapDumps() throws Exception {
|
||||||
|
TestUtils.compressHeapDumps();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testGatheringWrite() throws Throwable {
|
public void testGatheringWrite() throws Throwable {
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
@ -52,7 +63,7 @@ public class SocketGatheringWriteTest extends AbstractSocketTest {
|
|||||||
testGatheringWrite0(sb, cb, data, false, true);
|
testGatheringWrite0(sb, cb, data, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 60000)
|
@Test
|
||||||
public void testGatheringWriteNotAutoRead() throws Throwable {
|
public void testGatheringWriteNotAutoRead() throws Throwable {
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
@ -61,7 +72,7 @@ public class SocketGatheringWriteTest extends AbstractSocketTest {
|
|||||||
testGatheringWrite0(sb, cb, data, false, false);
|
testGatheringWrite0(sb, cb, data, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 60000)
|
@Test
|
||||||
public void testGatheringWriteWithComposite() throws Throwable {
|
public void testGatheringWriteWithComposite() throws Throwable {
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
@ -70,7 +81,7 @@ public class SocketGatheringWriteTest extends AbstractSocketTest {
|
|||||||
testGatheringWrite0(sb, cb, data, true, false);
|
testGatheringWrite0(sb, cb, data, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 60000)
|
@Test
|
||||||
public void testGatheringWriteWithCompositeNotAutoRead() throws Throwable {
|
public void testGatheringWriteWithCompositeNotAutoRead() throws Throwable {
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
@ -80,7 +91,7 @@ public class SocketGatheringWriteTest extends AbstractSocketTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test for https://github.com/netty/netty/issues/2647
|
// Test for https://github.com/netty/netty/issues/2647
|
||||||
@Test(timeout = 60000)
|
@Test
|
||||||
public void testGatheringWriteBig() throws Throwable {
|
public void testGatheringWriteBig() throws Throwable {
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import io.netty.util.concurrent.Future;
|
|||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
import io.netty.util.internal.logging.InternalLogger;
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||||
|
import org.junit.AfterClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.Parameterized;
|
import org.junit.runners.Parameterized;
|
||||||
@ -189,6 +190,11 @@ public class SocketSslEchoTest extends AbstractSocketTest {
|
|||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void compressHeapDumps() throws Exception {
|
||||||
|
TestUtils.compressHeapDumps();
|
||||||
|
}
|
||||||
|
|
||||||
public void testSslEcho(ServerBootstrap sb, Bootstrap cb) throws Throwable {
|
public void testSslEcho(ServerBootstrap sb, Bootstrap cb) throws Throwable {
|
||||||
final ExecutorService delegatedTaskExecutor = Executors.newCachedThreadPool();
|
final ExecutorService delegatedTaskExecutor = Executors.newCachedThreadPool();
|
||||||
final EchoHandler sh = new EchoHandler(true);
|
final EchoHandler sh = new EchoHandler(true);
|
||||||
|
@ -27,6 +27,7 @@ import javax.management.MBeanServer;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -44,6 +45,7 @@ import java.util.Date;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public final class TestUtils {
|
public final class TestUtils {
|
||||||
|
|
||||||
@ -59,6 +61,8 @@ public final class TestUtils {
|
|||||||
private static final Method hotspotMXBeanDumpHeap;
|
private static final Method hotspotMXBeanDumpHeap;
|
||||||
private static final Object hotspotMXBean;
|
private static final Object hotspotMXBean;
|
||||||
|
|
||||||
|
private static final long DUMP_PROGRESS_LOGGING_INTERVAL = TimeUnit.SECONDS.toNanos(5);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Populate the list of random ports.
|
// Populate the list of random ports.
|
||||||
for (int i = START_PORT; i < END_PORT; i ++) {
|
for (int i = START_PORT; i < END_PORT; i ++) {
|
||||||
@ -226,6 +230,79 @@ public final class TestUtils {
|
|||||||
dumpThreads(threadDumpFile);
|
dumpThreads(threadDumpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void compressHeapDumps() throws IOException {
|
||||||
|
final File[] files = new File(System.getProperty("user.dir")).listFiles(new FilenameFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(File dir, String name) {
|
||||||
|
return name.endsWith(".hprof");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final byte[] buf = new byte[65536];
|
||||||
|
final LZMA2Options options = new LZMA2Options(9);
|
||||||
|
|
||||||
|
for (File file: files) {
|
||||||
|
final String filename = file.toString();
|
||||||
|
final String xzFilename = filename + ".xz";
|
||||||
|
final long fileLength = file.length();
|
||||||
|
|
||||||
|
logger.info("Compressing the heap dump: {}", xzFilename);
|
||||||
|
|
||||||
|
long lastLogTime = System.nanoTime();
|
||||||
|
long counter = 0;
|
||||||
|
|
||||||
|
InputStream in = null;
|
||||||
|
OutputStream out = null;
|
||||||
|
try {
|
||||||
|
in = new FileInputStream(filename);
|
||||||
|
out = new XZOutputStream(new FileOutputStream(xzFilename), options);
|
||||||
|
for (;;) {
|
||||||
|
int readBytes = in.read(buf);
|
||||||
|
if (readBytes < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (readBytes == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.write(buf, 0, readBytes);
|
||||||
|
counter += readBytes;
|
||||||
|
|
||||||
|
long currentTime = System.nanoTime();
|
||||||
|
if (currentTime - lastLogTime > DUMP_PROGRESS_LOGGING_INTERVAL) {
|
||||||
|
logger.info("Compressing the heap dump: {} ({}%)",
|
||||||
|
xzFilename, counter * 100 / fileLength);
|
||||||
|
lastLogTime = currentTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
in.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("Failed to compress the heap dump: {}", xzFilename, e);
|
||||||
|
} finally {
|
||||||
|
if (in != null) {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (out != null) {
|
||||||
|
try {
|
||||||
|
out.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the uncompressed dump in favor of the compressed one.
|
||||||
|
if (!file.delete()) {
|
||||||
|
logger.warn("Failed to delete the uncompressed heap dump: {}", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static String timestamp() {
|
private static String timestamp() {
|
||||||
return new SimpleDateFormat("HHmmss.SSS").format(new Date());
|
return new SimpleDateFormat("HHmmss.SSS").format(new Date());
|
||||||
}
|
}
|
||||||
@ -242,51 +319,6 @@ public final class TestUtils {
|
|||||||
hotspotMXBeanDumpHeap.invoke(hotspotMXBean, filename, true);
|
hotspotMXBeanDumpHeap.invoke(hotspotMXBean, filename, true);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("Failed to dump heap: {}", filename, e);
|
logger.warn("Failed to dump heap: {}", filename, e);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String xzFilename = filename + ".xz";
|
|
||||||
logger.info("Compressing the heap dump: {}", xzFilename);
|
|
||||||
final byte[] buf = new byte[65536];
|
|
||||||
InputStream in = null;
|
|
||||||
OutputStream out = null;
|
|
||||||
try {
|
|
||||||
in = new FileInputStream(filename);
|
|
||||||
out = new XZOutputStream(new FileOutputStream(xzFilename), new LZMA2Options(9));
|
|
||||||
for (;;) {
|
|
||||||
int readBytes = in.read(buf);
|
|
||||||
if (readBytes < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (readBytes == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out.write(buf, 0, readBytes);
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
in.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.warn("Failed to compress the heap dump: {}", xzFilename, e);
|
|
||||||
} finally {
|
|
||||||
if (in != null) {
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
// Ignore.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (out != null) {
|
|
||||||
try {
|
|
||||||
out.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
// Ignore.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the uncompressed dump in favor of the compressed one.
|
|
||||||
if (!file.delete()) {
|
|
||||||
logger.warn("Failed to delete the uncompressed heap dump: {}", filename);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user