Subversion Repositories DevTools

Rev

Rev 4285 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.erggroup.buildtool.utf;

import com.erggroup.buildtool.daemon.BuildDaemon;
import com.erggroup.buildtool.daemon.BuildThread;
import com.erggroup.buildtool.daemon.MasterThread;
import com.erggroup.buildtool.daemon.SlaveThread;
import com.erggroup.buildtool.ripple.MutableString;
import com.erggroup.buildtool.ripple.ReleaseManager;
import com.erggroup.buildtool.ripple.Package;
import com.erggroup.buildtool.ripple.RippleEngine;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.JUnitCore;

import static org.junit.Assert.*;

/**container of Build Daemon test methods
 */
public class DaemonBuildTestCase
{
  private static final Logger mLogger = Logger.getLogger(DaemonBuildTestCase.class);

  public DaemonBuildTestCase()
  {
    mLogger.debug("DaemonBuildTestCase");
  }

  /**Test Case main line
   */
  public static void main(String[] args)
  {
    DOMConfigurator.configure("utf.xml");
    mLogger.debug("main");
    System.setProperty("vix.utf.name", "DaemonBuildTestCase");
    JUnitCore.main( "com.erggroup.buildtool.utf.DaemonBuildTestCase" );
  }

  /**set up performed prior to any test method
   */
  @BeforeClass
  public static void TestCaseSetUp()
  {
    mLogger.debug("TestCaseSetUp");
  }

  /**tear down performed after test methods
   */
  @AfterClass
  public static void TestCaseTearDown()
  {
    mLogger.debug("TestCaseTearDown");
  }

  /**set up performed prior to each test method
   */
  @Before
  public void TestSetUp()
  {
    mLogger.debug("TestSetUp");
    mLogger.fatal("TestSetUp: Property:" + System.getProperty("vix.utf.name"));
    ReleaseManager.mUseDatabase = false;
  }

  /**tear down performed after each test method
   */
  @After
  public void TestTearDown()
  {
    mLogger.debug("TestTearDown");
    ReleaseManager.mUseDatabase = true;
    ReleaseManager.mPersistedRunLevelCollection.removeAllElements();
  }

  /**test method designed primarily to test the sequence diagram spawn thread
   * also tests thread control out of necessity:
   *  1 constructs a BuildDaemon object, passing a connectionString of "unit test spawn thread"
   *    this utilises the following unit test hooks in the codebase:
   *    - BuildDaemon::BuildDaemon connectionString of "unit test spawn thread" exits while forever loop
   *    - BuildDaemon constructor, isActive and cleanUp made public for unit test use
   *    - ReleaseManager::queryReleaseConfig instantiates 2 ReleaseConfig objects
   *      with rcon_id's of 1 and 2, daemon_modes of 'M' and 'S' respectively, and gbebuildfilters of "unit test spawn thread"
   *    - MasterThread::run gbebuildfilter of "unit test spawn thread" limits method to sleep in while forever loop
   *    - SlaveThread::run gbebuildfilter of "unit test spawn thread" limits method to sleep in while forever loop
   *  2 checks the number of threads in the thread group is 3 (mainline thread + MasterThread + SlaveThread)
   *  3 checks isActive on the BuildDaemon object returns true when passed an rcon_id of 1
   *  4 checks isActive on the BuildDaemon object returns true when passed an rcon_id of 2
   *  5 checks isActive on the BuildDaemon object returns false when passed an rcon_id of 3
   *  6 calls cleanUp on the BuildDaemon object
   *  7 checks the number of threads in the thread group is 1 (mainline thread)
   *  8 checks isActive on the BuildDaemon object returns false when passed an rcon_id of 1
   *  9 checks isActive on the BuildDaemon object returns false when passed an rcon_id of 2
   * 10 checks isActive on the BuildDaemon object returns false when passed an rcon_id of 3
   */
  @Test
  public void TestSpawnThread()
  {
    mLogger.debug("TestSpawnThread");
    int tcount;
    BuildDaemon buildDaemon = new BuildDaemon("unit test spawn thread", "not used", "not used");
    tcount = BuildThread.mThreadGroup.activeCount();
    assertTrue(tcount == 2 );
    assertTrue(buildDaemon.isActive(1));
    assertTrue(buildDaemon.isActive(2));
    assertFalse(buildDaemon.isActive(3));
    buildDaemon.cleanUp();
    tcount = BuildThread.mThreadGroup.activeCount();
    assertTrue(tcount == 0);
    assertFalse(buildDaemon.isActive(1));
    assertFalse(buildDaemon.isActive(2));
    assertFalse(buildDaemon.isActive(3));
  }

