<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2009 Colin Guthrie <cguthrie@mandriva.org>

    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) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), Nokia Corporation
    (or its successors, if any) and the KDE Free Qt Foundation, which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    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, see <http://www.gnu.org/licenses/>.

*/

#include <stdio.h>
#include <glib.h>
#include <QtCore/QtGlobal>
#include <QtCore/QEventLoop>

#ifdef HAVE_PULSEAUDIO
#include <pulse/pulseaudio.h>
#include <pulse/glib-mainloop.h>
#endif // HAVE_PULSEAUDIO

#include "pulsesupport_p.h"

QT_BEGIN_NAMESPACE

namespace Phonon
{

#ifdef HAVE_PULSEAUDIO
class PulseUserData
{
    public:
        inline
        PulseUserData(QEventLoop *eventLoop)
            : m_eventLoop(eventLoop)
        {
            Q_ASSERT(eventLoop);
        }

        inline void initialConnectionLoopExit()
        {
            m_eventLoop->exit(0);
            m_eventLoop = NULL;
        }
    private:
        QEventLoop *m_eventLoop;
};

static PulseSupport* s_instance = NULL;
static bool s_pulseActive = false;

static pa_glib_mainloop *s_mainloop = NULL;
static pa_context *s_context = NULL;

static void pulseContextStateCallback(pa_context *context, void *userdata)
{
    PulseUserData *d = reinterpret_cast<PulseUserData *>(userdata);
    switch (pa_context_get_state(context)) {
        case PA_CONTEXT_READY:
            s_pulseActive = true;
            d->initialConnectionLoopExit();
            break;
        case PA_CONTEXT_FAILED:
            d->initialConnectionLoopExit();
            break;
        default:
            break;
    }
}

#endif // HAVE_PULSEAUDIO

PulseSupport* PulseSupport::getInstance()
{
    if (NULL == s_instance) {
        s_instance = new PulseSupport();
    }
    return s_instance;
}

void PulseSupport::shutdown()
{
    if (NULL != s_instance) {
        delete s_instance;
        s_instance = NULL;
    }
}

PulseSupport::PulseSupport()
{
#ifdef HAVE_PULSEAUDIO
    // To allow for easy debugging, give an easy way to disable this pulseaudio check
    QString pulseenv = qgetenv("PHONON_DISABLE_PULSEAUDIO");
    if (pulseenv.toInt())
        return;

    s_mainloop = pa_glib_mainloop_new(NULL);
    Q_ASSERT(s_mainloop);
    pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop);

    // We create a simple event loop to allow the glib loop
    // to iterate until we've connected or not to the server.
    QEventLoop loop;
    PulseUserData* userData = new PulseUserData(&loop);

    // XXX I don't want to show up in the client list. All I want to know is the list of sources
    // and sinks...
    s_context = pa_context_new(api, "KDE");
    // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required
    if (pa_context_connect(s_context, NULL, static_cast<pa_context_flags_t>(0), 0) >= 0) {
        pa_context_set_state_callback(s_context, &pulseContextStateCallback, userData);
        // Now we block until we connect or otherwise...
        loop.exec();
    }
#endif
}

PulseSupport::~PulseSupport()
{
#ifdef HAVE_PULSEAUDIO
    if (s_context) {
        pa_context_disconnect(s_context);
        s_context = NULL;
    }

    if (s_mainloop) {
        pa_glib_mainloop_free(s_mainloop);
        s_mainloop = NULL;
    }
#endif
}

bool PulseSupport::isActive()
{
#ifdef HAVE_PULSEAUDIO
    return s_pulseActive;
#else
    return false;
#endif
}

} // namespace Phonon

QT_END_NAMESPACE

// vim: sw=4 ts=4
<commit_msg>pulseaudio: Initialise and get information from the module-device-manager.<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2009 Colin Guthrie <cguthrie@mandriva.org>

    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) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), Nokia Corporation
    (or its successors, if any) and the KDE Free Qt Foundation, which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    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, see <http://www.gnu.org/licenses/>.

*/

#include <stdio.h>
#include <glib.h>
#include <QtCore/QtGlobal>
#include <QtCore/QEventLoop>
#include <QtCore/QDebug>

#ifdef HAVE_PULSEAUDIO
#include <pulse/pulseaudio.h>
#include <pulse/glib-mainloop.h>
#include <pulse/ext-device-manager.h>
#endif // HAVE_PULSEAUDIO

#include "pulsesupport_p.h"

QT_BEGIN_NAMESPACE

namespace Phonon
{

#ifdef HAVE_PULSEAUDIO
class PulseUserData
{
    public:
        inline
        PulseUserData(QEventLoop *eventLoop)
            : m_eventLoop(eventLoop)
        {
            Q_ASSERT(eventLoop);
        }

        inline void initialConnectionLoopExit()
        {
            m_eventLoop->exit(0);
            m_eventLoop = NULL;
        }
    private:
        QEventLoop *m_eventLoop;
};

/***
* Prints a conditional debug message based on the current debug level
* If obj is provided, classname and objectname will be printed as well
*
* see debugLevel()
*/

static int debugLevel() {
    return 2;
}

static void logMessage(const QString &message, int priority = 2, QObject *obj=0);
static void logMessage(const QString &message, int priority, QObject *obj)
{
    if (debugLevel() > 0) {
        QString output;
        if (obj) {
            // Strip away namespace from className
            QString className(obj->metaObject()->className());
            int nameLength = className.length() - className.lastIndexOf(':') - 1;
            className = className.right(nameLength);
            output.sprintf("%s %s (%s %p)", message.toLatin1().constData(),
                           obj->objectName().toLatin1().constData(),
                           className.toLatin1().constData(), obj);
        }
        else {
            output = message;
        }
        if (priority <= debugLevel()) {
            qDebug() << QString("PulseSupport(%1): %2").arg(priority).arg(output);
        }
    }
}

static PulseSupport* s_instance = NULL;
static bool s_pulseActive = false;

static pa_glib_mainloop *s_mainloop = NULL;
static pa_context *s_context = NULL;

static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manager_info *info, int eol, void *) {
    if (eol < 0) {
        logMessage(QString("Failed to initialize device manager extension: %1").arg(pa_strerror(pa_context_errno(c))));
        return;
    }

    if (!info)
        return;

    /* Do something with a widget when this part is written */
    logMessage(QString("Found: %1 '%2'").arg(info->name).arg(info->description));
}

static void ext_device_manager_subscribe_cb(pa_context *c, void *userdata) {
    pa_operation *o;

    if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, userdata))) {
        logMessage(QString("pa_ext_device_manager_read() failed"));
        return;
    }

    pa_operation_unref(o);
}

static void context_state_callback(pa_context *c, void *userdata)
{
    PulseUserData *u = reinterpret_cast<PulseUserData *>(userdata);
    switch (pa_context_get_state(c)) {
        case PA_CONTEXT_UNCONNECTED:
        case PA_CONTEXT_CONNECTING:
        case PA_CONTEXT_AUTHORIZING:
        case PA_CONTEXT_SETTING_NAME:
            break;

        case PA_CONTEXT_READY:
            u->initialConnectionLoopExit();

            pa_operation *o;

            /*
            pa_context_set_subscribe_callback(c, subscribe_cb, w);

            if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
                                           (PA_SUBSCRIPTION_MASK_SINK|
                                            PA_SUBSCRIPTION_MASK_SOURCE|
                                            PA_SUBSCRIPTION_MASK_SINK_INPUT|
                                            PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT|
                                            PA_SUBSCRIPTION_MASK_CLIENT|
                                            PA_SUBSCRIPTION_MASK_SERVER|
                                            PA_SUBSCRIPTION_MASK_CARD), NULL, NULL))) {
                show_error(_("pa_context_subscribe() failed"));
                return;
            }
            pa_operation_unref(o);
            */

            if ((o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) {
                pa_operation_unref(o);

                pa_ext_device_manager_set_subscribe_cb(c, ext_device_manager_subscribe_cb, u);

                if ((o = pa_ext_device_manager_subscribe(c, 1, NULL, NULL)))
                    pa_operation_unref(o);

            } else
                logMessage(QString("Failed to initialize stream_restore extension: %1").arg(pa_strerror(pa_context_errno(c))));

            s_pulseActive = true;
            break;

        case PA_CONTEXT_FAILED:
            s_pulseActive = false;
            u->initialConnectionLoopExit();
            break;

        case PA_CONTEXT_TERMINATED:
        default:
            s_pulseActive = false;
            /// @todo Deal with reconnection...
            break;
    }
}

#endif // HAVE_PULSEAUDIO

PulseSupport* PulseSupport::getInstance()
{
    if (NULL == s_instance) {
        s_instance = new PulseSupport();
    }
    return s_instance;
}

void PulseSupport::shutdown()
{
    if (NULL != s_instance) {
        delete s_instance;
        s_instance = NULL;
    }
}

PulseSupport::PulseSupport()
{
#ifdef HAVE_PULSEAUDIO
    // To allow for easy debugging, give an easy way to disable this pulseaudio check
    QString pulseenv = qgetenv("PHONON_DISABLE_PULSEAUDIO");
    if (pulseenv.toInt())
        return;

    s_mainloop = pa_glib_mainloop_new(NULL);
    Q_ASSERT(s_mainloop);
    pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop);

    // We create a simple event loop to allow the glib loop
    // to iterate until we've connected or not to the server.
    QEventLoop loop;
    PulseUserData* userData = new PulseUserData(&loop);

    // XXX I don't want to show up in the client list. All I want to know is the list of sources
    // and sinks...
    s_context = pa_context_new(api, "libphonon");
    // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required
    if (pa_context_connect(s_context, NULL, static_cast<pa_context_flags_t>(0), 0) >= 0) {
        pa_context_set_state_callback(s_context, &context_state_callback, userData);
        // Now we block until we connect or otherwise...
        loop.exec();
    }
#endif
}

PulseSupport::~PulseSupport()
{
#ifdef HAVE_PULSEAUDIO
    if (s_context) {
        pa_context_disconnect(s_context);
        s_context = NULL;
    }

    if (s_mainloop) {
        pa_glib_mainloop_free(s_mainloop);
        s_mainloop = NULL;
    }
#endif
}

