Java Source Code: org.limewire.nio.channel.InflaterReaderTest


   1: package org.limewire.nio.channel;
   2: 
   3: import java.io.ByteArrayOutputStream;
   4: import java.io.IOException;
   5: import java.io.OutputStream;
   6: import java.nio.ByteBuffer;
   7: import java.util.Random;
   8: import java.util.zip.Deflater;
   9: import java.util.zip.DeflaterOutputStream;
  10: import java.util.zip.Inflater;
  11: 
  12: import junit.framework.Test;
  13: 
  14: import org.limewire.util.BaseTestCase;
  15: 
  16: 
  17: /**
  18:  * Tests that InflaterReader inflates the source channel correctly.
  19:  */
  20:	  public final class InflaterReaderTest extends BaseTestCase {
  21:    
  22:    private Inflater INFLATER = new Inflater();
  23:    private InflaterReader READER = new InflaterReader(INFLATER);
  24:
  25:	      public InflaterReaderTest(String name) {
  26:        super(name);
  27:    }
  28:
  29:	      public static Test suite() {
  30:        return buildTestSuite(InflaterReaderTest.class);
  31:    }
  32:
  33:	      public static void main(String[] args) {
  34:        junit.textui.TestRunner.run(suite());
  35:    }
  36:    
  37:	      public void testChannelMethods() throws Exception {
  38:	          try {
  39:            READER.setReadChannel(null);
  40:            fail("expected NPE");
  41:        } catch(NullPointerException expected) {}
  42:        
  43:        InterestReadableByteChannel channel = new ReadBufferChannel(new byte[0]);
  44:        READER.setReadChannel(channel);
  45:        assertSame(channel, READER.getReadChannel());
  46:        
  47:	          try {
  48:            new InflaterReader(null);
  49:            fail("expected NPE");
  50:        } catch(NullPointerException expected) {}
  51:            
  52:        READER = new InflaterReader(channel, INFLATER);
  53:        assertSame(channel, READER.getReadChannel());
  54:        
  55:        READER = new InflaterReader(null, INFLATER);
  56:        assertNull(READER.getReadChannel());
  57:    }
  58:    
  59:	      public void testClosing() throws Exception {
  60:        ReadBufferChannel source = new ReadBufferChannel();
  61:        assertTrue(source.isOpen());
  62:        READER.setReadChannel(source);
  63:        assertTrue(READER.isOpen());
  64:        
  65:        source.setClosed(true);
  66:        assertFalse(READER.isOpen());
  67:        source.setClosed(false);
  68:        assertTrue(READER.isOpen());
  69:        
  70:        assertTrue(source.isOpen());
  71:        READER.close();
  72:        assertFalse(source.isOpen());
  73:    }
  74:    
  75:	      public void testFinishedInflation() throws Exception {
  76:        byte[] out = new byte[] { 1, (byte)2, (byte)3, (byte)-127, (byte)7, (byte)6 };
  77:        ByteBuffer b = deflate(out);
  78:        
  79:        READER.setReadChannel(channel(b));
  80:        ByteBuffer in = ByteBuffer.allocate(out.length + 1);
  81:        assertEquals(out.length, READER.read(in));
  82:        assertEquals(out.length, in.position());
  83:        assertEquals(buffer(out), in.flip());
  84:        
  85:        // Since the deflater finished the stream, the next read should return -1.
  86:        in.limit(out.length + 1);
  87:        assertEquals("should have seen finished stream", -1, READER.read(in));
  88:    }
  89:    
  90:	      public void testStreamedInflation() throws Exception {
  91:        byte[] out = new byte[] { 1, (byte)2, (byte)3, (byte)-127, (byte)7, (byte)6 };
  92:        ByteBuffer b = stream(out);
  93:        
  94:        READER.setReadChannel(channel(b));
  95:        ByteBuffer in = ByteBuffer.allocate(out.length + 1);
  96:        assertEquals(out.length, READER.read(in));
  97:        assertEquals(out.length, in.position());
  98:        assertEquals(buffer(out), in.flip());
  99:        
 100:        // Since the deflater didn't finish the stream, the next read should return 0.
 101:        in.limit(out.length + 1);
 102:        assertEquals("stream shouldn't have ended", 0, READER.read(in));
 103:    }
 104:    
 105:	      public void testLargeInput() throws Exception {
 106:        byte[] out = new byte[128 * 1024];
 107:        new Random().nextBytes(out);
 108:        ByteBuffer b = stream(out);
 109:        assertGreaterThan("deflated data too small", 20 * 1024, b.remaining());
 110:        
 111:        READER.setReadChannel(channel(b));
 112:        ByteBuffer in = ByteBuffer.allocate(out.length + 1);
 113:        assertEquals("input buffer: " + b, out.length, READER.read(in));
 114:        assertEquals(out.length, in.position());
 115:        assertEquals(buffer(out), in.flip());
 116:        
 117:        // Since the deflater didn't finish the stream, the next read should return 0.
 118:        in.limit(out.length + 1);
 119:        assertEquals("stream shouldn't have ended", 0, READER.read(in));
 120:    }
 121:    
 122:	      public void testEOFWithStream() throws Exception {
 123:        byte[] out = new byte[1024];
 124:        new Random().nextBytes(out);
 125:        ByteBuffer b = stream(out);
 126:        
 127:        READER.setReadChannel(eof(b));
 128:        ByteBuffer in = ByteBuffer.allocate(out.length + 1);
 129:        assertEquals("input buffer: " + b, out.length, READER.read(in));
 130:        assertEquals(out.length, in.position());
 131:        assertEquals(buffer(out), in.flip());
 132:        
 133:        // Even though there's data the deflater is waiting on, the stream EOF'd.
 134:        in.limit(out.length + 1);
 135:        assertEquals("stream should have EOF'd", -1, READER.read(in));
 136:    }
 137:    
 138:	      public void testPartialReads() throws Exception {
 139:        byte[] out = new byte[64 * 1024];
 140:        new Random().nextBytes(out);
 141:        ByteBuffer b1 = stream(out);
 142:        ByteBuffer b2 = b1.duplicate();
 143:        ByteBuffer b3 = b2.duplicate();
 144:        ByteBuffer b4 = b3.duplicate();
 145:        
 146:        b1.limit(500);
 147:        b2.position(500).limit(2000);
 148:        b3.position(2000).limit(8000);
 149:        b4.position(8000);
 150:        
 151:        ByteBuffer in = ByteBuffer.allocate(out.length + 1);
 152:        
 153:        // The data is going to be deflated randomly,
 154:        // according to what sections are decompressable and what aren't.
 155:        
 156:        int read = 0;
 157:        
 158:        READER.setReadChannel(channel(b1));
 159:        assertTrue(b1.hasRemaining());
 160:        read += READER.read(in);
 161:        assertEquals(read, in.position());
 162:        assertFalse(b1.hasRemaining());
 163:        
 164:        READER.setReadChannel(channel(b2));
 165:        assertTrue(b2.hasRemaining());
 166:        read += READER.read(in);
 167:        assertEquals(read, in.position());
 168:        assertFalse(b2.hasRemaining());
 169:
 170:        READER.setReadChannel(channel(b3));
 171:        assertTrue(b3.hasRemaining());
 172:        read += READER.read(in);
 173:        assertEquals(read, in.position());
 174:        assertFalse(b3.hasRemaining());
 175:        
 176:        READER.setReadChannel(channel(b4));
 177:        assertTrue(b4.hasRemaining());
 178:        read += READER.read(in);
 179:        assertEquals(out.length, in.position());
 180:        assertEquals(out.length, read);
 181:        assertFalse(b4.hasRemaining());
 182:        
 183:        assertEquals(buffer(out), in.flip());
 184:        
 185:        // Still another chunk that may come...
 186:        in.limit(out.length + 1);
 187:        assertEquals("stream shouldn't have ended.", 0, READER.read(in));
 188:    }
 189:    
 190:	      private InterestReadableByteChannel channel(ByteBuffer buffer) throws Exception {
 191:        return new ReadBufferChannel(buffer);
 192:    }
 193:    
 194:	      private InterestReadableByteChannel eof(ByteBuffer buffer) throws Exception {
 195:        return new ReadBufferChannel(buffer, true);
 196:    }
 197:    
 198:	      private ByteBuffer deflate(byte[] data) throws Exception {
 199:        OutputStream dos = null;
 200:	          try {
 201:            ByteArrayOutputStream baos=new ByteArrayOutputStream();
 202:            dos = new DeflaterOutputStream(baos);
 203:            dos.write(data, 0, data.length);
 204:            dos.close();                      //flushes bytes
 205:            return buffer(baos.toByteArray());
 206:        } finally {
 207:            try { dos.close(); } catch(IOException x) {}
 208:        }
 209:    }
 210:    
 211:	      private ByteBuffer stream(byte[] data) throws Exception {
 212:        OutputStream dos = null;
 213:        Deflater def = new Deflater();
 214:	          try {
 215:            ByteArrayOutputStream baos=new ByteArrayOutputStream();
 216:            dos = new FlushableDeflatingStream(baos, def);
 217:            dos.write(data, 0, data.length);
 218:            dos.flush();
 219:            return buffer(baos.toByteArray());
 220:        } finally {
 221:            try { dos.close(); } catch(IOException x) {}
 222:            def.end();
 223:        }
 224:    }
 225:
 226:	      private ByteBuffer buffer(byte[] b) throws Exception {
 227:        return ByteBuffer.wrap(b);
 228:    }
 229:
 230:    /** OutputStream that deflates but doesn't close when flushed. */
 231:	      private static final class FlushableDeflatingStream extends DeflaterOutputStream {
 232:        
 233:	          public FlushableDeflatingStream (final OutputStream out, final Deflater flate) {
 234:          super(out, flate);
 235:        }
 236:        
 237:	          public void flush() throws IOException {
 238:            if( def.finished() ) return;
 239:            def.setInput(new byte[0], 0, 0);
 240:            def.setLevel(Deflater.NO_COMPRESSION);
 241:            deflate();
 242:            def.setLevel(Deflater.DEFAULT_COMPRESSION);
 243:            deflate();
 244:            super.flush();
 245:        }
 246:        
 247:	          protected void deflate() throws IOException {
 248:	              try {
 249:                int deflated;
 250:                while( (deflated = def.deflate(buf, 0, buf.length)) > 0)
 251:                    out.write(buf, 0, deflated);
 252:            } catch(NullPointerException e) {
 253:                //This will happen if 'end' was called on the deflater
 254:                //while we were deflating.
 255:                throw new IOException("deflater was ended");
 256:            }
 257:        }
 258:    }    
 259:}