<commit_before>/*************************************************************************
 *
 *  $RCSfile: xlocx.hxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: kz $ $Date: 2004-10-04 20:10:24 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_XLOCX_HXX
#define SC_XLOCX_HXX

#ifndef _MSOCXIMEX_HXX
#include <svx/msocximex.hxx>
#endif

#ifndef SC_XIROOT_HXX
#include "xiroot.hxx"
#endif
#ifndef SC_XEROOT_HXX
#include "xeroot.hxx"
#endif

// 0 = Export TBX form controls, 1 = Export OCX form controls.
#define EXC_EXP_OCX_CTRL 0

// OCX controls ===============================================================

/** Converter base class for import and export of OXC controls.
    @descr  The purpose of this class is to manage all the draw pages occuring in a
    spreadsheet document. Derived classes implement import or export of the controls. */
class XclOcxConverter : protected SvxMSConvertOCXControls
{
protected:
    typedef ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >    XDrawPageRef;
    typedef ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >       XShapeRef;
    typedef ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent >  XFormComponentRef;
    typedef ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >    XControlModelRef;

protected:
    explicit            XclOcxConverter( const XclRoot& rRoot );
    virtual             ~XclOcxConverter();

    /** Sets the sheet index of the currently processed object. GetDrawPage() needs this. */
    void                SetScTab( SCTAB nScTab );

private:
    /** Returns the current draw page. */
    virtual const XDrawPageRef& GetDrawPage();

private:
    const XclRoot&      mrRoot;         /// Root data.
    SCTAB               mnCurrScTab;    /// Stores sheet index of an object for GetDrawPage().
    SCTAB               mnCachedScTab;  /// Sheet index of cached draw page.
};

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

class XclImpEscherOle;
class XclImpEscherTbxCtrl;
class XclImpCtrlLinkHelper;

/** Converter for import of OXC controls. */
class XclImpOcxConverter : public XclOcxConverter, protected XclImpRoot
{
public:
    explicit            XclImpOcxConverter( const XclImpRoot& rRoot );

    /** Reads the control formatting data for the passed object and creates the SdrUnoObj.
        @return  true = SdrUnoObj successfully created. */
    bool                CreateSdrUnoObj( XclImpEscherOle& rOleObj );

    /** Creates the SdrUnoObj for the passed TBX form control object.
        @return  true = SdrUnoObj successfully created. */
    bool                CreateSdrUnoObj( XclImpEscherTbxCtrl& rTbxCtrl );

private:
    /** Inserts the passed control rxFComp into the document. */
    virtual sal_Bool    InsertControl(
                            const XFormComponentRef& rxFComp,
                            const ::com::sun::star::awt::Size& rSize,
                            XShapeRef* pxShape,
                            BOOL bFloatingCtrl );

    /** Tries to set a spreadsheet cell link and source range link at the passed form control. */
    void                ConvertSheetLinks(
                            XControlModelRef rxModel,
                            const XclImpCtrlLinkHelper& rControl ) const;

private:
    SotStorageStreamRef  mxStrm;         /// The 'Ctls' strem.
};

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

class SdrObject;
#if EXC_EXP_OCX_CTRL
class XclExpObjOcxCtrl;
#else
class XclExpObjTbxCtrl;
#endif
class XclExpCtrlLinkHelper;

/** Converter for export of OXC controls. */
class XclExpOcxConverter : public XclOcxConverter, protected XclExpRoot
{
public:
    explicit            XclExpOcxConverter( const XclExpRoot& rRoot );

#if EXC_EXP_OCX_CTRL
    /** Creates an OCX form control OBJ record from the passed form control.
        @descr  Writes the form control data to the 'Ctls' stream. */
    XclExpObjOcxCtrl*   CreateCtrlObj( const XShapeRef& rxShape );
#else
    /** Creates a TBX form control OBJ record from the passed form control. */
    XclExpObjTbxCtrl*   CreateCtrlObj( const XShapeRef& rxShape );
#endif

private:
    /** Tries to get spreadsheet cell link and source range link from the passed model.
        @param rControl  The Excel form control that stores and exports the links. */
    void                ConvertSheetLinks(
                            XclExpCtrlLinkHelper& rControl,
                            const XControlModelRef& rxModel ) const;

private:
#if EXC_EXP_OCX_CTRL
    SotStorageStreamRef  mxStrm;         /// The 'Ctls' stream.
#endif
};

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

#endif

<commit_msg>INTEGRATION: CWS dr31 (1.10.116); FILE MERGED 2004/12/09 09:04:41 dr 1.10.116.1: #i37965# import/export of control<->macro links, code cleanup<commit_after>/*************************************************************************
 *
 *  $RCSfile: xlocx.hxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-14 12:13:23 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_XLOCX_HXX
#define SC_XLOCX_HXX

#ifndef _MSOCXIMEX_HXX
#include <svx/msocximex.hxx>
#endif

#ifndef SC_XIROOT_HXX
#include "xiroot.hxx"
#endif
#ifndef SC_XEROOT_HXX
#include "xeroot.hxx"
#endif

// 0 = Export TBX form controls, 1 = Export OCX form controls.
#define EXC_EXP_OCX_CTRL 0

// OCX controls ===============================================================

/** Converter base class for import and export of OXC controls.
    @descr  The purpose of this class is to manage all the draw pages occuring in a
    spreadsheet document. Derived classes implement import or export of the controls. */
class XclOcxConverter : protected SvxMSConvertOCXControls
{
protected:
    explicit            XclOcxConverter( const XclRoot& rRoot );
    virtual             ~XclOcxConverter();

    /** Sets the sheet index of the currently processed object. GetDrawPage() needs this. */
    void                SetScTab( SCTAB nScTab );
    /** Calls SetScTab() with the passed sheet index and updates the xDrawPage base class member. */
    void                SetDrawPage( SCTAB nScTab );

private:
    /** Returns the current draw page. */
    virtual const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >&
                            GetDrawPage();

private:
    const XclRoot&      mrRoot;         /// Root data.
    SCTAB               mnCurrScTab;    /// Stores sheet index of an object for GetDrawPage().
    SCTAB               mnCachedScTab;  /// Sheet index of cached draw page.
};

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

class XclImpEscherOle;
class XclImpEscherTbxCtrl;
class XclImpCtrlLinkHelper;

/** Converter for import of OXC controls. */
class XclImpOcxConverter : public XclOcxConverter, protected XclImpRoot
{
public:
    explicit            XclImpOcxConverter( const XclImpRoot& rRoot );

    /** Reads the control formatting data for the passed object and creates the SdrUnoObj.
        @return  true = SdrUnoObj successfully created. */
    bool                CreateSdrUnoObj( XclImpEscherOle& rOleObj );

    /** Creates the SdrUnoObj for the passed TBX form control object.
        @return  true = SdrUnoObj successfully created. */
    bool                CreateSdrUnoObj( XclImpEscherTbxCtrl& rTbxCtrl );

private:
    /** Inserts the passed control rxFComp into the document. */
    virtual sal_Bool    InsertControl(
                            const ::com::sun::star::uno::Reference<
                                ::com::sun::star::form::XFormComponent >& rxFComp,
                            const ::com::sun::star::awt::Size& rSize,
                            ::com::sun::star::uno::Reference<
                                ::com::sun::star::drawing::XShape >* pxShape,
                            BOOL bFloatingCtrl );

    /** Tries to set a spreadsheet cell link and source range link at the passed form control. */
    void                ConvertSheetLinks(
                            const ::com::sun::star::uno::Reference<
                                ::com::sun::star::awt::XControlModel >& rxModel,
                            const XclImpCtrlLinkHelper& rControl ) const;
    /** Tries to register a Basic macro for the control. */
    void                RegisterTbxMacro( XclImpEscherTbxCtrl& rTbxCtrl );

private:
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >
                        mxDocFactory;       /// The MultiServiceFactory of the Calc document.
    SotStorageStreamRef mxStrm;             /// The 'Ctls' stream in the Excel file.
    sal_Int32           mnLastIndex;        /// Last insertion index of a control.
};

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

