Merge "Getter/setter tests inside the aai model"
[vid.git] / vid-app-common / src / test / java / org / onap / vid / mso / rest / OutgoingRequestId.java
1 package org.onap.vid.mso.rest;
2
3 import com.google.common.collect.ImmutableList;
4 import com.google.common.collect.ImmutableMap;
5 import org.apache.commons.lang3.reflect.FieldUtils;
6 import org.mockito.*;
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;
22
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;
34 import java.util.Set;
35 import java.util.function.Consumer;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
38
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.*;
44
45
46 public class OutgoingRequestId {
47
48
49     @InjectMocks
50     private RestMsoImplementation restMsoImplementation;
51
52     @InjectMocks
53     private AAIRestInterface aaiRestInterface;
54
55     private RestfulAsdcClient restfulAsdcClient = new RestfulAsdcClient.Builder(mock(Client.class), null).build();
56
57     @Captor
58     private ArgumentCaptor<MultivaluedMap<String, Object>> multivaluedMapArgumentCaptor;
59
60     @BeforeClass
61     public void initMocks() {
62         MockitoAnnotations.initMocks(this);
63     }
64
65     @BeforeMethod
66     private void putRequestInSpringContext() {
67         RequestContextHolder.setRequestAttributes(new ServletRequestAttributes((HttpServletRequest) PromiseEcompRequestIdFilter.wrapIfNeeded(new MockHttpServletRequest())));
68     }
69
70     @DataProvider
71     public Object[][] sdcMethods() {
72         return Stream.<ThrowingConsumer<RestfulAsdcClient>>of(
73
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())
84
85         ).map(l -> ImmutableList.of(l).toArray()).collect(Collectors.toList()).toArray(new Object[][]{});
86     }
87
88     @Test(dataProvider = "sdcMethods")
89     public void sdc(Consumer<RestfulAsdcClient> f) throws Exception {
90         final Mocks mocks = setAndGetMocksInsideRestImpl(restfulAsdcClient);
91
92         f.accept(restfulAsdcClient);
93
94         verifyRequestIdHeaderWasAdded(mocks.getFakeBuilder());
95     }
96
97     @DataProvider
98     public Object[][] msoMethods() {
99         return Stream.<ThrowingConsumer<RestMsoImplementation>>of(
100
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<>())
106
107         ).map(l -> ImmutableList.of(l).toArray()).collect(Collectors.toList()).toArray(new Object[][]{});
108     }
109
110     @Test(dataProvider = "msoMethods")
111     public void mso(Consumer<RestMsoImplementation> f) throws Exception {
112         final Mocks mocks = setAndGetMocksInsideRestImpl(restMsoImplementation.getClass());
113
114         f.accept(restMsoImplementation);
115
116         verifyRequestIdHeaderWasAdded(mocks.getFakeBuilder());
117     }
118
119     @DataProvider
120     public Object[][] aaiMethods() {
121         return Stream.<ThrowingConsumer<AAIRestInterface>>of(
122
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)
127
128         ).map(l -> ImmutableList.of(l).toArray()).collect(Collectors.toList()).toArray(new Object[][]{});
129     }
130
131     @Test(dataProvider = "aaiMethods")
132     public void aai(Consumer<AAIRestInterface> f) throws Exception {
133         final Mocks mocks = setAndGetMocksInsideRestImpl(aaiRestInterface.getClass());
134
135         f.accept(aaiRestInterface);
136
137         verifyRequestIdHeaderWasAdded(mocks.getFakeBuilder());
138     }
139
140 //    @Test(dataProvider = "schedulerMethods")
141 //    public void scheduler(Consumer<AAIRestInterface> f) throws Exception {
142 //
143 //        This test os not feasible in the wat acheduler is implemented today,
144 //        as Scheduler's client is rewritten in every call.
145 //
146 //        :-(
147 //
148 //    }
149
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}";
153
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))
156
157         Object requestId;
158         // The 'verify()' will capture the request id. If no match -- AssertionError will
159         // catch for a second chance -- another 'verify()'.
160         try {
161             ArgumentCaptor<Object> argumentCaptor = ArgumentCaptor.forClass(Object.class);
162             Mockito.verify(fakeBuilder)
163                     .header(
164                             Matchers.argThat(equalToIgnoringCase(requestIdHeader)),
165                             argumentCaptor.capture()
166                     );
167             requestId = argumentCaptor.getValue();
168
169         } catch (AssertionError e) {
170             Mockito.verify(fakeBuilder).headers(multivaluedMapArgumentCaptor.capture());
171
172             final MultivaluedMap<String, Object> headersMap = multivaluedMapArgumentCaptor.getValue();
173             final String thisRequestIdHeader = getFromSetCaseInsensitive(headersMap.keySet(), requestIdHeader);
174
175             assertThat(headersMap.keySet(), hasItem(thisRequestIdHeader));
176             requestId = headersMap.getFirst(thisRequestIdHeader);
177         }
178
179         assertThat("header '" + requestIdHeader + "' should be a uuid", requestId,
180                 allOf(instanceOf(String.class), hasToString(matchesPattern(uuidRegex))));
181     }
182
183     private String getFromSetCaseInsensitive(Set<String> set, String key) {
184         return set.stream()
185                 .filter(anotherString -> anotherString.equalsIgnoreCase(key))
186                 .findFirst()
187                 .orElse(key);
188     }
189
190     private Mocks setAndGetMocksInsideRestImpl(Class<?> clazz) throws IllegalAccessException {
191         Mocks mocks = new Mocks();
192         Client fakeClient = mocks.getFakeClient();
193
194         FieldUtils.writeStaticField(clazz, "client", fakeClient, true);
195
196         return mocks;
197     }
198
199     private Mocks setAndGetMocksInsideRestImpl(Object instance) throws IllegalAccessException {
200         Mocks mocks = new Mocks();
201         Client fakeClient = mocks.getFakeClient();
202
203         FieldUtils.writeField(instance, "client", fakeClient, true);
204
205         return mocks;
206     }
207
208     private static class Mocks {
209         private final Client fakeClient;
210         private final Invocation.Builder fakeBuilder;
211
212         Client getFakeClient() {
213             return fakeClient;
214         }
215
216         Invocation.Builder getFakeBuilder() {
217             return fakeBuilder;
218         }
219
220         Mocks() {
221             final MockSettings mockSettings = withSettings().defaultAnswer(new TriesToReturnMockByType());
222
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);
227
228             TriesToReturnMockByType.setAvailableMocks(
229                     fakeClient,
230                     fakeWebTarget,
231                     fakeBuilder,
232                     fakeResponse
233             );
234
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);
238
239             Mockito.when(fakeResponse.getStatus()).thenReturn(200);
240         }
241     }
242
243     @FunctionalInterface
244     public interface ThrowingConsumer<T> extends Consumer<T> {
245         @Override
246         default void accept(T t) {
247             try {
248                 acceptThrows(t);
249             } catch (Exception e) {
250                 throw new RuntimeException(e);
251             }
252         }
253
254         void acceptThrows(T t) throws Exception;
255     }
256
257     /*
258    inspired out from newer Mockito version
259     returns a mock from given list if it's a matching return-type
260      */
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();
264
265         static void setAvailableMocks(Object... mocks) {
266             availableMocks = ImmutableList.copyOf(mocks);
267         }
268
269         public Object answer(InvocationOnMock invocation) throws Throwable {
270             Class<?> methodReturnType = invocation.getMethod().getReturnType();
271
272             return availableMocks.stream()
273                     .filter(mock -> methodReturnType.isAssignableFrom(mock.getClass()))
274                     //.peek(m -> System.out.println("found a mock: " + m.getClass().getName()))
275                     .findFirst()
276                     .orElse(defaultReturn.answer(invocation));
277         }
278     }
279
280 }