Path: blob/master/test/langtools/jdk/jshell/CompletenessStressTest.java
40930 views
/*1* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.File;24import java.io.IOException;25import java.io.StringWriter;26import java.nio.charset.StandardCharsets;27import java.nio.file.Files;28import java.nio.file.Path;29import java.nio.file.Paths;30import java.util.ArrayList;31import java.util.List;32import java.util.Set;33import java.util.stream.Collectors;3435import javax.lang.model.element.Modifier;36import javax.tools.JavaCompiler;37import javax.tools.JavaFileObject;38import javax.tools.StandardJavaFileManager;39import javax.tools.ToolProvider;4041import com.sun.source.tree.BlockTree;42import com.sun.source.tree.BreakTree;43import com.sun.source.tree.CaseTree;44import com.sun.source.tree.ClassTree;45import com.sun.source.tree.CompilationUnitTree;46import com.sun.source.tree.ContinueTree;47import com.sun.source.tree.DoWhileLoopTree;48import com.sun.source.tree.ExpressionStatementTree;49import com.sun.source.tree.ForLoopTree;50import com.sun.source.tree.IfTree;51import com.sun.source.tree.ImportTree;52import com.sun.source.tree.LabeledStatementTree;53import com.sun.source.tree.LineMap;54import com.sun.source.tree.MethodTree;55import com.sun.source.tree.ReturnTree;56import com.sun.source.tree.StatementTree;57import com.sun.source.tree.SwitchTree;58import com.sun.source.tree.Tree;59import com.sun.source.tree.WhileLoopTree;60import com.sun.source.util.SourcePositions;61import com.sun.source.util.Trees;62import com.sun.tools.javac.api.JavacTaskImpl;6364import jdk.jshell.SourceCodeAnalysis;6566import org.testng.annotations.DataProvider;67import org.testng.annotations.Test;6869import static java.lang.Integer.max;70import static java.lang.Integer.min;71import static jdk.jshell.SourceCodeAnalysis.Completeness.*;7273public class CompletenessStressTest extends KullaTesting {74public final static String JDK_ROOT_SRC_PROP = "jdk.root.src";75public final static String JDK_ROOT_SRC;7677static {78JDK_ROOT_SRC = System.getProperty(JDK_ROOT_SRC_PROP);79}8081public File getSourceFile(String fileName) {82for (File dir : getDirectoriesToTest()) {83File file = new File(dir, fileName);84if (file.exists()) {85return file;86}87}88throw new AssertionError("File not found: " + fileName);89}9091public File[] getDirectoriesToTest() {92return new File[]{93new File(JDK_ROOT_SRC, "langtools/src"),94new File(JDK_ROOT_SRC, "jaxp/src"),95new File(JDK_ROOT_SRC, "jaxws/src"),96new File(JDK_ROOT_SRC, "jdk/src"),97new File(JDK_ROOT_SRC, "corba/src")98};99}100101@DataProvider(name = "crawler")102public Object[][] dataProvider() throws IOException {103File[] srcDirs = getDirectoriesToTest();104List<String[]> list = new ArrayList<>();105for (File srcDir : srcDirs) {106String srcDirName = srcDir.getAbsolutePath();107// this is just to obtain pretty test names for testng tests108List<String[]> a = Files.walk(Paths.get(srcDirName))109.map(Path::toFile)110.map(File::getAbsolutePath)111.filter(n -> n.endsWith(".java"))112.map(n -> n.replace(srcDirName, ""))113.map(n -> new String[]{n})114.collect(Collectors.toList());115if (a.isEmpty()) {116throw new AssertionError("Java sources have not been found in directory: " + srcDirName);117}118list.addAll(a);119}120return list.toArray(new String[list.size()][]);121}122123@Test(dataProvider = "crawler")124public void testFile(String fileName) throws IOException {125File file = getSourceFile(fileName);126final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();127final StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);128boolean success = true;129StringWriter writer = new StringWriter();130writer.write("Testing : " + file.toString() + "\n");131String text = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);132Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(file);133JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, fileManager, null, null, null, compilationUnits);134Iterable<? extends CompilationUnitTree> asts = task.parse();135Trees trees = Trees.instance(task);136SourcePositions sp = trees.getSourcePositions();137138for (CompilationUnitTree cut : asts) {139for (ImportTree imp : cut.getImports()) {140success &= testStatement(writer, sp, text, cut, imp);141}142for (Tree decl : cut.getTypeDecls()) {143success &= testStatement(writer, sp, text, cut, decl);144if (decl instanceof ClassTree) {145ClassTree ct = (ClassTree) decl;146for (Tree mem : ct.getMembers()) {147if (mem instanceof MethodTree) {148MethodTree mt = (MethodTree) mem;149BlockTree bt = mt.getBody();150// No abstract methods or constructors151if (bt != null && mt.getReturnType() != null) {152// The modifiers synchronized, abstract, and default are not allowed on153// top-level declarations and are errors.154Set<Modifier> modifier = mt.getModifiers().getFlags();155if (!modifier.contains(Modifier.ABSTRACT)156&& !modifier.contains(Modifier.SYNCHRONIZED)157&& !modifier.contains(Modifier.DEFAULT)) {158success &= testStatement(writer, sp, text, cut, mt);159}160testBlock(writer, sp, text, cut, bt);161}162}163}164}165}166}167fileManager.close();168if (!success) {169throw new AssertionError(writer.toString());170}171}172173private boolean isLegal(StatementTree st) {174return !(st instanceof ReturnTree) &&175!(st instanceof ContinueTree) && !(st instanceof BreakTree);176}177178private boolean testBranch(StringWriter writer, SourcePositions sp, String text, CompilationUnitTree cut, StatementTree statementTree) {179if (statementTree instanceof BlockTree) {180return testBlock(writer, sp, text, cut, (BlockTree) statementTree);181} else if (isLegal(statementTree)) {182return testStatement(writer, sp, text, cut, statementTree);183}184return true;185}186187private boolean testBlock(StringWriter writer, SourcePositions sp, String text, CompilationUnitTree cut, BlockTree blockTree) {188boolean success = true;189for (StatementTree st : blockTree.getStatements()) {190if (isLegal(st)) {191success &= testStatement(writer, sp, text, cut, st);192}193if (st instanceof IfTree) {194IfTree ifTree = (IfTree) st;195success &= testBranch(writer, sp, text, cut, ifTree.getThenStatement());196success &= testBranch(writer, sp, text, cut, ifTree.getElseStatement());197} else if (st instanceof WhileLoopTree) {198WhileLoopTree whileLoopTree = (WhileLoopTree) st;199success &= testBranch(writer, sp, text, cut, whileLoopTree.getStatement());200} else if (st instanceof DoWhileLoopTree) {201DoWhileLoopTree doWhileLoopTree = (DoWhileLoopTree) st;202success &= testBranch(writer, sp, text, cut, doWhileLoopTree.getStatement());203} else if (st instanceof ForLoopTree) {204ForLoopTree forLoopTree = (ForLoopTree) st;205success &= testBranch(writer, sp, text, cut, forLoopTree.getStatement());206} else if (st instanceof LabeledStatementTree) {207LabeledStatementTree labelTree = (LabeledStatementTree) st;208success &= testBranch(writer, sp, text, cut, labelTree.getStatement());209} else if (st instanceof SwitchTree) {210SwitchTree switchTree = (SwitchTree) st;211for (CaseTree caseTree : switchTree.getCases()) {212for (StatementTree statementTree : caseTree.getStatements()) {213success &= testBranch(writer, sp, text, cut, statementTree);214}215}216}217}218return success;219}220221private boolean testStatement(StringWriter writer, SourcePositions sp, String text, CompilationUnitTree cut, Tree statement) {222if (statement == null) {223return true;224}225int start = (int) sp.getStartPosition(cut, statement);226int end = (int) sp.getEndPosition(cut, statement);227char ch = text.charAt(end - 1);228SourceCodeAnalysis.Completeness expected = COMPLETE;229LineMap lineMap = cut.getLineMap();230int row = (int) lineMap.getLineNumber(start);231int column = (int) lineMap.getColumnNumber(start);232switch (ch) {233case ',':234case ';':235expected = (statement instanceof ExpressionStatementTree)236? COMPLETE237: COMPLETE_WITH_SEMI;238--end;239break;240case '}':241break;242default:243writer.write(String.format("Unexpected end: row %d, column %d: '%c' -- %s\n",244row, column, ch, text.substring(start, end)));245return true;246}247String unit = text.substring(start, end);248SourceCodeAnalysis.CompletionInfo ci = getAnalysis().analyzeCompletion(unit);249if (ci.completeness() != expected) {250if (expected == COMPLETE_WITH_SEMI && (ci.completeness() == CONSIDERED_INCOMPLETE || ci.completeness() == EMPTY)) {251writer.write(String.format("Empty statement: row %d, column %d: -- %s\n",252start, end, unit));253} else {254writer.write(String.format("Expected %s got %s: '%s' row %d, column %d: -- %s\n",255expected, ci.completeness(), unit, row, column, unit));256return false;257}258}259return true;260}261}262263264