<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_Optional_inl_
#define _Stroika_Foundation_Memory_Optional_inl_    1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include   "../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Memory {

            /*
             ********************************************************************************
             ********************************** Optional<T> *********************************
             ********************************************************************************
             */
            template    <typename T>
            inline  Optional<T>::Optional ()
                : fValue_ (nullptr)
            {
            }
            template    <typename T>
            inline  Optional<T>::Optional (const T& from)
                : fValue_ (new BlockAllocated<T> (from))
            {
            }
            template    <typename T>
            inline  Optional<T>::Optional (T && from)
                : fValue_ (new BlockAllocated<T> (std::move (from)))
            {
            }
            template    <typename T>
            inline  Optional<T>::Optional (const Optional<T>& from)
                : fValue_ (from.fValue_ == nullptr ? nullptr : new BlockAllocated<T> (*from.fValue_))
            {
            }
            template    <typename T>
            inline  Optional<T>::Optional (Optional<T> && from)
                : fValue_ (from.fValue_)
            {
                from.fValue_ = nullptr;
            }
            template    <typename T>
            inline  Optional<T>::~Optional ()
            {
                delete fValue_;
            }
            template    <typename T>
            inline  Optional<T>&   Optional<T>::operator= (const T& from)
            {
                delete fValue_;
                fValue_ = nullptr;
                fValue_ = new BlockAllocated<T> (from);
                return *this;
            }
            template    <typename T>
            inline  Optional<T>&   Optional<T>::operator= (T && from)
            {
                fValue_ = new BlockAllocated<T> (std::move (from));
                return *this;
            }
            template    <typename T>
            inline  Optional<T>&   Optional<T>::operator= (const Optional<T>& from)
            {
                delete fValue_;
                fValue_ = nullptr;
                if (from.fValue_ != nullptr) {
                    fValue_ = new BlockAllocated<T> (*from.fValue_);
                }
                return *this;
            }
            template    <typename T>
            inline  Optional<T>&   Optional<T>::operator= (Optional<T> && from)
            {
                fValue_ = from.fValue_;
                from.fValue_ = nullptr;
                return *this;
            }
            template    <typename T>
            inline  void    Optional<T>::clear ()
            {
                delete fValue_;
                fValue_ = nullptr;
            }
            template    <typename T>
            inline  const T*    Optional<T>::get () const
            {
                return fValue_;
            }
            template    <typename T>
            inline  bool    Optional<T>::empty () const
            {
                return fValue_ == nullptr;
            }
            template    <typename T>
            inline  const T* Optional<T>::operator-> () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return fValue_->get ();
            }
            template    <typename T>
            inline  T* Optional<T>::operator-> ()
            {
                Require (not empty ());
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return fValue_->get ();
            }
            template    <typename T>
            inline  const T& Optional<T>::operator* () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return *fValue_->get ();
            }
            template    <typename T>
            inline  T& Optional<T>::operator* ()
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return *fValue_->get ();
            }
            template    <typename T>
            inline  Optional<T>::operator T () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                return *fValue_;
            }
            template    <typename T>
            bool    Optional<T>::operator< (const Optional<T>& rhs) const
            {
                if (fValue_ == nullptr) {
                    return (rhs.fValue_ == nullptr) ? false : true; // arbitrary choice - but assume if lhs is empty thats less than any T value
                }
                if (rhs.fValue_ == nullptr) {
                    return false;
                }
                return *fValue_ < *rhs.fValue_;
            }
            template    <typename T>
            bool    Optional<T>::operator<= (const Optional<T>& rhs) const
            {
                return *this < rhs or * this == rhs;
            }
            template    <typename T>
            inline  bool    Optional<T>::operator> (const Optional<T>& rhs) const
            {
                return rhs < *this;
            }
            template    <typename T>
            bool    Optional<T>::operator>= (const Optional<T>& rhs) const
            {
                return *this > rhs or * this == rhs;
            }
            template    <typename T>
            bool    Optional<T>::operator== (const Optional<T>& rhs) const
            {
                if (fValue_ == nullptr) {
                    return rhs.fValue_ == nullptr;
                }
                if (rhs.fValue_ == nullptr) {
                    return false;
                }
                return *fValue_ == *rhs.fValue_;
            }
            template    <typename T>
            inline  bool    Optional<T>::operator!= (const Optional<T>& rhs) const
            {
                return not (*this == rhs);
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Memory_Optional_inl_*/
<commit_msg>minor fix to Optional<T><commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_Optional_inl_
#define _Stroika_Foundation_Memory_Optional_inl_    1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include   "../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Memory {

            /*
             ********************************************************************************
             ********************************** Optional<T> *********************************
             ********************************************************************************
             */
            template    <typename T>
            inline  Optional<T>::Optional ()
                : fValue_ (nullptr)
            {
            }
            template    <typename T>
            inline  Optional<T>::Optional (const T& from)
                : fValue_ (new BlockAllocated<T> (from))
            {
            }
            template    <typename T>
            inline  Optional<T>::Optional (T && from)
                : fValue_ (new BlockAllocated<T> (std::move (from)))
            {
            }
            template    <typename T>
            inline  Optional<T>::Optional (const Optional<T>& from)
                : fValue_ (from.fValue_ == nullptr ? nullptr : new BlockAllocated<T> (*from.fValue_))
            {
            }
            template    <typename T>
            inline  Optional<T>::Optional (Optional<T> && from)
                : fValue_ (from.fValue_)
            {
                from.fValue_ = nullptr;
            }
            template    <typename T>
            inline  Optional<T>::~Optional ()
            {
                delete fValue_;
            }
            template    <typename T>
            inline  Optional<T>&   Optional<T>::operator= (const T& from)
            {
                delete fValue_;
                fValue_ = nullptr;
                fValue_ = new BlockAllocated<T> (from);
                return *this;
            }
            template    <typename T>
            inline  Optional<T>&   Optional<T>::operator= (T && from)
            {
                fValue_ = new BlockAllocated<T> (std::move (from));
                return *this;
            }
            template    <typename T>
            inline  Optional<T>&   Optional<T>::operator= (const Optional<T>& from)
            {
                delete fValue_;
                fValue_ = nullptr;
                if (from.fValue_ != nullptr) {
                    fValue_ = new BlockAllocated<T> (*from.fValue_);
                }
                return *this;
            }
            template    <typename T>
            inline  Optional<T>&   Optional<T>::operator= (Optional<T> && from)
            {
                fValue_ = from.fValue_;
                from.fValue_ = nullptr;
                return *this;
            }
            template    <typename T>
            inline  void    Optional<T>::clear ()
            {
                delete fValue_;
                fValue_ = nullptr;
            }
            template    <typename T>
            inline  const T*    Optional<T>::get () const
            {
                return fValue_ == nullptr ? nullptr : fValue_->get ();
            }
            template    <typename T>
            inline  bool    Optional<T>::empty () const
            {
                return fValue_ == nullptr;
            }
            template    <typename T>
            inline  const T* Optional<T>::operator-> () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return fValue_->get ();
            }
            template    <typename T>
            inline  T* Optional<T>::operator-> ()
            {
                Require (not empty ());
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return fValue_->get ();
            }
            template    <typename T>
            inline  const T& Optional<T>::operator* () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return *fValue_->get ();
            }
            template    <typename T>
            inline  T& Optional<T>::operator* ()
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                EnsureNotNull (fValue_->get ());
                return *fValue_->get ();
            }
            template    <typename T>
            inline  Optional<T>::operator T () const
            {
                Require (not empty ())
                AssertNotNull (fValue_);
                return *fValue_;
            }
            template    <typename T>
            bool    Optional<T>::operator< (const Optional<T>& rhs) const
            {
                if (fValue_ == nullptr) {
                    return (rhs.fValue_ == nullptr) ? false : true; // arbitrary choice - but assume if lhs is empty thats less than any T value
                }
                if (rhs.fValue_ == nullptr) {
                    return false;
                }
                return *fValue_ < *rhs.fValue_;
            }
            template    <typename T>
            bool    Optional<T>::operator<= (const Optional<T>& rhs) const
            {
                return *this < rhs or * this == rhs;
            }
            template    <typename T>
            inline  bool    Optional<T>::operator> (const Optional<T>& rhs) const
            {
                return rhs < *this;
            }
            template    <typename T>
            bool    Optional<T>::operator>= (const Optional<T>& rhs) const
            {
                return *this > rhs or * this == rhs;
            }
            template    <typename T>
            bool    Optional<T>::operator== (const Optional<T>& rhs) const
            {
                if (fValue_ == nullptr) {
                    return rhs.fValue_ == nullptr;
                }
                if (rhs.fValue_ == nullptr) {
                    return false;
                }
                return *fValue_ == *rhs.fValue_;
            }
            template    <typename T>
            inline  bool    Optional<T>::operator!= (const Optional<T>& rhs) const
            {
                return not (*this == rhs);
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Memory_Optional_inl_*/
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMultiThreaderTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkConfigure.h"
#include "itkMultiThreader.h"

int itkMultiThreaderTest(int argc, char* argv[])
{
  // Choose a number of threads.
  int numberOfThreads = 10;
  if( argc > 1 )
    {
    const int nt = atoi( argv[1] );
    if(nt > 1)
      {
      numberOfThreads = nt;
      }
    }

  itk::MultiThreader::Pointer    threader = itk::MultiThreader::New();

  itk::MultiThreader::SetGlobalDefaultNumberOfThreads( numberOfThreads );

  return EXIT_SUCCESS;
}

namespace itkMultiThreaderTestHelpers
{

void ThreadedMethod()
{

#ifdef ITK_USE_PTHREADS
// ThreadProcessIDType threadId = pthread_self();
#endif

#ifdef ITK_USE_WIN32_THREADS
// ThreadProcessIDType threadId = GetCurrentThread();
#endif

#ifdef ITK_USE_SPROC
// const ThreadProcessIDType threadId = GetCurrentThread()  ??;
#endif

}

} // end of itkMultiThreaderTestHelpers
<commit_msg>BUG: 0008357. Adding test cases for the global variable relationships that were      not treated properly, according to bug 0008357.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMultiThreaderTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkConfigure.h"
#include "itkMultiThreader.h"

bool VerifyRange(int value, int min, int max, const char * msg)
{
  if( value < min )
    {
    std::cerr << msg << std::endl;
    return false;
    }

  if( value > max )
    {
    std::cerr << msg << std::endl;
    return false;
    }
  return true;
}

bool SetAndVerifyGlobalMaximumNumberOfThreads( int value )
{
  itk::MultiThreader::SetGlobalMaximumNumberOfThreads( value );
  return VerifyRange( itk::MultiThreader::GetGlobalMaximumNumberOfThreads(),
        1, ITK_MAX_THREADS, "Range error in MaximumNumberOfThreads");
}

bool SetAndVerifyGlobalDefaultNumberOfThreads( int value )
{
  itk::MultiThreader::SetGlobalDefaultNumberOfThreads( value );
  return VerifyRange( itk::MultiThreader::GetGlobalDefaultNumberOfThreads(),
        1, itk::MultiThreader::GetGlobalMaximumNumberOfThreads(),
        "Range error in DefaultNumberOfThreads");
}

bool SetAndVerifyNumberOfThreads( int value, itk::MultiThreader * threader )
{
  threader->SetNumberOfThreads( value );
  return VerifyRange( threader->GetNumberOfThreads(),
        1, itk::MultiThreader::GetGlobalMaximumNumberOfThreads(),
        "Range error in NumberOfThreads");
}

int itkMultiThreaderTest(int argc, char* argv[])
{
  // Choose a number of threads.
  int numberOfThreads = 10;
  if( argc > 1 )
    {
    const int nt = atoi( argv[1] );
    if(nt > 1)
      {
      numberOfThreads = nt;
      }
    }

  itk::MultiThreader::Pointer    threader = itk::MultiThreader::New();

  itk::MultiThreader::SetGlobalDefaultNumberOfThreads( numberOfThreads );

  {
  // Test settings for GlobalMaximumNumberOfThreads

  bool result = true;

  result &= SetAndVerifyGlobalMaximumNumberOfThreads( -1 );
  result &= SetAndVerifyGlobalMaximumNumberOfThreads(  0 );
  result &= SetAndVerifyGlobalMaximumNumberOfThreads(  1 );
  result &= SetAndVerifyGlobalMaximumNumberOfThreads(  2 );
  result &= SetAndVerifyGlobalMaximumNumberOfThreads(  ITK_MAX_THREADS  );
  result &= SetAndVerifyGlobalMaximumNumberOfThreads(  ITK_MAX_THREADS - 1 );
  result &= SetAndVerifyGlobalMaximumNumberOfThreads(  ITK_MAX_THREADS + 1 );

  if( !result )
    {
    return EXIT_FAILURE;
    }

  result &= SetAndVerifyGlobalDefaultNumberOfThreads( -1 );
  result &= SetAndVerifyGlobalDefaultNumberOfThreads(  0 );
  result &= SetAndVerifyGlobalDefaultNumberOfThreads(  1 );
  result &= SetAndVerifyGlobalDefaultNumberOfThreads( itk::MultiThreader::GetGlobalMaximumNumberOfThreads() );
  result &= SetAndVerifyGlobalDefaultNumberOfThreads( itk::MultiThreader::GetGlobalMaximumNumberOfThreads() - 1 );
  result &= SetAndVerifyGlobalDefaultNumberOfThreads( itk::MultiThreader::GetGlobalMaximumNumberOfThreads() + 1 );

  if( !result )
    {
    return EXIT_FAILURE;
    }

  itk::MultiThreader::Pointer threader = itk::MultiThreader::New();

  result &= SetAndVerifyNumberOfThreads( -1, threader );
  result &= SetAndVerifyNumberOfThreads(  0, threader );
  result &= SetAndVerifyNumberOfThreads(  1, threader );
  result &= SetAndVerifyNumberOfThreads( itk::MultiThreader::GetGlobalMaximumNumberOfThreads(), threader );
  result &= SetAndVerifyNumberOfThreads( itk::MultiThreader::GetGlobalMaximumNumberOfThreads() - 1, threader);
  result &= SetAndVerifyNumberOfThreads( itk::MultiThreader::GetGlobalMaximumNumberOfThreads() + 1, threader);

  if( !result )
    {
    return EXIT_FAILURE;
    }

  }

  return EXIT_SUCCESS;
}

namespace itkMultiThreaderTestHelpers
{

void ThreadedMethod()
{

#ifdef ITK_USE_PTHREADS
// ThreadProcessIDType threadId = pthread_self();
#endif

#ifdef ITK_USE_WIN32_THREADS
// ThreadProcessIDType threadId = GetCurrentThread();
#endif

#ifdef ITK_USE_SPROC
// const ThreadProcessIDType threadId = GetCurrentThread()  ??;
#endif

}

} // end of itkMultiThreaderTestHelpers
<|endoftext|>


<commit_before>#include "../../DataStructures/StaticRTree.h"
#include "../../DataStructures/QueryNode.h"
#include "../../DataStructures/EdgeBasedNode.h"
#include "../../Include/osrm/Coordinate.h"
#include "../../typedefs.h"

#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>

#include <random>
#include <unordered_set>

BOOST_AUTO_TEST_SUITE(static_rtree)

constexpr uint32_t TEST_BRANCHING_FACTOR = 8;
constexpr uint32_t TEST_LEAF_NODE_SIZE   = 64;

typedef EdgeBasedNode TestData;
typedef StaticRTree<TestData,
                    std::vector<FixedPointCoordinate>,
                    false,
                    TEST_BRANCHING_FACTOR,
                    TEST_LEAF_NODE_SIZE>
        TestStaticRTree;

// Choosen by a fair W20 dice roll (this value is completely arbitrary)
constexpr unsigned RANDOM_SEED = 15;
constexpr int32_t WORLD_MIN_LAT = -90*COORDINATE_PRECISION;
constexpr int32_t WORLD_MAX_LAT = 90*COORDINATE_PRECISION;
constexpr int32_t WORLD_MIN_LON = -180*COORDINATE_PRECISION;
constexpr int32_t WORLD_MAX_LON = 180*COORDINATE_PRECISION;

class LinearSearchNN
{
public:
    LinearSearchNN(const std::shared_ptr<std::vector<FixedPointCoordinate>>& coords,
                   const std::vector<TestData>& edges)
    : coords(coords)
    , edges(edges)
    { }

    bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
                                            FixedPointCoordinate &result_coordinate,
                                            const unsigned zoom_level)
    {
        bool ignore_tiny_components = (zoom_level <= 14);

        float min_dist = std::numeric_limits<float>::max();
        FixedPointCoordinate min_coord;
        for (const TestData& e : edges)
        {
            if (ignore_tiny_components && e.is_in_tiny_cc)
                continue;

            const FixedPointCoordinate& start = coords->at(e.u);
            const FixedPointCoordinate& end = coords->at(e.v);
            float distance = FixedPointCoordinate::ApproximateEuclideanDistance(
                        input_coordinate.lat,
                        input_coordinate.lon,
                        start.lat,
                        start.lon);
            if (distance < min_dist)
            {
                min_coord = start;
                min_dist = distance;
            }

            distance = FixedPointCoordinate::ApproximateEuclideanDistance(
                        input_coordinate.lat,
                        input_coordinate.lon,
                        end.lat,
                        end.lon);
            if (distance < min_dist)
            {
                min_coord = end;
                min_dist = distance;
            }
        }

        result_coordinate = min_coord;
        return result_coordinate.isValid();
    }

    bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
                                      PhantomNode &result_phantom_node,
                                      const unsigned zoom_level)
    {
        bool ignore_tiny_components = (zoom_level <= 14);

        float min_dist = std::numeric_limits<float>::max();
        TestData nearest_edge;
        for (const TestData& e : edges)
        {
            if (ignore_tiny_components && e.is_in_tiny_cc)
                continue;

            float current_ratio = 0.;
            FixedPointCoordinate nearest;
            const float current_perpendicular_distance =
                FixedPointCoordinate::ComputePerpendicularDistance(
                        coords->at(e.u),
                        coords->at(e.v),
                        input_coordinate,
                        nearest,
                        current_ratio);

            if ((current_perpendicular_distance < min_dist) &&
                !EpsilonCompare(current_perpendicular_distance, min_dist))
            { // found a new minimum
                min_dist = current_perpendicular_distance;
                result_phantom_node = { e.forward_edge_based_node_id,
                    e.reverse_edge_based_node_id,
                    e.name_id,
                    e.forward_weight,
                    e.reverse_weight,
                    e.forward_offset,
                    e.reverse_offset,
                    e.packed_geometry_id,
                    nearest,
                    e.fwd_segment_position};
                nearest_edge = e;
            }
        }

        if (result_phantom_node.location.isValid())
        {
            // Hack to fix rounding errors and wandering via nodes.
            if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon))
            {
                result_phantom_node.location.lon = input_coordinate.lon;
            }
            if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat))
            {
                result_phantom_node.location.lat = input_coordinate.lat;
            }

            const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
                coords->at(nearest_edge.u),
                result_phantom_node.location);
            const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
                coords->at(nearest_edge.u),
                coords->at(nearest_edge.v));
            const float ratio = std::min(1.f, distance_1 / distance_2);

            if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
            {
                result_phantom_node.forward_weight *= ratio;
            }
            if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
            {
                result_phantom_node.reverse_weight *= (1. - ratio);
            }
        }

        return result_phantom_node.location.isValid();
    }

    template<typename FloatT>
    inline bool EpsilonCompare(const FloatT d1, const FloatT d2) const
    {
        return (std::abs(d1 - d2) < std::numeric_limits<FloatT>::epsilon());
    }

