Package com.google.enterprise.connector.otex

Source Code of com.google.enterprise.connector.otex.LivelinkTraversalManagerTest

// Copyright 2007 Google 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.google.enterprise.connector.otex;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.enterprise.connector.otex.client.Client;
import com.google.enterprise.connector.otex.client.ClientValue;
import com.google.enterprise.connector.otex.client.mock.MockClient;
import com.google.enterprise.connector.otex.client.mock.MockClientValue;
import com.google.enterprise.connector.spi.Document;
import com.google.enterprise.connector.spi.DocumentList;
import com.google.enterprise.connector.spi.RepositoryException;
import com.google.enterprise.connector.spi.Session;
import com.google.enterprise.connector.spi.SpiConstants;
import com.google.enterprise.connector.spi.Value;

import junit.framework.TestCase;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* Tests the construction of the queries for traversing Livelink.
*
* Note that many tests provide a candidates predicate of
* <code>null</code>, which is invalid. This leads to the string
* "null" appearing in the SQL query as a predicate, which is also
* invalid. But for our purposes this is OK, since it shows the
* candidates predicate being included in the query, which is all we
* need.
*/
public class LivelinkTraversalManagerTest extends TestCase {
    private LivelinkConnector conn;

  private final JdbcFixture jdbcFixture = new JdbcFixture();

  private final LivelinkDateFormat dateFormat =
      LivelinkDateFormat.getInstance();

  @Override
  protected void setUp() throws RepositoryException, SQLException {
    conn = LivelinkConnectorFactory.getConnector("connector.");

    jdbcFixture.setUp();
    jdbcFixture.executeUpdate(
        // Try inserting the DAuditNew entries out of date order, in
        // case that influences the natural order returned by the DB,
        // since we want an ORDER BY to pick the latest date.
        "insert into DAuditNew(EventID, AuditDate) "
        + "values(10017, timestamp'2001-01-01 00:00:00')",
        "insert into DAuditNew(EventID, AuditDate) "
        + "values(10042, timestamp'2013-04-24 08:00:00')",
        "insert into DAuditNew(EventID, AuditDate) "
        + "values(10024, timestamp'2005-10-06 12:34:56')",
        "insert into DTree(DataID, ParentID, OwnerID, SubType, ModifyDate) "
        + "values(24, 6, -2000, 0, timestamp'2001-01-01 00:00:00')",
        "insert into DTree(DataID, ParentID, OwnerID, SubType, ModifyDate) "
        + "values(42, 6, -2000, 144, timestamp'2001-01-01 00:00:00')",
        "insert into DTree(DataID, ParentID, OwnerID, SubType, ModifyDate) "
        + "values(66, 6, -2000, 144, timestamp'2002-02-02 00:00:00')",
        "insert into DTree(DataID, ParentID, OwnerID, SubType, ModifyDate) "
        + "values(6, 2000, -2000, 0, timestamp'2002-02-02 00:00:00')",
        "insert into DTree(DataID, ParentID, OwnerID, SubType, ModifyDate) "
        + "values(2000, -1, -2000, 141, timestamp'2001-01-01 00:00:00')",
        "insert into DTree(DataID, ParentID, OwnerID, SubType, ModifyDate) "
        + "values(2901, -1, -2901, 901, timestamp'2001-01-01 00:00:00')",
        "insert into DTreeAncestors(DataID, AncestorID) "
        + "values(24, 6)",
        "insert into DTreeAncestors(DataID, AncestorID) "
        + "values(42, 6)",
        "insert into DTreeAncestors(DataID, AncestorID) "
        + "values(66, 6)",
        "insert into DTreeAncestors(DataID, AncestorID) "
        + "values(6, 2000)",
        "insert into DTreeAncestors(DataID, AncestorID) "
        + "values(2000, -1)",
        "insert into KUAF(ID, Name, Type, GroupID, UserData) "
        + " values(1001, 'user1', 0, 2001, 'ExternalAuthentication=true' )",
        "insert into WebNodes(DataID, ParentID, OwnerID, SubType, ModifyDate, "
        + "MimeType, UserID) "
        + "values(24, 6, -2000, 0, timestamp'2001-01-01 00:00:00', null, 1001)",
        "insert into WebNodes(DataID, ParentID, OwnerID, SubType, ModifyDate, "
        + "MimeType, DataSize, UserID) "
        + "values(42, 6, -2000, 144, timestamp'2001-01-01 00:00:00', "
        + "'text/xml', 1729, 1001)",
        "insert into WebNodes(DataID, ParentID, OwnerID, SubType, ModifyDate, "
        + "MimeType, DataSize, UserID) "
        + "values(66, 6, -2000, 144, sysdate, 'text/xml', 1729, 1001)",
        "insert into WebNodes(DataID, ParentID, OwnerID, SubType, ModifyDate, "
        + "MimeType, UserID) "
        + "values(2901, -1, -2901, 901, timestamp'2001-01-01 00:00:00', null,"
        + " 1001)");
  }

