/*
* Copyright (C) 2011 Google Inc.
*
* Licensed 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.
*/
package org.ros.internal.node;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.ros.Assert.assertGraphNameEquals;
import com.google.common.collect.Lists;
import com.google.common.net.InetAddresses;
import org.junit.Test;
import org.ros.RosCore;
import org.ros.RosTest;
import org.ros.concurrent.Holder;
import org.ros.internal.node.client.SlaveClient;
import org.ros.internal.node.response.Response;
import org.ros.internal.node.server.master.MasterServer;
import org.ros.internal.transport.ProtocolDescription;
import org.ros.internal.transport.ProtocolNames;
import org.ros.namespace.GraphName;
import org.ros.namespace.NameResolver;
import org.ros.node.AbstractNodeMain;
import org.ros.node.ConnectedNode;
import org.ros.node.NodeConfiguration;
import org.ros.node.NodeMain;
import org.ros.node.topic.CountDownPublisherListener;
import org.ros.node.topic.CountDownSubscriberListener;
import org.ros.node.topic.Publisher;
import org.ros.node.topic.Subscriber;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Tests for the {@link DefaultNode}.
*
* @author kwc@willowgarage.com (Ken Conley)
* @author damonkohler@google.com (Damon Kohler)
*/
public class DefaultNodeTest extends RosTest {
void checkHostName(String hostName) {
assertTrue(!hostName.equals("0.0.0.0"));
assertTrue(!hostName.equals("0:0:0:0:0:0:0:0"));
}
private void checkNodeAddress(final String host) throws InterruptedException {
System.out.println(rosCore.getUri());
final Holder<InetSocketAddress> holder = Holder.newEmpty();
NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(host, rosCore.getUri());
nodeMainExecutor.execute(new AbstractNodeMain() {
@Override
public GraphName getDefaultNodeName() {
return GraphName.of("node");
}
@Override
public void onStart(ConnectedNode connectedNode) {
holder.set(((DefaultNode) connectedNode).getAddress());
}
}, nodeConfiguration);
assertTrue(holder.await(1, TimeUnit.SECONDS));
assertTrue(holder.get().getPort() > 0);
assertEquals(holder.get().getHostName(), host);
}
@Test
public void testCreatePublic() throws Exception {
String host = InetAddress.getLocalHost().getCanonicalHostName();
assertFalse(InetAddresses.isInetAddress(host));
checkNodeAddress(host);
}
@Test
public void testCreatePublicWithIpv4() throws InterruptedException {
String host = "1.2.3.4";
checkNodeAddress(host);
}
@Test
public void testCreatePublicWithIpv6() throws InterruptedException {
String host = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
checkNodeAddress(host);
}
@Test
public void testCreatePrivate() throws InterruptedException {
checkNodeAddress(nodeConfiguration.getTcpRosAdvertiseAddress().getHost());
}
@SuppressWarnings("unchecked")
@Test
public void testRegistration() throws InterruptedException {
final CountDownPublisherListener<std_msgs.String> publisherListener =
CountDownPublisherListener.newDefault();
final CountDownSubscriberListener<std_msgs.String> subscriberListener =
CountDownSubscriberListener.newDefault();
NodeMain nodeMain = new AbstractNodeMain() {
@Override
public GraphName getDefaultNodeName() {
return GraphName.of("node");
}
@Override
public void onStart(ConnectedNode connectedNode) {
Publisher<std_msgs.String> publisher =
connectedNode.newPublisher("foo", std_msgs.String._TYPE);
publisher.addListener(publisherListener);
Subscriber<std_msgs.String> subscriber =
connectedNode.newSubscriber("foo", std_msgs.String._TYPE);
subscriber.addSubscriberListener(subscriberListener);
}
};
nodeMainExecutor.execute(nodeMain, nodeConfiguration);
assertTrue(publisherListener.awaitMasterRegistrationSuccess(1, TimeUnit.SECONDS));
assertTrue(subscriberListener.awaitMasterRegistrationSuccess(1, TimeUnit.SECONDS));
// There are now two registered publishers /rosout and /foo.
List<Object> systemState = rosCore.getMasterServer().getSystemState();
assertEquals(2, ((List<Object>) systemState.get(MasterServer.SYSTEM_STATE_PUBLISHERS)).size());
assertEquals(1, ((List<Object>) systemState.get(MasterServer.SYSTEM_STATE_SUBSCRIBERS)).size());
nodeMainExecutor.shutdownNodeMain(nodeMain);
assertTrue(publisherListener.awaitShutdown(1, TimeUnit.SECONDS));
assertTrue(subscriberListener.awaitShutdown(1, TimeUnit.SECONDS));
systemState = rosCore.getMasterServer().getSystemState();
assertEquals(0, ((List<Object>) systemState.get(MasterServer.SYSTEM_STATE_PUBLISHERS)).size());
assertEquals(0, ((List<Object>) systemState.get(MasterServer.SYSTEM_STATE_SUBSCRIBERS)).size());
}
@Test
public void testResolveName() throws InterruptedException {
final Holder<ConnectedNode> holder = Holder.newEmpty();
nodeConfiguration.setParentResolver(NameResolver.newFromNamespace("/ns1"));
nodeMainExecutor.execute(new AbstractNodeMain() {
@Override
public GraphName getDefaultNodeName() {
return GraphName.of("test_resolver");
}
@Override
public void onStart(ConnectedNode connectedNode) {
holder.set(connectedNode);
}
}, nodeConfiguration);
assertTrue(holder.await(1, TimeUnit.SECONDS));
ConnectedNode connectedNode = holder.get();
assertGraphNameEquals("/foo", connectedNode.resolveName("/foo"));
assertGraphNameEquals("/ns1/foo", connectedNode.resolveName("foo"));
assertGraphNameEquals("/ns1/test_resolver/foo", connectedNode.resolveName("~foo"));
Publisher<std_msgs.Int64> pub = connectedNode.newPublisher("pub", std_msgs.Int64._TYPE);
assertGraphNameEquals("/ns1/pub", pub.getTopicName());
pub = connectedNode.newPublisher("/pub", std_msgs.Int64._TYPE);
assertGraphNameEquals("/pub", pub.getTopicName());
pub = connectedNode.newPublisher("~pub", std_msgs.Int64._TYPE);
assertGraphNameEquals("/ns1/test_resolver/pub", pub.getTopicName());
Subscriber<std_msgs.Int64> sub = connectedNode.newSubscriber("sub", std_msgs.Int64._TYPE);
assertGraphNameEquals("/ns1/sub", sub.getTopicName());
sub = connectedNode.newSubscriber("/sub", std_msgs.Int64._TYPE);
assertGraphNameEquals("/sub", sub.getTopicName());
sub = connectedNode.newSubscriber("~sub", std_msgs.Int64._TYPE);
assertGraphNameEquals("/ns1/test_resolver/sub", sub.getTopicName());
}
@Test
public void testPublicAddresses() throws InterruptedException {
RosCore rosCore = RosCore.newPublic(getExecutorService());
rosCore.start();
assertTrue(rosCore.awaitStart(1, TimeUnit.SECONDS));
URI masterUri = rosCore.getUri();
checkHostName(masterUri.getHost());
final Holder<ConnectedNode> holder = Holder.newEmpty();
NodeConfiguration nodeConfiguration =
NodeConfiguration.newPublic(masterUri.getHost(), masterUri);
nodeMainExecutor.execute(new AbstractNodeMain() {
@Override
public GraphName getDefaultNodeName() {
return GraphName.of("test_addresses");
}
@Override
public void onStart(ConnectedNode connectedNode) {
holder.set(connectedNode);
};
}, nodeConfiguration);
assertTrue(holder.await(1, TimeUnit.SECONDS));
ConnectedNode connectedNode = holder.get();
URI nodeUri = connectedNode.getUri();
assertTrue(nodeUri.getPort() > 0);
checkHostName(nodeUri.getHost());
CountDownPublisherListener<std_msgs.Int64> publisherListener =
CountDownPublisherListener.newDefault();
Publisher<std_msgs.Int64> publisher =
connectedNode.newPublisher("test_addresses_pub", std_msgs.Int64._TYPE);
publisher.addListener(publisherListener);
assertTrue(publisherListener.awaitMasterRegistrationSuccess(1, TimeUnit.SECONDS));
// Check the TCPROS server address via the XML-RPC API.
SlaveClient slaveClient = new SlaveClient(GraphName.of("test_addresses"), nodeUri);
Response<ProtocolDescription> response =
slaveClient.requestTopic(GraphName.of("test_addresses_pub"),
Lists.newArrayList(ProtocolNames.TCPROS));
ProtocolDescription result = response.getResult();
InetSocketAddress tcpRosAddress = result.getAdverstiseAddress().toInetSocketAddress();
checkHostName(tcpRosAddress.getHostName());
}
}