40009650737e4cc455120ec021a915c4ab4a5ab0
[policy/models.git] / models-interactions / model-actors / actor.aai / src / test / java / org / onap / policy / controlloop / actor / aai / AaiCustomQueryOperationTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020 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.policy.controlloop.actor.aai;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.assertj.core.api.Assertions.assertThatCode;
25 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertSame;
29 import static org.junit.Assert.assertTrue;
30 import static org.mockito.ArgumentMatchers.any;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33
34 import java.util.Arrays;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.TreeMap;
38 import java.util.concurrent.CompletableFuture;
39 import java.util.concurrent.ExecutionException;
40 import java.util.concurrent.TimeoutException;
41 import javax.ws.rs.client.InvocationCallback;
42 import org.junit.AfterClass;
43 import org.junit.Before;
44 import org.junit.BeforeClass;
45 import org.junit.Test;
46 import org.mockito.Mock;
47 import org.onap.policy.aai.AaiConstants;
48 import org.onap.policy.aai.AaiCqResponse;
49 import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
50 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
51 import org.onap.policy.common.utils.coder.StandardCoder;
52 import org.onap.policy.common.utils.coder.StandardCoderObject;
53 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
54 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
55 import org.onap.policy.controlloop.actorserviceprovider.Util;
56 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
57 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
58 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
59 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
60 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
61 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
62 import org.onap.policy.controlloop.policy.PolicyResult;
63
64 public class AaiCustomQueryOperationTest extends BasicAaiOperation {
65     private static final StandardCoder coder = new StandardCoder();
66
67     private static final String MY_LINK = "my-link";
68     private static final String MY_VSERVER = "my-vserver-name";
69     private static final String SIM_VSERVER = "OzVServer";
70
71     @Mock
72     private Actor tenantActor;
73
74     private AaiCustomQueryOperation oper;
75
76     public AaiCustomQueryOperationTest() {
77         super(AaiConstants.ACTOR_NAME, AaiCustomQueryOperation.NAME);
78     }
79
80     @BeforeClass
81     public static void setUpBeforeClass() throws Exception {
82         initBeforeClass();
83     }
84
85     @AfterClass
86     public static void tearDownAfterClass() {
87         destroyAfterClass();
88     }
89
90     /**
91      * Sets up.
92      */
93     @Before
94     public void setUp() throws Exception {
95         super.setUpBasic();
96
97         params.getContext().getEnrichment().put(AaiCustomQueryOperation.VSERVER_VSERVER_NAME, MY_VSERVER);
98
99         MyTenantOperator tenantOperator = new MyTenantOperator();
100
101         when(service.getActor(AaiConstants.ACTOR_NAME)).thenReturn(tenantActor);
102         when(tenantActor.getOperator(AaiGetTenantOperation.NAME)).thenReturn(tenantOperator);
103
104         oper = new AaiCustomQueryOperation(params, config);
105     }
106
107     /**
108      * Tests "success" case with simulator.
109      */
110     @Test
111     public void testSuccess() throws Exception {
112         HttpParams opParams = HttpParams.builder().clientName(MY_CLIENT).path("v16/query").build();
113         config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
114
115         preloadTenantData();
116
117         params = params.toBuilder().targetEntity(SIM_VSERVER).retry(0).timeoutSec(5).executor(blockingExecutor).build();
118         oper = new AaiCustomQueryOperation(params, config);
119
120         outcome = oper.start().get();
121         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
122
123         String resp = outcome.getResponse();
124         assertThat(resp).isNotNull().contains("relationship-list");
125     }
126
127     @Test
128     public void testConstructor() {
129         assertEquals(AaiConstants.ACTOR_NAME, oper.getActorName());
130         assertEquals(AaiCustomQueryOperation.NAME, oper.getName());
131         assertEquals(MY_VSERVER, oper.getVserver());
132
133         // verify that it works with an empty target entity
134         params = params.toBuilder().targetEntity("").build();
135         assertThatCode(() -> new AaiCustomQueryOperation(params, config)).doesNotThrowAnyException();
136
137         // try without enrichment data
138         params.getContext().getEnrichment().remove(AaiCustomQueryOperation.VSERVER_VSERVER_NAME);
139         assertThatIllegalArgumentException().isThrownBy(() -> new AaiCustomQueryOperation(params, config))
140                         .withMessage("missing " + AaiCustomQueryOperation.VSERVER_VSERVER_NAME + " in enrichment data");
141     }
142
143     @Test
144     public void testGetPropertyNames() {
145         assertThat(oper.getPropertyNames()).isEqualTo(List.of(OperationProperties.AAI_VSERVER_LINK));
146     }
147
148     @Test
149     public void testGenerateSubRequestId() {
150         oper.generateSubRequestId(3);
151         assertEquals("3", oper.getSubRequestId());
152     }
153
154     @Test
155     @SuppressWarnings("unchecked")
156     public void testStartOperationAsync_testStartPreprocessorAsync_testMakeRequest_testPostProcess() throws Exception {
157         // need two responses
158         when(rawResponse.readEntity(String.class)).thenReturn(makeTenantReply()).thenReturn(makeCqReply());
159         when(webAsync.get(any(InvocationCallback.class))).thenAnswer(provideResponse(rawResponse));
160         when(webAsync.put(any(), any(InvocationCallback.class))).thenAnswer(provideResponse(rawResponse, 1));
161
162         CompletableFuture<OperationOutcome> future2 = oper.start();
163
164         assertEquals(PolicyResult.SUCCESS, getResult(future2));
165
166         // tenant response should have been cached within the context
167         assertNotNull(context.getProperty(AaiGetTenantOperation.getKey(MY_VSERVER)));
168
169         // custom query response should have been cached within the context
170         AaiCqResponse cqData = context.getProperty(AaiCqResponse.CONTEXT_KEY);
171         assertNotNull(cqData);
172
173         assertEquals("1", future2.get().getSubRequestId());
174     }
175
176     /**
177      * Tests when preprocessor step is not needed.
178      */
179     @Test
180     @SuppressWarnings("unchecked")
181     public void testStartOperationAsync_testStartPreprocessorAsyncNotNeeded() throws Exception {
182         // pre-load the tenant data
183         final StandardCoderObject data = preloadTenantData();
184
185         // only need one response
186         when(rawResponse.readEntity(String.class)).thenReturn(makeCqReply());
187         when(webAsync.put(any(), any(InvocationCallback.class))).thenAnswer(provideResponse(rawResponse, 1));
188
189         CompletableFuture<OperationOutcome> future2 = oper.start();
190
191         assertEquals(PolicyResult.SUCCESS, getResult(future2));
192
193         // should not have replaced tenant response
194         assertSame(data, context.getProperty(AaiGetTenantOperation.getKey(MY_VSERVER)));
195
196         // custom query response should have been cached within the context
197         AaiCqResponse cqData = context.getProperty(AaiCqResponse.CONTEXT_KEY);
198         assertNotNull(cqData);
199     }
200
201     @Test
202     public void testMakeHeaders() {
203         verifyHeaders(oper.makeHeaders());
204     }
205
206     @Test
207     @SuppressWarnings("unchecked")
208     public void testMakeRequest() throws Exception {
209         // preload
210         preloadTenantData();
211
212         when(rawResponse.readEntity(String.class)).thenReturn(makeCqReply());
213         when(webAsync.put(any(), any(InvocationCallback.class))).thenAnswer(provideResponse(rawResponse, 1));
214
215         oper.start();
216         executor.runAll(100);
217
218         verify(webAsync).put(requestCaptor.capture(), any(InvocationCallback.class));
219
220         String reqText = requestCaptor.getValue().getEntity();
221         Map<String, String> reqMap = coder.decode(reqText, Map.class);
222
223         // sort the request fields so they match the order in cq.json
224         Map<String, String> request = new TreeMap<>(reqMap);
225
226         verifyRequest("cq.json", request);
227     }
228
229     @Test
230     @SuppressWarnings("unchecked")
231     public void testMakeRequestNoResourceLink() throws Exception {
232         // pre-load EMPTY tenant data
233         preloadTenantData(new StandardCoderObject());
234
235         when(rawResponse.readEntity(String.class)).thenReturn(makeCqReply());
236         when(webAsync.put(any(), any(InvocationCallback.class))).thenAnswer(provideResponse(rawResponse, 1));
237
238         CompletableFuture<OperationOutcome> future2 = oper.start();
239
240         assertEquals(PolicyResult.FAILURE_EXCEPTION, getResult(future2));
241     }
242
243     private String makeTenantReply() throws Exception {
244         Map<String, String> links = Map.of(AaiCustomQueryOperation.RESOURCE_LINK, MY_LINK);
245         List<Map<String, String>> data = Arrays.asList(links);
246
247         Map<String, Object> reply = Map.of(AaiCustomQueryOperation.RESULT_DATA, data);
248         return coder.encode(reply);
249     }
250
251     private String makeCqReply() {
252         return "{}";
253     }
254
255     private StandardCoderObject preloadTenantData() throws Exception {
256         StandardCoderObject data = coder.decode(makeTenantReply(), StandardCoderObject.class);
257         preloadTenantData(data);
258         return data;
259     }
260
261     private void preloadTenantData(StandardCoderObject data) {
262         context.setProperty(AaiGetTenantOperation.getKey(MY_VSERVER), data);
263         context.setProperty(AaiGetTenantOperation.getKey(SIM_VSERVER), data);
264     }
265
266     private PolicyResult getResult(CompletableFuture<OperationOutcome> future2)
267                     throws InterruptedException, ExecutionException, TimeoutException {
268
269         executor.runAll(100);
270         assertTrue(future2.isDone());
271
272         return future2.get().getResult();
273     }
274
275     protected class MyTenantOperator extends HttpOperator {
276         public MyTenantOperator() {
277             super(AaiConstants.ACTOR_NAME, AaiGetTenantOperation.NAME);
278
279             HttpParams http = HttpParams.builder().clientName(MY_CLIENT).path(PATH).timeoutSec(1).build();
280
281             configure(Util.translateToMap(AaiGetTenantOperation.NAME, http));
282             start();
283         }
284
285         @Override
286         public HttpOperation<?> buildOperation(ControlLoopOperationParams params) {
287             return new AaiGetTenantOperation(params, getCurrentConfig());
288         }
289
290         @Override
291         protected HttpClientFactory getClientFactory() {
292             return factory;
293         }
294     }
295 }