/**
* Copyright 2015 Confluent Inc.
*
* 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 io.confluent.kafka.schemaregistry.client;
import io.confluent.kafka.schemaregistry.client.rest.RestService;
import io.confluent.kafka.schemaregistry.client.rest.entities.SchemaString;
import org.apache.avro.Schema;
import org.junit.Test;
import static org.easymock.EasyMock.anyString;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class CachedSchemaRegistryClientTest {
@Test
public void testRegisterSchemaCache() throws Exception {
RestService restService = createMock(RestService.class);
CachedSchemaRegistryClient client = new CachedSchemaRegistryClient(restService, 20);
String schema = "{\"type\": \"record\", \"name\": \"Blah\", \"fields\": [{ \"name\": \"name\", \"type\": \"string\" }]}";
Schema avroSchema = new Schema.Parser().parse(schema);
String subject = "foo";
int id = 25;
// Expect one call to register schema
expect(restService.registerSchema(anyString(), eq(subject)))
.andReturn(id);
replay(restService);
assertEquals(id, client.register(subject, avroSchema));
assertEquals(id, client.register(subject, avroSchema)); // hit the cache
verify(restService);
}
@Test
public void testRegisterOverCapacity() throws Exception {
RestService restService = createMock(RestService.class);
CachedSchemaRegistryClient client = new CachedSchemaRegistryClient(restService, 1); // capacity is just one
String schema1 = "{\"type\": \"record\", \"name\": \"Blah\", \"fields\": [{ \"name\": \"name\", \"type\": \"string\" }]}";
Schema avroSchema1 = new Schema.Parser().parse(schema1);
String schema2 = "{\"type\": \"record\", \"name\": \"Blah\", \"fields\": [" +
"{ \"name\": \"name\", \"type\": \"string\" }," +
"{ \"name\": \"blah\", \"type\": \"string\" }" +
"]}";
Schema avroSchema2 = new Schema.Parser().parse(schema2);
String subject = "foo";
int id = 25;
// Expect one call to register schema (the second one will fail)
expect(restService.registerSchema(anyString(), eq(subject)))
.andReturn(id);
replay(restService);
assertEquals(id, client.register(subject, avroSchema1));
try {
// This call should exceed the identityMapCapacity
assertEquals(id, client.register(subject, avroSchema2));
fail();
} catch (IllegalStateException e) {
}
verify(restService);
}
@Test
public void testIdCache() throws Exception {
RestService restService = createMock(RestService.class);
CachedSchemaRegistryClient client = new CachedSchemaRegistryClient(restService, 20);
String schema = "{\"type\": \"record\", \"name\": \"Blah\", \"fields\": [{ \"name\": \"name\", \"type\": \"string\" }]}";
Schema avroSchema = new Schema.Parser().parse(schema);
String subject = "foo";
int id = 25;
expect(restService.registerSchema(anyString(), eq(subject)))
.andReturn(id);
// Expect only one call to getId (the rest should hit the cache)
expect(restService.getId(id))
.andReturn(new SchemaString(schema));
replay(restService);
assertEquals(id, client.register(subject, avroSchema));
assertEquals(avroSchema, client.getBySubjectAndId(subject, id));
assertEquals(avroSchema, client.getBySubjectAndId(subject, id)); // hit the cache
verify(restService);
}
@Test
public void testVersionCache() throws Exception {
RestService restService = createMock(RestService.class);
CachedSchemaRegistryClient client = new CachedSchemaRegistryClient(restService, 20);
String schema = "{\"type\": \"record\", \"name\": \"Blah\", \"fields\": [{ \"name\": \"name\", \"type\": \"string\" }]}";
Schema avroSchema = new Schema.Parser().parse(schema);
String subject = "foo";
int id = 25;
int version = 7;
expect(restService.registerSchema(anyString(), eq(subject)))
.andReturn(id);
// Expect only one call to lookup the subject (the rest should hit the cache)
expect(restService.lookUpSubjectVersion(anyString(), eq(subject), eq(true)))
.andReturn(new io.confluent.kafka.schemaregistry.client.rest.entities.Schema(subject, version, id, schema));
replay(restService);
assertEquals(id, client.register(subject, avroSchema));
assertEquals(version, client.getVersion(subject, avroSchema));
assertEquals(version, client.getVersion(subject, avroSchema)); // hit the cache
verify(restService);
}
@Test
public void testIdenticalSchemas() throws Exception {
RestService restService = createMock(RestService.class);
CachedSchemaRegistryClient client = new CachedSchemaRegistryClient(restService, 20);
String schema = "{\"type\": \"record\", \"name\": \"Blah\", \"fields\": [{ \"name\": \"name\", \"type\": \"string\" }]}";
Schema avroSchema = new Schema.Parser().parse(schema);
SchemaString schemaStringOne = new SchemaString(schema);
SchemaString schemaStringTwo = new SchemaString(schema);
String subjectOne = "subjectOne";
String subjectTwo = "subjectTwo";
int id = 25;
expect(restService.registerSchema(anyString(), eq(subjectOne)))
.andReturn(id);
expect(restService.registerSchema(anyString(), eq(subjectTwo)))
.andReturn(id);
expect(restService.getId(eq(id)))
.andReturn(schemaStringOne);
expect(restService.getId(eq(id)))
.andReturn(schemaStringTwo);
replay(restService);
// Make sure they still get the same ID
assertEquals(id, client.register(subjectOne, avroSchema));
assertEquals(id, client.register(subjectTwo, avroSchema));
// Neither of these two schemas should be cached yet
assertEquals(avroSchema, client.getBySubjectAndId(subjectOne, id));
assertEquals(avroSchema, client.getBySubjectAndId(subjectTwo, id));
// These two should be cached now
assertEquals(avroSchema, client.getBySubjectAndId(subjectOne, id));
assertEquals(avroSchema, client.getBySubjectAndId(subjectTwo, id));
verify(restService);
}
}