<commit_before>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2014-2015 Kim Kulling

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 "gtest/gtest.h"

#include <openddlparser/OpenDDLParserUtils.h>

#include "UnitTestCommon.h"

BEGIN_ODDLPARSER_NS

class OpenDDLParserUtilsTest : public testing::Test {
};

TEST_F( OpenDDLParserUtilsTest, isCommentTest ) {
    size_t len( 0 );
    bool result( false );
    char *end( nullptr );
    char token1[] = "//";
    end = findEnd( token1, len );
    result = isComment( token1, end );
    EXPECT_TRUE( result );

    char token2[] = "/*";
    end = findEnd( token2, len );
    result = isComment( token2, end );
    EXPECT_FALSE( result );

    char token3[] = "/";
    end = findEnd( token3, len );
    result = isComment( token3, end );
    EXPECT_FALSE( result );

}
TEST_F( OpenDDLParserUtilsTest, isUpperCaseTest ) {
    char val = 'a';
    EXPECT_TRUE( isLowerCase<char>( val ) );
    val = 'c';
    EXPECT_TRUE( isLowerCase<char>( val ) );
    val = 'z';
    EXPECT_TRUE( isLowerCase<char>( val ) );
    val = 'A';
    EXPECT_FALSE( isLowerCase<char>( val ) );
    val = '0';
    EXPECT_FALSE( isLowerCase<char>( val ) );
}

TEST_F( OpenDDLParserUtilsTest, isLowerCaseTest ) {
    char val = 'A';
    EXPECT_TRUE( isUpperCase<char>( val ) );
    val = 'C';
    EXPECT_TRUE( isUpperCase<char>( val ) );
    val = 'Z';
    EXPECT_TRUE( isUpperCase<char>( val ) );
    val = 'a';
    EXPECT_FALSE( isUpperCase<char>( val ) );
    val = '0';
    EXPECT_FALSE( isUpperCase<char>( val ) );
}

TEST_F( OpenDDLParserUtilsTest, isNumericTest ) {
    char val1 = '0';
    EXPECT_TRUE( isNumeric<char>( val1 ) );
    char val2 = '9';
    EXPECT_TRUE( isNumeric<char>( val2 ) );
    char val3 = '4';
    EXPECT_TRUE( isNumeric<char>( val3 ) );
    char notChar = 'a';
    EXPECT_FALSE( isNumeric<char>( notChar ) );
}

TEST_F( OpenDDLParserUtilsTest, isIntegerTest ) {
    size_t len( 0 );

    // positive value
    char val1[] = "12";
    char *end = findEnd( val1, len );
    bool result( false );
    result = isInteger( val1, end );
    EXPECT_TRUE( result );

    // positive value, separated by a comma
    char val2[] = "12,";
    end = findEnd( val2, len );
    result = isInteger( val2, end );
    EXPECT_TRUE( result );

    // negative value
    char val3[] = "-12";
    end = findEnd( val3, len );
    result = isInteger( val3, end );
    EXPECT_TRUE( result );

    // float value
    char val4[] = "12.";
    end = findEnd( val4, len );
    result = isInteger( val4, end );
    EXPECT_FALSE( result );

    // string literal
    char val5[] = "test";
    end = findEnd( val5, len );
    result = isInteger( val5, end );
    EXPECT_FALSE( result );

    // positive value, separated by a curly bracket
    char val6[] = "12}";
    end = findEnd( val6, len );
    result = isInteger( val6, end );
    EXPECT_TRUE( result );

}

TEST_F( OpenDDLParserUtilsTest, isFloatTest ) {
    size_t len( 0 );
    char val1[] = "12.0";
    char *end = findEnd( val1, len );
    bool result( false );
    result = isFloat( val1, end );
    EXPECT_TRUE( result );

    char val2[] = "-12.0";
    end = findEnd( val2, len );
    result = isFloat( val2, end );
    EXPECT_TRUE( result );

    char val3[] = "-12";
    end = findEnd( val3, len );
    result = isFloat( val3, end );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isCharacterTest ) {
    char val = 'a';
    EXPECT_TRUE( isCharacter<char>( val ) );
    val = 'z';
    EXPECT_TRUE( isCharacter<char>( val ) );
    val = 'A';
    EXPECT_TRUE( isCharacter<char>( val ) );
    val = 'Z';
    EXPECT_TRUE( isCharacter<char>( val ) );
    val = '1';
    EXPECT_FALSE( isCharacter<char>( val ) );
}

TEST_F( OpenDDLParserUtilsTest, isStringLiteralTest ) {
    char val = '\"';
    EXPECT_TRUE( isStringLiteral<char>( val ) );
    val = 'a';
    EXPECT_FALSE( isStringLiteral<char>( val ) );
}

TEST_F( OpenDDLParserUtilsTest, isHexLiteralTest ) {
    size_t len( 0 );
    char token1[] = "0x10";
    char *end = findEnd( token1, len );
    bool result = isHexLiteral( token1, end );
    EXPECT_TRUE( result );

    char token11[] = "0X10";
    end = findEnd( token11, len );
    result = isHexLiteral( token11, end );
    EXPECT_TRUE( result );

    char token2[] = "10";
    result = isHexLiteral( token2, end );
    EXPECT_FALSE( result );

    char token3[] = "lala";
    result = isHexLiteral( token3, end );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isReferenceTest ) {
    size_t len( 0 );
    char token1[] = "ref";
    char *end = findEnd( token1, len );
    bool result = isReference( token1, end );
    EXPECT_TRUE( result );

    char token2[] = "rf";
    end = findEnd( token2, len );
    result = isReference( token2, end );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isSpaceTest ) {
    bool result( false );
    char val;
    val = ' ';
    result = isSpace( val );
    EXPECT_TRUE( result );

    val = '\t';
    result = isSpace( val );
    EXPECT_TRUE( result );

    val = '1';
    result = isSpace( val );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isNewLineTest ) {
    bool result( false );
    char val;
    val = '\n';
    result = isNewLine( val );
    EXPECT_TRUE( result );

    val = '\r';
    result = isNewLine( val );
    EXPECT_TRUE( result );

    val = ' ';
    result = isNewLine( val );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isSeparatorTest ) {
    char val;
    val = ' ';
    EXPECT_TRUE( isSeparator( val ) );
    val = '\t';
    EXPECT_TRUE( isSeparator( val ) );
    val = '1';
    EXPECT_FALSE( isSeparator( val ) );
    val = 'a';
    EXPECT_FALSE( isSeparator( val ) );
    val = 'Z';
    EXPECT_FALSE( isSeparator( val ) );
    val = '{';
    EXPECT_TRUE( isSeparator( val ) );
    val = '}';
    EXPECT_TRUE( isSeparator( val ) );
    val = '[';
    EXPECT_TRUE( isSeparator( val ) );
}

END_ODDLPARSER_NS
<commit_msg>add unittest for float test with separators.<commit_after>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2014-2015 Kim Kulling

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 "gtest/gtest.h"

#include <openddlparser/OpenDDLParserUtils.h>

#include "UnitTestCommon.h"

BEGIN_ODDLPARSER_NS

class OpenDDLParserUtilsTest : public testing::Test {
};

TEST_F( OpenDDLParserUtilsTest, isCommentTest ) {
    size_t len( 0 );
    bool result( false );
    char *end( nullptr );
    char token1[] = "//";
    end = findEnd( token1, len );
    result = isComment( token1, end );
    EXPECT_TRUE( result );

    char token2[] = "/*";
    end = findEnd( token2, len );
    result = isComment( token2, end );
    EXPECT_FALSE( result );

    char token3[] = "/";
    end = findEnd( token3, len );
    result = isComment( token3, end );
    EXPECT_FALSE( result );

}
TEST_F( OpenDDLParserUtilsTest, isUpperCaseTest ) {
    char val = 'a';
    EXPECT_TRUE( isLowerCase<char>( val ) );
    val = 'c';
    EXPECT_TRUE( isLowerCase<char>( val ) );
    val = 'z';
    EXPECT_TRUE( isLowerCase<char>( val ) );
    val = 'A';
    EXPECT_FALSE( isLowerCase<char>( val ) );
    val = '0';
    EXPECT_FALSE( isLowerCase<char>( val ) );
}

TEST_F( OpenDDLParserUtilsTest, isLowerCaseTest ) {
    char val = 'A';
    EXPECT_TRUE( isUpperCase<char>( val ) );
    val = 'C';
    EXPECT_TRUE( isUpperCase<char>( val ) );
    val = 'Z';
    EXPECT_TRUE( isUpperCase<char>( val ) );
    val = 'a';
    EXPECT_FALSE( isUpperCase<char>( val ) );
    val = '0';
    EXPECT_FALSE( isUpperCase<char>( val ) );
}

TEST_F( OpenDDLParserUtilsTest, isNumericTest ) {
    char val1 = '0';
    EXPECT_TRUE( isNumeric<char>( val1 ) );
    char val2 = '9';
    EXPECT_TRUE( isNumeric<char>( val2 ) );
    char val3 = '4';
    EXPECT_TRUE( isNumeric<char>( val3 ) );
    char notChar = 'a';
    EXPECT_FALSE( isNumeric<char>( notChar ) );
}

TEST_F( OpenDDLParserUtilsTest, isIntegerTest ) {
    size_t len( 0 );

    // positive value
    char val1[] = "12";
    char *end = findEnd( val1, len );
    bool result( false );
    result = isInteger( val1, end );
    EXPECT_TRUE( result );

    // positive value, separated by a comma
    char val2[] = "12,";
    end = findEnd( val2, len );
    result = isInteger( val2, end );
    EXPECT_TRUE( result );

    // negative value
    char val3[] = "-12";
    end = findEnd( val3, len );
    result = isInteger( val3, end );
    EXPECT_TRUE( result );

    // float value
    char val4[] = "12.";
    end = findEnd( val4, len );
    result = isInteger( val4, end );
    EXPECT_FALSE( result );

    // string literal
    char val5[] = "test";
    end = findEnd( val5, len );
    result = isInteger( val5, end );
    EXPECT_FALSE( result );

    // positive value, separated by a curly bracket
    char val6[] = "12}";
    end = findEnd( val6, len );
    result = isInteger( val6, end );
    EXPECT_TRUE( result );

}

TEST_F( OpenDDLParserUtilsTest, isFloatTest ) {
    size_t len( 0 );
    char val1[] = "12.0";
    char *end = findEnd( val1, len );
    bool result( false );
    result = isFloat( val1, end );
    EXPECT_TRUE( result );

    char val2[] = "-12.0";
    end = findEnd( val2, len );
    result = isFloat( val2, end );
    EXPECT_TRUE( result );

    char val3[] = "-12";
    end = findEnd( val3, len );
    result = isFloat( val3, end );
    EXPECT_FALSE( result );

}

TEST_F( OpenDDLParserUtilsTest, isFloatWithSeparatorTest ) {
    bool result( false );
    size_t len( 0 );
    char val1[] = "-12.0}";
    char*end = findEnd( val1, len );
    result = isFloat( val1, end );
    EXPECT_TRUE( result );

    char val2[] = "-12.0,";
    end = findEnd( val2, len );
    result = isFloat( val2, end );
    EXPECT_TRUE( result );
}

TEST_F( OpenDDLParserUtilsTest, isCharacterTest ) {
    char val = 'a';
    EXPECT_TRUE( isCharacter<char>( val ) );
    val = 'z';
    EXPECT_TRUE( isCharacter<char>( val ) );
    val = 'A';
    EXPECT_TRUE( isCharacter<char>( val ) );
    val = 'Z';
    EXPECT_TRUE( isCharacter<char>( val ) );
    val = '1';
    EXPECT_FALSE( isCharacter<char>( val ) );
}

