1 /*
2  * Copyright (c) 2012, 2013, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 // this test has been disabled because of timeout issues.
27 // see JDK-8006746
28 
29 package org.openjdk.tests.vm;
30 
31 import java.util.*;
32 
33 import org.testng.ITestResult;
34 import org.testng.annotations.Test;
35 import org.testng.annotations.DataProvider;
36 import org.testng.annotations.AfterMethod;
37 import org.testng.annotations.AfterSuite;
38 
39 import org.openjdk.tests.separate.*;
40 import org.openjdk.tests.separate.Compiler;
41 
42 import org.openjdk.tests.shapegen.Hierarchy;
43 import org.openjdk.tests.shapegen.HierarchyGenerator;
44 import org.openjdk.tests.shapegen.ClassCase;
45 
46 import static org.testng.Assert.*;
47 import static org.openjdk.tests.separate.SourceModel.*;
48 import static org.openjdk.tests.separate.SourceModel.Class;
49 import static org.openjdk.tests.separate.SourceModel.Method;
50 import static org.openjdk.tests.separate.SourceModel.Type;
51 
52 public class FDSeparateCompilationTest extends TestHarness {
53 
54     private static String EMPTY = "\"\"";
55 
FDSeparateCompilationTest()56     public FDSeparateCompilationTest() {
57         super(false, true);
58     }
59 
60     @DataProvider(name = "allShapes", parallel = true)
hierarchyGenerator()61     public Object[][] hierarchyGenerator() {
62         ArrayList<Object[]> allCases = new ArrayList<>();
63 
64         HierarchyGenerator hg = new HierarchyGenerator();
65         for (Object x : hg.getOK()) {
66             allCases.add(new Object[]{x});
67         }
68         for (Object x : hg.getErr()) {
69             allCases.add(new Object[]{x});
70         }
71         return allCases.toArray(new Object[0][]);
72     }
73 
74     // The expected value obtained when invoking the method from the specified
75     // class.  If returns null, then an AbstractMethodError is expected.
getExpectedResult(ClassCase cc)76     private static String getExpectedResult(ClassCase cc) {
77         Set<ClassCase> provs = cc.get_mprov();
78         if (cc.get_mres() != null) {
79             return cc.get_mres().getName();
80         } else if (provs != null && provs.size() == 1) {
81             ClassCase cand = provs.iterator().next();
82             switch (cand.kind) {
83                 case CCONCRETE:
84                 case IDEFAULT:
85                     return cand.getName();
86                 case CNONE:
87                 case IVAC:
88                     return getExpectedResult(cand);
89             }
90         }
91         return null;
92     }
93 
94     private static final ConcreteMethod canonicalMethod = new ConcreteMethod(
95             "String", "m", "returns " + EMPTY + ";", AccessFlag.PUBLIC);
96 
97     @Test(enabled = false, groups = "vm", dataProvider = "allShapes")
separateCompilationTest(Hierarchy hs)98     public void separateCompilationTest(Hierarchy hs) {
99         ClassCase cc = hs.root;
100         Type type = sourceTypeFrom(hs.root);
101 
102         Class specimen = null;
103         if (type instanceof Class) {
104             Class ctype = (Class)type;
105             if (ctype.isAbstract()) {
106                 specimen = new Class("Test" + ctype.getName(), ctype);
107             } else {
108                 specimen = ctype;
109             }
110         } else {
111             specimen = new Class("Test" + type.getName(), (Interface)type);
112         }
113 
114         String value = getExpectedResult(cc);
115         if (value != null) {
116             assertInvokeVirtualEquals(value, specimen, canonicalMethod, EMPTY);
117         } else {
118             assertThrows(AbstractMethodError.class, specimen,
119                 canonicalMethod, EMPTY);
120         }
121     }
122 
123     @AfterMethod
printCaseError(ITestResult result)124     public void printCaseError(ITestResult result) {
125         if (result.getStatus() == ITestResult.FAILURE) {
126             Hierarchy hs = (Hierarchy)result.getParameters()[0];
127             System.out.println("Separate compilation case " + hs);
128             printCaseDetails(hs);
129         }
130     }
131 
132     @AfterSuite
cleanupCompilerCache()133     public void cleanupCompilerCache() {
134         Compiler.purgeCache();
135     }
136 
printCaseDetails(Hierarchy hs)137     private void printCaseDetails(Hierarchy hs) {
138         String exp = getExpectedResult(hs.root);
139         for (String s : hs.getDescription()) {
140              System.out.println("    " + s);
141         }
142         if (exp != null) {
143             System.out.println("    Expected \"" + exp + "\"");
144         } else {
145             System.out.println("    Expected AbstractMethodError");
146         }
147     }
148 
sourceTypeFrom(ClassCase cc)149     private Type sourceTypeFrom(ClassCase cc) {
150         Type type = null;
151 
152         if (cc.isInterface()) {
153             Interface iface = new Interface(cc.getName());
154             for (ClassCase scc : cc.getInterfaces()) {
155                 Interface supertype = (Interface)sourceTypeFrom(scc);
156                 iface.addSuperType(supertype);
157             }
158             type = iface;
159         } else {
160             Class cls = new Class(cc.getName());
161             if (cc.hasSuperclass()) {
162                 Class superc = (Class)sourceTypeFrom(cc.getSuperclass());
163                 cls.setSuperClass(superc);
164             }
165             for (ClassCase scc : cc.getInterfaces()) {
166                 Interface supertype = (Interface)sourceTypeFrom(scc);
167                 cls.addSuperType(supertype);
168             }
169             if (cc.isAbstract()) {
170                 cls.getAccessFlags().add(AccessFlag.ABSTRACT);
171             }
172             type = cls;
173         }
174         Method method = methodFrom(cc);
175         if (method != null) {
176             type.addMethod(method);
177         }
178         return type;
179     }
180 
methodFrom(ClassCase cc)181     private Method methodFrom(ClassCase cc) {
182         switch (cc.kind) {
183             case IVAC:
184             case CNONE: return null;
185             case IPRESENT:
186             case CABSTRACT:
187                 return new AbstractMethod("String", "m", AccessFlag.PUBLIC);
188             case IDEFAULT:
189                 return new DefaultMethod(
190                     "String", "m", "return \"" + cc.getName() + "\";");
191             case CCONCRETE:
192                 return new ConcreteMethod(
193                     "String", "m", "return \"" + cc.getName() + "\";",
194                     AccessFlag.PUBLIC);
195             default:
196                 fail("Unknown method type in class");
197                 return null;
198         }
199     }
200 }
201