private:
    const std::shared_ptr<std::vector<FixedPointCoordinate>>& coords;
    const std::vector<TestData>& edges;
};

template<unsigned NUM_NODES, unsigned NUM_EDGES,
         int32_t MIN_LON=WORLD_MIN_LON,
         int32_t MAX_LON=WORLD_MAX_LON,
         int32_t MIN_LAT=WORLD_MIN_LAT,
         int32_t MAX_LAT=WORLD_MAX_LAT>
struct RandomGraphFixture
{
    struct TupleHash
    {
        typedef std::pair<unsigned, unsigned>    argument_type;
        typedef std::size_t                      result_type;

        result_type operator()(const argument_type & t) const
        {
            std::size_t val { 0 };
            boost::hash_combine(val, t.first);
            boost::hash_combine(val, t.second);
            return val;
        }
    };

    RandomGraphFixture()
    : coords(std::make_shared<std::vector<FixedPointCoordinate>>())
    {
        BOOST_TEST_MESSAGE("Constructing " << NUM_NODES << " nodes and " << NUM_EDGES << " edges.");

        std::mt19937 g(RANDOM_SEED);

        std::uniform_int_distribution<> lat_udist(MIN_LAT, MAX_LAT);
        std::uniform_int_distribution<> lon_udist(MIN_LON, MAX_LON);

        for (unsigned i = 0; i < NUM_NODES; i++)
        {
            int lat = lat_udist(g);
            int lon = lon_udist(g);
            nodes.emplace_back(NodeInfo(lat, lon, i));
            coords->emplace_back(FixedPointCoordinate(lat, lon));
        }

        std::uniform_int_distribution<> edge_udist(0, nodes.size() - 1);

        std::unordered_set<std::pair<unsigned, unsigned>, TupleHash> used_edges;

        while(edges.size() < NUM_EDGES)
        {
            TestData data;
            data.u = edge_udist(g);
            data.v = edge_udist(g);
            if (used_edges.find(std::pair<unsigned, unsigned>(std::min(data.u, data.v), std::max(data.u, data.v))) == used_edges.end())
            {
                data.is_in_tiny_cc = false;
                edges.emplace_back(data);
                used_edges.emplace(std::min(data.u, data.v), std::max(data.u, data.v));
            }
        }

    }

