jjg@1401: /* jjg@1492: * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. jjg@1401: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@1401: * jjg@1401: * This code is free software; you can redistribute it and/or modify it jjg@1401: * under the terms of the GNU General Public License version 2 only, as jjg@1401: * published by the Free Software Foundation. jjg@1401: * jjg@1401: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@1401: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@1401: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@1401: * version 2 for more details (a copy is included in the LICENSE file that jjg@1401: * accompanied this code). jjg@1401: * jjg@1401: * You should have received a copy of the GNU General Public License version jjg@1401: * 2 along with this work; if not, write to the Free Software Foundation, jjg@1401: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@1401: * jjg@1401: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jjg@1401: * or visit www.oracle.com if you need additional information or have any jjg@1401: * questions. jjg@1401: */ jjg@1401: jjg@1401: /** jjg@1401: * @test jjg@1401: * @bug 8002157 jjg@1401: * @author sogoel jjg@1401: * @summary Combo test for all possible combinations for Retention Values jjg@1401: * @build Helper jjg@1401: * @compile RetentionAnnoCombo.java jjg@1401: * @run main RetentionAnnoCombo jjg@1401: */ jjg@1401: jjg@1401: import java.util.HashMap; jjg@1401: import java.util.Map; jjg@1401: jjg@1401: import javax.tools.DiagnosticCollector; jjg@1401: import javax.tools.JavaFileObject; jjg@1401: import javax.tools.Diagnostic; jjg@1401: jjg@1401: /* jjg@1401: * Generate all combinations for the use of @Retention on base anno or container jjg@1401: * anno or both. The test passes if valid test src compile as expected and jjg@1401: * and invalid test src fail as expected. jjg@1401: * Repeating annotations used only on class for these generated test src. jjg@1401: */ jjg@1401: jjg@1401: public class RetentionAnnoCombo extends Helper { jjg@1401: static int errors = 0; jjg@1401: static boolean exitMode = false; jjg@1401: static { jjg@1401: String exitOnFail = System.getenv("EXIT_ON_FAIL"); jjg@1401: if (exitOnFail == null || exitOnFail == "" ) { jjg@1401: exitMode = false; jjg@1401: } jjg@1401: else { jjg@1401: if (exitOnFail.equalsIgnoreCase("YES") || jjg@1401: exitOnFail.equalsIgnoreCase("Y") || jjg@1401: exitOnFail.equalsIgnoreCase("TRUE") || jjg@1401: exitOnFail.equalsIgnoreCase("T")) { jjg@1401: exitMode = true; jjg@1401: } jjg@1401: } jjg@1401: } jjg@1401: jjg@1401: public static void main(String args[]) throws Exception { jjg@1401: new RetentionAnnoCombo().runTest(); jjg@1401: } jjg@1401: jjg@1401: public void runTest() throws Exception { jjg@1401: jjg@1401: /* 4x4 matrix for Retention values SOURCE, DEFAULT, CLASS, RUNTIME jjg@1401: * i -> Retention value on ContainerAnno jjg@1401: * j -> Retention value on BaseAnno jjg@1401: * 1 -> retention value combo should compile jjg@1401: */ jjg@1401: int[][] retention = { {1, 0, 0, 0}, jjg@1401: {1, 1, 1, 0}, jjg@1401: {1, 1, 1, 0}, jjg@1401: {1, 1, 1, 1} }; jjg@1401: jjg@1401: Map retMap = setRetentionValMatrix(); jjg@1401: String contents = ""; jjg@1401: boolean result = false; jjg@1401: int testCtr = 0; jjg@1401: for (int i = 0; i < 4 ; i ++) { jjg@1401: for (int j = 0; j < 4; j++ ) { jjg@1401: testCtr++; jjg@1401: String className = "RetentionTest_"+i+"_"+j; jjg@1401: contents = getContent(className, retMap, i, j); jjg@1401: if (retention[i][j] == 1) { jjg@1401: // Code generated should compile jjg@1401: result = getCompileResult(contents,className, true); jjg@1401: if (!result) { jjg@1401: error("FAIL: " + className + " did not compile as expected!", contents); jjg@1401: } jjg@1401: } else { jjg@1401: result = getCompileResult(contents,className, false); jjg@1401: if (!result) { jjg@1401: error("FAIL: " + className + " compiled unexpectedly!", contents); jjg@1401: } jjg@1401: } jjg@1401: if (result) { jjg@1401: System.out.println("Test passed for className = " + className); jjg@1401: } jjg@1401: } jjg@1401: } jjg@1401: jjg@1401: System.out.println("Total number of tests run: " + testCtr); jjg@1401: System.out.println("Total number of errors: " + errors); jjg@1401: jjg@1401: if (errors > 0) jjg@1401: throw new Exception(errors + " errors found"); jjg@1401: } jjg@1401: jjg@1401: private boolean getCompileResult(String contents, String className, jjg@1401: boolean shouldCompile) throws Exception{ jjg@1401: jjg@1401: DiagnosticCollector diagnostics = jjg@1401: new DiagnosticCollector(); jjg@1401: boolean ok = compileCode(className, contents, diagnostics); jjg@1401: jjg@1492: String expectedErrKey = "compiler.err.invalid.repeatable" + jjg@1401: ".annotation.retention"; jjg@1401: if (!shouldCompile && !ok) { jjg@1401: for (Diagnostic d : diagnostics.getDiagnostics()) { jjg@1401: if (!((d.getKind() == Diagnostic.Kind.ERROR) && jjg@1401: d.getCode().contains(expectedErrKey))) { jjg@1401: error("FAIL: Incorrect error given, expected = " jjg@1401: + expectedErrKey + ", Actual = " + d.getCode() jjg@1401: + " for className = " + className, contents); jjg@1401: } jjg@1401: } jjg@1401: } jjg@1401: jjg@1401: return (shouldCompile == ok); jjg@1401: } jjg@1401: jjg@1401: private Map setRetentionValMatrix() { jjg@1401: HashMap hm = new HashMap<>(); jjg@1401: hm.put(0,"SOURCE"); jjg@1401: hm.put(1,"DEFAULT"); jjg@1401: hm.put(2,"CLASS"); jjg@1401: hm.put(3,"RUNTIME"); jjg@1401: return hm; jjg@1401: } jjg@1401: jjg@1401: private String getContent(String className, Map retMap, jjg@1401: int i, int j) { jjg@1401: jjg@1401: String retContainerVal = retMap.get(i).toString(); jjg@1401: String retBaseVal = retMap.get(j).toString(); jjg@1401: String replacedRetBaseVal = "", replacedRetCAVal = ""; jjg@1401: String retention = Helper.ContentVars.RETENTION.getVal(); jjg@1401: jjg@1401: // @Retention is available as default for both base and container anno jjg@1401: if (retContainerVal.equalsIgnoreCase("DEFAULT") jjg@1401: && retBaseVal.equalsIgnoreCase("DEFAULT")) { jjg@1401: replacedRetBaseVal = ""; jjg@1401: replacedRetCAVal = ""; jjg@1401: // @Retention is available as default for container anno jjg@1401: } else if (retContainerVal.equalsIgnoreCase("DEFAULT")) { jjg@1401: replacedRetBaseVal = retention.replace("#VAL", retBaseVal); jjg@1401: replacedRetCAVal = ""; jjg@1401: // @Retention is available as default for base anno jjg@1401: } else if (retBaseVal.equalsIgnoreCase("DEFAULT")) { jjg@1401: replacedRetBaseVal = ""; jjg@1401: replacedRetCAVal = retention.replace("#VAL", retContainerVal); jjg@1401: // @Retention is not available as default for both base and container anno jjg@1401: } else { jjg@1401: replacedRetBaseVal = retention.replace("#VAL", retBaseVal); jjg@1401: replacedRetCAVal = retention.replace("#VAL", retContainerVal); jjg@1401: } jjg@1401: jjg@1401: StringBuilder annoData = new StringBuilder(); jjg@1401: annoData.append(Helper.ContentVars.IMPORTCONTAINERSTMTS.getVal()) jjg@1401: .append(Helper.ContentVars.IMPORTRETENTION.getVal()) jjg@1401: .append(replacedRetCAVal) jjg@1401: .append(Helper.ContentVars.CONTAINER.getVal()) jjg@1492: .append(Helper.ContentVars.REPEATABLE.getVal()) jjg@1401: .append(replacedRetBaseVal) jjg@1401: .append(Helper.ContentVars.BASE.getVal()); jjg@1401: jjg@1401: String contents = annoData jjg@1401: + Helper.ContentVars.REPEATABLEANNO.getVal() jjg@1401: + "\nclass "+ className + "{}"; jjg@1401: return contents; jjg@1401: } jjg@1401: jjg@1401: private void error(String msg,String... contents) throws Exception { jjg@1401: System.out.println("error: " + msg); jjg@1401: errors++; jjg@1401: if (contents.length == 1) { jjg@1401: System.out.println("Contents = " + contents[0]); jjg@1401: } jjg@1401: // Test exits as soon as it gets a failure jjg@1401: if (exitMode) throw new Exception(); jjg@1401: } jjg@1401: } jjg@1401: