blob: 3b8bfc48d366448b56df1991873098f9f689f59a [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.pinot.core.common;
import com.clearspring.analytics.stream.cardinality.HyperLogLog;
import com.tdunning.math.stats.TDigest;
import it.unimi.dsi.fastutil.doubles.Double2LongOpenHashMap;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.floats.Float2LongOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.pinot.core.query.aggregation.function.PercentileEstAggregationFunction;
import org.apache.pinot.core.query.aggregation.function.PercentileTDigestAggregationFunction;
import org.apache.pinot.segment.local.customobject.AvgPair;
import org.apache.pinot.segment.local.customobject.DoubleLongPair;
import org.apache.pinot.segment.local.customobject.FloatLongPair;
import org.apache.pinot.segment.local.customobject.IntLongPair;
import org.apache.pinot.segment.local.customobject.LongLongPair;
import org.apache.pinot.segment.local.customobject.MinMaxRangePair;
import org.apache.pinot.segment.local.customobject.QuantileDigest;
import org.apache.pinot.segment.local.customobject.StringLongPair;
import org.apache.pinot.segment.local.customobject.ValueLongPair;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
public class ObjectSerDeUtilsTest {
private static final long RANDOM_SEED = System.currentTimeMillis();
private static final Random RANDOM = new Random(RANDOM_SEED);
private static final String ERROR_MESSAGE = "Random seed: " + RANDOM_SEED;
private static final int NUM_ITERATIONS = 100;
@Test
public void testString() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
String expected = RandomStringUtils.random(RANDOM.nextInt(20));
byte[] bytes = ObjectSerDeUtils.serialize(expected);
String actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.String);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testLong() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
Long expected = RANDOM.nextLong();
byte[] bytes = ObjectSerDeUtils.serialize(expected);
Long actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.Long);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testDouble() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
Double expected = RANDOM.nextDouble();
byte[] bytes = ObjectSerDeUtils.serialize(expected);
Double actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.Double);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testDoubleArrayList() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
int size = RANDOM.nextInt(100);
DoubleArrayList expected = new DoubleArrayList(size);
for (int j = 0; j < size; j++) {
expected.add(RANDOM.nextDouble());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
DoubleArrayList actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.DoubleArrayList);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testAvgPair() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
AvgPair expected = new AvgPair(RANDOM.nextDouble(), RANDOM.nextLong());
byte[] bytes = ObjectSerDeUtils.serialize(expected);
AvgPair actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.AvgPair);
assertEquals(actual.getSum(), expected.getSum(), ERROR_MESSAGE);
assertEquals(actual.getCount(), expected.getCount(), ERROR_MESSAGE);
}
}
@Test
public void testMinMaxRangePair() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
MinMaxRangePair expected = new MinMaxRangePair(RANDOM.nextDouble(), RANDOM.nextDouble());
byte[] bytes = ObjectSerDeUtils.serialize(expected);
MinMaxRangePair actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.MinMaxRangePair);
assertEquals(actual.getMin(), expected.getMin(), ERROR_MESSAGE);
assertEquals(actual.getMax(), expected.getMax(), ERROR_MESSAGE);
}
}
@Test
public void testIntValueTimePair() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
ValueLongPair<Integer> expected = new IntLongPair(RANDOM.nextInt(), RANDOM.nextLong());
byte[] bytes = ObjectSerDeUtils.serialize(expected);
ValueLongPair<Integer> actual = ObjectSerDeUtils.deserialize(bytes,
ObjectSerDeUtils.ObjectType.IntLongPair);
assertEquals(actual.getValue(), expected.getValue(), ERROR_MESSAGE);
assertEquals(actual.getTime(), expected.getTime(), ERROR_MESSAGE);
}
}
@Test
public void testLongValueTimePair() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
ValueLongPair<Long> expected = new LongLongPair(RANDOM.nextLong(), RANDOM.nextLong());
byte[] bytes = ObjectSerDeUtils.serialize(expected);
ValueLongPair<Long> actual = ObjectSerDeUtils.deserialize(bytes,
ObjectSerDeUtils.ObjectType.LongLongPair);
assertEquals(actual.getValue(), expected.getValue(), ERROR_MESSAGE);
assertEquals(actual.getTime(), expected.getTime(), ERROR_MESSAGE);
}
}
@Test
public void testFloatValueTimePair() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
ValueLongPair<Float> expected = new FloatLongPair(RANDOM.nextFloat(), RANDOM.nextLong());
byte[] bytes = ObjectSerDeUtils.serialize(expected);
ValueLongPair<Float> actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.FloatLongPair);
assertEquals(actual.getValue(), expected.getValue(), ERROR_MESSAGE);
assertEquals(actual.getTime(), expected.getTime(), ERROR_MESSAGE);
}
}
@Test
public void testDoubleValueTimePair() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
ValueLongPair<Double> expected = new DoubleLongPair(RANDOM.nextDouble(), RANDOM.nextLong());
byte[] bytes = ObjectSerDeUtils.serialize(expected);
ValueLongPair<Double> actual = ObjectSerDeUtils.deserialize(bytes,
ObjectSerDeUtils.ObjectType.DoubleLongPair);
assertEquals(actual.getValue(), expected.getValue(), ERROR_MESSAGE);
assertEquals(actual.getTime(), expected.getTime(), ERROR_MESSAGE);
}
}
@Test
public void testStringValueTimePair() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
ValueLongPair<String> expected = new StringLongPair(String.valueOf(RANDOM.nextDouble()), RANDOM.nextLong());
String temp = new String(expected.getValue().getBytes());
byte[] bytes = ObjectSerDeUtils.serialize(expected);
ValueLongPair<String> actual = ObjectSerDeUtils.deserialize(bytes,
ObjectSerDeUtils.ObjectType.StringLongPair);
assertEquals(actual.getValue(), expected.getValue(), ERROR_MESSAGE);
assertEquals(actual.getTime(), expected.getTime(), ERROR_MESSAGE);
}
}
@Test
public void testHyperLogLog() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
HyperLogLog expected = new HyperLogLog(7);
byte[] bytes = ObjectSerDeUtils.serialize(expected);
HyperLogLog actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.HyperLogLog);
assertEquals(actual.cardinality(), expected.cardinality(), ERROR_MESSAGE);
}
}
@Test
public void testQuantileDigest() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
QuantileDigest expected = new QuantileDigest(PercentileEstAggregationFunction.DEFAULT_MAX_ERROR);
int size = RANDOM.nextInt(100) + 1;
for (int j = 0; j < size; j++) {
expected.add(RANDOM.nextLong());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
QuantileDigest actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.QuantileDigest);
for (int j = 0; j <= 100; j++) {
assertEquals(actual.getQuantile(j / 100.0), expected.getQuantile(j / 100.0), 1e-5, ERROR_MESSAGE);
}
}
}
@Test
public void testMap() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
int size = RANDOM.nextInt(100);
Map<String, Double> expected = new HashMap<>(size);
for (int j = 0; j < size; j++) {
expected.put(RandomStringUtils.random(RANDOM.nextInt(20)), RANDOM.nextDouble());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
Map<String, Double> actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.Map);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testIntSet() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
int size = RANDOM.nextInt(100);
IntSet expected = new IntOpenHashSet(size);
for (int j = 0; j < size; j++) {
expected.add(RANDOM.nextInt());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
IntSet actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.IntSet);
// NOTE: use Object comparison instead of Collection comparison because the order might be different
assertEquals((Object) actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testTDigest() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
TDigest expected = TDigest.createMergingDigest(PercentileTDigestAggregationFunction.DEFAULT_TDIGEST_COMPRESSION);
int size = RANDOM.nextInt(100) + 1;
for (int j = 0; j < size; j++) {
expected.add(RANDOM.nextDouble());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
TDigest actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.TDigest);
for (int j = 0; j <= 100; j++) {
assertEquals(actual.quantile(j / 100.0), expected.quantile(j / 100.0), 1e-5);
}
}
}
@Test
public void testInt2LongMap() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
int size = RANDOM.nextInt(100);
Int2LongOpenHashMap expected = new Int2LongOpenHashMap(size);
for (int j = 0; j < size; j++) {
expected.put(RANDOM.nextInt(20), RANDOM.nextLong());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
Int2LongOpenHashMap actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.Int2LongMap);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testLong2LongMap() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
int size = RANDOM.nextInt(100);
Long2LongOpenHashMap expected = new Long2LongOpenHashMap(size);
for (int j = 0; j < size; j++) {
expected.put(RANDOM.nextLong(), RANDOM.nextLong());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
Long2LongOpenHashMap actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.Long2LongMap);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testFloat2LongMap() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
int size = RANDOM.nextInt(100);
Float2LongOpenHashMap expected = new Float2LongOpenHashMap(size);
for (int j = 0; j < size; j++) {
expected.put(RANDOM.nextFloat(), RANDOM.nextLong());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
Float2LongOpenHashMap actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.Float2LongMap);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
@Test
public void testDouble2LongMap() {
for (int i = 0; i < NUM_ITERATIONS; i++) {
int size = RANDOM.nextInt(100);
Double2LongOpenHashMap expected = new Double2LongOpenHashMap(size);
for (int j = 0; j < size; j++) {
expected.put(RANDOM.nextDouble(), RANDOM.nextLong());
}
byte[] bytes = ObjectSerDeUtils.serialize(expected);
Double2LongOpenHashMap actual = ObjectSerDeUtils.deserialize(bytes, ObjectSerDeUtils.ObjectType.Double2LongMap);
assertEquals(actual, expected, ERROR_MESSAGE);
}
}
}