<commit_before>#define BOOST_TEST_MODULE TemporaryTerminal
#include <boost/test/unit_test.hpp>
#include <vexcl/vector.hpp>
#include <vexcl/multivector.hpp>
#include <vexcl/temporary.hpp>
#include <vexcl/reductor.hpp>
#include "context_setup.hpp"

BOOST_AUTO_TEST_CASE(temporary)
{
    const size_t n = 1024;

    vex::vector<double> x(ctx, random_vector<double>(n));
    vex::vector<double> y(ctx, n);

    VEX_FUNCTION(sqr, double(double), "return prm1 * prm1;");

    auto s = vex::make_temp<double>( sqr(x) + 25 );
    y = s * (x + s);

    check_sample(y, [&](size_t idx, double v) {
            double X = x[idx];
            double S = X * X + 25;
            BOOST_CHECK_CLOSE(v, S * (X + S), 1e-8);
            });
}

BOOST_AUTO_TEST_CASE(nested_temporary)
{
    const size_t n = 1024;

    vex::vector<double> x(ctx, random_vector<double>(n));
    vex::vector<double> y(ctx, n);

    auto t1 = vex::make_temp<double, 1>( log(x) );
    auto t2 = vex::make_temp<double, 2>( t1 + sin(x) );

    y = t1 * t2;

    check_sample(y, [&](size_t idx, double v) {
            double X = x[idx];
            double T1 = log(X);
            double T2 = T1 + sin(X);
            BOOST_CHECK_CLOSE(v, T1 * T2, 1e-8);
            });
}

BOOST_AUTO_TEST_CASE(reduce_temporary)
{
    const size_t n = 1024;

    vex::vector<double> x(ctx, random_vector<double>(n));

    auto t1 = vex::make_temp<double, 1>( pow(sin(x), 2) );
    auto t2 = vex::make_temp<double, 2>( pow(cos(x), 2) );

    vex::Reductor<double, vex::SUM> sum(ctx);

    BOOST_CHECK_CLOSE(sum(10 * (t1 + t2)), 10.0 * n, 1e-6);
}

BOOST_AUTO_TEST_CASE(multiexpression_temporary)
{
    typedef std::array<double, 2> elem_t;
    const size_t n = 1024;

    vex::vector<double> x(ctx, random_vector<double>(n));

    vex::multivector<double, 2> y(ctx,n);

    auto tmp = vex::make_temp<double>( sin(x) );

    y = std::tie(tmp, sqrt(1 - tmp * tmp));

    check_sample(y, [&](size_t idx, elem_t v){
            double X = x[idx];
            BOOST_CHECK_CLOSE(v[0], sin(X), 1e-8);
            BOOST_CHECK_CLOSE(v[1], cos(X), 1e-8);
            });
}

#if BOOST_VERSION >= 105000
BOOST_AUTO_TEST_CASE(multivector_temporary)
{
    typedef std::array<double, 2> elem_t;
    const size_t n = 1024;

    vex::multivector<double, 2> x(ctx, random_vector<double>(2 * n));
    vex::multivector<double, 2> y(ctx,n);

    auto tmp = vex::make_temp<double>( tan(x) );

    y = tmp * tmp;

    check_sample(y, [&](size_t idx, elem_t v){
            elem_t X = x[idx];

            BOOST_CHECK_CLOSE(v[0], pow(tan(X[0]), 2.0), 1e-8);
            BOOST_CHECK_CLOSE(v[1], pow(tan(X[1]), 2.0), 1e-8);
            });
}
#endif

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>Temporary multivector expressions work with boost v1.52 and above<commit_after>#define BOOST_TEST_MODULE TemporaryTerminal
#include <boost/test/unit_test.hpp>
#include <vexcl/vector.hpp>
#include <vexcl/multivector.hpp>
#include <vexcl/temporary.hpp>
#include <vexcl/reductor.hpp>
#include "context_setup.hpp"

BOOST_AUTO_TEST_CASE(temporary)
{
    const size_t n = 1024;

    vex::vector<double> x(ctx, random_vector<double>(n));
    vex::vector<double> y(ctx, n);

    VEX_FUNCTION(sqr, double(double), "return prm1 * prm1;");

    auto s = vex::make_temp<double>( sqr(x) + 25 );
    y = s * (x + s);

    check_sample(y, [&](size_t idx, double v) {
            double X = x[idx];
            double S = X * X + 25;
            BOOST_CHECK_CLOSE(v, S * (X + S), 1e-8);
            });
}

BOOST_AUTO_TEST_CASE(nested_temporary)
{
    const size_t n = 1024;

    vex::vector<double> x(ctx, random_vector<double>(n));
    vex::vector<double> y(ctx, n);

    auto t1 = vex::make_temp<double, 1>( log(x) );
    auto t2 = vex::make_temp<double, 2>( t1 + sin(x) );

    y = t1 * t2;

    check_sample(y, [&](size_t idx, double v) {
            double X = x[idx];
            double T1 = log(X);
            double T2 = T1 + sin(X);
            BOOST_CHECK_CLOSE(v, T1 * T2, 1e-8);
            });
}

BOOST_AUTO_TEST_CASE(reduce_temporary)
{
    const size_t n = 1024;

    vex::vector<double> x(ctx, random_vector<double>(n));

    auto t1 = vex::make_temp<double, 1>( pow(sin(x), 2) );
    auto t2 = vex::make_temp<double, 2>( pow(cos(x), 2) );

    vex::Reductor<double, vex::SUM> sum(ctx);

    BOOST_CHECK_CLOSE(sum(10 * (t1 + t2)), 10.0 * n, 1e-6);
}

BOOST_AUTO_TEST_CASE(multiexpression_temporary)
{
    typedef std::array<double, 2> elem_t;
    const size_t n = 1024;

    vex::vector<double> x(ctx, random_vector<double>(n));

    vex::multivector<double, 2> y(ctx,n);

    auto tmp = vex::make_temp<double>( sin(x) );

    y = std::tie(tmp, sqrt(1 - tmp * tmp));

    check_sample(y, [&](size_t idx, elem_t v){
            double X = x[idx];
            BOOST_CHECK_CLOSE(v[0], sin(X), 1e-8);
            BOOST_CHECK_CLOSE(v[1], cos(X), 1e-8);
            });
}