TEST_F( OpenDDLParserUtilsTest, isStringLiteralTest ) {
    char val = '\"';
    EXPECT_TRUE( isStringLiteral<char>( val ) );
    val = 'a';
    EXPECT_FALSE( isStringLiteral<char>( val ) );
}

TEST_F( OpenDDLParserUtilsTest, isHexLiteralTest ) {
    size_t len( 0 );
    char token1[] = "0x10";
    char *end = findEnd( token1, len );
    bool result = isHexLiteral( token1, end );
    EXPECT_TRUE( result );

    char token11[] = "0X10";
    end = findEnd( token11, len );
    result = isHexLiteral( token11, end );
    EXPECT_TRUE( result );

    char token2[] = "10";
    result = isHexLiteral( token2, end );
    EXPECT_FALSE( result );

    char token3[] = "lala";
    result = isHexLiteral( token3, end );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isReferenceTest ) {
    size_t len( 0 );
    char token1[] = "ref";
    char *end = findEnd( token1, len );
    bool result = isReference( token1, end );
    EXPECT_TRUE( result );

    char token2[] = "rf";
    end = findEnd( token2, len );
    result = isReference( token2, end );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isSpaceTest ) {
    bool result( false );
    char val;
    val = ' ';
    result = isSpace( val );
    EXPECT_TRUE( result );

    val = '\t';
    result = isSpace( val );
    EXPECT_TRUE( result );

    val = '1';
    result = isSpace( val );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isNewLineTest ) {
    bool result( false );
    char val;
    val = '\n';
    result = isNewLine( val );
    EXPECT_TRUE( result );

    val = '\r';
    result = isNewLine( val );
    EXPECT_TRUE( result );

    val = ' ';
    result = isNewLine( val );
    EXPECT_FALSE( result );
}

TEST_F( OpenDDLParserUtilsTest, isSeparatorTest ) {
    char val;
    val = ' ';
    EXPECT_TRUE( isSeparator( val ) );
    val = '\t';
    EXPECT_TRUE( isSeparator( val ) );
    val = '1';
    EXPECT_FALSE( isSeparator( val ) );
    val = 'a';
    EXPECT_FALSE( isSeparator( val ) );
    val = 'Z';
    EXPECT_FALSE( isSeparator( val ) );
    val = '{';
    EXPECT_TRUE( isSeparator( val ) );
    val = '}';
    EXPECT_TRUE( isSeparator( val ) );
    val = '[';
    EXPECT_TRUE( isSeparator( val ) );
}

END_ODDLPARSER_NS
<|endoftext|>


<commit_before>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5pp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY
// 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., 51 Franklin Street, Fifth Floor
// Boston, MA  02110-1301 USA
// ===========================================================================
//
// Authors:
//    Eugen Wintersberger <eugen.wintersberger@desy.de>
//    Martin Shetty <martin.shetty@esss.se>
// Created on: Oct 19, 2017
//

#include <gtest/gtest.h>
#include <h5cpp/datatype/datatype.hpp>

using namespace hdf5;
using namespace hdf5::datatype;

TEST(Datatype, Constructors)
{
  Datatype a(ObjectHandle(H5Tcopy(H5T_NATIVE_INT)));
  EXPECT_TRUE(a.get_class()==Class::INTEGER);

  auto b = Datatype(ObjectHandle(H5Tcopy(H5T_NATIVE_INT)));
  EXPECT_TRUE(b.get_class()==Class::INTEGER);

  Datatype c = b = a;
  EXPECT_TRUE(c.get_class()==Class::INTEGER);
  EXPECT_NE(static_cast<hid_t>(a), static_cast<hid_t>(b));
  EXPECT_NE(static_cast<hid_t>(b), static_cast<hid_t>(c));
  EXPECT_NE(static_cast<hid_t>(a), static_cast<hid_t>(c));

  Datatype d(b);
  EXPECT_TRUE(d.get_class()==Class::INTEGER);
  EXPECT_NE(static_cast<hid_t>(d), static_cast<hid_t>(b));

  Datatype x;
  Datatype y;
  EXPECT_THROW(y=x, std::runtime_error);
  EXPECT_THROW(y=Datatype(x), std::runtime_error);
}

<commit_msg>better tests for Datatype #1<commit_after>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5pp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY
// 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., 51 Franklin Street, Fifth Floor
// Boston, MA  02110-1301 USA
// ===========================================================================
//
// Authors:
//    Eugen Wintersberger <eugen.wintersberger@desy.de>
//    Martin Shetty <martin.shetty@esss.se>
// Created on: Oct 19, 2017
//

#include <gtest/gtest.h>
#include <h5cpp/datatype/datatype.hpp>

using namespace hdf5;
using namespace hdf5::datatype;

TEST(Datatype, ConstructCopy)
{
  Datatype a(ObjectHandle(H5Tcopy(H5T_NATIVE_INT)));
  EXPECT_TRUE(a.get_class()==Class::INTEGER);

  auto b = Datatype(ObjectHandle(H5Tcopy(H5T_NATIVE_INT)));
  EXPECT_TRUE(b.get_class()==Class::INTEGER);

  Datatype c = b = a;
  EXPECT_TRUE(c.get_class()==Class::INTEGER);
  EXPECT_NE(static_cast<hid_t>(a), static_cast<hid_t>(b));
  EXPECT_NE(static_cast<hid_t>(b), static_cast<hid_t>(c));
  EXPECT_NE(static_cast<hid_t>(a), static_cast<hid_t>(c));

  Datatype d(b);
  EXPECT_TRUE(d.get_class()==Class::INTEGER);
  EXPECT_NE(static_cast<hid_t>(d), static_cast<hid_t>(b));

  Datatype x;
  Datatype y;
  EXPECT_THROW(y=x, std::runtime_error);
  EXPECT_THROW(y=Datatype(x), std::runtime_error);
}

TEST(Datatype, GetClass)
{
  Datatype a;
//  EXPECT_TRUE(a.get_class()==Class::NONE);

  a = Datatype(ObjectHandle(H5Tcopy(H5T_NATIVE_INT)));
  EXPECT_TRUE(a.get_class()==Class::INTEGER);

  a = Datatype(ObjectHandle(H5Tcopy(H5T_NATIVE_FLOAT)));
  EXPECT_TRUE(a.get_class()==Class::FLOAT);

  a = Datatype(ObjectHandle(H5Tcreate(H5T_STRING,1)));
  EXPECT_TRUE(a.get_class()==Class::STRING);

  a = Datatype(ObjectHandle(H5Tcreate(H5T_COMPOUND,1)));
  EXPECT_TRUE(a.get_class()==Class::COMPOUND);

  a = Datatype(ObjectHandle(H5Tcreate(H5T_OPAQUE,1)));
  EXPECT_TRUE(a.get_class()==Class::OPAQUE);

  a = Datatype(ObjectHandle(H5Tcreate(H5T_ENUM,1)));
  EXPECT_TRUE(a.get_class()==Class::ENUM);

//  a = Datatype(ObjectHandle(H5Tcreate(H5T_BITFIELD,1)));
//  a = Datatype(ObjectHandle(H5Tcopy(H5T_BITFIELD)));
//  EXPECT_TRUE(a.get_class()==Class::BITFIELD);

//  a = Datatype(ObjectHandle(H5Tcopy(H5T_REFERENCE)));
//  EXPECT_TRUE(a.get_class()==Class::REFERENCE);

//  a = Datatype(ObjectHandle(H5Tcreate(static_cast<H5T_class_t>(Class::TIME),1)));
//  EXPECT_TRUE(a.get_class()==Class::TIME);

}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_LOCALOPERATOR_INTERFACES_HH
#define DUNE_GDT_LOCALOPERATOR_INTERFACES_HH

#include <vector>

#include <dune/common/dynmatrix.hh>

#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/type_utils.hh>
#include <dune/stuff/functions/interfaces.hh>

#include <dune/gdt/discretefunction/local.hh>

namespace Dune {
namespace GDT {

template <class Traits>
class LocalOperatorInterface : public Stuff::CRTPInterface<LocalOperatorInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   * \brief Applies the local operator.
   * \param source Should be a Stuff::LocalizableFunctionInterface or a ConstDiscreteFunction.
   */
  template <class SourceType, class RangeSpaceType, class VectorType>
  void apply(const SourceType& source, LocalDiscreteFunction<RangeSpaceType, VectorType>& local_range) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply(source, local_range));
  }
}; // class LocalVolumeTwoFormInterface

template <class Traits>
class LocalVolumeTwoFormInterface : public Stuff::CRTPInterface<LocalVolumeTwoFormInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   *  \brief Applies the local operator as a two-form.
   *  \tparam T       Traits of the test Stuff::LocalfunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {test_base,ansatz_base}
   *  \tparam rC{T,a} dimRangeCols of the {test_base,ansatz_base}
   */
  template <class T, class A, class D, size_t d, class R, size_t rT, size_t rCT, size_t rA, size_t rCA>
  void apply2(const Stuff::LocalfunctionSetInterface<T, D, d, R, rT, rCT>& test_base,
              const Stuff::LocalfunctionSetInterface<A, D, d, R, rA, rCA>& ansatz_base,
              Dune::DynamicMatrix<R>& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply2(test_base, ansatz_base, ret));
  }
}; // class LocalVolumeTwoFormInterface

namespace internal {

template <class Tt>
struct is_local_operator_helper
{
  DSC_has_typedef_initialize_once(Traits)

      static const bool is_candidate = DSC_has_typedef(Traits)<Tt>::value;
};

template <class Tt>
struct is_local_volume_twoform_helper
{
  DSC_has_typedef_initialize_once(Traits)

      static const bool is_candidate = DSC_has_typedef(Traits)<Tt>::value;
};

} // namespace internal

template <class T, bool candidate = internal::is_local_operator_helper<T>::is_candidate>
struct is_local_operator : public std::is_base_of<LocalOperatorInterface<typename T::Traits>, T>
{
};

template <class T>
struct is_local_operator<T, false> : public std::false_type
{
};

template <class T, bool candidate = internal::is_local_volume_twoform_helper<T>::is_candidate>
struct is_local_volume_twoform : public std::is_base_of<LocalVolumeTwoFormInterface<typename T::Traits>, T>
{
};

template <class T>
struct is_local_volume_twoform<T, false> : public std::false_type
{
};

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCALOPERATOR_INTERFACES_HH
<commit_msg>[localoperator.interfaces] add first draft of LocalCouplingTwoFormInterface<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_LOCALOPERATOR_INTERFACES_HH
#define DUNE_GDT_LOCALOPERATOR_INTERFACES_HH

#include <vector>

#include <dune/common/dynmatrix.hh>

#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/type_utils.hh>
#include <dune/stuff/functions/interfaces.hh>

#include <dune/gdt/discretefunction/local.hh>

namespace Dune {
namespace GDT {

template <class Traits>
class LocalOperatorInterface : public Stuff::CRTPInterface<LocalOperatorInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   * \brief Applies the local operator.
   * \param source Should be a Stuff::LocalizableFunctionInterface or a ConstDiscreteFunction.
   */
  template <class SourceType, class RangeSpaceType, class VectorType>
  void apply(const SourceType& source, LocalDiscreteFunction<RangeSpaceType, VectorType>& local_range) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply(source, local_range));
  }
}; // class LocalVolumeTwoFormInterface

