Package org.olat.commons.coordinate

Source Code of org.olat.commons.coordinate.CoordinatorTest

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.commons.coordinate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.apache.log4j.Logger;
import org.olat.basesecurity.ManagerFactory;
import org.olat.basesecurity.SecurityGroup;
import org.olat.commons.lifecycle.LifeCycleManager;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.OLATResourceable;
import org.olat.core.logging.AssertException;
import org.olat.core.test.OlatTestCase;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.coordinate.SyncerCallback;
import org.olat.core.util.coordinate.SyncerExecutor;
import org.olat.core.util.resource.OresHelper;
import org.olat.course.CourseModule;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryManager;
import org.olat.resource.OLATResource;
import org.olat.resource.OLATResourceManager;
import org.olat.resource.lock.pessimistic.PessimisticLockManager;


/**
*
*/
public class CoordinatorTest extends OlatTestCase {

  private static Logger log = Logger.getLogger(CoordinatorTest.class.getName());
  private static boolean isInitialized = false;

  /**
   * @param name
   */
  public CoordinatorTest(String name) {
    super(name);
  }

  /**
   * @return Test
   */
  public static Test suite() {
    return new TestSuite(CoordinatorTest.class);
  }
 

  /**
   * Test with 2 threads T1 & T2.
   * T1          T2
   * doInSync T1-1  sleep 5sec
   * sleep 10sec    ...
   * ...            ...
   * ...            doInSync T2-1
   * ...            sleep 10sec
   * ...            ...
   * doInSync T1-2  ...
   * finished       ...
   *                doInSync T2-2
   *                finished
   */
  public void testDoInSyncWithSyncerExecutor() {

    final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
    final List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1));
 
    final OLATResourceable ores = OresHelper.createOLATResourceableInstance("testDoInSync", new Long("123"));
    // thread 1
    new Thread(new Runnable() {
      public void run() {
        try {
          // do something in sync
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor(){
            public void execute() {
              System.out.println("Thread-1: execute doInSync 1");
            }
          });//end syncerCallback
         
          // sleep
          sleep(10000);
         
          // do again do something in sync
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor(){
            public void execute() {
              System.out.println("Thread-1: execute doInSync 2");
            }
          });//end syncerCallback
          System.out.println("Thread-1: finished");
          statusList.add(Boolean.TRUE);
        } catch (Exception e) {
          exceptionHolder.add(e);
        } finally {
          try {
            DBFactory.getInstance().closeSession();
          } catch (Exception e) {
            // ignore
          };
       
      }}).start();
   
    // thread 2
    new Thread(new Runnable() {
      public void run() {
        try {
          // sleep
          sleep(5000);

          // do something in sync
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor(){
            public void execute() {
              System.out.println("Thread-2: execute doInSync 1");
            }
          });//end syncerCallback
         
          // sleep
          sleep(10000);
         
          // do again do something in sync
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor(){
            public void execute() {
              System.out.println("Thread-2: execute doInSync 2");
            }
          });//end syncerCallback
          System.out.println("Thread-2: finished");
          statusList.add(Boolean.TRUE);
        } catch (Exception e) {
          exceptionHolder.add(e);
        } finally {
          try {
            DBFactory.getInstance().closeSession();
          } catch (Exception e) {
            // ignore
          };
       
      }}).start();
   
    // sleep until t1 and t2 should have terminated/excepted
    int loopCount = 0;
    while ( (statusList.size()<2) && (exceptionHolder.size()<1) && (loopCount<90)) {
      sleep(1000);
      loopCount++;
    }
    assertTrue("Threads did not finish in 90sec", loopCount<90);
    // if not -> they are in deadlock and the db did not detect it
    for (Exception exception : exceptionHolder) {
      System.out.println("exception: "+exception.getMessage());
      exception.printStackTrace();
    }
    if (exceptionHolder.size() > 0) {
      assertTrue("It throws an exception in test => see sysout exception[0]=" + exceptionHolder.get(0).getMessage(), exceptionHolder.size() == 0)
    }
  }

  /**
   * Test with 2 threads T1 & T2.
   * T1          T2
   * doInSync T1-1  sleep 5sec
   * sleep 10sec    ...
   * ...            ...
   * ...            doInSync T2-1
   * ...            sleep 10sec
   * ...            ...
   * doInSync T1-2  ...
   * finished       ...
   *                doInSync T2-2
   *                finished
   */
  public void testDoInSyncWithSyncerCallback() {

    final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
    final List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1));
 
    final OLATResourceable ores = OresHelper.createOLATResourceableInstance("testDoInSync", new Long("123"));
    // thread 1
    new Thread(new Runnable() {
      public void run() {
        try {
          // do something in sync
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerCallback<Boolean>(){
            public Boolean execute() {
              System.out.println("Thread-1: execute doInSync 1");
              return Boolean.TRUE;
            }
          });//end syncerCallback
         
          // sleep
          sleep(10000);
         
          // do again do something in sync
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerCallback<Boolean>(){
            public Boolean execute() {
              System.out.println("Thread-1: execute doInSync 2");
              return Boolean.TRUE;
            }
          });//end syncerCallback
          System.out.println("Thread-1: finished");
          statusList.add(Boolean.TRUE);
        } catch (Exception e) {
          exceptionHolder.add(e);
        } finally {
          try {
            DBFactory.getInstance().closeSession();
          } catch (Exception e) {
            // ignore
          };
       
      }}).start();
   
    // thread 2
    new Thread(new Runnable() {
      public void run() {
        try {
          // sleep
          sleep(5000);

          // do something in sync
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerCallback<Boolean>(){
            public Boolean execute() {
              System.out.println("Thread-2: execute doInSync 1");
              return Boolean.TRUE;
            }
          });//end syncerCallback
         
          // sleep
          sleep(10000);
         
          // do again do something in sync
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerCallback<Boolean>(){
            public Boolean execute() {
              System.out.println("Thread-2: execute doInSync 2");
              return Boolean.TRUE;
            }
          });//end syncerCallback
          System.out.println("Thread-2: finished");
          statusList.add(Boolean.TRUE);
        } catch (Exception e) {
          exceptionHolder.add(e);
        } finally {
          try {
            DBFactory.getInstance().closeSession();
          } catch (Exception e) {
            // ignore
          };
       
      }}).start();
   
    // sleep until t1 and t2 should have terminated/excepted
    int loopCount = 0;
    while ( (statusList.size()<2) && (exceptionHolder.size()<1) && (loopCount<90)) {
      sleep(1000);
      loopCount++;
    }
    assertTrue("Threads did not finish in 90sec", loopCount<90);
    // if not -> they are in deadlock and the db did not detect it
    for (Exception exception : exceptionHolder) {
      System.out.println("exception: "+exception.getMessage());
      exception.printStackTrace();
    }
    if (exceptionHolder.size() > 0) {
      assertTrue("It throws an exception in test => see sysout exception[0]=" + exceptionHolder.get(0).getMessage(), exceptionHolder.size() == 0)
    }
  }
 

  public void testNestedAssertExceptionInDoInSync() {
    final OLATResourceable ores = OresHelper.createOLATResourceableInstance("testNestedAssertExceptionInDoInSync", new Long("123"));
   
    try {
      CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerCallback<Boolean>(){
        public Boolean execute() {
          System.out.println("testNestedAssertExceptionInDoInSync: execute doInSync 1");
         
          // Do agin in sync => nested => no allowed!
          CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerCallback<Boolean>(){
            public Boolean execute() {
              System.out.println("testNestedAssertExceptionInDoInSync: execute doInSync 2");
              fail("No NestedAssertException thrown");
              return Boolean.TRUE;
            }
          });//end syncerCallback
 
          return Boolean.TRUE;
        }
      });//end syncerCallback
    }catch(AssertException aex) {
      System.out.println("testNestedAssertExceptionInDoInSync: Ok, got a AssertException=" + aex);
    }
  }
 
  public void testSyncerAssertAlreadyDoInSyncFor() {
    final OLATResourceable ores = OresHelper.createOLATResourceableInstance("testSyncerAssertAlreadyDoInSyncFor", new Long("123"));
   
    // 1. check assertAlreadyDoInSyncFor WITHOUT sync-block => AssertException must be thrown
    try {
      CoordinatorManager.getCoordinator().getSyncer().assertAlreadyDoInSyncFor(ores);
      fail("Did not throw AssertException");
    } catch (AssertException ex) {
      System.out.println("testSyncerAssertAlreadyDoInSyncFor: This exception is ok, exception=" + ex.getMessage());
    }

    // 2.check assertAlreadyDoInSyncFor WITH sync-block => No AssertException should occour
    try {
      System.out.println("testSyncerAssertAlreadyDoInSyncFor: before doInSync");
      CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerCallback<Boolean>(){
        public Boolean execute() {
          System.out.println("testSyncerAssertAlreadyDoInSyncFor: execute before assertAlreadyDoInSyncFor");
          CoordinatorManager.getCoordinator().getSyncer().assertAlreadyDoInSyncFor(ores);
          System.out.println("testSyncerAssertAlreadyDoInSyncFor: execute done");
          return Boolean.TRUE;
        }
      });//end syncerCallback
    }catch(AssertException aex) {
      fail("testSyncerAssertAlreadyDoInSyncFor: got a AssertException=" + aex);
    }
 
  }

  public void testDoInSyncPerformance() {
    final OLATResourceable ores = OresHelper.createOLATResourceableInstance("testDoInSyncPerformance", new Long("123989456"));
    int maxLoop = 1000;
    final RepositoryEntry re = RepositoryManager.getInstance().createRepositoryEntryInstance("test", "perfTest", "perfTest description");
    re.setDisplayname("testPerf");
    // create security group
    SecurityGroup ownerGroup = ManagerFactory.getManager().createAndPersistSecurityGroup();
    re.setOwnerGroup(ownerGroup);
    RepositoryManager.getInstance().saveRepositoryEntry(re);
    DBFactory.getInstance().closeSession();
   
    // 1. Do job without doInSync
    System.out.println("testDoInSyncPerformance: start test with doInSync");
    long startTimeWithoutSync = System.currentTimeMillis();
    for (int i = 0; i<maxLoop ; i++) {
      doTestPerformanceJob(re);
      DBFactory.getInstance().closeSession();
    }
    long endTimeWithoutSync = System.currentTimeMillis();

    // 2. Do job with doInSync
    System.out.println("testDoInSyncPerformance: start test with doInSync");
    long startTimeDoInSync = System.currentTimeMillis();
    for (int i = 0; i<maxLoop ; i++) {
      CoordinatorManager.getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor(){
        public void execute() {
          doTestPerformanceJob(re);
        }

      });//end syncerCallback
      DBFactory.getInstance().closeSession();
    }
    long endTimeDoInSync = System.currentTimeMillis();
   
    // Compare time
    long timeWithoutSync = endTimeWithoutSync - startTimeWithoutSync;
    float perJobWithoutSync = (float)timeWithoutSync / maxLoop;
    System.out.println("testDoInSyncPerformance timeWithoutSync=" + timeWithoutSync + " ms for loop with " + maxLoop + " iterations");
    System.out.println("testDoInSyncPerformance perJobWithoutSync=" + perJobWithoutSync + " ms");

    long timeWithDoInSync = endTimeDoInSync - startTimeDoInSync;
    float perJobWithDoInSync = (float)timeWithDoInSync / maxLoop;
    System.out.println("testDoInSyncPerformance timeWithDoInSync=" + timeWithDoInSync + " ms for loop with " + maxLoop + " iterations");
    System.out.println("testDoInSyncPerformance perJobWithDoInSync=" + perJobWithDoInSync + " ms");
   
    long timeDiffLoop = timeWithDoInSync - timeWithoutSync;
    float timeDiffPerCall = perJobWithDoInSync - perJobWithoutSync;
    System.out.println("testDoInSyncPerformance diffLoop=" + timeDiffLoop + " ms for loop with " + maxLoop + " iterations");
    System.out.println("testDoInSyncPerformance diffPerCall=" + timeDiffPerCall + " ms");
    // Assert 10% Overhead
    assertTrue("DoInSync overhead is more than 15%", timeDiffLoop < ((timeWithoutSync * 115) / 100) );
  }

  private Boolean doTestPerformanceJob(RepositoryEntry re) {
    RepositoryEntry reloadedRe = (RepositoryEntry) DBFactory.getInstance().loadObject(re, true);
    reloadedRe.incrementLaunchCounter();
    reloadedRe.setLastUsage(new Date());
    RepositoryManager.getInstance().updateRepositoryEntry(reloadedRe);
        return true;
    }



  /**
   *
   * @param milis the duration in miliseconds to sleep
   */
  private void sleep(int milis) {
    try {
      Thread.sleep(milis);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see junit.framework.TestCase#setUp()
   */
  protected void setUp() throws Exception {
    super.setUp();
    if (CoordinatorTest.isInitialized == false) {
      CoordinatorTest.isInitialized = true;
    }
    DBFactory.getJunitInstance().clearDatabase();
   
    // now simulate the cluster module startup
    PessimisticLockManager.getInstance().init();
    DBFactory.getInstance().closeSession();
  }

  /*
   * (non-Javadoc)
   *
   * @see junit.framework.TestCase#tearDown()
   */
  protected void tearDown() throws Exception {
    try {
      DBFactory.getInstance().closeSession();
    } catch (Exception e) {
      log.error("tearDown failed: ", e);
    }
  }

}
TOP

Related Classes of org.olat.commons.coordinate.CoordinatorTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.