/*
* 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.node.service;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import interactivespaces.testing.sizes.TestSizeLarge;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.ros.RosTest;
import org.ros.exception.DuplicateServiceException;
import org.ros.exception.RemoteException;
import org.ros.exception.RosRuntimeException;
import org.ros.exception.ServiceException;
import org.ros.exception.ServiceNotFoundException;
import org.ros.namespace.GraphName;
import org.ros.node.AbstractNodeMain;
import org.ros.node.ConnectedNode;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class ServiceIntegrationTest extends RosTest {
private static final String SERVICE_NAME = "/add_two_ints";
@Category(TestSizeLarge.class)
@Test
public void testPersistentServiceConnection() throws Exception {
final CountDownServiceServerListener<test_ros.AddTwoIntsRequest, test_ros.AddTwoIntsResponse> countDownServiceServerListener =
CountDownServiceServerListener.newDefault();
nodeMainExecutor.execute(new AbstractNodeMain() {
@Override
public GraphName getDefaultNodeName() {
return GraphName.of("server");
}
@Override
public void onStart(final ConnectedNode connectedNode) {
ServiceServer<test_ros.AddTwoIntsRequest, test_ros.AddTwoIntsResponse> serviceServer =
connectedNode
.newServiceServer(
SERVICE_NAME,
test_ros.AddTwoInts._TYPE,
new ServiceResponseBuilder<test_ros.AddTwoIntsRequest, test_ros.AddTwoIntsResponse>() {
@Override
public void build(test_ros.AddTwoIntsRequest request,
test_ros.AddTwoIntsResponse response) {
response.setSum(request.getA() + request.getB());
}
});
try {
connectedNode.newServiceServer(SERVICE_NAME, test_ros.AddTwoInts._TYPE, null);
fail();
} catch (DuplicateServiceException e) {
// Only one ServiceServer with a given name can be created.
}
serviceServer.addListener(countDownServiceServerListener);
}
}, nodeConfiguration);
assertTrue(countDownServiceServerListener.awaitMasterRegistrationSuccess(1, TimeUnit.SECONDS));
final CountDownLatch latch = new CountDownLatch(2);
nodeMainExecutor.execute(new AbstractNodeMain() {
@Override
public GraphName getDefaultNodeName() {
return GraphName.of("client");
}
@Override
public void onStart(ConnectedNode connectedNode) {
ServiceClient<test_ros.AddTwoIntsRequest, test_ros.AddTwoIntsResponse> serviceClient;
try {
serviceClient = connectedNode.newServiceClient(SERVICE_NAME, test_ros.AddTwoInts._TYPE);
// Test that requesting another client for the same service returns
// the same instance.
ServiceClient<?, ?> duplicate =
connectedNode.newServiceClient(SERVICE_NAME, test_ros.AddTwoInts._TYPE);
assertEquals(serviceClient, duplicate);
} catch (ServiceNotFoundException e) {
throw new RosRuntimeException(e);
}
test_ros.AddTwoIntsRequest request = serviceClient.newMessage();
request.setA(2);
request.setB(2);
serviceClient.call(request, new ServiceResponseListener<test_ros.AddTwoIntsResponse>() {
@Override
public void onSuccess(test_ros.AddTwoIntsResponse response) {
assertEquals(response.getSum(), 4);
latch.countDown();
}
@Override
public void onFailure(RemoteException e) {
throw new RuntimeException(e);
}
});
// Regression test for issue 122.
request.setA(3);
request.setB(3);
serviceClient.call(request, new ServiceResponseListener<test_ros.AddTwoIntsResponse>() {
@Override
public void onSuccess(test_ros.AddTwoIntsResponse response) {
assertEquals(response.getSum(), 6);
latch.countDown();
}
@Override
public void onFailure(RemoteException e) {
throw new RuntimeException(e);
}
});
}
}, nodeConfiguration);
assertTrue(latch.await(1, TimeUnit.SECONDS));
}
@Test
public void testRequestFailure() throws Exception {
final String errorMessage = "Error!";
final CountDownServiceServerListener<test_ros.AddTwoIntsRequest, test_ros.AddTwoIntsResponse> countDownServiceServerListener =
CountDownServiceServerListener.newDefault();
nodeMainExecutor.execute(new AbstractNodeMain() {
@Override
public GraphName getDefaultNodeName() {
return GraphName.of("server");
}
@Override
public void onStart(ConnectedNode connectedNode) {
ServiceServer<test_ros.AddTwoIntsRequest, test_ros.AddTwoIntsResponse> serviceServer =
connectedNode
.newServiceServer(
SERVICE_NAME,
test_ros.AddTwoInts._TYPE,
new ServiceResponseBuilder<test_ros.AddTwoIntsRequest, test_ros.AddTwoIntsResponse>() {
@Override
public void build(test_ros.AddTwoIntsRequest request,
test_ros.AddTwoIntsResponse response) throws ServiceException {
throw new ServiceException(errorMessage);
}
});
serviceServer.addListener(countDownServiceServerListener);
}
}, nodeConfiguration);
assertTrue(countDownServiceServerListener.awaitMasterRegistrationSuccess(1, TimeUnit.SECONDS));
final CountDownLatch latch = new CountDownLatch(1);
nodeMainExecutor.execute(new AbstractNodeMain() {
@Override
public GraphName getDefaultNodeName() {
return GraphName.of("client");
}
@Override
public void onStart(ConnectedNode connectedNode) {
ServiceClient<test_ros.AddTwoIntsRequest, test_ros.AddTwoIntsResponse> serviceClient;
try {
serviceClient = connectedNode.newServiceClient(SERVICE_NAME, test_ros.AddTwoInts._TYPE);
} catch (ServiceNotFoundException e) {
throw new RosRuntimeException(e);
}
test_ros.AddTwoIntsRequest request = serviceClient.newMessage();
serviceClient.call(request, new ServiceResponseListener<test_ros.AddTwoIntsResponse>() {
@Override
public void onSuccess(test_ros.AddTwoIntsResponse message) {
fail();
}
@Override
public void onFailure(RemoteException e) {
assertEquals(e.getMessage(), errorMessage);
latch.countDown();
}
});
}
}, nodeConfiguration);
assertTrue(latch.await(1, TimeUnit.SECONDS));
}
}