/*
 * 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.
 */

package com.android.dumprendertree;

import com.android.dumprendertree.forwarder.AdbUtils;
import com.android.dumprendertree.forwarder.ForwardServer;

import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Debug;
import android.os.Environment;
import android.os.Process;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> {

    private final static String LOGTAG = "LoadTest";
    private final static String LOAD_TEST_RESULT =
        Environment.getExternalStorageDirectory() + "/load_test_result.txt";
    private final static int MAX_GC_WAIT_SEC = 10;
    private final static int LOCAL_PORT = 17171;
    private boolean mFinished;
    static final String LOAD_TEST_RUNNER_FILES[] = {
        "run_page_cycler.py"
    };
    private ForwardServer mForwardServer;

    public LoadTestsAutoTest() {
        super(TestShellActivity.class);
    }

    // This function writes the result of the layout test to
    // Am status so that it can be picked up from a script.
    public void passOrFailCallback(String file, boolean result) {
        Instrumentation inst = getInstrumentation();
        Bundle bundle = new Bundle();
        bundle.putBoolean(file, result);
        inst.sendStatus(0, bundle);
    }

    private String setUpForwarding(String forwardInfo, String suite, String iteration) throws IOException {
        // read forwarding information first
        Pattern forwardPattern = Pattern.compile("(.*):(\\d+)/(.*)/");
        Matcher matcher = forwardPattern.matcher(forwardInfo);
        if (!matcher.matches()) {
            throw new RuntimeException("Invalid forward information");
        }
        String host = matcher.group(1);
        int port = Integer.parseInt(matcher.group(2));
        mForwardServer = new ForwardServer(LOCAL_PORT, AdbUtils.resolve(host), port);
        mForwardServer.start();
        return String.format("http://127.0.0.1:%d/%s/%s/start.html?auto=1&iterations=%s",
                LOCAL_PORT, matcher.group(3), suite, iteration);
    }

    // Invokes running of layout tests
    // and waits till it has finished running.
    public void runPageCyclerTest() throws IOException {
        LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();

        if (runner.mPageCyclerSuite != null) {
            // start forwarder to use page cycler suites hosted on external web server
            if (runner.mPageCyclerForwardHost == null) {
                throw new RuntimeException("no forwarder information provided");
            }
            runner.mTestPath = setUpForwarding(runner.mPageCyclerForwardHost,
                    runner.mPageCyclerSuite, runner.mPageCyclerIteration);
            Log.d(LOGTAG, "using path: " + runner.mTestPath);
        }

        if (runner.mTestPath == null) {
            throw new RuntimeException("No test specified");
        }

        TestShellActivity activity = (TestShellActivity) getActivity();

        Log.v(LOGTAG, "About to run tests, calling gc first...");
        freeMem();

        // Run tests
        runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis,
                runner.mGetDrawTime, runner.mSaveImagePath);

        activity.clearCache();
        if (mForwardServer != null) {
            mForwardServer.stop();
            mForwardServer = null;
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
        }
        dumpMemoryInfo();

        // Kill activity
        activity.finish();
    }

    private void freeMem() {
        Log.v(LOGTAG, "freeMem: calling gc...");
        final CountDownLatch latch = new CountDownLatch(1);
        @SuppressWarnings("unused")
        Object dummy = new Object() {
            // this object instance is used to track gc
            @Override
            protected void finalize() throws Throwable {
                latch.countDown();
                super.finalize();
            }
        };
        dummy = null;
        System.gc();
        try {
            if (!latch.await(MAX_GC_WAIT_SEC, TimeUnit.SECONDS)) {
                Log.w(LOGTAG, "gc did not happen in 10s");
            }
        } catch (InterruptedException e) {
            //ignore
        }
    }

    private void printRow(PrintStream ps, String format, Object...objs) {
        ps.println(String.format(format, objs));
    }

    private void dumpMemoryInfo() {
        try {
            freeMem();
            Log.v(LOGTAG, "Dumping memory information.");

            FileOutputStream out = new FileOutputStream(LOAD_TEST_RESULT, true);
            PrintStream ps = new PrintStream(out);

            ps.print("\n\n\n");
            ps.println("** MEMINFO in pid " + Process.myPid()
                    + " [com.android.dumprendertree] **");
            String formatString = "%17s %8s %8s %8s %8s";

            long nativeMax = Debug.getNativeHeapSize() / 1024;
            long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
            long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
            Runtime runtime = Runtime.getRuntime();
            long dalvikMax = runtime.totalMemory() / 1024;
            long dalvikFree = runtime.freeMemory() / 1024;
            long dalvikAllocated = dalvikMax - dalvikFree;


            Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
            Debug.getMemoryInfo(memInfo);

            final int nativeShared = memInfo.nativeSharedDirty;
            final int dalvikShared = memInfo.dalvikSharedDirty;
            final int otherShared = memInfo.otherSharedDirty;

            final int nativePrivate = memInfo.nativePrivateDirty;
            final int dalvikPrivate = memInfo.dalvikPrivateDirty;
            final int otherPrivate = memInfo.otherPrivateDirty;

            printRow(ps, formatString, "", "native", "dalvik", "other", "total");
            printRow(ps, formatString, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
            printRow(ps, formatString, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
                    nativeAllocated + dalvikAllocated);
            printRow(ps, formatString, "free:", nativeFree, dalvikFree, "N/A",
                    nativeFree + dalvikFree);

            printRow(ps, formatString, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
                    memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);

            printRow(ps, formatString, "(shared dirty):", nativeShared, dalvikShared, otherShared,
                    nativeShared + dalvikShared + otherShared);
            printRow(ps, formatString, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
                    nativePrivate + dalvikPrivate + otherPrivate);
            ps.print("\n\n\n");
            ps.flush();
            ps.close();
            out.flush();
            out.close();
        } catch (IOException e) {
            Log.e(LOGTAG, e.getMessage());
        }
    }

    // A convenient method to be called by another activity.
    private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout,
            boolean getDrawTime, String saveImagePath) {
        activity.setCallback(new TestShellCallback() {
            public void finished() {
                synchronized (LoadTestsAutoTest.this) {
                    mFinished = true;
                    LoadTestsAutoTest.this.notifyAll();
                }
            }

            public void timedOut(String url) {
            }
        });

        mFinished = false;
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setClass(activity, TestShellActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.putExtra(TestShellActivity.TEST_URL, url);
        intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
        intent.putExtra(TestShellActivity.RESULT_FILE, LOAD_TEST_RESULT);
        intent.putExtra(TestShellActivity.GET_DRAW_TIME, getDrawTime);
        if (saveImagePath != null)
            intent.putExtra(TestShellActivity.SAVE_IMAGE, saveImagePath);
        activity.startActivity(intent);

        // Wait until done.
        synchronized (this) {
            while(!mFinished) {
                try {
                    this.wait();
                } catch (InterruptedException e) { }
            }
        }
    }

    public void copyRunnerAssetsToCache() {
        try {
            Context targetContext = getInstrumentation().getTargetContext();
            File cacheDir = targetContext.getCacheDir();

            for( int i=0; i< LOAD_TEST_RUNNER_FILES.length; i++) {
                InputStream in = targetContext.getAssets().open(
                        LOAD_TEST_RUNNER_FILES[i]);
                OutputStream out = new FileOutputStream(
                        new File(cacheDir, LOAD_TEST_RUNNER_FILES[i]));

                byte[] buf = new byte[2048];
                int len;

                while ((len = in.read(buf)) >= 0 ) {
                    out.write(buf, 0, len);
                }
                out.close();
                in.close();
            }
        }catch (IOException e) {
          e.printStackTrace();
        }

    }

}
