浏览代码

Add missing cases to factory.
Add test cases for all meaningfully different things.

Sam Jaffe 6 年之前
父节点
当前提交
198002373c

+ 20 - 1
src/main/lombok/org/leumasjaffe/json/schema/factory/SchemaV6Factory.java

@@ -43,6 +43,25 @@ class SchemaV6Factory extends SchemaFactory {
 		case "exclusiveMaximum": return new NumberTester(d -> d < value.asDouble());
 		case "minimum": return new NumberTester(d -> d >= value.asDouble());
 		case "exclusiveMinimum": return new NumberTester(d -> d > value.asDouble());
+		case "maxLength": return new SizeTester(JsonNodeType.STRING, i -> i < value.asInt());
+		case "minLength": return new SizeTester(JsonNodeType.STRING, i -> i >= value.asInt(0));
+		case "pattern": return j -> j.isTextual() && j.asText().matches(value.asText());
+		case "additionalItems": return j -> JsonHelper.toArray(j).stream().allMatch(create(value)::accepts);
+		case "items": 
+			if (value.isArray()) {
+				return j -> {
+					List<JsonNode> data = JsonHelper.toArray(j);
+					for (int i = 0; i < Math.min(value.size(), data.size()); ++i) {
+						if (!create(value.get(i)).accepts(data.get(i))) {
+							return false;
+						}
+					}
+					return true;
+				};
+			}
+			else {
+				return j -> JsonHelper.toArray(j).stream().allMatch(create(value)::accepts);
+			}
 		case "maxItems": return new SizeTester(JsonNodeType.ARRAY, i -> i < value.asInt());
 		case "minItems": return new SizeTester(JsonNodeType.ARRAY, i -> i >= value.asInt(0));
 		case "uniqueItems": return value.asBoolean() ? UniqueItemTester.INSTANCE : Tester.ACCEPT;
@@ -50,7 +69,7 @@ class SchemaV6Factory extends SchemaFactory {
 		case "maxProperties": return new SizeTester(JsonNodeType.OBJECT, i -> i < value.asInt());
 		case "minProperties": return new SizeTester(JsonNodeType.OBJECT, i -> i >= value.asInt(0));
 		case "required": return json -> JsonHelper.toArray(value, JsonNode::asText).stream().allMatch(json::has);
-		case "additionalProperties": return create(value);
+		case "additionalProperties": return j -> JsonHelper.toArray(j).stream().allMatch(create(value)::accepts);
 		// case "definitions": ; // TODO Implement definitions creation
 		case "properties": {
 			final List<PropertyTester.Pair> list = new ArrayList<>();

+ 5 - 1
src/main/lombok/org/leumasjaffe/json/schema/tester/SizeTester.java

@@ -19,7 +19,11 @@ public class SizeTester implements Tester {
 
 	@Override
 	public boolean accepts(JsonNode node) {
-		return node.getNodeType() == type && pred.test(node.size());
+		return node.getNodeType() == type && pred.test(getSize(node));
+	}
+
+	private int getSize(JsonNode node) {
+		return node.isTextual() ? node.asText().length() : node.size();
 	}
 
 }

+ 114 - 0
src/test/java/org/leumasjaffe/json/schema/factory/SchemaV6FactoryTest.java

@@ -134,6 +134,65 @@ public class SchemaV6FactoryTest {
 		assertFalse(test.accepts(new DoubleNode(2.5)));
 	}
 	
+	@Test
+	public void testMaxLengthSchema() {
+		Tester test = fromSingleElement("{ \"maxLength\": 2 }");
+		assertFalse(test.accepts(NullNode.getInstance()));
+		assertFalse(test.accepts(new DoubleNode(1.5)));
+		assertTrue(test.accepts(new TextNode("")));
+		assertFalse(test.accepts(new TextNode("  ")));
+	}
+	
+	@Test
+	public void testMinLengthSchema() {
+		Tester test = fromSingleElement("{ \"minLength\": 2 }");
+		assertFalse(test.accepts(NullNode.getInstance()));
+		assertFalse(test.accepts(new DoubleNode(1.5)));
+		assertFalse(test.accepts(new TextNode("")));
+		assertTrue(test.accepts(new TextNode("  ")));
+	}
+	
+	@Test
+	public void testPatternSchema() {
+		Tester test = fromSingleElement("{ \"pattern\": \"^\\\\s.*\" }");
+		assertFalse(test.accepts(NullNode.getInstance()));
+		assertFalse(test.accepts(new TextNode("S ")));
+		assertTrue(test.accepts(new TextNode(" S")));
+	}
+	
+	@Test
+	public void testAdditionalItemsSchema() {
+		Tester test = fromSingleElement("{ \"additionalItems\": false }");
+		final ArrayNode node = new ArrayNode(JsonNodeFactory.instance);
+		assertTrue(test.accepts(node));
+		node.add(false);
+		assertFalse(test.accepts(node));
+		node.add(false);
+		assertFalse(test.accepts(node));
+	}
+	
+	@Test
+	public void testItemsSchema() {
+		Tester test = fromSingleElement("{ \"items\": [ true, false ] }");
+		final ArrayNode node = new ArrayNode(JsonNodeFactory.instance);
+		assertTrue(test.accepts(node));
+		node.add(false);
+		assertTrue(test.accepts(node));
+		node.add(false);
+		assertFalse(test.accepts(node));
+	}
+
+	@Test
+	public void testItemsSchemaSingle() {
+		Tester test = fromSingleElement("{ \"items\": true }");
+		final ArrayNode node = new ArrayNode(JsonNodeFactory.instance);
+		assertTrue(test.accepts(node));
+		node.add(false);
+		assertTrue(test.accepts(node));
+		node.add(false);
+		assertTrue(test.accepts(node));
+	}
+	
 	@Test
 	public void testMaxItemsSchema() {
 		Tester test = fromSingleElement("{ \"maxItems\": 2 }");
@@ -171,6 +230,17 @@ public class SchemaV6FactoryTest {
 		assertTrue(any.accepts(node));
 	}
 	
+	@Test
+	public void testContainsSchema() {
+		Tester test = fromSingleElement("{ \"contains\": { } }");
+		final ArrayNode node = new ArrayNode(JsonNodeFactory.instance);
+		
+		assertFalse(test.accepts(node));
+		
+		node.add(new ObjectNode(JsonNodeFactory.instance));
+		assertTrue(test.accepts(node));
+	}
+	
 	@Test
 	public void testMaxPropertiesSchema() {
 		Tester test = fromSingleElement("{ \"maxProperties\": 2 }");
@@ -195,6 +265,50 @@ public class SchemaV6FactoryTest {
 		assertTrue(test.accepts(node));
 	}
 	
+	@Test
+	public void testRequiredSchema() {
+		Tester test = fromSingleElement("{ \"required\": [ \"A\", \"B\" ] }");
+		final ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
+		node.set("A", BooleanNode.FALSE);
+		node.set("C", BooleanNode.FALSE);
+		assertFalse(test.accepts(node));
+		node.set("B", BooleanNode.FALSE);
+		assertTrue(test.accepts(node));
+	}
+
+	@Test
+	public void testAdditionalPropertiesSchema() {
+		Tester test = fromSingleElement("{ \"additionalProperties\": false }");
+		assertTrue(test.accepts(readTree("{ }")));
+		assertFalse(test.accepts(readTree("{ \"A\": {} }")));
+		assertFalse(test.accepts(readTree("{ \"B\": {} }")));
+	}
+	
+	@Test
+	public void testPropertiesSchema() {
+		Tester test = fromSingleElement("{ \"properties\": { \"A\": true, \"B\": false } }");
+		assertTrue(test.accepts(readTree("{ }")));
+		assertTrue(test.accepts(readTree("{ \"A\": {} }")));
+		assertFalse(test.accepts(readTree("{ \"B\": {} }")));
+		assertFalse(test.accepts(readTree("{ \"A\": {}, \"B\": {} }")));
+	}
+	
+	@Test
+	public void testPatternPropertiesSchema() {
+		Tester test = fromSingleElement("{ \"patternProperties\": { \"A\": true, \"A.\": false } }");
+		assertTrue(test.accepts(readTree("{ }")));
+		assertTrue(test.accepts(readTree("{ \"A\": {} }")));
+		assertFalse(test.accepts(readTree("{ \"A.\": {} }")));
+		assertFalse(test.accepts(readTree("{ \"A_\": {} }")));
+	}
+	
+	@Test
+	public void testPropertyNamesSchema() {
+		Tester test = fromSingleElement("{ \"propertyNames\": false }");
+		assertTrue(test.accepts(readTree("{ }")));
+		assertFalse(test.accepts(readTree("{ \"A\": {} }")));
+	}
+	
 	@Test
 	public void testConstSchema() {
 		Tester test = fromSingleElement("{ \"const\": { \"nice\": \"meme\" } }");

+ 24 - 1
src/test/java/org/leumasjaffe/json/schema/tester/SizeTesterTest.java

@@ -6,6 +6,7 @@ import java.util.function.IntPredicate;
 
 import static com.fasterxml.jackson.databind.node.JsonNodeType.ARRAY;
 import static com.fasterxml.jackson.databind.node.JsonNodeType.OBJECT;
+import static com.fasterxml.jackson.databind.node.JsonNodeType.STRING;
 
 import org.junit.Test;
 import org.leumasjaffe.json.schema.tester.SizeTester;
@@ -15,6 +16,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
 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;
 
 public class SizeTesterTest {
 	static IntPredicate NON_ZERO = i -> i > 0;
@@ -32,6 +34,13 @@ public class SizeTesterTest {
 		final JsonNode node = new ArrayNode(JsonNodeFactory.instance);
 		assertFalse(notEmptyArray.accepts(node));
 	}
+	
+	@Test
+	public void textMatcherRejectsArray() {
+		final SizeTester notEmptyArray = new SizeTester(STRING, NON_ZERO);
+		final JsonNode node = new ArrayNode(JsonNodeFactory.instance);
+		assertFalse(notEmptyArray.accepts(node));
+	}
 
 	@Test
 	public void arrayMatcherRejectsTooSmall() {
@@ -47,6 +56,12 @@ public class SizeTesterTest {
 		assertFalse(notEmptyArray.accepts(node));
 	}
 
+	@Test
+	public void testMatcherRejectsTooSmall() {
+		final SizeTester notEmptyArray = new SizeTester(STRING, NON_ZERO);
+		assertFalse(notEmptyArray.accepts(new TextNode("")));
+	}
+
 	@Test
 	public void arrayMatcherAcceptsGoodSize() {
 		final SizeTester notEmptyArray = new SizeTester(ARRAY, NON_ZERO);
@@ -61,4 +76,12 @@ public class SizeTesterTest {
 		final ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
 		node.set("_", NullNode.getInstance());
 		assertTrue(notEmptyArray.accepts(node));
-	}}
+	}
+
+	@Test
+	public void testMatcherAcceptsGoodSize() {
+		final SizeTester notEmptyArray = new SizeTester(STRING, NON_ZERO);
+		assertTrue(notEmptyArray.accepts(new TextNode("_")));
+	}
+	
+}