/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * 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 com.linkedin.pinot.query.aggregation.groupby; import com.linkedin.pinot.common.utils.Pairs; import com.linkedin.pinot.common.utils.Pairs.IntObjectPair; import com.linkedin.pinot.core.query.aggregation.function.customobject.AvgPair; import com.linkedin.pinot.core.query.aggregation.groupby.GroupByResultHolder; import com.linkedin.pinot.core.query.aggregation.groupby.ObjectGroupByResultHolder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import org.testng.Assert; import org.testng.annotations.Test; /** * Unit test for {@link ObjectGroupByResultHolder} */ public class ObjectGroupByResultHolderTest { 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 INITIAL_CAPACITY = 100; private static final int MAX_CAPACITY = 1000; /** * Tests that trimming of results with max ordering is correct. */ @Test public void testMaxTrimResults() { testTrimResults(false); } /** * Tests that trimming of results with min ordering is correct. */ @Test public void testMinTrimResults() { testTrimResults(true); } /** * Helper method for testing trimming of results. * @param minOrder Min ordering if true, max ordering else. */ private void testTrimResults(boolean minOrder) { GroupByResultHolder resultHolder = new ObjectGroupByResultHolder(INITIAL_CAPACITY, MAX_CAPACITY, INITIAL_CAPACITY, minOrder); List<IntObjectPair<AvgPair>> expectedIntObjectPairs = new ArrayList<>(MAX_CAPACITY); for (int i = 0; i < INITIAL_CAPACITY; i++) { AvgPair avgPair = new AvgPair(RANDOM.nextDouble(), (long) RANDOM.nextInt(100)); IntObjectPair<AvgPair> intObjectPair = new IntObjectPair<>(i, avgPair); expectedIntObjectPairs.add(intObjectPair); resultHolder.setValueForKey(i, avgPair); } // This will trigger switch from array based storage to map based storage. resultHolder.ensureCapacity(MAX_CAPACITY); for (int i = INITIAL_CAPACITY; i < MAX_CAPACITY; i++) { AvgPair avgPair = new AvgPair(RANDOM.nextDouble(), (long) RANDOM.nextInt(100)); IntObjectPair<AvgPair> intObjectPair = new IntObjectPair<>(i, avgPair); expectedIntObjectPairs.add(intObjectPair); resultHolder.setValueForKey(i, avgPair); } Collections.sort(expectedIntObjectPairs, new Pairs.IntObjectComparator(!minOrder)); // Trim the results. Assert.assertEquals(resultHolder.trimResults().length, MAX_CAPACITY - INITIAL_CAPACITY, ERROR_MESSAGE); // Ensure that all the correct group keys survive after trimming. for (int i = 0; i < INITIAL_CAPACITY; i++) { IntObjectPair intObjectPair = expectedIntObjectPairs.get(i); AvgPair actualAvgPair = resultHolder.getResult(intObjectPair.getIntValue()); AvgPair expectedAvgPair = (AvgPair) intObjectPair.getObjectValue(); Assert.assertEquals(actualAvgPair.getSum(), expectedAvgPair.getSum(), ERROR_MESSAGE); Assert.assertEquals(actualAvgPair.getCount(), expectedAvgPair.getCount(), ERROR_MESSAGE); } } }