<commit_before>/*
 * PyClaw.cpp
 *
 *  Created on: Feb 18, 2012
 *      Author: kristof
 */

#include "peanoclaw/native/SWEKernel.h"

#include "peanoclaw/Patch.h"
#include "peanoclaw/Area.h"
#include "peanoclaw/interSubgridCommunication/DefaultTransfer.h"
#include "peanoclaw/native/SWE_WavePropagationBlock_patch.hh"

#include "tarch/multicore/MulticoreDefinitions.h"
#include "tarch/timing/Watch.h"
#include "tarch/parallel/Node.h"

tarch::logging::Log peanoclaw::native::SWEKernel::_log("peanoclaw::native::SWEKernel");

void peanoclaw::native::SWEKernel::transformWaterHeight(
  peanoclaw::Patch& subgrid,
  const Area&       area,
  bool              modifyUOld,
  bool              absoluteToAboveSeaFloor
) const {
  peanoclaw::grid::SubgridAccessor accessor = subgrid.getAccessor();
  double sign = absoluteToAboveSeaFloor ? -1 : +1;
  if(modifyUOld) {
    dfor(internalSubcellIndex, area._size) {
      tarch::la::Vector<DIMENSIONS,int> subcellIndex = internalSubcellIndex + area._offset;
      accessor.setValueUOld(
        subcellIndex,
        0,
        accessor.getValueUOld(subcellIndex, 0) + sign * accessor.getParameterWithGhostlayer(subcellIndex, 0)
      );
    }
  } else {
    dfor(internalSubcellIndex, area._size) {
      tarch::la::Vector<DIMENSIONS,int> subcellIndex = internalSubcellIndex + area._offset;
      accessor.setValueUNew(
        subcellIndex,
        0,
        accessor.getValueUNew(subcellIndex, 0) + sign * accessor.getParameterWithGhostlayer(subcellIndex, 0)
      );
    }
  }
}

void peanoclaw::native::SWEKernel::advanceBlockInTime(
  SWE_WavePropagationBlock_patch& block,
  peanoclaw::Patch& subgrid,
  double maximumTimestepSize
) {
  block.setArrays(
        subgrid,
        reinterpret_cast<float*>(subgrid.getUOldWithGhostlayerArray(0)),
        reinterpret_cast<float*>(subgrid.getUOldWithGhostlayerArray(1)),
        reinterpret_cast<float*>(subgrid.getUOldWithGhostlayerArray(2)),
        reinterpret_cast<float*>(subgrid.getParameterWithoutGhostlayerArray(0))
      );

  block.computeNumericalFluxes();

  double dt = fmin(block.getMaxTimestep(), maximumTimestepSize);
  double estimatedNextTimestepSize = block.getMaxTimestep();

  block.updateUnknowns(dt);

  peanoclaw::interSubgridCommunication::DefaultTransfer transfer;
  transfer.swapUNewAndUOld(subgrid);

  assertion4(
      tarch::la::greater(subgrid.getTimeIntervals().getTimestepSize(), 0.0)
      || tarch::la::greater(estimatedNextTimestepSize, 0.0)
      || tarch::la::equals(maximumTimestepSize, 0.0)
      || tarch::la::equals(subgrid.getTimeIntervals().getEstimatedNextTimestepSize(), 0.0),
      subgrid, maximumTimestepSize, estimatedNextTimestepSize, subgrid.toStringUNew());
  assertion(subgrid.getTimeIntervals().getTimestepSize() < std::numeric_limits<double>::infinity());

  if (tarch::la::greater(dt, 0.0)) {
    subgrid.getTimeIntervals().advanceInTime();
    subgrid.getTimeIntervals().setTimestepSize(dt);
  }
  subgrid.getTimeIntervals().setEstimatedNextTimestepSize(estimatedNextTimestepSize);
}

peanoclaw::native::SWEKernel::SWEKernel(
  peanoclaw::native::scenarios::SWEScenario& scenario,
  peanoclaw::interSubgridCommunication::DefaultTransfer* transfer,
  peanoclaw::interSubgridCommunication::Interpolation*   interpolation,
  peanoclaw::interSubgridCommunication::Restriction*     restriction,
  peanoclaw::interSubgridCommunication::FluxCorrection*  fluxCorrection
) : Numerics(transfer, interpolation, restriction, fluxCorrection),
_totalSolverCallbackTime(0.0),
_scenario(scenario),
_cachedSubdivisionFactor(-1),
_cachedGhostlayerWidth(-1),
_cachedBlock(0)
{
  //import_array();
}

peanoclaw::native::SWEKernel::~SWEKernel()
{
}

void peanoclaw::native::SWEKernel::initializePatch(
  Patch& patch
) {
  logTraceIn( "initializePatch(...)");

  _scenario.initializePatch(patch);

  logTraceOutWith1Argument( "initializePatch(...)", demandedMeshWidth);
}

void peanoclaw::native::SWEKernel::update(Patch& subgrid) {
  _scenario.update(subgrid);
}

void peanoclaw::native::SWEKernel::solveTimestep(Patch& patch, double maximumTimestepSize, bool useDimensionalSplitting) {
  logTraceInWith2Arguments( "solveTimestep(...)", maximumTimestepSize, useDimensionalSplitting);

  assertion2(tarch::la::greater(maximumTimestepSize, 0.0), "Timestepsize == 0 should be checked outside.", patch.getTimeIntervals().getMinimalNeighborTimeConstraint());

  tarch::timing::Watch solverWatch("", "", false);
  solverWatch.startTimer();

  #ifdef SharedMemoryParallelisation
  SWE_WavePropagationBlock_patch block(patch);
  advanceBlockInTime(
    block,
    patch,
    maximumTimestepSize
  );
  #else
  if(
    _cachedSubdivisionFactor != patch.getSubdivisionFactor()
    || _cachedGhostlayerWidth != patch.getGhostlayerWidth()
  ) {
    //SWE_WavePropagationBlock_patch swe(patch);
    _cachedBlock = std::auto_ptr<SWE_WavePropagationBlock_patch>(new SWE_WavePropagationBlock_patch(patch));
    _cachedSubdivisionFactor = patch.getSubdivisionFactor();
    _cachedGhostlayerWidth = patch.getGhostlayerWidth();
  }

  advanceBlockInTime(
    *_cachedBlock,
    patch,
    maximumTimestepSize
  );
  #endif

  solverWatch.stopTimer();
  _totalSolverCallbackTime += solverWatch.getCalendarTime();

  logTraceOut( "solveTimestep(...)");
}

tarch::la::Vector<DIMENSIONS, double> peanoclaw::native::SWEKernel::getDemandedMeshWidth(Patch& patch, bool isInitializing) {
  return _scenario.computeDemandedMeshWidth(patch, isInitializing);
}

void peanoclaw::native::SWEKernel::addPatchToSolution(Patch& patch) {
}

void peanoclaw::native::SWEKernel::fillBoundaryLayer(Patch& patch, int dimension, bool setUpper) {
  logTraceInWith3Arguments("fillBoundaryLayerInPyClaw", patch, dimension, setUpper);

  logDebug("fillBoundaryLayerInPyClaw", "Setting left boundary for " << patch.getPosition() << ", dim=" << dimension << ", setUpper=" << setUpper);

   //std::cout << "------ setUpper " << setUpper << " dimension " << dimension << std::endl;
   //std::cout << patch << std::endl;
   //std::cout << "++++++" << std::endl;
   //std::cout << patch.toStringUOldWithGhostLayer() << std::endl;
   //std::cout << "||||||" << std::endl;

   // implement a wall boundary
    tarch::la::Vector<DIMENSIONS, int> src_subcellIndex;
    tarch::la::Vector<DIMENSIONS, int> dest_subcellIndex;

    peanoclaw::grid::SubgridAccessor& accessor = patch.getAccessor();

    if (dimension == 0) {
        for (int yi = -1; yi < patch.getSubdivisionFactor()(1)+1; yi++) {
            int xi = setUpper ? patch.getSubdivisionFactor()(0) : -1;
            src_subcellIndex(0) = xi;
            src_subcellIndex(1) = yi;
            src_subcellIndex(dimension) += setUpper ? -1 : +1;

            dest_subcellIndex(0) = xi;
            dest_subcellIndex(1) = yi;

            for (int unknown=0; unknown < patch.getUnknownsPerSubcell(); unknown++) {
                double q = accessor.getValueUOld(src_subcellIndex, unknown);

                if (unknown == dimension + 1) {
                  accessor.setValueUOld(dest_subcellIndex, unknown, -q);
                } else {
                  accessor.setValueUOld(dest_subcellIndex, unknown, q);
                }
            }
        }

    } else {
        for (int xi = -1; xi < patch.getSubdivisionFactor()(0)+1; xi++) {
            int yi = setUpper ? patch.getSubdivisionFactor()(1) : -1;
            src_subcellIndex(0) = xi;
            src_subcellIndex(1) = yi;
            src_subcellIndex(dimension) += setUpper ? -1 : +1;

            dest_subcellIndex(0) = xi;
            dest_subcellIndex(1) = yi;

            for (int unknown=0; unknown < patch.getUnknownsPerSubcell(); unknown++) {
                double q = accessor.getValueUOld(src_subcellIndex, unknown);

                if (unknown == dimension + 1) {
                  accessor.setValueUOld(dest_subcellIndex, unknown, -q);
                } else {
                  accessor.setValueUOld(dest_subcellIndex, unknown, q);
                }
            }
        }
    }

      logTraceOut("fillBoundaryLayerInPyClaw");
    }

void peanoclaw::native::SWEKernel::interpolateSolution (
  const tarch::la::Vector<DIMENSIONS, int>& destinationSize,
  const tarch::la::Vector<DIMENSIONS, int>& destinationOffset,
  peanoclaw::Patch& source,
  peanoclaw::Patch& destination,
  bool interpolateToUOld,
  bool interpolateToCurrentTime,
  bool useTimeUNewOrTimeUOld
) const {
  peanoclaw::grid::SubgridAccessor sourceAccessor = source.getAccessor();
  peanoclaw::grid::SubgridAccessor destinationAccessor = destination.getAccessor();
  tarch::la::Vector<DIMENSIONS,int> sourceSubdivisionFactor = source.getSubdivisionFactor();

  Area destinationArea(destinationOffset, destinationSize);
  Area sourceArea = destinationArea.mapToPatch(destination, source);

  //Increase sourceArea by one cell in each direction.
  for(int d = 0; d < DIMENSIONS; d++) {
    if(sourceArea._offset[d] > 0) {
      sourceArea._offset[d] = sourceArea._offset[d]-1;
      sourceArea._size[d] = std::min(sourceSubdivisionFactor[d], sourceArea._size[d] + 2);
    } else {
      sourceArea._size[d] = std::min(sourceSubdivisionFactor[d], sourceArea._size[d] + 1);
    }
  }

  //Source: Water Height above Sea Floor -> Absolute Water Height
  transformWaterHeight(source, sourceArea, true, false); //UOld
  transformWaterHeight(source, sourceArea, false, false); // UNew

  //Interpolate
  Numerics::interpolateSolution (
    destinationSize,
    destinationOffset,
    source,
    destination,
    interpolateToUOld,
    interpolateToCurrentTime,
    useTimeUNewOrTimeUOld
  );

  //Source: Absolute Water Height -> Water Height above Sea Floor
  transformWaterHeight(source, sourceArea, true, true); //UOld
  transformWaterHeight(source, sourceArea, false, true); // UNew

  //Destination: Absolute Water Height -> Water Height above Sea Floor
  transformWaterHeight(destination, destinationArea, interpolateToUOld, true);
}