class SdrObject;
#if EXC_EXP_OCX_CTRL
class XclExpObjOcxCtrl;
#else
class XclExpObjTbxCtrl;
#endif
class XclExpCtrlLinkHelper;

/** Converter for export of OXC controls. */
class XclExpOcxConverter : public XclOcxConverter, protected XclExpRoot
{
public:
    explicit            XclExpOcxConverter( const XclExpRoot& rRoot );

#if EXC_EXP_OCX_CTRL
    /** Creates an OCX form control OBJ record from the passed form control.
        @descr  Writes the form control data to the 'Ctls' stream. */
    XclExpObjOcxCtrl*   CreateCtrlObj( const ::com::sun::star::uno::Reference<
                            ::com::sun::star::drawing::XShape >& rxShape );
#else
    /** Creates a TBX form control OBJ record from the passed form control. */
    XclExpObjTbxCtrl*   CreateCtrlObj( const ::com::sun::star::uno::Reference<
                            ::com::sun::star::drawing::XShape >& rxShape );
#endif

private:
    /** Tries to get spreadsheet cell link and source range link from the passed model.
        @param rControl  The Excel form control that stores and exports the links. */
    void                ConvertSheetLinks(
                            XclExpCtrlLinkHelper& rControl,
                            const ::com::sun::star::uno::Reference<
                                ::com::sun::star::awt::XControlModel >& rxModel ) const;
#if !EXC_EXP_OCX_CTRL
    /** Tries to get the name of a Basic macro from a control. */
    void                ConvertTbxMacro(
                            XclExpObjTbxCtrl& rTbxCtrl,
                            const ::com::sun::star::uno::Reference<
                                ::com::sun::star::awt::XControlModel >& rxModel );
#endif

private:
#if EXC_EXP_OCX_CTRL
    SotStorageStreamRef  mxStrm;         /// The 'Ctls' stream.
#endif
};

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

#endif

<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "fieldupdate.h"
#include <vespa/document/base/exceptions.h>
#include <vespa/document/fieldvalue/document.h>
#include <vespa/document/datatype/documenttype.h>

namespace document {

typedef std::vector<ValueUpdate::CP> ValueUpdateList;

FieldUpdate::FieldUpdate(const Field& field)
    : Printable(),
      _field(field),
      _updates()
{
}

namespace {

    int readInt(ByteBuffer & buffer) {
        int fieldId;
        buffer.getIntNetwork(fieldId);
        return fieldId;
    }
}

FieldUpdate::FieldUpdate(const DocumentTypeRepo& repo, const DocumentType& type, ByteBuffer& buffer, int16_t version)
    : Printable(),
      _field(type.getField(readInt(buffer))),
      _updates()
{
    int numUpdates = readInt(buffer);
    _updates.reserve(numUpdates);
    const DataType& dataType = _field.getDataType();
    for(int i(0); i < numUpdates; i++) {
        _updates.emplace_back(ValueUpdate::createInstance(repo, dataType, buffer, version).release());
    }
}

FieldUpdate::FieldUpdate(const FieldUpdate &) = default;
FieldUpdate & FieldUpdate::operator = (const FieldUpdate &) = default;
FieldUpdate::~FieldUpdate() = default;

bool
FieldUpdate::operator==(const FieldUpdate& other) const
{
    if (_field != other._field) return false;
    if (_updates.size() != other._updates.size()) return false;
    for (uint32_t i=0, n=_updates.size(); i<n; ++i) {
        if (*_updates[i] != *other._updates[i]) return false;
    }
    return true;
}

void
FieldUpdate::printXml(XmlOutputStream& xos) const
{
    for(const auto & update : _updates) {
        update->printXml(xos);
    }
}

// Apply this field update to the given document.
void
FieldUpdate::applyTo(Document& doc) const
{
    const DataType& datatype = _field.getDataType();
    FieldValue::UP value = doc.getValue(_field);

    for (const ValueUpdate::CP & update : _updates) {
        if ( ! value) {
            // Avoid passing a null pointer to a value update.
            value = datatype.createFieldValue();
        }
        if (!update->applyTo(*value)) {
            value.reset();
        }
    }

    if (value) {
        doc.setFieldValue(_field, std::move(value));
    } else {
        doc.remove(_field);
    }
}

// Print this field update as a human readable string.
void
FieldUpdate::print(std::ostream& out, bool verbose, const std::string& indent) const
{
    out << "FieldUpdate(" << _field.toString(verbose);
    for(const auto & update : _updates) {
        out << "\n" << indent << "  ";
        update->print(out, verbose, indent + "  ");
    }
    if (_updates.size() > 0) {
        out << "\n" << indent;
    }
    out << ")";
}

// Deserialize this field update from the given buffer.
void
FieldUpdate::deserialize(const DocumentTypeRepo& repo, const DocumentType& docType,
                         ByteBuffer& buffer, int16_t version)
{
    int fieldId;
    buffer.getIntNetwork(fieldId);
    _field = docType.getField(fieldId);
    const DataType& dataType = _field.getDataType();

    int numUpdates = 0;
    buffer.getIntNetwork(numUpdates);
    _updates.clear();
    _updates.resize(numUpdates);
    for(int i = 0; i < numUpdates; i++) {
        _updates[i].reset(ValueUpdate::createInstance(repo, dataType, buffer, version).release());
    }
}

}  // namespace document
<commit_msg>Better naming<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "fieldupdate.h"
#include <vespa/document/base/exceptions.h>
#include <vespa/document/fieldvalue/document.h>
#include <vespa/document/datatype/documenttype.h>

namespace document {

typedef std::vector<ValueUpdate::CP> ValueUpdateList;

FieldUpdate::FieldUpdate(const Field& field)
    : Printable(),
      _field(field),
      _updates()
{
}

namespace {

int readInt(ByteBuffer & buffer) {
    int tmp;
    buffer.getIntNetwork(tmp);
    return tmp;
}

}

FieldUpdate::FieldUpdate(const DocumentTypeRepo& repo, const DocumentType& type, ByteBuffer& buffer, int16_t version)
    : Printable(),
      _field(type.getField(readInt(buffer))),
      _updates()
{
    int numUpdates = readInt(buffer);
    _updates.reserve(numUpdates);
    const DataType& dataType = _field.getDataType();
    for(int i(0); i < numUpdates; i++) {
        _updates.emplace_back(ValueUpdate::createInstance(repo, dataType, buffer, version).release());
    }
}

FieldUpdate::FieldUpdate(const FieldUpdate &) = default;
FieldUpdate & FieldUpdate::operator = (const FieldUpdate &) = default;
FieldUpdate::~FieldUpdate() = default;

bool
FieldUpdate::operator==(const FieldUpdate& other) const
{
    if (_field != other._field) return false;
    if (_updates.size() != other._updates.size()) return false;
    for (uint32_t i=0, n=_updates.size(); i<n; ++i) {
        if (*_updates[i] != *other._updates[i]) return false;
    }
    return true;
}

void
FieldUpdate::printXml(XmlOutputStream& xos) const
{
    for(const auto & update : _updates) {
        update->printXml(xos);
    }
}

// Apply this field update to the given document.
void
FieldUpdate::applyTo(Document& doc) const
{
    const DataType& datatype = _field.getDataType();
    FieldValue::UP value = doc.getValue(_field);

    for (const ValueUpdate::CP & update : _updates) {
        if ( ! value) {
            // Avoid passing a null pointer to a value update.
            value = datatype.createFieldValue();
        }
        if (!update->applyTo(*value)) {
            value.reset();
        }
    }

    if (value) {
        doc.setFieldValue(_field, std::move(value));
    } else {
        doc.remove(_field);
    }
}

// Print this field update as a human readable string.
void
FieldUpdate::print(std::ostream& out, bool verbose, const std::string& indent) const
{
    out << "FieldUpdate(" << _field.toString(verbose);
    for(const auto & update : _updates) {
        out << "\n" << indent << "  ";
        update->print(out, verbose, indent + "  ");
    }
    if (_updates.size() > 0) {
        out << "\n" << indent;
    }
    out << ")";
}

// Deserialize this field update from the given buffer.
void
FieldUpdate::deserialize(const DocumentTypeRepo& repo, const DocumentType& docType,
                         ByteBuffer& buffer, int16_t version)
{
    int fieldId;
    buffer.getIntNetwork(fieldId);
    _field = docType.getField(fieldId);
    const DataType& dataType = _field.getDataType();

    int numUpdates = 0;
    buffer.getIntNetwork(numUpdates);
    _updates.clear();
    _updates.resize(numUpdates);
    for(int i = 0; i < numUpdates; i++) {
        _updates[i].reset(ValueUpdate::createInstance(repo, dataType, buffer, version).release());
    }
}

}  // namespace document
<|endoftext|>


