package com.limegroup.gnutella.dime; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import junit.framework.Test; import com.limegroup.gnutella.ByteOrder; /** * Tests for DIMERecord. */ public final class DIMERecordTest extends com.limegroup.gnutella.util.BaseTestCase { /** * Constructs a new test instance for responses. */ public DIMERecordTest(String name) { super(name); } public static Test suite() { return buildTestSuite(DIMERecordTest.class); } /** * Runs this test individually. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } // A DIME Record looks like the following: /////////////////////////////////////////////////////////////////// // 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 // ---------------------------------------------------------------- // VERSION |M|M|C| TYPE | RSRV | OPTIONS_LENGTH // |B|E|F| | | // ---------------------------------------------------------------- // ID_LENGTH | TYPE_LENGTH // ---------------------------------------------------------------- // DATA_LENGTH // ---------------------------------------------------------------- // OPTIONS + PADDING // ---------------------------------------------------------------- // ID + PADDING // ---------------------------------------------------------------- // TYPE + PADDING // ---------------------------------------------------------------- // DATA + PADDING // ---------------------------------------------------------------- /////////////////////////////////////////////////////////////////// // TYPES: // UNCHANGED: 0x00 // MEDIA_TYPE: 0x01 // ABSOLUTE_URI: 0x02 // UNKNOWN: 0x03 // NONE: 0x04 // TODO: Add tests for options (we currently don't use any options) public void testCreateFromStream() throws Exception { // Basic DIMERecord, no data at all, correct version. // More complex records are tested in other tests. ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x00 ); // no type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); DIMERecord record = DIMERecord.createFromStream(in); assertFalse(record.isFirstRecord()); assertFalse(record.isLastRecord()); assertEquals(DIMERecord.TYPE_UNCHANGED, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals("", record.getIdentifier()); // test again for coverage. assertEquals(new HashMap(), record.getOptionsMap()); assertEquals(new HashMap(), record.getOptionsMap()); // test again. } public void testCreate() throws Exception { // Basic DIMERecord, no data at all. // More complex creates are tested in other tests. DIMERecord record = new DIMERecord((byte)0x00, null, null, null, null); assertFalse(record.isFirstRecord()); assertFalse(record.isLastRecord()); assertEquals(DIMERecord.TYPE_UNCHANGED, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); assertEquals(12, record.getRecordLength()); ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in; record.write(out); in = new ByteArrayInputStream(out.toByteArray()); byte[] header = new byte[12]; assertEquals(12, in.read(header, 0, 12)); assertEquals(0x08, header[0]); assertEquals(0x00, header[1]); for(int i = 2; i < header.length; i++) assertEquals(0, header[i]); assertEquals(-1, in.read()); } public void testMessageBeginAndMessageEnd() throws Exception { DIMERecord record; ByteArrayOutputStream out; ByteArrayInputStream in; byte[] header = new byte[12]; record = new DIMERecord((byte)0x00, null, null, null, null); assertFalse(record.isFirstRecord()); assertFalse(record.isLastRecord()); record.setFirstRecord(true); assertTrue(record.isFirstRecord()); assertFalse(record.isLastRecord()); record.setFirstRecord(false); assertFalse(record.isFirstRecord()); assertFalse(record.isLastRecord()); record.setLastRecord(true); assertFalse(record.isFirstRecord()); assertTrue(record.isLastRecord()); record.setLastRecord(false); assertFalse(record.isFirstRecord()); assertFalse(record.isLastRecord()); record.setFirstRecord(true); record.setLastRecord(true); assertTrue(record.isFirstRecord()); assertTrue(record.isLastRecord()); record.setFirstRecord(true); record.setLastRecord(false); out = new ByteArrayOutputStream(); record.write(out); in = new ByteArrayInputStream(out.toByteArray()); assertEquals(12, in.read(header, 0, 12)); assertEquals( 0x08 | (0x01 << 2), header[0]); // test MB flag for(int i = 1; i < header.length; i++) assertEquals(0, header[i]); assertEquals(-1, in.read()); record.setFirstRecord(false); record.setLastRecord(true); out = new ByteArrayOutputStream(); record.write(out); in = new ByteArrayInputStream(out.toByteArray()); assertEquals(12, in.read(header, 0, 12)); assertEquals( 0x08 | (0x01 << 1), header[0]); // test ME flag for(int i = 1; i < header.length; i++) assertEquals(0, header[i]); assertEquals(-1, in.read()); record.setFirstRecord(true); record.setLastRecord(true); out = new ByteArrayOutputStream(); record.write(out); in = new ByteArrayInputStream(out.toByteArray()); assertEquals(12, in.read(header, 0, 12)); assertEquals( 0x08 | (0x01 << 2) | (0x01 << 1), header[0]); // ME & MB for(int i = 1; i < header.length; i++) assertEquals(0, header[i]); assertEquals(-1, in.read()); record.setFirstRecord(false); record.setLastRecord(false); out = new ByteArrayOutputStream(); record.write(out); in = new ByteArrayInputStream(out.toByteArray()); assertEquals(12, in.read(header, 0, 12)); assertEquals( 0x08, header[0]); // neither ME nor MB. for(int i = 1; i < header.length; i++) assertEquals(0, header[i]); assertEquals(-1, in.read()); } public void testPadding() throws Exception { // Make sure we pad output with the appropriate stuff. DIMERecord record; ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in; byte[] header = new byte[12]; record = new DIMERecord(DIMERecord.TYPE_MEDIA_TYPE, "4abc".getBytes(), "1".getBytes(), "2x".getBytes(), "3yz".getBytes()); assertEquals(DIMERecord.TYPE_MEDIA_TYPE, record.getTypeId()); assertEquals("1", record.getIdentifier()); assertEquals("1".getBytes(), record.getId()); assertEquals("2x", record.getTypeString()); assertEquals("3yz".getBytes(), record.getData()); assertEquals("4abc".getBytes(), record.getOptions()); assertEquals(28, record.getRecordLength()); record.write(out); in = new ByteArrayInputStream(out.toByteArray()); assertEquals(12, in.read(header, 0, 12)); // must read 12 bytes of the header. assertEquals(0x08, header[0]); // version + flags assertEquals(DIMERecord.TYPE_MEDIA_TYPE, header[1]); // type + reserve int optionsLength = ByteOrder.beb2int(header, 2, 2); int idLength = ByteOrder.beb2int(header, 4, 2); int typeLength = ByteOrder.beb2int(header, 6, 2); int dataLength = ByteOrder.beb2int(header, 8, 4); assertEquals(4, optionsLength); assertEquals(1, idLength); assertEquals(2, typeLength); assertEquals(3, dataLength); // this is the real padding test -- all data is in multiples of 4, // with extra 0s at the end for the padding. byte[] info = new byte[4]; assertEquals(4, in.read(info, 0, 4)); assertEquals( new byte[] { '4', 'a', 'b', 'c' }, info); assertEquals(4, in.read(info, 0, 4)); assertEquals( new byte[] { '1', 0, 0, 0 }, info ); assertEquals(4, in.read(info, 0, 4)); assertEquals( new byte[] { '2', 'x', 0, 0 }, info ); assertEquals(4, in.read(info, 0, 4)); assertEquals( new byte[] { '3', 'y', 'z', 0 }, info ); assertEquals(-1, in.read()); //Create a message with some padding and make sure we can read it. out = new ByteArrayOutputStream(); out.write(0x08); out.write(DIMERecord.TYPE_MEDIA_TYPE); ByteOrder.int2beb(5, out, 2); // options length: 5 ByteOrder.int2beb(6, out, 2); // id length: 6 ByteOrder.int2beb(7, out, 2); // type length: 7 ByteOrder.int2beb(8, out, 4); // data length: 8 out.write(new byte[] { 's', 'a', 'm', 'm', 'y', 0 , 0 , 0 } ); out.write(new byte[] { 'b', 'e', 'r', 'l', 'i', 'n', 0 , 0 } ); out.write(new byte[] { 'h', 'a', 'c', 'k', 'e', 'r', 's', 0 } ); out.write(new byte[] { 'l', 'i', 'm', 'e', 'w', 'i', 'r', 'e' } ); in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); assertEquals(DIMERecord.TYPE_MEDIA_TYPE, record.getTypeId()); assertEquals("sammy".getBytes(), record.getOptions()); assertEquals("berlin", record.getIdentifier()); assertEquals("berlin".getBytes(), record.getId()); assertEquals("hackers", record.getTypeString()); assertEquals("limewire".getBytes(), record.getData()); assertEquals(44, record.getRecordLength()); //Create a message with invalid padding and make sure we throw IOE. out = new ByteArrayOutputStream(); out.write(0x08); out.write(DIMERecord.TYPE_MEDIA_TYPE); ByteOrder.int2beb(5, out, 2); // options length: 5 ByteOrder.int2beb(6, out, 2); // id length: 6 ByteOrder.int2beb(7, out, 2); // type length: 7 ByteOrder.int2beb(8, out, 4); // data length: 8 out.write(new byte[] { 's', 'a', 'm', 'm', 'y', 0 , 0 } ); out.write(new byte[] { 'b', 'e', 'r', 'l', 'i', 'n', 0 , 0 } ); out.write(new byte[] { 'h', 'a', 'c', 'k', 'e', 'r', 's', 0 } ); out.write(new byte[] { 'l', 'i', 'm', 'e', 'w', 'i', 'r', 'e' } ); in = new ByteArrayInputStream(out.toByteArray()); try { record = DIMERecord.createFromStream(in); } catch(IOException expected) { assertEquals("eof", expected.getMessage()); } } public void testValidTypes() throws Exception { DIMERecord record; ByteArrayOutputStream out; ByteArrayInputStream in; // A - TYPE_UNCHANGED. // Valid only if the 'type' data is 0 length. record = new DIMERecord((byte)0x00, null, null, null, null); assertEquals(DIMERecord.TYPE_UNCHANGED, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); // we already tested the network TYPE_UNCHANGED in testCreateFromStream // Now try a bad case -- TYPE_UNCHANGED with a type passed to it. try { record = new DIMERecord((byte)0x00, null, null, "sam".getBytes(), null); fail("expected exception"); } catch(IllegalArgumentException expected) { assertEquals("TYPE_UNCHANGED requires 0 type length", expected.getMessage()); } // Try from network too try { out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x00 ); // no type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 ByteOrder.int2beb(3, out, 2); // type length: 3 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 out.write( new byte[] { 's', 'a', 'm', 0 } ); // type + padding in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); fail("expected exception."); } catch(IOException expected) { assertEquals("TYPE_UNCHANGED requires 0 type length", expected.getMessage()); } // B - TYPE_MEDIA_TYPE // Valid always. record = new DIMERecord((byte)(0x01 << 4), null, null, null, null); assertEquals(DIMERecord.TYPE_MEDIA_TYPE, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x01 << 4 ); // type out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); assertEquals(DIMERecord.TYPE_MEDIA_TYPE, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); // try with some type data too. record = new DIMERecord((byte)(0x01 << 4), null, null, "sam".getBytes(), null); assertEquals(DIMERecord.TYPE_MEDIA_TYPE, record.getTypeId()); assertEquals(3, record.getType().length); assertEquals("sam", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x01 << 4 ); // type out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 ByteOrder.int2beb(3, out, 2); out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 out.write( new byte[] { 's', 'a', 'm', 0 } ); // type data + padding. in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); assertEquals(DIMERecord.TYPE_MEDIA_TYPE, record.getTypeId()); assertEquals(3, record.getType().length); assertEquals("sam", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); // C - Absolute URI, valid always. record = new DIMERecord((byte)(0x02 << 4), null, null, null, null); assertEquals(DIMERecord.TYPE_ABSOLUTE_URI, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x02 << 4 ); // type out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); assertEquals(DIMERecord.TYPE_ABSOLUTE_URI, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); // try with some type data too. record = new DIMERecord((byte)(0x02 << 4), null, null, "sam".getBytes(), null); assertEquals(DIMERecord.TYPE_ABSOLUTE_URI, record.getTypeId()); assertEquals(3, record.getType().length); assertEquals("sam", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x02 << 4 ); // type out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 ByteOrder.int2beb(3, out, 2); out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 out.write( new byte[] { 's', 'a', 'm', 0 } ); // type data + padding. in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); assertEquals(DIMERecord.TYPE_ABSOLUTE_URI, record.getTypeId()); assertEquals(3, record.getType().length); assertEquals("sam", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); // D - TYPE_UNKNOWN. // Valid only if the 'type' data is 0 length. record = new DIMERecord((byte)(0x03 << 4), null, null, null, null); assertEquals(DIMERecord.TYPE_UNKNOWN, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x03 << 4 ); // type out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); assertEquals(DIMERecord.TYPE_UNKNOWN, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); // Now try a bad case -- TYPE_UNKNOWN with a type passed to it. try { record = new DIMERecord((byte)(0x03 << 4), null, null, "sam".getBytes(), null); fail("expected exception"); } catch(IllegalArgumentException expected) { assertEquals("TYPE_UNKNOWN requires 0 type length", expected.getMessage()); } // Try from network too try { out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x03 << 4); // no type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 ByteOrder.int2beb(3, out, 2); // type length: 3 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 out.write( new byte[] { 's', 'a', 'm', 0 } ); // type + padding in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); fail("expected exception."); } catch(IOException expected) { assertEquals("TYPE_UNKNOWN requires 0 type length", expected.getMessage()); } // E - TYPE_NONE // Requires no data & no type. record = new DIMERecord((byte)(0x04 << 4), null, null, null, null); assertEquals(DIMERecord.TYPE_NONE, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x04 << 4 ); // type out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); assertEquals(DIMERecord.TYPE_NONE, record.getTypeId()); assertEquals(0, record.getType().length); assertEquals("", record.getTypeString()); assertEquals(0, record.getData().length); assertEquals(0, record.getId().length); assertEquals(0, record.getOptions().length); assertEquals("", record.getIdentifier()); assertEquals(new HashMap(), record.getOptionsMap()); // Now try a bad case -- TYPE_NONE with a type passed to it. try { record = new DIMERecord((byte)(0x04 << 4), null, null, "sam".getBytes(), null); fail("expected exception"); } catch(IllegalArgumentException expected) { assertEquals("TYPE_NONE requires 0 type & data length", expected.getMessage()); } // Try from network too try { out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x04 << 4 ); // no type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 ByteOrder.int2beb(3, out, 2); // type length: 3 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 out.write( new byte[] { 's', 'a', 'm', 0 } ); // type + padding in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); fail("expected exception."); } catch(IOException expected) { assertEquals("TYPE_NONE requires 0 type & data length", expected.getMessage()); } // Try another bad case -- TYPE_NONE with data passed to it. try { record = new DIMERecord((byte)(0x04 << 4), null, null, null, "samuel".getBytes()); fail("expected exception"); } catch(IllegalArgumentException expected) { assertEquals("TYPE_NONE requires 0 type & data length", expected.getMessage()); } // Try from network too try { out = new ByteArrayOutputStream(); out.write( 0x08 ); // version + mb, me, cf (all clear) out.write( 0x04 << 4 ); // no type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 ByteOrder.int2beb(6, out, 4); // data length: 6 //data + padding out.write( new byte[] { 's', 'a', 'm', 'u', 'e', 'l', 0, 0 } ); in = new ByteArrayInputStream(out.toByteArray()); record = DIMERecord.createFromStream(in); fail("expected exception."); } catch(IOException expected) { assertEquals("TYPE_NONE requires 0 type & data length", expected.getMessage()); } } public void testBadType() throws Exception { // 0 through 4 are valid, so start at 5. for(int i = 5; i < 0xF; i++) { int type = i << 4; ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write( (byte)0x08 ); //version + mb, me & cf. out.write( (byte)type ); // bad type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); try { DIMERecord record = DIMERecord.createFromStream(in); fail("expected exception"); } catch(IOException expected) { assertEquals("invalid type: " + i, expected.getMessage()); } // try also creating not from network. try { DIMERecord record = new DIMERecord((byte)type, null, null, null, null); fail("expected exception"); } catch(IllegalArgumentException expected) { assertEquals("invalid type: " + i, expected.getMessage()); } } } public void testBadVersion() throws Exception { //test every invalid version possible. for(int i = 0; i < (0xF8 >> 3); i++) { if(i == 1) // valid continue; int version = i << 3; ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write( (byte)version ); // mb, me & cf clear. out.write( 0x00 ); // no type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); try { DIMERecord record = DIMERecord.createFromStream(in); fail("expected exception"); } catch(IOException expected) { assertEquals("invalid version: " + i, expected.getMessage()); } } } public void testBadReserved() throws Exception { //test every invalid reserved value possible. for(int i = 0; i < 0xF; i++) { if(i == 0) // valid continue; ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write( 0x08 ); // mb, me & cf clear. out.write( (byte)i ); // no type + [invalid] reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { 0, 0, 0, 0 } ); // data length: 0 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); try { DIMERecord record = DIMERecord.createFromStream(in); fail("expected exception"); } catch(IOException expected) { assertEquals("invalid reserved: " + i, expected.getMessage()); } } } public void testDataTooLarge() throws Exception { ByteArrayOutputStream out; ByteArrayInputStream in; DIMERecord record; out = new ByteArrayOutputStream(); out.write( 0x08 ); // mb, me & cf clear. out.write( 0x00 ); // // no type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 out.write( new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF } ); // data length: LARGE in = new ByteArrayInputStream(out.toByteArray()); try { record = DIMERecord.createFromStream(in); fail("expected exception"); } catch(IOException expected) { assertEquals("data too big.", expected.getMessage()); } // Test boundary cases. out = new ByteArrayOutputStream(); out.write( 0x08 ); // mb, me & cf clear. out.write( 0x00 ); // // no type + reserved out.write( new byte[] { 0, 0 } ); // option length: 0 out.write( new byte[] { 0, 0 } ); // id length: 0 out.write( new byte[] { 0, 0 } ); // type length: 0 // one over Integer.MAX_VALUE (in big endian format) out.write( new byte[] { (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00 } ); in = new ByteArrayInputStream(out.toByteArray()); try { record = DIMERecord.createFromStream(in); fail("expected exception"); } catch(IOException expected) { assertEquals("data too big.", expected.getMessage()); } // can't really test Integer.MAX_VALUE 'cause it's too big to // store. } }