template <class Traits>
class LocalVolumeTwoFormInterface : public Stuff::CRTPInterface<LocalVolumeTwoFormInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   *  \brief Applies the local operator as a two-form.
   *  \tparam T       Traits of the test Stuff::LocalfunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {test_base,ansatz_base}
   *  \tparam rC{T,a} dimRangeCols of the {test_base,ansatz_base}
   */
  template <class T, class A, class D, size_t d, class R, size_t rT, size_t rCT, size_t rA, size_t rCA>
  void apply2(const Stuff::LocalfunctionSetInterface<T, D, d, R, rT, rCT>& test_base,
              const Stuff::LocalfunctionSetInterface<A, D, d, R, rA, rCA>& ansatz_base,
              Dune::DynamicMatrix<R>& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply2(test_base, ansatz_base, ret));
  }
}; // class LocalVolumeTwoFormInterface

template <class Traits>
class LocalCouplingTwoFormInterface : public Stuff::CRTPInterface<LocalCouplingTwoFormInterface<Traits>, Traits>
{
public:
  typedef typename Traits::derived_type derived_type;

  /**
   *  \brief Applies the local operator associated with inner faces as a two-form.
   *  \tparam TE      Traits of the entity test Stuff::LocalfunctionSetInterface implementation
   *  \tparam AE      Traits of the entity ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam TN      Traits of the neighbor test Stuff::LocalfunctionSetInterface implementation
   *  \tparam AN      Traits of the neighbor ansatz Stuff::LocalfunctionSetInterface implementation
   *  \tparam IntersectionType
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {test_base*,ansatz_base*}
   *  \tparam rC{T,a} dimRangeCols of the {test_base*,ansatz_base*}
   */
  template <class TE, class AE, class TN, class AN, class IntersectionType, class D, size_t d, class R, size_t rT,
            size_t rCT, size_t rA, size_t rCA>
  void apply2(const Stuff::LocalfunctionSetInterface<TE, D, d, R, rT, rCT>& test_base_entity,
              const Stuff::LocalfunctionSetInterface<AE, D, d, R, rA, rCA>& ansatz_base_entity,
              const Stuff::LocalfunctionSetInterface<TN, D, d, R, rT, rCT>& test_base_neighbor,
              const Stuff::LocalfunctionSetInterface<AN, D, d, R, rA, rCA>& ansatz_base_neighbor,
              const IntersectionType& intersection, Dune::DynamicMatrix<R>& entityEntityRet,
              Dune::DynamicMatrix<R>& neighborNeighborRet, Dune::DynamicMatrix<R>& entityNeighborRet,
              Dune::DynamicMatrix<R>& neighborEntityRet) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().apply2(test_base_entity,
                                              ansatz_base_entity,
                                              test_base_neighbor,
                                              ansatz_base_neighbor,
                                              intersection,
                                              entityEntityRet,
                                              neighborNeighborRet,
                                              entityNeighborRet,
                                              neighborEntityRet));
  }
}; // class LocalCouplingTwoFormInterface

namespace internal {

template <class Tt>
struct is_local_operator_helper
{
  DSC_has_typedef_initialize_once(Traits)

      static const bool is_candidate = DSC_has_typedef(Traits)<Tt>::value;
};

template <class Tt>
struct is_local_volume_twoform_helper
{
  DSC_has_typedef_initialize_once(Traits)

      static const bool is_candidate = DSC_has_typedef(Traits)<Tt>::value;
};

} // namespace internal

template <class T, bool candidate = internal::is_local_operator_helper<T>::is_candidate>
struct is_local_operator : public std::is_base_of<LocalOperatorInterface<typename T::Traits>, T>
{
};

template <class T>
struct is_local_operator<T, false> : public std::false_type
{
};

template <class T, bool candidate = internal::is_local_volume_twoform_helper<T>::is_candidate>
struct is_local_volume_twoform : public std::is_base_of<LocalVolumeTwoFormInterface<typename T::Traits>, T>
{
};

template <class T>
struct is_local_volume_twoform<T, false> : public std::false_type
{
};

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCALOPERATOR_INTERFACES_HH
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

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 "config.h"
#include "bundle_compiler.h"
#include "vector.h"
#include "dynamic_string.h"
#include "allocator.h"
#include "os.h"
#include "log.h"
#include "resource.h"
#include "path.h"
#include "disk_filesystem.h"
#include "compile_options.h"
#include "resource_registry.h"
#include <inttypes.h>

namespace crown
{

BundleCompiler::BundleCompiler(const char* source_dir, const char* bundle_dir)
	: _source_fs(source_dir)
	, _bundle_fs(bundle_dir)
{
	DiskFilesystem temp;
	temp.create_directory(bundle_dir);
}

bool BundleCompiler::compile(const char* type, const char* name, Platform::Enum platform)
{
	const ResourceId id(type, name);
	char out_name[512];
	snprintf(out_name, 512, "%.16"PRIx64"-%.16"PRIx64, id.type, id.name);
	char path[512];
	snprintf(path, 512, "%s.%s", name, type);

	CE_LOGI("%s <= %s.%s", out_name, name, type);

	File* outf = _bundle_fs.open(out_name, FOM_WRITE);
	CompileOptions opts(_source_fs, outf, platform);
	resource_on_compile(id.type, path, opts);
	_bundle_fs.close(outf);
}

bool BundleCompiler::compile_all(Platform::Enum platform)
{
	Vector<DynamicString> files(default_allocator());
	BundleCompiler::scan("", files);

	if (!_source_fs.is_file("crown.config"))
	{
		CE_LOGD("'crown.config' does not exist.");
		return false;
	}

	File* src = _source_fs.open("crown.config", FOM_READ);
	File* dst = _bundle_fs.open("crown.config", FOM_WRITE);
	src->copy_to(*dst, src->size());
	_source_fs.close(src);
	_bundle_fs.close(dst);

	// Compile all resources
	for (uint32_t i = 0; i < vector::size(files); i++)
	{
		if (files[i].ends_with(".tga")
			|| files[i].ends_with(".dds")
			|| files[i].ends_with(".sh")
			|| files[i].ends_with(".sc")
			|| files[i].starts_with(".")
			|| files[i].ends_with(".config"))
		continue;

		const char* filename = files[i].c_str();
		char type[256];
		char name[256];
		path::extension(filename, type, 256);
		path::filename_without_extension(filename, name, 256);

		compile(type, name, platform);
	}

	return true;
}

void BundleCompiler::scan(const char* cur_dir, Vector<DynamicString>& files)
{
	Vector<DynamicString> my_files(default_allocator());

	_source_fs.list_files(cur_dir, my_files);

	for (uint32_t i = 0; i < vector::size(my_files); i++)
	{
		DynamicString file_i(default_allocator());

		if (string::strcmp(cur_dir, "") != 0)
		{
			file_i += cur_dir;
			file_i += '/';
		}
		file_i += my_files[i];

		if (_source_fs.is_directory(file_i.c_str()))
		{
			BundleCompiler::scan(file_i.c_str(), files);
		}
		else // Assume a regular file
		{
			vector::push_back(files, file_i);
		}
	}
}

namespace bundle_compiler
{
	bool main(bool do_compile, bool do_continue, Platform::Enum platform)
	{
		if (do_compile)
		{
			bool ok = bundle_compiler_globals::compiler()->compile_all(platform);
			if (!ok || !do_continue)
			{
				return false;
			}
		}

		return true;
	}
} // namespace bundle_compiler

namespace bundle_compiler_globals
{
	char _buffer[sizeof(BundleCompiler)];
	BundleCompiler* _compiler = NULL;

	void init(const char* source_dir, const char* bundle_dir)
	{
#if CROWN_PLATFORM_LINUX || CROWN_PLATFORM_WINDOWS
		_compiler = new (_buffer) BundleCompiler(source_dir, bundle_dir);
#endif
	}

	void shutdown()
	{
		_compiler->~BundleCompiler();
		_compiler = NULL;
	}

	BundleCompiler* compiler()
	{
		return _compiler;
	}
} // namespace bundle_compiler_globals
} // namespace crown
<commit_msg>Ignore some more extensions<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

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 "config.h"
#include "bundle_compiler.h"
#include "vector.h"
#include "dynamic_string.h"
#include "allocator.h"
#include "os.h"
#include "log.h"
#include "resource.h"
#include "path.h"
#include "disk_filesystem.h"
#include "compile_options.h"
#include "resource_registry.h"
#include <inttypes.h>

namespace crown
{

BundleCompiler::BundleCompiler(const char* source_dir, const char* bundle_dir)
	: _source_fs(source_dir)
	, _bundle_fs(bundle_dir)
{
	DiskFilesystem temp;
	temp.create_directory(bundle_dir);
}

bool BundleCompiler::compile(const char* type, const char* name, Platform::Enum platform)
{
	const ResourceId id(type, name);
	char out_name[512];
	snprintf(out_name, 512, "%.16"PRIx64"-%.16"PRIx64, id.type, id.name);
	char path[512];
	snprintf(path, 512, "%s.%s", name, type);

	CE_LOGI("%s <= %s.%s", out_name, name, type);

	File* outf = _bundle_fs.open(out_name, FOM_WRITE);
	CompileOptions opts(_source_fs, outf, platform);
	resource_on_compile(id.type, path, opts);
	_bundle_fs.close(outf);
}

bool BundleCompiler::compile_all(Platform::Enum platform)
{
	Vector<DynamicString> files(default_allocator());
	BundleCompiler::scan("", files);

	if (!_source_fs.is_file("crown.config"))
	{
		CE_LOGD("'crown.config' does not exist.");
		return false;
	}

	File* src = _source_fs.open("crown.config", FOM_READ);
	File* dst = _bundle_fs.open("crown.config", FOM_WRITE);
	src->copy_to(*dst, src->size());
	_source_fs.close(src);
	_bundle_fs.close(dst);

	// Compile all resources
	for (uint32_t i = 0; i < vector::size(files); i++)
	{
		if (files[i].ends_with(".tga")
			|| files[i].ends_with(".dds")
			|| files[i].ends_with(".sh")
			|| files[i].ends_with(".sc")
			|| files[i].starts_with(".")
			|| files[i].ends_with(".config")
			|| files[i].ends_with(".tmp")
			|| files[i].ends_with(".wav"))
		continue;

		const char* filename = files[i].c_str();
		char type[256];
		char name[256];
		path::extension(filename, type, 256);
		path::filename_without_extension(filename, name, 256);

		compile(type, name, platform);
	}

	return true;
}

void BundleCompiler::scan(const char* cur_dir, Vector<DynamicString>& files)
{
	Vector<DynamicString> my_files(default_allocator());

	_source_fs.list_files(cur_dir, my_files);

	for (uint32_t i = 0; i < vector::size(my_files); i++)
	{
		DynamicString file_i(default_allocator());

		if (string::strcmp(cur_dir, "") != 0)
		{
			file_i += cur_dir;
			file_i += '/';
		}
		file_i += my_files[i];

		if (_source_fs.is_directory(file_i.c_str()))
		{
			BundleCompiler::scan(file_i.c_str(), files);
		}
		else // Assume a regular file
		{
			vector::push_back(files, file_i);
		}
	}
}

namespace bundle_compiler
{
	bool main(bool do_compile, bool do_continue, Platform::Enum platform)
	{
		if (do_compile)
		{
			bool ok = bundle_compiler_globals::compiler()->compile_all(platform);
			if (!ok || !do_continue)
			{
				return false;
			}
		}

		return true;
	}
} // namespace bundle_compiler

namespace bundle_compiler_globals
{
	char _buffer[sizeof(BundleCompiler)];
	BundleCompiler* _compiler = NULL;

