<commit_before>#include <iostream>
#include <gtest/gtest.h>
#include "net/uri.hpp"

using namespace std::string_literals;
using namespace net;

TEST(NetURI,Parse1)
{
    auto raw = "http://kake:passwd@www.appinf.com:88/sample/isin?eq=FI123456789#frags"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;

    ASSERT_TRUE(parsed.absolute);
    ASSERT_EQ(parsed.scheme, "http");
    ASSERT_EQ(parsed.userinfo, "kake:passwd");
    ASSERT_EQ(parsed.host, "www.appinf.com");
    ASSERT_EQ(parsed.port, "88");
    ASSERT_EQ(parsed.path, "/sample/isin");
    ASSERT_EQ(parsed.path[0], "");
    ASSERT_EQ(parsed.path[1], "sample");
    ASSERT_EQ(parsed.path[2], "isin");
    ASSERT_EQ(parsed.query, "eq=FI123456789");
    ASSERT_EQ(parsed.fragment, "frags");
}

TEST(NetURI,Parse2)
{
    auto raw = "https://localhost/test/13"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;

    ASSERT_TRUE(parsed.absolute);
    ASSERT_EQ(parsed.scheme, "https");
    ASSERT_EQ(parsed.userinfo, "");
    ASSERT_EQ(parsed.host, "localhost");
    ASSERT_EQ(parsed.port, "");
    ASSERT_EQ(parsed.path, "/test/13");
    ASSERT_EQ(parsed.path[0], "");
    ASSERT_EQ(parsed.path[1], "test");
    ASSERT_EQ(parsed.path[2], "13");
    ASSERT_EQ(parsed.query, "");
    ASSERT_EQ(parsed.fragment, "");
}

TEST(NetURI,Parse3)
{
    auto raw = "urn:ISSN:1535–3613"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    // std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    // std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,Parse4)
{
    auto raw = "ftp://www.appinf.com:2112/sample/13#frags2"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,Parse5)
{
    auto raw = "ftp://kake@www.appinf.com:2112"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    // std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    // std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    // std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,ParseRelative1)
{
    auto raw = "../../sample/55#frags3"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;

    ASSERT_FALSE(parsed.absolute);
    ASSERT_EQ(parsed.scheme, "");
    ASSERT_EQ(parsed.userinfo, "");
    ASSERT_EQ(parsed.host, "");
    ASSERT_EQ(parsed.port, "");
    ASSERT_EQ(parsed.path, "../../sample/55");
    ASSERT_EQ(parsed.path[0], "..");
    ASSERT_EQ(parsed.path[1], "..");
    ASSERT_EQ(parsed.path[2], "sample");
    ASSERT_EQ(parsed.path[3], "55");
    ASSERT_EQ(parsed.query, "");
    ASSERT_EQ(parsed.fragment, "frags3");
}

TEST(NetURI,ParseRelative2)
{
    auto raw = "/sample/id?eg=13"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,ParseInvalid)
{
    auto raw = "ftp//www.appinf.com/sample/13#frags2"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,ParseRelative3)
{
    auto raw = "/xxx?tail=10"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,PortWithoutHost)
{
    auto raw = "FIXT1.1://KAKE@:2112/xxx?tail=10"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;

    ASSERT_TRUE(parsed.absolute);
    ASSERT_EQ(parsed.scheme, "FIXT1.1");
    ASSERT_EQ(parsed.userinfo, "KAKE");
    ASSERT_EQ(parsed.host, "");
    ASSERT_EQ(parsed.port, "2112");
    ASSERT_EQ(parsed.path, "/xxx");
    ASSERT_EQ(parsed.query, "tail=10");
    ASSERT_EQ(parsed.fragment, "");
}
<commit_msg>minor change<commit_after>#include <iostream>
#include <gtest/gtest.h>
#include "net/uri.hpp"

using namespace std::string_literals;
using namespace net;

TEST(NetURI,Parse1)
{
    auto raw = "http://kake:passwd@www.appinf.com:88/sample/isin?eq=FI123456789#frags"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;

    ASSERT_TRUE(parsed.absolute);
    ASSERT_EQ(parsed.scheme, "http");
    ASSERT_EQ(parsed.userinfo, "kake:passwd");
    ASSERT_EQ(parsed.host, "www.appinf.com");
    ASSERT_EQ(parsed.port, "88");
    ASSERT_EQ(parsed.path, "/sample/isin");
    ASSERT_EQ(parsed.path[0], "");
    ASSERT_EQ(parsed.path[1], "sample");
    ASSERT_EQ(parsed.path[2], "isin");
    ASSERT_EQ(parsed.query, "eq=FI123456789");
    ASSERT_EQ(parsed.fragment, "frags");
}

TEST(NetURI,Parse2)
{
    auto raw = "https://localhost/test/13"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;

    ASSERT_TRUE(parsed.absolute);
    ASSERT_EQ(parsed.scheme, "https");
    ASSERT_EQ(parsed.userinfo, "");
    ASSERT_EQ(parsed.host, "localhost");
    ASSERT_EQ(parsed.port, "");
    ASSERT_EQ(parsed.path, "/test/13");
    ASSERT_EQ(parsed.path[0], "");
    ASSERT_EQ(parsed.path[1], "test");
    ASSERT_EQ(parsed.path[2], "13");
    ASSERT_EQ(parsed.query, "");
    ASSERT_EQ(parsed.fragment, "");
}

TEST(NetURI,Parse3)
{
    auto raw = "urn:ISSN:1535–3613"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    // std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    // std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,Parse4)
{
    auto raw = "ftp://www.appinf.com:2112/sample/13#frags2"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,Parse5)
{
    auto raw = "ftp://kake@www.appinf.com:2112"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    // std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    // std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    // std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,ParseRelative1)
{
    auto raw = "../../sample/55#frags3"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;

    ASSERT_FALSE(parsed.absolute);
    ASSERT_EQ(parsed.scheme, "");
    ASSERT_EQ(parsed.userinfo, "");
    ASSERT_EQ(parsed.host, "");
    ASSERT_EQ(parsed.port, "");
    ASSERT_EQ(parsed.path, "../../sample/55");
    ASSERT_EQ(parsed.path[0], "..");
    ASSERT_EQ(parsed.path[1], "..");
    ASSERT_EQ(parsed.path[2], "sample");
    ASSERT_EQ(parsed.path[3], "55");
    ASSERT_EQ(parsed.query, "");
    ASSERT_EQ(parsed.fragment, "frags3");
}

TEST(NetURI,ParseRelative2)
{
    auto raw = "/sample/id?eg=13"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,ParseInvalid)
{
    auto raw = "ftp//www.appinf.com/sample/13#frags2"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Path[2]:  " << parsed.path[2]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,ParseRelative3)
{
    auto raw = "/xxx?tail=10"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;
}

TEST(NetURI,PortWithoutHost)
{
    auto raw = "FIXT.1.1://KAKE@:2112/xxx?tail=10"s;

    auto parsed = net::uri{raw};

    std::cout << "URI:      " << raw             << std::endl;
    std::cout << "Absolute: " << parsed.absolute << std::endl;
    std::cout << "Scheme:   " << parsed.scheme   << std::endl;
    std::cout << "Userinfo: " << parsed.userinfo << std::endl;
    std::cout << "Host:     " << parsed.host     << std::endl;
    std::cout << "Port:     " << parsed.port     << std::endl;
    std::cout << "Path:     " << parsed.path     << std::endl;
    std::cout << "Path[0]:  " << parsed.path[0]  << std::endl;
    std::cout << "Path[1]:  " << parsed.path[1]  << std::endl;
    std::cout << "Query:    " << parsed.query    << std::endl;
    std::cout << "Fragment: " << parsed.fragment << std::endl;

    ASSERT_TRUE(parsed.absolute);
    ASSERT_EQ(parsed.scheme, "FIXT.1.1");
    ASSERT_EQ(parsed.userinfo, "KAKE");
    ASSERT_EQ(parsed.host, "");
    ASSERT_EQ(parsed.port, "2112");
    ASSERT_EQ(parsed.path, "/xxx");
    ASSERT_EQ(parsed.query, "tail=10");
    ASSERT_EQ(parsed.fragment, "");
}
<|endoftext|>


<commit_before>#include "Runtime/World/CScriptPlayerHint.hpp"

#include "Runtime/CStateManager.hpp"
#include "Runtime/MP1/World/CMetroidPrimeRelay.hpp"
#include "Runtime/World/CActorParameters.hpp"
#include "Runtime/World/CPlayer.hpp"

#include "TCastTo.hpp" // Generated file, do not modify include path

namespace urde {

CScriptPlayerHint::CScriptPlayerHint(TUniqueId uid, std::string_view name, const CEntityInfo& info,
                                     const zeus::CTransform& xf, bool active, u32 priority, u32 overrideFlags)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), {EMaterialTypes::NoStepLogic},
         CActorParameters::None(), kInvalidUniqueId)
, x100_priority(priority)
, x104_overrideFlags(overrideFlags) {}

void CScriptPlayerHint::Accept(IVisitor& visit) { visit.Visit(this); }

void CScriptPlayerHint::AddToObjectList(TUniqueId uid) {
  for (TUniqueId existId : xe8_objectList)
    if (uid == existId)
      return;
  if (xe8_objectList.size() != 8)
    xe8_objectList.push_back(uid);
}

void CScriptPlayerHint::RemoveFromObjectList(TUniqueId uid) {
  for (auto it = xe8_objectList.begin(); it != xe8_objectList.end(); ++it) {
    if (*it == uid) {
      xe8_objectList.erase(it);
      return;
    }
  }
}

void CScriptPlayerHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
  switch (msg) {
  case EScriptObjectMessage::Deactivate:
  case EScriptObjectMessage::Deleted:
    RemoveFromObjectList(sender);
    mgr.GetPlayer().AddToPlayerHintRemoveList(GetUniqueId(), mgr);
    xfc_deactivated = true;
    break;
  case EScriptObjectMessage::Increment:
    x108_mpId = kInvalidUniqueId;
    if ((x104_overrideFlags & 0x4000) != 0) {
      for (const SConnection& conn : x20_conns) {
        if (conn.x0_state != EScriptObjectState::Play)
          continue;
        x108_mpId = mgr.GetIdForScript(conn.x8_objId);
        if (TCastToConstPtr<MP1::CMetroidPrimeRelay> mpRelay = mgr.GetObjectById(x108_mpId)) {
          x108_mpId = mpRelay->GetMetroidPrimeExoId();
          break;
        }
      }
    }
    break;
  default:
    break;
  }

  if (x30_24_active) {
    switch (msg) {
    case EScriptObjectMessage::Increment:
      AddToObjectList(sender);
      mgr.GetPlayer().AddToPlayerHintAddList(GetUniqueId(), mgr);
      xfc_deactivated = false;
      break;
    case EScriptObjectMessage::Decrement:
      RemoveFromObjectList(sender);
      mgr.GetPlayer().AddToPlayerHintRemoveList(GetUniqueId(), mgr);
      break;
    default:
      break;
    }
  }

  CActor::AcceptScriptMsg(msg, sender, mgr);
}

} // namespace urde<commit_msg>CScriptPlayerHint: Make use of std::any_of/std::find_if where applicable<commit_after>#include "Runtime/World/CScriptPlayerHint.hpp"

#include <algorithm>

#include "Runtime/CStateManager.hpp"
#include "Runtime/MP1/World/CMetroidPrimeRelay.hpp"
#include "Runtime/World/CActorParameters.hpp"
#include "Runtime/World/CPlayer.hpp"

#include "TCastTo.hpp" // Generated file, do not modify include path

namespace urde {

CScriptPlayerHint::CScriptPlayerHint(TUniqueId uid, std::string_view name, const CEntityInfo& info,
                                     const zeus::CTransform& xf, bool active, u32 priority, u32 overrideFlags)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), {EMaterialTypes::NoStepLogic},
         CActorParameters::None(), kInvalidUniqueId)
, x100_priority(priority)
, x104_overrideFlags(overrideFlags) {}

void CScriptPlayerHint::Accept(IVisitor& visit) { visit.Visit(this); }

void CScriptPlayerHint::AddToObjectList(TUniqueId uid) {
  const bool inList =
      std::any_of(xe8_objectList.cbegin(), xe8_objectList.cend(), [uid](const auto id) { return id == uid; });
  if (inList) {
    return;
  }

  if (xe8_objectList.size() == xe8_objectList.capacity()) {
    return;
  }

  xe8_objectList.push_back(uid);
}

void CScriptPlayerHint::RemoveFromObjectList(TUniqueId uid) {
  const auto iter =
      std::find_if(xe8_objectList.cbegin(), xe8_objectList.cend(), [uid](const auto id) { return id == uid; });

  if (iter == xe8_objectList.cend()) {
    return;
  }

  xe8_objectList.erase(iter);
}

void CScriptPlayerHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
  switch (msg) {
  case EScriptObjectMessage::Deactivate:
  case EScriptObjectMessage::Deleted:
    RemoveFromObjectList(sender);
    mgr.GetPlayer().AddToPlayerHintRemoveList(GetUniqueId(), mgr);
    xfc_deactivated = true;
    break;
  case EScriptObjectMessage::Increment:
    x108_mpId = kInvalidUniqueId;
    if ((x104_overrideFlags & 0x4000) != 0) {
      for (const SConnection& conn : x20_conns) {
        if (conn.x0_state != EScriptObjectState::Play)
          continue;
        x108_mpId = mgr.GetIdForScript(conn.x8_objId);
        if (TCastToConstPtr<MP1::CMetroidPrimeRelay> mpRelay = mgr.GetObjectById(x108_mpId)) {
          x108_mpId = mpRelay->GetMetroidPrimeExoId();
          break;
        }
      }
    }
    break;
  default:
    break;
  }

  if (x30_24_active) {
    switch (msg) {
    case EScriptObjectMessage::Increment:
      AddToObjectList(sender);
      mgr.GetPlayer().AddToPlayerHintAddList(GetUniqueId(), mgr);
      xfc_deactivated = false;
      break;
    case EScriptObjectMessage::Decrement:
      RemoveFromObjectList(sender);
      mgr.GetPlayer().AddToPlayerHintRemoveList(GetUniqueId(), mgr);
      break;
    default:
      break;
    }
  }

  CActor::AcceptScriptMsg(msg, sender, mgr);
}

} // namespace urde<|endoftext|>


<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2009-2012 Matthias Kretz <kretz@kde.org>

    Vc 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 3 of
    the License, or (at your option) any later version.

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

*/

#include "unittest.h"
#include <iostream>

using namespace Vc;

template<typename Vec> constexpr unsigned long alignmentMask()
{
    return Vec::Size == 1 ? (
            // on 32bit the maximal alignment is 4 Bytes, even for 8-Byte doubles.
            std::min(sizeof(void*), sizeof(typename Vec::EntryType)) - 1
        ) : (
            // sizeof(SSE::sfloat_v) is too large
            // AVX::VectorAlignment is too large
            std::min<size_t>(sizeof(Vec), VectorAlignment) - 1
        );
}

template<typename Vec> void checkAlignment()
{
    unsigned char i = 1;
    Vec a[10];
    unsigned long mask = alignmentMask<Vec>();
    for (i = 0; i < 10; ++i) {
        VERIFY((reinterpret_cast<size_t>(&a[i]) & mask) == 0) << "a = " << a << ", mask = " << mask;
    }
    const char *data = reinterpret_cast<const char *>(&a[0]);
    for (i = 0; i < 10; ++i) {
        VERIFY(&data[i * sizeof(Vec)] == reinterpret_cast<const char *>(&a[i]));
    }
}

void *hack_to_put_b_on_the_stack = 0;

template<typename Vec> void checkMemoryAlignment()
{
    typedef typename Vec::EntryType T;
    const T *b = 0;
    Vc::Memory<Vec, 10> a;
    b = a;
    hack_to_put_b_on_the_stack = &b;
    size_t mask = memory_alignment<Vec>::value - 1;
    for (int i = 0; i < 10; ++i) {
        VERIFY((reinterpret_cast<size_t>(&b[i * Vec::Size]) & mask) == 0) << "b = " << b << ", mask = " << mask;
    }
}

template<typename Vec> void loadArray()
{
    typedef typename Vec::EntryType T;
    typedef typename Vec::IndexType I;

    enum loadArrayEnum { count = 256 * 1024 / sizeof(T) };
    Vc::Memory<Vec, count> array;
    for (int i = 0; i < count; ++i) {
        array[i] = i;
    }

    const I indexesFromZero(IndexesFromZero);

    const Vec offsets(indexesFromZero);
    for (int i = 0; i < count; i += Vec::Size) {
        const T *const addr = &array[i];
        Vec ii(i);
        ii += offsets;

        Vec a(addr);
        COMPARE(a, ii);

        Vec b = Vec::Zero();
        b.load(addr);
        COMPARE(b, ii);
    }
}

enum Enum {
    loadArrayShortCount = 32 * 1024,
    streamingLoadCount = 1024
};
template<typename Vec> void loadArrayShort()
{
    typedef typename Vec::EntryType T;

    Vc::Memory<Vec, loadArrayShortCount> array;
    for (int i = 0; i < loadArrayShortCount; ++i) {
        array[i] = i;
    }

    const Vec &offsets = static_cast<Vec>(ushort_v::IndexesFromZero());
    for (int i = 0; i < loadArrayShortCount; i += Vec::Size) {
        const T *const addr = &array[i];
        Vec ii(i);
        ii += offsets;

        Vec a(addr);
        COMPARE(a, ii);

        Vec b = Vec::Zero();
        b.load(addr);
        COMPARE(b, ii);
    }
}

template<typename Vec> void streamingLoad()
{
    typedef typename Vec::EntryType T;

    Vc::Memory<Vec, streamingLoadCount> data;
    data[0] = static_cast<T>(-streamingLoadCount/2);
    for (int i = 1; i < streamingLoadCount; ++i) {
        data[i] = data[i - 1];
        ++data[i];
    }

    Vec ref = data.firstVector();
    for (int i = 0; i < streamingLoadCount - Vec::Size; ++i, ++ref) {
        Vec v1, v2;
        if (0 == i % Vec::Size) {
            v1 = Vec(&data[i], Vc::Streaming | Vc::Aligned);
            v2.load (&data[i], Vc::Streaming | Vc::Aligned);
        } else {
            v1 = Vec(&data[i], Vc::Streaming | Vc::Unaligned);
            v2.load (&data[i], Vc::Streaming | Vc::Unaligned);
        }
        COMPARE(v1, ref);
        COMPARE(v2, ref);
    }
}

template<typename T> struct TypeInfo;
template<> struct TypeInfo<double        > { static const char *string() { return "double"; } };
template<> struct TypeInfo<float         > { static const char *string() { return "float"; } };
template<> struct TypeInfo<int           > { static const char *string() { return "int"; } };
template<> struct TypeInfo<unsigned int  > { static const char *string() { return "uint"; } };
template<> struct TypeInfo<short         > { static const char *string() { return "short"; } };
template<> struct TypeInfo<unsigned short> { static const char *string() { return "ushort"; } };
template<> struct TypeInfo<signed char   > { static const char *string() { return "schar"; } };
template<> struct TypeInfo<unsigned char > { static const char *string() { return "uchar"; } };
template<> struct TypeInfo<double_v      > { static const char *string() { return "double_v"; } };
template<> struct TypeInfo<float_v       > { static const char *string() { return "float_v"; } };
template<> struct TypeInfo<sfloat_v      > { static const char *string() { return "sfloat_v"; } };
template<> struct TypeInfo<int_v         > { static const char *string() { return "int_v"; } };
template<> struct TypeInfo<uint_v        > { static const char *string() { return "uint_v"; } };
template<> struct TypeInfo<short_v       > { static const char *string() { return "short_v"; } };
template<> struct TypeInfo<ushort_v      > { static const char *string() { return "ushort_v"; } };

template<typename T, typename Current = void> struct SupportedConversions { typedef void Next; };
template<> struct SupportedConversions<float, void>           { typedef double         Next; };
template<> struct SupportedConversions<float, double>         { typedef int            Next; };
template<> struct SupportedConversions<float, int>            { typedef unsigned int   Next; };
template<> struct SupportedConversions<float, unsigned int>   { typedef short          Next; };
template<> struct SupportedConversions<float, short>          { typedef unsigned short Next; };
template<> struct SupportedConversions<float, unsigned short> { typedef signed char    Next; };
template<> struct SupportedConversions<float, signed char>    { typedef unsigned char  Next; };
template<> struct SupportedConversions<float, unsigned char>  { typedef void           Next; };
template<> struct SupportedConversions<int  , void          > { typedef unsigned int   Next; };
template<> struct SupportedConversions<int  , unsigned int  > { typedef short          Next; };
template<> struct SupportedConversions<int  , short         > { typedef unsigned short Next; };
template<> struct SupportedConversions<int  , unsigned short> { typedef signed char    Next; };
template<> struct SupportedConversions<int  , signed char   > { typedef unsigned char  Next; };
template<> struct SupportedConversions<int  , unsigned char > { typedef void           Next; };
template<> struct SupportedConversions<unsigned int, void          > { typedef unsigned short Next; };
template<> struct SupportedConversions<unsigned int, unsigned short> { typedef unsigned char  Next; };
template<> struct SupportedConversions<unsigned int, unsigned char > { typedef void           Next; };
template<> struct SupportedConversions<unsigned short, void          > { typedef unsigned char  Next; };
template<> struct SupportedConversions<unsigned short, unsigned char > { typedef void           Next; };
template<> struct SupportedConversions<         short, void          > { typedef unsigned char  Next; };
template<> struct SupportedConversions<         short, unsigned char > { typedef signed char    Next; };
template<> struct SupportedConversions<         short,   signed char > { typedef void           Next; };

template<typename Vec, typename MemT> struct LoadCvt {
    static void test() {
        typedef typename Vec::EntryType VecT;
        MemT *data = Vc::malloc<MemT, Vc::AlignOnCacheline>(128);
        for (size_t i = 0; i < 128; ++i) {
            data[i] = static_cast<MemT>(i - 64);
        }

        for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
            Vec v;
            if (i % (2 * Vec::Size) == 0) {
                v = Vec(&data[i]);
            } else if (i % Vec::Size == 0) {
                v = Vec(&data[i], Vc::Aligned);
            } else {
                v = Vec(&data[i], Vc::Unaligned);
            }
            for (size_t j = 0; j < Vec::Size; ++j) {
                COMPARE(v[j], static_cast<VecT>(data[i + j])) << " " << TypeInfo<MemT>::string();
            }
        }
        for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
            Vec v;
            if (i % (2 * Vec::Size) == 0) {
                v.load(&data[i]);
            } else if (i % Vec::Size == 0) {
                v.load(&data[i], Vc::Aligned);
            } else {
                v.load(&data[i], Vc::Unaligned);
            }
            for (size_t j = 0; j < Vec::Size; ++j) {
                COMPARE(v[j], static_cast<VecT>(data[i + j])) << " " << TypeInfo<MemT>::string();
            }
        }
        for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
            Vec v;
            if (i % (2 * Vec::Size) == 0) {
                v = Vec(&data[i], Vc::Streaming);
            } else if (i % Vec::Size == 0) {
                v = Vec(&data[i], Vc::Streaming | Vc::Aligned);
            } else {
                v = Vec(&data[i], Vc::Streaming | Vc::Unaligned);
            }
            for (size_t j = 0; j < Vec::Size; ++j) {
                COMPARE(v[j], static_cast<VecT>(data[i + j])) << " " << TypeInfo<MemT>::string();
            }
        }

        ADD_PASS() << "loadCvt: load " << TypeInfo<MemT>::string() << "* as " << TypeInfo<Vec>::string();
        LoadCvt<Vec, typename SupportedConversions<VecT, MemT>::Next>::test();
    }
};
template<typename Vec> struct LoadCvt<Vec, void> { static void test() {} };

template<typename Vec> void loadCvt()
{
    typedef typename Vec::EntryType T;
    LoadCvt<Vec, typename SupportedConversions<T>::Next>::test();
}

int main()
{
    runTest(checkAlignment<int_v>);
    runTest(checkAlignment<uint_v>);
    runTest(checkAlignment<float_v>);
    runTest(checkAlignment<double_v>);
    runTest(checkAlignment<short_v>);
    runTest(checkAlignment<ushort_v>);
    runTest(checkAlignment<sfloat_v>);
    testAllTypes(checkMemoryAlignment);
    runTest(loadArray<int_v>);
    runTest(loadArray<uint_v>);
    runTest(loadArray<float_v>);
    runTest(loadArray<double_v>);
    runTest(loadArray<sfloat_v>);
    runTest(loadArrayShort<short_v>);
    runTest(loadArrayShort<ushort_v>);

    testAllTypes(streamingLoad);

    testAllTypes(loadCvt);
    return 0;
}
<commit_msg>give more context on failure<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2009-2012 Matthias Kretz <kretz@kde.org>

    Vc 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 3 of
    the License, or (at your option) any later version.

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

*/

#include "unittest.h"
#include <iostream>

using namespace Vc;

template<typename Vec> constexpr unsigned long alignmentMask()
{
    return Vec::Size == 1 ? (
            // on 32bit the maximal alignment is 4 Bytes, even for 8-Byte doubles.
            std::min(sizeof(void*), sizeof(typename Vec::EntryType)) - 1
        ) : (
            // sizeof(SSE::sfloat_v) is too large
            // AVX::VectorAlignment is too large
            std::min<size_t>(sizeof(Vec), VectorAlignment) - 1
        );
}

template<typename Vec> void checkAlignment()
{
    unsigned char i = 1;
    Vec a[10];
    unsigned long mask = alignmentMask<Vec>();
    for (i = 0; i < 10; ++i) {
        VERIFY((reinterpret_cast<size_t>(&a[i]) & mask) == 0) << "a = " << a << ", mask = " << mask;
    }
    const char *data = reinterpret_cast<const char *>(&a[0]);
    for (i = 0; i < 10; ++i) {
        VERIFY(&data[i * sizeof(Vec)] == reinterpret_cast<const char *>(&a[i]));
    }
}

void *hack_to_put_b_on_the_stack = 0;

template<typename Vec> void checkMemoryAlignment()
{
    typedef typename Vec::EntryType T;
    const T *b = 0;
    Vc::Memory<Vec, 10> a;
    b = a;
    hack_to_put_b_on_the_stack = &b;
    size_t mask = memory_alignment<Vec>::value - 1;
    for (int i = 0; i < 10; ++i) {
        VERIFY((reinterpret_cast<size_t>(&b[i * Vec::Size]) & mask) == 0) << "b = " << b << ", mask = " << mask;
    }
}

template<typename Vec> void loadArray()
{
    typedef typename Vec::EntryType T;
    typedef typename Vec::IndexType I;

    enum loadArrayEnum { count = 256 * 1024 / sizeof(T) };
    Vc::Memory<Vec, count> array;
    for (int i = 0; i < count; ++i) {
        array[i] = i;
    }

    const I indexesFromZero(IndexesFromZero);

    const Vec offsets(indexesFromZero);
    for (int i = 0; i < count; i += Vec::Size) {
        const T *const addr = &array[i];
        Vec ii(i);
        ii += offsets;

        Vec a(addr);
        COMPARE(a, ii);

        Vec b = Vec::Zero();
        b.load(addr);
        COMPARE(b, ii);
    }
}

enum Enum {
    loadArrayShortCount = 32 * 1024,
    streamingLoadCount = 1024
};
template<typename Vec> void loadArrayShort()
{
    typedef typename Vec::EntryType T;

    Vc::Memory<Vec, loadArrayShortCount> array;
    for (int i = 0; i < loadArrayShortCount; ++i) {
        array[i] = i;
    }

    const Vec &offsets = static_cast<Vec>(ushort_v::IndexesFromZero());
    for (int i = 0; i < loadArrayShortCount; i += Vec::Size) {
        const T *const addr = &array[i];
        Vec ii(i);
        ii += offsets;

        Vec a(addr);
        COMPARE(a, ii);

        Vec b = Vec::Zero();
        b.load(addr);
        COMPARE(b, ii);
    }
}

template<typename Vec> void streamingLoad()
{
    typedef typename Vec::EntryType T;

    Vc::Memory<Vec, streamingLoadCount> data;
    data[0] = static_cast<T>(-streamingLoadCount/2);
    for (int i = 1; i < streamingLoadCount; ++i) {
        data[i] = data[i - 1];
        ++data[i];
    }

    Vec ref = data.firstVector();
    for (int i = 0; i < streamingLoadCount - Vec::Size; ++i, ++ref) {
        Vec v1, v2;
        if (0 == i % Vec::Size) {
            v1 = Vec(&data[i], Vc::Streaming | Vc::Aligned);
            v2.load (&data[i], Vc::Streaming | Vc::Aligned);
        } else {
            v1 = Vec(&data[i], Vc::Streaming | Vc::Unaligned);
            v2.load (&data[i], Vc::Streaming | Vc::Unaligned);
        }
        COMPARE(v1, ref) << ", i = " << i;
        COMPARE(v2, ref) << ", i = " << i;
    }
}

template<typename T> struct TypeInfo;
template<> struct TypeInfo<double        > { static const char *string() { return "double"; } };
template<> struct TypeInfo<float         > { static const char *string() { return "float"; } };
template<> struct TypeInfo<int           > { static const char *string() { return "int"; } };
template<> struct TypeInfo<unsigned int  > { static const char *string() { return "uint"; } };
template<> struct TypeInfo<short         > { static const char *string() { return "short"; } };
template<> struct TypeInfo<unsigned short> { static const char *string() { return "ushort"; } };
template<> struct TypeInfo<signed char   > { static const char *string() { return "schar"; } };
template<> struct TypeInfo<unsigned char > { static const char *string() { return "uchar"; } };
template<> struct TypeInfo<double_v      > { static const char *string() { return "double_v"; } };
template<> struct TypeInfo<float_v       > { static const char *string() { return "float_v"; } };
template<> struct TypeInfo<sfloat_v      > { static const char *string() { return "sfloat_v"; } };
template<> struct TypeInfo<int_v         > { static const char *string() { return "int_v"; } };
template<> struct TypeInfo<uint_v        > { static const char *string() { return "uint_v"; } };
template<> struct TypeInfo<short_v       > { static const char *string() { return "short_v"; } };
template<> struct TypeInfo<ushort_v      > { static const char *string() { return "ushort_v"; } };

