<commit_before>#include <ros/ros.h>
#include <std_msgs/MultiArrayDimension.h>
#include <std_msgs/UInt8MultiArray.h>

const int DRIVE_TELEGRAM_SIZE = 4;

//declarations
void driveTelegramCallback(const std_msgs::UInt8MultiArray::ConstPtr &msg);
void setDriveTelegram(unsigned char drive_telegram[], int velocity);

//Main function
int main(int argc, char *argv[])
{
  ros::init(argc, argv, "cp1616_sinamics_tutorial_node");
  ros::NodeHandle nh;

  //Subscribe to drive topic defined in yaml config file
  ros::Subscriber sub_drive = nh.subscribe("/drive_1_input_topic", 1,
					   &driveTelegramCallback);

  //Create publihser for drive topic defined in yaml config file
  ros::Publisher pub_drive = nh.advertise<std_msgs::UInt8MultiArray>
                                         ("/drive_1_output_topic", 1);

  //Telegram 111
  unsigned char drive_telegram_1[DRIVE_TELEGRAM_SIZE];

  //std_msgs::MultiArray variables
  std_msgs::MultiArrayDimension msg_dim;
  std_msgs::UInt8MultiArray msg;

  //Wait until communication starts properly
  ros::Duration(10).sleep();

  msg_dim.label = "Drive_1_output";
  msg_dim.size = DRIVE_TELEGRAM_SIZE;
  msg.layout.dim.clear();
  msg.layout.dim.push_back(msg_dim);

  msg.data.clear();

  drive_telegram_1[0] =  0b00000100;   //STW1 high
  drive_telegram_1[1] =  0b00000000;   //STW1 low
  drive_telegram_1[2] =  0b00000000;   //NSOLL_A high
  drive_telegram_1[3] =  0b00000000;   //NSOLL_A low

  msg.data.clear();
  for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
    msg.data.push_back(drive_telegram_1[i]);

  pub_drive.publish(msg);

  //Wait 2 seconds
  ros::Duration(2).sleep();

  //-------------------------------------------
  //Send initialization DRIVE telegram
  // - set all necessary bytes except ON/OFF1 to true
  //-------------------------------------------
  msg_dim.label = "Drive_1_output";
  msg_dim.size = DRIVE_TELEGRAM_SIZE;
  msg.layout.dim.clear();
  msg.layout.dim.push_back(msg_dim);

  msg.data.clear();

  drive_telegram_1[0] =  0b00000100;   //STW1 high
  drive_telegram_1[1] =  0b11111110;   //STW1 low
  drive_telegram_1[2] =  0b00000000;   //NSOLL_A high
  drive_telegram_1[3] =  0b00000000;   //NSOLL_A low

  msg.data.clear();
  for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
    msg.data.push_back(drive_telegram_1[i]);

  pub_drive.publish(msg);

  //Wait 2 seconds before entering loop
  ros::Duration(2).sleep();

  //-------------------------------------------
  // Main loop
  //-------------------------------------------
  while(ros::ok())
  {

    ROS_INFO("Goal speed: 500");
    //message header
    msg_dim.label = "Drive_1_output";
    msg_dim.size = DRIVE_TELEGRAM_SIZE;
    msg.layout.dim.clear();
    msg.layout.dim.push_back(msg_dim);

    setDriveTelegram(drive_telegram_1, 5000);

    //copy telegram data
    msg.data.clear();
    for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
        msg.data.push_back(drive_telegram_1[i]);

    //publish
    pub_drive.publish(msg);

    //wait for 5 seconds
    ros::Duration(5).sleep();
    ros::spinOnce();

    //======================================================

    ROS_INFO("Goal speed: 1000");
    //message header
    msg_dim.label = "Drive_1_output";
    msg_dim.size = DRIVE_TELEGRAM_SIZE;
    msg.layout.dim.clear();
    msg.layout.dim.push_back(msg_dim);

    setDriveTelegram(drive_telegram_1, 10000);

    //copy telegram data
    msg.data.clear();
    for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
        msg.data.push_back(drive_telegram_1[i]);

    //publish
    pub_drive.publish(msg);

    //wait for 5 seconds
    ros::Duration(5).sleep();
    ros::spinOnce();
  }

  return (EXIT_SUCCESS);
}

void setDriveTelegram(unsigned char drive_telegram[], int velocity)
{

  //Decompose velocity from int to 4*unsigned char
  unsigned char velocity_bytes[2];

  velocity_bytes[0] = (velocity >> 8)  & 0xFF;
  velocity_bytes[1] = velocity & 0xFF;

  //Set telegram data
  drive_telegram[0] =  0b00000100;           //STW1 high
  drive_telegram[1] =  0b11111111;           //STW1 low
  drive_telegram[2] =  velocity_bytes[0];    //NSOLL_A high
  drive_telegram[3] =  velocity_bytes[1];    //NSOLL_A low
}

void driveTelegramCallback(const std_msgs::UInt8MultiArray::ConstPtr &msg)
{
  unsigned int received_byte_array[DRIVE_TELEGRAM_SIZE];

  for(unsigned int i = 0; i < DRIVE_TELEGRAM_SIZE; i++)
    received_byte_array[i] = msg->data[i];
}
<commit_msg>tested with real hardware<commit_after>#include <ros/ros.h>
#include <std_msgs/MultiArrayDimension.h>
#include <std_msgs/UInt8MultiArray.h>

const int DRIVE_TELEGRAM_SIZE = 4;
const int N_MAX = 1500;

//declarations
void driveTelegramCallback(const std_msgs::UInt8MultiArray::ConstPtr &msg);
void setDriveTelegram(unsigned char drive_telegram[], int velocity);

//Main function
int main(int argc, char *argv[])
{
  ros::init(argc, argv, "cp1616_sinamics_tutorial_node");
  ros::NodeHandle nh;

  //Subscribe to drive topic defined in yaml config file
  ros::Subscriber sub_drive = nh.subscribe("/drive_1_input_topic", 1, &driveTelegramCallback);

  //Create publihser for drive topic defined in yaml config file
  ros::Publisher pub_drive = nh.advertise<std_msgs::UInt8MultiArray>("/drive_1_output_topic", 1);

  //Telegram 111
  unsigned char drive_telegram_1[DRIVE_TELEGRAM_SIZE];

  //std_msgs::MultiArray variables
  std_msgs::MultiArrayDimension msg_dim;
  std_msgs::UInt8MultiArray msg;

  //Wait until communication starts properly
  ros::Duration(10).sleep();

  msg_dim.label = "Drive_1_output";
  msg_dim.size = DRIVE_TELEGRAM_SIZE;
  msg.layout.dim.clear();
  msg.layout.dim.push_back(msg_dim);

  msg.data.clear();

  drive_telegram_1[0] =  0b00000100;   //STW1 high
  drive_telegram_1[1] =  0b00000000;   //STW1 low
  drive_telegram_1[2] =  0b00000000;   //NSOLL_A high
  drive_telegram_1[3] =  0b00000000;   //NSOLL_A low

  msg.data.clear();
  for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
    msg.data.push_back(drive_telegram_1[i]);

  pub_drive.publish(msg);

  //Wait for 2 seconds
  ros::Duration(2).sleep();

  //-------------------------------------------
  //Send initialization DRIVE telegram
  // - set ON/OFF2 ON/OFF/3 to true
  //-------------------------------------------
  msg_dim.label = "Drive_1_output";
  msg_dim.size = DRIVE_TELEGRAM_SIZE;
  msg.layout.dim.clear();
  msg.layout.dim.push_back(msg_dim);

  msg.data.clear();

  drive_telegram_1[0] =  0b00000100;   //STW1 high
  drive_telegram_1[1] =  0b10000110;   //STW1 low
  drive_telegram_1[2] =  0b00000000;   //NSOLL_A high
  drive_telegram_1[3] =  0b00000000;   //NSOLL_A low

  msg.data.clear();
  for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
    msg.data.push_back(drive_telegram_1[i]);

  pub_drive.publish(msg);

  //Wait for 2 seconds
  ros::Duration(2).sleep();

  //-------------------------------------------
  //Send initialization DRIVE telegram
  // - set all necessary bytes except ON/OFF1 to true
  //-------------------------------------------
  msg_dim.label = "Drive_1_output";
  msg_dim.size = DRIVE_TELEGRAM_SIZE;
  msg.layout.dim.clear();
  msg.layout.dim.push_back(msg_dim);

  msg.data.clear();

  drive_telegram_1[0] =  0b00000100;   //STW1 high
  drive_telegram_1[1] =  0b11111110;   //STW1 low
  drive_telegram_1[2] =  0b00000000;   //NSOLL_A high
  drive_telegram_1[3] =  0b00000000;   //NSOLL_A low

  msg.data.clear();
  for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
    msg.data.push_back(drive_telegram_1[i]);

  pub_drive.publish(msg);

  //Wait for 2 seconds
  ros::Duration(2).sleep();

  //-------------------------------------------
  // Main loop
  //-------------------------------------------
  while(ros::ok())
  {

    ROS_INFO("Goal speed: 500");
    //message header
    msg_dim.label = "Drive_1_output";
    msg_dim.size = DRIVE_TELEGRAM_SIZE;
    msg.layout.dim.clear();
    msg.layout.dim.push_back(msg_dim);

    setDriveTelegram(drive_telegram_1, 500);

    //copy telegram data
    msg.data.clear();
    for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
        msg.data.push_back(drive_telegram_1[i]);

    //publish
    pub_drive.publish(msg);

    //wait for 5 seconds
    ros::Duration(5).sleep();
    ros::spinOnce();

    //======================================================

    ROS_INFO("Goal speed: 1000");
    //message header
    msg_dim.label = "Drive_1_output";
    msg_dim.size = DRIVE_TELEGRAM_SIZE;
    msg.layout.dim.clear();
    msg.layout.dim.push_back(msg_dim);

    setDriveTelegram(drive_telegram_1, 1000);

    //copy telegram data
    msg.data.clear();
    for(size_t i = 0;  i < DRIVE_TELEGRAM_SIZE; i++)
        msg.data.push_back(drive_telegram_1[i]);

    //publish
    pub_drive.publish(msg);

    //wait for 5 seconds
    ros::Duration(5).sleep();
    ros::spinOnce();
  }

  return (EXIT_SUCCESS);
}

