/*
 * Copyright 2006 Takahiro Nakamura.
 *
 * 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 woolpack.test.ee;

import java.util.concurrent.CountDownLatch;

import junit.framework.TestCase;
import woolpack.LoadAllTests;
import woolpack.test.RunnableGate;

public class RunnableGateTest extends TestCase {

	public void testConstuctor() {
		try {
			new RunnableGate(null, "end", LoadAllTests.THREAD_POOL, 1);
			fail();
		} catch (final NullPointerException e) {
		}
		try {
			new RunnableGate("", "end", LoadAllTests.THREAD_POOL, 1);
			fail();
		} catch (final StringIndexOutOfBoundsException e) {
		}
		try {
			new RunnableGate("start", null, LoadAllTests.THREAD_POOL, 1);
			fail();
		} catch (final NullPointerException e) {
		}
		try {
			new RunnableGate("start", "", LoadAllTests.THREAD_POOL, 1);
			fail();
		} catch (final StringIndexOutOfBoundsException e) {
		}
		try {
			new RunnableGate("start", "end", null, 1);
			fail();
		} catch (final NullPointerException e) {
		}
		try {
			new RunnableGate("start", "end", LoadAllTests.THREAD_POOL, 0);
			fail();
		} catch (final IllegalArgumentException e) {
			assertEquals("timeout must be positive value.", e.getMessage());
		}
	}

	/**
	 * 確率的テスト(確率的に失敗する)
	 * 
	 * @throws InterruptedException test
	 * 
	 */
	public void testExecuteTimeout() throws InterruptedException {
		final CountDownLatch latch = new CountDownLatch(LoadAllTests.MAX_THREAD);
		try {
			final RunnableGate g = new RunnableGate("start", "end",
					LoadAllTests.THREAD_POOL, 1);

			// スレッドプールを5ミリ秒ほど全使用状態にする。
			for (int i = 0; i < LoadAllTests.MAX_THREAD; i++) {
				LoadAllTests.THREAD_POOL.execute(new Runnable() {
					public void run() {
						try {
							Thread.sleep(5);
						} catch (final InterruptedException e) {
							Thread.currentThread().interrupt();
							throw new RuntimeException(e);
						} finally {
							latch.countDown();
						}
					}
				});
			}

			g.execute(g.getGate("mid"));
			fail();
		} catch (final RuntimeException e) {
			assertTrue(e.getCause() instanceof InterruptedException);
			assertTrue(Thread.currentThread().isInterrupted());
			Thread.interrupted();
		} finally {
			// 次のテストへの副作用をなくすためスレッドプールの全てが待機状態になるまで待つ
			latch.await();
		}
	}
}
