Fix sonars from dependency upgrade
[policy/xacml-pdp.git] / applications / common / src / test / java / org / onap / policy / pdp / xacml / application / common / operationshistory / CountRecentOperationsPipTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019-2021 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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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=========================================================
17  */
18
19 package org.onap.policy.pdp.xacml.application.common.operationshistory;
20
21 import static org.assertj.core.api.Assertions.assertThatCode;
22 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
23 import static org.junit.Assert.assertEquals;
24 import static org.mockito.Mockito.when;
25
26 import com.att.research.xacml.api.Attribute;
27 import com.att.research.xacml.api.AttributeValue;
28 import com.att.research.xacml.api.Status;
29 import com.att.research.xacml.api.pip.PIPException;
30 import com.att.research.xacml.api.pip.PIPFinder;
31 import com.att.research.xacml.api.pip.PIPRequest;
32 import com.att.research.xacml.api.pip.PIPResponse;
33 import com.att.research.xacml.std.pip.StdPIPResponse;
34 import java.io.FileInputStream;
35 import java.io.IOException;
36 import java.sql.Date;
37 import java.time.Instant;
38 import java.util.Arrays;
39 import java.util.LinkedList;
40 import java.util.Properties;
41 import java.util.Queue;
42 import java.util.UUID;
43 import javax.persistence.EntityManager;
44 import javax.persistence.Persistence;
45 import javax.persistence.Query;
46 import org.junit.AfterClass;
47 import org.junit.Before;
48 import org.junit.BeforeClass;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.Mock;
52 import org.mockito.junit.MockitoJUnitRunner;
53 import org.onap.policy.guard.OperationsHistory;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 @RunWith(MockitoJUnitRunner.class)
58 public class CountRecentOperationsPipTest {
59     private static final Logger LOGGER = LoggerFactory.getLogger(CountRecentOperationsPipTest.class);
60
61     private static final String ACTOR = "my-actor";
62     private static final String RECIPE = "my-recipe";
63     private static final String TARGET = "my-target";
64     private static final String TEST_PROPERTIES = "src/test/resources/test.properties";
65
66     private static EntityManager em;
67
68     @Mock
69     private PIPRequest pipRequest;
70
71     @Mock
72     private PIPFinder pipFinder;
73
74     @Mock
75     private PIPResponse resp1;
76
77     @Mock
78     private PIPResponse resp2;
79
80     @Mock
81     private PIPResponse resp3;
82
83     @Mock
84     private Status okStatus;
85
86     private Properties properties;
87     private Queue<PIPResponse> responses;
88     private Queue<String> attributes;
89
90     private CountRecentOperationsPip pipEngine;
91
92     /**
93      * Establishes a connection to the DB and keeps it open until all tests have
94      * completed.
95      *
96      * @throws IOException if properties cannot be loaded
97      */
98     @BeforeClass
99     public static void setUpBeforeClass() throws IOException {
100         //
101         // Load our test properties to use
102         //
103         Properties props2 = new Properties();
104         try (FileInputStream is = new FileInputStream(TEST_PROPERTIES)) {
105             props2.load(is);
106         }
107         //
108         // Connect to in-mem db
109         //
110         String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit";
111         LOGGER.info("persistenceunit {}", persistenceUnit);
112         em = Persistence.createEntityManagerFactory(props2.getProperty(persistenceUnit), props2).createEntityManager();
113         //
114         //
115         //
116         LOGGER.info("Configured own entity manager", em.toString());
117     }
118
119     /**
120      * Close the entity manager.
121      */
122     @AfterClass
123     public static void cleanup() {
124         if (em != null) {
125             em.close();
126         }
127     }
128
129     /**
130      * Create an instance of our engine.
131      *
132      * @throws Exception if an error occurs
133      */
134     @Before
135     public void setUp() throws Exception {
136         when(pipRequest.getIssuer()).thenReturn("urn:org:onap:xacml:guard:tw:1:hour");
137
138         pipEngine = new MyPip();
139
140         properties = new Properties();
141         try (FileInputStream is = new FileInputStream(TEST_PROPERTIES)) {
142             properties.load(is);
143         }
144
145         responses = new LinkedList<>(Arrays.asList(resp1, resp2, resp3));
146         attributes = new LinkedList<>(Arrays.asList(ACTOR, RECIPE, TARGET));
147     }
148
149     @Test
150     public void testAttributesRequired() {
151         assertEquals(3, pipEngine.attributesRequired().size());
152     }
153
154     @Test
155     public void testConfigure_DbException() throws Exception {
156         properties.put("javax.persistence.jdbc.url", "invalid");
157         assertThatCode(() ->
158             pipEngine.configure("issuer", properties)
159         ).doesNotThrowAnyException();
160     }
161
162     @Test
163     public void testGetAttributes_NullIssuer() throws PIPException {
164         when(pipRequest.getIssuer()).thenReturn(null);
165         assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder));
166     }
167
168     @Test
169     public void testGetAttributes_WrongIssuer() throws PIPException {
170         when(pipRequest.getIssuer()).thenReturn("wrong-issuer");
171         assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder));
172     }
173
174     @Test
175     public void testGetAttributes_NullActor() throws PIPException {
176         attributes = new LinkedList<>(Arrays.asList(null, RECIPE, TARGET));
177         assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder));
178     }
179
180     @Test
181     public void testGetAttributes_NullRecipe() throws PIPException {
182         attributes = new LinkedList<>(Arrays.asList(ACTOR, null, TARGET));
183         assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder));
184     }
185
186     @Test
187     public void testGetAttributes_NullTarget() throws PIPException {
188         attributes = new LinkedList<>(Arrays.asList(ACTOR, RECIPE, null));
189         assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(pipRequest, pipFinder));
190     }
191
192     @Test
193     public void testShutdown() {
194         pipEngine.shutdown();
195         assertThatExceptionOfType(PIPException.class).isThrownBy(() -> pipEngine.getAttributes(pipRequest, pipFinder))
196             .withMessageContaining("Engine is shutdown");
197     }
198
199     @Test
200     public void testGetCountFromDb() throws Exception {
201         //
202         // Configure it using properties
203         //
204         pipEngine.configure("issuer", properties);
205         LOGGER.info("PIP configured now creating our entity manager");
206         LOGGER.info("properties {}", properties);
207         //
208         // create entry
209         //
210         OperationsHistory newEntry = createEntry("cl-foobar-1", "vnf-1", "SUCCESS");
211         //
212         // No entries yet
213         //
214         assertEquals(0, getCount(newEntry));
215         //
216         // Add entry
217         //
218         em.getTransaction().begin();
219         em.persist(newEntry);
220         em.getTransaction().commit();
221         //
222         // Directly check ground truth
223         //
224         Query queryCount = em.createNativeQuery("select count(*) as numops from operationshistory").setParameter(1, 1);
225         LOGGER.info("{} entries", queryCount.getSingleResult());
226         //
227         // Should count 1 entry now
228         //
229         assertEquals(1, getCount(newEntry));
230     }
231
232     @Test
233     public void testStringToChronoUnit() throws PIPException {
234         // not configured yet
235         OperationsHistory newEntry = createEntry("cl-foobar-1", "vnf-1", "SUCCESS");
236         assertEquals(-1, getCount(newEntry));
237
238         // now configure it
239         pipEngine.configure("issuer", properties);
240
241         String[] units = {"second", "minute", "hour", "day", "week", "month", "year"};
242
243         for (String unit : units) {
244             when(pipRequest.getIssuer()).thenReturn("urn:org:onap:xacml:guard:tw:1:" + unit);
245
246             /*
247              * It would be better to use assertEquals below, but the test DB doesn't
248              * support week, month, or year.
249              */
250
251             // should run without throwing an exception
252             getCount(newEntry);
253         }
254
255         // invalid time unit
256         when(pipRequest.getIssuer()).thenReturn("urn:org:onap:xacml:guard:tw:1:invalid");
257         assertEquals(-1, getCount(newEntry));
258     }
259
260     private long getCount(OperationsHistory newEntry) throws PIPException {
261         responses = new LinkedList<>(Arrays.asList(resp1, resp2, resp3));
262         attributes = new LinkedList<>(
263                         Arrays.asList(newEntry.getActor(), newEntry.getOperation(), newEntry.getTarget()));
264
265         PIPResponse result = pipEngine.getAttributes(pipRequest, pipFinder);
266
267         Attribute attr = result.getAttributes().iterator().next();
268         AttributeValue<?> value = attr.getValues().iterator().next();
269
270         return ((Number) value.getValue()).longValue();
271     }
272
273     private OperationsHistory createEntry(String cl, String target, String outcome) {
274         //
275         // Create entry
276         //
277         OperationsHistory newEntry = new OperationsHistory();
278         newEntry.setClosedLoopName(cl);
279         newEntry.setTarget(target);
280         newEntry.setOutcome(outcome);
281         newEntry.setActor("Controller");
282         newEntry.setOperation("operationA");
283         newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000)));
284         newEntry.setEndtime(Date.from(Instant.now()));
285         newEntry.setRequestId(UUID.randomUUID().toString());
286         return newEntry;
287     }
288
289     private class MyPip extends CountRecentOperationsPip {
290
291         @Override
292         protected PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
293             return responses.remove();
294         }
295
296         @Override
297         protected String findFirstAttributeValue(PIPResponse pipResponse) {
298             return attributes.remove();
299         }
300     }
301 }