2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017 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============================================
20 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 package org.onap.aai.champcore.core;
24 import static org.junit.Assert.assertTrue;
26 import java.io.IOException;
27 import java.util.Optional;
30 import org.junit.Test;
31 import org.onap.aai.champcore.ChampAPI;
32 import org.onap.aai.champcore.ChampGraph;
33 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
34 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
35 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
36 import org.onap.aai.champcore.exceptions.ChampTransactionException;
37 import org.onap.aai.champcore.model.ChampConnectionConstraint;
38 import org.onap.aai.champcore.model.ChampConnectionMultiplicity;
39 import org.onap.aai.champcore.model.ChampField;
40 import org.onap.aai.champcore.model.ChampObject;
41 import org.onap.aai.champcore.model.ChampObject.ReservedTypes;
42 import org.onap.aai.champcore.model.ChampObjectConstraint;
43 import org.onap.aai.champcore.model.ChampPartition;
44 import org.onap.aai.champcore.model.ChampPropertyConstraint;
45 import org.onap.aai.champcore.model.ChampRelationship;
46 import org.onap.aai.champcore.model.ChampRelationshipConstraint;
47 import org.onap.aai.champcore.model.ChampSchema;
48 import org.onap.aai.champcore.schema.AlwaysValidChampSchemaEnforcer;
49 import org.onap.aai.champcore.schema.ChampSchemaEnforcer;
50 import org.onap.aai.champcore.schema.DefaultChampSchemaEnforcer;
52 import com.fasterxml.jackson.databind.ObjectMapper;
54 public class ChampSchemaTest extends BaseChampAPITest {
57 public void runInMemoryTest() {
61 public void runTest(String apiType) {
62 final String graphName = ChampSchemaTest.class.getSimpleName();
64 final ChampAPI api = ChampAPI.Factory.newInstance(apiType);
67 ChampSchemaTest.testChampSchemaCrud(api.getGraph(graphName));
68 } catch (Throwable t) {
69 throw new AssertionError(apiType + " unit test failed", t);
75 public static void testChampSchemaCrud(ChampGraph graph) {
77 final ChampSchema schema = ChampSchema.create()
78 .withObjectConstraint()
80 .withPropertyConstraint()
84 .withPropertyConstraint()
89 .withRelationshipConstraint()
91 .withPropertyConstraint()
93 .ofType(ChampField.Type.STRING)
96 .withConnectionConstraint()
104 graph.storeSchema(schema);
105 } catch (ChampSchemaViolationException e) {
106 throw new AssertionError(e);
109 final ChampObject emptyFoo = ChampObject.create()
115 graph.storeObject(emptyFoo, Optional.empty());
116 } catch (ChampMarshallingException e1) {
117 throw new AssertionError(e1);
118 } catch (ChampSchemaViolationException e1) {
119 //Expected, since it does not have the required property "property1"
120 } catch (ChampObjectNotExistsException e) {
121 throw new AssertionError(e);
122 } catch (ChampTransactionException e) {
123 throw new AssertionError(e);
126 final ChampSchema retrievedSchema = graph.retrieveSchema();
128 if (!schema.equals(retrievedSchema)) throw new AssertionError("Retrieved schema is not the same as the schema that was previously stored");
131 graph.updateSchema(new ChampRelationshipConstraint.Builder("bard").build());
132 assertTrue(graph.retrieveSchema().getRelationshipConstraint("bard").isPresent());
134 graph.updateSchema(new ChampObjectConstraint.Builder("baz").build());
135 assertTrue(graph.retrieveSchema().getObjectConstraint("baz").isPresent());
136 } catch (ChampSchemaViolationException e) {
137 throw new AssertionError(e);
140 final ChampSchema updatedSchema = graph.retrieveSchema();
142 if (!updatedSchema.getObjectConstraint("baz").isPresent()) throw new AssertionError("Updated schema and retrieved, but retrieved schema did not contain updates");
143 if (!updatedSchema.getRelationshipConstraint("bard").isPresent()) throw new AssertionError("Updated schema and retrieved, but retrieved schema did not contain updates");
146 graph.updateSchema(new ChampObjectConstraint.Builder("foo")
148 new ChampPropertyConstraint.Builder(
149 new ChampField.Builder("property2")
157 final ChampObject storedEmptyFoo = graph.storeObject(emptyFoo, Optional.empty());
159 graph.deleteObject(storedEmptyFoo.getKey().get(), Optional.empty());
160 } catch (ChampMarshallingException e) {
161 throw new AssertionError(e);
162 } catch (ChampSchemaViolationException e) {
163 throw new AssertionError(e);
164 } catch (ChampObjectNotExistsException e) {
165 throw new AssertionError(e);
166 } catch (ChampTransactionException e) {
167 throw new AssertionError(e);
170 graph.deleteSchema();
171 assertTrue(graph.retrieveSchema().equals(ChampSchema.emptySchema()));
175 public void testChampSchemaFluentApi() {
176 final ChampSchema schema = ChampSchema.create()
177 .withObjectConstraint()
179 .withPropertyConstraint()
181 .ofType(ChampField.Type.STRING)
184 .withPropertyConstraint()
186 .ofType(ChampField.Type.BOOLEAN)
190 .withRelationshipConstraint()
192 .withPropertyConstraint()
194 .ofType(ChampField.Type.STRING)
197 .withPropertyConstraint()
201 .withConnectionConstraint()
204 .withMultiplicity(ChampConnectionMultiplicity.ONE)
206 .withConnectionConstraint()
213 assertTrue(schema.getObjectConstraint("foo").get().getType().equals("foo"));
215 for (ChampPropertyConstraint propConst : schema.getObjectConstraint("foo").get().getPropertyConstraints()) {
216 if (propConst.getField().getName().equals("bar")) {
217 assertTrue(propConst.getField().getJavaType().equals(String.class));
218 assertTrue(propConst.isRequired());
219 } else if (propConst.getField().getName().equals("baz")) {
220 assertTrue(propConst.getField().getJavaType().equals(Boolean.class));
221 assertTrue(!propConst.isRequired());
223 throw new AssertionError("Unknown property constraint found: " + propConst);
227 assertTrue(schema.getRelationshipConstraint("eats").get().getType().equals("eats"));
229 for (ChampPropertyConstraint propConst : schema.getRelationshipConstraint("eats").get().getPropertyConstraints()) {
230 if (propConst.getField().getName().equals("at")) {
231 assertTrue(propConst.getField().getJavaType().equals(String.class));
232 assertTrue(propConst.isRequired());
233 } else if (propConst.getField().getName().equals("for")) {
234 assertTrue(propConst.getField().getJavaType().equals(String.class));
235 assertTrue(!propConst.isRequired());
237 throw new AssertionError("Unknown property constraint found: " + propConst);
241 for (ChampConnectionConstraint connConst : schema.getRelationshipConstraint("eats").get().getConnectionConstraints()) {
242 if (connConst.getSourceType().equals("foo")) {
243 assertTrue(connConst.getTargetType().equals("foo"));
244 assertTrue(connConst.getMultiplicity() == ChampConnectionMultiplicity.ONE);
245 } else if (connConst.getSourceType().equals("bar")) {
246 assertTrue(connConst.getTargetType().equals("bar"));
247 assertTrue(connConst.getMultiplicity() == ChampConnectionMultiplicity.MANY);
249 throw new AssertionError("Unknown connection constraint found: " + connConst);
255 public void testDefaultChampSchemaEnforcer() {
257 final ChampSchemaEnforcer schemaEnforcer = new DefaultChampSchemaEnforcer();
258 final ChampSchema champSchema = ChampSchema.create()
259 .withObjectConstraint()
261 .withPropertyConstraint()
263 .ofType(ChampField.Type.STRING)
267 .withRelationshipConstraint()
269 .withPropertyConstraint()
273 .withConnectionConstraint()
276 .withMultiplicity(ChampConnectionMultiplicity.ONE)
282 schemaEnforcer.validate(ChampObject.create()
285 .withProperty("bar", "true")
287 champSchema.getObjectConstraint("foo").get());
288 } catch (ChampSchemaViolationException e) {
289 throw new AssertionError(e);
293 schemaEnforcer.validate(ChampObject.create()
297 champSchema.getObjectConstraint("foo").get());
298 throw new AssertionError("Failed to enforce required property constraint on object");
299 } catch (ChampSchemaViolationException e) {
304 schemaEnforcer.validate(ChampObject.create()
307 .withProperty("bar", true)
309 champSchema.getObjectConstraint("foo").get());
310 throw new AssertionError("Failed to enforce property type constraint on object");
311 } catch (ChampSchemaViolationException e) {
316 schemaEnforcer.validate(ChampRelationship.create()
327 .withProperty("bar", "true")
329 champSchema.getRelationshipConstraint("makes").get()
331 } catch (ChampSchemaViolationException e) {
332 throw new AssertionError(e);
336 schemaEnforcer.validate(ChampRelationship.create()
348 champSchema.getRelationshipConstraint("makes").get()
350 throw new AssertionError("Failed to enforce required property constraint on relationship");
351 } catch (ChampSchemaViolationException e) {
356 schemaEnforcer.validate(ChampPartition.create()
361 .withProperty("bar", "true")
371 ChampRelationship.create()
377 .withProperty("bar", "true")
383 .withProperty("bar", "true")
387 ChampRelationship.create()
397 .withProperty("bar", "true")
399 .withProperty("bar", "true")
405 } catch (ChampSchemaViolationException e) {
406 throw new AssertionError(e);
410 schemaEnforcer.validate(ChampPartition.create()
415 .withProperty("bar", "true")
425 ChampRelationship.create()
431 .withProperty("bar", "true")
437 .withProperty("bar", "true")
441 ChampRelationship.create()
447 .withProperty("bar", "true")
453 .withProperty("bar", "true")
459 throw new AssertionError("Failed to enforce connection constraint on relationship type 'makes'");
460 } catch (ChampSchemaViolationException e) {
466 public void testAlwaysValidChampSchemaEnforcer() {
468 final ChampSchemaEnforcer schemaEnforcer = new AlwaysValidChampSchemaEnforcer();
471 schemaEnforcer.validate(ChampObject.create()
474 .withProperty("bar", true)
476 new ChampObjectConstraint.Builder("foo")
478 new ChampPropertyConstraint.Builder(
479 new ChampField.Builder("bar")
480 .type(ChampField.Type.STRING)
489 schemaEnforcer.validate(ChampRelationship.create()
500 .withProperty("bar", true)
502 new ChampRelationshipConstraint.Builder("bar")
504 new ChampPropertyConstraint.Builder(
505 new ChampField.Builder("bar")
506 .type(ChampField.Type.STRING)
515 schemaEnforcer.validate(ChampPartition.create()
520 .withProperty("bar", true)
527 .withProperty("bar", true)
531 ChampRelationship.create()
545 ChampRelationship.create()
556 .withProperty("bar", true)
561 .withObjectConstraint()
563 .withPropertyConstraint()
568 .withRelationshipConstraint()
570 .withPropertyConstraint()
574 .withConnectionConstraint()
577 .withMultiplicity(ChampConnectionMultiplicity.ONE)
580 .withRelationshipConstraint()
582 .withConnectionConstraint()
584 .targetedTo("computer")
587 .withRelationshipConstraint()
589 .withConnectionConstraint()
590 .sourcedFrom("computer")
597 } catch (ChampSchemaViolationException e) {
598 throw new AssertionError(e);
603 public void testFluentSchemaApi() {
604 final ChampSchema schema = ChampSchema.create()
605 .withObjectConstraint()
607 .withPropertyConstraint()
609 .ofType(ChampField.Type.STRING)
613 .withObjectConstraint()
615 .withPropertyConstraint()
617 .ofType(ChampField.Type.LONG)
621 .withRelationshipConstraint()
623 .withPropertyConstraint()
625 .ofType(ChampField.Type.INTEGER)
628 .withConnectionConstraint()
631 .withMultiplicity(ChampConnectionMultiplicity.NONE)
633 .withConnectionConstraint()
636 .withMultiplicity(ChampConnectionMultiplicity.ONE)
638 .withConnectionConstraint()
641 .withMultiplicity(ChampConnectionMultiplicity.MANY)
643 .withConnectionConstraint()
646 .withMultiplicity(ChampConnectionMultiplicity.MANY)
651 final ChampObjectConstraint aObjConstraint = schema.getObjectConstraint("a").get();
653 assertTrue(aObjConstraint.getType().equals("a"));
655 final ChampPropertyConstraint zPropertyConstraint = aObjConstraint.getPropertyConstraint("z").get();
657 assertTrue(zPropertyConstraint.getField().getName().equals("z"));
658 assertTrue(zPropertyConstraint.getField().getJavaType().equals(String.class));
659 assertTrue(!zPropertyConstraint.isRequired());
661 final ChampObjectConstraint bObjConstraint = schema.getObjectConstraint("b").get();
663 assertTrue(bObjConstraint.getType().equals("b"));
665 final ChampPropertyConstraint yPropertyConstraint = bObjConstraint.getPropertyConstraint("y").get();
667 assertTrue(yPropertyConstraint.getField().getName().equals("y"));
668 assertTrue(yPropertyConstraint.getField().getJavaType().equals(Long.class));
669 assertTrue(yPropertyConstraint.isRequired());
671 final ChampRelationshipConstraint oneRelConstraint = schema.getRelationshipConstraint("one").get();
673 assertTrue(oneRelConstraint.getType().equals("one"));
675 final ChampPropertyConstraint ninePropertyConstraint = oneRelConstraint.getPropertyConstraint("nine").get();
677 assertTrue(ninePropertyConstraint.getField().getName().equals("nine"));
678 assertTrue(ninePropertyConstraint.getField().getJavaType().equals(Integer.class));
679 assertTrue(!ninePropertyConstraint.isRequired());
681 final Set<ChampConnectionConstraint> connectionConstraints = oneRelConstraint.getConnectionConstraints();
683 for (ChampConnectionConstraint cc : connectionConstraints) {
684 if (cc.getSourceType().equals("a") && cc.getTargetType().equals("b")) {
685 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.NONE);
686 } else if (cc.getSourceType().equals(ReservedTypes.ANY.toString()) && cc.getTargetType().equals("b")) {
687 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.MANY);
688 } else if (cc.getSourceType().equals(ReservedTypes.ANY.toString()) && cc.getTargetType().equals(ReservedTypes.ANY.toString())) {
689 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.MANY);
690 } else if (cc.getSourceType().equals("a") && cc.getTargetType().equals(ReservedTypes.ANY.toString())) {
691 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.ONE);
693 throw new AssertionError("Found unspecified connection constraint " + cc);
699 public void testJacksonObjectMapping() {
700 final ChampSchema schema = ChampSchema.create()
701 .withObjectConstraint()
703 .withPropertyConstraint()
705 .ofType(ChampField.Type.STRING)
709 .withObjectConstraint()
711 .withPropertyConstraint()
713 .ofType(ChampField.Type.LONG)
717 .withRelationshipConstraint()
719 .withPropertyConstraint()
721 .ofType(ChampField.Type.INTEGER)
724 .withConnectionConstraint()
727 .withMultiplicity(ChampConnectionMultiplicity.NONE)
729 .withConnectionConstraint()
732 .withMultiplicity(ChampConnectionMultiplicity.ONE)
734 .withConnectionConstraint()
737 .withMultiplicity(ChampConnectionMultiplicity.MANY)
739 .withConnectionConstraint()
742 .withMultiplicity(ChampConnectionMultiplicity.MANY)
747 final ObjectMapper om = new ObjectMapper();
750 final byte[] serialized = om.writeValueAsBytes(schema);
751 System.out.println(new String(serialized, "UTF-8"));
752 final ChampSchema deserialized = om.readValue(serialized, ChampSchema.class);
753 assert schema.equals(deserialized);
754 } catch (IOException e) {
755 throw new AssertionError(e);