<commit_before>#pragma once
#ifndef DSTREAMBUF_HPP
# define DSTREAMBUF_HPP

#include <streambuf>

#include "delegate.hpp"

template <std::size_t bufsize = 128>
struct dstreambuf : std::streambuf
{
  typedef delegate<void (char const*, std::size_t)> delegate_type;

  dstreambuf(delegate_type d)
    : delegate_(d)
  {
    setp(buffer_, buffer_ + bufsize);
  }

private:
  int overflow(int const c)
  {
    sync();

    if (traits_type::eof() != c)
    {
      *pptr() = traits_type::to_char_type(c);

      pbump(1);
    }
    // else do nothing

    return traits_type::to_int_type(c);
  }

  int sync()
  {
    if (pbase() != pptr())
    {
      delegate_(pbase(), pptr() - pbase());

      setp(buffer_, buffer_ + bufsize);
    }
    // else do nothing

    return 0;
  }

private:
  delegate_type delegate_;

  char buffer_[bufsize];
};

#endif // DSTREAMBUF_HPP
<commit_msg>strips<commit_after>#pragma once
#ifndef DSTREAMBUF_HPP
# define DSTREAMBUF_HPP

#include <streambuf>

#include "delegate.hpp"

template <std::size_t bufsize = 128>
struct dstreambuf : std::streambuf
{
  typedef delegate<void (char const*, std::size_t)> delegate_type;

  dstreambuf(delegate_type d)
    : delegate_(d)
  {
    super::setp(buffer_, buffer_ + bufsize);
  }

private:
  int overflow(int const c)
  {
    dstreambuf::sync();

    if (traits_type::eof() != c)
    {
      *super::pptr() = traits_type::to_char_type(c);

      super::pbump(1);
    }
    // else do nothing

    return traits_type::to_int_type(c);
  }

  int sync()
  {
    if (super::pbase() != super::pptr())
    {
      delegate_(pbase(), pptr() - pbase());

      super::setp(buffer_, buffer_ + bufsize);
    }
    // else do nothing

    return 0;
  }

private:
  typedef std::streambuf super;

  delegate_type delegate_;

  char buffer_[bufsize];
};

#endif // DSTREAMBUF_HPP
<|endoftext|>


<commit_before>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

#include "../snails/interpreter.h"

const std::string TYPES("pioe");
const char BLOCK_O = '[', BLOCK_C = ']', LINE_O = '=';

int main(int argc, char* argv[])
{
    const char* fname = argc > 1 ? argv[1] : "tests.txt";

    std::ifstream fs;

    std::vector<std::string> pr, in;
    std::string ln, str;
    int line = 0;
#define READLN (++line, std::getline(fs, ln))
#define FMT_ASSERT(E) if(!(E)) { std::cerr << "Bad test file format at line " << line << std::endl; return 2; }
#define FAIL_TEST(MSG) std::cerr << "Test failed: " << MSG << " on test #" << ntests << " at line " << line <<std::endl; return 3

    try {
        fs.open(fname);
        int last = 0;
        while (fs.exceptions(std::ifstream::badbit), READLN) {
            fs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
            int t, blk;
            if (ln.size() >= 2 && (t = 1 + TYPES.find(ln[0])) && ((blk = ln[1] == BLOCK_O) || ln[1] == LINE_O)) {
                if (t > 2) FMT_ASSERT(pr.size() && in.size());
                if (blk) {
                    FMT_ASSERT(!~ln.find_first_not_of(BLOCK_O, 2));
                    size_t nb = ln.size() - 1;
                    bool first = true;
                    str.clear();
                    while (READLN, ln.find_first_not_of(BLOCK_C) < nb || ln.size() < nb) {
                        if (first) first = false;
                        else str.append("\n");
                        str.append(ln);
                    }
                    FMT_ASSERT(ln.size() == nb);
                } else str = ln.substr(2);
                if (t == 1) {
                    if (last > 1) pr.clear();
                    pr.push_back(str);
                } else if (t == 2) {
                    if (last != 2) in.clear();
                    in.push_back(str);
                } else {
                    int ntests = 0;
                    for (std::string &p : pr) {
                        for (std::string &i : in) {
                            ++ntests;
                            std::stringstream out, err;
                            interpreter(p, i, out, err);
                            if (t == 3) {
                                if (!err.str().empty()) {
                                    FAIL_TEST("non-empty error output");
                                }
                                if (out.str() != str) {
                                    FAIL_TEST("incorrect output");
                                }
                            } else {
                                if (err.str().substr(0, str.size()) != str) {
                                    FAIL_TEST("incorrect error output");
                                }
                            }
                        }
                    }
                    std::cout << "Passed " << ntests << " test(s) on line " << line << std::endl;
                }
                last = t;
            }
        }

    } catch (std::ifstream::failure& x) {
        std::cerr << "Error reading " << fname << " : " << x.what() << std::endl;
        return 1;
    }

    std::cout << "All tests succeeded\n";

	return 0;
}

<commit_msg>Detect failure to open file in test.cpp<commit_after>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

#include "../snails/interpreter.h"

const std::string TYPES("pioe");
const char BLOCK_O = '[', BLOCK_C = ']', LINE_O = '=';

int main(int argc, char* argv[])
{
    const char* fname = argc > 1 ? argv[1] : "tests.txt";

    std::ifstream fs;

    std::vector<std::string> pr, in;
    std::string ln, str;
    int line = 0;
#define READLN (++line, std::getline(fs, ln))
#define FMT_ASSERT(E) if(!(E)) { std::cerr << "Bad test file format at line " << line << std::endl; return 2; }
#define FAIL_TEST(MSG) std::cerr << "Test failed: " << MSG << " on test #" << ntests << " at line " << line <<std::endl; return 3

    try {
        fs.open(fname);
        if (!fs.good()) {
            std::cerr << "Couldn't open the file: " << fname << std::endl;
            return 1;
        }
        int last = 0;
        while (fs.exceptions(std::ifstream::badbit), READLN) {
            fs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
            int t, blk;
            if (ln.size() >= 2 && (t = 1 + TYPES.find(ln[0])) && ((blk = ln[1] == BLOCK_O) || ln[1] == LINE_O)) {
                if (t > 2) FMT_ASSERT(pr.size() && in.size());
                if (blk) {
                    FMT_ASSERT(!~ln.find_first_not_of(BLOCK_O, 2));
                    size_t nb = ln.size() - 1;
                    bool first = true;
                    str.clear();
                    while (READLN, ln.find_first_not_of(BLOCK_C) < nb || ln.size() < nb) {
                        if (first) first = false;
                        else str.append("\n");
                        str.append(ln);
                    }
                    FMT_ASSERT(ln.size() == nb);
                } else str = ln.substr(2);
                if (t == 1) {
                    if (last > 1) pr.clear();
                    pr.push_back(str);
                } else if (t == 2) {
                    if (last != 2) in.clear();
                    in.push_back(str);
                } else {
                    int ntests = 0;
                    for (std::string &p : pr) {
                        for (std::string &i : in) {
                            ++ntests;
                            std::stringstream out, err;
                            interpreter(p, i, out, err);
                            if (t == 3) {
                                if (!err.str().empty()) {
                                    FAIL_TEST("non-empty error output");
                                }
                                if (out.str() != str) {
                                    FAIL_TEST("incorrect output");
                                }
                            } else {
                                if (err.str().substr(0, str.size()) != str) {
                                    FAIL_TEST("incorrect error output");
                                }
                            }
                        }
                    }
                    std::cout << "Passed " << ntests << " test(s) on line " << line << std::endl;
                }
                last = t;
            }
        }

    } catch (const decltype(fs)::failure& x) {
        std::cerr << "Error reading " << fname << " : " << x.what() << std::endl;
        return 1;
    }

    std::cout << "All tests succeeded\n";

    return 0;
}

