2ff441699ef65dc2ccad8579226d1285a339de6b
[ccsdk/oran.git] /
1 /*-
2  * ========================LICENSE_START=================================
3  * ONAP : ccsdk oran
4  * ======================================================================
5  * Copyright (C) 2019-2023 Nordix Foundation. 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.ccsdk.oran.a1policymanagementservice.controllers.v2;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.awaitility.Awaitility.await;
25 import static org.junit.jupiter.api.Assertions.*;
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.Mockito.doReturn;
28
29 import com.fasterxml.jackson.core.JsonProcessingException;
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import com.google.gson.Gson;
32 import com.google.gson.GsonBuilder;
33
34 import java.lang.invoke.MethodHandles;
35 import java.nio.charset.StandardCharsets;
36 import java.nio.file.Files;
37 import java.nio.file.Path;
38 import java.time.Duration;
39 import java.time.Instant;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.HashMap;
45
46 import org.junit.jupiter.api.AfterAll;
47 import org.junit.jupiter.api.AfterEach;
48 import org.junit.jupiter.api.BeforeEach;
49 import org.junit.jupiter.api.DisplayName;
50 import org.junit.jupiter.api.MethodOrderer;
51 import org.junit.jupiter.api.Test;
52 import org.junit.jupiter.api.TestMethodOrder;
53 import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory;
54 import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClient;
55 import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClientFactory;
56 import org.onap.ccsdk.oran.a1policymanagementservice.clients.SecurityContext;
57 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig;
58 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig.RicConfigUpdate;
59 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.RicConfig;
60 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientConfig;
61 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.OpenPolicyAgentSimulatorController;
62 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.ServiceCallbackInfo;
63 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.PolicyAuthorizationRequest;
64 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.PolicyAuthorizationRequest.Input.AccessType;
65 import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
66 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.RicInfo;
67 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyTypeIdList;
68 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfo;
69 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfoList;
70 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyIdList;
71 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyStatusInfo;
72 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceStatusList;
73 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceStatus;
74 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceRegistrationInfo;
75 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock;
76 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock.LockType;
77 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies;
78 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy;
79 import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyType;
80 import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes;
81 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric;
82 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric.RicState;
83 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics;
84 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Service;
85 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Services;
86 import org.onap.ccsdk.oran.a1policymanagementservice.tasks.RefreshConfigTask;
87 import org.onap.ccsdk.oran.a1policymanagementservice.tasks.RicSupervision;
88 import org.onap.ccsdk.oran.a1policymanagementservice.tasks.ServiceSupervision;
89 import org.onap.ccsdk.oran.a1policymanagementservice.utils.MockA1Client;
90 import org.onap.ccsdk.oran.a1policymanagementservice.utils.MockA1ClientFactory;
91 import org.slf4j.Logger;
92 import org.slf4j.LoggerFactory;
93 import org.springframework.beans.factory.annotation.Autowired;
94 import org.springframework.boot.test.context.SpringBootTest;
95 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
96 import org.springframework.boot.test.context.TestConfiguration;
97 import org.springframework.boot.test.web.server.LocalServerPort;
98 import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
99 import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
100 import org.springframework.context.ApplicationContext;
101 import org.springframework.context.annotation.Bean;
102 import org.springframework.http.HttpStatus;
103 import org.springframework.http.MediaType;
104 import org.springframework.http.ResponseEntity;
105 import org.springframework.test.context.TestPropertySource;
106 import org.springframework.util.FileSystemUtils;
107 import org.springframework.web.reactive.function.client.WebClientRequestException;
108 import org.springframework.web.reactive.function.client.WebClientResponseException;
109
110 import reactor.core.publisher.Mono;
111 import reactor.test.StepVerifier;
112 import reactor.util.annotation.Nullable;
113
114 @TestMethodOrder(MethodOrderer.MethodName.class)
115 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
116 @TestPropertySource(properties = { //
117         "server.ssl.key-store=./config/keystore.jks", //
118         "app.webclient.trust-store=./config/truststore.jks", //
119         "app.webclient.trust-store-used=true", //
120         "app.vardata-directory=/tmp/pmstest", //
121         "app.filepath=", //
122         "app.s3.bucket=" // If this is set, S3 will be used to store data.
123 })
124 class ApplicationTest {
125     private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
126
127     @Autowired
128     ApplicationContext context;
129
130     @Autowired
131     private Rics rics;
132
133     @Autowired
134     private Policies policies;
135
136     @Autowired
137     private PolicyTypes policyTypes;
138
139     @Autowired
140     MockA1ClientFactory a1ClientFactory;
141
142     @Autowired
143     private ObjectMapper objectMapper;
144
145     @Autowired
146     RicSupervision supervision;
147
148     @Autowired
149     ApplicationConfig applicationConfig;
150
151     @Autowired
152     Services services;
153
154     @Autowired
155     RappSimulatorController rAppSimulator;
156
157     @Autowired
158     RefreshConfigTask refreshConfigTask;
159
160     @Autowired
161     SecurityContext securityContext;
162
163     @Autowired
164     OpenPolicyAgentSimulatorController openPolicyAgentSimulatorController;
165
166     private static Gson gson = new GsonBuilder().create();
167
168     /**
169      * Overrides the BeanFactory.
170      */
171     @TestConfiguration
172     static class TestBeanFactory {
173
174         @Bean
175         A1ClientFactory getA1ClientFactory(@Autowired ApplicationConfig appConfig, @Autowired PolicyTypes types) {
176             return new MockA1ClientFactory(appConfig, types);
177         }
178
179         @Bean
180         public ServiceSupervision getServiceSupervision(@Autowired Services services,
181                 @Autowired A1ClientFactory a1ClientFactory, @Autowired Policies policies) {
182             Duration checkInterval = Duration.ofMillis(1);
183             return new ServiceSupervision(services, policies, a1ClientFactory, checkInterval);
184         }
185
186         @Bean
187         public ServletWebServerFactory servletContainer() {
188             return new TomcatServletWebServerFactory();
189         }
190     }
191
192     @LocalServerPort
193     private int port;
194
195     @BeforeEach
196     void init() {
197         this.applicationConfig.setAuthProviderUrl(baseUrl() + OpenPolicyAgentSimulatorController.ACCESS_CONTROL_URL);
198     }
199
200     @AfterEach
201     void reset() {
202         rics.clear();
203         policies.clear();
204         policyTypes.clear();
205         services.clear();
206         a1ClientFactory.reset();
207         this.rAppSimulator.getTestResults().clear();
208         this.a1ClientFactory.setPolicyTypes(policyTypes); // Default same types in RIC and in this app
209         this.securityContext.setAuthTokenFilePath(null);
210         this.openPolicyAgentSimulatorController.getTestResults().reset();
211     }
212
213     @AfterAll
214     static void clearTestDir() {
215         try {
216             FileSystemUtils.deleteRecursively(Path.of("/tmp/pmstest"));
217         } catch (Exception e) {
218             logger.warn("Could test directory : {}", e.getMessage());
219         }
220     }
221
222     @AfterEach
223     void verifyNoRicLocks() {
224         for (Ric ric : this.rics.getRics()) {
225             Lock.Grant grant = ric.getLock().lockBlocking(LockType.EXCLUSIVE, "verifyNoRicLocks");
226             grant.unlockBlocking();
227             assertThat(ric.getLock().getLockCounter()).isZero();
228             assertThat(ric.getState()).isEqualTo(Ric.RicState.AVAILABLE);
229         }
230     }
231
232     @Test
233     @SuppressWarnings("squid:S2925") // "Thread.sleep" should not be used in tests.
234     @DisplayName("test ZZ Actuator")
235     void testZZActuator() throws Exception {
236         // The test must be run last, hence the "ZZ" in the name. All succeeding tests
237         // will fail.
238         AsyncRestClient client = restClient(baseUrl(), false);
239
240         client.post("/actuator/loggers/org.onap.ccsdk.oran.a1policymanagementservice",
241                 "{\"configuredLevel\":\"trace\"}").block();
242
243         String resp = client.get("/actuator/loggers/org.onap.ccsdk.oran.a1policymanagementservice").block();
244         assertThat(resp).contains("TRACE");
245
246         client.post("/actuator/loggers/org.springframework.boot.actuate", "{\"configuredLevel\":\"trace\"}").block();
247
248         // This will stop the web server and all coming tests will fail.
249         client.post("/actuator/shutdown", "").block();
250
251         Thread.sleep(1000);
252
253         StepVerifier.create(restClient().get("/rics")) // Any call
254                 .expectSubscription() //
255                 .expectErrorMatches(t -> t instanceof WebClientRequestException) //
256                 .verify();
257
258     }
259
260     @Test
261     @DisplayName("test Persistency Policies")
262     void testPersistencyPolicies() throws Exception {
263         Ric ric = this.addRic("ric1");
264         PolicyType type = this.addPolicyType("type1", ric.id());
265
266         final int noOfPolicies = 100;
267         for (int i = 0; i < noOfPolicies; ++i) {
268             addPolicy("id" + i, type.getId(), "service", ric.id());
269         }
270         waitforS3();
271
272         {
273             Policies policies = new Policies(this.applicationConfig);
274             policies.restoreFromDatabase(ric, this.policyTypes).blockLast();
275             assertThat(policies.size()).isEqualTo(noOfPolicies);
276         }
277
278         {
279             restClient().delete("/policies/id2").block();
280             Policies policies = new Policies(this.applicationConfig);
281             policies.restoreFromDatabase(ric, this.policyTypes).blockLast();
282             assertThat(policies.size()).isEqualTo(noOfPolicies - 1);
283         }
284     }
285
286     @Test
287     @DisplayName("test Persistency Policy Types")
288     void testPersistencyPolicyTypes() throws Exception {
289         Ric ric = this.addRic("ric1");
290         this.addPolicyType("type1", ric.id());
291         waitforS3();
292
293         PolicyTypes types = new PolicyTypes(this.applicationConfig);
294         types.restoreFromDatabase().blockLast();
295         assertThat(types.size()).isEqualTo(1);
296     }
297
298     @SuppressWarnings("squid:S2925") // "Thread.sleep" should not be used in tests.
299     private void waitforS3() throws Exception {
300         if (applicationConfig.isS3Enabled()) {
301             Thread.sleep(1000);
302         }
303     }
304
305     @Test
306     @DisplayName("test Persistency Service")
307     void testPersistencyService() throws Exception {
308         final String SERVICE = "serviceName";
309         putService(SERVICE, 1234, HttpStatus.CREATED);
310         assertThat(this.services.size()).isEqualTo(1);
311         Service service = this.services.getService(SERVICE);
312         waitforS3();
313
314         Services servicesRestored = new Services(this.applicationConfig);
315         servicesRestored.restoreFromDatabase().blockLast();
316         Service serviceRestored = servicesRestored.getService(SERVICE);
317         assertThat(servicesRestored.size()).isEqualTo(1);
318         assertThat(serviceRestored.getCallbackUrl()).isEqualTo(service.getCallbackUrl());
319         assertThat(serviceRestored.getKeepAliveInterval()).isEqualTo(service.getKeepAliveInterval());
320
321         // check that the service can be deleted
322         this.services.remove(SERVICE);
323         servicesRestored = new Services(this.applicationConfig);
324         assertThat(servicesRestored.size()).isZero();
325     }
326
327     @Test
328     @DisplayName("test Adding Ric From Configuration")
329     void testAddingRicFromConfiguration() throws Exception {
330         // Test adding the RIC from configuration
331
332         final String RIC = "ric1";
333         final String TYPE = "type123";
334         PolicyTypes nearRtRicPolicyTypes = new PolicyTypes(this.applicationConfig);
335         nearRtRicPolicyTypes.put(createPolicyType(TYPE));
336         this.a1ClientFactory.setPolicyTypes(nearRtRicPolicyTypes);
337
338         putService("service");
339
340         refreshConfigTask.handleUpdatedRicConfig( //
341                 new RicConfigUpdate(ricConfig(RIC, "me1"), RicConfigUpdate.Type.ADDED)) //
342                 .block();
343         waitForRicState(RIC, RicState.AVAILABLE);
344
345         // Test that the type has been synched
346         Ric addedRic = this.rics.getRic(RIC);
347         assertThat(addedRic.getSupportedPolicyTypes()).hasSize(1);
348         assertThat(addedRic.getSupportedPolicyTypes().iterator().next().getId()).isEqualTo(TYPE);
349
350         // Check that a service callback for the AVAILABLE RIC is invoked
351         final RappSimulatorController.TestResults receivedCallbacks = rAppSimulator.getTestResults();
352         await().untilAsserted(() -> assertThat(receivedCallbacks.getReceivedInfo()).hasSize(1));
353         ServiceCallbackInfo callbackInfo = receivedCallbacks.getReceivedInfo().get(0);
354         assertThat(callbackInfo.ricId).isEqualTo(RIC);
355         assertThat(callbackInfo.eventType).isEqualTo(ServiceCallbackInfo.EventType.AVAILABLE);
356     }
357
358     @Test
359     @DisplayName("test Adding Ric From Configuration non Responding Ric")
360     void testAddingRicFromConfiguration_nonRespondingRic() throws Exception {
361         putService("service");
362
363         final String RIC = "NonRespondingRic";
364         MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client(RIC);
365         doReturn(MockA1Client.monoError("error", HttpStatus.BAD_GATEWAY)).when(a1Client).getPolicyTypeIdentities();
366
367         refreshConfigTask.handleUpdatedRicConfig( //
368                 new RicConfigUpdate(ricConfig(RIC, "me1"), RicConfigUpdate.Type.ADDED)) //
369                 .block();
370
371         waitForRicState(RIC, RicState.UNAVAILABLE);
372
373         // Check that no service callback for the UNAVAILABLE RIC is invoked
374         final RappSimulatorController.TestResults receivedCallbacks = rAppSimulator.getTestResults();
375         await().untilAsserted(() -> assertThat(receivedCallbacks.getReceivedInfo()).isEmpty());
376
377         // Run a synch and check that the AVAILABLE notification is received
378         a1ClientFactory.reset();
379         supervision.checkAllRics();
380         waitForRicState(RIC, RicState.AVAILABLE);
381
382         await().untilAsserted(() -> assertThat(receivedCallbacks.getReceivedInfo()).hasSize(1));
383     }
384
385     @Test
386     @DisplayName("test Trust Validation")
387     void testTrustValidation() {
388         addRic("ric1");
389
390         String rsp = restClient(true).get("/rics").block(); // restClient(true) enables trust validation
391         assertThat(rsp).contains("ric1");
392
393     }
394
395     @Test
396     @DisplayName("test Get Rics")
397     void testGetRics() throws Exception {
398         addRic("ric1");
399         this.addPolicyType("type1", "ric1");
400         String url = "/rics?policytype_id=type1";
401         String rsp = restClient().get(url).block();
402         String expectedResponse = "{\"rics\":[{\"managed_element_ids\":[],\"ric_id\":\"ric1\", \"state\":\"AVAILABLE\",\"policytype_ids\":[\"type1\"]}]}";
403         assertEquals(objectMapper.readTree(expectedResponse), objectMapper.readTree(rsp));
404
405         // nameless type for ORAN A1 1.1
406         addRic("ric2");
407         this.addPolicyType("", "ric2");
408         url = "/rics?policytype_id=";
409         rsp = restClient().get(url).block();
410         assertThat(rsp).contains("ric2") //
411                 .doesNotContain("ric1") //
412                 .contains("AVAILABLE");
413
414         // All RICs
415         rsp = restClient().get("/rics").block();
416         assertThat(rsp).contains("ric2") //
417                 .contains("ric1");
418
419         // Non existing policy type
420         url = "/rics?policytype_id=XXXX";
421         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
422     }
423
424     @Test
425     @DisplayName("test Synchronization")
426     void testSynchronization() throws Exception {
427         // Two polictypes will be put in the NearRT RICs
428         PolicyTypes nearRtRicPolicyTypes = new PolicyTypes(this.applicationConfig);
429         nearRtRicPolicyTypes.put(createPolicyType("typeName"));
430         nearRtRicPolicyTypes.put(createPolicyType("typeName2"));
431         this.a1ClientFactory.setPolicyTypes(nearRtRicPolicyTypes);
432
433         // One type and one instance added to the Policy Management Service's storage
434         final String ric1Name = "ric1";
435         Ric ric1 = addRic(ric1Name);
436         Policy policy2 = addPolicy("policyId2", "typeName", "service", ric1Name);
437         Ric ric2 = addRic("ric2");
438
439         getA1Client(ric1Name).putPolicy(policy2); // put it in the RIC (Near-RT RIC)
440         policies.remove(policy2); // Remove it from the repo -> should be deleted in the RIC
441
442         String policyId = "policyId";
443         Policy policy = addPolicy(policyId, "typeName", "service", ric1Name); // This should be created in the RIC
444         supervision.checkAllRics(); // The created policy should be put in the RIC
445
446         // Wait until synch is completed
447         waitForRicState(ric1Name, RicState.SYNCHRONIZING);
448         waitForRicState(ric1Name, RicState.AVAILABLE);
449         waitForRicState("ric2", RicState.AVAILABLE);
450
451         Policies ricPolicies = getA1Client(ric1Name).getPolicies();
452         assertThat(ricPolicies.size()).isEqualTo(1);
453         Policy ricPolicy = ricPolicies.get(policyId);
454         assertThat(ricPolicy.getJson()).isEqualTo(policy.getJson());
455
456         // Both types should be in the Policy Management Service's storage after the
457         // synch
458         assertThat(ric1.getSupportedPolicyTypes()).hasSize(2);
459         assertThat(ric2.getSupportedPolicyTypes()).hasSize(2);
460     }
461
462     @Test
463     @DisplayName("test Get Ric")
464     void testGetRic() throws Exception {
465         String ricId = "ric1";
466         String managedElementId = "kista_1";
467         addRic(ricId, managedElementId);
468
469         String url = "/rics/ric?managed_element_id=" + managedElementId;
470         String rsp = restClient().get(url).block();
471         RicInfo ricInfo = objectMapper.readValue(rsp, RicInfo.class);
472         assertThat(ricInfo.getRicId()).isEqualTo(ricId);
473
474         url = "/rics/ric?ric_id=" + ricId;
475         rsp = restClient().get(url).block();
476         ricInfo = objectMapper.readValue(rsp, RicInfo.class);
477         assertThat(ricInfo.getRicId()).isEqualTo(ricId);
478
479         // test GET RIC for ManagedElement that does not exist
480         url = "/rics/ric?managed_element_id=" + "junk";
481         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
482
483         url = "/rics/ric";
484         testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST);
485     }
486
487     private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId,
488             boolean isTransient, String statusNotificationUri) throws JsonProcessingException {
489         PolicyInfo policyInfo = new PolicyInfo();
490         policyInfo.setPolicyId(policyInstanceId);
491         policyInfo.setPolicytypeId(policyTypeName);
492         policyInfo.setRicId(ricId);
493         policyInfo.setServiceId(serviceName);
494         policyInfo.setPolicyData(jsonString());
495         policyInfo.setTransient(isTransient);
496         policyInfo.setStatusNotificationUri(statusNotificationUri);
497         return objectMapper.writeValueAsString(policyInfo);
498     }
499
500     private String putPolicyBod(String serviceName, String ricId, String policyTypeName, String policyInstanceId,
501                                        boolean isTransient, String statusNotificationUri) throws JsonProcessingException {
502         PolicyInfo policyInfo = new PolicyInfo();
503         policyInfo.setPolicyId(policyInstanceId);
504         policyInfo.setPolicytypeId(policyTypeName);
505         policyInfo.setRicId(ricId);
506         policyInfo.setServiceId(serviceName);
507         policyInfo.setPolicyData(jsonString());
508         policyInfo.setTransient(isTransient);
509         policyInfo.setStatusNotificationUri(statusNotificationUri);
510         return objectMapper.writeValueAsString(policyInfo);
511     }
512
513     private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId) throws JsonProcessingException {
514         return putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, false, "statusUri");
515     }
516
517     @Test
518     @DisplayName("test Put Policy")
519     void testPutPolicy() throws Exception {
520         String serviceName = "service.1";
521         String ricId = "ric.1";
522         String policyTypeName = "type1_1.2.3";
523         String policyInstanceId = "instance_1.2.3";
524
525         putService(serviceName);
526         addPolicyType(policyTypeName, ricId);
527
528         // PUT a transient policy
529         String url = "/policies";
530         String policyBody = putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, true, "statusNotif");
531         this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
532
533         restClient().put(url, policyBody).block();
534         {
535             // Check the authorization request
536             OpenPolicyAgentSimulatorController.TestResults res =
537                     this.openPolicyAgentSimulatorController.getTestResults();
538             assertThat(res.receivedRequests).hasSize(1);
539             PolicyAuthorizationRequest req = res.receivedRequests.get(0);
540             assertThat(req.getInput().getAccessType()).isEqualTo(AccessType.WRITE);
541             assertThat(req.getInput().getPolicyTypeId()).isEqualTo(policyTypeName);
542         }
543
544         Policy policy = policies.getPolicy(policyInstanceId);
545         assertThat(policy).isNotNull();
546         assertThat(policy.getId()).isEqualTo(policyInstanceId);
547         assertThat(policy.getOwnerServiceId()).isEqualTo(serviceName);
548         assertThat(policy.getRic().id()).isEqualTo(ricId);
549         assertThat(policy.isTransient()).isTrue();
550
551         // Put a non transient policy
552         policyBody = putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId);
553         restClient().put(url, policyBody).block();
554         policy = policies.getPolicy(policyInstanceId);
555         assertThat(policy.isTransient()).isFalse();
556
557         url = "/policy-instances";
558         String rsp = restClient().get(url).block();
559         assertThat(rsp).as("Response contains policy instance ID.").contains(policyInstanceId);
560
561         url = "/policies/" + policyInstanceId;
562         rsp = restClient().get(url).block();
563
564         assertThat(rsp).contains(policyBody);
565
566         // Test of error codes
567         url = "/policies";
568         policyBody = putPolicyBody(serviceName, ricId + "XX", policyTypeName, policyInstanceId);
569         testErrorCode(restClient().put(url, policyBody), HttpStatus.NOT_FOUND);
570
571         policyBody = putPolicyBody(serviceName, ricId, policyTypeName + "XX", policyInstanceId);
572         addPolicyType(policyTypeName + "XX", "otherRic");
573         testErrorCode(restClient().put(url, policyBody), HttpStatus.NOT_FOUND);
574
575         policyBody = putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId);
576         this.rics.getRic(ricId).setState(Ric.RicState.SYNCHRONIZING);
577         testErrorCode(restClient().put(url, policyBody), HttpStatus.LOCKED);
578         this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
579     }
580
581     @Test
582     void testFineGrainedAuth() throws Exception {
583         final String POLICY_ID = "policyId";
584         final String RIC_ID = "ric1";
585         final String TYPE_ID = "typeName";
586         addPolicy(POLICY_ID, TYPE_ID, null, RIC_ID);
587         assertThat(policies.size()).isEqualTo(1);
588
589         this.applicationConfig
590                 .setAuthProviderUrl(baseUrl() + OpenPolicyAgentSimulatorController.ACCESS_CONTROL_URL_REJECT);
591         String url = "/policy-instances";
592         String rsp = restClient().get(url).block();
593         assertThat(rsp).as("Response contains no policy instance ID.").contains("[]");
594
595         url = "/policies/" + POLICY_ID;
596         testErrorCode(restClient().delete(url), HttpStatus.UNAUTHORIZED, "Not authorized");
597
598         url = "/policies";
599         String policyBody = putPolicyBody(null, RIC_ID, TYPE_ID, POLICY_ID, false, null);
600         testErrorCode(restClient().put(url, policyBody), HttpStatus.UNAUTHORIZED, "Not authorized");
601
602         rsp = restClient().get(url).block();
603         assertThat(rsp).as("Response contains no policy instance ID.").contains("[]");
604     }
605
606     @Test
607     void testFineGrainedAuth_OPA_UNAVALIABLE() throws Exception {
608         final String POLICY_ID = "policyId";
609         final String RIC_ID = "ric1";
610         final String TYPE_ID = "typeName";
611         addPolicy(POLICY_ID, TYPE_ID, null, RIC_ID);
612         assertThat(policies.size()).isEqualTo(1);
613
614         this.applicationConfig.setAuthProviderUrl("junk");
615
616         String url = "/policy-instances";
617         String rsp = restClient().get(url).block();
618         assertThat(rsp).as("Response contains no policy instance ID.").contains("[]");
619
620         url = "/policies/" + POLICY_ID;
621         testErrorCode(restClient().delete(url), HttpStatus.UNAUTHORIZED, "Not authorized");
622
623         url = "/policies";
624         String policyBody = putPolicyBody(null, RIC_ID, TYPE_ID, POLICY_ID, false, null);
625         testErrorCode(restClient().put(url, policyBody), HttpStatus.UNAUTHORIZED, "Not authorized");
626
627         rsp = restClient().get(url).block();
628         assertThat(rsp).as("Response contains no policy instance ID.").contains("[]");
629     }
630     @Test
631     @DisplayName("test Put Policy No Service No Status Uri")
632     void testPutPolicy_NoServiceNoStatusUri() throws Exception {
633         String ricId = "ric.1";
634         String policyTypeName = "type1_1.2.3";
635         String policyInstanceId = "instance_1.2.3";
636
637         addPolicyType(policyTypeName, ricId);
638
639         // PUT a transient policy
640         String url = "/policies";
641         String policyBody = putPolicyBody(null, ricId, policyTypeName, policyInstanceId, true, null);
642         this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
643
644         restClient().put(url, policyBody).block();
645
646         Policy policy = policies.getPolicy(policyInstanceId);
647         assertThat(policy).isNotNull();
648         assertThat(policy.getOwnerServiceId()).isBlank();
649         assertThat(policy.getStatusNotificationUri()).isBlank();
650     }
651
652     @Test
653     /**
654      * Test that HttpStatus and body from failing REST call to A1 is passed on to
655      * the caller.
656      *
657      * @throws ServiceException
658      */
659     @DisplayName("test Error From Ric")
660     void testErrorFromRic() throws ServiceException, JsonProcessingException {
661         putService("service1");
662         addPolicyType("type1", "ric1");
663
664         MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client("ric1");
665         HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
666         String responseBody = "Refused";
667         byte[] responseBodyBytes = responseBody.getBytes(StandardCharsets.UTF_8);
668
669         WebClientResponseException a1Exception = new WebClientResponseException(httpStatus.value(), "statusText", null,
670                 responseBodyBytes, StandardCharsets.UTF_8, null);
671         doReturn(Mono.error(a1Exception)).when(a1Client).putPolicy(any());
672
673         // PUT Policy
674         String putBody = putPolicyBody("service1", "ric1", "type1", "id1");
675         String url = "/policies";
676         testErrorCode(restClient().put(url, putBody), httpStatus, responseBody);
677
678         // DELETE POLICY
679         this.addPolicy("instance1", "type1", "service1", "ric1");
680         doReturn(Mono.error(a1Exception)).when(a1Client).deletePolicy(any());
681         testErrorCode(restClient().delete("/policies/instance1"), httpStatus, responseBody);
682
683     }
684
685     @Test
686     @DisplayName("test Put Typeless Policy")
687     void testPutTypelessPolicy() throws Exception {
688         putService("service1");
689         addPolicyType("", "ric1");
690         String body = putPolicyBody("service1", "ric1", "", "id1");
691         restClient().put("/policies", body).block();
692
693         String rsp = restClient().get("/policy-instances").block();
694         PolicyInfoList info = objectMapper.readValue(rsp, PolicyInfoList.class);
695         assertThat(info.getPolicies()).hasSize(1);
696         PolicyInfo policyInfo = info.getPolicies().iterator().next();
697         assertThat(policyInfo.getPolicyId()).isEqualTo("id1");
698         assertThat(policyInfo.getPolicytypeId()).isEmpty();
699     }
700
701     @Test
702     @DisplayName("test Update Service")
703     void testUpdateService() throws Exception {
704         this.addRic("ric1");
705         this.addPolicy("policyId", "type1", "", "ric1");
706
707         String url = "/policies?service_id=";
708         String resp = restClient().get(url).block();
709         String expectedResponse = "{\"policy_ids\":[\"policyId\"]}";
710         assertEquals(expectedResponse, resp);
711
712         this.addPolicy("policyId", "type1", "service", "ric1");
713         url = "/policies?service_id=";
714         resp = restClient().get(url).block();
715         expectedResponse = "{\"policy_ids\":[]}";
716         assertEquals(expectedResponse, resp);
717
718         url = "/policies?service_id=service";
719         resp = restClient().get(url).block();
720         assertThat(resp).contains("[\"policyId\"]");
721     }
722
723     @Test
724     @DisplayName("test Refuse To Update Policy")
725     void testRefuseToUpdatePolicy() throws Exception {
726         // Test that only the json can be changed for a already created policy
727         // In this case service is attempted to be changed
728         this.addRic("ric1");
729         this.addRic("ricXXX");
730         this.addPolicy("instance1", "type1", "service1", "ric1");
731         this.addPolicy("instance2", "type1", "service1", "ricXXX");
732
733         // Try change ric1 -> ricXXX
734         String bodyWrongRic = putPolicyBody("service1", "ricXXX", "type1", "instance1");
735         testErrorCode(restClient().put("/policies", bodyWrongRic), HttpStatus.CONFLICT);
736     }
737
738     @Test
739     @DisplayName("test Get Policy")
740     void testGetPolicy() throws Exception {
741         String url = "/policies/id";
742         Policy policy = addPolicy("id", "typeName", "service1", "ric1");
743         {
744             String response = restClient().get(url).block();
745             PolicyInfo policyInfo = objectMapper.readValue(response, PolicyInfo.class);
746             String expectedResponse = "{\"ric_id\":\"ric1\",\"service_id\":\"service1\",\"policy_id\":\"id\",\"policy_data\":{\"servingCellNrcgi\":\"1\"},\"status_notification_uri\":\"/policy-status?id=XXX\",\"policytype_id\":\"typeName\",\"transient\":false}";
747             assertEquals(objectMapper.readTree(expectedResponse), objectMapper.readTree(response));
748         }
749         {
750             policies.remove(policy);
751             testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
752         }
753     }
754
755     @Test
756     @DisplayName("test Delete Policy")
757     void testDeletePolicy() throws Exception {
758         String policyId = "id.1";
759         addPolicy(policyId, "typeName", "service1", "ric1");
760         assertThat(policies.size()).isEqualTo(1);
761
762         String url = "/policies/" + policyId;
763         ResponseEntity<String> entity = restClient().deleteForEntity(url).block();
764
765         assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
766         assertThat(policies.size()).isZero();
767
768         // Delete a non existing policy
769         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
770     }
771
772
773     @Test
774     @DisplayName("test Get Policy Type")
775     void testGetPolicyType() throws Exception {
776         String typeId = "AC.D";
777         addPolicyType(typeId, "ric1");
778
779         waitForRicState("ric1", RicState.AVAILABLE);
780
781         String url = "/policy-types/" + typeId;
782
783         String response = this.restClient().get(url).block();
784
785         assertEquals("{\"policy_schema\":{\"title\":\"AC.D\"}}", response);
786
787         // Get non existing schema
788         url = "/policy-types/JUNK";
789         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
790     }
791
792     String createPolicyTypesJson(String... types) throws JsonProcessingException {
793         List<String> list = new ArrayList<>();
794         Collections.addAll(list, types);
795         PolicyTypeIdList ids = new PolicyTypeIdList();
796         ids.setPolicytypeIds(list);
797         return objectMapper.writeValueAsString(ids);
798     }
799
800     @Test
801     @DisplayName("test Get Policy Types")
802     void testGetPolicyTypes() throws Exception {
803         String TYPE_ID_1 = "A_type1_1.9.0";
804         String TYPE_ID_2 = "A_type1_2.0.0";
805         String TYPE_ID_3 = "A_type1_1.5.0";
806         String TYPE_ID_4 = "type3_1.9.0";
807         addPolicyType(TYPE_ID_1, "ric1");
808         addPolicyType(TYPE_ID_2, "ric2");
809         addPolicyType(TYPE_ID_3, "ric2");
810         addPolicyType(TYPE_ID_4, "ric2");
811
812         addPolicyType("junk", "ric2");
813         addPolicyType("junk_a.b.c", "ric2");
814
815         String url = "/policy-types";
816         String rsp = restClient().get(url).block();
817         assertThat(rsp).contains(TYPE_ID_1, TYPE_ID_2);
818
819         url = "/policy-types?ric_id=ric1";
820         rsp = restClient().get(url).block();
821         String expResp = createPolicyTypesJson(TYPE_ID_1);
822         assertThat(rsp).isEqualTo(expResp);
823
824         // Get policy types for non existing RIC
825         url = "/policy-types?ric_id=ric1XXX";
826         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
827
828         // All types with a type_name
829         url = "/policy-types?type_name=A_type1";
830         rsp = restClient().get(url).block();
831         assertThat(rsp).contains(TYPE_ID_1, TYPE_ID_2);
832
833         // All types compatible with type1_1.5.0 (which is type1_1.9.0)
834         url = "/policy-types?type_name=A_type1&&compatible_with_version=1.5.0";
835         rsp = restClient().get(url).block();
836         expResp = createPolicyTypesJson(TYPE_ID_3, TYPE_ID_1);
837         assertThat(rsp).isEqualTo(expResp);
838
839         url = "/policy-types?type_name=A_type1&&compatible_with_version=junk";
840         testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "Version must contain major.minor.patch code");
841
842         url = "/policy-types?type_name=A_type1&&compatible_with_version=a.b.c";
843         testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "Syntax error in");
844
845         url = "/policy-types?compatible_with_version=1.5.0";
846         testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "type_name");
847     }
848
849     @Test
850     @DisplayName("test Get Policy Instances")
851     void testGetPolicyInstances() throws Exception {
852         addPolicy("id1", "type1", "service1");
853
854         String url = "/policy-instances";
855         String response = restClient().get(url).block();
856         logger.info(response);
857         PolicyInfoList policyInfoList = objectMapper.readValue(response, PolicyInfoList.class);
858         assertThat(policyInfoList.getPolicies()).hasSize(1);
859         PolicyInfo policyInfo = policyInfoList.getPolicies().iterator().next();
860         assertThat(policyInfo.getPolicyId()).isEqualTo("id1");
861         assertThat(policyInfo.getPolicytypeId()).isEqualTo("type1");
862         assertThat(policyInfo.getServiceId()).isEqualTo("service1");
863     }
864
865     @Test
866     @DisplayName("test Get Policy Instances Filter")
867     void testGetPolicyInstancesFilter() throws Exception {
868         addPolicy("id1", "type1", "service1");
869         addPolicy("id2", "type1", "service2");
870         addPolicy("id3", "type2", "service1");
871         addPolicy("id4", "type1_1.0.0", "service1");
872
873         String url = "/policy-instances?policytype_id=type1";
874         String rsp = restClient().get(url).block();
875         logger.info(rsp);
876         assertThat(rsp).contains("id1")
877                 .contains("id2")
878                 .doesNotContain("id3");
879
880         url = "/policy-instances?policytype_id=type1&service_id=service2";
881         rsp = restClient().get(url).block();
882         logger.info(rsp);
883         assertThat(rsp).doesNotContain("id1")
884                 .contains("id2") //
885                 .doesNotContain("id3");
886
887         url = "/policy-instances?type_name=type1";
888         rsp = restClient().get(url).block();
889         assertThat(rsp).contains("id1") //
890                 .contains("id2") //
891                 .doesNotContain("id3")
892                 .contains("id4");
893
894         // Test get policies for non existing type
895         url = "/policy-instances?policytype_id=type1XXX";
896         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
897
898         // Test get policies for non existing RIC
899         url = "/policy-instances?ric_id=XXX";
900         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
901     }
902
903     @Test
904     @DisplayName("test Get Policy Ids Filter")
905     void testGetPolicyIdsFilter() throws Exception {
906         addPolicy("id1", "type1", "service1", "ric1");
907         addPolicy("id2", "type1", "service2", "ric1");
908         addPolicy("id3", "type2", "service1", "ric1");
909         addPolicy("id4", "type1_1.0.0", "service1");
910
911         String url = "/policies?policytype_id=type1";
912         String rsp = restClient().get(url).block();
913         logger.info(rsp);
914         assertThat(rsp).contains("id1")
915                 .contains("id2")
916                 .doesNotContain("id3");
917
918         url = "/policies?policytype_id=type1&service_id=service1&ric=ric1";
919         rsp = restClient().get(url).block();
920         PolicyIdList respList = objectMapper.readValue(rsp, PolicyIdList.class);
921         assertThat(respList.getPolicyIds().iterator().next()).isEqualTo("id1");
922
923         url = "/policies?type_name=type1&service_id=service1";
924         rsp = restClient().get(url).block();
925         assertThat(rsp).contains("id1").contains("id4");
926         assertThat(objectMapper.readValue(rsp, PolicyIdList.class).getPolicyIds()).hasSize(2);
927
928         // Test get policy ids for non existing type
929         url = "/policies?policytype_id=type1XXX";
930         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
931
932         // Test get policy ids for non existing RIC
933         url = "/policies?ric_id=XXX";
934         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
935     }
936
937
938     @Test
939     @DisplayName("test Put And Get Service")
940     void testPutAndGetService() throws Exception {
941         // PUT
942         String serviceName = "ac.dc";
943         putService(serviceName, 0, HttpStatus.CREATED);
944         putService(serviceName, 0, HttpStatus.OK);
945
946         // GET one service
947         String url = "/services?service_id=" + serviceName;
948         String rsp = restClient().get(url).block();
949         ServiceStatusList info = objectMapper.readValue(rsp, ServiceStatusList.class);
950         assertThat(info.getServiceList()).hasSize(1);
951         ServiceStatus status = info.getServiceList().iterator().next();
952         assertThat(status.getKeepAliveIntervalSeconds()).isZero();
953         assertThat(status.getServiceId()).isEqualTo(serviceName);
954
955         // GET (all)
956         url = "/services";
957         rsp = restClient().get(url).block();
958         assertThat(rsp).as("Response contains service name").contains(serviceName);
959         logger.info(rsp);
960
961         // Keep alive
962         url = "/services/" + serviceName + "/keepalive";
963         ResponseEntity<?> entity = restClient().putForEntity(url).block();
964         assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
965
966         // DELETE service
967         assertThat(services.size()).isEqualTo(1);
968         url = "/services/" + serviceName;
969         restClient().delete(url).block();
970         assertThat(services.size()).isZero();
971
972         // Keep alive, no registered service
973         testErrorCode(restClient().put("/services/junk/keepalive", ""), HttpStatus.NOT_FOUND);
974
975         // PUT service with bad payload
976         testErrorCode(restClient().put("/services", "crap"), HttpStatus.BAD_REQUEST, false);
977         testErrorCode(restClient().put("/services", "{}"), HttpStatus.BAD_REQUEST, false);
978         testErrorCode(restClient().put("/services", createServiceJson(serviceName, -123)), HttpStatus.BAD_REQUEST,
979                 false);
980         testErrorCode(restClient().put("/services", createServiceJson(serviceName, 0, "missing.portandprotocol.com")),
981                 HttpStatus.BAD_REQUEST, false);
982
983         // GET non existing service
984         testErrorCode(restClient().get("/services?service_id=XXX"), HttpStatus.NOT_FOUND);
985     }
986
987     @Test
988     @DisplayName("test Service Supervision")
989     void testServiceSupervision() throws Exception {
990         putService("service1", 2, HttpStatus.CREATED);
991         addPolicyType("type1", "ric1");
992
993         String policyBody = putPolicyBody("service1", "ric1", "type1", "instance1");
994         restClient().put("/policies", policyBody).block();
995
996         assertThat(policies.size()).isEqualTo(1);
997         assertThat(services.size()).isEqualTo(1);
998
999         // Timeout after ~2 second
1000         await().untilAsserted(() -> assertThat(policies.size()).isZero());
1001         assertThat(services.size()).isZero();
1002     }
1003
1004     @Test
1005     @DisplayName("test Get Policy Status")
1006     void testGetPolicyStatus() throws Exception {
1007         addPolicy("id", "typeName", "service1", "ric1");
1008         assertThat(policies.size()).isEqualTo(1);
1009
1010         String url = "/policies/id/status";
1011         String response = restClient().get(url).block();
1012         PolicyStatusInfo info = objectMapper.readValue(response, PolicyStatusInfo.class);
1013         assertThat(info.getStatus()).isEqualTo("OK");
1014
1015         // GET non existing policy status
1016         url = "/policies/XXX/status";
1017         testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
1018
1019         // GET STATUS, the NearRT RIC returns error
1020         MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client("ric1");
1021         url = "/policies/id/status";
1022         WebClientResponseException a1Exception = new WebClientResponseException(404, "", null, null, null);
1023         doReturn(Mono.error(a1Exception)).when(a1Client).getPolicyStatus(any());
1024         response = restClient().get(url).block();
1025         info = objectMapper.readValue(response, PolicyStatusInfo.class);
1026         assertThat(info.getStatus()).hasToString("{}");
1027     }
1028
1029     @Test
1030     @DisplayName("test Get Service Status")
1031     void testGetServiceStatus() {
1032         String url = "/status";
1033         String rsp = restClient().get(url).block();
1034         assertThat(rsp).contains("success");
1035
1036         rsp = restClient(baseUrl(), false).get(url).block(); // V1 status is used by a readinessProbe
1037         assertThat(rsp).isEqualTo("success");
1038     }
1039
1040     @Test
1041     @DisplayName("test Service Notification")
1042     void testServiceNotification() throws Exception {
1043
1044         final String AUTH_TOKEN = "testToken";
1045         Path authFile = Files.createTempFile("pmsTestAuthToken", ".txt");
1046         Files.write(authFile, AUTH_TOKEN.getBytes());
1047         this.securityContext.setAuthTokenFilePath(authFile);
1048
1049         putService("junkService");
1050         Service junkService = this.services.get("junkService");
1051         junkService.setCallbackUrl("https://junk");
1052         putService("service");
1053
1054         Ric ric = addRic("ric1");
1055         ric.setState(Ric.RicState.UNAVAILABLE);
1056         supervision.checkAllRics();
1057         waitForRicState("ric1", RicState.AVAILABLE);
1058
1059         final RappSimulatorController.TestResults receivedCallbacks = rAppSimulator.getTestResults();
1060         await().untilAsserted(() -> assertThat(receivedCallbacks.getReceivedInfo()).hasSize(1));
1061         ServiceCallbackInfo callbackInfo = receivedCallbacks.getReceivedInfo().get(0);
1062         assertThat(callbackInfo.ricId).isEqualTo("ric1");
1063         assertThat(callbackInfo.eventType).isEqualTo(ServiceCallbackInfo.EventType.AVAILABLE);
1064
1065         var headers = receivedCallbacks.receivedHeaders.get(0);
1066         assertThat(headers).containsEntry("authorization", "Bearer " + AUTH_TOKEN);
1067
1068         Files.delete(authFile);
1069     }
1070
1071     private Policy addPolicy(String id, String typeName, String service, String ric) throws ServiceException {
1072        try {
1073            addRic(ric);
1074            Policy policy = Policy.builder()
1075                    .id(id)
1076                    .json(objectMapper.writeValueAsString(jsonString()))
1077                    .ownerServiceId(service)
1078                    .ric(rics.getRic(ric))
1079                    .type(addPolicyType(typeName, ric))
1080                    .lastModified(Instant.now())
1081                    .isTransient(false)
1082                    .statusNotificationUri("/policy-status?id=XXX")
1083                    .build();
1084            policies.put(policy);
1085            return policy;
1086        } catch (JsonProcessingException ex) {
1087             throw new RuntimeException(ex);
1088        }
1089     }
1090
1091     private Policy addPolicy(String id, String typeName, String service) throws ServiceException {
1092         return addPolicy(id, typeName, service, "ric");
1093     }
1094
1095     private String createServiceJson(String name, long keepAliveIntervalSeconds) throws JsonProcessingException {
1096         String callbackUrl = baseUrl() + RappSimulatorController.SERVICE_CALLBACK_URL;
1097         return createServiceJson(name, keepAliveIntervalSeconds, callbackUrl);
1098     }
1099
1100     private String createServiceJson(String name, long keepAliveIntervalSeconds, String url) throws JsonProcessingException {
1101         ServiceRegistrationInfo service = new ServiceRegistrationInfo(name)
1102                 .keepAliveIntervalSeconds(keepAliveIntervalSeconds)
1103                 .callbackUrl(url);
1104
1105         return objectMapper.writeValueAsString(service);
1106     }
1107
1108     private void putService(String name) throws JsonProcessingException {
1109         putService(name, 0, null);
1110     }
1111
1112     private void putService(String name, long keepAliveIntervalSeconds, @Nullable HttpStatus expectedStatus) throws JsonProcessingException {
1113         String url = "/services";
1114         String body = createServiceJson(name, keepAliveIntervalSeconds);
1115         ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
1116         if (expectedStatus != null) {
1117             assertNotNull(resp);
1118             assertEquals(expectedStatus, resp.getStatusCode(), "");
1119         }
1120     }
1121
1122     private Map<String,String> jsonString() {
1123         Map<String,String> policyDataInMap = new HashMap<>();
1124         policyDataInMap.put("servingCellNrcgi","1");
1125         return policyDataInMap;
1126     }
1127
1128     @Test
1129     @DisplayName("test Concurrency")
1130     void testConcurrency() throws Exception {
1131         this.applicationConfig.setAuthProviderUrl("");
1132         logger.info("Concurrency test starting");
1133         final Instant startTime = Instant.now();
1134         List<Thread> threads = new ArrayList<>();
1135         List<ConcurrencyTestRunnable> tests = new ArrayList<>();
1136         a1ClientFactory.setResponseDelay(Duration.ofMillis(2));
1137         addRic("ric");
1138         addPolicyType("type1", "ric");
1139         addPolicyType("type2", "ric");
1140
1141         final String NON_RESPONDING_RIC = "NonRespondingRic";
1142         Ric nonRespondingRic = addRic(NON_RESPONDING_RIC);
1143         MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client(NON_RESPONDING_RIC);
1144         a1Client.setErrorInject("errorInject");
1145
1146         for (int i = 0; i < 10; ++i) {
1147             AsyncRestClient restClient = restClient();
1148             ConcurrencyTestRunnable test =
1149                     new ConcurrencyTestRunnable(restClient, supervision, a1ClientFactory, rics, policyTypes);
1150             Thread thread = new Thread(test, "TestThread_" + i);
1151             thread.start();
1152             threads.add(thread);
1153             tests.add(test);
1154         }
1155         for (Thread t : threads) {
1156             t.join();
1157         }
1158         for (ConcurrencyTestRunnable test : tests) {
1159             assertThat(test.isFailed()).isFalse();
1160         }
1161         assertThat(policies.size()).isZero();
1162         logger.info("Concurrency test took " + Duration.between(startTime, Instant.now()));
1163
1164         assertThat(nonRespondingRic.getState()).isEqualTo(RicState.UNAVAILABLE);
1165         nonRespondingRic.setState(RicState.AVAILABLE);
1166     }
1167
1168     private AsyncRestClient restClient(String baseUrl, boolean useTrustValidation) {
1169         WebClientConfig config = this.applicationConfig.getWebClientConfig();
1170         config = WebClientConfig.builder()
1171                 .keyStoreType(config.getKeyStoreType())
1172                 .keyStorePassword(config.getKeyStorePassword())
1173                 .keyStore(config.getKeyStore())
1174                 .keyPassword(config.getKeyPassword())
1175                 .isTrustStoreUsed(useTrustValidation)
1176                 .trustStore(config.getTrustStore())
1177                 .trustStorePassword(config.getTrustStorePassword())
1178                 .httpProxyConfig(config.getHttpProxyConfig())
1179                 .build();
1180
1181         AsyncRestClientFactory f = new AsyncRestClientFactory(config, new SecurityContext(""));
1182         return f.createRestClientNoHttpProxy(baseUrl);
1183
1184     }
1185
1186     private String baseUrl() {
1187         return "https://localhost:" + port;
1188     }
1189
1190     private AsyncRestClient restClient(boolean useTrustValidation) {
1191         return restClient(baseUrl() + Consts.V2_API_ROOT, useTrustValidation);
1192     }
1193
1194     private AsyncRestClient restClient() {
1195         return restClient(false);
1196     }
1197
1198     private void testErrorCode(Mono<?> request, HttpStatus expStatus) {
1199         testErrorCode(request, expStatus, "", true);
1200     }
1201
1202     private void testErrorCode(Mono<?> request, HttpStatus expStatus, boolean expectApplicationProblemJsonMediaType) {
1203         testErrorCode(request, expStatus, "", expectApplicationProblemJsonMediaType);
1204     }
1205
1206     private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains) {
1207         testErrorCode(request, expStatus, responseContains, true);
1208     }
1209
1210     private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains,
1211             boolean expectApplicationProblemJsonMediaType) {
1212         StepVerifier.create(request)
1213                 .expectSubscription()
1214                 .expectErrorMatches(
1215                         t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType))
1216                 .verify();
1217     }
1218
1219     private void waitForRicState(String ricId, RicState state) throws ServiceException {
1220         Ric ric = rics.getRic(ricId);
1221         await().untilAsserted(() -> state.equals(ric.getState()));
1222     }
1223
1224     private boolean checkWebClientError(Throwable throwable, HttpStatus expStatus, String responseContains,
1225             boolean expectApplicationProblemJsonMediaType) {
1226         assertTrue(throwable instanceof WebClientResponseException);
1227         WebClientResponseException responseException = (WebClientResponseException) throwable;
1228         String body = responseException.getResponseBodyAsString();
1229         assertThat(body).contains(responseContains);
1230         assertThat(responseException.getStatusCode()).isEqualTo(expStatus);
1231
1232         if (expectApplicationProblemJsonMediaType) {
1233             assertThat(responseException.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PROBLEM_JSON);
1234         }
1235         return true;
1236     }
1237
1238     private MockA1Client getA1Client(String ricId) {
1239         return a1ClientFactory.getOrCreateA1Client(ricId);
1240     }
1241
1242     private PolicyType createPolicyType(String policyTypeName) {
1243         return PolicyType.builder()
1244                 .id(policyTypeName)
1245                 .schema("{\"title\":\"" + policyTypeName + "\"}")
1246                 .build();
1247     }
1248
1249     private PolicyType addPolicyType(String policyTypeName, String ricId) {
1250         PolicyType type = createPolicyType(policyTypeName);
1251         policyTypes.put(type);
1252         addRic(ricId).addSupportedPolicyType(type);
1253         return type;
1254     }
1255
1256     private Ric addRic(String ricId) {
1257         return addRic(ricId, null);
1258     }
1259
1260     private RicConfig ricConfig(String ricId, String managedElement) {
1261         List<String> mes = new ArrayList<>();
1262         if (managedElement != null) {
1263             mes.add(managedElement);
1264         }
1265         return RicConfig.builder()
1266                 .ricId(ricId)
1267                 .baseUrl(ricId)
1268                 .managedElementIds(mes)
1269                 .build();
1270     }
1271
1272     private Ric addRic(String ricId, String managedElement) {
1273         if (rics.get(ricId) != null) {
1274             return rics.get(ricId);
1275         }
1276
1277         RicConfig conf = ricConfig(ricId, managedElement);
1278         Ric ric = new Ric(conf);
1279         ric.setState(Ric.RicState.AVAILABLE);
1280         this.rics.put(ric);
1281         return ric;
1282     }
1283
1284 }