Merge "Point to parent SNAPSHOT"
[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.Entity;
42 import javax.ws.rs.client.InvocationCallback;
43 import org.junit.AfterClass;
44 import org.junit.Before;
45 import org.junit.BeforeClass;
46 import org.junit.Test;
47 import org.mockito.ArgumentCaptor;
48 import org.mockito.Captor;
49 import org.mockito.Mock;
50 import org.onap.policy.aai.AaiConstants;
51 import org.onap.policy.aai.AaiCqResponse;
52 import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
53 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
54 import org.onap.policy.common.utils.coder.StandardCoder;
55 import org.onap.policy.common.utils.coder.StandardCoderObject;
56 import org.onap.policy.controlloop.actorserviceprovider.Operation;
57 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
58 import org.onap.policy.controlloop.actorserviceprovider.Util;
59 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
60 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
61 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
62 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
63 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
64 import org.onap.policy.controlloop.policy.PolicyResult;
65
66 public class AaiCustomQueryOperationTest extends BasicAaiOperation<Map<String, String>> {
67     private static final StandardCoder coder = new StandardCoder();
68
69     private static final String MY_LINK = "my-link";
70     private static final String MY_VSERVER = "my-vserver-name";
71     private static final String SIM_VSERVER = "OzVServer";
72
73     @Captor
74     private ArgumentCaptor<Entity<Map<String, String>>> entityCaptor;
75
76     @Mock
77     private Actor tenantActor;
78
79     private AaiCustomQueryOperation oper;
80
81     public AaiCustomQueryOperationTest() {
82         super(AaiConstants.ACTOR_NAME, AaiCustomQueryOperation.NAME);
83     }
84
85     @BeforeClass
86     public static void setUpBeforeClass() throws Exception {
87         initBeforeClass();
88     }
89
90     @AfterClass
91     public static void tearDownAfterClass() {
92         destroyAfterClass();
93     }
94
95     /**
96      * Sets up.
97      */
98     @Before
99     public void setUp() throws Exception {
100         super.setUpBasic();
101
102         params.getContext().getEnrichment().put(AaiCustomQueryOperation.VSERVER_VSERVER_NAME, MY_VSERVER);
103
104         MyTenantOperator tenantOperator = new MyTenantOperator();
105
106         when(service.getActor(AaiConstants.ACTOR_NAME)).thenReturn(tenantActor);
107         when(tenantActor.getOperator(AaiGetTenantOperation.NAME)).thenReturn(tenantOperator);
108
109         oper = new AaiCustomQueryOperation(params, config);
110     }
111
112     /**
113      * Tests "success" case with simulator.
114      */
115     @Test
116     public void testSuccess() throws Exception {
117         HttpParams opParams = HttpParams.builder().clientName(MY_CLIENT).path("v16/query").build();
118         config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
119
120         preloadTenantData();
121
122         params = params.toBuilder().targetEntity(SIM_VSERVER).retry(0).timeoutSec(5).executor(blockingExecutor).build();
123         oper = new AaiCustomQueryOperation(params, config);
124
125         outcome = oper.start().get();
126         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
127
128         String resp = outcome.getResponse();
129         assertThat(resp).isNotNull().contains("relationship-list");
130     }
131
132     @Test
133     public void testConstructor() {
134         assertEquals(AaiConstants.ACTOR_NAME, oper.getActorName());
135         assertEquals(AaiCustomQueryOperation.NAME, oper.getName());
136         assertEquals(MY_VSERVER, oper.getVserver());
137
138         // verify that it works with an empty target entity
139         params = params.toBuilder().targetEntity("").build();
140         assertThatCode(() -> new AaiCustomQueryOperation(params, config)).doesNotThrowAnyException();
141
142         // try without enrichment data
143         params.getContext().getEnrichment().remove(AaiCustomQueryOperation.VSERVER_VSERVER_NAME);
144         assertThatIllegalArgumentException().isThrownBy(() -> new AaiCustomQueryOperation(params, config))
145                         .withMessage("missing " + AaiCustomQueryOperation.VSERVER_VSERVER_NAME + " in enrichment data");
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(entityCaptor.capture(), any(InvocationCallback.class));
219
220         // sort the request fields so they match the order in cq.json
221         Map<String, String> request = new TreeMap<>(entityCaptor.getValue().getEntity());
222
223         verifyRequest("cq.json", request);
224     }
225
226     @Test
227     @SuppressWarnings("unchecked")
228     public void testMakeRequestNoResourceLink() throws Exception {
229         // pre-load EMPTY tenant data
230         preloadTenantData(new StandardCoderObject());
231
232         when(rawResponse.readEntity(String.class)).thenReturn(makeCqReply());
233         when(webAsync.put(any(), any(InvocationCallback.class))).thenAnswer(provideResponse(rawResponse, 1));
234
235         CompletableFuture<OperationOutcome> future2 = oper.start();
236
237         assertEquals(PolicyResult.FAILURE_EXCEPTION, getResult(future2));
238     }
239
240     private String makeTenantReply() throws Exception {
241         Map<String, String> links = Map.of(AaiCustomQueryOperation.RESOURCE_LINK, MY_LINK);
242         List<Map<String, String>> data = Arrays.asList(links);
243
244         Map<String, Object> reply = Map.of(AaiCustomQueryOperation.RESULT_DATA, data);
245         return coder.encode(reply);
246     }
247
248     private String makeCqReply() {
249         return "{}";
250     }
251
252     private StandardCoderObject preloadTenantData() throws Exception {
253         StandardCoderObject data = coder.decode(makeTenantReply(), StandardCoderObject.class);
254         preloadTenantData(data);
255         return data;
256     }
257
258     private void preloadTenantData(StandardCoderObject data) {
259         context.setProperty(AaiGetTenantOperation.getKey(MY_VSERVER), data);
260         context.setProperty(AaiGetTenantOperation.getKey(SIM_VSERVER), data);
261     }
262
263     private PolicyResult getResult(CompletableFuture<OperationOutcome> future2)
264                     throws InterruptedException, ExecutionException, TimeoutException {
265
266         executor.runAll(100);
267         assertTrue(future2.isDone());
268
269         return future2.get().getResult();
270     }
271
272     protected class MyTenantOperator extends HttpOperator {
273         public MyTenantOperator() {
274             super(AaiConstants.ACTOR_NAME, AaiGetTenantOperation.NAME);
275
276             HttpParams http = HttpParams.builder().clientName(MY_CLIENT).path(PATH).timeoutSec(1).build();
277
278             configure(Util.translateToMap(AaiGetTenantOperation.NAME, http));
279             start();
280         }
281
282         @Override
283         public Operation buildOperation(ControlLoopOperationParams params) {
284             return new AaiGetTenantOperation(params, getCurrentConfig());
285         }
286
287         @Override
288         protected HttpClientFactory getClientFactory() {
289             return factory;
290         }
291     }
292 }