import java.io.IOException;
import java.io.DataInput;
import java.lang.IllegalArgumentException;
import java.lang.Thread;
import java.util.Arrays;
import java.util.Random;
import lcm.lcm.LCM;
import lcm.lcm.LCMSubscriber;
import lcm.lcm.LCMDataInputStream;
import lcmtest.primitives_t;
import lcmtest.primitives_list_t;
import lcmtest.node_t;
import lcmtest.multidim_array_t;
import lcmtest2.cross_package_t;
import lcmtest2.another_type_t;
public class LcmTestClient implements LCMSubscriber {
private boolean test_success_ = false;
private boolean test_failed_ = false;
private boolean any_test_failed_ = false;
private LCM lcm_;
private byte echo_data_[];
private int echo_response_count_ = 0;
private Random random_ = new Random();
private long abort_time_ = 0;
LcmTestClient() {}
static private <T> void checkField(T actual, T expected, String field) {
if (!actual.equals(expected)) {
throw new IllegalArgumentException(
String.format("%s : Expected %s, got %s",
field, String.valueOf(expected), String.valueOf(actual)));
}
}
private void setupSubscribers() throws IOException {
lcm_ = new LCM();
lcm_.subscribe("TEST_ECHO_REPLY", this);
}
public void messageReceived(LCM lcm, String channel,
LCMDataInputStream ins) {
if (channel.equals("TEST_ECHO_REPLY")) {
handleEchoReply(ins);
}
}
private void handleEchoReply(LCMDataInputStream ins) {
try {
int len = ins.available();
byte data[] = new byte[len];
ins.readFully(data);
if (!Arrays.equals(data, echo_data_)) {
test_failed_ = true;
return;
}
echo_response_count_++;
if (echo_response_count_ >= 100) {
test_success_ = true;
} else {
sendNextEchoMessage();
}
} catch (IOException ex) {
System.err.println("Failed to handle echo reply");
}
}
private void sendNextEchoMessage() throws IOException {
echo_data_ = new byte[random_.nextInt(9990) + 10];
random_.nextBytes(echo_data_);
lcm_.publish("TEST_ECHO", echo_data_, 0, echo_data_.length);
}
private boolean waitForSuccessOrAbort() {
while(true) {
synchronized(this) {
if (test_success_) {
return true;
}
}
try {
Thread.sleep(100);
} catch (java.lang.InterruptedException ex) {
return false;
}
if (System.currentTimeMillis() >= abort_time_) {
System.err.printf("Timed out");
test_failed_ = true;
return false;
}
}
}
private boolean doEchoTest() throws IOException {
echo_data_ = new byte[10000];
echo_response_count_ = 0;
sendNextEchoMessage();
abort_time_ = System.currentTimeMillis() + 500;
return waitForSuccessOrAbort();
}
private interface MessageMakerChecker<MsgType> {
public MsgType makeMessage(int iteration);
public boolean checkReply(MsgType msg, int iteration);
}
private class MessageTester<MsgType extends lcm.lcm.LCMEncodable> implements LCMSubscriber {
private MessageMakerChecker<MsgType> makerChecker_;
private String name_;
private int iteration_ = 0;
private int numIterations_;
private LCM lcm_;
private long abortTime_;
private boolean success_ = false;
private boolean done_ = false;
private Class type_;
MessageTester(LCM lcm, String name, MessageMakerChecker<MsgType> makerChecker,
int numIterations) {
lcm_ = lcm;
makerChecker_ = makerChecker;
name_ = name;
numIterations_ = numIterations;
}
public void messageReceived(LCM lcm, String channel, LCMDataInputStream ins) {
MsgType msg;
try {
msg = (MsgType)type_.getConstructor(DataInput.class).newInstance(ins);
} catch (java.lang.Exception ex) {
done_ = true;
return;
}
if (!makerChecker_.checkReply(msg, iteration_ + 1)) {
success_ = false;
done_ = true;
return;
}
abortTime_ = System.currentTimeMillis() + 500;
iteration_++;
if (iteration_ >= numIterations_) {
success_ = true;
done_ = true;
return;
}
sendMessage();
}
private void sendMessage() {
MsgType msg = makerChecker_.makeMessage(iteration_);
lcm_.publish("test_" + name_, msg);
}
public boolean run() {
lcm_.subscribe("test_" + name_ + "_reply", this);
abortTime_ = System.currentTimeMillis() + 500;
MsgType msg = makerChecker_.makeMessage(iteration_);
lcm_.publish("test_" + name_, msg);
type_ = msg.getClass();
while(true) {
synchronized(this) {
if (done_) {
break;
}
}
try {
Thread.sleep(10);
} catch (java.lang.InterruptedException ex) {
break;
}
if (System.currentTimeMillis() >= abortTime_) {
System.err.printf("Timed out on iteration %d\n", iteration_);
break;
}
}
lcm_.unsubscribe("test_" + name_ + "_reply", this);
if (success_) {
System.out.println(" OK - " + name_);
} else {
System.out.printf(" FAIL - %s - iteration %d\n", name_, iteration_);
}
return success_;
}
}
private class PrimitivesMakerChecker implements MessageMakerChecker<primitives_t> {
public primitives_t makeMessage(int iteration) {
primitives_t msg = new primitives_t();
int n = iteration;
msg.i8 = (byte)(n % 100);
msg.i16 = (short)(n * 10);
msg.i64 = n * 10000;
msg.position[0] = n;
msg.position[1] = n;
msg.position[2] = n;
msg.orientation[0] = n;
msg.orientation[1] = n;
msg.orientation[2] = n;
msg.orientation[3] = n;
msg.num_ranges= n;
msg.ranges = new short[n];
msg.name = String.valueOf(n);
msg.enabled = n % 2 == 1;
return msg;
}
public boolean checkReply(primitives_t reply, int iteration) {
try {
int n = iteration;
checkField(reply.i8, (byte)(n % 100), "i8");
checkField(reply.i16, (short)(n * 10), "i16");
checkField((long)reply.i64, (long)(n * 10000), "i64");
checkField(reply.position[0], (float)n, "position[0]");
checkField(reply.position[1], (float)n, "position[1]");
checkField(reply.position[2], (float)n, "position[2]");
checkField(reply.orientation[0], (double)n, "orientation[0]");
checkField(reply.orientation[1], (double)n, "orientation[1]");
checkField(reply.orientation[2], (double)n, "orientation[2]");
checkField(reply.orientation[3], (double)n, "orientation[3]");
checkField(reply.num_ranges, n, "num_ranges");
for (int i = 0; i < reply.num_ranges; i++) {
checkField(reply.ranges[i], (short)i, String.format("ranges[%d]", i));
}
checkField(reply.name, String.valueOf(n), "name");
checkField(reply.enabled, n % 2 == 1, "enabled");
} catch (IllegalArgumentException ex) {
ex.printStackTrace(System.err);
return false;
}
return true;
}
}
private class PrimitivesListMakerChecker implements MessageMakerChecker<primitives_list_t> {
public primitives_list_t makeMessage(int iteration) {
primitives_list_t msg = new primitives_list_t();
msg.num_items = iteration;
msg.items = new primitives_t[msg.num_items];
for (int n = 0; n < msg.num_items; n++) {
primitives_t submsg = new primitives_t();
msg.items[n] = submsg;
submsg.i8 = (byte)(-(n % 100));
submsg.i16 = (short)(-n * 100);
submsg.i64 = (long)(-n * 10000);
submsg.position[0] = -n;
submsg.position[1] = -n;
submsg.position[2] = -n;
submsg.orientation[0] = -n;
submsg.orientation[1] = -n;
submsg.orientation[2] = -n;
submsg.orientation[3] = -n;
submsg.num_ranges = n;
submsg.ranges = new short[n];
for (int j = 0; j < n; j++) {
submsg.ranges[j] = (short)-j;
}
submsg.name = String.format("%d", -n);
submsg.enabled = ((n + 1) % 2) == 1;
}
return msg;
}
public boolean checkReply(primitives_list_t reply, int iteration) {
try {
checkField(reply.num_items, iteration, "num_items");
for (int n = 0; n < iteration; n++) {
primitives_t submsg = reply.items[n];
String errPrefix = String.format(".items[%d].", n);
checkField(submsg.i8, (byte)(-(n % 100)), errPrefix + "i8");
checkField(submsg.i16, (short)(-n * 10), errPrefix + "i8");
checkField(submsg.i64, (long)(-n * 10000), errPrefix + "i8");
checkField(submsg.position[0], (float)-n, errPrefix + "position[0]");
checkField(submsg.position[1], (float)-n, errPrefix + "position[1]");
checkField(submsg.position[2], (float)-n, errPrefix + "position[2]");
checkField(submsg.orientation[0], (double)-n, errPrefix + "orientation[0]");
checkField(submsg.orientation[1], (double)-n, errPrefix + "orientation[1]");
checkField(submsg.orientation[2], (double)-n, errPrefix + "orientation[2]");
checkField(submsg.orientation[3], (double)-n, errPrefix + "orientation[3]");
checkField(submsg.num_ranges, n, errPrefix + "num_ranges");
for (int i = 0; i < submsg.num_ranges; i++) {
checkField(submsg.ranges[i], (short)-i, errPrefix + String.format("ranges[%d]", i));
}
checkField(submsg.name, String.valueOf(-n), errPrefix + "name");
checkField(submsg.enabled, ((n + 1) % 2) == 1, errPrefix + "enabled");
}
} catch (IllegalArgumentException ex) {
ex.printStackTrace(System.err);
return false;
}
return true;
}
}
private class NodeMakerChecker implements MessageMakerChecker<node_t> {
public node_t makeMessage(int iteration) {
node_t msg = new node_t();
msg.num_children = iteration;
if (msg.num_children == 0) {
return msg;
}
msg.children = new node_t[msg.num_children];
for (int i = 0; i < msg.num_children; i++) {
msg.children[i] = makeMessage(iteration - 1);
}
return msg;
}
public boolean checkReply(node_t reply, int iteration) {
try {
checkField(reply.num_children, iteration, "num_children");
for (int i = 0; i < reply.num_children; i++) {
if (!checkReply(reply.children[i], iteration -1)) {
return false;
}
}
} catch (IllegalArgumentException ex) {
ex.printStackTrace(System.err);
return false;
}
return true;
}
}
private class MultidimArrayMakerChecker implements MessageMakerChecker<multidim_array_t> {
public multidim_array_t makeMessage(int iteration) {
multidim_array_t msg = new multidim_array_t();
msg.size_a = iteration;
msg.size_b = iteration;
msg.size_c = iteration;
msg.data = new int[msg.size_a][msg.size_b][msg.size_c];
int n = 0;
for (int a_iter = 0; a_iter < msg.size_a; a_iter++) {
for (int b_iter = 0; b_iter < msg.size_b; b_iter++) {
for (int c_iter = 0; c_iter < msg.size_c; c_iter++) {
msg.data[a_iter][b_iter][c_iter] = n++;
}
}
}
n = 0;
msg.strarray = new String[2][msg.size_c];
for (int i = 0; i < 2; i++) {
for (int c_iter = 0; c_iter < msg.size_c; c_iter++) {
msg.strarray[i][c_iter] = String.valueOf(n);
n++;
}
}
return msg;
}
public boolean checkReply(multidim_array_t reply, int iteration) {
try {
checkField(reply.size_a, iteration, "size_a");
checkField(reply.size_b, iteration, "size_b");
checkField(reply.size_c, iteration, "size_c");
int n = 0;
for (int a_iter = 0; a_iter < reply.size_a; a_iter++) {
for (int b_iter = 0; b_iter < reply.size_b; b_iter++) {
for (int c_iter = 0; c_iter < reply.size_c; c_iter++) {
checkField(reply.data[a_iter][b_iter][c_iter], n,
String.format("data[%d][%d][%d]", a_iter, b_iter, c_iter));
n++;
}
}
}
n = 0;
for (int i = 0; i < 2; i++) {
for (int c_iter = 0; c_iter < reply.size_c; c_iter++) {
checkField(reply.strarray[i][c_iter],
String.valueOf(n),
String.format("strarray[%d][%d]", i, c_iter));
n++;
}
}
} catch (IllegalArgumentException ex) {
ex.printStackTrace(System.err);
return false;
}
return true;
}
}
private class CrossPackageMakerChecker implements MessageMakerChecker<cross_package_t> {
private PrimitivesMakerChecker primitivesMakerChecker_ =
new PrimitivesMakerChecker();
public cross_package_t makeMessage(int iteration) {
cross_package_t msg = new cross_package_t();
msg.primitives = primitivesMakerChecker_.makeMessage(iteration);
msg.another = new another_type_t();
msg.another.val = iteration;
return msg;
}
public boolean checkReply(cross_package_t reply, int iteration) {
try {
if (!primitivesMakerChecker_.checkReply(reply.primitives, iteration)) {
return false;
}
checkField(reply.another.val, iteration, "another.val");
} catch (IllegalArgumentException ex) {
ex.printStackTrace(System.err);
return false;
}
return true;
}
}
public int runTests() {
try {
setupSubscribers();
boolean echo_test_success = doEchoTest();
if (echo_test_success) {
System.out.println(" OK - echo test");
} else {
System.out.println(" FAIL - echo test");
return 1;
}
MessageTester<primitives_t> primitives_tester = new MessageTester<primitives_t>(
lcm_, "lcmtest_primitives_t", new PrimitivesMakerChecker(), 1000);
if (!primitives_tester.run()) {
return 1;
}
MessageTester<primitives_list_t> primitives_list_tester = new MessageTester<primitives_list_t>(
lcm_, "lcmtest_primitives_list_t", new PrimitivesListMakerChecker(), 100);
if (!primitives_list_tester.run()) {
return 1;
}
MessageTester<node_t> node_tester = new MessageTester<node_t>(
lcm_, "lcmtest_node_t", new NodeMakerChecker(), 7);
if (!node_tester.run()) {
return 1;
}
MessageTester<multidim_array_t> multidim_array_tester = new MessageTester<multidim_array_t>(
lcm_, "lcmtest_multidim_array_t", new MultidimArrayMakerChecker(), 5);
if (!multidim_array_tester.run()) {
return 1;
}
MessageTester<cross_package_t> cross_package_tester = new MessageTester<cross_package_t>(
lcm_, "lcmtest2_cross_package_t", new CrossPackageMakerChecker(), 100);
if (!cross_package_tester.run()) {
return 1;
}
} catch(IOException ex) {
System.err.println("IOException");
return 1;
}
return 0;
}
public static void main(String[] args) {
LcmTestClient client = new LcmTestClient();
System.exit(client.runTests());
}
}