#if BOOST_VERSION >= 105200
BOOST_AUTO_TEST_CASE(multivector_temporary)
{
    typedef std::array<double, 2> elem_t;
    const size_t n = 1024;

    vex::multivector<double, 2> x(ctx, random_vector<double>(2 * n));
    vex::multivector<double, 2> y(ctx,n);

    auto tmp = vex::make_temp<double>( tan(x) );

    y = tmp * tmp;

    check_sample(y, [&](size_t idx, elem_t v){
            elem_t X = x[idx];

            BOOST_CHECK_CLOSE(v[0], pow(tan(X[0]), 2.0), 1e-8);
            BOOST_CHECK_CLOSE(v[1], pow(tan(X[1]), 2.0), 1e-8);
            });
}
#endif

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>/*  Sirikata Utilities -- Sirikata Utilities
 *  Factory.hpp
 *
 *  Copyright (c) 2009, Daniel Reiter Horn
 *  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 Sirikata 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 _SIRIKATA_FACTORY_HPP_
#define _SIRIKATA_FACTORY_HPP_

namespace Sirikata {

class FactoryMissingConstructorException : public std::exception {
public:
    FactoryMissingConstructorException(const String& _name)
     : name(_name),
       what_msg(new String())
    {}
    virtual ~FactoryMissingConstructorException() throw() {
        delete what_msg;
    }

    char const* what() const throw() {
        if (what_msg->empty())
            (*what_msg) = "Factory missing constructor: " + name + " not registered in the factory.";
        return what_msg->c_str();
    }
private:
    const String name;
    String* what_msg;
};

template<class T, class Ftype>
class FactoryImpl {

    typedef std::tr1::unordered_map<String,Ftype> ConstructorMap;
    ConstructorMap mConstructors;
    template <class U> static U* noop(U*) {
        return NULL;
    }
    template <class U> static U noop(const U&) {
        return U();
    }
    static T staticNoop() {
        T temp=T();
        return noop(temp);
    }
    Ftype mNoop;
    String mDefault;
public:
	FactoryImpl():mNoop(std::tr1::bind(&FactoryImpl<T,Ftype>::staticNoop)){}
    bool unregisterConstructor(const String& name) {

        typename ConstructorMap::iterator where=mConstructors.find(name);
        if (where==mConstructors.end())
            return false;
        mConstructors.erase(where);
        if (mDefault==name) {
            mDefault=String();
        }
        return true;
    }
    bool registerConstructor(const String& name,
                             const Ftype &constructor,
                             bool isDefault=false) {
        if (mConstructors.find(name)!=mConstructors.end())
            return false;
        mConstructors[name]=constructor;
        if (isDefault) {
            mDefault=name;
        }
        return true;
    }
    const String& getDefault() const {
        return mDefault;
    }
    bool hasConstructor(const String&name)const {
        return mConstructors.find(name) != mConstructors.end();
    }
    typedef std::list<String> ConstructorNameList;
    ConstructorNameList getNames() const {
        ConstructorNameList result;
        for(typename ConstructorMap::const_iterator it = mConstructors.begin(); it != mConstructors.end(); it++)
            result.push_back(it->first);
        return result;
    }

    const Ftype &getConstructorOrDefault(const String&name)const{
        typename ConstructorMap::const_iterator where=mConstructors.find(name);
        if (where==mConstructors.end()) {
            if (name.length()==0&&mDefault.length()) {
                return getConstructor(mDefault);
            }
            return mNoop;
        }
        return where->second;
    }

    // Gets a specific constructor and throws a
    // FactoryMissingConstructorException if it can't be found
    const Ftype& getConstructor(const String&name) const {
        if (!hasConstructor(name))
            throw FactoryMissingConstructorException(name);
        return getConstructorOrDefault(name);
    }

    const Ftype& getDefaultConstructor()const{
        return getConstructor(mDefault);
    }
};

template <class T>class Factory:public FactoryImpl<T,std::tr1::function<T()> >{};

template <class T, typename A>class Factory1:public FactoryImpl<T,std::tr1::function<T(A)> >{};

template <class T, typename A, typename B>class Factory2:public FactoryImpl<T,std::tr1::function<T(A,B)> >{};

template <class T, typename A, typename B, typename C>class Factory3:public FactoryImpl<T,std::tr1::function<T(A,B,C)> >{};

template <class T, typename A, typename B, typename C, typename D>class Factory4:public FactoryImpl<T,std::tr1::function<T(A,B,C,D)> >{};

template <class T, typename A, typename B, typename C, typename D, typename E>class Factory5:public FactoryImpl<T,std::tr1::function<T(A,B,C,D,E)> >{};

template <class T, typename A, typename B, typename C, typename D, typename E, typename F>class Factory6:public FactoryImpl<T,std::tr1::function<T(A,B,C,D,E,F)> >{};

}
#endif
<commit_msg>Fix FactoryMissingConstructorException copy constructor.<commit_after>/*  Sirikata Utilities -- Sirikata Utilities
 *  Factory.hpp
 *
 *  Copyright (c) 2009, Daniel Reiter Horn
 *  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 Sirikata 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 _SIRIKATA_FACTORY_HPP_
#define _SIRIKATA_FACTORY_HPP_

namespace Sirikata {

class FactoryMissingConstructorException : public std::exception {
public:
    FactoryMissingConstructorException(const String& _name)
     : name(_name),
       what_msg(new String())
    {}
    FactoryMissingConstructorException(const FactoryMissingConstructorException& rhs)
     : name(rhs.name),
       what_msg(new String(*(rhs.what_msg)))
    {}
    virtual ~FactoryMissingConstructorException() throw() {
        delete what_msg;
    }

    char const* what() const throw() {
        if (what_msg->empty())
            (*what_msg) = "Factory missing constructor: " + name + " not registered in the factory.";
        return what_msg->c_str();
    }
private:
    const String name;
    String* what_msg;
};

template<class T, class Ftype>
class FactoryImpl {

    typedef std::tr1::unordered_map<String,Ftype> ConstructorMap;
    ConstructorMap mConstructors;
    template <class U> static U* noop(U*) {
        return NULL;
    }
    template <class U> static U noop(const U&) {
        return U();
    }
    static T staticNoop() {
        T temp=T();
        return noop(temp);
    }
    Ftype mNoop;
    String mDefault;
public:
	FactoryImpl():mNoop(std::tr1::bind(&FactoryImpl<T,Ftype>::staticNoop)){}
    bool unregisterConstructor(const String& name) {

        typename ConstructorMap::iterator where=mConstructors.find(name);
        if (where==mConstructors.end())
            return false;
        mConstructors.erase(where);
        if (mDefault==name) {
            mDefault=String();
        }
        return true;
    }
    bool registerConstructor(const String& name,
                             const Ftype &constructor,
                             bool isDefault=false) {
        if (mConstructors.find(name)!=mConstructors.end())
            return false;
        mConstructors[name]=constructor;
        if (isDefault) {
            mDefault=name;
        }
        return true;
    }
    const String& getDefault() const {
        return mDefault;
    }
    bool hasConstructor(const String&name)const {
        return mConstructors.find(name) != mConstructors.end();
    }
    typedef std::list<String> ConstructorNameList;
    ConstructorNameList getNames() const {
        ConstructorNameList result;
        for(typename ConstructorMap::const_iterator it = mConstructors.begin(); it != mConstructors.end(); it++)
            result.push_back(it->first);
        return result;
    }

    const Ftype &getConstructorOrDefault(const String&name)const{
        typename ConstructorMap::const_iterator where=mConstructors.find(name);
        if (where==mConstructors.end()) {
            if (name.length()==0&&mDefault.length()) {
                return getConstructor(mDefault);
            }
            return mNoop;
        }
        return where->second;
    }

    // Gets a specific constructor and throws a
    // FactoryMissingConstructorException if it can't be found
    const Ftype& getConstructor(const String&name) const {
        if (!hasConstructor(name))
            throw FactoryMissingConstructorException(name);
        return getConstructorOrDefault(name);
    }

    const Ftype& getDefaultConstructor()const{
        return getConstructor(mDefault);
    }
};

template <class T>class Factory:public FactoryImpl<T,std::tr1::function<T()> >{};

template <class T, typename A>class Factory1:public FactoryImpl<T,std::tr1::function<T(A)> >{};

template <class T, typename A, typename B>class Factory2:public FactoryImpl<T,std::tr1::function<T(A,B)> >{};

template <class T, typename A, typename B, typename C>class Factory3:public FactoryImpl<T,std::tr1::function<T(A,B,C)> >{};

template <class T, typename A, typename B, typename C, typename D>class Factory4:public FactoryImpl<T,std::tr1::function<T(A,B,C,D)> >{};

template <class T, typename A, typename B, typename C, typename D, typename E>class Factory5:public FactoryImpl<T,std::tr1::function<T(A,B,C,D,E)> >{};

template <class T, typename A, typename B, typename C, typename D, typename E, typename F>class Factory6:public FactoryImpl<T,std::tr1::function<T(A,B,C,D,E,F)> >{};

}
#endif
<|endoftext|>


<commit_before>/*
* Copyright (C) 2015 German Aerospace Center (DLR/SC)
*
* Created: 2013-03-27 Martin Siggel <Martin.Siggel@dlr.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "test.h" // Brings in the GTest framework
#include "tixi.h"

TEST(Bugs,cdatatext_segfault)
{
  TixiDocumentHandle handle;
  ReturnCode ret = tixiOpenDocument("TestData/bug_segfault.xml", &handle);
  ASSERT_EQ(SUCCESS, ret);

  char* text = NULL;
  int nChilds = 0;

  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/Assembly", &text));

  tixiGetNumberOfChilds(handle, "/Assembly/BodySkeleton[1]/BodyFrame[1]", &nChilds);
  ASSERT_EQ(1, nChilds);

  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/Assembly/BodySkeleton[1]/BodyFrame[1]", &text));

  // this query segfaultet due to its cdata section
  ASSERT_EQ(SUCCESS, tixiGetChildNodeName(handle, "/Assembly/BodySkeleton[1]/BodyFrame[1]", 1, &text));
  ASSERT_STREQ("#cdata-section", text);

}

// tests, if an empty text element can be updated
TEST(Bugs, empty_textelement)
{
  TixiDocumentHandle handle;
  ASSERT_EQ(SUCCESS, tixiCreateDocument("Root", &handle));

  // the first test always worked... creating empty text element
  ASSERT_EQ(SUCCESS, tixiAddTextElement(handle, "/Root", "TextEl1", ""));
  ASSERT_EQ(SUCCESS, tixiUpdateTextElement(handle, "/Root/TextEl1", "mytext1"));

  char* text = NULL;
  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/Root/TextEl1", &text));
  ASSERT_STREQ("mytext1", text);

  // the second test does not create a text element, but an empty node
  ASSERT_EQ(SUCCESS, tixiCreateElement(handle, "/Root", "TextEl2"));
  ASSERT_EQ(SUCCESS, tixiUpdateTextElement(handle, "/Root/TextEl2", "mytext2"));

  // here the test failed due to wrong implementation of tixiUpdateTextElement
  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/Root/TextEl2", &text));
  ASSERT_STREQ("mytext2", text);
}

extern "C" void printMsg(MessageType type, const char* message, ...);

TEST(Bugs, printMessageCrash)
{
    char msg[3000];
    for (int i = 0; i < 3000; ++i) {
        msg[i] = 'a';
    }
    msg[2999] = '\0';

    printMsg(MESSAGETYPE_ERROR, "%s", msg);
}
<commit_msg>Add failing tests for a text element with XML comments<commit_after>/*
* Copyright (C) 2015 German Aerospace Center (DLR/SC)
*
* Created: 2013-03-27 Martin Siggel <Martin.Siggel@dlr.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "test.h" // Brings in the GTest framework
#include "tixi.h"

TEST(Bugs,cdatatext_segfault)
{
  TixiDocumentHandle handle;
  ReturnCode ret = tixiOpenDocument("TestData/bug_segfault.xml", &handle);
  ASSERT_EQ(SUCCESS, ret);

  char* text = NULL;
  int nChilds = 0;

  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/Assembly", &text));

  tixiGetNumberOfChilds(handle, "/Assembly/BodySkeleton[1]/BodyFrame[1]", &nChilds);
  ASSERT_EQ(1, nChilds);

  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/Assembly/BodySkeleton[1]/BodyFrame[1]", &text));

  // this query segfaultet due to its cdata section
  ASSERT_EQ(SUCCESS, tixiGetChildNodeName(handle, "/Assembly/BodySkeleton[1]/BodyFrame[1]", 1, &text));
  ASSERT_STREQ("#cdata-section", text);

}

// tests, if an empty text element can be updated
TEST(Bugs, empty_textelement)
{
  TixiDocumentHandle handle;
  ASSERT_EQ(SUCCESS, tixiCreateDocument("Root", &handle));

  // the first test always worked... creating empty text element
  ASSERT_EQ(SUCCESS, tixiAddTextElement(handle, "/Root", "TextEl1", ""));
  ASSERT_EQ(SUCCESS, tixiUpdateTextElement(handle, "/Root/TextEl1", "mytext1"));

  char* text = NULL;
  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/Root/TextEl1", &text));
  ASSERT_STREQ("mytext1", text);

  // the second test does not create a text element, but an empty node
  ASSERT_EQ(SUCCESS, tixiCreateElement(handle, "/Root", "TextEl2"));
  ASSERT_EQ(SUCCESS, tixiUpdateTextElement(handle, "/Root/TextEl2", "mytext2"));

  // here the test failed due to wrong implementation of tixiUpdateTextElement
  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/Root/TextEl2", &text));
  ASSERT_STREQ("mytext2", text);
}

// tests, if updating a text element that contains comments (ignored by GetText) does not prepend to existing text
TEST(Bugs, textelement_with_comment_in_the_middle)
{
  const char* s = "<?xml version=\"1.0\"?><root><elem>text_before <!-- comment_text --> text_after</elem></root>";
  TixiDocumentHandle handle;
  ASSERT_EQ(SUCCESS, tixiImportFromString(s, &handle));

  char* text = NULL;
  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/root/elem", &text));
  ASSERT_STREQ("text_before  text_after", text);

  ASSERT_EQ(FAILED, tixiUpdateTextElement(handle, "/root/elem", "new text"));

  /*
  // this could also be desirable behavior but the documentation currently states that this should not work!
  ASSERT_EQ(SUCCESS, tixiUpdateTextElement(handle, "/root/elem", "new text"));

  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/root/elem", &text));
  ASSERT_STREQ("new text", text);
  */

  tixiCloseDocument(handle);
}

