/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2015 by Pentaho : http://www.pentaho.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 org.pentaho.di.trans.steps.databaselookup.readallcache; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.core.row.value.ValueMetaInteger; import java.util.Arrays; import java.util.BitSet; import java.util.List; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * This is a base class for several similar cases. All of them are checking how indexes work with the same tuple of data: * [0, 1, 2, 2, 3]. Since the data set is known, each subclass show implement tests for the following values: * <ul> * <li>-1</li> * <li>0</li> * <li>1</li> * <li>2</li> * <li>3</li> * <li>100</li> * </ul> * * @author Andrey Khayrutdinov */ public abstract class IndexTestBase<T extends Index> { private static Long[][] toMatrix( long... values ) { Long[][] result = new Long[ values.length ][]; for ( int i = 0; i < values.length; i++ ) { result[ i ] = new Long[] { values[ i ] }; } return result; } static List<Object[]> createSampleData() { // sorted, reversely sorted, and shuffled data return Arrays.asList( new Object[] { toMatrix( 0, 1, 2, 2, 3 ) }, new Object[] { toMatrix( 3, 2, 2, 1, 0 ) }, new Object[] { toMatrix( 1, 3, 2, 0, 2 ) } ); } final Long[][] rows; private final Class<T> clazz; T index; SearchingContext context; public IndexTestBase( Class<T> clazz, Long[][] rows ) { this.rows = rows; this.clazz = clazz; } @Before public void setUp() throws Exception { index = createIndexInstance( 0, new ValueMetaInteger(), 5 ); index.performIndexingOf( rows ); context = new SearchingContext(); context.init( 5 ); } T createIndexInstance( int column, ValueMetaInterface meta, int rowsAmount ) throws Exception { return clazz .getDeclaredConstructor( int.class, ValueMetaInterface.class, int.class ) .newInstance( column, meta, rowsAmount ); } @After public void tearDown() { index = null; context = null; } void testFindsNothing( long value ) { assertFalse( context.isEmpty() ); index.applyRestrictionsTo( context, new ValueMetaInteger(), value ); assertTrue( "Expected not to find anything matching " + value, context.isEmpty() ); } void testFindsCorrectly( long lookupValue, int expectedAmount ) { assertFalse( context.isEmpty() ); index.applyRestrictionsTo( context, new ValueMetaInteger(), lookupValue ); assertFalse( "Expected to find something", context.isEmpty() ); BitSet actual = context.getCandidates(); int cnt = expectedAmount; int lastSetBit = 0; while ( cnt > 0 ) { lastSetBit = actual.nextSetBit( lastSetBit ); if ( lastSetBit < 0 ) { fail( "Expected to find " + expectedAmount + " values, but got: " + actual.toString() ); } doAssertMatches( actual, lookupValue, rows[ lastSetBit ][ 0 ] ); lastSetBit++; cnt--; } } abstract void doAssertMatches( BitSet candidates, long lookupValue, long actualValue ); @Test public abstract void lookupFor_MinusOne(); @Test public abstract void lookupFor_Zero(); @Test public abstract void lookupFor_One(); @Test public abstract void lookupFor_Two(); @Test public abstract void lookupFor_Three(); @Test public abstract void lookupFor_Hundred(); }