@Test
  public void execute_blocking_FAIL() throws KettleException {
    final long waitTime = 0;

    OozieJobExecutorConfig config = new OozieJobExecutorConfig();
    config.setOozieUrl(
        "http://localhost:11000/oozie"); // don't worry if it isn't running, we fake out our test
                                         // connection to it anyway
    config.setOozieWorkflowConfig("test-src/job.properties");
    config.setJobEntryName("name");
    config.setBlockingPollingInterval("1000");

    TestOozieJobExecutorJobEntry je = new TestOozieJobExecutorJobEntry(getFailingTest());

    je.setParentJob(new Job("test", null, null));
    je.setJobConfig(config);

    Result result = new Result();
    long start = System.currentTimeMillis();
    je.execute(result, 0);
    long end = System.currentTimeMillis();
    assertTrue(
        "Total runtime should be >= the wait time if we are blocking", (end - start) >= waitTime);

    Assert.assertEquals(1, result.getNrErrors());
    assertFalse(result.getResult());
  }
  @Test
  public void testExecuteSuccess() throws Exception {
    entry.arguments = new String[] {existingFile1, existingFile2};

    Result res = entry.execute(new Result(), 0);

    assertTrue("Entry failed", res.getResult());
  }
  @Test
  public void testExecuteFail() throws Exception {
    entry.arguments =
        new String[] {existingFile1, existingFile2, "nonExistingFile1.ext", "nonExistingFile2.ext"};

    Result res = entry.execute(new Result(), 0);

    assertFalse("Entry should fail", res.getResult());
  }
  @Test
  public void testNrErrorsSuccess() throws Exception {
    entry.limit = "5";
    entry.successCondition = JobEntryEvalTableContent.SUCCESS_CONDITION_ROWS_COUNT_EQUAL;
    entry.tablename = "table";

    Result res = entry.execute(new Result(), 0);

    assertTrue("Eval number of rows should be suceeded", res.getResult());
    assertEquals("Apparently there should no error", res.getNrErrors(), 0);

    // that should work regardless of old/new behavior flag
    entry.setVariable(Const.KETTLE_COMPATIBILITY_SET_ERROR_ON_SPECIFIC_JOB_ENTRIES, "Y");

    res = entry.execute(new Result(), 0);

    assertTrue("Eval number of rows should be suceeded", res.getResult());
    assertEquals("Apparently there should no error", res.getNrErrors(), 0);
  }
  @Test
  public void testExecuteWithException() throws Exception {
    entry.arguments = new String[] {null};

    Result res = entry.execute(new Result(), 0);

    assertFalse("Entry should fail", res.getResult());
    assertEquals(
        "File with wrong name was specified. One error should be reported", 1, res.getNrErrors());
  }
  @Test
  public void testNrErrorsNoCustomSql() throws Exception {
    entry.limit = "5";
    entry.successCondition = JobEntryEvalTableContent.SUCCESS_CONDITION_ROWS_COUNT_EQUAL;
    entry.iscustomSQL = true;
    entry.customSQL = null;

    Result res = entry.execute(new Result(), 0);

    assertFalse("Eval number of rows should fail", res.getResult());
    assertEquals("Apparently there should be an error", res.getNrErrors(), 1);

    // that should work regardless of old/new behavior flag
    entry.setVariable(Const.KETTLE_COMPATIBILITY_SET_ERROR_ON_SPECIFIC_JOB_ENTRIES, "Y");

    res = entry.execute(new Result(), 0);

    assertFalse("Eval number of rows should fail", res.getResult());
    assertEquals("Apparently there should be an error", res.getNrErrors(), 1);
  }
  @Test
  public void testSetNrErrorsNewBehaviorFalseResult() throws Exception {
    // this tests fix for PDI-10270
    entry.arguments = new String[] {"nonExistingFile.ext"};

    Result res = entry.execute(new Result(), 0);

    assertFalse("Entry should fail", res.getResult());
    assertEquals(
        "Files not found. Result is false. But... No of errors should be zero",
        0,
        res.getNrErrors());
  }
  @Test
  public void testNrErrorsFailureNewBehavior() throws Exception {
    entry.limit = "1";
    entry.successCondition = JobEntryEvalTableContent.SUCCESS_CONDITION_ROWS_COUNT_EQUAL;
    entry.tablename = "table";

    Result res = entry.execute(new Result(), 0);

    assertFalse("Eval number of rows should fail", res.getResult());
    assertEquals(
        "No errors should be reported in result object accoding to the new behavior",
        res.getNrErrors(),
        0);
  }
  @Test
  public void testSetNrErrorsOldBehaviorFalseResult() throws Exception {
    // this tests backward compatibility settings for PDI-10270
    entry.arguments = new String[] {"nonExistingFile1.ext", "nonExistingFile2.ext"};

    entry.setVariable(Const.KETTLE_COMPATIBILITY_SET_ERROR_ON_SPECIFIC_JOB_ENTRIES, "Y");

    Result res = entry.execute(new Result(), 0);

    assertFalse("Entry should fail", res.getResult());
    assertEquals(
        "Files not found. Result is false. And... Number of errors should be the same as number of not found files",
        entry.arguments.length,
        res.getNrErrors());
  }
  @Test
  public void testNrErrorsFailureOldBehavior() throws Exception {
    entry.limit = "1";
    entry.successCondition = JobEntryEvalTableContent.SUCCESS_CONDITION_ROWS_COUNT_EQUAL;
    entry.tablename = "table";

    entry.setVariable(Const.KETTLE_COMPATIBILITY_SET_ERROR_ON_SPECIFIC_JOB_ENTRIES, "Y");

    Result res = entry.execute(new Result(), 0);

    assertFalse("Eval number of rows should fail", res.getResult());
    assertEquals(
        "An error should be reported in result object accoding to the old behavior",
        res.getNrErrors(),
        1);
  }
  @Override
  public Result execute(Result previousResult, int nr) {
    Result result = previousResult;
    result.setResult(false);
    result.setNrErrors(1);
    String realCustomSQL = null;
    String realTablename = environmentSubstitute(tablename);
    String realSchemaname = environmentSubstitute(schemaname);

    if (connection == null) {
      logError(BaseMessages.getString(PKG, "JobEntryWaitForSQL.NoDbConnection"));
      return result;
    }

    if (iscustomSQL) {
      // clear result list rows
      if (isClearResultList) {
        result.getRows().clear();
      }

      realCustomSQL = customSQL;
      if (isUseVars) {
        realCustomSQL = environmentSubstitute(realCustomSQL);
      }
      if (log.isDebug()) {
        logDebug(
            BaseMessages.getString(PKG, "JobEntryWaitForSQL.Log.EnteredCustomSQL", realCustomSQL));
      }

      if (Const.isEmpty(realCustomSQL)) {
        logError(BaseMessages.getString(PKG, "JobEntryWaitForSQL.Error.NoCustomSQL"));
        return result;
      }

    } else {
      if (Const.isEmpty(realTablename)) {
        logError(BaseMessages.getString(PKG, "JobEntryWaitForSQL.Error.NoTableName"));
        return result;
      }
    }

    try {
      // check connection
      // connect and disconnect
      checkConnection();

      // starttime (in seconds)
      long timeStart = System.currentTimeMillis() / 1000;

      int nrRowsLimit = Const.toInt(environmentSubstitute(rowsCountValue), 0);
      if (log.isDetailed()) {
        logDetailed(
            BaseMessages.getString(PKG, "JobEntryWaitForSQL.Log.nrRowsLimit", "" + nrRowsLimit));
      }

      long iMaximumTimeout =
          Const.toInt(
              environmentSubstitute(maximumTimeout), Const.toInt(DEFAULT_MAXIMUM_TIMEOUT, 0));
      long iCycleTime =
          Const.toInt(
              environmentSubstitute(checkCycleTime), Const.toInt(DEFAULT_CHECK_CYCLE_TIME, 0));

      //
      // Sanity check on some values, and complain on insanity
      //
      if (iMaximumTimeout < 0) {
        iMaximumTimeout = Const.toInt(DEFAULT_MAXIMUM_TIMEOUT, 0);
        logBasic("Maximum timeout invalid, reset to " + iMaximumTimeout);
      }

      if (iCycleTime < 1) {
        // If lower than 1 set to the default
        iCycleTime = Const.toInt(DEFAULT_CHECK_CYCLE_TIME, 1);
        logBasic("Check cycle time invalid, reset to " + iCycleTime);
      }

      if (iMaximumTimeout == 0) {
        logBasic("Waiting indefinitely for SQL data");
      } else {
        logBasic("Waiting " + iMaximumTimeout + " seconds for SQL data");
      }

      boolean continueLoop = true;
      while (continueLoop && !parentJob.isStopped()) {
        if (SQLDataOK(result, nrRowsLimit, realSchemaname, realTablename, realCustomSQL)) {
          // SQL data exists, we're happy to exit
          logBasic("Detected SQL data within timeout");
          result.setResult(true);
          continueLoop = false;
        } else {
          long now = System.currentTimeMillis() / 1000;

          if ((iMaximumTimeout > 0) && (now > (timeStart + iMaximumTimeout))) {
            continueLoop = false;

            // SQL data doesn't exist after timeout, either true or false
            if (isSuccessOnTimeout()) {
              logBasic("Didn't detect SQL data before timeout, success");
              result.setResult(true);
            } else {
              logBasic("Didn't detect SQL data before timeout, failure");
              result.setResult(false);
            }
          }
          // sleep algorithm
          long sleepTime = 0;

          if (iMaximumTimeout == 0) {
            sleepTime = iCycleTime;
          } else {
            if ((now + iCycleTime) < (timeStart + iMaximumTimeout)) {
              sleepTime = iCycleTime;
            } else {
              sleepTime = iCycleTime - ((now + iCycleTime) - (timeStart + iMaximumTimeout));
            }
          }
          try {
            if (sleepTime > 0) {
              if (log.isDetailed()) {
                logDetailed("Sleeping " + sleepTime + " seconds before next check for SQL data");
              }
              Thread.sleep(sleepTime * 1000);
            }
          } catch (InterruptedException e) {
            // something strange happened
            result.setResult(false);
            continueLoop = false;
          }
        }
      }
    } catch (Exception e) {
      logBasic("Exception while waiting for SQL data: " + e.getMessage());
    }

    if (result.getResult()) {
      // Remove error count set at the beginning of the method
      // PDI-15437
      result.setNrErrors(0);
    }

    return result;
  }