2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ===================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END============================================
21 package org.onap.aai.champcore.core;
23 import static org.junit.Assert.assertTrue;
25 import java.io.IOException;
26 import java.util.Optional;
29 import org.junit.Test;
30 import org.onap.aai.champcore.ChampAPI;
31 import org.onap.aai.champcore.ChampGraph;
32 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
33 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
34 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
35 import org.onap.aai.champcore.exceptions.ChampTransactionException;
36 import org.onap.aai.champcore.model.ChampConnectionConstraint;
37 import org.onap.aai.champcore.model.ChampConnectionMultiplicity;
38 import org.onap.aai.champcore.model.ChampField;
39 import org.onap.aai.champcore.model.ChampObject;
40 import org.onap.aai.champcore.model.ChampObject.ReservedTypes;
41 import org.onap.aai.champcore.model.ChampObjectConstraint;
42 import org.onap.aai.champcore.model.ChampPartition;
43 import org.onap.aai.champcore.model.ChampPropertyConstraint;
44 import org.onap.aai.champcore.model.ChampRelationship;
45 import org.onap.aai.champcore.model.ChampRelationshipConstraint;
46 import org.onap.aai.champcore.model.ChampSchema;
47 import org.onap.aai.champcore.schema.AlwaysValidChampSchemaEnforcer;
48 import org.onap.aai.champcore.schema.ChampSchemaEnforcer;
49 import org.onap.aai.champcore.schema.DefaultChampSchemaEnforcer;
51 import com.fasterxml.jackson.databind.ObjectMapper;
53 public class ChampSchemaTest extends BaseChampAPITest {
56 public void runInMemoryTest() {
60 public void runTest(String apiType) {
61 final String graphName = ChampSchemaTest.class.getSimpleName();
63 final ChampAPI api = ChampAPI.Factory.newInstance(apiType);
66 ChampSchemaTest.testChampSchemaCrud(api.getGraph(graphName));
67 } catch (Throwable t) {
68 throw new AssertionError(apiType + " unit test failed", t);
74 public static void testChampSchemaCrud(ChampGraph graph) {
76 final ChampSchema schema = ChampSchema.create()
77 .withObjectConstraint()
79 .withPropertyConstraint()
83 .withPropertyConstraint()
88 .withRelationshipConstraint()
90 .withPropertyConstraint()
92 .ofType(ChampField.Type.STRING)
95 .withConnectionConstraint()
103 graph.storeSchema(schema);
104 } catch (ChampSchemaViolationException e) {
105 throw new AssertionError(e);
108 final ChampObject emptyFoo = ChampObject.create()
114 graph.storeObject(emptyFoo, Optional.empty());
115 } catch (ChampMarshallingException e1) {
116 throw new AssertionError(e1);
117 } catch (ChampSchemaViolationException e1) {
118 //Expected, since it does not have the required property "property1"
119 } catch (ChampObjectNotExistsException e) {
120 throw new AssertionError(e);
121 } catch (ChampTransactionException e) {
122 throw new AssertionError(e);
125 final ChampSchema retrievedSchema = graph.retrieveSchema();
127 if (!schema.equals(retrievedSchema)) throw new AssertionError("Retrieved schema is not the same as the schema that was previously stored");
130 graph.updateSchema(new ChampRelationshipConstraint.Builder("bard").build());
131 assertTrue(graph.retrieveSchema().getRelationshipConstraint("bard").isPresent());
133 graph.updateSchema(new ChampObjectConstraint.Builder("baz").build());
134 assertTrue(graph.retrieveSchema().getObjectConstraint("baz").isPresent());
135 } catch (ChampSchemaViolationException e) {
136 throw new AssertionError(e);
139 final ChampSchema updatedSchema = graph.retrieveSchema();
141 if (!updatedSchema.getObjectConstraint("baz").isPresent()) throw new AssertionError("Updated schema and retrieved, but retrieved schema did not contain updates");
142 if (!updatedSchema.getRelationshipConstraint("bard").isPresent()) throw new AssertionError("Updated schema and retrieved, but retrieved schema did not contain updates");
145 graph.updateSchema(new ChampObjectConstraint.Builder("foo")
147 new ChampPropertyConstraint.Builder(
148 new ChampField.Builder("property2")
156 final ChampObject storedEmptyFoo = graph.storeObject(emptyFoo, Optional.empty());
158 graph.deleteObject(storedEmptyFoo.getKey().get(), Optional.empty());
159 } catch (ChampMarshallingException e) {
160 throw new AssertionError(e);
161 } catch (ChampSchemaViolationException e) {
162 throw new AssertionError(e);
163 } catch (ChampObjectNotExistsException e) {
164 throw new AssertionError(e);
165 } catch (ChampTransactionException e) {
166 throw new AssertionError(e);
169 graph.deleteSchema();
170 assertTrue(graph.retrieveSchema().equals(ChampSchema.emptySchema()));
174 public void testChampSchemaFluentApi() {
175 final ChampSchema schema = ChampSchema.create()
176 .withObjectConstraint()
178 .withPropertyConstraint()
180 .ofType(ChampField.Type.STRING)
183 .withPropertyConstraint()
185 .ofType(ChampField.Type.BOOLEAN)
189 .withRelationshipConstraint()
191 .withPropertyConstraint()
193 .ofType(ChampField.Type.STRING)
196 .withPropertyConstraint()
200 .withConnectionConstraint()
203 .withMultiplicity(ChampConnectionMultiplicity.ONE)
205 .withConnectionConstraint()
212 assertTrue(schema.getObjectConstraint("foo").get().getType().equals("foo"));
214 for (ChampPropertyConstraint propConst : schema.getObjectConstraint("foo").get().getPropertyConstraints()) {
215 if (propConst.getField().getName().equals("bar")) {
216 assertTrue(propConst.getField().getJavaType().equals(String.class));
217 assertTrue(propConst.isRequired());
218 } else if (propConst.getField().getName().equals("baz")) {
219 assertTrue(propConst.getField().getJavaType().equals(Boolean.class));
220 assertTrue(!propConst.isRequired());
222 throw new AssertionError("Unknown property constraint found: " + propConst);
226 assertTrue(schema.getRelationshipConstraint("eats").get().getType().equals("eats"));
228 for (ChampPropertyConstraint propConst : schema.getRelationshipConstraint("eats").get().getPropertyConstraints()) {
229 if (propConst.getField().getName().equals("at")) {
230 assertTrue(propConst.getField().getJavaType().equals(String.class));
231 assertTrue(propConst.isRequired());
232 } else if (propConst.getField().getName().equals("for")) {
233 assertTrue(propConst.getField().getJavaType().equals(String.class));
234 assertTrue(!propConst.isRequired());
236 throw new AssertionError("Unknown property constraint found: " + propConst);
240 for (ChampConnectionConstraint connConst : schema.getRelationshipConstraint("eats").get().getConnectionConstraints()) {
241 if (connConst.getSourceType().equals("foo")) {
242 assertTrue(connConst.getTargetType().equals("foo"));
243 assertTrue(connConst.getMultiplicity() == ChampConnectionMultiplicity.ONE);
244 } else if (connConst.getSourceType().equals("bar")) {
245 assertTrue(connConst.getTargetType().equals("bar"));
246 assertTrue(connConst.getMultiplicity() == ChampConnectionMultiplicity.MANY);
248 throw new AssertionError("Unknown connection constraint found: " + connConst);
254 public void testDefaultChampSchemaEnforcer() {
256 final ChampSchemaEnforcer schemaEnforcer = new DefaultChampSchemaEnforcer();
257 final ChampSchema champSchema = ChampSchema.create()
258 .withObjectConstraint()
260 .withPropertyConstraint()
262 .ofType(ChampField.Type.STRING)
266 .withRelationshipConstraint()
268 .withPropertyConstraint()
272 .withConnectionConstraint()
275 .withMultiplicity(ChampConnectionMultiplicity.ONE)
281 schemaEnforcer.validate(ChampObject.create()
284 .withProperty("bar", "true")
286 champSchema.getObjectConstraint("foo").get());
287 } catch (ChampSchemaViolationException e) {
288 throw new AssertionError(e);
292 schemaEnforcer.validate(ChampObject.create()
296 champSchema.getObjectConstraint("foo").get());
297 throw new AssertionError("Failed to enforce required property constraint on object");
298 } catch (ChampSchemaViolationException e) {
303 schemaEnforcer.validate(ChampObject.create()
306 .withProperty("bar", true)
308 champSchema.getObjectConstraint("foo").get());
309 throw new AssertionError("Failed to enforce property type constraint on object");
310 } catch (ChampSchemaViolationException e) {
315 schemaEnforcer.validate(ChampRelationship.create()
326 .withProperty("bar", "true")
328 champSchema.getRelationshipConstraint("makes").get()
330 } catch (ChampSchemaViolationException e) {
331 throw new AssertionError(e);
335 schemaEnforcer.validate(ChampRelationship.create()
347 champSchema.getRelationshipConstraint("makes").get()
349 throw new AssertionError("Failed to enforce required property constraint on relationship");
350 } catch (ChampSchemaViolationException e) {
355 schemaEnforcer.validate(ChampPartition.create()
360 .withProperty("bar", "true")
370 ChampRelationship.create()
376 .withProperty("bar", "true")
382 .withProperty("bar", "true")
386 ChampRelationship.create()
396 .withProperty("bar", "true")
398 .withProperty("bar", "true")
404 } catch (ChampSchemaViolationException e) {
405 throw new AssertionError(e);
409 schemaEnforcer.validate(ChampPartition.create()
414 .withProperty("bar", "true")
424 ChampRelationship.create()
430 .withProperty("bar", "true")
436 .withProperty("bar", "true")
440 ChampRelationship.create()
446 .withProperty("bar", "true")
452 .withProperty("bar", "true")
458 throw new AssertionError("Failed to enforce connection constraint on relationship type 'makes'");
459 } catch (ChampSchemaViolationException e) {
465 public void testAlwaysValidChampSchemaEnforcer() {
467 final ChampSchemaEnforcer schemaEnforcer = new AlwaysValidChampSchemaEnforcer();
470 schemaEnforcer.validate(ChampObject.create()
473 .withProperty("bar", true)
475 new ChampObjectConstraint.Builder("foo")
477 new ChampPropertyConstraint.Builder(
478 new ChampField.Builder("bar")
479 .type(ChampField.Type.STRING)
488 schemaEnforcer.validate(ChampRelationship.create()
499 .withProperty("bar", true)
501 new ChampRelationshipConstraint.Builder("bar")
503 new ChampPropertyConstraint.Builder(
504 new ChampField.Builder("bar")
505 .type(ChampField.Type.STRING)
514 schemaEnforcer.validate(ChampPartition.create()
519 .withProperty("bar", true)
526 .withProperty("bar", true)
530 ChampRelationship.create()
544 ChampRelationship.create()
555 .withProperty("bar", true)
560 .withObjectConstraint()
562 .withPropertyConstraint()
567 .withRelationshipConstraint()
569 .withPropertyConstraint()
573 .withConnectionConstraint()
576 .withMultiplicity(ChampConnectionMultiplicity.ONE)
579 .withRelationshipConstraint()
581 .withConnectionConstraint()
583 .targetedTo("computer")
586 .withRelationshipConstraint()
588 .withConnectionConstraint()
589 .sourcedFrom("computer")
596 } catch (ChampSchemaViolationException e) {
597 throw new AssertionError(e);
602 public void testFluentSchemaApi() {
603 final ChampSchema schema = ChampSchema.create()
604 .withObjectConstraint()
606 .withPropertyConstraint()
608 .ofType(ChampField.Type.STRING)
612 .withObjectConstraint()
614 .withPropertyConstraint()
616 .ofType(ChampField.Type.LONG)
620 .withRelationshipConstraint()
622 .withPropertyConstraint()
624 .ofType(ChampField.Type.INTEGER)
627 .withConnectionConstraint()
630 .withMultiplicity(ChampConnectionMultiplicity.NONE)
632 .withConnectionConstraint()
635 .withMultiplicity(ChampConnectionMultiplicity.ONE)
637 .withConnectionConstraint()
640 .withMultiplicity(ChampConnectionMultiplicity.MANY)
642 .withConnectionConstraint()
645 .withMultiplicity(ChampConnectionMultiplicity.MANY)
650 final ChampObjectConstraint aObjConstraint = schema.getObjectConstraint("a").get();
652 assertTrue(aObjConstraint.getType().equals("a"));
654 final ChampPropertyConstraint zPropertyConstraint = aObjConstraint.getPropertyConstraint("z").get();
656 assertTrue(zPropertyConstraint.getField().getName().equals("z"));
657 assertTrue(zPropertyConstraint.getField().getJavaType().equals(String.class));
658 assertTrue(!zPropertyConstraint.isRequired());
660 final ChampObjectConstraint bObjConstraint = schema.getObjectConstraint("b").get();
662 assertTrue(bObjConstraint.getType().equals("b"));
664 final ChampPropertyConstraint yPropertyConstraint = bObjConstraint.getPropertyConstraint("y").get();
666 assertTrue(yPropertyConstraint.getField().getName().equals("y"));
667 assertTrue(yPropertyConstraint.getField().getJavaType().equals(Long.class));
668 assertTrue(yPropertyConstraint.isRequired());
670 final ChampRelationshipConstraint oneRelConstraint = schema.getRelationshipConstraint("one").get();
672 assertTrue(oneRelConstraint.getType().equals("one"));
674 final ChampPropertyConstraint ninePropertyConstraint = oneRelConstraint.getPropertyConstraint("nine").get();
676 assertTrue(ninePropertyConstraint.getField().getName().equals("nine"));
677 assertTrue(ninePropertyConstraint.getField().getJavaType().equals(Integer.class));
678 assertTrue(!ninePropertyConstraint.isRequired());
680 final Set<ChampConnectionConstraint> connectionConstraints = oneRelConstraint.getConnectionConstraints();
682 for (ChampConnectionConstraint cc : connectionConstraints) {
683 if (cc.getSourceType().equals("a") && cc.getTargetType().equals("b")) {
684 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.NONE);
685 } else if (cc.getSourceType().equals(ReservedTypes.ANY.toString()) && cc.getTargetType().equals("b")) {
686 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.MANY);
687 } else if (cc.getSourceType().equals(ReservedTypes.ANY.toString()) && cc.getTargetType().equals(ReservedTypes.ANY.toString())) {
688 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.MANY);
689 } else if (cc.getSourceType().equals("a") && cc.getTargetType().equals(ReservedTypes.ANY.toString())) {
690 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.ONE);
692 throw new AssertionError("Found unspecified connection constraint " + cc);
698 public void testJacksonObjectMapping() {
699 final ChampSchema schema = ChampSchema.create()
700 .withObjectConstraint()
702 .withPropertyConstraint()
704 .ofType(ChampField.Type.STRING)
708 .withObjectConstraint()
710 .withPropertyConstraint()
712 .ofType(ChampField.Type.LONG)
716 .withRelationshipConstraint()
718 .withPropertyConstraint()
720 .ofType(ChampField.Type.INTEGER)
723 .withConnectionConstraint()
726 .withMultiplicity(ChampConnectionMultiplicity.NONE)
728 .withConnectionConstraint()
731 .withMultiplicity(ChampConnectionMultiplicity.ONE)
733 .withConnectionConstraint()
736 .withMultiplicity(ChampConnectionMultiplicity.MANY)
738 .withConnectionConstraint()
741 .withMultiplicity(ChampConnectionMultiplicity.MANY)
746 final ObjectMapper om = new ObjectMapper();
749 final byte[] serialized = om.writeValueAsBytes(schema);
750 System.out.println(new String(serialized, "UTF-8"));
751 final ChampSchema deserialized = om.readValue(serialized, ChampSchema.class);
752 assert schema.equals(deserialized);
753 } catch (IOException e) {
754 throw new AssertionError(e);