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);
221 // mark private field to be accessible for testing purposes
222 AccessController.doPrivileged((PrivilegedAction) () -> {
223 privateField.setAccessible(true);
227 return privateFieldClass.cast(privateField.get(object));
229 } catch (IllegalAccessException e) {
230 logger.error("Unable to access field: {}", fieldName);
231 throw new IllegalStateException(e);
233 } catch (NoSuchFieldException e) {
234 logger.error("Unable to locate field name: {} in class: {}", fieldName, objectClass.getSimpleName());
235 throw new IllegalStateException(e);
241 * For testing purposes only sometime we may want to print classpath jars which are visible inside the class
243 * @param classLoader classloader of the calling class
245 public static void dumpClasspath(final ClassLoader classLoader) {
247 logger.info("Dumping ClassPath for classloader: {}", classLoader);
249 if (classLoader instanceof URLClassLoader) {
251 URLClassLoader ucl = (URLClassLoader) classLoader;
252 logger.info("\t ==========>>>" + Arrays.toString(ucl.getURLs()));
255 logger.info("\t(cannot display components as it is not a URLClassLoader)");
258 if (classLoader.getParent() != null) {
259 dumpClasspath(classLoader.getParent());
264 * Deserialize given Json file location to given model class and returns it back without any validation check.
266 * @param jsonFileLocation Classpath location of the json file
267 * @param modelClass Model Class type
268 * @param <T> Json Model Type
269 * @param objectMapper Jackson Json Object Mapper
271 * @return Deserialized Model Object
273 public static <T> T deserializeJsonFileToModel(final String jsonFileLocation, final Class<T> modelClass,
274 final ObjectMapper objectMapper) {
275 final InputStream jsonFileInputStream =
276 BaseAnalyticsTest.class.getClassLoader().getResourceAsStream(jsonFileLocation);
277 assertThat(jsonFileInputStream).as("Input JSON File location must be valid").isNotNull();
279 return objectMapper.readValue(jsonFileInputStream, modelClass);
280 } catch (IOException ex) {
281 logger.error("Error while doing assert Json for fileLocation: {}, modelClass: {}, Exception {}",
282 jsonFileLocation, modelClass, ex);
283 throw new RuntimeException(ex);
286 jsonFileInputStream.close();
287 } catch (IOException e) {
288 logger.error("Error while closing input stream at file location: {}", jsonFileLocation);
289 throw new RuntimeException(e);
295 * Serialize model to json string
297 * @param model model object
298 * @param objectMapper Jackson Json Object Mapper
302 * @throws JsonProcessingException when fails to process object
304 public static String serializeModelToJson(final Object model, final ObjectMapper objectMapper) throws
305 JsonProcessingException {
306 return objectMapper.writeValueAsString(model);
310 * Converts given model to json string and compare it with json present at given file location.
312 * @param model Model which needs to be compared
313 * @param expectedJsonFileLocation Location of file containing expected json string
314 * @param objectMapper Jackson Json Object Mapper
315 * @param <T> Json Model Type
317 * @return If assertion passes returns the input model
319 public static <T> T assertJsonSerialization(final T model, final String expectedJsonFileLocation,
320 final ObjectMapper objectMapper) {
322 final String actualModelString = serializeModelToJson(model, objectMapper);
323 final String expectedModelString = fromStream(expectedJsonFileLocation);
324 assertJson(expectedModelString, actualModelString);
326 } catch (IOException | JSONException ex) {
327 logger.error("Error while doing assert Json serialization Assertion: model: {}, "
328 + "expected Json File Location: {}, Exception {}", model, expectedJsonFileLocation, ex);
329 throw new RuntimeException(ex);
334 * Checks both serialization and deserialization.
336 * First checks deserialization and then serialize the deserialized object back to json
337 * and check if matches the given json file location string
339 * @param jsonFileLocation Classpath location of the json file
340 * @param modelClass Class type
341 * @param <T> Json Model Type
342 * @param objectMapper Jackson Json Object Mapper
344 * @return If assertion passes, returns deserialized object
347 public static <T> T assertJsonConversions(final String jsonFileLocation, final Class<T> modelClass,
348 final ObjectMapper objectMapper) {
349 //first check deserialization
350 final T actualValue = deserializeJsonFileToModel(jsonFileLocation, modelClass, objectMapper);
351 //then check serialization
352 assertJsonSerialization(actualValue, jsonFileLocation, objectMapper);
358 public static <T> T assertJsonConversions(final String jsonFileLocation,
359 final Function<String, Optional<T>> jsonConversionFunction,
360 final ObjectMapper objectMapper) {
361 final Optional<T> actualValueOptional = jsonConversionFunction.apply(fromStream(jsonFileLocation));
362 assertThat(actualValueOptional).isPresent();
363 if (actualValueOptional.isPresent()) {
364 assertJsonSerialization(actualValueOptional.get(), jsonFileLocation, objectMapper);
365 return actualValueOptional.get();
372 * Creates a mock URL Stream Handler
374 * @param mockURLConnection mock URL Connection
376 * @return Mock URL Stream Handler
378 public static URLStreamHandler createMockURLStreamHandler(final URLConnection mockURLConnection) {
379 return new URLStreamHandler() {
381 protected URLConnection openConnection(final URL url)
383 return mockURLConnection;
389 * Sets up environment variables for testing purposes
391 * @param testEnvironmentVariables key value map containing test environment variables
393 * @throws ClassNotFoundException class not found exception
394 * @throws IllegalAccessException illegal access exception
395 * @throws NoSuchFieldException no such method exception
397 @SuppressWarnings("unchecked")
398 protected static void setEnvironmentVariables(final Map<String, String> testEnvironmentVariables)
399 throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
401 final Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
402 final Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
404 AccessController.doPrivileged((PrivilegedAction) () -> {
405 theEnvironmentField.setAccessible(true);
409 final Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
410 env.putAll(testEnvironmentVariables);
411 Field theCaseInsensitiveEnvironmentField =
412 processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
413 AccessController.doPrivileged((PrivilegedAction) () -> {
414 theCaseInsensitiveEnvironmentField.setAccessible(true);
417 Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
418 cienv.putAll(testEnvironmentVariables);
419 } catch (NoSuchFieldException e) {
420 Class[] classes = Collections.class.getDeclaredClasses();
421 Map<String, String> env = System.getenv();
422 for (Class cl : classes) {
423 if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
424 Field field = cl.getDeclaredField("m");
425 AccessController.doPrivileged((PrivilegedAction) () -> {
426 field.setAccessible(true);
429 Object obj = field.get(env);
430 Map<String, String> map = (Map<String, String>) obj;
432 map.putAll(testEnvironmentVariables);
439 * Contains Locations for various files used for testing purposes
441 public abstract static class TestFileLocation {
443 public static final String CEF_JSON_MESSAGE = "data/json/cef/cef_message.json";
444 public static final String CEF_UNESCAPED_MESSAGES = "data/json/cef/cef_unescaped_messages.txt";
445 public static final String CEF_JSON_MESSAGE_WITH_VIOLATION = "data/json/cef/cef_message_with_violation.json";
446 public static final String CEF_JSON_MESSAGE_WITH_INAPPLICABLE_EVENT_NAME =
447 "data/json/cef/cef_meesage_with_inapplicable_event_name.json";
448 public static final String CEF_JSON_MESSAGE_WITH_ABATEMENT = "data/json/cef/cef_message_with_abatement.json";
449 public static final String CEF_JSON_MESSAGES = "data/json/cef/cef_messages.json";
451 public static final String TCA_POLICY_JSON = "data/json/policy/tca_policy.json";
452 public static final String TCA_APP_CONFIG_JSON = "data/json/config/tca_app_config.json";
453 public static final String TCA_ALERT_JSON = "data/json/facade/tca_alert.json";
456 public static final String CONFIG_SERVICE_BINDINGS_JSON =
457 "data/json/configservice/config_service_bindings.json";
460 public static final String TEST_JSON_MESSAGE = "data/json/test/test_message.json";