package test.org.itscool.commons.aop2;
import java.util.Date;

import junit.framework.TestCase;

import org.itscool.commons.aop.ProxyMethodInvocator;

public class Advice2Test extends TestCase{
	
	public void testAroundAdvice(){
		ProxyMethodInvocator proxy = new ProxyMethodInvocator(new LogicImpl(), Logic.class);
		proxy.addAdvice("execute", new NullCheckAdvice());
		proxy.addAdvice("execute", new IntegerCheckAdvice());
		Logic logic = (Logic)proxy.getProxy();
		
		assertEquals(120, logic.execute("30", "4"));
		assertEquals(0, logic.execute("30", "a"));
		assertEquals(0, logic.execute(null, "3"));		
	}
	
	public void testThreadSafe1(){
		int THREAD_NUM = 1000;
		int LOOP_NUM = 10000;
		LogicThread[] threads = new LogicThread[THREAD_NUM];
		for(int i=0; i<THREAD_NUM; i++ ){
			threads[i] = new LogicThread(LOOP_NUM);
			threads[i].start();
		}
	}
	
	public void testThreadSafe2(){
		ProxyMethodInvocator proxy = new ProxyMethodInvocator(new LogicImpl(), Logic.class);
		proxy.addAdvice("execute", new NullCheckAdvice());
		proxy.addAdvice("execute", new IntegerCheckAdvice());
		Logic logic = (Logic)proxy.getProxy();
		
		int THREAD_NUM = 50;
		int LOOP_NUM = 50;
		LogicThread2[] threads = new LogicThread2[THREAD_NUM];
		for(int i=0; i<THREAD_NUM; i++ ){
			threads[i] = new LogicThread2(LOOP_NUM, logic);
			threads[i].start();
		}
		
	}
	
	public void testThreadPeformance(){
		
		long start = getTimeInMilli();
		ProxyMethodInvocator proxy = new ProxyMethodInvocator(new LogicImpl(), Logic.class);
		proxy.addAdvice("execute", new NullCheckAdvice());
		proxy.addAdvice("execute", new IntegerCheckAdvice());
		Logic logic = (Logic)proxy.getProxy();
		
		int THREAD_NUM = 50;
		int LOOP_NUM = 50;
		LogicThread2[] threads = new LogicThread2[THREAD_NUM];
		for(int i=0; i<THREAD_NUM; i++ ){
			threads[i] = new LogicThread2(LOOP_NUM, logic);
			threads[i].start();
			
		}
		for(int i=0; i<THREAD_NUM; i++ ){
			try{
				threads[i].join();
			}catch( InterruptedException e){}
		}
		System.out.println("AOP版 経過時間(msec):"+ (getTimeInMilli()-start)+"msec" );
		
		start = getTimeInMilli();
		for(int i=0; i<THREAD_NUM; i++ ){
			threads[i] = new LogicThread2(LOOP_NUM, new LogicImpl());
			threads[i].start();
			
		}
		for(int i=0; i<THREAD_NUM; i++ ){
			try{
				threads[i].join();
			}catch( InterruptedException e){}
		}
		System.out.println("POJO版 経過時間(msec):"+ (getTimeInMilli()-start)+"msec" );
		
	}

	private long getTimeInMilli(){
		Date date = new Date();
        long inTime = date.getTime();
        return inTime;
	}
	
	class LogicThread extends Thread{
		int roop = 0;
		public LogicThread(int roop){
			this.roop = roop;
		}
		public void run(){			
			try{
				ProxyMethodInvocator proxy = new ProxyMethodInvocator(new LogicImpl(), Logic.class);
				proxy.addAdvice("execute", new NullCheckAdvice());
				proxy.addAdvice("execute", new IntegerCheckAdvice());
				Logic logic = (Logic)proxy.getProxy();
				
				for(int i=0; i<roop; i++){
					sleep(10+(int)(Math.random()*10));
					assertEquals(logic.execute("30", "4"), 120);
					assertEquals(logic.execute("100", "4"), 400);
				}
			}catch( InterruptedException e){}
		}
	}
	
	class LogicThread2 extends Thread{
		int roop = 0;
		Logic logic;
		public LogicThread2(int roop, Logic logic){
			this.roop = roop;
			this.logic = logic;
		}
		public void run(){			
			try{
				for(int i=0; i<roop; i++){
					sleep(10+(int)(Math.random()*10));
					assertEquals(logic.execute("30", "4"), 120);
					assertEquals(logic.execute("100", "4"), 400);
					assertEquals(logic.execute("100", "5"), 500);
					assertEquals(logic.execute("100", "6"), 600);
					assertEquals(logic.execute("100", "7"), 700);
				}
			}catch( InterruptedException e){}
		}
	}
	
	class LogicThreadPeformance extends Thread{
		int roop = 0;
		Logic logic;
		public LogicThreadPeformance(int roop, Logic logic){
			this.roop = roop;
			this.logic = logic;
		}
		public void run(){			
			try{
				for(int i=0; i<roop; i++){
					sleep(10);
					assertEquals(logic.execute("30", "4"), 120);
					assertEquals(logic.execute("100", "4"), 400);
					assertEquals(logic.execute("100", "5"), 500);
					assertEquals(logic.execute("100", "6"), 600);
					assertEquals(logic.execute("100", "7"), 700);
				}
			}catch( InterruptedException e){}
		}
	}
}

