<commit_before>//==============================================================================
// CellMLAnnotationView plugin
//==============================================================================

#include "cellmlannotationviewcellmldetailswidget.h"
#include "cellmlannotationviewdetailswidget.h"
#include "cellmlannotationviewlistswidget.h"
#include "cellmlannotationviewplugin.h"
#include "cellmlannotationviewwidget.h"
#include "cellmlfilemanager.h"
#include "coreutils.h"

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

#include <QApplication>
#include <QDesktopWidget>
#include <QMainWindow>
#include <QSettings>

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

namespace OpenCOR {
namespace CellMLAnnotationView {

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

PLUGININFO_FUNC CellMLAnnotationViewPluginInfo()
{
    Descriptions descriptions;

    descriptions.insert("en", "A plugin to annotate CellML files");
    descriptions.insert("fr", "Une extension pour annoter des fichiers CellML");

    return new PluginInfo(PluginInfo::V001,
                          PluginInfo::Gui,
                          PluginInfo::Editing,
                          true,
                          QStringList() << "CoreCellMLEditing" << "QJson" << "RICORDOSupport",
                          descriptions);
}

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

Q_EXPORT_PLUGIN2(CellMLAnnotationView, CellMLAnnotationViewPlugin)

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

CellMLAnnotationViewPlugin::CellMLAnnotationViewPlugin() :
    mSizes(QList<int>()),
    mListsWidgetSizes(QList<int>()),
    mCellmlDetailsWidgetSizes(QList<int>()),
    mViewWidgets(QMap<QString, CellmlAnnotationViewWidget *>())
{
    // Set our settings

    mGuiSettings->setView(GuiViewSettings::Editing);
}

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

CellMLAnnotationViewPlugin::~CellMLAnnotationViewPlugin()
{
    // Delete our view widgets

    foreach (QWidget *viewWidget, mViewWidgets)
        delete viewWidget;
}

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

static const QString SettingsCellmlAnnotationWidget                              = "CellmlAnnotationWidget";
static const QString SettingsCellmlAnnotationWidgetSizesCount                    = "SizesCount";
static const QString SettingsCellmlAnnotationWidgetSizes                         = "Sizes%1";
static const QString SettingsCellmlAnnotationWidgetListsWidgetSizesCount         = "ListsWidgetSizesCount";
static const QString SettingsCellmlAnnotationWidgetListsWidgetSizes              = "ListsWidgetSizes%1";
static const QString SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizesCount = "CellmlDetailsWidgetSizesCount";
static const QString SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizes      = "CellmlDetailsWidgetSizes%1";

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

void CellMLAnnotationViewPlugin::loadSettings(QSettings *pSettings)
{
    // Retrieve the size of the different items that make up our splitters
    // Note: we would normally do this in CellmlAnnotationViewWidget, but we
    //       have one instance of it per CellML file and we want to share some
    //       information between the different instances, so we have to do it
    //       here instead...

    pSettings->beginGroup(SettingsCellmlAnnotationWidget);
        // Sizes

        int sizesCount = pSettings->value(SettingsCellmlAnnotationWidgetSizesCount, 0).toInt();

        if (!sizesCount) {
            // There are no previous sizes, so get some default ones

            mSizes << 0.25*qApp->desktop()->screenGeometry().width()
                   << 0.75*qApp->desktop()->screenGeometry().width();
        } else {
            // There are previous sizes, so use them to initialise mSizes

            for (int i = 0; i < sizesCount; ++i)
                mSizes << pSettings->value(SettingsCellmlAnnotationWidgetSizes.arg(QString::number(i))).toInt();
        }

        // View widget sizes

        int listsWidgetSizesCount = pSettings->value(SettingsCellmlAnnotationWidgetListsWidgetSizesCount, 0).toInt();

        if (!listsWidgetSizesCount) {
            // There are no previous view widget sizes, so get some default ones

            mListsWidgetSizes << 0.75*qApp->desktop()->screenGeometry().height()
                              << 0.25*qApp->desktop()->screenGeometry().height();
        } else {
            // There are previous view widget sizes, so use them to initialise
            // mListsWidgetSizes

            for (int i = 0; i < listsWidgetSizesCount; ++i)
                mListsWidgetSizes << pSettings->value(SettingsCellmlAnnotationWidgetListsWidgetSizes.arg(QString::number(i))).toInt();
        }

        // CellML details view widget sizes

        int cellmlDetailsWidgetSizesCount = pSettings->value(SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizesCount, 0).toInt();

        if (!cellmlDetailsWidgetSizesCount) {
            // There are no previous view widget sizes, so get some default ones

            mCellmlDetailsWidgetSizes << 0.25*qApp->desktop()->screenGeometry().height()
                                      << 0.25*qApp->desktop()->screenGeometry().height()
                                      << 0.50*qApp->desktop()->screenGeometry().height();
        } else {
            // There are previous view widget sizes, so use them to initialise
            // mCellmlDetailsWidgetSizes

            for (int i = 0; i < cellmlDetailsWidgetSizesCount; ++i)
                mCellmlDetailsWidgetSizes << pSettings->value(SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizes.arg(QString::number(i))).toInt();
        }
    pSettings->endGroup();
}

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

void CellMLAnnotationViewPlugin::saveSettings(QSettings *pSettings) const
{
    // Keep track of the tree view's and CellML annotation's width
    // Note: we must also keep track of the CellML annotation's width because
    //       when loading our settings (see above), the view widget doesn't yet
    //       have a 'proper' width, so we couldn't simply assume that the Cellml
    //       annotation's initial width is this view widget's width minus the
    //       tree view's initial width, so...

    pSettings->beginGroup(SettingsCellmlAnnotationWidget);
        // Sizes

        pSettings->setValue(SettingsCellmlAnnotationWidgetSizesCount, mSizes.count());

        for (int i = 0, iMax = mSizes.count(); i < iMax; ++i)
            pSettings->setValue(SettingsCellmlAnnotationWidgetSizes.arg(QString::number(i)), mSizes[i]);

        // View widget sizes

        pSettings->setValue(SettingsCellmlAnnotationWidgetListsWidgetSizesCount, mListsWidgetSizes.count());

        for (int i = 0, iMax = mListsWidgetSizes.count(); i < iMax; ++i)
            pSettings->setValue(SettingsCellmlAnnotationWidgetListsWidgetSizes.arg(QString::number(i)), mListsWidgetSizes[i]);

        // CellML details view widget sizes

        pSettings->setValue(SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizesCount, mCellmlDetailsWidgetSizes.count());

        for (int i = 0, iMax = mCellmlDetailsWidgetSizes.count(); i < iMax; ++i)
            pSettings->setValue(SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizes.arg(QString::number(i)), mCellmlDetailsWidgetSizes[i]);
    pSettings->endGroup();
}

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

QWidget * CellMLAnnotationViewPlugin::viewWidget(const QString &pFileName)
{
    // Check that we are dealing with a CellML file

    if (!CellMLSupport::CellmlFileManager::instance()->cellmlFile(pFileName))
        // We are not dealing with a CellML file, so...

        return 0;

    // Retrieve from our list the view widget associated with the file name

    CellmlAnnotationViewWidget *res = mViewWidgets.value(pFileName);

    // Create a new view widget, if none could be retrieved

    if (!res) {
        res = new CellmlAnnotationViewWidget(mMainWindow, this, pFileName);

        // Initialise our new view widget's sizes

        res->setSizes(mSizes);
        res->listsWidget()->setSizes(mListsWidgetSizes);
        res->detailsWidget()->cellmlDetails()->setSizes(mCellmlDetailsWidgetSizes);

        // Keep track of the splitter move in our new view widget

        connect(res, SIGNAL(splitterMoved(const QList<int> &)),
                this, SLOT(splitterMoved(const QList<int> &)));
        connect(res->listsWidget(), SIGNAL(splitterMoved(const QList<int> &)),
                this, SLOT(listsWidgetSplitterMoved(const QList<int> &)));
        connect(res->detailsWidget()->cellmlDetails(), SIGNAL(splitterMoved(const QList<int> &)),
                this, SLOT(cellmlDetailsWidgetSplitterMoved(const QList<int> &)));

        // Some other connections to handle splitter moves between our view
        // widgets

        foreach (CellmlAnnotationViewWidget *viewWidget, mViewWidgets) {
            // Make sur that our new view widget is aware of any splitter move
            // occuring in the other view widget

            connect(res, SIGNAL(splitterMoved(const QList<int> &)),
                    viewWidget, SLOT(updateSizes(const QList<int> &)));
            connect(res->listsWidget(), SIGNAL(splitterMoved(const QList<int> &)),
                    viewWidget->listsWidget(), SLOT(updateSizes(const QList<int> &)));
            connect(res->detailsWidget()->cellmlDetails(), SIGNAL(splitterMoved(const QList<int> &)),
                    viewWidget->detailsWidget()->cellmlDetails(), SLOT(updateSizes(const QList<int> &)));

            // Make sur that the other view widget is aware of any splitter move
            // occuring in our new view widget

            connect(viewWidget, SIGNAL(splitterMoved(const QList<int> &)),
                    res, SLOT(updateSizes(const QList<int> &)));
            connect(viewWidget->listsWidget(), SIGNAL(splitterMoved(const QList<int> &)),
                    res->listsWidget(), SLOT(updateSizes(const QList<int> &)));
            connect(viewWidget->detailsWidget()->cellmlDetails(), SIGNAL(splitterMoved(const QList<int> &)),
                    res->detailsWidget()->cellmlDetails(), SLOT(updateSizes(const QList<int> &)));
        }

        // Keep track of our new view widget

        mViewWidgets.insert(pFileName, res);
    }

    // Return our view widget

    return res;
}

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

bool CellMLAnnotationViewPlugin::hasViewWidget(const QString &pFileName) const
{
    // Return whether a view widget exists or not for the given file name

    return mViewWidgets.value(pFileName);
}

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

void CellMLAnnotationViewPlugin::deleteViewWidget(const QString &pFileName)
{
    // Remove the view widget from our list, should there be one for the given
    // file name

    CellmlAnnotationViewWidget *viewWidget = mViewWidgets.value(pFileName);

    if (viewWidget) {
        // There is a view widget for the given file name, so delete it and
        // remove it from our list

        delete viewWidget;

        mViewWidgets.remove(pFileName);
    }
}

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

QString CellMLAnnotationViewPlugin::viewName()
{
    // Return our CellML annotation view's name

    return tr("CellML Annotation");
}

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

void CellMLAnnotationViewPlugin::retranslateUi()
{
    // Retranslate all of our CellML annotation view widgets

    foreach (CellmlAnnotationViewWidget *viewWidget, mViewWidgets)
        viewWidget->retranslateUi();
}

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

void CellMLAnnotationViewPlugin::splitterMoved(const QList<int> &pSizes)
{
    // The splitter of one of our CellML annotation view widgets has been moved,
    // so update things

    mSizes = pSizes;
}

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

void CellMLAnnotationViewPlugin::listsWidgetSplitterMoved(const QList<int> &pSizes)
{
    // The splitter of one of our CellML annotation view's lists widgets has
    // been moved, so update things

    mListsWidgetSizes = pSizes;
}

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

void CellMLAnnotationViewPlugin::cellmlDetailsWidgetSplitterMoved(const QList<int> &pSizes)
{
    // The splitter of one of our CellML annotation view's CellML details
    // widgets has been moved, so update things

    mCellmlDetailsWidgetSizes = pSizes;
}

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

}   // namespace CellMLAnnotationView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Minor GUI update as a result of our work on the CellML Annotation view (#78).<commit_after>//==============================================================================
// CellMLAnnotationView plugin
//==============================================================================

#include "cellmlannotationviewcellmldetailswidget.h"
#include "cellmlannotationviewdetailswidget.h"
#include "cellmlannotationviewlistswidget.h"
#include "cellmlannotationviewplugin.h"
#include "cellmlannotationviewwidget.h"
#include "cellmlfilemanager.h"
#include "coreutils.h"

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

#include <QApplication>
#include <QDesktopWidget>
#include <QMainWindow>
#include <QSettings>

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

namespace OpenCOR {
namespace CellMLAnnotationView {

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

PLUGININFO_FUNC CellMLAnnotationViewPluginInfo()
{
    Descriptions descriptions;

    descriptions.insert("en", "A plugin to annotate CellML files");
    descriptions.insert("fr", "Une extension pour annoter des fichiers CellML");

    return new PluginInfo(PluginInfo::V001,
                          PluginInfo::Gui,
                          PluginInfo::Editing,
                          true,
                          QStringList() << "CoreCellMLEditing" << "QJson" << "RICORDOSupport",
                          descriptions);
}

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

Q_EXPORT_PLUGIN2(CellMLAnnotationView, CellMLAnnotationViewPlugin)

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

CellMLAnnotationViewPlugin::CellMLAnnotationViewPlugin() :
    mSizes(QList<int>()),
    mListsWidgetSizes(QList<int>()),
    mCellmlDetailsWidgetSizes(QList<int>()),
    mViewWidgets(QMap<QString, CellmlAnnotationViewWidget *>())
{
    // Set our settings

    mGuiSettings->setView(GuiViewSettings::Editing);
}

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

CellMLAnnotationViewPlugin::~CellMLAnnotationViewPlugin()
{
    // Delete our view widgets

    foreach (QWidget *viewWidget, mViewWidgets)
        delete viewWidget;
}

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

static const QString SettingsCellmlAnnotationWidget                              = "CellmlAnnotationWidget";
static const QString SettingsCellmlAnnotationWidgetSizesCount                    = "SizesCount";
static const QString SettingsCellmlAnnotationWidgetSizes                         = "Sizes%1";
static const QString SettingsCellmlAnnotationWidgetListsWidgetSizesCount         = "ListsWidgetSizesCount";
static const QString SettingsCellmlAnnotationWidgetListsWidgetSizes              = "ListsWidgetSizes%1";
static const QString SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizesCount = "CellmlDetailsWidgetSizesCount";
static const QString SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizes      = "CellmlDetailsWidgetSizes%1";

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

void CellMLAnnotationViewPlugin::loadSettings(QSettings *pSettings)
{
    // Retrieve the size of the different items that make up our splitters
    // Note: we would normally do this in CellmlAnnotationViewWidget, but we
    //       have one instance of it per CellML file and we want to share some
    //       information between the different instances, so we have to do it
    //       here instead...

    pSettings->beginGroup(SettingsCellmlAnnotationWidget);
        // Sizes

        int sizesCount = pSettings->value(SettingsCellmlAnnotationWidgetSizesCount, 0).toInt();

        if (!sizesCount) {
            // There are no previous sizes, so get some default ones

            mSizes << 0.25*qApp->desktop()->screenGeometry().width()
                   << 0.75*qApp->desktop()->screenGeometry().width();
        } else {
            // There are previous sizes, so use them to initialise mSizes

            for (int i = 0; i < sizesCount; ++i)
                mSizes << pSettings->value(SettingsCellmlAnnotationWidgetSizes.arg(QString::number(i))).toInt();
        }

        // View widget sizes

        int listsWidgetSizesCount = pSettings->value(SettingsCellmlAnnotationWidgetListsWidgetSizesCount, 0).toInt();

        if (!listsWidgetSizesCount) {
            // There are no previous view widget sizes, so get some default ones

            mListsWidgetSizes << 0.65*qApp->desktop()->screenGeometry().height()
                              << 0.35*qApp->desktop()->screenGeometry().height();
        } else {
            // There are previous view widget sizes, so use them to initialise
            // mListsWidgetSizes

            for (int i = 0; i < listsWidgetSizesCount; ++i)
                mListsWidgetSizes << pSettings->value(SettingsCellmlAnnotationWidgetListsWidgetSizes.arg(QString::number(i))).toInt();
        }

        // CellML details view widget sizes

        int cellmlDetailsWidgetSizesCount = pSettings->value(SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizesCount, 0).toInt();

        if (!cellmlDetailsWidgetSizesCount) {
            // There are no previous view widget sizes, so get some default ones

            mCellmlDetailsWidgetSizes << 0.25*qApp->desktop()->screenGeometry().height()
                                      << 0.25*qApp->desktop()->screenGeometry().height()
                                      << 0.50*qApp->desktop()->screenGeometry().height();
        } else {
            // There are previous view widget sizes, so use them to initialise
            // mCellmlDetailsWidgetSizes

            for (int i = 0; i < cellmlDetailsWidgetSizesCount; ++i)
                mCellmlDetailsWidgetSizes << pSettings->value(SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizes.arg(QString::number(i))).toInt();
        }
    pSettings->endGroup();
}

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

void CellMLAnnotationViewPlugin::saveSettings(QSettings *pSettings) const
{
    // Keep track of the tree view's and CellML annotation's width
    // Note: we must also keep track of the CellML annotation's width because
    //       when loading our settings (see above), the view widget doesn't yet
    //       have a 'proper' width, so we couldn't simply assume that the Cellml
    //       annotation's initial width is this view widget's width minus the
    //       tree view's initial width, so...

    pSettings->beginGroup(SettingsCellmlAnnotationWidget);
        // Sizes

        pSettings->setValue(SettingsCellmlAnnotationWidgetSizesCount, mSizes.count());

        for (int i = 0, iMax = mSizes.count(); i < iMax; ++i)
            pSettings->setValue(SettingsCellmlAnnotationWidgetSizes.arg(QString::number(i)), mSizes[i]);

        // View widget sizes

        pSettings->setValue(SettingsCellmlAnnotationWidgetListsWidgetSizesCount, mListsWidgetSizes.count());

        for (int i = 0, iMax = mListsWidgetSizes.count(); i < iMax; ++i)
            pSettings->setValue(SettingsCellmlAnnotationWidgetListsWidgetSizes.arg(QString::number(i)), mListsWidgetSizes[i]);

        // CellML details view widget sizes

        pSettings->setValue(SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizesCount, mCellmlDetailsWidgetSizes.count());

        for (int i = 0, iMax = mCellmlDetailsWidgetSizes.count(); i < iMax; ++i)
            pSettings->setValue(SettingsCellmlAnnotationWidgetCellmlDetailsWidgetSizes.arg(QString::number(i)), mCellmlDetailsWidgetSizes[i]);
    pSettings->endGroup();
}

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

QWidget * CellMLAnnotationViewPlugin::viewWidget(const QString &pFileName)
{
    // Check that we are dealing with a CellML file

    if (!CellMLSupport::CellmlFileManager::instance()->cellmlFile(pFileName))
        // We are not dealing with a CellML file, so...

        return 0;

    // Retrieve from our list the view widget associated with the file name

    CellmlAnnotationViewWidget *res = mViewWidgets.value(pFileName);

    // Create a new view widget, if none could be retrieved

    if (!res) {
        res = new CellmlAnnotationViewWidget(mMainWindow, this, pFileName);

        // Initialise our new view widget's sizes

        res->setSizes(mSizes);
        res->listsWidget()->setSizes(mListsWidgetSizes);
        res->detailsWidget()->cellmlDetails()->setSizes(mCellmlDetailsWidgetSizes);

        // Keep track of the splitter move in our new view widget

        connect(res, SIGNAL(splitterMoved(const QList<int> &)),
                this, SLOT(splitterMoved(const QList<int> &)));
        connect(res->listsWidget(), SIGNAL(splitterMoved(const QList<int> &)),
                this, SLOT(listsWidgetSplitterMoved(const QList<int> &)));
        connect(res->detailsWidget()->cellmlDetails(), SIGNAL(splitterMoved(const QList<int> &)),
                this, SLOT(cellmlDetailsWidgetSplitterMoved(const QList<int> &)));

        // Some other connections to handle splitter moves between our view
        // widgets

        foreach (CellmlAnnotationViewWidget *viewWidget, mViewWidgets) {
            // Make sur that our new view widget is aware of any splitter move
            // occuring in the other view widget

            connect(res, SIGNAL(splitterMoved(const QList<int> &)),
                    viewWidget, SLOT(updateSizes(const QList<int> &)));
            connect(res->listsWidget(), SIGNAL(splitterMoved(const QList<int> &)),
                    viewWidget->listsWidget(), SLOT(updateSizes(const QList<int> &)));
            connect(res->detailsWidget()->cellmlDetails(), SIGNAL(splitterMoved(const QList<int> &)),
                    viewWidget->detailsWidget()->cellmlDetails(), SLOT(updateSizes(const QList<int> &)));

            // Make sur that the other view widget is aware of any splitter move
            // occuring in our new view widget

            connect(viewWidget, SIGNAL(splitterMoved(const QList<int> &)),
                    res, SLOT(updateSizes(const QList<int> &)));
            connect(viewWidget->listsWidget(), SIGNAL(splitterMoved(const QList<int> &)),
                    res->listsWidget(), SLOT(updateSizes(const QList<int> &)));
            connect(viewWidget->detailsWidget()->cellmlDetails(), SIGNAL(splitterMoved(const QList<int> &)),
                    res->detailsWidget()->cellmlDetails(), SLOT(updateSizes(const QList<int> &)));
        }

        // Keep track of our new view widget

        mViewWidgets.insert(pFileName, res);
    }

    // Return our view widget

    return res;
}

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

bool CellMLAnnotationViewPlugin::hasViewWidget(const QString &pFileName) const
{
    // Return whether a view widget exists or not for the given file name

    return mViewWidgets.value(pFileName);
}

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

void CellMLAnnotationViewPlugin::deleteViewWidget(const QString &pFileName)
{
    // Remove the view widget from our list, should there be one for the given
    // file name

    CellmlAnnotationViewWidget *viewWidget = mViewWidgets.value(pFileName);

    if (viewWidget) {
        // There is a view widget for the given file name, so delete it and
        // remove it from our list

        delete viewWidget;

        mViewWidgets.remove(pFileName);
    }
}

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

QString CellMLAnnotationViewPlugin::viewName()
{
    // Return our CellML annotation view's name

    return tr("CellML Annotation");
}

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

void CellMLAnnotationViewPlugin::retranslateUi()
{
    // Retranslate all of our CellML annotation view widgets

    foreach (CellmlAnnotationViewWidget *viewWidget, mViewWidgets)
        viewWidget->retranslateUi();
}

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

void CellMLAnnotationViewPlugin::splitterMoved(const QList<int> &pSizes)
{
    // The splitter of one of our CellML annotation view widgets has been moved,
    // so update things

    mSizes = pSizes;
}

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

void CellMLAnnotationViewPlugin::listsWidgetSplitterMoved(const QList<int> &pSizes)
{
    // The splitter of one of our CellML annotation view's lists widgets has
    // been moved, so update things

    mListsWidgetSizes = pSizes;
}

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

void CellMLAnnotationViewPlugin::cellmlDetailsWidgetSplitterMoved(const QList<int> &pSizes)
{
    // The splitter of one of our CellML annotation view's CellML details
    // widgets has been moved, so update things

    mCellmlDetailsWidgetSizes = pSizes;
}

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

}   // namespace CellMLAnnotationView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed 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 <atomic>
#include <stdexcept>

#include "gtest/gtest.h"

#include "rclcpp/rclcpp.hpp"

#ifdef RMW_IMPLEMENTATION
# define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX
# define CLASSNAME(NAME, SUFFIX) CLASSNAME_(NAME, SUFFIX)
#else
# define CLASSNAME(NAME, SUFFIX) NAME
#endif

TEST(CLASSNAME(test_executor, RMW_IMPLEMENTATION), recursive_spin_call) {
  rclcpp::executors::SingleThreadedExecutor executor;
  auto node = rclcpp::Node::make_shared("recursive_spin_call");
  auto timer = node->create_wall_timer(0_s, [&executor]() {
    ASSERT_THROW(executor.spin_some(), std::runtime_error);
    ASSERT_THROW(executor.spin_once(), std::runtime_error);
    ASSERT_THROW(executor.spin(), std::runtime_error);
    executor.cancel();
  });
  executor.add_node(node);
  executor.spin();
}

TEST(CLASSNAME(test_executor, RMW_IMPLEMENTATION), multithreaded_spin_call) {
  rclcpp::executors::SingleThreadedExecutor executor;
  auto node = rclcpp::Node::make_shared("multithreaded_spin_call");
  std::mutex m;
  bool ready = false;
  std::condition_variable cv;
  std::thread t([&executor, &m, &cv, &ready]() {
    std::unique_lock<std::mutex> lock(m);
    cv.wait(lock, [&ready] {return ready; });
    ASSERT_THROW(executor.spin_some(), std::runtime_error);
    ASSERT_THROW(executor.spin_once(), std::runtime_error);
    ASSERT_THROW(executor.spin(), std::runtime_error);
    executor.cancel();
  });
  auto timer = node->create_wall_timer(0_s, [&m, &cv, &ready]() {
    if (!ready) {
      {
        std::lock_guard<std::mutex> lock(m);
        ready = true;
      }
      cv.notify_one();
    }
  });
  executor.add_node(node);
  executor.spin();
  t.join();
}

// Try spinning 2 single-threaded executors in two separate threads.
TEST(CLASSNAME(test_executor, RMW_IMPLEMENTATION), multiple_executors) {
  std::atomic_uint counter;
  counter = 0;
  const uint32_t counter_goal = 20;

  // Initialize executor 1.
  rclcpp::executors::SingleThreadedExecutor executor1;
  auto callback1 = [&counter, &counter_goal, &executor1]() {
      if (counter == counter_goal) {
        executor1.cancel();
        return;
      }
      ++counter;
    };
  auto node1 = rclcpp::Node::make_shared("multiple_executors_1");
  auto timer1 = node1->create_wall_timer(1_ms, callback1);
  executor1.add_node(node1);

  // Initialize executor 2.
  rclcpp::executors::SingleThreadedExecutor executor2;

  auto callback2 = [&counter, &counter_goal, &executor2]() {
      if (counter == counter_goal) {
        executor2.cancel();
        return;
      }
      ++counter;
    };
  auto node2 = rclcpp::Node::make_shared("multiple_executors_2");
  auto timer2 = node2->create_wall_timer(1_ms, callback2);
  executor2.add_node(node2);

  auto spin_executor2 = [&executor2]() {
      executor2.spin();
    };

  // Launch both executors
  std::thread execution_thread(spin_executor2);

  executor1.spin();
  execution_thread.join();
  EXPECT_EQ(counter.load(), counter_goal);

  // Try to add node1 to executor2. It should throw, since node1 was already added to executor1.
  ASSERT_THROW(executor2.add_node(node1), std::runtime_error);
}

int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>use separate counter for each thread<commit_after>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed 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 <atomic>
#include <stdexcept>

#include "gtest/gtest.h"

#include "rclcpp/rclcpp.hpp"

#ifdef RMW_IMPLEMENTATION
# define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX
# define CLASSNAME(NAME, SUFFIX) CLASSNAME_(NAME, SUFFIX)
#else
# define CLASSNAME(NAME, SUFFIX) NAME
#endif

TEST(CLASSNAME(test_executor, RMW_IMPLEMENTATION), recursive_spin_call) {
  rclcpp::executors::SingleThreadedExecutor executor;
  auto node = rclcpp::Node::make_shared("recursive_spin_call");
  auto timer = node->create_wall_timer(0_s, [&executor]() {
    ASSERT_THROW(executor.spin_some(), std::runtime_error);
    ASSERT_THROW(executor.spin_once(), std::runtime_error);
    ASSERT_THROW(executor.spin(), std::runtime_error);
    executor.cancel();
  });
  executor.add_node(node);
  executor.spin();
}

TEST(CLASSNAME(test_executor, RMW_IMPLEMENTATION), multithreaded_spin_call) {
  rclcpp::executors::SingleThreadedExecutor executor;
  auto node = rclcpp::Node::make_shared("multithreaded_spin_call");
  std::mutex m;
  bool ready = false;
  std::condition_variable cv;
  std::thread t([&executor, &m, &cv, &ready]() {
    std::unique_lock<std::mutex> lock(m);
    cv.wait(lock, [&ready] {return ready; });
    ASSERT_THROW(executor.spin_some(), std::runtime_error);
    ASSERT_THROW(executor.spin_once(), std::runtime_error);
    ASSERT_THROW(executor.spin(), std::runtime_error);
    executor.cancel();
  });
  auto timer = node->create_wall_timer(0_s, [&m, &cv, &ready]() {
    if (!ready) {
      {
        std::lock_guard<std::mutex> lock(m);
        ready = true;
      }
      cv.notify_one();
    }
  });
  executor.add_node(node);
  executor.spin();
  t.join();
}

// Try spinning 2 single-threaded executors in two separate threads.
TEST(CLASSNAME(test_executor, RMW_IMPLEMENTATION), multiple_executors) {
  std::atomic_uint counter1;
  counter1 = 0;
  std::atomic_uint counter2;
  counter2 = 0;
  const uint32_t counter_goal = 20;

  // Initialize executor 1.
  rclcpp::executors::SingleThreadedExecutor executor1;
  auto callback1 = [&counter1, &counter_goal, &executor1]() {
      if (counter1 == counter_goal) {
        executor1.cancel();
        return;
      }
      ++counter1;
    };
  auto node1 = rclcpp::Node::make_shared("multiple_executors_1");
  auto timer1 = node1->create_wall_timer(1_ms, callback1);
  executor1.add_node(node1);

  // Initialize executor 2.
  rclcpp::executors::SingleThreadedExecutor executor2;

  auto callback2 = [&counter2, &counter_goal, &executor2]() {
      if (counter2 == counter_goal) {
        executor2.cancel();
        return;
      }
      ++counter2;
    };
  auto node2 = rclcpp::Node::make_shared("multiple_executors_2");
  auto timer2 = node2->create_wall_timer(1_ms, callback2);
  executor2.add_node(node2);

  auto spin_executor2 = [&executor2]() {
      executor2.spin();
    };

  // Launch both executors
  std::thread execution_thread(spin_executor2);

  executor1.spin();
  execution_thread.join();
  EXPECT_EQ(counter1.load(), counter_goal);
  EXPECT_EQ(counter2.load(), counter_goal);

  // Try to add node1 to executor2. It should throw, since node1 was already added to executor1.
  ASSERT_THROW(executor2.add_node(node1), std::runtime_error);
}

int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed 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 <gtest/gtest.h>
#include <algorithm>
#include <cstdlib>
#include <string>

#include "ccomptr.h"
#include "custom_binary_reader.h"
#include "dbg_breakpoint.h"
#include "dbg_object.h"
#include "i_cor_debug_mocks.h"
#include "i_dbg_object_factory_mock.h"
#include "i_dbg_stack_frame_mock.h"
#include "i_eval_coordinator_mock.h"
#include "i_portable_pdb_mocks.h"
#include "i_stack_frame_collection_mock.h"

using google::cloud::diagnostics::debug::Breakpoint;
using google_cloud_debugger::CComPtr;
using google_cloud_debugger::DbgBreakpoint;
using google_cloud_debugger_portable_pdb::IDocumentIndex;
using google_cloud_debugger_portable_pdb::MethodInfo;
using google_cloud_debugger_portable_pdb::SequencePoint;
using std::max;
using std::string;
using std::unique_ptr;
using std::vector;
using ::testing::_;
using ::testing::Const;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::SetArgPointee;

namespace google_cloud_debugger_test {

// Test Fixture for DbgBreakpoint
// Sets up a default DbgBreakpoint for the test.
class DbgBreakpointTest : public ::testing::Test {
 protected:
  virtual void SetUpBreakpoint() {
    breakpoint_.Initialize(file_name_, id_, line_, column_, condition_,
                           expressions_);
    // Gives the PDB file the same file name as this breakpoint's file name.
    pdb_file_fixture_.first_doc_.file_name_ = file_name_;
    pdb_file_fixture_.SetUpIPortablePDBFile(&file_mock_);
  }