    std::vector<NodeInfo> nodes;
    std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
    std::vector<TestData> edges;
};

typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*3,  TEST_LEAF_NODE_SIZE/2>  TestRandomGraphFixture_LeafHalfFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*5,  TEST_LEAF_NODE_SIZE>    TestRandomGraphFixture_LeafFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*10, TEST_LEAF_NODE_SIZE*2> TestRandomGraphFixture_TwoLeaves;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*TEST_BRANCHING_FACTOR*3,
                           TEST_LEAF_NODE_SIZE*TEST_BRANCHING_FACTOR> TestRandomGraphFixture_Branch;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*TEST_BRANCHING_FACTOR*3,
                           TEST_LEAF_NODE_SIZE*TEST_BRANCHING_FACTOR*2> TestRandomGraphFixture_MultipleLevels;

void simple_verify_rtree(TestStaticRTree& rtree, const std::shared_ptr<std::vector<FixedPointCoordinate>>& coords, const std::vector<TestData>& edges)
{
    BOOST_TEST_MESSAGE("Verify end points");
    for (const auto& e : edges)
    {
        FixedPointCoordinate result_u, result_v;
        const FixedPointCoordinate& pu = coords->at(e.u);
        const FixedPointCoordinate& pv = coords->at(e.v);
        bool found_u = rtree.LocateClosestEndPointForCoordinate(pu, result_u, 1);
        bool found_v = rtree.LocateClosestEndPointForCoordinate(pv, result_v, 1);
        BOOST_CHECK(found_u && found_v);
        float dist_u = FixedPointCoordinate::ApproximateEuclideanDistance(
                result_u.lat,
                result_u.lon,
                pu.lat,
                pu.lon);
        BOOST_CHECK_LE(dist_u, std::numeric_limits<float>::epsilon());
        float dist_v = FixedPointCoordinate::ApproximateEuclideanDistance(
                result_v.lat,
                result_v.lon,
                pv.lat,
                pv.lon);
        BOOST_CHECK_LE(dist_v, std::numeric_limits<float>::epsilon());
    }
}

void sampling_verify_rtree(TestStaticRTree& rtree, LinearSearchNN& lsnn, unsigned num_samples)
{
    std::mt19937 g(RANDOM_SEED);
    std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
    std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
    std::vector<FixedPointCoordinate> queries;
    for (unsigned i = 0; i < num_samples; i++)
    {
        queries.emplace_back(
            FixedPointCoordinate(lat_udist(g), lon_udist(g))
        );
    }

    BOOST_TEST_MESSAGE("Sampling queries");
    for (const auto& q : queries)
    {
        FixedPointCoordinate result_rtree;
        rtree.LocateClosestEndPointForCoordinate(q, result_rtree, 1);
        FixedPointCoordinate result_ln;
        lsnn.LocateClosestEndPointForCoordinate(q, result_ln, 1);
        BOOST_CHECK_EQUAL(result_ln, result_rtree);

        PhantomNode phantom_rtree;
        rtree.FindPhantomNodeForCoordinate(q, phantom_rtree, 1);
        PhantomNode phantom_ln;
        lsnn.FindPhantomNodeForCoordinate(q, phantom_ln, 1);
        BOOST_CHECK_EQUAL(phantom_rtree, phantom_ln);
    }
}

template<typename FixtureT>
void construction_test(const std::string& prefix, FixtureT* fixture)
{
    const std::string nodes_path = prefix + ".ramIndex";
    const std::string leaves_path = prefix + ".fileIndex";
    const std::string coords_path = prefix + ".nodes";

    boost::filesystem::ofstream node_stream(coords_path, std::ios::binary);
    const unsigned num_nodes = fixture->nodes.size();
    node_stream.write((char *)&num_nodes, sizeof(unsigned));
    node_stream.write((char *)&(fixture->nodes[0]), num_nodes * sizeof(NodeInfo));
    node_stream.close();

    TestStaticRTree::Build(fixture->edges, nodes_path, leaves_path, fixture->nodes);
    TestStaticRTree rtree_querry(nodes_path, leaves_path, fixture->coords);
    LinearSearchNN lsnn(fixture->coords, fixture->edges);

    simple_verify_rtree(rtree_querry, fixture->coords, fixture->edges);
    sampling_verify_rtree(rtree_querry, lsnn, 100);
}

BOOST_FIXTURE_TEST_CASE(construct_half_leaf_test, TestRandomGraphFixture_LeafHalfFull)
{
    construction_test("test_1", this);
}

BOOST_FIXTURE_TEST_CASE(construct_full_leaf_test, TestRandomGraphFixture_LeafFull)
{
    construction_test("test_2", this);
}

BOOST_FIXTURE_TEST_CASE(construct_two_leaves_test, TestRandomGraphFixture_TwoLeaves)
{
    construction_test("test_3", this);
}

BOOST_FIXTURE_TEST_CASE(construct_branch_test, TestRandomGraphFixture_Branch)
{
    construction_test("test_4", this);
}

BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_MultipleLevels)
{
    construction_test("test_5", this);
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>Add regression test for 'gap' querry bug<commit_after>#include "../../DataStructures/StaticRTree.h"
#include "../../DataStructures/QueryNode.h"
#include "../../DataStructures/EdgeBasedNode.h"
#include "../../Include/osrm/Coordinate.h"
#include "../../typedefs.h"

#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>

#include <random>
#include <unordered_set>

BOOST_AUTO_TEST_SUITE(static_rtree)

constexpr uint32_t TEST_BRANCHING_FACTOR = 8;
constexpr uint32_t TEST_LEAF_NODE_SIZE   = 64;

typedef EdgeBasedNode TestData;
typedef StaticRTree<TestData,
                    std::vector<FixedPointCoordinate>,
                    false,
                    TEST_BRANCHING_FACTOR,
                    TEST_LEAF_NODE_SIZE>
        TestStaticRTree;

// Choosen by a fair W20 dice roll (this value is completely arbitrary)
constexpr unsigned RANDOM_SEED = 15;
constexpr int32_t WORLD_MIN_LAT = -90*COORDINATE_PRECISION;
constexpr int32_t WORLD_MAX_LAT = 90*COORDINATE_PRECISION;
constexpr int32_t WORLD_MIN_LON = -180*COORDINATE_PRECISION;
constexpr int32_t WORLD_MAX_LON = 180*COORDINATE_PRECISION;

class LinearSearchNN
{
public:
    LinearSearchNN(const std::shared_ptr<std::vector<FixedPointCoordinate>>& coords,
                   const std::vector<TestData>& edges)
    : coords(coords)
    , edges(edges)
    { }

    bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
                                            FixedPointCoordinate &result_coordinate,
                                            const unsigned zoom_level)
    {
        bool ignore_tiny_components = (zoom_level <= 14);

        float min_dist = std::numeric_limits<float>::max();
        FixedPointCoordinate min_coord;
        for (const TestData& e : edges)
        {
            if (ignore_tiny_components && e.is_in_tiny_cc)
                continue;

            const FixedPointCoordinate& start = coords->at(e.u);
            const FixedPointCoordinate& end = coords->at(e.v);
            float distance = FixedPointCoordinate::ApproximateEuclideanDistance(
                        input_coordinate.lat,
                        input_coordinate.lon,
                        start.lat,
                        start.lon);
            if (distance < min_dist)
            {
                min_coord = start;
                min_dist = distance;
            }

            distance = FixedPointCoordinate::ApproximateEuclideanDistance(
                        input_coordinate.lat,
                        input_coordinate.lon,
                        end.lat,
                        end.lon);
            if (distance < min_dist)
            {
                min_coord = end;
                min_dist = distance;
            }
        }

        result_coordinate = min_coord;
        return result_coordinate.isValid();
    }

    bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
                                      PhantomNode &result_phantom_node,
                                      const unsigned zoom_level)
    {
        bool ignore_tiny_components = (zoom_level <= 14);

        float min_dist = std::numeric_limits<float>::max();
        TestData nearest_edge;
        for (const TestData& e : edges)
        {
            if (ignore_tiny_components && e.is_in_tiny_cc)
                continue;

            float current_ratio = 0.;
            FixedPointCoordinate nearest;
            const float current_perpendicular_distance =
                FixedPointCoordinate::ComputePerpendicularDistance(
                        coords->at(e.u),
                        coords->at(e.v),
                        input_coordinate,
                        nearest,
                        current_ratio);

            if ((current_perpendicular_distance < min_dist) &&
                !EpsilonCompare(current_perpendicular_distance, min_dist))
            { // found a new minimum
                min_dist = current_perpendicular_distance;
                result_phantom_node = { e.forward_edge_based_node_id,
                    e.reverse_edge_based_node_id,
                    e.name_id,
                    e.forward_weight,
                    e.reverse_weight,
                    e.forward_offset,
                    e.reverse_offset,
                    e.packed_geometry_id,
                    nearest,
                    e.fwd_segment_position};
                nearest_edge = e;
            }
        }

        if (result_phantom_node.location.isValid())
        {
            // Hack to fix rounding errors and wandering via nodes.
            if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon))
            {
                result_phantom_node.location.lon = input_coordinate.lon;
            }
            if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat))
            {
                result_phantom_node.location.lat = input_coordinate.lat;
            }

            const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
                coords->at(nearest_edge.u),
                result_phantom_node.location);
            const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
                coords->at(nearest_edge.u),
                coords->at(nearest_edge.v));
            const float ratio = std::min(1.f, distance_1 / distance_2);

            if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
            {
                result_phantom_node.forward_weight *= ratio;
            }
            if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
            {
                result_phantom_node.reverse_weight *= (1. - ratio);
            }
        }

        return result_phantom_node.location.isValid();
    }

    template<typename FloatT>
    inline bool EpsilonCompare(const FloatT d1, const FloatT d2) const
    {
        return (std::abs(d1 - d2) < std::numeric_limits<FloatT>::epsilon());
    }

private:
    const std::shared_ptr<std::vector<FixedPointCoordinate>>& coords;
    const std::vector<TestData>& edges;
};

