/**
  * Get the full name of this test.
  *
  * @return The full name of this test.
  */
 public String getFullName() {
   TestSuite suite = mParentCase.getParent();
   return suite.getFullName() + "." + mParentCase.getName() + METHOD_SEPARATOR + mName;
 }
 /**
  * Get the app package name space of this test.
  *
  * @return The app package name space of this test.
  */
 public String getAppNameSpace() {
   TestPackage pkg = mParentCase.getParent().getParent();
   return pkg.getAppNameSpace();
 }
 /**
  * Get the parent TestPackage containing the test.
  *
  * @return The parent TestPackage.
  */
 public TestPackage getTestPackage() {
   return mParentCase.getParent().getParent();
 }
 /**
  * Get the parent TestSuite containing the test.
  *
  * @return The parent TestSuite.
  */
 public TestSuite getTestSuite() {
   return mParentCase.getParent();
 }
 /**
  * Get the instrumentation runner.
  *
  * @return The instrumentation runner.
  */
 public String getInstrumentationRunner() {
   TestPackage pkg = mParentCase.getParent().getParent();
   return pkg.getInstrumentationRunner();
 }
  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();
    }
  }