  @Override
  protected void tearDown() throws SQLException {
    jdbcFixture.tearDown();
  }

  private void assertIncludedEmpty(String included) {
    assertFalse(included, included.contains("and (DataID in"));
    assertFalse(included, included.contains("and -OwnerID not in"));
  }

  private void assertExcludedEmpty(String excluded) {
    assertFalse(excluded, excluded.contains("and SubType not in"));
    assertFalse(excluded, excluded.contains("and not"));
  }

  public void testGetLastAuditEvent() throws RepositoryException {
    Session sess = conn.login();
    LivelinkTraversalManager ltm =
        (LivelinkTraversalManager) sess.getTraversalManager();

    ClientValue results = ltm.getLastAuditEvent();
    assertEquals(1, results.size());
    // toLong works with H2 (we check the type in the production code).
    assertEquals(10042L, results.toLong(0, "EventID"));
    // The fractional seconds are OK, because LivelinkDateFormat.parse
    // handles multiple variations in the timestamp strings.
    assertEquals("2013-04-24 08:00:00.0", results.toString(0, "AuditDate"));
  }

  /**
   * A helper method for the tests. The checkCandidatesTimeWarp method
   * was intentionally left with higher-level arguments to test the
   * extraction of the necessary dates. So the tests cover a little
   * more code, at the cost of this extra helper method to make the
   * tests simpler again.
   *
   * @param firstCandidateDate the ModifyDate of the first result row
   * @param lastCandidateDate the ModifyDate of the last result row,
   *     usually valid or invalid in opposition to {@code
   *     firstCandidateDate}, to make sure the check isn't using this
   *     value
   * @param checkpointDate the supposed starting point for the batch
   */
  private void checkCandidatesTimeWarp(Date firstCandidateDate,
      int firstCandidateId, Date lastCandidateDate, int lastCandidateId,
      String checkpoint) throws RepositoryException {
    Session sess = conn.login();
    LivelinkTraversalManager ltm =
        (LivelinkTraversalManager) sess.getTraversalManager();
    ClientValue candidates = new MockClientValue(
        new String[] { "ModifyDate", "DataID" },
        new Object[][] { { firstCandidateDate, firstCandidateId },
                         { lastCandidateDate, lastCandidateId } });
    ltm.checkCandidatesTimeWarp(candidates, new Checkpoint(checkpoint));
  }

  private void failCandidatesTimeWarp(Date firstCandidateDate,
      int firstCandidateId, Date lastCandidateDate, int lastCandidateId,
      String checkpoint) throws RepositoryException {
    try {
      checkCandidatesTimeWarp(firstCandidateDate, firstCandidateId,
          lastCandidateDate, lastCandidateId, checkpoint);
      fail("Expected a RepositoryException");
    } catch (RepositoryException expected) {
      assertTrue(expected.getMessage(),
          expected.getMessage().contains("CANDIDATES TIME WARP"));
    }
  }

  /** Checking time warp is disabled by default. */
  public void testCandidatesTimeWarp_default() throws RepositoryException {
    Date first = dateFormat.parse("2013-08-26 16:31:00");
    checkCandidatesTimeWarp(first, 0, first, 0, "2014-01-01 00:00:00,0");
  }

  public void testCandidatesTimeWarp_disabled() throws RepositoryException {
    conn.setCandidatesTimeWarpFuzz(-1);

    Date first = dateFormat.parse("2013-08-26 16:31:00");
    checkCandidatesTimeWarp(first, 0, first, 0, "2014-01-01 00:00:00,0");
  }

