/*
* 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.core.spi.store;
import org.ehcache.expiry.Duration;
import org.ehcache.core.spi.time.TimeSource;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
/**
* @author Ludovic Orban
*/
public class AbstractValueHolderTest {
@Test
public void testCreationTime() throws Exception {
AbstractValueHolder<String> valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L);
assertThat(valueHolder.creationTime(TimeUnit.SECONDS), is(1L));
assertThat(valueHolder.creationTime(TimeUnit.MILLISECONDS), is(1000L));
assertThat(valueHolder.creationTime(TimeUnit.MICROSECONDS), is(1000000L));
}
@Test
public void testExpirationTime() throws Exception {
AbstractValueHolder<String> valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 1000L);
assertThat(valueHolder.expirationTime(TimeUnit.SECONDS), is(1L));
assertThat(valueHolder.expirationTime(TimeUnit.MILLISECONDS), is(1000L));
assertThat(valueHolder.expirationTime(TimeUnit.MICROSECONDS), is(1000000L));
}
@Test
public void testLastAccessTime() throws Exception {
// last access time defaults to create time
AbstractValueHolder<String> valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L);
assertThat(valueHolder.lastAccessTime(TimeUnit.SECONDS), is(1L));
assertThat(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS), is(1000L));
assertThat(valueHolder.lastAccessTime(TimeUnit.MICROSECONDS), is(1000000L));
valueHolder = newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 0L, 2000L);
assertThat(valueHolder.lastAccessTime(TimeUnit.SECONDS), is(2L));
assertThat(valueHolder.lastAccessTime(TimeUnit.MILLISECONDS), is(2000L));
assertThat(valueHolder.lastAccessTime(TimeUnit.MICROSECONDS), is(2000000L));
}
@Test
public void testIsExpired() throws Exception {
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L).isExpired(1L, TimeUnit.SECONDS), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L).isExpired(1000L, TimeUnit.MILLISECONDS), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1001L).isExpired(1L, TimeUnit.SECONDS), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1001L).isExpired(1000L, TimeUnit.MILLISECONDS), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1001L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1000L).isExpired(1L, TimeUnit.SECONDS), is(true));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1000L).isExpired(1000L, TimeUnit.MILLISECONDS), is(true));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L, 1000L).isExpired(1000000L, TimeUnit.MICROSECONDS), is(true));
}
@Test
public void testEquals() throws Exception {
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L)), is(true));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 0L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 0L)), is(true));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 0L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 1L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 2L, 0L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 3L, 0L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(true));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1L, 2L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 3L, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 3L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 0L, 2L, 1L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1L).equals(newAbstractValueHolder(TimeUnit.SECONDS, 1L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.NANOSECONDS, 1L).equals(newAbstractValueHolder(TimeUnit.SECONDS, 0L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.SECONDS, 0L).equals(newAbstractValueHolder(TimeUnit.NANOSECONDS, 1L)), is(false));
assertThat(newAbstractValueHolder(TimeUnit.SECONDS, 1L).equals(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L)), is(true));
assertThat(newAbstractValueHolder(TimeUnit.MILLISECONDS, 1000L).equals(newAbstractValueHolder(TimeUnit.SECONDS, 1L)), is(true));
}
@Test
public void testSubclassEquals() throws Exception {
assertThat(new AbstractValueHolder<String>(-1, 1000L) {
@Override
public String value() {
return "aaa";
}
@Override
protected TimeUnit nativeTimeUnit() {
return TimeUnit.MILLISECONDS;
}
@Override
public int hashCode() {
return super.hashCode() + value().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof AbstractValueHolder) {
AbstractValueHolder<?> other = (AbstractValueHolder<?>) obj;
return super.equals(obj) && value().equals(other.value());
}
return false;
}
}.equals(new AbstractValueHolder<String>(-1, 1L) {
@Override
public String value() {
return "aaa";
}
@Override
protected TimeUnit nativeTimeUnit() {
return TimeUnit.SECONDS;
}
@Override
public int hashCode() {
return super.hashCode() + value().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof AbstractValueHolder) {
AbstractValueHolder<?> other = (AbstractValueHolder<?>)obj;
return super.equals(obj) && value().equals(other.value());
}
return false;
}
}), is(true));
assertThat(new AbstractValueHolder<String>(-1, 1000L) {
@Override
public String value() {
return "aaa";
}
@Override
protected TimeUnit nativeTimeUnit() {
return TimeUnit.MICROSECONDS;
}
@Override
public int hashCode() {
return super.hashCode() + value().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof AbstractValueHolder) {
AbstractValueHolder<?> other = (AbstractValueHolder<?>) obj;
return super.equals(obj) && value().equals(other.value());
}
return false;
}
}.equals(new AbstractValueHolder<String>(-1, 1L) {
@Override
public String value() {
return "bbb";
}
@Override
protected TimeUnit nativeTimeUnit() {
return TimeUnit.MILLISECONDS;
}
@Override
public int hashCode() {
return super.hashCode() + value().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof AbstractValueHolder) {
AbstractValueHolder<?> other = (AbstractValueHolder<?>)obj;
return super.equals(obj) && value().equals(other.value());
}
return false;
}
}), is(false));
}
@Test
public void testAbstractValueHolderHitRate() {
TestTimeSource timeSource = new TestTimeSource();
timeSource.advanceTime(1);
AbstractValueHolder<String> valueHolder = new AbstractValueHolder<String>(-1, timeSource.getTimeMillis()) {
@Override
protected TimeUnit nativeTimeUnit() {
return TimeUnit.MILLISECONDS;
}
@Override
public String value() {
return "abc";
}
};
valueHolder.accessed((timeSource.getTimeMillis()), new Duration(1L, TimeUnit.MILLISECONDS));
timeSource.advanceTime(1000);
assertThat(valueHolder.hitRate(timeSource.getTimeMillis(),
TimeUnit.SECONDS), is(1.0f));
}
private AbstractValueHolder<String> newAbstractValueHolder(final TimeUnit timeUnit, long creationTime) {
return new AbstractValueHolder<String>(-1, creationTime) {
@Override
protected TimeUnit nativeTimeUnit() {
return timeUnit;
}
@Override
public String value() {
throw new UnsupportedOperationException();
}
};
}
private AbstractValueHolder<String> newAbstractValueHolder(final TimeUnit timeUnit, long creationTime, long expirationTime) {
return new AbstractValueHolder<String>(-1, creationTime, expirationTime) {
@Override
protected TimeUnit nativeTimeUnit() {
return timeUnit;
}
@Override
public String value() {
throw new UnsupportedOperationException();
}
};
}
private AbstractValueHolder<String> newAbstractValueHolder(final TimeUnit timeUnit, long creationTime, long expirationTime, long lastAccessTime) {
final AbstractValueHolder<String> abstractValueHolder = new AbstractValueHolder<String>(-1, creationTime, expirationTime) {
@Override
protected TimeUnit nativeTimeUnit() {
return timeUnit;
}
@Override
public String value() {
throw new UnsupportedOperationException();
}
};
abstractValueHolder.setLastAccessTime(lastAccessTime, timeUnit);
return abstractValueHolder;
}
private static class TestTimeSource implements TimeSource {
private long time = 0;
@Override
public long getTimeMillis() {
return time;
}
public void advanceTime(long step) {
time += step;
}
}
}