void SetSuite_TestUnion( SetSuiteData* data ) {
   Set*        setC=NULL;
   unsigned    int_I;

   pcu_docstring( "Checks that the Union of two overlapping sets results in a new set that "
      "contains correct Union of set elements." );

   for( int_I = NUM_ITEMS*1/4; int_I < NUM_ITEMS*5/8; int_I++ ) {
      Set_Insert( data->setA, &int_I );
   }
   for( int_I = NUM_ITEMS*3/8; int_I < NUM_ITEMS*3/4; int_I++ ) {
      Set_Insert( data->setB, &int_I );
   }

   setC = (Set*)Set_Union( data->setA, data->setB );
   Set_Traverse( setC, markArray, data );
   
   for( int_I = 0; int_I < NUM_ITEMS*1/4; int_I++ ) {
      pcu_check_true( data->inSet[int_I] == False );
   }
   for( int_I = NUM_ITEMS*1/4; int_I < NUM_ITEMS*3/4; int_I++ ) {
      pcu_check_true( data->inSet[int_I] == True );
   }
   for( int_I = NUM_ITEMS*3/4; int_I < NUM_ITEMS; int_I++ ) {
      pcu_check_true( data->inSet[int_I] == False );
   }
}
void Variable_RegisterSuite_TestAddGet( Variable_RegisterSuiteData* data ) {
   Variable*		var[10];
   #define ARRAY_SIZE	4
   #define STRUCT_SIZE	4
   double			array[ARRAY_SIZE];
   Index			   arraySize = ARRAY_SIZE;
   char*			   name[10] = {"testVar0", "testVar1", "testVar2", "testVar3",
                  "testVar4", "testVar5", "testVar6", "testVar7",
                  "testVar8", "testVar9"};
   Index		   	i;

   for (i = 0; i < 10; i++) {
      var[i] = Variable_NewVector( name[i], NULL, Variable_DataType_Double, 4, &arraySize, NULL, (void**)&array, 0 );
   }

   for (i = 0; i < 10; i++)
   {
      Variable_Register_Add(data->reg, var[i]);
   }

   for (i = 0; i < 10; i++) {
      pcu_check_true( i == Variable_Register_GetIndex(data->reg, name[i]));
   }

   for (i = 0; i < 10; i++) {
      pcu_check_true( var[i] == Variable_Register_GetByName(data->reg, name[i]));
   }

   for (i = 0; i < 10; i++) {
      Stg_Class_Delete(var[i]);
   }
}
void ProgressSuite_TestSetStream( ProgressSuiteData* data ) {
   Progress_SetStream( data->prog, NULL );
   pcu_check_true( data->prog->strm == NULL );
   Progress_SetStream( data->prog, (Stream*)1 );
   pcu_check_true( data->prog->strm == (void*)1 );
   Progress_SetStream( data->prog, NULL );
}
void ElementCellLayoutSuite_TestElementCellLayout( ElementCellLayoutSuiteData* data ) {
   int                 procToWatch = data->nProcs > 1 ? 1 : 0;
   Cell_Index          cell;
   Element_DomainIndex element;
   GlobalParticle      testParticle;
      
   if( data->rank == procToWatch ) {
      for( element = 0; element < Mesh_GetLocalSize( data->mesh, data->nDims ); element++ ) {
         Cell_PointIndex   count;
         Cell_Points       cellPoints;
   
         cell = CellLayout_MapElementIdToCellId( data->elementCellLayout, element );

         pcu_check_true( cell == element );

         count = data->elementCellLayout->_pointCount( data->elementCellLayout, cell );
         cellPoints = Memory_Alloc_Array( Cell_Point, count, "cellPoints" );
         /* for the element cell layout, the elements map to cells as 1:1, as such the "points" which define the cell as the
          * same as the "nodes" which define the element */
         data->elementCellLayout->_initialisePoints( data->elementCellLayout, cell, count, cellPoints );

         testParticle.coord[0] = ( (cellPoints[0])[0] + (cellPoints[1])[0] ) / 2;
         testParticle.coord[1] = ( (cellPoints[0])[1] + (cellPoints[2])[1] ) / 2;
         testParticle.coord[2] = ( (cellPoints[0])[2] + (cellPoints[4])[2] ) / 2;
         pcu_check_true( CellLayout_IsInCell( data->elementCellLayout, cell, &testParticle ) );

         testParticle.coord[0] = (cellPoints[count-2])[0] + 1;
         testParticle.coord[1] = (cellPoints[count-2])[1] + 1;
         testParticle.coord[2] = (cellPoints[count-2])[2] + 1;
         pcu_check_true( !CellLayout_IsInCell( data->elementCellLayout, cell, &testParticle ) );

         Memory_Free( cellPoints );
      }
   }
}
void MemoryPoolSuite_TestIllegalDeallocation( MemoryPoolSuiteData* data ) {
   Plane*      p = NULL;
   int         i = 0;
   Bool        passed = False;
   int         objCounter = 0;
   int*        junkRefs[CACHE_SIZE];
   int         testData[CACHE_SIZE];

   for( i=0; i<CACHE_SIZE; i++ ){
      p = NULL;
      p = MemoryPool_NewObject( Plane, data->pool );
      objCounter++;
      data->planeRefs[i] = p;
   }

   passed = True;
   for( i=0; i<CACHE_SIZE; i++ ){
      junkRefs[i] = &testData[i];
   }

   for( i=0; i<CACHE_SIZE/4; i++ ){
      junkRefs[i] = (int*)(junkRefs+i+1);
      pcu_check_true(False == MemoryPool_DeleteObject( data->pool, junkRefs[i] ));
   }

   pcu_check_true( data->pool->numInitialElements == CACHE_SIZE );
   pcu_check_true( data->pool->numElements == CACHE_SIZE );
   pcu_check_true( data->pool->numElementsFree == 0 );
   pcu_check_true( data->pool->numMemChunks == 1 );
}
void MemoryPoolSuite_TestDeallocation( MemoryPoolSuiteData* data ) {
   Plane*      p = NULL;
   int         i = 0;
   Bool        passed = False;
   int         objCounter = 0;

   passed = True;

   for( i=0; i<CACHE_SIZE; i++ ){
      p = NULL;
      p = MemoryPool_NewObject( Plane, data->pool );
      objCounter++;
      data->planeRefs[i] = p;
   }

   for( i=0; i<CACHE_SIZE; i++ ){
      if(False == MemoryPool_DeleteObject( data->pool, data->planeRefs[i] )){
         passed = False;
         break;
      }
   }
   pcu_check_true( passed );

   pcu_check_true( data->pool->numInitialElements == CACHE_SIZE );
   pcu_check_true( data->pool->numElements == 0 );
   pcu_check_true( data->pool->numElementsFree == 0 );
   pcu_check_true( data->pool->numMemChunks == 0 );
}
void IMapSuite_TestSetMaxSize( IMapSuiteData* data ) {
   IMap_SetMaxSize( data->iMap, 10 );
   pcu_check_true( data->iMap->maxSize == 10 );
   pcu_check_true( data->iMap->tblSize >= 10 );
   IMap_SetMaxSize( data->iMap, 20 );
   pcu_check_true( data->iMap->maxSize == 20 );
   pcu_check_true( data->iMap->tblSize >= 20 );
}
void ProgressSuite_TestSetPrefix( ProgressSuiteData* data ) {
   Progress_SetPrefix( data->prog, NULL );
   pcu_check_true( data->prog->preStr == NULL );
   Progress_SetPrefix( data->prog, "foo" );
   pcu_check_streq( data->prog->preStr, "foo" );
   Progress_SetPrefix( data->prog, NULL );
   pcu_check_true( data->prog->preStr == NULL );
}
void ProgressSuite_TestSetTitle( ProgressSuiteData* data ) {
   Progress_SetTitle( data->prog, NULL );
   pcu_check_true( data->prog->title == NULL );
   Progress_SetTitle( data->prog, "foo" );
   pcu_check_streq( data->prog->title, "foo" );
   Progress_SetTitle( data->prog, NULL );
   pcu_check_true( data->prog->title == NULL );
}
void STreeSuite_TestInsert( STreeSuiteData* data ) {
   int depth = 0, curDepth = 0;
   int i_i;

   for( i_i = 0; i_i < 15; i_i++ )
      STree_Insert( data->sTree, &i_i );
   pcu_check_true( STree_GetSize( data->sTree ) == 15 );
   pcu_check_true( (calcDepth( STree_GetRoot( data->sTree ), &curDepth, &depth), depth) == 4 );
}
void EscapedRoutineSuite_TestCompareParticles( EscapedRoutineSuiteData* data ) {
   unsigned pToRemoveList[3] = { 1, 4, 7 };

   /* This function is needed for sorting plists into order. Should just be based on value of ptrs, which
    *  implies position in particle array */
   pcu_check_true( _EscapedRoutine_CompareParticles( &pToRemoveList[0], &pToRemoveList[1] ) < 0 );
   pcu_check_true( _EscapedRoutine_CompareParticles( &pToRemoveList[2], &pToRemoveList[1] ) > 0 );
   pcu_check_true( _EscapedRoutine_CompareParticles( &pToRemoveList[1], &pToRemoveList[1] ) == 0 );
}
void ProgressSuite_TestSetRange( ProgressSuiteData* data ) {
   Progress_SetRange( data->prog, 5, 10 );
   pcu_check_true( data->prog->start == 5 );
   pcu_check_true( data->prog->end == 10 );
   Progress_SetPrefix( data->prog, "foo" );
   pcu_check_streq( data->prog->preStr, "foo" );
   Progress_SetPrefix( data->prog, NULL );
   pcu_check_true( data->prog->preStr == NULL );
}
void DVCWeightsSuite_TestInitialiseStructs2D( DVCWeightsSuiteData* data ) {
   unsigned int ii;   

   _DVCWeights_InitialiseStructs2D( &data->bchain2D, &data->pList2D, data->nump2D);

   for (ii = 0; ii < data->nump2D; ii++) {
      pcu_check_true( data->bchain2D[ii].new_claimed_cells_malloced == DVC_INC );
      pcu_check_true( data->bchain2D[ii].new_bound_cells_malloced == DVC_INC );
   }
}
void ProgressSuite_TestCalcStatus( ProgressSuiteData* data ) {
   int ii;

   Progress_SetRange( data->prog, 0, 100 );
   pcu_check_true( data->prog->perc == 0 );
   for( ii = 0; ii < 99; ii++ ) {
      Progress_Increment( data->prog );
      pcu_check_true( data->prog->perc == ii );
   }
}
void ListSuite_TestClear( ListSuiteData* data ) {
   Index idx;

   for( idx = 0; idx < NUM_ITEMS; idx++ ) {
      List_Append( data->list, &data->arrayData[idx] );
   }
   List_Clear( data->list );
   pcu_check_true( data->list->nItems == 0 );
   List_Clear( data->list );
   pcu_check_true( data->list->nItems == 0 );
}
void IArraySuite_TestSet( IArraySuiteData* data ) {
   const int* ptr;
   int i_i;

   IArray_Set( data->iArray, NUM_ITEMS, data->arrayData );
   pcu_check_true( IArray_GetSize( data->iArray ) == NUM_ITEMS );
   pcu_check_true( (ptr = IArray_GetPtr( data->iArray )) != 0 );
   for( i_i = 0; i_i < NUM_ITEMS; i_i++ ) {
      pcu_check_true( ptr[i_i] == i_i );
   }
}
void DVCWeightsSuite_TestResetGrid2D( DVCWeightsSuiteData* data ) {
   unsigned int   i;
   
   _DVCWeights_ConstructGrid2D(&data->cells2D,data->numy,data->numx, BBXMIN,BBYMIN,BBXMAX,BBYMAX);
   _DVCWeights_ResetGrid2D(&data->cells2D,data->numx*data->numy);

   for ( i = 0; i < data->numx*data->numy; i++) {
      pcu_check_true( data->cells2D[i].p == -1 );
      pcu_check_true( data->cells2D[i].done == 0 );
   }
}
void STreeSuite_TestHas( STreeSuiteData* data ) {
   int i_i;

   for( i_i = 0; i_i < 15; i_i++ )
      STree_Insert( data->sTree, &i_i );
   for( i_i = 0; i_i < 15; i_i++ ) {
      pcu_check_true( STree_Has( data->sTree, &i_i ) );
   }
   for( i_i = 15; i_i < 30; i_i++ ) {
      pcu_check_true( !STree_Has( data->sTree, &i_i ) );
   }
}
void ListSuite_TestPrepend( ListSuiteData* data ) {
   Index idx;

   for( idx = 0; idx < NUM_ITEMS; idx++ ) {
      List_Prepend( data->list, &data->arrayData[idx] );
   }

   pcu_check_true( data->list->nItems == NUM_ITEMS );
   for( idx = 0; idx < NUM_ITEMS; idx++ ) {
      pcu_check_true( *(int*)List_GetItem( data->list, idx ) == ((NUM_ITEMS-1) - idx) );
   }
}
void IMapSuite_TestInsert( IMapSuiteData* data ) {
   int i_i;

   IMap_SetMaxSize( data->iMap, 10 );
   for( i_i = 0; i_i < 20; i_i += 2 ) {
      IMap_Insert( data->iMap, i_i, i_i + 100 );
   }
   pcu_check_assert( IMap_Insert( data->iMap, 0, 100 ) );
   pcu_check_true( IMap_GetSize( data->iMap ) == 10 );
   for( i_i = 0; i_i < 20; i_i += 2 ) {
      pcu_check_true( IMap_Has( data->iMap, i_i ) );
   }
}
void DVCWeightsSuite_TestCreateVoronoi2D( DVCWeightsSuiteData* data ) {
   int i;

   _DVCWeights_ConstructGrid2D(&data->cells2D,data->numy,data->numx, BBXMIN,BBYMIN,BBXMAX,BBYMAX);
   _DVCWeights_InitialiseStructs2D( &data->bchain2D, &data->pList2D, data->nump2D);

   _DVCWeightsSuite_InitialiseParticleCoords2D( data );
   _DVCWeights_CreateVoronoi2D( &data->bchain2D, &data->pList2D, &data->cells2D, data->dx, data->dy,
      data->nump2D, data->numx, data->numy, BBXMIN, BBXMAX, BBYMIN, BBYMAX);
   
   /* data->bchain2D changes */
   for (i = 0; i < data->nump2D; i++) {
      //pcu_check_true( data->bchain2D[i].index == (data->nump2D-1) );//This value doesn't matter at the moment: also nump2D-1 is the wrong number anyway
      pcu_check_true( data->bchain2D[i].sizeofboundary == 0 );
      pcu_check_true( data->bchain2D[i].numclaimed == 0 );
      pcu_check_true( data->bchain2D[i].totalclaimed == 1 );
      pcu_check_true( data->bchain2D[i].new_bound_cells_malloced == DVC_INC );
      pcu_check_true( data->bchain2D[i].new_claimed_cells_malloced == DVC_INC );
      pcu_check_true( data->bchain2D[i].done == 0 );
   }
   /* particle values */
   for (i = 0; i < data->nump2D; i++) {
      pcu_check_true( (data->pList2D[i].cx == 0) && (data->pList2D[i].cy == 0) );
      pcu_check_true( data->pList2D[i].w == 0 );
   }
}
void MaxHeapSuite_TestCreationExtraction( MaxHeapSuiteData* data ) {
   Index    ii=0;

   /* These initial totals due to set up above */
   pcu_check_true( data->heap->numHeapElements == NUM_INITIAL_DATA );
   pcu_check_true( data->heap->numArrayElements == NUM_INITIAL_DATA );

   for( ii=0; ii<NUM_INITIAL_DATA; ii++ ){
      /* Since we are always extracting the max, expect the order to be reversed */
      pcu_check_true( *(int*)MaxHeap_Extract( data->heap ) == data->dataArray[(NUM_INITIAL_DATA-1)-ii] );
   }

   pcu_check_true( data->heap->numHeapElements == 0 );
   pcu_check_true( data->heap->numArrayElements == NUM_INITIAL_DATA );
}
void DictionarySuite_TestCopyCompare( DictionarySuiteData* data ) {
   Index                    ii=0, jj=0;
   Dictionary_Entry_Value*  copiedDev;
   
   for( ii = 0; ii < data->dict->count; ii++ ) {
      copiedDev = Dictionary_Entry_Value_Copy( data->testDD->testValues[ii], True );
      pcu_check_true( Dictionary_Entry_Value_Compare( data->testDD->testValues[ii], copiedDev ) ); 
      Dictionary_Entry_Value_Delete( copiedDev );

      for( jj = 0; jj < data->dict->count; jj++ ) {
         if ( ii == jj ) continue;
         pcu_check_true( False == Dictionary_Entry_Value_Compare( data->testDD->testValues[ii], data->testDD->testValues[jj] ) ); 
      }
   }
}
void EscapedRoutineSuite_TestInitialiseParticleList( EscapedRoutineSuiteData* data ) {
   Particle_Index pToRemove_I = 0;
   
   /* Fill the list with some initial random data */
   for ( pToRemove_I = 0; pToRemove_I < data->escRoutine->particlesToRemoveAlloced; pToRemove_I++ ) {
      data->escRoutine->particlesToRemoveList[pToRemove_I] = pToRemove_I*2;
   }

   EscapedRoutine_InitialiseParticleList( data->escRoutine );

   pcu_check_true( data->escRoutine->particlesToRemoveCount == 0 );
   for ( pToRemove_I = 0; pToRemove_I < data->escRoutine->particlesToRemoveAlloced; pToRemove_I++ ) {
      pcu_check_true( 0 == data->escRoutine->particlesToRemoveList[pToRemove_I] );
   }
}
void ListSuite_TestExists( ListSuiteData* data ) {
   Index idx;
   int   inArray=5;
   int   notInArray=34352;
 
   for( idx = 0; idx < NUM_ITEMS; idx++ ) {
      List_Append( data->list, &data->arrayData[idx] );
   }

   for( idx = 0; idx < NUM_ITEMS; idx++ ) {
      pcu_check_true( List_Exists( data->list, &data->arrayData[idx] ) == True );
   }
   pcu_check_true( List_Exists( data->list, &inArray ) == True );
   pcu_check_true( List_Exists( data->list, &notInArray ) == False );
}
/* Test the Get and Set of a vector double....................................................................... */
void VariableSuite_TestGetValueAtDouble( VariableSuiteData* data ) {
    Index                   ii;
    double tmp;
    Variable*      var = Variable_Register_GetByName( data->vr, "velocity" );

    /* Fill the velocity array with a known pattern of kinda random (bit filling) numbers. */
    for( ii = 0; ii < data->aSize[1]; ii++ ) {
        int         d;

        for( d = 0; d < 3; d++ ) {
            data->velocity[ii][d] = 1.0f / ((data->aSize[1]*3)+2) * (ii*3+d+1);
        }
    }

    /* Check that Variable_GetPtrDouble on the velocity Variable returns the right numbers */
    for( ii = 0; ii < data->aSize[1]; ii++ ) {
        int         d;

        for( d = 0; d < 3; d++ ) {
            tmp = 1.0f / ((data->aSize[1]*3)+2) * (ii*3+d+1);

            pcu_check_true( fabs(Variable_GetValueAtDouble(var, ii, d ) - tmp) < 1e-12);
        }
    }
}
void DictionarySuite_TestSet( DictionarySuiteData* data ) {
   Dictionary_Entry_Value* currValue;
   Dictionary_Entry_Value* listValue;
   double                  newVal1 = 34.3, newVal2 = 38.9;
   Index                   ii=0;

   DictionarySuite_PopulateDictWithTestValues( data->dict, data->testDD );

   listValue = Dictionary_Get( data->dict, (Dictionary_Entry_Key)"test_list" );
   /* getting dictionary out of a list */
   currValue = Dictionary_Entry_Value_GetFirstElement( listValue  );
   /* do something to this value */
   Dictionary_Entry_Value_SetFromDouble( currValue, newVal1 );
   currValue = currValue->next;
   /* do something to this value */
   Dictionary_Entry_Value_SetFromDouble( currValue, newVal2 );
   
   pcu_check_true( 5 == Dictionary_Entry_Value_GetCount( listValue ) );
   currValue = Dictionary_Entry_Value_GetFirstElement( listValue );
   pcu_check_le( fabs(newVal1 - Dictionary_Entry_Value_AsDouble( currValue )), 0.01 );
   currValue = currValue->next;
   pcu_check_le( fabs(newVal2 - Dictionary_Entry_Value_AsDouble( currValue )), 0.01 );
   currValue = currValue->next;
   for ( ii=2; ii<data->testDD->testListCount; ii++ ) {
      pcu_check_le( fabs(data->testDD->testList[ii]
         - Dictionary_Entry_Value_AsDouble( currValue )), 0.01 );
      currValue = currValue->next;
   }
}
void compareAgainstReferenceSolution(PICelleratorContext* context, Stream* stream, double mean, double standardDeviation, char* expFile) {
   double meanTolerance, stdDevTolerance;
   double expectedMean, expectedStdDev;
   char   expectedFile[PCU_PATH_MAX];
   FILE*  expectedfp;

   pcu_filename_expected( expFile, expectedFile );
   expectedfp = fopen( expectedFile, "r" );

   fscanf( expectedfp, "%lf %lf", &meanTolerance, &expectedMean );
   pcu_check_true( fabs( expectedMean - mean ) < meanTolerance );

   fscanf( expectedfp, "%lf %lf", &stdDevTolerance, &expectedStdDev );
   pcu_check_true( fabs( expectedStdDev - standardDeviation ) < stdDevTolerance );
   
   fclose( expectedfp );
}
/* Add a set of values to a dictionary, and check they were added as desired
 * using the Compare functions.
 */