  public void testCandidatesTimeWarp_enabledBadDate()
      throws RepositoryException {
    conn.setCandidatesTimeWarpFuzz(0);

    Date first = dateFormat.parse("2013-08-26 16:31:00");
    Date last = dateFormat.parse("2014-08-26 16:31:00");
    failCandidatesTimeWarp(first, 0, last, 0, "2014-01-01 00:00:00,0");
  }

  public void testCandidatesTimeWarp_enabledBadId() throws RepositoryException {
    conn.setCandidatesTimeWarpFuzz(0);

    Date first = dateFormat.parse("2014-01-01 00:00:00");
    failCandidatesTimeWarp(first, 0, first, 1000, "2014-01-01 00:00:00,999");
  }

  /**
   * The last candidate is impossibly set before the first candidate
   * and the checkpoint.
   */
  public void testCandidatesTimeWarp_enabledGoodDate()
      throws RepositoryException {
    conn.setCandidatesTimeWarpFuzz(0);

    Date first = dateFormat.parse("2014-01-26 16:31:00");
    Date last = dateFormat.parse("2013-08-26 16:31:00");
    checkCandidatesTimeWarp(first, 0, last, 0, "2014-01-01 00:00:00,0");
  }

  /**
   * The last candidate is impossibly set before the first candidate
   * and the checkpoint.
   */
  public void testCandidatesTimeWarp_enabledGoodId()
      throws RepositoryException {
    conn.setCandidatesTimeWarpFuzz(0);

    Date first = dateFormat.parse("2014-01-01 00:00:00");
    checkCandidatesTimeWarp(first, 1000, first, 0, "2014-01-01 00:00:00,999");
  }

  /**
   * Livelink only stores timestamps to the nearest second, but LAPI
   * 9.7 and earlier constructs a Date object that includes
   * milliseconds, which are taken from the current time.
   */
  public void testCandidatesTimeWarp_enabledMilliseconds()
      throws RepositoryException {
    conn.setCandidatesTimeWarpFuzz(0);

    Date first = dateFormat.parse("2014-01-01 00:00:00.999");
    Date last = dateFormat.parse("2014-01-01 00:00:01.999");
    failCandidatesTimeWarp(first, 999, last, 999, "2014-01-01 00:00:00,1000");
  }

  /**
   * Sets the fuzz to 30 days and test an even later candidate. The
   * last candidate is impossibly set before the first candidate,
   * inside the 30 day fuzz.
   */
  public void testCandidatesTimeWarp_futureFailure()
      throws RepositoryException {
    conn.setCandidatesTimeWarpFuzz(30);

    Date first = dateFormat.parse("2014-08-26 16:31:00");
    Date last = dateFormat.parse("2014-01-26 16:31:00");
    failCandidatesTimeWarp(first, 0, last, 0, "2014-01-01 00:00:00,0");
  }

  /**
   * Sets the first candidate inside the 30 day fuzz, and the last
   * candidate outside it (which is fine).
   */
  public void testCandidatesTimeWarp_futureSuccess()
      throws RepositoryException {
    conn.setCandidatesTimeWarpFuzz(30);

    Date first = dateFormat.parse("2014-01-26 16:31:00");
    Date last = dateFormat.parse("2014-08-26 16:31:00");
    checkCandidatesTimeWarp(first, 0, last, 0, "2014-01-01 00:00:00,0");
  }

  /** Calls the like-named method under test. */
  private String getMatchingQuery() throws RepositoryException {
    Session sess = conn.login();
    LivelinkTraversalManager ltm =
        (LivelinkTraversalManager) sess.getTraversalManager();
    return ltm.getMatchingQuery(null, new Date(), false);
  }

    public void testExcludedNodes1() throws RepositoryException {
        // No excluded nodes configured.

        String query = getMatchingQuery();

        assertTrue(query, query.indexOf("and SubType not in "
                + "(137,142,143,148,150,154,161,162,201,203,209,210,211,"
                + "345,346,361,374,431,441,3030004,3030201)") != -1);
    }