	void init(const char* source_dir, const char* bundle_dir)
	{
#if CROWN_PLATFORM_LINUX || CROWN_PLATFORM_WINDOWS
		_compiler = new (_buffer) BundleCompiler(source_dir, bundle_dir);
#endif
	}

	void shutdown()
	{
		_compiler->~BundleCompiler();
		_compiler = NULL;
	}

	BundleCompiler* compiler()
	{
		return _compiler;
	}
} // namespace bundle_compiler_globals
} // namespace crown
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "reply_message.h"
#include "replies.pb.h"

// Test that basic message serializing work
TEST(MessagesReply, basic_serialize_reply) {
	std::string bytes;
	traffic::ReplyMessage msg;

	msg.serialize(bytes);
	ASSERT_TRUE(bytes.size() != 0U);

	replies::Reply rep;
	rep.ParseFromString(bytes);

	EXPECT_EQ(rep.Payload_case(), replies::Reply::PAYLOAD_NOT_SET);
	EXPECT_EQ(rep.version(), 1U);
}

// Test Summary message generation
TEST(MessagesReply, summary_reply_message) {
	std::string bytes;
	traffic::SummaryReply msg;

	msg.add_entry("1.1.1.1", 10U, 20U);
	msg.add_entry("1.1.1.2", 30U, 40U);

	msg.serialize(bytes);
	ASSERT_TRUE(bytes.size() != 0U);

	replies::Reply rep;
	rep.ParseFromString(bytes);

	ASSERT_EQ(rep.Payload_case(), replies::Reply::kSummary);
	replies::Summary const &sum(rep.summary());
	EXPECT_EQ(sum.data_size(), 2);

	replies::SummaryEntry const &en1(sum.data(0));
	EXPECT_EQ(en1.address(), "1.1.1.1");
	EXPECT_EQ(en1.sum_traffic_in(), 10U);
	EXPECT_EQ(en1.sum_traffic_out(), 20U);

	replies::SummaryEntry const &en2(sum.data(1));
	EXPECT_EQ(en2.address(), "1.1.1.2");
	EXPECT_EQ(en2.sum_traffic_in(), 30U);
	EXPECT_EQ(en2.sum_traffic_out(), 40U);
}

// test Statistic message generation
TEST(MessagesReply, statistic_reply_test) {
	std::string bytes;
	traffic::StatisticReply msg(1U, 2U, 3U);

	msg.add_slice(10U, 11U, 12U);
	msg.add_slice(20U, 21U, 22U);

	msg.serialize(bytes);

	replies::Reply rep;
	rep.ParseFromString(bytes);

	ASSERT_EQ(rep.Payload_case(), replies::Reply::kStatistic);
	replies::Statistic const &stat(rep.statistic());
	EXPECT_EQ(stat.slice_size(), 2);

	EXPECT_EQ(stat.data_interval_step(), 1U);
	EXPECT_EQ(stat.sum_traffic_in(), 2U);
	EXPECT_EQ(stat.sum_traffic_out(), 3U);

	replies::StatisticSlice const &sl1(stat.slice(0));
	EXPECT_EQ(sl1.timestamp(), 10U);
	EXPECT_EQ(sl1.traffic_in(), 11U);
	EXPECT_EQ(sl1.traffic_out(), 12U);

	replies::StatisticSlice const &sl2(stat.slice(1));
	EXPECT_EQ(sl2.timestamp(), 20U);
	EXPECT_EQ(sl2.traffic_in(), 21U);
	EXPECT_EQ(sl2.traffic_out(), 22U);
}

// test error message generation
TEST(MessagesReply, error_message_test) {
	std::string bytes;
	traffic::ErrorReply msg(2U, "TestPeng");

	msg.serialize(bytes);

	replies::Reply rep;
	rep.ParseFromString(bytes);

	ASSERT_EQ(rep.Payload_case(), replies::Reply::kError);
	replies::Error const &err(rep.error());

	EXPECT_EQ(err.code(), 2U);
	EXPECT_EQ(err.reason(), "TestPeng");
}
<commit_msg>Globally shut down protobuf library after testing<commit_after>#include "gtest/gtest.h"

#include "reply_message.h"
#include "replies.pb.h"

// Test that basic message serializing work
TEST(MessagesReply, basic_serialize_reply) {
	std::string bytes;
	traffic::ReplyMessage msg;

	msg.serialize(bytes);
	ASSERT_TRUE(bytes.size() != 0U);

	replies::Reply rep;
	rep.ParseFromString(bytes);

	EXPECT_EQ(rep.Payload_case(), replies::Reply::PAYLOAD_NOT_SET);
	EXPECT_EQ(rep.version(), 1U);
}

// Test Summary message generation
TEST(MessagesReply, summary_reply_message) {
	std::string bytes;
	traffic::SummaryReply msg;

	msg.add_entry("1.1.1.1", 10U, 20U);
	msg.add_entry("1.1.1.2", 30U, 40U);

	msg.serialize(bytes);
	ASSERT_TRUE(bytes.size() != 0U);

	replies::Reply rep;
	rep.ParseFromString(bytes);

	ASSERT_EQ(rep.Payload_case(), replies::Reply::kSummary);
	replies::Summary const &sum(rep.summary());
	EXPECT_EQ(sum.data_size(), 2);

	replies::SummaryEntry const &en1(sum.data(0));
	EXPECT_EQ(en1.address(), "1.1.1.1");
	EXPECT_EQ(en1.sum_traffic_in(), 10U);
	EXPECT_EQ(en1.sum_traffic_out(), 20U);

	replies::SummaryEntry const &en2(sum.data(1));
	EXPECT_EQ(en2.address(), "1.1.1.2");
	EXPECT_EQ(en2.sum_traffic_in(), 30U);
	EXPECT_EQ(en2.sum_traffic_out(), 40U);
}

// test Statistic message generation
TEST(MessagesReply, statistic_reply_test) {
	std::string bytes;
	traffic::StatisticReply msg(1U, 2U, 3U);

	msg.add_slice(10U, 11U, 12U);
	msg.add_slice(20U, 21U, 22U);

	msg.serialize(bytes);

	replies::Reply rep;
	rep.ParseFromString(bytes);

	ASSERT_EQ(rep.Payload_case(), replies::Reply::kStatistic);
	replies::Statistic const &stat(rep.statistic());
	EXPECT_EQ(stat.slice_size(), 2);

	EXPECT_EQ(stat.data_interval_step(), 1U);
	EXPECT_EQ(stat.sum_traffic_in(), 2U);
	EXPECT_EQ(stat.sum_traffic_out(), 3U);

	replies::StatisticSlice const &sl1(stat.slice(0));
	EXPECT_EQ(sl1.timestamp(), 10U);
	EXPECT_EQ(sl1.traffic_in(), 11U);
	EXPECT_EQ(sl1.traffic_out(), 12U);

	replies::StatisticSlice const &sl2(stat.slice(1));
	EXPECT_EQ(sl2.timestamp(), 20U);
	EXPECT_EQ(sl2.traffic_in(), 21U);
	EXPECT_EQ(sl2.traffic_out(), 22U);
}

// test error message generation
TEST(MessagesReply, error_message_test) {
	std::string bytes;
	traffic::ErrorReply msg(2U, "TestPeng");

	msg.serialize(bytes);

	replies::Reply rep;
	rep.ParseFromString(bytes);

	ASSERT_EQ(rep.Payload_case(), replies::Reply::kError);
	replies::Error const &err(rep.error());

	EXPECT_EQ(err.code(), 2U);
	EXPECT_EQ(err.reason(), "TestPeng");
}

/**
 * Shut down the protobuf library after the tests to make valgrind happy
 */
namespace {

class ShutdownEnvironment : public ::testing::Environment
{
public:
	void TearDown()
	{
		google::protobuf::ShutdownProtobufLibrary();
	}
};

::testing::Environment* const shutdown_env =
	::testing::AddGlobalTestEnvironment(new ShutdownEnvironment);
}
<|endoftext|>


<commit_before><commit_msg>Reconstruct the code and add parameter for customize color.<commit_after><|endoftext|>


<commit_before><commit_msg>Bug fix: internals.textSurroundingNode crashes when the node is NULL<commit_after><|endoftext|>


<commit_before><commit_msg>Fix unsigned to signed comparison warning<commit_after><|endoftext|>


<commit_before>
#include <KAI/Language/Pi/PiParser.h>
#include <KAI/Language/Common/Structure.h>

using namespace std;
using namespace boost;

KAI_BEGIN

bool PiParser::Process(std::shared_ptr<Lexer> lex, Structure st)
{
	current = 0;
	indent = 0;
	lexer = lex;

	if (lexer->Failed)
	{
		return Fail(lexer->Error);
	}

	// strip whitespace and comments
	for (auto tok : lexer->GetTokens())
		if (tok.type != TokenEnum::Whitespace && tok.type != TokenEnum::Comment)
			tokens.push_back(tok);

	root = NewNode(AstEnum::Continuation);

	return Run(st);
}

bool PiParser::Run(Structure st)
{
	KAI_UNUSED_1(st);
	while (!Failed && NextSingle(root))
		;

	return !Failed;
}

bool PiParser::NextSingle(AstNodePtr root)
{
	if (Empty())
		return false;

	auto tok = Current();
	switch (tok.type)
	{
	case PiTokens::CloseSquareBracket:
	case PiTokens::CloseBrace:
		Fail(Lexer::CreateErrorMessage(Current(), "%s", "Unopened compound"));
		return false;

	case PiTokens::OpenSquareBracket:
		Consume();
		return ParseArray(root);

	case PiTokens::OpenBrace:
		Consume();
		return ParseContinuation(root);

	case PiTokens::Clear:
	case PiTokens::Drop:
	case PiTokens::Dup:
	case PiTokens::Rot:
	case PiTokens::PickN:
	case PiTokens::Pathname:
	case PiTokens::String:
	case PiTokens::Int:
	case PiTokens::Float:
	case PiTokens::True:
	case PiTokens::False:
	case PiTokens::Plus:
	case PiTokens::Minus:
	case PiTokens::Mul:
	case PiTokens::Divide:
	case PiTokens::PlusAssign:
	case PiTokens::MinusAssign:
	case PiTokens::MulAssign:
	case PiTokens::DivAssign:
	default:
		root->Add(Consume());
		return true;
	}
}

bool PiParser::ParseArray(AstNodePtr root)
{
	auto node = NewNode(PiAstNodes::Array);
	while (!Failed && !Try(PiTokens::CloseSquareBracket))
	{
		if (!NextSingle(node))
		{
			Fail("Malformed Array");
			return false;
		}
	}

	if (Failed)
		return false;

	Consume();
	root->Add(node);

	return true;
}

bool PiParser::ParseContinuation(AstNodePtr root)
{
	AstNodePtr node = NewNode(PiAstNodes::Continuation);
	while (!Failed && !Try(PiTokenEnumType::CloseBrace))
	{
		if (!NextSingle(node))
		{
			Fail("Malformed Coro");
			return false;
		}
	}

	if (Failed)
		return false;
	Consume();

	root->Add(node);

	return true;
}

KAI_END
<commit_msg>Fixed bug in PiParser for malformed arrays causing a crash.<commit_after>
#include <KAI/Language/Pi/PiParser.h>
#include <KAI/Language/Common/Structure.h>

using namespace std;
using namespace boost;

KAI_BEGIN