<|endoftext|>


<commit_before><commit_msg>sc LOKit callback for search not found.<commit_after><|endoftext|>


<commit_before>#include "vec.hpp"
#include "lib/catch.hpp"

int main() {
}
<commit_msg>add tests<commit_after>#define CATCH_CONFIG_MAIN
#include "lib/catch.hpp"

#include "vec.hpp"

TEST_CASE( "base vector accessors", "" ) {
    Vec<1> x = { 5 };
    REQUIRE( x[0] == 5 );
    x[0] = 9;
    REQUIRE( x[0] == 9 );

    Vec<2> xy = { 1, 2 };
    REQUIRE( xy[0] == 1 );
    REQUIRE( xy[1] == 2 );

    Vec<100> big;
    for ( int i = 0; i < 100; i++ ) big[i] = i;
    for ( int i = 0; i < 100; i++ ) REQUIRE( big[i] == i );
}

TEST_CASE( "structured vector accessors", "" ) {
    Vec2 xy = { 1, 2 };
    REQUIRE( xy.x == 1 );
    REQUIRE( xy.y == 2 );

    xy.x = 3;
    xy.y = 4;
    REQUIRE( xy.x == 3 );
    REQUIRE( xy.y == 4 );

    Vec3 xyz = { 5, 6, 7 };
    REQUIRE( xyz.x == 5 );
    REQUIRE( xyz.y == 6 );
    REQUIRE( xyz.z == 7 );
    REQUIRE( xyz.r == 5 );
    REQUIRE( xyz.g == 6 );
    REQUIRE( xyz.b == 7 );
    REQUIRE( xyz.xy.x == 5 );
    REQUIRE( xyz.xy.y == 6 );

    Vec4 xyzw = { 9, 10, 11, 12 };
    REQUIRE( xyzw.x == 9 );
    REQUIRE( xyzw.y == 10 );
    REQUIRE( xyzw.z == 11 );
    REQUIRE( xyzw.w == 12 );
    REQUIRE( xyzw.r == 9 );
    REQUIRE( xyzw.g == 10 );
    REQUIRE( xyzw.b == 11 );
    REQUIRE( xyzw.a == 12 );
    REQUIRE( xyzw.xy.x == 9 );
    REQUIRE( xyzw.xy.y == 10 );
    REQUIRE( xyzw.xyz.x == 9 );
    REQUIRE( xyzw.xyz.y == 10 );
    REQUIRE( xyzw.xyz.z == 11 );
}
<|endoftext|>


<commit_before>/*
// Copyright (c) 2015 Pierre Guillot.
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#include "../xpd/xpd.hpp"
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
#include <cstdlib>

using namespace xpd;

#ifndef XPD_TEST_HPP
#define XPD_TEST_HPP

#define XPD_TEST_NLOOP 1

class instance_test : private instance
{
public:
    instance_test(const size_t index) : m_index(index)
    {
        ;
    }

    ~instance_test()
    {
        ;
    }

    void receive(console::post const& post) xpd_final
    {
        if(post.type == console::fatal) {
            m_count_fatal++;
        }
        else if(post.type == console::error) {
            m_count_error++;
        }
        else if(post.type == console::normal) {
            m_count_normal++;
        }
        else {
            m_count_log++;
        }
    }

    void receive(tie tie, symbol s, std::vector<atom> const& atoms) xpd_final
    {
        if(s == symbol::bang_s) {
            m_count_bang++;
        }
        else if(s == symbol::float_s) {
            m_count_float++;
        }
        else if(s == symbol::symbol_s) {
            m_count_symbol++;
        }
        else if(s == symbol::list_s) {
            m_count_list++;
        }
        else {
            m_count_anything++;
        }

        std::vector<atom> const& temp = m_atoms;
        assert("receive atoms s" && s == m_name);
        assert("receive atoms size" && atoms.size() == temp.size());

        int to_check_strange;
        /*
        for(size_t i = 0; i < atoms.size(); ++i)
        {
            assert("receive atoms type" && atoms[i].type() == temp[i].type());
            if(atoms[i].type() == atom::float_t)
            {
                assert("receive atoms type" && float(atoms[i]) == float(temp[i]));
            }
            else if(atoms[i].type() == atom::symbol_t)
            {
                assert("receive atoms type" && symbol(atoms[i]) == symbol(temp[i]));
            }
        }
         */
    }

    void receive(midi::event const& event)
    {
        if(event.type() == midi::event::note_t) {
            m_count_note++;
        }
        else if(event.type() == midi::event::control_change_t) {
            m_count_ctl++;
        }
        else if(event.type() == midi::event::program_change_t) {
            m_count_pgm++;
        }
        else if(event.type() == midi::event::pitch_bend_t) {
            m_count_bend++;
        }
        else if(event.type() == midi::event::after_touch_t) {
            m_count_after++;
        }
        else if(event.type() == midi::event::poly_after_touch_t) {
            m_count_poly++;
        }
        else {
            m_count_byte++;
        }
    }

    static void test_post(instance_test* inst)
    {
        inst->m_count_log = 0;
        inst->m_count_normal = 0;
        inst->m_count_error = 0;
        inst->m_count_fatal = 0;
        for(size_t i = 0; i < XPD_TEST_NLOOP; i++)
        {
            inst->send(console::post(console::log, "test"));
            inst->send(console::post(console::normal, "test"));
            inst->send(console::post(console::error, "test"));
            inst->send(console::post(console::fatal, "test"));
        }
        assert("test_post log" && inst->m_count_log == XPD_TEST_NLOOP);
        assert("test_post normal" && inst->m_count_normal == XPD_TEST_NLOOP);
        assert("test_post error" && inst->m_count_error == XPD_TEST_NLOOP);
        assert("test_post fatal" && inst->m_count_fatal == XPD_TEST_NLOOP);
    }

    static void test_message(instance_test* inst)
    {
        char uid[512];
        patch* p = inst->load("test.pd", "");
        assert("test_message patch" && p);
        sprintf(uid, "%i", int(p->unique_id()));
        tie from(std::string(uid) + "-fromxpd");
        tie to1(std::string(uid) + "-toxpd1");
        tie to2(std::string(uid) + "-toxpd2");
        inst->bind(to1);
        inst->bind(to1);
        inst->bind(to2);

        inst->m_count_bang = 0;
        inst->m_count_float = 0;
        inst->m_count_symbol = 0;
        inst->m_count_list = 0;
        inst->m_count_anything = 0;
        inst->m_atoms.reserve(5);
        symbol zozo("zozo");
        for(size_t i = 0; i < XPD_TEST_NLOOP; i++)
        {
            inst->m_name = symbol::bang_s;
            inst->m_atoms.clear();
            inst->send(from, inst->m_name, inst->m_atoms);

            inst->m_name = symbol::float_s;
            inst->m_atoms.push_back(1.f);
            assert("test_message float" && inst->m_atoms[0].type() == atom::float_t && float(inst->m_atoms[0]) == 1.f);
            inst->send(from, inst->m_name, inst->m_atoms);

            inst->m_name = symbol::symbol_s;
            inst->m_atoms[0] = zozo;
            assert("test_message symbol" && inst->m_atoms[0].type() == atom::symbol_t && symbol(inst->m_atoms[0]) == zozo);
            inst->send(from, inst->m_name, inst->m_atoms);

            inst->m_name = symbol::list_s;
            inst->m_atoms[0] = 1.f;
            inst->m_atoms.push_back(1.f);
            inst->m_atoms.push_back(zozo);
            inst->send(from, inst->m_name, inst->m_atoms);

            inst->m_name = symbol("zaza");
            inst->m_atoms[0] = zozo;
            inst->m_atoms.push_back(symbol("zizi"));
            inst->send(from, inst->m_name, inst->m_atoms);
        }
        inst->unbind(to1);
        inst->unbind(to2);
        assert("test_message bang" && inst->m_count_bang == XPD_TEST_NLOOP * 2);
        assert("test_message float" && inst->m_count_float == XPD_TEST_NLOOP * 2);
        assert("test_message symbol" && inst->m_count_symbol == XPD_TEST_NLOOP * 2);
        assert("test_message list" && inst->m_count_list == XPD_TEST_NLOOP * 2);
        assert("test_message anything" && inst->m_count_anything == XPD_TEST_NLOOP * 2);
        inst->close(*p);
    }

    static void test_midi(instance_test* inst)
    {
        patch* p = inst->load("test.pd", "");
        inst->m_count_note = 0;
        inst->m_count_ctl = 0;
        inst->m_count_pgm = 0;
        inst->m_count_bend = 0;
        inst->m_count_after = 0;
        inst->m_count_poly = 0;
        inst->m_count_byte = 0;

        for(size_t i = 0; i < XPD_TEST_NLOOP; i++)
        {
            inst->send(midi::event::note(1, 1, 127));
            inst->send(midi::event::control_change(1, 1, 127));
            inst->send(midi::event::program_change(1, 1));
            inst->send(midi::event::pitch_bend(1, 1));
            inst->send(midi::event::after_touch(1, 1));
            inst->send(midi::event::poly_after_touch(1, 1, 1));
            inst->send(midi::event::byte(1));
        }

        assert("test_midi note" && inst->m_count_note == XPD_TEST_NLOOP);
        assert("test_midi ctl" && inst->m_count_ctl == XPD_TEST_NLOOP);
        assert("test_midi pgm" && inst->m_count_pgm == XPD_TEST_NLOOP);
        assert("test_midi bend" && inst->m_count_bend == XPD_TEST_NLOOP);
        assert("test_midi after" && inst->m_count_after == XPD_TEST_NLOOP);
        assert("test_midi poly" && inst->m_count_poly == XPD_TEST_NLOOP);
        assert("test_midi byte" && inst->m_count_byte == XPD_TEST_NLOOP);
        inst->close(*p);
    }

    static void test_dsp_int(instance_test* inst, int sr, int blks, int nins, int nouts)
    {
        inst->prepare(nins, nouts, sr, blks);
        assert("test_dsp sample rate" && inst->samplerate() == sr);

        for(size_t i = 0; i < XPD_TEST_NLOOP; i++)
        {
            for(size_t k = 0; k < nins; k++)
            {
                for(size_t j = 0; j < blks; j++)
                {
                    inst->m_input[k][j] = ((rand() % 4000) - 2000.f) / 2000.f;
                }
            }
            inst->perform(blks, nins, const_cast<float const **>(inst->m_input), nouts, inst->m_output);
            for(size_t k = 0; k < nouts; k++)
            {
                for(size_t j = 0; j < blks; j++)
                {
                    assert("test_dsp samples" && inst->m_output[k][j] == inst->m_input[k][j]);
                }
            }
        }
    }

    static void test_dsp(instance_test* inst)
    {
        patch* p = inst->load("test.pd", "");
        inst->m_input[0] = new float[256];
        inst->m_input[1] = new float[256];
        inst->m_output[0] = new float[256];
        inst->m_output[1] = new float[256];
        assert("test_dsp inputs outputs" && inst->m_input[0] && inst->m_input[1] && inst->m_output[0] && inst->m_output[1]);

        test_dsp_int(inst, 44100, 64, 2, 2);
        test_dsp_int(inst, 44100, 256, 2, 1);
        test_dsp_int(inst, 96000, 128, 1, 1);

        delete [] inst->m_input[0];
        delete [] inst->m_input[1];
        delete [] inst->m_output[0];
        delete [] inst->m_output[1];
        inst->close(*p);
    }