void setDriveTelegram(unsigned char drive_telegram[], int velocity)
{
  //Scale to 0x4000 = 100% ratio
  int velocity_rel = (velocity * 0x4000) / N_MAX;

  //Decompose velocity from int to 4*unsigned char
  unsigned char velocity_bytes[2];

  velocity_bytes[0] = (velocity_rel >> 8)  & 0xFF;
  velocity_bytes[1] = velocity_rel & 0xFF;

  //Set telegram data
  drive_telegram[0] =  0b00000100;           //STW1 high
  drive_telegram[1] =  0b11111111;           //STW1 low
  drive_telegram[2] =  velocity_bytes[0];    //NSOLL_A high
  drive_telegram[3] =  velocity_bytes[1];    //NSOLL_A low

}

void driveTelegramCallback(const std_msgs::UInt8MultiArray::ConstPtr &msg)
{
  unsigned int received_byte_array[DRIVE_TELEGRAM_SIZE];

  for(unsigned int i = 0; i < DRIVE_TELEGRAM_SIZE; i++)
    received_byte_array[i] = msg->data[i];
}
<|endoftext|>


<commit_before>#include <iostream>
#include <typeinfo>
#define BOOST_TEST_MODULE DenseMIAAddSubtractTests

#include "MIAConfig.h"

#ifdef MIA_USE_HEADER_ONLY_TESTS
#include <boost/test/included/unit_test.hpp>
#else
#include <boost/test/unit_test.hpp>
#endif

#include "DenseMIA.h"
#include "Index.h"

template<class _data_type>
void do_work(size_t dim1,size_t dim2){

    LibMIA::MIAINDEX i;
    LibMIA::MIAINDEX j;
    LibMIA::MIAINDEX k;
    LibMIA::MIAINDEX l;
//    LibMIA::MIAINDEX m;
//    LibMIA::MIAINDEX n;
//    LibMIA::MIAINDEX o;
//    LibMIA::MIAINDEX p;

    LibMIA::DenseMIA<_data_type,4> a(dim1,dim1,dim2,dim2);
    LibMIA::DenseMIA<_data_type,4> b(dim2,dim1,dim2,dim1);
    LibMIA::DenseMIA<_data_type,4> c(dim2,dim1,dim2,dim1);
    LibMIA::DenseMIA<_data_type,4> c2(dim2,dim1,dim2,dim1);
    LibMIA::DenseMIA<_data_type,4> b2(dim1,dim1,dim2,dim2);

    a.ones();
    b.ones();

    c(i,j,k,l)=b(i,j,k,l)+a(j,l,i,k);
    c2.init(2);
    BOOST_CHECK_MESSAGE(c==c2,std::string("Non-destructive Add 1 for ")+typeid(_data_type).name());

    b(i,j,k,l)+=a(j,l,i,k);
    BOOST_CHECK_MESSAGE(b==c2,std::string("Destructive Add 1 for ")+typeid(_data_type).name());

    b.init(3);
    c(i,j,k,l)=b(i,j,k,l)-a(j,l,i,k);
    BOOST_CHECK_MESSAGE(c==c2,std::string("Non-destructive Subtract 1 for ")+typeid(_data_type).name());

    b(i,j,k,l)-=a(j,l,i,k);
    BOOST_CHECK_MESSAGE(b==c2,std::string("Destructive Subtract 1 for ")+typeid(_data_type).name());

}

BOOST_AUTO_TEST_CASE( DenseMIAAddSubtractTests )
{

    do_work<double>(8,10);
    do_work<float>(8,10);
    do_work<int>(8,10);
    do_work<long long int>(8,10);

}
<commit_msg>Added a second set of dense add/subtract unit tests<commit_after>#include <iostream>
#include <typeinfo>
#define BOOST_TEST_MODULE DenseMIAAddSubtractTests

#include "MIAConfig.h"

#ifdef MIA_USE_HEADER_ONLY_TESTS
#include <boost/test/included/unit_test.hpp>
#else
#include <boost/test/unit_test.hpp>
#endif

#include "DenseMIA.h"
#include "Index.h"

template<class _data_type>
void do_work(size_t dim1,size_t dim2){

    LibMIA::MIAINDEX i;
    LibMIA::MIAINDEX j;
    LibMIA::MIAINDEX k;
    LibMIA::MIAINDEX l;
//    LibMIA::MIAINDEX m;
//    LibMIA::MIAINDEX n;
//    LibMIA::MIAINDEX o;
//    LibMIA::MIAINDEX p;

    LibMIA::DenseMIA<_data_type,4> a(dim1,dim1,dim2,dim2);
    LibMIA::DenseMIA<_data_type,4> b(dim2,dim1,dim2,dim1);
    LibMIA::DenseMIA<_data_type,4> c(dim2,dim1,dim2,dim1);
    LibMIA::DenseMIA<_data_type,4> c2(dim2,dim1,dim2,dim1);
    LibMIA::DenseMIA<_data_type,4> b2(dim1,dim1,dim2,dim2);

    a.ones();
    b.ones();

    c(i,j,k,l)=b(i,j,k,l)+a(j,l,i,k);
    c2.init(2);
    BOOST_CHECK_MESSAGE(c==c2,std::string("Non-destructive Add 1 for ")+typeid(_data_type).name());

    b(i,j,k,l)+=a(j,l,i,k);
    BOOST_CHECK_MESSAGE(b==c2,std::string("Destructive Add 1 for ")+typeid(_data_type).name());

    b.init(3);
    c(i,j,k,l)=b(i,j,k,l)-a(j,l,i,k);
    BOOST_CHECK_MESSAGE(c==c2,std::string("Non-destructive Subtract 1 for ")+typeid(_data_type).name());

    b(i,j,k,l)-=a(j,l,i,k);
    BOOST_CHECK_MESSAGE(b==c2,std::string("Destructive Subtract 1 for ")+typeid(_data_type).name());

    a.zeros();
    b.zeros();
    a.at(dim1-1,dim1-1,dim2-1,dim2-1)=1;
    b.at(dim2-1,dim1-1,dim2-1,dim1-1)=1;

    c(i,j,k,l)=b(i,j,k,l)+a(j,l,i,k);
    c2.zeros();
    c2.at(dim2-1,dim1-1,dim2-1,dim1-1)=2;
    BOOST_CHECK_MESSAGE(c==c2,std::string("Non-destructive Add 2 for ")+typeid(_data_type).name());

    b(i,j,k,l)+=a(j,l,i,k);
    BOOST_CHECK_MESSAGE(b==c2,std::string("Destructive Add 2 for ")+typeid(_data_type).name());

    a.at(dim1-1,dim1-1,dim2-1,dim2-1)=3;
    b.at(dim2-1,dim1-1,dim2-1,dim1-1)=5;
    c(i,j,k,l)=b(i,j,k,l)-a(j,l,i,k);
    BOOST_CHECK_MESSAGE(c==c2,std::string("Non-destructive Subtract 2 for ")+typeid(_data_type).name());

    b(i,j,k,l)-=a(j,l,i,k);
    BOOST_CHECK_MESSAGE(b==c2,std::string("Destructive Subtract 2 for ")+typeid(_data_type).name());

}

BOOST_AUTO_TEST_CASE( DenseMIAAddSubtractTests )
{

    do_work<double>(8,10);
    do_work<float>(8,10);
    do_work<int>(8,10);
    do_work<long long int>(8,10);

    do_work<double>(10,8);
    do_work<float>(10,8);
    do_work<int>(10,8);
    do_work<long long int>(10,8);

}
<|endoftext|>


