Add support for ABATED alerts within CDAP TCA
[dcaegen2/analytics/tca.git] / dcae-analytics-tca / src / test / java / org / openecomp / dcae / apod / analytics / tca / utils / TCAUtilsTest.java
1 /*
2  * ===============================LICENSE_START======================================
3  *  dcae-analytics
4  * ================================================================================
5  *    Copyright © 2017 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.openecomp.dcae.apod.analytics.tca.utils;
22
23 import com.google.common.base.Supplier;
24 import com.google.common.collect.ImmutableSet;
25 import com.google.common.collect.Table;
26 import org.apache.commons.lang3.tuple.Pair;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.rules.ExpectedException;
30 import org.mockito.Mockito;
31 import org.openecomp.dcae.apod.analytics.common.AnalyticsConstants;
32 import org.openecomp.dcae.apod.analytics.common.exception.MessageProcessingException;
33 import org.openecomp.dcae.apod.analytics.model.domain.cef.CommonEventHeader;
34 import org.openecomp.dcae.apod.analytics.model.domain.cef.Domain;
35 import org.openecomp.dcae.apod.analytics.model.domain.cef.Event;
36 import org.openecomp.dcae.apod.analytics.model.domain.cef.EventListener;
37 import org.openecomp.dcae.apod.analytics.model.domain.cef.EventSeverity;
38 import org.openecomp.dcae.apod.analytics.model.domain.policy.tca.ControlLoopEventStatus;
39 import org.openecomp.dcae.apod.analytics.model.domain.policy.tca.ControlLoopSchemaType;
40 import org.openecomp.dcae.apod.analytics.model.domain.policy.tca.Direction;
41 import org.openecomp.dcae.apod.analytics.model.domain.policy.tca.MetricsPerEventName;
42 import org.openecomp.dcae.apod.analytics.model.domain.policy.tca.TCAPolicy;
43 import org.openecomp.dcae.apod.analytics.model.domain.policy.tca.Threshold;
44 import org.openecomp.dcae.apod.analytics.model.facade.tca.TCAVESResponse;
45 import org.openecomp.dcae.apod.analytics.tca.BaseAnalyticsTCAUnitTest;
46 import org.openecomp.dcae.apod.analytics.tca.processor.TCACEFProcessorContext;
47 import org.quartz.Job;
48 import org.quartz.JobDataMap;
49 import org.quartz.JobDetail;
50 import org.quartz.Scheduler;
51 import org.quartz.SimpleTrigger;
52 import org.quartz.impl.StdSchedulerFactory;
53
54 import java.util.Arrays;
55 import java.util.HashMap;
56 import java.util.List;
57 import java.util.Map;
58 import java.util.Set;
59
60 import static org.hamcrest.CoreMatchers.is;
61 import static org.hamcrest.CoreMatchers.isA;
62 import static org.hamcrest.Matchers.containsInAnyOrder;
63 import static org.junit.Assert.assertEquals;
64 import static org.junit.Assert.assertFalse;
65 import static org.junit.Assert.assertNotNull;
66 import static org.junit.Assert.assertNull;
67 import static org.junit.Assert.assertThat;
68 import static org.junit.Assert.assertTrue;
69 import static org.mockito.Mockito.mock;
70 import static org.mockito.Mockito.times;
71 import static org.mockito.Mockito.verify;
72 import static org.mockito.Mockito.when;
73
74 /**
75  * @author Rajiv Singla . Creation Date: 11/9/2016.
76  */
77 public class TCAUtilsTest extends BaseAnalyticsTCAUnitTest {
78
79     @Test
80     public void testGetPolicyEventNames() throws Exception {
81
82         final TCAPolicy sampleTCAPolicy = getSampleTCAPolicy();
83         final List<String> eventNames = TCAUtils.getPolicyEventNames(sampleTCAPolicy);
84
85         assertThat("Policy event names must contain vFirewall and vLoadBalancer", eventNames,
86                 containsInAnyOrder("Mfvs_eNodeB_RANKPI", "vLoadBalancer"));
87     }
88
89     @Test
90     public void testGetPolicyEventNamesSupplier() throws Exception {
91         final TCAPolicy sampleTCAPolicy = getSampleTCAPolicy();
92         final Supplier<List<String>> policyEventNamesSupplier = TCAUtils.getPolicyEventNamesSupplier
93                 (sampleTCAPolicy);
94         final List<String> eventNames = policyEventNamesSupplier.get();
95         assertThat("Policy event names must contain vFirewall and vLoadBalancer", eventNames,
96                 containsInAnyOrder("Mfvs_eNodeB_RANKPI", "vLoadBalancer"));
97     }
98
99     @Test
100     public void testProcessCEFMessage() throws Exception {
101         final String cefMessageString = fromStream(CEF_MESSAGE_JSON_FILE_LOCATION);
102         final TCACEFProcessorContext tcacefProcessorContext = TCAUtils.filterCEFMessage(cefMessageString,
103                 getSampleTCAPolicy());
104         assertThat("TCAECEFProcessor Processor Context can continue flag is true", tcacefProcessorContext
105                 .canProcessingContinue(), is(true));
106     }
107
108     @Test
109     public void testGetPolicyFRThresholdsTableSupplier() throws Exception {
110         final Table<String, String, List<Threshold>> policyFRThresholdPathTable = TCAUtils
111                 .getPolicyEventNameThresholdsTableSupplier(getSampleTCAPolicy()).get();
112
113         final Map<String, List<Threshold>> eNodeBRankpi = policyFRThresholdPathTable.row("Mfvs_eNodeB_RANKPI");
114         final Map<String, List<Threshold>> vLoadBalancer = policyFRThresholdPathTable.row("vLoadBalancer");
115
116         final Set<String> eNodeBRankpiFieldPaths = eNodeBRankpi.keySet();
117         final Set<String> vLoadBalancerPaths = vLoadBalancer.keySet();
118
119         final String receivedBroadcastPacketsFieldPath =
120                 "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated";
121         assertThat("eNodeBRankpi threshold field path size must be " +
122                         "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*]" +
123                         ".receivedBroadcastPacketsAccumulated",
124                 eNodeBRankpiFieldPaths.iterator().next(),
125                 is(receivedBroadcastPacketsFieldPath));
126
127         assertThat("vLoadBalancer threshold field path size must be " +
128                         "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*]" +
129                         ".receivedBroadcastPacketsAccumulated",
130                 vLoadBalancerPaths.iterator().next(),
131                 is(receivedBroadcastPacketsFieldPath));
132
133         final List<Threshold> eNodeBRankpiThresholds = policyFRThresholdPathTable.get("Mfvs_eNodeB_RANKPI",
134                 receivedBroadcastPacketsFieldPath);
135         final List<Threshold> vLoadBalancerThresholds = policyFRThresholdPathTable.get("vLoadBalancer",
136                 receivedBroadcastPacketsFieldPath);
137
138         assertThat("eNodeBRankpi Threshold size must be 3", eNodeBRankpiThresholds.size(), is(3));
139         assertThat("vLoadBalancer Threshold size must be 2", vLoadBalancerThresholds.size(), is(2));
140     }
141
142     @Test
143     public void testGetJsonPathValueWithValidMessageAndPolicy() throws Exception {
144         final String cefMessageString = fromStream(CEF_MESSAGE_JSON_FILE_LOCATION);
145         final String jsonPath =
146                 "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated";
147         final ImmutableSet<String> fieldPaths = ImmutableSet.of(jsonPath);
148         final Map<String, List<Long>> jsonPathValueMap = TCAUtils.getJsonPathValue(cefMessageString, fieldPaths);
149         assertThat("Json Path value must match", jsonPathValueMap.get(jsonPath).get(0), is(5000L));
150
151     }
152
153     @Test
154     public void testGetJsonPathValueWithValidPath() throws Exception {
155         final String cefMessageString = fromStream(CEF_MESSAGE_JSON_FILE_LOCATION);
156         final String jsonPath = "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].invalid";
157         final ImmutableSet<String> fieldPaths = ImmutableSet.of(jsonPath);
158         final Map<String, List<Long>> jsonPathValueMap = TCAUtils.getJsonPathValue(cefMessageString, fieldPaths);
159         assertThat("Json path value must be empty", jsonPathValueMap.size(), is(0));
160
161     }
162
163
164     @Test
165     public void testCreateNewTCAVESResponseWithVFControlLoopSchemaType() throws Exception {
166         TCACEFProcessorContext tcacefProcessorContext = mock(TCACEFProcessorContext.class);
167
168         MetricsPerEventName metricsPerEventName = mock(MetricsPerEventName.class);
169         when(metricsPerEventName.getThresholds()).thenReturn(getThresholds());
170         when(metricsPerEventName.getPolicyScope()).thenReturn("Test Policy scope");
171         when(tcacefProcessorContext.getMetricsPerEventName()).thenReturn(metricsPerEventName);
172         when(metricsPerEventName.getEventName()).thenReturn("testEventName");
173         when(metricsPerEventName.getControlLoopSchemaType()).thenReturn(ControlLoopSchemaType.VM);
174
175         when(tcacefProcessorContext.getCEFEventListener()).thenReturn(getCEFEventListener());
176         TCAVESResponse tcaVESResponse = TCAUtils.createNewTCAVESResponse(tcacefProcessorContext, "TCA_APP_NAME");
177
178         //TODO :  Add proper assertions, as the usage is not clearly understood
179         assertThat(tcaVESResponse.getClosedLoopControlName(),
180                 is("CL-LBAL-LOW-TRAFFIC-SIG-FB480F95-A453-6F24-B767-FD703241AB1A"));
181         assertThat(tcaVESResponse.getVersion(), is("Test Version"));
182         assertThat(tcaVESResponse.getPolicyScope(), is("Test Policy scope"));
183         assertNull(tcaVESResponse.getAai().getGenericVNFId());
184         assertNotNull(tcaVESResponse.getAai().getGenericServerId());
185     }
186
187     @Test
188     public void testCreateNewTCAVESResponseWithFunctionalRolevFirewall() throws Exception {
189         TCACEFProcessorContext tcacefProcessorContext = mock(TCACEFProcessorContext.class);
190
191         MetricsPerEventName metricsPerEventName = mock(MetricsPerEventName.class);
192         when(metricsPerEventName.getThresholds()).thenReturn(getThresholds());
193         when(metricsPerEventName.getPolicyScope()).thenReturn("Test Policy scope");
194         when(tcacefProcessorContext.getMetricsPerEventName()).thenReturn(metricsPerEventName);
195         when(metricsPerEventName.getEventName()).thenReturn("vFirewall");
196
197         when(tcacefProcessorContext.getCEFEventListener()).thenReturn(getCEFEventListener());
198         TCAVESResponse tcaVESResponse = TCAUtils.createNewTCAVESResponse(tcacefProcessorContext, "TCA_APP_NAME");
199
200         //TODO :  Add proper assertions, as the usage is not clearly understood
201         assertThat(tcaVESResponse.getClosedLoopControlName(),
202                 is("CL-LBAL-LOW-TRAFFIC-SIG-FB480F95-A453-6F24-B767-FD703241AB1A"));
203         assertThat(tcaVESResponse.getVersion(), is("Test Version"));
204         assertThat(tcaVESResponse.getPolicyScope(), is("Test Policy scope"));
205         assertNotNull(tcaVESResponse.getAai().getGenericVNFId());
206         assertNull(tcaVESResponse.getAai().getGenericServerId());
207     }
208
209     @Rule
210     public ExpectedException expectedIllegalArgumentException = ExpectedException.none();
211
212     @Test
213     public void testCreateNewTCAVESResponseNullFunctionalRole() throws Exception {
214         expectedIllegalArgumentException.expect(MessageProcessingException.class);
215         expectedIllegalArgumentException.expectCause(isA(IllegalArgumentException.class));
216         expectedIllegalArgumentException.expectMessage("No violations metrics. Unable to create VES Response");
217
218         TCACEFProcessorContext tcacefProcessorContext = mock(TCACEFProcessorContext.class);
219         TCAVESResponse tcaVESResponse = TCAUtils.createNewTCAVESResponse(tcacefProcessorContext, "TCA_APP_NAME");
220         assertNotNull(tcaVESResponse.getClosedLoopControlName());
221     }
222
223     @Test
224     public void testPrioritizeThresholdViolations() throws Exception {
225
226         Map<String, Threshold> thresholdMap = new HashMap<>();
227         Threshold majorThreshold = mock(Threshold.class);
228         when(majorThreshold.getSeverity()).thenReturn(EventSeverity.MAJOR);
229         thresholdMap.put("MAJOR", majorThreshold);
230
231         Threshold result1 = TCAUtils.prioritizeThresholdViolations(thresholdMap);
232         assertEquals(result1.getSeverity(), EventSeverity.MAJOR);
233
234         Threshold criticalThreshold = mock(Threshold.class);
235         when(criticalThreshold.getSeverity()).thenReturn(EventSeverity.CRITICAL);
236         thresholdMap.put("CRITICAL", criticalThreshold);
237
238         Threshold result2 = TCAUtils.prioritizeThresholdViolations(thresholdMap);
239         assertEquals(result2.getSeverity(), EventSeverity.CRITICAL);
240     }
241
242     @Test
243     public void testCreateViolatedMetrics() throws Exception {
244         TCAPolicy tcaPolicy = getSampleTCAPolicy();
245         Threshold violatedThreshold = getCriticalThreshold();
246         String functionalRole = "Mfvs_eNodeB_RANKPI";
247         MetricsPerEventName result = TCAUtils.createViolatedMetrics(tcaPolicy, violatedThreshold, functionalRole);
248         assertThat(result.getPolicyScope(), is("resource=vFirewall;type=configuration"));
249         assertThat(result.getPolicyName(), is("configuration.dcae.microservice.tca.xml"));
250     }
251
252     @Test
253     public void testCreateViolatedMetricsWrongEventName() throws Exception {
254         expectedIllegalArgumentException.expect(MessageProcessingException.class);
255         expectedIllegalArgumentException.expectCause(isA(IllegalStateException.class));
256         String eventName = "badEventName";
257         expectedIllegalArgumentException.expectMessage("TCA Policy must contain eventName: " + eventName);
258         TCAPolicy tcaPolicy = getSampleTCAPolicy();
259         Threshold violatedThreshold = getCriticalThreshold();
260         TCAUtils.createViolatedMetrics(tcaPolicy, violatedThreshold, eventName);
261     }
262
263     @Test
264     public void testGetDomainAndEventName() {
265         TCACEFProcessorContext tcacefProcessorContext = mock(TCACEFProcessorContext.class);
266         EventListener eventListener = mock(EventListener.class);
267         Event event = mock(Event.class);
268         CommonEventHeader commonEventHeader = mock(CommonEventHeader.class);
269
270         Pair<String, String> result = TCAUtils.getDomainAndEventName(tcacefProcessorContext);
271         assertNull(result.getLeft());
272         assertNull(result.getRight());
273
274         when(tcacefProcessorContext.getCEFEventListener()).thenReturn(eventListener);
275         result = TCAUtils.getDomainAndEventName(tcacefProcessorContext);
276         assertNull(result.getLeft());
277         assertNull(result.getRight());
278
279         when(eventListener.getEvent()).thenReturn(event);
280         result = TCAUtils.getDomainAndEventName(tcacefProcessorContext);
281         assertNull(result.getLeft());
282         assertNull(result.getRight());
283
284         when(event.getCommonEventHeader()).thenReturn(commonEventHeader);
285         result = TCAUtils.getDomainAndEventName(tcacefProcessorContext);
286         assertNull(result.getLeft());
287         assertNull(result.getRight());
288
289         when(commonEventHeader.getDomain()).thenReturn(Domain.other);
290         when(commonEventHeader.getEventName()).thenReturn("eventName");
291
292         result = TCAUtils.getDomainAndEventName(tcacefProcessorContext);
293         assertEquals(result.getLeft(), "other");
294         assertEquals(result.getRight(), "eventName");
295
296     }
297
298     @Test
299     public void testComputeThresholdViolationsNotPresent() throws Exception {
300         TCACEFProcessorContext tcacefProcessorContext = mock(TCACEFProcessorContext.class);
301         when(tcacefProcessorContext.canProcessingContinue()).thenReturn(true);
302         when(tcacefProcessorContext.getMessage()).thenReturn(getValidCEFMessage());
303
304         when(tcacefProcessorContext.getTCAPolicy()).thenReturn(getSampleTCAPolicy());
305         when(tcacefProcessorContext.getCEFEventListener()).thenReturn(getCEFEventListener());
306
307         TCACEFProcessorContext result = TCAUtils.computeThresholdViolations(tcacefProcessorContext);
308         assertNotNull(result);
309         verify(result, times(0)).setMetricsPerEventName(Mockito.any(MetricsPerEventName.class));
310         assertEquals("Policy must not change", getSampleTCAPolicy(), result.getTCAPolicy());
311     }
312
313     @Test
314     public void testComputeThresholdViolationsPresent() throws Exception {
315         TCACEFProcessorContext tcacefProcessorContext = mock(TCACEFProcessorContext.class);
316         when(tcacefProcessorContext.canProcessingContinue()).thenReturn(true);
317         final String cefMessageString = fromStream(CEF_MESSAGE_WITH_THRESHOLD_VIOLATION_JSON_FILE_LOCATION);
318         when(tcacefProcessorContext.getMessage()).thenReturn(cefMessageString);
319
320         when(tcacefProcessorContext.getTCAPolicy()).thenReturn(getSampleTCAPolicy());
321         when(tcacefProcessorContext.getCEFEventListener()).thenReturn(getCEFEventListener());
322
323         TCACEFProcessorContext result = TCAUtils.computeThresholdViolations(tcacefProcessorContext);
324         verify(result, times(1)).setMetricsPerEventName(Mockito.any(MetricsPerEventName.class));
325
326         assertEquals("Policy must not change", getSampleTCAPolicy(), result.getTCAPolicy());
327     }
328
329
330     @Test
331     public void testCreateTCAPolicyMetricsPerFunctionalRoleList() throws Exception {
332
333         final Map<String, String> tcaPolicyMap = TCAUtils.filterMapByKeyNamePrefix(getControllerRuntimeArguments(),
334                 AnalyticsConstants.TCA_POLICY_METRICS_PER_FUNCTIONAL_ROLE_PATH);
335
336         // determine functional Roles
337         final Map<String, Map<String, String>> functionalRolesMap =
338                 TCAUtils.extractSubTree(tcaPolicyMap, 2, 3, AnalyticsConstants.TCA_POLICY_DELIMITER);
339
340         final List<MetricsPerEventName> tcaPolicyMetricsPerEventNameList =
341                 TCAUtils.createTCAPolicyMetricsPerEventNameList(functionalRolesMap);
342
343         assertThat("There are two Metrics per function role", 2,
344                 is(tcaPolicyMetricsPerEventNameList.size()));
345     }
346
347
348     @Test
349     public void testCreateQuartzScheduler() throws Exception {
350         final Scheduler scheduler = Mockito.mock(Scheduler.class);
351         final StdSchedulerFactory stdSchedulerFactory = Mockito.mock(StdSchedulerFactory.class);
352         when(stdSchedulerFactory.getScheduler()).thenReturn(scheduler);
353         final JobDataMap jobDataMap = Mockito.mock(JobDataMap.class);
354         TCAUtils.createQuartzScheduler(1000, stdSchedulerFactory,
355                 "data/properties/quartz-test.properties", jobDataMap, Job.class,
356                 "testJob", "testTigger");
357         verify(scheduler, times(1))
358                 .scheduleJob(Mockito.any(JobDetail.class), Mockito.any(SimpleTrigger.class));
359     }
360
361
362     @Test
363     public void testCreateTCAAlertStringWhenCEFIsEnabled() throws Exception {
364         final MetricsPerEventName violatedMetrics = createViolatedMetricsPerEventName(EventSeverity.CRITICAL);
365         TCACEFProcessorContext processorContext = mock(TCACEFProcessorContext.class);
366         when(processorContext.getMetricsPerEventName()).thenReturn(violatedMetrics);
367         when(processorContext.getCEFEventListener()).thenReturn(getCEFEventListener());
368         final String alertString = TCAUtils.createTCAAlertString(processorContext, "testApp", true);
369         assertTrue(alertString.contains("thresholdCrossingAlertFields"));
370     }
371
372     @Test(expected = MessageProcessingException.class)
373     public void testCreateTCAAlertStringWhenViolatedMetricsNotPresentAndCEFIsEnabled() throws Exception {
374         TCACEFProcessorContext processorContext = mock(TCACEFProcessorContext.class);
375         when(processorContext.getMetricsPerEventName()).thenReturn(null);
376         TCAUtils.createTCAAlertString(processorContext, "testApp", true);
377     }
378
379     @Test
380     public void testCreateTCAAlertStringWhenCEFIsDisabled() throws Exception {
381         final MetricsPerEventName violatedMetrics = createViolatedMetricsPerEventName(EventSeverity.MAJOR);
382         TCACEFProcessorContext processorContext = mock(TCACEFProcessorContext.class);
383         when(processorContext.getMetricsPerEventName()).thenReturn(violatedMetrics);
384         when(processorContext.getCEFEventListener()).thenReturn(getCEFEventListener());
385         final String alertString = TCAUtils.createTCAAlertString(processorContext, "testApp", false);
386         assertFalse(alertString.contains("thresholdCrossingAlertFields"));
387     }
388
389     @Test(expected = MessageProcessingException.class)
390     public void testCreateTCAAlertStringWhenViolatedMetricsNotPresentAndCEFIsDisabled() throws Exception {
391         TCACEFProcessorContext processorContext = mock(TCACEFProcessorContext.class);
392         when(processorContext.getMetricsPerEventName()).thenReturn(null);
393         TCAUtils.createTCAAlertString(processorContext, "testApp", false);
394     }
395
396     private static MetricsPerEventName createViolatedMetricsPerEventName(EventSeverity severity) {
397         final Threshold violatedThreshold = new Threshold();
398         violatedThreshold.setSeverity(severity);
399         violatedThreshold.setDirection(Direction.GREATER);
400         violatedThreshold.setClosedLoopControlName("violatedThresholdClosedLoopName");
401         violatedThreshold.setActualFieldValue(100L);
402         violatedThreshold.setFieldPath("violatedThresholdFieldPath");
403         violatedThreshold.setVersion("violatedThresholdVersion");
404         violatedThreshold.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
405         violatedThreshold.setThresholdValue(50L);
406
407         final MetricsPerEventName violatedMetrics = new MetricsPerEventName();
408         violatedMetrics.setPolicyName("violatePolicyName");
409         violatedMetrics.setPolicyVersion("violatedPolicyVersion");
410         violatedMetrics.setPolicyScope("violatedPolicyScope");
411         violatedMetrics.setEventName("violatedEventName");
412         violatedMetrics.setThresholds(Arrays.asList(violatedThreshold));
413         return violatedMetrics;
414     }
415 }