  // ICorDebugBreakpoint associated with this breakpoint.
  ICorDebugBreakpointMock cordebug_breakpoint_;

  // Breakpoint.
  DbgBreakpoint breakpoint_;

  // File name of the breakpoint.
  string file_name_ = "My file";

  // Lower case of the file name of the breakpoint.
  string lower_case_file_name_ = "my file";

  string condition_;

  std::vector<string> expressions_;

  // Id of the breakpoint.
  string id_ = "My ID";

  // Line number of breakpoint.
  uint32_t line_ = 32;

  // Column of the breakpoint.
  uint32_t column_ = 64;

  // Mock object for Portable PDB file.
  IPortablePdbFileMock file_mock_;

  // Fixture for the PDB File.
  PortablePDBFileFixture pdb_file_fixture_;

  // Mock stackframe, eval coordinator and object factory.
  IDbgStackFrameMock dbg_stack_frame_;
  IEvalCoordinatorMock eval_coordinator_mock_;
  IDbgObjectFactoryMock object_factory_;

  // Mock active debug frame.
  ICorDebugILFrameMock active_frame_mock_;
};

// Tests that the Initialize function sets up the correct fields.
TEST_F(DbgBreakpointTest, Initialize) {
  SetUpBreakpoint();
  // The names stored should be lower case.
  EXPECT_EQ(breakpoint_.GetFileName(), lower_case_file_name_);
  EXPECT_EQ(breakpoint_.GetId(), id_);
  EXPECT_EQ(breakpoint_.GetLine(), line_);
  EXPECT_EQ(breakpoint_.GetColumn(), column_);

  // Now we use the other Initialize function,
  // file name, ID, line and column should be copied over.
  DbgBreakpoint breakpoint2;
  breakpoint2.Initialize(breakpoint_);

  EXPECT_EQ(breakpoint2.GetFileName(), breakpoint_.GetFileName());
  EXPECT_EQ(breakpoint2.GetId(), breakpoint_.GetId());
  EXPECT_EQ(breakpoint2.GetLine(), breakpoint_.GetLine());
  EXPECT_EQ(breakpoint2.GetColumn(), breakpoint_.GetColumn());
}

// Tests that the Set/GetMethodToken function sets up the correct fields.
TEST_F(DbgBreakpointTest, SetGetMethodToken) {
  mdMethodDef method_token = 10;
  SetUpBreakpoint();
  breakpoint_.SetMethodToken(method_token);
  EXPECT_EQ(breakpoint_.GetMethodToken(), method_token);
}

// Tests that Set/GetICorDebugBreakpoint function works.
TEST_F(DbgBreakpointTest, SetGetICorDebugBreakpoint) {
  SetUpBreakpoint();
  breakpoint_.SetCorDebugBreakpoint(&cordebug_breakpoint_);

  CComPtr<ICorDebugBreakpoint> cordebug_breakpoint2;
  HRESULT hr = breakpoint_.GetCorDebugBreakpoint(&cordebug_breakpoint2);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;
}

// Tests the error cases of Set/GetICorDebugBreakpoint function.
TEST_F(DbgBreakpointTest, SetGetICorDebugBreakpointError) {
  SetUpBreakpoint();
  // Null argument.
  EXPECT_EQ(breakpoint_.GetCorDebugBreakpoint(nullptr), E_INVALIDARG);

  // Calls without setting the breakpoint.
  CComPtr<ICorDebugBreakpoint> cordebug_breakpoint2;
  EXPECT_EQ(breakpoint_.GetCorDebugBreakpoint(&cordebug_breakpoint2), E_FAIL);
}

// Returns a method that contains a sequence point
// thats contains breakpoint_line. Also sets the method
// def to method_def and the IL Offset of the matching
// sequence point to il_offset.
MethodInfo MakeMatchingMethod(uint32_t breakpoint_line,
                              uint32_t method_first_line, uint32_t method_def,
                              uint32_t il_offset) {
  assert(method_first_line < breakpoint_line);

  // Minimum amount of lines from breakpoint to last line.
  uint32_t min_line = 10;

  // This method's first line is less than the breakpoint's line
  // and its last line is greater than the breakpoint's line,
  // so the TrySetBreakpoint method should be able to use this method.
  MethodInfo method;
  method.first_line = method_first_line;
  method.last_line = breakpoint_line + max(breakpoint_line, min_line);
  method.method_def = method_def;

  // Puts a sequence point that does not match the line of the breakpoint.
  SequencePoint seq_point;
  seq_point.start_line = method.first_line;
  // End line is between the start line of the method and breakpoint_line.
  seq_point.end_line =
      method.first_line + (rand() % (breakpoint_line - method.first_line));
  seq_point.il_offset = rand() % il_offset;
  method.sequence_points.push_back(seq_point);

  assert(seq_point.end_line < breakpoint_line);

  // Puts in another sequence point that matches the line of the breakpoint.
  SequencePoint seq_point2;
  seq_point2.start_line = breakpoint_line;
  seq_point2.end_line = breakpoint_line + 1;
  seq_point2.il_offset = il_offset;
  method.sequence_points.push_back(seq_point2);

  // Puts a sequence point that does not match the line of the breakpoint.
  SequencePoint seq_point3;
  seq_point3.start_line = seq_point2.end_line + 1;
  // End line is between the start line of the method and breakpoint_line.
  seq_point3.end_line = seq_point3.end_line + 2;
  seq_point3.il_offset = il_offset + 10;
  method.sequence_points.push_back(seq_point3);

  assert(seq_point3.end_line < method.last_line);

  return method;
}

// Test the TrySetBreakpoint function of DbgBreakpoint.
TEST_F(DbgBreakpointTest, TrySetBreakpoint) {
  SetUpBreakpoint();

  // Gets a method that matches the breakpoint.
  uint32_t method_first_line = rand() % line_;
  uint32_t method_def = 100;
  uint32_t il_offset = 99;
  MethodInfo method =
      MakeMatchingMethod(line_, method_first_line, method_def, il_offset);

  // Gets another method that does not match the breakpoint.
  MethodInfo method2 =
      MakeMatchingMethod(line_ * 2, line_ + 1, method_def * 2, il_offset * 2);

  // Push the methods into the method vector that
  // the document index matching this Breakpoint will return.
  pdb_file_fixture_.first_doc_.methods_.push_back(method);
  pdb_file_fixture_.first_doc_.methods_.push_back(method2);

  EXPECT_TRUE(breakpoint_.TrySetBreakpoint(&file_mock_));
  EXPECT_EQ(breakpoint_.GetILOffset(), il_offset);
  EXPECT_EQ(breakpoint_.GetMethodDef(), method_def);
}

// Test the TrySetBreakpoint function of DbgBreakpoint
// when there are multiple methods in the Document Index.
TEST_F(DbgBreakpointTest, TrySetBreakpointWithMultipleMethods) {
  SetUpBreakpoint();

  // Gets a method that matches the breakpoint.
  uint32_t method_first_line = line_ - 10;
  uint32_t method_def = 100;
  uint32_t il_offset = 99;
  MethodInfo method =
      MakeMatchingMethod(line_, method_first_line, method_def, il_offset);

  // Gets another method that does not match the breakpoint.
  uint32_t method2_first_line = line_ + 100;
  uint32_t method2_def = method_def * 2;
  uint32_t il_offset_2 = il_offset * 2;
  MethodInfo method2 = MakeMatchingMethod(line_ + 120, method2_first_line,
                                          method2_def, il_offset_2);

  // Makes another the method that match the breakpoint
  // but has start line greater than the first method (so
  // this method should be selected since it is a better match).
  uint32_t method3_first_line = line_ - 5;
  uint32_t method3_def = method_def * 3;
  uint32_t il_offset_3 = 130;
  MethodInfo method3 =
      MakeMatchingMethod(line_, method3_first_line, method3_def, il_offset_3);

  // Push the methods into the method vector that
  // the document index matching this Breakpoint will return.
  pdb_file_fixture_.first_doc_.methods_.push_back(method);
  pdb_file_fixture_.first_doc_.methods_.push_back(method2);
  pdb_file_fixture_.first_doc_.methods_.push_back(method3);

  EXPECT_TRUE(breakpoint_.TrySetBreakpoint(&file_mock_));
  EXPECT_EQ(breakpoint_.GetILOffset(), il_offset_3);
  EXPECT_EQ(breakpoint_.GetMethodDef(), method3_def);
}

// Tests the case where no matching methods are found.
TEST_F(DbgBreakpointTest, TrySetBreakpointWithNoMatching) {
  SetUpBreakpoint();

  // Gets a method that does not match the breakpoint.
  uint32_t method_first_line = line_ + 5;
  uint32_t method_def = 100;
  uint32_t il_offset = 99;
  MethodInfo method =
      MakeMatchingMethod(line_ + 10, method_first_line, method_def, il_offset);

  // Gets another method that does not match the breakpoint.
  uint32_t method2_first_line = line_ + 100;
  uint32_t method2_def = method_def * 2;
  uint32_t il_offset_2 = il_offset * 2;
  MethodInfo method2 = MakeMatchingMethod(line_ + 120, method2_first_line,
                                          method2_def, il_offset_2);

  // Push the methods into the method vector that
  // the document index matching this Breakpoint will return.
  pdb_file_fixture_.first_doc_.methods_.push_back(method);
  pdb_file_fixture_.first_doc_.methods_.push_back(method2);

  EXPECT_FALSE(breakpoint_.TrySetBreakpoint(&file_mock_));
}

// Tests the PopulateBreakpoint function of DbgBreakpoint.
TEST_F(DbgBreakpointTest, PopulateBreakpoint) {
  SetUpBreakpoint();

  Breakpoint proto_breakpoint;
  IStackFrameCollectionMock stackframe_collection_mock;

  EXPECT_CALL(
      stackframe_collection_mock,
      PopulateStackFrames(&proto_breakpoint, &eval_coordinator_mock_))
      .Times(1)
      .WillRepeatedly(Return(S_OK));

  HRESULT hr = breakpoint_.PopulateBreakpoint(
      &proto_breakpoint, &stackframe_collection_mock, &eval_coordinator_mock_);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;

  // Checks that the proto breakpoint's properties are set.
  EXPECT_EQ(proto_breakpoint.location().line(), line_);
  EXPECT_EQ(proto_breakpoint.location().path(), lower_case_file_name_);
  EXPECT_EQ(proto_breakpoint.id(), id_);
}

// Tests the error cases of PopulateBreakpoint function of DbgBreakpoint.
TEST_F(DbgBreakpointTest, PopulateBreakpointError) {
  SetUpBreakpoint();

  Breakpoint proto_breakpoint;
  IStackFrameCollectionMock stackframe_collection_mock;

  // Checks for null error.
  EXPECT_EQ(breakpoint_.PopulateBreakpoint(nullptr, &stackframe_collection_mock,
                                           &eval_coordinator_mock_),
            E_INVALIDARG);
  EXPECT_EQ(breakpoint_.PopulateBreakpoint(&proto_breakpoint, nullptr,
                                           &eval_coordinator_mock_),
            E_INVALIDARG);
  EXPECT_EQ(breakpoint_.PopulateBreakpoint(
                &proto_breakpoint, &stackframe_collection_mock, nullptr),
            E_INVALIDARG);

  // Makes PopulateStackFrames returns error.
  EXPECT_CALL(
      stackframe_collection_mock,
      PopulateStackFrames(&proto_breakpoint, &eval_coordinator_mock_))
      .Times(1)
      .WillRepeatedly(Return(CORDBG_E_BAD_REFERENCE_VALUE));

  EXPECT_EQ(breakpoint_.PopulateBreakpoint(&proto_breakpoint,
                                           &stackframe_collection_mock,
                                           &eval_coordinator_mock_),
            CORDBG_E_BAD_REFERENCE_VALUE);
}

// Tests the EvaluateExpressions function of DbgBreakpoint.
TEST_F(DbgBreakpointTest, EvaluateExpressions) {
  expressions_ = { "1", "2" };
  SetUpBreakpoint();

  EXPECT_CALL(eval_coordinator_mock_, GetActiveDebugFrame(_))
    .Times(expressions_.size())
    .WillOnce(DoAll(SetArgPointee<0>(&active_frame_mock_), Return(S_OK)));

  HRESULT hr = breakpoint_.EvaluateExpressions(&dbg_stack_frame_, &eval_coordinator_mock_, &object_factory_);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;
}

// Tests that after EvaluateExpressions is called, PopulateBreakpoint
// populates breakpoint proto with expressions.
TEST_F(DbgBreakpointTest, PopulateBreakpointExpression) {
  expressions_ = { "1", "2" };
  SetUpBreakpoint();

  EXPECT_CALL(eval_coordinator_mock_, GetActiveDebugFrame(_))
    .Times(expressions_.size())
    .WillOnce(DoAll(SetArgPointee<0>(&active_frame_mock_), Return(S_OK)));

  HRESULT hr = breakpoint_.EvaluateExpressions(&dbg_stack_frame_, &eval_coordinator_mock_, &object_factory_);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;

  Breakpoint proto_breakpoint;
  IStackFrameCollectionMock stackframe_collection_mock;

  EXPECT_CALL(
      stackframe_collection_mock,
      PopulateStackFrames(&proto_breakpoint, &eval_coordinator_mock_))
      .Times(1)
      .WillRepeatedly(Return(S_OK));

  hr = breakpoint_.PopulateBreakpoint(
      &proto_breakpoint, &stackframe_collection_mock, &eval_coordinator_mock_);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;

  EXPECT_EQ(proto_breakpoint.evaluated_expressions_size(), 2);
  EXPECT_EQ(proto_breakpoint.evaluated_expressions(0).name(), "1");
  EXPECT_EQ(proto_breakpoint.evaluated_expressions(0).value(), "1");
  EXPECT_EQ(proto_breakpoint.evaluated_expressions(1).name(), "2");
  EXPECT_EQ(proto_breakpoint.evaluated_expressions(1).value(), "2");
}

}  // namespace google_cloud_debugger_test
<commit_msg>Fix tests<commit_after>// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed 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 <gtest/gtest.h>
#include <algorithm>
#include <cstdlib>
#include <string>

#include "ccomptr.h"
#include "custom_binary_reader.h"
#include "dbg_breakpoint.h"
#include "dbg_object.h"
#include "i_cor_debug_mocks.h"
#include "i_dbg_object_factory_mock.h"
#include "i_dbg_stack_frame_mock.h"
#include "i_eval_coordinator_mock.h"
#include "i_portable_pdb_mocks.h"
#include "i_stack_frame_collection_mock.h"

using google::cloud::diagnostics::debug::Breakpoint;
using google_cloud_debugger::CComPtr;
using google_cloud_debugger::DbgBreakpoint;
using google_cloud_debugger_portable_pdb::IDocumentIndex;
using google_cloud_debugger_portable_pdb::MethodInfo;
using google_cloud_debugger_portable_pdb::SequencePoint;
using std::max;
using std::string;
using std::unique_ptr;
using std::vector;
using ::testing::_;
using ::testing::Const;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::SetArgPointee;

namespace google_cloud_debugger_test {

// Test Fixture for DbgBreakpoint
// Sets up a default DbgBreakpoint for the test.
class DbgBreakpointTest : public ::testing::Test {
 protected:
  virtual void SetUpBreakpoint() {
    breakpoint_.Initialize(file_name_, id_, line_, column_, condition_,
                           expressions_);
    // Gives the PDB file the same file name as this breakpoint's file name.
    pdb_file_fixture_.first_doc_.file_name_ = file_name_;
    pdb_file_fixture_.SetUpIPortablePDBFile(&file_mock_);
  }

