Merge "Add a semicolon at the end of this statement."
[vid.git] / vid-app-common / src / test / java / org / onap / vid / testUtils / TestUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.vid.testUtils;
22
23 import static com.fasterxml.jackson.module.kotlin.ExtensionsKt.jacksonObjectMapper;
24 import static java.util.function.Function.identity;
25 import static java.util.stream.Collectors.toList;
26 import static java.util.stream.Collectors.toMap;
27 import static org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptors;
28 import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
29 import static org.apache.commons.text.CharacterPredicates.DIGITS;
30 import static org.apache.commons.text.CharacterPredicates.LETTERS;
31 import static org.mockito.Matchers.any;
32 import static org.mockito.Mockito.RETURNS_DEFAULTS;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.when;
35 import static org.mockito.Mockito.withSettings;
36 import static org.testng.Assert.fail;
37
38 import com.fasterxml.jackson.databind.DeserializationFeature;
39 import com.fasterxml.jackson.databind.ObjectMapper;
40 import com.google.code.beanmatchers.BeanMatchers;
41 import com.google.common.collect.ImmutableList;
42 import java.beans.PropertyDescriptor;
43 import java.io.ByteArrayInputStream;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.Serializable;
47 import java.net.URI;
48 import java.util.Arrays;
49 import java.util.Iterator;
50 import java.util.List;
51 import javax.ws.rs.client.Client;
52 import javax.ws.rs.client.Invocation;
53 import javax.ws.rs.client.WebTarget;
54 import javax.ws.rs.core.GenericType;
55 import javax.ws.rs.core.MediaType;
56 import javax.ws.rs.core.Response;
57 import org.apache.commons.beanutils.BeanUtils;
58 import org.apache.commons.io.IOUtils;
59 import org.apache.commons.lang3.reflect.MethodUtils;
60 import org.apache.commons.text.RandomStringGenerator;
61 import org.apache.log4j.LogManager;
62 import org.apache.log4j.Logger;
63 import org.json.JSONArray;
64 import org.json.JSONObject;
65 import org.junit.Assert;
66 import org.mockito.MockSettings;
67 import org.mockito.Mockito;
68 import org.mockito.invocation.InvocationOnMock;
69 import org.mockito.stubbing.Answer;
70 import org.onap.portalsdk.core.util.SystemProperties;
71 import org.onap.vid.asdc.AsdcCatalogException;
72 import org.onap.vid.asdc.beans.Service;
73 import org.onap.vid.mso.model.CloudConfiguration;
74 import org.springframework.core.env.Environment;
75 import org.testng.annotations.DataProvider;
76
77 /**
78  * Created by Oren on 6/7/17.
79  */
80 public class TestUtils {
81
82     private static final Logger logger = LogManager.getLogger(TestUtils.class);
83
84     /**
85      * The method compares between two jsons. the function assert that the actual object does not reduce or change the functionallity/parsing of the expected json.
86      * This means that if the expected JSON has a key which is null or the JSON doesn't have a key which contained in the expected JSON the assert will succeed and the will pass.
87      * For example : For JSON expected = {a:null} and actual {a:3} the test will pass
88      * Other example : For JSON expected = {a:3} and actual {a:null} the test will fail
89      *
90      * @param expected JSON
91      * @param actual JSON
92      */
93     public static void assertJsonStringEqualsIgnoreNulls(String expected, String actual) {
94         if (expected == null || expected == JSONObject.NULL) {return;}
95
96         JSONObject expectedJSON = new JSONObject(expected);
97         JSONObject actualJSON = new JSONObject(actual);
98         Iterator<?> keys = expectedJSON.keys();
99
100         while( keys.hasNext() ) {
101             String key = (String)keys.next();
102             Object expectedValue = expectedJSON.get(key);
103             if (expectedValue == JSONObject.NULL){
104                 continue;
105             }
106
107             Object actualValue = actualJSON.get(key);
108
109             if (expectedValue instanceof JSONObject) {
110                 String expectedVal = expectedValue.toString();
111                 String actualVal = actualValue.toString();
112                 assertJsonStringEqualsIgnoreNulls(expectedVal, actualVal);
113             }
114             else if (expectedValue instanceof JSONArray) {
115                 if (actualValue instanceof JSONArray) {
116                     JSONArray expectedJSONArray = (JSONArray)expectedValue;
117                     JSONArray actualJSONArray = (JSONArray)actualValue;
118                     for (int i = 0; i < expectedJSONArray.length(); i++) {
119                         String expectedItem = expectedJSONArray.get(i).toString();
120                         String actualItem = actualJSONArray.get(i).toString();
121                         if (expectedValue instanceof JSONObject)
122                             assertJsonStringEqualsIgnoreNulls(expectedItem, actualItem);
123                     }
124                 }
125                 else {
126                     fail("expected: " + expectedValue + " got:" + actualValue);
127                 }
128             }
129             else {
130                 Assert.assertEquals("assertion fail for key:"+key, expectedValue, actualValue);
131             }
132         }
133     }
134
135     public static <T> T readJsonResourceFileAsObject(String pathInResource, Class<T> valueType) throws IOException {
136         return readJsonResourceFileAsObject(pathInResource, valueType, false);
137     }
138
139     public static <T> T readJsonResourceFileAsObject(String pathInResource, Class<T> valueType,
140         boolean failOnUnknownProperties)
141         throws IOException {
142         ObjectMapper objectMapper = jacksonObjectMapper()
143             .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, failOnUnknownProperties);
144         return objectMapper.readValue(
145             TestUtils.class.getResource(pathInResource),
146             valueType);
147     }
148
149     public static String readFileAsString(String pathInResource) {
150         try {
151             return IOUtils.toString(TestUtils.class.getResource(pathInResource), "UTF-8");
152         } catch (IOException e) {
153             throw new RuntimeException(e);
154         }
155     }
156
157     public static String[] allPropertiesOf(Class<?> aClass) {
158         return Arrays.stream(getPropertyDescriptors(aClass))
159             .map(PropertyDescriptor::getDisplayName)
160             .toArray(String[]::new);
161     }
162
163     private static <T> List<String> allStringPropertiesOf(T object) {
164         return Arrays.stream(getPropertyDescriptors(object.getClass()))
165             .filter(descriptor -> descriptor.getPropertyType().isAssignableFrom(String.class))
166             .map(PropertyDescriptor::getDisplayName)
167             .collect(toList());
168     }
169
170     /**
171      * Sets each String property with a value equal to the name of
172      * the property; e.g.: { name: "name", city: "city" }
173      * @param object
174      * @param <T>
175      * @return The modified object
176      */
177     public static <T> T setStringsInStringProperties(T object) {
178         try {
179             final List<String> stringFields = allStringPropertiesOf(object);
180
181             BeanUtils.populate(object, stringFields.stream()
182                 .collect(toMap(identity(), identity())));
183
184             return object;
185         } catch (Exception e) {
186             throw new RuntimeException(e);
187         }
188     }
189
190     public static void registerCloudConfigurationValueGenerator() {
191         BeanMatchers.registerValueGenerator(() -> new CloudConfiguration(
192                 randomAlphabetic(7), randomAlphabetic(7), randomAlphabetic(7)
193             ), CloudConfiguration.class);
194     }
195
196
197     public static class JavaxRsClientMocks {
198         private final javax.ws.rs.client.Client fakeClient;
199         private final javax.ws.rs.client.Invocation.Builder fakeBuilder;
200         private final javax.ws.rs.client.Invocation fakeInvocation;
201         private final Response fakeResponse;
202
203         public javax.ws.rs.client.Client getFakeClient() {
204             return fakeClient;
205         }
206
207         public javax.ws.rs.client.Invocation.Builder getFakeBuilder() {
208             return fakeBuilder;
209         }
210
211         public Response getFakeResponse() {
212             return fakeResponse;
213         }
214
215         public JavaxRsClientMocks() {
216             final MockSettings mockSettings = withSettings().defaultAnswer(new TriesToReturnMockByType());
217
218             fakeClient = mock(javax.ws.rs.client.Client.class, mockSettings);
219             fakeBuilder = mock(javax.ws.rs.client.Invocation.Builder.class, mockSettings);
220             fakeInvocation = mock(javax.ws.rs.client.Invocation.class, mockSettings);
221             fakeResponse = mock(Response.class, mockSettings);
222             final javax.ws.rs.client.WebTarget fakeWebTarget = mock(javax.ws.rs.client.WebTarget.class, mockSettings);
223
224             TriesToReturnMockByType.setAvailableMocks(
225                     fakeClient,
226                     fakeWebTarget,
227                     fakeBuilder,
228                     fakeInvocation,
229                     fakeResponse
230             );
231             Mockito.when(fakeBuilder.get(any(Class.class))).thenReturn(null);
232             Mockito.when(fakeBuilder.get(any(GenericType.class))).thenReturn(null);
233             Mockito.when(fakeResponse.getStatus()).thenReturn(200);
234             Mockito.when(fakeResponse.getStatusInfo()).thenReturn(Response.Status.OK);
235             Mockito.when(fakeResponse.readEntity(Service.class)).thenReturn(null);
236             Mockito.when(fakeResponse.readEntity(InputStream.class)).thenReturn(new ByteArrayInputStream(new byte[]{}));
237             Mockito.when(fakeResponse.readEntity(String.class)).thenReturn(null);
238         }
239     }
240
241     /*
242        inspired out from newer Mockito version
243         returns a mock from given list if it's a matching return-type
244     */
245     private static class TriesToReturnMockByType implements Answer<Object>, Serializable {
246         private final Answer<Object> defaultReturn = RETURNS_DEFAULTS;
247         private static List<Object> availableMocks = ImmutableList.of();
248
249         static void setAvailableMocks(Object... mocks) {
250             availableMocks = ImmutableList.copyOf(mocks);
251         }
252
253         public Object answer(InvocationOnMock invocation) throws Throwable {
254             Class<?> methodReturnType = invocation.getMethod().getReturnType();
255
256             return availableMocks.stream()
257                     .filter(mock -> methodReturnType.isAssignableFrom(mock.getClass()))
258                     //.peek(m -> logger.info("found a mock: " + m.getClass().getName()))
259                     .findFirst()
260                     .orElse(defaultReturn.answer(invocation));
261         }
262     }
263
264
265     //The method mocks only some methods used in my case
266     //You may add some other when for your test here
267     public static Response mockResponseForJavaxClient(Client javaxClientMock) {
268         Response  mockResponse = mock(Response.class);
269         WebTarget webTarget = mock(WebTarget.class);
270         Invocation.Builder builder = mock(Invocation.Builder.class);
271         when(javaxClientMock.target(any(URI.class))).thenReturn(webTarget);
272         when(webTarget.path(any())).thenReturn(webTarget);
273         when(webTarget.request(any(MediaType.class))).thenReturn(builder);
274         when(builder.headers(any())).thenReturn(builder);
275         when(builder.header(any(), any())).thenReturn(builder);
276         when(builder.get()).thenReturn(mockResponse);
277         return mockResponse;
278     }
279
280
281     public interface Test {
282
283         void apply() throws AsdcCatalogException;
284     }
285
286     public static void testWithSystemProperty(String key, String value, Test test) throws Exception {
287         SystemProperties systemProperties = new SystemProperties();
288         //use reflection to invoke protected method
289         Environment originalEnvironment = (Environment) MethodUtils
290             .invokeMethod(systemProperties, true, "getEnvironment");
291
292         try {
293             Environment environment = mock(Environment.class);
294             systemProperties.setEnvironment(environment);
295             when(environment.getRequiredProperty(key)).thenReturn(value);
296             when(environment.containsProperty(key)).thenReturn(true);
297             test.apply();
298         }
299         finally {
300             systemProperties.setEnvironment(originalEnvironment);
301         }
302     }
303
304     private static RandomStringGenerator generator = new RandomStringGenerator.Builder()
305             .withinRange('0', 'z')
306             .filteredBy(LETTERS, DIGITS)
307             .build();
308
309     public static String generateRandomAlphaNumeric(int length) {
310         return generator.generate(length);
311     }
312
313     @DataProvider
314     public static Object[][] trueAndFalse() {
315         return new Object[][]{{true}, {false}};
316     }
317
318 }