/*******************************************************************************
* Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University
* as Operator of the SLAC National Accelerator Laboratory.
* Copyright (c) 2011 Brookhaven National Laboratory.
* EPICS archiver appliance is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*******************************************************************************/
package edu.stanford.slac.archiverappliance.PB.search;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Random;
import org.apache.log4j.Logger;
import org.epics.archiverappliance.config.ConfigServiceForTests;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import edu.stanford.slac.archiverappliance.PB.utils.LineByteStream;
/**
* Test a file event stream
* @author mshankar
*
*/
public class FileEventStreamSearchTest {
private static final Logger logger = Logger.getLogger(FileEventStreamSearchTest.class);
String pathName = ConfigServiceForTests.getDefaultPBTestFolder() + "/" + "FileEventStreamSearchTest.txt";
Path path = Paths.get(pathName);
@Before
public void setUp() throws Exception {
Files.deleteIfExists(path);
EvenNumberSampleFileGenerator.generateSampleFile(pathName);
}
@After
public void tearDown() throws Exception {
Files.deleteIfExists(path);
}
@Test
public void testSeekToTime() throws Exception {
// Check for lower boundary conditions
for(int i = -1000; i < 1000; i++) {
seekAndCheck(path, i);
}
// Test in the middle
for(int i = EvenNumberSampleFileGenerator.MAXSAMPLEINT/2; i < EvenNumberSampleFileGenerator.MAXSAMPLEINT/2+1000; i++) {
seekAndCheck(path, i);
}
// Check for upper boundary conditions
for(int i = EvenNumberSampleFileGenerator.MAXSAMPLEINT - 1000; i < EvenNumberSampleFileGenerator.MAXSAMPLEINT+1000; i++) {
seekAndCheck(path, i);
}
// Test randomly
Random random = new Random();
for(int i = 0; i < 10000; i++) {
seekAndCheck(path, random.nextInt(EvenNumberSampleFileGenerator.MAXSAMPLEINT));
}
}
// The exhaustive test takes about 30 minutes to run.
// So, if we suspect something is wrong with searches, uncomment and run.
// Otherwise, the testSeekToTime test should be more than adequate.
//
// @Test
// public void exhaustiveTest() throws Exception {
// for(int i = 0; i < TestSampleGenerator.MAXSAMPLEINT; i++) {
// seekAndCheck(f, i);
// }
// }
private static void seekAndCheck(Path path, final int searchNum) throws IOException {
try {
CompareEventLine compare = new CompareEventLine() {
@Override
public CompareEventLine.NextStep compare(byte[] line1, byte[] line2) {
try {
String inputline1 = new String(line1, "UTF-8");
int inputNum1 = Integer.parseInt(inputline1);
int inputNum2 = Integer.MAX_VALUE;
if(line2 != null) {
String inputline2 = new String(line2, "UTF-8");
inputNum2 = Integer.parseInt(inputline2);
}
if(inputNum1 > searchNum) {
logger.debug("When searching for " + searchNum + ", comparing with " + inputNum1 + " and " + inputNum2 + " sayz GO_LEFT 1");
return NextStep.GO_LEFT;
} else if(inputNum2 < searchNum) {
logger.debug("When searching for " + searchNum + ", comparing with " + inputNum1 + " and " + inputNum2 + " sayz GO_RIGHT 2");
return NextStep.GO_RIGHT;
} else {
if(line2 != null) {
if(inputNum1 < searchNum && inputNum2 >= searchNum) {
logger.debug("When searching for " + searchNum + ", comparing with " + inputNum1 + " and " + inputNum2 + " sayz STAY_WHERE_YOU_ARE 3");
return NextStep.STAY_WHERE_YOU_ARE;
} else {
logger.debug("When searching for " + searchNum + ", comparing with " + inputNum1 + " and " + inputNum2 + " sayz GO_LEFT 4");
return NextStep.GO_LEFT;
}
} else {
logger.debug("When searching for " + searchNum + ", comparing with " + inputNum1 + " and " + inputNum2 + " sayz STAY_WHERE_YOU_ARE 5");
return NextStep.STAY_WHERE_YOU_ARE;
}
}
} catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex);}
}
};
FileEventStreamSearch bs = new FileEventStreamSearch(path, 0L);
boolean found = bs.seekToTime(compare);
if(!found) {
if(searchNum >= 0 && searchNum < EvenNumberSampleFileGenerator.MAXSAMPLEINT) {
if(searchNum == 0) {
logger.debug("0 is a special case as it is the first item on the list and technically we did not find an event that satisfies the conditions.");
} else {
fail("Failure when searching for " + searchNum);
}
} else {
// The number was out of range anyways...
}
} else {
// Check to see if s1 <= t1 < s2
try(LineByteStream lis = new LineByteStream(path, bs.getFoundPosition())) {
lis.seekToFirstNewLine();
byte[] line1 = lis.readLine();
byte[] line2 = lis.readLine();
if(line1 == null || line2 == null || line1.length == 0 || line2.length == 0) {
if(searchNum >=0 && searchNum < EvenNumberSampleFileGenerator.MAXSAMPLEINT) {
fail("One of the lines was null but we could not find the number " + searchNum);
} else {
// In this case, we really did not find the event as it is out of range.
}
} else {
int num1 = Integer.parseInt(new String(line1, "UTF-8"));
int num2 = Integer.parseInt(new String(line2, "UTF-8"));
// s1 <= t1 < s2
if(num1 < searchNum && searchNum <= num2) {
} else {
if(searchNum >=0 && searchNum < EvenNumberSampleFileGenerator.MAXSAMPLEINT) {
fail("Potential failure - could not locate " + searchNum);
} else {
// In this case, we really did not find the event as it is out of range.
}
}
}
}
}
}
catch(Exception ex) {
logger.error(ex.getMessage(), ex);
System.err.println("Exception when searching for " + searchNum);
}
}
}