/*
 * Copyright (c) 1999, 2006, 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 4238644 4238643 4238641 4944198
 *  @summary Test javac regressions in the generation of line number info
 *  @author Gordon Hirsch
 *
 *  @run build TestScaffold VMConnection TargetListener TargetAdapter
 *  @run compile -g LineNumberInfo.java ControlFlow.java
 *
 *  @run main LineNumberInfo
 */
import com.sun.jdi.*;
import com.sun.jdi.event.*;
import com.sun.jdi.request.*;

import java.util.List;
import java.util.Iterator;

public class LineNumberInfo extends TestScaffold {
    /*
     * These two arrays are used to validate the line number
     * information returned by JDI. There are limitations to
     * this approach:
     * - there are no strict rules about
     *   what constitutes the "right" line number mapping, so
     *   this kind of test may have false negatives with other
     *   compilers.
     * - this test is also sensitive to the compiler's code generation;
     *   if that changes, this test will likely need updating.
     * - this test assumes that JDI code index == class file
     *   byte code index which may not be true in all VMs.
     * - To find the values for these tables, compile ControlFlow.java and then
     *   do:
     *   javap -classpath _jj1.solaris-sparc/JTwork/classes/com/sun/jdi \
     *                    -l ControlFlow
     */
    final int[] lineNumbers = {
        15,
        16,
        19,
        20,
        22,
        25,
        26,
        28,
        32,
        33,
        34,
        36,
        37,
        36,
        40,
        41,
        42,
        45,
        46,
        45,
        49,
        51,
        53,
        55,
        57,
        59,
        60,
        62,
        65,
        67,
        69,
        71,
        73,
        75,
        78
    };

    final int[] codeIndices = {
        0  ,
        7  ,
        15 ,
        22 ,
        33 ,
        43 ,
        50 ,
        60 ,
        68 ,
        76 ,
        77 ,
        85 ,
        93 ,
        96 ,
        107,
        111,
        119,
        129,
        139,
        178,
        184,
        240,
        250,
        260,
        270,
        280,
        288,
        291,
        301,
        336,
        346,
        356,
        366,
        376,
        384
    };

    LineNumberInfo(String args[]) {
        super(args);
    }

    public static void main(String args[]) throws Exception {
        new LineNumberInfo(args).startTests();
    }

    protected void runTests() throws Exception {
        startUp("ControlFlow");

        // Get the ControlFlow class loaded.
        ClassPrepareEvent event = resumeToPrepareOf("ControlFlow");

        ClassType clazz = (ClassType)event.referenceType();
        Method method = clazz.concreteMethodByName("go", "()V");
        List locations = method.allLineLocations();

        if (lineNumbers.length != codeIndices.length) {
            failure("FAILED: Bad test. Line number and code index arrays " +
                 "must be equal in size");
        }

        if (locations.size() != codeIndices.length) {
            // Help the tester see why it failed.
            Iterator iter = locations.iterator();
            while (iter.hasNext()) {
                Location location = (Location)iter.next();
                System.err.println("location=" + location);
            }

            failure("FAILED: Bad line number table size: jdi=" +
                 locations.size() +
                 ", test=" + codeIndices.length);
        }

        int i = 0;
        Iterator iter = locations.iterator();
        while (iter.hasNext()) {
            Location location = (Location)iter.next();
            if (location.codeIndex() != codeIndices[i]) {
                failure("FAILED: Code index mismatch: jdi=" +
                                    location.codeIndex() +
                                    ", test=" + codeIndices[i]);
            }
            if (location.lineNumber() != lineNumbers[i]) {
                failure("FAILED: Line number mismatch: jdi=" +
                                    location.lineNumber() +
                                    ", test=" + lineNumbers[i]);
            }
            i++;
        }


        // Allow application to complete
        listenUntilVMDisconnect();

        /*
         * deal with results of test
         * if anything has called failure("foo") testFailed will be true
         */
        if (!testFailed) {
            println("LineNumberInfo: passed");
        } else {
            throw new Exception("LineNumberInfo: failed");
        }

    }
}
