/*
 * Copyright (C) 2010, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.lib;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

public class ThreadSafeProgressMonitorTest {
	@Test
	public void testFailsMethodsOnBackgroundThread()
			throws InterruptedException {
		final MockProgressMonitor mock = new MockProgressMonitor();
		final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);

		runOnThread(new Runnable() {
			@Override
			public void run() {
				try {
					pm.start(1);
					fail("start did not fail on background thread");
				} catch (IllegalStateException notMainThread) {
					// Expected result
				}

				try {
					pm.beginTask("title", 1);
					fail("beginTask did not fail on background thread");
				} catch (IllegalStateException notMainThread) {
					// Expected result
				}

				try {
					pm.endTask();
					fail("endTask did not fail on background thread");
				} catch (IllegalStateException notMainThread) {
					// Expected result
				}
			}
		});

		// Ensure we didn't alter the mock above when checking threads.
		assertNull(mock.taskTitle);
		assertEquals(0, mock.value);
	}

	@Test
	public void testMethodsOkOnMainThread() {
		final MockProgressMonitor mock = new MockProgressMonitor();
		final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);

		pm.start(1);
		assertEquals(1, mock.value);

		pm.beginTask("title", 42);
		assertEquals("title", mock.taskTitle);
		assertEquals(42, mock.value);

		pm.update(1);
		pm.pollForUpdates();
		assertEquals(43, mock.value);

		pm.update(2);
		pm.pollForUpdates();
		assertEquals(45, mock.value);

		pm.endTask();
		assertNull(mock.taskTitle);
		assertEquals(0, mock.value);
	}

	@Test
	public void testUpdateOnBackgroundThreads() throws InterruptedException {
		final MockProgressMonitor mock = new MockProgressMonitor();
		final ThreadSafeProgressMonitor pm = new ThreadSafeProgressMonitor(mock);

		pm.startWorker();

		final CountDownLatch doUpdate = new CountDownLatch(1);
		final CountDownLatch didUpdate = new CountDownLatch(1);
		final CountDownLatch doEndWorker = new CountDownLatch(1);

		final Thread bg = new Thread() {
			@Override
			public void run() {
				assertFalse(pm.isCancelled());

				await(doUpdate);
				pm.update(2);
				didUpdate.countDown();

				await(doEndWorker);
				pm.update(1);
				pm.endWorker();
			}
		};
		bg.start();

		pm.pollForUpdates();
		assertEquals(0, mock.value);
		doUpdate.countDown();

		await(didUpdate);
		pm.pollForUpdates();
		assertEquals(2, mock.value);

		doEndWorker.countDown();
		pm.waitForCompletion();
		assertEquals(3, mock.value);
	}

	private static void await(CountDownLatch cdl) {
		try {
			assertTrue("latch released", cdl.await(1000, TimeUnit.MILLISECONDS));
		} catch (InterruptedException ie) {
			fail("Did not expect to be interrupted");
		}
	}

	private static void runOnThread(Runnable task) throws InterruptedException {
		Thread t = new Thread(task);
		t.start();
		t.join(1000);
		assertFalse("thread has stopped", t.isAlive());
	}

	private static class MockProgressMonitor implements ProgressMonitor {
		String taskTitle;

		int value;

		@Override
		public void update(int completed) {
			value += completed;
		}

		@Override
		public void start(int totalTasks) {
			value = totalTasks;
		}

		@Override
		public void beginTask(String title, int totalWork) {
			taskTitle = title;
			value = totalWork;
		}

		@Override
		public void endTask() {
			taskTitle = null;
			value = 0;
		}

		@Override
		public boolean isCancelled() {
			return false;
		}
	}
}
