common-clients/src/test/java/org/gcube/common/clients/AsyncDelegateTest.java

327 lines
7.3 KiB
Java
Raw Normal View History

package org.gcube.common.clients;
2022-06-15 17:51:59 +02:00
import static java.util.concurrent.TimeUnit.SECONDS;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.gcube.common.clients.delegates.MockDelegate.mockDelegate;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
2022-06-15 17:51:59 +02:00
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.gcube.common.clients.delegates.AsyncProxyDelegate;
import org.gcube.common.clients.delegates.Callback;
import org.gcube.common.clients.delegates.ProxyPlugin;
2022-06-15 17:51:59 +02:00
import org.gcube.common.security.Owner;
import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.common.security.secrets.Secret;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
@RunWith(MockitoJUnitRunner.class)
public class AsyncDelegateTest {
AsyncProxyDelegate<Object> delegate;
2022-07-26 15:14:18 +02:00
@Mock ProxyPlugin<Object,Object,?> plugin;
@Mock Object endpoint;
2022-07-26 15:14:18 +02:00
@Mock Call<Object,Object> call;
2022-07-26 15:14:18 +02:00
@Mock Object value;
@Mock Exception original;
@Mock Exception converted;
2022-07-26 15:14:18 +02:00
@Before
@SuppressWarnings("all")
public void setup() throws Exception {
//create subject-under-testing
delegate =new AsyncProxyDelegate<Object>(mockDelegate(plugin,endpoint));
2022-07-26 15:14:18 +02:00
//common configuration staging: mocking a delegate is not that immediate..
when(plugin.name()).thenReturn("some service");
when(plugin.convert(original,delegate.config())).thenReturn(converted);
2022-07-26 15:14:18 +02:00
}
2022-07-26 15:14:18 +02:00
@Test
public void asyncCallsReturnFutureValues() throws Exception {
2022-07-26 15:14:18 +02:00
//stage call
when(call.call(endpoint)).thenReturn(value);
2022-07-26 15:14:18 +02:00
Future<Object> future = delegate.makeAsync(call);
2022-07-26 15:14:18 +02:00
Object output = future.get();
2022-07-26 15:14:18 +02:00
assertEquals(value,output);
2022-07-26 15:14:18 +02:00
assertFalse(future.isCancelled());
2022-07-26 15:14:18 +02:00
assertTrue(future.isDone());
}
@Test
public void asyncCallsTimeout() throws Exception {
2022-07-26 15:14:18 +02:00
//stage call
Answer<?> slowly = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Thread.sleep(300); //simulate longer process within call timeout
return value;
}
};
when(call.call(endpoint)).thenAnswer(slowly);
2022-07-26 15:14:18 +02:00
Future<Object> future = delegate.makeAsync(call);
2022-07-26 15:14:18 +02:00
try {
future.get(100,TimeUnit.MILLISECONDS);
fail();
}
catch(TimeoutException e) {}
2022-07-26 15:14:18 +02:00
}
2022-07-26 15:14:18 +02:00
@Test
public void asyncCallsExecuteInCallScope() throws Exception {
2022-07-26 15:14:18 +02:00
final String scope = "a/b/c";
2024-02-22 12:22:41 +01:00
SecretManagerProvider.set(new Secret() {
2022-07-26 15:14:18 +02:00
2022-06-15 17:51:59 +02:00
@Override
public boolean isExpired() {
// TODO Auto-generated method stub
return false;
}
2022-07-26 15:14:18 +02:00
2022-06-15 17:51:59 +02:00
@Override
public Owner getOwner() {
// TODO Auto-generated method stub
return null;
}
2022-07-26 15:14:18 +02:00
2022-06-15 17:51:59 +02:00
@Override
public Map<String, String> getHTTPAuthorizationHeaders() {
// TODO Auto-generated method stub
return null;
}
2022-07-26 15:14:18 +02:00
2022-06-15 17:51:59 +02:00
@Override
public String getContext() {
return scope;
}
});
2022-07-26 15:14:18 +02:00
//stage call
Answer<?> checkingScope= new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
2024-02-22 12:22:41 +01:00
assertEquals(scope,SecretManagerProvider.get().getContext());
return value;
}
};
2022-07-26 15:14:18 +02:00
when(call.call(endpoint)).thenAnswer(checkingScope);
2022-07-26 15:14:18 +02:00
Future<Object> future = delegate.makeAsync(call);
2022-07-26 15:14:18 +02:00
future.get();
}
2022-07-26 15:14:18 +02:00
@Test
public void asyncCallReturnConvertedFaultsAsInnerCauses() throws Exception {
2022-07-26 15:14:18 +02:00
//stage call
when(call.call(endpoint)).thenThrow(original);
2022-07-26 15:14:18 +02:00
Future<Object> future = delegate.makeAsync(call);
2022-07-26 15:14:18 +02:00
try {
future.get();
fail();
}
catch(Exception fault) {
assertEquals(converted,fault.getCause());
}
2022-07-26 15:14:18 +02:00
}
@Test
public void asyncCallsAreInterrupted() throws Exception {
2022-07-26 15:14:18 +02:00
final String scope = "a/b/c";
2024-02-22 12:22:41 +01:00
SecretManagerProvider.set(new Secret() {
2022-07-26 15:14:18 +02:00
2022-06-15 17:51:59 +02:00
@Override
public boolean isExpired() {
// TODO Auto-generated method stub
return false;
}
2022-07-26 15:14:18 +02:00
2022-06-15 17:51:59 +02:00
@Override
public Owner getOwner() {
// TODO Auto-generated method stub
return null;
}
2022-07-26 15:14:18 +02:00
2022-06-15 17:51:59 +02:00
@Override
public Map<String, String> getHTTPAuthorizationHeaders() {
// TODO Auto-generated method stub
return null;
}
2022-07-26 15:14:18 +02:00
2022-06-15 17:51:59 +02:00
@Override
public String getContext() {
return scope;
}
});
2022-07-26 15:14:18 +02:00
//stage call
Answer<?> slowly = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Thread.sleep(300); //simulate longer process within call timeout
return value;
}
};
when(call.call(endpoint)).thenAnswer(slowly);
final Future<Object> future = delegate.makeAsync(call);
new Thread() {
public void run() {
2022-07-26 15:14:18 +02:00
future.cancel(true);
2022-07-26 15:14:18 +02:00
};
}.start();
2022-07-26 15:14:18 +02:00
try {
future.get();
fail();
}
catch(CancellationException fault) {
assertTrue(future.isCancelled());
}
2022-07-26 15:14:18 +02:00
}
2022-07-26 15:14:18 +02:00
@Test
public void callbacksGetResults() throws Exception {
2022-07-26 15:14:18 +02:00
//stage call
Answer<?> answer = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return value;
}
};
2022-07-26 15:14:18 +02:00
when(call.call(endpoint)).thenAnswer(answer);
2022-07-26 15:14:18 +02:00
@SuppressWarnings("all")
Callback<Object> callback = mock(Callback.class);
Future<?> future = delegate.makeAsync(call,callback);
//make sure the callback has had time to arrive
Thread.sleep(400);
2022-07-26 15:14:18 +02:00
verify(callback).done(value);
2022-07-26 15:14:18 +02:00
assertTrue(future.isDone());
2022-07-26 15:14:18 +02:00
}
2022-07-26 15:14:18 +02:00
@Test
public void callbacksGetTimeoutErrors() throws Exception {
2022-07-26 15:14:18 +02:00
//stage call
Answer<?> slowly = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Thread.sleep(1000);
return value;
}
};
2022-07-26 15:14:18 +02:00
when(call.call(endpoint)).thenAnswer(slowly);
2022-07-26 15:14:18 +02:00
@SuppressWarnings("all")
Callback<Object> callback = mock(Callback.class);
when(callback.timeout()).thenReturn(100L);
final CountDownLatch latch = new CountDownLatch(1);
2022-07-26 15:14:18 +02:00
Answer<?> unblock = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
latch.countDown();
return value;
}
};
2022-07-26 15:14:18 +02:00
doAnswer(unblock).when(callback).onFailure(any(TimeoutException.class));
2022-07-26 15:14:18 +02:00
Future<?> future = delegate.makeAsync(call,callback);
2022-07-26 15:14:18 +02:00
//makes sure callback has been invoked
latch.await(5,SECONDS);
2022-07-26 15:14:18 +02:00
assertTrue(future.isCancelled());
}
2022-07-26 15:14:18 +02:00
@Test
public void callbacksGetFaults() throws Exception {
2022-07-26 15:14:18 +02:00
when(call.call(endpoint)).thenThrow(original);
2022-07-26 15:14:18 +02:00
@SuppressWarnings("all")
Callback<Object> callback = mock(Callback.class);
2022-07-26 15:14:18 +02:00
final CountDownLatch latch = new CountDownLatch(1);
2022-07-26 15:14:18 +02:00
Answer<?> unblock = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Throwable e = (Throwable) invocation.getArguments()[0];
assertEquals(converted,e);
//male sure this method has been invoked
latch.countDown();
return null;
}
};
2022-07-26 15:14:18 +02:00
doAnswer(unblock).when(callback).onFailure(any(Throwable.class));
2022-07-26 15:14:18 +02:00
delegate.makeAsync(call,callback);
2022-07-26 15:14:18 +02:00
//makes sure callback has been invoked
latch.await(1,SECONDS);
2022-07-26 15:14:18 +02:00
}
2022-07-26 15:14:18 +02:00
}