1 /*
2  * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package org.openjdk.tests.javac;
25 
26 import org.openjdk.tests.shapegen.*;
27 
28 import com.sun.source.util.JavacTask;
29 import com.sun.tools.javac.util.Pair;
30 
31 import java.io.IOException;
32 import java.net.URI;
33 import java.util.Arrays;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.List;
37 
38 import javax.tools.Diagnostic;
39 import javax.tools.JavaCompiler;
40 import javax.tools.JavaFileObject;
41 import javax.tools.SimpleJavaFileObject;
42 import javax.tools.StandardJavaFileManager;
43 import javax.tools.ToolProvider;
44 
45 import org.testng.annotations.AfterSuite;
46 import org.testng.annotations.Test;
47 import org.testng.annotations.BeforeSuite;
48 import org.testng.annotations.DataProvider;
49 import static org.testng.Assert.*;
50 
51 public class FDTest {
52 
53     public enum TestKind {
54         POSITIVE,
55         NEGATIVE;
56 
getHierarchy(HierarchyGenerator hg)57         Collection<Hierarchy> getHierarchy(HierarchyGenerator hg) {
58             return this == POSITIVE ?
59                     hg.getOK() : hg.getErr();
60         }
61     }
62 
63     public static JavaCompiler comp;
64     public static StandardJavaFileManager fm;
65 
66     @BeforeSuite
init()67     static void init() {
68         // create default shared JavaCompiler - reused across multiple
69         // compilations
70 
71         comp = ToolProvider.getSystemJavaCompiler();
72         fm = comp.getStandardFileManager(null, null, null);
73     }
74 
75     @AfterSuite
teardown()76     static void teardown() throws IOException {
77         fm.close();
78     }
79 
main(String[] args)80     public static void main(String[] args) throws Exception {
81         init();
82 
83         for (Pair<TestKind,Hierarchy> fdtest : generateCases()) {
84             runTest(fdtest.fst, fdtest.snd, comp, fm);
85         }
86 
87         teardown();
88     }
89 
90     @Test(dataProvider = "fdCases")
testOneCase(TestKind tk, Hierarchy hs)91     public void testOneCase(TestKind tk, Hierarchy hs)
92             throws Exception {
93         FDTest.runTest(tk, hs, comp, fm);
94     }
95 
96     @DataProvider(name = "fdCases")
caseGenerator()97     public Object[][] caseGenerator() {
98         List<Pair<TestKind, Hierarchy>> cases = generateCases();
99         Object[][] fdCases = new Object[cases.size()][];
100         for (int i = 0; i < cases.size(); ++i) {
101             fdCases[i] = new Object[2];
102             fdCases[i][0] = cases.get(i).fst;
103             fdCases[i][1] = cases.get(i).snd;
104         }
105         return fdCases;
106     }
107 
generateCases()108     public static List<Pair<TestKind, Hierarchy>> generateCases() {
109         ArrayList<Pair<TestKind,Hierarchy>> list = new ArrayList<>();
110         HierarchyGenerator hg = new HierarchyGenerator();
111         int i = 0;
112         for (TestKind tk : TestKind.values()) {
113             for (Hierarchy hs : tk.getHierarchy(hg)) {
114                 list.add((i++ % 2) == 0 ? new Pair<>(tk, hs) {} : new Pair<>(tk, hs));
115             }
116         }
117         return list;
118     }
119 
runTest(TestKind tk, Hierarchy hs, JavaCompiler comp, StandardJavaFileManager fm)120     public static void runTest(TestKind tk, Hierarchy hs,
121             JavaCompiler comp, StandardJavaFileManager fm) throws Exception {
122         new FDTest(tk, hs).run(comp, fm);
123     }
124 
125     TestKind tk;
126     Hierarchy hs;
127     DefenderTestSource source;
128     DiagnosticChecker diagChecker;
129 
FDTest()130     public FDTest() {}
131 
FDTest(TestKind tk, Hierarchy hs)132     FDTest(TestKind tk, Hierarchy hs) {
133         this.tk = tk;
134         this.hs = hs;
135         this.source = new DefenderTestSource();
136         this.diagChecker = new DiagnosticChecker();
137     }
138 
run(JavaCompiler tool, StandardJavaFileManager fm)139     void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
140         JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
141                 null, null, Arrays.asList(source));
142         try {
143             ct.analyze();
144         } catch (Throwable ex) {
145             fail("Error thrown when analyzing the following source:\n" + source.getCharContent(true));
146         }
147         check();
148     }
149 
check()150     void check() {
151         boolean errorExpected = tk == TestKind.NEGATIVE;
152         if (errorExpected != diagChecker.errorFound) {
153             fail("problem in source: \n" +
154                  "\nerror found = " + diagChecker.errorFound +
155                  "\nerror expected = " + errorExpected +
156                  "\n" + dumpHierarchy() +
157                  "\n" + source.getCharContent(true));
158         }
159     }
160 
dumpHierarchy()161     String dumpHierarchy() {
162         StringBuilder buf = new StringBuilder();
163         buf.append("root = " + hs.root + "\n");
164         for (ClassCase cc : hs.all) {
165             buf.append("  class name = " + cc.getName() + "\n");
166             buf.append("    class OK = " + cc.get_OK() + "\n");
167             buf.append("    prov = " + cc.get_mprov() + "\n");
168 
169         }
170         return buf.toString();
171     }
172 
173     class DefenderTestSource extends SimpleJavaFileObject {
174 
175         String source;
176 
DefenderTestSource()177         public DefenderTestSource() {
178             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
179             StringBuilder buf = new StringBuilder();
180             List<ClassCase> defaultRef = new ArrayList<>();
181             for (ClassCase cc : hs.all) {
182                 Hierarchy.genClassDef(buf, cc, null, defaultRef);
183             }
184             source = buf.toString();
185         }
186 
187         @Override
getCharContent(boolean ignoreEncodingErrors)188         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
189             return source;
190         }
191     }
192 
193     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
194 
195         boolean errorFound;
196 
report(Diagnostic<? extends JavaFileObject> diagnostic)197         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
198             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
199                 errorFound = true;
200             }
201         }
202     }
203 }
204