package org.flowcomputing.commons.resgc;

import org.testng.annotations.Test;
import org.testng.AssertJUnit;

import java.util.Random;

/**
 * ResCollectorTest is a test class which contains several test cases for the
 * purpose of validating part of functionalities of class ResCollector.
 * 
 * @author wg
 *
 */
public class ResCollectorTest {
	public class DoubleHolder extends ResHolder<Double, DoubleHolder> {

		public DoubleHolder(Double val) {
			super(val);
		}
	}

	private volatile int count;

	/**
	 * Test a register function of collector to verify collector is able to
	 * register specified holder and release it properly.
	 * 
	 */
	@Test
	public void ResCollectorRegister() {

		Random random = new Random();

		count = 0;

		ResReclaim<Double> rr = new ResReclaim<Double>() {
			@Override
			public void reclaim(Double val) {
				System.out.println(String.format("%f has been reclaimed...",
						val));
				count--;
			}
		};

		ResCollector<DoubleHolder, Double> rc = new ResCollector<DoubleHolder, Double>(
				rr);

		for (int i = 0; i < 500; ++i) {
			Double val = new Double(random.nextDouble() * 2000);
			DoubleHolder holder = new DoubleHolder(val);
			rc.register(holder);
			if (2 == i) {
				rc.unregister(holder);
			}
			if (6 == i) {
				holder.cancelAutoReclaim();
			}
			count++;
		}
		AssertJUnit.assertTrue(count > 0);

		System.gc();
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
		}

		AssertJUnit.assertTrue(count == 2);

	}

	/**
	 * Test a holder's destroy function that hosted by a collector. the holder
	 * will be forced to release its managed resource.
	 * 
	 */
	@Test
	public void ResCollectorDestroy() {

		Random random = new Random();

		count = 0;

		ResReclaim<Double> rr = new ResReclaim<Double>() {
			@Override
			public void reclaim(Double val) {
				System.out.println(String.format("%f has been reclaimed...",
						val));
				count--;
			}
		};

		ResCollector<DoubleHolder, Double> rc = new ResCollector<DoubleHolder, Double>(
				rr);

		for (int i = 0; i < 100; ++i) {
			Double val = new Double(random.nextDouble() * 2000);
			DoubleHolder dh = new DoubleHolder(val);
			rc.register(dh);
			++count;
			dh.destroy();
		}

		AssertJUnit.assertTrue(count == 0);

	}
}

@@ -1024,32 +1024,64 @@
 ble%3E(%0A%09%09%09%09rr);%0A%0A
+%09%09DoubleHolder m_holder = null;%0A
 %09%09for (int i = 0
@@ -1329,16 +1329,61 @@
 );%0A%09%09%09%7D%0A
+%09%09%09if (9 == i) %7B%0A%09%09%09%09m_holder = holder;%0A%09%09%09%7D%0A
 %09%09%09count
@@ -1434,128 +1434,187 @@
 %0A%0A%09%09
-System.gc();%0A%09%09try %7B%0A%09%09%09Thread.sleep(500);%0A%09%09%7D catch (InterruptedException e) %7B%0A%09%09%7D%0A%0A%09%09AssertJUnit.assertTrue(count == 2
+rc.waitReclaimCoolDown(rc.WAITRECLAIMTIMEOUT);%0A%0A%09%09AssertJUnit.assertTrue(count == 3);%0A%09%09System.out.println(String.format(%22********** %25f has been hold ***********%22, m_holder.get())
 );%0A%0A

verify holding value