template<unsigned NUM_NODES, unsigned NUM_EDGES,
         int32_t MIN_LON=WORLD_MIN_LON,
         int32_t MAX_LON=WORLD_MAX_LON,
         int32_t MIN_LAT=WORLD_MIN_LAT,
         int32_t MAX_LAT=WORLD_MAX_LAT>
struct RandomGraphFixture
{
    struct TupleHash
    {
        typedef std::pair<unsigned, unsigned>    argument_type;
        typedef std::size_t                      result_type;

        result_type operator()(const argument_type & t) const
        {
            std::size_t val { 0 };
            boost::hash_combine(val, t.first);
            boost::hash_combine(val, t.second);
            return val;
        }
    };

    RandomGraphFixture()
    : coords(std::make_shared<std::vector<FixedPointCoordinate>>())
    {
        BOOST_TEST_MESSAGE("Constructing " << NUM_NODES << " nodes and " << NUM_EDGES << " edges.");

        std::mt19937 g(RANDOM_SEED);

        std::uniform_int_distribution<> lat_udist(MIN_LAT, MAX_LAT);
        std::uniform_int_distribution<> lon_udist(MIN_LON, MAX_LON);

        for (unsigned i = 0; i < NUM_NODES; i++)
        {
            int lat = lat_udist(g);
            int lon = lon_udist(g);
            nodes.emplace_back(NodeInfo(lat, lon, i));
            coords->emplace_back(FixedPointCoordinate(lat, lon));
        }

        std::uniform_int_distribution<> edge_udist(0, nodes.size() - 1);

        std::unordered_set<std::pair<unsigned, unsigned>, TupleHash> used_edges;

        while(edges.size() < NUM_EDGES)
        {
            TestData data;
            data.u = edge_udist(g);
            data.v = edge_udist(g);
            if (used_edges.find(std::pair<unsigned, unsigned>(std::min(data.u, data.v), std::max(data.u, data.v))) == used_edges.end())
            {
                data.is_in_tiny_cc = false;
                edges.emplace_back(data);
                used_edges.emplace(std::min(data.u, data.v), std::max(data.u, data.v));
            }
        }

    }

    std::vector<NodeInfo> nodes;
    std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
    std::vector<TestData> edges;
};

struct GraphFixture
{
    GraphFixture(const std::vector<std::pair<float, float>>& input_coords,
                 const std::vector<std::pair<unsigned, unsigned>>& input_edges)
    : coords(std::make_shared<std::vector<FixedPointCoordinate>>())
    {

        for (unsigned i = 0; i < input_coords.size(); i++)
        {
            FixedPointCoordinate c(input_coords[i].first * COORDINATE_PRECISION, input_coords[i].second * COORDINATE_PRECISION);
            coords->emplace_back(c);
            nodes.emplace_back(NodeInfo(c.lat, c.lon, i));
        }

        for (const auto& pair : input_edges)
        {
            TestData d;
            d.u = pair.first;
            d.v = pair.second;
            edges.emplace_back(d);
        }

    }

    std::vector<NodeInfo> nodes;
    std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
    std::vector<TestData> edges;
};

typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*3,  TEST_LEAF_NODE_SIZE/2>  TestRandomGraphFixture_LeafHalfFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*5,  TEST_LEAF_NODE_SIZE>    TestRandomGraphFixture_LeafFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*10, TEST_LEAF_NODE_SIZE*2> TestRandomGraphFixture_TwoLeaves;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*TEST_BRANCHING_FACTOR*3,
                           TEST_LEAF_NODE_SIZE*TEST_BRANCHING_FACTOR> TestRandomGraphFixture_Branch;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE*TEST_BRANCHING_FACTOR*3,
                           TEST_LEAF_NODE_SIZE*TEST_BRANCHING_FACTOR*2> TestRandomGraphFixture_MultipleLevels;

template<typename RTreeT>
void simple_verify_rtree(RTreeT& rtree, const std::shared_ptr<std::vector<FixedPointCoordinate>>& coords, const std::vector<TestData>& edges)
{
    BOOST_TEST_MESSAGE("Verify end points");
    for (const auto& e : edges)
    {
        FixedPointCoordinate result_u, result_v;
        const FixedPointCoordinate& pu = coords->at(e.u);
        const FixedPointCoordinate& pv = coords->at(e.v);
        bool found_u = rtree.LocateClosestEndPointForCoordinate(pu, result_u, 1);
        bool found_v = rtree.LocateClosestEndPointForCoordinate(pv, result_v, 1);
        BOOST_CHECK(found_u && found_v);
        float dist_u = FixedPointCoordinate::ApproximateEuclideanDistance(
                result_u.lat,
                result_u.lon,
                pu.lat,
                pu.lon);
        BOOST_CHECK_LE(dist_u, std::numeric_limits<float>::epsilon());
        float dist_v = FixedPointCoordinate::ApproximateEuclideanDistance(
                result_v.lat,
                result_v.lon,
                pv.lat,
                pv.lon);
        BOOST_CHECK_LE(dist_v, std::numeric_limits<float>::epsilon());
    }
}

template<typename RTreeT>
void sampling_verify_rtree(RTreeT& rtree, LinearSearchNN& lsnn, unsigned num_samples)
{
    std::mt19937 g(RANDOM_SEED);
    std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
    std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
    std::vector<FixedPointCoordinate> queries;
    for (unsigned i = 0; i < num_samples; i++)
    {
        queries.emplace_back(
            FixedPointCoordinate(lat_udist(g), lon_udist(g))
        );
    }

    BOOST_TEST_MESSAGE("Sampling queries");
    for (const auto& q : queries)
    {
        FixedPointCoordinate result_rtree;
        rtree.LocateClosestEndPointForCoordinate(q, result_rtree, 1);
        FixedPointCoordinate result_ln;
        lsnn.LocateClosestEndPointForCoordinate(q, result_ln, 1);
        BOOST_CHECK_EQUAL(result_ln, result_rtree);

        PhantomNode phantom_rtree;
        rtree.FindPhantomNodeForCoordinate(q, phantom_rtree, 1);
        PhantomNode phantom_ln;
        lsnn.FindPhantomNodeForCoordinate(q, phantom_ln, 1);
        BOOST_CHECK_EQUAL(phantom_rtree, phantom_ln);
    }
}

template<typename FixtureT, typename RTreeT=TestStaticRTree>
void build_rtree(const std::string& prefix, FixtureT* fixture, std::string& leaves_path, std::string& nodes_path)
{
    nodes_path = prefix + ".ramIndex";
    leaves_path = prefix + ".fileIndex";
    const std::string coords_path = prefix + ".nodes";

    boost::filesystem::ofstream node_stream(coords_path, std::ios::binary);
    const unsigned num_nodes = fixture->nodes.size();
    node_stream.write((char *)&num_nodes, sizeof(unsigned));
    node_stream.write((char *)&(fixture->nodes[0]), num_nodes * sizeof(NodeInfo));
    node_stream.close();

    RTreeT::Build(fixture->edges, nodes_path, leaves_path, fixture->nodes);
}

template<typename FixtureT, typename RTreeT=TestStaticRTree>
void construction_test(const std::string& prefix, FixtureT* fixture)
{
    std::string leaves_path;
    std::string nodes_path;
    build_rtree<FixtureT, RTreeT>(prefix, fixture, leaves_path, nodes_path);
    RTreeT rtree(nodes_path, leaves_path, fixture->coords);
    LinearSearchNN lsnn(fixture->coords, fixture->edges);

    simple_verify_rtree(rtree, fixture->coords, fixture->edges);
    sampling_verify_rtree(rtree, lsnn, 100);
}

BOOST_FIXTURE_TEST_CASE(construct_half_leaf_test, TestRandomGraphFixture_LeafHalfFull)
{
    construction_test("test_1", this);
}

BOOST_FIXTURE_TEST_CASE(construct_full_leaf_test, TestRandomGraphFixture_LeafFull)
{
    construction_test("test_2", this);
}

BOOST_FIXTURE_TEST_CASE(construct_two_leaves_test, TestRandomGraphFixture_TwoLeaves)
{
    construction_test("test_3", this);
}

BOOST_FIXTURE_TEST_CASE(construct_branch_test, TestRandomGraphFixture_Branch)
{
    construction_test("test_4", this);
}

BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_MultipleLevels)
{
    construction_test("test_5", this);
}

/*
 * Bug: If you querry a point that lies between two BBs that have a gap,
 * one BB will be pruned, even if it could contain a nearer match.
 */
BOOST_AUTO_TEST_CASE(regression_test)
{
    typedef std::pair<float, float> Coord;
    typedef std::pair<unsigned, unsigned> Edge;
    GraphFixture fixture({
        Coord(40.0, 0.0),
        Coord(35.0, 5.0),

        Coord(5.0, 5.0),
        Coord(0.0, 10.0),

        Coord(20.0, 10.0),
        Coord(20.0, 5.0),

        Coord(40.0, 100.0),
        Coord(35.0, 105.0),

        Coord(5.0, 105.0),
        Coord(0.0, 110.0),
    },
    {
        Edge(0, 1),
        Edge(2, 3),
        Edge(4, 5),
        Edge(6, 7),
        Edge(8, 9)
    }
    );

    typedef StaticRTree<TestData,
                    std::vector<FixedPointCoordinate>,
                    false,
                    2,
                    3> MiniStaticRTree;

    std::string leaves_path;
    std::string nodes_path;
    build_rtree<GraphFixture, MiniStaticRTree>("test_regression", &fixture, leaves_path, nodes_path);
    MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords);

    // query a node just right of the center of the gap
    FixedPointCoordinate input(20.0 * COORDINATE_PRECISION, 55.1 * COORDINATE_PRECISION);
    FixedPointCoordinate result;
    rtree.LocateClosestEndPointForCoordinate(input, result, 1);
    FixedPointCoordinate result_ln;
    LinearSearchNN lsnn(fixture.coords, fixture.edges);
    lsnn.LocateClosestEndPointForCoordinate(input, result_ln, 1);

    BOOST_CHECK_EQUAL(result_ln, result);
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    cxxFunctionType.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
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.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER 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 AUTHORS 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.

=========================================================================*/
#include "cxxFunctionType.h"

