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
27package org.openjdk.tests.vm;
28
29import java.util.*;
30
31import org.testng.ITestResult;
32import org.testng.annotations.Test;
33import org.testng.annotations.DataProvider;
34import org.testng.annotations.AfterMethod;
35import org.testng.annotations.AfterSuite;
36
37import org.openjdk.tests.separate.*;
38import org.openjdk.tests.separate.Compiler;
39
40import org.openjdk.tests.shapegen.Hierarchy;
41import org.openjdk.tests.shapegen.HierarchyGenerator;
42import org.openjdk.tests.shapegen.ClassCase;
43
44import static org.testng.Assert.*;
45import static org.openjdk.tests.separate.SourceModel.*;
46import static org.openjdk.tests.separate.SourceModel.Class;
47import static org.openjdk.tests.separate.SourceModel.Method;
48import static org.openjdk.tests.separate.SourceModel.Type;
49
50public class FDSeparateCompilationTest extends TestHarness {
51
52    private static String EMPTY = "\"\"";
53
54    public FDSeparateCompilationTest() {
55        super(false, true);
56    }
57
58    @DataProvider(name = "allShapes", parallel = true)
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.
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")
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
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
131    public void cleanupCompilerCache() {
132        Compiler.purgeCache();
133    }
134
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
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
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