<commit_before>/*
    This file is part of KDE Kontact.

    Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org>
    Copyright (c) 2002-2003 Daniel Molkentin <molkentin@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include <dcopclient.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kuniqueapplication.h>

#include <qlabel.h>
#if (QT_VERSION-0 >= 0x030200)
#include <qsplashscreen.h>
#else
#include "splash.h"
#endif

#include "mainwindow.h"

static const char *description =
    I18N_NOOP( "A KDE Personal Information Manager" );

static const char *version = "0.2.9 (CVS)";

int main(int argc, char **argv)
{
  KAboutData about( "kontact", I18N_NOOP( "Kontact" ), version, description,
                    KAboutData::License_GPL, "(C) 2001-2003 The Kontact developers", 0, "http://kontact.kde.org", "kde-pim@kde.org" );
  about.addAuthor( "Matthias Hoelzer-Kluepfel", 0, "mhk@kde.org" );
  about.addAuthor( "Daniel Molkentin", 0, "molkentin@kde.org" );
  about.addAuthor( "Don Sanders", 0, "sanders@kde.org" );
  about.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
  about.addAuthor( "Sven Lüppken", 0, "sven@kde.org" );
  about.addAuthor( "Tobias Koenig", I18N_NOOP( "Summary view widgets" ),
                   "tokoe@kde.org" );

  KCmdLineArgs::init( argc, argv, &about );
  KUniqueApplication app;

  // show splash
#if (QT_VERSION-0 >= 0x030200)
  QPixmap splashPixmap( UserIcon( "splash" ) );

  QSplashScreen *splash = new QSplashScreen( splashPixmap );
  splash->show();
#else
  Kontact::Splash *splash = new Kontact::Splash( 0, "splash" );
  splash->show();
#endif

  // see if we are starting with session management
  if ( app.isRestored() )
    RESTORE( Kontact::MainWindow )
  else {
    // no session.. just start up normally
    Kontact::MainWindow *mw = new Kontact::MainWindow;
     mw->show();
  }

  // delete splash
  delete splash;

  return app.exec();
}
<commit_msg>Some credits shuffeling: - Ordered project members chronoligically (date of join) - Tobias did far more than just the summary view, I hope he is fine with removing   the attribution. If not, please speak up - Moved mhk to the bottom and marked him as original author as requested by him   quite a while ago<commit_after>/*
    This file is part of KDE Kontact.

    Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org>
    Copyright (c) 2002-2003 Daniel Molkentin <molkentin@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include <dcopclient.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kuniqueapplication.h>

#include <qlabel.h>
#if (QT_VERSION-0 >= 0x030200)
#include <qsplashscreen.h>
#else
#include "splash.h"
#endif

#include "mainwindow.h"

static const char *description =
    I18N_NOOP( "A KDE Personal Information Manager" );

static const char *version = "0.2.9 (CVS)";

int main(int argc, char **argv)
{
  KAboutData about( "kontact", I18N_NOOP( "Kontact" ), version, description,
                    KAboutData::License_GPL, "(C) 2001-2003 The Kontact developers", 0, "http://kontact.kde.org", "kde-pim@kde.org" );
  about.addAuthor( "Daniel Molkentin", 0, "molkentin@kde.org" );
  about.addAuthor( "Don Sanders", 0, "sanders@kde.org" );
  about.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
  about.addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" );
  about.addAuthor( "Sven Lüppken", 0, "sven@kde.org" );
  about.addAuthor( "Matthias Hoelzer-Kluepfel", I18N_NOOP("Original Author"), "mhk@kde.org" );

  KCmdLineArgs::init( argc, argv, &about );
  KUniqueApplication app;

  // show splash
#if (QT_VERSION-0 >= 0x030200)
  QPixmap splashPixmap( UserIcon( "splash" ) );

  QSplashScreen *splash = new QSplashScreen( splashPixmap );
  splash->show();
#else
  Kontact::Splash *splash = new Kontact::Splash( 0, "splash" );
  splash->show();
#endif

  // see if we are starting with session management
  if ( app.isRestored() )
    RESTORE( Kontact::MainWindow )
  else {
    // no session.. just start up normally
    Kontact::MainWindow *mw = new Kontact::MainWindow;
     mw->show();
  }

  // delete splash
  delete splash;

  return app.exec();
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2015                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/config.hpp"

#define CAF_SUITE local_migration
#include "caf/test/unit_test.hpp"

#include "caf/all.hpp"

#include "caf/detail/actor_registry.hpp"

using namespace caf;

using std::endl;

namespace {

struct migratable_state {
  int value = 0;
  static const char* name;
};

const char* migratable_state::name = "migratable_actor";

template <class Archive>
void serialize(Archive& ar, migratable_state& x, const unsigned int) {
  ar & x.value;
}

struct migratable_actor : stateful_actor<migratable_state> {
  behavior make_behavior() override {
    return {
      [=](get_atom) {
        return state.value;
      },
      [=](put_atom, int value) {
        state.value = value;
      }
    };
  }
};

// always migrates to `dest`
behavior pseudo_mm(event_based_actor* self, const actor& dest) {
  return {
    [=](migrate_atom, const std::string& name, std::vector<char>& buf) {
      CAF_CHECK(name == "migratable_actor");
      self->delegate(dest, sys_atom::value, migrate_atom::value,
                     std::move(buf));
    }
  };
}

} // namespace <anonymous>

CAF_TEST(migrate_locally) {
  auto a = spawn<migratable_actor>();
  auto b = spawn<migratable_actor>();
  auto mm1 = spawn(pseudo_mm, b);
  scoped_actor self;
  self->send(a, put_atom::value, 42);
  // migrate from a to b
  self->sync_send(a, sys_atom::value, migrate_atom::value, mm1).await(
    [&](ok_atom, const actor_addr& dest) {
      CAF_CHECK(dest == b);
    }
  );
  self->sync_send(a, get_atom::value).await(
    [&](int result) {
      CAF_CHECK(result == 42);
      CAF_CHECK(self->current_sender() == b.address());
    }
  );
  auto mm2 = spawn(pseudo_mm, a);
  self->send(b, put_atom::value, 23);
  // migrate back from b to a
  self->sync_send(b, sys_atom::value, migrate_atom::value, mm2).await(
    [&](ok_atom, const actor_addr& dest) {
      CAF_CHECK(dest == a);
    }
  );
  self->sync_send(b, get_atom::value).await(
    [&](int result) {
      CAF_CHECK(result == 23);
      CAF_CHECK(self->current_sender() == a.address());
    }
  );
  self->send_exit(a, exit_reason::kill);
  self->send_exit(b, exit_reason::kill);
  self->send_exit(mm1, exit_reason::kill);
  self->send_exit(mm2, exit_reason::kill);
  self->await_all_other_actors_done();
  shutdown();
}
<commit_msg>Fix heap-use-after-free in local_migration unit-test<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2015                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/config.hpp"

#define CAF_SUITE local_migration
#include "caf/test/unit_test.hpp"

#include "caf/all.hpp"

#include "caf/detail/actor_registry.hpp"

using namespace caf;

using std::endl;

namespace {

struct migratable_state {
  int value = 0;
  static const char* name;
};

const char* migratable_state::name = "migratable_actor";

template <class Archive>
void serialize(Archive& ar, migratable_state& x, const unsigned int) {
  ar & x.value;
}

struct migratable_actor : stateful_actor<migratable_state> {
  behavior make_behavior() override {
    return {
      [=](get_atom) {
        return state.value;
      },
      [=](put_atom, int value) {
        state.value = value;
      }
    };
  }
};

// always migrates to `dest`
behavior pseudo_mm(event_based_actor* self, const actor& dest) {
  return {
    [=](migrate_atom, const std::string& name, std::vector<char>& buf) {
      CAF_CHECK(name == "migratable_actor");
      self->delegate(dest, sys_atom::value, migrate_atom::value,
                     std::move(buf));
    }
  };
}

} // namespace <anonymous>

CAF_TEST(migrate_locally) {
  auto a = spawn<migratable_actor>();
  auto b = spawn<migratable_actor>();
  auto mm1 = spawn(pseudo_mm, b);
  { // Lifetime scope of scoped_actor
    scoped_actor self;
    self->send(a, put_atom::value, 42);
    // migrate from a to b
    self->sync_send(a, sys_atom::value, migrate_atom::value, mm1).await(
      [&](ok_atom, const actor_addr& dest) {
        CAF_CHECK(dest == b);
      }
    );
    self->sync_send(a, get_atom::value).await(
      [&](int result) {
        CAF_CHECK(result == 42);
        CAF_CHECK(self->current_sender() == b.address());
      }
    );
    auto mm2 = spawn(pseudo_mm, a);
    self->send(b, put_atom::value, 23);
    // migrate back from b to a
    self->sync_send(b, sys_atom::value, migrate_atom::value, mm2).await(
      [&](ok_atom, const actor_addr& dest) {
        CAF_CHECK(dest == a);
      }
    );
    self->sync_send(b, get_atom::value).await(
      [&](int result) {
        CAF_CHECK(result == 23);
        CAF_CHECK(self->current_sender() == a.address());
      }
    );
    self->send_exit(a, exit_reason::kill);
    self->send_exit(b, exit_reason::kill);
    self->send_exit(mm1, exit_reason::kill);
    self->send_exit(mm2, exit_reason::kill);
    self->await_all_other_actors_done();
  }
  shutdown();
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
 * $Log$
 * Revision 1.4  2001/03/02 14:39:21  tng
 * Enabling libWWW NetAccessor support under UNIX. Tested with latest tarball of libWWW
 * (w3c-libwww-5.3.2) under RedHat Linux 6.1.  Added by Martin Kalen.
 *
 * There is one MAJOR problem with the use of libwww and the patches
 * below, which someone with knowledge of libwww filters etc. might want
 * to look into. Default behavior for content-type text/xml is to consume
 * all xml data before it reaches the simple HTML presenter. Hence, only
 * files with content-type text/html will actually reach the xerces-c
 * library. If you have a *.xml file on the webbserver, processing of the
 * file will throw an exception stating "The main XML document cannot be
 * empty" (correct in a xerces point of view since if you enable debug
 * build you will see that libwww "eats" all text/xml).
 *
 * See "Diffs for enabling libWWW NetAccessor support under UNIX" posted in March 1, 2001
 * in the xerces-c-dev mailing list for further information.
 *
 * Revision 1.3  2000/05/15 22:31:31  andyh
 * Replace #include<memory.h> with <string.h> everywhere.
 *
 * Revision 1.2  2000/02/26 07:56:36  rahulj
 * Fixed the license header as pointed out by Bill Schindler <developer@bitranch.com>
 *
 * Revision 1.1  2000/02/17 22:06:19  rahulj
 * Moved the four LibWWW files to its own sub-directory in the
 * NetAccessor directory.
 *
 *
 * Revision 1.1  2000/01/15 01:08:04  rahulj
 * Added support for HTTP to the parser.
 * Error handling is not very good. Also cannot guarantee that
 * there are no memory leaks.
 * Only tested under NT 4.0 SP 5 using libWWW 5.2.8.
 *
 */

