Java 17 / Spring 6 / Spring Boot 3 Upgrade
[policy/pap.git] / main / src / test / java / org / onap / policy / pap / main / rest / CommonPapRestServer.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019, 2023 Nordix Foundation.
4  *  Modifications Copyright (C) 2019, 2021 AT&T Intellectual Property.
5  *  Modifications Copyright (C) 2021-2022 Bell Canada. 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  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.pap.main.rest;
24
25 import static org.junit.jupiter.api.Assertions.assertEquals;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27
28 import jakarta.ws.rs.client.Client;
29 import jakarta.ws.rs.client.ClientBuilder;
30 import jakarta.ws.rs.client.Invocation;
31 import jakarta.ws.rs.client.WebTarget;
32 import jakarta.ws.rs.core.MediaType;
33 import jakarta.ws.rs.core.Response;
34 import java.io.File;
35 import java.io.FileOutputStream;
36 import java.nio.charset.StandardCharsets;
37 import java.security.SecureRandom;
38 import java.util.Objects;
39 import java.util.concurrent.atomic.AtomicBoolean;
40 import java.util.function.Function;
41 import javax.net.ssl.SSLContext;
42 import org.glassfish.jersey.client.ClientProperties;
43 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
44 import org.junit.jupiter.api.AfterAll;
45 import org.junit.jupiter.api.AfterEach;
46 import org.junit.jupiter.api.BeforeAll;
47 import org.junit.jupiter.api.BeforeEach;
48 import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
49 import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
50 import org.onap.policy.common.endpoints.http.server.YamlMessageBodyHandler;
51 import org.onap.policy.common.gson.GsonMessageBodyHandler;
52 import org.onap.policy.common.utils.network.NetworkUtil;
53 import org.onap.policy.common.utils.security.SelfSignedKeyStore;
54 import org.onap.policy.common.utils.services.Registry;
55 import org.onap.policy.pap.main.PapConstants;
56 import org.onap.policy.pap.main.PolicyPapApplication;
57 import org.onap.policy.pap.main.parameters.CommonTestData;
58 import org.onap.policy.pap.main.startstop.PapActivator;
59 import org.springframework.boot.test.context.SpringBootTest;
60 import org.springframework.boot.test.web.server.LocalServerPort;
61 import org.springframework.test.annotation.DirtiesContext;
62 import org.springframework.test.annotation.DirtiesContext.ClassMode;
63 import org.springframework.test.context.DynamicPropertyRegistry;
64 import org.springframework.test.context.DynamicPropertySource;
65 import org.springframework.test.util.ReflectionTestUtils;
66
67 /**
68  * Class to perform unit test of {@link PapRestControllerV1}.
69  *
70  * @author Ram Krishna Verma (ram.krishna.verma@est.tech)
71  */
72 @SpringBootTest(classes = PolicyPapApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
73     properties = {"db.initialize=false"})
74 @DirtiesContext(classMode = ClassMode.AFTER_CLASS)
75 public abstract class CommonPapRestServer {
76
77     protected static final String CONFIG_FILE = "src/test/resources/parameters/TestConfigParams.json";
78
79     public static final String NOT_ALIVE = "not alive";
80     public static final String ALIVE = "alive";
81     public static final String SELF = NetworkUtil.getHostname();
82     public static final String NAME = "Policy PAP";
83     public static final String ENDPOINT_PREFIX = "policy/pap/v1/";
84
85     private static SelfSignedKeyStore keystore;
86
87     private boolean activatorWasAlive;
88     protected String httpsPrefix;
89
90     @LocalServerPort
91     private int port;
92
93     private PapActivator papActivator;
94
95     /**
96      * Allocates a new db url, writes a config file.
97      *
98      * @throws Exception if an error occurs
99      */
100     @BeforeAll
101     public static void setUpBeforeClass() throws Exception {
102         keystore = new SelfSignedKeyStore();
103         CommonTestData.newDb();
104         makeConfigFile();
105
106         HttpServletServerFactoryInstance.getServerFactory().destroy();
107         TopicEndpointManager.getManager().shutdown();
108         Registry.newRegistry();
109     }
110
111     @DynamicPropertySource
112     static void registerPgProperties(DynamicPropertyRegistry registry) {
113         registry.add("spring.datasource.url", () -> "jdbc:h2:mem:testdb" + CommonTestData.dbNum);
114         registry.add("server.ssl.enabled", () -> "true");
115         registry.add("server.ssl.key-store", () -> keystore.getKeystoreName());
116         registry.add("server.ssl.key-store-password", () -> SelfSignedKeyStore.KEYSTORE_PASSWORD);
117     }
118
119     /**
120      * Set up.
121      *
122      * @throws Exception if an error occurs
123      */
124     @BeforeEach
125     public void setUp() throws Exception {
126         httpsPrefix = "https://localhost:" + port + "/";
127         papActivator = Registry.get(PapConstants.REG_PAP_ACTIVATOR, PapActivator.class);
128         activatorWasAlive = papActivator.isAlive();
129     }
130
131     /**
132      * Restores the activator's "alive" state.
133      */
134     @AfterEach
135     public void tearDown() {
136         markActivator(activatorWasAlive);
137     }
138
139     @AfterAll
140     public static void cleanRegistry() {
141         Registry.newRegistry();
142     }
143
144     /**
145      * Verifies that an endpoint appears within the swagger response.
146      *
147      * @param endpoint the endpoint of interest
148      * @throws Exception if an error occurs
149      */
150     protected void testSwagger(final String endpoint) throws Exception {
151         final Invocation.Builder invocationBuilder = sendFqeRequest(httpsPrefix
152             + ENDPOINT_PREFIX + "v3/api-docs", true, MediaType.APPLICATION_JSON);
153         final String resp = invocationBuilder.get(String.class);
154         assertTrue(resp.contains(endpoint));
155     }
156
157     /**
158      * Makes a parameter configuration file.
159      *
160      * @throws Exception if an error occurs
161      */
162     private static void makeConfigFile() throws Exception {
163         String json = new CommonTestData().getPapParameterGroupAsString(6969);
164
165         File file = new File(CONFIG_FILE);
166         file.deleteOnExit();
167
168         try (FileOutputStream output = new FileOutputStream(file)) {
169             output.write(json.getBytes(StandardCharsets.UTF_8));
170         }
171     }
172
173     /**
174      * Mark the activator as dead, but leave its REST server running.
175      */
176     protected void markActivatorDead() {
177         markActivator(false);
178     }
179
180     private void markActivator(boolean wasAlive) {
181         Object manager = ReflectionTestUtils.getField(papActivator, "serviceManager");
182         AtomicBoolean running = (AtomicBoolean) ReflectionTestUtils
183             .getField(Objects.requireNonNull(manager), "running");
184         running.set(wasAlive);
185     }
186
187     /**
188      * Verifies that unauthorized requests fail.
189      *
190      * @param endpoint the target end point
191      * @param sender   function that sends the requests to the target
192      * @throws Exception if an error occurs
193      */
194     protected void checkUnauthRequest(final String endpoint, Function<Invocation.Builder, Response> sender)
195         throws Exception {
196         assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(),
197             sender.apply(sendNoAuthRequest(endpoint)).getStatus());
198     }
199
200     /**
201      * Sends a request to an endpoint.
202      *
203      * @param endpoint the target endpoint
204      * @return a request builder
205      * @throws Exception if an error occurs
206      */
207     protected Invocation.Builder sendRequest(final String endpoint) throws Exception {
208         return sendFqeRequest(httpsPrefix + ENDPOINT_PREFIX + endpoint, true, MediaType.APPLICATION_JSON);
209     }
210
211     /**
212      * Sends a request to an endpoint.
213      *
214      * @param endpoint  the target endpoint
215      * @param mediaType the media type for the request
216      * @return a request builder
217      * @throws Exception if an error occurs
218      */
219     protected Invocation.Builder sendRequest(final String endpoint, String mediaType) throws Exception {
220         return sendFqeRequest(httpsPrefix + ENDPOINT_PREFIX + endpoint, true, mediaType);
221     }
222
223     /**
224      * Sends a request to an endpoint, without any authorization header.
225      *
226      * @param endpoint the target endpoint
227      * @return a request builder
228      * @throws Exception if an error occurs
229      */
230     protected Invocation.Builder sendNoAuthRequest(final String endpoint) throws Exception {
231         return sendFqeRequest(httpsPrefix + ENDPOINT_PREFIX + endpoint, false, MediaType.APPLICATION_JSON);
232     }
233
234     /**
235      * Sends a request to a fully qualified endpoint.
236      *
237      * @param fullyQualifiedEndpoint the fully qualified target endpoint
238      * @param includeAuth            if authorization header should be included
239      * @return a request builder
240      * @throws Exception if an error occurs
241      */
242     protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint, boolean includeAuth,
243                                                 String mediaType) throws Exception {
244         final SSLContext sc = SSLContext.getInstance("TLSv1.2");
245         sc.init(null, NetworkUtil.getAlwaysTrustingManager(), new SecureRandom());
246         final ClientBuilder clientBuilder =
247             ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true);
248         final Client client = clientBuilder.build();
249
250         client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true");
251         client.register((mediaType.equalsIgnoreCase(MediaType.APPLICATION_JSON) ? GsonMessageBodyHandler.class
252             : YamlMessageBodyHandler.class));
253
254         if (includeAuth) {
255             final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("policyadmin", "zb!XztG34");
256             client.register(feature);
257         }
258
259         final WebTarget webTarget = client.target(fullyQualifiedEndpoint);
260
261         return webTarget.request(mediaType);
262     }
263 }