private:
    const size_t m_index;
    size_t  m_ninouts;
    float* m_input[2];
    float* m_output[2];
    symbol            m_name;
    std::vector<atom> m_atoms;

    size_t m_count_fatal;
    size_t m_count_error;
    size_t m_count_normal;
    size_t m_count_log;

    size_t m_count_bang;
    size_t m_count_float;
    size_t m_count_symbol;
    size_t m_count_list;
    size_t m_count_anything;

    size_t m_count_note;
    size_t m_count_ctl;
    size_t m_count_pgm;
    size_t m_count_bend;
    size_t m_count_after;
    size_t m_count_poly;
    size_t m_count_byte;
};

#endif // XPD_TEST_HPP
<commit_msg>symbol tests<commit_after>/*
// Copyright (c) 2015 Pierre Guillot.
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#include "../xpd/xpd.hpp"
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
#include <cstdlib>

using namespace xpd;

#ifndef XPD_TEST_HPP
#define XPD_TEST_HPP

#define XPD_TEST_NLOOP 1

class instance_test : private instance
{
public:
    instance_test(const size_t index) : m_index(index)
    {
        ;
    }

    ~instance_test()
    {
        ;
    }

    void receive(console::post const& post) xpd_final
    {
        if(post.type == console::fatal) {
            m_count_fatal++;
        }
        else if(post.type == console::error) {
            m_count_error++;
        }
        else if(post.type == console::normal) {
            m_count_normal++;
        }
        else {
            m_count_log++;
        }
    }

    void receive(tie tie, symbol s, std::vector<atom> const& atoms) xpd_final
    {
        if(s == symbol::bang_s) {
            m_count_bang++;
        }
        else if(s == symbol::float_s) {
            m_count_float++;
        }
        else if(s == symbol::symbol_s) {
            m_count_symbol++;
        }
        else if(s == symbol::list_s) {
            m_count_list++;
        }
        else {
            m_count_anything++;
        }

        std::vector<atom> const& temp = m_atoms;
        assert("receive atoms s" && s == m_name);
        assert("receive atoms size" && atoms.size() == temp.size());

        int to_check_strange;
        /*
        for(size_t i = 0; i < atoms.size(); ++i)
        {
            assert("receive atoms type" && atoms[i].type() == temp[i].type());
            if(atoms[i].type() == atom::float_t)
            {
                assert("receive atoms type" && float(atoms[i]) == float(temp[i]));
            }
            else if(atoms[i].type() == atom::symbol_t)
            {
                assert("receive atoms type" && symbol(atoms[i]) == symbol(temp[i]));
            }
        }
         */
    }

    void receive(midi::event const& event)
    {
        if(event.type() == midi::event::note_t) {
            m_count_note++;
        }
        else if(event.type() == midi::event::control_change_t) {
            m_count_ctl++;
        }
        else if(event.type() == midi::event::program_change_t) {
            m_count_pgm++;
        }
        else if(event.type() == midi::event::pitch_bend_t) {
            m_count_bend++;
        }
        else if(event.type() == midi::event::after_touch_t) {
            m_count_after++;
        }
        else if(event.type() == midi::event::poly_after_touch_t) {
            m_count_poly++;
        }
        else {
            m_count_byte++;
        }
    }

    static void test_post(instance_test* inst)
    {
        inst->m_count_log = 0;
        inst->m_count_normal = 0;
        inst->m_count_error = 0;
        inst->m_count_fatal = 0;
        for(size_t i = 0; i < XPD_TEST_NLOOP; i++)
        {
            inst->send(console::post(console::log, "test"));
            inst->send(console::post(console::normal, "test"));
            inst->send(console::post(console::error, "test"));
            inst->send(console::post(console::fatal, "test"));
        }
        assert("test_post log" && inst->m_count_log == XPD_TEST_NLOOP);
        assert("test_post normal" && inst->m_count_normal == XPD_TEST_NLOOP);
        assert("test_post error" && inst->m_count_error == XPD_TEST_NLOOP);
        assert("test_post fatal" && inst->m_count_fatal == XPD_TEST_NLOOP);
    }

    static void test_message(instance_test* inst)
    {
        char uid[512];
        patch* p = inst->load("test.pd", "");
        assert("test_message patch" && p);
        sprintf(uid, "%i", int(p->unique_id()));
        tie from(std::string(uid) + "-fromxpd");
        tie to1(std::string(uid) + "-toxpd1");
        tie to2(std::string(uid) + "-toxpd2");
        inst->bind(to1);
        inst->bind(to1);
        inst->bind(to2);

        inst->m_count_bang = 0;
        inst->m_count_float = 0;
        inst->m_count_symbol = 0;
        inst->m_count_list = 0;
        inst->m_count_anything = 0;
        inst->m_atoms.reserve(5);
        symbol zozo("zozo");
        for(size_t i = 0; i < XPD_TEST_NLOOP; i++)
        {
            inst->m_name = symbol::bang_s;
            inst->m_atoms.clear();
            inst->send(from, inst->m_name, inst->m_atoms);

            inst->m_name = symbol::float_s;
            inst->m_atoms.push_back(1.f);
            assert("test_message float" && inst->m_atoms[0].type() == atom::float_t && float(inst->m_atoms[0]) == 1.f);
            inst->send(from, inst->m_name, inst->m_atoms);

            inst->m_name = symbol::symbol_s;
            inst->m_atoms[0] = zozo;
            assert("test_message symbol" && inst->m_atoms[0].type() == atom::symbol_t && symbol(inst->m_atoms[0]) == zozo);
            inst->send(from, inst->m_name, inst->m_atoms);

            inst->m_name = symbol::list_s;
            inst->m_atoms[0] = 1.f;
            inst->m_atoms.push_back(1.f);
            inst->m_atoms.push_back(zozo);
            inst->send(from, inst->m_name, inst->m_atoms);

            inst->m_name = symbol(std::string("zaza"));
            inst->m_atoms[0] = "zozo";
            inst->m_atoms[2] = std::string("zuzu");
            inst->m_atoms.push_back(symbol("zizi"));
            inst->send(from, inst->m_name, inst->m_atoms);
        }
        inst->unbind(to1);
        inst->unbind(to2);
        assert("test_message bang" && inst->m_count_bang == XPD_TEST_NLOOP * 2);
        assert("test_message float" && inst->m_count_float == XPD_TEST_NLOOP * 2);
        assert("test_message symbol" && inst->m_count_symbol == XPD_TEST_NLOOP * 2);
        assert("test_message list" && inst->m_count_list == XPD_TEST_NLOOP * 2);
        assert("test_message anything" && inst->m_count_anything == XPD_TEST_NLOOP * 2);
        inst->close(*p);
    }

    static void test_midi(instance_test* inst)
    {
        patch* p = inst->load("test.pd", "");
        inst->m_count_note = 0;
        inst->m_count_ctl = 0;
        inst->m_count_pgm = 0;
        inst->m_count_bend = 0;
        inst->m_count_after = 0;
        inst->m_count_poly = 0;
        inst->m_count_byte = 0;

        for(size_t i = 0; i < XPD_TEST_NLOOP; i++)
        {
            inst->send(midi::event::note(1, 1, 127));
            inst->send(midi::event::control_change(1, 1, 127));
            inst->send(midi::event::program_change(1, 1));
            inst->send(midi::event::pitch_bend(1, 1));
            inst->send(midi::event::after_touch(1, 1));
            inst->send(midi::event::poly_after_touch(1, 1, 1));
            inst->send(midi::event::byte(1));
        }

        assert("test_midi note" && inst->m_count_note == XPD_TEST_NLOOP);
        assert("test_midi ctl" && inst->m_count_ctl == XPD_TEST_NLOOP);
        assert("test_midi pgm" && inst->m_count_pgm == XPD_TEST_NLOOP);
        assert("test_midi bend" && inst->m_count_bend == XPD_TEST_NLOOP);
        assert("test_midi after" && inst->m_count_after == XPD_TEST_NLOOP);
        assert("test_midi poly" && inst->m_count_poly == XPD_TEST_NLOOP);
        assert("test_midi byte" && inst->m_count_byte == XPD_TEST_NLOOP);
        inst->close(*p);
    }

    static void test_dsp_int(instance_test* inst, int sr, int blks, int nins, int nouts)
    {
        inst->prepare(nins, nouts, sr, blks);
        assert("test_dsp sample rate" && inst->samplerate() == sr);

        for(size_t i = 0; i < XPD_TEST_NLOOP; i++)
        {
            for(size_t k = 0; k < nins; k++)
            {
                for(size_t j = 0; j < blks; j++)
                {
                    inst->m_input[k][j] = ((rand() % 4000) - 2000.f) / 2000.f;
                }
            }
            inst->perform(blks, nins, const_cast<float const **>(inst->m_input), nouts, inst->m_output);
            for(size_t k = 0; k < nouts; k++)
            {
                for(size_t j = 0; j < blks; j++)
                {
                    assert("test_dsp samples" && inst->m_output[k][j] == inst->m_input[k][j]);
                }
            }
        }
    }

    static void test_dsp(instance_test* inst)
    {
        patch* p = inst->load("test.pd", "");
        inst->m_input[0] = new float[256];
        inst->m_input[1] = new float[256];
        inst->m_output[0] = new float[256];
        inst->m_output[1] = new float[256];
        assert("test_dsp inputs outputs" && inst->m_input[0] && inst->m_input[1] && inst->m_output[0] && inst->m_output[1]);

        test_dsp_int(inst, 44100, 64, 2, 2);
        test_dsp_int(inst, 44100, 256, 2, 1);
        test_dsp_int(inst, 96000, 128, 1, 1);

        delete [] inst->m_input[0];
        delete [] inst->m_input[1];
        delete [] inst->m_output[0];
        delete [] inst->m_output[1];
        inst->close(*p);
    }

