/*
 * Copyright (c) 2013, 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.
 */

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicInteger;

/* @test
 * @bug 8027351
 * @summary Basic test of the finalize method
 */

public class FinalizeOverride {
    // finalizedCount is incremented when the finalize method is invoked
    private static AtomicInteger finalizedCount = new AtomicInteger();

    // finalizedSum and privateFinalizedInvoke are used to verify
    // the right overrided finalize method is invoked
    private static AtomicInteger finalizedSum = new AtomicInteger();
    private static volatile boolean privateFinalizeInvoked = false;

    public static void main(String[] argvs) throws IOException {
        patchPrivateFinalize();

        test(new Base(10), 10);
        test(new Subclass(20), 0);
        test(new SubSubclass(30), 30);
        test(new PublicFinalize(40), 40*100+40);
        test(new PrivateFinalize(50), 50);
        test(new NoOverride(60), 60);
    }

    static void test(Object o, int expected) {
        int count = finalizedCount.get();
        int sum = finalizedSum.get();
        privateFinalizeInvoked = false;

        // force GC and finalization
        o = null;
        while (finalizedCount.get() != (count+1)) {
            System.gc();
            System.runFinalization();
        }

        if (privateFinalizeInvoked) {
            throw new RuntimeException("private finalize method invoked");
        }
        if (finalizedCount.get() != (count+1)) {
            throw new RuntimeException("Unexpected count=" + finalizedCount +
                " expected=" + (count+1));
        }
        if (finalizedSum.get() != (sum+expected)) {
            throw new RuntimeException("Unexpected sum=" + finalizedSum +
                " prev=" + sum + " value=" + expected);
        }
    }

    static void patchPrivateFinalize() throws IOException {
        // patch the private f_nal_ze method name to "finalize"
        String testClasses = System.getProperty("test.classes", ".");
        Path p = Paths.get(testClasses, "FinalizeOverride$PrivateFinalize.class");
        byte[] bytes = Files.readAllBytes(p);
        int len = "f_nal_ze".length();
        for (int i=0; i < bytes.length-len; i++) {
            if (bytes[i] == 'f' &&
                bytes[i+1] == '_' &&
                bytes[i+2] == 'n' &&
                bytes[i+3] == 'a' &&
                bytes[i+4] == 'l' &&
                bytes[i+5] == '_' &&
                bytes[i+6] == 'z' &&
                bytes[i+7] == 'e')
            {
                // s%_%i%
                bytes[i+1] = 'i';
                bytes[i+5] = 'i';
                break;
            }
        }
        Files.write(p, bytes);
    }

    static class Base {
        protected int value;
        Base(int v) {
            this.value = v;
        }
        int called() {
            finalizedSum.addAndGet(value);
            return value;
        }
        protected void finalize() {
            System.out.println("Base.finalize() sum += " + called());
            finalizedCount.incrementAndGet();
        }
    }
    static class PublicFinalize extends Base {
        PublicFinalize(int v) {
            super(v);
        }
        public void finalize() {
            finalizedSum.addAndGet(value * 100);
            System.out.println("PublicFinalize.finalize() sum += " + called() +
                "+"+value+"*100");
            finalizedCount.incrementAndGet();
        }
    }
    static class Subclass extends Base {
        Subclass(int v) {
            super(v);
        }
        protected void finalize() {
            // no value added to sum
            System.out.println("Subclass.finalize() sum += 0");
            finalizedCount.incrementAndGet();
        }
    }
    static class SubSubclass extends Subclass {
        SubSubclass(int v) {
            super(v);
        }
        protected final void finalize() {
            finalizedSum.addAndGet(value);
            System.out.println("SubSubclass.finalize() sum +=" +value);
            finalizedCount.incrementAndGet();
        }
    }
    static class PrivateFinalize extends Base {
        PrivateFinalize(int v) {
            super(v);
        }
        private void f_nal_ze() {
            // finalization catches any exception
            System.out.println("Error: private finalize invoked!!");
            privateFinalizeInvoked = true;
            finalizedCount.incrementAndGet();
        }
    }
    static class NoOverride extends PrivateFinalize {
        NoOverride(int v) {
            super(v);
        }
    }
}