bool PiParser::Process(std::shared_ptr<Lexer> lex, Structure st)
{
	current = 0;
	indent = 0;
	lexer = lex;

	if (lexer->Failed)
	{
		return Fail(lexer->Error);
	}

	// strip whitespace and comments
	for (auto tok : lexer->GetTokens())
		if (tok.type != TokenEnum::Whitespace && tok.type != TokenEnum::Comment)
			tokens.push_back(tok);

	root = NewNode(AstEnum::Continuation);

	return Run(st);
}

bool PiParser::Run(Structure st)
{
	KAI_UNUSED_1(st);
	while (!Failed && NextSingle(root))
		;

	return !Failed;
}

bool PiParser::NextSingle(AstNodePtr root)
{
	if (Empty())
		return false;

	auto tok = Current();
	switch (tok.type)
	{
	case PiTokens::CloseSquareBracket:
	case PiTokens::CloseBrace:
		Fail(Lexer::CreateErrorMessage(Current(), "%s", "Unopened compound"));
		return false;

	case PiTokens::OpenSquareBracket:
		Consume();
		return ParseArray(root);

	case PiTokens::OpenBrace:
		Consume();
		return ParseContinuation(root);

	case PiTokens::Clear:
	case PiTokens::Drop:
	case PiTokens::Dup:
	case PiTokens::Rot:
	case PiTokens::PickN:
	case PiTokens::Pathname:
	case PiTokens::String:
	case PiTokens::Int:
	case PiTokens::Float:
	case PiTokens::True:
	case PiTokens::False:
	case PiTokens::Plus:
	case PiTokens::Minus:
	case PiTokens::Mul:
	case PiTokens::Divide:
	case PiTokens::PlusAssign:
	case PiTokens::MinusAssign:
	case PiTokens::MulAssign:
	case PiTokens::DivAssign:
	default:
		root->Add(Consume());
		return true;
	}
}

bool PiParser::ParseArray(AstNodePtr root)
{
	auto node = NewNode(PiAstNodes::Array);
	while (!Empty() && !Failed && !Try(PiTokens::CloseSquareBracket))
	{
		if (!NextSingle(node))
		{
			Fail("Malformed Array");
			return false;
		}
	}

	if (Empty())
	{
		Fail("Malformed array");
		return false;
	}

	if (Failed)
		return false;

	Consume();
	root->Add(node);

	return true;
}

bool PiParser::ParseContinuation(AstNodePtr root)
{
	AstNodePtr node = NewNode(PiAstNodes::Continuation);
	while (!Failed && !Try(PiTokenEnumType::CloseBrace))
	{
		if (!NextSingle(node))
		{
			Fail("Malformed Coro");
			return false;
		}
	}

	if (Failed)
		return false;
	Consume();

	root->Add(node);

	return true;
}

KAI_END
<|endoftext|>


<commit_before>
#include "gtest/gtest.h"

#include "ColorDebug.hpp"
#include "DtwCgdaRecognition.hpp"

namespace teo
{

/**
 * @brief Tests ...
 */
class TestCgdaRecognitionLib : public testing::Test // -- inherit the Test class (gtest.h)
{

public:

    virtual void SetUp() {
        // -- code here will execute just before each test ensues
        cgdaRecognition = new DtwCgdaRecognition;
    }

    virtual void TearDown()
    {
        // -- code here will be called just after each test completes
        // -- ok to through exceptions from here if need be
        delete cgdaRecognition;
        cgdaRecognition = 0;
    }

protected:

    /** CgdaRecognition object. */
    CgdaRecognition* cgdaRecognition;
};

TEST_F( TestCgdaRecognitionLib, TestCgdaRecognitionLib_DTW_setGeneralized)
{
    std::vector<std::vector<double>> generalizedRandom;

    //-- test Generalized
    generalizedRandom.push_back({27,58,48,35,25});
    generalizedRandom.push_back({24,8,3453,48,89});
    generalizedRandom.push_back({24,58,22,58,47});
    bool ok = cgdaRecognition->setGeneralized( generalizedRandom );

    ASSERT_TRUE( ok );
}

TEST_F( TestCgdaRecognitionLib, TestCgdaRecognitionLib_DTW_compare)
{

    std::vector<std::vector<double>> generalizedRandom;
    std::vector<std::vector<double>> attempVectRandom;

    //-- test Generalized
    //Each push_back adds a new row.
    generalizedRandom.push_back({27,58,48,35,25});
    generalizedRandom.push_back({24,8,3453,48,89});
    generalizedRandom.push_back({24,58,22,58,47});
    cgdaRecognition->setGeneralized( generalizedRandom );

    //-- test compare
    attempVectRandom.push_back({23,54, 345, 2, 18794});
    attempVectRandom.push_back({4,58, 324, 12, 7847});

    double discrepancy;
    bool ok = cgdaRecognition->compare(attempVectRandom,discrepancy);

    ASSERT_TRUE( ok );
}

TEST_F( TestCgdaRecognitionLib, TestCgdaRecognitionLib_DTW_zero)
{
    std::vector<std::vector<double>> generalizedForZeroDiscrepancy;
    std::vector<std::vector<double>> attempVectforZeroDiscrepancy;

    //-- test Generalized
    generalizedForZeroDiscrepancy.push_back({27,58,48,35,25});
    generalizedForZeroDiscrepancy.push_back({24,8,3453,12,43});

    cgdaRecognition->setGeneralized( generalizedForZeroDiscrepancy );

    //-- test compare
    attempVectforZeroDiscrepancy.push_back({27,58,48,35,25});
    attempVectforZeroDiscrepancy.push_back({24,8,3453,12,43});

    double discrepancy;
    cgdaRecognition->compare(attempVectforZeroDiscrepancy,discrepancy);

    ASSERT_EQ( discrepancy, 0 );
}

TEST_F( TestCgdaRecognitionLib, TestCgdaRecognitionLib_DTW_simple)
{

    /*
     * The Matrix cost using euclidean distance is the following one.
     *  ------------>Generalized
     *  |  0    0    1
     *  |
     *  |  0    1    1
     *  |     \
     *  |  1    0    0
     *  |          \
     *  |  0    1    1
     *  "
     * Attemp
     *
     * The optimal path is the one in the figure, wich corresponds with the lower cost
     * of aligning both signals, in this case is one.
     */

    std::vector<std::vector<double>> generalizedForSimpleDiscrepancy;
    std::vector<std::vector<double>> attempVectforSimpleDiscrepancy;

    //-- test Generalized
    generalizedForSimpleDiscrepancy.push_back({0});
    generalizedForSimpleDiscrepancy.push_back({1});
    generalizedForSimpleDiscrepancy.push_back({1});

    cgdaRecognition->setGeneralized( generalizedForSimpleDiscrepancy );

    //-- test compare
    attempVectforSimpleDiscrepancy.push_back({0});
    attempVectforSimpleDiscrepancy.push_back({0});
    attempVectforSimpleDiscrepancy.push_back({1});
    attempVectforSimpleDiscrepancy.push_back({0});

    double discrepancy;
    cgdaRecognition->compare(attempVectforSimpleDiscrepancy,discrepancy);

    ASSERT_EQ( discrepancy, 1 );

}

}  // namespace teo

<commit_msg>cleaning<commit_after><|endoftext|>


<commit_before>#include "test/test_common/environment.h"

#include <sys/un.h>
#include <unistd.h>

#ifdef __has_include
#if __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
#endif
#endif
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include "common/common/assert.h"
#include "common/common/compiler_requirements.h"
#include "common/common/logger.h"
#include "common/common/macros.h"
#include "common/common/utility.h"

#include "server/options_impl.h"

#include "test/test_common/network_utility.h"

#include "absl/strings/match.h"
#include "gtest/gtest.h"
#include "spdlog/spdlog.h"