bool PulseSupport::isActive()
{
#ifdef HAVE_PULSEAUDIO
    return s_pulseActive;
#else
    return false;
#endif
}

} // namespace Phonon

QT_END_NAMESPACE

// vim: sw=4 ts=4
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: nativenumberwrapper.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 09:45:12 $
 *
 *  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
 *
 ************************************************************************/

#include <unotools/nativenumberwrapper.hxx>

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_
#include <comphelper/componentfactory.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#pragma hdrstop

#define LOCALEDATA_LIBRARYNAME "i18npool"
#define LOCALEDATA_SERVICENAME "com.sun.star.i18n.NativeNumberSupplier"

using namespace ::com::sun::star;

NativeNumberWrapper::NativeNumberWrapper(
            const uno::Reference< lang::XMultiServiceFactory > & xSF
            )
        :
        xSMgr( xSF )
{
    if ( xSMgr.is() )
    {
        try
        {
            xNNS = uno::Reference< i18n::XNativeNumberSupplier > ( xSMgr->createInstance(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) ),
                uno::UNO_QUERY );
        }
        catch ( uno::Exception& e )
        {
            DBG_ERRORFILE( "NativeNumberWrapper ctor: Exception caught!" );
        }
    }
    else
    {   // try to get an instance somehow
        DBG_ERRORFILE( "NativeNumberWrapper: no service manager, trying own" );
        try
        {
            uno::Reference< uno::XInterface > xI = ::comphelper::getComponentInstance(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( LOCALEDATA_LIBRARYNAME ) ) ),
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) );
            if ( xI.is() )
            {
                uno::Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XNativeNumberSupplier >*)0) );
                x >>= xNNS;
            }
        }
        catch ( uno::Exception& e )
        {
            DBG_ERRORFILE( "getComponentInstance: Exception caught!" );
        }
    }
    DBG_ASSERT( xNNS.is(), "NativeNumberWrapper: no NativeNumberSupplier" );
}

NativeNumberWrapper::~NativeNumberWrapper()
{
}

::rtl::OUString
NativeNumberWrapper::getNativeNumberString(
                    const ::rtl::OUString& rNumberString,
                    const ::com::sun::star::lang::Locale& rLocale,
                    sal_Int16 nNativeNumberMode ) const
{
    try
    {
        if ( xNNS.is() )
            return xNNS->getNativeNumberString( rNumberString, rLocale, nNativeNumberMode );
    }
    catch ( uno::Exception& e )
    {
        DBG_ERRORFILE( "getNativeNumberString: Exception caught!" );
    }
    return ::rtl::OUString();
}

sal_Bool
NativeNumberWrapper::isValidNatNum(
                    const ::com::sun::star::lang::Locale& rLocale,
                    sal_Int16 nNativeNumberMode ) const
{
    try
    {
        if ( xNNS.is() )
            return xNNS->isValidNatNum( rLocale, nNativeNumberMode );
    }
    catch ( uno::Exception& e )
    {
        DBG_ERRORFILE( "isValidNatNum: Exception caught!" );
    }
    return sal_False;
}

i18n::NativeNumberXmlAttributes
NativeNumberWrapper::convertToXmlAttributes(
                    const ::com::sun::star::lang::Locale& rLocale,
                    sal_Int16 nNativeNumberMode ) const
{
    try
    {
        if ( xNNS.is() )
            return xNNS->convertToXmlAttributes( rLocale, nNativeNumberMode );
    }
    catch ( uno::Exception& e )
    {
        DBG_ERRORFILE( "convertToXmlAttributes: Exception caught!" );
    }
    return i18n::NativeNumberXmlAttributes();
}

sal_Int16
NativeNumberWrapper::convertFromXmlAttributes(
                    const i18n::NativeNumberXmlAttributes& rAttr ) const
{
    try
    {
        if ( xNNS.is() )
            return xNNS->convertFromXmlAttributes( rAttr );
    }
    catch ( uno::Exception& e )
    {
        DBG_ERRORFILE( "convertFromXmlAttributes: Exception caught!" );
    }
    return 0;
}

<commit_msg>INTEGRATION: CWS warnings01 (1.3.16); FILE MERGED 2005/12/21 11:32:03 fs 1.3.16.2: #i55991# warning-free code 2005/10/21 09:48:57 dbo 1.3.16.1: #i53898# warning free code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: nativenumberwrapper.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 14:06:56 $
 *
 *  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
 *
 ************************************************************************/

#include <unotools/nativenumberwrapper.hxx>

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _COMPHELPER_COMPONENTFACTORY_HXX_
#include <comphelper/componentfactory.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#define LOCALEDATA_LIBRARYNAME "i18npool"
#define LOCALEDATA_SERVICENAME "com.sun.star.i18n.NativeNumberSupplier"

using namespace ::com::sun::star;

NativeNumberWrapper::NativeNumberWrapper(
            const uno::Reference< lang::XMultiServiceFactory > & xSF
            )
        :
        xSMgr( xSF )
{
    if ( xSMgr.is() )
    {
        try
        {
            xNNS = uno::Reference< i18n::XNativeNumberSupplier > ( xSMgr->createInstance(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) ),
                uno::UNO_QUERY );
        }
        catch ( uno::Exception& e )
        {
            (void)e;
            DBG_ERRORFILE( "NativeNumberWrapper ctor: Exception caught!" );
        }
    }
    else
    {   // try to get an instance somehow
        DBG_ERRORFILE( "NativeNumberWrapper: no service manager, trying own" );
        try
        {
            uno::Reference< uno::XInterface > xI = ::comphelper::getComponentInstance(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( LOCALEDATA_LIBRARYNAME ) ) ),
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LOCALEDATA_SERVICENAME ) ) );
            if ( xI.is() )
            {
                uno::Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XNativeNumberSupplier >*)0) );
                x >>= xNNS;
            }
        }
        catch ( uno::Exception& e )
        {
            (void)e;
            DBG_ERRORFILE( "getComponentInstance: Exception caught!" );
        }
    }
    DBG_ASSERT( xNNS.is(), "NativeNumberWrapper: no NativeNumberSupplier" );
}

NativeNumberWrapper::~NativeNumberWrapper()
{
}

::rtl::OUString
NativeNumberWrapper::getNativeNumberString(
                    const ::rtl::OUString& rNumberString,
                    const ::com::sun::star::lang::Locale& rLocale,
                    sal_Int16 nNativeNumberMode ) const
{
    try
    {
        if ( xNNS.is() )
            return xNNS->getNativeNumberString( rNumberString, rLocale, nNativeNumberMode );
    }
    catch ( uno::Exception& e )
    {
        (void)e;
        DBG_ERRORFILE( "getNativeNumberString: Exception caught!" );
    }
    return ::rtl::OUString();
}

sal_Bool
NativeNumberWrapper::isValidNatNum(
                    const ::com::sun::star::lang::Locale& rLocale,
                    sal_Int16 nNativeNumberMode ) const
{
    try
    {
        if ( xNNS.is() )
            return xNNS->isValidNatNum( rLocale, nNativeNumberMode );
    }
    catch ( uno::Exception& e )
    {
        (void)e;
        DBG_ERRORFILE( "isValidNatNum: Exception caught!" );
    }
    return sal_False;
}

i18n::NativeNumberXmlAttributes
NativeNumberWrapper::convertToXmlAttributes(
                    const ::com::sun::star::lang::Locale& rLocale,
                    sal_Int16 nNativeNumberMode ) const
{
    try
    {
        if ( xNNS.is() )
            return xNNS->convertToXmlAttributes( rLocale, nNativeNumberMode );
    }
    catch ( uno::Exception& e )
    {
        (void)e;
        DBG_ERRORFILE( "convertToXmlAttributes: Exception caught!" );
    }
    return i18n::NativeNumberXmlAttributes();
}

sal_Int16
NativeNumberWrapper::convertFromXmlAttributes(
                    const i18n::NativeNumberXmlAttributes& rAttr ) const
{
    try
    {
        if ( xNNS.is() )
            return xNNS->convertFromXmlAttributes( rAttr );
    }
    catch ( uno::Exception& e )
    {
        (void)e;
        DBG_ERRORFILE( "convertFromXmlAttributes: Exception caught!" );
    }
    return 0;
}

<|endoftext|>


<commit_before>// Catch
#include <catch.hpp>

// C++ standard library
#include <stdexcept>
#include <unordered_map>
#include <memory>

// Mantella
#include <mantella>

TEST_CASE("verify") {
  SECTION("Throws std::logic_error if the expression is false.") {
    CHECK_THROWS_AS(mant::verify(false, "Some message ..."), std::logic_error);
  }

  SECTION("Does nothing if the expression is true.") {
    CHECK_NOTHROW(mant::verify(true, "Some message ..."));
  }
}

TEST_CASE("isRotationMatrix") {
  SECTION("Returns true if a rotation matrix is provided.") {
    const arma::uword numberOfDimensions = std::uniform_int_distribution<arma::uword>(2, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfDimensions);

    const arma::Mat<double>& rotationMatrix = mant::getRandomRotationMatrix(numberOfDimensions);
    CAPTURE(rotationMatrix);

    CHECK(mant::isRotationMatrix(rotationMatrix) == true);
  }

  SECTION("Returns false if the provided matrix is not a rotation matrix.") {
    const arma::uword numberOfDimensions = std::uniform_int_distribution<arma::uword>(2, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfDimensions);

    arma::Mat<double> nonRotationMatrix = mant::getRandomRotationMatrix(numberOfDimensions);

    SECTION("Returns false if the provided matrix is not square.") {
      nonRotationMatrix.shed_col(0);
      CAPTURE(nonRotationMatrix);

      CHECK(mant::isRotationMatrix(nonRotationMatrix) == false);
    }

    SECTION("Returns false if the provided matrix has not an determinant of (nearly) -1 or 1.") {
      // Increasing any element should change the determinant significantly
      nonRotationMatrix(0, 0) += 1;
      CAPTURE(nonRotationMatrix);

      CHECK(mant::isRotationMatrix(nonRotationMatrix) == false);
    }

    SECTION("Returns false if its transpose is not (nearly) equal to its inverse.") {
      // Increasing any element should divert its transpose and inverse significantly
      nonRotationMatrix(0, nonRotationMatrix.n_cols - 1) += 1;
      CAPTURE(nonRotationMatrix);

      CHECK(mant::isRotationMatrix(nonRotationMatrix) == false);
    }
  }
}

