@Test
  public void testSortDoesNotAddExtraRootPaths() throws Exception {
    // create a sort request against the entity directly
    List<SortRequestProperty> sortRequestProperties = new ArrayList<>();

    sortRequestProperties.add(
        new SortRequestProperty(AlertHistoryResourceProvider.ALERT_HISTORY_TIMESTAMP,
            org.apache.ambari.server.controller.spi.SortRequest.Order.ASC));

    SortRequest sortRequest = new SortRequestImpl(sortRequestProperties);

    // create a complex, cross-entity predicate
    Predicate predicate = new PredicateBuilder().property(
            AlertHistoryResourceProvider.ALERT_HISTORY_DEFINITION_NAME).equals("foo").toPredicate();

    MockAlertHistoryredicateVisitor visitor = new MockAlertHistoryredicateVisitor();
    PredicateHelper.visit(predicate, visitor);

    JpaSortBuilder<AlertHistoryEntity> sortBuilder = new JpaSortBuilder<>();
    List<Order> sortOrders = sortBuilder.buildSortOrders(sortRequest, visitor);

    Assert.assertEquals(sortOrders.size(), 1);

    // verify the CriteriaQuery has the correct roots
    // it should have one for the main query predicate
    CriteriaQuery<AlertHistoryEntity> query = visitor.getCriteriaQuery();
    Set<Root<?>> roots = query.getRoots();
    Assert.assertEquals(1, roots.size());
  }
Tests that adding a sort does not create another {@link Root} in the
{@link CriteriaQuery}. A duplicate root will cause a cartesian product
similar to:

<pre>
SELECT t0.alert_id,
  t0.alert_instance,
  t0.alert_label,
  t0.alert_state,
  t0.alert_text,
  t0.alert_timestamp,
  t0.cluster_id,
  t0.component_name,
  t0.host_name,
  t0.service_name,
  t0.alert_definition_id
FROM   alert_history t0,
  alert_history t2,
  alert_definition t1
WHERE  ( ( t1.definition_name = ? )
    AND ( t1.definition_id = t2.alert_definition_id ) )
ORDER  BY t0.alert_timestamp DESC
</pre>

where the root for {@code alert_history} is added twice.

@throws Exception
ambari-server/src/test/java/org/apache/ambari/server/api/query/JpaSortBuilderTest.java