#include <util/XMLNetAccessor.hpp>
#include <util/NetAccessors/libWWW/BinURLInputStream.hpp>
#include <util/XMLString.hpp>
#include <util/XMLExceptMsgs.hpp>
#include <strings.h>
#include <WWWInit.h>

//
// This define specifies the size of the buffer used to read chunks
// out of the URL input stream.
//

#define URLISBUFMAXSIZE        8192

//
// We assume here that the URL is essentially composed of just ASCII characters
// and hence converting it to a 'char *' requires just to drop the leading zero
// byte. The reason, we can get away with this is that libWWW currently provides
// no wide character API's.
//
// The input Unicode string is assumed to be 0 terminated.
// The caller is responsible to free the memory allocated to store the resultant
// 'char *' string.
//

static char* localTranscode(const XMLCh* latinStrInUnicode)
{
    unsigned int   lent = XMLString::stringLen(latinStrInUnicode);
    char*  retval = new char[lent + 1];
    unsigned int  i = 0;
    for (i = 0; i < lent; i++)
        retval[i] = (char) latinStrInUnicode[i]; // drop the leading byte.
    retval[lent] = 0;
    return retval;
}

BinURLInputStream::BinURLInputStream(const XMLURL& urlSource)
      : fBuffer(0)
      , fBufferSize(0)
      , fBufferIndex(0)
      , fRemoteFileSize(0)
      , fAnchor(0)
      , fBytesProcessed(0)
{
    fBuffer = new XMLByte[URLISBUFMAXSIZE];
    const XMLCh*  uri = urlSource.getURLText();
    char*   uriAsCharStar = localTranscode(uri);

    //
    // First find the size of the remote resource being asked for.
    // We use the ContentCounter stream provided by libWWW.
    //

    fAnchor = HTAnchor_findAddress(uriAsCharStar);
    HTRequest*   request = HTRequest_new();
    HTRequest_setOutputFormat(request, WWW_SOURCE);
    HTStream*    counterStrm = HTContentCounter(HTBlackHole(), request, 0xFFFF);
    BOOL  status = HTLoadToStream(uriAsCharStar, counterStrm, request);
    if (status == YES)
    {
        // I am not happy at all with the error handling. So that needs to
        // happen.
        HTParentAnchor*  parentAnchor = HTAnchor_parent(fAnchor);
        fRemoteFileSize = HTAnchor_length(parentAnchor);
    }

    // Cleanup, before you throw any errors.
    delete [] uriAsCharStar;
    HTRequest_delete(request);
    // Don't know whether I am supposed to delete counterStrm.

    if (status == NO)
    {
        ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_InternalError,
            "Cannot determine length of remote file.");
    }
}

BinURLInputStream::~BinURLInputStream()
{
    delete [] fBuffer;
    fBuffer = 0;
    // Do not delete the fAnchor. Its deleted when the destructor of
    // libWWWNetAccessor is called.
}

void BinURLInputStream::reset()
{
    fBufferSize = 0;
    fBytesProcessed = 0;
    fBufferIndex = 0;
    memset((void*) fBuffer, 0x00, sizeof(XMLByte) * URLISBUFMAXSIZE);
}

unsigned int BinURLInputStream::curPos() const
{
    return fBytesProcessed;
}

unsigned int BinURLInputStream::bytesAvail() const
{
    unsigned int  retval = fBufferSize - fBufferIndex;
    return retval;
}

unsigned int BinURLInputStream::readBytes(XMLByte* const  toFill
                                  , const unsigned int    maxToRead)
{
    unsigned int  retval = 0;
    unsigned int  bytesAsked = maxToRead;
    unsigned int  bytesForCopy = 0;

    // Wipe out the old stuff from the destination buffer to fill.

    memset((void*)toFill, 0x00, sizeof(XMLByte) * maxToRead);

    // You can only read till the end of the remote resource file.
    // So, adjust the count of bytes you want to read now.

    if (fBytesProcessed + bytesAsked >= fRemoteFileSize)
    {
        bytesAsked = fRemoteFileSize - fBytesProcessed;
    }

    if (fBufferSize > 0)
        bytesForCopy = fBufferSize - fBufferIndex;

    if (bytesAsked <= bytesForCopy)
    {
        // ...then you can satisfy this request completely from fBuffer.
        // Simply copy over the bytes to the destination array.
        memcpy((void*) toFill, (void*) (fBuffer + fBufferIndex), bytesAsked);
        fBufferIndex += bytesAsked;
        if (fBufferIndex >= fBufferSize)
        {
            fBufferSize = 0;
            fBufferIndex = 0;
        }
        fBytesProcessed += bytesAsked;
        retval = bytesAsked;
    }

    else
    {
        // ...will need to read some more bytes out of the stream.
        unsigned int    bufToFillIndex = 0;
        HTRequest*      request = HTRequest_new();
        HTChunk*        result = NULL;
        char            ranges[64];

        // First copy over what is left in fBuffer, before reading another
        // chunk out of the stream.

        if (bytesForCopy != 0)
        {
            memcpy((void*) toFill, (void*) (fBuffer + fBufferSize), bytesForCopy);
            fBufferSize = 0;
            fBufferIndex = 0;
            fBytesProcessed += bytesForCopy;
            bufToFillIndex = bytesForCopy;
            retval = bytesForCopy;
        }

        unsigned int    bytesRemainingForCopy = bytesAsked - bytesForCopy;

        // Now read a new chunk from the stream. HTTP lets you specify the
        // range of bytes that you would like.

        sprintf(ranges, "%ld-%ld",
                fBytesProcessed, fBytesProcessed + URLISBUFMAXSIZE - 1);
        HTRequest_addRange(request, "bytes", ranges);
        HTRequest_setOutputFormat(request, WWW_SOURCE);
        result = HTLoadAnchorToChunk(fAnchor, request);
        fBufferSize = HTChunk_size(result);
        if (fBufferSize > 0)
        {
            // Store the read chunk in fBuffer.
            memset((void*) fBuffer, 0x00, URLISBUFMAXSIZE);
            memcpy((void*) fBuffer, (void*) HTChunk_data(result), fBufferSize);
            fBufferIndex = 0;
        }

        HTRequest_delete(request);
        HTChunk_delete(result);

        // Now fill the destination buffer with the new data just read.

        bytesForCopy = fBufferSize;
        if (bytesRemainingForCopy > fBufferSize)
        {
            bytesRemainingForCopy = fBufferSize;
        }
        memcpy((void*) (toFill + bufToFillIndex),
               (void*) fBuffer,
               bytesRemainingForCopy);

        // Update counters.
        retval += bytesRemainingForCopy;
        fBufferIndex += bytesRemainingForCopy;
        fBytesProcessed += bytesRemainingForCopy;
    }

    return retval;
}
<commit_msg>Bug 2237: fix by Artur Klauser<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
 * $Log$
 * Revision 1.5  2001/11/28 19:11:33  knoaman
 * Bug 2237: fix by Artur Klauser
 *
 * Revision 1.4  2001/03/02 14:39:21  tng
 * Enabling libWWW NetAccessor support under UNIX. Tested with latest tarball of libWWW
 * (w3c-libwww-5.3.2) under RedHat Linux 6.1.  Added by Martin Kalen.
 *
 * There is one MAJOR problem with the use of libwww and the patches
 * below, which someone with knowledge of libwww filters etc. might want
 * to look into. Default behavior for content-type text/xml is to consume
 * all xml data before it reaches the simple HTML presenter. Hence, only
 * files with content-type text/html will actually reach the xerces-c
 * library. If you have a *.xml file on the webbserver, processing of the
 * file will throw an exception stating "The main XML document cannot be
 * empty" (correct in a xerces point of view since if you enable debug
 * build you will see that libwww "eats" all text/xml).
 *
 * See "Diffs for enabling libWWW NetAccessor support under UNIX" posted in March 1, 2001
 * in the xerces-c-dev mailing list for further information.
 *
 * Revision 1.3  2000/05/15 22:31:31  andyh
 * Replace #include<memory.h> with <string.h> everywhere.
 *
 * Revision 1.2  2000/02/26 07:56:36  rahulj
 * Fixed the license header as pointed out by Bill Schindler <developer@bitranch.com>
 *
 * Revision 1.1  2000/02/17 22:06:19  rahulj
 * Moved the four LibWWW files to its own sub-directory in the
 * NetAccessor directory.
 *
 *
 * Revision 1.1  2000/01/15 01:08:04  rahulj
 * Added support for HTTP to the parser.
 * Error handling is not very good. Also cannot guarantee that
 * there are no memory leaks.
 * Only tested under NT 4.0 SP 5 using libWWW 5.2.8.
 *
 */

