Added a soak test & isolated test for just fixed bug.
This commit is contained in:
@@ -24,22 +24,19 @@ package com.threerings.io;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Pipe;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class FrameTest extends TestCase
|
||||
public class FrameTest
|
||||
{
|
||||
public FrameTest ()
|
||||
{
|
||||
super(FrameTest.class.getName());
|
||||
}
|
||||
|
||||
public void writeFrames (WritableByteChannel out)
|
||||
throws IOException
|
||||
{
|
||||
@@ -90,28 +87,142 @@ public class FrameTest extends TestCase
|
||||
assertTrue("hit eof", fin.read() == -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runTest ()
|
||||
// @Test
|
||||
public void testReadWriteFrames () throws IOException
|
||||
{
|
||||
try {
|
||||
Pipe pipe = SelectorProvider.provider().openPipe();
|
||||
writeFrames(pipe.sink());
|
||||
readFrames(pipe.source());
|
||||
Pipe pipe = SelectorProvider.provider().openPipe();
|
||||
writeFrames(pipe.sink());
|
||||
readFrames(pipe.source());
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace(System.err);
|
||||
@Test
|
||||
public void testInvariantFailure () throws Exception {
|
||||
final int[] FRAME_COUNTS = new int[] {
|
||||
14349, 14054, 15574, 575, 15497, 5417, 3732, 13746, 3043, 3829, 15862, 2285, 4242,
|
||||
4903, 16361, 14213, 7981, 4591, 12263, 16268, 15296, 11822, 2713, 4353, 15013, 9810,
|
||||
3015, 189, 7988, 6347, 5859, 13433, 3551, 13795, 5164, 7821, 2383, 1513, 16383, 2106,
|
||||
7376, 8168
|
||||
};
|
||||
|
||||
for (int cc = 0; cc < 50; cc += 1) {
|
||||
final Pipe pipe = SelectorProvider.provider().openPipe();
|
||||
final WritableByteChannel out = pipe.sink();
|
||||
final ReadableByteChannel in = pipe.source();
|
||||
|
||||
// write out the frames of the specified sizes
|
||||
Thread writer = new Thread() {
|
||||
public void run () {
|
||||
try {
|
||||
FramingOutputStream fout = new FramingOutputStream();
|
||||
DataOutputStream dout = new DataOutputStream(fout);
|
||||
|
||||
for (int count : FRAME_COUNTS) {
|
||||
for (int ii = 0; ii < count; ii++) dout.writeInt(ii);
|
||||
ByteBuffer frame = fout.frameAndReturnBuffer();
|
||||
int wrote = 0, size = frame.remaining(), window = 128;
|
||||
while (wrote < size) {
|
||||
// write out the buffer in small chunks so we trigger the failure in
|
||||
// the reader
|
||||
frame.limit(Math.min(window, size));
|
||||
wrote += out.write(frame);
|
||||
window += 128;
|
||||
}
|
||||
fout.resetFrame();
|
||||
// System.out.println("Sent frame @ " + count);
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
fail(ioe.getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
writer.start();
|
||||
|
||||
// read them back in and check their contents
|
||||
FramedInputStream fin = new FramedInputStream();
|
||||
DataInputStream din = new DataInputStream(fin);
|
||||
for (int ff = 0; ff < FRAME_COUNTS.length; ff += 1) {
|
||||
try {
|
||||
while (!fin.readFrame(in)) {} // loop!
|
||||
int count = fin.available() / 4;
|
||||
for (int ii = 0; ii < count; ii++) assertEquals(ii, din.readInt());
|
||||
// System.out.println("Read frame " + ff + " @ " + count);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
System.err.println("Invariant violation reading frame " + ff + ": " + iae);
|
||||
throw iae;
|
||||
}
|
||||
}
|
||||
|
||||
writer.join();
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static Test suite ()
|
||||
{
|
||||
return new FrameTest();
|
||||
}
|
||||
// this soak test was used to generate a series of frame sizes that triggered the nasty bug
|
||||
// that is isolated and tested by the above testInvariantFailure test; let's hope we go another
|
||||
// 17 years before we have to use the soak test again
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
FrameTest test = new FrameTest();
|
||||
test.runTest();
|
||||
// @Test
|
||||
public void testManyRandomFrames () throws Exception {
|
||||
final int PAIRS = 102400;
|
||||
|
||||
for (int pp = 0; pp < PAIRS; pp++) {
|
||||
if (pp % 128 == 0) System.out.println("Starting reader/writer pair " + pp);
|
||||
|
||||
final Pipe pipe = SelectorProvider.provider().openPipe();
|
||||
final WritableByteChannel out = pipe.sink();
|
||||
final ReadableByteChannel in = pipe.source();
|
||||
final int FRAMES = 100;
|
||||
final List<Integer> frameSizes = new ArrayList<Integer>();
|
||||
|
||||
// write out a series of randomly sized frames
|
||||
Thread writer = new Thread() {
|
||||
public void run () {
|
||||
try {
|
||||
Random rando = new Random();
|
||||
FramingOutputStream fout = new FramingOutputStream();
|
||||
DataOutputStream dout = new DataOutputStream(fout);
|
||||
|
||||
for (int ff = 0; ff < FRAMES; ff++) {
|
||||
int count = rando.nextInt(16*1024);
|
||||
frameSizes.add(count);
|
||||
for (int ii = 0; ii < count; ii++) dout.writeInt(ii);
|
||||
ByteBuffer frame = fout.frameAndReturnBuffer();
|
||||
int wrote = 0;
|
||||
while (wrote < frame.limit()) wrote += out.write(frame);
|
||||
fout.resetFrame();
|
||||
// if (ff % 1000 == 0) System.out.println("Sent frame " + ff);
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
fail(ioe.getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
writer.start();
|
||||
|
||||
// read them back in and check their contents
|
||||
FramedInputStream fin = new FramedInputStream();
|
||||
DataInputStream din = new DataInputStream(fin);
|
||||
for (int ff = 0; ff < FRAMES; ff++) {
|
||||
// if (ff % 1000 == 0) System.out.println("Reading frame " + ff);
|
||||
try {
|
||||
while (!fin.readFrame(in)) {} // loop!
|
||||
int ints = fin.available() / 4;
|
||||
for (int ii = 0; ii < ints; ii++) assertEquals(ii, din.readInt());
|
||||
} catch (IllegalArgumentException iae) {
|
||||
System.err.println("Invariant violation: " + iae.getMessage());
|
||||
System.err.println("While reading frame: " + ff);
|
||||
System.err.println("Frame sizes: " + frameSizes);
|
||||
throw iae;
|
||||
}
|
||||
}
|
||||
|
||||
writer.join();
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected static final String STRING1 = "This is a test.";
|
||||
@@ -121,11 +232,9 @@ public class FrameTest extends TestCase
|
||||
"this frame and someone would probably be enjoying themselves.";
|
||||
|
||||
protected static final String STRING4 =
|
||||
"Now is the time for all good men to come to the aid of " +
|
||||
"their country.";
|
||||
"Now is the time for all good men to come to the aid of their country.";
|
||||
protected static final String STRING5 = "Every good boy deserves fudge.";
|
||||
protected static final String STRING6 =
|
||||
"The quick brown fox jumped over the lazy dog.";
|
||||
protected static final String STRING6 = "The quick brown fox jumped over the lazy dog.";
|
||||
|
||||
protected static final String STRING7 = "Third time is the charm.";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user