private:
    const size_t m_index;
    size_t  m_ninouts;
    float* m_input[2];
    float* m_output[2];
    symbol            m_name;
    std::vector<atom> m_atoms;

    size_t m_count_fatal;
    size_t m_count_error;
    size_t m_count_normal;
    size_t m_count_log;

    size_t m_count_bang;
    size_t m_count_float;
    size_t m_count_symbol;
    size_t m_count_list;
    size_t m_count_anything;

    size_t m_count_note;
    size_t m_count_ctl;
    size_t m_count_pgm;
    size_t m_count_bend;
    size_t m_count_after;
    size_t m_count_poly;
    size_t m_count_byte;
};

#endif // XPD_TEST_HPP
<|endoftext|>


<commit_before>/*
 * OXT - OS eXtensions for boosT
 * Provides important functionality necessary for writing robust server software.
 *
 * Copyright (c) 2008 Phusion
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#ifndef _OXT_SYSTEM_CALLS_HPP_
#define _OXT_SYSTEM_CALLS_HPP_

#include <boost/thread/tss.hpp>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <cstdio>
#include <ctime>
#include <cassert>

/**
 * Support for interruption of blocking system calls and C library calls
 *
 * This file provides a framework for writing multithreading code that can
 * be interrupted, even when blocked on system calls or C library calls.
 *
 * One must first call oxt::setup_syscall_interruption_support().
 * Then one may use the functions in oxt::syscalls as drop-in replacements
 * for system calls or C library functions. These functions throw
 * boost::thread_interrupted upon interruption.
 *
 * System call interruption is disabled by default. In other words: the
 * replacement functions in this file don't throw boost::thread_interrupted.
 * You can enable or disable system call interruption in the current scope
 * by creating instances of boost::this_thread::enable_syscall_interruption
 * and similar objects. This is similar to Boost thread interruption.
 *
 *
How to interrupt

 * Generally, oxt::thread::interrupt() and oxt::thread::interrupt_and_join()
 * should be used for interrupting threads. These methods will interrupt
 * the thread at all Boost interruption points, as well as system calls that
 * are caled through the oxt::syscalls namespace. Do *not* use
 * boost::thread::interrupt, because that will not honor system calls as
 * interruption points.
 *
 * Under the hood, system calls are interrupted by sending a signal to the
 * to a specific thread (note: sending a signal to a process will deliver the
 * signal to the main thread).
 *
 * Any signal will do, but of course, one should only send a signal whose
 * signal handler doesn't do undesirable things (such as aborting the entire
 * program). That's why it's generally recommended that you only use
 * oxt::INTERRUPTION_SIGNAL to interrupt system calls, because
 * oxt::setup_syscall_interruption_support() installs an "nice" signal
 * handler for that signal (though you should of course use
 * oxt::thread::interrupt() instead of sending signals whenever
 * possible).
 *
 * Note that sending a signal once may not interrupt the thread, because
 * the thread may not be calling a system call at the time the signal was
 * received. So one must keep sending signals periodically until the
 * thread has quit.
 *
 * @warning
 * After oxt::setup_syscall_interruption_support() is called, sending a signal
 * will cause system calls to return with an EINTR error. The oxt::syscall
 * functions will automatically take care of this, but if you're calling any
 * system calls without using that namespace, then you should check for and
 * take care of EINTR errors.
 */

