/** * Copyright 2016 Hortonworks. * * Licensed 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 com.hortonworks.registries.schemaregistry.avro; import com.hortonworks.registries.schemaregistry.SchemaCompatibility; import com.hortonworks.registries.schemaregistry.SchemaMetadataInfo; import com.hortonworks.registries.schemaregistry.SchemaVersionInfo; import com.hortonworks.registries.schemaregistry.errors.SchemaNotFoundException; import com.hortonworks.registries.schemaregistry.DefaultSchemaRegistry; import com.hortonworks.registries.schemaregistry.errors.IncompatibleSchemaException; import com.hortonworks.registries.schemaregistry.errors.InvalidSchemaException; import com.hortonworks.registries.schemaregistry.SchemaMetadata; import com.hortonworks.registries.schemaregistry.SchemaVersionKey; import com.hortonworks.registries.schemaregistry.errors.UnsupportedSchemaTypeException; import com.hortonworks.registries.storage.StorageManager; import com.hortonworks.registries.storage.impl.memory.InMemoryStorageManager; import org.apache.avro.Schema; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Map; import java.util.UUID; /** * */ public class AvroSchemaRegistryTest { private static final String SCHEMA_GROUP = "test-group"; private static final String INVALID_SCHEMA_METADATA_KEY = "invalid-schema" + System.currentTimeMillis(); private DefaultSchemaRegistry schemaRegistry; @Rule public TestName TEST_NAME_RULE = new TestName(); @Before public void setup() throws IOException { schema1 = getSchema("/device.avsc"); schema2 = getSchema("/device-compat.avsc"); schemaName = "org.hwx.schemas.test-schema." + UUID.randomUUID(); StorageManager storageManager = new InMemoryStorageManager(); Collection<Map<String, Object>> schemaProvidersConfig = Collections.singleton(Collections.singletonMap("providerClass", AvroSchemaProvider.class.getName())); schemaRegistry = new DefaultSchemaRegistry(storageManager, null, schemaProvidersConfig); schemaRegistry.init(Collections.<String, Object>emptyMap()); } protected String schema1; protected String schema2; protected String schemaName; private String getSchema(String schemaFileName) throws IOException { InputStream avroSchemaStream = AvroSchemaRegistryTest.class.getResourceAsStream(schemaFileName); Schema.Parser parser = new Schema.Parser(); return parser.parse(avroSchemaStream).toString(); } @Test public void testSchemaMetadataOps() throws Exception { for (SchemaCompatibility schemaCompatibility : SchemaCompatibility.values()) { SchemaMetadata schemaMetadata = new SchemaMetadata.Builder("compatibility-"+schemaCompatibility) .type(AvroSchemaProvider.TYPE) .description("devices schema") .compatibility(schemaCompatibility) .schemaGroup(SCHEMA_GROUP).build(); Long schemaMetadataId = schemaRegistry.addSchemaMetadata(schemaMetadata); SchemaMetadata schemaMetadataReturned = schemaRegistry.getSchemaMetadata(schemaMetadataId).getSchemaMetadata(); Assert.assertEquals(schemaMetadata, schemaMetadataReturned); } } @Test public void testRegistrySchemaOps() throws Exception { SchemaCompatibility compatibility = SchemaCompatibility.BOTH; SchemaMetadata schemaMetadata = new SchemaMetadata.Builder(schemaName) .type(AvroSchemaProvider.TYPE) .description("devices schema") .compatibility(compatibility) .schemaGroup(SCHEMA_GROUP).build(); Long schemaMetadataId = schemaRegistry.addSchemaMetadata(schemaMetadata); SchemaMetadata schemaMetadataReturned = schemaRegistry.getSchemaMetadata(schemaMetadataId).getSchemaMetadata(); Assert.assertEquals(schemaMetadata, schemaMetadataReturned); Integer v1 = schemaRegistry.addSchemaVersion(schemaMetadata, schema1, "initial version of the schema"); Integer v2 = schemaRegistry.addSchemaVersion(schemaName, schema2, "second version of the the schema"); Assert.assertTrue(v2 == v1 + 1); Collection<SchemaVersionInfo> allSchemaVersions = schemaRegistry.findAllVersions(schemaName); Assert.assertTrue(allSchemaVersions.size() == 2); SchemaMetadataInfo schemaMetadataInfo = schemaRegistry.getSchemaMetadata(schemaName); Assert.assertEquals(schemaMetadata, schemaMetadataInfo.getSchemaMetadata()); Integer schemaVersion = schemaRegistry.getSchemaVersion(schemaName, schema1); Assert.assertEquals(v1, schemaVersion); SchemaVersionInfo schemaVersionInfo1 = schemaRegistry.getSchemaVersionInfo(new SchemaVersionKey(schemaName, v1)); Assert.assertEquals(schemaVersionInfo1.getSchemaText(), schema1); SchemaVersionInfo schemaVersionInfo2 = schemaRegistry.getSchemaVersionInfo(new SchemaVersionKey(schemaName, v2)); Assert.assertEquals(schemaVersionInfo2.getSchemaText(), schema2); // receive the same version as earlier without adding a new schema entry as it exists in the same schema group. Integer version = schemaRegistry.addSchemaVersion(schemaMetadata, schema1, "already added schema"); Assert.assertEquals(version, v1); } @Test public void testNonExistingSchemaMetadata() { SchemaMetadataInfo schemaMetadataInfo = schemaRegistry.getSchemaMetadata(INVALID_SCHEMA_METADATA_KEY); Assert.assertNull(schemaMetadataInfo); } @Test(expected = SchemaNotFoundException.class) public void testAddVersionToNonExistingSchema() throws SchemaNotFoundException, IncompatibleSchemaException, InvalidSchemaException, UnsupportedSchemaTypeException { schemaRegistry.addSchemaVersion(INVALID_SCHEMA_METADATA_KEY, "foo", "dummy"); } @Test(expected = InvalidSchemaException.class) public void testInvalidSchema() throws Exception { String schema = "--- random invalid schema ---" + new Date(); SchemaMetadata schemaMetadataInfo = createSchemaInfo(TEST_NAME_RULE.getMethodName(), SchemaCompatibility.BACKWARD); // registering a new schema Integer v1 = schemaRegistry.addSchemaVersion(schemaMetadataInfo, schema, "Initial version of the schema"); } @Test(expected = IncompatibleSchemaException.class) public void testIncompatibleSchemas() throws Exception { String schema = getSchema("/device.avsc"); String incompatSchema = getSchema("/device-incompat.avsc"); SchemaMetadata schemaMetadata = createSchemaInfo(TEST_NAME_RULE.getMethodName(), SchemaCompatibility.BACKWARD); // registering a new schema Integer v1 = schemaRegistry.addSchemaVersion(schemaMetadata, schema, "Initial version of the schema"); // adding a new version of the schema Integer v2 = schemaRegistry.addSchemaVersion(schemaMetadata, incompatSchema, "second version"); } private SchemaMetadata createSchemaInfo(String testName, SchemaCompatibility compatibility) { return new SchemaMetadata.Builder(testName + "-schema") .type(AvroSchemaProvider.TYPE) .schemaGroup(testName + "-group") .description("Schema for " + testName) .compatibility(compatibility) .build(); } }