TEST_CASE("isPermutation") {
  SECTION("Returns true if a permutation is provided.") {
    const arma::uword numberOfPermutations = std::uniform_int_distribution<arma::uword>(1, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfPermutations);

    const arma::uword numberOfElements = numberOfPermutations + std::uniform_int_distribution<arma::uword>(0, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfElements);

    const arma::Col<arma::uword>& permutation = mant::getRandomPermutation(numberOfElements, numberOfPermutations);
    CAPTURE(permutation);

    CHECK(mant::isPermutation(permutation, numberOfPermutations, numberOfElements) == true);
  }

  SECTION("Returns false if the provided vector is not a permutation.") {
    const arma::uword numberOfPermutations = std::uniform_int_distribution<arma::uword>(2, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfPermutations);

    const arma::uword numberOfElements = numberOfPermutations + std::uniform_int_distribution<arma::uword>(0, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfElements);

    arma::Col<arma::uword> nonPermutation = mant::getRandomPermutation(numberOfElements, numberOfPermutations);

    SECTION("Returns false if the number of permutations is larger than the number of elements.") {
      nonPermutation.resize(numberOfElements + 1);
      CAPTURE(nonPermutation);

      CHECK(mant::isPermutation(nonPermutation, numberOfPermutations, numberOfElements) == false);
    }

    SECTION("Returns false if the number of permutations is not equal to the number of elements within the vector.") {
      nonPermutation.resize(numberOfPermutations - 1);
      CAPTURE(nonPermutation);

      CHECK(mant::isPermutation(nonPermutation, numberOfPermutations, numberOfElements) == false);
    }

    SECTION("Returns false if any element of the vector is not within [0, numberOfElements - 1]") {
      nonPermutation(0) = numberOfElements;
      CAPTURE(nonPermutation);

      CHECK(mant::isPermutation(nonPermutation, numberOfPermutations, numberOfElements) == false);
    }

    SECTION("Returns false if the vector is not unique") {
      nonPermutation(0) = nonPermutation(1);
      CAPTURE(nonPermutation);

      CHECK(mant::isPermutation(nonPermutation, numberOfPermutations, numberOfElements) == false);
    }
  }
}

TEST_CASE("isDimensionallyConsistent") {
  SECTION("Returns true if the number of dimensions is consistent over all samples.") {
    const arma::uword numberOfDimensions = std::uniform_int_distribution<arma::uword>(1, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfDimensions);

    std::shared_ptr<mant::OptimisationProblem> optimisationProblem(new mant::bbob::SphereFunction(numberOfDimensions));
    mant::RandomSearch optimisationAlgorithm(optimisationProblem);
    optimisationAlgorithm.optimise();

    const auto& samples = optimisationProblem->getCachedSamples();
    // unordered maps cannot be captured by Catch

    CHECK(mant::isDimensionallyConsistent(samples) == true);
  }

  SECTION("Returns false if the number of dimensions is inconsistent between any two samples.") {
    std::unordered_map<arma::Col<double>, double, mant::Hash, mant::IsEqual> samples;

    const arma::uword firstNumberOfDimensions = std::uniform_int_distribution<arma::uword>(2, 10)(mant::Rng::getGenerator());
    CAPTURE(firstNumberOfDimensions);

    std::shared_ptr<mant::OptimisationProblem> firstOptimisationProblem(new mant::bbob::SphereFunction(firstNumberOfDimensions));
    mant::RandomSearch firstOptimisationAlgorithm(firstOptimisationProblem);
    firstOptimisationAlgorithm.optimise();

    for (const auto& sample : firstOptimisationProblem->getCachedSamples()) {
      samples.insert(sample);
    }

    const arma::uword secondNumberOfDimensions = std::uniform_int_distribution<arma::uword>(1, firstNumberOfDimensions - 1)(mant::Rng::getGenerator());
    CAPTURE(secondNumberOfDimensions);

    std::shared_ptr<mant::OptimisationProblem> secondOptimisationProblem(new mant::bbob::SphereFunction(secondNumberOfDimensions));
    mant::RandomSearch secondOptimisationAlgorithm(secondOptimisationProblem);
    secondOptimisationAlgorithm.optimise();

    // Hopefully, we wont get a hash collision, otherwise mant::IsEqual may throw an exception when comparing vectors with an unequal number of dimensions.
    for (const auto& sample : secondOptimisationProblem->getCachedSamples()) {
      samples.insert(sample);
    }

    // unordered maps cannot be captured by Catch

    CHECK(mant::isDimensionallyConsistent(samples) == true);
  }
}<commit_msg>Added missing includes<commit_after>// Catch
#include <catch.hpp>

// C++ standard library
#include <stdexcept>
#include <unordered_map>
#include <memory>
#include <random>

// Armadillo
#include <armadillo>

// Mantella
#include <mantella>

TEST_CASE("verify") {
  SECTION("Throws std::logic_error if the expression is false.") {
    CHECK_THROWS_AS(mant::verify(false, "Some message ..."), std::logic_error);
  }

  SECTION("Does nothing if the expression is true.") {
    CHECK_NOTHROW(mant::verify(true, "Some message ..."));
  }
}

TEST_CASE("isRotationMatrix") {
  SECTION("Returns true if a rotation matrix is provided.") {
    const arma::uword numberOfDimensions = std::uniform_int_distribution<arma::uword>(2, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfDimensions);

    const arma::Mat<double>& rotationMatrix = mant::getRandomRotationMatrix(numberOfDimensions);
    CAPTURE(rotationMatrix);

    CHECK(mant::isRotationMatrix(rotationMatrix) == true);
  }

  SECTION("Returns false if the provided matrix is not a rotation matrix.") {
    const arma::uword numberOfDimensions = std::uniform_int_distribution<arma::uword>(2, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfDimensions);

    arma::Mat<double> nonRotationMatrix = mant::getRandomRotationMatrix(numberOfDimensions);

    SECTION("Returns false if the provided matrix is not square.") {
      nonRotationMatrix.shed_col(0);
      CAPTURE(nonRotationMatrix);

      CHECK(mant::isRotationMatrix(nonRotationMatrix) == false);
    }

    SECTION("Returns false if the provided matrix has not an determinant of (nearly) -1 or 1.") {
      // Increasing any element should change the determinant significantly
      nonRotationMatrix(0, 0) += 1;
      CAPTURE(nonRotationMatrix);

      CHECK(mant::isRotationMatrix(nonRotationMatrix) == false);
    }

    SECTION("Returns false if its transpose is not (nearly) equal to its inverse.") {
      // Increasing any element should divert its transpose and inverse significantly
      nonRotationMatrix(0, nonRotationMatrix.n_cols - 1) += 1;
      CAPTURE(nonRotationMatrix);

      CHECK(mant::isRotationMatrix(nonRotationMatrix) == false);
    }
  }
}

TEST_CASE("isPermutation") {
  SECTION("Returns true if a permutation is provided.") {
    const arma::uword numberOfPermutations = std::uniform_int_distribution<arma::uword>(1, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfPermutations);

    const arma::uword numberOfElements = numberOfPermutations + std::uniform_int_distribution<arma::uword>(0, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfElements);

    const arma::Col<arma::uword>& permutation = mant::getRandomPermutation(numberOfElements, numberOfPermutations);
    CAPTURE(permutation);

    CHECK(mant::isPermutation(permutation, numberOfPermutations, numberOfElements) == true);
  }

  SECTION("Returns false if the provided vector is not a permutation.") {
    const arma::uword numberOfPermutations = std::uniform_int_distribution<arma::uword>(2, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfPermutations);

    const arma::uword numberOfElements = numberOfPermutations + std::uniform_int_distribution<arma::uword>(0, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfElements);

    arma::Col<arma::uword> nonPermutation = mant::getRandomPermutation(numberOfElements, numberOfPermutations);

    SECTION("Returns false if the number of permutations is larger than the number of elements.") {
      nonPermutation.resize(numberOfElements + 1);
      CAPTURE(nonPermutation);

      CHECK(mant::isPermutation(nonPermutation, numberOfPermutations, numberOfElements) == false);
    }

    SECTION("Returns false if the number of permutations is not equal to the number of elements within the vector.") {
      nonPermutation.resize(numberOfPermutations - 1);
      CAPTURE(nonPermutation);

      CHECK(mant::isPermutation(nonPermutation, numberOfPermutations, numberOfElements) == false);
    }

    SECTION("Returns false if any element of the vector is not within [0, numberOfElements - 1]") {
      nonPermutation(0) = numberOfElements;
      CAPTURE(nonPermutation);

      CHECK(mant::isPermutation(nonPermutation, numberOfPermutations, numberOfElements) == false);
    }

    SECTION("Returns false if the vector is not unique") {
      nonPermutation(0) = nonPermutation(1);
      CAPTURE(nonPermutation);

      CHECK(mant::isPermutation(nonPermutation, numberOfPermutations, numberOfElements) == false);
    }
  }
}

