hudson.remoting.BinarySafeStreamTest.java Source code

Java tutorial

Introduction

Here is the source code for hudson.remoting.BinarySafeStreamTest.java

Source

/*
 * The MIT License
 * 
 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package hudson.remoting;

import junit.framework.TestCase;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;

import org.apache.commons.codec.binary.Base64;

/**
 * @author Kohsuke Kawaguchi
 */
public class BinarySafeStreamTest extends TestCase {
    public void test1() throws IOException {
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        OutputStream o = BinarySafeStream.wrap(buf);
        byte[] data = "Sending some data to make sure it's encoded".getBytes("UTF-8");

        o.write(data);
        o.close();

        InputStream in = BinarySafeStream.wrap(new ByteArrayInputStream(buf.toByteArray()));
        for (byte b : data) {
            int ch = in.read();
            assertEquals(b, ch);
        }
        assertEquals(-1, in.read());
    }

    public void testSingleWrite() throws IOException {
        byte[] ds = getDataSet(65536);
        String master = new String(Base64.encodeBase64(ds));

        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        OutputStream o = BinarySafeStream.wrap(buf);
        o.write(ds, 0, ds.length);
        o.close();
        assertEquals(buf.toString(), master);
    }

    public void testChunkedWrites() throws IOException {
        byte[] ds = getDataSet(65536);
        String master = new String(Base64.encodeBase64(ds));

        Random r = new Random(0);
        for (int i = 0; i < 16; i++) {
            ByteArrayOutputStream buf = new ByteArrayOutputStream();
            OutputStream o = BinarySafeStream.wrap(buf);
            randomCopy(r, new ByteArrayInputStream(ds), o, false);
            assertEquals(buf.toString(), master);
        }
    }

    public void testRoundtripNoFlush() throws IOException {
        _testRoundtrip(false);
    }

    public void testRoundtripFlush() throws IOException {
        _testRoundtrip(true);
    }

    private void _testRoundtrip(boolean flush) throws IOException {
        byte[] dataSet = getDataSet(65536);
        Random r = new Random(0);

        for (int i = 0; i < 16; i++) {
            if (dump)
                System.out.println("test started");
            ByteArrayOutputStream buf = new ByteArrayOutputStream();
            randomCopy(r, new ByteArrayInputStream(dataSet), BinarySafeStream.wrap(buf), flush);

            decodeByMaster(buf.toString(), dataSet);

            if (dump)
                System.out.println("------");

            ByteArrayOutputStream dst = new ByteArrayOutputStream();
            randomCopy(r, BinarySafeStream.wrap(new ByteArrayInputStream(buf.toByteArray())), dst, flush);

            byte[] result = dst.toByteArray();
            if (!Arrays.equals(dataSet, result)) {
                String msg = print(result, 0, result.length);
                for (int j = 0; j < result.length; j++)
                    assertEquals("offset " + j + " at " + msg, result[j], dataSet[j]);
                fail(msg);
            }

            if (dump)
                System.out.println("------");
        }
    }

    /**
     * Decodes by the JDK base64 code and make sure the encoded string looks correct.
     */
    private void decodeByMaster(String s, byte[] dataSet) throws IOException {
        int ptr = 0;

        for (int i = 0; i < s.length(); i += 4) {
            byte[] buf = Base64.decodeBase64(s.substring(i, i + 4).getBytes());
            for (int j = 0; j < buf.length; j++) {
                if (buf[j] != dataSet[ptr])
                    fail("encoding error at offset " + ptr);
                ptr++;
            }
        }
    }

    /**
     * Creates a test data set.
     */
    private byte[] getDataSet(int len) {
        byte[] dataSet = new byte[len];
        for (int i = 0; i < dataSet.length; i++)
            dataSet[i] = (byte) i;
        return dataSet;
    }

    private void randomCopy(Random r, InputStream in, OutputStream out, boolean randomFlash) throws IOException {
        try {
            while (true) {
                switch (r.nextInt(3)) {
                case 0:
                    int ch = in.read();
                    if (dump)
                        System.out.println("read1(" + ch + ')');
                    assertTrue(255 >= ch && ch >= -1); // make sure the range is [-1,255]
                    if (ch == -1)
                        return;
                    out.write(ch);
                    break;

                case 1:
                    int start = r.nextInt(16);
                    int chunk = r.nextInt(16);
                    int trail = r.nextInt(16);

                    byte[] tmp = new byte[start + chunk + trail];
                    int len = in.read(tmp, start, chunk);
                    if (dump)
                        System.out.println(
                                "read2(" + print(tmp, start, len) + ",len=" + len + ",chunk=" + chunk + ")");
                    if (len == -1)
                        return;

                    // check extra data corruption
                    for (int i = 0; i < start; i++)
                        assertEquals(tmp[i], 0);
                    for (int i = 0; i < trail; i++)
                        assertEquals(tmp[start + chunk + i], 0);

                    out.write(tmp, start, len);
                    break;

                case 2:
                    len = r.nextInt(16);
                    tmp = new byte[len];
                    len = in.read(tmp);
                    if (dump)
                        System.out.println("read3(" + print(tmp, 0, len) + ",len=" + len + ')');
                    if (len == -1)
                        return;

                    // obtain the array of the exact size
                    byte[] n = new byte[len];
                    System.arraycopy(tmp, 0, n, 0, len);
                    out.write(n);
                }
                if (randomFlash && r.nextInt(8) == 0)
                    out.flush();
            }
        } finally {
            out.close();
        }
    }

    private static String print(byte[] buf, int start, int len) {
        StringBuilder out = new StringBuilder();
        out.append('{');
        for (int i = 0; i < len; i++) {
            byte b = buf[i + start];
            if (i > 0)
                out.append(',');
            out.append(((int) b) & 0xFF);
        }
        return out.append('}').toString();
    }

    private static final boolean dump = false;
}