/*
* Copyright (C) 2014 Indeed Inc.
*
* 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.indeed.flamdex.fieldcache;
import com.google.common.collect.Lists;
import com.google.common.primitives.Longs;
import com.indeed.util.io.Files;
import com.indeed.flamdex.api.IntValueLookup;
import com.indeed.flamdex.reader.MockFlamdexReader;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author jsgroth
*/
public class TestFieldCacher {
private final Random rand = new Random();
@Test
public void testFieldCacher() throws IOException {
runCacheTest(Integer.MAX_VALUE, 65535, FieldCacher.INT, 40);
runCacheTest(65535, 255, FieldCacher.CHAR, 20);
runCacheTest(255, 1, FieldCacher.BYTE, 10);
runCacheTest(1, 0, FieldCacher.BITSET, 8);
}
private void runCacheTest(int maxVal, int lowerMaxVal, FieldCacher expectedType, long expectedMemory) throws IOException {
for (int i = 0; i < 10; ++i) {
MockFlamdexReader r = new MockFlamdexReader(Arrays.asList("f"), Collections.<String>emptyList(), Arrays.asList("f"), 10);
long maxTerm = rand.nextInt(maxVal - lowerMaxVal) + lowerMaxVal + 1;
int maxTermDoc = rand.nextInt(10);
r.addIntTerm("f", maxTerm, maxTermDoc);
List<Integer> docs = Lists.newArrayList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
docs.remove(Integer.valueOf(maxTermDoc));
Set<Integer> terms = new HashSet<Integer>();
long[] cache = new long[10];
cache[maxTermDoc] = maxTerm;
if (lowerMaxVal >= docs.size()) {
while (!docs.isEmpty()) {
int numDocs = docs.size() > 1 ? rand.nextInt(docs.size() - 1) + 1 : 1;
int term = rand.nextInt(lowerMaxVal + 1);
if (terms.contains(term)) continue;
List<Integer> termDocs = new ArrayList<Integer>();
for (int j = 0; j < numDocs; ++j) {
termDocs.add(docs.remove(rand.nextInt(docs.size())));
}
Collections.sort(termDocs);
r.addIntTerm("f", term, termDocs);
terms.add(term);
for (int doc : termDocs) {
cache[doc] = term;
}
}
} else {
int term = rand.nextInt(lowerMaxVal + 1);
r.addIntTerm("f", term, docs);
for (int doc : docs) {
cache[doc] = term;
}
}
FieldCacher fieldCacher = FieldCacher.getCacherForField("f", r);
assertEquals(expectedType, fieldCacher);
assertEquals(expectedMemory, fieldCacher.memoryRequired(r.getNumDocs()));
IntValueLookup ivl = fieldCacher.newFieldCache("f", r);
verifyCache(cache, ivl);
String tempDir = Files.getTempDirectory("asdf", "");
for (int x = 0; x < 5; ++x) {
if (x > 0) {
assertTrue(new File(tempDir, fieldCacher.getMMapFileName("f")).exists());
} else {
assertFalse(new File(tempDir, fieldCacher.getMMapFileName("f")).exists());
}
IntValueLookup mmivl = fieldCacher.newMMapFieldCache("f", r, tempDir);
verifyCache(cache, mmivl);
assertTrue(new File(tempDir, fieldCacher.getMMapFileName("f")).exists());
mmivl.close();
assertTrue(new File(tempDir, fieldCacher.getMMapFileName("f")).exists());
}
Files.delete(tempDir);
}
}
private static void verifyCache(long[] cache, IntValueLookup ivl) {
int[] docIds = new int[10];
for (int j = 0; j < 10; ++j) docIds[j] = j;
long[] values = new long[10];
ivl.lookup(docIds, values, 10);
assertEquals(Longs.asList(cache), Longs.asList(values));
}
}