template<typename T, typename Current = void> struct SupportedConversions { typedef void Next; };
template<> struct SupportedConversions<float, void>           { typedef double         Next; };
template<> struct SupportedConversions<float, double>         { typedef int            Next; };
template<> struct SupportedConversions<float, int>            { typedef unsigned int   Next; };
template<> struct SupportedConversions<float, unsigned int>   { typedef short          Next; };
template<> struct SupportedConversions<float, short>          { typedef unsigned short Next; };
template<> struct SupportedConversions<float, unsigned short> { typedef signed char    Next; };
template<> struct SupportedConversions<float, signed char>    { typedef unsigned char  Next; };
template<> struct SupportedConversions<float, unsigned char>  { typedef void           Next; };
template<> struct SupportedConversions<int  , void          > { typedef unsigned int   Next; };
template<> struct SupportedConversions<int  , unsigned int  > { typedef short          Next; };
template<> struct SupportedConversions<int  , short         > { typedef unsigned short Next; };
template<> struct SupportedConversions<int  , unsigned short> { typedef signed char    Next; };
template<> struct SupportedConversions<int  , signed char   > { typedef unsigned char  Next; };
template<> struct SupportedConversions<int  , unsigned char > { typedef void           Next; };
template<> struct SupportedConversions<unsigned int, void          > { typedef unsigned short Next; };
template<> struct SupportedConversions<unsigned int, unsigned short> { typedef unsigned char  Next; };
template<> struct SupportedConversions<unsigned int, unsigned char > { typedef void           Next; };
template<> struct SupportedConversions<unsigned short, void          > { typedef unsigned char  Next; };
template<> struct SupportedConversions<unsigned short, unsigned char > { typedef void           Next; };
template<> struct SupportedConversions<         short, void          > { typedef unsigned char  Next; };
template<> struct SupportedConversions<         short, unsigned char > { typedef signed char    Next; };
template<> struct SupportedConversions<         short,   signed char > { typedef void           Next; };

template<typename Vec, typename MemT> struct LoadCvt {
    static void test() {
        typedef typename Vec::EntryType VecT;
        MemT *data = Vc::malloc<MemT, Vc::AlignOnCacheline>(128);
        for (size_t i = 0; i < 128; ++i) {
            data[i] = static_cast<MemT>(i - 64);
        }

        for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
            Vec v;
            if (i % (2 * Vec::Size) == 0) {
                v = Vec(&data[i]);
            } else if (i % Vec::Size == 0) {
                v = Vec(&data[i], Vc::Aligned);
            } else {
                v = Vec(&data[i], Vc::Unaligned);
            }
            for (size_t j = 0; j < Vec::Size; ++j) {
                COMPARE(v[j], static_cast<VecT>(data[i + j])) << " " << TypeInfo<MemT>::string();
            }
        }
        for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
            Vec v;
            if (i % (2 * Vec::Size) == 0) {
                v.load(&data[i]);
            } else if (i % Vec::Size == 0) {
                v.load(&data[i], Vc::Aligned);
            } else {
                v.load(&data[i], Vc::Unaligned);
            }
            for (size_t j = 0; j < Vec::Size; ++j) {
                COMPARE(v[j], static_cast<VecT>(data[i + j])) << " " << TypeInfo<MemT>::string();
            }
        }
        for (size_t i = 0; i < 128 - Vec::Size + 1; ++i) {
            Vec v;
            if (i % (2 * Vec::Size) == 0) {
                v = Vec(&data[i], Vc::Streaming);
            } else if (i % Vec::Size == 0) {
                v = Vec(&data[i], Vc::Streaming | Vc::Aligned);
            } else {
                v = Vec(&data[i], Vc::Streaming | Vc::Unaligned);
            }
            for (size_t j = 0; j < Vec::Size; ++j) {
                COMPARE(v[j], static_cast<VecT>(data[i + j])) << " " << TypeInfo<MemT>::string();
            }
        }

        ADD_PASS() << "loadCvt: load " << TypeInfo<MemT>::string() << "* as " << TypeInfo<Vec>::string();
        LoadCvt<Vec, typename SupportedConversions<VecT, MemT>::Next>::test();
    }
};
template<typename Vec> struct LoadCvt<Vec, void> { static void test() {} };

template<typename Vec> void loadCvt()
{
    typedef typename Vec::EntryType T;
    LoadCvt<Vec, typename SupportedConversions<T>::Next>::test();
}

int main()
{
    runTest(checkAlignment<int_v>);
    runTest(checkAlignment<uint_v>);
    runTest(checkAlignment<float_v>);
    runTest(checkAlignment<double_v>);
    runTest(checkAlignment<short_v>);
    runTest(checkAlignment<ushort_v>);
    runTest(checkAlignment<sfloat_v>);
    testAllTypes(checkMemoryAlignment);
    runTest(loadArray<int_v>);
    runTest(loadArray<uint_v>);
    runTest(loadArray<float_v>);
    runTest(loadArray<double_v>);
    runTest(loadArray<sfloat_v>);
    runTest(loadArrayShort<short_v>);
    runTest(loadArrayShort<ushort_v>);

    testAllTypes(streamingLoad);

    testAllTypes(loadCvt);
    return 0;
}
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE BypassParserTests

#include <boost/test/included/unit_test.hpp>
#include <string>
#include "parser.h"

using namespace Bypass;

struct F
{
	F() : parser()
	{
		BOOST_TEST_MESSAGE( "setup fixture" );
	}

	~F()
	{
		BOOST_TEST_MESSAGE( "teardown fixture" );
	}

	Parser parser;
};

BOOST_FIXTURE_TEST_CASE(parse_with_null_input, F)
{
	Document document = parser.parse(NULL);
}

BOOST_FIXTURE_TEST_CASE(parse_with_empty_string, F)
{
	std::string s = std::string();
	Document document = parser.parse(s);
}
<commit_msg>Adding an initial block-level element to test with<commit_after>#define BOOST_TEST_MODULE BypassParserTests

#include <boost/test/included/unit_test.hpp>
#include <string>
#include "parser.h"

using namespace Bypass;

struct F {
	F() :
		parser(),
		p("A paragraph is simply one or more consecutive lines of text, "
		  " separated by one or more blank lines. (A blank line is any line"
		  " that looks like a blank line — a line containing nothing but spaces"
		  " or tabs is considered blank.) Normal paragraphs should not be "
		  " indented with spaces or tabs.")
	{
		BOOST_TEST_MESSAGE( "setup fixture" );
	}

	~F() {
		BOOST_TEST_MESSAGE( "teardown fixture" );
	}

	Parser parser;
	std::string p;
};

BOOST_FIXTURE_TEST_CASE(parse_with_null_input, F) {
	Document document = parser.parse(NULL);
}

BOOST_FIXTURE_TEST_CASE(parse_with_empty_string, F) {
	std::string s = std::string();
	Document document = parser.parse(s);
}<|endoftext|>


<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * 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.hpp"
#include <array>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <miopen/logger.hpp>
#include <miopen/miopen.h>
#include <miopen/pooling.hpp>
#include <miopen/stringutils.hpp>
#include <miopen/tensor.hpp>
#include <utility>

// #include "network_data.hpp"
#include "driver.hpp"
#include "get_handle.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"

template <class T>
tensor<T> get_output_tensor(const miopen::PoolingDescriptor& filter, const tensor<T>& input)
{
    return tensor<T>{filter.GetForwardOutputTensor(input.desc)};
}

template <class T>
struct pooling_operators
{
    miopen::PoolingDescriptor filter;
    pooling_operators(miopen::PoolingDescriptor f) : filter(f) {}

    T start() const
    {
        if(filter.GetMode() == miopenPoolingMax)
            return std::numeric_limits<T>::lowest();
        else
            return 0.0;
    }

    T operator()(T x, T y) const
    {
        if(filter.GetMode() == miopenPoolingMax)
            return std::max(x, y);
        else
            return x + y;
    }

    T final(T x, T y)
    {
        if(filter.GetMode() == miopenPoolingMax)
            return x;
        else
            return x / y;
    }
};

struct verify_forward_pooling
{
    template <class T>
    tensor<T>
    cpu(const tensor<T>& input, const miopen::PoolingDescriptor& filter, std::vector<uint8_t>&)
    {
        auto out = get_output_tensor(filter, input);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tien<4>(input.desc.GetLengths());

        int u, v, pad_h, pad_w, window_h, window_w;
        std::tie(u, v)               = miopen::tien<2>(filter.GetStrides());
        std::tie(pad_h, pad_w)       = miopen::tien<2>(filter.GetPads());
        std::tie(window_h, window_w) = miopen::tien<2>(filter.GetLengths());

        auto op = pooling_operators<T>{filter};

        out.par_for_each([&](int o, int w, int i, int j) {
            const int start_x = i * v - pad_h;
            const int start_y = j * u - pad_w;

            const int hend = std::min(start_x + window_h, in_h + pad_h);
            const int wend = std::min(start_y + window_w, in_w + pad_w);

            const int pool_size = (hend - start_x) * (wend - start_y);

            T acc = op.start();
            ford(window_h, window_w)([&](int x, int y) {
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w)
                {
                    acc = op(acc, input(o, w, in_x, in_y));
                }
            });
            out(o, w, i, j) = op.final(acc, pool_size);
        });
        return out;
    }

    template <class T>
    tensor<T> gpu(const tensor<T>& input,
                  const miopen::PoolingDescriptor& filter,
                  std::vector<uint8_t>& indices)
    {
        auto&& handle = get_handle();
        auto out      = get_output_tensor(filter, input);
        indices.resize(out.data.size(), 0);

        auto in_dev        = handle.Write(input.data);
        auto out_dev       = handle.Create<T>(out.data.size());
        auto workspace_dev = handle.Write(indices);

        float alpha = 1, beta = 0;
        filter.Forward(handle,
                       &alpha,
                       input.desc,
                       in_dev.get(),
                       &beta,
                       out.desc,
                       out_dev.get(),
                       true,
                       workspace_dev.get(),
                       indices.size() * sizeof(uint8_t));

        indices  = handle.Read<uint8_t>(workspace_dev, indices.size());
        out.data = handle.Read<T>(out_dev, out.data.size());
        return out;
    }

    template <class T>
    void fail(float,
              const tensor<T>& input,
              const miopen::PoolingDescriptor& filter,
              const std::vector<uint8_t>&)
    {
        std::cout << "Forward pooling: ";
        if(filter.GetMode() == miopenPoolingAverage)
            std::cout << "Average";
        else
            std::cout << "Max";
        std::cout << std::endl;
        std::cout << "Lengths: ";
        miopen::LogRange(std::cout, filter.GetLengths(), ", ") << std::endl;
        std::cout << "Pads: ";
        miopen::LogRange(std::cout, filter.GetPads(), ", ") << std::endl;
        std::cout << "Strides: ";
        miopen::LogRange(std::cout, filter.GetStrides(), ", ") << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
        std::cout << "Output tensor: " << filter.GetForwardOutputTensor(input.desc).ToString()
                  << std::endl;
    }
};