TEST_CASE("isDimensionallyConsistent") {
  SECTION("Returns true if the number of dimensions is consistent over all samples.") {
    const arma::uword numberOfDimensions = std::uniform_int_distribution<arma::uword>(1, 10)(mant::Rng::getGenerator());
    CAPTURE(numberOfDimensions);

    std::shared_ptr<mant::OptimisationProblem> optimisationProblem(new mant::bbob::SphereFunction(numberOfDimensions));
    mant::RandomSearch optimisationAlgorithm(optimisationProblem);
    optimisationAlgorithm.optimise();

    const auto& samples = optimisationProblem->getCachedSamples();
    // unordered maps cannot be captured by Catch

    CHECK(mant::isDimensionallyConsistent(samples) == true);
  }

  SECTION("Returns false if the number of dimensions is inconsistent between any two samples.") {
    std::unordered_map<arma::Col<double>, double, mant::Hash, mant::IsEqual> samples;

    const arma::uword firstNumberOfDimensions = std::uniform_int_distribution<arma::uword>(2, 10)(mant::Rng::getGenerator());
    CAPTURE(firstNumberOfDimensions);

    std::shared_ptr<mant::OptimisationProblem> firstOptimisationProblem(new mant::bbob::SphereFunction(firstNumberOfDimensions));
    mant::RandomSearch firstOptimisationAlgorithm(firstOptimisationProblem);
    firstOptimisationAlgorithm.optimise();

    for (const auto& sample : firstOptimisationProblem->getCachedSamples()) {
      samples.insert(sample);
    }

    const arma::uword secondNumberOfDimensions = std::uniform_int_distribution<arma::uword>(1, firstNumberOfDimensions - 1)(mant::Rng::getGenerator());
    CAPTURE(secondNumberOfDimensions);

    std::shared_ptr<mant::OptimisationProblem> secondOptimisationProblem(new mant::bbob::SphereFunction(secondNumberOfDimensions));
    mant::RandomSearch secondOptimisationAlgorithm(secondOptimisationProblem);
    secondOptimisationAlgorithm.optimise();

    // Hopefully, we wont get a hash collision, otherwise mant::IsEqual may throw an exception when comparing vectors with an unequal number of dimensions.
    for (const auto& sample : secondOptimisationProblem->getCachedSamples()) {
      samples.insert(sample);
    }

    // unordered maps cannot be captured by Catch

    CHECK(mant::isDimensionallyConsistent(samples) == true);
  }
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// configuration.cpp
//
// Identification: benchmark/tpcc/configuration.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <iomanip>
#include <algorithm>

#include "backend/benchmark/tpcc/tpcc_configuration.h"
#include "backend/common/logger.h"

namespace peloton {
namespace benchmark {
namespace tpcc {

void Usage(FILE *out) {
  fprintf(out,
          "Command line options : tpcc <options> \n"
          "   -h --help              :  Print help message \n"
          "   -b --backend_count     :  # of backends \n"
          "   -d --duration          :  execution duration \n"
          "   -k --scale_factor      :  scale factor \n"
  );
}

static struct option opts[] = {
    { "backend_count", optional_argument, NULL, 'b'},
    { "duration", optional_argument, NULL, 'd' },
    { "scale_factor", optional_argument, NULL, 'k' },
    {NULL, 0, NULL, 0}
};

void ValidateScaleFactor(const configuration &state) {
  if (state.scale_factor <= 0) {
    LOG_ERROR("Invalid scale_factor :: %d", state.scale_factor);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %d", "scale_factor", state.scale_factor);
}

void ValidateDuration(const configuration &state) {
  if (state.duration <= 0) {
    LOG_ERROR("Invalid duration :: %d", state.duration);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %d", "duration", state.duration);
}

void ValidateBackendCount(const configuration &state) {
  if (state.backend_count <= 0) {
    LOG_ERROR("Invalid backend_count :: %d", state.backend_count);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %d", "backend_count", state.backend_count);
}

void ParseArguments(int argc, char *argv[], configuration &state) {

  // Default Values
  state.scale_factor = 1;
  state.duration = 1000;
  state.backend_count = 2;

  // Parse args
  while (1) {
    int idx = 0;
    int c = getopt_long(argc, argv, "ah:b:d:k:", opts, &idx);

    if (c == -1) break;

    switch (c) {
      case 'b':
        state.backend_count = atoi(optarg);
        break;
      case 'd':
        state.duration = atoi(optarg);
        break;
      case 'k':
        state.scale_factor = atoi(optarg);
        break;

      case 'h':
        Usage(stderr);
        exit(EXIT_FAILURE);
        break;

      default:
        fprintf(stderr, "\nUnknown option: -%c-\n", c);
        Usage(stderr);
        exit(EXIT_FAILURE);
    }
  }

  // Static TPCC parameters
  state.warehouse_count = 4;                   // 10
  state.item_count = 10000;                    // 100000
  state.districts_per_warehouse = 2;           // 10
  state.customers_per_district = 3000;         // 3000
  state.new_orders_per_district = 900;         // 900

  // Print configuration
  ValidateBackendCount(state);
  ValidateScaleFactor(state);
  ValidateDuration(state);

}

}  // namespace tpcc
}  // namespace benchmark
}  // namespace peloton
<commit_msg>Updated tpcc configuration<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// configuration.cpp
//
// Identification: benchmark/tpcc/configuration.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <iomanip>
#include <algorithm>

#include "backend/benchmark/tpcc/tpcc_configuration.h"
#include "backend/common/logger.h"

namespace peloton {
namespace benchmark {
namespace tpcc {

void Usage(FILE *out) {
  fprintf(out,
          "Command line options : tpcc <options> \n"
          "   -h --help              :  Print help message \n"
          "   -b --backend_count     :  # of backends \n"
          "   -d --duration          :  execution duration \n"
          "   -k --scale_factor      :  scale factor \n"
  );
}

static struct option opts[] = {
    { "backend_count", optional_argument, NULL, 'b'},
    { "duration", optional_argument, NULL, 'd' },
    { "scale_factor", optional_argument, NULL, 'k' },
    {NULL, 0, NULL, 0}
};

void ValidateScaleFactor(const configuration &state) {
  if (state.scale_factor <= 0) {
    LOG_ERROR("Invalid scale_factor :: %d", state.scale_factor);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %d", "scale_factor", state.scale_factor);
}

void ValidateDuration(const configuration &state) {
  if (state.duration <= 0) {
    LOG_ERROR("Invalid duration :: %d", state.duration);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %d", "duration", state.duration);
}

void ValidateBackendCount(const configuration &state) {
  if (state.backend_count <= 0) {
    LOG_ERROR("Invalid backend_count :: %d", state.backend_count);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %d", "backend_count", state.backend_count);
}

void ParseArguments(int argc, char *argv[], configuration &state) {

  // Default Values
  state.scale_factor = 1;
  state.duration = 1000;
  state.backend_count = 2;

  // Parse args
  while (1) {
    int idx = 0;
    int c = getopt_long(argc, argv, "ah:b:d:k:", opts, &idx);

    if (c == -1) break;

    switch (c) {
      case 'b':
        state.backend_count = atoi(optarg);
        break;
      case 'd':
        state.duration = atoi(optarg);
        break;
      case 'k':
        state.scale_factor = atoi(optarg);
        break;

      case 'h':
        Usage(stderr);
        exit(EXIT_FAILURE);
        break;

      default:
        fprintf(stderr, "\nUnknown option: -%c-\n", c);
        Usage(stderr);
        exit(EXIT_FAILURE);
    }
  }

  // Static TPCC parameters
  state.warehouse_count = 10;                  // 10
  state.item_count = 50000;                    // 100000
  state.districts_per_warehouse = 4;           // 10
  state.customers_per_district = 300;          // 3000
  state.new_orders_per_district = 90;          // 900

  // Print configuration
  ValidateBackendCount(state);
  ValidateScaleFactor(state);
  ValidateDuration(state);

}

}  // namespace tpcc
}  // namespace benchmark
}  // namespace peloton
<|endoftext|>


<commit_before>// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <timedata.h>

#include <netaddress.h>
#include <sync.h>
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
#include <warnings.h>

static RecursiveMutex cs_nTimeOffset;
static int64_t nTimeOffset GUARDED_BY(cs_nTimeOffset) = 0;

/**
 * "Never go to sea with two chronometers; take one or three."
 * Our three time sources are:
 *  - System clock
 *  - Median of other nodes clocks
 *  - The user (asking the user to fix the system clock if the first two disagree)
 */
int64_t GetTimeOffset()
{
    LOCK(cs_nTimeOffset);
    return nTimeOffset;
}

int64_t GetAdjustedTime()
{
    return GetTime() + GetTimeOffset();
}

static int64_t abs64(int64_t n)
{
    return (n >= 0 ? n : -n);
}

#define BITCOIN_TIMEDATA_MAX_SAMPLES 200

void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
{
    LOCK(cs_nTimeOffset);
    // Ignore duplicates
    static std::set<CNetAddr> setKnown;
    if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES)
        return;
    if (!setKnown.insert(ip).second)
        return;

    // Add data
    static CMedianFilter<int64_t> vTimeOffsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0);
    vTimeOffsets.input(nOffsetSample);
    LogPrint(BCLog::NET,"added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);

    // There is a known issue here (see issue #4521):
    //
    // - The structure vTimeOffsets contains up to 200 elements, after which
    // any new element added to it will not increase its size, replacing the
    // oldest element.
    //
    // - The condition to update nTimeOffset includes checking whether the
    // number of elements in vTimeOffsets is odd, which will never happen after
    // there are 200 elements.
    //
    // But in this case the 'bug' is protective against some attacks, and may
    // actually explain why we've never seen attacks which manipulate the
    // clock offset.
    //
    // So we should hold off on fixing this and clean it up as part of
    // a timing cleanup that strengthens it in a number of other ways.
    //
    if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
    {
        int64_t nMedian = vTimeOffsets.median();
        std::vector<int64_t> vSorted = vTimeOffsets.sorted();
        // Only let other nodes change our time by so much
        if (abs64(nMedian) <= std::max<int64_t>(0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT)))
        {
            nTimeOffset = nMedian;
        }
        else
        {
            nTimeOffset = 0;

            static bool fDone;
            if (!fDone)
            {
                // If nobody has a time different than ours but within 5 minutes of ours, give a warning
                bool fMatch = false;
                for (const int64_t nOffset : vSorted)
                    if (nOffset != 0 && abs64(nOffset) < 5 * 60)
                        fMatch = true;

                if (!fMatch)
                {
                    fDone = true;
                    bilingual_str strMessage = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly."), PACKAGE_NAME);
                    SetMiscWarning(strMessage.translated);
                    uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
                }
            }
        }

        if (LogAcceptCategory(BCLog::NET)) {
            for (const int64_t n : vSorted) {
                LogPrint(BCLog::NET, "%+d  ", n); /* Continued */
            }
            LogPrint(BCLog::NET, "|  "); /* Continued */

            LogPrint(BCLog::NET, "nTimeOffset = %+d  (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
        }
    }
}
<commit_msg>refactor: Replace RecursiveMutex with Mutex in timedata.cpp<commit_after>// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <timedata.h>

#include <netaddress.h>
#include <sync.h>
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
#include <warnings.h>

static Mutex g_timeoffset_mutex;
static int64_t nTimeOffset GUARDED_BY(g_timeoffset_mutex) = 0;

/**
 * "Never go to sea with two chronometers; take one or three."
 * Our three time sources are:
 *  - System clock
 *  - Median of other nodes clocks
 *  - The user (asking the user to fix the system clock if the first two disagree)
 */
int64_t GetTimeOffset()
{
    LOCK(g_timeoffset_mutex);
    return nTimeOffset;
}

int64_t GetAdjustedTime()
{
    return GetTime() + GetTimeOffset();
}

static int64_t abs64(int64_t n)
{
    return (n >= 0 ? n : -n);
}

#define BITCOIN_TIMEDATA_MAX_SAMPLES 200

void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
{
    LOCK(g_timeoffset_mutex);
    // Ignore duplicates
    static std::set<CNetAddr> setKnown;
    if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES)
        return;
    if (!setKnown.insert(ip).second)
        return;

    // Add data
    static CMedianFilter<int64_t> vTimeOffsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0);
    vTimeOffsets.input(nOffsetSample);
    LogPrint(BCLog::NET,"added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);

    // There is a known issue here (see issue #4521):
    //
    // - The structure vTimeOffsets contains up to 200 elements, after which
    // any new element added to it will not increase its size, replacing the
    // oldest element.
    //
    // - The condition to update nTimeOffset includes checking whether the
    // number of elements in vTimeOffsets is odd, which will never happen after
    // there are 200 elements.
    //
    // But in this case the 'bug' is protective against some attacks, and may
    // actually explain why we've never seen attacks which manipulate the
    // clock offset.
    //
    // So we should hold off on fixing this and clean it up as part of
    // a timing cleanup that strengthens it in a number of other ways.
    //
    if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
    {
        int64_t nMedian = vTimeOffsets.median();
        std::vector<int64_t> vSorted = vTimeOffsets.sorted();
        // Only let other nodes change our time by so much
        if (abs64(nMedian) <= std::max<int64_t>(0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT)))
        {
            nTimeOffset = nMedian;
        }
        else
        {
            nTimeOffset = 0;

            static bool fDone;
            if (!fDone)
            {
                // If nobody has a time different than ours but within 5 minutes of ours, give a warning
                bool fMatch = false;
                for (const int64_t nOffset : vSorted)
                    if (nOffset != 0 && abs64(nOffset) < 5 * 60)
                        fMatch = true;

                if (!fMatch)
                {
                    fDone = true;
                    bilingual_str strMessage = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly."), PACKAGE_NAME);
                    SetMiscWarning(strMessage.translated);
                    uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
                }
            }
        }

        if (LogAcceptCategory(BCLog::NET)) {
            for (const int64_t n : vSorted) {
                LogPrint(BCLog::NET, "%+d  ", n); /* Continued */
            }
            LogPrint(BCLog::NET, "|  "); /* Continued */

            LogPrint(BCLog::NET, "nTimeOffset = %+d  (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
        }
    }
}
<|endoftext|>


<commit_before>//
//
//
#ifndef UNIX_LOG_HPP
#define UNIX_LOG_HPP

#include <functional>

#include "dlog.h"
#include "dpid.h"

#include "log-core.hpp"

extern "C" {
  const char* led_create_pid_file_name (void);
}

const char* led_create_pid_file_name (void)
{
  return "/var/run/led/led-d.pid";
}

using log_t = unix::log::core_t;

namespace log
{

  void init (bool foreground, char *argv0);

  //
  //
  //

  inline void init (bool foreground, char *argv0)
  {
    if (foreground == true)
      return;

    daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0 (argv0);

    daemon_pid_file_proc = led_create_pid_file_name;

    log_t::init (std::bind (&daemon_log, LOG_ERR, std::placeholders::_1),
                 std::bind (&daemon_log, LOG_INFO, std::placeholders::_1));

  }

} // namespace log_t

#endif
<commit_msg>pi: Fix compile error<commit_after>//
//
//
#ifndef UNIX_LOG_HPP
#define UNIX_LOG_HPP

#include <functional>

#include "dlog.h"
#include "dpid.h"

#include "log-core.hpp"

extern "C" {
  const char* led_create_pid_file_name (void);
}

inline const char* led_create_pid_file_name (void)
{
  return "/var/run/led/led-d.pid";
}

using log_t = unix::log::core_t;

namespace log
{

  void init (bool foreground, char *argv0);

  //
  //
  //

  inline void init (bool foreground, char *argv0)
  {
    if (foreground == true)
      return;

    daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0 (argv0);

    daemon_pid_file_proc = led_create_pid_file_name;

    log_t::init (std::bind (&daemon_log, LOG_ERR, std::placeholders::_1),
                 std::bind (&daemon_log, LOG_INFO, std::placeholders::_1));

  }

} // namespace log_t

#endif
<|endoftext|>


<commit_before>#include "acmacs-chart-2/selected-antigens-sera.hh"
#include "acmacs-map-draw/mapi-procrustes.hh"
#include "acmacs-map-draw/draw.hh"
#include "acmacs-map-draw/map-elements-v2.hh"

// ----------------------------------------------------------------------

constexpr const std::string_view sProcrustesArrowElementKeyword{"procrustes-arrow"};

// ----------------------------------------------------------------------

acmacs::mapi::v1::distances_t acmacs::mapi::v1::procrustes_arrows(ChartDraw& chart_draw, const acmacs::chart::Projection& secondary_projection, const acmacs::chart::CommonAntigensSera& common, const acmacs::chart::ProcrustesData& procrustes_data, const ArrowPlotSpec& arrow_plot_spec)
{
    auto secondary_layout = procrustes_data.apply(*secondary_projection.layout());
    auto primary_layout = chart_draw.chart(0).modified_projection().transformed_layout();
    const std::vector<acmacs::chart::CommonAntigensSera::common_t> common_points = common.points(acmacs::chart::CommonAntigensSera::subset::all);
    distances_t distances; // point_no in primary chart and its arrow distance
    for (size_t point_no = 0; point_no < common_points.size(); ++point_no) {
        const auto primary_coords = primary_layout->at(common_points[point_no].primary), secondary_coords = secondary_layout->at(common_points[point_no].secondary);
        const auto distance{acmacs::distance(primary_coords, secondary_coords)};
        distances.emplace_back(common_points[point_no].primary, distance);
        if (distance > arrow_plot_spec.threshold) {
            auto& path = chart_draw.map_elements().add<map_elements::v2::Path>(sProcrustesArrowElementKeyword);
            path.outline(arrow_plot_spec.outline);
            path.outline_width(arrow_plot_spec.line_width);
            path.data().close = false;
            path.data().vertices.emplace_back(map_elements::v2::Coordinates::not_transformed{primary_coords});
            path.data().vertices.emplace_back(map_elements::v2::Coordinates::not_transformed{secondary_coords});
            auto& arrow = path.arrows().emplace_back();
            arrow.at(1);
            arrow.fill(arrow_plot_spec.arrow_fill);
            arrow.outline(arrow_plot_spec.arrow_outline);
            arrow.width(arrow_plot_spec.arrow_width);
            arrow.outline_width(arrow_plot_spec.arrow_outline_width);
        }
    }
    return distances;

} // acmacs::mapi::v1::procrustes_arrows

// ----------------------------------------------------------------------

std::pair<acmacs::mapi::v1::distances_t, acmacs::chart::ProcrustesData> acmacs::mapi::v1::procrustes_arrows(ChartDraw& chart_draw, const acmacs::chart::Projection& secondary_projection, const acmacs::chart::CommonAntigensSera& common, acmacs::chart::procrustes_scaling_t scaling, const ArrowPlotSpec& arrow_plot_spec)
{
    auto procrustes_data = acmacs::chart::procrustes(chart_draw.chart(0).modified_projection(), secondary_projection, common.points(acmacs::chart::CommonAntigensSera::subset::all), scaling);
    return {procrustes_arrows(chart_draw, secondary_projection, common, procrustes_data, arrow_plot_spec), procrustes_data};

} // acmacs::mapi::v1::procrustes_arrows

// ----------------------------------------------------------------------

namespace acmacs::mapi::inline v1
{
    static inline void make_line(map_elements::v2::Path& path, map_elements::v2::Coordinates&& p1, map_elements::v2::Coordinates&& p2, const acmacs::color::Modifier& outline, Pixels outline_width)
    {
        path.data().close = false;
        path.data().vertices.emplace_back(std::move(p1));
        path.data().vertices.emplace_back(std::move(p2));
        path.outline(outline);
        path.outline_width(outline_width);

    } // make_line

} // namespace acmacs::mapi::inline v1

// ----------------------------------------------------------------------

void acmacs::mapi::v1::connection_lines(ChartDraw& chart_draw, const acmacs::chart::SelectedAntigensModify& antigens, const acmacs::chart::SelectedSeraModify& sera, const ConnectionLinePlotSpec& plot_spec, bool report)
{
    const auto number_of_antigens = chart_draw.chart().number_of_antigens();
    auto layout = chart_draw.chart(0).modified_layout();
    std::vector<std::pair<size_t, size_t>> lines_to_draw;
    auto titers = chart_draw.chart().titers();
    for (const auto ag_no : ranges::views::filter(antigens.indexes, [&layout](size_t index) { return layout->point_has_coordinates(index); })) {
        for (const auto sr_no : ranges::views::filter(sera.indexes, [&layout, number_of_antigens](size_t index) { return layout->point_has_coordinates(index + number_of_antigens); })) {
            if (const auto titer = titers->titer(ag_no, sr_no); !titer.is_dont_care()) {
                make_line(chart_draw.map_elements().add<map_elements::v2::Path>(), map_elements::v2::Coordinates::points{ag_no}, map_elements::v2::Coordinates::points{sr_no + number_of_antigens},
                            plot_spec.color, plot_spec.line_width);
                lines_to_draw.emplace_back(ag_no, sr_no);
            }
        }
    }

    if (report)
        AD_INFO("connection lines: ({}) {}", lines_to_draw.size(), lines_to_draw);

} // acmacs::mapi::v1::connection_lines

// ----------------------------------------------------------------------

void acmacs::mapi::v1::error_lines(ChartDraw& chart_draw, const acmacs::chart::SelectedAntigensModify& antigens, const acmacs::chart::SelectedSeraModify& sera, const ErrorLinePlotSpec& plot_spec,
                                   bool report)
{
    const auto number_of_antigens = chart_draw.chart().number_of_antigens();
    auto layout = chart_draw.chart(0).modified_layout();
    const auto error_lines = chart_draw.chart(0).modified_projection().error_lines();
    auto titers = chart_draw.chart().titers();
    std::vector<std::tuple<size_t, size_t, double>> line_data;
    for (const auto ag_no : ranges::views::filter(antigens.indexes, [&layout](size_t index) { return layout->point_has_coordinates(index); })) {
        for (const auto sr_no : ranges::views::filter(sera.indexes, [&layout, number_of_antigens](size_t index) { return layout->point_has_coordinates(index + number_of_antigens); })) {
            const auto p2_no = sr_no + number_of_antigens;
            const auto line_present = [p1_no = ag_no, p2_no](const auto& erl) { return erl.point_1 == p1_no && erl.point_2 == p2_no; };
            if (const auto found = std::find_if(std::begin(error_lines), std::end(error_lines), line_present); found != std::end(error_lines)) {
                line_data.emplace_back(ag_no, sr_no, found->error_line);
                const auto p1 = layout->at(ag_no), p2 = layout->at(p2_no);
                const auto v3 = (p2 - p1) / distance(p1, p2) * (-found->error_line) / 2.0;
                const auto& color = found->error_line > 0 ? plot_spec.more : plot_spec.less;
                make_line(chart_draw.map_elements().add<map_elements::v2::Path>(), map_elements::v2::Coordinates::transformed{p1}, map_elements::v2::Coordinates::transformed{p1 + v3}, color,
                          plot_spec.line_width);
                make_line(chart_draw.map_elements().add<map_elements::v2::Path>(), map_elements::v2::Coordinates::transformed{p2}, map_elements::v2::Coordinates::transformed{p2 - v3}, color,
                          plot_spec.line_width);
            }
        }
    }

    if (report) {
        ranges::sort(line_data, [](const auto& e1, const auto& e2) { return std::abs(std::get<double>(e1)) > std::abs(std::get<double>(e2)); });
        auto c_antigens = chart_draw.chart().antigens();
        auto c_sera = chart_draw.chart().sera();
        AD_INFO("Error lines ({}):", line_data.size());
        for (const auto& [ag_no, sr_no, line] : line_data)
            AD_PRINT("    AG {:3d} {:<40s} -- SR {:2d} {:<40s} : {:7.4f}\n", ag_no, c_antigens->at(ag_no)->name_full(), sr_no, c_sera->at(sr_no)->name_full(), line);
    }

} // acmacs::mapi::v1::error_lines

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>connection/error lines for acmacs_py<commit_after>#include "acmacs-chart-2/selected-antigens-sera.hh"
#include "acmacs-map-draw/mapi-procrustes.hh"
#include "acmacs-map-draw/draw.hh"
#include "acmacs-map-draw/map-elements-v2.hh"

// ----------------------------------------------------------------------

constexpr const std::string_view sProcrustesArrowElementKeyword{"procrustes-arrow"};

// ----------------------------------------------------------------------

acmacs::mapi::v1::distances_t acmacs::mapi::v1::procrustes_arrows(ChartDraw& chart_draw, const acmacs::chart::Projection& secondary_projection, const acmacs::chart::CommonAntigensSera& common, const acmacs::chart::ProcrustesData& procrustes_data, const ArrowPlotSpec& arrow_plot_spec)
{
    auto secondary_layout = procrustes_data.apply(*secondary_projection.layout());
    auto primary_layout = chart_draw.chart(0).modified_projection().transformed_layout();
    const std::vector<acmacs::chart::CommonAntigensSera::common_t> common_points = common.points(acmacs::chart::CommonAntigensSera::subset::all);
    distances_t distances; // point_no in primary chart and its arrow distance
    for (size_t point_no = 0; point_no < common_points.size(); ++point_no) {
        const auto primary_coords = primary_layout->at(common_points[point_no].primary), secondary_coords = secondary_layout->at(common_points[point_no].secondary);
        const auto distance{acmacs::distance(primary_coords, secondary_coords)};
        distances.emplace_back(common_points[point_no].primary, distance);
        if (distance > arrow_plot_spec.threshold) {
            auto& path = chart_draw.map_elements().add<map_elements::v2::Path>(sProcrustesArrowElementKeyword);
            path.outline(arrow_plot_spec.outline);
            path.outline_width(arrow_plot_spec.line_width);
            path.data().close = false;
            path.data().vertices.emplace_back(map_elements::v2::Coordinates::not_transformed{primary_coords});
            path.data().vertices.emplace_back(map_elements::v2::Coordinates::not_transformed{secondary_coords});
            auto& arrow = path.arrows().emplace_back();
            arrow.at(1);
            arrow.fill(arrow_plot_spec.arrow_fill);
            arrow.outline(arrow_plot_spec.arrow_outline);
            arrow.width(arrow_plot_spec.arrow_width);
            arrow.outline_width(arrow_plot_spec.arrow_outline_width);
        }
    }
    return distances;

} // acmacs::mapi::v1::procrustes_arrows

// ----------------------------------------------------------------------

std::pair<acmacs::mapi::v1::distances_t, acmacs::chart::ProcrustesData> acmacs::mapi::v1::procrustes_arrows(ChartDraw& chart_draw, const acmacs::chart::Projection& secondary_projection, const acmacs::chart::CommonAntigensSera& common, acmacs::chart::procrustes_scaling_t scaling, const ArrowPlotSpec& arrow_plot_spec)
{
    auto procrustes_data = acmacs::chart::procrustes(chart_draw.chart(0).modified_projection(), secondary_projection, common.points(acmacs::chart::CommonAntigensSera::subset::all), scaling);
    return {procrustes_arrows(chart_draw, secondary_projection, common, procrustes_data, arrow_plot_spec), procrustes_data};

} // acmacs::mapi::v1::procrustes_arrows

// ----------------------------------------------------------------------

namespace acmacs::mapi::inline v1
{
    static inline void make_line(map_elements::v2::Path& path, map_elements::v2::Coordinates&& p1, map_elements::v2::Coordinates&& p2, const acmacs::color::Modifier& outline, Pixels outline_width)
    {
        path.data().close = false;
        path.data().vertices.emplace_back(std::move(p1));
        path.data().vertices.emplace_back(std::move(p2));
        path.outline(outline);
        path.outline_width(outline_width);

    } // make_line

} // namespace acmacs::mapi::inline v1

// ----------------------------------------------------------------------

void acmacs::mapi::v1::connection_lines(ChartDraw& chart_draw, const acmacs::chart::SelectedAntigensModify& antigens, const acmacs::chart::SelectedSeraModify& sera, const ConnectionLinePlotSpec& plot_spec, bool report)
{
    const auto number_of_antigens = chart_draw.chart().number_of_antigens();
    auto layout = chart_draw.chart(0).modified_layout();
    std::vector<std::pair<size_t, size_t>> lines_to_draw;
    auto titers = chart_draw.chart().titers();
    for (const auto ag_no : ranges::views::filter(antigens.indexes, [&layout](size_t index) { return layout->point_has_coordinates(index); })) {
        for (const auto sr_no : ranges::views::filter(sera.indexes, [&layout, number_of_antigens](size_t index) { return layout->point_has_coordinates(index + number_of_antigens); })) {
            if (const auto titer = titers->titer(ag_no, sr_no); !titer.is_dont_care()) {
                make_line(chart_draw.map_elements().add<map_elements::v2::Path>(), map_elements::v2::Coordinates::points{ag_no}, map_elements::v2::Coordinates::points{sr_no + number_of_antigens},
                            plot_spec.color, plot_spec.line_width);
                lines_to_draw.emplace_back(ag_no, sr_no);
            }
        }
    }

    if (report)
        AD_INFO("connection lines: ({}) {}", lines_to_draw.size(), lines_to_draw);

} // acmacs::mapi::v1::connection_lines

// ----------------------------------------------------------------------

void acmacs::mapi::v1::error_lines(ChartDraw& chart_draw, const acmacs::chart::SelectedAntigensModify& antigens, const acmacs::chart::SelectedSeraModify& sera, const ErrorLinePlotSpec& plot_spec,
                                   bool report)
{
    const auto number_of_antigens = chart_draw.chart().number_of_antigens();
    auto layout = chart_draw.chart(0).modified_layout();
    const auto error_lines = chart_draw.chart(0).modified_projection().error_lines();
    auto titers = chart_draw.chart().titers();
    std::vector<std::tuple<size_t, size_t, double>> line_data;
    for (const auto ag_no : ranges::views::filter(antigens.indexes, [&layout](size_t index) { return layout->point_has_coordinates(index); })) {
        for (const auto sr_no : ranges::views::filter(sera.indexes, [&layout, number_of_antigens](size_t index) { return layout->point_has_coordinates(index + number_of_antigens); })) {
            const auto p2_no = sr_no + number_of_antigens;
            const auto line_present = [p1_no = ag_no, p2_no](const auto& erl) { return erl.point_1 == p1_no && erl.point_2 == p2_no; };
            if (const auto found = std::find_if(std::begin(error_lines), std::end(error_lines), line_present); found != std::end(error_lines)) {
                line_data.emplace_back(ag_no, sr_no, found->error_line);
                const auto p1 = layout->at(ag_no), p2 = layout->at(p2_no);
                const auto v3 = (p2 - p1) / distance(p1, p2) * (-found->error_line) / 2.0;
                const auto& color = found->error_line > 0 ? plot_spec.more : plot_spec.less;
                make_line(chart_draw.map_elements().add<map_elements::v2::Path>(), map_elements::v2::Coordinates::transformed{p1}, map_elements::v2::Coordinates::transformed{p1 + v3}, color,
                          plot_spec.line_width);
                make_line(chart_draw.map_elements().add<map_elements::v2::Path>(), map_elements::v2::Coordinates::transformed{p2}, map_elements::v2::Coordinates::transformed{p2 - v3}, color,
                          plot_spec.line_width);
            }
        }
    }

    if (report) {
        ranges::sort(line_data, [](const auto& e1, const auto& e2) { return std::abs(std::get<double>(e1)) > std::abs(std::get<double>(e2)); });
        auto c_antigens = chart_draw.chart().antigens();
        auto c_sera = chart_draw.chart().sera();
        const auto [max_ag, max_sr] = ranges::accumulate(line_data, std::make_pair(0ul, 0ul), [&c_antigens, &c_sera](const auto& mx, const auto& en) {
            return std::make_pair(std::max(mx.first, c_antigens->at(std::get<0>(en))->name_full().size()), std::max(mx.second, c_sera->at(std::get<1>(en))->name_full().size()));
        });
        AD_INFO("Error lines ({}):", line_data.size());
        for (const auto& [ag_no, sr_no, line] : line_data)
            AD_PRINT("    AG {:3d} {:<{}s} | SR {:2d} {:<{}s} | {:7.4f}\n", ag_no, c_antigens->at(ag_no)->name_full(), max_ag, sr_no, c_sera->at(sr_no)->name_full(), max_sr, line);
    }

} // acmacs::mapi::v1::error_lines

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>/**
Copyright (c) 2015, Ubiquity Robotics
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of ubiquity_motor nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN AiiiiiiiiiiiNY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

#include <ubiquity_motor/motor_message.h>
#include <gtest/gtest.h>

TEST(ubiquity_motor_message, motor_message_commandtype) {
	MotorMessage mc;

	mc.setType(MotorMessage::TYPE_READ);
	ASSERT_EQ(MotorMessage::TYPE_READ, mc.getType());

	mc.setType(MotorMessage::TYPE_WRITE);
	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());

	mc.setType(MotorMessage::TYPE_RESPONSE);
	ASSERT_EQ(MotorMessage::TYPE_RESPONSE, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_commandtype_values) {
	MotorMessage mc;

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xAA));
	ASSERT_EQ(MotorMessage::TYPE_READ, mc.getType());

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xBB));
	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xCC));
	ASSERT_EQ(MotorMessage::TYPE_RESPONSE, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_commandtype_invalid) {
	MotorMessage mc;

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xAB));
	ASSERT_NE(0xAB, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_commandtype_overflow) {
	MotorMessage mc;

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xFFFFFF));
	ASSERT_NE(0xFFFFFF, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_commandtype_neg) {
	MotorMessage mc;

	mc.setType(static_cast<MotorMessage::MessageTypes>(-0xAA));
	ASSERT_NE(-0xAA, mc.getType());
	ASSERT_NE(0xAA, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_register) {
	MotorMessage mc;

	mc.setRegister(MotorMessage::REG_BRAKE_STOP);
	ASSERT_EQ(MotorMessage::REG_BRAKE_STOP, mc.getRegister());
	ASSERT_NE(MotorMessage::REG_STOP_START, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_register_values) {
	MotorMessage mc;

	mc.setRegister(static_cast<MotorMessage::Registers>(0x01));
	ASSERT_EQ(MotorMessage::REG_BRAKE_STOP, mc.getRegister());

	mc.setRegister(static_cast<MotorMessage::Registers>(0x10));
	ASSERT_EQ(MotorMessage::REG_ERROR_COUNT, mc.getRegister());

	mc.setRegister(static_cast<MotorMessage::Registers>(0x0B));
	ASSERT_EQ(MotorMessage::REG_LEFT_ODOM, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_register_invalid) {
	MotorMessage mc;

	mc.setRegister(static_cast<MotorMessage::Registers>(0x05));
	ASSERT_NE(0x05, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_register_overflow) {
	MotorMessage mc;

	mc.setRegister(static_cast<MotorMessage::Registers>(0xFFFFFF));
	ASSERT_NE(0xFFFFFF, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_register_neg) {
	MotorMessage mc;

	mc.setRegister(static_cast<MotorMessage::Registers>(-0x07));
	ASSERT_NE(-0x07, mc.getRegister());
	ASSERT_NE(0x07, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_data_64bit_pos) {
	MotorMessage mc;
	int64_t i = 0xABC;
	mc.setData(i);
	ASSERT_EQ(0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_64bit_zero) {
	MotorMessage mc;
	int64_t i = 0;
	mc.setData(i);
	ASSERT_EQ(0, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_64bit_neg) {
	MotorMessage mc;
	int64_t i = -0xABC;
	mc.setData(i);
	ASSERT_EQ(-0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_32bit_pos) {
	MotorMessage mc;
	int32_t i = 0xABC;
	mc.setData(i);
	ASSERT_EQ(0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_32bit_zero) {
	MotorMessage mc;
	int32_t i = 0;
	mc.setData(i);
	ASSERT_EQ(0, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_32bit_neg) {
	MotorMessage mc;
	int32_t i = -0xABC;
	mc.setData(i);
	ASSERT_EQ(-0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_16bit_pos) {
	MotorMessage mc;
	int16_t i = 0xABC;
	mc.setData(i);
	ASSERT_EQ(0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_16bit_zero) {
	MotorMessage mc;
	int16_t i = 0;
	mc.setData(i);
	ASSERT_EQ(0, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_16bit_neg) {
	MotorMessage mc;
	int16_t i = -0xABC;
	mc.setData(i);
	ASSERT_EQ(-0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_8bit_pos) {
	MotorMessage mc;
	int8_t i = 0x50;
	mc.setData(i);
	ASSERT_EQ(0x50, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_8bit_zero) {
	MotorMessage mc;
	int8_t i = 0;
	mc.setData(i);
	ASSERT_EQ(0, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_8bit_neg) {
	MotorMessage mc;
	int8_t i = -0x50;
	mc.setData(i);
	ASSERT_EQ(-0x50, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_serialize) {
	MotorMessage mc;
	mc.setData(300);
	mc.setType(MotorMessage::TYPE_WRITE);
	mc.setRegister(MotorMessage::REG_LEFT_SPEED_SET);

	uint8_t arr[] = {0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0E};

	std::vector<uint8_t> expect(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(expect, mc.serialize());
}

TEST(ubiquity_motor_message, motor_message_deserialize_good) {
	MotorMessage mc;

	//Test good message
	uint8_t arr[] = {0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0E};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(0, mc.deserialize(input));
	ASSERT_EQ(300, mc.getData());
	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());
	ASSERT_EQ(MotorMessage::REG_LEFT_SPEED_SET, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_deserialize_delimeter_in_data) {
	MotorMessage mc;

	//Test good message
	uint8_t arr[] = {0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x7E, 0xBC};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(0, mc.deserialize(input));
	ASSERT_EQ(382, mc.getData());
	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());
	ASSERT_EQ(MotorMessage::REG_LEFT_SPEED_SET, mc.getRegister());
}

// TEST(ubiquity_motor_message, motor_message_deserialize_double_delimeter) {
// 	MotorMessage mc;

// 	//Test bad delimeter with good checksum
// 	uint8_t arr[] = {0x7E, 0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0E};

// 	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

// 	ASSERT_EQ(0, mc.deserialize(input));
// 	ASSERT_EQ(300, mc.getData());
// 	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());
// 	ASSERT_EQ(MotorMessage::REG_LEFT_SPEED_SET, mc.getRegister());
// }

TEST(ubiquity_motor_message, motor_message_deserialize_bad_delimeter) {
	MotorMessage mc;

	//Test bad delimeter with good checksum
	uint8_t arr[] = {0x67, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x3B};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(1, mc.deserialize(input));
}

TEST(ubiquity_motor_message, motor_message_deserialize_bad_protocol) {
	MotorMessage mc;

	//Test bad protocol_verstion with good checksum
	uint8_t arr[] = {0x7E, 0x01, 0xBB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x3C};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(2, mc.deserialize(input));
}

TEST(ubiquity_motor_message, motor_message_deserialize_bad_checksum) {
	MotorMessage mc;

	//Test bad checksum
	uint8_t arr1[] = {0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0F};

	std::vector<uint8_t> input1(arr1, arr1 + sizeof(arr1)/ sizeof(uint8_t));

	ASSERT_EQ(3, mc.deserialize(input1));
}

TEST(ubiquity_motor_message, motor_message_deserialize_bad_type) {
	MotorMessage mc;

	//Test type with good checksum
	uint8_t arr1[] = {0x7E, 0x02, 0xBA, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0F};

	std::vector<uint8_t> input1(arr1, arr1 + sizeof(arr1)/ sizeof(uint8_t));

	ASSERT_EQ(4, mc.deserialize(input1));
}

TEST(ubiquity_motor_message, motor_message_deserialize_bad_register) {
	MotorMessage mc;

	//Test bad register with good checksum
	uint8_t arr[] = {0x7E, 0x02, 0xBB, 0x30, 0x00, 0x00, 0x01, 0x2C, 0xE5};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(5, mc.deserialize(input));
}

int main(int argc, char **argv){
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}<commit_msg>add basic tests for ERROR_TYPE<commit_after>/**
Copyright (c) 2015, Ubiquity Robotics
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of ubiquity_motor nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN AiiiiiiiiiiiNY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

#include <ubiquity_motor/motor_message.h>
#include <gtest/gtest.h>

TEST(ubiquity_motor_message, motor_message_commandtype) {
	MotorMessage mc;

	mc.setType(MotorMessage::TYPE_READ);
	ASSERT_EQ(MotorMessage::TYPE_READ, mc.getType());

	mc.setType(MotorMessage::TYPE_WRITE);
	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());

	mc.setType(MotorMessage::TYPE_RESPONSE);
	ASSERT_EQ(MotorMessage::TYPE_RESPONSE, mc.getType());

	mc.setType(MotorMessage::TYPE_ERROR);
	ASSERT_EQ(MotorMessage::TYPE_ERROR, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_commandtype_values) {
	MotorMessage mc;

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xAA));
	ASSERT_EQ(MotorMessage::TYPE_READ, mc.getType());

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xBB));
	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xCC));
	ASSERT_EQ(MotorMessage::TYPE_RESPONSE, mc.getType());

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xDD));
	ASSERT_EQ(MotorMessage::TYPE_ERROR, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_commandtype_invalid) {
	MotorMessage mc;

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xAB));
	ASSERT_NE(0xAB, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_commandtype_overflow) {
	MotorMessage mc;

	mc.setType(static_cast<MotorMessage::MessageTypes>(0xFFFFFF));
	ASSERT_NE(0xFFFFFF, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_commandtype_neg) {
	MotorMessage mc;

	mc.setType(static_cast<MotorMessage::MessageTypes>(-0xAA));
	ASSERT_NE(-0xAA, mc.getType());
	ASSERT_NE(0xAA, mc.getType());
}

TEST(ubiquity_motor_message, motor_message_register) {
	MotorMessage mc;

	mc.setRegister(MotorMessage::REG_BRAKE_STOP);
	ASSERT_EQ(MotorMessage::REG_BRAKE_STOP, mc.getRegister());
	ASSERT_NE(MotorMessage::REG_STOP_START, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_register_values) {
	MotorMessage mc;

	mc.setRegister(static_cast<MotorMessage::Registers>(0x01));
	ASSERT_EQ(MotorMessage::REG_BRAKE_STOP, mc.getRegister());

	mc.setRegister(static_cast<MotorMessage::Registers>(0x10));
	ASSERT_EQ(MotorMessage::REG_ERROR_COUNT, mc.getRegister());

	mc.setRegister(static_cast<MotorMessage::Registers>(0x0B));
	ASSERT_EQ(MotorMessage::REG_LEFT_ODOM, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_register_invalid) {
	MotorMessage mc;

	mc.setRegister(static_cast<MotorMessage::Registers>(0x05));
	ASSERT_NE(0x05, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_register_overflow) {
	MotorMessage mc;

	mc.setRegister(static_cast<MotorMessage::Registers>(0xFFFFFF));
	ASSERT_NE(0xFFFFFF, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_register_neg) {
	MotorMessage mc;

	mc.setRegister(static_cast<MotorMessage::Registers>(-0x07));
	ASSERT_NE(-0x07, mc.getRegister());
	ASSERT_NE(0x07, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_data_64bit_pos) {
	MotorMessage mc;
	int64_t i = 0xABC;
	mc.setData(i);
	ASSERT_EQ(0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_64bit_zero) {
	MotorMessage mc;
	int64_t i = 0;
	mc.setData(i);
	ASSERT_EQ(0, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_64bit_neg) {
	MotorMessage mc;
	int64_t i = -0xABC;
	mc.setData(i);
	ASSERT_EQ(-0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_32bit_pos) {
	MotorMessage mc;
	int32_t i = 0xABC;
	mc.setData(i);
	ASSERT_EQ(0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_32bit_zero) {
	MotorMessage mc;
	int32_t i = 0;
	mc.setData(i);
	ASSERT_EQ(0, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_32bit_neg) {
	MotorMessage mc;
	int32_t i = -0xABC;
	mc.setData(i);
	ASSERT_EQ(-0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_16bit_pos) {
	MotorMessage mc;
	int16_t i = 0xABC;
	mc.setData(i);
	ASSERT_EQ(0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_16bit_zero) {
	MotorMessage mc;
	int16_t i = 0;
	mc.setData(i);
	ASSERT_EQ(0, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_16bit_neg) {
	MotorMessage mc;
	int16_t i = -0xABC;
	mc.setData(i);
	ASSERT_EQ(-0xABC, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_8bit_pos) {
	MotorMessage mc;
	int8_t i = 0x50;
	mc.setData(i);
	ASSERT_EQ(0x50, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_8bit_zero) {
	MotorMessage mc;
	int8_t i = 0;
	mc.setData(i);
	ASSERT_EQ(0, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_data_8bit_neg) {
	MotorMessage mc;
	int8_t i = -0x50;
	mc.setData(i);
	ASSERT_EQ(-0x50, mc.getData());
}

TEST(ubiquity_motor_message, motor_message_serialize) {
	MotorMessage mc;
	mc.setData(300);
	mc.setType(MotorMessage::TYPE_WRITE);
	mc.setRegister(MotorMessage::REG_LEFT_SPEED_SET);

	uint8_t arr[] = {0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0E};

	std::vector<uint8_t> expect(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(expect, mc.serialize());
}

TEST(ubiquity_motor_message, motor_message_deserialize_good) {
	MotorMessage mc;

	//Test good message
	uint8_t arr[] = {0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0E};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(0, mc.deserialize(input));
	ASSERT_EQ(300, mc.getData());
	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());
	ASSERT_EQ(MotorMessage::REG_LEFT_SPEED_SET, mc.getRegister());
}

TEST(ubiquity_motor_message, motor_message_deserialize_delimeter_in_data) {
	MotorMessage mc;

	//Test good message
	uint8_t arr[] = {0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x7E, 0xBC};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(0, mc.deserialize(input));
	ASSERT_EQ(382, mc.getData());
	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());
	ASSERT_EQ(MotorMessage::REG_LEFT_SPEED_SET, mc.getRegister());
}

// TEST(ubiquity_motor_message, motor_message_deserialize_double_delimeter) {
// 	MotorMessage mc;

// 	//Test bad delimeter with good checksum
// 	uint8_t arr[] = {0x7E, 0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0E};

// 	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

// 	ASSERT_EQ(0, mc.deserialize(input));
// 	ASSERT_EQ(300, mc.getData());
// 	ASSERT_EQ(MotorMessage::TYPE_WRITE, mc.getType());
// 	ASSERT_EQ(MotorMessage::REG_LEFT_SPEED_SET, mc.getRegister());
// }

TEST(ubiquity_motor_message, motor_message_deserialize_bad_delimeter) {
	MotorMessage mc;

	//Test bad delimeter with good checksum
	uint8_t arr[] = {0x67, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x3B};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(1, mc.deserialize(input));
}

TEST(ubiquity_motor_message, motor_message_deserialize_bad_protocol) {
	MotorMessage mc;

	//Test bad protocol_verstion with good checksum
	uint8_t arr[] = {0x7E, 0x01, 0xBB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x3C};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(2, mc.deserialize(input));
}

TEST(ubiquity_motor_message, motor_message_deserialize_bad_checksum) {
	MotorMessage mc;

	//Test bad checksum
	uint8_t arr1[] = {0x7E, 0x02, 0xBB, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0F};

	std::vector<uint8_t> input1(arr1, arr1 + sizeof(arr1)/ sizeof(uint8_t));

	ASSERT_EQ(3, mc.deserialize(input1));
}

TEST(ubiquity_motor_message, motor_message_deserialize_bad_type) {
	MotorMessage mc;

	//Test type with good checksum
	uint8_t arr1[] = {0x7E, 0x02, 0xBA, 0x07, 0x00, 0x00, 0x01, 0x2C, 0x0F};

	std::vector<uint8_t> input1(arr1, arr1 + sizeof(arr1)/ sizeof(uint8_t));

	ASSERT_EQ(4, mc.deserialize(input1));
}

TEST(ubiquity_motor_message, motor_message_deserialize_bad_register) {
	MotorMessage mc;

	//Test bad register with good checksum
	uint8_t arr[] = {0x7E, 0x02, 0xBB, 0x30, 0x00, 0x00, 0x01, 0x2C, 0xE5};

	std::vector<uint8_t> input(arr, arr + sizeof(arr)/ sizeof(uint8_t));

	ASSERT_EQ(5, mc.deserialize(input));
}

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


<commit_before>/**
 * \file
 * <!--
 * Copyright 2015 Develer S.r.l. (http://www.develer.com/)
 * -->
 *
 * \brief History class implementation
 *
 * \author Aurelien Rainone <aurelien@develer.org>
 */

#include "history.h"

History::History(QObject *parent)
    : QObject(parent),
      max_entries(5)
{
    _current = -1;
}

void History::add(const QString &entry)
{
    // remove eventual duplicate of new entry
    int dup = history.indexOf(entry);
    if (dup >= 0)
        history.removeAt(dup);

    history.prepend(entry);

    // remove extra elements
    if (history.size() > max_entries)
        history.pop_back();

    _current = -1;
}

const QString History::previous()
{
    QString prev("");
    if (history.size() > 0)
    {
        if (_current == -1)
            _current = history.size() - 1;
        else if (_current > 0)
            --_current;
        prev = history[_current];
    }
   return prev;
}

const QString History::next()
{
    QString nex("");
    if (history.size() > 0)
    {
        if (_current == -1)
            _current = 0;
        else if (_current < history.size() - 1)
            ++_current;
        nex = history[_current];
    }
    return nex;
}

const QStringList& History::getHistory() const
{
    return history;
}

void History::setCurrent(int current_index)
{
    _current = current_index;
}

int History::current() const
{
    return _current;
}
<commit_msg>set max history entries to 10<commit_after>/**
 * \file
 * <!--
 * Copyright 2015 Develer S.r.l. (http://www.develer.com/)
 * -->
 *
 * \brief History class implementation
 *
 * \author Aurelien Rainone <aurelien@develer.org>
 */

#include "history.h"

History::History(QObject *parent)
    : QObject(parent),
      max_entries(10)
{
    _current = -1;
}

void History::add(const QString &entry)
{
    // remove eventual duplicate of new entry
    int dup = history.indexOf(entry);
    if (dup >= 0)
        history.removeAt(dup);

    history.prepend(entry);

    // remove extra elements
    if (history.size() > max_entries)
        history.pop_back();

    _current = -1;
}

const QString History::previous()
{
    QString prev("");
    if (history.size() > 0)
    {
        if (_current == -1)
            _current = history.size() - 1;
        else if (_current > 0)
            --_current;
        prev = history[_current];
    }
   return prev;
}

const QString History::next()
{
    QString nex("");
    if (history.size() > 0)
    {
        if (_current == -1)
            _current = 0;
        else if (_current < history.size() - 1)
            ++_current;
        nex = history[_current];
    }
    return nex;
}

const QStringList& History::getHistory() const
{
    return history;
}

void History::setCurrent(int current_index)
{
    _current = current_index;
}

int History::current() const
{
    return _current;
}
<|endoftext|>