// This is one of the things that Java is good at and C++ sucks at. Sigh...

namespace oxt {
	static const int INTERRUPTION_SIGNAL = SIGINT;

	/**
	 * Setup system call interruption support.
	 * This function may only be called once. It installs a signal handler
	 * for INTERRUPTION_SIGNAL, so one should not install a different signal
	 * handler for that signal after calling this function.
	 *
	 * @warning
	 * After oxt::setup_syscall_interruption_support() is called, sending a signal
	 * will cause system calls to return with an EINTR error. The oxt::syscall
	 * functions will automatically take care of this, but if you're calling any
	 * system calls without using that namespace, then you should check for and
	 * take care of EINTR errors.
	 */
	void setup_syscall_interruption_support();

	/**
	 * System call and C library call wrappers with interruption support.
	 * These functions are interruption points, i.e. they throw
	 * boost::thread_interrupted whenever the calling thread is interrupted
	 * by oxt::thread::interrupt() or oxt::thread::interrupt_and_join().
	 */
	namespace syscalls {
		ssize_t read(int fd, void *buf, size_t count);
		ssize_t write(int fd, const void *buf, size_t count);
		int close(int fd);

		int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
		int socket(int domain, int type, int protocol);
		int socketpair(int d, int type, int protocol, int sv[2]);
		ssize_t recvmsg(int s, struct msghdr *msg, int flags);
		ssize_t sendmsg(int s, const struct msghdr *msg, int flags);
		int setsockopt(int s, int level, int optname, const void *optval,
			socklen_t optlen);
		int shutdown(int s, int how);

		FILE *fopen(const char *path, const char *mode);
		int fclose(FILE *fp);

		time_t time(time_t *t);
		int usleep(useconds_t usec);
		int nanosleep(const struct timespec *req, struct timespec *rem);

		pid_t fork();
		int kill(pid_t pid, int sig);
		pid_t waitpid(pid_t pid, int *status, int options);
	}

} // namespace oxt

namespace boost {
namespace this_thread {

	/**
	 * @intern
	 */
	extern thread_specific_ptr<bool> _syscalls_interruptable;

	/**
	 * Check whether system calls should be interruptable in
	 * the calling thread.
	 */
	bool syscalls_interruptable();

	class restore_syscall_interruption;

	/**
	 * Create this struct on the stack to temporarily enable system
	 * call interruption, until the object goes out of scope.
	 */
	class enable_syscall_interruption {
	private:
		bool last_value;
	public:
		enable_syscall_interruption() {
			if (_syscalls_interruptable.get() == NULL) {
				last_value = true;
				_syscalls_interruptable.reset(new bool(true));
			} else {
				last_value = *_syscalls_interruptable;
				*_syscalls_interruptable = true;
			}
		}

		~enable_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};

	/**
	 * Create this struct on the stack to temporarily disable system
	 * call interruption, until the object goes out of scope.
	 * While system call interruption is disabled, the functions in
	 * InterruptableCalls will try until the return code is not EINTR.
	 */
	class disable_syscall_interruption {
	private:
		friend class restore_syscall_interruption;
		bool last_value;
	public:
		disable_syscall_interruption() {
			if (_syscalls_interruptable.get() == NULL) {
				last_value = true;
				_syscalls_interruptable.reset(new bool(false));
			} else {
				last_value = *_syscalls_interruptable;
				*_syscalls_interruptable = false;
			}
		}

		~disable_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};

	/**
	 * Creating an object of this class on the stack will restore the
	 * system call interruption state to what it was before.
	 */
	class restore_syscall_interruption {
	private:
		int last_value;
	public:
		restore_syscall_interruption(const disable_syscall_interruption &intr) {
			assert(_syscalls_interruptable.get() != NULL);
			last_value = *_syscalls_interruptable;
			*_syscalls_interruptable = intr.last_value;
		}

		~restore_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};

} // namespace this_thread
} // namespace boost

#endif /* _OXT_SYSTEM_CALLS_HPP_ */

<commit_msg>Improve documentation for oxt/system_calls.hpp.<commit_after>/*
 * OXT - OS eXtensions for boosT
 * Provides important functionality necessary for writing robust server software.
 *
 * Copyright (c) 2008 Phusion
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#ifndef _OXT_SYSTEM_CALLS_HPP_
#define _OXT_SYSTEM_CALLS_HPP_

#include <boost/thread/tss.hpp>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <cstdio>
#include <ctime>
#include <cassert>

/**
 * Support for interruption of blocking system calls and C library calls
 *
 * This file provides a framework for writing multithreading code that can
 * be interrupted, even when blocked on system calls or C library calls.
 *
 * One must first call oxt::setup_syscall_interruption_support().
 * Then one may use the functions in oxt::syscalls as drop-in replacements
 * for system calls or C library functions. These functions throw
 * boost::thread_interrupted upon interruption, instead of returning an EINTR
 * error.
 *
 * System call interruption is disabled by default. As long as system call
 * interruption is disabled, the replacement functions in oxt::syscalls will
 * never throw boost::thread_interrupted, and they will ignore any EINTR errors.
 * You can enable or disable system call interruption in the current scope
 * by creating instances of boost::this_thread::enable_syscall_interruption
 * and similar objects. This is similar to Boost thread interruption.
 *
 *
How to interrupt

 * Generally, oxt::thread::interrupt() and oxt::thread::interrupt_and_join()
 * should be used for interrupting threads. These methods will interrupt
 * the thread at all Boost interruption points, as well as system calls that
 * are caled through the oxt::syscalls namespace. Do *not* use
 * boost::thread::interrupt, because that will not honor system calls as
 * interruption points.
 *
 * Under the hood, system calls are interrupted by sending a signal to the
 * to a specific thread (note: sending a signal to a process will deliver the
 * signal to the main thread).
 *
 * Any signal will do, but of course, one should only send a signal whose
 * signal handler doesn't do undesirable things (such as aborting the entire
 * program). That's why it's generally recommended that you only use
 * oxt::INTERRUPTION_SIGNAL to interrupt system calls, because
 * oxt::setup_syscall_interruption_support() installs an "nice" signal
 * handler for that signal (though you should of course use
 * oxt::thread::interrupt() instead of sending signals whenever
 * possible).
 *
 * Note that sending a signal once may not interrupt the thread, because
 * the thread may not be calling a system call at the time the signal was
 * received. So one must keep sending signals periodically until the
 * thread has quit.
 *
 * @warning
 * After oxt::setup_syscall_interruption_support() is called, sending a signal
 * will cause system calls to return with an EINTR error. The oxt::syscall
 * functions will automatically take care of this, but if you're calling any
 * system calls without using that namespace, then you should check for and
 * take care of EINTR errors.
 */

// This is one of the things that Java is good at and C++ sucks at. Sigh...

namespace oxt {
	static const int INTERRUPTION_SIGNAL = SIGINT;

	/**
	 * Setup system call interruption support.
	 * This function may only be called once. It installs a signal handler
	 * for INTERRUPTION_SIGNAL, so one should not install a different signal
	 * handler for that signal after calling this function.
	 *
	 * @warning
	 * After oxt::setup_syscall_interruption_support() is called, sending a signal
	 * will cause system calls to return with an EINTR error. The oxt::syscall
	 * functions will automatically take care of this, but if you're calling any
	 * system calls without using that namespace, then you should check for and
	 * take care of EINTR errors.
	 */
	void setup_syscall_interruption_support();