struct verify_backward_pooling
{
    template <class T>
    tensor<T> cpu(const tensor<T>& input,
                  const tensor<T>& dout,
                  const tensor<T>& out,
                  const miopen::PoolingDescriptor& filter,
                  const std::vector<uint8_t>& indices)
    {
        auto dinput = input;
        CHECK(dout.desc == out.desc);
        std::fill(dinput.begin(), dinput.end(), 0.0);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tien<4>(dinput.desc.GetLengths());

        int u, v, pad_h, pad_w, window_h, window_w;
        std::tie(u, v)               = miopen::tien<2>(filter.GetStrides());
        std::tie(pad_h, pad_w)       = miopen::tien<2>(filter.GetPads());
        std::tie(window_h, window_w) = miopen::tien<2>(filter.GetLengths());

        int out_n, out_c, out_h, out_w;
        std::tie(out_n, out_c, out_h, out_w) = miopen::tien<4>(out.desc.GetLengths());

        par_ford(out_n, out_c)([&](int o, int w) {
            if(filter.GetMode() == miopenPoolingMax)
            {
                ford(out_h, out_w)([&](int i, int j) {
                    auto idx   = indices.at(dout.desc.GetIndex(o, w, i, j));
                    auto idx_h = idx / window_w;
                    auto idx_w = idx % window_w;
                    auto in_y  = i * v - pad_h + idx_h;
                    auto in_x  = j * u - pad_w + idx_w;
                    if(in_y >= 0 && in_x >= 0 && in_y < in_h && in_x < in_w)
                    {
                        CHECK(miopen::float_equal(input(o, w, in_y, in_x), out(o, w, i, j)));
                        dinput(o, w, in_y, in_x) += dout(o, w, i, j);
                    }
                });
            }
            else
            {
                ford(out_h, out_w, window_h, window_w)([&](int i, int j, int x, int y) {
                    const int start_x = i * v - pad_h;
                    const int start_y = j * u - pad_w;

                    const int hend = std::min(start_x + window_h, in_h + pad_h);
                    const int wend = std::min(start_y + window_w, in_w + pad_w);

                    const int pool_size = (hend - start_x) * (wend - start_y);

                    const int in_x = start_x + x;
                    const int in_y = start_y + y;
                    if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w)
                    {
                        dinput(o, w, in_x, in_y) += dout(o, w, i, j) / pool_size;
                    }
                });
            }
        });
        return dinput;
    }

    template <class T>
    tensor<T> gpu(const tensor<T>& input,
                  const tensor<T>& dout,
                  const tensor<T>& out,
                  const miopen::PoolingDescriptor& filter,
                  const std::vector<uint8_t>& indices)
    {
        auto&& handle = get_handle();
        auto dinput   = input;

        auto in_dev   = handle.Write(input.data);
        auto dout_dev = handle.Write(dout.data);
        auto out_dev  = handle.Write(out.data);
        auto din_dev  = handle.Create<T>(dinput.data.size());

        // std::vector<char> workspace(filter.GetWorkSpaceSize(out.desc));
        // auto workspace_dev = handle.Write(workspace);
        auto workspace_dev = handle.Write(indices);

        float alpha = 1, beta = 0;
        filter.Backward(handle,
                        &alpha,
                        // y
                        out.desc,
                        out_dev.get(),
                        // dy
                        dout.desc,
                        dout_dev.get(),
                        // x
                        input.desc,
                        in_dev.get(),
                        &beta,
                        // dx
                        dinput.desc,
                        din_dev.get(),
                        workspace_dev.get());

        dinput.data = handle.Read<T>(din_dev, dinput.data.size());
        return dinput;
    }

    template <class T>
    void fail(float,
              const tensor<T>& input,
              const tensor<T>&,
              const tensor<T>& out,
              const miopen::PoolingDescriptor& filter,
              const std::vector<uint8_t>&)
    {
        std::cout << "Backward pooling: ";
        if(filter.GetMode() == miopenPoolingAverage)
            std::cout << "Average";
        else
            std::cout << "Max";
        std::cout << std::endl;
        std::cout << "Lengths: ";
        miopen::LogRange(std::cout, filter.GetLengths(), ", ") << std::endl;
        std::cout << "Pads: ";
        miopen::LogRange(std::cout, filter.GetPads(), ", ") << std::endl;
        std::cout << "Strides: ";
        miopen::LogRange(std::cout, filter.GetStrides(), ", ") << std::endl;
        std::cout << "Output tensor: " << out.desc.ToString() << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
    }
};

template <class T>
struct pooling_driver : test_driver
{
    tensor<T> input;
    std::vector<int> lens;
    std::vector<int> pads;
    std::vector<int> strides;
    std::string mode;
    std::unordered_map<std::string, miopenPoolingMode_t> mode_lookup = {
        {"MAX", miopenPoolingMax},
        {"MIOPENPOOLINGMAX", miopenPoolingMax},
        {"AVERAGE", miopenPoolingAverage},
        {"MIOPENPOOLINGAVERAGE", miopenPoolingAverage},
    };

    pooling_driver()
    {
        add(input, "input", get_input_tensor());
        add(lens, "lens", generate_data({{2, 2}, {3, 3}}));
        add(strides, "strides", generate_data({{2, 2}, {1, 1}}));
        add(pads, "pads", generate_data({{0, 0}, {1, 1}}));
        add(mode, "mode", generate_data({"miopenPoolingMax", "miopenPoolingAverage"}));
    }

    void run()
    {
        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tien<4>(input.desc.GetLengths());

        miopen::PoolingDescriptor filter{
            mode_lookup.at(miopen::ToUpper(mode)), lens, strides, pads};

        std::vector<uint8_t> indices{};
        auto out  = verify(verify_forward_pooling{}, input, filter, indices);
        auto dout = out.first;
        dout.generate([&](int n, int c, int h, int w) {
            T x      = out.first(n, c, h, w);
            double y = (877 * n + 547 * c + 701 * h + 1049 * w + static_cast<int>(769 * x)) % 2503;
            return ((x * y) / 1301.0);
        });
        verify(verify_backward_pooling{}, input, dout, out.first, filter, indices);
    }
};

int main(int argc, const char* argv[]) { test_drive<pooling_driver<float>>(argc, argv); }
<commit_msg>Enable Tensorflow padding in pooling tests/test driver<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * 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.hpp"
#include <array>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <miopen/logger.hpp>
#include <miopen/miopen.h>
#include <miopen/pooling.hpp>
#include <miopen/stringutils.hpp>
#include <miopen/tensor.hpp>
#include <utility>

// #include "network_data.hpp"
#include "driver.hpp"
#include "get_handle.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"

template <class T>
tensor<T> get_output_tensor(const miopen::PoolingDescriptor& filter, const tensor<T>& input)
{
    return tensor<T>{filter.GetForwardOutputTensor(input.desc)};
}

template <class T>
struct pooling_operators
{
    miopen::PoolingDescriptor filter;
    pooling_operators(miopen::PoolingDescriptor f) : filter(f) {}

    T start() const
    {
        if(filter.GetMode() == miopenPoolingMax)
            return std::numeric_limits<T>::lowest();
        else
            return 0.0;
    }

    T operator()(T x, T y) const
    {
        if(filter.GetMode() == miopenPoolingMax)
            return std::max(x, y);
        else
            return x + y;
    }

    T final(T x, T y)
    {
        if(filter.GetMode() == miopenPoolingMax)
            return x;
        else
            return x / y;
    }
};

struct verify_forward_pooling
{
    template <class T>
    tensor<T>
    cpu(const tensor<T>& input, const miopen::PoolingDescriptor& filter, std::vector<uint8_t>&)
    {
        auto out = get_output_tensor(filter, input);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tien<4>(input.desc.GetLengths());

        int u, v, pad_h, pad_w, window_h, window_w;
        std::tie(u, v)               = miopen::tien<2>(filter.GetStrides());
        std::tie(pad_h, pad_w)       = miopen::tien<2>(filter.GetPads());
        std::tie(window_h, window_w) = miopen::tien<2>(filter.GetLengths());

        auto op = pooling_operators<T>{filter};

        out.par_for_each([&](int o, int w, int i, int j) {
            const int start_x = i * v - pad_h;
            const int start_y = j * u - pad_w;

            const int hend = std::min(start_x + window_h, in_h + pad_h);
            const int wend = std::min(start_y + window_w, in_w + pad_w);

            const int pool_size = (hend - start_x) * (wend - start_y);

            T acc = op.start();
            ford(window_h, window_w)([&](int x, int y) {
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w)
                {
                    acc = op(acc, input(o, w, in_x, in_y));
                }
            });
            out(o, w, i, j) = op.final(acc, pool_size);
        });
        return out;
    }

    template <class T>
    tensor<T> gpu(const tensor<T>& input,
                  const miopen::PoolingDescriptor& filter,
                  std::vector<uint8_t>& indices)
    {
        auto&& handle = get_handle();
        auto out      = get_output_tensor(filter, input);
        indices.resize(out.data.size(), 0);

        auto in_dev        = handle.Write(input.data);
        auto out_dev       = handle.Create<T>(out.data.size());
        auto workspace_dev = handle.Write(indices);

        float alpha = 1, beta = 0;
        filter.Forward(handle,
                       &alpha,
                       input.desc,
                       in_dev.get(),
                       &beta,
                       out.desc,
                       out_dev.get(),
                       true,
                       workspace_dev.get(),
                       indices.size() * sizeof(uint8_t));

        indices  = handle.Read<uint8_t>(workspace_dev, indices.size());
        out.data = handle.Read<T>(out_dev, out.data.size());
        return out;
    }

    template <class T>
    void fail(float,
              const tensor<T>& input,
              const miopen::PoolingDescriptor& filter,
              const std::vector<uint8_t>&)
    {
        std::cout << "Forward pooling: ";
        if(filter.GetMode() == miopenPoolingAverage)
            std::cout << "Average";
        else
            std::cout << "Max";
        std::cout << std::endl;
        std::cout << "Lengths: ";
        miopen::LogRange(std::cout, filter.GetLengths(), ", ") << std::endl;
        std::cout << "Pads: ";
        miopen::LogRange(std::cout, filter.GetPads(), ", ") << std::endl;
        std::cout << "Strides: ";
        miopen::LogRange(std::cout, filter.GetStrides(), ", ") << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
        std::cout << "Output tensor: " << filter.GetForwardOutputTensor(input.desc).ToString()
                  << std::endl;
    }
};

