/**
* BlueCove - Java library for Bluetooth
* Copyright (C) 2006-2007 Vlad Skarzhevskyy
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @author vlads
* @version $Id$
*/
package net.sf.bluecove.tests;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.bluecove.tester.log.Logger;
import org.bluecove.tester.util.TimeUtils;
import junit.framework.Assert;
import net.sf.bluecove.CommunicationData;
import net.sf.bluecove.ConnectionHolderStream;
/**
* Test two directional Stream. Create Second Thread to Write to connection.
* Main Test thread will read data sent by connected party. Test is symmetrical
* in regards to client and server.
*
*/
public class TwoThreadsPerConnection {
private static final int DATA_SIZE = 8 * 1024;
private int arraySize;
private boolean synchronize;
private int iterations;
private int bytesTotal;
private int sentCount = 0;
private int receivedCount = 0;
private boolean stoped = false;
private class WriteTread extends Thread {
ConnectionHolderStream c;
boolean isRunning;
boolean sendFinishedSuccessfully = false;
public void run() {
try {
isRunning = true;
sendingData(c.os, c);
sendFinishedSuccessfully = true;
} catch (IOException e) {
Logger.error("Sending", e);
} finally {
isRunning = false;
}
}
}
WriteTread startSender(ConnectionHolderStream c) {
WriteTread t = new WriteTread();
t.c = c;
t.start();
return t;
}
void equalizeWrite() {
while ((!stoped) && (sentCount - receivedCount > 256)) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Assert.fail("interrupted");
}
}
}
void sendingData(OutputStream os, ConnectionHolderStream c) throws IOException {
long start = System.currentTimeMillis();
long reported = start;
int k = 0;
for (int i = 1; (!stoped) && i <= iterations; i++) {
if (arraySize == 1) {
os.write((byte) i);
if (i % 64 == 0) {
os.flush();
}
} else {
byte[] data = new byte[arraySize];
for (int j = 0; j < arraySize; j++, k++) {
data[j] = (byte) k;
}
os.write(data);
if (i % 2 == 0) {
os.flush();
}
}
sentCount += arraySize;
if ((i % 100 == 0) && (TimeUtils.since(reported) > 10000)) {
Logger.debug("sent " + sentCount + "; received " + receivedCount + " bytes in "
+ TimeUtils.secSince(start));
reported = System.currentTimeMillis();
}
if (synchronize) {
equalizeWrite();
}
c.active();
}
if (!stoped) {
Logger.debug("speed " + TimeUtils.bps(sentCount, start));
}
}
void readingData(InputStream is, ConnectionHolderStream c) throws IOException {
int k = 0;
for (int i = 1; i <= iterations; i++) {
try {
if (arraySize == 1) {
byte got = (byte) is.read();
Assert.assertEquals("sent " + sentCount + " bytes; read byte[" + i + "]", (byte) i, got);
receivedCount++;
} else {
byte[] data = new byte[arraySize];
int len = arraySize;
int read_off = 0;
while (len != 0) {
int rcvd = is.read(data, read_off, len);
if (rcvd == -1) {
throw new IOException("EOF not expected");
}
len -= rcvd;
read_off += rcvd;
}
for (int j = 0; j < arraySize; j++, k++) {
Assert.assertEquals("sent " + sentCount + " bytes; read byte[" + k + "]", (byte) k, data[j]);
}
c.active();
receivedCount += arraySize;
}
} catch (IOException e) {
Logger.debug("Received only " + receivedCount + " bytes");
throw e;
}
c.active();
}
}
public static void start(ConnectionHolderStream c, int arraySize, boolean synchronize) throws IOException {
TwoThreadsPerConnection worker = new TwoThreadsPerConnection();
worker.synchronize = synchronize;
worker.arraySize = arraySize;
if (arraySize == 1) {
worker.bytesTotal = DATA_SIZE;
worker.iterations = worker.bytesTotal;
} else {
worker.iterations = DATA_SIZE / arraySize;
worker.bytesTotal = worker.iterations * arraySize;
}
WriteTread sender = worker.startSender(c);
try {
worker.readingData(c.is, c);
try {
if (sender.isRunning) {
sender.join();
}
} catch (InterruptedException e) {
Assert.fail("interrupted");
}
} finally {
worker.stoped = true;
}
Assert.assertEquals("sentCount", worker.bytesTotal, worker.sentCount);
Assert.assertTrue("sendFinishedSuccessfully", sender.sendFinishedSuccessfully);
c.os.write(CommunicationData.aKnowndPositiveByte);
Assert.assertEquals("end conformation", CommunicationData.aKnowndPositiveByte, c.is.read());
}
}