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.
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 // this test has been disabled because of timeout issues.
25 // see JDK-8006746
26 
27 package org.openjdk.tests.vm;
28 
29 import java.util.*;
30 
31 import org.testng.ITestResult;
32 import org.testng.annotations.Test;
33 import org.testng.annotations.DataProvider;
34 import org.testng.annotations.AfterMethod;
35 import org.testng.annotations.AfterSuite;
36 
37 import org.openjdk.tests.separate.*;
38 import org.openjdk.tests.separate.Compiler;
39 
40 import org.openjdk.tests.shapegen.Hierarchy;
41 import org.openjdk.tests.shapegen.HierarchyGenerator;
42 import org.openjdk.tests.shapegen.ClassCase;
43 
44 import static org.testng.Assert.*;
45 import static org.openjdk.tests.separate.SourceModel.*;
46 import static org.openjdk.tests.separate.SourceModel.Class;
47 import static org.openjdk.tests.separate.SourceModel.Method;
48 import static org.openjdk.tests.separate.SourceModel.Type;
49 
50 public class FDSeparateCompilationTest extends TestHarness {
51 
52     private static String EMPTY = "\"\"";
53 
FDSeparateCompilationTest()54     public FDSeparateCompilationTest() {
55         super(false, true);
56     }
57 
58     @DataProvider(name = "allShapes", parallel = true)
hierarchyGenerator()59     public Object[][] hierarchyGenerator() {
60         ArrayList<Object[]> allCases = new ArrayList<>();
61 
62         HierarchyGenerator hg = new HierarchyGenerator();
63         for (Object x : hg.getOK()) {
64             allCases.add(new Object[]{x});
65         }
66         for (Object x : hg.getErr()) {
67             allCases.add(new Object[]{x});
68         }
69         return allCases.toArray(new Object[0][]);
70     }
71 
72     // The expected value obtained when invoking the method from the specified
73     // class.  If returns null, then an AbstractMethodError is expected.
getExpectedResult(ClassCase cc)74     private static String getExpectedResult(ClassCase cc) {
75         Set<ClassCase> provs = cc.get_mprov();
76         if (cc.get_mres() != null) {
77             return cc.get_mres().getName();
78         } else if (provs != null && provs.size() == 1) {
79             ClassCase cand = provs.iterator().next();
80             switch (cand.kind) {
81                 case CCONCRETE:
82                 case IDEFAULT:
83                     return cand.getName();
84                 case CNONE:
85                 case IVAC:
86                     return getExpectedResult(cand);
87             }
88         }
89         return null;
90     }
91 
92     private static final ConcreteMethod canonicalMethod = new ConcreteMethod(
93             "String", "m", "returns " + EMPTY + ";", AccessFlag.PUBLIC);
94 
95     @Test(enabled = false, groups = "vm", dataProvider = "allShapes")
separateCompilationTest(Hierarchy hs)96     public void separateCompilationTest(Hierarchy hs) {
97         ClassCase cc = hs.root;
98         Type type = sourceTypeFrom(hs.root);
99 
100         Class specimen = null;
101         if (type instanceof Class) {
102             Class ctype = (Class)type;
103             if (ctype.isAbstract()) {
104                 specimen = new Class("Test" + ctype.getName(), ctype);
105             } else {
106                 specimen = ctype;
107             }
108         } else {
109             specimen = new Class("Test" + type.getName(), (Interface)type);
110         }
111 
112         String value = getExpectedResult(cc);
113         if (value != null) {
114             assertInvokeVirtualEquals(value, specimen, canonicalMethod, EMPTY);
115         } else {
116             assertThrows(AbstractMethodError.class, specimen,
117                 canonicalMethod, EMPTY);
118         }
119     }
120 
121     @AfterMethod
printCaseError(ITestResult result)122     public void printCaseError(ITestResult result) {
123         if (result.getStatus() == ITestResult.FAILURE) {
124             Hierarchy hs = (Hierarchy)result.getParameters()[0];
125             System.out.println("Separate compilation case " + hs);
126             printCaseDetails(hs);
127         }
128     }
129 
130     @AfterSuite
cleanupCompilerCache()131     public void cleanupCompilerCache() {
132         Compiler.purgeCache();
133     }
134 
printCaseDetails(Hierarchy hs)135     private void printCaseDetails(Hierarchy hs) {
136         String exp = getExpectedResult(hs.root);
137         for (String s : hs.getDescription()) {
138              System.out.println("    " + s);
139         }
140         if (exp != null) {
141             System.out.println("    Expected \"" + exp + "\"");
142         } else {
143             System.out.println("    Expected AbstractMethodError");
144         }
145     }
146 
sourceTypeFrom(ClassCase cc)147     private Type sourceTypeFrom(ClassCase cc) {
148         Type type = null;
149 
150         if (cc.isInterface()) {
151             Interface iface = new Interface(cc.getName());
152             for (ClassCase scc : cc.getInterfaces()) {
153                 Interface supertype = (Interface)sourceTypeFrom(scc);
154                 iface.addSuperType(supertype);
155             }
156             type = iface;
157         } else {
158             Class cls = new Class(cc.getName());
159             if (cc.hasSuperclass()) {
160                 Class superc = (Class)sourceTypeFrom(cc.getSuperclass());
161                 cls.setSuperClass(superc);
162             }
163             for (ClassCase scc : cc.getInterfaces()) {
164                 Interface supertype = (Interface)sourceTypeFrom(scc);
165                 cls.addSuperType(supertype);
166             }
167             if (cc.isAbstract()) {
168                 cls.getAccessFlags().add(AccessFlag.ABSTRACT);
169             }
170             type = cls;
171         }
172         Method method = methodFrom(cc);
173         if (method != null) {
174             type.addMethod(method);
175         }
176         return type;
177     }
178 
methodFrom(ClassCase cc)179     private Method methodFrom(ClassCase cc) {
180         switch (cc.kind) {
181             case IVAC:
182             case CNONE: return null;
183             case IPRESENT:
184             case CABSTRACT:
185                 return new AbstractMethod("String", "m", AccessFlag.PUBLIC);
186             case IDEFAULT:
187                 return new DefaultMethod(
188                     "String", "m", "return \"" + cc.getName() + "\";");
189             case CCONCRETE:
190                 return new ConcreteMethod(
191                     "String", "m", "return \"" + cc.getName() + "\";",
192                     AccessFlag.PUBLIC);
193             default:
194                 fail("Unknown method type in class");
195                 return null;
196         }
197     }
198 }
199