content: package edu.berkeley.cs.succinct;
  
  import edu.berkeley.cs.succinct.regex.RegExMatch;
  import edu.berkeley.cs.succinct.util.Source;
  import junit.framework.TestCase;
  
  import java.util.Iterator;
  import java.util.Set;
  
  import static edu.berkeley.cs.succinct.TestUtils.stringCount;
  
  abstract public class SuccinctFileTest extends TestCase {
  
    protected SuccinctFile sFile;
    protected Source fileData;
  
    abstract public String getQueryString(int i);
  
    abstract public int numQueryStrings();
  
    abstract public String getData();
  
    /**
     * Test method: char charAt(long i)
     *
     * @throws Exception
     */
    public void testCharAt() throws Exception {
  
      for (int i = 0; i < sFile.getSize() - 1; i++) {
        char c = sFile.charAt(i);
        assertEquals(fileData.get(i), c);
      }
    }
  
    /**
     * Test method: byte[] extract(int offset, int len)
     *
     * @throws Exception
     */
    public void testExtract() throws Exception {
  
      String buf1 = sFile.extract(0, 100);
      assertEquals(100, buf1.length());
      for (int i = 0; i < 100; i++) {
        assertEquals(fileData.get(i), buf1.charAt(i));
      }
  
      String buf2 = sFile.extract(fileData.length() - 101, 100);
      assertEquals(100, buf2.length());
      for (int i = 0; i < 100; i++) {
        assertEquals(fileData.get(fileData.length() - 101 + i), buf2.charAt(i));
      }
    }
  
    /**
     * Test method: byte[] extractUntil(int offset, char delim)
     *
     * @throws Exception
     */
    public void testExtractBytesUntil() throws Exception {
  
      String buf = sFile.extractUntil(0, '\n');
      for (int i = 0; i < buf.length(); i++) {
        assertEquals(fileData.get(i), buf.charAt(i));
        assertFalse(buf.charAt(i) == '\n');
      }
      assertEquals(fileData.get(buf.length()), '\n');
    }
  
    /**
     * Test method: long count(byte[] query)
     *
     * @throws Exception
     */
    public void testCount() throws Exception {
  
      for (int i = 0; i < numQueryStrings(); i++) {
        String query = getQueryString(i);
        long count = sFile.count(query.toCharArray());
        long expected = stringCount(getData(), query);
        assertEquals(expected, count);
      }
  
    }
  
    /**
     * Test method: long[] search(byte[] query)
     *
     * @throws Exception
     */
    public void testSearch() throws Exception {
      for (int i = 0; i < numQueryStrings(); i++) {
        String query = getQueryString(i);
        Long[] positions = sFile.search(query.toCharArray());
        assertEquals(stringCount(getData(), query), positions.length);
        for (Long pos : positions) {
          for (int j = 0; j < query.length(); j++) {
            assertEquals(query.charAt(j), fileData.get((int) (pos + j)));
          }
        }
      }
    }
  
    /**
     * Test method: Iterator<Long> searchIterator(byte[] query)
     *
     * @throws Exception
     */
    public void testSearchIterator() throws Exception {
  
      for (int i = 0; i < numQueryStrings(); i++) {
        String query = getQueryString(i);
        Iterator<Long> positions = sFile.searchIterator(query.toCharArray());
        long count = 0;
        while (positions.hasNext()) {
          long pos = positions.next();
          for (int j = 0; j < query.length(); j++) {
            assertEquals(query.charAt(j), fileData.get((int) (pos + j)));
          }
          count++;
        }
        assertEquals(stringCount(getData(), query), count);
      }
    }
  
    /**
     * Helper method to check results for a regex query.
     *
     * @param results Results to check.
     * @param exp     Expression to check against.
     * @return The check result.
     */
    protected boolean checkResults(Set<RegExMatch> results, String exp) {
      for (RegExMatch m : results) {
        for (int i = 0; i < exp.length(); i++) {
          if (fileData.get(((int) (m.getOffset() + i))) != exp.charAt(i)) {
            return false;
          }
        }
      }
      return true;
    }
  
    /**
     * Helper method to check results for a union query.
     *
     * @param results Results to check.
     * @param exp1    First expression to check against.
     * @param exp2    Second expression to check against.
     * @return The check result.
     */
    protected boolean checkResultsUnion(Set<RegExMatch> results, String exp1, String exp2) {
      for (RegExMatch m : results) {
        boolean flagFirst = true;
        boolean flagSecond = true;
        for (int i = 0; i < exp1.length(); i++) {
          if (fileData.get((int) (m.getOffset() + i)) != exp1.charAt(i)) {
            flagFirst = false;
          }
        }
  
        for (int i = 0; i < exp2.length(); i++) {
          if (fileData.get((int) (m.getOffset() + i)) != exp2.charAt(i)) {
            flagSecond = false;
          }
        }
  
        if (!flagFirst && !flagSecond)
          return false;
      }
      return true;
    }
  
    /**
     * Helper method to check results for a regex repeat query.
     *
     * @param results Results to check.
     * @param exp     Expression to check against.
     * @return The check result.
     */
    protected boolean checkResultsRepeat(Set<RegExMatch> results, String exp) {
      for (RegExMatch m : results) {
        for (int i = 0; i < m.getLength(); i++) {
          if (fileData.get(((int) (m.getOffset() + i))) != exp.charAt(i % exp.length())) {
            return false;
          }
        }
      }
      return true;
    }
  }
  