  /**test method designed to test the sequence diagram coordinate slave thread:
   *  1 constructs a ReleaseManager object, passing a connectionString of "unit test coordinate slave threads"
   *  2 constructs a MasterThread object, passing a gbebuildfilter of "unit test coordinate slave threads"
   *    this utilises the following unit test hooks in the codebase:
   *    - MasterThread constructor made public for unit test use
   *    - MasterThread::run gbebuildfilter of "unit test coordinate slave threads" limits method to the sequence diagram
   *      interrupts the thread if, on one pass, at least one RunLevel object does not have a run level DB_WAITING
   *      exits the while forever loop if, on one pass, all RunLevel objects have a run level DB_WAITING
   *    - ReleaseManager::queryRunLevel connectionString of "unit test coordinate slave threads" instantiates 2 RunLevel objects
   *      initially with run levels of waiting and idle
   *      subsequently with run levels both waiting
   *  3 calls run on the MasterThread object
   *  4 checks its thread has been interrupted
   */
  @SuppressWarnings("unused")
@Test
  public void TestCoordinateSlaveThreads()
  {
    mLogger.debug("TestCoordinateSlaveThreads");
    ReleaseManager releaseManager = new ReleaseManager("unit test coordinate slave threads", "not used", "not used");
    MasterThread masterThread = new MasterThread(1, 1, "unit test coordinate slave threads");
    assertFalse(Thread.interrupted());
    masterThread.run();
    // interrupted checks and importantly clears the interrupted status of this thread for subsequent tests
    assertTrue(Thread.interrupted());
    assertFalse(Thread.interrupted());
  }

  /**test method designed to test the sequence diagram generate build files
   * note does not test the RippleEngine:
   *  1 constructs a ReleaseManager object, passing a connectionString of "unit test generate build files"
   *  2 constructs a MasterThread object, passing a gbebuildfilter of "unit test generate build files"
   *    this utilises the following unit test hooks in the codebase:
   *    - MasterThread constructor made public for unit test use
   *    - MasterThread::run gbebuildfilter of "unit test generate build files" limits method to the sequence diagram
   *      exits the while forever loop
   *    - ReleaseManager::queryReleaseConfig instantiates 2 ReleaseConfig objects
   *      with rcon_id's of 1 and 2, daemon_modes of 'M' and 'S' respectively, and gbebuildfilters of "unit test spawn thread"
   *    - ReleaseManager::updateCurrentRunLevel utilises the public mPersistedRunLevelCollection
   *  3 calls run on the MasterThread object
   *  4 checks the first persisted run level is DB_ACTIVE
   *  5 checks the second persisted run level is DB_ACTIVE
   *  6 checks no further run levels were persisted
   */
  @SuppressWarnings("unused")
@Test
  public void TestGenerateBuildFiles()
  {
    mLogger.debug("TestGenerateBuildFiles");
    ReleaseManager releaseManager = new ReleaseManager("unit test generate build files", "not used", "not used");
    MasterThread masterThread = new MasterThread(1, 1, "unit test generate build files");
    masterThread.run();
    Integer persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 0 );
    assertTrue( persistedRunLevel.intValue() == ReleaseManager.DB_ACTIVE );
    persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 1 );
    assertTrue( persistedRunLevel.intValue() == ReleaseManager.DB_ACTIVE );
    boolean caughtOOB = false;
    
    try
    {
      persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 2 );
    }
    catch( ArrayIndexOutOfBoundsException e )
    {
      caughtOOB = true;
    }
    
    assertTrue(caughtOOB);
  }

  /**test method designed to test the sequence diagram consume build files
   *  1 constructs a ReleaseManager object, passing a connectionString of "unit test consume build files"
   *  2 constructs a SlaveThread object, passing a gbebuildfilter of "unit test consume build files"
   *    this utilises the following unit test hooks in the codebase:
   *    - SlaveThread constructor made public for unit test use
   *    - SlaveThread::run gbebuildfilter of "unit test consume build files" limits method to the sequence diagram
   *      interrupts the thread if, on one pass, the current build file string is empty
   *      exits the while forever loop
   *    - ReleaseManager::queryRunLevel
   *      initially returns an empty current build file string
   *      subsequently returns a "unit test build file content" current build file string
   *  3 calls run on the SlaveThread object
   */
  @SuppressWarnings("unused")
