/** @throws Exception If failed. */
  @SuppressWarnings("unchecked")
  public void testCancel() throws Exception {
    Grid grid = G.grid(getTestGridName());

    grid.compute()
        .localDeployTask(GridCancelTestTask.class, U.detectClassLoader(GridCancelTestTask.class));

    GridComputeTaskFuture<?> fut = grid.compute().execute(GridCancelTestTask.class.getName(), null);

    // Wait until jobs begin execution.
    boolean await = startSignal.await(WAIT_TIME, TimeUnit.MILLISECONDS);

    assert await : "Jobs did not start.";

    info("Test task result: " + fut);

    assert fut != null;

    // Only first job should successfully complete.
    Object res = fut.get();
    assert (Integer) res == 1;

    // Wait for all jobs to finish.
    await = stopSignal.await(WAIT_TIME, TimeUnit.MILLISECONDS);
    assert await : "Jobs did not stop.";

    // One is definitely processed. But there might be some more processed or cancelled or processed
    // and cancelled.
    // Thus total number should be at least SPLIT_COUNT and at most (SPLIT_COUNT - 1) *2 +1
    assert (cancelCnt + processedCnt) >= SPLIT_COUNT
            && (cancelCnt + processedCnt) <= (SPLIT_COUNT - 1) * 2 + 1
        : "Invalid cancel count value: " + cancelCnt;
  }
  /**
   * Starts the local node and checks for presence of log file. Also checks that this is really a
   * log of a started node.
   *
   * @param id Test-local node ID.
   * @throws Exception If error occurred.
   */
  private void checkOneNode(int id) throws Exception {
    try (Grid grid = G.start(getConfiguration("grid" + id))) {
      String id8 = U.id8(grid.localNode().id());
      String logPath = "work/log/gridgain-" + id8 + ".log";
      File logFile = U.resolveGridGainPath(logPath);

      assertNotNull("Failed to resolve path: " + logPath, logFile);
      assertTrue("Log file does not exist: " + logFile, logFile.exists());

      String logContent = U.readFileToString(logFile.getAbsolutePath(), "UTF-8");

      assertTrue(
          "Log file does not contain it's node ID: " + logFile,
          logContent.contains(">>> Local node [ID=" + id8.toUpperCase()));
    }
  }
    /**
     * Send message optionally either blocking it or throwing an exception if it is of {@link
     * GridJobExecuteResponse} type.
     *
     * @param node Destination node.
     * @param msg Message to be sent.
     * @throws GridSpiException If failed.
     */
    private void sendMessage0(GridNode node, GridTcpCommunicationMessageAdapter msg)
        throws GridSpiException {
      if (msg instanceof GridIoMessage) {
        GridIoMessage msg0 = (GridIoMessage) msg;

        if (msg0.message() instanceof GridJobExecuteResponse) {
          respLatch.countDown();

          if (wait) {
            try {
              U.await(waitLatch);
            } catch (GridInterruptedException ignore) {
              // No-op.
            }
          }
        }
      }

      if (!block) super.sendMessage(node, msg);
    }
 /**
  * Await for job execution response to come.
  *
  * @throws GridInterruptedException If interrupted.
  */
 private void awaitResponse() throws GridInterruptedException {
   U.await(respLatch);
 }