namespace _cxx_
{

/**
 * Retrieve what kind of Type this is.
 */
RepresentationType FunctionType::GetRepresentationType() const
{
  return FunctionType_id;
}

/**
 * Try to cast the given Type to an FunctionType.  If this returns, the
 * pointer will be valid.  If the cast is not allowed, an exception is
 * thrown.
 */
FunctionType* FunctionType::SafeDownCast(Type* t)
{
  FunctionType* result = dynamic_cast<FunctionType*>(t);
  if(!result) { throw TypeDownCastException(t, FunctionType_id); }
  return result;
}

/**
 * Try to cast the given Type to an FunctionType.  If this returns, the
 * pointer will be valid.  If the cast is not allowed, an exception is
 * thrown.
 */
const FunctionType* FunctionType::SafeDownCast(const Type* t)
{
  const FunctionType* result = dynamic_cast<const FunctionType*>(t);
  if(!result) { throw TypeDownCastException(t, FunctionType_id); }
  return result;
}

String FunctionType::GenerateName(const String& outerType,
                                  bool isConst, bool) const
{
  String arguments = this->GenerateArgumentString();
  String outerString = "("+outerType+")( "+arguments+" )"+this->GetRightCvString(isConst, false);
  return m_ReturnType.GenerateName(outerString);
}

/**
 * Get the name of the type as it would be used in a declaration with the
 * given name.
 */
String FunctionType::GenerateDeclaration(const String& name,
                                         bool isConst, bool) const
{
  String arguments = this->GenerateArgumentString();
  String outerString = "("+name+"( "+arguments+" ))";
  return m_ReturnType.GenerateName(outerString);
}

/**
 * Called by GenerateName and GenerateDeclaration to prepare a string
 * holding the function type's arguments.
 */
String FunctionType::GenerateArgumentString() const
{
  String arguments = "";
  CvQualifiedTypes::const_iterator arg = m_Arguments.begin();
  if(arg != m_Arguments.end())
    {
    arguments += arg->GetName();
    for(++arg;arg != m_Arguments.end(); ++arg)
      {
      arguments += ", "+arg->GetName();
      }
    }
  return arguments;
}

/**
 * Constructor takes the return type of the function.
 */
FunctionType::FunctionType(const CvQualifiedType& returnType,
                           const CvQualifiedTypes& arguments):
  m_ReturnType(returnType),
  m_Arguments(arguments)
{
}

} // namespace _cxx_
<commit_msg>ENH: Modified FunctionType declaration generation to not add an extra set of parentheses around a named declaration.  Also added support to print out a const qualifier on the function type in case it is being used for a method type.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    cxxFunctionType.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
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.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER 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 AUTHORS 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.

=========================================================================*/
#include "cxxFunctionType.h"

namespace _cxx_
{

/**
 * Retrieve what kind of Type this is.
 */
RepresentationType FunctionType::GetRepresentationType() const
{
  return FunctionType_id;
}

/**
 * Try to cast the given Type to an FunctionType.  If this returns, the
 * pointer will be valid.  If the cast is not allowed, an exception is
 * thrown.
 */
FunctionType* FunctionType::SafeDownCast(Type* t)
{
  FunctionType* result = dynamic_cast<FunctionType*>(t);
  if(!result) { throw TypeDownCastException(t, FunctionType_id); }
  return result;
}

/**
 * Try to cast the given Type to an FunctionType.  If this returns, the
 * pointer will be valid.  If the cast is not allowed, an exception is
 * thrown.
 */
const FunctionType* FunctionType::SafeDownCast(const Type* t)
{
  const FunctionType* result = dynamic_cast<const FunctionType*>(t);
  if(!result) { throw TypeDownCastException(t, FunctionType_id); }
  return result;
}

String FunctionType::GenerateName(const String& outerType,
                                  bool isConst, bool) const
{
  String arguments = this->GenerateArgumentString();
  String outerString = "("+outerType+")( "+arguments+" )"+this->GetRightCvString(isConst, false);
  return m_ReturnType.GenerateName(outerString);
}

/**
 * Get the name of the type as it would be used in a declaration with the
 * given name.
 */
String FunctionType::GenerateDeclaration(const String& name,
                                         bool isConst, bool) const
{
  String arguments = this->GenerateArgumentString();
  String outerString;
  if(name.length() > 0)
    {
    outerString = name+"("+arguments+")"+this->GetRightCvString(isConst, false);
    }
  else
    {
    outerString = "(("+arguments+"))"+this->GetRightCvString(isConst, false);
    }
  return m_ReturnType.GenerateName(outerString);
}

/**
 * Called by GenerateName and GenerateDeclaration to prepare a string
 * holding the function type's arguments.
 */
String FunctionType::GenerateArgumentString() const
{
  String arguments = "";
  CvQualifiedTypes::const_iterator arg = m_Arguments.begin();
  if(arg != m_Arguments.end())
    {
    arguments += arg->GetName();
    for(++arg;arg != m_Arguments.end(); ++arg)
      {
      arguments += ", "+arg->GetName();
      }
    }
  return arguments;
}

/**
 * Constructor takes the return type of the function.
 */
FunctionType::FunctionType(const CvQualifiedType& returnType,
                           const CvQualifiedTypes& arguments):
  m_ReturnType(returnType),
  m_Arguments(arguments)
{
}

} // namespace _cxx_
<|endoftext|>


