/** entry actions of a substate must not be included in a states entry action list */
  @Test
  public void testSubStateEntryActionExclusion() {
    Statechart sc = _createStatechart("test");
    Scope scope = _createInterfaceScope("interface", sc);
    VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, scope);
    Region r = _createRegion("main", sc);
    // Entry e = _createEntry(EntryKind.INITIAL, null, r);
    State s2 = _createState("s2", r);

    Region s2_r = _createRegion("sub", s2);
    State s2_1 = _createState("s2_1", s2_r);
    LocalReaction entryAction = _createEntryAction(s2_1);
    _createVariableAssignment(
        v1, AssignmentOperator.ASSIGN, _createValue(42), (ReactionEffect) entryAction.getEffect());
    LocalReaction exitAction = _createExitAction(s2_1);
    _createVariableAssignment(
        v1, AssignmentOperator.ASSIGN, _createValue(43), (ReactionEffect) exitAction.getEffect());

    ExecutionFlow flow = sequencer.transform(sc);

    ExecutionState _s2 = flow.getStates().get(0);
    ExecutionState _s2_1 = flow.getStates().get(1);
    assertEquals(s2.getName(), _s2.getSimpleName());
    assertEquals(s2_1.getName(), _s2_1.getSimpleName());

    assertNull(_s2.getEntryAction());
    assertNotNull(_s2_1.getEntryAction());

    assertNull(_s2.getExitAction());
    assertNotNull(_s2_1.getExitAction());
  }
  /** Local reactions must be created for behavior with 'always' trigger */
  @Test
  public void testAlwaysLocalReaction() {

    Statechart sc = _createStatechart("test");
    Scope scope = _createInterfaceScope("interface", sc);
    VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, scope);
    Region r = _createRegion("main", sc);
    State s = _createState("s", r);

    LocalReaction timeTriggeredReaction =
        _createLocalReaction(s, StextFactory.eINSTANCE.createAlwaysEvent());
    AssignmentExpression assign =
        _createVariableAssignment(
            v1,
            AssignmentOperator.ASSIGN,
            _createValue(42),
            (ReactionEffect) timeTriggeredReaction.getEffect());

    ExecutionFlow flow = sequencer.transform(sc);

    ExecutionState _s = flow.getStates().get(0);

    // assert that a local reaction is created
    Reaction reaction = _s.getReactions().get(0);
    PrimitiveValueExpression pve = (PrimitiveValueExpression) reaction.getCheck().getCondition();
    assertBoolLiteral(true, pve.getValue());
  }
  /**
   * If a entry trigger is combined with a guard condition then the entry action is executed
   * conditionally with this trigger.
   */
  @Test
  public void testExitActionWithoutGuard() {

    Statechart sc = _createStatechart("test");
    Scope scope = _createInterfaceScope("interface", sc);
    VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, scope);
    Region r = _createRegion("main", sc);
    Entry e = _createEntry(EntryKind.INITIAL, null, r);
    State s1 = _createState("s1", r);
    State s2 = _createState("s2", r);
    _createTransition(e, s1);
    _createTransition(s1, s2);
    LocalReaction exitAction = _createExitAction(s2);
    _createVariableAssignment(
        v1, AssignmentOperator.ASSIGN, _createValue(42), (ReactionEffect) exitAction.getEffect());
    // ((ReactionTrigger)entryAction.getTrigger()).setGuardExpression(_createValue(true));

    ExecutionFlow flow = sequencer.transform(sc);

    ExecutionState _s1 = flow.getStates().get(0);
    ExecutionState _s2 = flow.getStates().get(1);
    assertEquals(s1.getName(), _s1.getSimpleName());
    assertEquals(s2.getName(), _s2.getSimpleName());

    Sequence _exitSeq = (Sequence) _s2.getExitAction();

    assertClass(Sequence.class, _exitSeq.getSteps().get(0));
    assertAssignment(
        ((Sequence) _exitSeq.getSteps().get(0)).getSteps().get(0),
        "v1",
        AssignmentOperator.ASSIGN,
        "42");
  }
  /** The exit action must be part of the reaction effect sequence */
  @SuppressWarnings("unused")
  @Test
  public void testStateReaction_WithEntryAction() {
    SimpleFlatTSC tsc = new SimpleFlatTSC();

    VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, tsc.s_scope);
    LocalReaction entryAction = _createEntryAction(tsc.s2);
    AssignmentExpression assign =
        _createVariableAssignment(
            v1,
            AssignmentOperator.ASSIGN,
            _createValue(21),
            (ReactionEffect) entryAction.getEffect());

    ExecutionFlow flow = sequencer.transform(tsc.sc);

    // test state with one outgoing transition
    ExecutionState _s1 = flow.getStates().get(0);
    ExecutionState _s2 = flow.getStates().get(1);
    assertEquals(tsc.s1.getName(), _s1.getSimpleName());
    assertEquals(tsc.s2.getName(), _s2.getSimpleName());

    assertEquals(1, _s1.getReactions().size());
    Reaction reaction = _s1.getReactions().get(0);

    assertNotNull(reaction.getCheck());

    assertNotNull(reaction.getEffect());
    Sequence seq = (Sequence) reaction.getEffect();
    assertEquals(2, seq.getSteps().size());

    assertCall(seq, 0, _s1.getExitSequence());
    assertCall(seq, 1, _s2.getEnterSequences().get(0));
    assertCall(_s2.getEnterSequences().get(0), 0, _s2.getEntryAction());
  }
  /**
   * A leaf state must have a enter sequence. This enter sequence consists of an entry action call
   * and a state enter step.
   */
  @SuppressWarnings("unused")
  @Test
  public void testLeafStateEnterSequence() {
    Statechart sc = _createStatechart("cs");
    Scope scope = _createInterfaceScope("interface", sc);
    VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, scope);
    Region r = _createRegion("r", sc);
    State s1 = _createState("s1", r);
    LocalReaction entryAction = _createEntryAction(s1);
    _createVariableAssignment(
        v1, AssignmentOperator.ASSIGN, _createValue(42), (ReactionEffect) entryAction.getEffect());

    Entry e = _createEntry(EntryKind.INITIAL, null, r);
    Transition t = _createTransition(e, s1);

    ExecutionFlow flow = sequencer.transform(sc);

    ExecutionState _s1 = flow.getStates().get(0);
    assertEquals(s1.getName(), _s1.getSimpleName());

    assertNotNull(_s1.getEntryAction());
    assertNotNull(_s1.getEnterSequences().get(0));
    assertEquals(2, _s1.getEnterSequences().get(0).getSteps().size());

    assertCall(_s1.getEnterSequences().get(0), 0, _s1.getEntryAction());

    assertClass(EnterState.class, _s1.getEnterSequences().get(0).getSteps().get(1));
  }
  @Test
  public void testSingleLocalTimeTrigger() {

    Statechart sc = _createStatechart("test");
    Scope scope = _createInterfaceScope("interface", sc);
    VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, scope);
    Region r = _createRegion("main", sc);
    State s = _createState("s", r);

    LocalReaction timeTriggeredReaction =
        _createTimeTriggeredReaction(s, TimeEventType.AFTER, _createValue(2), TimeUnit.MILLISECOND);
    AssignmentExpression assign =
        _createVariableAssignment(
            v1,
            AssignmentOperator.ASSIGN,
            _createValue(42),
            (ReactionEffect) timeTriggeredReaction.getEffect());

    ExecutionFlow flow = sequencer.transform(sc);

    Scope timerScope = flow.getScopes().get(1);
    assertTrue(timerScope.getDeclarations().get(0) instanceof TimeEvent);

    TimeEvent te = (TimeEvent) timerScope.getDeclarations().get(0);

    // assert that the reaction check checks the time event
    ExecutionState _s = flow.getStates().get(0);

    // assert the scheduling of the time event during state entry
    assertNotNull(_s.getEntryAction());
    Sequence entryAction = (Sequence) _s.getEntryAction();
    ScheduleTimeEvent ste = (ScheduleTimeEvent) entryAction.getSteps().get(0);
    assertSame(te, ste.getTimeEvent());
    PrimitiveValueExpression value = (PrimitiveValueExpression) ste.getTimeValue();
    assertIntLiteral(2, value.getValue());
    assertNotNull(_s.getExitAction());
    Sequence exitAction = (Sequence) _s.getExitAction();
    UnscheduleTimeEvent ute = (UnscheduleTimeEvent) exitAction.getSteps().get(0);
    assertSame(te, ute.getTimeEvent());
  }