void peanoclaw::native::SWEKernel::restrict (
  peanoclaw::Patch& source,
  peanoclaw::Patch& destination,
  bool              restrictOnlyOverlappedAreas
) const {

  Area sourceArea(tarch::la::Vector<DIMENSIONS,int>(0), source.getSubdivisionFactor());

  transformWaterHeight(source, sourceArea, true, false); //UOld
  transformWaterHeight(source, sourceArea, false, false); //UNew

  Numerics::restrict(
    source,
    destination,
    restrictOnlyOverlappedAreas
  );

  transformWaterHeight(source, sourceArea, true, true); //UOld
  transformWaterHeight(source, sourceArea, false, true); //UNew
}

void peanoclaw::native::SWEKernel::postProcessRestriction(
  peanoclaw::Patch& destination,
  bool              restrictOnlyOverlappedAreas
) const {
  Area destinationArea(tarch::la::Vector<DIMENSIONS,int>(0), destination.getSubdivisionFactor());
  transformWaterHeight(destination, destinationArea, true, true); //UOld
  transformWaterHeight(destination, destinationArea, false, true); //UNew
}

<commit_msg>fixed<commit_after>/*
 * PyClaw.cpp
 *
 *  Created on: Feb 18, 2012
 *      Author: kristof
 */

#include "peanoclaw/native/SWEKernel.h"

#include "peanoclaw/Patch.h"
#include "peanoclaw/Area.h"
#include "peanoclaw/interSubgridCommunication/DefaultTransfer.h"
#include "peanoclaw/native/SWE_WavePropagationBlock_patch.hh"

#include "tarch/multicore/MulticoreDefinitions.h"
#include "tarch/timing/Watch.h"
#include "tarch/parallel/Node.h"

tarch::logging::Log peanoclaw::native::SWEKernel::_log("peanoclaw::native::SWEKernel");

void peanoclaw::native::SWEKernel::transformWaterHeight(
  peanoclaw::Patch& subgrid,
  const Area&       area,
  bool              modifyUOld,
  bool              absoluteToAboveSeaFloor
) const {
  peanoclaw::grid::SubgridAccessor accessor = subgrid.getAccessor();
  double sign = absoluteToAboveSeaFloor ? -1 : +1;
  if(modifyUOld) {
    dfor(internalSubcellIndex, area._size) {
      tarch::la::Vector<DIMENSIONS,int> subcellIndex = internalSubcellIndex + area._offset;
      accessor.setValueUOld(
        subcellIndex,
        0,
        accessor.getValueUOld(subcellIndex, 0) + sign * accessor.getParameterWithGhostlayer(subcellIndex, 0)
      );
    }
  } else {
    dfor(internalSubcellIndex, area._size) {
      tarch::la::Vector<DIMENSIONS,int> subcellIndex = internalSubcellIndex + area._offset;
      accessor.setValueUNew(
        subcellIndex,
        0,
        accessor.getValueUNew(subcellIndex, 0) + sign * accessor.getParameterWithGhostlayer(subcellIndex, 0)
      );
    }
  }
}

void peanoclaw::native::SWEKernel::advanceBlockInTime(
  SWE_WavePropagationBlock_patch& block,
  peanoclaw::Patch& subgrid,
  double maximumTimestepSize
) {
  block.setArrays(
        subgrid,
        reinterpret_cast<float*>(subgrid.getUOldWithGhostlayerArray(0)),
        reinterpret_cast<float*>(subgrid.getUOldWithGhostlayerArray(1)),
        reinterpret_cast<float*>(subgrid.getUOldWithGhostlayerArray(2)),
        reinterpret_cast<float*>(subgrid.getParameterWithoutGhostlayerArray(0))
      );

  block.computeNumericalFluxes();

  double dt = fmin(block.getMaxTimestep(), maximumTimestepSize);
  double estimatedNextTimestepSize = block.getMaxTimestep();

  block.updateUnknowns(dt);

  peanoclaw::interSubgridCommunication::DefaultTransfer transfer;
  transfer.swapUNewAndUOld(subgrid);

  assertion4(
      tarch::la::greater(subgrid.getTimeIntervals().getTimestepSize(), 0.0)
      || tarch::la::greater(estimatedNextTimestepSize, 0.0)
      || tarch::la::equals(maximumTimestepSize, 0.0)
      || tarch::la::equals(subgrid.getTimeIntervals().getEstimatedNextTimestepSize(), 0.0),
      subgrid, maximumTimestepSize, estimatedNextTimestepSize, subgrid.toStringUNew());
  assertion(subgrid.getTimeIntervals().getTimestepSize() < std::numeric_limits<double>::infinity());

  if (tarch::la::greater(dt, 0.0)) {
    subgrid.getTimeIntervals().advanceInTime();
    subgrid.getTimeIntervals().setTimestepSize(dt);
  }
  subgrid.getTimeIntervals().setEstimatedNextTimestepSize(estimatedNextTimestepSize);
}

peanoclaw::native::SWEKernel::SWEKernel(
  peanoclaw::native::scenarios::SWEScenario& scenario,
  peanoclaw::interSubgridCommunication::DefaultTransfer* transfer,
  peanoclaw::interSubgridCommunication::Interpolation*   interpolation,
  peanoclaw::interSubgridCommunication::Restriction*     restriction,
  peanoclaw::interSubgridCommunication::FluxCorrection*  fluxCorrection
) : Numerics(transfer, interpolation, restriction, fluxCorrection),
_totalSolverCallbackTime(0.0),
_scenario(scenario),
_cachedSubdivisionFactor(-1),
_cachedGhostlayerWidth(-1),
_cachedBlock(0)
{
  //import_array();
}

peanoclaw::native::SWEKernel::~SWEKernel()
{
}

void peanoclaw::native::SWEKernel::initializePatch(
  Patch& patch
) {
  logTraceIn( "initializePatch(...)");

  _scenario.initializePatch(patch);

  logTraceOutWith1Argument( "initializePatch(...)", demandedMeshWidth);
}

void peanoclaw::native::SWEKernel::update(Patch& subgrid) {
  _scenario.update(subgrid);
}

void peanoclaw::native::SWEKernel::solveTimestep(Patch& patch, double maximumTimestepSize, bool useDimensionalSplitting) {
  logTraceInWith2Arguments( "solveTimestep(...)", maximumTimestepSize, useDimensionalSplitting);

  assertion2(tarch::la::greater(maximumTimestepSize, 0.0), "Timestepsize == 0 should be checked outside.", patch.getTimeIntervals().getMinimalNeighborTimeConstraint());

  tarch::timing::Watch solverWatch("", "", false);
  solverWatch.startTimer();

  #ifdef SharedMemoryParallelisation
  SWE_WavePropagationBlock_patch block(patch);
  advanceBlockInTime(
    block,
    patch,
    maximumTimestepSize
  );
  #else
  if(
    _cachedSubdivisionFactor != patch.getSubdivisionFactor()
    || _cachedGhostlayerWidth != patch.getGhostlayerWidth()
  ) {
    //SWE_WavePropagationBlock_patch swe(patch);
    _cachedBlock = std::auto_ptr<SWE_WavePropagationBlock_patch>(new SWE_WavePropagationBlock_patch(patch));
    _cachedSubdivisionFactor = patch.getSubdivisionFactor();
    _cachedGhostlayerWidth = patch.getGhostlayerWidth();
  }

  advanceBlockInTime(
    *_cachedBlock,
    patch,
    maximumTimestepSize
  );
  #endif

  solverWatch.stopTimer();
  _totalSolverCallbackTime += solverWatch.getCalendarTime();

  logTraceOut( "solveTimestep(...)");
}

tarch::la::Vector<DIMENSIONS, double> peanoclaw::native::SWEKernel::getDemandedMeshWidth(Patch& patch, bool isInitializing) {
  return _scenario.computeDemandedMeshWidth(patch, isInitializing);
}

void peanoclaw::native::SWEKernel::addPatchToSolution(Patch& patch) {
}

void peanoclaw::native::SWEKernel::fillBoundaryLayer(Patch& patch, int dimension, bool setUpper) {
  logTraceInWith3Arguments("fillBoundaryLayerInPyClaw", patch, dimension, setUpper);

  logDebug("fillBoundaryLayerInPyClaw", "Setting left boundary for " << patch.getPosition() << ", dim=" << dimension << ", setUpper=" << setUpper);

   //std::cout << "------ setUpper " << setUpper << " dimension " << dimension << std::endl;
   //std::cout << patch << std::endl;
   //std::cout << "++++++" << std::endl;
   //std::cout << patch.toStringUOldWithGhostLayer() << std::endl;
   //std::cout << "||||||" << std::endl;

   // implement a wall boundary
    tarch::la::Vector<DIMENSIONS, int> src_subcellIndex;
    tarch::la::Vector<DIMENSIONS, int> dest_subcellIndex;

    peanoclaw::grid::SubgridAccessor& accessor = patch.getAccessor();

    if (dimension == 0) {
        for (int yi = -1; yi < patch.getSubdivisionFactor()(1)+1; yi++) {
            int xi = setUpper ? patch.getSubdivisionFactor()(0) : -1;
            src_subcellIndex(0) = xi;
            src_subcellIndex(1) = yi;
            src_subcellIndex(dimension) += setUpper ? -1 : +1;

            dest_subcellIndex(0) = xi;
            dest_subcellIndex(1) = yi;

            for (int unknown=0; unknown < patch.getUnknownsPerSubcell(); unknown++) {
                double q = accessor.getValueUOld(src_subcellIndex, unknown);

                if (unknown == dimension + 1) {
                  accessor.setValueUOld(dest_subcellIndex, unknown, -q);
                } else {
                  accessor.setValueUOld(dest_subcellIndex, unknown, q);
                }
            }
        }

    } else {
        for (int xi = -1; xi < patch.getSubdivisionFactor()(0)+1; xi++) {
            int yi = setUpper ? patch.getSubdivisionFactor()(1) : -1;
            src_subcellIndex(0) = xi;
            src_subcellIndex(1) = yi;
            src_subcellIndex(dimension) += setUpper ? -1 : +1;

            dest_subcellIndex(0) = xi;
            dest_subcellIndex(1) = yi;

            for (int unknown=0; unknown < patch.getUnknownsPerSubcell(); unknown++) {
                double q = accessor.getValueUOld(src_subcellIndex, unknown);

                if (unknown == dimension + 1) {
                  accessor.setValueUOld(dest_subcellIndex, unknown, -q);
                } else {
                  accessor.setValueUOld(dest_subcellIndex, unknown, q);
                }
            }
        }
    }

      logTraceOut("fillBoundaryLayerInPyClaw");
    }

