@Test
  public void testJavaApiWithDeferredSoltionSetUpdateWithMapper() {
    try {
      Plan plan = getJavaTestPlan(false, true);

      OptimizedPlan oPlan = compileNoStats(plan);

      OptimizerPlanNodeResolver resolver = getOptimizerPlanNodeResolver(oPlan);
      DualInputPlanNode joinWithInvariantNode = resolver.getNode(JOIN_WITH_INVARIANT_NAME);
      DualInputPlanNode joinWithSolutionSetNode = resolver.getNode(JOIN_WITH_SOLUTION_SET);
      SingleInputPlanNode worksetReducer = resolver.getNode(NEXT_WORKSET_REDUCER_NAME);
      SingleInputPlanNode deltaMapper = resolver.getNode(SOLUTION_DELTA_MAPPER_NAME);

      // iteration preserves partitioning in reducer, so the first partitioning is out of the loop,
      // the in-loop partitioning is before the final reducer

      // verify joinWithInvariant
      assertEquals(ShipStrategyType.FORWARD, joinWithInvariantNode.getInput1().getShipStrategy());
      assertEquals(
          ShipStrategyType.PARTITION_HASH, joinWithInvariantNode.getInput2().getShipStrategy());
      assertEquals(new FieldList(1, 2), joinWithInvariantNode.getKeysForInput1());
      assertEquals(new FieldList(1, 2), joinWithInvariantNode.getKeysForInput2());

      // verify joinWithSolutionSet
      assertEquals(
          ShipStrategyType.PARTITION_HASH, joinWithSolutionSetNode.getInput1().getShipStrategy());
      assertEquals(ShipStrategyType.FORWARD, joinWithSolutionSetNode.getInput2().getShipStrategy());
      assertEquals(new FieldList(1, 0), joinWithSolutionSetNode.getKeysForInput1());

      // verify reducer
      assertEquals(ShipStrategyType.PARTITION_HASH, worksetReducer.getInput().getShipStrategy());
      assertEquals(new FieldList(1, 2), worksetReducer.getKeys(0));

      // currently, the system may partition before or after the mapper
      ShipStrategyType ss1 = deltaMapper.getInput().getShipStrategy();
      ShipStrategyType ss2 = deltaMapper.getOutgoingChannels().get(0).getShipStrategy();

      assertTrue(
          (ss1 == ShipStrategyType.FORWARD && ss2 == ShipStrategyType.PARTITION_HASH)
              || (ss2 == ShipStrategyType.FORWARD && ss1 == ShipStrategyType.PARTITION_HASH));

      new JobGraphGenerator().compileJobGraph(oPlan);
    } catch (Exception e) {
      System.err.println(e.getMessage());
      e.printStackTrace();
      fail("Test errored: " + e.getMessage());
    }
  }
  private boolean checkRepartitionMergeJoin(DualInputPlanNode join, SingleInputPlanNode reducer) {
    if (DriverStrategy.MERGE == join.getDriverStrategy()) {
      // driver keys
      Assert.assertEquals(set0, join.getKeysForInput1());
      Assert.assertEquals(set0, join.getKeysForInput2());

      // local strategies
      Assert.assertEquals(LocalStrategy.SORT, join.getInput1().getLocalStrategy());
      Assert.assertEquals(LocalStrategy.SORT, join.getInput2().getLocalStrategy());
      Assert.assertEquals(LocalStrategy.NONE, reducer.getInput().getLocalStrategy());

      // local strategy keys
      Assert.assertEquals(set01, join.getInput1().getLocalStrategyKeys());
      Assert.assertEquals(set0, join.getInput2().getLocalStrategyKeys());
      Assert.assertTrue(
          join.getInput1().getLocalStrategySortOrder()[0]
              == join.getInput2().getLocalStrategySortOrder()[0]);
      Assert.assertEquals(set01, reducer.getKeys(0));
      Assert.assertTrue(
          Arrays.equals(join.getInput1().getLocalStrategySortOrder(), reducer.getSortOrders(0)));
      return true;
    } else {
      return false;
    }
  }
  private boolean checkHashJoinStrategies(
      DualInputPlanNode join, SingleInputPlanNode reducer, boolean buildFirst) {
    if ((buildFirst && DriverStrategy.HYBRIDHASH_BUILD_FIRST == join.getDriverStrategy())
        || (!buildFirst && DriverStrategy.HYBRIDHASH_BUILD_SECOND == join.getDriverStrategy())) {
      // driver keys
      Assert.assertEquals(set0, join.getKeysForInput1());
      Assert.assertEquals(set0, join.getKeysForInput2());

      // local strategies
      Assert.assertEquals(LocalStrategy.NONE, join.getInput1().getLocalStrategy());
      Assert.assertEquals(LocalStrategy.NONE, join.getInput2().getLocalStrategy());
      Assert.assertEquals(LocalStrategy.COMBININGSORT, reducer.getInput().getLocalStrategy());

      // local strategy keys
      Assert.assertEquals(set01, reducer.getInput().getLocalStrategyKeys());
      Assert.assertEquals(set01, reducer.getKeys(0));
      Assert.assertTrue(
          Arrays.equals(reducer.getInput().getLocalStrategySortOrder(), reducer.getSortOrders(0)));
      return true;
    } else {
      return false;
    }
  }