@Deployment
  public void testConcurrentScopeCompensation() {
    // given a process instance with two concurrent tasks, one of which is waiting
    // before throwing compensation
    ProcessInstance processInstance =
        runtimeService.startProcessInstanceByKey("concurrentScopeCompensation");
    Task beforeCompensationTask =
        taskService.createTaskQuery().taskDefinitionKey("beforeCompensationTask").singleResult();
    Task concurrentTask =
        taskService.createTaskQuery().taskDefinitionKey("concurrentTask").singleResult();

    // when throwing compensation such that two subprocesses are compensated
    taskService.complete(beforeCompensationTask.getId());

    // then both compensation handlers have been executed
    if (processEngineConfiguration.getHistoryLevel().getId()
        >= ProcessEngineConfigurationImpl.HISTORYLEVEL_AUDIT) {
      HistoricVariableInstanceQuery historicVariableInstanceQuery =
          historyService.createHistoricVariableInstanceQuery().variableName("compensateScope1Task");

      assertEquals(1, historicVariableInstanceQuery.count());
      assertEquals(1, historicVariableInstanceQuery.list().get(0).getValue());

      historicVariableInstanceQuery =
          historyService.createHistoricVariableInstanceQuery().variableName("compensateScope2Task");

      assertEquals(1, historicVariableInstanceQuery.count());
      assertEquals(1, historicVariableInstanceQuery.list().get(0).getValue());
    }

    // and after completing the concurrent task, the process instance ends successfully
    taskService.complete(concurrentTask.getId());
    assertProcessEnded(processInstance.getId());
  }
  /**
   * enable test case when bug is fixed
   *
   * @see https://app.camunda.com/jira/browse/CAM-4304
   */
  @Deployment(
      resources = {
        "org/camunda/bpm/engine/test/bpmn/event/compensate/CompensateEventTest.testCompensationInEventSubProcess.bpmn20.xml"
      })
  public void testCompensateInEventSubprocess() {
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("compensateProcess");
    assertProcessEnded(processInstance.getId());

    HistoricVariableInstanceQuery historicVariableInstanceQuery =
        historyService.createHistoricVariableInstanceQuery().variableName("undoBookSecondHotel");

    if (processEngineConfiguration.getHistoryLevel().getId()
        >= ProcessEngineConfigurationImpl.HISTORYLEVEL_AUDIT) {
      assertEquals(1, historicVariableInstanceQuery.count());
      assertEquals(
          "undoBookSecondHotel", historicVariableInstanceQuery.list().get(0).getVariableName());
      assertEquals(5, historicVariableInstanceQuery.list().get(0).getValue());

      historicVariableInstanceQuery =
          historyService.createHistoricVariableInstanceQuery().variableName("undoBookFlight");

      assertEquals(1, historicVariableInstanceQuery.count());
      assertEquals(5, historicVariableInstanceQuery.list().get(0).getValue());

      historicVariableInstanceQuery =
          historyService.createHistoricVariableInstanceQuery().variableName("undoBookHotel");

      assertEquals(1, historicVariableInstanceQuery.count());
      assertEquals(5, historicVariableInstanceQuery.list().get(0).getValue());
    }
  }
  @Deployment(resources = {"org/camunda/bpm/engine/test/api/oneTaskProcess.bpmn20.xml"})
  public void testSetVariableLocalOnUserTask() {
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("oneTaskProcess");

    Task task = taskService.createTaskQuery().singleResult();
    assertNotNull(task);

    taskService.setVariableLocal(task.getId(), "testVar", "testValue");
    ExecutionEntity taskExecution =
        (ExecutionEntity)
            runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
    assertNotNull(taskExecution);

    HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery();
    assertEquals(1, query.count());

    HistoricVariableInstance variable = query.singleResult();
    assertNotNull(variable);

    // the variable is in the task scope
    assertEquals(taskExecution.getActivityInstanceId(), variable.getActivityInstanceId());

    taskService.complete(task.getId());
    assertProcessEnded(pi.getId());
  }
  @Deployment(resources = {"org/camunda/bpm/engine/test/api/oneTaskProcess.bpmn20.xml"})
  public void testSetVariableOnProcessIntanceStartAndSetVariableLocalOnUserTask() {
    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("testVar", "testValue");
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("oneTaskProcess", variables);

    Task task = taskService.createTaskQuery().singleResult();
    assertNotNull(task);

    taskService.setVariableLocal(task.getId(), "testVar", "anotherTestValue");
    ExecutionEntity taskExecution =
        (ExecutionEntity) runtimeService.createExecutionQuery().singleResult();
    assertNotNull(taskExecution);

    HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery();
    assertEquals(2, query.count());

    List<HistoricVariableInstance> result = query.list();

    HistoricVariableInstance firstVar = result.get(0);
    assertEquals("testVar", firstVar.getVariableName());
    assertEquals("testValue", firstVar.getValue());
    // the variable is in the process instance scope
    assertEquals(pi.getId(), firstVar.getActivityInstanceId());

    HistoricVariableInstance secondVar = result.get(1);
    assertEquals("testVar", secondVar.getVariableName());
    assertEquals("anotherTestValue", secondVar.getValue());
    // the variable is in the task scope
    assertEquals(taskExecution.getActivityInstanceId(), secondVar.getActivityInstanceId());

    taskService.complete(task.getId());
    assertProcessEnded(pi.getId());
  }
  @Deployment
  public void testSetVariableOnServiceTaskInsideParallelBranch() {
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("process");

    HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery();
    assertEquals(1, query.count());

    HistoricVariableInstance variable = query.singleResult();
    // the variable is in the process instance scope
    assertEquals(pi.getId(), variable.getActivityInstanceId());

    assertProcessEnded(pi.getId());
  }
  @Deployment(resources = {"org/camunda/bpm/engine/test/api/oneTaskProcess.bpmn20.xml"})
  public void testSetVariableOnProcessInstanceStart() {
    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("testVar", "testValue");
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("oneTaskProcess", variables);

    HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery();
    assertEquals(1, query.count());

    HistoricVariableInstance variable = query.singleResult();
    assertNotNull(variable);

    // the variable is in the process instance scope
    assertEquals(pi.getId(), variable.getActivityInstanceId());

    taskService.complete(taskService.createTaskQuery().singleResult().getId());
    assertProcessEnded(pi.getId());
  }
  @Deployment(resources = {"org/camunda/bpm/engine/test/api/oneSubProcess.bpmn20.xml"})
  public void testSetVariableOnUserTaskInsideSubProcess() {
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("startSimpleSubProcess");

    Task task = taskService.createTaskQuery().singleResult();
    assertNotNull(task);

    taskService.setVariable(task.getId(), "testVar", "testValue");

    HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery();
    assertEquals(1, query.count());

    HistoricVariableInstance variable = query.singleResult();
    // the variable is in the process instance scope
    assertEquals(pi.getId(), variable.getActivityInstanceId());

    taskService.complete(task.getId());
    assertProcessEnded(pi.getId());
  }
  @Deployment
  public void testSetVariableLocalOnServiceTaskInsideSubProcess() {
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("process");

    HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery();
    assertEquals(1, query.count());

    String activityInstanceId =
        historyService
            .createHistoricActivityInstanceQuery()
            .activityId("SubProcess_1")
            .singleResult()
            .getId();

    HistoricVariableInstance variable = query.singleResult();
    // the variable is in the sub process scope
    assertEquals(activityInstanceId, variable.getActivityInstanceId());

    assertProcessEnded(pi.getId());
  }
  @Deployment
  public void testSetVariableLocalOnTaskInsideParallelBranch() {
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("process");

    Task task = taskService.createTaskQuery().singleResult();
    assertNotNull(task);

    taskService.setVariableLocal(task.getId(), "testVar", "testValue");
    ExecutionEntity taskExecution =
        (ExecutionEntity)
            runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
    assertNotNull(taskExecution);

    HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery();
    assertEquals(1, query.count());

    HistoricVariableInstance variable = query.singleResult();
    // the variable is in the user task scope
    assertEquals(taskExecution.getActivityInstanceId(), variable.getActivityInstanceId());

    taskService.complete(task.getId());

    assertProcessEnded(pi.getId());
  }