/* * Copyright (c) 2009, 2011, 2012 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.net4j.util.tests; import org.eclipse.net4j.util.io.ExtendedDataInput; import org.eclipse.net4j.util.io.ExtendedDataInputStream; import org.eclipse.net4j.util.io.ExtendedDataOutputStream; import org.eclipse.net4j.util.io.StringCompressor; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * @author Eike Stepper */ public class StringCompressorTest extends AbstractOMTest { private static long SLEEP_WRITER = 1; private static long SLEEP_READER = 0; private static final String[] strings = createStrings(50, 837456); private static final int[] indices = createIndices(100, 50, 9087346); private StringCompressor.Counting client; private StringCompressor.Counting server; public void testSingleStreamToServer() throws Exception { run(1, 0); } public void testSingleStreamToClient() throws Exception { run(0, 1); } public void testBidi1() throws Exception { run(1, 1); } public void testBidi10() throws Exception { run(10, 10); } public void testBidi1Plus10() throws Exception { run(1, 1); run(10, 10); } @Override protected void doSetUp() throws Exception { super.doSetUp(); client = new StringCompressor.Counting(true); server = new StringCompressor.Counting(false); } @Override protected void doTearDown() throws Exception { System.out.println("Strings read by client compressor: " + client.getStringsRead()); System.out.println("Strings read by server compressor: " + server.getStringsRead()); System.out.println("Strings written by client compressor: " + client.getStringsWritten()); System.out.println("Strings written by server compressor: " + server.getStringsWritten()); super.doTearDown(); } private void run(int toServer, int toClient) throws IOException, InterruptedException { CountDownLatch latch = new CountDownLatch(toServer + toClient); while (toServer > 0 || toClient > 0) { if (toServer > 0) { --toServer; new Stream(latch, client, server).start(); } if (toClient > 0) { --toClient; new Stream(latch, server, client).start(); } } latch.await(300, TimeUnit.SECONDS); } private static String[] createStrings(int count, long seed) { Random random = new Random(seed); String[] result = new String[count]; for (int i = 0; i < result.length; i++) { String str = ""; int length = next(random) % 13; for (int j = 0; j < length + 1; j++) { int val = next(random); str += Integer.toString(val, 36); } result[i] = str; } return result; } private static int[] createIndices(int count, int range, long seed) { Random random = new Random(seed); int[] result = new int[count]; for (int i = 0; i < result.length; i++) { result[i] = next(random) % range; } return result; } private static int next(Random random) { for (;;) { int val = random.nextInt(); if (val > 0) { return val; } } } /** * @author Eike Stepper */ public static class Stream extends Thread { private CountDownLatch latch; private Writer writer; private Reader reader; public Stream(CountDownLatch latch, StringCompressor writer, StringCompressor reader) throws IOException { this.latch = latch; this.writer = new Writer(writer); this.reader = new Reader(reader, this.writer); } @Override public void run() { try { reader.start(); writer.start(); reader.join(); writer.join(); latch.countDown(); } catch (Exception ex) { ex.printStackTrace(); } } } /** * @author Eike Stepper */ public static class Writer extends Thread { private StringCompressor compressor; private PipedOutputStream pipe; private Exception exception; public Writer(StringCompressor compressor) { this.compressor = compressor; pipe = new PipedOutputStream(); } public PipedOutputStream getPipe() { return pipe; } public Exception getException() { return exception; } @Override public void run() { try { ExtendedDataOutputStream out = new ExtendedDataOutputStream(pipe); for (int i = 0; i < indices.length; i++) { int index = indices[i]; msg(getName() + " --> " + i); compressor.write(out, strings[index]); if (SLEEP_WRITER > 0) { Thread.sleep(SLEEP_WRITER); } } } catch (Exception ex) { exception = ex; ex.printStackTrace(); } } } /** * @author Eike Stepper */ public static class Reader extends Thread { private StringCompressor compressor; private PipedInputStream pipe; private Exception exception; public Reader(StringCompressor compressor, Writer writer) throws IOException { this.compressor = compressor; pipe = new PipedInputStream(writer.getPipe()); } public Exception getException() { return exception; } @Override public void run() { try { ExtendedDataInput in = new ExtendedDataInputStream(pipe); for (int i = 0; i < indices.length; i++) { int index = indices[i]; msg(getName() + " --> " + i); String toBeRead = strings[index]; String read = compressor.read(in); assertEquals(toBeRead, read); if (SLEEP_READER > 0) { Thread.sleep(SLEEP_READER); } } } catch (Exception ex) { exception = ex; ex.printStackTrace(); } } } }