<commit_before>/* algorithm.cpp - CS 472 Project #3: Genetic Programming
 * Copyright 2014 Andrew Schwartzmeyer
 *
 * Source file for algorithm namespace
 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <ctime>
#include <fstream>
#include <future>
#include <thread>

#include "algorithm.hpp"
#include "../individual/individual.hpp"
#include "../logging/logging.hpp"
#include "../options/options.hpp"
#include "../random_generator/random_generator.hpp"

namespace algorithm
{
  using std::vector;
  using individual::Individual;
  using options::Options;
  using namespace random_generator;

  // Prototypes
  vector<Individual>
  new_population(const Options& opts);

  vector<Individual>
  new_offspring(vector<Individual>& pop, int gen, const Options& opts);

  const Individual&
  select(int size, int start, int stop, const vector<Individual>& pop);

  void
  recombination(vector<Individual>& offspring, int gen, const Options& opts);

  // Definitions

  // Returns true if "a" is ordered before "b", i.e. more fit
  bool
  compare_fitness::operator()(const Individual& a, const Individual& b)
  {
    return std::isnormal(a.get_fitness())
      ? (a.get_fitness() > b.get_fitness()) : false;
  }

  /* Create an initial population using "ramped half-and-half" (half
     full trees, half randomly grown trees, all to random depths
     between 0 and maximum depth). */
  vector<Individual>
  new_population(const Options& opts)
  {
    vector<Individual> pop;
    pop.reserve(opts.pop_size);

    generate_n(back_inserter(pop), opts.pop_size, [&opts]
	       { return Individual{opts}; });

    return pop;
  }

  /* Return best candidate from size number of contestants randomly
     drawn from population.  Assume population is sorted. */
  const Individual&
  select(int size, int start, int stop, const vector<Individual>& pop)
  {
    int_dist dist{start, stop - 1}; // closed interval
    vector<unsigned int> group;
    group.reserve(size);

    // Generate tournament size number of random indexes
    generate_n(back_inserter(group), size, [&pop, &dist]
	       { return dist(rg.engine); } );

    // Population is sorted, so choose lowest index of those generated
    return pop[*min_element(begin(group), end(group))];
  }

  void
  breed_pups(vector<Individual>::iterator& parent, int gen, const Options& opts)
  {
    // Brood selection, see Banzhaf section 6.5.1
    vector<Individual> brood;
    brood.reserve(opts.brood_count * opts.crossover_size);

    // Create N copies of the pair
    for (int i(0); i < opts.brood_count; ++i)
      {
	brood.push_back(*parent);
	brood.push_back(*next(parent));
      }

    // Crossover each pair of pups
    for (auto pup = begin(brood); pup != end(brood); advance(pup, 2))
      { crossover(opts.internals_chance, *pup, *next(pup)); }

    /* Evaluate pups with fewer ticks: minimum plus [0, 1] * 600
       where 0 is the first generation and 1 is the final
       generation (thus scaling the evaluation with the run's
       age). */
    options::Map map = opts.map;
    float scale = static_cast<float>(gen) / opts.generations;;
    int min = 0.1 * map.max_ticks;
    map.max_ticks = min + scale * (map.max_ticks - min);
    for (auto& pup : brood)
      { pup.evaluate(map, opts.penalty); }

    // Kill pups with too great a depth.
    auto remove = [&opts, &brood](const Individual& a)
      { return (a.get_depth() > opts.depth_limit); };
    brood.erase(remove_if(begin(brood), end(brood), remove), end(brood));

    // Replace parents with best pair of brood if available.
    sort(begin(brood), end(brood), compare_fitness());
    if (brood.size() >= 1) // Assign the first pup to the first parent
      { *parent = std::move(*begin(brood)); }
    if (brood.size() >= 2) // Assign the second pup to the second parent
      { *next(parent) = std::move(*next(begin(brood))); }
  }

  void
  recombination(vector<Individual>& offspring, int gen, const Options& opts)
  {
    bool_dist crossover_dist{opts.crossover_chance};
    for (auto iter = begin(offspring); iter != end(offspring); advance(iter, 2))
      {
	if (crossover_dist(rg.engine))
	  {
	    if (opts.brood_count == 0)
	      { crossover(opts.internals_chance, *iter, *next(iter)); }
	    else
	      { breed_pups(iter, gen, opts); }
	  }
      }
  }

  /* Return new offspring population.  The pop is not passed const as
     it must be sorted. */
  vector<Individual>
  new_offspring(vector<Individual>& pop, int gen, const Options& opts)
  {
    // Select parents for children.
    vector<Individual> offspring;
    offspring.reserve(opts.pop_size);

    /* Implements over-selection.  80% drawn from a fitter group of
       320, the other 20% drawn from the weaker group (past the first
       sorted 320).  See Eiben section 6.6. */
    sort(begin(pop), end(pop), compare_fitness());
    bool_dist select_dist(opts.over_select_chance);
    auto over_select = [&opts, &pop, &select_dist]
      {
	if (select_dist(rg.engine))
	  { return select(opts.tourney_size, 0, opts.fit_size, pop); }
	else
	  { return select(opts.tourney_size, opts.fit_size, opts.pop_size, pop); }
      };

    generate_n(back_inserter(offspring), opts.pop_size, over_select);

    // Binary crossover if enabled.
    if (opts.crossover_size == 2)
      { recombination(offspring, gen, opts); }

    // Mutate and evaluate children.
    bool_dist mutate_dist(opts.mutate_chance);
    for (auto& child : offspring)
      {
	if (mutate_dist(rg.engine))
	  { child.mutate(opts.min_depth, opts.max_depth, opts.grow_chance); }

	child.evaluate(opts.map, opts.penalty); // Evaluate all children
      }
    return offspring;
  }

  /* The actual genetic algorithm applied which (hopefully) produces a
     well-fit expression for a given dataset. */
  const individual::Individual
  genetic(const std::time_t& time, int trial, const Options& opts)
  {
    // Start logging
    std::ofstream log;
    if (opts.verbosity > 0)
      {
	logging::open_log(log, time, trial, opts.logs_dir);
	logging::start_log(log, time, opts);
      }

    // Begin timing algorithm.
    auto start = std::chrono::system_clock::now();

    // Create initial population.
    vector<Individual> pop = new_population(opts);
    Individual best;

    // Run algorithm to termination.
    for (int g(0); g < opts.generations; ++g)
      {
	// Find best Individual of current population.
	best = *min_element(begin(pop), end(pop), compare_fitness());

	// Launch background logging thread.
	auto log_thread =
	  async(std::launch::async, logging::log_info,
		opts.verbosity, opts.logs_dir, time, trial, g, best, pop);

	// Create replacement population.
	vector<Individual> offspring = new_offspring(pop, g, opts);

	// Perform elitism replacement of random individuals.
	int_dist dist{0, opts.pop_size - 1};
	for (int e(0); e < opts.elitism_size; ++e)
	  { offspring[dist(rg.engine)] = best; }

	// Replace current population with offspring.
	pop = move(offspring);

	// Sync with background logging thread.
	log_thread.wait();
      }

    // End timing algorithm.
    auto stop = std::chrono::system_clock::now();
    std::chrono::duration<double> elapsed_seconds = stop - start;
    auto stop_time = std::chrono::system_clock::to_time_t(stop);

    // Log time information.
    if (opts.verbosity > 0)
      {
	logging::open_log(log, time, trial, opts.logs_dir);
	log << best.print() << best.print_formula()
	    << "# Finished computation @ " << ctime(&stop_time)
	    << "# Elapsed time: " << elapsed_seconds.count() << "s\n";
	log.close();
      }

    // Log evaluation plot data of best individual.
    std::ofstream plot;
    logging::open_log(plot, time, trial, opts.plots_dir);
    plot << best.evaluate(opts.map, opts.penalty, true);
    plot.close();

    return best;
  }
}
<commit_msg>More universal brace initialization!<commit_after>/* algorithm.cpp - CS 472 Project #3: Genetic Programming
 * Copyright 2014 Andrew Schwartzmeyer
 *
 * Source file for algorithm namespace
 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <ctime>
#include <fstream>
#include <future>
#include <thread>

#include "algorithm.hpp"
#include "../individual/individual.hpp"
#include "../logging/logging.hpp"
#include "../options/options.hpp"
#include "../random_generator/random_generator.hpp"

namespace algorithm
{
  using std::vector;
  using individual::Individual;
  using options::Options;
  using namespace random_generator;

  // Prototypes
  vector<Individual>
  new_population(const Options& opts);

  vector<Individual>
  new_offspring(vector<Individual>& pop, int gen, const Options& opts);

  const Individual&
  select(int size, int start, int stop, const vector<Individual>& pop);

  void
  recombination(vector<Individual>& offspring, int gen, const Options& opts);

  // Definitions

  // Returns true if "a" is ordered before "b", i.e. more fit
  bool
  compare_fitness::operator()(const Individual& a, const Individual& b)
  {
    return std::isnormal(a.get_fitness())
      ? (a.get_fitness() > b.get_fitness()) : false;
  }

  /* Create an initial population using "ramped half-and-half" (half
     full trees, half randomly grown trees, all to random depths
     between 0 and maximum depth). */
  vector<Individual>
  new_population(const Options& opts)
  {
    vector<Individual> pop;
    pop.reserve(opts.pop_size);

    generate_n(back_inserter(pop), opts.pop_size, [&opts]
	       { return Individual{opts}; });

    return pop;
  }

  /* Return best candidate from size number of contestants randomly
     drawn from population.  Assume population is sorted. */
  const Individual&
  select(int size, int start, int stop, const vector<Individual>& pop)
  {
    int_dist dist{start, stop - 1}; // closed interval
    vector<unsigned int> group;
    group.reserve(size);

    // Generate tournament size number of random indexes
    generate_n(back_inserter(group), size, [&pop, &dist]
	       { return dist(rg.engine); } );

    // Population is sorted, so choose lowest index of those generated
    return pop[*min_element(begin(group), end(group))];
  }

  void
  breed_pups(vector<Individual>::iterator& parent, int gen, const Options& opts)
  {
    // Brood selection, see Banzhaf section 6.5.1
    vector<Individual> brood;
    brood.reserve(opts.brood_count * opts.crossover_size);

    // Create N copies of the pair
    for (int i{0}; i < opts.brood_count; ++i)
      {
	brood.push_back(*parent);
	brood.push_back(*next(parent));
      }

    // Crossover each pair of pups
    for (auto pup = begin(brood); pup != end(brood); advance(pup, 2))
      { crossover(opts.internals_chance, *pup, *next(pup)); }

    /* Evaluate pups with fewer ticks: minimum plus [0, 1] * 600
       where 0 is the first generation and 1 is the final
       generation (thus scaling the evaluation with the run's
       age). */
    options::Map map = opts.map;
    float scale = static_cast<float>(gen) / opts.generations;;
    int min = 0.1 * map.max_ticks;
    map.max_ticks = min + scale * (map.max_ticks - min);
    for (auto& pup : brood)
      { pup.evaluate(map, opts.penalty); }

    // Kill pups with too great a depth.
    auto remove = [&opts, &brood](const Individual& a)
      { return (a.get_depth() > opts.depth_limit); };
    brood.erase(remove_if(begin(brood), end(brood), remove), end(brood));

    // Replace parents with best pair of brood if available.
    sort(begin(brood), end(brood), compare_fitness());
    if (brood.size() >= 1) // Assign the first pup to the first parent
      { *parent = std::move(*begin(brood)); }
    if (brood.size() >= 2) // Assign the second pup to the second parent
      { *next(parent) = std::move(*next(begin(brood))); }
  }

  void
  recombination(vector<Individual>& offspring, int gen, const Options& opts)
  {
    bool_dist crossover_dist{opts.crossover_chance};
    for (auto iter = begin(offspring); iter != end(offspring); advance(iter, 2))
      {
	if (crossover_dist(rg.engine))
	  {
	    if (opts.brood_count == 0)
	      { crossover(opts.internals_chance, *iter, *next(iter)); }
	    else
	      { breed_pups(iter, gen, opts); }
	  }
      }
  }

  /* Return new offspring population.  The pop is not passed const as
     it must be sorted. */
  vector<Individual>
  new_offspring(vector<Individual>& pop, int gen, const Options& opts)
  {
    // Select parents for children.
    vector<Individual> offspring;
    offspring.reserve(opts.pop_size);

    /* Implements over-selection.  80% drawn from a fitter group of
       320, the other 20% drawn from the weaker group (past the first
       sorted 320).  See Eiben section 6.6. */
    sort(begin(pop), end(pop), compare_fitness());
    bool_dist select_dist(opts.over_select_chance);
    auto over_select = [&opts, &pop, &select_dist]
      {
	if (select_dist(rg.engine))
	  { return select(opts.tourney_size, 0, opts.fit_size, pop); }
	else
	  { return select(opts.tourney_size, opts.fit_size, opts.pop_size, pop); }
      };

    generate_n(back_inserter(offspring), opts.pop_size, over_select);

    // Binary crossover if enabled.
    if (opts.crossover_size == 2)
      { recombination(offspring, gen, opts); }

    // Mutate and evaluate children.
    bool_dist mutate_dist(opts.mutate_chance);
    for (auto& child : offspring)
      {
	if (mutate_dist(rg.engine))
	  { child.mutate(opts.min_depth, opts.max_depth, opts.grow_chance); }

	child.evaluate(opts.map, opts.penalty); // Evaluate all children
      }
    return offspring;
  }

  /* The actual genetic algorithm applied which (hopefully) produces a
     well-fit expression for a given dataset. */
  const individual::Individual
  genetic(const std::time_t& time, int trial, const Options& opts)
  {
    // Start logging
    std::ofstream log;
    if (opts.verbosity > 0)
      {
	logging::open_log(log, time, trial, opts.logs_dir);
	logging::start_log(log, time, opts);
      }

    // Begin timing algorithm.
    auto start = std::chrono::system_clock::now();

    // Create initial population.
    vector<Individual> pop = new_population(opts);
    Individual best;

    // Run algorithm to termination.
    for (int g(0); g < opts.generations; ++g)
      {
	// Find best Individual of current population.
	best = *min_element(begin(pop), end(pop), compare_fitness());

	// Launch background logging thread.
	auto log_thread =
	  async(std::launch::async, logging::log_info,
		opts.verbosity, opts.logs_dir, time, trial, g, best, pop);

	// Create replacement population.
	vector<Individual> offspring = new_offspring(pop, g, opts);

	// Perform elitism replacement of random individuals.
	int_dist dist{0, opts.pop_size - 1};
	for (int e(0); e < opts.elitism_size; ++e)
	  { offspring[dist(rg.engine)] = best; }

	// Replace current population with offspring.
	pop = move(offspring);

	// Sync with background logging thread.
	log_thread.wait();
      }

    // End timing algorithm.
    auto stop = std::chrono::system_clock::now();
    std::chrono::duration<double> elapsed_seconds = stop - start;
    auto stop_time = std::chrono::system_clock::to_time_t(stop);

    // Log time information.
    if (opts.verbosity > 0)
      {
	logging::open_log(log, time, trial, opts.logs_dir);
	log << best.print() << best.print_formula()
	    << "# Finished computation @ " << ctime(&stop_time)
	    << "# Elapsed time: " << elapsed_seconds.count() << "s\n";
	log.close();
      }

    // Log evaluation plot data of best individual.
    std::ofstream plot;
    logging::open_log(plot, time, trial, opts.plots_dir);
    plot << best.evaluate(opts.map, opts.penalty, true);
    plot.close();

    return best;
  }
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <mitkNavigationDataRecorder.h>
#include <mitkNavigationDataPlayer.h>
#include <mitkNavigationData.h>
#include <mitkStandardFileLocations.h>
#include <mitkTestingMacros.h>

#include <Poco/Path.h>
#include <Poco/File.h>

#include <iostream>
#include <sstream>

//for exceptions
#include "mitkIGTException.h"
#include "mitkIGTIOException.h"