void peanoclaw::native::SWEKernel::interpolateSolution (
  const tarch::la::Vector<DIMENSIONS, int>& destinationSize,
  const tarch::la::Vector<DIMENSIONS, int>& destinationOffset,
  peanoclaw::Patch& source,
  peanoclaw::Patch& destination,
  bool interpolateToUOld,
  bool interpolateToCurrentTime,
  bool useTimeUNewOrTimeUOld
) const {
  peanoclaw::grid::SubgridAccessor sourceAccessor = source.getAccessor();
  peanoclaw::grid::SubgridAccessor destinationAccessor = destination.getAccessor();
  tarch::la::Vector<DIMENSIONS,int> sourceSubdivisionFactor = source.getSubdivisionFactor();

  Area destinationArea(destinationOffset, destinationSize);
  Area sourceArea = destinationArea.mapToPatch(destination, source);

  //Increase sourceArea by one cell in each direction.
  for(int d = 0; d < DIMENSIONS; d++) {
    if(sourceArea._offset[d] > 0) {
      sourceArea._offset[d] = sourceArea._offset[d]-1;
      sourceArea._size[d] = std::min(sourceSubdivisionFactor[d], sourceArea._size[d] + 2);
    } else {
      sourceArea._size[d] = std::min(sourceSubdivisionFactor[d], sourceArea._size[d] + 1);
    }
  }

  //Source: Water Height above Sea Floor -> Absolute Water Height
  transformWaterHeight(source, sourceArea, true, false); //UOld
  transformWaterHeight(source, sourceArea, false, false); // UNew

  //Interpolate
  Numerics::interpolateSolution (
    destinationSize,
    destinationOffset,
    source,
    destination,
    interpolateToUOld,
    interpolateToCurrentTime,
    useTimeUNewOrTimeUOld
  );

  //Source: Absolute Water Height -> Water Height above Sea Floor
  transformWaterHeight(source, sourceArea, true, true); //UOld
  transformWaterHeight(source, sourceArea, false, true); // UNew

  //Destination: Absolute Water Height -> Water Height above Sea Floor
  transformWaterHeight(destination, destinationArea, interpolateToUOld, true);
}

void peanoclaw::native::SWEKernel::restrictSolution (
  peanoclaw::Patch& source,
  peanoclaw::Patch& destination,
  bool              restrictOnlyOverlappedAreas
) const {

  Area sourceArea(tarch::la::Vector<DIMENSIONS,int>(0), source.getSubdivisionFactor());

  transformWaterHeight(source, sourceArea, true, false); //UOld
  transformWaterHeight(source, sourceArea, false, false); //UNew

  Numerics::restrictSolution(
    source,
    destination,
    restrictOnlyOverlappedAreas
  );

  transformWaterHeight(source, sourceArea, true, true); //UOld
  transformWaterHeight(source, sourceArea, false, true); //UNew
}

void peanoclaw::native::SWEKernel::postProcessRestriction(
  peanoclaw::Patch& destination,
  bool              restrictOnlyOverlappedAreas
) const {
  Area destinationArea(tarch::la::Vector<DIMENSIONS,int>(0), destination.getSubdivisionFactor());
  transformWaterHeight(destination, destinationArea, true, true); //UOld
  transformWaterHeight(destination, destinationArea, false, true); //UNew
}

<|endoftext|>


<commit_before>#include <cstddef>
#include <map>

#include "pegr/script/ScriptHelper.hpp"
#include "pegr/script/Script.hpp"
#include "pegr/logger/Logger.hpp"

namespace pegr {
namespace Test {

typedef Script::Regref_Guard RG;

//@Test Script Helper
void test_script_helper() {
    RG sandbox(Script::new_sandbox());
    RG table_fun(Script::load_lua_function("test/simple_table.lua", sandbox));

    Script::run_function(table_fun, 0, 1);

    lua_State* l = Script::get_lua_state();

    std::map<std::string, std::string> expected = {
        {"a", "apple"},
        {"b", "banana"},
        {"c", "cherry"}
    };

    std::map<std::string, std::string> got;

    bool success = true;
    auto body = [l, &got, &expected]() {
        std::size_t strlen;
        const char* strdata;

        lua_pushvalue(l, -2);
        lua_pushvalue(l, -2);
        strdata = lua_tolstring(l, -2, &strlen);
        std::string key(strdata, strlen);
        strdata = lua_tolstring(l, -1, &strlen);
        std::string val(strdata, strlen);

        got[key] = val;

        Logger::log()->verbose(1, "%v\t%v", key, val);

        lua_pop(l, 2);
    };

    Script::Helper::for_pairs(-1, [body, l]()->bool {
        body();
        return true;
    }, false);
    Script::Helper::for_pairs(-1, [body, l]()->bool {
        body();
        lua_pop(l, 1);
        return true;
    }, true);

    if (expected != got) {
        throw std::runtime_error("Resulting table does not match expectation.");
    }
}

}
}
<commit_msg>Fix table comparison<commit_after>#include <cstddef>
#include <sstream>
#include <map>

#include "pegr/script/ScriptHelper.hpp"
#include "pegr/script/Script.hpp"
#include "pegr/logger/Logger.hpp"

namespace pegr {
namespace Test {

typedef Script::Regref_Guard RG;

//@Test Script Helper
void test_script_helper() {
    RG sandbox(Script::new_sandbox());
    RG table_fun(Script::load_lua_function("test/simple_table.lua", sandbox));

    Script::run_function(table_fun, 0, 1);

    lua_State* l = Script::get_lua_state();

    std::map<std::string, std::string> expected = {
        {"a", "apple"},
        {"b", "banana"},
        {"c", "cherry"}
    };

    std::map<std::string, std::string> got;

    bool success = true;
    auto body = [l, &got, &expected]() {
        std::size_t strlen;
        const char* strdata;

        lua_pushvalue(l, -2);
        lua_pushvalue(l, -2);
        strdata = lua_tolstring(l, -2, &strlen);
        std::string key(strdata, strlen);
        strdata = lua_tolstring(l, -1, &strlen);
        std::string val(strdata, strlen);

        got[key] = val;

        Logger::log()->verbose(1, "%v\t%v", key, val);

        lua_pop(l, 2);
    };

    Script::Helper::for_pairs(-1, [body, l]()->bool {
        body();
        return true;
    }, false);
    Script::Helper::for_pairs(-1, [body, l]()->bool {
        body();
        lua_pop(l, 1);
        return true;
    }, true);

    for (auto key_value : expected) {
        auto iter = got.find(key_value.first);
        if (iter == got.end()) {
            std::stringstream ss;
            ss << "Resulting table missing key: ";
            ss << key_value.first;
            throw std::runtime_error(ss.str());
        }
        if (key_value.second != (*iter).second) {
            std::stringstream ss;
            ss << "Resulting table has wrong value for ";
            ss << key_value.first;
            ss << ": Expected: ";
            ss << key_value.second;
            ss << ": Got: ";
            ss << (*iter).second;
            throw std::runtime_error(ss.str());
        }
    }
}

}
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2014 Paul T. Bauman, Roy H. Stogner
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/elastic_membrane.h"

// GRINS
#include "grins_config.h"
#include "grins/assembly_context.h"
#include "grins/solid_mechanics_bc_handling.h"

// libMesh
#include "libmesh/getpot.h"
#include "libmesh/quadrature.h"
#include "libmesh/boundary_info.h"
#include "libmesh/fem_system.h"

namespace GRINS
{
  template<typename StressStrainLaw>
  ElasticMembrane<StressStrainLaw>::ElasticMembrane( const GRINS::PhysicsName& physics_name, const GetPot& input,
                                                     bool lambda_sq_coupled, bool lambda_sq_var )
    : ElasticMembraneBase(physics_name,input),
      _stress_strain_law(input),
      _h0( input("Physics/"+physics_name+"/h0", 1.0 ) ),
      _lambda_sq_coupled(lambda_sq_coupled),
      _lambda_sq_var(lambda_sq_var)
  {
    // Force the user to set h0
    if( !input.have_variable("Physics/"+physics_name+"/h0") )
      {
        std::cerr << "Error: Must specify initial thickness for "+physics_name << std::endl
                  << "       Input the option Physics/"+physics_name+"/h0" << std::endl;
        libmesh_error();
      }

    this->_bc_handler = new SolidMechanicsBCHandling( physics_name, input );

    return;
  }

  template<typename StressStrainLaw>
  ElasticMembrane<StressStrainLaw>::~ElasticMembrane()
  {
    return;
  }