  // ICorDebugBreakpoint associated with this breakpoint.
  ICorDebugBreakpointMock cordebug_breakpoint_;

  // Breakpoint.
  DbgBreakpoint breakpoint_;

  // File name of the breakpoint.
  string file_name_ = "My file";

  // Lower case of the file name of the breakpoint.
  string lower_case_file_name_ = "my file";

  string condition_;

  std::vector<string> expressions_;

  // Id of the breakpoint.
  string id_ = "My ID";

  // Line number of breakpoint.
  uint32_t line_ = 32;

  // Column of the breakpoint.
  uint32_t column_ = 64;

  // Mock object for Portable PDB file.
  IPortablePdbFileMock file_mock_;

  // Fixture for the PDB File.
  PortablePDBFileFixture pdb_file_fixture_;

  // Mock stackframe, eval coordinator and object factory.
  IDbgStackFrameMock dbg_stack_frame_;
  IEvalCoordinatorMock eval_coordinator_mock_;
  IDbgObjectFactoryMock object_factory_;

  // Mock active debug frame.
  ICorDebugILFrameMock active_frame_mock_;
};

// Tests that the Initialize function sets up the correct fields.
TEST_F(DbgBreakpointTest, Initialize) {
  SetUpBreakpoint();
  // The names stored should be lower case.
  EXPECT_EQ(breakpoint_.GetFileName(), lower_case_file_name_);
  EXPECT_EQ(breakpoint_.GetId(), id_);
  EXPECT_EQ(breakpoint_.GetLine(), line_);
  EXPECT_EQ(breakpoint_.GetColumn(), column_);

  // Now we use the other Initialize function,
  // file name, ID, line and column should be copied over.
  DbgBreakpoint breakpoint2;
  breakpoint2.Initialize(breakpoint_);

  EXPECT_EQ(breakpoint2.GetFileName(), breakpoint_.GetFileName());
  EXPECT_EQ(breakpoint2.GetId(), breakpoint_.GetId());
  EXPECT_EQ(breakpoint2.GetLine(), breakpoint_.GetLine());
  EXPECT_EQ(breakpoint2.GetColumn(), breakpoint_.GetColumn());
}

// Tests that the Set/GetMethodToken function sets up the correct fields.
TEST_F(DbgBreakpointTest, SetGetMethodToken) {
  mdMethodDef method_token = 10;
  SetUpBreakpoint();
  breakpoint_.SetMethodToken(method_token);
  EXPECT_EQ(breakpoint_.GetMethodToken(), method_token);
}

// Tests that Set/GetICorDebugBreakpoint function works.
TEST_F(DbgBreakpointTest, SetGetICorDebugBreakpoint) {
  SetUpBreakpoint();
  breakpoint_.SetCorDebugBreakpoint(&cordebug_breakpoint_);

  CComPtr<ICorDebugBreakpoint> cordebug_breakpoint2;
  HRESULT hr = breakpoint_.GetCorDebugBreakpoint(&cordebug_breakpoint2);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;
}

// Tests the error cases of Set/GetICorDebugBreakpoint function.
TEST_F(DbgBreakpointTest, SetGetICorDebugBreakpointError) {
  SetUpBreakpoint();
  // Null argument.
  EXPECT_EQ(breakpoint_.GetCorDebugBreakpoint(nullptr), E_INVALIDARG);

  // Calls without setting the breakpoint.
  CComPtr<ICorDebugBreakpoint> cordebug_breakpoint2;
  EXPECT_EQ(breakpoint_.GetCorDebugBreakpoint(&cordebug_breakpoint2), E_FAIL);
}

// Returns a method that contains a sequence point
// thats contains breakpoint_line. Also sets the method
// def to method_def and the IL Offset of the matching
// sequence point to il_offset.
MethodInfo MakeMatchingMethod(uint32_t breakpoint_line,
                              uint32_t method_first_line, uint32_t method_def,
                              uint32_t il_offset) {
  assert(method_first_line < breakpoint_line);

  // Minimum amount of lines from breakpoint to last line.
  uint32_t min_line = 10;

  // This method's first line is less than the breakpoint's line
  // and its last line is greater than the breakpoint's line,
  // so the TrySetBreakpoint method should be able to use this method.
  MethodInfo method;
  method.first_line = method_first_line;
  method.last_line = breakpoint_line + max(breakpoint_line, min_line);
  method.method_def = method_def;

  // Puts a sequence point that does not match the line of the breakpoint.
  SequencePoint seq_point;
  seq_point.start_line = method.first_line;
  // End line is between the start line of the method and breakpoint_line.
  seq_point.end_line =
      method.first_line + (rand() % (breakpoint_line - method.first_line));
  seq_point.il_offset = rand() % il_offset;
  method.sequence_points.push_back(seq_point);

  assert(seq_point.end_line < breakpoint_line);

  // Puts in another sequence point that matches the line of the breakpoint.
  SequencePoint seq_point2;
  seq_point2.start_line = breakpoint_line;
  seq_point2.end_line = breakpoint_line + 1;
  seq_point2.il_offset = il_offset;
  method.sequence_points.push_back(seq_point2);

  // Puts a sequence point that does not match the line of the breakpoint.
  SequencePoint seq_point3;
  seq_point3.start_line = seq_point2.end_line + 1;
  // End line is between the start line of the method and breakpoint_line.
  seq_point3.end_line = seq_point3.end_line + 2;
  seq_point3.il_offset = il_offset + 10;
  method.sequence_points.push_back(seq_point3);

  assert(seq_point3.end_line < method.last_line);

  return method;
}

// Test the TrySetBreakpoint function of DbgBreakpoint.
TEST_F(DbgBreakpointTest, TrySetBreakpoint) {
  SetUpBreakpoint();

  // Gets a method that matches the breakpoint.
  uint32_t method_first_line = rand() % line_;
  uint32_t method_def = 100;
  uint32_t il_offset = 99;
  MethodInfo method =
      MakeMatchingMethod(line_, method_first_line, method_def, il_offset);

  // Gets another method that does not match the breakpoint.
  MethodInfo method2 =
      MakeMatchingMethod(line_ * 2, line_ + 1, method_def * 2, il_offset * 2);

  // Push the methods into the method vector that
  // the document index matching this Breakpoint will return.
  pdb_file_fixture_.first_doc_.methods_.push_back(method);
  pdb_file_fixture_.first_doc_.methods_.push_back(method2);

  EXPECT_TRUE(breakpoint_.TrySetBreakpoint(&file_mock_));
  EXPECT_EQ(breakpoint_.GetILOffset(), il_offset);
  EXPECT_EQ(breakpoint_.GetMethodDef(), method_def);
}

// Test the TrySetBreakpoint function of DbgBreakpoint
// when there are multiple methods in the Document Index.
TEST_F(DbgBreakpointTest, TrySetBreakpointWithMultipleMethods) {
  SetUpBreakpoint();

  // Gets a method that matches the breakpoint.
  uint32_t method_first_line = line_ - 10;
  uint32_t method_def = 100;
  uint32_t il_offset = 99;
  MethodInfo method =
      MakeMatchingMethod(line_, method_first_line, method_def, il_offset);

  // Gets another method that does not match the breakpoint.
  uint32_t method2_first_line = line_ + 100;
  uint32_t method2_def = method_def * 2;
  uint32_t il_offset_2 = il_offset * 2;
  MethodInfo method2 = MakeMatchingMethod(line_ + 120, method2_first_line,
                                          method2_def, il_offset_2);

  // Makes another the method that match the breakpoint
  // but has start line greater than the first method (so
  // this method should be selected since it is a better match).
  uint32_t method3_first_line = line_ - 5;
  uint32_t method3_def = method_def * 3;
  uint32_t il_offset_3 = 130;
  MethodInfo method3 =
      MakeMatchingMethod(line_, method3_first_line, method3_def, il_offset_3);

  // Push the methods into the method vector that
  // the document index matching this Breakpoint will return.
  pdb_file_fixture_.first_doc_.methods_.push_back(method);
  pdb_file_fixture_.first_doc_.methods_.push_back(method2);
  pdb_file_fixture_.first_doc_.methods_.push_back(method3);

  EXPECT_TRUE(breakpoint_.TrySetBreakpoint(&file_mock_));
  EXPECT_EQ(breakpoint_.GetILOffset(), il_offset_3);
  EXPECT_EQ(breakpoint_.GetMethodDef(), method3_def);
}

// Tests the case where no matching methods are found.
TEST_F(DbgBreakpointTest, TrySetBreakpointWithNoMatching) {
  SetUpBreakpoint();

  // Gets a method that does not match the breakpoint.
  uint32_t method_first_line = line_ + 5;
  uint32_t method_def = 100;
  uint32_t il_offset = 99;
  MethodInfo method =
      MakeMatchingMethod(line_ + 10, method_first_line, method_def, il_offset);

  // Gets another method that does not match the breakpoint.
  uint32_t method2_first_line = line_ + 100;
  uint32_t method2_def = method_def * 2;
  uint32_t il_offset_2 = il_offset * 2;
  MethodInfo method2 = MakeMatchingMethod(line_ + 120, method2_first_line,
                                          method2_def, il_offset_2);

  // Push the methods into the method vector that
  // the document index matching this Breakpoint will return.
  pdb_file_fixture_.first_doc_.methods_.push_back(method);
  pdb_file_fixture_.first_doc_.methods_.push_back(method2);

  EXPECT_FALSE(breakpoint_.TrySetBreakpoint(&file_mock_));
}

// Tests the PopulateBreakpoint function of DbgBreakpoint.
TEST_F(DbgBreakpointTest, PopulateBreakpoint) {
  SetUpBreakpoint();

  Breakpoint proto_breakpoint;
  IStackFrameCollectionMock stackframe_collection_mock;

  EXPECT_CALL(
      stackframe_collection_mock,
      PopulateStackFrames(&proto_breakpoint, &eval_coordinator_mock_))
      .Times(1)
      .WillRepeatedly(Return(S_OK));

  HRESULT hr = breakpoint_.PopulateBreakpoint(
      &proto_breakpoint, &stackframe_collection_mock, &eval_coordinator_mock_);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;

  // Checks that the proto breakpoint's properties are set.
  EXPECT_EQ(proto_breakpoint.location().line(), line_);
  EXPECT_EQ(proto_breakpoint.location().path(), lower_case_file_name_);
  EXPECT_EQ(proto_breakpoint.id(), id_);
}

// Tests the error cases of PopulateBreakpoint function of DbgBreakpoint.
TEST_F(DbgBreakpointTest, PopulateBreakpointError) {
  SetUpBreakpoint();

  Breakpoint proto_breakpoint;
  IStackFrameCollectionMock stackframe_collection_mock;

  // Checks for null error.
  EXPECT_EQ(breakpoint_.PopulateBreakpoint(nullptr, &stackframe_collection_mock,
                                           &eval_coordinator_mock_),
            E_INVALIDARG);
  EXPECT_EQ(breakpoint_.PopulateBreakpoint(&proto_breakpoint, nullptr,
                                           &eval_coordinator_mock_),
            E_INVALIDARG);
  EXPECT_EQ(breakpoint_.PopulateBreakpoint(
                &proto_breakpoint, &stackframe_collection_mock, nullptr),
            E_INVALIDARG);

  // Makes PopulateStackFrames returns error.
  EXPECT_CALL(
      stackframe_collection_mock,
      PopulateStackFrames(&proto_breakpoint, &eval_coordinator_mock_))
      .Times(1)
      .WillRepeatedly(Return(CORDBG_E_BAD_REFERENCE_VALUE));

  EXPECT_EQ(breakpoint_.PopulateBreakpoint(&proto_breakpoint,
                                           &stackframe_collection_mock,
                                           &eval_coordinator_mock_),
            CORDBG_E_BAD_REFERENCE_VALUE);
}

// Tests the EvaluateExpressions function of DbgBreakpoint.
TEST_F(DbgBreakpointTest, EvaluateExpressions) {
  expressions_ = { "1", "2" };
  SetUpBreakpoint();

  EXPECT_CALL(eval_coordinator_mock_, GetActiveDebugFrame(_))
    .Times(expressions_.size())
    .WillOnce(DoAll(SetArgPointee<0>(&active_frame_mock_), Return(S_OK)));

  HRESULT hr = breakpoint_.EvaluateExpressions(&dbg_stack_frame_, &eval_coordinator_mock_, &object_factory_);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;
}

// Tests that after EvaluateExpressions is called, PopulateBreakpoint
// populates breakpoint proto with expressions.
TEST_F(DbgBreakpointTest, PopulateBreakpointExpression) {
  expressions_ = { "1", "2" };
  SetUpBreakpoint();

  EXPECT_CALL(eval_coordinator_mock_, GetActiveDebugFrame(_))
    .Times(expressions_.size())
    .WillRepeatedly(DoAll(SetArgPointee<0>(&active_frame_mock_), Return(S_OK)));

  HRESULT hr = breakpoint_.EvaluateExpressions(&dbg_stack_frame_, &eval_coordinator_mock_, &object_factory_);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;

  Breakpoint proto_breakpoint;
  IStackFrameCollectionMock stackframe_collection_mock;

  EXPECT_CALL(
      stackframe_collection_mock,
      PopulateStackFrames(&proto_breakpoint, &eval_coordinator_mock_))
      .Times(1)
      .WillRepeatedly(Return(S_OK));

  hr = breakpoint_.PopulateBreakpoint(
      &proto_breakpoint, &stackframe_collection_mock, &eval_coordinator_mock_);
  EXPECT_TRUE(SUCCEEDED(hr)) << "Failed with hr: " << hr;

  EXPECT_EQ(proto_breakpoint.evaluated_expressions_size(), 2);
  EXPECT_EQ(proto_breakpoint.evaluated_expressions(0).name(), "1");
  EXPECT_EQ(proto_breakpoint.evaluated_expressions(0).value(), "1");
  EXPECT_EQ(proto_breakpoint.evaluated_expressions(1).name(), "2");
  EXPECT_EQ(proto_breakpoint.evaluated_expressions(1).value(), "2");
}

}  // namespace google_cloud_debugger_test
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sreg.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: ihi $ $Date: 2007-09-13 18:06:40 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_lingucomponent.hxx"

#include <cppuhelper/factory.hxx>   // helper for factories
#ifndef _RTL_STRING_HXX_
#include <rtl/string.hxx>
#endif

#include <com/sun/star/registry/XRegistryKey.hpp>

using namespace rtl;
using namespace com::sun::star::lang;
using namespace com::sun::star::registry;

////////////////////////////////////////
// declaration of external RegEntry-functions defined by the service objects
//

extern sal_Bool SAL_CALL SpellChecker_writeInfo(
    void * /*pServiceManager*/, XRegistryKey * pRegistryKey );

extern void * SAL_CALL SpellChecker_getFactory(
    const sal_Char * pImplName,
    XMultiServiceFactory * pServiceManager,
    void * /*pRegistryKey*/ );
////////////////////////////////////////
// definition of the two functions that are used to provide the services
//

extern "C"
{

sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, XRegistryKey * pRegistryKey )
{
    return SpellChecker_writeInfo( pServiceManager, pRegistryKey );
}

void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    void * pRet = NULL;
    pRet = SpellChecker_getFactory(
        pImplName,
        reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
        pRegistryKey );

