package org.basex.index;
import static org.basex.util.Token.*;
import static org.junit.Assert.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.List;
import org.basex.*;
import org.basex.core.*;
import org.basex.core.cmd.*;
import org.basex.core.cmd.Set;
import org.basex.index.query.*;
import org.basex.index.value.*;
import org.basex.util.hash.*;
import org.junit.*;
import org.junit.Test;
import org.junit.runner.*;
import org.junit.runners.*;
import org.junit.runners.Parameterized.Parameters;
/**
* Tests for the value index.
*
* @author BaseX Team 2005-17, BSD License
* @author Jens Erat
*/
@RunWith(Parameterized.class)
public final class ValueIndexTest extends SandboxTest {
/** Test file. */
private static final String FILE = "src/test/resources/test.xml";
/** Test parameters. */
private final Collection<Set> paramSet;
/**
* Runs tests with different parameters, like in-memory or disk databases.
* @return collection of parameter sets
*/
@Parameters
public static Collection<Object[]> generateParams() {
final List<Object[]> paramsSet = new ArrayList<>();
paramsSet.add(paramSet(false, false));
paramsSet.add(paramSet(true, false));
paramsSet.add(paramSet(false, true));
paramsSet.add(paramSet(true, true));
return paramsSet;
}
/**
* Return parameter set for parameterized execution.
* @param mainmem MAINMEM option
* @param updindex UPDINDEX option
* @return parameter set
*/
private static Object[] paramSet(final boolean mainmem, final boolean updindex) {
final ArrayList<Set> params = new ArrayList<>();
params.add(new Set(MainOptions.MAINMEM, mainmem));
params.add(new Set(MainOptions.UPDINDEX, updindex));
final ArrayList<ArrayList<Set>> paramArray = new ArrayList<>();
paramArray.add(params);
return paramArray.toArray();
}
/**
* Apply parameter sets.
* @param paramSet parameter set for current test run
*/
public ValueIndexTest(final Collection<Set> paramSet) {
this.paramSet = paramSet;
}
/** Set down database. */
@After
public void setDown() {
set(MainOptions.MAINMEM, false);
set(MainOptions.UPDINDEX, false);
execute(new DropDB(NAME));
}
/**
* Tests the text index.
*/
@Test
public void textIndexTest() {
final LinkedHashMap<String, Integer> tokens = new LinkedHashMap<>();
tokens.put("3", 3);
tokens.put("3.4", 1);
tokens.put("text in child", 1);
tokens.put("nonexistant", 0);
tokens.put("", 0);
valueIndexTest(IndexType.TEXT, tokens, paramSet);
}
/**
* Tests the attribute index.
*/
@Test
public void attributeIndexTest() {
final LinkedHashMap<String, Integer> tokens = new LinkedHashMap<>();
tokens.put("context", 1);
tokens.put("baz bar blu", 1);
tokens.put("baz", 0);
tokens.put("bar", 0);
tokens.put("blu", 0);
tokens.put("", 0);
tokens.put("nonexistant", 0);
valueIndexTest(IndexType.ATTRIBUTE, tokens, paramSet);
}
/**
* Tests the token index.
*/
@Test
public void tokenIndexTest() {
set(MainOptions.TOKENINDEX, true);
final LinkedHashMap<String, Integer> tokens = new LinkedHashMap<>();
tokens.put("context", 1);
tokens.put("baz bar blu", 0);
tokens.put("baz", 1);
tokens.put("bar", 1);
tokens.put("blu", 1);
tokens.put("", 0);
tokens.put("nonexistant", 0);
valueIndexTest(IndexType.TOKEN, tokens, paramSet);
}
/**
* Tests the index: fetch results for different tokens, compare whether the right node was
* returned and verify against the expected result size.
* @param indexType text or attribute index
* @param tokens map of search tokens
* @param options options to apply
*/
private static void valueIndexTest(final IndexType indexType, final LinkedHashMap<String,
Integer> tokens, final Collection<Set> options) {
// set up environment
for(final Set option : options) execute(option);
execute(new CreateDB(NAME, FILE));
// fetch index reference to be tested
final boolean text = indexType == IndexType.TEXT;
final ValueIndex index = (ValueIndex) context.data().index(indexType);
// receive, verify and count results for passed tokens
for(final Entry<String, Integer> entry : tokens.entrySet()) {
final byte[] token = token(entry.getKey());
final IndexIterator it = index.iter(new IndexEntries(token, indexType));
long count = 0;
while(it.more()) {
final int pre = it.pre();
final byte[] result = context.data().text(pre, text);
if(indexType == IndexType.TOKEN)
assertTrue("Token '" + entry.getKey() + "' not found in match '" + string(result) + "'!",
new TokenSet(distinctTokens(result)).contains(token(entry.getKey())));
else
assertEquals("Wrong result returned!", entry.getKey(), string(result));
count++;
}
assertEquals("Wrong number of nodes returned: \"" + entry.getKey() + "\": ",
(long) entry.getValue(), count);
}
}
}