struct verify_backward_pooling
{
    template <class T>
    tensor<T> cpu(const tensor<T>& input,
                  const tensor<T>& dout,
                  const tensor<T>& out,
                  const miopen::PoolingDescriptor& filter,
                  const std::vector<uint8_t>& indices)
    {
        auto dinput = input;
        CHECK(dout.desc == out.desc);
        std::fill(dinput.begin(), dinput.end(), 0.0);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tien<4>(dinput.desc.GetLengths());

        int u, v, pad_h, pad_w, window_h, window_w;
        std::tie(u, v)               = miopen::tien<2>(filter.GetStrides());
        std::tie(pad_h, pad_w)       = miopen::tien<2>(filter.GetPads());
        std::tie(window_h, window_w) = miopen::tien<2>(filter.GetLengths());

        int out_n, out_c, out_h, out_w;
        std::tie(out_n, out_c, out_h, out_w) = miopen::tien<4>(out.desc.GetLengths());

        par_ford(out_n, out_c)([&](int o, int w) {
            if(filter.GetMode() == miopenPoolingMax)
            {
                ford(out_h, out_w)([&](int i, int j) {
                    auto idx   = indices.at(dout.desc.GetIndex(o, w, i, j));
                    auto idx_h = idx / window_w;
                    auto idx_w = idx % window_w;
                    auto in_y  = i * v - pad_h + idx_h;
                    auto in_x  = j * u - pad_w + idx_w;
                    if(in_y >= 0 && in_x >= 0 && in_y < in_h && in_x < in_w)
                    {
                        CHECK(miopen::float_equal(input(o, w, in_y, in_x), out(o, w, i, j)));
                        dinput(o, w, in_y, in_x) += dout(o, w, i, j);
                    }
                });
            }
            else
            {
                ford(out_h, out_w, window_h, window_w)([&](int i, int j, int x, int y) {
                    const int start_x = i * v - pad_h;
                    const int start_y = j * u - pad_w;

                    const int hend = std::min(start_x + window_h, in_h + pad_h);
                    const int wend = std::min(start_y + window_w, in_w + pad_w);

                    const int pool_size = (hend - start_x) * (wend - start_y);

                    const int in_x = start_x + x;
                    const int in_y = start_y + y;
                    if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w)
                    {
                        dinput(o, w, in_x, in_y) += dout(o, w, i, j) / pool_size;
                    }
                });
            }
        });
        return dinput;
    }

    template <class T>
    tensor<T> gpu(const tensor<T>& input,
                  const tensor<T>& dout,
                  const tensor<T>& out,
                  const miopen::PoolingDescriptor& filter,
                  const std::vector<uint8_t>& indices)
    {
        auto&& handle = get_handle();
        auto dinput   = input;

        auto in_dev   = handle.Write(input.data);
        auto dout_dev = handle.Write(dout.data);
        auto out_dev  = handle.Write(out.data);
        auto din_dev  = handle.Create<T>(dinput.data.size());

        // std::vector<char> workspace(filter.GetWorkSpaceSize(out.desc));
        // auto workspace_dev = handle.Write(workspace);
        auto workspace_dev = handle.Write(indices);

        float alpha = 1, beta = 0;
        filter.Backward(handle,
                        &alpha,
                        // y
                        out.desc,
                        out_dev.get(),
                        // dy
                        dout.desc,
                        dout_dev.get(),
                        // x
                        input.desc,
                        in_dev.get(),
                        &beta,
                        // dx
                        dinput.desc,
                        din_dev.get(),
                        workspace_dev.get());

        dinput.data = handle.Read<T>(din_dev, dinput.data.size());
        return dinput;
    }

    template <class T>
    void fail(float,
              const tensor<T>& input,
              const tensor<T>&,
              const tensor<T>& out,
              const miopen::PoolingDescriptor& filter,
              const std::vector<uint8_t>&)
    {
        std::cout << "Backward pooling: ";
        if(filter.GetMode() == miopenPoolingAverage)
            std::cout << "Average";
        else
            std::cout << "Max";
        std::cout << std::endl;
        std::cout << "Lengths: ";
        miopen::LogRange(std::cout, filter.GetLengths(), ", ") << std::endl;
        std::cout << "Pads: ";
        miopen::LogRange(std::cout, filter.GetPads(), ", ") << std::endl;
        std::cout << "Strides: ";
        miopen::LogRange(std::cout, filter.GetStrides(), ", ") << std::endl;
        std::cout << "Output tensor: " << out.desc.ToString() << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
    }
};

template <class T>
struct pooling_driver : test_driver
{
    tensor<T> input;
    std::vector<int> lens;
    std::vector<int> pads;
    std::vector<int> strides;
    std::string mode;
    std::string pmode;
    std::unordered_map<std::string, miopenPoolingMode_t> mode_lookup = {
        {"MAX", miopenPoolingMax},
        {"MIOPENPOOLINGMAX", miopenPoolingMax},
        {"AVERAGE", miopenPoolingAverage},
        {"MIOPENPOOLINGAVERAGE", miopenPoolingAverage},
    };

    std::unordered_map<std::string, miopenPaddingMode_t> pmode_lookup = {
            {"DEFAULT", miopenPaddingDefault},
            {"SAME", miopenPaddingSame},
            {"VALID", miopenPaddingValid},
    };

    pooling_driver()
    {
        add(input, "input", get_input_tensor());
        add(lens, "lens", generate_data({{2, 2}, {3, 3}}));
        add(strides, "strides", generate_data({{2, 2}, {1, 1}}));
        add(pads, "pads", generate_data({{0, 0}, {1, 1}}));
        add(mode, "mode", generate_data({"miopenPoolingMax", "miopenPoolingAverage"}));
        add(pmode, "pmode", generate_data({"default", "same","valid"}));
    }

    void run()
    {
        int in_h, in_w, window_h, window_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tien<4>(input.desc.GetLengths());

        miopen::PoolingDescriptor filter{
            mode_lookup.at(miopen::ToUpper(mode)), pmode_lookup.at(miopen::ToUpper(pmode)), lens, strides, pads};

        std::tie(window_h, window_w) = miopen::tien<2>(filter.GetLengths());
        if (filter.pmode == miopenPaddingSame) {
            filter.pads[0] = (in_h % filter.strides[0] == 0)
                           ? (std::max((window_h - filter.strides[0]), 0))
                           : (std::max((window_h - (in_h % filter.strides[0])), 0));
            filter.pads[1] = (in_w % filter.strides[1]== 0)
                           ? (std::max((window_w - filter.strides[1]), 0))
                           : (std::max((window_w - (in_w % filter.strides[1])), 0));
        } else if (filter.pmode == miopenPaddingValid) {
            filter.pads[0] = 0;
            filter.pads[1] = 0;
        }

        std::vector<uint8_t> indices{};
        auto out  = verify(verify_forward_pooling{}, input, filter, indices);
        auto dout = out.first;
        dout.generate([&](int n, int c, int h, int w) {
            T x      = out.first(n, c, h, w);
            double y = (877 * n + 547 * c + 701 * h + 1049 * w + static_cast<int>(769 * x)) % 2503;
            return ((x * y) / 1301.0);
        });
        verify(verify_backward_pooling{}, input, dout, out.first, filter, indices);
    }
};

int main(int argc, const char* argv[]) { test_drive<pooling_driver<float>>(argc, argv); }
<|endoftext|>


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

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <csignal>
#include <cmath>

#include <time.h>
#include <unistd.h>

using namespace Realm;

Logger log_app("app");

// Task IDs, some IDs are reserved so start at first available number
enum {
  TOP_LEVEL_TASK = Processor::TASK_ID_FIRST_AVAILABLE+0,
  CHILD_TASK_ID_START,
};

void child_task(const void *args, size_t arglen,
		const void *userdata, size_t userlen, Processor p)
{
  log_app.print() << "child task on " << p << ": arglen=" << arglen << ", userlen=" << userlen;
}

void top_level_task(const void *args, size_t arglen,
		    const void *userdata, size_t userlen, Processor p)
{
  Machine machine = Machine::get_machine();
  Processor::TaskFuncID func_id = CHILD_TASK_ID_START;

  // first test - register a task individually on each processor and run it
  {
    std::set<Event> finish_events;

    CodeDescriptor child_task_desc(child_task);
    int count = 0;

    std::set<Processor> all_processors;
    machine.get_all_processors(all_processors);
    for(std::set<Processor>::const_iterator it = all_processors.begin();
	it != all_processors.end();
	it++) {
      Processor pp = (*it);

      Event e = pp.register_task(func_id, child_task_desc,
				 ProfilingRequestSet(),
				 &pp, sizeof(pp));

      Event e2 = pp.spawn(func_id, &count, sizeof(count), e);

      finish_events.insert(e2);

      func_id++;
    }

    Event merged = Event::merge_events(finish_events);

    merged.wait();
  }

  // second test - register a task on all LOC_PROCs
  {
    std::set<Event> finish_events;

    CodeDescriptor child_task_desc(child_task);

    Event e = Processor::register_task_by_kind(Processor::LOC_PROC, true /*global*/,
					       func_id,
					       child_task_desc,
					       ProfilingRequestSet());

    int count = 0;

    std::set<Processor> all_processors;
    machine.get_all_processors(all_processors);
    for(std::set<Processor>::const_iterator it = all_processors.begin();
	it != all_processors.end();
	it++) {
      Processor pp = (*it);

      // only LOC_PROCs
      if(pp.kind() != Processor::LOC_PROC)
	continue;

      Event e2 = pp.spawn(func_id, &count, sizeof(count), e);

      finish_events.insert(e2);
    }

    func_id++;

    Event merged = Event::merge_events(finish_events);

    merged.wait();
  }

  printf("all done!\n");

  Runtime::get_runtime().shutdown();
}

