package com.limegroup.gnutella.util; import java.io.IOException; import junit.framework.Test; import com.limegroup.gnutella.ByteOrder; /** * Tests COBSUtil */ public class COBSUtilTest extends com.limegroup.gnutella.util.BaseTestCase { public COBSUtilTest(String name) { super(name); } public static Test suite() { return buildTestSuite(COBSUtilTest.class); } public void testBoundCase() throws IOException { byte[] bytes = new byte[254]; for (int i = 0; i < bytes.length; i++) bytes[i] = (byte) 7; byte[] after = COBSUtil.cobsEncode(bytes); assertTrue("after[0] is " + after[0], after[0] == ((byte)0xFF)); assertEquals(256, after.length); // 2 bytes of overhead for 254 bytes byte[] afterOptimized = new byte[255]; // some people leave off that last 0, we should react OK System.arraycopy(after, 0, afterOptimized, 0, afterOptimized.length); byte[] decoded = COBSUtil.cobsDecode(afterOptimized); assertEquals(254, decoded.length); for (int i = 0; i < bytes.length; i++) assertTrue(bytes[i] == decoded[i]); } public void testEncodeAndDecode() throws IOException { for (int num = 1; num < 260; num++) encodeAndDecode(num); } private void encodeAndDecode(int num) throws IOException { // test all 0s... debug("COBSUtilTest.encode(): num = " + num); byte[] bytes = new byte[num]; for (int i = 0; i < bytes.length; i++) bytes[i] = 0; byte[] after = COBSUtil.cobsEncode(bytes); assertEquals(bytes.length , (after.length-1)); for (int i = 0; i < after.length; i++) assertEquals(0x01, after[i]); byte[] decoded = COBSUtil.cobsDecode(after); for (int i = 0; i < bytes.length; i++) assertEquals(bytes[i], decoded[i]); // test all 1s.... for (int i = 0; i < bytes.length; i++) bytes[i] = 1; after = COBSUtil.cobsEncode(bytes); assertTrue("bytes.length = " + bytes.length + ", after.length + " + after.length + ", num = " + num, bytes.length == (after.length-((num / 254) + 1))); for (int i = 1; i < after.length; i++) if (i % 255 != 0) assertTrue(after[i] == 0x01); assertTrue("after[0] = " + after[0], (ByteOrder.ubyte2int(after[0]) == (num+1)) || (ByteOrder.ubyte2int(after[0]) == 255) ); decoded = COBSUtil.cobsDecode(after); for (int i = 0; i < bytes.length; i++) assertEquals("num = " + num + ", i = " + i, bytes[i], decoded[i]); // ---------------------------------- // build up 'induction' case for 0(1..). we can trust 'induction' due // to nature of the COBS algorithm... // test 0 and 1s, specifically 0(1)^(j-1)s.... for (int j = 2; (j < 255) && (num > 1); j++) { debug("COBSUtilTest.encode(): j = " + j); for (int i = 0; i < bytes.length; i++) if (i % j == 0) bytes[i] = 0; else bytes[i] = 1; after = COBSUtil.cobsEncode(bytes); assertEquals(bytes.length,(after.length-1)); for (int i = 0; i < after.length; i++) { debug("COBSUtilTest.encode(): i = " + i); if (i == 0) assertEquals(1,after[0]); else if ((i == 1) || ((((i-1) % j) == 0) && (num > i)) ) assertGreaterThan(1, ByteOrder.ubyte2int(after[i])); else assertEquals(1, after[i]); } decoded = COBSUtil.cobsDecode(after); for (int i = 0; i < bytes.length; i++) assertEquals(bytes[i], decoded[i]); } // ---------------------------------- // ---------------------------------- // build up 'induction' case for (1..)0. we can trust 'induction' due // to nature of the COBS algorithm... // test 1s and 0, specifically (1)^(j-1s)0.... for (int j = 2; j < 255; j++) { for (int i = 0; i < bytes.length; i++) if (i % j == 0) bytes[i] = 1; else bytes[i] = 0; after = COBSUtil.cobsEncode(bytes); assertEquals(bytes.length ,(after.length - 1)); for (int i = 0; i < bytes.length; i++) if ((i == 0) || (i % j == 0) ) assertGreaterThan(1, ByteOrder.ubyte2int(after[i])); else assertEquals(1, after[i]); decoded = COBSUtil.cobsDecode(after); for (int i = 0; i < bytes.length; i++) assertEquals(bytes[i] , decoded[i]); } // ---------------------------------- } private static final boolean debugOn = false; private static final void debug(String out) { if (debugOn) System.out.println(out); } public void testSymmetry() throws IOException { // a quick test for symmetry - but symmetry was actually tested above, // so no need for much testing... byte[] bytes = (new String("Sush Is Cool!")).getBytes(); byte[] after = COBSUtil.cobsDecode(COBSUtil.cobsEncode(bytes)); assertEquals(bytes.length , after.length); } public void testBadCOBSBlock() throws Exception { byte[] badBlock = new byte[10]; badBlock[0] = (byte) 11; for (int i = 1; i < badBlock.length; i++) badBlock[i] = (byte)1; try { byte[] badDecode = COBSUtil.cobsDecode(badBlock); assertTrue(false); } catch (IOException expected) {} badBlock = new byte[10]; badBlock[0] = (byte) 10; for (int i = 1; i < badBlock.length; i++) badBlock[i] = (byte)1; try { // should pass this time // badBlock is actually good ;) byte[] badDecode = COBSUtil.cobsDecode(badBlock); } catch (IOException unexpected) { assertTrue(false); } badBlock = new byte[4]; badBlock[0] = (byte) 2; badBlock[1] = (byte) 1; badBlock[2] = (byte) 1; badBlock[3] = (byte) 2; try { byte[] badDecode = COBSUtil.cobsDecode(badBlock); assertTrue(false); } catch (IOException expected) { } } public static void main(String argv[]) { junit.textui.TestRunner.run(suite()); } }