  template<typename StressStrainLaw>
  void ElasticMembrane<StressStrainLaw>::element_time_derivative( bool compute_jacobian,
                                                                   AssemblyContext& context,
                                                                   CachedValues& /*cache*/ )
  {
    const unsigned int n_u_dofs = context.get_dof_indices(_disp_vars.u_var()).size();

    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(_disp_vars.u_var())->get_JxW();

    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
      context.get_element_fe(_disp_vars.u_var())->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(_disp_vars.u_var());
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(_disp_vars.v_var());
    libMesh::DenseSubVector<libMesh::Number> &Fw = context.get_elem_residual(_disp_vars.w_var());

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    const std::vector<libMesh::RealGradient>& dxdxi  = context.get_element_fe(_disp_vars.u_var())->get_dxyzdxi();
    const std::vector<libMesh::RealGradient>& dxdeta = context.get_element_fe(_disp_vars.u_var())->get_dxyzdeta();

    const std::vector<libMesh::Real>& dxidx  = context.get_element_fe(_disp_vars.u_var())->get_dxidx();
    const std::vector<libMesh::Real>& dxidy  = context.get_element_fe(_disp_vars.u_var())->get_dxidy();
    const std::vector<libMesh::Real>& dxidz  = context.get_element_fe(_disp_vars.u_var())->get_dxidz();

    const std::vector<libMesh::Real>& detadx  = context.get_element_fe(_disp_vars.u_var())->get_detadx();
    const std::vector<libMesh::Real>& detady  = context.get_element_fe(_disp_vars.u_var())->get_detady();
    const std::vector<libMesh::Real>& detadz  = context.get_element_fe(_disp_vars.u_var())->get_detadz();

    const unsigned int dim = 2; // The manifold dimension is always 2 for this physics

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::Gradient grad_u = context.interior_gradient(_disp_vars.u_var(), qp);
        libMesh::Gradient grad_v = context.interior_gradient(_disp_vars.v_var(), qp);
        libMesh::Gradient grad_w = context.interior_gradient(_disp_vars.w_var(), qp);

        libMesh::RealGradient grad_x( dxdxi[qp](0), dxdeta[qp](0) );
        libMesh::RealGradient grad_y( dxdxi[qp](1), dxdeta[qp](1) );
        libMesh::RealGradient grad_z( dxdxi[qp](2), dxdeta[qp](2) );

        libMesh::RealGradient dudxi( grad_u(0), grad_v(0), grad_w(0) );
        libMesh::RealGradient dudeta( grad_u(1), grad_v(1), grad_w(1) );

        libMesh::RealGradient dxi( dxidx[qp], dxidy[qp], dxidz[qp] );
        libMesh::RealGradient deta( detadx[qp], detady[qp], detadz[qp] );

        // Covariant metric tensor of reference configuration
        libMesh::TensorValue<libMesh::Real> a_cov( dxdxi[qp]*dxdxi[qp], dxdxi[qp]*dxdeta[qp], 0.0,
                                                   dxdeta[qp]*dxdxi[qp], dxdeta[qp]*dxdeta[qp] );

        // Covariant metric tensor of current configuration
        libMesh::TensorValue<libMesh::Real> A_cov( (dxdxi[qp] + dudxi)*(dxdxi[qp] + dudxi),
                                                   (dxdxi[qp] + dudxi)*(dxdeta[qp] + dudeta), 0.0,
                                                   (dxdeta[qp] + dudeta)*(dxdxi[qp] + dudxi),
                                                   (dxdeta[qp] + dudeta)*(dxdeta[qp] + dudeta) );

        // Contravariant metric tensor of reference configuration
        libMesh::TensorValue<libMesh::Real> a_contra( dxi*dxi, dxi*deta, 0.0,
                                                      deta*dxi, deta*deta );

        // Contravariant metric tensor in current configuration is A_cov^{-1}
        libMesh::Real det_A = A_cov(0,0)*A_cov(1,1) - A_cov(0,1)*A_cov(1,0);
        libMesh::TensorValue<libMesh::Real> A_contra(  A_cov(1,1)/det_A, -A_cov(0,1)/det_A, 0.0,
                                                      -A_cov(1,0)/det_A,  A_cov(0,0)/det_A );

        if( _lambda_sq_coupled )
          {
            a_cov(2,2)    = 1.0;
            a_contra(2,2) = 1.0;

            libMesh::Real det_a = a_cov.det();

            // If the material is incompressible, lambda^2 is known
            libMesh::Real lambda_sq = det_a/det_A;

            // If the material is compressible, then lambda_sq is an independent variable
            if( _lambda_sq_var )
              {
                libmesh_not_implemented();
              }

            A_cov(2,2) = lambda_sq;
            A_contra(2,2) = 1.0/lambda_sq;
          }

        // Compute stress tensor
        libMesh::TensorValue<libMesh::Real> tau;
        _stress_strain_law.compute_stress(dim,a_contra,a_cov,A_contra,A_cov,tau);

        libMesh::Real jac = JxW[qp];

        for (unsigned int i=0; i != n_u_dofs; i++)
	  {
            for( unsigned int alpha = 0; alpha < dim; alpha++ )
              {
                for( unsigned int beta = 0; beta < dim; beta++ )
                  {
                    Fu(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_x(beta) + grad_u(beta))*u_gradphi[i][qp](alpha) +
                                                       (grad_x(alpha) + grad_u(alpha))*u_gradphi[i][qp](beta) )*jac;

                    Fv(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_y(beta) + grad_v(beta))*u_gradphi[i][qp](alpha) +
                                                       (grad_y(alpha) + grad_v(alpha))*u_gradphi[i][qp](beta) )*jac;

                    Fw(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_z(beta) + grad_w(beta))*u_gradphi[i][qp](alpha) +
                                                       (grad_z(alpha) + grad_w(alpha))*u_gradphi[i][qp](beta) )*jac;
                  }
              }
            if( compute_jacobian )
              {
                libmesh_not_implemented();
              }
          }

      }

    return;
  }

  template<typename StressStrainLaw>
  void ElasticMembrane<StressStrainLaw>::side_time_derivative( bool /*compute_jacobian*/,
                                                               AssemblyContext& /*context*/,
                                                               CachedValues& /*cache*/ )
  {
    /*
      std::vector<BoundaryID> ids = context.side_boundary_ids();

      for( std::vector<BoundaryID>::const_iterator it = ids.begin();
      it != ids.end(); it++ )
      {
      libmesh_assert (*it != libMesh::BoundaryInfo::invalid_id);

      _bc_handler->apply_neumann_bcs( context, cache, compute_jacobian, *it );
      }
    */

    return;
  }

  template<typename StressStrainLaw>
  void ElasticMembrane<StressStrainLaw>::mass_residual( bool /*compute_jacobian*/,
                                                        AssemblyContext& /*context*/,
                                                        CachedValues& /*cache*/ )
  {
    libmesh_not_implemented();
    return;
  }

} // end namespace GRINS
<commit_msg>Have GenericICHandler there to play with initial conditions<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2014 Paul T. Bauman, Roy H. Stogner
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/elastic_membrane.h"

// GRINS
#include "grins_config.h"
#include "grins/assembly_context.h"
#include "grins/solid_mechanics_bc_handling.h"
#include "grins/generic_ic_handler.h"

// libMesh
#include "libmesh/getpot.h"
#include "libmesh/quadrature.h"
#include "libmesh/boundary_info.h"
#include "libmesh/fem_system.h"

namespace GRINS
{
  template<typename StressStrainLaw>
  ElasticMembrane<StressStrainLaw>::ElasticMembrane( const GRINS::PhysicsName& physics_name, const GetPot& input,
                                                     bool lambda_sq_coupled, bool lambda_sq_var )
    : ElasticMembraneBase(physics_name,input),
      _stress_strain_law(input),
      _h0( input("Physics/"+physics_name+"/h0", 1.0 ) ),
      _lambda_sq_coupled(lambda_sq_coupled),
      _lambda_sq_var(lambda_sq_var)
  {
    // Force the user to set h0
    if( !input.have_variable("Physics/"+physics_name+"/h0") )
      {
        std::cerr << "Error: Must specify initial thickness for "+physics_name << std::endl
                  << "       Input the option Physics/"+physics_name+"/h0" << std::endl;
        libmesh_error();
      }

    this->_bc_handler = new SolidMechanicsBCHandling( physics_name, input );

    this->_ic_handler = new GenericICHandler(physics_name, input);

    return;
  }

  template<typename StressStrainLaw>
  ElasticMembrane<StressStrainLaw>::~ElasticMembrane()
  {
    return;
  }

  template<typename StressStrainLaw>
  void ElasticMembrane<StressStrainLaw>::element_time_derivative( bool compute_jacobian,
                                                                   AssemblyContext& context,
                                                                   CachedValues& /*cache*/ )
  {
    const unsigned int n_u_dofs = context.get_dof_indices(_disp_vars.u_var()).size();

    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(_disp_vars.u_var())->get_JxW();

    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
      context.get_element_fe(_disp_vars.u_var())->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(_disp_vars.u_var());
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(_disp_vars.v_var());
    libMesh::DenseSubVector<libMesh::Number> &Fw = context.get_elem_residual(_disp_vars.w_var());

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    const std::vector<libMesh::RealGradient>& dxdxi  = context.get_element_fe(_disp_vars.u_var())->get_dxyzdxi();
    const std::vector<libMesh::RealGradient>& dxdeta = context.get_element_fe(_disp_vars.u_var())->get_dxyzdeta();

    const std::vector<libMesh::Real>& dxidx  = context.get_element_fe(_disp_vars.u_var())->get_dxidx();
    const std::vector<libMesh::Real>& dxidy  = context.get_element_fe(_disp_vars.u_var())->get_dxidy();
    const std::vector<libMesh::Real>& dxidz  = context.get_element_fe(_disp_vars.u_var())->get_dxidz();

    const std::vector<libMesh::Real>& detadx  = context.get_element_fe(_disp_vars.u_var())->get_detadx();
    const std::vector<libMesh::Real>& detady  = context.get_element_fe(_disp_vars.u_var())->get_detady();
    const std::vector<libMesh::Real>& detadz  = context.get_element_fe(_disp_vars.u_var())->get_detadz();

    const unsigned int dim = 2; // The manifold dimension is always 2 for this physics

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::Gradient grad_u = context.interior_gradient(_disp_vars.u_var(), qp);
        libMesh::Gradient grad_v = context.interior_gradient(_disp_vars.v_var(), qp);
        libMesh::Gradient grad_w = context.interior_gradient(_disp_vars.w_var(), qp);

        libMesh::RealGradient grad_x( dxdxi[qp](0), dxdeta[qp](0) );
        libMesh::RealGradient grad_y( dxdxi[qp](1), dxdeta[qp](1) );
        libMesh::RealGradient grad_z( dxdxi[qp](2), dxdeta[qp](2) );

        libMesh::RealGradient dudxi( grad_u(0), grad_v(0), grad_w(0) );
        libMesh::RealGradient dudeta( grad_u(1), grad_v(1), grad_w(1) );

        libMesh::RealGradient dxi( dxidx[qp], dxidy[qp], dxidz[qp] );
        libMesh::RealGradient deta( detadx[qp], detady[qp], detadz[qp] );

        // Covariant metric tensor of reference configuration
        libMesh::TensorValue<libMesh::Real> a_cov( dxdxi[qp]*dxdxi[qp], dxdxi[qp]*dxdeta[qp], 0.0,
                                                   dxdeta[qp]*dxdxi[qp], dxdeta[qp]*dxdeta[qp] );

        // Covariant metric tensor of current configuration
        libMesh::TensorValue<libMesh::Real> A_cov( (dxdxi[qp] + dudxi)*(dxdxi[qp] + dudxi),
                                                   (dxdxi[qp] + dudxi)*(dxdeta[qp] + dudeta), 0.0,
                                                   (dxdeta[qp] + dudeta)*(dxdxi[qp] + dudxi),
                                                   (dxdeta[qp] + dudeta)*(dxdeta[qp] + dudeta) );

        // Contravariant metric tensor of reference configuration
        libMesh::TensorValue<libMesh::Real> a_contra( dxi*dxi, dxi*deta, 0.0,
                                                      deta*dxi, deta*deta );

        // Contravariant metric tensor in current configuration is A_cov^{-1}
        libMesh::Real det_A = A_cov(0,0)*A_cov(1,1) - A_cov(0,1)*A_cov(1,0);
        libMesh::TensorValue<libMesh::Real> A_contra(  A_cov(1,1)/det_A, -A_cov(0,1)/det_A, 0.0,
                                                      -A_cov(1,0)/det_A,  A_cov(0,0)/det_A );

        if( _lambda_sq_coupled )
          {
            a_cov(2,2)    = 1.0;
            a_contra(2,2) = 1.0;

            libMesh::Real det_a = a_cov.det();

            // If the material is incompressible, lambda^2 is known
            libMesh::Real lambda_sq = det_a/det_A;

            // If the material is compressible, then lambda_sq is an independent variable
            if( _lambda_sq_var )
              {
                libmesh_not_implemented();
              }

            A_cov(2,2) = lambda_sq;
            A_contra(2,2) = 1.0/lambda_sq;
          }

        // Compute stress tensor
        libMesh::TensorValue<libMesh::Real> tau;
        _stress_strain_law.compute_stress(dim,a_contra,a_cov,A_contra,A_cov,tau);

        libMesh::Real jac = JxW[qp];

        for (unsigned int i=0; i != n_u_dofs; i++)
	  {
            for( unsigned int alpha = 0; alpha < dim; alpha++ )
              {
                for( unsigned int beta = 0; beta < dim; beta++ )
                  {
                    Fu(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_x(beta) + grad_u(beta))*u_gradphi[i][qp](alpha) +
                                                       (grad_x(alpha) + grad_u(alpha))*u_gradphi[i][qp](beta) )*jac;

                    Fv(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_y(beta) + grad_v(beta))*u_gradphi[i][qp](alpha) +
                                                       (grad_y(alpha) + grad_v(alpha))*u_gradphi[i][qp](beta) )*jac;

                    Fw(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_z(beta) + grad_w(beta))*u_gradphi[i][qp](alpha) +
                                                       (grad_z(alpha) + grad_w(alpha))*u_gradphi[i][qp](beta) )*jac;
                  }
              }
            if( compute_jacobian )
              {
                libmesh_not_implemented();
              }
          }

      }

    return;
  }

  template<typename StressStrainLaw>
  void ElasticMembrane<StressStrainLaw>::side_time_derivative( bool /*compute_jacobian*/,
                                                               AssemblyContext& /*context*/,
                                                               CachedValues& /*cache*/ )
  {
    /*
      std::vector<BoundaryID> ids = context.side_boundary_ids();

      for( std::vector<BoundaryID>::const_iterator it = ids.begin();
      it != ids.end(); it++ )
      {
      libmesh_assert (*it != libMesh::BoundaryInfo::invalid_id);

      _bc_handler->apply_neumann_bcs( context, cache, compute_jacobian, *it );
      }
    */

    return;
  }

  template<typename StressStrainLaw>
  void ElasticMembrane<StressStrainLaw>::mass_residual( bool /*compute_jacobian*/,
                                                        AssemblyContext& /*context*/,
                                                        CachedValues& /*cache*/ )
  {
    libmesh_not_implemented();
    return;
  }

} // end namespace GRINS
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef RENDERER_HPP
#define RENDERER_HPP