namespace Envoy {
namespace {

std::string makeTempDir(char* name_template) {
#ifdef WIN32
  char* dirname = ::_mktemp(name_template);
  RELEASE_ASSERT(dirname != nullptr,
                 fmt::format("failed to create tempdir: {} {}", dirname, strerror(errno)));
  std::experimental::filesystem::create_directories(dirname);
#else
  char* dirname = ::mkdtemp(name_template);
  RELEASE_ASSERT(dirname != nullptr,
                 fmt::format("failed to create tempdir: {} {}", dirname, strerror(errno)));
#endif
  return std::string(dirname);
}

std::string getOrCreateUnixDomainSocketDirectory() {
  const char* path = std::getenv("TEST_UDSDIR");
  if (path != nullptr) {
    return std::string(path);
  }
  // Generate temporary path for Unix Domain Sockets only. This is a workaround
  // for the sun_path limit on sockaddr_un, since TEST_TMPDIR as generated by
  // Bazel may be too long.
  char test_udsdir[] = "/tmp/envoy_test_uds.XXXXXX";
  return makeTempDir(test_udsdir);
}

std::string getTemporaryDirectory() {
  if (std::getenv("TEST_TMPDIR")) {
    return TestEnvironment::getCheckedEnvVar("TEST_TMPDIR");
  }
  if (std::getenv("TMPDIR")) {
    return TestEnvironment::getCheckedEnvVar("TMPDIR");
  }
  char test_tmpdir[] = "/tmp/envoy_test_tmp.XXXXXX";
  return makeTempDir(test_tmpdir);
}

// Allow initializeOptions() to remember CLI args for getOptions().
int argc_;
char** argv_;

} // namespace

void TestEnvironment::createPath(const std::string& path) {
#ifdef __cpp_lib_experimental_filesystem
  // We don't want to rely on mkdir etc. if we can avoid it, since it might not
  // exist in some environments such as ClusterFuzz.
  std::experimental::filesystem::create_directories(std::experimental::filesystem::path(path));
#else
  // No support on this system for std::experimental::filesystem.
  RELEASE_ASSERT(::system(("mkdir -p " + path).c_str()) == 0, "");
#endif
}

void TestEnvironment::createParentPath(const std::string& path) {
#ifdef __cpp_lib_experimental_filesystem
  // We don't want to rely on mkdir etc. if we can avoid it, since it might not
  // exist in some environments such as ClusterFuzz.
  std::experimental::filesystem::create_directories(
      std::experimental::filesystem::path(path).parent_path());
#else
  // No support on this system for std::experimental::filesystem.
  RELEASE_ASSERT(::system(("mkdir -p $(dirname " + path + ")").c_str()) == 0, "");
#endif
}

void TestEnvironment::removePath(const std::string& path) {
  RELEASE_ASSERT(absl::StartsWith(path, TestEnvironment::temporaryDirectory()), "");
#ifdef __cpp_lib_experimental_filesystem
  // We don't want to rely on rm etc. if we can avoid it, since it might not
  // exist in some environments such as ClusterFuzz.
  if (!std::experimental::filesystem::exists(path)) {
    return;
  }
  std::experimental::filesystem::remove_all(std::experimental::filesystem::path(path));
#else
  // No support on this system for std::experimental::filesystem.
  RELEASE_ASSERT(::system(("rm -rf " + path).c_str()) == 0, "");
#endif
}

absl::optional<std::string> TestEnvironment::getOptionalEnvVar(const std::string& var) {
  const char* path = std::getenv(var.c_str());
  if (path == nullptr) {
    return {};
  }
  return std::string(path);
}

std::string TestEnvironment::getCheckedEnvVar(const std::string& var) {
  auto optional = getOptionalEnvVar(var);
  RELEASE_ASSERT(optional.has_value(), "");
  return optional.value();
}

void TestEnvironment::initializeOptions(int argc, char** argv) {
  argc_ = argc;
  argv_ = argv;
}

bool TestEnvironment::shouldRunTestForIpVersion(Network::Address::IpVersion type) {
  const char* value = std::getenv("ENVOY_IP_TEST_VERSIONS");
  std::string option(value ? value : "");
  if (option.empty()) {
    return true;
  }
  if ((type == Network::Address::IpVersion::v4 && option == "v6only") ||
      (type == Network::Address::IpVersion::v6 && option == "v4only")) {
    return false;
  }
  return true;
}

std::vector<Network::Address::IpVersion> TestEnvironment::getIpVersionsForTest() {
  std::vector<Network::Address::IpVersion> parameters;
  for (auto version : {Network::Address::IpVersion::v4, Network::Address::IpVersion::v6}) {
    if (TestEnvironment::shouldRunTestForIpVersion(version)) {
      parameters.push_back(version);
      if (!Network::Test::supportsIpVersion(version)) {
        ENVOY_LOG_TO_LOGGER(Logger::Registry::getLog(Logger::Id::testing), warn,
                            "Testing with IP{} addresses may not be supported on this machine. If "
                            "testing fails, set the environment variable ENVOY_IP_TEST_VERSIONS.",
                            Network::Test::addressVersionAsString(version));
      }
    }
  }
  return parameters;
}

Server::Options& TestEnvironment::getOptions() {
  static OptionsImpl* options = new OptionsImpl(
      argc_, argv_, [](uint64_t, uint64_t, bool) { return "1"; }, spdlog::level::err);
  return *options;
}

const std::string& TestEnvironment::temporaryDirectory() {
  CONSTRUCT_ON_FIRST_USE(std::string, getTemporaryDirectory());
}

const std::string& TestEnvironment::runfilesDirectory() {
  CONSTRUCT_ON_FIRST_USE(std::string, getCheckedEnvVar("TEST_RUNDIR"));
}

const std::string TestEnvironment::unixDomainSocketDirectory() {
  CONSTRUCT_ON_FIRST_USE(std::string, getOrCreateUnixDomainSocketDirectory());
}

std::string TestEnvironment::substitute(const std::string& str,
                                        Network::Address::IpVersion version) {
  const std::unordered_map<std::string, std::string> path_map = {
      {"test_tmpdir", TestEnvironment::temporaryDirectory()},
      {"test_udsdir", TestEnvironment::unixDomainSocketDirectory()},
      {"test_rundir", TestEnvironment::runfilesDirectory()},
  };
  std::string out_json_string = str;
  for (auto it : path_map) {
    const std::regex port_regex("\\{\\{ " + it.first + " \\}\\}");
    out_json_string = std::regex_replace(out_json_string, port_regex, it.second);
  }

  // Substitute IP loopback addresses.
  const std::regex loopback_address_regex("\\{\\{ ip_loopback_address \\}\\}");
  out_json_string = std::regex_replace(out_json_string, loopback_address_regex,
                                       Network::Test::getLoopbackAddressUrlString(version));
  const std::regex ntop_loopback_address_regex("\\{\\{ ntop_ip_loopback_address \\}\\}");
  out_json_string = std::regex_replace(out_json_string, ntop_loopback_address_regex,
                                       Network::Test::getLoopbackAddressString(version));

  // Substitute IP any addresses.
  const std::regex any_address_regex("\\{\\{ ip_any_address \\}\\}");
  out_json_string = std::regex_replace(out_json_string, any_address_regex,
                                       Network::Test::getAnyAddressString(version));

  // Substitute dns lookup family.
  const std::regex lookup_family_regex("\\{\\{ dns_lookup_family \\}\\}");
  switch (version) {
  case Network::Address::IpVersion::v4:
    out_json_string = std::regex_replace(out_json_string, lookup_family_regex, "v4_only");
    break;
  case Network::Address::IpVersion::v6:
    out_json_string = std::regex_replace(out_json_string, lookup_family_regex, "v6_only");
    break;
  }

  return out_json_string;
}

std::string TestEnvironment::temporaryFileSubstitute(const std::string& path,
                                                     const PortMap& port_map,
                                                     Network::Address::IpVersion version) {
  return temporaryFileSubstitute(path, ParamMap(), port_map, version);
}

std::string TestEnvironment::readFileToStringForTest(const std::string& filename) {
  std::ifstream file(filename);
  if (file.fail()) {
    std::cerr << "failed to open: " << filename << std::endl;
    RELEASE_ASSERT(false, "");
  }

  std::stringstream file_string_stream;
  file_string_stream << file.rdbuf();
  return file_string_stream.str();
}

std::string TestEnvironment::temporaryFileSubstitute(const std::string& path,
                                                     const ParamMap& param_map,
                                                     const PortMap& port_map,
                                                     Network::Address::IpVersion version) {
  // Load the entire file as a string, regex replace one at a time and write it back out. Proper
  // templating might be better one day, but this works for now.
  const std::string json_path = TestEnvironment::runfilesPath(path);
  std::string out_json_string = readFileToStringForTest(json_path);

  // Substitute params.
  for (auto it : param_map) {
    const std::regex param_regex("\\{\\{ " + it.first + " \\}\\}");
    out_json_string = std::regex_replace(out_json_string, param_regex, it.second);
  }

  // Substitute ports.
  for (auto it : port_map) {
    const std::regex port_regex("\\{\\{ " + it.first + " \\}\\}");
    out_json_string = std::regex_replace(out_json_string, port_regex, std::to_string(it.second));
  }

  // Substitute paths and other common things.
  out_json_string = substitute(out_json_string, version);

  const std::string extension = absl::EndsWith(path, ".yaml") ? ".yaml" : ".json";
  const std::string out_json_path =
      TestEnvironment::temporaryPath(path + ".with.ports" + extension);
  createParentPath(out_json_path);
  {
    std::ofstream out_json_file(out_json_path);
    out_json_file << out_json_string;
  }
  return out_json_path;
}

Json::ObjectSharedPtr TestEnvironment::jsonLoadFromString(const std::string& json,
                                                          Network::Address::IpVersion version) {
  return Json::Factory::loadFromString(substitute(json, version));
}

void TestEnvironment::exec(const std::vector<std::string>& args) {
  std::stringstream cmd;
  // Symlinked args[0] can confuse Python when importing module relative, so we let Python know
  // where it can find its module relative files.
  cmd << "PYTHONPATH=$(dirname " << args[0] << ") ";
  for (auto& arg : args) {
    cmd << arg << " ";
  }
  if (::system(cmd.str().c_str()) != 0) {
    std::cerr << "Failed " << cmd.str() << "\n";
    RELEASE_ASSERT(false, "");
  }
}

std::string TestEnvironment::writeStringToFileForTest(const std::string& filename,
                                                      const std::string& contents) {
  const std::string out_path = TestEnvironment::temporaryPath(filename);
  createParentPath(out_path);
  unlink(out_path.c_str());
  {
    std::ofstream out_file(out_path);
    RELEASE_ASSERT(!out_file.fail(), "");
    out_file << contents;
  }
  return out_path;
}

void TestEnvironment::setEnvVar(const std::string& name, const std::string& value, int overwrite) {
#ifdef WIN32
  if (!overwrite) {
    size_t requiredSize;
    const int rc = ::getenv_s(&requiredSize, NULL, 0, name.c_str());
    ASSERT_EQ(rc, 0);
    if (requiredSize != 0) {
      return;
    }
  }
  const int rc = ::_putenv_s(name.c_str(), value.c_str());
  ASSERT_EQ(0, rc);
#else
  const int rc = ::setenv(name.c_str(), value.c_str(), overwrite);
  ASSERT_EQ(rc, 0);
#endif
}

} // namespace Envoy
<commit_msg>test: fix nullptr dereference. (#5533)<commit_after>#include "test/test_common/environment.h"

#include <sys/un.h>
#include <unistd.h>

#ifdef __has_include
#if __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
#endif
#endif
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include "common/common/assert.h"
#include "common/common/compiler_requirements.h"
#include "common/common/logger.h"
#include "common/common/macros.h"
#include "common/common/utility.h"

#include "server/options_impl.h"

#include "test/test_common/network_utility.h"

#include "absl/strings/match.h"
#include "gtest/gtest.h"
#include "spdlog/spdlog.h"

namespace Envoy {
namespace {

std::string makeTempDir(char* name_template) {
#ifdef WIN32
  char* dirname = ::_mktemp(name_template);
  RELEASE_ASSERT(dirname != nullptr, fmt::format("failed to create tempdir from template: {} {}",
                                                 name_template, strerror(errno)));
  std::experimental::filesystem::create_directories(dirname);
#else
  char* dirname = ::mkdtemp(name_template);
  RELEASE_ASSERT(dirname != nullptr, fmt::format("failed to create tempdir from template: {} {}",
                                                 name_template, strerror(errno)));
#endif
  return std::string(dirname);
}

std::string getOrCreateUnixDomainSocketDirectory() {
  const char* path = std::getenv("TEST_UDSDIR");
  if (path != nullptr) {
    return std::string(path);
  }
  // Generate temporary path for Unix Domain Sockets only. This is a workaround
  // for the sun_path limit on sockaddr_un, since TEST_TMPDIR as generated by
  // Bazel may be too long.
  char test_udsdir[] = "/tmp/envoy_test_uds.XXXXXX";
  return makeTempDir(test_udsdir);
}

std::string getTemporaryDirectory() {
  if (std::getenv("TEST_TMPDIR")) {
    return TestEnvironment::getCheckedEnvVar("TEST_TMPDIR");
  }
  if (std::getenv("TMPDIR")) {
    return TestEnvironment::getCheckedEnvVar("TMPDIR");
  }
  char test_tmpdir[] = "/tmp/envoy_test_tmp.XXXXXX";
  return makeTempDir(test_tmpdir);
}

// Allow initializeOptions() to remember CLI args for getOptions().
int argc_;
char** argv_;

} // namespace

void TestEnvironment::createPath(const std::string& path) {
#ifdef __cpp_lib_experimental_filesystem
  // We don't want to rely on mkdir etc. if we can avoid it, since it might not
  // exist in some environments such as ClusterFuzz.
  std::experimental::filesystem::create_directories(std::experimental::filesystem::path(path));
#else
  // No support on this system for std::experimental::filesystem.
  RELEASE_ASSERT(::system(("mkdir -p " + path).c_str()) == 0, "");
#endif
}

void TestEnvironment::createParentPath(const std::string& path) {
#ifdef __cpp_lib_experimental_filesystem
  // We don't want to rely on mkdir etc. if we can avoid it, since it might not
  // exist in some environments such as ClusterFuzz.
  std::experimental::filesystem::create_directories(
      std::experimental::filesystem::path(path).parent_path());
#else
  // No support on this system for std::experimental::filesystem.
  RELEASE_ASSERT(::system(("mkdir -p $(dirname " + path + ")").c_str()) == 0, "");
#endif
}

void TestEnvironment::removePath(const std::string& path) {
  RELEASE_ASSERT(absl::StartsWith(path, TestEnvironment::temporaryDirectory()), "");
#ifdef __cpp_lib_experimental_filesystem
  // We don't want to rely on rm etc. if we can avoid it, since it might not
  // exist in some environments such as ClusterFuzz.
  if (!std::experimental::filesystem::exists(path)) {
    return;
  }
  std::experimental::filesystem::remove_all(std::experimental::filesystem::path(path));
#else
  // No support on this system for std::experimental::filesystem.
  RELEASE_ASSERT(::system(("rm -rf " + path).c_str()) == 0, "");
#endif
}

absl::optional<std::string> TestEnvironment::getOptionalEnvVar(const std::string& var) {
  const char* path = std::getenv(var.c_str());
  if (path == nullptr) {
    return {};
  }
  return std::string(path);
}

std::string TestEnvironment::getCheckedEnvVar(const std::string& var) {
  auto optional = getOptionalEnvVar(var);
  RELEASE_ASSERT(optional.has_value(), "");
  return optional.value();
}

void TestEnvironment::initializeOptions(int argc, char** argv) {
  argc_ = argc;
  argv_ = argv;
}

bool TestEnvironment::shouldRunTestForIpVersion(Network::Address::IpVersion type) {
  const char* value = std::getenv("ENVOY_IP_TEST_VERSIONS");
  std::string option(value ? value : "");
  if (option.empty()) {
    return true;
  }
  if ((type == Network::Address::IpVersion::v4 && option == "v6only") ||
      (type == Network::Address::IpVersion::v6 && option == "v4only")) {
    return false;
  }
  return true;
}

std::vector<Network::Address::IpVersion> TestEnvironment::getIpVersionsForTest() {
  std::vector<Network::Address::IpVersion> parameters;
  for (auto version : {Network::Address::IpVersion::v4, Network::Address::IpVersion::v6}) {
    if (TestEnvironment::shouldRunTestForIpVersion(version)) {
      parameters.push_back(version);
      if (!Network::Test::supportsIpVersion(version)) {
        ENVOY_LOG_TO_LOGGER(Logger::Registry::getLog(Logger::Id::testing), warn,
                            "Testing with IP{} addresses may not be supported on this machine. If "
                            "testing fails, set the environment variable ENVOY_IP_TEST_VERSIONS.",
                            Network::Test::addressVersionAsString(version));
      }
    }
  }
  return parameters;
}

Server::Options& TestEnvironment::getOptions() {
  static OptionsImpl* options = new OptionsImpl(
      argc_, argv_, [](uint64_t, uint64_t, bool) { return "1"; }, spdlog::level::err);
  return *options;
}

const std::string& TestEnvironment::temporaryDirectory() {
  CONSTRUCT_ON_FIRST_USE(std::string, getTemporaryDirectory());
}

const std::string& TestEnvironment::runfilesDirectory() {
  CONSTRUCT_ON_FIRST_USE(std::string, getCheckedEnvVar("TEST_RUNDIR"));
}

const std::string TestEnvironment::unixDomainSocketDirectory() {
  CONSTRUCT_ON_FIRST_USE(std::string, getOrCreateUnixDomainSocketDirectory());
}

std::string TestEnvironment::substitute(const std::string& str,
                                        Network::Address::IpVersion version) {
  const std::unordered_map<std::string, std::string> path_map = {
      {"test_tmpdir", TestEnvironment::temporaryDirectory()},
      {"test_udsdir", TestEnvironment::unixDomainSocketDirectory()},
      {"test_rundir", TestEnvironment::runfilesDirectory()},
  };
  std::string out_json_string = str;
  for (auto it : path_map) {
    const std::regex port_regex("\\{\\{ " + it.first + " \\}\\}");
    out_json_string = std::regex_replace(out_json_string, port_regex, it.second);
  }

  // Substitute IP loopback addresses.
  const std::regex loopback_address_regex("\\{\\{ ip_loopback_address \\}\\}");
  out_json_string = std::regex_replace(out_json_string, loopback_address_regex,
                                       Network::Test::getLoopbackAddressUrlString(version));
  const std::regex ntop_loopback_address_regex("\\{\\{ ntop_ip_loopback_address \\}\\}");
  out_json_string = std::regex_replace(out_json_string, ntop_loopback_address_regex,
                                       Network::Test::getLoopbackAddressString(version));

  // Substitute IP any addresses.
  const std::regex any_address_regex("\\{\\{ ip_any_address \\}\\}");
  out_json_string = std::regex_replace(out_json_string, any_address_regex,
                                       Network::Test::getAnyAddressString(version));

  // Substitute dns lookup family.
  const std::regex lookup_family_regex("\\{\\{ dns_lookup_family \\}\\}");
  switch (version) {
  case Network::Address::IpVersion::v4:
    out_json_string = std::regex_replace(out_json_string, lookup_family_regex, "v4_only");
    break;
  case Network::Address::IpVersion::v6:
    out_json_string = std::regex_replace(out_json_string, lookup_family_regex, "v6_only");
    break;
  }

  return out_json_string;
}

std::string TestEnvironment::temporaryFileSubstitute(const std::string& path,
                                                     const PortMap& port_map,
                                                     Network::Address::IpVersion version) {
  return temporaryFileSubstitute(path, ParamMap(), port_map, version);
}

std::string TestEnvironment::readFileToStringForTest(const std::string& filename) {
  std::ifstream file(filename);
  if (file.fail()) {
    std::cerr << "failed to open: " << filename << std::endl;
    RELEASE_ASSERT(false, "");
  }

  std::stringstream file_string_stream;
  file_string_stream << file.rdbuf();
  return file_string_stream.str();
}

std::string TestEnvironment::temporaryFileSubstitute(const std::string& path,
                                                     const ParamMap& param_map,
                                                     const PortMap& port_map,
                                                     Network::Address::IpVersion version) {
  // Load the entire file as a string, regex replace one at a time and write it back out. Proper
  // templating might be better one day, but this works for now.
  const std::string json_path = TestEnvironment::runfilesPath(path);
  std::string out_json_string = readFileToStringForTest(json_path);

  // Substitute params.
  for (auto it : param_map) {
    const std::regex param_regex("\\{\\{ " + it.first + " \\}\\}");
    out_json_string = std::regex_replace(out_json_string, param_regex, it.second);
  }

  // Substitute ports.
  for (auto it : port_map) {
    const std::regex port_regex("\\{\\{ " + it.first + " \\}\\}");
    out_json_string = std::regex_replace(out_json_string, port_regex, std::to_string(it.second));
  }

  // Substitute paths and other common things.
  out_json_string = substitute(out_json_string, version);

  const std::string extension = absl::EndsWith(path, ".yaml") ? ".yaml" : ".json";
  const std::string out_json_path =
      TestEnvironment::temporaryPath(path + ".with.ports" + extension);
  createParentPath(out_json_path);
  {
    std::ofstream out_json_file(out_json_path);
    out_json_file << out_json_string;
  }
  return out_json_path;
}

Json::ObjectSharedPtr TestEnvironment::jsonLoadFromString(const std::string& json,
                                                          Network::Address::IpVersion version) {
  return Json::Factory::loadFromString(substitute(json, version));
}

void TestEnvironment::exec(const std::vector<std::string>& args) {
  std::stringstream cmd;
  // Symlinked args[0] can confuse Python when importing module relative, so we let Python know
  // where it can find its module relative files.
  cmd << "PYTHONPATH=$(dirname " << args[0] << ") ";
  for (auto& arg : args) {
    cmd << arg << " ";
  }
  if (::system(cmd.str().c_str()) != 0) {
    std::cerr << "Failed " << cmd.str() << "\n";
    RELEASE_ASSERT(false, "");
  }
}

std::string TestEnvironment::writeStringToFileForTest(const std::string& filename,
                                                      const std::string& contents) {
  const std::string out_path = TestEnvironment::temporaryPath(filename);
  createParentPath(out_path);
  unlink(out_path.c_str());
  {
    std::ofstream out_file(out_path);
    RELEASE_ASSERT(!out_file.fail(), "");
    out_file << contents;
  }
  return out_path;
}

void TestEnvironment::setEnvVar(const std::string& name, const std::string& value, int overwrite) {
#ifdef WIN32
  if (!overwrite) {
    size_t requiredSize;
    const int rc = ::getenv_s(&requiredSize, NULL, 0, name.c_str());
    ASSERT_EQ(rc, 0);
    if (requiredSize != 0) {
      return;
    }
  }
  const int rc = ::_putenv_s(name.c_str(), value.c_str());
  ASSERT_EQ(0, rc);
#else
  const int rc = ::setenv(name.c_str(), value.c_str(), overwrite);
  ASSERT_EQ(rc, 0);
#endif
}

} // namespace Envoy
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <memory>

#include "kangaru.hpp"

/**
 * This example explains advanced use of kangaru and it's components.
 * It covers overriding services
 */

using namespace std;
using namespace kgr;

struct Wand {
	virtual void doTrick() = 0;
};

struct MagicWand : Wand {
	void doTrick() override {
		cout << "It's doing magic tricks!" << endl;
	}
};

struct FireWand : MagicWand {
	void doTrick() override {
		cout << "It's doing fire tricks!" << endl;
	}
};

struct LavaWand : FireWand {
	void doTrick() override {
		cout << "It's doing lava tricks!" << endl;
	}
};

// Every following service_ptr will be shared_ptr.
struct Trickster {
	Trickster(service_ptr<Wand> _wand) : wand{move(_wand)} {}

	void doTrick() {
		wand->doTrick();
	}

private:
	service_ptr<Wand> wand;
};

struct Wizard {
	Wizard(service_ptr<MagicWand> _wand) : wand{move(_wand)} {}

	void doTrick() {
		wand->doTrick();
	}

private:
	service_ptr<MagicWand> wand;
};

struct FireMage {
	FireMage(service_ptr<FireWand> _wand) : wand{move(_wand)} {}

	void doTrick() {
		wand->doTrick();
	}

private:
	service_ptr<FireWand> wand;
};

struct MyContainer : Container {
	// This is the init function, we are initiating what we need to make the container behave correctly.
    virtual void init() {
		// MagicWand is the first, because it's the highest non-abstract service in the hierarchy.
		instance<MagicWand>();

		// FireWand is the second, because it's the second service in the hierarchy.
		instance<FireWand>();

		// LavaWand is the last, because it's the last service in the hierarchy.
		instance<LavaWand>();
    }
};

void c(service_ptr<Wizard>, service_ptr<FireWand>, service_ptr<FireMage>) {
	cout << "invoked" << endl;
}

// Service definitions must be in the kgr namespace
namespace kgr {

// This is our service definitions
template<> struct Service<Wand> : NoDependencies, Single {};
template<> struct Service<MagicWand> : NoDependencies, Overrides<Wand> {};
template<> struct Service<FireWand> : NoDependencies, Overrides<MagicWand> {};
template<> struct Service<LavaWand> : NoDependencies, Overrides<FireWand, MagicWand> {};
template<> struct Service<Trickster> : Dependency<Wand> {};
template<> struct Service<Wizard> : Dependency<MagicWand> {};
template<> struct Service<FireMage> : Dependency<FireWand> {};

}

int main()
{
	// The container type will be MyContainer.
	auto container = make_container<MyContainer>();

	auto trickster = container->service<Trickster>();
	auto wizard = container->service<Wizard>();
	auto fireMage = container->service<FireMage>();

	// The trickster will show "It's doing magic tricks!"
	// because the only service that overrides Wand is MagicWand.
	// Even if another service is overriding MagicWand, it does not overrides Wand.
	trickster->doTrick();

	// The trickster will show "It's doing lava tricks!"
	// because LavaWand overrides MagicWand, which was the Wizard's dependency.
	// Even if FireWand is overriding MagicWand, LavaWand is lower in the hierarchy,
	// which grants it priority (see MyContainer::init() for more detail).
	// A misconfigured hierarchy may lead to incorrect result. Invert instance calls and see by yourself.
	wizard->doTrick();

	// The trickster will show "It's doing lava tricks!"
	// because LavaWand is overriding FireWand.
	fireMage->doTrick();

	return 0;
}
<commit_msg>removed dead code<commit_after>#include <iostream>
#include <string>
#include <memory>

#include "kangaru.hpp"

/**
 * This example explains advanced use of kangaru and it's components.
 * It covers overriding services
 */

using namespace std;
using namespace kgr;

struct Wand {
	virtual void doTrick() = 0;
};

struct MagicWand : Wand {
	void doTrick() override {
		cout << "It's doing magic tricks!" << endl;
	}
};

struct FireWand : MagicWand {
	void doTrick() override {
		cout << "It's doing fire tricks!" << endl;
	}
};

struct LavaWand : FireWand {
	void doTrick() override {
		cout << "It's doing lava tricks!" << endl;
	}
};

// Every following service_ptr will be shared_ptr.
struct Trickster {
	Trickster(service_ptr<Wand> _wand) : wand{move(_wand)} {}

	void doTrick() {
		wand->doTrick();
	}

private:
	service_ptr<Wand> wand;
};

struct Wizard {
	Wizard(service_ptr<MagicWand> _wand) : wand{move(_wand)} {}

	void doTrick() {
		wand->doTrick();
	}

private:
	service_ptr<MagicWand> wand;
};

struct FireMage {
	FireMage(service_ptr<FireWand> _wand) : wand{move(_wand)} {}

	void doTrick() {
		wand->doTrick();
	}

private:
	service_ptr<FireWand> wand;
};

struct MyContainer : Container {
	// This is the init function, we are initiating what we need to make the container behave correctly.
    virtual void init() {
		// MagicWand is the first, because it's the highest non-abstract service in the hierarchy.
		instance<MagicWand>();

		// FireWand is the second, because it's the second service in the hierarchy.
		instance<FireWand>();

		// LavaWand is the last, because it's the last service in the hierarchy.
		instance<LavaWand>();
    }
};

// Service definitions must be in the kgr namespace
namespace kgr {

// This is our service definitions
template<> struct Service<Wand> : NoDependencies, Single {};
template<> struct Service<MagicWand> : NoDependencies, Overrides<Wand> {};
template<> struct Service<FireWand> : NoDependencies, Overrides<MagicWand> {};
template<> struct Service<LavaWand> : NoDependencies, Overrides<FireWand, MagicWand> {};
template<> struct Service<Trickster> : Dependency<Wand> {};
template<> struct Service<Wizard> : Dependency<MagicWand> {};
template<> struct Service<FireMage> : Dependency<FireWand> {};

}

int main()
{
	// The container type will be MyContainer.
	auto container = make_container<MyContainer>();

	auto trickster = container->service<Trickster>();
	auto wizard = container->service<Wizard>();
	auto fireMage = container->service<FireMage>();

	// The trickster will show "It's doing magic tricks!"
	// because the only service that overrides Wand is MagicWand.
	// Even if another service is overriding MagicWand, it does not overrides Wand.
	trickster->doTrick();

	// The trickster will show "It's doing lava tricks!"
	// because LavaWand overrides MagicWand, which was the Wizard's dependency.
	// Even if FireWand is overriding MagicWand, LavaWand is lower in the hierarchy,
	// which grants it priority (see MyContainer::init() for more detail).
	// A misconfigured hierarchy may lead to incorrect result. Invert instance calls and see by yourself.
	wizard->doTrick();

	// The trickster will show "It's doing lava tricks!"
	// because LavaWand is overriding FireWand.
	fireMage->doTrick();

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <memory>

#include "kangaru.hpp"

/**
 * This example explains advanced use of kangaru and it's components.
 * It covers invoke and autocall (injection by setters) through service map.
 */

// This is a utility macro to workaround the lack of type inference for non-type template parameter
// Will not be needed when N4469 will be accepted
#define METHOD(...) ::kgr::Method<decltype(__VA_ARGS__), __VA_ARGS__>

using namespace std;
using namespace kgr;

struct Keyboard {
	string switchColor;
};

struct Monitor {
	double size;
};

struct Mouse {
	int nbButton;
};

struct Speakers {
	int maxDb;
};

struct Computer {
	Computer(Keyboard& myKeyboard) : keyboard{myKeyboard} {}

	void setAccessories(Mouse& aMouse, Speakers& someSpeakers) {
		mouse = &aMouse;
		speakers = &someSpeakers;
	}

	void setMonitor(Monitor& aMonitor) {
		monitor = &aMonitor;
	}

	void printGear() const {
		cout << "This computer has a keyboard with " << keyboard.switchColor << " switches. " << endl;

		if (monitor) {
			cout << "    It got a " << monitor->size << " inch monitor." << endl;
		}

		if (mouse) {
			cout << "    It got a mouse with " << mouse->nbButton << " buttons." << endl;
		}

		if (speakers) {
			cout << "    It got speakers with a maximum of " << speakers->maxDb << " decibels." << endl;
		}

		cout << endl;
	}

private:
	Keyboard& keyboard;
	Monitor* monitor = nullptr;
	Mouse* mouse = nullptr;
	Speakers* speakers = nullptr;
};

// this is a struct that associate a type with a service.
// It will tell the container which service definition to pick when a specific type is encountered.
template<typename>
struct ServiceMap;

// service definitions
struct KeyboardService : SingleService<Keyboard> {};
struct MonitorService : SingleService<Monitor> {};
struct MouseService : SingleService<Mouse> {};
struct SpeakersService : SingleService<Speakers> {};

struct MinimalComputerService : Service<Computer, Dependency<KeyboardService>> {};

struct EquippedComputerService : Service<Computer, Dependency<KeyboardService>> {
	using invoke = kgr::Invoke<
		METHOD(&EquippedComputerService::autocall<METHOD(&Computer::setMonitor), MonitorService>)
	>;
};

// To which service definition do we refer when the function parameter 'Keyboard&' is found?
template<> struct ServiceMap<Keyboard&> : kgr::Map<KeyboardService> {};

// Same for the following...
template<> struct ServiceMap<Monitor&> : kgr::Map<MonitorService> {};
template<> struct ServiceMap<Mouse&> : kgr::Map<MouseService> {};
template<> struct ServiceMap<Speakers&> : kgr::Map<SpeakersService> {};

// A funtion to wash our favourite monitor and keyboard.
// A service will be needed to be used with invoke.
double washMonitorAndKeyboard(Monitor& monitor, Keyboard& keyboard) {
	cout << "Monitor of size of " << monitor.size
		 << " inch and a keyboard with " << keyboard.switchColor
		 << " switches has been washed." << endl;

	return 9.8;
}

int main()
{
	Container container;

	// getting our four pieces of hardware
	auto& keyboard = container.service<KeyboardService>();
	auto& monitor = container.service<MonitorService>();
	auto& mouse = container.service<MouseService>();
	auto& speakers = container.service<SpeakersService>();

	// and give them values.
	keyboard.switchColor = "blue";
	monitor.size = 19.5;
	mouse.nbButton = 3;
	speakers.maxDb = 80;

	// make two computers
	auto computer1 = container.service<EquippedComputerService>();
	auto computer2 = container.service<MinimalComputerService>();

	// computer 1 will print everything.
	computer1.printGear();
	// computer 2 will print only about the keyboard.
	computer2.printGear();

	// will call 'washMonitorAndKeyboard' with the right parameters.
	double result = container.invoke<ServiceMap>(washMonitorAndKeyboard);

	cout << "Result of washMonitorAndKeyboard is " << result << "!" << endl;

	return 0;
}
<commit_msg>example7 now has the same behaviour as before<commit_after>#include <iostream>
#include <string>
#include <memory>

#include "kangaru.hpp"

/**
 * This example explains advanced use of kangaru and it's components.
 * It covers invoke and autocall (injection by setters) through service map.
 */

// This is a utility macro to workaround the lack of type inference for non-type template parameter
// Will not be needed when N4469 will be accepted
#define METHOD(...) ::kgr::Method<decltype(__VA_ARGS__), __VA_ARGS__>

using namespace std;
using namespace kgr;

struct Keyboard {
	string switchColor;
};

struct Monitor {
	double size;
};

struct Mouse {
	int nbButton;
};

struct Speakers {
	int maxDb;
};

struct Computer {
	Computer(Keyboard& myKeyboard) : keyboard{myKeyboard} {}

	void setAccessories(Mouse& aMouse, Speakers& someSpeakers) {
		mouse = &aMouse;
		speakers = &someSpeakers;
	}

	void setMonitor(Monitor& aMonitor) {
		monitor = &aMonitor;
	}

	void printGear() const {
		cout << "This computer has a keyboard with " << keyboard.switchColor << " switches. " << endl;

		if (monitor) {
			cout << "    It got a " << monitor->size << " inch monitor." << endl;
		}

		if (mouse) {
			cout << "    It got a mouse with " << mouse->nbButton << " buttons." << endl;
		}

		if (speakers) {
			cout << "    It got speakers with a maximum of " << speakers->maxDb << " decibels." << endl;
		}

		cout << endl;
	}

private:
	Keyboard& keyboard;
	Monitor* monitor = nullptr;
	Mouse* mouse = nullptr;
	Speakers* speakers = nullptr;
};

// this is a struct that associate a type with a service.
// It will tell the container which service definition to pick when a specific type is encountered.
template<typename>
struct ServiceMap;

// service definitions
struct KeyboardService : SingleService<Keyboard> {};
struct MonitorService : SingleService<Monitor> {};
struct MouseService : SingleService<Mouse> {};
struct SpeakersService : SingleService<Speakers> {};

struct MinimalComputerService : Service<Computer, Dependency<KeyboardService>> {};

struct EquippedComputerService : Service<Computer, Dependency<KeyboardService>>, kgr::AutoCall<ServiceMap,
	METHOD(&Computer::setMonitor),
	METHOD(&Computer::setAccessories)> {};

// To which service definition do we refer when the function parameter 'Keyboard&' is found?
template<> struct ServiceMap<Keyboard&> : kgr::Map<KeyboardService> {};

// Same for the following...
template<> struct ServiceMap<Monitor&> : kgr::Map<MonitorService> {};
template<> struct ServiceMap<Mouse&> : kgr::Map<MouseService> {};
template<> struct ServiceMap<Speakers&> : kgr::Map<SpeakersService> {};

// A funtion to wash our favourite monitor and keyboard.
// A service will be needed to be used with invoke.
double washMonitorAndKeyboard(Monitor& monitor, Keyboard& keyboard) {
	cout << "Monitor of size of " << monitor.size
		 << " inch and a keyboard with " << keyboard.switchColor
		 << " switches has been washed." << endl;

	return 9.8;
}

int main()
{
	Container container;

	// getting our four pieces of hardware
	auto& keyboard = container.service<KeyboardService>();
	auto& monitor = container.service<MonitorService>();
	auto& mouse = container.service<MouseService>();
	auto& speakers = container.service<SpeakersService>();

	// and give them values.
	keyboard.switchColor = "blue";
	monitor.size = 19.5;
	mouse.nbButton = 3;
	speakers.maxDb = 80;

	// make two computers
	auto computer1 = container.service<EquippedComputerService>();
	auto computer2 = container.service<MinimalComputerService>();

	// computer 1 will print everything.
	computer1.printGear();
	// computer 2 will print only about the keyboard.
	computer2.printGear();

	// will call 'washMonitorAndKeyboard' with the right parameters.
	double result = container.invoke<ServiceMap>(washMonitorAndKeyboard);

	cout << "Result of washMonitorAndKeyboard is " << result << "!" << endl;

	return 0;
}
<|endoftext|>