2 * ================================================================================
3 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * ============LICENSE_END=========================================================
20 package org.onap.dcae.analytics.test;
22 import static java.nio.file.Files.deleteIfExists;
23 import static java.nio.file.Files.exists;
24 import static org.assertj.core.api.Assertions.assertThat;
26 import com.fasterxml.jackson.core.JsonProcessingException;
27 import com.fasterxml.jackson.databind.ObjectMapper;
29 import java.io.BufferedReader;
31 import java.io.FileOutputStream;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.InputStreamReader;
35 import java.io.ObjectOutputStream;
36 import java.io.OutputStreamWriter;
37 import java.lang.invoke.MethodHandles;
38 import java.lang.reflect.Field;
40 import java.net.URLClassLoader;
41 import java.net.URLConnection;
42 import java.net.URLStreamHandler;
43 import java.nio.charset.Charset;
44 import java.nio.file.Paths;
45 import java.security.AccessController;
46 import java.security.PrivilegedAction;
47 import java.util.Arrays;
48 import java.util.Collections;
50 import java.util.Optional;
51 import java.util.function.Function;
53 import org.json.JSONException;
54 import org.skyscreamer.jsonassert.JSONAssert;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
59 * Base common test class for all DCAE Analytics Test e.g. unit tests, integration test etc.
61 * @author Rajiv Singla
63 abstract class BaseAnalyticsTest {
65 protected static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
68 * Asserts if expected Json String and actual Json String contain the same properties ignoring
69 * property order. Simple String assertion might fail as property order during serialization and deserialization
70 * is generally non-deterministic. Also proper error message are generated more missing or unexpected
73 * @param expectedJsonString expected Json String
74 * @param actualJsonString actual Json String
76 * @throws JSONException Json Exception
78 public static void assertJson(final String expectedJsonString, final String actualJsonString) throws JSONException {
79 JSONAssert.assertEquals(expectedJsonString, actualJsonString, true);
83 * Converts given file location to String
85 * @param fileLocation location of the file which needs to be converted to String
87 * @return Contents of file as string
89 public static String fromStream(final String fileLocation) {
90 try (InputStream fileInputStream = asInputStream(fileLocation);
91 BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream, Charset.forName
93 final StringBuilder result = new StringBuilder();
94 final String newLine = System.getProperty("line.separator");
95 String line = reader.readLine();
96 while (line != null) {
97 result.append(line).append(newLine);
98 line = reader.readLine();
100 return result.toString();
101 } catch (IOException e) {
102 throw new RuntimeException("Unable to get contents for file Location: " + fileLocation, e);
107 * Converts given file location to input stream
109 * @param fileLocation file location
111 * @return input stream of given file location
113 public static InputStream asInputStream(final String fileLocation) {
114 final InputStream fileInputStream =
115 BaseAnalyticsTest.class.getClassLoader().getResourceAsStream(fileLocation);
116 assertThat(fileInputStream).as("Input File Location must be valid").isNotNull();
117 return fileInputStream;
121 * Checks if object can be serialized properly
123 * @param object input object
124 * @param callingClass calling class
126 public static void testSerialization(final Object object, final Class<?> callingClass) {
128 final URL location = callingClass.getProtectionDomain().getCodeSource().getLocation();
129 final File serializedOutputFile =
130 new File(location.getPath() + String.format("serialization/%s.ser", object.getClass().getSimpleName()));
132 // Maybe file already exists try deleting it first
133 final boolean deleteIfExists = deleteIfExists(Paths.get(serializedOutputFile.getPath()));
135 if (deleteIfExists) {
136 logger.warn("Previous serialization file was overwritten at location: {}",
137 serializedOutputFile.getPath());
140 boolean mkdirs = true;
141 if (!Paths.get(serializedOutputFile.getParentFile().getPath()).toFile().exists()) {
142 mkdirs = serializedOutputFile.getParentFile().mkdirs();
145 try (FileOutputStream fileOutputStream = new FileOutputStream(serializedOutputFile);
146 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
147 objectOutputStream.writeObject(object);
148 logger.debug("Successfully created serialization file at location: {}", serializedOutputFile
153 } catch (IOException ex) {
154 throw new IllegalStateException(
155 String.format("Failed to create location to store serialization file: %s", serializedOutputFile));
160 * Writes Text to Output file
162 * @param textFileLocation location of text file e.g. textfiles/fileName.json
163 * @param content file content
164 * @param callingClass calling class
166 * @throws IOException ioException
168 public static void writeToOutputTextFile(final String textFileLocation,
169 final String content, Class<?> callingClass) throws IOException {
170 final URL location = callingClass.getProtectionDomain().getCodeSource().getLocation();
171 final File fileLocation = new File(location.getPath() + textFileLocation);
173 // Maybe file already try deleting it first
174 final boolean deleteIfExists = deleteIfExists(Paths.get(fileLocation.getPath()));
176 if (deleteIfExists) {
177 logger.warn("Previous file will be overwritten at location: {}", fileLocation.getPath());
180 boolean mkdirs = true;
181 if (!exists(Paths.get(fileLocation.getParentFile().getPath()))) {
182 mkdirs = fileLocation.getParentFile().mkdirs();
186 FileOutputStream fileOutputStream = new FileOutputStream(fileLocation);
187 OutputStreamWriter outputStream =
188 new OutputStreamWriter(fileOutputStream, Charset.forName("UTF-8"))) {
189 outputStream.write(content);
190 logger.debug("Successfully created text file at location: {}", fileLocation.getPath());
193 throw new IllegalStateException(
194 String.format("Failed to create location to store text file: %s", fileLocation));
200 * For testing purposes only sometime we may want to access private fields of underlying
201 * object to confirm the values are setup correctly.
202 * This method uses java reflection to get the value to private object in the class
204 * @param object Actual object which has the private field you want to check
205 * @param fieldName Field name in the Actual Object you want to get the value of
206 * @param privateFieldClass Type of the private field
207 * @param <T> Class of Actual Object
208 * @param <U> Class of private field
210 * @return value of the private field
212 @SuppressWarnings("unchecked")
213 public static <T, U> U getPrivateFiledValue(final T object, final String fieldName,
214 final Class<U> privateFieldClass) {
216 final Class<?> objectClass = object.getClass();
218 final Field privateField = objectClass.getDeclaredField(fieldName);
220 // mark private field to be accessible for testing purposes
221 AccessController.doPrivileged((PrivilegedAction) () -> {
222 privateField.setAccessible(true);
226 return privateFieldClass.cast(privateField.get(object));
228 } catch (IllegalAccessException e) {
229 logger.error("Unable to access field: {}", fieldName);
230 throw new IllegalStateException(e);
231 } catch (NoSuchFieldException e) {
232 logger.error("Unable to locate field name: {} in class: {}", fieldName,
233 objectClass.getSimpleName());
234 throw new IllegalStateException(e);
240 * For testing purposes only sometime we may want to print classpath jars which are visible inside the class
242 * @param classLoader classloader of the calling class
244 public static void dumpClasspath(final ClassLoader classLoader) {
246 logger.info("Dumping ClassPath for classloader: {}", classLoader);
248 if (classLoader instanceof URLClassLoader) {
250 URLClassLoader ucl = (URLClassLoader) classLoader;
251 logger.info("\t ==========>>>" + Arrays.toString(ucl.getURLs()));
254 logger.info("\t(cannot display components as it is not a URLClassLoader)");
257 if (classLoader.getParent() != null) {
258 dumpClasspath(classLoader.getParent());
263 * Deserialize given Json file location to given model class and returns it back without any validation check.
265 * @param jsonFileLocation Classpath location of the json file
266 * @param modelClass Model Class type
267 * @param <T> Json Model Type
268 * @param objectMapper Jackson Json Object Mapper
270 * @return Deserialized Model Object
272 public static <T> T deserializeJsonFileToModel(final String jsonFileLocation, final Class<T> modelClass,
273 final ObjectMapper objectMapper) {
274 try( final InputStream jsonFileInputStream =
275 BaseAnalyticsTest.class.getClassLoader().getResourceAsStream(jsonFileLocation)) {
276 assertThat(jsonFileInputStream).as("Input JSON File location must be valid").isNotNull();
277 return objectMapper.readValue(jsonFileInputStream, modelClass);
278 } catch (IOException ex) {
279 logger.error("Error while doing assert Json for fileLocation: {}, modelClass: {}, Exception {}",
280 jsonFileLocation, modelClass, ex);
281 throw new RuntimeException(ex);
286 * Serialize model to json string
288 * @param model model object
289 * @param objectMapper Jackson Json Object Mapper
293 * @throws JsonProcessingException when fails to process object
295 public static String serializeModelToJson(final Object model, final ObjectMapper objectMapper) throws
296 JsonProcessingException {
297 return objectMapper.writeValueAsString(model);
301 * Converts given model to json string and compare it with json present at given file location.
303 * @param model Model which needs to be compared
304 * @param expectedJsonFileLocation Location of file containing expected json string
305 * @param objectMapper Jackson Json Object Mapper
306 * @param <T> Json Model Type
308 * @return If assertion passes returns the input model
310 public static <T> T assertJsonSerialization(final T model, final String expectedJsonFileLocation,
311 final ObjectMapper objectMapper) {
313 final String actualModelString = serializeModelToJson(model, objectMapper);
314 final String expectedModelString = fromStream(expectedJsonFileLocation);
315 assertJson(expectedModelString, actualModelString);
317 } catch (IOException | JSONException ex) {
318 logger.error("Error while doing assert Json serialization Assertion: model: {}, "
319 + "expected Json File Location: {}, Exception {}", model, expectedJsonFileLocation, ex);
320 throw new RuntimeException(ex);
325 * Checks both serialization and deserialization.
327 * First checks deserialization and then serialize the deserialized object back to json
328 * and check if matches the given json file location string
330 * @param jsonFileLocation Classpath location of the json file
331 * @param modelClass Class type
332 * @param <T> Json Model Type
333 * @param objectMapper Jackson Json Object Mapper
335 * @return If assertion passes, returns deserialized object
338 public static <T> T assertJsonConversions(final String jsonFileLocation, final Class<T> modelClass,
339 final ObjectMapper objectMapper) {
340 //first check deserialization
341 final T actualValue = deserializeJsonFileToModel(jsonFileLocation, modelClass, objectMapper);
342 //then check serialization
343 assertJsonSerialization(actualValue, jsonFileLocation, objectMapper);
349 public static <T> T assertJsonConversions(final String jsonFileLocation,
350 final Function<String, Optional<T>> jsonConversionFunction,
351 final ObjectMapper objectMapper) {
352 final Optional<T> actualValueOptional = jsonConversionFunction.apply(fromStream(jsonFileLocation));
353 assertThat(actualValueOptional).isPresent();
354 if (actualValueOptional.isPresent()) {
355 assertJsonSerialization(actualValueOptional.get(), jsonFileLocation, objectMapper);
356 return actualValueOptional.get();
363 * Creates a mock URL Stream Handler
365 * @param mockURLConnection mock URL Connection
367 * @return Mock URL Stream Handler
369 public static URLStreamHandler createMockURLStreamHandler(final URLConnection mockURLConnection) {
370 return new URLStreamHandler() {
372 protected URLConnection openConnection(final URL url)
374 return mockURLConnection;
380 * Sets up environment variables for testing purposes
382 * @param testEnvironmentVariables key value map containing test environment variables
384 * @throws ClassNotFoundException class not found exception
385 * @throws IllegalAccessException illegal access exception
386 * @throws NoSuchFieldException no such method exception
388 @SuppressWarnings("unchecked")
389 public static void setEnvironmentVariables(final Map<String, String> testEnvironmentVariables)
390 throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
392 final Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
393 final Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
395 AccessController.doPrivileged((PrivilegedAction) () -> {
396 theEnvironmentField.setAccessible(true);
400 final Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
401 env.putAll(testEnvironmentVariables);
402 Field theCaseInsensitiveEnvironmentField =
403 processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
404 AccessController.doPrivileged((PrivilegedAction) () -> {
405 theCaseInsensitiveEnvironmentField.setAccessible(true);
408 Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
409 cienv.putAll(testEnvironmentVariables);
410 } catch (NoSuchFieldException e) {
411 logger.error("NoSuchFieldException in setEnvironmentVariables", e);
412 Class[] classes = Collections.class.getDeclaredClasses();
413 Map<String, String> env = System.getenv();
414 for (Class cl : classes) {
415 if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
416 Field field = cl.getDeclaredField("m");
417 AccessController.doPrivileged((PrivilegedAction) () -> {
418 field.setAccessible(true);
421 Object obj = field.get(env);
422 Map<String, String> map = (Map<String, String>) obj;
424 map.putAll(testEnvironmentVariables);
431 * Contains Locations for various files used for testing purposes
433 public abstract static class TestFileLocation {
435 public static final String CEF_JSON_MESSAGE = "data/json/cef/cef_message.json";
436 public static final String CEF_UNESCAPED_MESSAGES = "data/json/cef/cef_unescaped_messages.txt";
437 public static final String CEF_JSON_MESSAGE_WITH_VIOLATION = "data/json/cef/cef_message_with_violation.json";
438 public static final String CEF_JSON_MESSAGE_WITH_INAPPLICABLE_EVENT_NAME =
439 "data/json/cef/cef_meesage_with_inapplicable_event_name.json";
440 public static final String CEF_JSON_MESSAGE_WITH_ABATEMENT = "data/json/cef/cef_message_with_abatement.json";
441 public static final String CEF_JSON_MESSAGES = "data/json/cef/cef_messages.json";
443 public static final String TCA_POLICY_JSON = "data/json/policy/tca_policy.json";
444 public static final String TCA_APP_CONFIG_JSON = "data/json/config/tca_app_config.json";
445 public static final String TCA_ALERT_JSON = "data/json/facade/tca_alert.json";
448 public static final String CONFIG_SERVICE_BINDINGS_JSON =
449 "data/json/configservice/config_service_bindings.json";
452 public static final String TEST_JSON_MESSAGE = "data/json/test/test_message.json";