/******************************************************************************* * Copyright (c) 2009, 2014 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation * Zend Technologies * Dawid PakuĊ‚a - convert to JUnit4 *******************************************************************************/ package org.eclipse.php.core.tests.typeinference; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.io.File; import java.util.LinkedHashMap; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.declarations.ModuleDeclaration; import org.eclipse.dltk.ast.expressions.CallExpression; import org.eclipse.dltk.ast.expressions.Expression; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.SourceParserUtil; import org.eclipse.dltk.ti.IContext; import org.eclipse.dltk.ti.goals.ExpressionTypeGoal; import org.eclipse.dltk.ti.types.IEvaluatedType; import org.eclipse.php.core.tests.PdttFile; import org.eclipse.php.core.tests.TestSuiteWatcher; import org.eclipse.php.core.tests.TestUtils; import org.eclipse.php.core.tests.runner.PDTTList; import org.eclipse.php.core.tests.runner.PDTTList.AfterList; import org.eclipse.php.core.tests.runner.PDTTList.BeforeList; import org.eclipse.php.core.tests.runner.PDTTList.Parameters; import org.eclipse.php.core.PHPVersion; import org.eclipse.php.internal.core.typeinference.PHPTypeInferencer; import org.eclipse.php.internal.core.typeinference.context.ContextFinder; import org.junit.After; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TestWatcher; import org.junit.runner.RunWith; @RunWith(PDTTList.class) public class TypeInferenceTests { @ClassRule public static TestWatcher watcher = new TestSuiteWatcher(); protected static final int ENGINE_TIMEOUT = 100000; @Parameters public static final Map<PHPVersion, String[]> TESTS = new LinkedHashMap<PHPVersion, String[]>(); static { TESTS.put(PHPVersion.PHP5, new String[] { "/workspace/typeinference/php5" }); TESTS.put(PHPVersion.PHP5_3, new String[] { "/workspace/typeinference/php5" }); TESTS.put(PHPVersion.PHP5_4, new String[] { "/workspace/typeinference/php5", "/workspace/typeinference/php54" }); TESTS.put(PHPVersion.PHP5_5, new String[] { "/workspace/typeinference/php5", "/workspace/typeinference/php54", "/workspace/typeinference/php55" }); TESTS.put(PHPVersion.PHP5_6, new String[] { "/workspace/typeinference/php5", "/workspace/typeinference/php54", "/workspace/typeinference/php55", "/workspace/typeinference/php56" }); TESTS.put(PHPVersion.PHP7_0, new String[] { "/workspace/typeinference/php5", "/workspace/typeinference/php54", "/workspace/typeinference/php55", "/workspace/typeinference/php56" }); }; private static int counter = 0; private PHPTypeInferencer typeInferenceEngine; private IProject project; private PHPVersion version; protected IFile testFile; public TypeInferenceTests(PHPVersion version, String[] fileNames) { this.version = version; } @BeforeList public void setUpSuite() throws Exception { project = TestUtils.createProject("TypeInferenceTests_" + version.toString()); TestUtils.setProjectPhpVersion(project, version); typeInferenceEngine = new PHPTypeInferencer(); } @AfterList public void tearDownSuite() throws Exception { TestUtils.deleteProject(project); typeInferenceEngine = null; } @Test public void inference(String fileName) throws Exception { final PdttFile pdttFile = new PdttFile(fileName); createFile(pdttFile); final String pruner = getPrunerType(pdttFile); String criteriaFunction = new File(fileName).getName().replaceAll("\\.pdtt", ""); String code = pdttFile.getFile(); IEvaluatedType evaluatedType = findEvaluatedType(code, criteriaFunction, pruner); assertNotNull("Can't evaluate type for: " + code, evaluatedType); assertEquals(pdttFile.getExpected().trim(), evaluatedType.getTypeName().trim()); } @After public void after() throws Exception { TestUtils.deleteFile(testFile); } private static String getPrunerType(PdttFile pdttFile) { Map<String, String> config = pdttFile.getConfig(); return config.get("prune"); } class ASTNodeSearcher extends ContextFinder { private IContext context; private ASTNode result; private String criteriaFunction; public ASTNodeSearcher(ISourceModule sourceModule, String criteriaFunction) { super(sourceModule); this.criteriaFunction = criteriaFunction; } public boolean visit(Expression node) throws Exception { if (node instanceof CallExpression) { CallExpression callExpression = (CallExpression) node; if (criteriaFunction.equals(callExpression.getName())) { result = (ASTNode) callExpression.getArgs().getChilds().get(0); context = contextStack.peek(); return false; } } return true; } public ASTNode getResult() { return result; } public IContext getContext() { return context; } } protected void createFile(PdttFile pdttFile) throws Exception { String data = pdttFile.getFile(); testFile = TestUtils.createFile(project, "test-" + counter++ + ".php", data); TestUtils.waitForIndexer(); } protected IEvaluatedType findEvaluatedType(String code, String criteriaFunction, String pruner) throws Exception { ISourceModule sourceModule = DLTKCore.createSourceModuleFrom(testFile); ModuleDeclaration moduleDecl = SourceParserUtil.getModuleDeclaration(sourceModule); ASTNodeSearcher searcher = new ASTNodeSearcher(sourceModule, criteriaFunction); moduleDecl.traverse(searcher); assertNotNull("Method call " + criteriaFunction + "() in code: " + code, searcher.getResult()); assertNotNull("Can't find context for " + criteriaFunction + "() in code: " + code, searcher.getContext()); ExpressionTypeGoal goal = new ExpressionTypeGoal(searcher.getContext(), searcher.getResult()); if ("phpdocGoals".equals(pruner)) { return typeInferenceEngine.evaluateTypeHeavy(goal, ENGINE_TIMEOUT); } if ("heavyGoals".equals(pruner)) { return typeInferenceEngine.evaluateTypePHPDoc(goal, ENGINE_TIMEOUT); } return typeInferenceEngine.evaluateType(goal, ENGINE_TIMEOUT); } }