    return pRet;
}

}

///////////////////////////////////////////////////////////////////////////

<commit_msg>INTEGRATION: CWS changefileheader (1.7.46); FILE MERGED 2008/04/01 15:21:14 thb 1.7.46.2: #i85898# Stripping all external header guards 2008/03/31 16:25:05 rt 1.7.46.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: sreg.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_lingucomponent.hxx"

#include <cppuhelper/factory.hxx>   // helper for factories
#include <rtl/string.hxx>

#include <com/sun/star/registry/XRegistryKey.hpp>

using namespace rtl;
using namespace com::sun::star::lang;
using namespace com::sun::star::registry;

////////////////////////////////////////
// declaration of external RegEntry-functions defined by the service objects
//

extern sal_Bool SAL_CALL SpellChecker_writeInfo(
    void * /*pServiceManager*/, XRegistryKey * pRegistryKey );

extern void * SAL_CALL SpellChecker_getFactory(
    const sal_Char * pImplName,
    XMultiServiceFactory * pServiceManager,
    void * /*pRegistryKey*/ );
////////////////////////////////////////
// definition of the two functions that are used to provide the services
//

extern "C"
{

sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, XRegistryKey * pRegistryKey )
{
    return SpellChecker_writeInfo( pServiceManager, pRegistryKey );
}

