/*
 * Copyright (C) 2009 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.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class Main {
    private static final int TEST_LENGTH = 100;

    private static boolean makeArray(int i) {
        return i % 10 == 0;
    }

    private static void fillArray(Object global[], Object local[], int i) {
        // Very stupid linking.
        local[0] = global;
        for (int j = 1; j < local.length; j++) {
            local[j] = global[j];
        }
    }

    private static Object allocInDifferentLoader() throws Exception {
        final String DEX_FILE = System.getenv("DEX_LOCATION") + "/130-hprof-ex.jar";
        Class<?> pathClassLoader = Class.forName("dalvik.system.PathClassLoader");
        if (pathClassLoader == null) {
            throw new AssertionError("Couldn't find path class loader class");
        }
        Constructor<?> constructor =
            pathClassLoader.getDeclaredConstructor(String.class, ClassLoader.class);
        ClassLoader loader = (ClassLoader)constructor.newInstance(
                DEX_FILE, ClassLoader.getSystemClassLoader());
        Class<?> allocator = loader.loadClass("Allocator");
        return allocator.getDeclaredMethod("allocObject", null).invoke(null);
    }

    private static void createDumpAndConv() throws RuntimeException {
        File dumpFile = null;
        File convFile = null;

        try {
            // Now dump the heap.
            dumpFile = createDump();

            // Run hprof-conv on it.
            convFile = getConvFile();

            File hprof_conv = getHprofConf();
            try {
                ProcessBuilder pb = new ProcessBuilder(
                        hprof_conv.getAbsoluteFile().toString(),
                        dumpFile.getAbsoluteFile().toString(),
                        convFile.getAbsoluteFile().toString());
                pb.redirectErrorStream(true);
                Process process = pb.start();
                int ret = process.waitFor();
                if (ret != 0) {
                    throw new RuntimeException("Exited abnormally with " + ret);
                }
            } catch (Exception exc) {
                throw new RuntimeException(exc);
            }
        } finally {
            // Delete the files.
            if (dumpFile != null) {
                dumpFile.delete();
            }
            if (convFile != null) {
                convFile.delete();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        testBasicDump();
        testAllocationTrackingAndClassUnloading();
        testGcAndDump();
    }

    private static void testBasicDump() throws Exception {
        // Create some data.
        Object data[] = new Object[TEST_LENGTH];
        for (int i = 0; i < data.length; i++) {
            if (makeArray(i)) {
                data[i] = new Object[TEST_LENGTH];
            } else {
                data[i] = String.valueOf(i);
            }
        }
        for (int i = 0; i < data.length; i++) {
            if (makeArray(i)) {
                Object data2[] = (Object[]) data[i];
                fillArray(data, data2, i);
            }
        }
        System.out.println("Generated data.");
        createDumpAndConv();
    }

    private static void testAllocationTrackingAndClassUnloading() throws Exception {
        Class<?> klass = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal");
        if (klass == null) {
            throw new AssertionError("Couldn't find path class loader class");
        }
        Method enableMethod = klass.getDeclaredMethod("setRecentAllocationsTrackingEnabled",
            boolean.class);
        if (enableMethod == null) {
            throw new AssertionError("Couldn't find setRecentAllocationsTrackingEnabled method");
        }
        enableMethod.invoke(null, true);
        Object o = allocInDifferentLoader();
        // Run GC to cause class unloading.
        Runtime.getRuntime().gc();
        createDumpAndConv();
        // TODO: Somehow check contents of hprof file.
        enableMethod.invoke(null, false);
    }

    private static void testGcAndDump() throws Exception {
        Allocator allocator = new Allocator();
        Dumper dumper = new Dumper(allocator);
        allocator.start();
        dumper.start();
        try {
            allocator.join();
            dumper.join();
        } catch (InterruptedException e) {
            System.out.println("join interrupted");
        }
    }

    private static class Allocator extends Thread {
        private static int ARRAY_SIZE = 1024;
        public volatile boolean running = true;
        public void run() {
            Object[] array = new Object[ARRAY_SIZE];
            int i = 0;
            while (running) {
                array[i] = new byte[1024];
                if (i % ARRAY_SIZE == 0) {
                    Main.sleep(100L);
                }
                i = (i + 1) % ARRAY_SIZE;
            }
        }
    }

    private static class Dumper extends Thread {
        Dumper(Allocator allocator) {
            this.allocator = allocator;
        }
        Allocator allocator;
        public void run() {
            for (int i = 0; i < 5; ++i) {
                Main.sleep(1000L);
                createDumpAndConv();
            }
            allocator.running = false;
        }
    }

    public static void sleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            System.out.println("sleep interrupted");
        }
    }

    private static File getHprofConf() {
        // Use the java.library.path. It points to the lib directory.
        File libDir = new File(System.getProperty("java.library.path").split(":")[0]);
        return new File(new File(libDir.getParentFile(), "bin"), "hprof-conv");
    }

    private static File createDump() {
        java.lang.reflect.Method dumpHprofDataMethod = getDumpHprofDataMethod();
        if (dumpHprofDataMethod != null) {
            File f = getDumpFile();
            try {
                dumpHprofDataMethod.invoke(null, f.getAbsoluteFile().toString());
                return f;
            } catch (Exception exc) {
                exc.printStackTrace(System.out);
            }
        } else {
            System.out.println("Could not find dump method!");
        }
        return null;
    }

    /**
     * Finds VMDebug.dumpHprofData() through reflection.  In the reference
     * implementation this will not be available.
     *
     * @return the reflection object, or null if the method can't be found
     */
    private static Method getDumpHprofDataMethod() {
        ClassLoader myLoader = Main.class.getClassLoader();
        Class<?> vmdClass;
        try {
            vmdClass = myLoader.loadClass("dalvik.system.VMDebug");
        } catch (ClassNotFoundException cnfe) {
            return null;
        }

        Method meth;
        try {
            meth = vmdClass.getMethod("dumpHprofData", String.class);
        } catch (NoSuchMethodException nsme) {
            System.out.println("Found VMDebug but not dumpHprofData method");
            return null;
        }

        return meth;
    }

    private static File getDumpFile() {
        try {
            return File.createTempFile("test-130-hprof", "dump");
        } catch (Exception exc) {
            return null;
        }
    }

    private static File getConvFile() {
        try {
            return File.createTempFile("test-130-hprof", "conv");
        } catch (Exception exc) {
            return null;
        }
    }
}
