// This method does the actual body generation: the body is forked for every children and only
 // added to the bodies list when the leaf is reached
 private static void generateTestBodies(
     RoundTripPathTreeNode node,
     BlockStmt body,
     List<BlockStmt> bodies,
     Map<String, Integer> usedVarNames) {
   final List<Statement> statements = body.getStmts();
   final Transition transition = node.getTransition();
   // This comment will be added to the first statement in this event check
   final LineComment comment = new LineComment(" " + node.getSignature());
   boolean commentAdded = false;
   // Generate the condition reacher first if needed
   if (!transition.getCondition().isEmpty()) {
     final Statement conditionReacher = generateConditionReacher(transition.getCondition());
     conditionReacher.setComment(comment);
     commentAdded = true;
     statements.add(conditionReacher);
   }
   // Next place the pre statements of the action checks
   final List<ActionCheck> checks = generateActionChecks(transition.getAction(), usedVarNames);
   for (ActionCheck check : checks) {
     final List<Statement> pre = check.getPre();
     // Add the comment to the first pre statement, if any exist
     if (!commentAdded && !pre.isEmpty()) {
       pre.get(0).setComment(comment);
       commentAdded = true;
     }
     statements.addAll(pre);
   }
   // Now we add the actual event call
   final Statement eventStatement = eventAsStatement(transition.getEvent());
   if (!commentAdded) {
     // If this is the first statement, add the comment now
     eventStatement.setComment(comment);
   }
   statements.add(eventStatement);
   // Next we check that the event caused the right state
   statements.add(generateStateCheck(transition.getTo().getName()));
   // Finally we check the action results using the post statements
   for (ActionCheck check : checks) {
     statements.add(check.getPost());
   }
   // Generate the rest of the test case using the children
   final List<RoundTripPathTreeNode> children = node.getChildren();
   if (children.isEmpty()) {
     // Reached leaf, test case is complete
     bodies.add(body);
   } else {
     // Generate the test statements for the next state transitions
     for (RoundTripPathTreeNode child : children) {
       // Clone the body and used variable names to ensure each test case has its own
       generateTestBodies(
           child, (BlockStmt) body.clone(), bodies, new HashMap<String, Integer>(usedVarNames));
     }
   }
 }
 // This generates generates the bodies of the test methods, given a starting node
 private static List<BlockStmt> generateTestBodies(RoundTripPathTreeNode node) {
   if (!node.isAlpha()) {
     throw new IllegalArgumentException("Expected first node to be alpha");
   }
   final BlockStmt body = new BlockStmt(new ArrayList<Statement>());
   final List<BlockStmt> bodies = new ArrayList<BlockStmt>();
   // We need to track variable names used through the test case to prevent conflicts
   final Map<String, Integer> usedVarNames = new HashMap<String, Integer>();
   // Don't pass the alpha node, but the children
   for (RoundTripPathTreeNode child : node.getChildren()) {
     generateTestBodies(child, body, bodies, usedVarNames);
   }
   return bodies;
 }
 /**
  * Generates the test cases for the state machine in {@link StateMachine#getInstance()} and writes
  * the file to the given output path.
  *
  * @param outputClassName The simple name of the generate class containing the generated test
  *     cases
  * @return The source code for the generated test class
  */
 public static String generate(String outputClassName) {
   final StateMachine machine = StateMachine.getInstance();
   final RoundTripPathTreeNode tree = RoundTripPathTreeNode.build(machine.getStartState());
   final List<BodyDeclaration> methods = generateTestMethods(tree);
   final ClassOrInterfaceDeclaration testClass =
       new ClassOrInterfaceDeclaration(ModifierSet.PUBLIC, false, outputClassName);
   testClass.setMembers(methods);
   final CompilationUnit file =
       new CompilationUnit(
           new PackageDeclaration(new NameExpr(machine.getPackageName())),
           generateImports(Assert.class, Test.class),
           Collections.<TypeDeclaration>singletonList(testClass));
   return file.toString();
 }