/* * Copyright (C) 2014 The Guava Authors * * 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.google.common.collect; import static com.google.common.truth.Truth.assertThat; import com.google.common.math.IntMath; import com.google.common.primitives.Ints; import java.math.RoundingMode; import java.util.Collections; import java.util.Comparator; import java.util.List; import junit.framework.TestCase; /** * Tests for {@code TopKSelector}. * * @author Louis Wasserman */ public class TopKSelectorTest extends TestCase { public void testNegativeK() { try { TopKSelector.least(-1); fail(); } catch (IllegalArgumentException expected) { } try { TopKSelector.greatest(-1); fail(); } catch (IllegalArgumentException expected) { } try { TopKSelector.least(-1, Ordering.natural()); fail(); } catch (IllegalArgumentException expected) { } try { TopKSelector.greatest(-1, Ordering.natural()); fail(); } catch (IllegalArgumentException expected) { } } public void testZeroK() { TopKSelector<Integer> top = TopKSelector.least(0); for (int i = 0; i < 10; i++) { top.offer(i); } assertThat(top.topK()).isEmpty(); } public void testNoElementsOffered() { TopKSelector<Integer> top = TopKSelector.least(10); assertThat(top.topK()).isEmpty(); } public void testOfferedFewerThanK() { TopKSelector<Integer> top = TopKSelector.least(10); top.offer(3); top.offer(5); top.offer(2); assertThat(top.topK()).containsExactly(2, 3, 5).inOrder(); } public void testOfferedKPlusOne() { for (List<Integer> list : Collections2.permutations(Ints.asList(1, 2, 3, 4, 5))) { TopKSelector<Integer> top = TopKSelector.least(4); top.offerAll(list); assertThat(top.topK()).containsExactly(1, 2, 3, 4).inOrder(); } } public void testOfferedThreeK() { for (List<Integer> list : Collections2.permutations(Ints.asList(1, 2, 3, 4, 5, 6))) { TopKSelector<Integer> top = TopKSelector.least(2); top.offerAll(list); assertThat(top.topK()).containsExactly(1, 2).inOrder(); } } public void testDifferentComparator() { TopKSelector<String> top = TopKSelector.least(3, String.CASE_INSENSITIVE_ORDER); top.offerAll(ImmutableList.of("a", "B", "c", "D", "e", "F")); assertThat(top.topK()).containsExactly("a", "B", "c").inOrder(); } public void testWorstCase() { int n = 2000000; int k = 200000; final long[] compareCalls = {0}; Comparator<Integer> cmp = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { compareCalls[0]++; return o1.compareTo(o2); } }; TopKSelector<Integer> top = TopKSelector.least(k, cmp); top.offer(1); for (int i = 1; i < n; i++) { top.offer(0); } assertThat(top.topK()).containsExactlyElementsIn(Collections.nCopies(k, 0)); assertThat(compareCalls[0]).isAtMost(10L * n * IntMath.log2(k, RoundingMode.CEILING)); } }