| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- package org.leumasjaffe.json.schema;
- import static com.fasterxml.jackson.databind.node.JsonNodeType.*;
- import static org.junit.Assert.assertThat;
- import static org.leumasjaffe.json.schema.matcher.Accepts.accepts;
- import static org.leumasjaffe.json.schema.matcher.Not.not;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.Map;
- import org.junit.Test;
- import org.leumasjaffe.json.schema.tester.AllItemsTester;
- import org.leumasjaffe.json.schema.tester.ContainsTester;
- import org.leumasjaffe.json.schema.tester.EqualsTester;
- import org.leumasjaffe.json.schema.tester.FixedTester;
- import org.leumasjaffe.json.schema.tester.FormatTester;
- import org.leumasjaffe.json.schema.tester.ItemsTester;
- import org.leumasjaffe.json.schema.tester.NumberTester;
- import org.leumasjaffe.json.schema.tester.PropertyNameTester;
- import org.leumasjaffe.json.schema.tester.PropertyTester;
- import org.leumasjaffe.json.schema.tester.SizeTester;
- import org.leumasjaffe.json.schema.tester.TypeTester;
- import org.leumasjaffe.json.schema.tester.UniqueItemTester;
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.node.ArrayNode;
- import com.fasterxml.jackson.databind.node.BooleanNode;
- import com.fasterxml.jackson.databind.node.DoubleNode;
- import com.fasterxml.jackson.databind.node.JsonNodeFactory;
- import com.fasterxml.jackson.databind.node.NullNode;
- import com.fasterxml.jackson.databind.node.ObjectNode;
- import com.fasterxml.jackson.databind.node.TextNode;
- // TODO: patternProperties
- // TODO: dependencies
- // TODO: $ref
- // TODO: additionalItems with mixed results
- public class SchemaTest {
- private Schema getConstSchema(JsonNode json) {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("const", new EqualsTester(json));
- return new Schema(tests);
- }
-
- private Schema getEnumSchema(JsonNode... jsons) {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("enum", new EqualsTester(jsons));
- return new Schema(tests);
- }
- private Schema getNumberSchema() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("type", TypeTester.fromType("number"));
- tests.put("minimum", new NumberTester(d -> d >= 0.0));
- tests.put("multipleOf", new NumberTester(d -> Math.abs(d % 0.25) < 1E-7));
- tests.put("exclusiveMaximum", new NumberTester(d -> d < 1.0));
- return new Schema(tests);
- }
-
- private Schema getStringSchema() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("type", TypeTester.fromType("string"));
- tests.put("maxLength", new SizeTester(STRING, s -> s <= 30));
- tests.put("minLength", new SizeTester(STRING, s -> s >= 10));
- tests.put("pattern", j -> j.asText().matches("^https://.*"));
- tests.put("format", FormatTester.forCode("uri"));
- return new Schema(tests);
- }
-
- private Schema getArraySchema() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("type", TypeTester.fromType("array"));
- tests.put("maxItems", new SizeTester(ARRAY, s -> s <= 3));
- tests.put("minItems", new SizeTester(ARRAY, s -> s >= 1));
- tests.put("uniqueItems", new UniqueItemTester());
- tests.put("contains", new ContainsTester(getNumberSchema()));
- return new Schema(tests);
- }
- private Schema getObjectSchema() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("type", TypeTester.fromType("object"));
- tests.put("maxProperties", new SizeTester(OBJECT, s -> s <= 3));
- tests.put("minProperties", new SizeTester(OBJECT, s -> s >= 2));
- tests.put("required", json -> json.has("string"));
- tests.put("propertyNames", new PropertyNameTester(j -> j.asText().matches("^[a-z]*$")));
- // TODO Dependencies
- return new Schema(tests);
- }
- @Test
- public void testRejectsWrongTypeOnlyIfHasTypeArg() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("minProperties", FixedTester.REJECT);
- assertThat(new Schema(tests), accepts(NullNode.getInstance()));
- tests.put("type", TypeTester.fromType("string"));
- assertThat(new Schema(tests), not(accepts(NullNode.getInstance())));
- }
- @Test
- public void testHandlesUniversalChecksForBoolean() {
- assertThat(getConstSchema(BooleanNode.TRUE), accepts(BooleanNode.TRUE));
- assertThat(getConstSchema(BooleanNode.TRUE),
- not(accepts(NullNode.getInstance())));
- assertThat(getEnumSchema(BooleanNode.TRUE, BooleanNode.FALSE),
- accepts(BooleanNode.TRUE));
- assertThat(getEnumSchema(BooleanNode.TRUE, BooleanNode.FALSE),
- accepts(BooleanNode.FALSE));
- assertThat(getEnumSchema(BooleanNode.TRUE, BooleanNode.FALSE),
- not(accepts(NullNode.getInstance())));
- }
- @Test
- public void testHandlesMultipleTestsForNumber() {
- assertThat(getNumberSchema(), not(accepts(new DoubleNode(-0.25))));
- assertThat(getNumberSchema(), accepts(new DoubleNode(0.0)));
- assertThat(getNumberSchema(), accepts(new DoubleNode(0.5)));
- assertThat(getNumberSchema(), not(accepts(new DoubleNode(0.6))));
- assertThat(getNumberSchema(), not(accepts(new DoubleNode(1.0))));
- }
- @Test
- public void testHandlesOtherNumberChecks() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("exclusiveMinimum", new NumberTester(d -> d > 0.0));
- tests.put("maximum", new NumberTester(d -> d <= 1.0));
- Schema schema = new Schema(tests);
-
- assertThat(schema, not(accepts(new DoubleNode(0.0))));
- assertThat(schema, accepts(new DoubleNode(0.5)));
- assertThat(schema, accepts(new DoubleNode(0.6)));
- assertThat(schema, accepts(new DoubleNode(1.0)));
- assertThat(schema, not(accepts(new DoubleNode(1.1))));
- }
- @Test
- public void testHandlesUniversalChecksForNumber() {
- assertThat(getConstSchema(new DoubleNode(0.0)), accepts(new DoubleNode(0.0)));
- assertThat(getConstSchema(new DoubleNode(0.0)), not(accepts(new DoubleNode(0.5))));
- assertThat(getEnumSchema(new DoubleNode(0.0), new DoubleNode(1.0)),
- accepts(new DoubleNode(0.0)));
- assertThat(getEnumSchema(new DoubleNode(0.0), new DoubleNode(1.0)),
- accepts(new DoubleNode(1.0)));
- assertThat(getEnumSchema(new DoubleNode(0.0), new DoubleNode(1.0)),
- not(accepts(new DoubleNode(0.5))));
- }
-
- @Test
- public void testHandlesMultipleTestsForString() {
- assertThat(getStringSchema(), not(accepts(new TextNode("https://a"))));
- assertThat(getStringSchema(), accepts(new TextNode("https://google.com")));
- assertThat(getStringSchema(), not(accepts(new TextNode("http://google.com"))));
- assertThat(getStringSchema(), not(accepts(new TextNode("https://google.com/query?q=Hippopotomonstrosesquippedaliophobia"))));
- }
-
- @Test
- public void testHandlesUniversalChecksForString() {
- assertThat(getConstSchema(new TextNode("A")), accepts(new TextNode("A")));
- assertThat(getConstSchema(new TextNode("A")), not(accepts(new TextNode("C"))));
- assertThat(getEnumSchema(new TextNode("A"), new TextNode("B")),
- accepts(new TextNode("A")));
- assertThat(getEnumSchema(new TextNode("A"), new TextNode("B")),
- accepts(new TextNode("B")));
- assertThat(getEnumSchema(new TextNode("A"), new TextNode("B")),
- not(accepts(new TextNode("C"))));
- }
- @Test
- public void testHandlesMultipleTestsForArray() {
- final ArrayNode array = new ArrayNode(JsonNodeFactory.instance);
- assertThat(getArraySchema(), not(accepts(array)));
- array.add("Test");
- assertThat(getArraySchema(), not(accepts(array)));
- array.add(0.5);
- assertThat(getArraySchema(), accepts(array));
- array.add(0.5);
- assertThat(getArraySchema(), not(accepts(array)));
- array.remove(2);
- array.add(true);
- array.add(false);
- assertThat(getArraySchema(), not(accepts(array)));
- }
-
- @Test
- public void testHandlesAdditionalMatcherWhenArrayItems() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("items", new ItemsTester(getNumberSchema(), getStringSchema()));
- tests.put("additionalItems", FixedTester.REJECT);
- Schema schema = new Schema(tests);
- final ArrayNode node = new ArrayNode(JsonNodeFactory.instance);
- node.add(0.5);
- node.add("https://google.com");
- assertThat(schema, accepts(node));
- node.add(true);
- assertThat(schema, not(accepts(node)));
- tests.put("additionalItems", FixedTester.ACCEPT);
- assertThat(new Schema(tests), accepts(node));
- tests.remove("additionalItems");
- assertThat(new Schema(tests), accepts(node));
- }
- @Test
- public void testHandlesAdditionalNotCalledIfFailsInItems() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("items", new ItemsTester(getNumberSchema(), getStringSchema()));
- tests.put("additionalItems", FixedTester.ACCEPT);
- Schema schema = new Schema(tests);
- final ArrayNode node = new ArrayNode(JsonNodeFactory.instance);
- node.add(0.5);
- node.add("https://a");
- node.add(true);
- assertThat(schema, not(accepts(node)));
- }
-
- @Test
- public void testHandlesUniversalChecksForArray() {
- final ArrayNode expected = new ArrayNode(JsonNodeFactory.instance);
- expected.add(true);
- Map<String, Tester> tests = new HashMap<>();
- tests.put("const", new EqualsTester(expected));
- Schema schema = new Schema(tests);
- final ArrayNode node = new ArrayNode(JsonNodeFactory.instance);
- assertThat(schema, not(accepts(node)));
- node.add(true);
- assertThat(schema, accepts(node));
- }
- @Test
- public void testHandlesMultipleTestsForObject() {
- final ObjectNode object = new ObjectNode(JsonNodeFactory.instance);
- assertThat(getObjectSchema(), not(accepts(object)));
- object.set("string", new TextNode("https://google.com"));
- assertThat(getObjectSchema(), not(accepts(object)));
- object.set("float", new DoubleNode(0.5));
- assertThat(getObjectSchema(), accepts(object));
- object.set("Caps", BooleanNode.TRUE);
- assertThat(getObjectSchema(), not(accepts(object)));
- object.remove("Caps");
- object.set("bool", BooleanNode.TRUE);
- assertThat(getObjectSchema(), accepts(object));
- object.set("null", NullNode.getInstance());
- assertThat(getObjectSchema(), not(accepts(object)));
- }
-
- @Test
- public void testHandlesAdditionalMatcherWhenObjectProps() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("properties", new PropertyTester(Arrays.asList(
- new PropertyTester.Pair("float"::equals, getNumberSchema()),
- new PropertyTester.Pair("string"::equals, getStringSchema()))));
- tests.put("additionalProperties", FixedTester.REJECT);
- Schema schema = new Schema(tests);
- final ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
- node.set("float", new DoubleNode(0.5));
- node.set("string", new TextNode("https://google.com"));
- assertThat(schema, accepts(node));
- node.set("boolean", BooleanNode.TRUE);
- assertThat(schema, not(accepts(node)));
- tests.put("additionalProperties", FixedTester.ACCEPT);
- assertThat(new Schema(tests), accepts(node));
- tests.remove("additionalProperties");
- assertThat(new Schema(tests), accepts(node));
- }
-
- @Test
- public void testAdditionalPropertiesRunsOnEachUnmatched() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("additionalProperties", new AllItemsTester(OBJECT,
- TypeTester.fromType("string")));
- Schema schema = new Schema(tests);
- final ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
- node.set("string", new TextNode("https://google.com"));
- assertThat(schema, accepts(node));
- node.set("float", new DoubleNode(0.5));
- assertThat(schema, not(accepts(node)));
- }
- @Test
- public void testHandlesAdditionalNotCalledIfFailsInProps() {
- Map<String, Tester> tests = new HashMap<>();
- tests.put("properties", new PropertyTester(Arrays.asList(
- new PropertyTester.Pair("float"::equals, getNumberSchema()),
- new PropertyTester.Pair("string"::equals, getStringSchema()))));
- tests.put("additionalProperties", FixedTester.ACCEPT);
- Schema schema = new Schema(tests);
- final ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
- node.set("float", new DoubleNode(0.5));
- node.set("string", new TextNode("https://a"));
- node.set("boolean", BooleanNode.TRUE);
- assertThat(schema, not(accepts(node)));
- }
-
- @Test
- public void testHandlesUniversalChecksForObject() {
- final ObjectNode expected = new ObjectNode(JsonNodeFactory.instance);
- expected.set("A", BooleanNode.TRUE);
- Map<String, Tester> tests = new HashMap<>();
- tests.put("const", new EqualsTester(expected));
- Schema schema = new Schema(tests);
- final ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
- assertThat(schema, not(accepts(node)));
- node.set("A", BooleanNode.TRUE);
- assertThat(schema, accepts(node));
- }}
|