/*                          
 * mBench: The Open Source Micro Benchmark Tool 
 *                                             
 * Distributable under GPL license. 
 * See terms of license at gnu.org.                 
 *
 * Copyright (C) 2005 Sumisho Computer Systems Corp.
 */
package test.jp.co.scs.mbench;

import jp.co.scs.mbench.Synchronizer;
import junit.framework.TestCase;

/**
 *      @author Masato Koga
 */
public class SynchronizerTest extends TestCase {
    /**
     *  Only the first invoker can get the lock, the second and later
     *  must wait until the lock is released.
     *  When the lock is released, the second and later are returned.
     */
    public void testDoSynchronize() {
        class TestThread extends Thread {
            boolean isRunning = false;
            boolean isFinished = false;
            Synchronizer sync = null;
            public void run() {
                isRunning = true;
                sync.doSynchronize();
                isRunning = false;
                isFinished = true;
            }
        }
        Synchronizer synchronizer = new Synchronizer();
        TestThread[] thread = new TestThread[]{
            new TestThread(), new TestThread(), new TestThread()};
        for (int i = 0; i < thread.length; i++) {
            thread[i].sync = synchronizer;
        }    
        synchronizer.start();
        for (int i = 0; i < thread.length; i++) {
            thread[i].start();
        }  
        boolean threadAllRunning = false;
        while (!threadAllRunning) {
            threadAllRunning = true;
            for (int i = 0; i < thread.length; i++) {
                if (!thread[i].isRunning) {
                    threadAllRunning = false;
                    break;
                }
            }
        }
        try {
            Thread.sleep(20);
        } catch (InterruptedException ex) {
            fail();
        }
        for (int i = 0; i < thread.length; i++) {
            assertTrue(thread[i].isRunning);
        }
        synchronizer.interrupt();
        try {
            Thread.sleep(20);
        } catch (InterruptedException ex) {
            fail();
        }
        for (int i = 0; i < thread.length; i++) {
            assertFalse(thread[i].isRunning);
            assertTrue(thread[i].isFinished);
        }
    }
    
    /**
     *  Even if the lock doesn't be released by call, timeout cause
     *  the release of lock.
     */
    public void testDoSynchronize2() {
        class TestThread extends Thread {
            boolean isRunning = false;
            boolean isFinished = false;
            Synchronizer sync = null;
            public void run() {
                isRunning = true;
                sync.doSynchronize();
                isRunning = false;
                isFinished = true;
            }
        }
        Synchronizer synchronizer = new Synchronizer();
        int timeout = 1000;
        synchronizer.setTimeout(timeout);
        TestThread[] thread = new TestThread[]{
            new TestThread(), new TestThread(), new TestThread()};
        for (int i = 0; i < thread.length; i++) {
            thread[i].sync = synchronizer;
        }    
        synchronizer.start();
        for (int i = 0; i < thread.length; i++) {
            thread[i].start();
        }  
        boolean threadAllRunning = false;
        while (!threadAllRunning) {
            threadAllRunning = true;
            for (int i = 0; i < thread.length; i++) {
                if (!thread[i].isRunning) {
                    threadAllRunning = false;
                    break;
                }
            }
        }
        try {
            Thread.sleep(20);
        } catch (InterruptedException ex) {
            fail();
        }
        for (int i = 0; i < thread.length; i++) {
            assertTrue(thread[i].isRunning);
        }
        try {
            Thread.sleep(timeout + 20);
        } catch (InterruptedException ex) {
            fail();
        }
        for (int i = 0; i < thread.length; i++) {
            assertFalse(thread[i].isRunning);
            assertTrue(thread[i].isFinished);
        }
    }
}
