/*
* Copyright Terracotta, 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 org.ehcache.integration;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.impl.config.copy.DefaultCopierConfiguration;
import org.ehcache.impl.config.serializer.DefaultSerializerConfiguration;
import org.ehcache.spi.serialization.SerializerException;
import org.ehcache.impl.copy.ReadWriteCopier;
import org.ehcache.impl.copy.SerializingCopier;
import org.ehcache.spi.copy.Copier;
import org.ehcache.spi.serialization.Serializer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder;
import static org.ehcache.config.builders.ResourcePoolsBuilder.heap;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
/**
* Created by alsu on 01/09/15.
*/
public class CacheCopierTest {
CacheManager cacheManager;
CacheConfigurationBuilder<Long, Person> baseConfig = newCacheConfigurationBuilder(Long.class, Person.class, heap(5));
@Before
public void setUp() throws Exception {
cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.build(true);
}
@After
public void tearDown() throws Exception {
cacheManager.close();
}
@Test
public void testCopyValueOnRead() throws Exception {
CacheConfiguration<Long, Person> cacheConfiguration = baseConfig
.add(new DefaultCopierConfiguration<Person>(PersonOnReadCopier.class, DefaultCopierConfiguration.Type.VALUE))
.build();
Cache<Long, Person> cache = cacheManager.createCache("cache", cacheConfiguration);
Person original = new Person("Bar", 24);
cache.put(1l, original);
Person retrieved = cache.get(1l);
assertNotSame(original, retrieved);
assertThat(retrieved.name, equalTo("Bar"));
assertThat(retrieved.age, equalTo(24));
original.age = 56;
retrieved = cache.get(1l);
assertThat(retrieved.age, equalTo(56));
assertNotSame(cache.get(1l), cache.get(1l));
}
@Test
public void testCopyValueOnWrite() throws Exception {
CacheConfiguration<Long, Person> cacheConfiguration = baseConfig
.add(new DefaultCopierConfiguration<Person>(PersonOnWriteCopier.class, DefaultCopierConfiguration.Type.VALUE))
.build();
Cache<Long, Person> cache = cacheManager.createCache("cache", cacheConfiguration);
Person original = new Person("Bar", 24);
cache.put(1l, original);
Person retrieved = cache.get(1l);
assertNotSame(original, retrieved);
assertThat(retrieved.name, equalTo("Bar"));
assertThat(retrieved.age, equalTo(24));
original.age = 56;
retrieved = cache.get(1l);
assertThat(retrieved.age, equalTo(24));
assertSame(cache.get(1l), cache.get(1l));
}
@Test
public void testIdentityCopier() throws Exception {
CacheConfiguration<Long, Person> cacheConfiguration = baseConfig.build();
Cache<Long, Person> cache = cacheManager.createCache("cache", cacheConfiguration);
Person original = new Person("Bar", 24);
cache.put(1l, original);
Person retrieved = cache.get(1l);
assertSame(original, retrieved);
original.age = 25;
retrieved = cache.get(1l);
assertSame(original, retrieved);
assertSame(cache.get(1l), cache.get(1l));
}
@Test
public void testSerializingCopier() throws Exception {
CacheConfiguration<Long, Person> cacheConfiguration = baseConfig
.add(new DefaultCopierConfiguration<Person>(SerializingCopier.<Person>asCopierClass(), DefaultCopierConfiguration.Type.VALUE))
.add(new DefaultSerializerConfiguration<Person>(PersonSerializer.class, DefaultSerializerConfiguration.Type.VALUE))
.build();
Cache<Long, Person> cache = cacheManager.createCache("cache", cacheConfiguration);
Person original = new Person("Bar", 24);
cache.put(1l, original);
Person retrieved = cache.get(1l);
assertNotSame(original, retrieved);
assertThat(retrieved.name, equalTo("Bar"));
assertThat(retrieved.age, equalTo(24));
original.age = 56;
retrieved = cache.get(1l);
assertThat(retrieved.age, equalTo(24));
assertNotSame(cache.get(1l), cache.get(1l));
}
@Test
public void testReadWriteCopier() throws Exception {
CacheConfiguration<Long, Person> cacheConfiguration = baseConfig
.add(new DefaultCopierConfiguration<Person>(PersonCopier.class, DefaultCopierConfiguration.Type.VALUE))
.build();
Cache<Long, Person> cache = cacheManager.createCache("cache", cacheConfiguration);
Person original = new Person("Bar", 24);
cache.put(1l, original);
Person retrieved = cache.get(1l);
assertNotSame(original, retrieved);
assertThat(retrieved.name, equalTo("Bar"));
assertThat(retrieved.age, equalTo(24));
original.age = 56;
retrieved = cache.get(1l);
assertThat(retrieved.age, equalTo(24));
assertNotSame(cache.get(1l), cache.get(1l));
}
private static class Description {
int id;
String alias;
Description(Description other) {
this.id = other.id;
this.alias = other.alias;
}
Description(int id, String alias) {
this.id = id;
this.alias = alias;
}
@Override
public boolean equals(final Object other) {
if(this == other) return true;
if(other == null || this.getClass() != other.getClass()) return false;
Description that = (Description)other;
if(id != that.id) return false;
if ((alias == null) ? (alias != null) : !alias.equals(that.alias)) return false;
return true;
}
@Override
public int hashCode() {
int result = 1;
result = 31 * result + id;
result = 31 * result + (alias == null ? 0 : alias.hashCode());
return result;
}
}
private static class Person implements Serializable {
String name;
int age;
Person(Person other) {
this.name = other.name;
this.age = other.age;
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(final Object other) {
if(this == other) return true;
if(other == null || this.getClass() != other.getClass()) return false;
Person that = (Person)other;
if(age != that.age) return false;
if((name == null) ? (that.name != null) : !name.equals(that.name)) return false;
return true;
}
@Override
public int hashCode() {
int result = 1;
result = 31 * result + age;
result = 31 * result + (name == null ? 0 : name.hashCode());
return result;
}
@Override
public String toString() {
return "Person[name: " + (name != null ? name : "") + ", age: " + age + "]";
}
}
public static class DescriptionCopier extends ReadWriteCopier<Description> {
@Override
public Description copy(final Description obj) {
return new Description(obj);
}
}
public static class PersonOnReadCopier implements Copier<Person> {
@Override
public Person copyForRead(final Person obj) {
return new Person(obj);
}
@Override
public Person copyForWrite(final Person obj) {
return obj;
}
}
public static class PersonOnWriteCopier implements Copier<Person> {
@Override
public Person copyForRead(final Person obj) {
return obj;
}
@Override
public Person copyForWrite(final Person obj) {
return new Person(obj);
}
}
public static class PersonCopier extends ReadWriteCopier<Person> {
@Override
public Person copy(final Person obj) {
return new Person(obj);
}
}
public static class PersonSerializer implements Serializer<Person> {
private static final Charset CHARSET = Charset.forName("US-ASCII");
public PersonSerializer(ClassLoader loader) {
}
@Override
public ByteBuffer serialize(final Person object) throws SerializerException {
ByteBuffer buffer = ByteBuffer.allocate(object.name.length() + 4);
buffer.putInt(object.age);
buffer.put(object.name.getBytes(CHARSET)).flip();
return buffer;
}
@Override
public Person read(final ByteBuffer binary) throws ClassNotFoundException, SerializerException {
int age = binary.getInt();
byte[] bytes = new byte[binary.remaining()];
binary.get(bytes);
String name = new String(bytes, CHARSET);
return new Person(name, age);
}
@Override
public boolean equals(final Person object, final ByteBuffer binary) throws ClassNotFoundException, SerializerException {
return object.equals(read(binary));
}
}
}