    public void testExcludedNodes2() throws RepositoryException {
        conn.setExcludedVolumeTypes("");
        conn.setExcludedNodeTypes("");
        conn.setExcludedLocationNodes("");

        String query = getMatchingQuery();

        assertExcludedEmpty(query);
    }

    public void testExcludedNodes3() throws RepositoryException {
        conn.setExcludedVolumeTypes("2001,4104");
        conn.setExcludedNodeTypes("");
        conn.setExcludedLocationNodes("");

        String query = getMatchingQuery();

        assertExcludedEmpty(query);
    }

    public void testExcludedNodes4() throws RepositoryException {
        conn.setExcludedVolumeTypes("");
        conn.setExcludedNodeTypes(
            "137,142,143,148,150,154,161,162,201,203,209,210,211");
        conn.setExcludedLocationNodes("");

        String query = getMatchingQuery();

        assertTrue(query, query.indexOf("and SubType not in " +
            "(137,142,143,148,150,154,161,162,201,203,209,210,211)") != -1);
    }

    public void testExcludedNodes5() throws RepositoryException {
        conn.setExcludedVolumeTypes("148,162");
        conn.setExcludedNodeTypes("");
        conn.setExcludedLocationNodes("");

        String query = getMatchingQuery();

        assertExcludedEmpty(query);
        assertTrue(query, query.indexOf("and -OwnerID not in") != -1);
        assertTrue(query,
            query.indexOf("SubType in (148,162)") != -1);
    }

    public void testExcludedNodes6() throws RepositoryException {
        conn.setExcludedVolumeTypes("");
        conn.setExcludedNodeTypes("");
        conn.setExcludedLocationNodes("13832");

        String query = getMatchingQuery();

        String expectedExcluded = "and not (DataID in (13832) or " +
            "DataID in (select DataID from DTreeAncestors where " +
            "DataID in (null) and AncestorID in (13832,-13832)))";
        assertTrue(query, query.indexOf(expectedExcluded) != -1);

        conn.setExcludedVolumeTypes("2001,4104");
        conn.setExcludedLocationNodes("13832");

        String query2 = getMatchingQuery();

        assertTrue(query2, query2.indexOf(expectedExcluded) != -1);
    }

    public void testExcludedNodes7() throws RepositoryException {
        conn.setExcludedVolumeTypes("148,162");
        conn.setExcludedNodeTypes(
            "137,142,143,148,150,154,161,162,201,203,209,210,211");
        conn.setExcludedLocationNodes("");

        String query = getMatchingQuery();

        assertTrue(query, query.indexOf("and SubType not in " +
            "(137,142,143,148,150,154,161,162,201,203,209,210,211)") != -1);
        assertTrue(query, query.indexOf("and -OwnerID not in") != -1);
        assertTrue(query,
            query.indexOf("SubType in (148,162)") != -1);
    }

    public void testExcludedNodes8() throws RepositoryException {
        conn.setExcludedVolumeTypes("148,162");
        conn.setExcludedNodeTypes("");
        conn.setExcludedLocationNodes("13832");

        String query = getMatchingQuery();

        assertTrue(query, query.indexOf("and not (DataID in (13832) or " +
            "DataID in (select DataID from DTreeAncestors where " +
            "DataID in (null) and AncestorID in (13832,-13832)))") != -1);
        assertTrue(query, query.indexOf("and -OwnerID not in") != -1);
        assertTrue(query,
            query.indexOf("SubType in (148,162)") != -1);
    }

    public void testExcludedNodes9() throws RepositoryException {
        conn.setExcludedVolumeTypes("");
        conn.setExcludedNodeTypes(
            "137,142,143,148,150,154,161,162,201,203,209,210,211");
        conn.setExcludedLocationNodes("13832");

        String query = getMatchingQuery();

        assertIncludedEmpty(query);
        assertTrue(query, query.indexOf("and SubType not in " +
            "(137,142,143,148,150,154,161,162,201,203,209,210,211) and " +
            "not (DataID in (13832) or DataID in (select DataID from " +
            "DTreeAncestors where DataID in (null) and " +
            "AncestorID in (13832,-13832)))") != -1);
    }