#include "compare_images.hpp"

// stl
#include <sstream>
#include <iomanip>
#include <fstream>

// mapnik
#include <mapnik/map.hpp>
#include <mapnik/agg_renderer.hpp>
#if defined(HAVE_CAIRO)
#include <mapnik/cairo/cairo_renderer.hpp>
#include <mapnik/cairo/cairo_image_util.hpp>
#endif
#if defined(SVG_RENDERER)
#include <mapnik/svg/output/svg_renderer.hpp>
#endif

// boost
#include <boost/filesystem.hpp>

namespace visual_tests
{

template <typename ImageType>
struct renderer_base
{
    using image_type = ImageType;

    static constexpr const char * ext = ".png";

    unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const
    {
        return compare_images(actual, reference.string());
    }

    void save(image_type const & image, boost::filesystem::path const& path) const
    {
        mapnik::save_to_file(image, path.string(), "png32");
    }
};

struct agg_renderer : renderer_base<mapnik::image_rgba8>
{
    static constexpr const char * name = "agg";

    image_type render(mapnik::Map const & map, double scale_factor) const
    {
        image_type image(map.width(), map.height());
        mapnik::agg_renderer<image_type> ren(map, image, scale_factor);
        ren.apply();
        return image;
    }
};

#if defined(HAVE_CAIRO)
struct cairo_renderer : renderer_base<mapnik::image_rgba8>
{
    static constexpr const char * name = "cairo";

    image_type render(mapnik::Map const & map, double scale_factor) const
    {
        mapnik::cairo_surface_ptr image_surface(
            cairo_image_surface_create(CAIRO_FORMAT_ARGB32, map.width(), map.height()),
            mapnik::cairo_surface_closer());
        mapnik::cairo_ptr image_context(mapnik::create_context(image_surface));
        mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map, image_context, scale_factor);
        ren.apply();
        image_type image(map.width(), map.height());
        mapnik::cairo_image_to_rgba8(image, image_surface);
        return image;
    }
};
#endif

#if defined(SVG_RENDERER)
struct svg_renderer : renderer_base<std::string>
{
    static constexpr const char * name = "svg";
    static constexpr const char * ext = ".svg";

    image_type render(mapnik::Map const & map, double scale_factor) const
    {
        std::stringstream ss;
        std::ostream_iterator<char> output_stream_iterator(ss);
        mapnik::svg_renderer<std::ostream_iterator<char>> ren(map, output_stream_iterator, scale_factor);
        ren.apply();
        return ss.str();
    }

    unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const
    {
        std::ifstream stream(reference.string().c_str(),std::ios_base::in|std::ios_base::binary);
        if (!stream.is_open())
        {
            throw std::runtime_error("could not open: '" + reference.string() + "'");
        }
        std::string expected(std::istreambuf_iterator<char>(stream.rdbuf()),(std::istreambuf_iterator<char>()));
        stream.close();
        return std::fabs(actual.size() - expected.size());
    }

    void save(image_type const & image, boost::filesystem::path const& path) const
    {
        std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary);
        if (!file) {
            throw std::runtime_error((std::string("cannot open file for writing file ") + path.string()).c_str());
        } else {
            file << image;
            file.close();
        }
    }

};
#endif

struct grid_renderer : renderer_base<mapnik::image_gray8>
{
    static constexpr const char * name = "grid";

    image_type render(mapnik::Map const & map, double scale_factor) const
    {
        image_type image(map.width(), map.height());
        // TODO: Render grid here.
        return image;
    }
};

template <typename Renderer>
class renderer
{
public:
    renderer(boost::filesystem::path const & output_dir, boost::filesystem::path const & reference_dir, bool overwrite)
        : output_dir(output_dir), reference_dir(reference_dir), overwrite(overwrite)
    {
    }

    result test(std::string const & name, mapnik::Map const & map, double scale_factor) const
    {
        typename Renderer::image_type image(ren.render(map, scale_factor));
        boost::filesystem::path reference = reference_dir / image_file_name(name, map.width(), map.height(), scale_factor, true, Renderer::ext);
        bool reference_exists = boost::filesystem::exists(reference);
        result res;

        res.state = reference_exists ? STATE_OK : STATE_OVERWRITE;
        res.name = name;
        res.renderer_name = Renderer::name;
        res.scale_factor = scale_factor;
        res.size = map_size(map.width(), map.height());
        res.reference_image_path = reference;
        res.diff = reference_exists ? ren.compare(image, reference) : 0;

        if (res.diff)
        {
            boost::filesystem::create_directories(output_dir);
            boost::filesystem::path path = output_dir / image_file_name(name, map.width(), map.height(), scale_factor, false, Renderer::ext);
            res.actual_image_path = path;
            res.state = STATE_FAIL;
            ren.save(image, path);
        }

        if ((res.diff && overwrite) || !reference_exists)
        {
            ren.save(image, reference);
            res.state = STATE_OVERWRITE;
        }

        return res;
    }

private:
    std::string image_file_name(std::string const & test_name,
                                double width,
                                double height,
                                double scale_factor,
                                bool reference,
                                std::string const& ext) const
    {
        std::stringstream s;
        s << test_name << '-' << width << '-' << height << '-'
          << std::fixed << std::setprecision(1) << scale_factor
          << '-' << Renderer::name << (reference ? "-reference" : "") << ext;
        return s.str();
    }

    Renderer ren;
    boost::filesystem::path const & output_dir;
    boost::filesystem::path const & reference_dir;
    const bool overwrite;
};

}

#endif
<commit_msg>visual tests: apply constness<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef RENDERER_HPP
#define RENDERER_HPP

#include "compare_images.hpp"

// stl
#include <sstream>
#include <iomanip>
#include <fstream>

// mapnik
#include <mapnik/map.hpp>
#include <mapnik/agg_renderer.hpp>
#if defined(HAVE_CAIRO)
#include <mapnik/cairo/cairo_renderer.hpp>
#include <mapnik/cairo/cairo_image_util.hpp>
#endif
#if defined(SVG_RENDERER)
#include <mapnik/svg/output/svg_renderer.hpp>
#endif

// boost
#include <boost/filesystem.hpp>

namespace visual_tests
{

template <typename ImageType>
struct renderer_base
{
    using image_type = ImageType;

    static constexpr const char * ext = ".png";

    unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const
    {
        return compare_images(actual, reference.string());
    }

    void save(image_type const & image, boost::filesystem::path const& path) const
    {
        mapnik::save_to_file(image, path.string(), "png32");
    }
};

struct agg_renderer : renderer_base<mapnik::image_rgba8>
{
    static constexpr const char * name = "agg";

    image_type render(mapnik::Map const & map, double scale_factor) const
    {
        image_type image(map.width(), map.height());
        mapnik::agg_renderer<image_type> ren(map, image, scale_factor);
        ren.apply();
        return image;
    }
};

#if defined(HAVE_CAIRO)
struct cairo_renderer : renderer_base<mapnik::image_rgba8>
{
    static constexpr const char * name = "cairo";

    image_type render(mapnik::Map const & map, double scale_factor) const
    {
        mapnik::cairo_surface_ptr image_surface(
            cairo_image_surface_create(CAIRO_FORMAT_ARGB32, map.width(), map.height()),
            mapnik::cairo_surface_closer());
        mapnik::cairo_ptr image_context(mapnik::create_context(image_surface));
        mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map, image_context, scale_factor);
        ren.apply();
        image_type image(map.width(), map.height());
        mapnik::cairo_image_to_rgba8(image, image_surface);
        return image;
    }
};
#endif

#if defined(SVG_RENDERER)
struct svg_renderer : renderer_base<std::string>
{
    static constexpr const char * name = "svg";
    static constexpr const char * ext = ".svg";

    image_type render(mapnik::Map const & map, double scale_factor) const
    {
        std::stringstream ss;
        std::ostream_iterator<char> output_stream_iterator(ss);
        mapnik::svg_renderer<std::ostream_iterator<char>> ren(map, output_stream_iterator, scale_factor);
        ren.apply();
        return ss.str();
    }

    unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const
    {
        std::ifstream stream(reference.string().c_str(),std::ios_base::in|std::ios_base::binary);
        if (!stream.is_open())
        {
            throw std::runtime_error("could not open: '" + reference.string() + "'");
        }
        std::string expected(std::istreambuf_iterator<char>(stream.rdbuf()),(std::istreambuf_iterator<char>()));
        stream.close();
        return std::fabs(actual.size() - expected.size());
    }

    void save(image_type const & image, boost::filesystem::path const& path) const
    {
        std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary);
        if (!file) {
            throw std::runtime_error((std::string("cannot open file for writing file ") + path.string()).c_str());
        } else {
            file << image;
            file.close();
        }
    }

};
#endif

struct grid_renderer : renderer_base<mapnik::image_gray8>
{
    static constexpr const char * name = "grid";

    image_type render(mapnik::Map const & map, double scale_factor) const
    {
        image_type image(map.width(), map.height());
        // TODO: Render grid here.
        return image;
    }
};

template <typename Renderer>
class renderer
{
public:
    renderer(boost::filesystem::path const & output_dir, boost::filesystem::path const & reference_dir, bool overwrite)
        : ren(), output_dir(output_dir), reference_dir(reference_dir), overwrite(overwrite)
    {
    }