void DictionarySuite_TestAddEmpty( DictionarySuiteData* data ) {
   Dictionary_Index        ii;
   Dictionary_Entry*       entryPtr;

   DictionarySuite_PopulateDictWithTestValues( data->dict, data->testDD );

   pcu_check_true( data->testDD->testEntriesCount == data->dict->count );

   for( ii = 0; ii < data->dict->count; ii++ ) {
      entryPtr = data->dict->entryPtr[ii];
      pcu_check_true( Dictionary_Entry_Compare( entryPtr, data->testDD->testKeys[ii] ) ); 
      pcu_check_true( Dictionary_Entry_Value_Compare( entryPtr->value, data->testDD->testValues[ii] ) ); 
   }

   Dictionary_Empty( data->dict );
   pcu_check_true( 0 == data->dict->count );
}
void EscapedRoutineSuite_TestSetParticleToRemove( EscapedRoutineSuiteData* data ) {
   Particle_Index lParticle_I = 0;

   pcu_check_true( data->escRoutine->particlesToRemoveCount == 0 );
   pcu_check_true( data->escRoutine->particlesToRemoveAlloced == 10*data->escRoutine->particlesToRemoveDelta );

   /* Do it enough times that pToRemoveList has to be expanded at least once */
   for ( lParticle_I = 0; lParticle_I < data->swarm->particleLocalCount; lParticle_I++ ) {
      EscapedRoutine_SetParticleToRemove( data->escRoutine, data->swarm, lParticle_I );
   }
   
   pcu_check_true( data->escRoutine->particlesToRemoveCount == data->swarm->particleLocalCount );
   pcu_check_true( data->escRoutine->particlesToRemoveAlloced >= data->escRoutine->particlesToRemoveCount );
   for ( lParticle_I = 0; lParticle_I < data->swarm->particleLocalCount; lParticle_I++ ) {
      pcu_check_true( data->escRoutine->particlesToRemoveList[lParticle_I] == lParticle_I );
   }
}