/*
 * Copyright (c) 2021, 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 8232948
 * @summary Make sure inner classes are correctly encoded
 * @library /tools/lib
 * @modules jdk.compiler/com.sun.tools.javac.api
 * @modules jdk.compiler/com.sun.tools.javac.main
 * @build toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox
 * @run main EncodeInnerClassNameTest
 */

import toolbox.JavacTask;
import toolbox.ToolBox;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;

public class EncodeInnerClassNameTest {
    private final ToolBox toolBox = new ToolBox();
    private final String source = """
            package p.q;
            public class Outer {
                public class Inner {
                    native Inner aMethod();
                    native void aMethod(Inner i);
                    native void aMethod(Inner i, Inner j);
                }
            }
            """;

    private final String expected = """
            /* DO NOT EDIT THIS FILE - it is machine generated */
            #include <jni.h>
            /* Header for class p_q_Outer_Inner */

            #ifndef _Included_p_q_Outer_Inner
            #define _Included_p_q_Outer_Inner
            #ifdef __cplusplus
            extern "C" {
            #endif
            /*
             * Class:     p_q_Outer_Inner
             * Method:    aMethod
             * Signature: ()Lp/q/Outer/Inner;
             */
            JNIEXPORT jobject JNICALL Java_p_q_Outer_00024Inner_aMethod__
              (JNIEnv *, jobject);

            /*
             * Class:     p_q_Outer_Inner
             * Method:    aMethod
             * Signature: (Lp/q/Outer/Inner;)V
             */
            JNIEXPORT void JNICALL Java_p_q_Outer_00024Inner_aMethod__Lp_q_Outer_00024Inner_2
              (JNIEnv *, jobject, jobject);

            /*
             * Class:     p_q_Outer_Inner
             * Method:    aMethod
             * Signature: (Lp/q/Outer/Inner;Lp/q/Outer/Inner;)V
             */
            JNIEXPORT void JNICALL Java_p_q_Outer_00024Inner_aMethod__Lp_q_Outer_00024Inner_2Lp_q_Outer_00024Inner_2
              (JNIEnv *, jobject, jobject, jobject);

            #ifdef __cplusplus
            }
            #endif
            #endif
            """;

    public static void main(String... args) throws Exception {
        new EncodeInnerClassNameTest().runTest();
    }

    public void runTest() throws Exception {
        JavacTask task = new JavacTask(toolBox);
        task.outdir(".")
                .sources(source)
                .options("-h", ".")
                .run()
                .writeAll();

        List<String> expected = Arrays.asList(this.expected.split("\\R"));
        List<String> res = toolBox.readAllLines(Path.of(".", "p_q_Outer_Inner.h"));

        toolBox.checkEqual(expected, res);
    }
}
