/*
 * Copyright (c) 1999, 2001, 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 4272800 4274208 4392010
 *  @summary Test debugger operations in finalize() methods
 *  @author Gordon Hirsch  (modified for HotSpot by tbell & rfield)
 *
 *  @run build TestScaffold VMConnection TargetListener TargetAdapter
 *  @run compile -g FinalizerTest.java
 *
 *  @run main FinalizerTest
 */
import com.sun.jdi.*;
import com.sun.jdi.event.*;
import com.sun.jdi.request.*;

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


/*
 * Debuggee which exercises a finalize() method. There's no guarantee
 * that this will work, but we need some way of attempting to test
 * the debugging of finalizers.
 * @author Gordon Hirsch  (modified for HotSpot by tbell & rfield)
 */
class FinalizerTarg {
    static String lockit = "lock";
    static boolean finalizerRun = false;
    static class BigObject {
        String name;
        byte[] foo = new byte[300000];

        public BigObject (String _name) {
            super();
            this.name = _name;
        }

        protected void finalize() throws Throwable {
            /*
             * JLS 2nd Ed. section 12.6 "Finalization of Class Instances" "[...]
             * invoke the finalize method for its superclass, [...] usually good
             * practice [...]"
             */
            super.finalize();
            //Thread.dumpStack();
            finalizerRun = true;
        }
    }

    static void waitForAFinalizer() {
        String s = Integer.toString(1);
        BigObject b = new BigObject (s);
        b = null; // Drop the object, creating garbage...
        System.gc();
        System.runFinalization();

        // Now, we have to make sure the finalizer
        // gets run.  We will keep allocating more
        // and more memory with the idea that eventually,
        // the memory occupied by the BigObject will get reclaimed
        // and the finalizer will be run.
        List holdAlot = new ArrayList();
        for (int chunk=10000000; chunk > 10000; chunk = chunk / 2) {
            if (finalizerRun) {
                return;
            }
            try {
                while(true) {
                    holdAlot.add(new byte[chunk]);
                    System.err.println("Allocated " + chunk);
                }
            }
            catch ( Throwable thrown ) {  // OutOfMemoryError
                System.gc();
            }
            System.runFinalization();
        }
        return;  // not reached
    }

    public static void main(String[] args) throws Exception {
        /*
         * Spin in waitForAFinalizer() while waiting for
         * another thread to run the finalizer on one of the
         * BigObjects ...
         */
        waitForAFinalizer();
    }
}
///// End of debuggee


public class FinalizerTest extends TestScaffold {

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

    public FinalizerTest (String args[]) {
        super(args);
    }

    protected void runTests() throws Exception {
        try {
            BreakpointEvent event0 = startToMain("FinalizerTarg");

            BreakpointEvent event1 = resumeTo("FinalizerTarg$BigObject",
                                              "finalize", "()V");

            println("Breakpoint at " +
                    event1.location().method().name() + ":" +
                    event1.location().lineNumber() + " (" +
                    event1.location().codeIndex() + ")");

            /*
             * Record information about the current location
             */
            List frames = event1.thread().frames();
            List methodStack = new ArrayList(frames.size());
            Iterator iter = frames.iterator();
            while (iter.hasNext()) {
                StackFrame frame = (StackFrame) iter.next();
                methodStack.add(frame.location().declaringType().name() +
                                "." + frame.location().method().name());
            }
            println("Try a stepOverLine()...");
            StepEvent stepEvent = stepOverLine(event1.thread());

            println("Step Complete at " +
                               stepEvent.location().method().name() + ":" +
                               stepEvent.location().lineNumber() + " (" +
                               stepEvent.location().codeIndex() + ")");

            /*
             * Compare current location with recorded location
             */
            if (stepEvent.thread().frameCount() != methodStack.size()) {
                throw new Exception("Stack depths do not match: original=" +
                                    methodStack.size() +
                                    ", current=" +
                                    stepEvent.thread().frameCount());
            }
            iter = stepEvent.thread().frames().iterator();
            Iterator iter2 = methodStack.iterator();
            while (iter.hasNext()) {
                StackFrame frame = (StackFrame) iter.next();
                String name = (String) iter2.next();
                String currentName = frame.location().declaringType().name() +
                "." + frame.location().method().name();
                if (!name.equals(currentName)) {
                    throw new Exception("Stacks do not match at: original=" +
                                         name + ", current=" + currentName);

                }
            }
        } catch(Exception ex) {
            ex.printStackTrace();
            testFailed = true;
        } finally {
            // Allow application to complete and shut down
            listenUntilVMDisconnect();
        }
        if (!testFailed) {
            println("FinalizerTest: passed");
        } else {
            throw new Exception("FinalizerTest: failed");
        }
    }
}
