Sonar Issues in Apex plugins-context
[policy/apex-pdp.git] / plugins / plugins-context / plugins-context-schema / plugins-context-schema-avro / src / test / java / org / onap / policy / apex / plugins / context / schema / avro / AvroSchemaMapTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2020-2021 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.plugins.context.schema.avro;
23
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertNull;
27 import static org.junit.Assert.assertThrows;
28
29 import java.io.File;
30 import java.io.IOException;
31 import java.util.HashMap;
32 import org.apache.avro.generic.GenericRecord;
33 import org.apache.avro.util.Utf8;
34 import org.junit.After;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.onap.policy.apex.context.ContextRuntimeException;
38 import org.onap.policy.apex.context.SchemaHelper;
39 import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
40 import org.onap.policy.apex.context.parameters.ContextParameterConstants;
41 import org.onap.policy.apex.context.parameters.SchemaParameters;
42 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
43 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
44 import org.onap.policy.apex.model.basicmodel.service.ModelService;
45 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
46 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
47 import org.onap.policy.common.parameters.ParameterService;
48 import org.onap.policy.common.utils.resources.TextFileUtils;
49
50 /**
51  * The Class TestAvroSchemaMap.
52  *
53  * @author Liam Fallon (liam.fallon@ericsson.com)
54  * @version
55  */
56 public class AvroSchemaMapTest {
57     private final AxKey testKey = new AxArtifactKey("AvroTest", "0.0.1");
58     private AxContextSchemas schemas;
59     private String longMapSchema;
60     private String addressMapSchema;
61     private String addressMapSchemaInvalidFields;
62
63     /**
64      * Inits the test.
65      *
66      * @throws IOException Signals that an I/O exception has occurred.
67      */
68     @Before
69     public void initTest() throws IOException {
70         schemas = new AxContextSchemas(new AxArtifactKey("AvroSchemas", "0.0.1"));
71         ModelService.registerModel(AxContextSchemas.class, schemas);
72         longMapSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/MapExampleLong.avsc");
73         addressMapSchema = TextFileUtils.getTextFileAsString("src/test/resources/avsc/MapExampleAddress.avsc");
74         addressMapSchemaInvalidFields =
75                 TextFileUtils.getTextFileAsString("src/test/resources/avsc/MapExampleAddressInvalidFields.avsc");
76     }
77
78     /**
79      * Inits the context.
80      */
81     @Before
82     public void initContext() {
83         SchemaParameters schemaParameters = new SchemaParameters();
84         schemaParameters.setName(ContextParameterConstants.SCHEMA_GROUP_NAME);
85         schemaParameters.getSchemaHelperParameterMap().put("AVRO", new AvroSchemaHelperParameters());
86         ParameterService.register(schemaParameters);
87     }
88
89     /**
90      * Clear context.
91      */
92     @After
93     public void clearContext() {
94         ParameterService.deregister(ContextParameterConstants.SCHEMA_GROUP_NAME);
95     }
96
97     /**
98      * Test valid schemas with substitutions.
99      *
100      * @throws IOException Signals that an I/O exception has occurred.
101      */
102     @Test
103     public void testValidSubstitutions() throws IOException {
104         final String subst1 = "{\"type\":\"record\",\"name\":\"Subst1\","
105                 + "\"fields\":[{\"name\": \"A_DasH_B\",\"type\":\"string\"}]}";
106         final AxContextSchema avroSubstSchema1 = new AxContextSchema(
107                 new AxArtifactKey("AvroSubst1", "0.0.1"), "AVRO", subst1);
108         schemas.getSchemasMap().put(avroSubstSchema1.getKey(), avroSubstSchema1);
109
110         SchemaHelper schemaHelperSubst1 = new SchemaHelperFactory()
111                 .createSchemaHelper(testKey, avroSubstSchema1.getKey());
112         final GenericRecord subst1A = (GenericRecord) schemaHelperSubst1.unmarshal("{\"A-B\":\"foo\"}");
113         assertEquals(new Utf8("foo"), subst1A.get("A_DasH_B"));
114         assertNull(subst1A.get("A-B"));
115         final Throwable exception1 = assertThrows(ContextRuntimeException.class,
116             () -> schemaHelperSubst1.unmarshal("{\"A-B\":123}"));
117         assertNotNull(exception1.getCause());
118         assertEquals("Expected string. Got VALUE_NUMBER_INT", exception1.getCause().getMessage());
119
120         final String subst2 = "{\"type\":\"record\",\"name\":\"Subst2\","
121                 + "\"fields\":[{\"name\": \"C_DoT_D\",\"type\":\"int\"}]}";
122         final AxContextSchema avroSubstSchema2 = new AxContextSchema(
123                 new AxArtifactKey("AvroSubst2", "0.0.1"), "AVRO", subst2);
124         schemas.getSchemasMap().put(avroSubstSchema2.getKey(), avroSubstSchema2);
125
126         final SchemaHelper schemaHelperSubst2 = new SchemaHelperFactory()
127                 .createSchemaHelper(testKey, avroSubstSchema2.getKey());
128         final GenericRecord subst2A = (GenericRecord) schemaHelperSubst2.unmarshal("{\"C.D\":123}");
129         assertEquals(123, subst2A.get("C_DoT_D"));
130         assertNull(subst2A.get("C.D"));
131         final Throwable exception2 = assertThrows(ContextRuntimeException.class,
132             () -> schemaHelperSubst2.unmarshal("{\"C_DoT_D\":\"bar\"}"));
133         assertNotNull(exception2.getCause());
134         assertEquals("Expected int. Got VALUE_STRING", exception2.getCause().getMessage());
135
136         final String subst3 = "{\"type\":\"record\",\"name\":\"Subst3\","
137                 + "\"fields\":[{\"name\": \"E_ColoN_F\",\"type\":\"boolean\"}]}";
138         final AxContextSchema avroSubstSchema3 = new AxContextSchema(
139                 new AxArtifactKey("AvroSubst3", "0.0.1"), "AVRO", subst3);
140         schemas.getSchemasMap().put(avroSubstSchema3.getKey(), avroSubstSchema3);
141
142         final SchemaHelper schemaHelperSubst3 = new SchemaHelperFactory()
143                 .createSchemaHelper(testKey, avroSubstSchema3.getKey());
144         final GenericRecord subst3A = (GenericRecord) schemaHelperSubst3.unmarshal("{\"E:F\":true}");
145         assertEquals(true, subst3A.get("E_ColoN_F"));
146         assertNull(subst3A.get("E:F"));
147         final Throwable exception3 = assertThrows(ContextRuntimeException.class,
148             () -> schemaHelperSubst3.unmarshal("{\"E_ColoN_F\":\"gaz\"}"));
149         assertNotNull(exception3.getCause());
150         assertEquals("Expected boolean. Got VALUE_STRING", exception3.getCause().getMessage());
151     }
152
153     /**
154      * Test invalid schemas without substitutions.
155      *
156      * @throws IOException Signals that an I/O exception has occurred.
157      */
158     @Test
159     public void testInValidSubstitutions() throws IOException {
160         final String fail1 = "{\"type\":\"record\",\"name\":\"Fail1\","
161                 + "\"fields\":[{\"name\": \"A-B\",\"type\":\"string\"}]}";
162         final AxContextSchema avroFailSchema1 = new AxContextSchema(
163                 new AxArtifactKey("AvroFail1", "0.0.1"), "AVRO", fail1);
164         schemas.getSchemasMap().put(avroFailSchema1.getKey(), avroFailSchema1);
165
166         SchemaHelperFactory sh = new SchemaHelperFactory();
167         AxArtifactKey ak = avroFailSchema1.getKey();
168         final Throwable exception1 = assertThrows(ContextRuntimeException.class,
169             () -> sh.createSchemaHelper(testKey, ak));
170         assertNotNull(exception1.getCause());
171         assertEquals("Illegal character in: A-B", exception1.getCause().getMessage());
172
173         final String fail2 = "{\"type\":\"record\",\"name\":\"Fail2\","
174                 + "\"fields\":[{\"name\": \"C.D\",\"type\":\"int\"}]}";
175         final AxContextSchema avroFailSchema2 = new AxContextSchema(
176                 new AxArtifactKey("AvroFail2", "0.0.1"), "AVRO", fail2);
177         schemas.getSchemasMap().put(avroFailSchema2.getKey(), avroFailSchema2);
178
179         AxArtifactKey ak2 = avroFailSchema2.getKey();
180         final Throwable exception2 = assertThrows(ContextRuntimeException.class,
181             () -> sh.createSchemaHelper(testKey, ak2));
182         assertNotNull(exception2.getCause());
183         assertEquals("Illegal character in: C.D", exception2.getCause().getMessage());
184
185         final String fail3 = "{\"type\":\"record\",\"name\":\"Fail3\","
186                 + "\"fields\":[{\"name\": \"E:F\",\"type\":\"boolean\"}]}";
187         final AxContextSchema avroFailSchema3 = new AxContextSchema(
188                 new AxArtifactKey("AvroFail3", "0.0.1"), "AVRO", fail3);
189         schemas.getSchemasMap().put(avroFailSchema3.getKey(), avroFailSchema3);
190         AxArtifactKey ak3 = avroFailSchema3.getKey();
191         final Throwable exception3 = assertThrows(ContextRuntimeException.class,
192             () -> sh.createSchemaHelper(testKey, ak3));
193         assertNotNull(exception3.getCause());
194         assertEquals("Illegal character in: E:F", exception3.getCause().getMessage());
195     }
196
197     /**
198      * Test map init.
199      *
200      * @throws IOException Signals that an I/O exception has occurred.
201      */
202     @Test
203     public void testMapInit() throws IOException {
204         final AxContextSchema avroSchema =
205                 new AxContextSchema(new AxArtifactKey("AvroRecord", "0.0.1"), "AVRO", addressMapSchema);
206
207         schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
208         final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
209
210         final HashMap<?, ?> newMapEmpty = (HashMap<?, ?>) schemaHelper.createNewInstance();
211         assertEquals(0, newMapEmpty.size());
212
213         final String inString = TextFileUtils.getTextFileAsString("src/test/resources/data/MapExampleAddressFull.json");
214         final HashMap<?, ?> newMapFull = (HashMap<?, ?>) schemaHelper.createNewInstance(inString);
215
216         assertEquals("{\"streetaddress\": \"221 B Baker St.\", \"city\": \"London\"}",
217                 newMapFull.get(new Utf8("address2")).toString());
218     }
219
220     /**
221      * Test long map unmarshal marshal.
222      *
223      * @throws IOException Signals that an I/O exception has occurred.
224      */
225     @Test
226     public void testLongMapUnmarshalMarshal() throws IOException {
227         final AxContextSchema avroSchema =
228                 new AxContextSchema(new AxArtifactKey("AvroMap", "0.0.1"), "AVRO", longMapSchema);
229
230         schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
231         final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
232
233         testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleLongNull.json");
234         testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleLongFull.json");
235     }
236
237     /**
238      * Test address map unmarshal marshal.
239      *
240      * @throws IOException Signals that an I/O exception has occurred.
241      */
242     @Test
243     public void testAddressMapUnmarshalMarshal() throws IOException {
244         final AxContextSchema avroSchema =
245                 new AxContextSchema(new AxArtifactKey("AvroMap", "0.0.1"), "AVRO", addressMapSchema);
246
247         schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
248         final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
249
250         testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleAddressNull.json");
251         testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleAddressFull.json");
252     }
253
254     /**
255      * Test sub record create.
256      *
257      * @throws IOException Signals that an I/O exception has occurred.
258      */
259     @Test
260     public void testSubRecordCreateRecord() throws IOException {
261         final AxContextSchema avroSchema =
262                 new AxContextSchema(new AxArtifactKey("AvroMap", "0.0.1"), "AVRO", addressMapSchema);
263
264         schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
265         final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
266
267         GenericRecord subRecord = (GenericRecord) schemaHelper.createNewSubInstance("AddressUSRecord");
268         assertNull(subRecord.get("streetAddress"));
269     }
270
271     /**
272      * Test address map unmarshal marshal invalid fields.
273      *
274      * @throws IOException Signals that an I/O exception has occurred.
275      */
276     @Test
277     public void testAddressMapUnmarshalMarshalInvalidFields() throws IOException {
278         final AxContextSchema avroSchema =
279                 new AxContextSchema(new AxArtifactKey("AvroMap", "0.0.1"), "AVRO", addressMapSchemaInvalidFields);
280
281         schemas.getSchemasMap().put(avroSchema.getKey(), avroSchema);
282         final SchemaHelper schemaHelper = new SchemaHelperFactory().createSchemaHelper(testKey, avroSchema.getKey());
283
284         testUnmarshalMarshal(schemaHelper, "src/test/resources/data/MapExampleAddressInvalidFields.json");
285
286         String vals = TextFileUtils.getTextFileAsString("src/test/resources/data/MapExampleAddressInvalidFields.json");
287         final HashMap<?, ?> newMapFull = (HashMap<?, ?>) schemaHelper.createNewInstance(vals);
288         final String expect = "{\"street_DasH_address\": \"Wayne Manor\", \"the_DoT_city\": \"Gotham City\", "
289                 + "\"the_ColoN_code\": \"BatCave7\"}";
290         assertEquals(expect, newMapFull.get(new Utf8("address_DoT_3")).toString());
291     }
292
293     /**
294      * Test unmarshal marshal.
295      *
296      * @param schemaHelper the schema helper
297      * @param fileName the file name
298      * @throws IOException Signals that an I/O exception has occurred.
299      */
300     private void testUnmarshalMarshal(final SchemaHelper schemaHelper, final String fileName) throws IOException {
301         final String originalInString = TextFileUtils.getTextFileAsString(fileName);
302         final HashMap<?, ?> firstDecodedMap = (HashMap<?, ?>) schemaHelper.unmarshal(originalInString);
303
304         final String outString = schemaHelper.marshal2String(firstDecodedMap);
305
306         final File tempOutFile = File.createTempFile("ApexAvro", ".json");
307         TextFileUtils.putStringAsFile(outString, tempOutFile);
308
309         final String decodeEncodeInString = TextFileUtils.getTextFileAsString(fileName);
310         tempOutFile.delete();
311
312         final HashMap<?, ?> secondDecodedMap = (HashMap<?, ?>) schemaHelper.unmarshal(decodeEncodeInString);
313
314         // Now check that our doubly encoded map equals the first decoded map, Java map equals
315         // checks values and keys
316         assertEquals(firstDecodedMap, secondDecodedMap);
317     }
318 }