void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    void * pRet = NULL;
    pRet = SpellChecker_getFactory(
        pImplName,
        reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
        pRegistryKey );

    return pRet;
}

}

///////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>/*******************************************************************************
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*
* "@(#) $Id: bdNT32ReceiversTest.cpp,v 1.1 2011/11/30 15:47:32 bjeram Exp $"
*
* who       when      what
* --------  --------  ----------------------------------------------
* bjeram  2011-04-19  created
*/
#include "bulkDataNTReceiverStream.h"
#include "bulkDataNTCallback.h"
#include <iostream>
#include <ace/Get_Opt.h>
#include <ace/Tokenizer_T.h>

using namespace std;

class  TestCB:  public BulkDataNTCallback
{
public:
	int cbStart(unsigned char* userParam_p, unsigned  int size)
	{
		std::cout << "cbStart: got " << size << " :";
		for(unsigned int i=0; i<size; i++)
		{
			std::cout <<  *(char*)(userParam_p+i);
		}
		std::cout << std::endl;
		return 0;
	}

	int cbReceive(unsigned char* data, unsigned  int size)
	{
		// std::cout << "cbReceive: got " << size << " :";
/*		for(unsigned int i=0; i<frame_p->length(); i++)
		{
			std::cout <<  *(char*)(frame_p->base()+i);
		}
	*/
		//std::cout << std::endl;
		return 0;
	}

