package org.jenetics.util;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.testng.Assert;
import org.testng.annotations.Test;

public class ConcurrentTest {

	@Test
	public void serialScope() {
		final long start = System.currentTimeMillis();

		final long sleep = 100;
		final int loops = 10;
		try (Scoped<Executor> e = Concurrent.serial()) {
			for (int i = 0; i < loops; ++i) {
				e.get().execute(new Sleep(String.format("sleep(%d)", i), sleep));
			}
		}
		
		final long end = System.currentTimeMillis();
		final long duration = end - start;
		final long expected = sleep*loops;
		Assert.assertTrue(
			duration >= expected, 
			String.format("%d < %d", duration, expected)
		);
		Assert.assertTrue(
			duration < 1.2*expected, 
			String.format("%d >= %d", duration, expected)
		);		
		System.out.println("Duration: " + (double)(end - start)/1000.0);
	}
	
	@Test
	public void scope() {
		final long start = System.currentTimeMillis();

		final long sleep = 100;
		final int loops = 20;
		final int parallelism = 5;
		final ExecutorService executor = Executors.newFixedThreadPool(parallelism);
		
		try {
			try (Scoped<Executor> e = Concurrent.scope(executor)) {
				for (int i = 0; i < loops; ++i) {
					e.get().execute(new Sleep(String.format("sleep(%d)", i), sleep));
				}
			}
			
			final long end = System.currentTimeMillis();
			final long duration = end - start;
			final long expected = sleep*loops/parallelism;
			
			Assert.assertTrue(
				duration >= expected, 
				String.format("%d < %d", duration, expected)
			);
			Assert.assertTrue(
				duration < 1.2*expected, 
				String.format("%d >= %d", duration, expected)
			);
			System.out.println("Duration: " + (double)(end - start)/1000.0);
		} finally {
			executor.shutdownNow();
		}
	}
	
	private static final class Sleep implements Runnable {
		private final String _name;
		private final long _duration;
		
		Sleep(final String name, final long duration) {
			_name = name;
			_duration = duration;
		}
		
		@Override
		public void run() {
			System.out.println("Starting " + _name);
			try {
				Thread.sleep(_duration);
			} catch (InterruptedException e) {
				System.out.println("Sleep interrupted.");
				Thread.currentThread().interrupt();
			}
			System.out.println("    ...finished " + _name);
		}
		
	}
	
}

@@ -541,19 +541,17 @@
 %09%09%7D%0A%09%09%7D%0A
-%09%09
 %0A
+
 %09%09final 
@@ -700,33 +700,32 @@
 ion %3E= expected,
- 
 %0A%09%09%09String.forma
@@ -791,33 +791,33 @@
 %09%09%09duration %3C 1.
-2
+5
 *expected, %0A%09%09%09S
@@ -806,25 +806,24 @@
 .5*expected,
- 
 %0A%09%09%09String.f
@@ -864,18 +864,16 @@
 ed)%0A%09%09);
-%09%09
 %0A%09%09Syste
@@ -935,18 +935,17 @@
 .0);%0A%09%7D%0A
-%09
 %0A
+
 %09@Test%0A%09
@@ -1173,19 +1173,17 @@
 elism);%0A
-%09%09
 %0A
+
 %09%09try %7B%0A
@@ -1361,20 +1361,17 @@
 %09%7D%0A%09%09%09%7D%0A
-%09%09%09
 %0A
+
 %09%09%09final
@@ -1502,12 +1502,9 @@
 sm;%0A
-%09%09%09
 %0A
+
 %09%09%09A
@@ -1538,33 +1538,32 @@
 ion %3E= expected,
- 
 %0A%09%09%09%09String.form
@@ -1641,17 +1641,17 @@
 ion %3C 1.
-2
+5
 *expecte
@@ -1652,17 +1652,16 @@
 xpected,
- 
 %0A%09%09%09%09Str
@@ -1825,18 +1825,17 @@
 %0A%09%09%7D%0A%09%7D%0A
-%09
 %0A
+
 %09private
@@ -1944,19 +1944,17 @@
 ration;%0A
-%09%09
 %0A
+
 %09%09Sleep(
@@ -2041,19 +2041,17 @@
 on;%0A%09%09%7D%0A
-%09%09
 %0A
+
 %09%09@Overr
@@ -2346,14 +2346,11 @@
 %09%09%7D%0A
-%09%09
 %0A
+
 %09%7D%0A
-%09
 %0A%7D%0A

Make test more robust.