// 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; }