#include <util/XMLNetAccessor.hpp>
#include <util/NetAccessors/libWWW/BinURLInputStream.hpp>
#include <util/XMLString.hpp>
#include <util/XMLExceptMsgs.hpp>
#include <strings.h>
#include <WWWInit.h>

//
// This define specifies the size of the buffer used to read chunks
// out of the URL input stream.
//

#define URLISBUFMAXSIZE        8192

//
// We assume here that the URL is essentially composed of just ASCII characters
// and hence converting it to a 'char *' requires just to drop the leading zero
// byte. The reason, we can get away with this is that libWWW currently provides
// no wide character API's.
//
// The input Unicode string is assumed to be 0 terminated.
// The caller is responsible to free the memory allocated to store the resultant
// 'char *' string.
//

static char* localTranscode(const XMLCh* latinStrInUnicode)
{
    unsigned int   lent = XMLString::stringLen(latinStrInUnicode);
    char*  retval = new char[lent + 1];
    unsigned int  i = 0;
    for (i = 0; i < lent; i++)
        retval[i] = (char) latinStrInUnicode[i]; // drop the leading byte.
    retval[lent] = 0;
    return retval;
}

BinURLInputStream::BinURLInputStream(const XMLURL& urlSource)
      : fBuffer(0)
      , fBufferSize(0)
      , fBufferIndex(0)
      , fRemoteFileSize(0)
      , fAnchor(0)
      , fBytesProcessed(0)
{
    fBuffer = new XMLByte[URLISBUFMAXSIZE];
    const XMLCh*  uri = urlSource.getURLText();
    char*   uriAsCharStar = localTranscode(uri);

    //
    // First find the size of the remote resource being asked for.
    // We use the ContentCounter stream provided by libWWW.
    //

    fAnchor = HTAnchor_findAddress(uriAsCharStar);
    HTRequest*   request = HTRequest_new();
    HTRequest_setOutputFormat(request, WWW_SOURCE);
    HTStream*    counterStrm = HTContentCounter(HTBlackHole(), request, 0xFFFF);
    BOOL  status = HTLoadToStream(uriAsCharStar, counterStrm, request);
    if (status == YES)
    {
        // Patch by Artur Klauser
        // When a redirection is processed in libWWW, it seems that
        // HTAnchor_length(anchor) == -1 on the original anchor, whereas
        // HTResponse_length(response) gives the correct content length of
        // the redirection target. This has confusedfRemoteFileSize and it was
        // not checked for a -1 response at all.
        HTResponse * response = HTRequest_response (request);
        fRemoteFileSize = HTResponse_length(response);
        if (fRemoteFileSize < 0) {
            ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_InternalError,
                "Cannot determine length of remote file.");
        }
    }

    // Cleanup, before you throw any errors.
    delete [] uriAsCharStar;
    HTRequest_delete(request);
    // Don't know whether I am supposed to delete counterStrm.

    if (status == NO)
    {
        ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_InternalError,
            "Cannot determine length of remote file.");
    }
}

BinURLInputStream::~BinURLInputStream()
{
    delete [] fBuffer;
    fBuffer = 0;
    // Do not delete the fAnchor. Its deleted when the destructor of
    // libWWWNetAccessor is called.
}

void BinURLInputStream::reset()
{
    fBufferSize = 0;
    fBytesProcessed = 0;
    fBufferIndex = 0;
    memset((void*) fBuffer, 0x00, sizeof(XMLByte) * URLISBUFMAXSIZE);
}

unsigned int BinURLInputStream::curPos() const
{
    return fBytesProcessed;
}

unsigned int BinURLInputStream::bytesAvail() const
{
    unsigned int  retval = fBufferSize - fBufferIndex;
    return retval;
}

unsigned int BinURLInputStream::readBytes(XMLByte* const  toFill
                                  , const unsigned int    maxToRead)
{
    unsigned int  retval = 0;
    unsigned int  bytesAsked = maxToRead;
    unsigned int  bytesForCopy = 0;

    // Wipe out the old stuff from the destination buffer to fill.

    memset((void*)toFill, 0x00, sizeof(XMLByte) * maxToRead);

    // You can only read till the end of the remote resource file.
    // So, adjust the count of bytes you want to read now.

    if (fBytesProcessed + bytesAsked >= fRemoteFileSize)
    {
        bytesAsked = fRemoteFileSize - fBytesProcessed;
    }

    if (fBufferSize > 0)
        bytesForCopy = fBufferSize - fBufferIndex;

    if (bytesAsked <= bytesForCopy)
    {
        // ...then you can satisfy this request completely from fBuffer.
        // Simply copy over the bytes to the destination array.
        memcpy((void*) toFill, (void*) (fBuffer + fBufferIndex), bytesAsked);
        fBufferIndex += bytesAsked;
        if (fBufferIndex >= fBufferSize)
        {
            fBufferSize = 0;
            fBufferIndex = 0;
        }
        fBytesProcessed += bytesAsked;
        retval = bytesAsked;
    }

    else
    {
        // ...will need to read some more bytes out of the stream.
        unsigned int    bufToFillIndex = 0;
        HTRequest*      request = HTRequest_new();
        HTChunk*        result = NULL;
        char            ranges[64];

        // First copy over what is left in fBuffer, before reading another
        // chunk out of the stream.

        if (bytesForCopy != 0)
        {
            memcpy((void*) toFill, (void*) (fBuffer + fBufferSize), bytesForCopy);
            fBufferSize = 0;
            fBufferIndex = 0;
            fBytesProcessed += bytesForCopy;
            bufToFillIndex = bytesForCopy;
            retval = bytesForCopy;
        }

        unsigned int    bytesRemainingForCopy = bytesAsked - bytesForCopy;

        // Now read a new chunk from the stream. HTTP lets you specify the
        // range of bytes that you would like.

        sprintf(ranges, "%ld-%ld",
                fBytesProcessed, fBytesProcessed + URLISBUFMAXSIZE - 1);
        HTRequest_addRange(request, "bytes", ranges);
        HTRequest_setOutputFormat(request, WWW_SOURCE);
        result = HTLoadAnchorToChunk(fAnchor, request);
        fBufferSize = HTChunk_size(result);
        if (fBufferSize > 0)
        {
            // Store the read chunk in fBuffer.
            memset((void*) fBuffer, 0x00, URLISBUFMAXSIZE);
            memcpy((void*) fBuffer, (void*) HTChunk_data(result), fBufferSize);
            fBufferIndex = 0;
        }

        HTRequest_delete(request);
        HTChunk_delete(result);

        // Now fill the destination buffer with the new data just read.

        bytesForCopy = fBufferSize;
        if (bytesRemainingForCopy > fBufferSize)
        {
            bytesRemainingForCopy = fBufferSize;
        }
        memcpy((void*) (toFill + bufToFillIndex),
               (void*) fBuffer,
               bytesRemainingForCopy);

        // Update counters.
        retval += bytesRemainingForCopy;
        fBufferIndex += bytesRemainingForCopy;
        fBytesProcessed += bytesRemainingForCopy;
    }

    return retval;
}
<|endoftext|>


<commit_before>#include "llvm/runner.hpp"

Runner::Runner(ModuleCompiler::Link v): v(v) {
  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();
  llvm::InitializeNativeTargetAsmParser();

  std::string onError = "";
  auto eb = new llvm::EngineBuilder(std::unique_ptr<llvm::Module>(v->getModule()));
  engine = eb
    ->setErrorStr(&onError)
    .setEngineKind(llvm::EngineKind::JIT)
    .create();
  for (const auto& pair : nameToFunPtr) {
    auto funPtr = v->getModule()->getFunction(pair.first);
    if (funPtr == nullptr) continue; // Function not used
    engine->addGlobalMapping(funPtr, pair.second);
  }
  using namespace std::placeholders;
  if (auto funPtr = v->getModule()->getFunction("_xyl_dynAllocType")) {
    auto boundToThis = std::bind(&Runner::dynAllocType, this, _1);
    engine->addGlobalMapping(funPtr, &boundToThis);
  }
  engine->finalizeObject();
  if (onError != "") throw InternalError("ExecutionEngine error", {
    METADATA_PAIRS,
    {"supplied error string", onError}
  });
}

int Runner::run() {
  return engine->runFunctionAsMain(v->getEntryPoint(), {}, {});
}

