8f522740fa327574169b64d99b8aa364788b5cb3
[policy/pap.git] / main / src / test / java / org / onap / policy / pap / main / rest / CommonPapRestServer.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 Nordix Foundation.
4  *  Modifications Copyright (C) 2019 AT&T Intellectual Property.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.pap.main.rest;
23
24 import static org.junit.Assert.assertTrue;
25
26 import java.io.File;
27 import java.io.IOException;
28 import java.net.InetSocketAddress;
29 import java.net.ServerSocket;
30 import java.security.SecureRandom;
31 import java.security.cert.X509Certificate;
32 import java.util.HashMap;
33 import java.util.Map;
34 import java.util.Properties;
35 import javax.net.ssl.SSLContext;
36 import javax.net.ssl.TrustManager;
37 import javax.net.ssl.X509TrustManager;
38 import javax.ws.rs.client.Client;
39 import javax.ws.rs.client.ClientBuilder;
40 import javax.ws.rs.client.Invocation;
41 import javax.ws.rs.client.WebTarget;
42 import javax.ws.rs.core.MediaType;
43 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
44 import org.junit.After;
45 import org.junit.AfterClass;
46 import org.junit.Before;
47 import org.junit.BeforeClass;
48 import org.onap.policy.common.utils.coder.Coder;
49 import org.onap.policy.common.utils.coder.StandardCoder;
50 import org.onap.policy.common.utils.network.NetworkUtil;
51 import org.onap.policy.pap.main.PolicyPapException;
52 import org.onap.policy.pap.main.startstop.Main;
53 import org.onap.policy.pap.main.startstop.PapActivator;
54 import org.powermock.reflect.Whitebox;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 /**
59  * Class to perform unit test of {@link PapRestServer}.
60  *
61  * @author Ram Krishna Verma (ram.krishna.verma@est.tech)
62  */
63 public class CommonPapRestServer {
64
65     private static final Logger LOGGER = LoggerFactory.getLogger(CommonPapRestServer.class);
66
67     private static String KEYSTORE = System.getProperty("user.dir") + "/src/test/resources/ssl/policy-keystore";
68
69     private static Coder coder = new StandardCoder();
70
71     public static final String NOT_ALIVE = "not alive";
72     public static final String ALIVE = "alive";
73     public static final String SELF = "self";
74     public static final String NAME = "Policy PAP";
75     public static final String ENDPOINT_PREFIX = "policy/pap/v1/";
76
77     private static int port;
78     protected static String httpsPrefix;
79
80     private static Main main;
81
82     private boolean activatorWasAlive;
83
84     /**
85      * Allocates a port for the server, writes a config file, and then starts Main.
86      *
87      * @throws Exception if an error occurs
88      */
89     @BeforeClass
90     public static void setUpBeforeClass() throws Exception {
91         allocPort();
92
93         httpsPrefix = "https://localhost:" + port + "/";
94
95         makeConfigFile();
96
97         startMain();
98     }
99
100     /**
101      * Stops Main.
102      */
103     @AfterClass
104     public static void teardownAfterClass() {
105         try {
106             stopMain();
107
108         } catch (PolicyPapException exp) {
109             LOGGER.error("cannot stop main", exp);
110         }
111     }
112
113     /**
114      * Set up.
115      *
116      * @throws Exception if an error occurs
117      */
118     @Before
119     public void setUp() throws Exception {
120         // restart, if not currently running
121         if (main == null) {
122             startMain();
123         }
124
125         activatorWasAlive = PapActivator.getCurrent().isAlive();
126     }
127
128     /**
129      * Restores the activator's "alive" state.
130      */
131     @After
132     public void tearDown() {
133         Whitebox.setInternalState(PapActivator.getCurrent(), "alive", activatorWasAlive);
134     }
135
136     /**
137      * Verifies that an endpoint appears within the swagger response.
138      *
139      * @param endpoint the endpoint of interest
140      * @throws Exception if an error occurs
141      */
142     protected void testSwagger(final String endpoint) throws Exception {
143         final Invocation.Builder invocationBuilder = sendFqeRequest(httpsPrefix + "swagger.yaml");
144         final String resp = invocationBuilder.get(String.class);
145
146         assertTrue(resp.contains(ENDPOINT_PREFIX + endpoint + ":"));
147     }
148
149     /**
150      * Allocates a port for the server.
151      *
152      * @throws IOException if an error occurs
153      */
154     private static void allocPort() throws IOException {
155         ServerSocket socket = new ServerSocket();
156         socket.bind(new InetSocketAddress("localhost", 0));
157
158         port = socket.getLocalPort();
159         socket.close();
160     }
161
162     /**
163      * Makes a parameter configuration file.
164      *
165      * @throws Exception if an error occurs
166      */
167     private static void makeConfigFile() throws Exception {
168         Map<String, Object> params = new HashMap<>();
169         params.put("host", "0.0.0.0");
170         params.put("port", port);
171         params.put("userName", "healthcheck");
172         params.put("password", "zb!XztG34");
173         params.put("https", true);
174
175         Map<String, Object> config = new HashMap<>();
176         config.put("name", "PapGroup");
177         config.put("restServerParameters", params);
178
179         File file = new File("src/test/resources/parameters/TestConfigParams.json");
180         file.deleteOnExit();
181
182         coder.encode(file, config);
183     }
184
185     /**
186      * Starts the "Main".
187      *
188      * @throws Exception if an error occurs
189      */
190     private static void startMain() throws Exception {
191         // make sure port is available
192         if (NetworkUtil.isTcpPortOpen("localhost", port, 1, 1L)) {
193             throw new IllegalStateException("port " + port + " is still in use");
194         }
195
196         final Properties systemProps = System.getProperties();
197         systemProps.put("javax.net.ssl.keyStore", KEYSTORE);
198         systemProps.put("javax.net.ssl.keyStorePassword", "Pol1cy_0nap");
199         System.setProperties(systemProps);
200
201         final String[] papConfigParameters = new String[2];
202         papConfigParameters[0] = "-c";
203         papConfigParameters[1] = "src/test/resources/parameters/TestConfigParams.json";
204
205         main = new Main(papConfigParameters);
206
207         if (!NetworkUtil.isTcpPortOpen("localhost", port, 6, 10000L)) {
208             throw new IllegalStateException("server is not listening on port " + port);
209         }
210     }
211
212     /**
213      * Stops the "Main".
214      *
215      * @throws Exception if an error occurs
216      */
217     private static void stopMain() throws PolicyPapException {
218         if (main != null) {
219             Main main2 = main;
220             main = null;
221
222             main2.shutdown();
223         }
224     }
225
226     /**
227      * Mark the activator as dead, but leave its REST server running.
228      */
229     protected void markActivatorDead() {
230         Whitebox.setInternalState(PapActivator.getCurrent(), "alive", false);
231     }
232
233     /**
234      * Sends a request to an endpoint.
235      *
236      * @param endpoint the target endpoint
237      * @return a request builder
238      * @throws Exception if an error occurs
239      */
240     protected Invocation.Builder sendRequest(final String endpoint) throws Exception {
241         return sendFqeRequest(httpsPrefix + ENDPOINT_PREFIX + endpoint);
242     }
243
244     /**
245      * Sends a request to a fully qualified endpoint.
246      *
247      * @param endpoint the fully qualified target endpoint
248      * @return a request builder
249      * @throws Exception if an error occurs
250      */
251     protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint) throws Exception {
252
253         // @formatter:off
254         final TrustManager[] noopTrustManager = new TrustManager[] {
255             new X509TrustManager() {
256
257                 @Override
258                 public X509Certificate[] getAcceptedIssuers() {
259                     return new X509Certificate[0];
260                 }
261
262                 @Override
263                 public void checkClientTrusted(final java.security.cert.X509Certificate[] certs,
264                                 final String authType) {}
265
266                 @Override
267                 public void checkServerTrusted(final java.security.cert.X509Certificate[] certs,
268                                 final String authType) {}
269             }
270         };
271         // @formatter:on
272
273         final SSLContext sc = SSLContext.getInstance("TLSv1.2");
274         sc.init(null, noopTrustManager, new SecureRandom());
275         final ClientBuilder clientBuilder =
276                         ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true);
277         final Client client = clientBuilder.build();
278         final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34");
279         client.register(feature);
280
281         final WebTarget webTarget = client.target(fullyQualifiedEndpoint);
282
283         return webTarget.request(MediaType.APPLICATION_JSON);
284     }
285 }