/* * 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.geode.cache.query.internal; import static org.junit.Assert.*; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.SortedSet; import java.util.TreeSet; import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.geode.cache.query.Struct; import org.apache.geode.cache.query.internal.types.ObjectTypeImpl; import org.apache.geode.cache.query.internal.types.StructTypeImpl; import org.apache.geode.cache.query.types.ObjectType; import org.apache.geode.test.junit.categories.UnitTest; @Category(UnitTest.class) public class NWayMergeResultsJUnitTest { @Test public void testNonDistinct() throws Exception { final int numSortedLists = 40; Collection<List<Integer>> listOfSortedLists = new ArrayList<List<Integer>>(); for (int i = 0; i < numSortedLists; ++i) { listOfSortedLists.add(new ArrayList<Integer>()); } int step = 0; for (List<Integer> list : listOfSortedLists) { step = step + 1; for (int i = -500; i < 500; i = i + step) { list.add(i); } } int totalElements = 0; for (List<Integer> list : listOfSortedLists) { totalElements += list.size(); } int combinedArray[] = new int[totalElements]; int i = 0; for (List<Integer> list : listOfSortedLists) { for (Integer num : list) { combinedArray[i++] = num.intValue(); } } Arrays.sort(combinedArray); NWayMergeResults<Integer> mergedResults = createSingleFieldMergedResult(listOfSortedLists, false, -1); Iterator<Integer> iter = mergedResults.iterator(); for (int elem : combinedArray) { assertEquals(elem, iter.next().intValue()); } assertFalse(iter.hasNext()); try { iter.next(); fail("next should have thrown NoSuchElementException"); } catch (NoSuchElementException nsee) { // Ok. } assertEquals(combinedArray.length, mergedResults.size()); } @Test public void testDistinct() throws Exception { final int numSortedLists = 40; Collection<List<Integer>> listOfSortedLists = new ArrayList<List<Integer>>(); for (int i = 0; i < numSortedLists; ++i) { listOfSortedLists.add(new ArrayList<Integer>()); } int step = 0; for (List<Integer> list : listOfSortedLists) { step = step + 1; for (int i = -500; i < 500; i = i + step) { list.add(i); } } SortedSet<Integer> sortedSet = new TreeSet<Integer>(); for (List<Integer> list : listOfSortedLists) { for (Integer num : list) { sortedSet.add(num); } } NWayMergeResults<Integer> mergedResults = createSingleFieldMergedResult(listOfSortedLists, true, -1); Iterator<Integer> iter = mergedResults.iterator(); for (int elem : sortedSet) { assertEquals(elem, iter.next().intValue()); } assertFalse(iter.hasNext()); try { iter.next(); fail("next should have thrown NoSuchElementException"); } catch (NoSuchElementException nsee) { // Ok. } assertEquals(sortedSet.size(), mergedResults.size()); } @Test public void testLimitNoDistinct() throws Exception { final int numSortedLists = 40; final int limit = 53; Collection<List<Integer>> listOfSortedLists = new ArrayList<List<Integer>>(); for (int i = 0; i < numSortedLists; ++i) { listOfSortedLists.add(new ArrayList<Integer>()); } int step = 0; for (List<Integer> list : listOfSortedLists) { step = step + 1; for (int i = -500; i < 500; i = i + step) { list.add(i); } } int totalElements = 0; for (List<Integer> list : listOfSortedLists) { totalElements += list.size(); } int combinedArray[] = new int[totalElements]; int i = 0; for (List<Integer> list : listOfSortedLists) { for (Integer num : list) { combinedArray[i++] = num.intValue(); } } Arrays.sort(combinedArray); NWayMergeResults<Integer> mergedResults = createSingleFieldMergedResult(listOfSortedLists, false, limit); Iterator<Integer> iter = mergedResults.iterator(); int count = 0; for (int elem : combinedArray) { if (count == limit) { break; } assertEquals(elem, iter.next().intValue()); ++count; } assertFalse(iter.hasNext()); try { iter.next(); fail("next should have thrown NoSuchElementException"); } catch (NoSuchElementException nsee) { // Ok. } assertEquals(limit, mergedResults.size()); } @Test public void testLimitDistinct() throws Exception { final int numSortedLists = 40; final int limit = 53; Collection<List<Integer>> listOfSortedLists = new ArrayList<List<Integer>>(); for (int i = 0; i < numSortedLists; ++i) { listOfSortedLists.add(new ArrayList<Integer>()); } int step = 0; for (List<Integer> list : listOfSortedLists) { step = step + 1; for (int i = -500; i < 500; i = i + step) { list.add(i); } } SortedSet<Integer> sortedSet = new TreeSet<Integer>(); for (List<Integer> list : listOfSortedLists) { for (Integer num : list) { sortedSet.add(num); } } NWayMergeResults<Integer> mergedResults = createSingleFieldMergedResult(listOfSortedLists, true, limit); Iterator<Integer> iter = mergedResults.iterator(); int count = 0; for (int elem : sortedSet) { if (count == limit) { break; } assertEquals(elem, iter.next().intValue()); ++count; } assertFalse(iter.hasNext()); try { iter.next(); fail("next should have thrown NoSuchElementException"); } catch (NoSuchElementException nsee) { // Ok. } assertEquals(limit, mergedResults.size()); } @Test public void testNonDistinctStruct() throws Exception { final int numSortedLists = 40; StructTypeImpl structType = new StructTypeImpl(new String[] {"a", "b"}, new ObjectType[] {new ObjectTypeImpl(Integer.TYPE), new ObjectTypeImpl(Integer.TYPE)}); Collection<List<Struct>> listOfSortedLists = new ArrayList<List<Struct>>(); for (int i = 0; i < numSortedLists; ++i) { listOfSortedLists.add(new ArrayList<Struct>()); } int step = 0; for (List<Struct> list : listOfSortedLists) { step = step + 1; int j = 1000; for (int i = -500; i < 500; i = i + step) { Struct struct = new StructImpl(structType, new Object[] {Integer.valueOf(i), Integer.valueOf(j - step)}); list.add(struct); } } int totalElements = 0; for (List<Struct> list : listOfSortedLists) { totalElements += list.size(); } Struct combinedArray[] = new Struct[totalElements]; int i = 0; for (List<Struct> list : listOfSortedLists) { for (Struct struct : list) { combinedArray[i++] = struct; } } Arrays.sort(combinedArray, new Comparator<Struct>() { @Override public int compare(Struct o1, Struct o2) { Object[] fields_1 = o1.getFieldValues(); Object[] fields_2 = o2.getFieldValues(); int compare = ((Comparable) fields_1[0]).compareTo((Comparable) fields_2[0]); if (compare == 0) { // second field is descending compare = ((Comparable) fields_2[1]).compareTo((Comparable) fields_1[1]); } return compare; } }); NWayMergeResults<Struct> mergedResults = createStructFieldMergedResult(listOfSortedLists, false, -1, structType); Iterator<Struct> iter = mergedResults.iterator(); for (Struct elem : combinedArray) { assertEquals(elem, iter.next()); } assertFalse(iter.hasNext()); try { iter.next(); fail("next should have thrown NoSuchElementException"); } catch (NoSuchElementException nsee) { // Ok. } } @Test public void testDistinctStruct() throws Exception { final int numSortedLists = 40; StructTypeImpl structType = new StructTypeImpl(new String[] {"a", "b"}, new ObjectType[] {new ObjectTypeImpl(Integer.TYPE), new ObjectTypeImpl(Integer.TYPE)}); Collection<List<Struct>> listOfSortedLists = new ArrayList<List<Struct>>(); for (int i = 0; i < numSortedLists; ++i) { listOfSortedLists.add(new ArrayList<Struct>()); } int step = 0; for (List<Struct> list : listOfSortedLists) { step = step + 1; int j = 1000; for (int i = -500; i < 500; i = i + step) { Struct struct = new StructImpl(structType, new Object[] {Integer.valueOf(i), Integer.valueOf(j - step)}); list.add(struct); } } SortedSet<Struct> sortedSet = new TreeSet<Struct>(new Comparator<Struct>() { @Override public int compare(Struct o1, Struct o2) { Object[] fields_1 = o1.getFieldValues(); Object[] fields_2 = o2.getFieldValues(); int compare = ((Comparable) fields_1[0]).compareTo((Comparable) fields_2[0]); if (compare == 0) { // second field is descending compare = ((Comparable) fields_2[1]).compareTo((Comparable) fields_1[1]); } return compare; } }); int i = 0; for (List<Struct> list : listOfSortedLists) { for (Struct struct : list) { sortedSet.add(struct); } } NWayMergeResults<Struct> mergedResults = createStructFieldMergedResult(listOfSortedLists, true, -1, structType); Iterator<Struct> iter = mergedResults.iterator(); for (Struct elem : sortedSet) { assertEquals(elem, iter.next()); } assertFalse(iter.hasNext()); try { iter.next(); fail("next should have thrown NoSuchElementException"); } catch (NoSuchElementException nsee) { // Ok. } } @Test public void testOccurenceNonDistinct() throws Exception { final int numSortedLists = 40; Collection<List<Integer>> listOfSortedLists = new ArrayList<List<Integer>>(); for (int i = 0; i < numSortedLists; ++i) { listOfSortedLists.add(new ArrayList<Integer>()); } int step = 0; for (List<Integer> list : listOfSortedLists) { step = step + 1; for (int i = -500; i < 500; i = i + step) { list.add(i); } } int totalElements = 0; for (List<Integer> list : listOfSortedLists) { totalElements += list.size(); } int combinedArray[] = new int[totalElements]; int i = 0; for (List<Integer> list : listOfSortedLists) { for (Integer num : list) { combinedArray[i++] = num.intValue(); } } Arrays.sort(combinedArray); // count occurrence of 70, 72,73 , 75 int num70 = 0, num72 = 0, num73 = 0, num75 = 0; for (int num : combinedArray) { if (num == 70) { ++num70; } else if (num == 72) { ++num72; } else if (num == 73) { ++num73; } else if (num == 75) { ++num75; } } NWayMergeResults<Integer> mergedResults = createSingleFieldMergedResult(listOfSortedLists, false, -1); assertEquals(num70, mergedResults.occurrences(Integer.valueOf(70))); assertEquals(num72, mergedResults.occurrences(Integer.valueOf(72))); assertEquals(num73, mergedResults.occurrences(Integer.valueOf(73))); assertEquals(num75, mergedResults.occurrences(Integer.valueOf(75))); } @Test public void testOccurenceDistinct() throws Exception { final int numSortedLists = 40; Collection<List<Integer>> listOfSortedLists = new ArrayList<List<Integer>>(); for (int i = 0; i < numSortedLists; ++i) { listOfSortedLists.add(new ArrayList<Integer>()); } int step = 0; for (List<Integer> list : listOfSortedLists) { step = step + 1; for (int i = -500; i < 500; i = i + step) { list.add(i); } } SortedSet<Integer> sortedSet = new TreeSet<Integer>(); for (List<Integer> list : listOfSortedLists) { for (Integer num : list) { sortedSet.add(num); } } NWayMergeResults<Integer> mergedResults = createSingleFieldMergedResult(listOfSortedLists, true, -1); assertEquals(1, mergedResults.occurrences(Integer.valueOf(70))); assertEquals(1, mergedResults.occurrences(Integer.valueOf(72))); assertEquals(1, mergedResults.occurrences(Integer.valueOf(73))); assertEquals(1, mergedResults.occurrences(Integer.valueOf(75))); } private <E> NWayMergeResults<E> createSingleFieldMergedResult( Collection<? extends Collection<E>> sortedResults, boolean isDistinct, int limit) throws Exception { CompiledSortCriterion csc = new CompiledSortCriterion(false, CompiledSortCriterion.ProjectionField.getProjectionField()); Method method = CompiledSortCriterion.class .getDeclaredMethod("substituteExpressionWithProjectionField", Integer.TYPE); method.setAccessible(true); method.invoke(csc, 0); List<CompiledSortCriterion> orderByAttribs = new ArrayList<CompiledSortCriterion>(); orderByAttribs.add(csc); ExecutionContext context = new ExecutionContext(null, null); ObjectType elementType = new ObjectTypeImpl(Object.class); return new NWayMergeResults<E>(sortedResults, isDistinct, limit, orderByAttribs, context, elementType); } private NWayMergeResults<Struct> createStructFieldMergedResult( Collection<? extends Collection<Struct>> sortedResults, boolean isDistinct, int limit, StructTypeImpl structType) throws Exception { CompiledSortCriterion csc1 = new CompiledSortCriterion(false, CompiledSortCriterion.ProjectionField.getProjectionField()); CompiledSortCriterion csc2 = new CompiledSortCriterion(true, CompiledSortCriterion.ProjectionField.getProjectionField()); Method method = CompiledSortCriterion.class .getDeclaredMethod("substituteExpressionWithProjectionField", Integer.TYPE); method.setAccessible(true); method.invoke(csc1, 0); method.invoke(csc2, 1); List<CompiledSortCriterion> orderByAttribs = new ArrayList<CompiledSortCriterion>(); orderByAttribs.add(csc1); orderByAttribs.add(csc2); ExecutionContext context = new ExecutionContext(null, null); return new NWayMergeResults<Struct>(sortedResults, false, -1, orderByAttribs, context, structType); } @Test public void testCombination() throws Exception { List<String> results1 = new ArrayList<String>(); results1.add("IBM"); results1.add("YHOO"); List<String> results2 = new ArrayList<String>(); results2.add("APPL"); results2.add("ORCL"); List<String> results3 = new ArrayList<String>(); results3.add("DELL"); results3.add("RHAT"); List<String> results4 = new ArrayList<String>(); results4.add("ORCL"); results4.add("SAP"); List<String> results5 = Collections.emptyList(); List<String> results6 = Collections.emptyList(); List<String> results7 = Collections.emptyList(); List<Collection<String>> sortedLists = new ArrayList<Collection<String>>(); sortedLists.add(results1); sortedLists.add(results2); sortedLists.add(results3); sortedLists.add(results4); sortedLists.add(results5); sortedLists.add(results6); sortedLists.add(results7); NWayMergeResults<String> mergedResults = createSingleFieldMergedResult(sortedLists, true, -1); List<String> results8 = new ArrayList<String>(); results8.add("DELL"); results8.add("GOOG"); results8.add("HP"); results8.add("MSFT"); results8.add("SAP"); results8.add("SUN"); List<String> results9 = new ArrayList<String>(); results9.add("AOL"); results9.add("APPL"); results9.add("GOOG"); results9.add("IBM"); results9.add("SUN"); results9.add("YHOO"); List<Collection<String>> sortedLists1 = new ArrayList<Collection<String>>(); sortedLists1.add(mergedResults); sortedLists1.add(results8); sortedLists1.add(results9); NWayMergeResults<String> netMergedResults = createSingleFieldMergedResult(sortedLists1, true, -1); assertEquals(12, netMergedResults.size()); } }