Adding validation of updated policies
[nonrtric.git] / policy-agent / src / test / java / org / oransc / policyagent / ApplicationTest.java
1 /*-
2  * ========================LICENSE_START=================================
3  * O-RAN-SC
4  * %%
5  * Copyright (C) 2019 Nordix Foundation
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.oransc.policyagent;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.awaitility.Awaitility.await;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.jupiter.api.Assertions.assertFalse;
27
28 import com.google.gson.Gson;
29 import com.google.gson.GsonBuilder;
30 import com.google.gson.JsonArray;
31 import com.google.gson.JsonElement;
32 import com.google.gson.JsonParser;
33
34 import java.io.IOException;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Vector;
38
39 import org.junit.jupiter.api.Test;
40 import org.junit.jupiter.api.extension.ExtendWith;
41 import org.oransc.policyagent.configuration.ApplicationConfig;
42 import org.oransc.policyagent.configuration.ImmutableRicConfig;
43 import org.oransc.policyagent.configuration.RicConfig;
44 import org.oransc.policyagent.controllers.PolicyInfo;
45 import org.oransc.policyagent.controllers.ServiceRegistrationInfo;
46 import org.oransc.policyagent.controllers.ServiceStatus;
47 import org.oransc.policyagent.exceptions.ServiceException;
48 import org.oransc.policyagent.repository.ImmutablePolicy;
49 import org.oransc.policyagent.repository.ImmutablePolicyType;
50 import org.oransc.policyagent.repository.Policies;
51 import org.oransc.policyagent.repository.Policy;
52 import org.oransc.policyagent.repository.PolicyType;
53 import org.oransc.policyagent.repository.PolicyTypes;
54 import org.oransc.policyagent.repository.Ric;
55 import org.oransc.policyagent.repository.Ric.RicState;
56 import org.oransc.policyagent.repository.Rics;
57 import org.oransc.policyagent.repository.Services;
58 import org.oransc.policyagent.tasks.RepositorySupervision;
59 import org.oransc.policyagent.utils.MockA1Client;
60 import org.oransc.policyagent.utils.MockA1ClientFactory;
61 import org.springframework.beans.factory.annotation.Autowired;
62 import org.springframework.boot.test.context.SpringBootTest;
63 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
64 import org.springframework.boot.test.context.TestConfiguration;
65 import org.springframework.boot.web.server.LocalServerPort;
66 import org.springframework.context.ApplicationContext;
67 import org.springframework.context.annotation.Bean;
68 import org.springframework.http.HttpEntity;
69 import org.springframework.http.HttpHeaders;
70 import org.springframework.http.HttpStatus;
71 import org.springframework.http.HttpStatus.Series;
72 import org.springframework.http.MediaType;
73 import org.springframework.http.ResponseEntity;
74 import org.springframework.http.client.ClientHttpResponse;
75 import org.springframework.test.context.junit.jupiter.SpringExtension;
76 import org.springframework.web.client.ResponseErrorHandler;
77 import org.springframework.web.client.RestTemplate;
78
79 @ExtendWith(SpringExtension.class)
80 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
81 public class ApplicationTest {
82     @Autowired
83     ApplicationContext context;
84
85     @Autowired
86     private Rics rics;
87
88     @Autowired
89     private Policies policies;
90
91     @Autowired
92     private PolicyTypes policyTypes;
93
94     @Autowired
95     MockA1ClientFactory a1ClientFactory;
96
97     @Autowired
98     RepositorySupervision supervision;
99
100     @Autowired
101     Services services;
102
103     private static Gson gson = new GsonBuilder() //
104         .serializeNulls() //
105         .create(); //
106
107     public static class MockApplicationConfig extends ApplicationConfig {
108         @Override
109         public String getLocalConfigurationFilePath() {
110             return ""; // No config file loaded for the test
111         }
112     }
113
114     /**
115      * Overrides the BeanFactory.
116      */
117     @TestConfiguration
118     static class TestBeanFactory {
119         private final PolicyTypes policyTypes = new PolicyTypes();
120
121         @Bean
122         public ApplicationConfig getApplicationConfig() {
123             return new MockApplicationConfig();
124         }
125
126         @Bean
127         MockA1ClientFactory getA1ClientFactory() {
128             return new MockA1ClientFactory(this.policyTypes);
129         }
130
131         @Bean
132         public Policies getPolicies() {
133             return new Policies();
134         }
135
136         @Bean
137         public PolicyTypes getPolicyTypes() {
138             return this.policyTypes;
139         }
140
141         @Bean
142         public Rics getRics() {
143             return new Rics();
144         }
145     }
146
147     @LocalServerPort
148     private int port;
149
150     private final RestTemplate restTemplate = new RestTemplate();
151
152     public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
153
154         @Override
155         public boolean hasError(ClientHttpResponse httpResponse) throws IOException {
156             return (httpResponse.getStatusCode().series() == Series.CLIENT_ERROR
157                 || httpResponse.getStatusCode().series() == Series.SERVER_ERROR);
158         }
159
160         @Override
161         public void handleError(ClientHttpResponse httpResponse) throws IOException {
162             System.out.println("Error " + httpResponse.toString());
163         }
164     }
165
166     private void reset() {
167         rics.clear();
168         policies.clear();
169         policyTypes.clear();
170         assertThat(policies.size()).isEqualTo(0);
171         restTemplate.setErrorHandler(new RestTemplateResponseErrorHandler());
172     }
173
174     @Test
175     public void testGetRics() throws Exception {
176         reset();
177         addRic("kista_1");
178         String url = baseUrl() + "/rics";
179         String rsp = this.restTemplate.getForObject(url, String.class);
180         System.out.println(rsp);
181         assertThat(rsp).contains("kista_1");
182
183         url = baseUrl() + "/rics?policyType=STD_PolicyModelUnconstrained_0.2.0";
184         rsp = this.restTemplate.getForObject(url, String.class);
185         assertThat(rsp).isEqualTo("[]");
186     }
187
188     @Test
189     public void testRecovery() throws Exception {
190         reset();
191         Policy policy2 = addPolicy("policyId2", "typeName", "service", "ric");
192
193         getA1Client("ric").putPolicy(policy2); // put it in the RIC
194         policies.remove(policy2); // Remove it from the repo -> should be deleted in the RIC
195
196         Policy policy = addPolicy("policyId", "typeName", "service", "ric"); // This should be created in the RIC
197         supervision.checkAllRics(); // The created policy should be put in the RIC
198         await().untilAsserted(() -> RicState.RECOVERING.equals(rics.getRic("ric").getState()));
199         await().untilAsserted(() -> RicState.IDLE.equals(rics.getRic("ric").getState()));
200
201         Policies ricPolicies = getA1Client("ric").getPolicies();
202         assertThat(ricPolicies.size()).isEqualTo(1);
203         Policy ricPolicy = ricPolicies.get("policyId");
204         assertThat(ricPolicy.json()).isEqualTo(policy.json());
205     }
206
207     MockA1Client getA1Client(String ricName) throws ServiceException {
208         return a1ClientFactory.getOrCreateA1Client(ricName);
209     }
210
211     @Test
212     public void testGetRic() throws Exception {
213         reset();
214         Ric ric = addRic("ric1");
215         ric.addManagedElement("kista_1");
216         String url = baseUrl() + "/ric?managedElementId=kista_1";
217
218         String rsp = this.restTemplate.getForObject(url, String.class);
219         System.out.println(rsp);
220         assertThat(rsp).isEqualTo("ric1");
221     }
222
223     @Test
224     public void testPutPolicy() throws Exception {
225         reset();
226         putService("service1");
227         this.addRic("ric1").setState(Ric.RicState.IDLE);
228         addPolicyType("type1", "ric1");
229
230         final String json = jsonString();
231         String url = baseUrl() + "/policy?type=type1&instance=instance1&ric=ric1&service=service1";
232         this.restTemplate.put(url, createJsonHttpEntity(json));
233         Policy policy = policies.getPolicy("instance1");
234
235         assertThat(policy).isNotNull();
236         assertThat(policy.id()).isEqualTo("instance1");
237         assertThat(policy.ownerServiceName()).isEqualTo("service1");
238         assertThat(policy.ric().name()).isEqualTo("ric1");
239
240         url = baseUrl() + "/policies";
241         String rsp = this.restTemplate.getForObject(url, String.class);
242         System.out.println(rsp);
243
244     }
245
246     @Test
247     public void testRefuseToUpdatePolicy() throws Exception {
248         // Test that only the json can be changed for a already created policy
249         // In this case service is attempted to be changed
250         reset();
251         this.addRic("ric1").setState(Ric.RicState.IDLE);
252         this.addRic("ricXXX").setState(Ric.RicState.IDLE);
253
254         this.addPolicy("instance1", "type1", "service1", "ric1");
255         String urlWrongRic = baseUrl() + "/policy?type=type1&instance=instance1&ric=ricXXX&service=service1";
256         this.restTemplate.put(urlWrongRic, createJsonHttpEntity(jsonString()));
257         Policy policy = policies.getPolicy("instance1");
258         assertThat(policy.ric().name()).isEqualTo("ric1"); // Not changed
259     }
260
261     private PolicyType addPolicyType(String policyTypeName, String ricName) {
262         PolicyType type = ImmutablePolicyType.builder() //
263             .name(policyTypeName) //
264             .schema("{\"title\":\"" + policyTypeName + "\"}") //
265             .build();
266
267         policyTypes.put(type);
268         addRic(ricName).addSupportedPolicyType(type);
269         return type;
270     }
271
272     private Ric addRic(String ricName) {
273         if (rics.get(ricName) != null) {
274             return rics.get(ricName);
275         }
276         Vector<String> mes = new Vector<>();
277         RicConfig conf = ImmutableRicConfig.builder() //
278             .name(ricName) //
279             .baseUrl(ricName) //
280             .managedElementIds(mes) //
281             .build();
282         Ric ric = new Ric(conf);
283         this.rics.put(ric);
284         return ric;
285     }
286
287     private String createServiceJson(String name) {
288         ServiceRegistrationInfo service = new ServiceRegistrationInfo(name, 1, "callbackUrl");
289
290         String json = gson.toJson(service);
291         return json;
292     }
293
294     HttpEntity<String> createJsonHttpEntity(String content) {
295         HttpHeaders headers = new HttpHeaders();
296         headers.setContentType(MediaType.APPLICATION_JSON);
297         return new HttpEntity<String>(content, headers);
298     }
299
300     private void putService(String name) {
301         String url = baseUrl() + "/service";
302         HttpEntity<String> entity = createJsonHttpEntity(createServiceJson(name));
303         this.restTemplate.put(url, entity);
304     }
305
306     private String jsonString() {
307         return "{\n  \"servingCellNrcgi\": \"1\"\n }";
308     }
309
310     private Policy addPolicy(String id, String typeName, String service, String ric) throws ServiceException {
311         addRic(ric);
312         Policy p = ImmutablePolicy.builder().id(id) //
313             .json(jsonString()) //
314             .ownerServiceName(service) //
315             .ric(rics.getRic(ric)) //
316             .type(addPolicyType(typeName, ric)) //
317             .lastModified("lastModified").build();
318         policies.put(p);
319         return p;
320     }
321
322     private Policy addPolicy(String id, String typeName, String service) throws ServiceException {
323         return addPolicy(id, typeName, service, "ric");
324     }
325
326     private String baseUrl() {
327         return "http://localhost:" + port;
328     }
329
330     @Test
331     public void testGetPolicy() throws Exception {
332         String url = baseUrl() + "/policy?instance=id";
333         Policy policy = addPolicy("id", "typeName", "service1", "ric1");
334         {
335             String rsp = this.restTemplate.getForObject(url, String.class);
336             assertThat(rsp).isEqualTo(policy.json());
337         }
338         {
339             policies.remove(policy);
340             ResponseEntity<String> rsp = this.restTemplate.getForEntity(url, String.class);
341             assertThat(rsp.getStatusCodeValue()).isEqualTo(HttpStatus.NO_CONTENT.value());
342         }
343     }
344
345     @Test
346     public void testDeletePolicy() throws Exception {
347         reset();
348         String url = baseUrl() + "/policy?instance=id";
349         Policy policy = addPolicy("id", "typeName", "service1", "ric1");
350         policy.ric().setState(Ric.RicState.IDLE);
351         assertThat(policies.size()).isEqualTo(1);
352
353         this.restTemplate.delete(url);
354
355         assertThat(policies.size()).isEqualTo(0);
356     }
357
358     @Test
359     public void testGetPolicySchemas() throws Exception {
360         reset();
361         addPolicyType("type1", "ric1");
362         addPolicyType("type2", "ric2");
363
364         String url = baseUrl() + "/policy_schemas";
365         String rsp = this.restTemplate.getForObject(url, String.class);
366         System.out.println("*** " + rsp);
367         assertThat(rsp).contains("type1");
368         assertThat(rsp).contains("[{\"title\":\"type2\"}");
369
370         List<String> info = parseSchemas(rsp);
371         assertEquals(2, info.size());
372
373         url = baseUrl() + "/policy_schemas?ric=ric1";
374         rsp = this.restTemplate.getForObject(url, String.class);
375         assertThat(rsp).contains("type1");
376         info = parseSchemas(rsp);
377         assertEquals(1, info.size());
378     }
379
380     @Test
381     public void testGetPolicySchema() throws Exception {
382         reset();
383         addPolicyType("type1", "ric1");
384         addPolicyType("type2", "ric2");
385
386         String url = baseUrl() + "/policy_schema?id=type1";
387         String rsp = this.restTemplate.getForObject(url, String.class);
388         System.out.println(rsp);
389         assertThat(rsp).contains("type1");
390         assertThat(rsp).contains("title");
391     }
392
393     @Test
394     public void testGetPolicyTypes() throws Exception {
395         reset();
396         addPolicyType("type1", "ric1");
397         addPolicyType("type2", "ric2");
398
399         String url = baseUrl() + "/policy_types";
400         String rsp = this.restTemplate.getForObject(url, String.class);
401         assertThat(rsp).isEqualTo("[\"type2\",\"type1\"]");
402
403         url = baseUrl() + "/policy_types?ric=ric1";
404         rsp = this.restTemplate.getForObject(url, String.class);
405         assertThat(rsp).isEqualTo("[\"type1\"]");
406     }
407
408     @Test
409     public void testGetPolicies() throws Exception {
410         String url = baseUrl() + "/policies";
411         addPolicy("id1", "type1", "service1");
412
413         String rsp = this.restTemplate.getForObject(url, String.class);
414         System.out.println(rsp);
415         List<PolicyInfo> info = parseList(rsp, PolicyInfo.class);
416         assertThat(info).size().isEqualTo(1);
417         PolicyInfo policyInfo = info.get(0);
418         assert (policyInfo.validate());
419         assertThat(policyInfo.id).isEqualTo("id1");
420         assertThat(policyInfo.type).isEqualTo("type1");
421         assertThat(policyInfo.service).isEqualTo("service1");
422     }
423
424     @Test
425     public void testGetPoliciesFilter() throws Exception {
426         addPolicy("id1", "type1", "service1");
427         addPolicy("id2", "type1", "service2");
428         addPolicy("id3", "type2", "service1");
429
430         String url = baseUrl() + "/policies?type=type1";
431         String rsp = this.restTemplate.getForObject(url, String.class);
432         System.out.println(rsp);
433         assertThat(rsp).contains("id1");
434         assertThat(rsp).contains("id2");
435         assertFalse(rsp.contains("id3"));
436
437         url = baseUrl() + "/policies?type=type1&service=service2";
438         rsp = this.restTemplate.getForObject(url, String.class);
439         System.out.println(rsp);
440         assertFalse(rsp.contains("id1"));
441         assertThat(rsp).contains("id2");
442         assertFalse(rsp.contains("id3"));
443     }
444
445     @Test
446     public void testPutAndGetService() throws Exception {
447         reset();
448         // PUT
449         putService("name");
450
451         // GET
452         String url = baseUrl() + "/services?name=name";
453         String rsp = this.restTemplate.getForObject(url, String.class);
454         List<ServiceStatus> info = parseList(rsp, ServiceStatus.class);
455         assertThat(info.size() == 1);
456         ServiceStatus status = info.iterator().next();
457         assertThat(status.keepAliveIntervalSeconds == 1);
458         assertThat(status.serviceName.equals("name"));
459
460         // GET (all)
461         url = baseUrl() + "/services";
462         rsp = this.restTemplate.getForObject(url, String.class);
463         assertThat(rsp.contains("name"));
464         System.out.println(rsp);
465
466         // Keep alive
467         url = baseUrl() + "/services/keepalive?name=name";
468         rsp = this.restTemplate.postForObject(url, null, String.class);
469         assertThat(rsp.contains("OK"));
470
471         // DELETE
472         assertThat(services.size() == 1);
473         url = baseUrl() + "/services?name=name";
474         this.restTemplate.delete(url);
475         assertThat(services.size() == 0);
476
477         // Keep alive, no registerred service
478         url = baseUrl() + "/services/keepalive?name=nameXXX";
479         ResponseEntity<String> entity = this.restTemplate.postForEntity(url, null, String.class);
480         assertThat(entity.getStatusCode().equals(HttpStatus.NOT_FOUND));
481     }
482
483     @Test
484     public void testGetPolicyStatus() throws Exception {
485         reset();
486         Policy policy = addPolicy("id", "typeName", "service1", "ric1");
487         policy.ric().setState(Ric.RicState.IDLE);
488         assertThat(policies.size()).isEqualTo(1);
489
490         String url = baseUrl() + "/policy_status?instance=id";
491         String rsp = this.restTemplate.getForObject(url, String.class);
492         assertThat(rsp.equals("OK"));
493     }
494
495     private static <T> List<T> parseList(String jsonString, Class<T> clazz) {
496         List<T> result = new ArrayList<>();
497         JsonArray jsonArr = JsonParser.parseString(jsonString).getAsJsonArray();
498         for (JsonElement jsonElement : jsonArr) {
499             T o = gson.fromJson(jsonElement.toString(), clazz);
500             result.add(o);
501         }
502         return result;
503     }
504
505     private static List<String> parseSchemas(String jsonString) {
506         JsonArray arrayOfSchema = JsonParser.parseString(jsonString).getAsJsonArray();
507         List<String> result = new ArrayList<>();
508         for (JsonElement schemaObject : arrayOfSchema) {
509             result.add(schemaObject.toString());
510         }
511         return result;
512     }
513
514 }