    result test(std::string const & name, mapnik::Map const & map, double scale_factor) const
    {
        typename Renderer::image_type image(ren.render(map, scale_factor));
        boost::filesystem::path reference = reference_dir / image_file_name(name, map.width(), map.height(), scale_factor, true, Renderer::ext);
        bool reference_exists = boost::filesystem::exists(reference);
        result res;

        res.state = reference_exists ? STATE_OK : STATE_OVERWRITE;
        res.name = name;
        res.renderer_name = Renderer::name;
        res.scale_factor = scale_factor;
        res.size = map_size(map.width(), map.height());
        res.reference_image_path = reference;
        res.diff = reference_exists ? ren.compare(image, reference) : 0;

        if (res.diff)
        {
            boost::filesystem::create_directories(output_dir);
            boost::filesystem::path path = output_dir / image_file_name(name, map.width(), map.height(), scale_factor, false, Renderer::ext);
            res.actual_image_path = path;
            res.state = STATE_FAIL;
            ren.save(image, path);
        }

        if ((res.diff && overwrite) || !reference_exists)
        {
            ren.save(image, reference);
            res.state = STATE_OVERWRITE;
        }

        return res;
    }

private:
    std::string image_file_name(std::string const & test_name,
                                double width,
                                double height,
                                double scale_factor,
                                bool reference,
                                std::string const& ext) const
    {
        std::stringstream s;
        s << test_name << '-' << width << '-' << height << '-'
          << std::fixed << std::setprecision(1) << scale_factor
          << '-' << Renderer::name << (reference ? "-reference" : "") << ext;
        return s.str();
    }

    const Renderer ren;
    boost::filesystem::path const & output_dir;
    boost::filesystem::path const & reference_dir;
    const bool overwrite;
};

}

#endif
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////
// Copyright (c) 2011 - Hiairrassary Victor
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the copyright holder nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "Console.hpp"

#include <exception>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <functional>

namespace plt
{
    Console::Console
    (
    ) :
    m_enabled(false)
    {
        std::function<std::string()> function = std::bind(&Console::getCommands, this);

        registerCommand("?", function);
    }

    void Console::sendChar(char Character)
    {
        // Si la console n'est pas active on ne traite pas le caractère
        if (!m_enabled)
            return;

        // Traitement du caractère
        switch (Character)
        {
            // Saut de ligne : on traite la commande et on efface la ligne
            case '\n' :
            case '\r' :
                if (!m_current.empty())
                {
                    processCurrent();
                    m_current.clear();
                }
                break;

            // Backspace : on efface le dernier caractère
            case '\b' :
                if (!m_current.empty())
                    m_current.erase(m_current.size() - 1);
                break;

            // Tout le reste : on ajoute le caractère à la ligne courante
            default :
                m_current += Character;
                break;
        }

        m_view->textChanged(m_current);
    }

    void Console::setView
    (
        const std::shared_ptr<ConsoleView> &view
    )
    {
        if(!view)
            throw std::runtime_error("The view is an invalid pointer");

        m_view = view;
    }

    std::string Console::getCommands() const
    {
        std::string list;
        for (auto it = m_commands.begin(); it != m_commands.end(); ++it)
            list += it->first + " ";

        return list;
    }

    void Console::processCurrent
    (
    )
    {
        std::string command;

        std::istringstream iss(m_current);

        if( !(iss >> command) )
            throw std::runtime_error("Error when parsing the command name");

        auto it = m_commands.find(command);

        if (it != m_commands.end())
        {
            std::string params;
            std::getline(iss, params);

            try
            {
                m_view->commandCalled(
                                        (it->second)->execute(params)
                                     );
            }

            catch (const std::exception &e)
            {
                m_view->error( e.what() );
            }

        }

        else
            m_view->error("Commande \"" + command + "\" inconnue");
    }

    void Console::enable
    (
        bool state
    )
    {
        m_enabled = state;

        m_view->show(state);
    }

    bool Console::isEnable
    (
    ) const
    {
        return m_enabled;
    }

} // namespace plt
<commit_msg>Traduction en anglais d'une erreur en français<commit_after>////////////////////////////////////////////////////////////
// Copyright (c) 2011 - Hiairrassary Victor
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the copyright holder nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "Console.hpp"

#include <exception>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <functional>

namespace plt
{
    Console::Console
    (
    ) :
    m_enabled(false)
    {
        std::function<std::string()> function = std::bind(&Console::getCommands, this);

        registerCommand("?", function);
    }

    void Console::sendChar(char Character)
    {
        // Si la console n'est pas active on ne traite pas le caractère
        if (!m_enabled)
            return;

        // Traitement du caractère
        switch (Character)
        {
            // Saut de ligne : on traite la commande et on efface la ligne
            case '\n' :
            case '\r' :
                if (!m_current.empty())
                {
                    processCurrent();
                    m_current.clear();
                }
                break;

            // Backspace : on efface le dernier caractère
            case '\b' :
                if (!m_current.empty())
                    m_current.erase(m_current.size() - 1);
                break;

            // Tout le reste : on ajoute le caractère à la ligne courante
            default :
                m_current += Character;
                break;
        }

        m_view->textChanged(m_current);
    }

    void Console::setView
    (
        const std::shared_ptr<ConsoleView> &view
    )
    {
        if(!view)
            throw std::runtime_error("The view is an invalid pointer");

        m_view = view;
    }

    std::string Console::getCommands() const
    {
        std::string list;
        for (auto it = m_commands.begin(); it != m_commands.end(); ++it)
            list += it->first + " ";

        return list;
    }

    void Console::processCurrent
    (
    )
    {
        std::string command;

        std::istringstream iss(m_current);

        if( !(iss >> command) )
            throw std::runtime_error("Error when parsing the command name");

        auto it = m_commands.find(command);

        if (it != m_commands.end())
        {
            std::string params;
            std::getline(iss, params);

            try
            {
                m_view->commandCalled(
                                        (it->second)->execute(params)
                                     );
            }

            catch (const std::exception &e)
            {
                m_view->error( e.what() );
            }

        }

        else
            m_view->error("Unknown command : \"" + command);
    }

    void Console::enable
    (
        bool state
    )
    {
        m_enabled = state;

        m_view->show(state);
    }

    bool Console::isEnable
    (
    ) const
    {
        return m_enabled;
    }

} // namespace plt
<|endoftext|>


<commit_before>#include <iostream>

#include "compressedarray.h"
#include "test_utils.h"

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE TestCompressedArray
#include <boost/test/unit_test.hpp>

template<int N, class T>
void testCompressedArray(typename vigra::MultiArray<N,T>::difference_type dataShape)
{
    vigra::MultiArray<N,T> theData(dataShape);
    FillRandom<T, typename vigra::MultiArray<N,T>::iterator>::fillRandom(theData.begin(), theData.end());

    typedef CompressedArray<N, T> CA;

    //std::cout << "read" << std::endl;
    //read
    CA ca(theData);
    BOOST_CHECK(!ca.isDirty());
    BOOST_CHECK(!ca.isCompressed());
    BOOST_CHECK_EQUAL(ca.compressedSize(), 0);
    BOOST_CHECK_EQUAL(ca.shape(), theData.shape());
    vigra::MultiArray<N,T> r(dataShape);
    ca.readArray(r);
    BOOST_CHECK(arraysEqual(theData, r));

    //std::cout << "compress & uncompress" << std::endl;
    //compress & uncompress
    ca.compress();
    std::fill(r.begin(), r.end(), 0);
    ca.readArray(r);
    BOOST_CHECK(arraysEqual(theData, r));

    BOOST_CHECK(ca.isCompressed());
    BOOST_CHECK(ca.compressedSize() > 0);
    ca.uncompress();
    BOOST_CHECK(ca.compressedSize() > 0);
    BOOST_CHECK(!ca.isCompressed());
    std::fill(r.begin(), r.end(), 0);
    ca.readArray(r);
    BOOST_CHECK(arraysEqual(theData, r));

    //std::cout << "compress & read" << std::endl;
    //compress and read
    ca.compress();
    BOOST_CHECK(ca.isCompressed());
    ca.readArray(r);
    BOOST_CHECK(arraysEqual(theData, r));

    //std::cout << "copy-construct" << std::endl;
    //copy-construct
    {
        CA ca2(ca);
        vigra::MultiArray<N,T> r1(dataShape);
        vigra::MultiArray<N,T> r2(dataShape);
        ca.readArray(r1);
        ca2.readArray(r2);
        BOOST_CHECK(arraysEqual(r1, r2));
    }

    //std::cout << "assignment" << std::endl;
    //assignment
    {
        CA ca2;
        ca2 = ca;
        vigra::MultiArray<N,T> r1(dataShape);
        vigra::MultiArray<N,T> r2(dataShape);
        ca.readArray(r1);
        ca2.readArray(r2);
        BOOST_CHECK(arraysEqual(r1, r2));
    }

    BOOST_CHECK(!ca.isDirty());
    ca.setDirty(true);
    BOOST_CHECK(ca.isDirty());

    {
        vigra::MultiArray<N,T> toWrite(ca.shape());
        std::fill(toWrite.begin(), toWrite.end(), 42);
        ca.writeArray(typename CA::difference_type(), ca.shape(), toWrite);
        std::fill(r.begin(), r.end(), 0);
        ca.readArray(r);
        BOOST_CHECK(arraysEqual(r, toWrite));
    }

    ca.compress();

    {
        vigra::MultiArray<N,T> toWrite(ca.shape());
        std::fill(toWrite.begin(), toWrite.end(), 42);
        ca.writeArray(typename CA::difference_type(), ca.shape(), toWrite);
        std::fill(r.begin(), r.end(), 0);
        ca.readArray(r);
        BOOST_CHECK(arraysEqual(r, toWrite));
    }
}

BOOST_AUTO_TEST_CASE( testDim1 ) {
    testCompressedArray<1, vigra::UInt8 >(vigra::Shape1(20));
    testCompressedArray<1, vigra::UInt16>(vigra::Shape1(20));
    testCompressedArray<1, vigra::UInt32>(vigra::Shape1(20));
    testCompressedArray<1, vigra::UInt64>(vigra::Shape1(20));
    testCompressedArray<1, vigra::Int32 >(vigra::Shape1(20));
    testCompressedArray<1, float        >(vigra::Shape1(20));
    testCompressedArray<1, vigra::Int64 >(vigra::Shape1(20));
}

BOOST_AUTO_TEST_CASE( testDim2 ) {
    testCompressedArray<2, vigra::UInt8 >(vigra::Shape2(20,30));
    testCompressedArray<2, vigra::UInt32>(vigra::Shape2(20,30));
    testCompressedArray<2, float        >(vigra::Shape2(20,30));
    testCompressedArray<2, vigra::Int64 >(vigra::Shape2(20,30));
}

BOOST_AUTO_TEST_CASE( testDim3 ) {
    testCompressedArray<3, vigra::UInt8 >(vigra::Shape3(20,30,40));
    testCompressedArray<3, vigra::UInt32>(vigra::Shape3(20,30,40));
    testCompressedArray<3, float        >(vigra::Shape3(20,30,40));
    testCompressedArray<3, vigra::Int64 >(vigra::Shape3(20,30,40));
}

BOOST_AUTO_TEST_CASE( testDim5 ) {
    testCompressedArray<5, vigra::UInt8 >(vigra::Shape5(2,20,30,4,1));
    testCompressedArray<5, vigra::UInt32>(vigra::Shape5(2,20,30,4,1));
    testCompressedArray<5, float        >(vigra::Shape5(2,20,30,4,1));
    testCompressedArray<5, vigra::Int64 >(vigra::Shape5(2,20,30,4,1));
}
<commit_msg>minor cleanups + minor additional tests<commit_after>#include <iostream>

#include "compressedarray.h"
#include "test_utils.h"

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE TestCompressedArray
#include <boost/test/unit_test.hpp>

