/*
 * Copyright (c) 2012, 2018, 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
 * @bug 7150368 8003412 8000407 7016187
 * @summary javac should include basic ability to generate native headers
 * @modules jdk.compiler/com.sun.tools.javac.api
 *          jdk.compiler/com.sun.tools.javac.file
 */

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;

import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.JavacTool;

public class NativeHeaderTest {
    public static void main(String... args) throws Exception {
        new NativeHeaderTest().run();
    }

    /** How to invoke javac. */
    enum RunKind {
        /** Use the command line entry point. */
        CMD,
        /** Use the JavaCompiler API. */
        API
    };

    /** Which classes for which to generate headers. */
    enum GenKind {
        /** Just classes with native methods or the marker annotation. */
        SIMPLE,
        /** All appropriate classes within the top level class. */
        FULL
    };

    // ---------- Test cases, invoked reflectively via run. ----------

    @Test
    void simpleTest(RunKind rk, GenKind gk) throws Exception {
        List<File> files = new ArrayList<File>();
        files.add(createFile("p/C.java",
                "class C { native void m(); }"));

        Set<String> expect = createSet("C.h");

        test(rk, gk, files, expect);
    }

    @Test
    void nestedClassTest(RunKind rk, GenKind gk) throws Exception {
        List<File> files = new ArrayList<File>();
        files.add(createFile("p/C.java",
                "class C { static class Inner { native void m(); } }"));

        Set<String> expect = createSet("C_Inner.h");
        if (gk == GenKind.FULL) expect.add("C.h");

        test(rk, gk, files, expect);
    }

    @Test
    void localClassTest(RunKind rk, GenKind gk) throws Exception {
        List<File> files = new ArrayList<File>();
        files.add(createFile("p/C.java",
                "class C { native void m(); void m2() { class Local { } } }"));

        Set<String> expect = createSet("C.h");

        test(rk, gk, files, expect);
    }

    @Test
    void syntheticClassTest(RunKind rk, GenKind gk) throws Exception {
        List<File> files = new ArrayList<File>();
        files.add(createFile("p/C.java",
                "class C {\n"
                + "    private C() { }\n"
                + "    class Inner extends C { native void m(); }\n"
                + "}"));

        Set<String> expect = createSet("C_Inner.h");
        if (gk == GenKind.FULL) expect.add("C.h");

        test(rk, gk, files, expect);

        // double check the synthetic class was generated
        checkEqual("generatedClasses",
                createSet("C.class", "C$Inner.class"),
                createSet(classesDir.list()));
    }

    @Test
    void annoTest(RunKind rk, GenKind gk) throws Exception {
        List<File> files = new ArrayList<File>();
        files.add(createFile("p/C.java",
                "class C { @java.lang.annotation.Native public static final int i = 1907; }"));

        Set<String> expect = createSet("C.h");

        test(rk, gk, files, expect);
    }

    @Test
    void annoNestedClassTest(RunKind rk, GenKind gk) throws Exception {
        List<File> files = new ArrayList<File>();
        files.add(createFile("p/C.java",
                "class C { class Inner { @java.lang.annotation.Native public static final int i = 1907; } }"));

        Set<String> expect = createSet("C_Inner.h");
        if (gk == GenKind.FULL) expect.add("C.h");

        test(rk, gk, files, expect);
    }

    @Test
    void conflictTest(RunKind rk, GenKind gk) throws Exception {

        // These two classes will generate the same header file "Foo_Bar.h"
        List<File> files = new ArrayList<File>();
        files.add(createFile("p/Foo.java", """
            public class Foo {
                public static class Bar {
                    public static native void method1();
                }
            }
        """));
        files.add(createFile("p/Foo_Bar.java", """
            public class Foo_Bar {
                public static native void method2();
            }
        """));

        try {
            test(rk, gk, files, null);
            throw new AssertionError("expected failure");
        } catch (Exception e) {
            // expected
        }
    }

