/** * 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(); }
// This finds the reflection method for a given name and parameter count and returns its return // type. // This assumes the methods have no overload on argument types, else it returns a non-existent // type to be corrected manually // If the method returns void, an exception is thrown as this shouldn't be happening. An // exception is also // thrown if the class isn't in the class path, which shouldn't happen either private static Type getReturnType(String methodName, int paramCount) { final Class<?> _class; try { _class = Class.forName( StateMachine.getInstance().getPackageName() + "." + getMachineClassName()); } catch (ClassNotFoundException exception) { throw new RuntimeException("Expected state machine class to be in classpath", exception); } final Method[] methods = _class.getMethods(); Type match = null; for (Method method : methods) { // Check for name match if (method.getName().equals(methodName)) { final int count = method.getParameterTypes().length; // Check for param count match, taking into account possible vararg expansion if (method.isVarArgs() ? count <= paramCount : count == paramCount) { if (match != null) { // Got a previous match, so we have an overload conflict on param types // This is hard to resolve, just give up, let the user figure it out return new ClassOrInterfaceType("FixMeType"); } // Found a (so far) unique match, get the return type final Class<?> returnType = method.getReturnType(); if (returnType == void.class) { throw new IllegalStateException("Getter shouldn't be returning void: " + methodName); } match = fromClass(returnType); } } } // We only get here if we find a unique method match return match; }
// This returns the simple name of the machine currently loaded private static String getMachineClassName() { final String javaFileName = StateMachine.getInstance().getClassName(); return javaFileName.substring(0, javaFileName.lastIndexOf(".java")); }