// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.base.test.util;

import android.os.Handler;
import android.os.Looper;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * This class is usefull when writing instrumentation tests that exercise code that posts tasks
 * (to the same thread).
 * Since the test code is run in a single thread, the posted tasks are never executed.
 * The TestThread class lets you run that code on a specific thread synchronously and flush the
 * message loop on that thread.
 *
 * Example of test using this:
 *
 * public void testMyAwesomeClass() {
 *   TestThread testThread = new TestThread();
 *   testThread.startAndWaitForReadyState();
 *
 *   testThread.runOnTestThreadSyncAndProcessPendingTasks(new Runnable() {
 *       @Override
 *       public void run() {
 *           MyAwesomeClass.doStuffAsync();
 *       }
 *   });
 *   // Once we get there we know doStuffAsync has been executed and all the tasks it posted.
 *   assertTrue(MyAwesomeClass.stuffWasDone());
 * }
 *
 * Notes:
 * - this is only for tasks posted to the same thread. Anyway if you were posting to a different
 *   thread, you'd probably need to set that other thread up.
 * - this only supports tasks posted using Handler.post(), it won't work with postDelayed and
 *   postAtTime.
 * - if your test instanciates an object and that object is the one doing the posting of tasks, you
 *   probably want to instanciate it on the test thread as it might create the Handler it posts
 *   tasks to in the constructor.
 */

public class TestThread extends Thread {
    private Object mThreadReadyLock;
    private AtomicBoolean mThreadReady;
    private Handler mMainThreadHandler;
    private Handler mTestThreadHandler;

    public TestThread() {
        mMainThreadHandler = new Handler();
        // We can't use the AtomicBoolean as the lock or findbugs will freak out...
        mThreadReadyLock = new Object();
        mThreadReady = new AtomicBoolean();
    }

    @Override
    public void run() {
        Looper.prepare();
        mTestThreadHandler = new Handler();
        mTestThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                synchronized (mThreadReadyLock) {
                    mThreadReady.set(true);
                    mThreadReadyLock.notify();
                }
            }
        });
        Looper.loop();
    }

    /**
     * Starts this TestThread and blocks until it's ready to accept calls.
     */
    public void startAndWaitForReadyState() {
        checkOnMainThread();
        start();
        synchronized (mThreadReadyLock) {
            try {
                // Note the mThreadReady and while are not really needed.
                // There are there so findbugs don't report warnings.
                while (!mThreadReady.get()) {
                    mThreadReadyLock.wait();
                }
            } catch (InterruptedException ie) {
                System.err.println("Error starting TestThread.");
                ie.printStackTrace();
            }
        }
    }

    /**
     * Runs the passed Runnable synchronously on the TestThread and returns when all pending
     * runnables have been excuted.
     * Should be called from the main thread.
     */
    public void runOnTestThreadSyncAndProcessPendingTasks(Runnable r) {
        checkOnMainThread();

        runOnTestThreadSync(r);

        // Run another task, when it's done it means all pendings tasks have executed.
        runOnTestThreadSync(null);
    }

    /**
     * Runs the passed Runnable on the test thread and blocks until it has finished executing.
     * Should be called from the main thread.
     * @param r The runnable to be executed.
     */
    public void runOnTestThreadSync(final Runnable r) {
        checkOnMainThread();
        final Object lock = new Object();
        // Task executed is not really needed since we are only on one thread, it is here to appease
        // findbugs.
        final AtomicBoolean taskExecuted = new AtomicBoolean();
        mTestThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                if (r != null) r.run();
                synchronized (lock) {
                    taskExecuted.set(true);
                    lock.notify();
                }
            }
        });
        synchronized (lock) {
            try {
                while (!taskExecuted.get()) {
                    lock.wait();
                }
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
    }

    private void checkOnMainThread() {
        assert Looper.myLooper() == mMainThreadHandler.getLooper();
    }
}