@Test
  public void TestConsumeBuildFiles()
  {
    mLogger.debug("TestConsumeBuildFiles");
    ReleaseManager releaseManager = new ReleaseManager("unit test consume build files", "not used", "not used");
    SlaveThread slaveThread = new SlaveThread(1, 1, "unit test consume build files");
    assertFalse(Thread.interrupted());
    slaveThread.run();
  }

  /**test method designed to test the sequence diagram allowed to proceed
   *  1 constructs a ReleaseManager object, passing a connectionString of "unit test allowed to proceed"
   *  2 constructs a MasterThread object, passing a gbebuildfilter of "unit test allowed to proceed"
   *    this utilises the following unit test hooks in the codebase:
   *    - MasterThread constructor made public for unit test use
   *    - MasterThread::run gbebuildfilter of "unit test allowed to proceed" limits method to the sequence diagram
   *      exits the while forever loop
   *    - ReleaseManager::queryReleaseConfig, queryRunLevelSchedule, queryDirectedRunLevel methods return true
   *    - ReleaseManager::updateCurrentRunLevel utilises the public mPersistedRunLevelCollection
   *  3 calls run on the MasterThread object
   *  4 checks the first persisted run level is DB_IDLE
   *  5 checks the second persisted run level is DB_IDLE
   *  6 checks the third persisted run level is DB_WAITING
   *  7 checks no further run levels were persisted
   */
  @Test
  @SuppressWarnings("unused")
  public void TestAllowedToProceed()
  {
    mLogger.debug("TestAllowedToProceed");
    ReleaseManager releaseManager = new ReleaseManager("unit test allowed to proceed", "not used", "not used");
    MasterThread masterThread = new MasterThread(1, 1, "unit test allowed to proceed");
    masterThread.run();
    Integer persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 0 );
    assertTrue( persistedRunLevel.intValue() == ReleaseManager.DB_IDLE );
    boolean caughtOOB = false;
    
    try
    {
      persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 1 );
    }
    catch( ArrayIndexOutOfBoundsException e )
    {
      caughtOOB = true;
    }
    
    assertTrue(caughtOOB);
  }

  /**test method designed to test the sequence diagram not allowed to proceed
   *  1 constructs a ReleaseManager object, passing a connectionString of "unit test not allowed to proceed"
   *  2 constructs a MasterThread object, passing a gbebuildfilter of "unit test not allowed to proceed"
   *    this utilises the following unit test hooks in the codebase:
   *    - MasterThread constructor made public for unit test use
   *    - MasterThread::run gbebuildfilter of "unit test not allowed to proceed" limits method to the sequence diagram
   *      exits the while forever loop
   *    - ReleaseManager::queryReleaseConfig method returns true
   *    - ReleaseManager::queryRunLevelSchedule method returns false
   *    - ReleaseManager::updateCurrentRunLevel utilises the public mPersistedRunLevelCollection
   *  3 calls run on the MasterThread object
   *  4 checks the first persisted run level is DB_IDLE
   *  5 checks the second persisted run level is DB_IDLE
   *  6 checks the third persisted run level is DB_PAUSED
   *  7 checks no further run levels were persisted
   * nb cannot check only one thread is running,
   * a Timer thread, though having run to completion, may still be "active"
   */
  @Test
  @SuppressWarnings("unused")
  public void TestNotAllowedToProceed()
  {
    mLogger.debug("TestNotAllowedToProceed");
    ReleaseManager releaseManager = new ReleaseManager("unit test not allowed to proceed", "not used", "not used");
    MasterThread masterThread = new MasterThread(1, 1, "unit test not allowed to proceed");
    masterThread.run();
    Integer persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 0 );
    assertTrue( persistedRunLevel.intValue() == ReleaseManager.DB_IDLE );
    persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 1 );
    assertTrue( persistedRunLevel.intValue() == ReleaseManager.DB_PAUSED );
    boolean caughtOOB = false;
    
    try
    {
      persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 2 );
    }
    catch( ArrayIndexOutOfBoundsException e )
    {
      caughtOOB = true;
    }
    
    assertTrue(caughtOOB);
  }

  /**test method designed to test the sequence diagram exit
   *  1 constructs a ReleaseManager object, passing a connectionString of "unit test exit"
   *  2 constructs a MasterThread object, passing a gbebuildfilter of "unit test exit"
   *    this utilises the following unit test hooks in the codebase:
   *    - MasterThread constructor made public for unit test use
   *    - MasterThread::run gbebuildfilter of "unit test exit" limits method to the sequence diagram
   *    - ReleaseManager::queryReleaseConfig method returns false
   *    - ReleaseManager::updateCurrentRunLevel utilises the public mPersistedRunLevelCollection
   *  3 calls run on the MasterThread object
   *  4 checks the first persisted run level is DB_IDLE
   *  5 checks no further run levels were persisted
   */
  @Test
  @SuppressWarnings("unused")
  public void TestExit()
  {
    mLogger.debug("TestExit");
    ReleaseManager releaseManager = new ReleaseManager("unit test exit", "not used", "not used");
    MasterThread masterThread = new MasterThread(1, 1, "unit test exit");
    masterThread.run();
    Integer persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 0 );
    assertTrue( persistedRunLevel.intValue() == ReleaseManager.DB_IDLE );

    boolean caughtOOB = false;
    
    try
    {
      persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 2 );
    }
    catch( ArrayIndexOutOfBoundsException e )
    {
      caughtOOB = true;
    }
    
    assertTrue(caughtOOB);
  }

  /**test method designed to test the sequence diagram check environment
   *  1 constructs a ReleaseManager object, passing a connectionString of "unit check environment"
   *  2 constructs a MasterThread object, passing a gbebuildfilter of "unit check environment"
   *    this utilises the following unit test hooks in the codebase:
   *    - MasterThread constructor made public for unit test use
   *    - MasterThread::run gbebuildfilter of "unit test check environment" limits method to the sequence diagram
   *      exits the while forever loop
   *    - MasterThread::housekeep method does not call deleteDirectory
   *    - MasterThread::hasSufficientDiskSpace initially returns false, then true
   *    - ReleaseManager::updateCurrentRunLevel utilises the public mPersistedRunLevelCollection
   *  3 calls run on the MasterThread object
   *  4 checks the first persisted run level is DB_CANNOT_CONTINUE
   *  5 checks the next persisted run level is DB_ACTIVE
   *  6 checks no further run levels were persisted
   */
  @Test
  @SuppressWarnings("unused")
  public void TestCheckEnvironment()
  {
    mLogger.debug("TestCheckEnvironment");
    ReleaseManager releaseManager = new ReleaseManager("unit test check environment", "not used", "not used");
    MasterThread masterThread = new MasterThread(1, 1, "unit test check environment");
    masterThread.run();
    Integer persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 0 );
    assertTrue( persistedRunLevel.intValue() == ReleaseManager.DB_CANNOT_CONTINUE );
    persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 1 );
    assertTrue( persistedRunLevel.intValue() == ReleaseManager.DB_ACTIVE );
    boolean caughtOOB = false;
    
    try
    {
      persistedRunLevel = (Integer)ReleaseManager.mPersistedRunLevelCollection.get( 2 );
    }
    catch( ArrayIndexOutOfBoundsException e )
    {
      caughtOOB = true;
    }
    
    assertTrue(caughtOOB);
  }

  /**test method designed to test the ripple engine
   *  1 constructs a ReleaseManager object with connection string "iteration1"
   *  2 constructs a RippleEngine object
   *  3 calls planRelease on the RippleEngine object
   *  4 calls getFirstBuildFileContent
   *  5 checks it returns true
   *  6 writes the content to "daemon1.xml"
   *  7 checks the content matches the content in "expecteddaemon1.xml"
   *  8 calls getNextBuildFileContent
   *  9 checks it returns false
   * 10 constructs a ReleaseManager object with connection string "iteration2"
   * 11 calls planRelease on the RippleEngine object
   * 12 calls getFirstBuildFileContent
   * 13 checks it returns true
   * 14 writes the content to "daemon2.xml"
   * 15 checks the content matches the content in "expecteddaemon2.xml"
   * 16 calls getNextBuildFileContent
   * 17 checks it returns false
   * 18 steps 10 to 17 are repeated for iteration3,4,5 and 6
   * 19 constructs a ReleaseManager object with connection string "iteration7"
   * 20 calls planRelease on the RippleEngine object
   * 21 calls getFirstBuildFileContent
   * 22 checks it returns true (a benign build file content)
   */
  @Test
  public void TestPlanRelease()
  {
    mLogger.debug("TestPlanRelease");
    ReleaseManager releaseManager = 
      new ReleaseManager("iteration1", "not used", "not used");
      
    RippleEngine rippleEngine = new RippleEngine(releaseManager, 11111, true);
    // this is all the MasterThread does
    try
    {
      rippleEngine.collectMetaData();
      rippleEngine.planRelease();
    }
    catch(Exception e)
    {
    }
    
    boolean rv;
    MutableString buildFileContent = new MutableString();
    
    boolean moreBuildFiles = rippleEngine.getFirstBuildFileContent(buildFileContent);
    assertTrue(moreBuildFiles);

    rv = checkBuildfile(buildFileContent,"daemon1");
    assertTrue(rv);
    moreBuildFiles = rippleEngine.getNextBuildFileContent(buildFileContent);
    assertFalse(moreBuildFiles);
    
    releaseManager = 
      new ReleaseManager("iteration2", "not used", "not used");
      
    // this is all the MasterThread does
    try
    {
      rippleEngine.collectMetaData();
      rippleEngine.planRelease();
    }
    catch(Exception e)
    {
    }
    
    moreBuildFiles = rippleEngine.getFirstBuildFileContent(buildFileContent);
    assertTrue(moreBuildFiles);

    rv = checkBuildfile(buildFileContent,"daemon2");
    assertTrue(rv);
    moreBuildFiles = rippleEngine.getNextBuildFileContent(buildFileContent);
    assertFalse(moreBuildFiles);

    releaseManager = 
      new ReleaseManager("iteration3", "not used", "not used");
      
    // this is all the MasterThread does
    try
    {
      rippleEngine.collectMetaData();
      rippleEngine.planRelease();
    }
    catch(Exception e)
    {
    }
    
    moreBuildFiles = rippleEngine.getFirstBuildFileContent(buildFileContent);
    assertTrue(moreBuildFiles);

    rv = checkBuildfile(buildFileContent,"daemon3");
    assertTrue(rv);
    moreBuildFiles = rippleEngine.getNextBuildFileContent(buildFileContent);
    assertFalse(moreBuildFiles);

    releaseManager = 
      new ReleaseManager("iteration4", "not used", "not used");
      
    // this is all the MasterThread does
    try
    {
      rippleEngine.collectMetaData();
      rippleEngine.planRelease();
    }
    catch(Exception e)
    {
    }
    
    moreBuildFiles = rippleEngine.getFirstBuildFileContent(buildFileContent);
    assertTrue(moreBuildFiles);
    rv = checkBuildfile(buildFileContent,"daemon4");
    assertTrue(rv);
    moreBuildFiles = rippleEngine.getNextBuildFileContent(buildFileContent);
    assertFalse(moreBuildFiles);

    releaseManager = 
      new ReleaseManager("iteration5", "not used", "not used");
      
    // this is all the MasterThread does
    try
    {
      rippleEngine.collectMetaData();
      rippleEngine.planRelease();
    }
    catch(Exception e)
    {
    }
    
    moreBuildFiles = rippleEngine.getFirstBuildFileContent(buildFileContent);
    assertTrue(moreBuildFiles);

    rv = checkBuildfile(buildFileContent,"daemon5");
    assertTrue(rv);
    moreBuildFiles = rippleEngine.getNextBuildFileContent(buildFileContent);
    assertFalse(moreBuildFiles);

    releaseManager = 
      new ReleaseManager("iteration6", "not used", "not used");
      
    // this is all the MasterThread does
    try
    {
      rippleEngine.collectMetaData();
      rippleEngine.planRelease();
    }
    catch(Exception e)
    {
    }
    
    moreBuildFiles = rippleEngine.getFirstBuildFileContent(buildFileContent);
    assertTrue(moreBuildFiles);

    rv = checkBuildfile(buildFileContent,"daemon6");
    assertTrue(rv);
    moreBuildFiles = rippleEngine.getNextBuildFileContent(buildFileContent);
    assertFalse(moreBuildFiles);

    releaseManager = 
      new ReleaseManager("iteration7", "not used", "not used");
      
    // this is all the MasterThread does
    try
    {
      rippleEngine.collectMetaData();
      rippleEngine.planRelease();
    }
    catch(Exception e)
    {
    }
    
    moreBuildFiles = rippleEngine.getFirstBuildFileContent(buildFileContent);
    assertTrue(moreBuildFiles);
  }

  /** Check build file against golden image
   * 
   * @param buildFileContent - Generated build file
   * @param baseName             - Base name used to save buildfile and for golden image
   * @return boolean             - True if the build file matches the golden image
   */
