/*
* 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.impl.internal.store.heap.holders;
import org.ehcache.core.spi.time.TimeSource;
import org.ehcache.core.spi.store.Store.ValueHolder;
import org.ehcache.impl.serialization.JavaSerializer;
import org.ehcache.spi.serialization.Serializer;
import org.junit.Test;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.concurrent.Exchanger;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
* @author vfunshteyn
*
*/
public class SerializedOnHeapValueHolderTest {
@Test
public void testValue() {
String o = "foo";
ValueHolder<?> vh1 = newValueHolder(o);
ValueHolder<?> vh2 = newValueHolder(o);
assertFalse(vh1.value() == vh2.value());
assertEquals(vh1.value(), vh2.value());
assertNotSame(vh1.value(), vh1.value());
}
@Test
public void testHashCode() {
ValueHolder<Integer> vh1 = newValueHolder(10);
ValueHolder<Integer> vh2 = newValueHolder(10);
// make sure reading the value multiple times doesn't change the hashcode
vh1.value();
vh1.value();
vh2.value();
vh2.value();
assertThat(vh1.hashCode(), is(vh2.hashCode()));
}
@Test
public void testEquals() {
ValueHolder<Integer> vh = newValueHolder(10);
assertThat(newValueHolder(10), equalTo(vh));
}
@Test
public void testNotEquals() {
ValueHolder<Integer> vh = newValueHolder(10);
assertThat(newValueHolder(101), not(equalTo(vh)));
}
@Test(expected=NullPointerException.class)
public void testNullValue() {
newValueHolder(null);
}
@Test
public void testSerializerGetsDifferentByteBufferOnRead() {
final Exchanger<ByteBuffer> exchanger = new Exchanger<ByteBuffer>();
final ReadExchangeSerializer serializer = new ReadExchangeSerializer(exchanger);
final SerializedOnHeapValueHolder<String> valueHolder = new SerializedOnHeapValueHolder<String>("test it!", System
.currentTimeMillis(), false, serializer);
new Thread(new Runnable() {
@Override
public void run() {
valueHolder.value();
}
}).start();
valueHolder.value();
}
private static class ReadExchangeSerializer implements Serializer<String> {
private final Exchanger<ByteBuffer> exchanger;
private final Serializer<String> delegate = new JavaSerializer<String>(SerializedOnHeapValueHolderTest.class.getClassLoader());
private ReadExchangeSerializer(Exchanger<ByteBuffer> exchanger) {
this.exchanger = exchanger;
}
@Override
public ByteBuffer serialize(String object) {
return delegate.serialize(object);
}
@Override
public String read(ByteBuffer binary) throws ClassNotFoundException {
ByteBuffer received = binary;
ByteBuffer exchanged = null;
try {
exchanged = exchanger.exchange(received);
} catch (InterruptedException e) {
fail("Received InterruptedException");
}
assertNotSame(exchanged, received);
return delegate.read(received);
}
@Override
public boolean equals(String object, ByteBuffer binary) throws ClassNotFoundException {
throw new UnsupportedOperationException("TODO Implement me!");
}
}
private static <V extends Serializable> ValueHolder<V> newValueHolder(V value) {
return new SerializedOnHeapValueHolder<V>(value, TestTimeSource.INSTANCE.getTimeMillis(), false, new JavaSerializer<V>(SerializedOnHeapValueHolderTest.class.getClassLoader()));
}
private static class TestTimeSource implements TimeSource {
static final TestTimeSource INSTANCE = new TestTimeSource();
private long time = 1;
@Override
public long getTimeMillis() {
return time;
}
private void advanceTime(long delta) {
this.time += delta;
}
}
}