TEST(Bugs, textelement_before_comment)
{
  const char* s = "<?xml version=\"1.0\"?><root><elem>some_text <!-- comment_text --></elem></root>";
  TixiDocumentHandle handle;
  ASSERT_EQ(SUCCESS, tixiImportFromString(s, &handle));

  char* text = NULL;
  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/root/elem", &text));
  ASSERT_STREQ("some_text ", text);

  ASSERT_EQ(FAILED, tixiUpdateTextElement(handle, "/root/elem", "new text"));

  /*
  // this could also be desirable behavior but the documentation currently states that this should not work!
  ASSERT_EQ(SUCCESS, tixiUpdateTextElement(handle, "/root/elem", "new text"));

  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/root/elem", &text));
  ASSERT_STREQ("new text", text);
  */

  tixiCloseDocument(handle);
}

TEST(Bugs, textelement_after_comment)
{
  const char* s = "<?xml version=\"1.0\"?><root><elem><!-- comment_text --> text_after</elem></root>";
  TixiDocumentHandle handle;
  ASSERT_EQ(SUCCESS, tixiImportFromString(s, &handle));

  char* text = NULL;
  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/root/elem", &text));
  ASSERT_STREQ(" text_after", text);

  ASSERT_EQ(FAILED, tixiUpdateTextElement(handle, "/root/elem", "new text"));

  /*
  // this could also be desirable behavior but the documentation currently states that this should not work!
  ASSERT_EQ(SUCCESS, tixiUpdateTextElement(handle, "/root/elem", "new text"));

  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/root/elem", &text));
  ASSERT_STREQ("new text", text);
  */

  tixiCloseDocument(handle);
}

// directly access the 'text()' of an element (should behave the same for GetText and UpdateText)
TEST(Bugs, textelement_directly_access_text)
{
  const char* s = "<?xml version=\"1.0\"?><root><elem>some text</elem></root>";
  TixiDocumentHandle handle;
  ASSERT_EQ(SUCCESS, tixiImportFromString(s, &handle));

  char* text = NULL;
  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/root/elem/text()", &text));
  ASSERT_STREQ("some text", text);

  ASSERT_EQ(NOT_AN_ELEMENT, tixiUpdateTextElement(handle, "/root/elem/text()", "new text"));

  /*
  // this could also be desirable behavior but the documentation currently states that this should not work!
  ASSERT_EQ(SUCCESS, tixiUpdateTextElement(handle, "/root/elem/text()", "new text"));

  ASSERT_EQ(SUCCESS, tixiGetTextElement(handle, "/root/elem/text()", &text));
  ASSERT_STREQ("new text", text);
  */

  tixiCloseDocument(handle);
}

extern "C" void printMsg(MessageType type, const char* message, ...);

TEST(Bugs, printMessageCrash)
{
    char msg[3000];
    for (int i = 0; i < 3000; ++i) {
        msg[i] = 'a';
    }
    msg[2999] = '\0';

    printMsg(MESSAGETYPE_ERROR, "%s", msg);
}
<|endoftext|>


<commit_before>#include <isl/set.h>
#include <isl/union_map.h>
#include <isl/union_set.h>
#include <isl/ast_build.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>

#include <coli/debug.h>
#include <coli/core.h>

#include <String.h>
#include <Halide.h>

int main(int argc, char **argv)
{
	isl_ctx *ctx = isl_ctx_alloc();
	IRProgram pgm("program0");
	IRFunction fct("function0", &pgm);

	Computation computation0(ctx, Halide::Expr(3), "{S0[i,j]: 0<=i<=1000 and 0<=j<=1000}", &fct);
/*	Computation computation1(ctx, Halide::Expr(5), "{S1[i,j]: 0<=i<=1023 and 0<=j<=1023}", &fct);
	Computation computation2(ctx, Halide::Expr(7), "{S2[i,j]: 0<=i<=1023 and 0<=j<=1023}", &fct);*/
//	Computation computation0(ctx, Halide::Expr(3), "{S0[0, 0]}", &fct);

	// Mapping to memory buffers
	Halide::Buffer buf(Halide::Int(32), 10, 10, 0, 0, NULL, "buf");
	fct.buffers_list.insert(std::pair<std::string, Halide::Buffer *>(buf.name(), &buf));
	computation0.SetAccess("{S0[i,j]->buf[i, j]}");
/*	computation1.SetAccess("{S1[i,j]->buf[0]}");
	computation2.SetAccess("{S2[i,j]->buf[0]}");*/

	// Schedule
	computation0.Tile(0,1,32,32);
/*	computation1.Schedule("{S1[i,j]->[1,i1,j1,i2,j3,j4]: i1=floor(i/32) and j1=floor(j/32) and i2=i and j3=floor(j/4) and j4=j%4 and 0<=i<=1023 and 0<=j<=1023}");
	computation2.Split(0, 32);
	computation2.Split(2, 32);
	computation2.Interchange(1, 2);
	pgm.tag_parallel_dimension("S0", 1);
	pgm.tag_vector_dimension("S1", 5);
*/
	isl_union_map *schedule_map = pgm.get_schedule_map();

	// Create time space IR
	isl_union_set *time_space = coli_create_time_space(isl_union_set_copy(pgm.get_iteration_spaces()), isl_union_map_copy(schedule_map));

	// Generate code
	isl_ast_build *ast_build = isl_ast_build_alloc(ctx);
	isl_options_set_ast_build_atomic_upper_bound(ctx, 1);
	ast_build = isl_ast_build_set_after_each_for(ast_build, &for_halide_code_generator_after_for, NULL);
	ast_build = isl_ast_build_set_at_each_domain(ast_build, &stmt_halide_code_generator, NULL);
	isl_ast_node *program = isl_ast_build_node_from_schedule_map(ast_build, isl_union_map_copy(schedule_map));
	isl_ast_build_free(ast_build);

	if (DEBUG)
		isl_ast_node_dump_c_code(ctx, program);

	std::vector<std::string> generated_stmts, iterators;
	Halide::Internal::Stmt halide_pgm = generate_Halide_stmt_from_isl_node(pgm, program, 0, generated_stmts, iterators);

	// Dump IRs
	pgm.dump_ISIR();
	pgm.dump_schedule();
	IF_DEBUG(coli_str_dump("\n\nTime Space IR:\n")); IF_DEBUG(isl_union_set_dump(time_space)); IF_DEBUG(coli_str_dump("\n\n"));
	halide_IR_dump(halide_pgm);

	Halide::Target target;
	target.os = Halide::Target::OSX;
	target.arch = Halide::Target::X86;
	target.bits = 64;
	std::vector<Halide::Target::Feature> x86_features;
	x86_features.push_back(Halide::Target::AVX);
	x86_features.push_back(Halide::Target::SSE41);
	target.set_features(x86_features);

	Halide::Argument buffer_arg("buf", Halide::Argument::OutputBuffer, Halide::Int(32), 2);
    	std::vector<Halide::Argument> args(1);
    	args[0] = buffer_arg;

	Halide::Module::Module m("test1", target);
	m.append(Halide::Internal::LoweredFunc("test1", args, halide_pgm, Halide::Internal::LoweredFunc::External));

	Halide::compile_module_to_object(m, "LLVM_generated_code.o");

	return 0;
}
<commit_msg>Add few computations to the test_coli<commit_after>#include <isl/set.h>
#include <isl/union_map.h>
#include <isl/union_set.h>
#include <isl/ast_build.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>

#include <coli/debug.h>
#include <coli/core.h>

#include <String.h>
#include <Halide.h>

