private boolean pruneTestCase(TestCase testCase) {
    returnToInitialState();
    executeTestCase(testCase);

    WidgetHierarchy widgetHierarchy = new WidgetHierarchy();
    widgetHierarchy.getWidgetHierarchy(true);
    widgetHierarchy.populateValues();

    if (widgetStates.contains(widgetHierarchy)) {
      return true;
    } else {
      for (WidgetHierarchy existingState : widgetStates) {
        logger.debug(CompareHierarchies.compare(existingState, widgetHierarchy));
      }
    }
    widgetStates.add(widgetHierarchy);
    return false;
  }
 private void returnToInitialState() {
   final WidgetHierarchy widgetHierarchy = new WidgetHierarchy();
   widgetHierarchy.getWidgetHierarchy(true);
   initialStateStrategy.resetToInitialState(widgetHierarchy);
 }
  private List<TestStep> generateNextSteps() {
    List<TestStep> testSteps = new ArrayList<TestStep>();

    final WidgetHierarchy widgetHierarchy = new WidgetHierarchy();
    widgetHierarchy.getWidgetHierarchy(true);

    MessageBoxHelper messageBoxHelper = widgetHierarchy.getMessageBoxHelper();
    if (messageBoxHelper == null) {
      WidgetFilterVisitor visitor = new WidgetFilterVisitor(widgetFilterStrategy, widgetHierarchy);
      widgetHierarchy.accept(visitor);
      Set<WidgetInfo> filteredSet = visitor.getFilteredSet();

      for (WidgetInfo widgetInfo : filteredSet) {
        Object proxy = widgetHierarchy.getWidgetProxy(widgetInfo.getWidgetID());
        if (proxy instanceof MenuItemProxy || proxy instanceof ButtonProxy) {
          TestStep testStep = new TestStep(TestCaseAction.LEFT_MOUSE_CLICK, widgetInfo);
          testSteps.add(testStep);
        } else if (proxy instanceof TextProxy) {
          TestStep testStep = new EnterTextTestStep(TestCaseAction.ENTER_TEXT, widgetInfo, "Test");
          testSteps.add(testStep);
        } else if (proxy instanceof ComboProxy) {
          final ComboProxy comboProxy = (ComboProxy) proxy;
          int itemCount =
              Displays.syncExec(
                  comboProxy.getDisplay(),
                  new Displays.IntResult() {
                    public int result() {
                      return comboProxy.getItemCount();
                    }
                  });
          for (int i = 0; i < itemCount; ++i) {
            TestStep testStep = new ComboTestStep(TestCaseAction.SELECT_ITEM, widgetInfo, i);
            testSteps.add(testStep);
          }
        }
      }
    } else {
      if (messageBoxHelper.hasOKButton()) {
        testSteps.add(
            new MessageBoxTestStep(TestCaseAction.LEFT_MOUSE_CLICK, MessageBoxHelper.Button.OK));
      }
      if (messageBoxHelper.hasCancelButton()) {
        testSteps.add(
            new MessageBoxTestStep(
                TestCaseAction.LEFT_MOUSE_CLICK, MessageBoxHelper.Button.CANCEL));
      }
      if (messageBoxHelper.hasYesButton()) {
        testSteps.add(
            new MessageBoxTestStep(TestCaseAction.LEFT_MOUSE_CLICK, MessageBoxHelper.Button.YES));
      }
      if (messageBoxHelper.hasNoButton()) {
        testSteps.add(
            new MessageBoxTestStep(TestCaseAction.LEFT_MOUSE_CLICK, MessageBoxHelper.Button.NO));
      }
      if (messageBoxHelper.hasAbortButton()) {
        testSteps.add(
            new MessageBoxTestStep(TestCaseAction.LEFT_MOUSE_CLICK, MessageBoxHelper.Button.ABORT));
      }
      if (messageBoxHelper.hasRetryButton()) {
        testSteps.add(
            new MessageBoxTestStep(TestCaseAction.LEFT_MOUSE_CLICK, MessageBoxHelper.Button.RETRY));
      }
      if (messageBoxHelper.hasIgnoreButton()) {
        testSteps.add(
            new MessageBoxTestStep(
                TestCaseAction.LEFT_MOUSE_CLICK, MessageBoxHelper.Button.IGNORE));
      }
    }

    return testSteps;
  }
  private void executeTestStep(TestStep testStep) {
    //        logger.debug("Executing test step, testStep=" + testStep);

    WidgetHierarchy widgetHierarchy = new WidgetHierarchy();
    widgetHierarchy.getWidgetHierarchy(true);

    if (!(testStep instanceof MessageBoxTestStep)) {
      WidgetInfo widgetInfo = testStep.getWidgetInfo();
      Object proxy = widgetHierarchy.getWidgetProxy(widgetInfo.getWidgetID());
      if (proxy == null) {
        throw new GenerateTestCasesException("Widget doesn't exist, widgetInfo=" + widgetInfo);
      }
      WidgetProxy widgetProxy = (WidgetProxy) proxy;
      WidgetTester widgetTester = WidgetTesterFactory.getDefault().getTester(widgetProxy);
      widgetTester.mouseMove(widgetProxy);
      switch (testStep.getAction()) {
        case LEFT_MOUSE_CLICK:
          {
            widgetTester.actionClick(widgetProxy, SWTProxy.BUTTON1);
            break;
          }
        case RIGHT_MOUSE_CLICK:
          {
            widgetTester.actionClick(widgetProxy, SWTProxy.BUTTON3);
            break;
          }
        case ENTER_TEXT:
          {
            if (testStep instanceof EnterTextTestStep && widgetProxy instanceof TextProxy) {
              final TextProxy textProxy = (TextProxy) widgetProxy;
              widgetTester.actionClick(textProxy);
              textProxy
                  .getDisplay()
                  .syncExec(
                      new Runnable() {
                        public void run() {
                          textProxy.setText(
                              ""); // Clear the textfield to prevent generation of new strings.
                        }
                      });

              EnterTextTestStep enterTextTestStep = (EnterTextTestStep) testStep;
              widgetTester.actionKeyString(enterTextTestStep.getTextToEnter());
            }
            break;
          }
        case SELECT_ITEM:
          {
            if (testStep instanceof ComboTestStep
                && widgetProxy instanceof ComboProxy
                && widgetTester instanceof ComboTester) {
              ComboTestStep comboTestStep = (ComboTestStep) testStep;
              int itemIndex = comboTestStep.getItemIndex();

              ComboProxy comboProxy = (ComboProxy) widgetProxy;

              ComboTester comboTester = (ComboTester) widgetTester;
              comboTester.actionSelectIndex(comboProxy, itemIndex);
            }
            break;
          }
      }
    } else {
      MessageBoxHelper messageBoxHelper = widgetHierarchy.getMessageBoxHelper();
      if (messageBoxHelper == null) {
        throw new GenerateTestCasesException("MessageBox doesn't exist.");
      }
      MessageBoxTestStep messageBoxTestStep = (MessageBoxTestStep) testStep;
      messageBoxHelper.clickButton(messageBoxTestStep.getButton());
    }
  }
  private void generate() {
    synchronized (lock) {
      widgetStates.clear();
      uniqueTestCases.clear();
      processedTestCases.clear();
      currentTestCase = null;
      throwable = null;
    }

    try {
      final DisplayProxy defaultDisplay = DisplayProxy.Factory.getDefault();
      defaultDisplay.asyncExec(
          new Runnable() {
            public void run() {
              defaultDisplay.addFilter(SWTProxy.KeyDown, keyListener);
            }
          });

      returnToInitialState();

      // Add initial SUT state.
      WidgetHierarchy widgetHierarchy = new WidgetHierarchy();
      widgetHierarchy.getWidgetHierarchy(true);
      widgetHierarchy.populateValues();
      widgetStates.add(widgetHierarchy);

      boolean newUniqueTestCasesFound;
      do {
        newUniqueTestCasesFound = false;

        candidateTestCases = new LinkedHashSet<TestCase>();
        boolean firstStep = uniqueTestCases.size() == 0;
        if (firstStep) {
          List<TestStep> nextSteps = generateNextSteps();
          for (TestStep testStep : nextSteps) {
            TestCase newTestCase = new TestCase();
            newTestCase.add(testStep);
            candidateTestCases.add(newTestCase);
          }
        } else {
          for (TestCase testCase : uniqueTestCases) {
            if (processedTestCases.contains(testCase)) {
              continue;
            }

            returnToInitialState();

            if (isStopped()) {
              break;
            }

            currentTestCase = testCase;
            executeTestCase(testCase);

            List<TestStep> nextSteps = generateNextSteps();
            for (TestStep nextStep : nextSteps) {
              try {
                TestCase newTestCase = (TestCase) testCase.clone();
                newTestCase.add(nextStep);
                newTestCase.setParent(testCase);
                candidateTestCases.add(newTestCase);
              } catch (CloneNotSupportedException ignore) {
                // Ignore.
              }
            }

            processedTestCases.add(testCase);
          }
        }

        for (TestCase newTestCase : candidateTestCases) {
          if (isStopped()) {
            break;
          }

          if (!pruneTestCase(newTestCase)) {
            if (uniqueTestCases.add(newTestCase)) {
              uniqueTestCases.remove(newTestCase.getParent());
              logger.debug("Adding test case, newTestCase=" + newTestCase);
              newUniqueTestCasesFound = true;
            }
          } else {
            logger.debug("Test case will be pruned, newTestCase=" + newTestCase);
          }
        }

        logger.debug(
            "Current test case count="
                + uniqueTestCases.size()
                + ", new unique test cases found="
                + newUniqueTestCasesFound);
      } while (newUniqueTestCasesFound && !isStopped());

      returnToInitialState();
    } catch (Throwable throwable) {
      logger.error("An exception occurred during test case generation.", throwable);
      this.throwable = throwable;
    }

    final DisplayProxy defaultDisplay = DisplayProxy.Factory.getDefault();
    defaultDisplay.asyncExec(
        new Runnable() {
          public void run() {
            defaultDisplay.removeFilter(SWTProxy.KeyDown, keyListener);
          }
        });

    synchronized (lock) {
      executionState = ExecutionState.STOPPED;
      lock.notifyAll();
    }
  }