	int cbStop()
	{
		std::cout << "cbStop" << std::endl;
		return 0;
	}

};

int main(int argc, char *argv[])
{

	char c;
	unsigned int sleepPeriod=0;
	ReceiverFlowConfiguration cfg; //just

	LoggingProxy m_logger(0, 0, 31, 0);
	LoggingProxy::init (&m_logger);
	ACS_CHECK_LOGGER;

	char buf[]="00";
	AcsBulkdata::BulkDataNTReceiverStream<TestCB>* receiverStreams[32];
	for (int i=0; i<32; i++)
	  {
	    sprintf(buf, "%d", i);
	    std::string streamName("Stream");
	    streamName += buf;
	    std::cout << "Going to create stream: " << streamName << std::endl;
	    receiverStreams[i] = new AcsBulkdata::BulkDataNTReceiverStream<TestCB>(streamName.c_str());
	    std::cout << "Stream: " << streamName << " has been created. Going to create a flow inside the stream" << std::endl;
	   receiverStreams[i]->createFlow("00");
	  }

	getchar();

	for (int i=0; i<32; i++)
	  {
	    std::cout << "Going to destroy stream: " << receiverStreams[i]->getName() << std::endl;
	    delete receiverStreams[i];
	  }

}
<commit_msg>removed<commit_after><|endoftext|>