template<int N, class T>
void testCompressedArray(typename vigra::MultiArray<N,T>::difference_type dataShape)
{
    vigra::MultiArray<N,T> theData(dataShape);
    FillRandom<T, typename vigra::MultiArray<N,T>::iterator>::fillRandom(theData.begin(), theData.end());

    typedef CompressedArray<N, T> CA;

    {
        CA e; //empty
        BOOST_CHECK(!e.isCompressed());
        BOOST_CHECK_EQUAL(e.compressedSize(), 0);
        BOOST_CHECK(!e.isDirty());
    }

    //std::cout << "construct" << std::endl;
    CA ca(theData);
    BOOST_CHECK(!ca.isDirty());
    BOOST_CHECK(!ca.isCompressed());
    BOOST_CHECK_EQUAL(ca.compressedSize(), 0);
    BOOST_CHECK_EQUAL(ca.shape(), theData.shape());

    //std::cout << "read" << std::endl;
    vigra::MultiArray<N,T> r(dataShape);
    ca.readArray(r);
    BOOST_CHECK(arraysEqual(theData, r));

    //std::cout << "compress & uncompress" << std::endl;
    ca.compress();
    std::fill(r.begin(), r.end(), 0);
    ca.readArray(r);
    BOOST_CHECK(arraysEqual(theData, r));

    BOOST_CHECK(ca.isCompressed());
    BOOST_CHECK(ca.compressedSize() > 0);
    ca.uncompress();
    BOOST_CHECK(ca.compressedSize() > 0);
    BOOST_CHECK(!ca.isCompressed());
    std::fill(r.begin(), r.end(), 0);
    ca.readArray(r);
    BOOST_CHECK(arraysEqual(theData, r));

    //std::cout << "compress & read" << std::endl;
    ca.compress();
    BOOST_CHECK(ca.isCompressed());
    ca.readArray(r);
    BOOST_CHECK(arraysEqual(theData, r));

    //std::cout << "copy-construct" << std::endl;
    {
        CA ca2(ca);
        vigra::MultiArray<N,T> r1(dataShape);
        vigra::MultiArray<N,T> r2(dataShape);
        ca.readArray(r1);
        ca2.readArray(r2);
        BOOST_CHECK(arraysEqual(r1, r2));
    }

    //std::cout << "assignment" << std::endl;
    {
        CA ca2;
        ca2 = ca;
        vigra::MultiArray<N,T> r1(dataShape);
        vigra::MultiArray<N,T> r2(dataShape);
        ca.readArray(r1);
        ca2.readArray(r2);
        BOOST_CHECK(arraysEqual(r1, r2));
    }

    BOOST_CHECK(!ca.isDirty());
    ca.setDirty(true);
    BOOST_CHECK(ca.isDirty());

    {
        vigra::MultiArray<N,T> toWrite(ca.shape());
        std::fill(toWrite.begin(), toWrite.end(), 42);
        ca.writeArray(typename CA::difference_type(), ca.shape(), toWrite);
        std::fill(r.begin(), r.end(), 0);
        ca.readArray(r);
        BOOST_CHECK(arraysEqual(r, toWrite));
    }

    ca.compress();

    {
        vigra::MultiArray<N,T> toWrite(ca.shape());
        std::fill(toWrite.begin(), toWrite.end(), 42);
        ca.writeArray(typename CA::difference_type(), ca.shape(), toWrite);
        std::fill(r.begin(), r.end(), 0);
        ca.readArray(r);
        BOOST_CHECK(arraysEqual(r, toWrite));
    }
}

BOOST_AUTO_TEST_CASE( testDim1 ) {
    testCompressedArray<1, vigra::UInt8 >(vigra::Shape1(20));
    testCompressedArray<1, vigra::UInt16>(vigra::Shape1(20));
    testCompressedArray<1, vigra::UInt32>(vigra::Shape1(20));
    testCompressedArray<1, vigra::UInt64>(vigra::Shape1(20));
    testCompressedArray<1, vigra::Int32 >(vigra::Shape1(20));
    testCompressedArray<1, float        >(vigra::Shape1(20));
    testCompressedArray<1, vigra::Int64 >(vigra::Shape1(20));
}

BOOST_AUTO_TEST_CASE( testDim2 ) {
    testCompressedArray<2, vigra::UInt8 >(vigra::Shape2(20,30));
    testCompressedArray<2, vigra::UInt32>(vigra::Shape2(20,30));
    testCompressedArray<2, float        >(vigra::Shape2(20,30));
    testCompressedArray<2, vigra::Int64 >(vigra::Shape2(20,30));
}

BOOST_AUTO_TEST_CASE( testDim3 ) {
    testCompressedArray<3, vigra::UInt8 >(vigra::Shape3(20,30,40));
    testCompressedArray<3, vigra::UInt32>(vigra::Shape3(20,30,40));
    testCompressedArray<3, float        >(vigra::Shape3(20,30,40));
    testCompressedArray<3, vigra::Int64 >(vigra::Shape3(20,30,40));
}

BOOST_AUTO_TEST_CASE( testDim5 ) {
    testCompressedArray<5, vigra::UInt8 >(vigra::Shape5(2,20,30,4,1));
    testCompressedArray<5, vigra::UInt32>(vigra::Shape5(2,20,30,4,1));
    testCompressedArray<5, float        >(vigra::Shape5(2,20,30,4,1));
    testCompressedArray<5, vigra::Int64 >(vigra::Shape5(2,20,30,4,1));
}
<|endoftext|>


<commit_before>#include "UnitTest++/UnitTestPP.h"
#include "RecordingReporter.h"
#include "UnitTest++/ReportAssert.h"
#include "UnitTest++/TestList.h"
#include "UnitTest++/TimeHelpers.h"
#include "UnitTest++/TimeConstraint.h"
#include "UnitTest++/ReportAssertImpl.h"

using namespace UnitTest;

namespace
{

    struct MockTest : public Test
    {
        MockTest(char const* testName, bool const success_, bool const assert_, int const count_ = 1)
        : Test(testName)
        , success(success_)
        , asserted(assert_)
        , count(count_)
        {
        }

        virtual void RunImpl() const
        {
            TestResults& testResults_ = *CurrentTest::Results();
            for (int i=0; i < count; ++i)
            {
                if (asserted)
                    ReportAssert("desc", "file", 0);
                else if (!success)
                    testResults_.OnTestFailure(m_details, "message");
            }
        }

        bool const success;
        bool const asserted;
        int const count;
    };

    struct FixtureBase {
        explicit FixtureBase() : runner(reporter) { }
        template <class Predicate>
        int RunTestsIf(TestList const& list, char const* suiteName,
                       const Predicate& predicate, int maxTestTimeInMs)
        {
            TestResults* oldResults = CurrentTest::Results();
            const TestDetails* oldDetails = CurrentTest::Details();
            int result = runner.RunTestsIf(list, suiteName, predicate, maxTestTimeInMs);
            CurrentTest::Results() = oldResults;
            CurrentTest::Details() = oldDetails;
            return result;
        }
        TestRunner runner;
        RecordingReporter reporter;
    };

    struct TestRunnerFixture : public FixtureBase
    {
        TestList list;
    };

    TEST_FIXTURE(TestRunnerFixture, TestStartIsReportedCorrectly)
    {
        MockTest test("goodtest", true, false);
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(1, reporter.testRunCount);
        CHECK_EQUAL("goodtest", reporter.lastStartedTest);
    }

    TEST_FIXTURE(TestRunnerFixture, TestFinishIsReportedCorrectly)
    {
        MockTest test("goodtest", true, false);
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(1, reporter.testFinishedCount);
        CHECK_EQUAL("goodtest", reporter.lastFinishedTest);
    }

    class SlowTest : public Test
    {
    public:
        SlowTest() : Test("slow", "somesuite", "filename", 123) {}
        virtual void RunImpl() const
        {
            TimeHelpers::SleepMs(20);
        }
    };

    TEST_FIXTURE(TestRunnerFixture, TestFinishIsCalledWithCorrectTime)
    {
        SlowTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK(reporter.lastFinishedTestTime >= 0.005f && reporter.lastFinishedTestTime <= 0.050f);
    }

    TEST_FIXTURE(TestRunnerFixture, FailureCountIsZeroWhenNoTestsAreRun)
    {
        CHECK_EQUAL(0, RunTestsIf(list, NULL, True(), 0));
        CHECK_EQUAL(0, reporter.testRunCount);
        CHECK_EQUAL(0, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, CallsReportFailureOncePerFailingTest)
    {
        MockTest test1("test", false, false);
        list.Add(&test1);
        MockTest test2("test", true, false);
        list.Add(&test2);
        MockTest test3("test", false, false);
        list.Add(&test3);

        CHECK_EQUAL(2, RunTestsIf(list, NULL, True(), 0));
        CHECK_EQUAL(2, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, TestsThatAssertAreReportedAsFailing)
    {
        MockTest test("test", true, true);
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(1, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfTestCount)
    {
        MockTest test1("test", true, false);
        MockTest test2("test", true, false);
        MockTest test3("test", true, false);
        list.Add(&test1);
        list.Add(&test2);
        list.Add(&test3);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(3, reporter.summaryTotalTestCount);
    }

    TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfFailedTests)
    {
        MockTest test1("test", false, false, 2);
        MockTest test2("test", true, false);
        MockTest test3("test", false, false, 3);
        list.Add(&test1);
        list.Add(&test2);
        list.Add(&test3);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(2, reporter.summaryFailedTestCount);
    }

    TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfFailures)
    {
        MockTest test1("test", false, false, 2);
        MockTest test2("test", true, false);
        MockTest test3("test", false, false, 3);
        list.Add(&test1);
        list.Add(&test2);
        list.Add(&test3);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(5, reporter.summaryFailureCount);
    }

    TEST_FIXTURE(TestRunnerFixture, SlowTestPassesForHighTimeThreshold)
    {
        SlowTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(0, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, SlowTestFailsForLowTimeThreshold)
    {
        SlowTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 3);
        CHECK_EQUAL(1, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, SlowTestHasCorrectFailureInformation)
    {
        SlowTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 3);

        using namespace std;

        CHECK_EQUAL(test.m_details.testName, reporter.lastFailedTest);
        CHECK(strstr(test.m_details.filename, reporter.lastFailedFile));
        CHECK_EQUAL(test.m_details.lineNumber, reporter.lastFailedLine);

        CHECK(strstr(reporter.lastFailedMessage, "Global time constraint failed"));
        CHECK(strstr(reporter.lastFailedMessage, "3ms"));
    }

    TEST_FIXTURE(TestRunnerFixture, SlowTestWithTimeExemptionPasses)
    {
        class SlowExemptedTest : public Test
        {
        public:
            SlowExemptedTest() : Test("slowexempted", "", 0) {}
            virtual void RunImpl() const
            {
                UNITTEST_TIME_CONSTRAINT_EXEMPT();
                TimeHelpers::SleepMs(20);
            }
        };

        SlowExemptedTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 3);
        CHECK_EQUAL(0, reporter.testFailedCount);
    }

    struct TestSuiteFixture : FixtureBase
    {
        TestSuiteFixture()
        : test1("TestInDefaultSuite")
        , test2("TestInOtherSuite", "OtherSuite")
        , test3("SecondTestInDefaultSuite")
        {
            list.Add(&test1);
            list.Add(&test2);
        }