int main(int argc, char **argv)
{
  Runtime rt;

  rt.init(&argc, &argv);

  rt.register_task(TOP_LEVEL_TASK, top_level_task);

  // Start the machine running
  // Control never returns from this call
  // Note we only run the top level task on one processor
  // You can also run the top level task on all processors or one processor per node
  rt.run(TOP_LEVEL_TASK, Runtime::ONE_TASK_ONLY);

  //rt.shutdown();
  return 0;
}
<commit_msg>update taskreg test to use collective spawn calls<commit_after>#include "realm/realm.h"

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <csignal>
#include <cmath>

#include <time.h>
#include <unistd.h>

using namespace Realm;

Logger log_app("app");

// Task IDs, some IDs are reserved so start at first available number
enum {
  TOP_LEVEL_TASK = Processor::TASK_ID_FIRST_AVAILABLE+0,
  CHILD_TASK_ID_START,
};

void child_task(const void *args, size_t arglen,
		const void *userdata, size_t userlen, Processor p)
{
  log_app.print() << "child task on " << p << ": arglen=" << arglen << ", userlen=" << userlen;
}

void top_level_task(const void *args, size_t arglen,
		    const void *userdata, size_t userlen, Processor p)
{
  log_app.print() << "top task running on " << p;

  Machine machine = Machine::get_machine();
  Processor::TaskFuncID func_id = CHILD_TASK_ID_START;

  // first test - register a task individually on each processor and run it
  {
    std::set<Event> finish_events;

    CodeDescriptor child_task_desc(child_task);
    int count = 0;

    std::set<Processor> all_processors;
    machine.get_all_processors(all_processors);
    for(std::set<Processor>::const_iterator it = all_processors.begin();
	it != all_processors.end();
	it++) {
      Processor pp = (*it);

      Event e = pp.register_task(func_id, child_task_desc,
				 ProfilingRequestSet(),
				 &pp, sizeof(pp));

      Event e2 = pp.spawn(func_id, &count, sizeof(count), e);

      finish_events.insert(e2);

      func_id++;
    }

    Event merged = Event::merge_events(finish_events);

    merged.wait();
  }

  // second test - register a task on all LOC_PROCs
  {
    std::set<Event> finish_events;

    CodeDescriptor child_task_desc(child_task);

    Event e = Processor::register_task_by_kind(Processor::LOC_PROC, true /*global*/,
					       func_id,
					       child_task_desc,
					       ProfilingRequestSet());

    int count = 0;

    std::set<Processor> all_processors;
    machine.get_all_processors(all_processors);
    for(std::set<Processor>::const_iterator it = all_processors.begin();
	it != all_processors.end();
	it++) {
      Processor pp = (*it);

      // only LOC_PROCs
      if(pp.kind() != Processor::LOC_PROC)
	continue;

      Event e2 = pp.spawn(func_id, &count, sizeof(count), e);

      finish_events.insert(e2);
    }

    func_id++;

    Event merged = Event::merge_events(finish_events);

    merged.wait();
  }

  log_app.print() << "all done!";
}

int main(int argc, char **argv)
{
  Runtime rt;

  rt.init(&argc, &argv);

  rt.register_task(TOP_LEVEL_TASK, top_level_task);

  // select a processor to run the top level task on
  Processor p = Processor::NO_PROC;
  {
    std::set<Processor> all_procs;
    Machine::get_machine().get_all_processors(all_procs);
    for(std::set<Processor>::const_iterator it = all_procs.begin();
	it != all_procs.end();
	it++)
      if(it->kind() == Processor::LOC_PROC) {
	p = *it;
	break;
      }
  }
  assert(p.exists());

  // collective launch of a single task - everybody gets the same finish event
  Event e = rt.collective_spawn(p, TOP_LEVEL_TASK, 0, 0);

  // request shutdown once that task is complete
  rt.shutdown(e);

  // now sleep this thread until that shutdown actually happens
  rt.wait_for_shutdown();

  return 0;
}
<|endoftext|>


<commit_before>#include "catch.hpp"

#include <regexmanager.h>
#include <exceptions.h>

using namespace newsbeuter;

TEST_CASE("RegexManager behaves correctly", "[regexmanager]") {
	regexmanager rxman;
	std::vector<std::string> params;
	std::string input;

	SECTION("Throws on incorrect `highlight' definition") {
		SECTION("on `highlight' without parameters") {
			REQUIRE_THROWS_AS(rxman.handle_action("highlight", params), confighandlerexception);
		}

		SECTION("on invalid location") {
			params = {"invalidloc", "foo", "blue", "red"};
			REQUIRE_THROWS_AS(rxman.handle_action("highlight", params), confighandlerexception);
		}

		SECTION("on invalid regex") {
			params = {"feedlist", "*", "blue", "red"};
			REQUIRE_THROWS_AS(rxman.handle_action("highlight", params), confighandlerexception);
		}

		SECTION("on invalid command") {
			REQUIRE_THROWS_AS(rxman.handle_action("an-invalid-command", params), confighandlerexception);
		}
	}

	SECTION("Doesn't throw on correct `highlight' definition") {
		params = {"articlelist", "foo", "blue", "red"};
		REQUIRE_NOTHROW(rxman.handle_action("highlight", params));

		params = {"feedlist", "foo", "blue", "red"};
		REQUIRE_NOTHROW(rxman.handle_action("highlight", params));

		params = {"feedlist", "fbo", "blue", "red", "bold", "underline"};
		REQUIRE_NOTHROW(rxman.handle_action("highlight", params));

		params = {"all", "fba", "blue", "red", "bold", "underline"};
		REQUIRE_NOTHROW(rxman.handle_action("highlight", params));

		SECTION("Highlights according to definition") {
			input = "xfoox";
			rxman.quote_and_highlight(input, "articlelist");
			REQUIRE(input == "x<0>foo</>x");

			input = "yfooy";
			rxman.quote_and_highlight(input, "feedlist");
			REQUIRE(input == "y<0>foo</>y");
		}

		SECTION("Preserves text when there's nothing to highlight") {
			input = "xbarx";
			rxman.quote_and_highlight(input, "feedlist");
			REQUIRE(input == "xbarx");

			input = "<";
			rxman.quote_and_highlight(input, "feedlist");
			REQUIRE(input == "<");

			input = "a<b>";
			rxman.quote_and_highlight(input, "feedlist");
			REQUIRE(input == "a<b>");
		}
	}
}

TEST_CASE("`highlight all` adds rules for all locations", "[regexmanager]") {
	regexmanager rxman;
	std::vector<std::string> params = {"all", "foo", "red"};
	REQUIRE_NOTHROW(rxman.handle_action("highlight", params));
	std::string input = "xxfooyy";

	for (auto location : {"article", "articlelist", "feedlist"}) {
		SECTION(location) {
		rxman.quote_and_highlight(input, location);
		REQUIRE(input == "xx<0>foo</>yy");
		}
	}
}
<commit_msg>Drop "correctly" from regexmanager tests<commit_after>#include "catch.hpp"

#include <regexmanager.h>
#include <exceptions.h>

using namespace newsbeuter;

TEST_CASE("RegexManager throws on invalid `highlight' definition",
          "[regexmanager]")
{
	regexmanager rxman;
	std::vector<std::string> params;

	SECTION("on `highlight' without parameters") {
		REQUIRE_THROWS_AS(rxman.handle_action("highlight", params),
				confighandlerexception);
	}

	SECTION("on invalid location") {
		params = {"invalidloc", "foo", "blue", "red"};
		REQUIRE_THROWS_AS(rxman.handle_action("highlight", params),
				confighandlerexception);
	}

	SECTION("on invalid regex") {
		params = {"feedlist", "*", "blue", "red"};
		REQUIRE_THROWS_AS(rxman.handle_action("highlight", params),
				confighandlerexception);
	}

	SECTION("on invalid command") {
		REQUIRE_THROWS_AS(rxman.handle_action("an-invalid-command", params),
				confighandlerexception);
	}
}

TEST_CASE("RegexManager doesn't throw on valid `highlight' definition",
          "[regexmanager]")
{
	regexmanager rxman;
	std::vector<std::string> params;

	params = {"articlelist", "foo", "blue", "red"};
	REQUIRE_NOTHROW(rxman.handle_action("highlight", params));

	params = {"feedlist", "foo", "blue", "red"};
	REQUIRE_NOTHROW(rxman.handle_action("highlight", params));

	params = {"feedlist", "fbo", "blue", "red", "bold", "underline"};
	REQUIRE_NOTHROW(rxman.handle_action("highlight", params));

	params = {"all", "fba", "blue", "red", "bold", "underline"};
	REQUIRE_NOTHROW(rxman.handle_action("highlight", params));
}

TEST_CASE("RegexManager highlights according to definition",
          "[regexmanager]")
{
	regexmanager rxman;
	std::string input;

	rxman.handle_action("highlight", {"articlelist", "foo", "blue", "red"});
	input = "xfoox";
	rxman.quote_and_highlight(input, "articlelist");
	REQUIRE(input == "x<0>foo</>x");

	rxman.handle_action("highlight", {"feedlist", "foo", "blue", "red"});
	input = "yfooy";
	rxman.quote_and_highlight(input, "feedlist");
	REQUIRE(input == "y<0>foo</>y");
}

TEST_CASE("RegexManager preserves text when there's nothing to highlight",
          "[regexmanager]")
{
	regexmanager rxman;
	std::string input = "xbarx";
	rxman.quote_and_highlight(input, "feedlist");
	REQUIRE(input == "xbarx");

	input = "<";
	rxman.quote_and_highlight(input, "feedlist");
	REQUIRE(input == "<");

	input = "a<b>";
	rxman.quote_and_highlight(input, "feedlist");
	REQUIRE(input == "a<b>");
}

TEST_CASE("`highlight all` adds rules for all locations", "[regexmanager]") {
	regexmanager rxman;
	std::vector<std::string> params = {"all", "foo", "red"};
	REQUIRE_NOTHROW(rxman.handle_action("highlight", params));
	std::string input = "xxfooyy";

	for (auto location : {"article", "articlelist", "feedlist"}) {
		SECTION(location) {
		rxman.quote_and_highlight(input, location);
		REQUIRE(input == "xx<0>foo</>yy");
		}
	}
}
<|endoftext|>


<commit_before>#include "catch.hpp"
#include "kangaru/kangaru.hpp"

namespace test_autowire_construct {
	struct service1 {};
	auto service_map(service1 const&) -> kgr::autowire;