int main(int argc, char **argv)
{
	isl_ctx *ctx = isl_ctx_alloc();
	IRProgram pgm("program0");
	IRFunction fct("function0", &pgm);

	Computation computation0(ctx, Halide::Expr(3), "{S0[i,j]: 0<=i<=1000 and 0<=j<=1000}", &fct);
	Computation computation1(ctx, Halide::Expr(5), "{S1[i,j]: 0<=i<=1023 and 0<=j<=1023}", &fct);
	Computation computation2(ctx, Halide::Expr(7), "{S2[i,j]: 0<=i<=1023 and 0<=j<=1023}", &fct);

	// Mapping to memory buffers
	Halide::Buffer buf(Halide::Int(32), 10, 10, 0, 0, NULL, "buf");
	fct.buffers_list.insert(std::pair<std::string, Halide::Buffer *>(buf.name(), &buf));
	computation0.SetAccess("{S0[i,j]->buf[i, j]}");
	computation1.SetAccess("{S1[i,j]->buf[0, 0]}");
	computation2.SetAccess("{S2[i,j]->buf[0, 0]}");

	// Schedule
	computation0.Tile(0,1,32,32);
	computation1.Schedule("{S1[i,j]->[1,i1,j1,i2,j3,j4]: i1=floor(i/32) and j1=floor(j/32) and i2=i and j3=floor(j/4) and j4=j%4 and 0<=i<=1023 and 0<=j<=1023}");
	computation2.Split(0, 32);
	computation2.Split(2, 32);
	computation2.Interchange(1, 2);
	pgm.tag_parallel_dimension("S0", 1);
//	pgm.tag_vector_dimension("S1", 5);

	isl_union_map *schedule_map = pgm.get_schedule_map();

	// Create time space IR
	isl_union_set *time_space = coli_create_time_space(isl_union_set_copy(pgm.get_iteration_spaces()), isl_union_map_copy(schedule_map));

	// Generate code
	isl_ast_build *ast_build = isl_ast_build_alloc(ctx);
	isl_options_set_ast_build_atomic_upper_bound(ctx, 1);
	ast_build = isl_ast_build_set_after_each_for(ast_build, &for_halide_code_generator_after_for, NULL);
	ast_build = isl_ast_build_set_at_each_domain(ast_build, &stmt_halide_code_generator, NULL);
	isl_ast_node *program = isl_ast_build_node_from_schedule_map(ast_build, isl_union_map_copy(schedule_map));
	isl_ast_build_free(ast_build);

	if (DEBUG)
		isl_ast_node_dump_c_code(ctx, program);

	std::vector<std::string> generated_stmts, iterators;
	Halide::Internal::Stmt halide_pgm = generate_Halide_stmt_from_isl_node(pgm, program, 0, generated_stmts, iterators);

	// Dump IRs
	pgm.dump_ISIR();
	pgm.dump_schedule();
	IF_DEBUG(coli_str_dump("\n\nTime Space IR:\n")); IF_DEBUG(isl_union_set_dump(time_space)); IF_DEBUG(coli_str_dump("\n\n"));
	halide_IR_dump(halide_pgm);

	Halide::Target target;
	target.os = Halide::Target::OSX;
	target.arch = Halide::Target::X86;
	target.bits = 64;
	std::vector<Halide::Target::Feature> x86_features;
	x86_features.push_back(Halide::Target::AVX);
	x86_features.push_back(Halide::Target::SSE41);
	target.set_features(x86_features);

	Halide::Argument buffer_arg("buf", Halide::Argument::OutputBuffer, Halide::Int(32), 2);
    	std::vector<Halide::Argument> args(1);
    	args[0] = buffer_arg;

	Halide::Module::Module m("test1", target);
	m.append(Halide::Internal::LoweredFunc("test1", args, halide_pgm, Halide::Internal::LoweredFunc::External));

	Halide::compile_module_to_object(m, "LLVM_generated_code.o");

	return 0;
}
<|endoftext|>


<commit_before>/* Copyright (C) 2015 Martin Albrecht

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

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

#include <cstring>
#include <hlll.h>
#include <householder.h>
#include <test_utils.h>

using namespace std;
using namespace fplll;

#ifndef TESTDATADIR
#define TESTDATADIR ".."
#endif

template <class ZT, class FT> int test_lll(ZZ_mat<ZT> &A, int flags, int prec = 53)
{
  MatHouseholder<Z_NR<ZT>, FP_NR<FT>> Mhouseholder(A, flags);
  HouseholderLLLReduction<Z_NR<ZT>, FP_NR<FT>> hlll_obj(Mhouseholder, 0.99, 0.52, 0.01);
  hlll_obj.lll();
  MatHouseholder<Z_NR<ZT>, FP_NR<double>> M(A, flags);
  int status = is_hlll_reduced<Z_NR<ZT>, FP_NR<double>>(M, 0.99, 0.52);

  if (status == 0)
    cerr << "Output of HLLL reduction is not HLLL reduced." << endl;

  return (status == 0);
}

/**
   @brief Test HLLL for matrix stored in file pointed to by `input_filename`.

   @param input_filename   a path
   @param flags            flags to use

   @return zero on success
*/

template <class ZT, class FT> int test_filename(const char *input_filename, int flags)
{
  ZZ_mat<ZT> A;
  int status = 0;
  status |= read_matrix(A, input_filename);
  status |= test_lll<ZT, FT>(A, flags);
  return status;
}

/**
   @brief Construct d × (d+1) integer relations matrix with bit size b and test LLL.

   @param d                dimension
   @param b                bit size
   @param method           LLL method to test
   @param float_type       floating point type to test
   @param flags            flags to use
   @param prec             precision used for is_lll_reduced

   @return zero on success
*/