        Test test1;
        Test test2;
        Test test3;
        TestList list;
    };

    TEST_FIXTURE(TestSuiteFixture, TestRunnerRunsAllSuitesIfNullSuiteIsPassed)
    {
        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(2, reporter.summaryTotalTestCount);
    }

    TEST_FIXTURE(TestSuiteFixture,TestRunnerRunsOnlySpecifiedSuite)
    {
        RunTestsIf(list, "OtherSuite", True(), 0);
        CHECK_EQUAL(1, reporter.summaryTotalTestCount);
        CHECK_EQUAL("TestInOtherSuite", reporter.lastFinishedTest);
    }

    struct RunTestIfNameIs
    {
        RunTestIfNameIs(char const* name_)
        : name(name_)
        {
        }

        bool operator()(const Test* const test) const
        {
            using namespace std;
            return (0 == strcmp(test->m_details.testName, name));
        }

        char const* name;
    };

    TEST(TestMockPredicateBehavesCorrectly)
    {
        RunTestIfNameIs predicate("pass");

        Test pass("pass");
        Test fail("fail");

        CHECK(predicate(&pass));
        CHECK(!predicate(&fail));
    }

    TEST_FIXTURE(TestRunnerFixture, TestRunnerRunsTestsThatPassPredicate)
    {
        Test should_run("goodtest");
        list.Add(&should_run);

        Test should_not_run("badtest");
        list.Add(&should_not_run);

        RunTestsIf(list, NULL, RunTestIfNameIs("goodtest"), 0);
        CHECK_EQUAL(1, reporter.testRunCount);
        CHECK_EQUAL("goodtest", reporter.lastStartedTest);
    }

    TEST_FIXTURE(TestRunnerFixture, TestRunnerOnlyRunsTestsInSpecifiedSuiteAndThatPassPredicate)
    {
        Test runningTest1("goodtest", "suite");
        Test skippedTest2("goodtest");
        Test skippedTest3("badtest", "suite");
        Test skippedTest4("badtest");

        list.Add(&runningTest1);
        list.Add(&skippedTest2);
        list.Add(&skippedTest3);
        list.Add(&skippedTest4);

        RunTestsIf(list, "suite", RunTestIfNameIs("goodtest"), 0);

        CHECK_EQUAL(1, reporter.testRunCount);
        CHECK_EQUAL("goodtest", reporter.lastStartedTest);
        CHECK_EQUAL("suite", reporter.lastStartedSuite);
    }

}<commit_msg>Reformatted code from #54.<commit_after>#include "UnitTest++/UnitTestPP.h"
#include "RecordingReporter.h"
#include "UnitTest++/ReportAssert.h"
#include "UnitTest++/TestList.h"
#include "UnitTest++/TimeHelpers.h"
#include "UnitTest++/TimeConstraint.h"
#include "UnitTest++/ReportAssertImpl.h"

using namespace UnitTest;

namespace
{

    struct MockTest : public Test
    {
        MockTest(char const* testName, bool const success_, bool const assert_, int const count_ = 1)
        : Test(testName)
        , success(success_)
        , asserted(assert_)
        , count(count_)
        {
        }

        virtual void RunImpl() const
        {
            TestResults& testResults_ = *CurrentTest::Results();

            for (int i=0; i < count; ++i)
            {
                if (asserted)
                {
                    ReportAssert("desc", "file", 0);
                }
                else if (!success)
                {
                    testResults_.OnTestFailure(m_details, "message");
                }
            }
        }

        bool const success;
        bool const asserted;
        int const count;
    };

    struct FixtureBase
    {
        FixtureBase()
        : runner(reporter)
        {
        }

        template <class Predicate>
        int RunTestsIf(TestList const& list, char const* suiteName,
                       const Predicate& predicate, int maxTestTimeInMs)
        {
            TestResults* oldResults = CurrentTest::Results();
            const TestDetails* oldDetails = CurrentTest::Details();
            int result = runner.RunTestsIf(list, suiteName, predicate, maxTestTimeInMs);
            CurrentTest::Results() = oldResults;
            CurrentTest::Details() = oldDetails;
            return result;
        }

        TestRunner runner;
        RecordingReporter reporter;
    };

    struct TestRunnerFixture : public FixtureBase
    {
        TestList list;
    };

    TEST_FIXTURE(TestRunnerFixture, TestStartIsReportedCorrectly)
    {
        MockTest test("goodtest", true, false);
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(1, reporter.testRunCount);
        CHECK_EQUAL("goodtest", reporter.lastStartedTest);
    }

    TEST_FIXTURE(TestRunnerFixture, TestFinishIsReportedCorrectly)
    {
        MockTest test("goodtest", true, false);
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(1, reporter.testFinishedCount);
        CHECK_EQUAL("goodtest", reporter.lastFinishedTest);
    }

    class SlowTest : public Test
    {
    public:
        SlowTest()
        : Test("slow", "somesuite", "filename", 123)
        {
        }

        virtual void RunImpl() const
        {
            TimeHelpers::SleepMs(20);
        }
    };

    TEST_FIXTURE(TestRunnerFixture, TestFinishIsCalledWithCorrectTime)
    {
        SlowTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK(reporter.lastFinishedTestTime >= 0.005f && reporter.lastFinishedTestTime <= 0.050f);
    }

    TEST_FIXTURE(TestRunnerFixture, FailureCountIsZeroWhenNoTestsAreRun)
    {
        CHECK_EQUAL(0, RunTestsIf(list, NULL, True(), 0));
        CHECK_EQUAL(0, reporter.testRunCount);
        CHECK_EQUAL(0, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, CallsReportFailureOncePerFailingTest)
    {
        MockTest test1("test", false, false);
        list.Add(&test1);
        MockTest test2("test", true, false);
        list.Add(&test2);
        MockTest test3("test", false, false);
        list.Add(&test3);

        CHECK_EQUAL(2, RunTestsIf(list, NULL, True(), 0));
        CHECK_EQUAL(2, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, TestsThatAssertAreReportedAsFailing)
    {
        MockTest test("test", true, true);
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(1, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfTestCount)
    {
        MockTest test1("test", true, false);
        MockTest test2("test", true, false);
        MockTest test3("test", true, false);
        list.Add(&test1);
        list.Add(&test2);
        list.Add(&test3);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(3, reporter.summaryTotalTestCount);
    }

    TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfFailedTests)
    {
        MockTest test1("test", false, false, 2);
        MockTest test2("test", true, false);
        MockTest test3("test", false, false, 3);
        list.Add(&test1);
        list.Add(&test2);
        list.Add(&test3);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(2, reporter.summaryFailedTestCount);
    }

    TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfFailures)
    {
        MockTest test1("test", false, false, 2);
        MockTest test2("test", true, false);
        MockTest test3("test", false, false, 3);
        list.Add(&test1);
        list.Add(&test2);
        list.Add(&test3);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(5, reporter.summaryFailureCount);
    }

    TEST_FIXTURE(TestRunnerFixture, SlowTestPassesForHighTimeThreshold)
    {
        SlowTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(0, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, SlowTestFailsForLowTimeThreshold)
    {
        SlowTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 3);
        CHECK_EQUAL(1, reporter.testFailedCount);
    }

    TEST_FIXTURE(TestRunnerFixture, SlowTestHasCorrectFailureInformation)
    {
        SlowTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 3);

        using namespace std;

        CHECK_EQUAL(test.m_details.testName, reporter.lastFailedTest);
        CHECK(strstr(test.m_details.filename, reporter.lastFailedFile));
        CHECK_EQUAL(test.m_details.lineNumber, reporter.lastFailedLine);

        CHECK(strstr(reporter.lastFailedMessage, "Global time constraint failed"));
        CHECK(strstr(reporter.lastFailedMessage, "3ms"));
    }

    TEST_FIXTURE(TestRunnerFixture, SlowTestWithTimeExemptionPasses)
    {
        class SlowExemptedTest : public Test
        {
        public:
            SlowExemptedTest() : Test("slowexempted", "", 0) {}
            virtual void RunImpl() const
            {
                UNITTEST_TIME_CONSTRAINT_EXEMPT();
                TimeHelpers::SleepMs(20);
            }
        };

        SlowExemptedTest test;
        list.Add(&test);

        RunTestsIf(list, NULL, True(), 3);
        CHECK_EQUAL(0, reporter.testFailedCount);
    }

    struct TestSuiteFixture : FixtureBase
    {
        TestSuiteFixture()
        : test1("TestInDefaultSuite")
        , test2("TestInOtherSuite", "OtherSuite")
        , test3("SecondTestInDefaultSuite")
        {
            list.Add(&test1);
            list.Add(&test2);
        }

        Test test1;
        Test test2;
        Test test3;
        TestList list;
    };

    TEST_FIXTURE(TestSuiteFixture, TestRunnerRunsAllSuitesIfNullSuiteIsPassed)
    {
        RunTestsIf(list, NULL, True(), 0);
        CHECK_EQUAL(2, reporter.summaryTotalTestCount);
    }

    TEST_FIXTURE(TestSuiteFixture,TestRunnerRunsOnlySpecifiedSuite)
    {
        RunTestsIf(list, "OtherSuite", True(), 0);
        CHECK_EQUAL(1, reporter.summaryTotalTestCount);
        CHECK_EQUAL("TestInOtherSuite", reporter.lastFinishedTest);
    }

    struct RunTestIfNameIs
    {
        RunTestIfNameIs(char const* name_)
        : name(name_)
        {
        }

        bool operator()(const Test* const test) const
        {
            using namespace std;
            return (0 == strcmp(test->m_details.testName, name));
        }

        char const* name;
    };

    TEST(TestMockPredicateBehavesCorrectly)
    {
        RunTestIfNameIs predicate("pass");

        Test pass("pass");
        Test fail("fail");

        CHECK(predicate(&pass));
        CHECK(!predicate(&fail));
    }

    TEST_FIXTURE(TestRunnerFixture, TestRunnerRunsTestsThatPassPredicate)
    {
        Test should_run("goodtest");
        list.Add(&should_run);

        Test should_not_run("badtest");
        list.Add(&should_not_run);

        RunTestsIf(list, NULL, RunTestIfNameIs("goodtest"), 0);
        CHECK_EQUAL(1, reporter.testRunCount);
        CHECK_EQUAL("goodtest", reporter.lastStartedTest);
    }

    TEST_FIXTURE(TestRunnerFixture, TestRunnerOnlyRunsTestsInSpecifiedSuiteAndThatPassPredicate)
    {
        Test runningTest1("goodtest", "suite");
        Test skippedTest2("goodtest");
        Test skippedTest3("badtest", "suite");
        Test skippedTest4("badtest");

        list.Add(&runningTest1);
        list.Add(&skippedTest2);
        list.Add(&skippedTest3);
        list.Add(&skippedTest4);

        RunTestsIf(list, "suite", RunTestIfNameIs("goodtest"), 0);

        CHECK_EQUAL(1, reporter.testRunCount);
        CHECK_EQUAL("goodtest", reporter.lastStartedTest);
        CHECK_EQUAL("suite", reporter.lastStartedSuite);
    }

}<|endoftext|>