	/**
	 * System call and C library call wrappers with interruption support.
	 * These functions are interruption points, i.e. they throw
	 * boost::thread_interrupted whenever the calling thread is interrupted
	 * by oxt::thread::interrupt() or oxt::thread::interrupt_and_join().
	 */
	namespace syscalls {
		ssize_t read(int fd, void *buf, size_t count);
		ssize_t write(int fd, const void *buf, size_t count);
		int close(int fd);

		int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
		int socket(int domain, int type, int protocol);
		int socketpair(int d, int type, int protocol, int sv[2]);
		ssize_t recvmsg(int s, struct msghdr *msg, int flags);
		ssize_t sendmsg(int s, const struct msghdr *msg, int flags);
		int setsockopt(int s, int level, int optname, const void *optval,
			socklen_t optlen);
		int shutdown(int s, int how);

		FILE *fopen(const char *path, const char *mode);
		int fclose(FILE *fp);

		time_t time(time_t *t);
		int usleep(useconds_t usec);
		int nanosleep(const struct timespec *req, struct timespec *rem);

		pid_t fork();
		int kill(pid_t pid, int sig);
		pid_t waitpid(pid_t pid, int *status, int options);
	}

} // namespace oxt

namespace boost {
namespace this_thread {

	/**
	 * @intern
	 */
	extern thread_specific_ptr<bool> _syscalls_interruptable;

	/**
	 * Check whether system calls should be interruptable in
	 * the calling thread.
	 */
	bool syscalls_interruptable();

	class restore_syscall_interruption;

	/**
	 * Create this struct on the stack to temporarily enable system
	 * call interruption, until the object goes out of scope.
	 */
	class enable_syscall_interruption {
	private:
		bool last_value;
	public:
		enable_syscall_interruption() {
			if (_syscalls_interruptable.get() == NULL) {
				last_value = true;
				_syscalls_interruptable.reset(new bool(true));
			} else {
				last_value = *_syscalls_interruptable;
				*_syscalls_interruptable = true;
			}
		}

		~enable_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};

	/**
	 * Create this struct on the stack to temporarily disable system
	 * call interruption, until the object goes out of scope.
	 * While system call interruption is disabled, the functions in
	 * InterruptableCalls will try until the return code is not EINTR.
	 */
	class disable_syscall_interruption {
	private:
		friend class restore_syscall_interruption;
		bool last_value;
	public:
		disable_syscall_interruption() {
			if (_syscalls_interruptable.get() == NULL) {
				last_value = true;
				_syscalls_interruptable.reset(new bool(false));
			} else {
				last_value = *_syscalls_interruptable;
				*_syscalls_interruptable = false;
			}
		}

		~disable_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};

	/**
	 * Creating an object of this class on the stack will restore the
	 * system call interruption state to what it was before.
	 */
	class restore_syscall_interruption {
	private:
		int last_value;
	public:
		restore_syscall_interruption(const disable_syscall_interruption &intr) {
			assert(_syscalls_interruptable.get() != NULL);
			last_value = *_syscalls_interruptable;
			*_syscalls_interruptable = intr.last_value;
		}

		~restore_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};

} // namespace this_thread
} // namespace boost

#endif /* _OXT_SYSTEM_CALLS_HPP_ */

<|endoftext|>


<commit_before>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#ifndef TEST_HPP
#define TEST_HPP

#include <boost/config.hpp>
#include <exception>
#include <sstream>

#include "libtorrent/config.hpp"

#ifdef TORRENT_BUILDING_TEST_SHARED
#define EXPORT BOOST_SYMBOL_EXPORT
#else
#define EXPORT BOOST_SYMBOL_IMPORT
#endif

// the unit tests need access to these.
// they are built into the unit test library as well.
// not exported from libtorrent itself
extern "C"
{
	int TORRENT_EXPORT ed25519_create_seed(unsigned char *seed);
	void TORRENT_EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
	void TORRENT_EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
	int TORRENT_EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key);
	void TORRENT_EXPORT ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
	void TORRENT_EXPORT ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
}

void EXPORT report_failure(char const* err, char const* file, int line);

#if defined(_MSC_VER)
#define COUNTER_GUARD(x)
#else
#define COUNTER_GUARD(type) \
    struct BOOST_PP_CAT(type, _counter_guard) \
    { \
        ~BOOST_PP_CAT(type, _counter_guard()) \
        { \
            TEST_CHECK(counted_type<type>::count == 0); \
        } \
    } BOOST_PP_CAT(type, _guard)
#endif

#define TEST_REPORT_AUX(x, line, file) \
	report_failure(x, line, file)

#ifdef BOOST_NO_EXCEPTIONS
#define TEST_CHECK(x) \
	if (!(x)) \
		TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__);
#define TEST_EQUAL(x, y) \
	if (x != y) { \
		std::stringstream s__; \
		s__ << "TEST_EQUAL_ERROR:\n" #x ": " << x << "\nexpected: " << y << std::endl; \
		TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
	}
#else
#define TEST_CHECK(x) \
	try \
	{ \
		if (!(x)) \
			TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__); \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#define TEST_EQUAL(x, y) \
	try { \
		if (x != y) { \
			std::stringstream s__; \
			s__ << "TEST_EQUAL_ERROR: " #x ": " << x << " expected: " << y << std::endl; \
			TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
		} \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}
#endif

#define TEST_ERROR(x) \
	TEST_REPORT_AUX((std::string("ERROR: \"") + x + "\"").c_str(), __FILE__, __LINE__)

#define TEST_NOTHROW(x) \
	try \
	{ \
		x; \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#endif // TEST_HPP

<commit_msg>use export macro from test<commit_after>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#ifndef TEST_HPP
#define TEST_HPP

#include <boost/config.hpp>
#include <exception>
#include <sstream>

#include "libtorrent/config.hpp"

#ifdef TORRENT_BUILDING_TEST_SHARED
#define EXPORT BOOST_SYMBOL_EXPORT
#else
#define EXPORT BOOST_SYMBOL_IMPORT
#endif

// the unit tests need access to these.
// they are built into the unit test library as well.
// not exported from libtorrent itself
extern "C"
{
	int EXPORT ed25519_create_seed(unsigned char *seed);
	void EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
	void EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
	int EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key);
	void EXPORT ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
	void EXPORT ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
}

void EXPORT report_failure(char const* err, char const* file, int line);

#if defined(_MSC_VER)
#define COUNTER_GUARD(x)
#else
#define COUNTER_GUARD(type) \
    struct BOOST_PP_CAT(type, _counter_guard) \
    { \
        ~BOOST_PP_CAT(type, _counter_guard()) \
        { \
            TEST_CHECK(counted_type<type>::count == 0); \
        } \
    } BOOST_PP_CAT(type, _guard)
#endif

#define TEST_REPORT_AUX(x, line, file) \
	report_failure(x, line, file)

#ifdef BOOST_NO_EXCEPTIONS
#define TEST_CHECK(x) \
	if (!(x)) \
		TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__);
#define TEST_EQUAL(x, y) \
	if (x != y) { \
		std::stringstream s__; \
		s__ << "TEST_EQUAL_ERROR:\n" #x ": " << x << "\nexpected: " << y << std::endl; \
		TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
	}
#else
#define TEST_CHECK(x) \
	try \
	{ \
		if (!(x)) \
			TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__); \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#define TEST_EQUAL(x, y) \
	try { \
		if (x != y) { \
			std::stringstream s__; \
			s__ << "TEST_EQUAL_ERROR: " #x ": " << x << " expected: " << y << std::endl; \
			TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
		} \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}
#endif

#define TEST_ERROR(x) \
	TEST_REPORT_AUX((std::string("ERROR: \"") + x + "\"").c_str(), __FILE__, __LINE__)

#define TEST_NOTHROW(x) \
	try \
	{ \
		x; \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#endif // TEST_HPP

<|endoftext|>