    public void testExcludedNodes10() throws RepositoryException {
        conn.setExcludedVolumeTypes("148,162");
        conn.setExcludedNodeTypes(
            "137,142,143,148,150,154,161,162,201,203,209,210,211");
        conn.setExcludedLocationNodes("13832");

        String query = getMatchingQuery();

        assertTrue(query, query.indexOf("and SubType not in " +
            "(137,142,143,148,150,154,161,162,201,203,209,210,211) and " +
            "not (DataID in (13832) or DataID in (select DataID from " +
            "DTreeAncestors where DataID in (null) and " +
            "AncestorID in (13832,-13832)))") != -1);
        assertTrue(query, query.indexOf("and -OwnerID not in") != -1);
        assertTrue(query,
            query.indexOf("SubType in (148,162)") != -1);
    }

    /**
     * As an aside, excludedVolumeTypes and includedLocationNodes are
     * mutually exclusive, and includedLocationNodes wins.
     */
    public void testExcludedNodes11() throws RepositoryException {
        conn.setExcludedVolumeTypes("148,162");
        conn.setExcludedNodeTypes("");
        conn.setExcludedLocationNodes("");
        conn.setIncludedLocationNodes("2000");

        String query = getMatchingQuery();

        assertExcludedEmpty(query);
        assertTrue(query, query.indexOf(
            " and (DataID in (2000) or DataID in (select DataID from "
            + "DTreeAncestors where DataID in (null) "
            + "and AncestorID in (2000,-2000)))") != -1);
    }

    /** Test the default exclusions. */
    public void testExcludedNodes12() throws RepositoryException {
        String query = getMatchingQuery();

        assertTrue(query, query.indexOf("and SubType not in "
            + "(137,142,143,148,150,154,161,162,201,203,209,210,211,"
            + "345,346,361,374,431,441,3030004,3030201)") != -1);
        assertTrue(query, query.indexOf("and -OwnerID not in") != -1);
        assertTrue(query,
            query.indexOf("SubType in (148,161,162,901)") != -1);
    }

  public void testUseDTreeAncestors_true() throws RepositoryException {
    conn.setExcludedLocationNodes("13832");
    conn.setIncludedLocationNodes("2000");
    conn.setUseDTreeAncestors(true);

    String query = getMatchingQuery();

    // The included and excluded conditions are nearly identical, but
    // the excluded portion starts with "and NOT".
    assertTrue(query, query.contains(
        "and not (DataID in (13832) or DataID in (select DataID from "
        + "DTreeAncestors where DataID in (null) "
        + "and AncestorID in (13832,-13832)))"));
    assertTrue(query, query.contains(
        " and (DataID in (2000) or DataID in (select DataID from "
        + "DTreeAncestors where DataID in (null) "
        + "and AncestorID in (2000,-2000)))"));
  }

  public void testUseDTreeAncestors_false() throws RepositoryException {
    conn.setExcludedLocationNodes("13832");
    conn.setIncludedLocationNodes("2000");
    conn.setUseDTreeAncestors(false);

    String query = getMatchingQuery();

    assertFalse(query, query.contains("DTreeAncestors"));
  }

    /** Tests a null select expressions map. */
    public void testIncludedSelectExpressions_null()
            throws RepositoryException {
        testIncludedSelectExpressions(null);
    }

    /** Tests an empty select expressions map. */
    public void testIncludedSelectExpressions_empty()
            throws RepositoryException {
      Map<String, String> empty = ImmutableMap.of();
      testIncludedSelectExpressions(empty);
    }

    /** Tests a singleton select expressions map. */
    public void testIncludedSelectExpressions_singleton()
            throws RepositoryException {
        testIncludedSelectExpressions(
            ImmutableMap.of("propname", "'a string literal'"));
    }

    /** Tests a larger select expressions map. */
    public void testIncludedSelectExpressions_multiple()
            throws RepositoryException {
      ImmutableMap.Builder<String, String> map =
          new ImmutableMap.Builder<String, String>();
      // There is no syntax checking on these values. I'm just giving
      // strange but plausible values.
      map.put("propname", "'a string literal'");
      map.put("siblingCount",
          "(select count(*)-1 from DTree d where d.ParentID = a.ParentID)");
      map.put("google:folder", "storedProcedure(DataID)");
      testIncludedSelectExpressions(map.build());
    }

