/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.LinkedList;

/**
 * Exercise the construction and throwing of OutOfMemoryError.
 */
public class Main {
    public static void main(String args[]) {
        System.out.println("tests beginning");
        testOomeLarge();
        testOomeSmall();
        System.out.println("tests succeeded");
    }

    private static void testOomeLarge() {
        System.out.println("testOomeLarge beginning");

        /* Just shy of the typical max heap size so that it will actually
         * try to allocate it instead of short-circuiting.
         */
        final int SIXTEEN_MB = (16 * 1024 * 1024 - 32);

        Boolean sawEx = false;
        byte a[];

        try {
            a = new byte[SIXTEEN_MB];
        } catch (OutOfMemoryError oom) {
            //Log.i(TAG, "HeapTest/OomeLarge caught " + oom);
            sawEx = true;
        }

        if (!sawEx) {
            throw new RuntimeException("Test failed: " +
                    "OutOfMemoryError not thrown");
        }

        System.out.println("testOomeLarge succeeded");
    }

    /* Do this in another method so that the GC has a chance of freeing the
     * list afterwards.  Even if we null out list when we're done, the conservative
     * GC may see a stale pointer to it in a register.
     */
    private static boolean testOomeSmallInternal() {
        final int SIXTEEN_MB = (16 * 1024 * 1024);
        final int LINK_SIZE = 6 * 4; // estimated size of a LinkedList's node

        LinkedList<Object> list = new LinkedList<Object>();

        /* Allocate progressively smaller objects to fill up the entire heap.
         */
        int objSize = 1 * 1024 * 1024;
        while (objSize >= LINK_SIZE) {
            boolean sawEx = false;
            try {
                for (int i = 0; i < SIXTEEN_MB / objSize; i++) {
                    list.add((Object)new byte[objSize]);
                }
            } catch (OutOfMemoryError oom) {
                sawEx = true;
            }

            if (!sawEx) {
                return false;
            }

            objSize = (objSize * 4) / 5;
        }

        return true;
    }

    private static void testOomeSmall() {
        System.out.println("testOomeSmall beginning");
        if (!testOomeSmallInternal()) {
            /* Can't reliably throw this from inside the internal function, because
             * we may not be able to allocate the RuntimeException.
             */
            throw new RuntimeException("Test failed: " +
                    "OutOfMemoryError not thrown while filling heap");
        }
        System.out.println("testOomeSmall succeeded");
    }
}
