1 package org.onap.vid.mso.rest;
3 import com.google.common.collect.ImmutableList;
4 import com.google.common.collect.ImmutableMap;
5 import org.apache.commons.lang3.reflect.FieldUtils;
7 import org.mockito.invocation.InvocationOnMock;
8 import org.mockito.stubbing.Answer;
9 import org.onap.vid.aai.util.AAIRestInterface;
10 import org.onap.vid.asdc.rest.RestfulAsdcClient;
11 import org.onap.vid.changeManagement.RequestDetailsWrapper;
12 import org.onap.vid.controller.filter.PromiseEcompRequestIdFilter;
13 import org.onap.vid.mso.RestMsoImplementation;
14 import org.onap.vid.mso.RestObject;
15 import org.springframework.mock.web.MockHttpServletRequest;
16 import org.springframework.web.context.request.RequestContextHolder;
17 import org.springframework.web.context.request.ServletRequestAttributes;
18 import org.testng.annotations.BeforeClass;
19 import org.testng.annotations.BeforeMethod;
20 import org.testng.annotations.DataProvider;
21 import org.testng.annotations.Test;
23 import javax.servlet.http.HttpServletRequest;
24 import javax.ws.rs.client.Client;
25 import javax.ws.rs.client.Invocation;
26 import javax.ws.rs.client.WebTarget;
27 import javax.ws.rs.core.GenericType;
28 import javax.ws.rs.core.MultivaluedMap;
29 import javax.ws.rs.core.Response;
30 import java.io.ByteArrayInputStream;
31 import java.io.InputStream;
32 import java.io.Serializable;
33 import java.util.List;
35 import java.util.function.Consumer;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
39 import static java.util.UUID.randomUUID;
40 import static org.hamcrest.MatcherAssert.assertThat;
41 import static org.hamcrest.Matchers.*;
42 import static org.mockito.Matchers.any;
43 import static org.mockito.Mockito.*;
46 public class OutgoingRequestId {
50 private RestMsoImplementation restMsoImplementation;
53 private AAIRestInterface aaiRestInterface;
55 private RestfulAsdcClient restfulAsdcClient = new RestfulAsdcClient.Builder(mock(Client.class), null).build();
58 private ArgumentCaptor<MultivaluedMap<String, Object>> multivaluedMapArgumentCaptor;
61 public void initMocks() {
62 MockitoAnnotations.initMocks(this);
66 private void putRequestInSpringContext() {
67 RequestContextHolder.setRequestAttributes(new ServletRequestAttributes((HttpServletRequest) PromiseEcompRequestIdFilter.wrapIfNeeded(new MockHttpServletRequest())));
71 public Object[][] sdcMethods() {
72 return Stream.<ThrowingConsumer<RestfulAsdcClient>>of(
74 client -> client.getResource(randomUUID()),
75 client -> client.getResourceArtifact(randomUUID(), randomUUID()),
76 RestfulAsdcClient::getResources,
77 client -> client.getResources(ImmutableMap.of()),
78 client -> client.getResourceToscaModel(randomUUID()),
79 client -> client.getService(randomUUID()),
80 client -> client.getServiceArtifact(randomUUID(), randomUUID()),
81 RestfulAsdcClient::getServices,
82 client -> client.getServices(ImmutableMap.of()),
83 client -> client.getServiceToscaModel(randomUUID())
85 ).map(l -> ImmutableList.of(l).toArray()).collect(Collectors.toList()).toArray(new Object[][]{});
88 @Test(dataProvider = "sdcMethods")
89 public void sdc(Consumer<RestfulAsdcClient> f) throws Exception {
90 final Mocks mocks = setAndGetMocksInsideRestImpl(restfulAsdcClient);
92 f.accept(restfulAsdcClient);
94 verifyRequestIdHeaderWasAdded(mocks.getFakeBuilder());
98 public Object[][] msoMethods() {
99 return Stream.<ThrowingConsumer<RestMsoImplementation>>of(
101 client -> client.Get(new Object(), "whatever source id", "/any path", new RestObject<>()),
102 client -> client.GetForObject("whatever source id", "/any path", Object.class),
103 client -> client.Post(new Object(), "some payload", "whatever source id", "/any path", new RestObject<>()),
104 client -> client.PostForObject("some payload", "whatever source id", "/any path", Object.class),
105 client -> client.Put(Object.class, new RequestDetailsWrapper(), "whatever source id", "/any path", new RestObject<>())
107 ).map(l -> ImmutableList.of(l).toArray()).collect(Collectors.toList()).toArray(new Object[][]{});
110 @Test(dataProvider = "msoMethods")
111 public void mso(Consumer<RestMsoImplementation> f) throws Exception {
112 final Mocks mocks = setAndGetMocksInsideRestImpl(restMsoImplementation.getClass());
114 f.accept(restMsoImplementation);
116 verifyRequestIdHeaderWasAdded(mocks.getFakeBuilder());
120 public Object[][] aaiMethods() {
121 return Stream.<ThrowingConsumer<AAIRestInterface>>of(
123 client -> client.RestGet("from app id", "some transId", "/any path", false),
124 client -> client.Delete("whatever source id", "some transId", "/any path"),
125 client -> client.RestPost("from app id", "some transId", "/any path", "some payload", false),
126 client -> client.RestPut("from app id", "some transId", "/any path", "some payload", false)
128 ).map(l -> ImmutableList.of(l).toArray()).collect(Collectors.toList()).toArray(new Object[][]{});
131 @Test(dataProvider = "aaiMethods")
132 public void aai(Consumer<AAIRestInterface> f) throws Exception {
133 final Mocks mocks = setAndGetMocksInsideRestImpl(aaiRestInterface.getClass());
135 f.accept(aaiRestInterface);
137 verifyRequestIdHeaderWasAdded(mocks.getFakeBuilder());
140 // @Test(dataProvider = "schedulerMethods")
141 // public void scheduler(Consumer<AAIRestInterface> f) throws Exception {
143 // This test os not feasible in the wat acheduler is implemented today,
144 // as Scheduler's client is rewritten in every call.
150 private void verifyRequestIdHeaderWasAdded(Invocation.Builder fakeBuilder) {
151 final String requestIdHeader = "x-ecomp-requestid";
152 final String uuidRegex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
154 // Checks that the builder was called with either one of header("x-ecomp-requestid", uuid)
155 // or the plural brother: headers(Map.of("x-ecomp-requestid", Set.of(uuid))
158 // The 'verify()' will capture the request id. If no match -- AssertionError will
159 // catch for a second chance -- another 'verify()'.
161 ArgumentCaptor<Object> argumentCaptor = ArgumentCaptor.forClass(Object.class);
162 Mockito.verify(fakeBuilder)
164 Matchers.argThat(equalToIgnoringCase(requestIdHeader)),
165 argumentCaptor.capture()
167 requestId = argumentCaptor.getValue();
169 } catch (AssertionError e) {
170 Mockito.verify(fakeBuilder).headers(multivaluedMapArgumentCaptor.capture());
172 final MultivaluedMap<String, Object> headersMap = multivaluedMapArgumentCaptor.getValue();
173 final String thisRequestIdHeader = getFromSetCaseInsensitive(headersMap.keySet(), requestIdHeader);
175 assertThat(headersMap.keySet(), hasItem(thisRequestIdHeader));
176 requestId = headersMap.getFirst(thisRequestIdHeader);
179 assertThat("header '" + requestIdHeader + "' should be a uuid", requestId,
180 allOf(instanceOf(String.class), hasToString(matchesPattern(uuidRegex))));
183 private String getFromSetCaseInsensitive(Set<String> set, String key) {
185 .filter(anotherString -> anotherString.equalsIgnoreCase(key))
190 private Mocks setAndGetMocksInsideRestImpl(Class<?> clazz) throws IllegalAccessException {
191 Mocks mocks = new Mocks();
192 Client fakeClient = mocks.getFakeClient();
194 FieldUtils.writeStaticField(clazz, "client", fakeClient, true);
199 private Mocks setAndGetMocksInsideRestImpl(Object instance) throws IllegalAccessException {
200 Mocks mocks = new Mocks();
201 Client fakeClient = mocks.getFakeClient();
203 FieldUtils.writeField(instance, "client", fakeClient, true);
208 private static class Mocks {
209 private final Client fakeClient;
210 private final Invocation.Builder fakeBuilder;
212 Client getFakeClient() {
216 Invocation.Builder getFakeBuilder() {
221 final MockSettings mockSettings = withSettings().defaultAnswer(new TriesToReturnMockByType());
223 fakeClient = mock(Client.class, mockSettings);
224 fakeBuilder = mock(Invocation.Builder.class, mockSettings);
225 final WebTarget fakeWebTarget = mock(WebTarget.class, mockSettings);
226 final Response fakeResponse = mock(Response.class, mockSettings);
228 TriesToReturnMockByType.setAvailableMocks(
235 Mockito.when(fakeBuilder.get(any(Class.class))).thenReturn(null);
236 Mockito.when(fakeBuilder.get(eq(InputStream.class))).thenReturn(new ByteArrayInputStream(new byte[]{}));
237 Mockito.when(fakeBuilder.get(any(GenericType.class))).thenReturn(null);
239 Mockito.when(fakeResponse.getStatus()).thenReturn(200);
244 public interface ThrowingConsumer<T> extends Consumer<T> {
246 default void accept(T t) {
249 } catch (Exception e) {
250 throw new RuntimeException(e);
254 void acceptThrows(T t) throws Exception;
258 inspired out from newer Mockito version
259 returns a mock from given list if it's a matching return-type
261 public static class TriesToReturnMockByType implements Answer<Object>, Serializable {
262 private final Answer<Object> defaultReturn = RETURNS_DEFAULTS;
263 private static List<Object> availableMocks = ImmutableList.of();
265 static void setAvailableMocks(Object... mocks) {
266 availableMocks = ImmutableList.copyOf(mocks);
269 public Object answer(InvocationOnMock invocation) throws Throwable {
270 Class<?> methodReturnType = invocation.getMethod().getReturnType();
272 return availableMocks.stream()
273 .filter(mock -> methodReturnType.isAssignableFrom(mock.getClass()))
274 //.peek(m -> System.out.println("found a mock: " + m.getClass().getName()))
276 .orElse(defaultReturn.answer(invocation));