/******************************************************************************* * Copyright (c) 2012 Google, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Google, Inc. - initial API and implementation *******************************************************************************/ package com.windowtester.eclipse.ui.convert; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.CompilationUnit; import junit.framework.TestCase; public abstract class AbstractWTConvertAPITest extends TestCase { /** * Answer the content of the specified file in * com/windowtester/eclipse/ui/convert/<dirName>. In the process of reading the file * content, convert the line ends for this execution environment * * @param dirName the subdirectory name (not <code>null</code>) * @param fileName the file name (not <code>null</code>) */ protected String getSource(String dirName, String fileName) throws IOException { StringBuilder result = new StringBuilder(5000); InputStream stream = getClass().getResourceAsStream(dirName + "/" + fileName); if (stream == null) { String className = getClass().getName(); String packageName = className.substring(0, className.lastIndexOf('.')); String relPath = packageName.replace('.', '/'); return "Missing file: " + relPath + "/" + dirName + "/" + fileName; } try { LineNumberReader reader = new LineNumberReader(new InputStreamReader(new BufferedInputStream(stream))); while (true) { String line = reader.readLine(); if (line == null) break; result.append(line); // Standardize on \n because the AST nodes all default to \n line endings result.append('\n'); } } finally { stream.close(); } return result.toString(); } /** * Assert that the class, start position, and length of each node in the compilation * units match. */ public void assertEquals(CompilationUnit expected, CompilationUnit actual) { final Collection<ASTNode> expectedNodes = new ArrayList<ASTNode>(); expected.accept(new ASTVisitor() { public void postVisit(ASTNode node) { expectedNodes.add(node); } }); final Iterator<ASTNode> iter = expectedNodes.iterator(); actual.accept(new ASTVisitor() { public void postVisit(ASTNode actualNode) { ASTNode expectedNode = iter.next(); if (expectedNode.getClass() != actualNode.getClass() || expectedNode.getStartPosition() != actualNode.getStartPosition() || expectedNode.getLength() != actualNode.getLength()) { String errMsg = "Actual node does not equal expected node"; errMsg += "\nExpected getClass() = " + expectedNode.getClass(); errMsg += "\nActual getClass() = " + actualNode.getClass(); errMsg += "\nExpected getStartPosition() = " + expectedNode.getStartPosition(); errMsg += "\nActual getStartPosition() = " + actualNode.getStartPosition(); errMsg += "\nExpected getLength() = " + expectedNode.getLength(); errMsg += "\nActual getLength() = " + actualNode.getLength(); errMsg += "\nExpected = " + getSourceSnippet(expectedNode, 7); errMsg += "\nActual = " + getSourceSnippet(actualNode, 7); fail(errMsg); } } private String getSourceSnippet(ASTNode node, int depth) { String snippet = node.toString(); if (snippet.length() > 80) snippet = snippet.substring(0, 80) + "..."; if (depth > 0) { ASTNode parent = node.getParent(); if (parent != null) snippet += "\n " + getSourceSnippet(parent, depth - 1); } return snippet; } }); } /** * Test the specified set of rules by applying them to the source in the file * com/windowtester/eclipse/ui/convert/original/<fileName> and comparing the result to * the content of the file * com/windowtester/eclipse/ui/convert/<expectedDirName>/<fileName> * * @param expectedDirName the subdirectory of com/windowtester/eclipse/ui/convert that * contains the file with the expected result (e.g. "expandedimports") * @param fileName the name of both the original file and the expected result file * @param rules the rules to be applied */ public void testRules(String expectedDirName, String fileName, WTConvertAPIRule[] rules) throws IOException { String original = getSource("original", fileName); WTConvertAPIRefactoring refactoring = new WTConvertAPIRefactoring(null); refactoring.setRules(rules); WTConvertAPIContext context = refactoring.convertCompilationUnitSource(original); String actualSource = context.getSource(); CompilationUnit actualCompUnit = context.getCompilationUnit(); String expectedSource = getSource(expectedDirName, fileName); assertEquals(expectedSource, actualSource); ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setSource(expectedSource.toCharArray()); CompilationUnit expectedCompUnit = (CompilationUnit) parser.createAST(new NullProgressMonitor()); assertEquals(expectedCompUnit, actualCompUnit); } }