class mitkNavigationDataRecorderTestClass
  {
  public:

  static void TestInstantiation()
    {
    // let's create an object of our class
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();
    MITK_TEST_CONDITION( recorder.IsNotNull(), "Testing instatiation of NavigationDataRecorder");
    }

  static void TestRecordingWithGivenStream()
    {
    std::string tmp = "";
  std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc );
  stream->setf( std::ios::fixed, std::ios::floatfield );

  // let's create an object of our class
  mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

  MITK_TEST_CONDITION(recorder->GetInputs().size() == 0, "testing initial number of inputs");
  MITK_TEST_CONDITION(recorder->GetOutputs().size() == 0, "testing initial number of outputs");

  mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
  recorder->AddNavigationData( naviData );
  //recorder->SetFileName("e:/test");
  //recorder->SetRecordingMode( mitk::NavigationDataRecorder::NormalFile );
  recorder->StartRecording( stream );
  for ( unsigned int i=0; i<5; i++ )
  {
    mitk::Point3D pnt;
    pnt[0] = i + 1;
    pnt[1] = i + 1/2;
    pnt[2] = i +1*3;

    naviData->SetPosition(pnt);
    //naviData->Modified();
    recorder->Update();

    //Sleep(80 + i*10);

  }

  recorder->StopRecording();

  std::string str = stream->str();
  int pos = str.find( "ToolCount=" );
  std::string sub = stream->str().substr(pos+11, 1);
  MITK_TEST_CONDITION( sub.compare("1") == 0, "check if number of inputs is correct by stringstream");

  pos = str.find( "X=" );
  sub = stream->str().substr(pos+3, 1);
  MITK_TEST_CONDITION( sub.compare("1") == 0, "check if the X coordinate is correct");

  pos = str.find( "Y=" );
  sub = stream->str().substr(pos+3, 1);
  MITK_TEST_CONDITION( sub.compare("0") == 0, "check if the Y coordinate is correct");

  pos = str.find( "Z=" );
  sub = stream->str().substr(pos+3, 1);
  MITK_TEST_CONDITION( sub.compare("3") == 0, "check if the Z coordinate is correct");

  recorder->SetFileName("blablabla");
  const char* string = recorder->GetFileName();
  MITK_TEST_CONDITION( strcmp(string, "blablabla") == 0, "check if set- and getName-methods work");

    }

  static void TestRecordingOnHarddiscXML()
    {
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml";

    recorder->SetFileName(filename.c_str());

    mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
    recorder->AddNavigationData( naviData );
    recorder->StartRecording();

    for ( unsigned int i=0; i<5; i++ )
     {
     mitk::Point3D pnt;
     pnt[0] = i + 1;
     pnt[1] = i + 1/2;
     pnt[2] = i +1*3;
     naviData->SetPosition(pnt);
     recorder->Update();
     }

    recorder->StopRecording();

    std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml";
    Poco::File myFile(prooffilename);
    MITK_TEST_CONDITION(myFile.exists(),"Testing XML recording on harddisc (does file exist?).");
    }

  static void TestRecordingOnHarddiscXMLZIP()
    {
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertestzip.xml";

    recorder->SetFileName(filename.c_str());
    recorder->SetRecordingMode(mitk::NavigationDataRecorder::ZipFile);

    MITK_TEST_CONDITION(recorder->GetRecordingMode()==mitk::NavigationDataRecorder::ZipFile,"Testing setter of recording mode.");

    /* Zip file not supported yet, activate later
    mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
    recorder->AddNavigationData( naviData );
    recorder->StartRecording();

    for ( unsigned int i=0; i<5; i++ )
     {
     mitk::Point3D pnt;
     pnt[0] = i + 1;
     pnt[1] = i + 1/2;
     pnt[2] = i +1*3;
     naviData->SetPosition(pnt);
     recorder->Update();
     }

    recorder->StopRecording();

    std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml";
    Poco::File myFile(prooffilename);
    MITK_TEST_CONDITION(myFile.exists(),"Testing XML Zip recording on harddisc (does file exist?).");
    */
    }

  static void TestRecordingOnHarddiscCSV()
    {
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml";

    recorder->SetFileName(filename.c_str());
    recorder->SetOutputFormat(mitk::NavigationDataRecorder::csv);

    mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
    recorder->AddNavigationData( naviData );
    recorder->StartRecording();

    for ( unsigned int i=0; i<5; i++ )
     {
     mitk::Point3D pnt;
     pnt[0] = i + 1;
     pnt[1] = i + 1/2;
     pnt[2] = i + 1*3;
     naviData->SetPosition(pnt);
     recorder->Update();
     }

    recorder->StopRecording();

    std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.csv";
    Poco::File myFile(prooffilename);
    MITK_TEST_CONDITION(myFile.exists(),"Testing CSV recording on harddisc (does file exist?).");
    }

  static void TestLoadingRecordedXMLFile()
    {
    mitk::NavigationDataPlayer::Pointer myPlayer = mitk::NavigationDataPlayer::New();
    std::string filenameXML = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml";
    myPlayer->SetFileName(filenameXML.c_str());
    myPlayer->StartPlaying();

    //only testing first position at the moment
    myPlayer->Update();
    mitk::NavigationData::Pointer thisData = myPlayer->GetOutput();
    mitk::Point3D reference_pnt;
    reference_pnt[0] = 1;
    reference_pnt[1] = 1/2;
    reference_pnt[2] = 1*3;

    myPlayer->StopPlaying();

    MITK_TEST_CONDITION((thisData->GetPosition() == reference_pnt),"Testing load data from xml file.");
    }

  static void TestRecordingInvalidData()
    {
    std::string tmp = "";
    std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc );
    stream->setf( std::ios::fixed, std::ios::floatfield );

    // let's create an object of our class
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

    mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
    recorder->AddNavigationData( naviData );
    naviData->SetDataValid(false);
    //recorder->SetFileName("e:/test");
    //recorder->SetRecordingMode( mitk::NavigationDataRecorder::NormalFile );
    recorder->StartRecording( stream );
    for ( unsigned int i=0; i<5; i++ )
    {
      mitk::Point3D pnt;
      pnt[0] = i + 1;
      pnt[1] = i + 1/2;
      pnt[2] = i +1*3;

      naviData->SetPosition(pnt);
      //naviData->Modified();
      recorder->Update();

      //Sleep(80 + i*10);

    }

    recorder->StopRecording();

    bool record_success = true;

    std::string str = stream->str();
    int pos = str.find( "ToolCount=" );
    std::string sub = stream->str().substr(pos+11, 1);
    if (sub.compare("1") != 0) {record_success = false;}

    pos = str.find( "X=" );
    sub = stream->str().substr(pos+3, 1);
    if (sub.compare("1") != 0) {record_success = false;}

    pos = str.find( "Y=" );
    sub = stream->str().substr(pos+3, 1);
    if (sub.compare("0") != 0) {record_success = false;}

    pos = str.find( "Z=" );
    sub = stream->str().substr(pos+3, 1);
    if (sub.compare("3") != 0) {record_success = false;}

    MITK_TEST_CONDITION(record_success,"Testing recording of invalid data.");

    }

  static void CleanUp()
    {
    std::string filenameXML = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml";
    std::string filenameCSV = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.csv";
    Poco::File myFileXML(filenameXML);
    Poco::File myFileCSV(filenameCSV);

    try
    {
    if (myFileXML.exists())
      {myFileXML.remove();}
    }
    catch(std::exception e)
    {
      MITK_WARN << "Cannot delete file while cleanup: " << filenameXML;
    }

    try
    {
    if (myFileCSV.exists())
      {myFileCSV.remove();}
    }
    catch(std::exception e)
    {
      MITK_WARN << "Cannot delete file while cleanup: " << filenameCSV;
    }

    }

  static void TestStartRecordingExceptions()
     {
     //Testing Start Recording for exceptions if recording has already started
     mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();
     std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml";
     recorder->SetFileName(filename.c_str());

     //Testing double call of StartRecording().
     mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
     recorder->AddNavigationData( naviData );
     recorder->StartRecording();
     recorder->StartRecording();
     recorder->StopRecording();
     MITK_TEST_OUTPUT(<<"Tested double call of StartRecording(). Application should not crash.");

     //Testing exceptions for method StartRecording() when no file is set.
     mitk::NavigationDataRecorder::Pointer recorder1 = mitk::NavigationDataRecorder::New();
     std::string filename1 = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml";
     recorder->SetFileName("");
     bool exceptionThrown1 = false;
     mitk::NavigationData::Pointer naviData1 = mitk::NavigationData::New();
     recorder1->AddNavigationData( naviData1 );
     try
       {
       recorder1->StartRecording();
       }
     catch(mitk::IGTException)
       {
       exceptionThrown1 = true;
       }
     MITK_TEST_CONDITION(exceptionThrown1,"Testing exception throwing when no file name or file path is set.");

     //Testing double call of StartRecording(stream) method.
     mitk::NavigationDataRecorder::Pointer recorder2 = mitk::NavigationDataRecorder::New();
     std::string tmp = "";
     std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc );
     stream->setf( std::ios::fixed, std::ios::floatfield );
     recorder2->StartRecording(stream);
     recorder2->StartRecording(stream);
     recorder2->StopRecording();
     MITK_TEST_OUTPUT(<<"Tested double call of StartRecording(stream). Application should not crash.");

     //Testing exceptions if the stream is not good
     mitk::NavigationDataRecorder::Pointer recorder3 = mitk::NavigationDataRecorder::New();
     std::ofstream stream3; //making an invalid stream
     stream3.open("");
     bool exceptionThrown3 = false;
     try
       {
       recorder3->StartRecording(&stream3);
       }
     catch(mitk::IGTException)
       {
       exceptionThrown3 = true;
       }
     MITK_TEST_CONDITION(exceptionThrown3,"Testing exception thrown when the stream in not good.");
     }

  };

/**Documentation
 *  test for the class "NavigationDataRecorder".
 */
int mitkNavigationDataRecorderTest(int /* argc */, char* /*argv*/[])
{
  MITK_TEST_BEGIN("NavigationDataRecorder");

  mitkNavigationDataRecorderTestClass::TestInstantiation();
  mitkNavigationDataRecorderTestClass::TestRecordingWithGivenStream();
  mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscXML();
  mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscXMLZIP();
  mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscCSV();
  mitkNavigationDataRecorderTestClass::TestRecordingInvalidData();
  mitkNavigationDataRecorderTestClass::TestStartRecordingExceptions();

  //Test fails under linux, perhaps reading permission problems, deactivated it temporary
  //mitkNavigationDataRecorderTestClass::TestLoadingRecordedXMLFile();

  mitkNavigationDataRecorderTestClass::CleanUp();

  // always end with this!
  MITK_TEST_END();
}
<commit_msg>COMP: fixed use of std::ostringstream<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <mitkNavigationDataRecorder.h>
#include <mitkNavigationDataPlayer.h>
#include <mitkNavigationData.h>
#include <mitkStandardFileLocations.h>
#include <mitkTestingMacros.h>

#include <Poco/Path.h>
#include <Poco/File.h>

#include <iostream>
#include <sstream>

//for exceptions
#include "mitkIGTException.h"
#include "mitkIGTIOException.h"