void* Runner::dynAllocType(UniqueIdentifier typeId) {
  llvm::DataLayout d(v->getModule());
  auto id = *std::find_if(ALL(*v->getTypeSetPtr().get()), [=](auto id) {
    return *id == typeId;
  });
  return std::malloc(d.getTypeAllocSize(id->getAllocaType()));
}
<commit_msg>Fix shadowing<commit_after>#include "llvm/runner.hpp"

Runner::Runner(ModuleCompiler::Link v): v(v) {
  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();
  llvm::InitializeNativeTargetAsmParser();

  std::string onError = "";
  auto eb = new llvm::EngineBuilder(std::unique_ptr<llvm::Module>(v->getModule()));
  engine = eb
    ->setErrorStr(&onError)
    .setEngineKind(llvm::EngineKind::JIT)
    .create();
  for (const auto& pair : nameToFunPtr) {
    auto funPtr = v->getModule()->getFunction(pair.first);
    if (funPtr == nullptr) continue; // Function not used
    engine->addGlobalMapping(funPtr, pair.second);
  }
  using namespace std::placeholders;
  if (auto funPtr = v->getModule()->getFunction("_xyl_dynAllocType")) {
    auto boundToThis = std::bind(&Runner::dynAllocType, this, _1);
    engine->addGlobalMapping(funPtr, &boundToThis);
  }
  engine->finalizeObject();
  if (onError != "") throw InternalError("ExecutionEngine error", {
    METADATA_PAIRS,
    {"supplied error string", onError}
  });
}

int Runner::run() {
  return engine->runFunctionAsMain(v->getEntryPoint(), {}, {});
}

