| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * permissions and limitations under the License. |
| */ |
| |
| package org.apache.avro; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| public class TestSchemaValidation { |
| |
| SchemaValidatorBuilder builder = new SchemaValidatorBuilder(); |
| |
| Schema rec = SchemaBuilder.record("test.Rec").fields() |
| .name("a").type().intType().intDefault(1) |
| .name("b").type().longType().noDefault() |
| .endRecord(); |
| |
| Schema rec2 = SchemaBuilder.record("test.Rec").fields() |
| .name("a").type().intType().intDefault(1) |
| .name("b").type().longType().noDefault() |
| .name("c").type().intType().intDefault(0) |
| .endRecord(); |
| |
| Schema rec3 = SchemaBuilder.record("test.Rec").fields() |
| .name("b").type().longType().noDefault() |
| .name("c").type().intType().intDefault(0) |
| .endRecord(); |
| |
| Schema rec4 = SchemaBuilder.record("test.Rec").fields() |
| .name("b").type().longType().noDefault() |
| .name("c").type().intType().noDefault() |
| .endRecord(); |
| |
| Schema rec5 = SchemaBuilder.record("test.Rec").fields() |
| .name("a").type().stringType().stringDefault("") // different type from original |
| .name("b").type().longType().noDefault() |
| .name("c").type().intType().intDefault(0) |
| .endRecord(); |
| |
| @Test |
| public void testAllTypes() throws SchemaValidationException { |
| Schema s = SchemaBuilder.record("r").fields() |
| .requiredBoolean("boolF") |
| .requiredInt("intF") |
| .requiredLong("longF") |
| .requiredFloat("floatF") |
| .requiredDouble("doubleF") |
| .requiredString("stringF") |
| .requiredBytes("bytesF") |
| .name("fixedF1").type().fixed("F1").size(1).noDefault() |
| .name("enumF").type().enumeration("E1").symbols("S").noDefault() |
| .name("mapF").type().map().values().stringType().noDefault() |
| .name("arrayF").type().array().items().stringType().noDefault() |
| .name("recordF").type().record("inner").fields() |
| .name("f").type().intType().noDefault() |
| .endRecord().noDefault() |
| .optionalBoolean("boolO") |
| .endRecord(); |
| testValidatorPasses(builder.mutualReadStrategy().validateLatest(), s, s); |
| } |
| |
| @Test |
| public void testReadOnePrior() throws SchemaValidationException { |
| testValidatorPasses(builder.canReadStrategy().validateLatest(), rec3, rec); |
| testValidatorPasses(builder.canReadStrategy().validateLatest(), rec5, rec3); |
| testValidatorFails(builder.canReadStrategy().validateLatest(), rec4, rec); |
| } |
| |
| @Test |
| public void testReadAllPrior() throws SchemaValidationException { |
| testValidatorPasses(builder.canReadStrategy().validateAll(), rec3, rec, rec2); |
| testValidatorFails(builder.canReadStrategy().validateAll(), rec4, rec, rec2, rec3); |
| testValidatorFails(builder.canReadStrategy().validateAll(), rec5, rec, rec2, rec3); |
| } |
| |
| @Test |
| public void testOnePriorCanRead() throws SchemaValidationException { |
| testValidatorPasses(builder.canBeReadStrategy().validateLatest(), rec, rec3); |
| testValidatorFails(builder.canBeReadStrategy().validateLatest(), rec, rec4); |
| } |
| |
| @Test |
| public void testAllPriorCanRead() throws SchemaValidationException { |
| testValidatorPasses(builder.canBeReadStrategy().validateAll(), rec, rec3, rec2); |
| testValidatorFails(builder.canBeReadStrategy().validateAll(), rec, rec4, rec3, rec2); |
| } |
| |
| @Test |
| public void testOnePriorCompatible() throws SchemaValidationException { |
| testValidatorPasses(builder.mutualReadStrategy().validateLatest(), rec, rec3); |
| testValidatorFails(builder.mutualReadStrategy().validateLatest(), rec, rec4); |
| } |
| |
| @Test |
| public void testAllPriorCompatible() throws SchemaValidationException { |
| testValidatorPasses(builder.mutualReadStrategy().validateAll(), rec, rec3, rec2); |
| testValidatorFails(builder.mutualReadStrategy().validateAll(), rec, rec4, rec3, rec2); |
| } |
| |
| @Test(expected=AvroRuntimeException.class) |
| public void testInvalidBuild() { |
| builder.strategy(null).validateAll(); |
| } |
| |
| @Test |
| public void testUnionWithIncompatibleElements() throws SchemaValidationException { |
| Schema union1 = Schema.createUnion(Arrays.asList(rec)); |
| Schema union2 = Schema.createUnion(Arrays.asList(rec4)); |
| testValidatorFails(builder.canReadStrategy().validateAll(), |
| union2, union1); |
| } |
| |
| @Test |
| public void testUnionWithCompatibleElements() throws SchemaValidationException { |
| Schema union1 = Schema.createUnion(Arrays.asList(rec)); |
| Schema union2 = Schema.createUnion(Arrays.asList(rec3)); |
| testValidatorPasses(builder.canReadStrategy().validateAll(), |
| union2, union1); |
| } |
| |
| private void testValidatorPasses(SchemaValidator validator, |
| Schema schema, Schema... prev) throws SchemaValidationException { |
| ArrayList<Schema> prior = new ArrayList<Schema>(); |
| for(int i = prev.length - 1; i >= 0; i--) { |
| prior.add(prev[i]); |
| } |
| validator.validate(schema, prior); |
| } |
| |
| private void testValidatorFails(SchemaValidator validator, |
| Schema schemaFails, Schema... prev) throws SchemaValidationException { |
| ArrayList<Schema> prior = new ArrayList<Schema>(); |
| for(int i = prev.length - 1; i >= 0; i--) { |
| prior.add(prev[i]); |
| } |
| boolean threw = false; |
| try { |
| // should fail |
| validator.validate(schemaFails, prior); |
| } catch (SchemaValidationException sve) { |
| threw = true; |
| } |
| Assert.assertTrue(threw); |
| } |
| public static final org.apache.avro.Schema recursiveSchema = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"Node\",\"namespace\":\"avro\",\"fields\":[{\"name\":\"value\",\"type\":[\"null\",\"Node\"],\"default\":null}]}"); |
| |
| /** |
| * Unit test to verify that recursive schemas can be validated. |
| * See AVRO-2122. |
| */ |
| @Test |
| public void testRecursiveSchemaValidation() throws SchemaValidationException { |
| // before AVRO-2122, this would cause a StackOverflowError |
| final SchemaValidator backwardValidator = builder.canReadStrategy().validateLatest(); |
| backwardValidator.validate(recursiveSchema, Arrays.asList(recursiveSchema)); |
| } |
| } |