2 * ========================LICENSE_START=================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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===================================
21 package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2;
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.awaitility.Awaitility.await;
25 import static org.junit.jupiter.api.Assertions.assertEquals;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27 import static org.mockito.ArgumentMatchers.any;
28 import static org.mockito.Mockito.doReturn;
30 import com.fasterxml.jackson.core.JsonProcessingException;
31 import com.fasterxml.jackson.databind.ObjectMapper;
32 import com.google.gson.Gson;
33 import com.google.gson.GsonBuilder;
35 import java.lang.invoke.MethodHandles;
36 import java.nio.charset.StandardCharsets;
37 import java.nio.file.Files;
38 import java.nio.file.Path;
39 import java.time.Duration;
40 import java.time.Instant;
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.List;
45 import java.util.HashMap;
47 import org.junit.jupiter.api.AfterAll;
48 import org.junit.jupiter.api.AfterEach;
49 import org.junit.jupiter.api.BeforeEach;
50 import org.junit.jupiter.api.DisplayName;
51 import org.junit.jupiter.api.MethodOrderer;
52 import org.junit.jupiter.api.Test;
53 import org.junit.jupiter.api.TestMethodOrder;
54 import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory;
55 import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClient;
56 import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClientFactory;
57 import org.onap.ccsdk.oran.a1policymanagementservice.clients.SecurityContext;
58 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig;
59 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig.RicConfigUpdate;
60 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.RicConfig;
61 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientConfig;
62 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.OpenPolicyAgentSimulatorController;
63 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.ServiceCallbackInfo;
64 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.PolicyAuthorizationRequest;
65 import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.PolicyAuthorizationRequest.Input.AccessType;
66 import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
67 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.RicInfo;
68 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyTypeDefinition;
69 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyTypeIdList;
70 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfo;
71 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfoList;
72 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyIdList;
73 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyStatusInfo;
74 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceStatusList;
75 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceStatus;
76 import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceRegistrationInfo;
77 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock;
78 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock.LockType;
79 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies;
80 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy;
81 import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyType;
82 import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes;
83 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric;
84 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric.RicState;
85 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics;
86 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Service;
87 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Services;
88 import org.onap.ccsdk.oran.a1policymanagementservice.tasks.RefreshConfigTask;
89 import org.onap.ccsdk.oran.a1policymanagementservice.tasks.RicSupervision;
90 import org.onap.ccsdk.oran.a1policymanagementservice.tasks.ServiceSupervision;
91 import org.onap.ccsdk.oran.a1policymanagementservice.utils.MockA1Client;
92 import org.onap.ccsdk.oran.a1policymanagementservice.utils.MockA1ClientFactory;
93 import org.slf4j.Logger;
94 import org.slf4j.LoggerFactory;
95 import org.springframework.beans.factory.annotation.Autowired;
96 import org.springframework.boot.test.context.SpringBootTest;
97 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
98 import org.springframework.boot.test.context.TestConfiguration;
99 import org.springframework.boot.test.web.server.LocalServerPort;
100 import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
101 import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
102 import org.springframework.context.ApplicationContext;
103 import org.springframework.context.annotation.Bean;
104 import org.springframework.http.HttpStatus;
105 import org.springframework.http.MediaType;
106 import org.springframework.http.ResponseEntity;
107 import org.springframework.test.context.TestPropertySource;
108 import org.springframework.util.FileSystemUtils;
109 import org.springframework.web.reactive.function.client.WebClientRequestException;
110 import org.springframework.web.reactive.function.client.WebClientResponseException;
112 import reactor.core.publisher.Mono;
113 import reactor.test.StepVerifier;
114 import reactor.util.annotation.Nullable;
116 @TestMethodOrder(MethodOrderer.MethodName.class)
117 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
118 @TestPropertySource(properties = { //
119 "server.ssl.key-store=./config/keystore.jks", //
120 "app.webclient.trust-store=./config/truststore.jks", //
121 "app.webclient.trust-store-used=true", //
122 "app.vardata-directory=/tmp/pmstest", //
124 "app.s3.bucket=" // If this is set, S3 will be used to store data.
126 class ApplicationTest {
127 private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
130 ApplicationContext context;
136 private Policies policies;
139 private PolicyTypes policyTypes;
142 MockA1ClientFactory a1ClientFactory;
145 private ObjectMapper objectMapper;
148 RicSupervision supervision;
151 ApplicationConfig applicationConfig;
157 RappSimulatorController rAppSimulator;
160 RefreshConfigTask refreshConfigTask;
163 SecurityContext securityContext;
166 OpenPolicyAgentSimulatorController openPolicyAgentSimulatorController;
168 private static Gson gson = new GsonBuilder().create();
171 * Overrides the BeanFactory.
174 static class TestBeanFactory {
177 A1ClientFactory getA1ClientFactory(@Autowired ApplicationConfig appConfig, @Autowired PolicyTypes types) {
178 return new MockA1ClientFactory(appConfig, types);
182 public ServiceSupervision getServiceSupervision(@Autowired Services services,
183 @Autowired A1ClientFactory a1ClientFactory, @Autowired Policies policies) {
184 Duration checkInterval = Duration.ofMillis(1);
185 return new ServiceSupervision(services, policies, a1ClientFactory, checkInterval);
189 public ServletWebServerFactory servletContainer() {
190 return new TomcatServletWebServerFactory();
199 this.applicationConfig.setAuthProviderUrl(baseUrl() + OpenPolicyAgentSimulatorController.ACCESS_CONTROL_URL);
208 a1ClientFactory.reset();
209 this.rAppSimulator.getTestResults().clear();
210 this.a1ClientFactory.setPolicyTypes(policyTypes); // Default same types in RIC and in this app
211 this.securityContext.setAuthTokenFilePath(null);
212 this.openPolicyAgentSimulatorController.getTestResults().reset();
216 static void clearTestDir() {
218 FileSystemUtils.deleteRecursively(Path.of("/tmp/pmstest"));
219 } catch (Exception e) {
220 logger.warn("Could test directory : {}", e.getMessage());
225 void verifyNoRicLocks() {
226 for (Ric ric : this.rics.getRics()) {
227 Lock.Grant grant = ric.getLock().lockBlocking(LockType.EXCLUSIVE, "verifyNoRicLocks");
228 grant.unlockBlocking();
229 assertThat(ric.getLock().getLockCounter()).isZero();
230 assertThat(ric.getState()).isEqualTo(Ric.RicState.AVAILABLE);
235 @SuppressWarnings("squid:S2925") // "Thread.sleep" should not be used in tests.
236 @DisplayName("test ZZ Actuator")
237 void testZZActuator() throws Exception {
238 // The test must be run last, hence the "ZZ" in the name. All succeeding tests
240 AsyncRestClient client = restClient(baseUrl(), false);
242 client.post("/actuator/loggers/org.onap.ccsdk.oran.a1policymanagementservice",
243 "{\"configuredLevel\":\"trace\"}").block();
245 String resp = client.get("/actuator/loggers/org.onap.ccsdk.oran.a1policymanagementservice").block();
246 assertThat(resp).contains("TRACE");
248 client.post("/actuator/loggers/org.springframework.boot.actuate", "{\"configuredLevel\":\"trace\"}").block();
250 // This will stop the web server and all coming tests will fail.
251 client.post("/actuator/shutdown", "").block();
255 StepVerifier.create(restClient().get("/rics")) // Any call
256 .expectSubscription() //
257 .expectErrorMatches(t -> t instanceof WebClientRequestException) //
263 @DisplayName("test Persistency Policies")
264 void testPersistencyPolicies() throws Exception {
265 Ric ric = this.addRic("ric1");
266 PolicyType type = this.addPolicyType("type1", ric.id());
268 final int noOfPolicies = 100;
269 for (int i = 0; i < noOfPolicies; ++i) {
270 addPolicy("id" + i, type.getId(), "service", ric.id());
275 Policies policies = new Policies(this.applicationConfig);
276 policies.restoreFromDatabase(ric, this.policyTypes).blockLast();
277 assertThat(policies.size()).isEqualTo(noOfPolicies);
281 restClient().delete("/policies/id2").block();
282 Policies policies = new Policies(this.applicationConfig);
283 policies.restoreFromDatabase(ric, this.policyTypes).blockLast();
284 assertThat(policies.size()).isEqualTo(noOfPolicies - 1);
289 @DisplayName("test Persistency Policy Types")
290 void testPersistencyPolicyTypes() throws Exception {
291 Ric ric = this.addRic("ric1");
292 this.addPolicyType("type1", ric.id());
295 PolicyTypes types = new PolicyTypes(this.applicationConfig);
296 types.restoreFromDatabase().blockLast();
297 assertThat(types.size()).isEqualTo(1);
300 @SuppressWarnings("squid:S2925") // "Thread.sleep" should not be used in tests.
301 private void waitforS3() throws Exception {
302 if (applicationConfig.isS3Enabled()) {
308 @DisplayName("test Persistency Service")
309 void testPersistencyService() throws Exception {
310 final String SERVICE = "serviceName";
311 putService(SERVICE, 1234, HttpStatus.CREATED);
312 assertThat(this.services.size()).isEqualTo(1);
313 Service service = this.services.getService(SERVICE);
316 Services servicesRestored = new Services(this.applicationConfig);
317 servicesRestored.restoreFromDatabase().blockLast();
318 Service serviceRestored = servicesRestored.getService(SERVICE);
319 assertThat(servicesRestored.size()).isEqualTo(1);
320 assertThat(serviceRestored.getCallbackUrl()).isEqualTo(service.getCallbackUrl());
321 assertThat(serviceRestored.getKeepAliveInterval()).isEqualTo(service.getKeepAliveInterval());
323 // check that the service can be deleted
324 this.services.remove(SERVICE);
325 servicesRestored = new Services(this.applicationConfig);
326 assertThat(servicesRestored.size()).isZero();
330 @DisplayName("test Adding Ric From Configuration")
331 void testAddingRicFromConfiguration() throws Exception {
332 // Test adding the RIC from configuration
334 final String RIC = "ric1";
335 final String TYPE = "type123";
336 PolicyTypes nearRtRicPolicyTypes = new PolicyTypes(this.applicationConfig);
337 nearRtRicPolicyTypes.put(createPolicyType(TYPE));
338 this.a1ClientFactory.setPolicyTypes(nearRtRicPolicyTypes);
340 putService("service");
342 refreshConfigTask.handleUpdatedRicConfig( //
343 new RicConfigUpdate(ricConfig(RIC, "me1"), RicConfigUpdate.Type.ADDED)) //
345 waitForRicState(RIC, RicState.AVAILABLE);
347 // Test that the type has been synched
348 Ric addedRic = this.rics.getRic(RIC);
349 assertThat(addedRic.getSupportedPolicyTypes()).hasSize(1);
350 assertThat(addedRic.getSupportedPolicyTypes().iterator().next().getId()).isEqualTo(TYPE);
352 // Check that a service callback for the AVAILABLE RIC is invoked
353 final RappSimulatorController.TestResults receivedCallbacks = rAppSimulator.getTestResults();
354 await().untilAsserted(() -> assertThat(receivedCallbacks.getReceivedInfo()).hasSize(1));
355 ServiceCallbackInfo callbackInfo = receivedCallbacks.getReceivedInfo().get(0);
356 assertThat(callbackInfo.ricId).isEqualTo(RIC);
357 assertThat(callbackInfo.eventType).isEqualTo(ServiceCallbackInfo.EventType.AVAILABLE);
361 @DisplayName("test Adding Ric From Configuration non Responding Ric")
362 void testAddingRicFromConfiguration_nonRespondingRic() throws Exception {
363 putService("service");
365 final String RIC = "NonRespondingRic";
366 MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client(RIC);
367 doReturn(MockA1Client.monoError("error", HttpStatus.BAD_GATEWAY)).when(a1Client).getPolicyTypeIdentities();
369 refreshConfigTask.handleUpdatedRicConfig( //
370 new RicConfigUpdate(ricConfig(RIC, "me1"), RicConfigUpdate.Type.ADDED)) //
373 waitForRicState(RIC, RicState.UNAVAILABLE);
375 // Check that no service callback for the UNAVAILABLE RIC is invoked
376 final RappSimulatorController.TestResults receivedCallbacks = rAppSimulator.getTestResults();
377 await().untilAsserted(() -> assertThat(receivedCallbacks.getReceivedInfo()).isEmpty());
379 // Run a synch and check that the AVAILABLE notification is received
380 a1ClientFactory.reset();
381 supervision.checkAllRics();
382 waitForRicState(RIC, RicState.AVAILABLE);
384 await().untilAsserted(() -> assertThat(receivedCallbacks.getReceivedInfo()).hasSize(1));
388 @DisplayName("test Trust Validation")
389 void testTrustValidation() {
392 String rsp = restClient(true).get("/rics").block(); // restClient(true) enables trust validation
393 assertThat(rsp).contains("ric1");
398 @DisplayName("test Get Rics")
399 void testGetRics() throws Exception {
401 this.addPolicyType("type1", "ric1");
402 String url = "/rics?policytype_id=type1";
403 String rsp = restClient().get(url).block();
404 String expectedResponse = "{\"rics\":[{\"managed_element_ids\":[],\"ric_id\":\"ric1\", \"state\":\"AVAILABLE\",\"policytype_ids\":[\"type1\"]}]}";
405 assertEquals(objectMapper.readTree(expectedResponse), objectMapper.readTree(rsp));
407 // nameless type for ORAN A1 1.1
409 this.addPolicyType("", "ric2");
410 url = "/rics?policytype_id=";
411 rsp = restClient().get(url).block();
412 assertThat(rsp).contains("ric2") //
413 .doesNotContain("ric1") //
414 .contains("AVAILABLE");
417 rsp = restClient().get("/rics").block();
418 assertThat(rsp).contains("ric2") //
421 // Non existing policy type
422 url = "/rics?policytype_id=XXXX";
423 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
427 @DisplayName("test Synchronization")
428 void testSynchronization() throws Exception {
429 // Two polictypes will be put in the NearRT RICs
430 PolicyTypes nearRtRicPolicyTypes = new PolicyTypes(this.applicationConfig);
431 nearRtRicPolicyTypes.put(createPolicyType("typeName"));
432 nearRtRicPolicyTypes.put(createPolicyType("typeName2"));
433 this.a1ClientFactory.setPolicyTypes(nearRtRicPolicyTypes);
435 // One type and one instance added to the Policy Management Service's storage
436 final String ric1Name = "ric1";
437 Ric ric1 = addRic(ric1Name);
438 Policy policy2 = addPolicy("policyId2", "typeName", "service", ric1Name);
439 Ric ric2 = addRic("ric2");
441 getA1Client(ric1Name).putPolicy(policy2); // put it in the RIC (Near-RT RIC)
442 policies.remove(policy2); // Remove it from the repo -> should be deleted in the RIC
444 String policyId = "policyId";
445 Policy policy = addPolicy(policyId, "typeName", "service", ric1Name); // This should be created in the RIC
446 supervision.checkAllRics(); // The created policy should be put in the RIC
448 // Wait until synch is completed
449 waitForRicState(ric1Name, RicState.SYNCHRONIZING);
450 waitForRicState(ric1Name, RicState.AVAILABLE);
451 waitForRicState("ric2", RicState.AVAILABLE);
453 Policies ricPolicies = getA1Client(ric1Name).getPolicies();
454 assertThat(ricPolicies.size()).isEqualTo(1);
455 Policy ricPolicy = ricPolicies.get(policyId);
456 assertThat(ricPolicy.getJson()).isEqualTo(policy.getJson());
458 // Both types should be in the Policy Management Service's storage after the
460 assertThat(ric1.getSupportedPolicyTypes()).hasSize(2);
461 assertThat(ric2.getSupportedPolicyTypes()).hasSize(2);
465 @DisplayName("test Get Ric")
466 void testGetRic() throws Exception {
467 String ricId = "ric1";
468 String managedElementId = "kista_1";
469 addRic(ricId, managedElementId);
471 String url = "/rics/ric?managed_element_id=" + managedElementId;
472 String rsp = restClient().get(url).block();
473 RicInfo ricInfo = objectMapper.readValue(rsp, RicInfo.class);
474 assertThat(ricInfo.getRicId()).isEqualTo(ricId);
476 url = "/rics/ric?ric_id=" + ricId;
477 rsp = restClient().get(url).block();
478 ricInfo = objectMapper.readValue(rsp, RicInfo.class);
479 assertThat(ricInfo.getRicId()).isEqualTo(ricId);
481 // test GET RIC for ManagedElement that does not exist
482 url = "/rics/ric?managed_element_id=" + "junk";
483 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
486 testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST);
489 private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId,
490 boolean isTransient, String statusNotificationUri) throws JsonProcessingException {
491 PolicyInfo policyInfo = new PolicyInfo();
492 policyInfo.setPolicyId(policyInstanceId);
493 policyInfo.setPolicytypeId(policyTypeName);
494 policyInfo.setRicId(ricId);
495 policyInfo.setServiceId(serviceName);
496 policyInfo.setPolicyData(jsonString());
497 policyInfo.setTransient(isTransient);
498 policyInfo.setStatusNotificationUri(statusNotificationUri);
499 return objectMapper.writeValueAsString(policyInfo);
502 private String putPolicyBod(String serviceName, String ricId, String policyTypeName, String policyInstanceId,
503 boolean isTransient, String statusNotificationUri) throws JsonProcessingException {
504 PolicyInfo policyInfo = new PolicyInfo();
505 policyInfo.setPolicyId(policyInstanceId);
506 policyInfo.setPolicytypeId(policyTypeName);
507 policyInfo.setRicId(ricId);
508 policyInfo.setServiceId(serviceName);
509 policyInfo.setPolicyData(jsonString());
510 policyInfo.setTransient(isTransient);
511 policyInfo.setStatusNotificationUri(statusNotificationUri);
512 return objectMapper.writeValueAsString(policyInfo);
515 private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId) throws JsonProcessingException {
516 return putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, false, "statusUri");
520 @DisplayName("test Put Policy")
521 void testPutPolicy() throws Exception {
522 String serviceName = "service.1";
523 String ricId = "ric.1";
524 String policyTypeName = "type1_1.2.3";
525 String policyInstanceId = "instance_1.2.3";
527 putService(serviceName);
528 addPolicyType(policyTypeName, ricId);
530 // PUT a transient policy
531 String url = "/policies";
532 String policyBody = putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, true, "statusNotif");
533 this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
535 restClient().put(url, policyBody).block();
537 // Check the authorization request
538 OpenPolicyAgentSimulatorController.TestResults res =
539 this.openPolicyAgentSimulatorController.getTestResults();
540 assertThat(res.receivedRequests).hasSize(1);
541 PolicyAuthorizationRequest req = res.receivedRequests.get(0);
542 assertThat(req.getInput().getAccessType()).isEqualTo(AccessType.WRITE);
543 assertThat(req.getInput().getPolicyTypeId()).isEqualTo(policyTypeName);
546 Policy policy = policies.getPolicy(policyInstanceId);
547 assertThat(policy).isNotNull();
548 assertThat(policy.getId()).isEqualTo(policyInstanceId);
549 assertThat(policy.getOwnerServiceId()).isEqualTo(serviceName);
550 assertThat(policy.getRic().id()).isEqualTo(ricId);
551 assertThat(policy.isTransient()).isTrue();
553 // Put a non transient policy
554 policyBody = putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId);
555 restClient().put(url, policyBody).block();
556 policy = policies.getPolicy(policyInstanceId);
557 assertThat(policy.isTransient()).isFalse();
559 url = "/policy-instances";
560 String rsp = restClient().get(url).block();
561 assertThat(rsp).as("Response contains policy instance ID.").contains(policyInstanceId);
563 url = "/policies/" + policyInstanceId;
564 rsp = restClient().get(url).block();
566 assertThat(rsp).contains(policyBody);
568 // Test of error codes
570 policyBody = putPolicyBody(serviceName, ricId + "XX", policyTypeName, policyInstanceId);
571 testErrorCode(restClient().put(url, policyBody), HttpStatus.NOT_FOUND);
573 policyBody = putPolicyBody(serviceName, ricId, policyTypeName + "XX", policyInstanceId);
574 addPolicyType(policyTypeName + "XX", "otherRic");
575 testErrorCode(restClient().put(url, policyBody), HttpStatus.NOT_FOUND);
577 policyBody = putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId);
578 this.rics.getRic(ricId).setState(Ric.RicState.SYNCHRONIZING);
579 testErrorCode(restClient().put(url, policyBody), HttpStatus.LOCKED);
580 this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
584 void testFineGrainedAuth() throws Exception {
585 final String POLICY_ID = "policyId";
586 final String RIC_ID = "ric1";
587 final String TYPE_ID = "typeName";
588 addPolicy(POLICY_ID, TYPE_ID, null, RIC_ID);
589 assertThat(policies.size()).isEqualTo(1);
591 this.applicationConfig
592 .setAuthProviderUrl(baseUrl() + OpenPolicyAgentSimulatorController.ACCESS_CONTROL_URL_REJECT);
593 String url = "/policy-instances";
594 String rsp = restClient().get(url).block();
595 assertThat(rsp).as("Response contains no policy instance ID.").contains("[]");
597 url = "/policies/" + POLICY_ID;
598 testErrorCode(restClient().delete(url), HttpStatus.UNAUTHORIZED, "Not authorized");
601 String policyBody = putPolicyBody(null, RIC_ID, TYPE_ID, POLICY_ID, false, null);
602 testErrorCode(restClient().put(url, policyBody), HttpStatus.UNAUTHORIZED, "Not authorized");
604 rsp = restClient().get(url).block();
605 assertThat(rsp).as("Response contains no policy instance ID.").contains("[]");
609 void testFineGrainedAuth_OPA_UNAVALIABLE() throws Exception {
610 final String POLICY_ID = "policyId";
611 final String RIC_ID = "ric1";
612 final String TYPE_ID = "typeName";
613 addPolicy(POLICY_ID, TYPE_ID, null, RIC_ID);
614 assertThat(policies.size()).isEqualTo(1);
616 this.applicationConfig.setAuthProviderUrl("junk");
618 String url = "/policy-instances";
619 String rsp = restClient().get(url).block();
620 assertThat(rsp).as("Response contains no policy instance ID.").contains("[]");
622 url = "/policies/" + POLICY_ID;
623 testErrorCode(restClient().delete(url), HttpStatus.UNAUTHORIZED, "Not authorized");
626 String policyBody = putPolicyBody(null, RIC_ID, TYPE_ID, POLICY_ID, false, null);
627 testErrorCode(restClient().put(url, policyBody), HttpStatus.UNAUTHORIZED, "Not authorized");
629 rsp = restClient().get(url).block();
630 assertThat(rsp).as("Response contains no policy instance ID.").contains("[]");
633 @DisplayName("test Put Policy No Service No Status Uri")
634 void testPutPolicy_NoServiceNoStatusUri() throws Exception {
635 String ricId = "ric.1";
636 String policyTypeName = "type1_1.2.3";
637 String policyInstanceId = "instance_1.2.3";
639 addPolicyType(policyTypeName, ricId);
641 // PUT a transient policy
642 String url = "/policies";
643 String policyBody = putPolicyBody(null, ricId, policyTypeName, policyInstanceId, true, null);
644 this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
646 restClient().put(url, policyBody).block();
648 Policy policy = policies.getPolicy(policyInstanceId);
649 assertThat(policy).isNotNull();
650 assertThat(policy.getOwnerServiceId()).isBlank();
651 assertThat(policy.getStatusNotificationUri()).isBlank();
656 * Test that HttpStatus and body from failing REST call to A1 is passed on to
659 * @throws ServiceException
661 @DisplayName("test Error From Ric")
662 void testErrorFromRic() throws ServiceException, JsonProcessingException {
663 putService("service1");
664 addPolicyType("type1", "ric1");
666 MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client("ric1");
667 HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
668 String responseBody = "Refused";
669 byte[] responseBodyBytes = responseBody.getBytes(StandardCharsets.UTF_8);
671 WebClientResponseException a1Exception = new WebClientResponseException(httpStatus.value(), "statusText", null,
672 responseBodyBytes, StandardCharsets.UTF_8, null);
673 doReturn(Mono.error(a1Exception)).when(a1Client).putPolicy(any());
676 String putBody = putPolicyBody("service1", "ric1", "type1", "id1");
677 String url = "/policies";
678 testErrorCode(restClient().put(url, putBody), httpStatus, responseBody);
681 this.addPolicy("instance1", "type1", "service1", "ric1");
682 doReturn(Mono.error(a1Exception)).when(a1Client).deletePolicy(any());
683 testErrorCode(restClient().delete("/policies/instance1"), httpStatus, responseBody);
688 @DisplayName("test Put Typeless Policy")
689 void testPutTypelessPolicy() throws Exception {
690 putService("service1");
691 addPolicyType("", "ric1");
692 String body = putPolicyBody("service1", "ric1", "", "id1");
693 restClient().put("/policies", body).block();
695 String rsp = restClient().get("/policy-instances").block();
696 PolicyInfoList info = objectMapper.readValue(rsp, PolicyInfoList.class);
697 assertThat(info.getPolicies()).hasSize(1);
698 PolicyInfo policyInfo = info.getPolicies().iterator().next();
699 assertThat(policyInfo.getPolicyId()).isEqualTo("id1");
700 assertThat(policyInfo.getPolicytypeId()).isEmpty();
704 @DisplayName("test Update Service")
705 void testUpdateService() throws Exception {
707 this.addPolicy("policyId", "type1", "", "ric1");
709 String url = "/policies?service_id=";
710 String resp = restClient().get(url).block();
711 String expectedResponse = "{\"policy_ids\":[\"policyId\"]}";
712 assertEquals(expectedResponse, resp);
714 this.addPolicy("policyId", "type1", "service", "ric1");
715 url = "/policies?service_id=";
716 resp = restClient().get(url).block();
717 expectedResponse = "{\"policy_ids\":[]}";
718 assertEquals(expectedResponse, resp);
720 url = "/policies?service_id=service";
721 resp = restClient().get(url).block();
722 assertThat(resp).contains("[\"policyId\"]");
726 @DisplayName("test Refuse To Update Policy")
727 void testRefuseToUpdatePolicy() throws Exception {
728 // Test that only the json can be changed for a already created policy
729 // In this case service is attempted to be changed
731 this.addRic("ricXXX");
732 this.addPolicy("instance1", "type1", "service1", "ric1");
733 this.addPolicy("instance2", "type1", "service1", "ricXXX");
735 // Try change ric1 -> ricXXX
736 String bodyWrongRic = putPolicyBody("service1", "ricXXX", "type1", "instance1");
737 testErrorCode(restClient().put("/policies", bodyWrongRic), HttpStatus.CONFLICT);
741 @DisplayName("test Get Policy")
742 void testGetPolicy() throws Exception {
743 String url = "/policies/id";
744 Policy policy = addPolicy("id", "typeName", "service1", "ric1");
746 String response = restClient().get(url).block();
747 PolicyInfo policyInfo = objectMapper.readValue(response, PolicyInfo.class);
748 String policyData = gson.toJson(policyInfo.getPolicyData());
749 assertThat(policyData).isEqualTo(policy.getJson());
752 policies.remove(policy);
753 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
758 @DisplayName("test Delete Policy")
759 void testDeletePolicy() throws Exception {
760 String policyId = "id.1";
761 addPolicy(policyId, "typeName", "service1", "ric1");
762 assertThat(policies.size()).isEqualTo(1);
764 String url = "/policies/" + policyId;
765 ResponseEntity<String> entity = restClient().deleteForEntity(url).block();
767 assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
768 assertThat(policies.size()).isZero();
770 // Delete a non existing policy
771 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
776 @DisplayName("test Get Policy Type")
777 void testGetPolicyType() throws Exception {
778 String typeId = "AC.D";
779 addPolicyType(typeId, "ric1");
781 waitForRicState("ric1", RicState.AVAILABLE);
783 String url = "/policy-types/" + typeId;
785 String response = this.restClient().get(url).block();
787 assertEquals("{\"policy_schema\":{\"title\":\"AC.D\"}}", response);
789 // Get non existing schema
790 url = "/policy-types/JUNK";
791 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
794 String createPolicyTypesJson(String... types) throws JsonProcessingException {
795 List<String> list = new ArrayList<>();
796 Collections.addAll(list, types);
797 PolicyTypeIdList ids = new PolicyTypeIdList();
798 ids.setPolicytypeIds(list);
799 return objectMapper.writeValueAsString(ids);
803 @DisplayName("test Get Policy Types")
804 void testGetPolicyTypes() throws Exception {
805 String TYPE_ID_1 = "A_type1_1.9.0";
806 String TYPE_ID_2 = "A_type1_2.0.0";
807 String TYPE_ID_3 = "A_type1_1.5.0";
808 String TYPE_ID_4 = "type3_1.9.0";
809 addPolicyType(TYPE_ID_1, "ric1");
810 addPolicyType(TYPE_ID_2, "ric2");
811 addPolicyType(TYPE_ID_3, "ric2");
812 addPolicyType(TYPE_ID_4, "ric2");
814 addPolicyType("junk", "ric2");
815 addPolicyType("junk_a.b.c", "ric2");
817 String url = "/policy-types";
818 String rsp = restClient().get(url).block();
819 assertThat(rsp).contains(TYPE_ID_1, TYPE_ID_2);
821 url = "/policy-types?ric_id=ric1";
822 rsp = restClient().get(url).block();
823 String expResp = createPolicyTypesJson(TYPE_ID_1);
824 assertThat(rsp).isEqualTo(expResp);
826 // Get policy types for non existing RIC
827 url = "/policy-types?ric_id=ric1XXX";
828 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
830 // All types with a type_name
831 url = "/policy-types?type_name=A_type1";
832 rsp = restClient().get(url).block();
833 assertThat(rsp).contains(TYPE_ID_1, TYPE_ID_2);
835 // All types compatible with type1_1.5.0 (which is type1_1.9.0)
836 url = "/policy-types?type_name=A_type1&&compatible_with_version=1.5.0";
837 rsp = restClient().get(url).block();
838 expResp = createPolicyTypesJson(TYPE_ID_3, TYPE_ID_1);
839 assertThat(rsp).isEqualTo(expResp);
841 url = "/policy-types?type_name=A_type1&&compatible_with_version=junk";
842 testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "Version must contain major.minor.patch code");
844 url = "/policy-types?type_name=A_type1&&compatible_with_version=a.b.c";
845 testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "Syntax error in");
847 url = "/policy-types?compatible_with_version=1.5.0";
848 testErrorCode(restClient().get(url), HttpStatus.BAD_REQUEST, "type_name");
852 @DisplayName("test Get Policy Instances")
853 void testGetPolicyInstances() throws Exception {
854 addPolicy("id1", "type1", "service1");
856 String url = "/policy-instances";
857 String response = restClient().get(url).block();
858 logger.info(response);
859 PolicyInfoList policyInfoList = objectMapper.readValue(response, PolicyInfoList.class);
860 assertThat(policyInfoList.getPolicies()).hasSize(1);
861 PolicyInfo policyInfo = policyInfoList.getPolicies().iterator().next();
862 assertThat(policyInfo.getPolicyId()).isEqualTo("id1");
863 assertThat(policyInfo.getPolicytypeId()).isEqualTo("type1");
864 assertThat(policyInfo.getServiceId()).isEqualTo("service1");
868 @DisplayName("test Get Policy Instances Filter")
869 void testGetPolicyInstancesFilter() throws Exception {
870 addPolicy("id1", "type1", "service1");
871 addPolicy("id2", "type1", "service2");
872 addPolicy("id3", "type2", "service1");
873 addPolicy("id4", "type1_1.0.0", "service1");
875 String url = "/policy-instances?policytype_id=type1";
876 String rsp = restClient().get(url).block();
878 assertThat(rsp).contains("id1")
880 .doesNotContain("id3");
882 url = "/policy-instances?policytype_id=type1&service_id=service2";
883 rsp = restClient().get(url).block();
885 assertThat(rsp).doesNotContain("id1")
887 .doesNotContain("id3");
889 url = "/policy-instances?type_name=type1";
890 rsp = restClient().get(url).block();
891 assertThat(rsp).contains("id1") //
893 .doesNotContain("id3")
896 // Test get policies for non existing type
897 url = "/policy-instances?policytype_id=type1XXX";
898 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
900 // Test get policies for non existing RIC
901 url = "/policy-instances?ric_id=XXX";
902 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
906 @DisplayName("test Get Policy Ids Filter")
907 void testGetPolicyIdsFilter() throws Exception {
908 addPolicy("id1", "type1", "service1", "ric1");
909 addPolicy("id2", "type1", "service2", "ric1");
910 addPolicy("id3", "type2", "service1", "ric1");
911 addPolicy("id4", "type1_1.0.0", "service1");
913 String url = "/policies?policytype_id=type1";
914 String rsp = restClient().get(url).block();
916 assertThat(rsp).contains("id1")
918 .doesNotContain("id3");
920 url = "/policies?policytype_id=type1&service_id=service1&ric=ric1";
921 rsp = restClient().get(url).block();
922 PolicyIdList respList = objectMapper.readValue(rsp, PolicyIdList.class);
923 assertThat(respList.getPolicyIds().iterator().next()).isEqualTo("id1");
925 url = "/policies?type_name=type1&service_id=service1";
926 rsp = restClient().get(url).block();
927 assertThat(rsp).contains("id1").contains("id4");
928 assertThat(objectMapper.readValue(rsp, PolicyIdList.class).getPolicyIds()).hasSize(2);
930 // Test get policy ids for non existing type
931 url = "/policies?policytype_id=type1XXX";
932 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
934 // Test get policy ids for non existing RIC
935 url = "/policies?ric_id=XXX";
936 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
941 @DisplayName("test Put And Get Service")
942 void testPutAndGetService() throws Exception {
944 String serviceName = "ac.dc";
945 putService(serviceName, 0, HttpStatus.CREATED);
946 putService(serviceName, 0, HttpStatus.OK);
949 String url = "/services?service_id=" + serviceName;
950 String rsp = restClient().get(url).block();
951 ServiceStatusList info = objectMapper.readValue(rsp, ServiceStatusList.class);
952 assertThat(info.getServiceList()).hasSize(1);
953 ServiceStatus status = info.getServiceList().iterator().next();
954 assertThat(status.getKeepAliveIntervalSeconds()).isZero();
955 assertThat(status.getServiceId()).isEqualTo(serviceName);
959 rsp = restClient().get(url).block();
960 assertThat(rsp).as("Response contains service name").contains(serviceName);
964 url = "/services/" + serviceName + "/keepalive";
965 ResponseEntity<?> entity = restClient().putForEntity(url).block();
966 assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
969 assertThat(services.size()).isEqualTo(1);
970 url = "/services/" + serviceName;
971 restClient().delete(url).block();
972 assertThat(services.size()).isZero();
974 // Keep alive, no registered service
975 testErrorCode(restClient().put("/services/junk/keepalive", ""), HttpStatus.NOT_FOUND);
977 // PUT service with bad payload
978 testErrorCode(restClient().put("/services", "crap"), HttpStatus.BAD_REQUEST, false);
979 testErrorCode(restClient().put("/services", "{}"), HttpStatus.BAD_REQUEST, false);
980 testErrorCode(restClient().put("/services", createServiceJson(serviceName, -123)), HttpStatus.BAD_REQUEST,
982 testErrorCode(restClient().put("/services", createServiceJson(serviceName, 0, "missing.portandprotocol.com")),
983 HttpStatus.BAD_REQUEST, false);
985 // GET non existing service
986 testErrorCode(restClient().get("/services?service_id=XXX"), HttpStatus.NOT_FOUND);
990 @DisplayName("test Service Supervision")
991 void testServiceSupervision() throws Exception {
992 putService("service1", 2, HttpStatus.CREATED);
993 addPolicyType("type1", "ric1");
995 String policyBody = putPolicyBody("service1", "ric1", "type1", "instance1");
996 restClient().put("/policies", policyBody).block();
998 assertThat(policies.size()).isEqualTo(1);
999 assertThat(services.size()).isEqualTo(1);
1001 // Timeout after ~2 second
1002 await().untilAsserted(() -> assertThat(policies.size()).isZero());
1003 assertThat(services.size()).isZero();
1007 @DisplayName("test Get Policy Status")
1008 void testGetPolicyStatus() throws Exception {
1009 addPolicy("id", "typeName", "service1", "ric1");
1010 assertThat(policies.size()).isEqualTo(1);
1012 String url = "/policies/id/status";
1013 String response = restClient().get(url).block();
1014 PolicyStatusInfo info = objectMapper.readValue(response, PolicyStatusInfo.class);
1015 assertThat(info.getStatus()).isEqualTo("OK");
1017 // GET non existing policy status
1018 url = "/policies/XXX/status";
1019 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
1021 // GET STATUS, the NearRT RIC returns error
1022 MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client("ric1");
1023 url = "/policies/id/status";
1024 WebClientResponseException a1Exception = new WebClientResponseException(404, "", null, null, null);
1025 doReturn(Mono.error(a1Exception)).when(a1Client).getPolicyStatus(any());
1026 response = restClient().get(url).block();
1027 info = objectMapper.readValue(response, PolicyStatusInfo.class);
1028 assertThat(info.getStatus()).hasToString("{}");
1032 @DisplayName("test Get Service Status")
1033 void testGetServiceStatus() throws Exception {
1034 String url = "/status";
1035 String rsp = restClient().get(url).block();
1036 assertThat(rsp).contains("success");
1038 rsp = restClient(baseUrl(), false).get(url).block(); // V1 status is used by a readinessProbe
1039 assertThat(rsp).isEqualTo("success");
1043 @DisplayName("test Service Notification")
1044 void testServiceNotification() throws Exception {
1046 final String AUTH_TOKEN = "testToken";
1047 Path authFile = Files.createTempFile("pmsTestAuthToken", ".txt");
1048 Files.write(authFile, AUTH_TOKEN.getBytes());
1049 this.securityContext.setAuthTokenFilePath(authFile);
1051 putService("junkService");
1052 Service junkService = this.services.get("junkService");
1053 junkService.setCallbackUrl("https://junk");
1054 putService("service");
1056 Ric ric = addRic("ric1");
1057 ric.setState(Ric.RicState.UNAVAILABLE);
1058 supervision.checkAllRics();
1059 waitForRicState("ric1", RicState.AVAILABLE);
1061 final RappSimulatorController.TestResults receivedCallbacks = rAppSimulator.getTestResults();
1062 await().untilAsserted(() -> assertThat(receivedCallbacks.getReceivedInfo()).hasSize(1));
1063 ServiceCallbackInfo callbackInfo = receivedCallbacks.getReceivedInfo().get(0);
1064 assertThat(callbackInfo.ricId).isEqualTo("ric1");
1065 assertThat(callbackInfo.eventType).isEqualTo(ServiceCallbackInfo.EventType.AVAILABLE);
1067 var headers = receivedCallbacks.receivedHeaders.get(0);
1068 assertThat(headers).containsEntry("authorization", "Bearer " + AUTH_TOKEN);
1070 Files.delete(authFile);
1073 private Policy addPolicy(String id, String typeName, String service, String ric) throws ServiceException {
1075 Policy policy = Policy.builder()
1077 .json(gson.toJson(jsonString()))
1078 .ownerServiceId(service)
1079 .ric(rics.getRic(ric))
1080 .type(addPolicyType(typeName, ric))
1081 .lastModified(Instant.now())
1083 .statusNotificationUri("/policy-status?id=XXX")
1085 policies.put(policy);
1089 private Policy addPolicy(String id, String typeName, String service) throws ServiceException {
1090 return addPolicy(id, typeName, service, "ric");
1093 private String createServiceJson(String name, long keepAliveIntervalSeconds) throws JsonProcessingException {
1094 String callbackUrl = baseUrl() + RappSimulatorController.SERVICE_CALLBACK_URL;
1095 return createServiceJson(name, keepAliveIntervalSeconds, callbackUrl);
1098 private String createServiceJson(String name, long keepAliveIntervalSeconds, String url) throws JsonProcessingException {
1099 ServiceRegistrationInfo service = new ServiceRegistrationInfo(name)
1100 .keepAliveIntervalSeconds(keepAliveIntervalSeconds)
1103 return objectMapper.writeValueAsString(service);
1106 private void putService(String name) throws JsonProcessingException {
1107 putService(name, 0, null);
1110 private void putService(String name, long keepAliveIntervalSeconds, @Nullable HttpStatus expectedStatus) throws JsonProcessingException {
1111 String url = "/services";
1112 String body = createServiceJson(name, keepAliveIntervalSeconds);
1113 ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
1114 if (expectedStatus != null) {
1115 assertEquals(expectedStatus, resp.getStatusCode(), "");
1119 private Map<String,String> jsonString() {
1120 Map<String,String> policyDataInMap = new HashMap<>();
1121 policyDataInMap.put("servingCellNrcgi","1");
1122 return policyDataInMap;
1126 @DisplayName("test Concurrency")
1127 void testConcurrency() throws Exception {
1128 this.applicationConfig.setAuthProviderUrl("");
1129 logger.info("Concurrency test starting");
1130 final Instant startTime = Instant.now();
1131 List<Thread> threads = new ArrayList<>();
1132 List<ConcurrencyTestRunnable> tests = new ArrayList<>();
1133 a1ClientFactory.setResponseDelay(Duration.ofMillis(2));
1135 addPolicyType("type1", "ric");
1136 addPolicyType("type2", "ric");
1138 final String NON_RESPONDING_RIC = "NonRespondingRic";
1139 Ric nonRespondingRic = addRic(NON_RESPONDING_RIC);
1140 MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client(NON_RESPONDING_RIC);
1141 a1Client.setErrorInject("errorInject");
1143 for (int i = 0; i < 10; ++i) {
1144 AsyncRestClient restClient = restClient();
1145 ConcurrencyTestRunnable test =
1146 new ConcurrencyTestRunnable(restClient, supervision, a1ClientFactory, rics, policyTypes);
1147 Thread thread = new Thread(test, "TestThread_" + i);
1149 threads.add(thread);
1152 for (Thread t : threads) {
1155 for (ConcurrencyTestRunnable test : tests) {
1156 assertThat(test.isFailed()).isFalse();
1158 assertThat(policies.size()).isZero();
1159 logger.info("Concurrency test took " + Duration.between(startTime, Instant.now()));
1161 assertThat(nonRespondingRic.getState()).isEqualTo(RicState.UNAVAILABLE);
1162 nonRespondingRic.setState(RicState.AVAILABLE);
1165 private AsyncRestClient restClient(String baseUrl, boolean useTrustValidation) {
1166 WebClientConfig config = this.applicationConfig.getWebClientConfig();
1167 config = WebClientConfig.builder()
1168 .keyStoreType(config.getKeyStoreType())
1169 .keyStorePassword(config.getKeyStorePassword())
1170 .keyStore(config.getKeyStore())
1171 .keyPassword(config.getKeyPassword())
1172 .isTrustStoreUsed(useTrustValidation)
1173 .trustStore(config.getTrustStore())
1174 .trustStorePassword(config.getTrustStorePassword())
1175 .httpProxyConfig(config.getHttpProxyConfig())
1178 AsyncRestClientFactory f = new AsyncRestClientFactory(config, new SecurityContext(""));
1179 return f.createRestClientNoHttpProxy(baseUrl);
1183 private String baseUrl() {
1184 return "https://localhost:" + port;
1187 private AsyncRestClient restClient(boolean useTrustValidation) {
1188 return restClient(baseUrl() + Consts.V2_API_ROOT, useTrustValidation);
1191 private AsyncRestClient restClient() {
1192 return restClient(false);
1195 private void testErrorCode(Mono<?> request, HttpStatus expStatus) {
1196 testErrorCode(request, expStatus, "", true);
1199 private void testErrorCode(Mono<?> request, HttpStatus expStatus, boolean expectApplicationProblemJsonMediaType) {
1200 testErrorCode(request, expStatus, "", expectApplicationProblemJsonMediaType);
1203 private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains) {
1204 testErrorCode(request, expStatus, responseContains, true);
1207 private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains,
1208 boolean expectApplicationProblemJsonMediaType) {
1209 StepVerifier.create(request)
1210 .expectSubscription()
1211 .expectErrorMatches(
1212 t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType))
1216 private void waitForRicState(String ricId, RicState state) throws ServiceException {
1217 Ric ric = rics.getRic(ricId);
1218 await().untilAsserted(() -> state.equals(ric.getState()));
1221 private boolean checkWebClientError(Throwable throwable, HttpStatus expStatus, String responseContains,
1222 boolean expectApplicationProblemJsonMediaType) {
1223 assertTrue(throwable instanceof WebClientResponseException);
1224 WebClientResponseException responseException = (WebClientResponseException) throwable;
1225 String body = responseException.getResponseBodyAsString();
1226 assertThat(body).contains(responseContains);
1227 assertThat(responseException.getStatusCode()).isEqualTo(expStatus);
1229 if (expectApplicationProblemJsonMediaType) {
1230 assertThat(responseException.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PROBLEM_JSON);
1235 private MockA1Client getA1Client(String ricId) throws ServiceException {
1236 return a1ClientFactory.getOrCreateA1Client(ricId);
1239 private PolicyType createPolicyType(String policyTypeName) {
1240 return PolicyType.builder()
1242 .schema("{\"title\":\"" + policyTypeName + "\"}")
1246 private PolicyType addPolicyType(String policyTypeName, String ricId) {
1247 PolicyType type = createPolicyType(policyTypeName);
1248 policyTypes.put(type);
1249 addRic(ricId).addSupportedPolicyType(type);
1253 private Ric addRic(String ricId) {
1254 return addRic(ricId, null);
1257 private RicConfig ricConfig(String ricId, String managedElement) {
1258 List<String> mes = new ArrayList<>();
1259 if (managedElement != null) {
1260 mes.add(managedElement);
1262 return RicConfig.builder()
1265 .managedElementIds(mes)
1269 private Ric addRic(String ricId, String managedElement) {
1270 if (rics.get(ricId) != null) {
1271 return rics.get(ricId);
1274 RicConfig conf = ricConfig(ricId, managedElement);
1275 Ric ric = new Ric(conf);
1276 ric.setState(Ric.RicState.AVAILABLE);