void* Runner::dynAllocType(UniqueIdentifier typeId) {
  llvm::DataLayout d(v->getModule());
  auto id = *std::find_if(ALL(*v->getTypeSetPtr().get()), [=](auto tid) {
    return *tid == typeId;
  });
  return std::malloc(d.getTypeAllocSize(id->getAllocaType()));
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 **/

#include "tmb/message_bus.h"

#include <chrono>  // NOLINT(build/c++11)
#include <cstdio>
#include <cstdlib>
#include <thread>  // NOLINT(build/c++11)

#include "gflags/gflags.h"

namespace tmb {

static bool ValidateTmbReceivePollInterval(const char *flagname,
                                           std::int32_t value) {
  if (value > 0) {
    return true;
  } else {
    std::fprintf(stderr, "--%s must be at least 1\n", flagname);
    return false;
  }
}
DEFINE_int32(tmb_receive_poll_interval, 50,
             "The number of milliseconds to sleep between calls to ReceiveIfAvailableImpl() "
             "in the default active-polling implementation of ReceiveImpl().");
static const bool tmb_receive_poll_interval_dummy = gflags::RegisterFlagValidator(
    &FLAGS_tmb_receive_poll_interval,
    &ValidateTmbReceivePollInterval);

internal::NetMessageRemovalInterface*
    MessageBus::GetNetMessageRemovalInterface() {
  std::fprintf(stderr,
               "FATAL: TMB internal error. Called "
               "GetNetMessageRemovalInterface() on a MessageBus that does not "
               "support it.");
  std::exit(1);
}

std::size_t MessageBus::ReceiveImpl(const client_id receiver_id,
                                    const Priority minimum_priority,
                                    const std::size_t max_messages,
                                    const bool delete_immediately,
                                    internal::ContainerPusher *pusher) {
  std::size_t received = ReceiveIfAvailableImpl(receiver_id,
                                                minimum_priority,
                                                max_messages,
                                                delete_immediately,
                                                pusher);
  while (received == 0) {
    std::this_thread::sleep_for(
        std::chrono::milliseconds(FLAGS_tmb_receive_poll_interval));
    received = ReceiveIfAvailableImpl(receiver_id,
                                      minimum_priority,
                                      max_messages,
                                      delete_immediately,
                                      pusher);
  }

  return received;
}

}  // namespace tmb
<commit_msg>volatile keyword fixes gcc compile error<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 **/

#include "tmb/message_bus.h"

#include <chrono>  // NOLINT(build/c++11)
#include <cstdio>
#include <cstdlib>
#include <thread>  // NOLINT(build/c++11)

#include "gflags/gflags.h"

namespace tmb {

static bool ValidateTmbReceivePollInterval(const char *flagname,
                                           std::int32_t value) {
  if (value > 0) {
    return true;
  } else {
    std::fprintf(stderr, "--%s must be at least 1\n", flagname);
    return false;
  }
}
DEFINE_int32(tmb_receive_poll_interval, 50,
             "The number of milliseconds to sleep between calls to ReceiveIfAvailableImpl() "
             "in the default active-polling implementation of ReceiveImpl().");
static volatile const bool tmb_receive_poll_interval_dummy = gflags::RegisterFlagValidator(
    &FLAGS_tmb_receive_poll_interval,
    &ValidateTmbReceivePollInterval);

internal::NetMessageRemovalInterface*
    MessageBus::GetNetMessageRemovalInterface() {
  std::fprintf(stderr,
               "FATAL: TMB internal error. Called "
               "GetNetMessageRemovalInterface() on a MessageBus that does not "
               "support it.");
  std::exit(1);
}

std::size_t MessageBus::ReceiveImpl(const client_id receiver_id,
                                    const Priority minimum_priority,
                                    const std::size_t max_messages,
                                    const bool delete_immediately,
                                    internal::ContainerPusher *pusher) {
  std::size_t received = ReceiveIfAvailableImpl(receiver_id,
                                                minimum_priority,
                                                max_messages,
                                                delete_immediately,
                                                pusher);
  while (received == 0) {
    std::this_thread::sleep_for(
        std::chrono::milliseconds(FLAGS_tmb_receive_poll_interval));
    received = ReceiveIfAvailableImpl(receiver_id,
                                      minimum_priority,
                                      max_messages,
                                      delete_immediately,
                                      pusher);
  }

  return received;
}

}  // namespace tmb
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2001-2008.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : simple implementation for Unit Test Framework parameter
//  handling routines. May be rewritten in future to use some kind of
//  command-line arguments parsing facility and environment variable handling
//  facility
// ***************************************************************************

#ifndef BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
#define BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER

// Boost.Test
#include <boost/test/detail/unit_test_parameters.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/basic_cstring/compare.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/fixed_mapping.hpp>
#include <boost/test/debug.hpp>

// Boost
#include <boost/config.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/test/detail/enable_warnings.hpp>

// STL
#include <map>
#include <cstdlib>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::getenv; using ::strncmp; using ::strcmp; }
# endif

namespace boost {

namespace unit_test {

namespace {

// framework parameters and there corresponding command-line arguments
literal_string LOG_LEVEL         = "BOOST_TEST_LOG_LEVEL";
literal_string NO_RESULT_CODE    = "BOOST_TEST_RESULT_CODE";
literal_string REPORT_LEVEL      = "BOOST_TEST_REPORT_LEVEL";
literal_string TESTS_TO_RUN      = "BOOST_TESTS_TO_RUN";
literal_string SAVE_TEST_PATTERN = "BOOST_TEST_SAVE_PATTERN";
literal_string BUILD_INFO        = "BOOST_TEST_BUILD_INFO";
literal_string SHOW_PROGRESS     = "BOOST_TEST_SHOW_PROGRESS";
literal_string CATCH_SYS_ERRORS  = "BOOST_TEST_CATCH_SYSTEM_ERRORS";
literal_string AUTO_START_DBG    = "BOOST_TEST_AUTO_START_DBG";
literal_string USE_ALT_STACK     = "BOOST_TEST_USE_ALT_STACK";
literal_string DETECT_FP_EXCEPT  = "BOOST_TEST_DETECT_FP_EXCEPTIONS";
literal_string REPORT_FORMAT     = "BOOST_TEST_REPORT_FORMAT";
literal_string LOG_FORMAT        = "BOOST_TEST_LOG_FORMAT";
literal_string OUTPUT_FORMAT     = "BOOST_TEST_OUTPUT_FORMAT";
literal_string DETECT_MEM_LEAK   = "BOOST_TEST_DETECT_MEMORY_LEAK";
literal_string RANDOM_SEED       = "BOOST_TEST_RANDOM";
literal_string BREAK_EXEC_PATH   = "BOOST_TEST_BREAK_EXEC_PATH";

unit_test::log_level    s_log_level;
bool                    s_no_result_code;
unit_test::report_level s_report_level;
const_string            s_tests_to_run;
const_string            s_exec_path_to_break;
bool                    s_save_pattern;
bool                    s_show_build_info;
bool                    s_show_progress;
bool                    s_catch_sys_errors;
bool                    s_auto_start_dbg;
bool                    s_use_alt_stack;
bool                    s_detect_fp_except;
output_format           s_report_format;
output_format           s_log_format;
long                    s_detect_mem_leaks;
unsigned int            s_random_seed;

// ************************************************************************** //
// **************                 runtime_config               ************** //
// ************************************************************************** //

const_string
retrieve_framework_parameter( const_string parameter_name, int* argc, char** argv )
{
    static fixed_mapping<const_string,const_string> parameter_2_cla_name_map(
        LOG_LEVEL         , "--log_level",
        NO_RESULT_CODE    , "--result_code",
        REPORT_LEVEL      , "--report_level",
        TESTS_TO_RUN      , "--run_test",
        SAVE_TEST_PATTERN , "--save_pattern",
        BUILD_INFO        , "--build_info",
        SHOW_PROGRESS     , "--show_progress",
        CATCH_SYS_ERRORS  , "--catch_system_errors",
        AUTO_START_DBG    , "--auto_start_dbg",
        USE_ALT_STACK     , "--use_alt_stack",
        DETECT_FP_EXCEPT  , "--detect_fp_exceptions",
        REPORT_FORMAT     , "--report_format",
        LOG_FORMAT        , "--log_format",
        OUTPUT_FORMAT     , "--output_format",
        DETECT_MEM_LEAK   , "--detect_memory_leaks",
        RANDOM_SEED       , "--random",
        BREAK_EXEC_PATH   , "--break_exec_path",

        ""
    );

    // first try to find parameter among command line arguments if present
    if( argc ) {
        // locate corresponding cla name
        const_string cla_name = parameter_2_cla_name_map[parameter_name];

        if( !cla_name.is_empty() ) {
            for( int i = 1; i < *argc; ++i ) {
                if( cla_name == const_string( argv[i], cla_name.size() ) && argv[i][cla_name.size()] == '=' ) {
                    const_string result = argv[i] + cla_name.size() + 1;

                    for( int j = i; j < *argc; ++j ) {
                        argv[j] = argv[j+1];
                    }
                    --(*argc);

                    return result;
                }
            }
        }
    }

    return std::getenv( parameter_name.begin() );
}

long interpret_long( const_string from )
{
    bool negative = false;
    long res = 0;

    if( first_char( from ) == '-' ) {
        negative = true;
        from.trim_left( 1 );
    }

    const_string::iterator it = from.begin();
    for( ;it != from.end(); ++it ) {
        int d = *it - '0';

        res = 10 * res + d;
    }

    if( negative )
        res = -res;

    return res;
}

} // local namespace

//____________________________________________________________________________//

namespace runtime_config {

void
init( int* argc, char** argv )
{
    fixed_mapping<const_string,unit_test::log_level,case_ins_less<char const> > log_level_name(
        "all"           , log_successful_tests,
        "success"       , log_successful_tests,
        "test_suite"    , log_test_units,
        "unit_scope"    , log_test_units,
        "message"       , log_messages,
        "warning"       , log_warnings,
        "error"         , log_all_errors,
        "cpp_exception" , log_cpp_exception_errors,
        "system_error"  , log_system_errors,
        "fatal_error"   , log_fatal_errors,
        "nothing"       , log_nothing,

        invalid_log_level
    );

    fixed_mapping<const_string,unit_test::report_level,case_ins_less<char const> > report_level_name (
        "confirm",  CONFIRMATION_REPORT,
        "short",    SHORT_REPORT,
        "detailed", DETAILED_REPORT,
        "no",       NO_REPORT,

        INV_REPORT_LEVEL
    );

    fixed_mapping<const_string,output_format,case_ins_less<char const> > output_format_name (
        "HRF", CLF,
        "CLF", CLF,
        "XML", XML,

        CLF
    );

    s_no_result_code    = retrieve_framework_parameter( NO_RESULT_CODE, argc, argv ) == "no";
    s_save_pattern      = retrieve_framework_parameter( SAVE_TEST_PATTERN, argc, argv ) == "yes";
    s_show_build_info   = retrieve_framework_parameter( BUILD_INFO, argc, argv ) == "yes";
    s_show_progress     = retrieve_framework_parameter( SHOW_PROGRESS, argc, argv ) == "yes";
    s_catch_sys_errors  = retrieve_framework_parameter( CATCH_SYS_ERRORS, argc, argv ) != "no";
    s_use_alt_stack     = retrieve_framework_parameter( USE_ALT_STACK, argc, argv ) != "no";
    s_detect_fp_except  = retrieve_framework_parameter( DETECT_FP_EXCEPT, argc, argv ) == "yes";
    s_tests_to_run      = retrieve_framework_parameter( TESTS_TO_RUN, argc, argv );
    s_exec_path_to_break= retrieve_framework_parameter( BREAK_EXEC_PATH, argc, argv );

    const_string rs_str = retrieve_framework_parameter( RANDOM_SEED, argc, argv );
    s_random_seed       = rs_str.is_empty() ? 0 : lexical_cast<unsigned int>( rs_str );

    s_log_level         = log_level_name[retrieve_framework_parameter( LOG_LEVEL, argc, argv )];
    s_report_level      = report_level_name[retrieve_framework_parameter( REPORT_LEVEL, argc, argv )];

    s_report_format     = output_format_name[retrieve_framework_parameter( REPORT_FORMAT, argc, argv )];
    s_log_format        = output_format_name[retrieve_framework_parameter( LOG_FORMAT, argc, argv )];

    const_string output_format = retrieve_framework_parameter( OUTPUT_FORMAT, argc, argv );
    if( !output_format.is_empty() ) {
        s_report_format     = output_format_name[output_format];
        s_log_format        = output_format_name[output_format];
    }

    const_string ml_str = retrieve_framework_parameter( DETECT_MEM_LEAK, argc, argv );
    s_detect_mem_leaks  =  ml_str.is_empty() ? 1 : interpret_long( ml_str );

    const_string dbg = retrieve_framework_parameter( AUTO_START_DBG, argc, argv );

    if( dbg.is_empty() || dbg == "no" )
        s_auto_start_dbg = false;
    else {
        s_auto_start_dbg = true;

        if( dbg != "yes" )
            debug::set_debugger( dbg );
    }
}

//____________________________________________________________________________//

unit_test::log_level
log_level()
{
    return s_log_level;
}

//____________________________________________________________________________//

bool
no_result_code()
{
    return s_no_result_code;
}

//____________________________________________________________________________//

unit_test::report_level
report_level()
{
    return s_report_level;
}

//____________________________________________________________________________//

const_string
test_to_run()
{
    return s_tests_to_run;
}

//____________________________________________________________________________//

const_string
break_exec_path()
{
    return s_exec_path_to_break;
}

//____________________________________________________________________________//

bool
save_pattern()
{
    return s_save_pattern;
}

//____________________________________________________________________________//

bool
show_progress()
{
    return s_show_progress;
}

//____________________________________________________________________________//

bool
show_build_info()
{
    return s_show_build_info;
}

//____________________________________________________________________________//

bool
catch_sys_errors()
{
    return s_catch_sys_errors;
}

//____________________________________________________________________________//

bool
auto_start_dbg()
{
    return s_auto_start_dbg;
}

//____________________________________________________________________________//

bool
use_alt_stack()
{
    return s_use_alt_stack;
}

//____________________________________________________________________________//

bool
detect_fp_exceptions()
{
    return s_detect_fp_except;
}

//____________________________________________________________________________//

output_format
report_format()
{
    return s_report_format;
}

//____________________________________________________________________________//

output_format
log_format()
{
    return s_log_format;
}

//____________________________________________________________________________//

long
detect_memory_leaks()
{
    return s_detect_mem_leaks;
}

//____________________________________________________________________________//

int
random_seed()
{
    return s_random_seed;
}

//____________________________________________________________________________//

} // namespace runtime_config

} // namespace unit_test

} // namespace boost

//____________________________________________________________________________//

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
<commit_msg>compile time switch to change default for catch_system_error parameter<commit_after>//  (C) Copyright Gennadiy Rozental 2001-2008.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : simple implementation for Unit Test Framework parameter
//  handling routines. May be rewritten in future to use some kind of
//  command-line arguments parsing facility and environment variable handling
//  facility
// ***************************************************************************

#ifndef BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
#define BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER

// Boost.Test
#include <boost/test/detail/unit_test_parameters.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/basic_cstring/compare.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/fixed_mapping.hpp>
#include <boost/test/debug.hpp>

// Boost
#include <boost/config.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/test/detail/enable_warnings.hpp>

// STL
#include <map>
#include <cstdlib>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::getenv; using ::strncmp; using ::strcmp; }
# endif

namespace boost {

namespace unit_test {

namespace {

// framework parameters and there corresponding command-line arguments
literal_string LOG_LEVEL         = "BOOST_TEST_LOG_LEVEL";
literal_string NO_RESULT_CODE    = "BOOST_TEST_RESULT_CODE";
literal_string REPORT_LEVEL      = "BOOST_TEST_REPORT_LEVEL";
literal_string TESTS_TO_RUN      = "BOOST_TESTS_TO_RUN";
literal_string SAVE_TEST_PATTERN = "BOOST_TEST_SAVE_PATTERN";
literal_string BUILD_INFO        = "BOOST_TEST_BUILD_INFO";
literal_string SHOW_PROGRESS     = "BOOST_TEST_SHOW_PROGRESS";
literal_string CATCH_SYS_ERRORS  = "BOOST_TEST_CATCH_SYSTEM_ERRORS";
literal_string AUTO_START_DBG    = "BOOST_TEST_AUTO_START_DBG";
literal_string USE_ALT_STACK     = "BOOST_TEST_USE_ALT_STACK";
literal_string DETECT_FP_EXCEPT  = "BOOST_TEST_DETECT_FP_EXCEPTIONS";
literal_string REPORT_FORMAT     = "BOOST_TEST_REPORT_FORMAT";
literal_string LOG_FORMAT        = "BOOST_TEST_LOG_FORMAT";
literal_string OUTPUT_FORMAT     = "BOOST_TEST_OUTPUT_FORMAT";
literal_string DETECT_MEM_LEAK   = "BOOST_TEST_DETECT_MEMORY_LEAK";
literal_string RANDOM_SEED       = "BOOST_TEST_RANDOM";
literal_string BREAK_EXEC_PATH   = "BOOST_TEST_BREAK_EXEC_PATH";

unit_test::log_level    s_log_level;
bool                    s_no_result_code;
unit_test::report_level s_report_level;
const_string            s_tests_to_run;
const_string            s_exec_path_to_break;
bool                    s_save_pattern;
bool                    s_show_build_info;
bool                    s_show_progress;
bool                    s_catch_sys_errors;
bool                    s_auto_start_dbg;
bool                    s_use_alt_stack;
bool                    s_detect_fp_except;
output_format           s_report_format;
output_format           s_log_format;
long                    s_detect_mem_leaks;
unsigned int            s_random_seed;

// ************************************************************************** //
// **************                 runtime_config               ************** //
// ************************************************************************** //

const_string
retrieve_framework_parameter( const_string parameter_name, int* argc, char** argv )
{
    static fixed_mapping<const_string,const_string> parameter_2_cla_name_map(
        LOG_LEVEL         , "--log_level",
        NO_RESULT_CODE    , "--result_code",
        REPORT_LEVEL      , "--report_level",
        TESTS_TO_RUN      , "--run_test",
        SAVE_TEST_PATTERN , "--save_pattern",
        BUILD_INFO        , "--build_info",
        SHOW_PROGRESS     , "--show_progress",
        CATCH_SYS_ERRORS  , "--catch_system_errors",
        AUTO_START_DBG    , "--auto_start_dbg",
        USE_ALT_STACK     , "--use_alt_stack",
        DETECT_FP_EXCEPT  , "--detect_fp_exceptions",
        REPORT_FORMAT     , "--report_format",
        LOG_FORMAT        , "--log_format",
        OUTPUT_FORMAT     , "--output_format",
        DETECT_MEM_LEAK   , "--detect_memory_leaks",
        RANDOM_SEED       , "--random",
        BREAK_EXEC_PATH   , "--break_exec_path",

        ""
    );

    // first try to find parameter among command line arguments if present
    if( argc ) {
        // locate corresponding cla name
        const_string cla_name = parameter_2_cla_name_map[parameter_name];

        if( !cla_name.is_empty() ) {
            for( int i = 1; i < *argc; ++i ) {
                if( cla_name == const_string( argv[i], cla_name.size() ) && argv[i][cla_name.size()] == '=' ) {
                    const_string result = argv[i] + cla_name.size() + 1;

                    for( int j = i; j < *argc; ++j ) {
                        argv[j] = argv[j+1];
                    }
                    --(*argc);

                    return result;
                }
            }
        }
    }

    return std::getenv( parameter_name.begin() );
}

long interpret_long( const_string from )
{
    bool negative = false;
    long res = 0;

    if( first_char( from ) == '-' ) {
        negative = true;
        from.trim_left( 1 );
    }

    const_string::iterator it = from.begin();
    for( ;it != from.end(); ++it ) {
        int d = *it - '0';

        res = 10 * res + d;
    }

    if( negative )
        res = -res;

    return res;
}

} // local namespace

//____________________________________________________________________________//

namespace runtime_config {

void
init( int* argc, char** argv )
{
    fixed_mapping<const_string,unit_test::log_level,case_ins_less<char const> > log_level_name(
        "all"           , log_successful_tests,
        "success"       , log_successful_tests,
        "test_suite"    , log_test_units,
        "unit_scope"    , log_test_units,
        "message"       , log_messages,
        "warning"       , log_warnings,
        "error"         , log_all_errors,
        "cpp_exception" , log_cpp_exception_errors,
        "system_error"  , log_system_errors,
        "fatal_error"   , log_fatal_errors,
        "nothing"       , log_nothing,

        invalid_log_level
    );

    fixed_mapping<const_string,unit_test::report_level,case_ins_less<char const> > report_level_name (
        "confirm",  CONFIRMATION_REPORT,
        "short",    SHORT_REPORT,
        "detailed", DETAILED_REPORT,
        "no",       NO_REPORT,

        INV_REPORT_LEVEL
    );

    fixed_mapping<const_string,output_format,case_ins_less<char const> > output_format_name (
        "HRF", CLF,
        "CLF", CLF,
        "XML", XML,

        CLF
    );

    s_no_result_code    = retrieve_framework_parameter( NO_RESULT_CODE, argc, argv ) == "no";
    s_save_pattern      = retrieve_framework_parameter( SAVE_TEST_PATTERN, argc, argv ) == "yes";
    s_show_build_info   = retrieve_framework_parameter( BUILD_INFO, argc, argv ) == "yes";
    s_show_progress     = retrieve_framework_parameter( SHOW_PROGRESS, argc, argv ) == "yes";
#ifdef BOOST_TEST_DEFAULTS_TO_CORE_DUMP
    s_catch_sys_errors  = retrieve_framework_parameter( CATCH_SYS_ERRORS, argc, argv ) == "yes";
#else
    s_catch_sys_errors  = retrieve_framework_parameter( CATCH_SYS_ERRORS, argc, argv ) != "no";
#endif
    s_use_alt_stack     = retrieve_framework_parameter( USE_ALT_STACK, argc, argv ) != "no";
    s_detect_fp_except  = retrieve_framework_parameter( DETECT_FP_EXCEPT, argc, argv ) == "yes";
    s_tests_to_run      = retrieve_framework_parameter( TESTS_TO_RUN, argc, argv );
    s_exec_path_to_break= retrieve_framework_parameter( BREAK_EXEC_PATH, argc, argv );

    const_string rs_str = retrieve_framework_parameter( RANDOM_SEED, argc, argv );
    s_random_seed       = rs_str.is_empty() ? 0 : lexical_cast<unsigned int>( rs_str );

    s_log_level         = log_level_name[retrieve_framework_parameter( LOG_LEVEL, argc, argv )];
    s_report_level      = report_level_name[retrieve_framework_parameter( REPORT_LEVEL, argc, argv )];

    s_report_format     = output_format_name[retrieve_framework_parameter( REPORT_FORMAT, argc, argv )];
    s_log_format        = output_format_name[retrieve_framework_parameter( LOG_FORMAT, argc, argv )];

    const_string output_format = retrieve_framework_parameter( OUTPUT_FORMAT, argc, argv );
    if( !output_format.is_empty() ) {
        s_report_format     = output_format_name[output_format];
        s_log_format        = output_format_name[output_format];
    }

    const_string ml_str = retrieve_framework_parameter( DETECT_MEM_LEAK, argc, argv );
    s_detect_mem_leaks  =  ml_str.is_empty() ? 1 : interpret_long( ml_str );

    const_string dbg = retrieve_framework_parameter( AUTO_START_DBG, argc, argv );

    if( dbg.is_empty() || dbg == "no" )
        s_auto_start_dbg = false;
    else {
        s_auto_start_dbg = true;

        if( dbg != "yes" )
            debug::set_debugger( dbg );
    }
}

//____________________________________________________________________________//

unit_test::log_level
log_level()
{
    return s_log_level;
}

//____________________________________________________________________________//

bool
no_result_code()
{
    return s_no_result_code;
}

//____________________________________________________________________________//

unit_test::report_level
report_level()
{
    return s_report_level;
}

//____________________________________________________________________________//

const_string
test_to_run()
{
    return s_tests_to_run;
}

//____________________________________________________________________________//

const_string
break_exec_path()
{
    return s_exec_path_to_break;
}

//____________________________________________________________________________//

bool
save_pattern()
{
    return s_save_pattern;
}

//____________________________________________________________________________//

bool
show_progress()
{
    return s_show_progress;
}

//____________________________________________________________________________//

bool
show_build_info()
{
    return s_show_build_info;
}

//____________________________________________________________________________//

bool
catch_sys_errors()
{
    return s_catch_sys_errors;
}

//____________________________________________________________________________//

bool
auto_start_dbg()
{
    return s_auto_start_dbg;
}

//____________________________________________________________________________//

bool
use_alt_stack()
{
    return s_use_alt_stack;
}

//____________________________________________________________________________//

bool
detect_fp_exceptions()
{
    return s_detect_fp_except;
}

//____________________________________________________________________________//

output_format
report_format()
{
    return s_report_format;
}

//____________________________________________________________________________//

output_format
log_format()
{
    return s_log_format;
}

//____________________________________________________________________________//

long
detect_memory_leaks()
{
    return s_detect_mem_leaks;
}

//____________________________________________________________________________//

int
random_seed()
{
    return s_random_seed;
}

//____________________________________________________________________________//

} // namespace runtime_config

} // namespace unit_test

} // namespace boost

//____________________________________________________________________________//

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
<|endoftext|>