private boolean checkBuildfile(MutableString buildFileContent, String baseName) {
        String buildFileName;
        String testFilename;
        String expected = "";
    String user = "";
        File cwd = new File( "." );
        
        // persist the generated build file content to daemon2.xml for visibility
    buildFileName = new String(baseName + ".xml");
    testFilename = new String("expected" + baseName + ".xml");
    
    try
    {
      File buildFile = new File(cwd, buildFileName);
      FileWriter buildFileWriter = new FileWriter(buildFile);
      buildFileWriter.write(buildFileContent.value);
      buildFileWriter.close();
      
      File expectedBuildFile = new File(cwd, testFilename);
      FileReader expectedBuildFileReader = new FileReader(expectedBuildFile);
      char[] expectedBuildFileContent = new char[(int)expectedBuildFile.length()];
      expectedBuildFileReader.read(expectedBuildFileContent);
      expectedBuildFileReader.close();
      
      expected = new String(expectedBuildFileContent);
      expected = expected.replace("\r", "");

      user = buildFileContent.value.replace("\r", "");
    }
    catch( IOException e )
    {
      System.out.println("DaemonBuildTestCase::TestPlanRelease caught IOException:" + baseName);
      expected = "";
    }
    int retVal = user.compareTo(expected);
    return  retVal == 0;
}

  /**test method designed to test ripple field limits
   *  1 tests applyPV returns 1 for package with version a.b.1.2.0
   */
  @Test
  public void TestRippleFieldLimits()
  {
    ReleaseManager rm = new ReleaseManager();
    // for test purposes, p.mId will contain the return value of applyPV
    // test applyPV returns 1 and leaves mVersion alone
    Package p = new Package(rm, "a.b.1.2.0", 255, 255, 255, 255);
    assertTrue( p.getId() == 1 );
    assertTrue( p.getVersion().compareTo( "a.b.1.2.0" ) == 0);

    // test applyPV returns 2 and leaves mVersion alone
    p = new Package( rm, "1.0.0000", 0, 0, 0, 0 );
    assertTrue( p.getId() == 2 );
    assertTrue( p.getVersion().compareTo( "1.0.0000" ) == 0);

    // test applyPV returns 2 and leaves mVersion alone
    p = new Package( rm, "1.0.0009", 0, 0, 0, 9 );
    assertTrue( p.getId() == 2 );
    assertTrue( p.getVersion().compareTo( "1.0.0009" ) == 0);
    
    // test applyPV returns 2 and leaves mVersion alone
    p = new Package( rm, "1.0.9000", 0, 0, 9, 0 );
    assertTrue( p.getId() == 2 );
    assertTrue( p.getVersion().compareTo( "1.0.9000" ) == 0);
    
    // test applyPV returns 2 and leaves mVersion alone
    p = new Package( rm, "1.9.0000", 0, 9, 0, 0 );
    assertTrue( p.getId() == 2 );
    assertTrue( p.getVersion().compareTo( "1.9.0000" ) == 0);
    
    // test applyPV returns 2 and leaves mVersion alone
    p = new Package( rm, "1.0.0000", 1, 0, 0, 0 );
    assertTrue( p.getId() == 2 );
    assertTrue( p.getVersion().compareTo( "1.0.0000" ) == 0);
    
    // test applyPV returns 2 and leaves mVersion alone - wince style limits
    p = new Package( rm, "9.9.9000", 9, 9, 9, 0 );
    assertTrue( p.getId() == 2 );
    assertTrue( p.getVersion().compareTo( "9.9.9000" ) == 0);

    // test applyPV returns 0 and sets mVersion from 8.8.8000 to 8.8.9000
    p = new Package( rm, "8.8.8000", 9, 9, 9, 0 );
    assertTrue( p.getId() == 0 );
    assertTrue( p.getVersion().compareTo( "8.8.9000" ) == 0);

    // test applyPV returns 0 and sets mVersion from 8.8.9000 to 8.9.0000
    p = new Package( rm, "8.8.9000", 9, 9, 9, 0 );
    assertTrue( p.getId() == 0 );
    assertTrue( p.getVersion().compareTo( "8.9.0000" ) == 0);

    // test applyPV returns 0 and sets mVersion from 8.9.9000 to 9.0.0000
    p = new Package( rm, "8.9.9000", 9, 9, 9, 0 );
    assertTrue( p.getId() == 0 );
    assertTrue( p.getVersion().compareTo( "9.0.0000" ) == 0);

    // test applyPV returns 2 and leaves mVersion alone - mos style limits
    p = new Package( rm, "99.99.0000", 99, 99, 0, 0 );
    assertTrue( p.getId() == 2 );
    assertTrue( p.getVersion().compareTo( "99.99.0000" ) == 0);

    // test applyPV returns 0 and sets mVersion from 98.98.0000 to 98.99.0000
    p = new Package( rm, "98.98.0000", 99, 99, 0, 0 );
    assertTrue( p.getId() == 0 );
    assertTrue( p.getVersion().compareTo( "98.99.0000" ) == 0);

    // test applyPV returns 0 and sets mVersion from 98.99.0000 to 99.0.0000
    p = new Package( rm, "98.99.0000", 99, 99, 0, 0 );
    assertTrue( p.getId() == 0 );
    assertTrue( p.getVersion().compareTo( "99.0.0000" ) == 0);

  }

  /**test method designed to ripple of COTS packages
   *  1 tests applyPV returns 1 for package with version a.b.1.2.0
   */
  @Test
  public void TestCotsRipples()
  {
    ReleaseManager rm = new ReleaseManager();
    // for test purposes, p.mId will contain the return value of applyPV
    // test applyPV returns 1 and leaves mVersion alone

    mLogger.debug("TestCotsRipples: willNotRipple.cots");
    Package p = new Package(rm, "willNotRipple.cots", 255, 255, 255, 255);
    assertTrue( p.getId() == 1 );
    assertTrue( p.getVersion().compareTo( "willNotRipple" ) == 0);

    mLogger.debug("TestCotsRipples: willRipple.0000.cots");
    p = new Package(rm, "willRipple.0000.cots", 255, 255, 255, 255);
    assertTrue( p.getId() == 0 );
    assertTrue( p.getVersion().compareTo( "willRipple.1000" ) == 0);

    mLogger.debug("TestCotsRipples: willNotRipple.000.cots");
    p = new Package(rm, "willNotRipple.000.cots", 255, 255, 255, 255);
    assertTrue( p.getId() == 1 );
    assertTrue( p.getVersion().compareTo( "willNotRipple.000" ) == 0);
    
  }
  
}