class mitkNavigationDataRecorderTestClass
  {
  public:

  static void TestInstantiation()
    {
    // let's create an object of our class
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();
    MITK_TEST_CONDITION( recorder.IsNotNull(), "Testing instatiation of NavigationDataRecorder");
    }

  static void TestRecordingWithGivenStream()
    {
    std::string tmp = "";
  std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc );
  stream->setf( std::ios::fixed, std::ios::floatfield );

  // let's create an object of our class
  mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

  MITK_TEST_CONDITION(recorder->GetInputs().size() == 0, "testing initial number of inputs");
  MITK_TEST_CONDITION(recorder->GetOutputs().size() == 0, "testing initial number of outputs");

  mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
  recorder->AddNavigationData( naviData );
  //recorder->SetFileName("e:/test");
  //recorder->SetRecordingMode( mitk::NavigationDataRecorder::NormalFile );
  recorder->StartRecording( stream );
  for ( unsigned int i=0; i<5; i++ )
  {
    mitk::Point3D pnt;
    pnt[0] = i + 1;
    pnt[1] = i + 1/2;
    pnt[2] = i +1*3;

    naviData->SetPosition(pnt);
    //naviData->Modified();
    recorder->Update();

    //Sleep(80 + i*10);

  }

  recorder->StopRecording();

  std::string str = stream->str();
  int pos = str.find( "ToolCount=" );
  std::string sub = stream->str().substr(pos+11, 1);
  MITK_TEST_CONDITION( sub.compare("1") == 0, "check if number of inputs is correct by stringstream");

  pos = str.find( "X=" );
  sub = stream->str().substr(pos+3, 1);
  MITK_TEST_CONDITION( sub.compare("1") == 0, "check if the X coordinate is correct");

  pos = str.find( "Y=" );
  sub = stream->str().substr(pos+3, 1);
  MITK_TEST_CONDITION( sub.compare("0") == 0, "check if the Y coordinate is correct");

  pos = str.find( "Z=" );
  sub = stream->str().substr(pos+3, 1);
  MITK_TEST_CONDITION( sub.compare("3") == 0, "check if the Z coordinate is correct");

  recorder->SetFileName("blablabla");
  const char* string = recorder->GetFileName();
  MITK_TEST_CONDITION( strcmp(string, "blablabla") == 0, "check if set- and getName-methods work");

    }

  static void TestRecordingOnHarddiscXML()
    {
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml";

    recorder->SetFileName(filename.c_str());

    mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
    recorder->AddNavigationData( naviData );
    recorder->StartRecording();

    for ( unsigned int i=0; i<5; i++ )
     {
     mitk::Point3D pnt;
     pnt[0] = i + 1;
     pnt[1] = i + 1/2;
     pnt[2] = i +1*3;
     naviData->SetPosition(pnt);
     recorder->Update();
     }

    recorder->StopRecording();

    std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml";
    Poco::File myFile(prooffilename);
    MITK_TEST_CONDITION(myFile.exists(),"Testing XML recording on harddisc (does file exist?).");
    }

  static void TestRecordingOnHarddiscXMLZIP()
    {
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertestzip.xml";

    recorder->SetFileName(filename.c_str());
    recorder->SetRecordingMode(mitk::NavigationDataRecorder::ZipFile);

    MITK_TEST_CONDITION(recorder->GetRecordingMode()==mitk::NavigationDataRecorder::ZipFile,"Testing setter of recording mode.");

    /* Zip file not supported yet, activate later
    mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
    recorder->AddNavigationData( naviData );
    recorder->StartRecording();

    for ( unsigned int i=0; i<5; i++ )
     {
     mitk::Point3D pnt;
     pnt[0] = i + 1;
     pnt[1] = i + 1/2;
     pnt[2] = i +1*3;
     naviData->SetPosition(pnt);
     recorder->Update();
     }

    recorder->StopRecording();

    std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml";
    Poco::File myFile(prooffilename);
    MITK_TEST_CONDITION(myFile.exists(),"Testing XML Zip recording on harddisc (does file exist?).");
    */
    }

  static void TestRecordingOnHarddiscCSV()
    {
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

    //create filename
    std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml";

    recorder->SetFileName(filename.c_str());
    recorder->SetOutputFormat(mitk::NavigationDataRecorder::csv);

    mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
    recorder->AddNavigationData( naviData );
    recorder->StartRecording();

    for ( unsigned int i=0; i<5; i++ )
     {
     mitk::Point3D pnt;
     pnt[0] = i + 1;
     pnt[1] = i + 1/2;
     pnt[2] = i + 1*3;
     naviData->SetPosition(pnt);
     recorder->Update();
     }

    recorder->StopRecording();

    std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.csv";
    Poco::File myFile(prooffilename);
    MITK_TEST_CONDITION(myFile.exists(),"Testing CSV recording on harddisc (does file exist?).");
    }

  static void TestLoadingRecordedXMLFile()
    {
    mitk::NavigationDataPlayer::Pointer myPlayer = mitk::NavigationDataPlayer::New();
    std::string filenameXML = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml";
    myPlayer->SetFileName(filenameXML.c_str());
    myPlayer->StartPlaying();

    //only testing first position at the moment
    myPlayer->Update();
    mitk::NavigationData::Pointer thisData = myPlayer->GetOutput();
    mitk::Point3D reference_pnt;
    reference_pnt[0] = 1;
    reference_pnt[1] = 1/2;
    reference_pnt[2] = 1*3;

    myPlayer->StopPlaying();

    MITK_TEST_CONDITION((thisData->GetPosition() == reference_pnt),"Testing load data from xml file.");
    }

  static void TestRecordingInvalidData()
    {
    std::string tmp = "";
    std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc );
    stream->setf( std::ios::fixed, std::ios::floatfield );

    // let's create an object of our class
    mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();

    mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
    recorder->AddNavigationData( naviData );
    naviData->SetDataValid(false);
    //recorder->SetFileName("e:/test");
    //recorder->SetRecordingMode( mitk::NavigationDataRecorder::NormalFile );
    recorder->StartRecording( stream );
    for ( unsigned int i=0; i<5; i++ )
    {
      mitk::Point3D pnt;
      pnt[0] = i + 1;
      pnt[1] = i + 1/2;
      pnt[2] = i +1*3;

      naviData->SetPosition(pnt);
      //naviData->Modified();
      recorder->Update();

      //Sleep(80 + i*10);

    }

    recorder->StopRecording();

    bool record_success = true;

    std::string str = stream->str();
    int pos = str.find( "ToolCount=" );
    std::string sub = stream->str().substr(pos+11, 1);
    if (sub.compare("1") != 0) {record_success = false;}

    pos = str.find( "X=" );
    sub = stream->str().substr(pos+3, 1);
    if (sub.compare("1") != 0) {record_success = false;}

    pos = str.find( "Y=" );
    sub = stream->str().substr(pos+3, 1);
    if (sub.compare("0") != 0) {record_success = false;}

    pos = str.find( "Z=" );
    sub = stream->str().substr(pos+3, 1);
    if (sub.compare("3") != 0) {record_success = false;}

    MITK_TEST_CONDITION(record_success,"Testing recording of invalid data.");

    }

  static void CleanUp()
    {
    std::string filenameXML = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml";
    std::string filenameCSV = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.csv";
    Poco::File myFileXML(filenameXML);
    Poco::File myFileCSV(filenameCSV);

    try
    {
    if (myFileXML.exists())
      {myFileXML.remove();}
    }
    catch(std::exception e)
    {
      MITK_WARN << "Cannot delete file while cleanup: " << filenameXML;
    }

    try
    {
    if (myFileCSV.exists())
      {myFileCSV.remove();}
    }
    catch(std::exception e)
    {
      MITK_WARN << "Cannot delete file while cleanup: " << filenameCSV;
    }

    }

  static void TestStartRecordingExceptions()
     {
     //Testing Start Recording for exceptions if recording has already started
     mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New();
     std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml";
     recorder->SetFileName(filename.c_str());

     //Testing double call of StartRecording().
     mitk::NavigationData::Pointer naviData = mitk::NavigationData::New();
     recorder->AddNavigationData( naviData );
     recorder->StartRecording();
     recorder->StartRecording();
     recorder->StopRecording();
     MITK_TEST_OUTPUT(<<"Tested double call of StartRecording(). Application should not crash.");

     //Testing exceptions for method StartRecording() when no file is set.
     mitk::NavigationDataRecorder::Pointer recorder1 = mitk::NavigationDataRecorder::New();
     std::string filename1 = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml";
     recorder->SetFileName("");
     bool exceptionThrown1 = false;
     mitk::NavigationData::Pointer naviData1 = mitk::NavigationData::New();
     recorder1->AddNavigationData( naviData1 );
     try
       {
       recorder1->StartRecording();
       }
     catch(mitk::IGTException)
       {
       exceptionThrown1 = true;
       }
     MITK_TEST_CONDITION(exceptionThrown1,"Testing exception throwing when no file name or file path is set.");

     //Testing double call of StartRecording(stream) method.
     mitk::NavigationDataRecorder::Pointer recorder2 = mitk::NavigationDataRecorder::New();
     std::string tmp = "";
     std::ostringstream stream;// = new std::ostringstream( std::ostringstream::trunc );
     stream.setf( std::ios::fixed, std::ios::floatfield );
     recorder2->StartRecording(&stream);
     recorder2->StartRecording(&stream);
     recorder2->StopRecording();
     MITK_TEST_OUTPUT(<<"Tested double call of StartRecording(stream). Application should not crash.");

     //Testing exceptions if the stream is not good
     mitk::NavigationDataRecorder::Pointer recorder3 = mitk::NavigationDataRecorder::New();
     std::ofstream stream3; //making an invalid stream
     stream3.open("");
     bool exceptionThrown3 = false;
     try
       {
       recorder3->StartRecording(&stream3);
       }
     catch(mitk::IGTException)
       {
       exceptionThrown3 = true;
       }
     MITK_TEST_CONDITION(exceptionThrown3,"Testing exception thrown when the stream in not good.");
     }

  };

/**Documentation
 *  test for the class "NavigationDataRecorder".
 */
int mitkNavigationDataRecorderTest(int /* argc */, char* /*argv*/[])
{
  MITK_TEST_BEGIN("NavigationDataRecorder");

  mitkNavigationDataRecorderTestClass::TestInstantiation();
  mitkNavigationDataRecorderTestClass::TestRecordingWithGivenStream();
  mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscXML();
  mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscXMLZIP();
  mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscCSV();
  mitkNavigationDataRecorderTestClass::TestRecordingInvalidData();
  mitkNavigationDataRecorderTestClass::TestStartRecordingExceptions();

  //Test fails under linux, perhaps reading permission problems, deactivated it temporary
  //mitkNavigationDataRecorderTestClass::TestLoadingRecordedXMLFile();

  mitkNavigationDataRecorderTestClass::CleanUp();

  // always end with this!
  MITK_TEST_END();
}
<|endoftext|>