    /**
     * The worker method for each test case.
     * Compile the files and verify that exactly the expected set of header files
     * is generated.
     */
    void test(RunKind rk, GenKind gk, List<File> files, Set<String> expect) throws Exception {
        List<String> args = new ArrayList<String>();
        if (gk == GenKind.FULL)
            args.add("-XDjavah:full");

        switch (rk) {
            case CMD:
                args.add("-d");
                args.add(classesDir.getPath());
                args.add("-h");
                args.add(headersDir.getPath());
                for (File f: files)
                    args.add(f.getPath());
                int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]));
                if (rc != 0)
                    throw new Exception("compilation failed, rc=" + rc);
                break;

            case API:
                fm.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(srcDir));
                fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(classesDir));
                fm.setLocation(StandardLocation.NATIVE_HEADER_OUTPUT, Arrays.asList(headersDir));
                JavacTask task = javac.getTask(null, fm, null, args, null,
                        fm.getJavaFileObjectsFromFiles(files));
                if (!task.call())
                    throw new Exception("compilation failed");
                break;
        }

        Set<String> found = createSet(headersDir.list());
        checkEqual("header files", expect, found);
    }

    /** Marker annotation for test cases. */
    @Retention(RetentionPolicy.RUNTIME)
    @interface Test { }

    /** Combo test to run all test cases in all modes. */
    void run() throws Exception {
        javac = JavacTool.create();
        fm = javac.getStandardFileManager(null, null, null);
        try {
            for (RunKind rk: RunKind.values()) {
                for (GenKind gk: GenKind.values()) {
                    for (Method m: getClass().getDeclaredMethods()) {
                        Annotation a = m.getAnnotation(Test.class);
                        if (a != null) {
                            init(rk, gk, m.getName());
                            try {
                                m.invoke(this, new Object[] { rk, gk });
                            } catch (InvocationTargetException e) {
                                Throwable cause = e.getCause();
                                throw (cause instanceof Exception) ? ((Exception) cause) : e;
                            }
                            System.err.println();
                        }
                    }
                }
            }
            System.err.println(testCount + " tests" + ((errorCount == 0) ? "" : ", " + errorCount + " errors"));
            if (errorCount > 0)
                throw new Exception(errorCount + " errors found");
        } finally {
            fm.close();
        }
    }

    /**
     * Init directories for a test case.
     */
    void init(RunKind rk, GenKind gk, String name) throws IOException {
        System.err.println("Test " + rk + " " + gk + " " + name);
        testCount++;

        testDir = new File(rk.toString().toLowerCase() + "_" + gk.toString().toLowerCase() + "-" + name);
        srcDir = new File(testDir, "src");
        srcDir.mkdirs();
        classesDir = new File(testDir, "classes");
        classesDir.mkdirs();
        headersDir = new File(testDir, "headers");
        headersDir.mkdirs();
    }

    /** Create a source file with given body text. */
    File createFile(String path, final String body) throws IOException {
        File f = new File(srcDir, path);
        f.getParentFile().mkdirs();
        try (FileWriter out = new FileWriter(f)) {
            out.write(body);
        }
        return f;
    }

    /** Convenience method to create a set of items. */
    <T> Set<T> createSet(T... items) {
        return new HashSet<T>(Arrays.asList(items));
    }

    /** Convenience method to check two values are equal, and report an error if not. */
    <T> void checkEqual(String label, T expect, T found) {
        if ((found == null) ? (expect == null) : found.equals(expect))
            return;
        System.err.println("Error: mismatch");
        System.err.println("  expected: " + expect);
        System.err.println("     found: " + found);
        errorCount++;
    }

    // Shared across API test cases
    JavacTool javac;
    StandardJavaFileManager fm;

    // Directories set up by init
    File testDir;
    File srcDir;
    File classesDir;
    File headersDir;

    // Statistics
    int testCount;
    int errorCount;
}