    /**
     * Tests setting the included select expressions, comparing the
     * resulting fields array and select list array to the expected
     * output.
     *
     * @param map the included select expressions, may be {@code null}
     */
    private void testIncludedSelectExpressions(Map<String, String> map)
            throws RepositoryException {
        conn.setIncludedSelectExpressions(map);
        Map<String, String> selectExpressions =
            conn.getIncludedSelectExpressions();
        assertNotNull(selectExpressions);
        int size = (map == null) ? 0 : map.size();
        assertEquals(selectExpressions.toString(),
            size, selectExpressions.size());

        Session sess = conn.login();
        LivelinkTraversalManager ltm =
            (LivelinkTraversalManager) sess.getTraversalManager();

        Field[] fields = ltm.getFields();
        assertEquals(LivelinkTraversalManager.DEFAULT_FIELDS.length + size,
            fields.length);
        String expected =
            Arrays.toString(LivelinkTraversalManager.DEFAULT_FIELDS);
        String actual = Arrays.toString(fields);
        assertTrue("Expected: " + expected + "; but got: " + actual,
            actual.startsWith(expected.substring(0, expected.length() - 1)));

        String[] selectList = ltm.getSelectList();
        assertEquals(fields.length, selectList.length);
  }

  public void testIncludedSelectExpressions_long()
      throws RepositoryException {
    // GoogleDataSize is the non-negative alias of DataSize that is
    // selected in the WebNodes query.
    conn.setIncludedSelectExpressions(
        ImmutableMap.of("MyDataSize", "GoogleDataSize"));
    Session sess = conn.login();
    LivelinkTraversalManager ltm =
        (LivelinkTraversalManager) sess.getTraversalManager();
    DocumentList list = ltm.startTraversal();
    assertNotNull(list.nextDocument());
    Document doc = list.nextDocument();
    assertNotNull(doc);
    assertEquals("1729", Value.getSingleValueString(doc, "MyDataSize"));
  }

  public void testGetResults() throws RepositoryException {
    Session sess = conn.login();
    LivelinkTraversalManager ltm =
        (LivelinkTraversalManager) sess.getTraversalManager();

    // Not sure why, but 6 and 2000 are not in the WebNodes data.
    // 2901 is, but it's an excluded volume type.
    ClientValue results = ltm.getResults("6,24,42,2000,2901", new Date());
    assertEquals(2, results.size());
  }

  private LivelinkTraversalManager getObjectUnderTest(Client traversalClient)
      throws RepositoryException {
    conn.login();
    return new LivelinkTraversalManager(conn, traversalClient, "Admin",
        new MockClient(), conn.getContentHandler(traversalClient));
  }

  /**
   * Asserts that the given DocumentList contains exactly the expected
   * documents and nothing else.
   */
  private void assertDocumentListEquals(List<String> expectedDocids,
      DocumentList list) throws RepositoryException {
    assertNotNull(list);
    for (String docid : expectedDocids) {
      Document doc = list.nextDocument();
      assertNotNull(doc);
      assertEquals(docid,
          Value.getSingleValueString(doc, SpiConstants.PROPNAME_DOCID));
    }
    assertNull(list.nextDocument());
  }

  /**
   * Checks the first traversal query with a single batch repository,
   * including asserting that the checkpoint is the expected value
   * after the entire list is retrieved (i.e., nextDocument has
   * returned null). This test is here rather than in
   * LivelinkDocumentListTest because it's the
   * LivelinkTraversalManager that creates the underlying recarray and
   * checkpoint.
   */
  private void testStartTraversal(boolean useDTreeAncestors)
      throws SQLException, RepositoryException {
    LivelinkTraversalManager ltm = getObjectUnderTest(useDTreeAncestors, null);

    // 66 is modified later, and appears in the candidates, but appears
    // updated because of its current date in WebNodes, so it's left
    // out of the results.
    DocumentList list = ltm.startTraversal();
    assertDocumentListEquals(ImmutableList.of("24", "42"), list);

    // When nextDocument returns null, the advance checkpoint is used,
    // which includes 66 with its original ModifyDate, since that was
    // in the candidates.
    // TODO(jlacey): We could query these values as the max(ModifyDate)
    // from DTree when it matches WebNodes, and from DAuditNew.
    assertEquals("2002-02-02 00:00:00,66,2013-04-24 08:00:00.000,10042",
        list.checkpoint());
  }

