/**
* 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.schemarepo;
import java.util.Iterator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* An abstract JUnit test for thoroughly testing a Repository implementation
*/
public abstract class AbstractTestRepository<R extends Repository> {
private static final String SUB = "sub";
private static final String CONF = "conf";
private static final String NOCONF = "noconf";
private static final String VALIDATING = "validating";
private static final String FOO = "foo";
private static final String BAR = "bar";
private static final String BAZ = "baz";
protected R repo;
protected abstract R createRepository() throws Exception;
@Before
public void setUpRepository() throws Exception {
repo = createRepository();
}
@After
public void tearDownRepository() throws Exception {
repo = null;
}
protected final R getRepo() {
return repo;
}
@Test
public void testRepository() throws SchemaValidationException {
// lookup a subject that does not exist, when none do
Subject none = repo.lookup(SUB);
Assert.assertNull("non-existent subject lookup should return null", none);
// ensure that when there are no subjects, an empty iterable is produced
Iterable<Subject> subjects = repo.subjects();
Assert.assertNotNull("subjects must not be null");
Assert.assertFalse("subjects must be empty", subjects.iterator().hasNext());
// register a subject
Subject sub = repo.register(SUB, null);
Assert.assertNotNull("failed to register subject: " + SUB, sub);
// a duplicate register is idempotent; the result is the same
Subject sub2 = repo.register(SUB, null);
Assert.assertNotNull("failed to re-register subject: " + SUB, sub2);
Assert.assertEquals(
"registering a subject twice did not produce the same result",
sub.getName(), sub2.getName());
// lookup subject that was just registered
Subject sub3 = repo.lookup(SUB);
Assert.assertNotNull("subject lookup failed", sub3);
Assert.assertEquals("subject lookup failed", sub.getName(), sub3.getName());
// lookup a subject that does not exist, this time when some do
Subject none2 = repo.lookup("nothing");
Assert.assertNull("non-existent subject lookup should return null", none2);
// go through all subjects
boolean hasSub = false;
for (Subject s : repo.subjects()) {
if (sub.getName().equals(s.getName())) {
hasSub = true;
break;
}
}
Assert.assertTrue("subjects() did not contain registered subject: " + sub,
hasSub);
// ensure that latest is null when a subject is first created
SchemaEntry noLatest = sub.latest();
Assert.assertNull("latest must be null if it does not exist", noLatest);
// ensure that registerIfLatest does not register if provided a latest
// value when latest is null
SchemaEntry didNotRegister =
sub.registerIfLatest(FOO, new SchemaEntry("not", "there"));
Assert.assertNull(
"registerIfLatest must return null if there are no schemas in the " +
"subject and the passed in latest is not null. Found: " +
didNotRegister, didNotRegister);
// ensure registerIflatest works when latest is null
SchemaEntry foo = sub.registerIfLatest(FOO, null);
validateSchemaEntry(FOO, foo);
// ensure that register is idempotent
SchemaEntry foo2 = sub.register(FOO);
Assert.assertEquals("duplicate schema registration must be idempotent",
foo, foo2);
validateSchemaEntry(FOO, foo2);
// ensure registerIflatest works when latest is not null
SchemaEntry bar = sub.registerIfLatest(BAR, foo2);
validateSchemaEntry(BAR, bar);
// ensure registerIfLatest does not register if latest does not match
SchemaEntry none3 = sub.registerIfLatest("none", foo);
Assert.assertNull(
"registerIfLatest must return null if latest does not match", none3);
// ensure registerIfLatest does not register when provided null does not match
SchemaEntry none4 = sub.registerIfLatest("none", null);
Assert.assertNull(
"registerIfLatest must return null if there is a latest schema in"
+ " the subject and the passed in value is null", none4);
// ensure register can add new schemas
SchemaEntry baz = sub.register(BAZ);
validateSchemaEntry(BAZ, baz);
// test lookup
Subject subject = repo.lookup(SUB);
Assert.assertNotNull("lookup of previously registered subject failed",
subject);
// test latest
Assert.assertEquals("latest schema must match last registered", baz,
subject.latest());
boolean foundfoo = false, foundbar = false;
for (SchemaEntry s : sub3.allEntries()) {
if (s.equals(foo)) {
foundfoo = true;
}
if (s.equals(bar)) {
foundbar = true;
}
}
Assert.assertTrue("AllEntries did not contain schema: " + FOO, foundfoo);
Assert.assertTrue("AllEntries did not contain schema: " + BAR, foundbar);
//ensure order of allEntries is correct
Iterator<SchemaEntry> allEntries = sub3.allEntries().iterator();
// latest must match first one:
Assert.assertEquals("Latest must be first returned from allEntries()",
sub3.latest(), allEntries.next());
Assert.assertEquals("second-latest must be BAR", bar, allEntries.next());
Assert.assertEquals("third must be FOO", foo, allEntries.next());
// test lookupBySchema
SchemaEntry resultfoo = subject.lookupBySchema(foo.getSchema());
Assert.assertEquals("lookup by Schema did not return same result", foo,
resultfoo);
SchemaEntry notThere = subject.lookupBySchema("notThere");
Assert.assertNull("non existent schema should return null", notThere);
// test lookupById
SchemaEntry resultfooid = subject.lookupById(foo.getId());
Assert.assertEquals("lookup by ID did not return same result", foo,
resultfooid);
SchemaEntry notTherById = subject.lookupById("notThere");
Assert.assertNull("non existent schema should return null", notTherById);
// test integralKeys()
if(subject.integralKeys()) {
Integer.parseInt(resultfoo.getId());
}
}
@Test
public void testAllEntriesMultiLineSchema() throws Exception {
String endOfLine = System.getProperty("line.separator");
String multiLineSchema1 = "first line" + endOfLine + "second line";
String multiLineSchema2 = "first line" + endOfLine + "second line" + endOfLine;
repo.register("sub1", null).register(multiLineSchema1);
repo.register("sub1", null).register(multiLineSchema2);
Subject s1 = repo.lookup("sub1");
Assert.assertNotNull(s1);
Iterable<SchemaEntry> allEntries = s1.allEntries();
boolean foundSub1 = false, foundSub2 = false;
for (SchemaEntry entry: allEntries) {
if (entry.getSchema().equals(multiLineSchema1)) {
foundSub1 = true;
} else if (entry.getSchema().equals(multiLineSchema2)) {
foundSub2 = true;
}
}
Assert.assertTrue("Check that allEntries() returns proper multi-line schemas",
foundSub1 && foundSub2);
}
@Test
public void testSubjectConfigs() {
String testKey = "test.key";
String testVal = "test.val";
String testVal2 = "test.val2";
SubjectConfig conf = new SubjectConfig.Builder().set(testKey, testVal).build();
SubjectConfig conf2 = new SubjectConfig.Builder().set(testKey, testVal2).build();
// lookup a subject that does not exist, when none do
Subject none = repo.lookup(CONF);
Assert.assertNull("non-existent subject lookup should return null", none);
// register a subject
Subject sub = repo.register(CONF, conf);
Assert.assertNotNull("failed to register subject: " + CONF, sub);
// a duplicate register is idempotent; the result is the same
Subject sub2 = repo.register(CONF, conf2);
Assert.assertNotNull("failed to re-register subject: " + SUB, sub2);
validateSubject(sub, sub2);
// lookup subject that was just registered
Subject sub3 = repo.lookup(CONF);
validateSubject(sub, sub3);
// lookup something that is not there
Subject sub4 = repo.lookup(NOCONF);
Assert.assertNull("subject should not exist", sub4);
}
@Test
public void testValidation() {
SubjectConfig conf = new SubjectConfig.Builder().addValidator(ValidatorFactory.REJECT_VALIDATOR).build();
// lookup a subject that does not exist, when none do
Subject none = repo.lookup(VALIDATING);
Assert.assertNull("non-existent subject lookup should return null", none);
// register a subject that should reject all schemas
Subject sub = repo.register(VALIDATING, conf);
Assert.assertNotNull("failed to register subject: " + VALIDATING, sub);
boolean threw = false;
try {
sub.register("stuff");
} catch (SchemaValidationException e) {
threw = true;
}
Assert.assertTrue("must throw a SchemaValidationException", threw);
}
private void validateSubject(Subject sub, Subject sub3) {
Assert.assertEquals(
"subject names do not match",
sub.getName(), sub3.getName());
Assert.assertEquals(
"subject configurations do not match",
sub.getConfig(), sub3.getConfig());
}
private void validateSchemaEntry(String expectedSchema, SchemaEntry foo) {
Assert.assertNotNull("Failed to create SchemaEntry with schema: "
+ expectedSchema, foo);
Assert.assertEquals("SchemaEntry does not have expected schema value",
expectedSchema, foo.getSchema());
Assert.assertNotNull("SchemaEntry does not have a valid id", foo.getId());
Assert.assertFalse("SchemaEntry has an empty id", foo.getId().isEmpty());
}
}