25d383eb8d5a3db465ed7b021575b9c226772558
[policy/models.git] /
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.sdnc;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNotNull;
25
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.concurrent.CompletableFuture;
29 import java.util.concurrent.ExecutionException;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.TimeoutException;
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.POST;
34 import javax.ws.rs.Path;
35 import javax.ws.rs.Produces;
36 import javax.ws.rs.core.Response;
37 import javax.ws.rs.core.Response.Status;
38 import lombok.Setter;
39 import org.junit.After;
40 import org.junit.AfterClass;
41 import org.junit.Before;
42 import org.junit.BeforeClass;
43 import org.junit.Test;
44 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
45 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams.TopicParamsBuilder;
46 import org.onap.policy.common.endpoints.http.client.HttpClient;
47 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
48 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
49 import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
50 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
51 import org.onap.policy.common.gson.GsonMessageBodyHandler;
52 import org.onap.policy.common.utils.coder.CoderException;
53 import org.onap.policy.common.utils.coder.StandardCoder;
54 import org.onap.policy.common.utils.network.NetworkUtil;
55 import org.onap.policy.controlloop.VirtualControlLoopEvent;
56 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
57 import org.onap.policy.controlloop.actorserviceprovider.Util;
58 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
59 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
60 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
61 import org.onap.policy.controlloop.policy.PolicyResult;
62 import org.onap.policy.sdnc.SdncHealRequest;
63 import org.onap.policy.sdnc.SdncRequest;
64 import org.onap.policy.sdnc.SdncResponse;
65 import org.onap.policy.sdnc.SdncResponseOutput;
66
67 public class SdncOperatorTest {
68     public static final String MEDIA_TYPE_APPLICATION_JSON = "application/json";
69     private static final String EXPECTED_EXCEPTION = "expected exception";
70     public static final String HTTP_CLIENT = "my-http-client";
71     public static final String HTTP_NO_SERVER = "my-http-no-server-client";
72     private static final String ACTOR = "my-actor";
73     private static final String OPERATION = "my-operation";
74
75     /**
76      * Outcome to be added to the response.
77      */
78     @Setter
79     private static SdncResponseOutput output;
80
81
82     private VirtualControlLoopEvent event;
83     private ControlLoopEventContext context;
84     private MyOper oper;
85
86     /**
87      * Starts the SDNC simulator.
88      */
89     @BeforeClass
90     public static void setUpBeforeClass() throws Exception {
91         // allocate a port
92         int port = NetworkUtil.allocPort();
93
94         /*
95          * Start the simulator. Must use "Properties" to configure it, otherwise the
96          * server will use the wrong serialization provider.
97          */
98         Properties svrprops = getServerProperties("my-server", port);
99         HttpServletServerFactoryInstance.getServerFactory().build(svrprops).forEach(HttpServletServer::start);
100
101         /*
102          * Start the clients, one to the server, and one to a non-existent server.
103          */
104         TopicParamsBuilder builder = BusTopicParams.builder().managed(true).hostname("localhost").basePath("sdnc")
105                         .serializationProvider(GsonMessageBodyHandler.class.getName());
106
107         HttpClientFactoryInstance.getClientFactory().build(builder.clientName(HTTP_CLIENT).port(port).build());
108
109         HttpClientFactoryInstance.getClientFactory()
110                         .build(builder.clientName(HTTP_NO_SERVER).port(NetworkUtil.allocPort()).build());
111     }
112
113     @AfterClass
114     public static void tearDownAfterClass() {
115         HttpClientFactoryInstance.getClientFactory().destroy();
116         HttpServletServerFactoryInstance.getServerFactory().destroy();
117     }
118
119     /**
120      * Initializes {@link #oper} and sets {@link #output} to a success code.
121      */
122     @Before
123     public void setUp() {
124         event = new VirtualControlLoopEvent();
125         context = new ControlLoopEventContext(event);
126
127         initOper(HTTP_CLIENT);
128
129         output = new SdncResponseOutput();
130         output.setResponseCode("200");
131     }
132
133     @After
134     public void tearDown() {
135         oper.shutdown();
136     }
137
138     @Test
139     public void testSdncOperator() {
140         assertEquals(ACTOR, oper.getActorName());
141         assertEquals(OPERATION, oper.getName());
142         assertEquals(ACTOR + "." + OPERATION, oper.getFullName());
143     }
144
145     @Test
146     public void testGetClient() {
147         assertNotNull(oper.getTheClient());
148     }
149
150     @Test
151     public void testStartOperationAsync_testPostRequest() throws Exception {
152         OperationOutcome outcome = runOperation();
153         assertNotNull(outcome);
154         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
155     }
156
157     /**
158      * Tests postRequest() when decode() throws an exception.
159      */
160     @Test
161     public void testPostRequestDecodeException() throws Exception {
162
163         oper.setDecodeFailure(true);
164
165         OperationOutcome outcome = runOperation();
166         assertNotNull(outcome);
167         assertEquals(PolicyResult.FAILURE_EXCEPTION, outcome.getResult());
168     }
169
170     /**
171      * Tests postRequest() when there is no "output" field in the response.
172      */
173     @Test
174     public void testPostRequestNoOutput() throws Exception {
175
176         setOutput(null);
177
178         OperationOutcome outcome = runOperation();
179         assertNotNull(outcome);
180         assertEquals(PolicyResult.FAILURE, outcome.getResult());
181     }
182
183     /**
184      * Tests postRequest() when the output is not a success.
185      */
186     @Test
187     public void testPostRequestOutputFailure() throws Exception {
188
189         output.setResponseCode(null);
190
191         OperationOutcome outcome = runOperation();
192         assertNotNull(outcome);
193         assertEquals(PolicyResult.FAILURE, outcome.getResult());
194     }
195
196     /**
197      * Tests postRequest() when the post() request throws an exception retrieving the
198      * response.
199      */
200     @Test
201     public void testPostRequestException() throws Exception {
202
203         // reset "oper" to point to a non-existent server
204         oper.shutdown();
205         initOper(HTTP_NO_SERVER);
206
207         OperationOutcome outcome = runOperation();
208         assertNotNull(outcome);
209         assertEquals(PolicyResult.FAILURE_EXCEPTION, outcome.getResult());
210     }
211
212     private static Properties getServerProperties(String name, int port) {
213         final Properties props = new Properties();
214         props.setProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES, name);
215
216         final String svcpfx = PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + name;
217
218         props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX, Server.class.getName());
219         props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX, "localhost");
220         props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, String.valueOf(port));
221         props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "true");
222         props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX, "false");
223
224         props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER,
225                         GsonMessageBodyHandler.class.getName());
226         return props;
227     }
228
229     /**
230      * Initializes {@link #oper}.
231      *
232      * @param clientName name of the client which it should use
233      */
234     private void initOper(String clientName) {
235         oper = new MyOper();
236
237         HttpParams params = HttpParams.builder().clientName(clientName).path("request").build();
238         Map<String, Object> mapParams = Util.translateToMap(OPERATION, params);
239         oper.configure(mapParams);
240         oper.start();
241     }
242
243     /**
244      * Runs the operation.
245      *
246      * @return the outcome of the operation, or {@code null} if it does not complete in
247      *         time
248      */
249     private OperationOutcome runOperation() throws InterruptedException, ExecutionException, TimeoutException {
250         ControlLoopOperationParams params =
251                         ControlLoopOperationParams.builder().actor(ACTOR).operation(OPERATION).context(context).build();
252
253         CompletableFuture<OperationOutcome> future = oper.startOperationAsync(params, 1, params.makeOutcome());
254
255         return future.get(5, TimeUnit.SECONDS);
256     }
257
258
259     private class MyOper extends SdncOperator {
260
261         /**
262          * Set to {@code true} to cause the decoder to throw an exception.
263          */
264         @Setter
265         private boolean decodeFailure = false;
266
267         public MyOper() {
268             super(ACTOR, OPERATION);
269         }
270
271         protected HttpClient getTheClient() {
272             return getClient();
273         }
274
275         @Override
276         protected SdncRequest constructRequest(ControlLoopEventContext context) {
277             SdncRequest request = new SdncRequest();
278
279             SdncHealRequest heal = new SdncHealRequest();
280             request.setHealRequest(heal);
281
282             return request;
283         }
284
285         @Override
286         protected StandardCoder makeDecoder() {
287             if (decodeFailure) {
288                 // return a coder that throws exceptions when decode() is invoked
289                 return new StandardCoder() {
290                     @Override
291                     public <T> T decode(String json, Class<T> clazz) throws CoderException {
292                         throw new CoderException(EXPECTED_EXCEPTION);
293                     }
294                 };
295
296             } else {
297                 return super.makeDecoder();
298             }
299         }
300     }
301
302     /**
303      * SDNC Simulator.
304      */
305     @Path("/sdnc")
306     @Produces(MEDIA_TYPE_APPLICATION_JSON)
307     public static class Server {
308
309         /**
310          * Generates a response.
311          *
312          * @param request incoming request
313          * @return resulting response
314          */
315         @POST
316         @Path("/request")
317         @Consumes(value = {MEDIA_TYPE_APPLICATION_JSON})
318         public Response postRequest(SdncRequest request) {
319
320             SdncResponse response = new SdncResponse();
321             response.setResponseOutput(output);
322
323             return Response.status(Status.OK).entity(response).build();
324         }
325     }
326 }