  public void testStartTraversalWithDTreeAncestors()
      throws SQLException, RepositoryException {
    testStartTraversal(true);
  }

  public void testStartTraversalWithGenealogist()
      throws SQLException, RepositoryException {
    testStartTraversal(false);
  }

  /** Positive test to set a baseline for testResumeTraversalPingError. */
  public void testResumeTraversal() throws RepositoryException {
    LivelinkTraversalManager ltm = getObjectUnderTest(new MockClient());

    DocumentList list = ltm.resumeTraversal("2011-10-16 14:13:52,12345");
    assertNotNull(list);
    assertNull(list.nextDocument());
  }

  /**
   * Tests that if GetCurrentUserID throws an exception, so does
   * resumeTraversal. Legacy code returned null and triggered the
   * retry delay instead of the error wait.
   */
  public void testResumeTraversalPingError() throws RepositoryException {
    final RepositoryException expected = new RepositoryException();
    LivelinkTraversalManager ltm = getObjectUnderTest(new MockClient() {
        @Override
        public int GetCurrentUserID() throws RepositoryException {
          throw expected;
        }
      });

    try {
      DocumentList list = ltm.resumeTraversal("2011-10-16 14:13:52,12345");
      fail("Expected an exception, but got " + list);
    } catch (RepositoryException e) {
      assertSame(expected, e);
    }
  }

  private LivelinkTraversalManager getObjectUnderTest(
      boolean useDTreeAncestors, String sqlWhereCondition)
      throws RepositoryException, SQLException {
    // This is a little twisted. We need to call login after setting
    // includedLocationNodes for it to sanitize the value, but we don't
    // want to validate the sqlWhereCondition, since we're explicitly
    // testing the traversal manager here.
    conn.setIncludedLocationNodes("6");
    conn.login();
    conn.setUseDTreeAncestors(useDTreeAncestors);
    conn.setSqlWhereCondition(sqlWhereCondition);

    Client client = new MockClient();
    return new LivelinkTraversalManager(conn, client, "Admin", client,
        conn.getContentHandler(client));
  }

  private void testSqlWhereCondition(boolean useDTreeAncestors,
      String sqlWhereCondition, int expectedRows) throws Exception {
    LivelinkTraversalManager ltm =
        getObjectUnderTest(useDTreeAncestors, sqlWhereCondition);
    ClientValue results = ltm.getResults("24,42", new Date());

    if (expectedRows == 0) {
      assertNullOrEmpty(results);
    } else {     
      assertEquals(expectedRows, results.size());
    }
  }

  private void assertNullOrEmpty(ClientValue value) {
    if (value != null) {
      assertEquals(0, value.size());
    }
  }

  public void testSqlWhereCondition_none_dta() throws Exception {
    testSqlWhereCondition(true, "", 2);
  }

  public void testSqlWhereCondition_none_gen() throws Exception {
    testSqlWhereCondition(false, "", 2);
  }

  public void testSqlWhereCondition_empty_dta() throws Exception {
    testSqlWhereCondition(true, "DataID = 0", 0);
  }

  public void testSqlWhereCondition_empty_gen() throws Exception {
    testSqlWhereCondition(false, "DataID = 0", 0);
  }

  public void testSqlWhereCondition_condition_dta() throws Exception {
    testSqlWhereCondition(true, "DataID > 40", 1);
  }

  public void testSqlWhereCondition_condition_gen() throws Exception {
    testSqlWhereCondition(false, "DataID > 40", 1);
  }

  /** Tests selecting a column that only exists in WebNodes and not DTree. */
  public void testSqlWhereCondition_webnodes_dta() throws Exception {
    testSqlWhereCondition(true, "MimeType is not null", 1);
  }

  /** Tests selecting a column that only exists in WebNodes and not DTree. */
  public void testSqlWhereCondition_webnodes_gen() throws Exception {
    testSqlWhereCondition(false, "MimeType is not null", 1);
  }
}
TOP

Related Classes of com.google.enterprise.connector.otex.LivelinkTraversalManagerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.