	struct service2 { friend auto service_map(service2 const&) -> kgr::autowire; };

	TEST_CASE("autowire can construct a service", "[autowire]") {
		SECTION("Without dependency") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service1>>::value);
			(void) kgr::container{}.service<kgr::autowired<service1>>();
		}

		SECTION("Without dependency with a friend function") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);
			(void) kgr::container{}.service<kgr::autowired<service2>>();
		}
	}
}

namespace test_autowire_depencency {
	int nb_s1_constructed;

	struct service1 { service1() { nb_s1_constructed++; } };
	auto service_map(service1 const&) -> kgr::autowire;

	struct service2 {
		service1 s1;

		friend auto service_map(service2 const&) -> kgr::autowire;
	};

	TEST_CASE("autowire can have depencencies", "[autowire]") {
		nb_s1_constructed = 0;
		kgr::container container;

		SECTION("Without dependency") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service1>>::value);
			(void) container.service<kgr::autowired<service1>>();

			CHECK(nb_s1_constructed == 1);

			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);
			(void) container.service<kgr::autowired<service2>>();

			CHECK(nb_s1_constructed == 2);
		}
	}
}

namespace test_autowire_single {
	int nb_s1_constructed;

	struct service1 { service1() { nb_s1_constructed++; } };
	auto service_map(service1 const&) -> kgr::autowire_single;

	struct service2 {
		service1& s1;

		friend auto service_map(service2 const&) -> kgr::autowire;
	};

	TEST_CASE("autowire single behave as a single service", "[autowire]") {
		nb_s1_constructed = 0;

		REQUIRE(kgr::detail::is_single<kgr::autowired<service1>>::value);
		kgr::container container;

		SECTION("When injected as dependency") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service1>>::value);
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);

			auto& s1 = container.service<kgr::autowired<service1>>();
			CHECK(nb_s1_constructed == 1);

			auto s2 = container.service<kgr::autowired<service2>>();
			CHECK(nb_s1_constructed == 1);

			REQUIRE(&s1 == &s2.s1);
		}
	}
}

namespace test_autowire_multiple_dependency {
	int nb_s1_constructed;

	struct service1 { service1() { nb_s1_constructed++; } };
	auto service_map(service1 const&) -> kgr::autowire_single;

	struct service2 {
		service1& s1;
		kgr::container& container;

		friend auto service_map(service2 const&) -> kgr::autowire;
	};

	struct service3 {
		service3(kgr::container f, service2 s) : forked(std::move(f)), s2(std::move(s)) {}
		kgr::container forked;
		service2 s2;

		friend auto service_map(service3 const&) -> kgr::autowire;
	};

	TEST_CASE("autowired service can have multiple dependencis", "[autowire]") {
		nb_s1_constructed = 0;
		kgr::container container;

		SECTION("Work with multiple dependencies") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);
			(void) container.service<kgr::autowired<service2>>();
			REQUIRE(nb_s1_constructed == 1);
		}

		SECTION("Work with multiple levels of dependencies") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service3>>::value);
			(void) container.service<kgr::autowired<service3>>();
			REQUIRE(nb_s1_constructed == 1);
		}
	}
}

namespace test_autowire_normal_services {
	struct service1 {
		kgr::invoker i;
	};

	auto service_map(service1 const&) -> kgr::single_service<service1, kgr::autowire>;

	struct service2 {
		service1& s1;
		kgr::container& container;

		friend auto service_map(service2 const&) -> kgr::service<service2, kgr::autowire>;
	};

	TEST_CASE("autowire works with other service types", "[autowire]") {
		kgr::container container;

		REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service1>>::value);
		REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);
		(void) container.service<kgr::autowired<service1>>();
		(void) container.service<kgr::autowired<service2>>();
	}
}

namespace test_autowire_mapped {
	bool bad_constructed = false;

	struct service_bad {
		service_bad() { bad_constructed = true; }
	};
	struct service1 {
		service1() = default;
		service1(service_bad) {}
	};

	struct service2 {
		service1 s1;
	};

	struct map {};
	struct definition2 : kgr::service<service2, kgr::mapped_autowire<kgr::map<map>>> {};

	struct definition1 : kgr::service<service1> {};
	struct definition_bad : kgr::service<service_bad> {};
	struct not_definition : kgr::service<service1, kgr::dependency<definition_bad>> {};

	auto service_map(service1 const&, kgr::map_t<map>) -> definition1;
	auto service_map(service1 const&) -> not_definition;
	auto service_map(service2 const&, kgr::map_t<map>) -> definition2;

	TEST_CASE("The service map maps function to services using service_map with specific map", "[service_map]") {
		kgr::container container;
		bad_constructed = false;

		REQUIRE((std::is_same<kgr::autowired<service1, kgr::map<map>>, definition1>::value));

		(void) container.service<definition2>();
		REQUIRE(!bad_constructed);

		(void) container.service<not_definition>();
		CHECK(bad_constructed);
	}
}
<commit_msg>Added back the 'no self injection' test<commit_after>#include "catch.hpp"
#include "kangaru/kangaru.hpp"

namespace test_autowire_construct {
	struct service1 {};
	auto service_map(service1 const&) -> kgr::autowire;

	struct service2 { friend auto service_map(service2 const&) -> kgr::autowire; };

	TEST_CASE("autowire can construct a service", "[autowire]") {
		SECTION("Without dependency") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service1>>::value);
			(void) kgr::container{}.service<kgr::autowired<service1>>();
		}

		SECTION("Without dependency with a friend function") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);
			(void) kgr::container{}.service<kgr::autowired<service2>>();
		}
	}
}

namespace test_autowire_depencency {
	int nb_s1_constructed;

	struct service1 { service1() { nb_s1_constructed++; } };
	auto service_map(service1 const&) -> kgr::autowire;

	struct service2 {
		service1 s1;

		friend auto service_map(service2 const&) -> kgr::autowire;
	};

	TEST_CASE("autowire can have depencencies", "[autowire]") {
		nb_s1_constructed = 0;
		kgr::container container;

		SECTION("Without dependency") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service1>>::value);
			(void) container.service<kgr::autowired<service1>>();

			CHECK(nb_s1_constructed == 1);

			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);
			(void) container.service<kgr::autowired<service2>>();

			CHECK(nb_s1_constructed == 2);
		}
	}
}

namespace test_autowire_single {
	int nb_s1_constructed;

	struct service1 { service1() { nb_s1_constructed++; } };
	auto service_map(service1 const&) -> kgr::autowire_single;

	struct service2 {
		service1& s1;

		friend auto service_map(service2 const&) -> kgr::autowire;
	};

	struct service3 {
		service3& s3;

		friend auto service_map(service3 const&) -> kgr::autowire_single;
	};

	TEST_CASE("autowire single behave as a single service", "[autowire]") {
		nb_s1_constructed = 0;

		REQUIRE(kgr::detail::is_single<kgr::autowired<service1>>::value);
		kgr::container container;

		SECTION("When injected as dependency") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service1>>::value);
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);

			auto& s1 = container.service<kgr::autowired<service1>>();
			CHECK(nb_s1_constructed == 1);

			auto s2 = container.service<kgr::autowired<service2>>();
			CHECK(nb_s1_constructed == 1);

			REQUIRE(&s1 == &s2.s1);
		}

		SECTION("Cannot inject itself into itself") {
			REQUIRE(!kgr::detail::is_service_valid<kgr::autowired<service3>>::value);
		}
	}
}

namespace test_autowire_multiple_dependency {
	int nb_s1_constructed;

	struct service1 { service1() { nb_s1_constructed++; } };
	auto service_map(service1 const&) -> kgr::autowire_single;

	struct service2 {
		service1& s1;
		kgr::container& container;

		friend auto service_map(service2 const&) -> kgr::autowire;
	};

	struct service3 {
		service3(kgr::container f, service2 s) : forked(std::move(f)), s2(std::move(s)) {}
		kgr::container forked;
		service2 s2;

		friend auto service_map(service3 const&) -> kgr::autowire;
	};

	TEST_CASE("autowired service can have multiple dependencis", "[autowire]") {
		nb_s1_constructed = 0;
		kgr::container container;

		SECTION("Work with multiple dependencies") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);
			(void) container.service<kgr::autowired<service2>>();
			REQUIRE(nb_s1_constructed == 1);
		}

		SECTION("Work with multiple levels of dependencies") {
			REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service3>>::value);
			(void) container.service<kgr::autowired<service3>>();
			REQUIRE(nb_s1_constructed == 1);
		}
	}
}

namespace test_autowire_normal_services {
	struct service1 {
		kgr::invoker i;
	};

	auto service_map(service1 const&) -> kgr::single_service<service1, kgr::autowire>;

	struct service2 {
		service1& s1;
		kgr::container& container;

		friend auto service_map(service2 const&) -> kgr::service<service2, kgr::autowire>;
	};

	TEST_CASE("autowire works with other service types", "[autowire]") {
		kgr::container container;

		REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service1>>::value);
		REQUIRE(kgr::detail::is_service_valid<kgr::autowired<service2>>::value);
		(void) container.service<kgr::autowired<service1>>();
		(void) container.service<kgr::autowired<service2>>();
	}
}

namespace test_autowire_mapped {
	bool bad_constructed = false;

	struct service_bad {
		service_bad() { bad_constructed = true; }
	};
	struct service1 {
		service1() = default;
		service1(service_bad) {}
	};

	struct service2 {
		service1 s1;
	};

	struct map {};
	struct definition2 : kgr::service<service2, kgr::mapped_autowire<kgr::map<map>>> {};

	struct definition1 : kgr::service<service1> {};
	struct definition_bad : kgr::service<service_bad> {};
	struct not_definition : kgr::service<service1, kgr::dependency<definition_bad>> {};

	auto service_map(service1 const&, kgr::map_t<map>) -> definition1;
	auto service_map(service1 const&) -> not_definition;
	auto service_map(service2 const&, kgr::map_t<map>) -> definition2;

	TEST_CASE("The service map maps function to services using service_map with specific map", "[service_map]") {
		kgr::container container;
		bad_constructed = false;

		REQUIRE((std::is_same<kgr::autowired<service1, kgr::map<map>>, definition1>::value));

		(void) container.service<definition2>();
		REQUIRE(!bad_constructed);

		(void) container.service<not_definition>();
		CHECK(bad_constructed);
	}
}
<|endoftext|>