int main(int /*argc*/, char ** /*argv*/)
{

  int status = 0;

  status |=
      test_filename<mpz_t, double>(TESTDATADIR "/tests/lattices/dim55_in", HOUSEHOLDER_DEFAULT);
#ifdef FPLLL_WITH_LONG_DOUBLE
  status |= test_filename<mpz_t, long double>(TESTDATADIR "/tests/lattices/dim55_in",
                                              HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_LONG_DOUBLE
#ifdef FPLLL_WITH_DPE
  status |=
      test_filename<mpz_t, dpe_t>(TESTDATADIR "/tests/lattices/dim55_in", HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_DPE
#ifdef FPLLL_WITH_QD
  status |=
      test_filename<mpz_t, qd_real>(TESTDATADIR "/tests/lattices/dim55_in", HOUSEHOLDER_DEFAULT);
  status |=
      test_filename<mpz_t, dd_real>(TESTDATADIR "/tests/lattices/dim55_in", HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_QD
// status |= test_filename<mpz_t, mpfr_t>(TESTDATADIR "/tests/lattices/dim55_in",
// HOUSEHOLDER_DEFAULT);

#if 0
  status |= test_filename<mpz_t, double>(TESTDATADIR "/tests/lattices/example_in", HOUSEHOLDER_DEFAULT);
#ifdef FPLLL_WITH_LONG_DOUBLE
  status |= test_filename<mpz_t, long double>(TESTDATADIR "/tests/lattices/example_in", HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_LONG_DOUBLE
#ifdef FPLLL_WITH_DPE
  status |= test_filename<mpz_t, dpe_t>(TESTDATADIR "/tests/lattices/example_in", HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_DPE
#ifdef FPLLL_WITH_QD
  status |= test_filename<mpz_t, qd_real>(TESTDATADIR "/tests/lattices/example_in", HOUSEHOLDER_DEFAULT);
  status |= test_filename<mpz_t, dd_real>(TESTDATADIR "/tests/lattices/example_in", HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_QD
  //status |= test_filename<mpz_t, mpfr_t>(TESTDATADIR "/tests/lattices/example_in", HOUSEHOLDER_DEFAULT);
#endif  // 0

  if (status == 0)
  {
    cerr << "All tests passed." << endl;
    return 0;
  }
  else
  {
    return -1;
  }
}
<commit_msg>Add new tests for H-LLL.<commit_after>/* Copyright (C) 2015 Martin Albrecht

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

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

#include <cstring>
#include <hlll.h>
#include <householder.h>
#include <test_utils.h>

using namespace std;
using namespace fplll;

#ifndef TESTDATADIR
#define TESTDATADIR ".."
#endif

template <class ZT, class FT> int test_lll(ZZ_mat<ZT> &A, int flags, int prec = 53)
{
  MatHouseholder<Z_NR<ZT>, FP_NR<FT>> Mhouseholder(A, flags);
  HouseholderLLLReduction<Z_NR<ZT>, FP_NR<FT>> hlll_obj(Mhouseholder, 0.99, 0.52, 0.01);
  hlll_obj.lll();
  MatHouseholder<Z_NR<ZT>, FP_NR<double>> M(A, flags);
  int status = is_hlll_reduced<Z_NR<ZT>, FP_NR<double>>(M, 0.99, 0.52);

  if (status == 0)
    cerr << "Output of HLLL reduction is not HLLL reduced." << endl;

  return (status == 0);
}

/**
   @brief Test HLLL for matrix stored in file pointed to by `input_filename`.

   @param input_filename   a path
   @param flags            flags to use

   @return zero on success
*/

template <class ZT, class FT> int test_filename(const char *input_filename, int flags)
{
  ZZ_mat<ZT> A;
  int status = 0;
  status |= read_matrix(A, input_filename);
  status |= test_lll<ZT, FT>(A, flags);
  return status;
}

/**
   @brief Construct d × (d+1) integer relations matrix with bit size b and test LLL.

   @param d                dimension
   @param b                bit size
   @param method           LLL method to test
   @param float_type       floating point type to test
   @param flags            flags to use
   @param prec             precision used for is_lll_reduced

   @return zero on success
*/

int main(int /*argc*/, char ** /*argv*/)
{

  int status = 0;

  status |=
      test_filename<mpz_t, double>(TESTDATADIR "/tests/lattices/dim55_in", HOUSEHOLDER_DEFAULT);
#ifdef FPLLL_WITH_LONG_DOUBLE
  status |= test_filename<mpz_t, long double>(TESTDATADIR "/tests/lattices/dim55_in",
                                              HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_LONG_DOUBLE
#ifdef FPLLL_WITH_DPE
  status |=
      test_filename<mpz_t, dpe_t>(TESTDATADIR "/tests/lattices/dim55_in", HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_DPE
#ifdef FPLLL_WITH_QD
  status |=
      test_filename<mpz_t, qd_real>(TESTDATADIR "/tests/lattices/dim55_in", HOUSEHOLDER_DEFAULT);
  status |=
      test_filename<mpz_t, dd_real>(TESTDATADIR "/tests/lattices/dim55_in", HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_QD
        // status |= test_filename<mpz_t, mpfr_t>(TESTDATADIR "/tests/lattices/dim55_in",
        // HOUSEHOLDER_DEFAULT);

  status |= test_filename<mpz_t, double>(TESTDATADIR "/tests/lattices/example_cvp_in_lattice4",
                                         HOUSEHOLDER_DEFAULT);
#ifdef FPLLL_WITH_LONG_DOUBLE
  status |= test_filename<mpz_t, long double>(TESTDATADIR "/tests/lattices/example_cvp_in_lattice4",
                                              HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_LONG_DOUBLE
#ifdef FPLLL_WITH_DPE
  status |= test_filename<mpz_t, dpe_t>(TESTDATADIR "/tests/lattices/example_cvp_in_lattice4",
                                        HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_DPE
#ifdef FPLLL_WITH_QD
  status |= test_filename<mpz_t, qd_real>(TESTDATADIR "/tests/lattices/example_cvp_in_lattice4",
                                          HOUSEHOLDER_DEFAULT);
  status |= test_filename<mpz_t, dd_real>(TESTDATADIR "/tests/lattices/example_cvp_in_lattice4",
                                          HOUSEHOLDER_DEFAULT);
#endif  // FPLLL_WITH_QD
  // status |= test_filename<mpz_t, mpfr_t>(TESTDATADIR "/tests/lattices/example_cvp_in_lattice4",
  // HOUSEHOLDER_DEFAULT);

  if (status == 0)
  {
    cerr << "All tests passed." << endl;
    return 0;
  }
  else
  {
    return -1;
  }
}
<|endoftext|>


<commit_before>/*************************************************************************/
/*  test_main.cpp                                                        */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* 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.                */
/*************************************************************************/

#include "test_main.h"

#include "core/templates/list.h"

#include "test_astar.h"
#include "test_basis.h"
#include "test_class_db.h"
#include "test_color.h"
#include "test_command_queue.h"
#include "test_config_file.h"
#include "test_curve.h"
#include "test_expression.h"
#include "test_gradient.h"
#include "test_gui.h"
#include "test_list.h"
#include "test_math.h"
#include "test_method_bind.h"
#include "test_node_path.h"
#include "test_oa_hash_map.h"
#include "test_ordered_hash_map.h"
#include "test_pck_packer.h"
#include "test_physics_2d.h"
#include "test_physics_3d.h"
#include "test_render.h"
#include "test_shader_lang.h"
#include "test_string.h"
#include "test_validate_testing.h"
#include "test_variant.h"

#include "modules/modules_tests.gen.h"

#include "tests/test_macros.h"

int test_main(int argc, char *argv[]) {
	bool run_tests = true;

	// Convert arguments to Godot's command-line.
	List<String> args;

	for (int i = 0; i < argc; i++) {
		args.push_back(String::utf8(argv[i]));
	}
	OS::get_singleton()->set_cmdline("", args);

	// Run custom test tools.
	if (test_commands) {
		for (Map<String, TestFunc>::Element *E = test_commands->front(); E; E = E->next()) {
			if (args.find(E->key())) {
				const TestFunc &test_func = E->get();
				test_func();
				run_tests = false;
				break;
			}
		}
		if (!run_tests) {
			delete test_commands;
			return 0;
		}
	}
	// Doctest runner.
	doctest::Context test_context;
	List<String> test_args;

	// Clean arguments of "--test" from the args.
	for (int x = 0; x < argc; x++) {
		String arg = String(argv[x]);
		if (arg != "--test") {
			test_args.push_back(arg);
		}
	}
	// Convert Godot command line arguments back to standard arguments.
	char **doctest_args = new char *[test_args.size()];
	for (int x = 0; x < test_args.size(); x++) {
		// Operation to convert Godot string to non wchar string.
		CharString cs = test_args[x].utf8();
		const char *str = cs.get_data();
		// Allocate the string copy.
		doctest_args[x] = new char[strlen(str) + 1];
		// Copy this into memory.
		memcpy(doctest_args[x], str, strlen(str) + 1);
	}

	test_context.applyCommandLine(test_args.size(), doctest_args);

	test_context.setOption("order-by", "name");
	test_context.setOption("abort-after", 5);
	test_context.setOption("no-breaks", true);

	for (int x = 0; x < test_args.size(); x++) {
		delete[] doctest_args[x];
	}
	delete[] doctest_args;

	return test_context.run();
}
<commit_msg>doctest: Do not override command-line options<commit_after>/*************************************************************************/
/*  test_main.cpp                                                        */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* 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.                */
/*************************************************************************/

#include "test_main.h"

#include "core/templates/list.h"

#include "test_astar.h"
#include "test_basis.h"
#include "test_class_db.h"
#include "test_color.h"
#include "test_command_queue.h"
#include "test_config_file.h"
#include "test_curve.h"
#include "test_expression.h"
#include "test_gradient.h"
#include "test_gui.h"
#include "test_list.h"
#include "test_math.h"
#include "test_method_bind.h"
#include "test_node_path.h"
#include "test_oa_hash_map.h"
#include "test_ordered_hash_map.h"
#include "test_pck_packer.h"
#include "test_physics_2d.h"
#include "test_physics_3d.h"
#include "test_render.h"
#include "test_shader_lang.h"
#include "test_string.h"
#include "test_validate_testing.h"
#include "test_variant.h"

#include "modules/modules_tests.gen.h"

#include "tests/test_macros.h"

int test_main(int argc, char *argv[]) {
	bool run_tests = true;

	// Convert arguments to Godot's command-line.
	List<String> args;

	for (int i = 0; i < argc; i++) {
		args.push_back(String::utf8(argv[i]));
	}
	OS::get_singleton()->set_cmdline("", args);

	// Run custom test tools.
	if (test_commands) {
		for (Map<String, TestFunc>::Element *E = test_commands->front(); E; E = E->next()) {
			if (args.find(E->key())) {
				const TestFunc &test_func = E->get();
				test_func();
				run_tests = false;
				break;
			}
		}
		if (!run_tests) {
			delete test_commands;
			return 0;
		}
	}
	// Doctest runner.
	doctest::Context test_context;
	List<String> test_args;

	// Clean arguments of "--test" from the args.
	for (int x = 0; x < argc; x++) {
		String arg = String(argv[x]);
		if (arg != "--test") {
			test_args.push_back(arg);
		}
	}
	// Convert Godot command line arguments back to standard arguments.
	char **doctest_args = new char *[test_args.size()];
	for (int x = 0; x < test_args.size(); x++) {
		// Operation to convert Godot string to non wchar string.
		CharString cs = test_args[x].utf8();
		const char *str = cs.get_data();
		// Allocate the string copy.
		doctest_args[x] = new char[strlen(str) + 1];
		// Copy this into memory.
		memcpy(doctest_args[x], str, strlen(str) + 1);
	}

	test_context.applyCommandLine(test_args.size(), doctest_args);

	for (int x = 0; x < test_args.size(); x++) {
		delete[] doctest_args[x];
	}
	delete[] doctest_args;

	return test_context.run();
}
<|endoftext|>


<commit_before><commit_msg>POSIX: Don't convert backslashes in filenames into forward slashes.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#ifdef WIN32
# include <winsock2.h>
# include <process.h>  // for getpid
#else
# include <arpa/inet.h>
# include <unistd.h> // for getpid
#endif
#ifdef ANDROID
# include <sys/socket.h>
#endif

#include <cstdio>

#include <gtest/gtest.h>
#include <boost/filesystem.hpp>

#include <qi/path.hpp>
#include <qi/os.hpp>
#include <qi/qi.hpp>

#ifdef _MSC_VER
# pragma warning( push )
// truncation of constant value when building char* objects
# pragma warning( disable : 4309 )
#endif
class QiOSTests: public ::testing::Test
{
public:
  QiOSTests()
    : a_newPath()
  {
  }

protected:
  void SetUp() {
    a_newPath = qi::os::mktmpdir("QiOsTest");
    a_newPath.append(a_accent, qi::unicodeFacet());
    FILE* fileHandle = qi::os::fopen(a_newPath.string(qi::unicodeFacet()).c_str(), "w");
    fclose(fileHandle);
  }

  void TearDown() {
    if(boost::filesystem::exists(a_newPath)) {
      try {
        boost::filesystem::remove_all(a_newPath.parent_path());
      } catch (std::exception &) {
      }
    }
  }

public:
  boost::filesystem::path a_newPath;
  static const char       a_accent[4];
};

// "é" in utf-8 w. french locale.
const char QiOSTests::a_accent[4] =  { '/', 0xc3, 0xa9, '\0' } ;

TEST_F(QiOSTests, LowLevelAccent)
{
  // Try to retrieve the file.
  // The name must be in utf-8 to be retrieved on unix.
  ASSERT_TRUE(boost::filesystem::exists(a_newPath))
    << a_newPath.string() << std::endl;
}

// TODO: us qi::time when it's available :)
TEST(QiOs, sleep)
{
  qi::os::sleep(1);
}

TEST(QiOs, msleep)
{
  qi::os::msleep(1000);
}

TEST(QiOs, env)
{
  int ret = qi::os::setenv("TITI", "TUTU");
  ASSERT_FALSE(ret);
  EXPECT_EQ("TUTU", qi::os::getenv("TITI"));
}

TEST(QiOs, getpid)
{
  ASSERT_EQ(getpid(), qi::os::getpid());
}

TEST(QiOs, tmp)
{
  std::string temp = qi::os::tmp();

  ASSERT_NE(temp, std::string(""));

  EXPECT_TRUE(boost::filesystem::exists(temp));
  EXPECT_TRUE(boost::filesystem::is_directory(temp));
}

//check if the folder exists and is writable
void test_writable_and_empty(std::string fdir) {
  std::string             tempfile;
  boost::filesystem::path p(fdir, qi::unicodeFacet());
  boost::filesystem::path pp(fdir, qi::unicodeFacet());

  EXPECT_TRUE(boost::filesystem::exists(p));
  EXPECT_TRUE(boost::filesystem::is_directory(p));

  pp.append("tmpfile", qi::unicodeFacet());
  tempfile = pp.string(qi::unicodeFacet());

  FILE *f = qi::os::fopen(tempfile.c_str(), "w+");
  EXPECT_TRUE(f != NULL);
  fclose(f);

  EXPECT_TRUE(boost::filesystem::exists(pp));
  EXPECT_TRUE(boost::filesystem::is_regular_file(pp));

  boost::filesystem::directory_iterator it(p);

  EXPECT_EQ(pp, it->path());
  it++;

  EXPECT_TRUE((boost::filesystem::directory_iterator() == it));

}

void clean_dir(std::string fdir) {
  if(boost::filesystem::exists(fdir)) {
    //fail is dir is not removable => dir should be removable
    boost::filesystem::remove_all(fdir);
  }
}

TEST(QiOs, tmpdir_noprefix)
{
  std::string temp = qi::os::mktmpdir();
  test_writable_and_empty(temp);
  clean_dir(temp);
}

TEST(QiOs, tmpdir_tmpdir)
{
  std::string temp1 = qi::os::mktmpdir();
  std::string temp2 = qi::os::mktmpdir();
  EXPECT_NE(temp1, temp2);
  clean_dir(temp1);
  clean_dir(temp2);
}

TEST(QiOs, tmpdir_parent)
{
  std::string temp = qi::os::mktmpdir("plaf");

  boost::filesystem::path ppa(temp, qi::unicodeFacet());
  ppa = ppa.parent_path();

  boost::filesystem::path ppatmp(qi::os::tmp(), qi::unicodeFacet());
  EXPECT_TRUE(boost::filesystem::equivalent(ppa, ppatmp));

  clean_dir(temp);
}

TEST(QiOs, tmpdir_prefix)
{
  std::string temp = qi::os::mktmpdir("plaf");

  test_writable_and_empty(temp);

  boost::filesystem::path pp(temp, qi::unicodeFacet());
  std::string tempfname = pp.filename().string(qi::unicodeFacet());

  EXPECT_EQ(tempfname[0], 'p');
  EXPECT_EQ(tempfname[1], 'l');
  EXPECT_EQ(tempfname[2], 'a');
  EXPECT_EQ(tempfname[3], 'f');

  clean_dir(temp);
}

TEST(QiOs, tmpdir_prefix_accentuated)
{
  char utf8[]     = { 0xC5, 0xAA, 0x6E, 0xC4, 0xAD, 0x63, 0xC5, 0x8D, 0x64, 0x65, 0xCC, 0xBD, 0 };

  std::string temp = qi::os::mktmpdir(utf8);

  test_writable_and_empty(temp);
  clean_dir(temp);
}

TEST(QiOs, tmpdir_prefix_zero)
{
  std::string temp = qi::os::mktmpdir(0);
  test_writable_and_empty(temp);
  clean_dir(temp);
}

TEST(QiOs, get_host_name)
{
  std::string temp = qi::os::gethostname();
  EXPECT_NE(std::string(), temp);
}

bool freeportbind(unsigned short port, int &sock)
{
  struct sockaddr_in name;
  name.sin_family = AF_INET;
  name.sin_addr.s_addr = htonl(INADDR_ANY);
  sock = ::socket(AF_INET, SOCK_STREAM, 0);
  name.sin_port = htons(port);

  return ::bind(sock, (struct sockaddr *)&name, sizeof(name));
}

TEST(QiOs, free_port)
{
  int sock;
  unsigned short port = qi::os::findAvailablePort(9559);
  int success = freeportbind(port, sock);

  if (success == -1)
    EXPECT_TRUE(false);
  else
#ifndef WIN32
    ::close(sock);
#else
    ::closesocket(sock);
#endif

  EXPECT_TRUE(true);
}

TEST(QiOs, free_port_multiple_connection)
{
  int sock1;
  unsigned short port1 = qi::os::findAvailablePort(9559);
  int success1 = freeportbind(port1, sock1);
  int sock2;
  unsigned short port2 = qi::os::findAvailablePort(9559);
  int success2 = freeportbind(port2, sock2);
  int sock3;
  unsigned short port3 = qi::os::findAvailablePort(9559);
  int success3 = freeportbind(port3, sock3);

  if (success1 == -1)
    EXPECT_TRUE(false);
  else
#ifndef WIN32
    ::close(sock1);
#else
    ::closesocket(sock1);
#endif
  if (success2 == -1)
    EXPECT_TRUE(false);
  else
#ifndef WIN32
    ::close(sock2);
#else
    ::closesocket(sock2);
#endif
  if (success3 == -1)
    EXPECT_TRUE(false);
  else
#ifndef WIN32
    ::close(sock3);
#else
    ::closesocket(sock3);
#endif

  EXPECT_TRUE(true);
}

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<commit_msg>Adding test for hostIPAddrs<commit_after>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#ifdef WIN32
# include <winsock2.h>
# include <process.h>  // for getpid
#else
# include <arpa/inet.h>
# include <unistd.h> // for getpid
#endif
#ifdef ANDROID
# include <sys/socket.h>
#endif

#include <cstdio>

#include <gtest/gtest.h>
#include <boost/filesystem.hpp>

#include <qi/path.hpp>
#include <qi/os.hpp>
#include <qi/qi.hpp>
#include <qi/os.hpp>

#ifdef _MSC_VER
# pragma warning( push )
// truncation of constant value when building char* objects
# pragma warning( disable : 4309 )
#endif
class QiOSTests: public ::testing::Test
{
public:
  QiOSTests()
    : a_newPath()
  {
  }

protected:
  void SetUp() {
    a_newPath = qi::os::mktmpdir("QiOsTest");
    a_newPath.append(a_accent, qi::unicodeFacet());
    FILE* fileHandle = qi::os::fopen(a_newPath.string(qi::unicodeFacet()).c_str(), "w");
    fclose(fileHandle);
  }

  void TearDown() {
    if(boost::filesystem::exists(a_newPath)) {
      try {
        boost::filesystem::remove_all(a_newPath.parent_path());
      } catch (std::exception &) {
      }
    }
  }

public:
  boost::filesystem::path a_newPath;
  static const char       a_accent[4];
};

// "é" in utf-8 w. french locale.
const char QiOSTests::a_accent[4] =  { '/', 0xc3, 0xa9, '\0' } ;

TEST_F(QiOSTests, LowLevelAccent)
{
  // Try to retrieve the file.
  // The name must be in utf-8 to be retrieved on unix.
  ASSERT_TRUE(boost::filesystem::exists(a_newPath))
    << a_newPath.string() << std::endl;
}

// TODO: us qi::time when it's available :)
TEST(QiOs, sleep)
{
  qi::os::sleep(1);
}

TEST(QiOs, msleep)
{
  qi::os::msleep(1000);
}

TEST(QiOs, env)
{
  int ret = qi::os::setenv("TITI", "TUTU");
  ASSERT_FALSE(ret);
  EXPECT_EQ("TUTU", qi::os::getenv("TITI"));
}

TEST(QiOs, getpid)
{
  ASSERT_EQ(getpid(), qi::os::getpid());
}

TEST(QiOs, tmp)
{
  std::string temp = qi::os::tmp();

  ASSERT_NE(temp, std::string(""));

  EXPECT_TRUE(boost::filesystem::exists(temp));
  EXPECT_TRUE(boost::filesystem::is_directory(temp));
}

//check if the folder exists and is writable
void test_writable_and_empty(std::string fdir) {
  std::string             tempfile;
  boost::filesystem::path p(fdir, qi::unicodeFacet());
  boost::filesystem::path pp(fdir, qi::unicodeFacet());

  EXPECT_TRUE(boost::filesystem::exists(p));
  EXPECT_TRUE(boost::filesystem::is_directory(p));

  pp.append("tmpfile", qi::unicodeFacet());
  tempfile = pp.string(qi::unicodeFacet());

  FILE *f = qi::os::fopen(tempfile.c_str(), "w+");
  EXPECT_TRUE(f != NULL);
  fclose(f);

  EXPECT_TRUE(boost::filesystem::exists(pp));
  EXPECT_TRUE(boost::filesystem::is_regular_file(pp));

  boost::filesystem::directory_iterator it(p);

  EXPECT_EQ(pp, it->path());
  it++;

  EXPECT_TRUE((boost::filesystem::directory_iterator() == it));

}

void clean_dir(std::string fdir) {
  if(boost::filesystem::exists(fdir)) {
    //fail is dir is not removable => dir should be removable
    boost::filesystem::remove_all(fdir);
  }
}

TEST(QiOs, tmpdir_noprefix)
{
  std::string temp = qi::os::mktmpdir();
  test_writable_and_empty(temp);
  clean_dir(temp);
}

TEST(QiOs, tmpdir_tmpdir)
{
  std::string temp1 = qi::os::mktmpdir();
  std::string temp2 = qi::os::mktmpdir();
  EXPECT_NE(temp1, temp2);
  clean_dir(temp1);
  clean_dir(temp2);
}

TEST(QiOs, tmpdir_parent)
{
  std::string temp = qi::os::mktmpdir("plaf");

  boost::filesystem::path ppa(temp, qi::unicodeFacet());
  ppa = ppa.parent_path();

  boost::filesystem::path ppatmp(qi::os::tmp(), qi::unicodeFacet());
  EXPECT_TRUE(boost::filesystem::equivalent(ppa, ppatmp));

  clean_dir(temp);
}

TEST(QiOs, tmpdir_prefix)
{
  std::string temp = qi::os::mktmpdir("plaf");

  test_writable_and_empty(temp);

  boost::filesystem::path pp(temp, qi::unicodeFacet());
  std::string tempfname = pp.filename().string(qi::unicodeFacet());

  EXPECT_EQ(tempfname[0], 'p');
  EXPECT_EQ(tempfname[1], 'l');
  EXPECT_EQ(tempfname[2], 'a');
  EXPECT_EQ(tempfname[3], 'f');

  clean_dir(temp);
}

TEST(QiOs, tmpdir_prefix_accentuated)
{
  char utf8[]     = { 0xC5, 0xAA, 0x6E, 0xC4, 0xAD, 0x63, 0xC5, 0x8D, 0x64, 0x65, 0xCC, 0xBD, 0 };

  std::string temp = qi::os::mktmpdir(utf8);

  test_writable_and_empty(temp);
  clean_dir(temp);
}

TEST(QiOs, tmpdir_prefix_zero)
{
  std::string temp = qi::os::mktmpdir(0);
  test_writable_and_empty(temp);
  clean_dir(temp);
}

TEST(QiOs, get_host_name)
{
  std::string temp = qi::os::gethostname();
  EXPECT_NE(std::string(), temp);
}

bool freeportbind(unsigned short port, int &sock)
{
  struct sockaddr_in name;
  name.sin_family = AF_INET;
  name.sin_addr.s_addr = htonl(INADDR_ANY);
  sock = ::socket(AF_INET, SOCK_STREAM, 0);
  name.sin_port = htons(port);

  return ::bind(sock, (struct sockaddr *)&name, sizeof(name));
}

TEST(QiOs, free_port)
{
  int sock;
  unsigned short port = qi::os::findAvailablePort(9559);
  int success = freeportbind(port, sock);

  if (success == -1)
    EXPECT_TRUE(false);
  else
#ifndef WIN32
    ::close(sock);
#else
    ::closesocket(sock);
#endif

  EXPECT_TRUE(true);
}

TEST(QiOs, free_port_multiple_connection)
{
  int sock1;
  unsigned short port1 = qi::os::findAvailablePort(9559);
  int success1 = freeportbind(port1, sock1);
  int sock2;
  unsigned short port2 = qi::os::findAvailablePort(9559);
  int success2 = freeportbind(port2, sock2);
  int sock3;
  unsigned short port3 = qi::os::findAvailablePort(9559);
  int success3 = freeportbind(port3, sock3);

  if (success1 == -1)
    EXPECT_TRUE(false);
  else
#ifndef WIN32
    ::close(sock1);
#else
    ::closesocket(sock1);
#endif
  if (success2 == -1)
    EXPECT_TRUE(false);
  else
#ifndef WIN32
    ::close(sock2);
#else
    ::closesocket(sock2);
#endif
  if (success3 == -1)
    EXPECT_TRUE(false);
  else
#ifndef WIN32
    ::close(sock3);
#else
    ::closesocket(sock3);
#endif

  EXPECT_TRUE(true);
}

TEST(QiOs, hostIPAddrs)
{
  std::map<std::string, std::vector<std::string> > ifsMap;

  ifsMap = qi::os::hostIPAddrs();
  ASSERT_TRUE(ifsMap.empty() == false);
}

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<|endoftext|>


<commit_before>// Copyright 2015-2018 Elviss Strazdins. All rights reserved.

#include "core/Setup.h"

#if OUZEL_COMPILE_DIRECTSOUND

#include "AudioDeviceDS.hpp"
#include "core/Engine.hpp"
#include "core/Window.hpp"
#include "core/windows/NativeWindowWin.hpp"
#include "utils/Log.hpp"
#include "utils/Utils.hpp"

BOOL CALLBACK enumCallback(LPGUID, LPCWSTR description, LPCWSTR, LPVOID)
{
    int bufferSize = WideCharToMultiByte(CP_UTF8, 0, description, -1, nullptr, 0, nullptr, nullptr);
    if (bufferSize != 0)
    {
        std::vector<char> buffer(bufferSize);
        if (WideCharToMultiByte(CP_UTF8, 0, description, -1, buffer.data(), bufferSize, nullptr, nullptr) != 0)
            ouzel::engine->log(ouzel::Log::Level::INFO) << "Using " << buffer.data() << " for audio";
    }
    return FALSE;
}

namespace ouzel
{
    namespace audio
    {
        class DirectSoundErrorCategory: public std::error_category
        {
        public:
            const char* name() const noexcept override
            {
                return "DirectSound";
            }

            std::string message(int condition) const override
            {
                switch (condition)
                {
                    case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED";
                    case DSERR_ALLOCATED: return "DSERR_ALLOCATED";
                    case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED";
                    case DSERR_BADFORMAT: return "DSERR_BADFORMAT";
                    case DSERR_BADSENDBUFFERGUID: return "DSERR_BADSENDBUFFERGUID";
                    case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST";
                    case DSERR_BUFFERTOOSMALL: return "DSERR_BUFFERTOOSMALL";
                    case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL";
                    case DSERR_DS8_REQUIRED: return "DSERR_DS8_REQUIRED";
                    case DSERR_FXUNAVAILABLE: return "DSERR_FXUNAVAILABLE";
                    case DSERR_GENERIC: return "DSERR_GENERIC";
                    case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL";
                    case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM";
                    case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION";
                    case DSERR_NODRIVER: return "DSERR_NODRIVER";
                    case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE";
                    case DSERR_OBJECTNOTFOUND: return "DSERR_OBJECTNOTFOUND";
                    case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO";
                    case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY";
                    case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED";
                    case DSERR_SENDLOOP: return "DSERR_SENDLOOP";
                    case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED";
                    case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED";
                    default: return "Unknown error (" + std::to_string(condition) + ")";
                }
            }
        };

        const DirectSoundErrorCategory directSoundErrorCategory {};

        AudioDeviceDS::AudioDeviceDS(Window* window):
            AudioDevice(Driver::DIRECTSOUND), running(true)
        {
            HRESULT hr;
            if (FAILED(hr = DirectSoundEnumerateW(enumCallback, this)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to enumerate DirectSound 8 devices");

            if (FAILED(hr = DirectSoundCreate8(&DSDEVID_DefaultPlayback, &directSound, nullptr)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to create DirectSound 8 instance");

            NativeWindowWin* windowWin = static_cast<NativeWindowWin*>(window->getNativeWindow());

            if (FAILED(hr = directSound->SetCooperativeLevel(windowWin->getNativeWindow(), DSSCL_PRIORITY)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to set cooperative level for DirectSound 8");

            DSBUFFERDESC primaryBufferDesc;
            primaryBufferDesc.dwSize = sizeof(primaryBufferDesc);
            primaryBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
            primaryBufferDesc.dwBufferBytes = 0;
            primaryBufferDesc.dwReserved = 0;
            primaryBufferDesc.lpwfxFormat = nullptr;
            primaryBufferDesc.guid3DAlgorithm = GUID_NULL;

            if (FAILED(hr = directSound->CreateSoundBuffer(&primaryBufferDesc, &primaryBuffer, nullptr)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to create DirectSound buffer");

            WAVEFORMATEX waveFormat;
            waveFormat.wFormatTag = WAVE_FORMAT_PCM;
            waveFormat.nChannels = channels;
            waveFormat.nSamplesPerSec = sampleRate;
            waveFormat.wBitsPerSample = 16;
            waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
            waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
            waveFormat.cbSize = 0;

            if (FAILED(hr = primaryBuffer->SetFormat(&waveFormat)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to set DirectSound buffer format");

            sampleFormat = SampleFormat::SINT16;
            sampleSize = sizeof(int16_t);

            IDirectSoundBuffer* tempBuffer = nullptr;

            DSBUFFERDESC bufferDesc;
            bufferDesc.dwSize = sizeof(bufferDesc);
            bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY;
            bufferDesc.dwBufferBytes = 2 * bufferSize;
            bufferDesc.dwReserved = 0;
            bufferDesc.lpwfxFormat = &waveFormat;
            bufferDesc.guid3DAlgorithm = GUID_NULL;

            if (FAILED(hr = directSound->CreateSoundBuffer(&bufferDesc, &tempBuffer, nullptr)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to create DirectSound buffer");

            if (FAILED(hr = tempBuffer->QueryInterface(IID_IDirectSoundBuffer8, reinterpret_cast<void**>(&buffer))))
            {
                tempBuffer->Release();
                throw std::system_error(hr, directSoundErrorCategory, "Failed to create DirectSound buffer");
            }

            if (FAILED(hr = tempBuffer->QueryInterface(IID_IDirectSoundNotify, reinterpret_cast<void**>(&notify))))
            {
                tempBuffer->Release();
                throw std::system_error(hr, directSoundErrorCategory, "Failed to get DirectSound notify interface");
            }

            tempBuffer->Release();

            uint8_t* bufferPointer;
            DWORD lockedBufferSize;
            if (FAILED(hr = buffer->Lock(0, bufferDesc.dwBufferBytes, reinterpret_cast<void**>(&bufferPointer), &lockedBufferSize, nullptr, 0, 0)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to lock DirectSound buffer");

            getData(lockedBufferSize / (channels * sizeof(int16_t)), data);
            std::copy(data.begin(), data.end(), bufferPointer);

            if (FAILED(hr = buffer->Unlock(bufferPointer, lockedBufferSize, nullptr, 0)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to unlock DirectSound buffer");

            nextBuffer = 0;

            notifyEvents[0] = CreateEvent(nullptr, true, false, nullptr);
            if (!notifyEvents[0])
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create event");

            notifyEvents[1] = CreateEvent(nullptr, true, false, nullptr);
            if (!notifyEvents[1])
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create event");

            DSBPOSITIONNOTIFY positionNotifyEvents[2];
            positionNotifyEvents[0].dwOffset = bufferSize - 1;
            positionNotifyEvents[0].hEventNotify = notifyEvents[0];

            positionNotifyEvents[1].dwOffset = 2 * bufferSize - 1;
            positionNotifyEvents[1].hEventNotify = notifyEvents[1];

            if (FAILED(hr = notify->SetNotificationPositions(2, positionNotifyEvents)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to set DirectSound notification positions");

            if (FAILED(hr = buffer->Play(0, 0, DSBPLAY_LOOPING)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to play DirectSound buffer");

            audioThread = std::thread(&AudioDeviceDS::run, this);
        }

        AudioDeviceDS::~AudioDeviceDS()
        {
            running = false;
            for (HANDLE notifyEvent : notifyEvents)
                SetEvent(notifyEvent);

            if (audioThread.joinable()) audioThread.join();

            for (HANDLE notifyEvent : notifyEvents)
                if (notifyEvent) CloseHandle(notifyEvent);

            if (notify) notify->Release();
            if (buffer) buffer->Release();
            if (primaryBuffer) primaryBuffer->Release();
            if (directSound) directSound->Release();
        }

        void AudioDeviceDS::run()
        {
            setCurrentThreadName("Audio");

            while (running)
            {
                try
                {
                    if (WaitForSingleObject(notifyEvents[nextBuffer], INFINITE) == WAIT_OBJECT_0)
                    {
                        if (!running) break;

                        ResetEvent(notifyEvents[nextBuffer]);

                        process();

                        uint8_t* bufferPointer;
                        DWORD lockedBufferSize;
                        HRESULT hr;
                        if (FAILED(hr = buffer->Lock(nextBuffer * bufferSize, bufferSize, reinterpret_cast<void**>(&bufferPointer), &lockedBufferSize, nullptr, 0, 0)))
                            throw std::system_error(hr, directSoundErrorCategory, "Failed to lock DirectSound buffer");

                        getData(lockedBufferSize / (sampleSize * channels), data);

                        std::copy(data.begin(), data.end(), bufferPointer);

                        if (FAILED(hr = buffer->Unlock(bufferPointer, lockedBufferSize, nullptr, 0)))
                            throw std::system_error(hr, directSoundErrorCategory, "Failed to unlock DirectSound buffer");

                        nextBuffer = (nextBuffer + 1) % 2;
                    }
                }
                catch (const std::exception& e)
                {
                    engine->log(Log::Level::ERR) << e.what();
                }
            }
        }
    } // namespace audio
} // namespace ouzel

#endif
<commit_msg>Handle more event errors<commit_after>// Copyright 2015-2018 Elviss Strazdins. All rights reserved.

#include "core/Setup.h"

#if OUZEL_COMPILE_DIRECTSOUND

#include <system_error>
#include "AudioDeviceDS.hpp"
#include "core/Engine.hpp"
#include "core/Window.hpp"
#include "core/windows/NativeWindowWin.hpp"
#include "utils/Log.hpp"
#include "utils/Utils.hpp"

BOOL CALLBACK enumCallback(LPGUID, LPCWSTR description, LPCWSTR, LPVOID)
{
    int bufferSize = WideCharToMultiByte(CP_UTF8, 0, description, -1, nullptr, 0, nullptr, nullptr);
    if (bufferSize != 0)
    {
        std::vector<char> buffer(bufferSize);
        if (WideCharToMultiByte(CP_UTF8, 0, description, -1, buffer.data(), bufferSize, nullptr, nullptr) != 0)
            ouzel::engine->log(ouzel::Log::Level::INFO) << "Using " << buffer.data() << " for audio";
    }
    return FALSE;
}

namespace ouzel
{
    namespace audio
    {
        class DirectSoundErrorCategory: public std::error_category
        {
        public:
            const char* name() const noexcept override
            {
                return "DirectSound";
            }

            std::string message(int condition) const override
            {
                switch (condition)
                {
                    case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED";
                    case DSERR_ALLOCATED: return "DSERR_ALLOCATED";
                    case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED";
                    case DSERR_BADFORMAT: return "DSERR_BADFORMAT";
                    case DSERR_BADSENDBUFFERGUID: return "DSERR_BADSENDBUFFERGUID";
                    case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST";
                    case DSERR_BUFFERTOOSMALL: return "DSERR_BUFFERTOOSMALL";
                    case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL";
                    case DSERR_DS8_REQUIRED: return "DSERR_DS8_REQUIRED";
                    case DSERR_FXUNAVAILABLE: return "DSERR_FXUNAVAILABLE";
                    case DSERR_GENERIC: return "DSERR_GENERIC";
                    case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL";
                    case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM";
                    case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION";
                    case DSERR_NODRIVER: return "DSERR_NODRIVER";
                    case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE";
                    case DSERR_OBJECTNOTFOUND: return "DSERR_OBJECTNOTFOUND";
                    case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO";
                    case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY";
                    case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED";
                    case DSERR_SENDLOOP: return "DSERR_SENDLOOP";
                    case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED";
                    case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED";
                    default: return "Unknown error (" + std::to_string(condition) + ")";
                }
            }
        };

        const DirectSoundErrorCategory directSoundErrorCategory {};

        AudioDeviceDS::AudioDeviceDS(Window* window):
            AudioDevice(Driver::DIRECTSOUND), running(true)
        {
            HRESULT hr;
            if (FAILED(hr = DirectSoundEnumerateW(enumCallback, this)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to enumerate DirectSound 8 devices");

            if (FAILED(hr = DirectSoundCreate8(&DSDEVID_DefaultPlayback, &directSound, nullptr)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to create DirectSound 8 instance");

            NativeWindowWin* windowWin = static_cast<NativeWindowWin*>(window->getNativeWindow());

            if (FAILED(hr = directSound->SetCooperativeLevel(windowWin->getNativeWindow(), DSSCL_PRIORITY)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to set cooperative level for DirectSound 8");

            DSBUFFERDESC primaryBufferDesc;
            primaryBufferDesc.dwSize = sizeof(primaryBufferDesc);
            primaryBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
            primaryBufferDesc.dwBufferBytes = 0;
            primaryBufferDesc.dwReserved = 0;
            primaryBufferDesc.lpwfxFormat = nullptr;
            primaryBufferDesc.guid3DAlgorithm = GUID_NULL;

            if (FAILED(hr = directSound->CreateSoundBuffer(&primaryBufferDesc, &primaryBuffer, nullptr)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to create DirectSound buffer");

            WAVEFORMATEX waveFormat;
            waveFormat.wFormatTag = WAVE_FORMAT_PCM;
            waveFormat.nChannels = channels;
            waveFormat.nSamplesPerSec = sampleRate;
            waveFormat.wBitsPerSample = 16;
            waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
            waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
            waveFormat.cbSize = 0;

            if (FAILED(hr = primaryBuffer->SetFormat(&waveFormat)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to set DirectSound buffer format");

            sampleFormat = SampleFormat::SINT16;
            sampleSize = sizeof(int16_t);

            IDirectSoundBuffer* tempBuffer = nullptr;

            DSBUFFERDESC bufferDesc;
            bufferDesc.dwSize = sizeof(bufferDesc);
            bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY;
            bufferDesc.dwBufferBytes = 2 * bufferSize;
            bufferDesc.dwReserved = 0;
            bufferDesc.lpwfxFormat = &waveFormat;
            bufferDesc.guid3DAlgorithm = GUID_NULL;

            if (FAILED(hr = directSound->CreateSoundBuffer(&bufferDesc, &tempBuffer, nullptr)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to create DirectSound buffer");

            if (FAILED(hr = tempBuffer->QueryInterface(IID_IDirectSoundBuffer8, reinterpret_cast<void**>(&buffer))))
            {
                tempBuffer->Release();
                throw std::system_error(hr, directSoundErrorCategory, "Failed to create DirectSound buffer");
            }

            if (FAILED(hr = tempBuffer->QueryInterface(IID_IDirectSoundNotify, reinterpret_cast<void**>(&notify))))
            {
                tempBuffer->Release();
                throw std::system_error(hr, directSoundErrorCategory, "Failed to get DirectSound notify interface");
            }

            tempBuffer->Release();

            uint8_t* bufferPointer;
            DWORD lockedBufferSize;
            if (FAILED(hr = buffer->Lock(0, bufferDesc.dwBufferBytes, reinterpret_cast<void**>(&bufferPointer), &lockedBufferSize, nullptr, 0, 0)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to lock DirectSound buffer");

            getData(lockedBufferSize / (channels * sizeof(int16_t)), data);
            std::copy(data.begin(), data.end(), bufferPointer);

            if (FAILED(hr = buffer->Unlock(bufferPointer, lockedBufferSize, nullptr, 0)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to unlock DirectSound buffer");

            nextBuffer = 0;

            notifyEvents[0] = CreateEvent(nullptr, true, false, nullptr);
            if (!notifyEvents[0])
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create event");

            notifyEvents[1] = CreateEvent(nullptr, true, false, nullptr);
            if (!notifyEvents[1])
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create event");

            DSBPOSITIONNOTIFY positionNotifyEvents[2];
            positionNotifyEvents[0].dwOffset = bufferSize - 1;
            positionNotifyEvents[0].hEventNotify = notifyEvents[0];

            positionNotifyEvents[1].dwOffset = 2 * bufferSize - 1;
            positionNotifyEvents[1].hEventNotify = notifyEvents[1];

            if (FAILED(hr = notify->SetNotificationPositions(2, positionNotifyEvents)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to set DirectSound notification positions");

            if (FAILED(hr = buffer->Play(0, 0, DSBPLAY_LOOPING)))
                throw std::system_error(hr, directSoundErrorCategory, "Failed to play DirectSound buffer");

            audioThread = std::thread(&AudioDeviceDS::run, this);
        }

        AudioDeviceDS::~AudioDeviceDS()
        {
            running = false;
            for (HANDLE notifyEvent : notifyEvents)
                SetEvent(notifyEvent);

            if (audioThread.joinable()) audioThread.join();

            for (HANDLE notifyEvent : notifyEvents)
                if (notifyEvent) CloseHandle(notifyEvent);

            if (notify) notify->Release();
            if (buffer) buffer->Release();
            if (primaryBuffer) primaryBuffer->Release();
            if (directSound) directSound->Release();
        }

        void AudioDeviceDS::run()
        {
            setCurrentThreadName("Audio");

            while (running)
            {
                try
                {
                    DWORD result;
                    if ((result = WaitForSingleObject(notifyEvents[nextBuffer], INFINITE)) == WAIT_FAILED)
                            throw std::system_error(GetLastError(), std::system_category(), "Failed to wait for event");

                    if (result == WAIT_OBJECT_0)
                    {
                        if (!running) break;

                        if (!ResetEvent(notifyEvents[nextBuffer]))
                            throw std::system_error(GetLastError(), std::system_category(), "Failed to reset event");

                        process();

                        uint8_t* bufferPointer;
                        DWORD lockedBufferSize;
                        HRESULT hr;
                        if (FAILED(hr = buffer->Lock(nextBuffer * bufferSize, bufferSize, reinterpret_cast<void**>(&bufferPointer), &lockedBufferSize, nullptr, 0, 0)))
                            throw std::system_error(hr, directSoundErrorCategory, "Failed to lock DirectSound buffer");

                        getData(lockedBufferSize / (sampleSize * channels), data);

                        std::copy(data.begin(), data.end(), bufferPointer);

                        if (FAILED(hr = buffer->Unlock(bufferPointer, lockedBufferSize, nullptr, 0)))
                            throw std::system_error(hr, directSoundErrorCategory, "Failed to unlock DirectSound buffer");

                        nextBuffer = (nextBuffer + 1) % 2;
                    }
                }
                catch (const std::exception& e)
                {
                    engine->log(Log::Level::ERR) << e.what();
                }
            }
        }
    } // namespace audio
} // namespace ouzel

#endif
<|endoftext|>