blob: 1f29e8a7e8fcf18dd6fa12548d0b551371fc5251 [file] [log] [blame]
/*
* 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.apache.druid.query.cache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.druid.java.util.common.Cacheable;
import org.apache.druid.java.util.common.StringUtils;
import org.junit.Assert;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CacheKeyBuilderTest
{
@Test
public void testCacheKeyBuilder()
{
final Cacheable cacheable = () -> new byte[]{10, 20};
final byte[] actual = new CacheKeyBuilder((byte) 10)
.appendBoolean(false)
.appendString("test")
.appendInt(10)
.appendLong(Long.MAX_VALUE)
.appendFloat(0.1f)
.appendDouble(2.3)
.appendByteArray(CacheKeyBuilder.STRING_SEPARATOR) // test when an item is same with the separator
.appendFloatArray(new float[]{10.0f, 11.0f})
.appendStrings(Lists.newArrayList("test1", "test2"))
.appendCacheable(cacheable)
.appendCacheable(null)
.appendCacheables(Lists.newArrayList(cacheable, null, cacheable))
.build();
final int expectedSize = 1 // id
+ 1 // bool
+ 4 // 'test'
+ Integer.BYTES // 10
+ Long.BYTES // Long.MAX_VALUE
+ Float.BYTES // 0.1f
+ Double.BYTES // 2.3
+ CacheKeyBuilder.STRING_SEPARATOR.length // byte array
+ Float.BYTES * 2 // 10.0f, 11.0f
+ Integer.BYTES + 5 * 2 + 1 // 'test1' 'test2'
+ cacheable.getCacheKey().length // cacheable
+ Integer.BYTES + 4 // cacheable list
+ 12; // type keys
Assert.assertEquals(expectedSize, actual.length);
final byte[] expected = ByteBuffer.allocate(expectedSize)
.put((byte) 10)
.put(CacheKeyBuilder.BOOLEAN_KEY)
.put((byte) 0)
.put(CacheKeyBuilder.STRING_KEY)
.put(StringUtils.toUtf8("test"))
.put(CacheKeyBuilder.INT_KEY)
.putInt(10)
.put(CacheKeyBuilder.LONG_KEY)
.putLong(Long.MAX_VALUE)
.put(CacheKeyBuilder.FLOAT_KEY)
.putFloat(0.1f)
.put(CacheKeyBuilder.DOUBLE_KEY)
.putDouble(2.3)
.put(CacheKeyBuilder.BYTE_ARRAY_KEY)
.put(CacheKeyBuilder.STRING_SEPARATOR)
.put(CacheKeyBuilder.FLOAT_ARRAY_KEY)
.putFloat(10.0f)
.putFloat(11.0f)
.put(CacheKeyBuilder.STRING_LIST_KEY)
.putInt(2)
.put(StringUtils.toUtf8("test1"))
.put(CacheKeyBuilder.STRING_SEPARATOR)
.put(StringUtils.toUtf8("test2"))
.put(CacheKeyBuilder.CACHEABLE_KEY)
.put(cacheable.getCacheKey())
.put(CacheKeyBuilder.CACHEABLE_KEY)
.put(CacheKeyBuilder.CACHEABLE_LIST_KEY)
.putInt(3)
.put(cacheable.getCacheKey())
.put(cacheable.getCacheKey())
.array();
Assert.assertArrayEquals(expected, actual);
}
@Test
public void testDifferentOrderList()
{
byte[] key1 = new CacheKeyBuilder((byte) 10)
.appendStringsIgnoringOrder(Lists.newArrayList("AB", "BA"))
.build();
byte[] key2 = new CacheKeyBuilder((byte) 10)
.appendStringsIgnoringOrder(Lists.newArrayList("BA", "AB"))
.build();
Assert.assertArrayEquals(key1, key2);
final Cacheable cacheable1 = () -> new byte[]{1};
final Cacheable cacheable2 = () -> new byte[]{2};
key1 = new CacheKeyBuilder((byte) 10)
.appendCacheablesIgnoringOrder(Lists.newArrayList(cacheable1, cacheable2))
.build();
key2 = new CacheKeyBuilder((byte) 10)
.appendCacheablesIgnoringOrder(Lists.newArrayList(cacheable2, cacheable1))
.build();
Assert.assertArrayEquals(key1, key2);
}
@Test
public void testNotEqualStrings()
{
final List<byte[]> keys = new ArrayList<>();
keys.add(
new CacheKeyBuilder((byte) 10)
.appendString("test")
.appendString("test")
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendString("testtest")
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendString("testtest")
.appendString("")
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendString("")
.appendString("testtest")
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendStrings(ImmutableList.of("test", "test"))
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendStrings(ImmutableList.of("testtest"))
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendStrings(ImmutableList.of("testtest", ""))
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendStrings(ImmutableList.of("testtest"))
.appendStrings(ImmutableList.of())
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendStrings(ImmutableList.of())
.appendStrings(ImmutableList.of("testtest"))
.build()
);
assertNotEqualsEachOther(keys);
}
@Test
public void testNotEqualCacheables()
{
final Cacheable test = () -> StringUtils.toUtf8("test");
final Cacheable testtest = () -> StringUtils.toUtf8("testtest");
final List<byte[]> keys = new ArrayList<>();
keys.add(
new CacheKeyBuilder((byte) 10)
.appendCacheable(test)
.appendCacheable(test)
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendCacheable(testtest)
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendCacheables(Lists.newArrayList(test, test))
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendCacheables(Collections.singletonList(testtest))
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendCacheables(Collections.singletonList(testtest))
.appendCacheables(new ArrayList<>())
.build()
);
keys.add(
new CacheKeyBuilder((byte) 10)
.appendCacheables(new ArrayList<>())
.appendCacheables(Collections.singletonList(testtest))
.build()
);
assertNotEqualsEachOther(keys);
}
private static void assertNotEqualsEachOther(List<byte[]> keys)
{
for (int i = 0; i < keys.size(); i++) {
for (int j = i + 1; j < keys.size(); j++) {
Assert.assertFalse(Arrays.equals(keys.get(i), keys.get(j)));
}
}
}
@Test
public void testEmptyOrNullStringLists()
{
byte[] key1 = new CacheKeyBuilder((byte) 10)
.appendStrings(Lists.newArrayList("", ""))
.build();
byte[] key2 = new CacheKeyBuilder((byte) 10)
.appendStrings(Collections.singletonList(""))
.build();
Assert.assertFalse(Arrays.equals(key1, key2));
key1 = new CacheKeyBuilder((byte) 10)
.appendStrings(Collections.singletonList(""))
.build();
key2 = new CacheKeyBuilder((byte) 10)
.appendStrings(Collections.singletonList(null))
.build();
Assert.assertArrayEquals(key1, key2);
}
@Test
public void testEmptyOrNullCacheables()
{
final byte[] key1 = new CacheKeyBuilder((byte) 10)
.appendCacheables(new ArrayList<>())
.build();
final byte[] key2 = new CacheKeyBuilder((byte) 10)
.appendCacheables(Collections.singletonList(null))
.build();
Assert.assertFalse(Arrays.equals(key1, key2));
}
@Test
public void testIgnoringOrder()
{
byte[] actual = new CacheKeyBuilder((byte) 10)
.appendStringsIgnoringOrder(Lists.newArrayList("test2", "test1", "te"))
.build();
byte[] expected = ByteBuffer.allocate(20)
.put((byte) 10)
.put(CacheKeyBuilder.STRING_LIST_KEY)
.putInt(3)
.put(StringUtils.toUtf8("te"))
.put(CacheKeyBuilder.STRING_SEPARATOR)
.put(StringUtils.toUtf8("test1"))
.put(CacheKeyBuilder.STRING_SEPARATOR)
.put(StringUtils.toUtf8("test2"))
.array();
Assert.assertArrayEquals(expected, actual);
final Cacheable c1 = () -> StringUtils.toUtf8("te");
final Cacheable c2 = () -> StringUtils.toUtf8("test1");
final Cacheable c3 = () -> StringUtils.toUtf8("test2");
actual = new CacheKeyBuilder((byte) 10)
.appendCacheablesIgnoringOrder(Lists.newArrayList(c3, c2, c1))
.build();
expected = ByteBuffer.allocate(18)
.put((byte) 10)
.put(CacheKeyBuilder.CACHEABLE_LIST_KEY)
.putInt(3)
.put(c1.getCacheKey())
.put(c2.getCacheKey())
.put(c3.getCacheKey())
.array();
Assert.assertArrayEquals(expected, actual);
}
}