jdk/test/java/lang/Package/annotation/PackageInfoTest.java
author amlu
Fri, 18 Nov 2016 14:39:03 +0800
changeset 42166 5582c83b1156
parent 36511 9d0388c6b336
child 44358 d1d1a888d492
permissions -rw-r--r--
8169836: ProblemList update for java/lang/management/MemoryMXBean/PendingAllGC.sh Reviewed-by: mchung

/*
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @summary Basic test of package-info in named module and duplicate
 *          package-info in unnamed module
 * @modules java.compiler
 *          java.desktop
 *          jdk.compiler
 *          jdk.xml.dom
 * @build jdk.xml.dom/org.w3c.dom.css.Fake
 *        jdk.xml.dom/org.w3c.dom.css.FakePackage
 * @compile/module=jdk.xml.dom org/w3c/dom/css/package-info.java
 * @compile package-info.java PackageInfoTest.java
 * @run testng p.PackageInfoTest
 */

package p;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.w3c.dom.css.CSSRule;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import static org.testng.Assert.*;

public class PackageInfoTest {
    @DataProvider(name = "jdkClasses")
    public Object[][] jdkClasses() {
        return new Object[][] {
            { java.awt.Button.class,             null },
            { java.lang.Object.class,            null },
            { org.w3c.dom.css.CSSRule.class,     null },
            { loadClass("org.w3c.dom.css.Fake"), loadClass("org.w3c.dom.css.FakePackage") },
        };
    }

    @Test(dataProvider = "jdkClasses")
    public void testPackageInfo(Class<?> type, Class<? extends Annotation> annType) {
        Package pkg = type.getPackage();
        assertTrue(pkg.isSealed());
        assertTrue(annType == null || pkg.getDeclaredAnnotations().length != 0);
        if (annType != null) {
            assertTrue(pkg.isAnnotationPresent(annType));
        }
    }

    private Class<?> loadClass(String name) {
        return Class.forName(CSSRule.class.getModule(), name);
    }

    @DataProvider(name = "classpathClasses")
    public Object[][] cpClasses() throws IOException, ClassNotFoundException {
        // these classes will be loaded from classpath in unnamed module
        return new Object[][]{
                { p.PackageInfoTest.class, Deprecated.class }
        };
    }

    @Test(dataProvider = "classpathClasses")
    public void testClassPathPackage(Class<?> type, Class<? extends Annotation> annType) {
        Package pkg = type.getPackage();
        assertTrue(pkg.isSealed() == false);
        assertTrue(pkg.isAnnotationPresent(annType));
    }

    static final String[] otherClasses = new String[] {
            "p/package-info.class",
            "p/Duplicate.class",
            "p/Bar.class"
    };

    @Test
    public void testDuplicatePackage() throws Exception {
        // a custom class loader loading another package p annotated with @Duplicate
        Path classes = Paths.get(System.getProperty("test.classes", "."), "tmp");
        Files.createDirectories(classes);
        URLClassLoader loader = new URLClassLoader(new URL[] { classes.toUri().toURL() });

        // clean up before compiling classes
        Arrays.stream(otherClasses)
                .forEach(c -> {
                    try {
                        Files.deleteIfExists(classes.resolve(c));
                    } catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
                });

        Path src = Paths.get(System.getProperty("test.src", "."), "src", "p");
        compile(classes,
                src.resolve("package-info.java"),
                src.resolve("Duplicate.java"),
                src.resolve("Bar.java"));

        // verify if classes are present
        Arrays.stream(otherClasses)
              .forEach(c -> {
                  if (Files.notExists(classes.resolve(c))) {
                      throw new RuntimeException(c + " not exist");
                  }
        });

        Class<?> c = Class.forName("p.Bar", true, loader);
        assertTrue(c.getClassLoader() == loader);
        assertTrue(this.getClass().getClassLoader() != loader);

        // package p defined by the custom class loader
        Package pkg = c.getPackage();
        assertTrue(pkg.getName().equals("p"));
        assertTrue(pkg.isSealed() == false);

        // package p defined by the application class loader
        Package p = this.getClass().getPackage();
        assertTrue(p.getName().equals("p"));
        assertTrue(p != pkg);

        Arrays.stream(pkg.getDeclaredAnnotations())
              .forEach(ann -> System.out.format("%s @%s%n", pkg.getName(), ann));

        Arrays.stream(p.getDeclaredAnnotations())
              .forEach(ann -> System.out.format("%s @%s%n", p.getName(), ann));

        // local package p defined by loader
        Class<? extends Annotation> ann =
            (Class<? extends Annotation>)Class.forName("p.Duplicate", false, loader);
        assertTrue(pkg.isAnnotationPresent(ann));
    }

    private void compile(Path destDir, Path... files) throws IOException {
        compile(null, destDir, files);
    }

    private void compile(String option, Path destDir, Path... files)
            throws IOException
    {
        System.err.println("compile...");
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
            Iterable<? extends JavaFileObject> fileObjects =
                fm.getJavaFileObjectsFromPaths(Arrays.asList(files));

            List<String> options = new ArrayList<>();
            if (option != null) {
                options.add(option);
            }
            if (destDir != null) {
                options.add("-d");
                options.add(destDir.toString());
            }
            options.add("-cp");
            options.add(System.getProperty("test.classes", "."));

            JavaCompiler.CompilationTask task =
                compiler.getTask(null, fm, null, options, null, fileObjects);
            if (!task.call())
                throw new AssertionError("compilation failed");
        }
    }

}