<commit_before>#include "stdsneezy.h"
#include "database.h"
#include "session.cgi.h"

#include <vector>
#include <map>
#include <list>
#include "sstring.h"

#include "cgicc/Cgicc.h"
#include "cgicc/HTTPHTMLHeader.h"
#include "cgicc/HTTPPlainHeader.h"
#include "cgicc/HTMLClasses.h"
#include <cgicc/HTTPCookie.h>
#include <cgicc/CgiEnvironment.h>
#include <cgicc/HTTPRedirectHeader.h>

#include <sys/types.h>

using namespace cgicc;

void sendJavaScript();
sstring mudColorToHTML(sstring, bool spacer=true);

void sendResplist(int);
void sendShowResp(int, int, bool);
void saveResp(Cgicc, int);
void makeNewResp(Cgicc, int, bool);
void delResp(Cgicc, int);

bool checkPlayerName(int account_id, sstring name)
{
  TDatabase db(DB_SNEEZY);

  db.query("select 1 from player where lower(name)=lower('%s') and account_id=%i", name.c_str(), account_id);

  if(db.fetchRow())
    return true;
  return false;
}

sstring getPlayerNames(int account_id)
{
  TDatabase db(DB_SNEEZY);
  sstring names;

  db.query("select lower(name) as name from player where account_id=%i",
	   account_id);

  if(db.fetchRow())
    names=fmt("'%s'") % db["name"];

  while(db.fetchRow()){
    names+=fmt(", '%s'") % db["name"];
  }

  return names;
}

int main(int argc, char **argv)
{
  // trick the DB code into use prod database
  gamePort=PROD_GAMEPORT;

  Cgicc cgi;
  form_iterator state_form=cgi.getElement("state");
  TSession session(cgi, "SneezyMUD");

  if(!session.isValid()){
    session.doLogin(cgi, "respeditor.cgi");
    return 0;
  }

  if(!session.hasWizPower(POWER_BUILDER)){
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head(title("Response Editor")) << endl;
    cout << body() << endl;
    cout << "You don't have permission to use this.";
    cout << body() << endl;
    return 0;
  }

  if(state_form == cgi.getElements().end() || **state_form == "main"){
    sendResplist(session.getAccountID());
    return 0;
  } else if(**state_form == "delresp"){
    delResp(cgi, session.getAccountID());
    sendResplist(session.getAccountID());
    return 0;
  } else if(**state_form == "newresp"){
    form_iterator vnum=cgi.getElement("vnum");
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Respeditor") << endl;
    cout << head() << body() << endl;

    makeNewResp(cgi, session.getAccountID(), session.hasWizPower(POWER_LOAD));
    sendShowResp(session.getAccountID(), convertTo<int>(**vnum),
		session.hasWizPower(POWER_WIZARD));
    return 0;
  } else if(**state_form == "showresp"){
    form_iterator vnum=cgi.getElement("vnum");
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Respeditor") << endl;
    cout << head() << body() << endl;

    sendShowResp(session.getAccountID(), convertTo<int>(**vnum),
		session.hasWizPower(POWER_WIZARD));
    return 0;
  } else if(**state_form == "saveresp"){
    form_iterator vnum=cgi.getElement("vnum");
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Respeditor") << endl;
    cout << head() << body() << endl;

    saveResp(cgi, session.getAccountID());
    sendShowResp(session.getAccountID(), convertTo<int>(**vnum),
		session.hasWizPower(POWER_WIZARD));
    return 0;
  } else if(**state_form == "logout"){
    session.logout();
    cout << HTTPRedirectHeader("respeditor.cgi").setCookie(session.getCookie());
    cout << endl;
    return 0;
  }

  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Respeditor") << endl;
  cout << head() << body() << endl;
  cout << "Fell through state switch.  Bad.

" << endl;
  cout << **state_form << endl;
  cout << body() << endl;
  cout << html() << endl;

  return 0;
}

void delResp(Cgicc cgi, int account_id)
{
  TDatabase db(DB_IMMORTAL);

  if(!checkPlayerName(account_id, **(cgi.getElement("owner")))){
    cout << "Owner name didn't match - security violation.";
    return;
  }

  db.query("delete from mobresponse where vnum=%s and owner='%s'",
	   (**(cgi.getElement("vnum"))).c_str(),
	   (**(cgi.getElement("owner"))).c_str());
}

void makeNewResp(Cgicc cgi, int account_id, bool power_load)
{
  TDatabase db(DB_IMMORTAL);
  TDatabase db_sneezy(DB_SNEEZY);

  if(!checkPlayerName(account_id, **(cgi.getElement("owner")))){
    cout << "Owner name didn't match - security violation.";
    return;
  }

  db_sneezy.query("select response from mobresponses where vnum=%s", (**(cgi.getElement("template"))).c_str());
  db_sneezy.fetchRow();

  db.query("insert into mobresponses (ownerm vnum, response) values ('%s', %s, '%s')",
	   (**(cgi.getElement("owner"))).c_str(),
	   (**(cgi.getElement("vnum"))).c_str(),
	   db_sneezy["response"].c_str());

}

void saveResp(Cgicc cgi, int account_id)
{
  TDatabase db(DB_IMMORTAL);

  if(!checkPlayerName(account_id, **(cgi.getElement("owner")))){
    cout << "Owner name didn't match - security violation.";
    return;
  }

  db.query("delete from mobresponses where owner='%s' and vnum=%s",
  	   (**(cgi.getElement("owner"))).c_str(),
  	   (**(cgi.getElement("vnum"))).c_str());

  db.query("insert into mobresponses (owner, vnum, response) values ('%s', %s, '%s')",
	   (**(cgi.getElement("owner"))).c_str(),
	   (**(cgi.getElement("vnum"))).c_str(),
	   (**(cgi.getElement("response"))).c_str());

  cout << "Saved.
";
}

void sendShowResp(int account_id, int vnum, bool wizard)
{
  TDatabase db(DB_IMMORTAL);

  assign_item_info();

  db.query("select owner, vnum, response from mobresonses where vnum=%i and owner in (%r)", vnum, getPlayerNames(account_id).c_str());
  db.fetchRow();

  cout << "<form method=post action=objeditor.cgi>" << endl;
  cout << "

";
  cout << "<button name=state value=logout type=submit>logout</button>	";
  cout << "<button name=state value=main type=submit>response list</button>	";
  cout << "<button name=state value=delresp type=submit>delete</button>	";
  cout << "<input type=hidden name=owner value='" << db["owner"] << "'>";
  cout << "<input type=hidden name=vnum value='" << vnum << "'>";
  cout << "
</form>" << endl;

  cout << "<form action=\"respeditor.cgi\" method=post name=saveresp>" << endl;
  cout << "<input type=hidden name=state value=saveresp>" << endl;

  cout << "<input type=hidden name=owner value='" << db["owner"] << "'>";

  cout << "
";

  cout << fmt("
%s	<input type=text size=127 name='%s' value='%s'>
\n") % "vnum" % "vnum" % db["vnum"];

  sstring buf=db["response"];
  while (buf.find("'") != sstring::npos)
    buf.replace(buf.find("'"), 1, "’");

  cout << fmt("
%s	<input type=text size=127 name='%s' value='%s'>
\n") % "response" % "response" % buf;

  cout << fmt("
	%s
\n") %
    mudColorToHTML(db["response"]);

  cout << "
";

  cout << "<input type=submit value='save changes'>";
  cout << "</form>" << endl;

  cout << body() << endl;
  cout << html() << endl;

}

void sendResplist(int account_id){
  TDatabase db(DB_IMMORTAL);

  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Respeditor") << endl;
  sendJavaScript();
  cout << head() << body() << endl;

  cout << "<form method=post action=respeditor.cgi>" << endl;
  cout << "<button name=state value=logout type=submit>logout</button>";
  cout << "
</form>";

  sstring buildername;

  db.query("select owner, max(vnum)+1 as nvnum from resp where lower(owner) in (%r) group by owner",
	   getPlayerNames(account_id).c_str());

  if(db.fetchRow())
    buildername=db["owner"];
  else {
    // no objects yet
    TDatabase db_sneezy(DB_SNEEZY);
    db_sneezy.query("select p.name as name from wizpower w, account a, player p where p.id=w.player_id and p.account_id=a.account_id and a.account_id=%i and w.wizpower=%i", account_id, mapWizPowerToFile(POWER_BUILDER));
    db_sneezy.fetchRow();
    buildername=db_sneezy["name"];
  }

  cout << "<form method=post action=respeditor.cgi>" << endl;
  cout << "<button name=state value=newresp type=submit>new resp</button>";
  cout << "vnum <input type=text name=vnum value=" << db["nvnum"] << ">";
  cout << "template <input type=text name=template value=1>";
  cout << "<input type=hidden name=owner value='" << buildername << "'>";
  cout << "</form>";
  cout << endl;

  cout << "<form action=\"respeditor.cgi\" method=post name=pickresp>" << endl;
  cout << "<input type=hidden name=vnum>" << endl;
  cout << "<input type=hidden name=state>" << endl;

  cout << "
";
  cout << "
vnum	name	short_desc	extras	affects
";

  db.query("select vnum, name, short_desc from resp o where lower(owner) in (%r) order by vnum asc", getPlayerNames(account_id).c_str());

  while(db.fetchRow()){
    cout << "
" << "<a href=javascript:pickresp('" << db["vnum"];
    cout << "','showresp')>" << db["vnum"] << "" << endl;
    cout << "	" << endl;
    cout << "
" << endl;

  }

  cout << "
</form>" << endl;

  cout << body() << endl;
  cout << html() << endl;
}

void sendJavaScript()
{
  cout << "" << endl;

}

// candidate for inclusion in sstring
void replaceString(sstring &str, sstring find, sstring replace)
{
  while(str.find(find)!=sstring::npos){
    str.replace(str.find(find), find.size(), replace);
  }
}

// candidate for some sort of global cgi tools library
sstring mudColorToHTML(sstring str, bool spacer)
{

  replaceString(str, "\n", "
");

  replaceString(str, "<f>", "");
  //  replaceString(str, " ", " ");
  replaceString(str, "<r>", "");
  replaceString(str, "<R>", "");

  replaceString(str, "", "");
  replaceString(str, "", "");
  replaceString(str, "<g>", "");
  replaceString(str, "<G>", "");
  replaceString(str, "<c>", "");
  replaceString(str, "<C>", "");
  replaceString(str, "
", "");
  replaceString(str, "
", "");
  replaceString(str, "<o>", "");
  replaceString(str, "<O>", "");
  replaceString(str, "<y>", "");
  replaceString(str, "<Y>", "");
  replaceString(str, "<k>", "");
  replaceString(str, "<K>", "");
  replaceString(str, "<w>", "");
  replaceString(str, "<W>", "");
  replaceString(str, "<Z>", "");
  replaceString(str, "<z>", "");
  replaceString(str, "<1>", "");

  // to help builders line up text
  sstring spacing_strip="01234567890123456789012345678901234567890123456789012345678901234567890123456789
";

  if(!spacer)
    spacing_strip="";

  return fmt("%s%s") % spacing_strip % str;
}

<commit_msg>fixed a few bugs, tested<commit_after>#include "stdsneezy.h"
#include "database.h"
#include "session.cgi.h"

#include <vector>
#include <map>
#include <list>
#include "sstring.h"

#include "cgicc/Cgicc.h"
#include "cgicc/HTTPHTMLHeader.h"
#include "cgicc/HTTPPlainHeader.h"
#include "cgicc/HTMLClasses.h"
#include <cgicc/HTTPCookie.h>
#include <cgicc/CgiEnvironment.h>
#include <cgicc/HTTPRedirectHeader.h>

#include <sys/types.h>

using namespace cgicc;

void sendJavaScript();
sstring mudColorToHTML(sstring, bool spacer=true);

void sendResplist(int);
void sendShowResp(int, int, bool);
void saveResp(Cgicc, int);
void makeNewResp(Cgicc, int, bool);
void delResp(Cgicc, int);

bool checkPlayerName(int account_id, sstring name)
{
  TDatabase db(DB_SNEEZY);

  db.query("select 1 from player where lower(name)=lower('%s') and account_id=%i", name.c_str(), account_id);

  if(db.fetchRow())
    return true;
  return false;
}

sstring getPlayerNames(int account_id)
{
  TDatabase db(DB_SNEEZY);
  sstring names;

  db.query("select lower(name) as name from player where account_id=%i",
	   account_id);

  if(db.fetchRow())
    names=fmt("'%s'") % db["name"];

  while(db.fetchRow()){
    names+=fmt(", '%s'") % db["name"];
  }

  return names;
}

int main(int argc, char **argv)
{
  // trick the DB code into use prod database
  gamePort=PROD_GAMEPORT;

  Cgicc cgi;
  form_iterator state_form=cgi.getElement("state");
  TSession session(cgi, "SneezyMUD");

  if(!session.isValid()){
    session.doLogin(cgi, "respeditor.cgi");
    return 0;
  }

  if(!session.hasWizPower(POWER_BUILDER)){
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head(title("Response Editor")) << endl;
    cout << body() << endl;
    cout << "You don't have permission to use this.";
    cout << body() << endl;
    return 0;
  }

  if(state_form == cgi.getElements().end() || **state_form == "main"){
    sendResplist(session.getAccountID());
    return 0;
  } else if(**state_form == "delresp"){
    delResp(cgi, session.getAccountID());
    sendResplist(session.getAccountID());
    return 0;
  } else if(**state_form == "newresp"){
    form_iterator vnum=cgi.getElement("vnum");
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Respeditor") << endl;
    cout << head() << body() << endl;

    makeNewResp(cgi, session.getAccountID(), session.hasWizPower(POWER_LOAD));
    sendShowResp(session.getAccountID(), convertTo<int>(**vnum),
		session.hasWizPower(POWER_WIZARD));
    return 0;
  } else if(**state_form == "showresp"){
    form_iterator vnum=cgi.getElement("vnum");
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Respeditor") << endl;
    cout << head() << body() << endl;

    sendShowResp(session.getAccountID(), convertTo<int>(**vnum),
		session.hasWizPower(POWER_WIZARD));
    return 0;
  } else if(**state_form == "saveresp"){
    form_iterator vnum=cgi.getElement("vnum");
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Respeditor") << endl;
    cout << head() << body() << endl;

    saveResp(cgi, session.getAccountID());
    sendShowResp(session.getAccountID(), convertTo<int>(**vnum),
		session.hasWizPower(POWER_WIZARD));
    return 0;
  } else if(**state_form == "logout"){
    session.logout();
    cout << HTTPRedirectHeader("respeditor.cgi").setCookie(session.getCookie());
    cout << endl;
    return 0;
  }

  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Respeditor") << endl;
  cout << head() << body() << endl;
  cout << "Fell through state switch.  Bad.

" << endl;
  cout << **state_form << endl;
  cout << body() << endl;
  cout << html() << endl;

  return 0;
}

void delResp(Cgicc cgi, int account_id)
{
  TDatabase db(DB_IMMORTAL);

  if(!checkPlayerName(account_id, **(cgi.getElement("owner")))){
    cout << "Owner name didn't match - security violation.";
    return;
  }

  db.query("delete from mobresponses where vnum=%s and owner='%s'",
	   (**(cgi.getElement("vnum"))).c_str(),
	   (**(cgi.getElement("owner"))).c_str());
}

void makeNewResp(Cgicc cgi, int account_id, bool power_load)
{
  TDatabase db(DB_IMMORTAL);
  TDatabase db_sneezy(DB_SNEEZY);

  if(!checkPlayerName(account_id, **(cgi.getElement("owner")))){
    cout << "Owner name didn't match - security violation.";
    return;
  }

  db.query("insert into mobresponses (owner, vnum, response) values ('%s', %s, '')",
	   (**(cgi.getElement("owner"))).c_str(),
	   (**(cgi.getElement("vnum"))).c_str());

}

void saveResp(Cgicc cgi, int account_id)
{
  TDatabase db(DB_IMMORTAL);

  if(!checkPlayerName(account_id, **(cgi.getElement("owner")))){
    cout << "Owner name didn't match - security violation.";
    return;
  }

  db.query("delete from mobresponses where owner='%s' and vnum=%s",
  	   (**(cgi.getElement("owner"))).c_str(),
  	   (**(cgi.getElement("vnum"))).c_str());

  db.query("insert into mobresponses (owner, vnum, response) values ('%s', %s, '%s')",
	   (**(cgi.getElement("owner"))).c_str(),
	   (**(cgi.getElement("vnum"))).c_str(),
	   (**(cgi.getElement("response"))).c_str());

  cout << "Saved.
";
}

void sendShowResp(int account_id, int vnum, bool wizard)
{
  TDatabase db(DB_IMMORTAL);

  assign_item_info();

  db.query("select owner, vnum, response from mobresponses where vnum=%i and owner in (%r)", vnum, getPlayerNames(account_id).c_str());
  db.fetchRow();

  cout << "<form method=post action=respeditor.cgi>" << endl;
  cout << "

";
  cout << "<button name=state value=logout type=submit>logout</button>	";
  cout << "<button name=state value=main type=submit>response list</button>	";
  cout << "<button name=state value=delresp type=submit>delete</button>	";
  cout << "<input type=hidden name=owner value='" << db["owner"] << "'>";
  cout << "<input type=hidden name=vnum value='" << vnum << "'>";
  cout << "
</form>" << endl;

  cout << "<form action=\"respeditor.cgi\" method=post name=saveresp>" << endl;
  cout << "<input type=hidden name=state value=saveresp>" << endl;

  cout << "<input type=hidden name=owner value='" << db["owner"] << "'>";

  cout << "
";

  cout << fmt("
%s	<input type=text size=127 name='%s' value='%s'>
\n") % "vnum" % "vnum" % db["vnum"];

  sstring buf=db["response"];
  while (buf.find("'") != sstring::npos)
    buf.replace(buf.find("'"), 1, "’");

  cout << fmt("
%s	<textarea name='%s' cols=90 rows=30>%s</textarea>
\n") % "response" % "response" % buf;

  cout << "
";

  cout << "<input type=submit value='save changes'>";
  cout << "</form>" << endl;

  cout << body() << endl;
  cout << html() << endl;

}

void sendResplist(int account_id){
  TDatabase db(DB_IMMORTAL);

  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Respeditor") << endl;
  sendJavaScript();
  cout << head() << body() << endl;

  cout << "<form method=post action=respeditor.cgi>" << endl;
  cout << "<button name=state value=logout type=submit>logout</button>";
  cout << "
</form>";

  sstring buildername;

  db.query("select owner, max(vnum)+1 as nvnum from mobresponses where lower(owner) in (%r) group by owner",
	   getPlayerNames(account_id).c_str());

  if(db.fetchRow())
    buildername=db["owner"];
  else {
    // no objects yet
    TDatabase db_sneezy(DB_SNEEZY);
    db_sneezy.query("select p.name as name from wizpower w, account a, player p where p.id=w.player_id and p.account_id=a.account_id and a.account_id=%i and w.wizpower=%i", account_id, mapWizPowerToFile(POWER_BUILDER));
    db_sneezy.fetchRow();
    buildername=db_sneezy["name"];
  }

  cout << "<form method=post action=respeditor.cgi>" << endl;
  cout << "<button name=state value=newresp type=submit>new resp</button>";
  cout << "vnum <input type=text name=vnum value=" << db["nvnum"] << ">";
  cout << "<input type=hidden name=owner value='" << buildername << "'>";
  cout << "</form>";
  cout << endl;

  cout << "<form action=\"respeditor.cgi\" method=post name=pickresp>" << endl;
  cout << "<input type=hidden name=vnum>" << endl;
  cout << "<input type=hidden name=state>" << endl;

  cout << "
";
  cout << "
vnum
";

  db.query("select vnum, response from mobresponses where lower(owner) in (%r) order by vnum asc", getPlayerNames(account_id).c_str());

  while(db.fetchRow()){
    cout << "
" << "<a href=javascript:pickresp('" << db["vnum"];
    cout << "','showresp')>" << db["vnum"] << "" << endl;
    cout << "	" << endl;
    cout << "
" << endl;

  }

  cout << "
</form>" << endl;

  cout << body() << endl;
  cout << html() << endl;
}

void sendJavaScript()
{
  cout << "" << endl;

}

// candidate for inclusion in sstring
void replaceString(sstring &str, sstring find, sstring replace)
{
  while(str.find(find)!=sstring::npos){
    str.replace(str.find(find), find.size(), replace);
  }
}

// candidate for some sort of global cgi tools library
sstring mudColorToHTML(sstring str, bool spacer)
{

  replaceString(str, "\n", "
");

  replaceString(str, "<f>", "");
  //  replaceString(str, " ", " ");
  replaceString(str, "<r>", "");
  replaceString(str, "<R>", "");

  replaceString(str, "", "");
  replaceString(str, "", "");
  replaceString(str, "<g>", "");
  replaceString(str, "<G>", "");
  replaceString(str, "<c>", "");
  replaceString(str, "<C>", "");
  replaceString(str, "
", "");
  replaceString(str, "
", "");
  replaceString(str, "<o>", "");
  replaceString(str, "<O>", "");
  replaceString(str, "<y>", "");
  replaceString(str, "<Y>", "");
  replaceString(str, "<k>", "");
  replaceString(str, "<K>", "");
  replaceString(str, "<w>", "");
  replaceString(str, "<W>", "");
  replaceString(str, "<Z>", "");
  replaceString(str, "<z>", "");
  replaceString(str, "<1>", "");

  // to help builders line up text
  sstring spacing_strip="01234567890123456789012345678901234567890123456789012345678901234567890123456789
";

  if(!spacer)
    spacing_strip="";

  return fmt("%s%s") % spacing_strip % str;
}

<|endoftext|>


<commit_before>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  David Shah <david@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "place_common.h"
#include <cmath>
#include "log.h"
#include "util.h"

NEXTPNR_NAMESPACE_BEGIN

// Get the total estimated wirelength for a net
wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type, float &tns)
{
    wirelen_t wirelength = 0;
    Loc driver_loc;
    bool driver_gb;
    CellInfo *driver_cell = net->driver.cell;
    if (!driver_cell)
        return 0;
    if (driver_cell->bel == BelId())
        return 0;
    driver_gb = ctx->getBelGlobalBuf(driver_cell->bel);
    driver_loc = ctx->getBelLocation(driver_cell->bel);
    if (driver_gb)
        return 0;
    delay_t worst_slack = std::numeric_limits<delay_t>::max();
    int xmin = driver_loc.x, xmax = driver_loc.x, ymin = driver_loc.y, ymax = driver_loc.y;
    for (auto load : net->users) {
        if (load.cell == nullptr)
            continue;
        CellInfo *load_cell = load.cell;
        if (load_cell->bel == BelId())
            continue;
        if (ctx->timing_driven && type == MetricType::COST) {
            delay_t net_delay = ctx->predictDelay(net, load);
            auto slack = load.budget - net_delay;
            if (slack < 0)
                tns += slack;
            worst_slack = std::min(slack, worst_slack);
        }

        if (ctx->getBelGlobalBuf(load_cell->bel))
            continue;
        Loc load_loc = ctx->getBelLocation(load_cell->bel);

        xmin = std::min(xmin, load_loc.x);
        ymin = std::min(ymin, load_loc.y);
        xmax = std::max(xmax, load_loc.x);
        ymax = std::max(ymax, load_loc.y);
    }
    if (ctx->timing_driven && type == MetricType::COST) {
        wirelength = wirelen_t((((ymax - ymin) + (xmax - xmin)) * std::min(5.0, (1.0 + std::exp(-worst_slack / 5)))));
    } else {
        wirelength = wirelen_t((ymax - ymin) + (xmax - xmin));
    }

    tns = ctx->getDelayNS(tns);
    return wirelength;
}

// Get the total wirelength for a cell
wirelen_t get_cell_metric(const Context *ctx, const CellInfo *cell, MetricType type)
{
    std::set<IdString> nets;
    for (auto p : cell->ports) {
        if (p.second.net)
            nets.insert(p.second.net->name);
    }
    wirelen_t wirelength = 0;
    float tns = 0;
    for (auto n : nets) {
        wirelength += get_net_metric(ctx, ctx->nets.at(n).get(), type, tns);
    }
    return wirelength;
}

wirelen_t get_cell_metric_at_bel(const Context *ctx, CellInfo *cell, BelId bel, MetricType type)
{
    BelId oldBel = cell->bel;
    cell->bel = bel;
    wirelen_t wirelen = get_cell_metric(ctx, cell, type);
    cell->bel = oldBel;
    return wirelen;
}

// Placing a single cell
bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
{
    bool all_placed = false;
    int iters = 25;
    while (!all_placed) {
        BelId best_bel = BelId();
        wirelen_t best_wirelen = std::numeric_limits<wirelen_t>::max(),
                  best_ripup_wirelen = std::numeric_limits<wirelen_t>::max();
        CellInfo *ripup_target = nullptr;
        BelId ripup_bel = BelId();
        if (cell->bel != BelId()) {
            ctx->unbindBel(cell->bel);
        }
        BelType targetType = ctx->belTypeFromId(cell->type);
        for (auto bel : ctx->getBels()) {
            if (ctx->getBelType(bel) == targetType && (!require_legality || ctx->isValidBelForCell(cell, bel))) {
                if (ctx->checkBelAvail(bel)) {
                    wirelen_t wirelen = get_cell_metric_at_bel(ctx, cell, bel, MetricType::COST);
                    if (iters >= 4)
                        wirelen += ctx->rng(25);
                    if (wirelen <= best_wirelen) {
                        best_wirelen = wirelen;
                        best_bel = bel;
                    }
                } else {
                    wirelen_t wirelen = get_cell_metric_at_bel(ctx, cell, bel, MetricType::COST);
                    if (iters >= 4)
                        wirelen += ctx->rng(25);
                    if (wirelen <= best_ripup_wirelen) {
                        CellInfo *curr_cell = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
                        if (curr_cell->belStrength < STRENGTH_STRONG) {
                            best_ripup_wirelen = wirelen;
                            ripup_bel = bel;
                            ripup_target = curr_cell;
                        }
                    }
                }
            }
        }
        if (best_bel == BelId()) {
            if (iters == 0) {
                log_error("failed to place cell '%s' of type '%s' (ripup iteration limit exceeded)\n",
                          cell->name.c_str(ctx), cell->type.c_str(ctx));
            }
            if (ripup_bel == BelId()) {
                log_error("failed to place cell '%s' of type '%s'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
            }
            --iters;
            ctx->unbindBel(ripup_target->bel);
            best_bel = ripup_bel;
        } else {
            all_placed = true;
        }
        ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);

        cell = ripup_target;
    }
    return true;
}

NEXTPNR_NAMESPACE_END
<commit_msg>Fix tns computation<commit_after>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  David Shah <david@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "place_common.h"
#include <cmath>
#include "log.h"
#include "util.h"

NEXTPNR_NAMESPACE_BEGIN

// Get the total estimated wirelength for a net
wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type, float &tns)
{
    wirelen_t wirelength = 0;
    Loc driver_loc;
    bool driver_gb;
    CellInfo *driver_cell = net->driver.cell;
    if (!driver_cell)
        return 0;
    if (driver_cell->bel == BelId())
        return 0;
    driver_gb = ctx->getBelGlobalBuf(driver_cell->bel);
    driver_loc = ctx->getBelLocation(driver_cell->bel);
    if (driver_gb)
        return 0;
    delay_t negative_slack = 0;
    delay_t worst_slack = std::numeric_limits<delay_t>::max();
    int xmin = driver_loc.x, xmax = driver_loc.x, ymin = driver_loc.y, ymax = driver_loc.y;
    for (auto load : net->users) {
        if (load.cell == nullptr)
            continue;
        CellInfo *load_cell = load.cell;
        if (load_cell->bel == BelId())
            continue;
        if (ctx->timing_driven && type == MetricType::COST) {
            delay_t net_delay = ctx->predictDelay(net, load);
            auto slack = load.budget - net_delay;
            if (slack < 0)
                negative_slack += slack;
            worst_slack = std::min(slack, worst_slack);
        }

        if (ctx->getBelGlobalBuf(load_cell->bel))
            continue;
        Loc load_loc = ctx->getBelLocation(load_cell->bel);

        xmin = std::min(xmin, load_loc.x);
        ymin = std::min(ymin, load_loc.y);
        xmax = std::max(xmax, load_loc.x);
        ymax = std::max(ymax, load_loc.y);
    }
    if (ctx->timing_driven && type == MetricType::COST) {
        wirelength = wirelen_t((((ymax - ymin) + (xmax - xmin)) * std::min(5.0, (1.0 + std::exp(-worst_slack / 5)))));
    } else {
        wirelength = wirelen_t((ymax - ymin) + (xmax - xmin));
    }

    tns += ctx->getDelayNS(negative_slack);
    return wirelength;
}

// Get the total wirelength for a cell
wirelen_t get_cell_metric(const Context *ctx, const CellInfo *cell, MetricType type)
{
    std::set<IdString> nets;
    for (auto p : cell->ports) {
        if (p.second.net)
            nets.insert(p.second.net->name);
    }
    wirelen_t wirelength = 0;
    float tns = 0;
    for (auto n : nets) {
        wirelength += get_net_metric(ctx, ctx->nets.at(n).get(), type, tns);
    }
    return wirelength;
}

wirelen_t get_cell_metric_at_bel(const Context *ctx, CellInfo *cell, BelId bel, MetricType type)
{
    BelId oldBel = cell->bel;
    cell->bel = bel;
    wirelen_t wirelen = get_cell_metric(ctx, cell, type);
    cell->bel = oldBel;
    return wirelen;
}

// Placing a single cell
bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
{
    bool all_placed = false;
    int iters = 25;
    while (!all_placed) {
        BelId best_bel = BelId();
        wirelen_t best_wirelen = std::numeric_limits<wirelen_t>::max(),
                  best_ripup_wirelen = std::numeric_limits<wirelen_t>::max();
        CellInfo *ripup_target = nullptr;
        BelId ripup_bel = BelId();
        if (cell->bel != BelId()) {
            ctx->unbindBel(cell->bel);
        }
        BelType targetType = ctx->belTypeFromId(cell->type);
        for (auto bel : ctx->getBels()) {
            if (ctx->getBelType(bel) == targetType && (!require_legality || ctx->isValidBelForCell(cell, bel))) {
                if (ctx->checkBelAvail(bel)) {
                    wirelen_t wirelen = get_cell_metric_at_bel(ctx, cell, bel, MetricType::COST);
                    if (iters >= 4)
                        wirelen += ctx->rng(25);
                    if (wirelen <= best_wirelen) {
                        best_wirelen = wirelen;
                        best_bel = bel;
                    }
                } else {
                    wirelen_t wirelen = get_cell_metric_at_bel(ctx, cell, bel, MetricType::COST);
                    if (iters >= 4)
                        wirelen += ctx->rng(25);
                    if (wirelen <= best_ripup_wirelen) {
                        CellInfo *curr_cell = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
                        if (curr_cell->belStrength < STRENGTH_STRONG) {
                            best_ripup_wirelen = wirelen;
                            ripup_bel = bel;
                            ripup_target = curr_cell;
                        }
                    }
                }
            }
        }
        if (best_bel == BelId()) {
            if (iters == 0) {
                log_error("failed to place cell '%s' of type '%s' (ripup iteration limit exceeded)\n",
                          cell->name.c_str(ctx), cell->type.c_str(ctx));
            }
            if (ripup_bel == BelId()) {
                log_error("failed to place cell '%s' of type '%s'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
            }
            --iters;
            ctx->unbindBel(ripup_target->bel);
            best_bel = ripup_bel;
        } else {
            all_placed = true;
        }
        ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);

        cell = ripup_target;
    }
    return true;
}

NEXTPNR_NAMESPACE_END
<|endoftext|>


<commit_before>#include <string>
#include <stdexcept>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <sauce/sauce.h>

using ::testing::Sequence;
using ::testing::Return;

using ::sauce::Binder;
using ::sauce::Named;

namespace sauce {
namespace test {

struct C {};
struct D {};
struct N {};

TEST(BindingTest, shouldThrowExceptionWhenGettingAnUnboundIface) {
  sauce::shared_ptr<Injector> injector(Modules().createInjector());
  ASSERT_THROW((injector->get<C>()), ::sauce::UnboundException);
}

struct B;

struct A {
  A(sauce::shared_ptr<B>) {}
};

struct B {
  B(sauce::shared_ptr<A>) {}
};

void CircularModule(Binder & binder) {
  binder.bind<A>().to<A(B)>();
  binder.bind<B>().to<B(A)>();
}

TEST(BindingTest, shouldThrowExceptionWhenResolvingCircularDependency) {
  sauce::shared_ptr<Injector> injector(Modules().add(&CircularModule).createInjector());
  ASSERT_THROW((injector->get<A>()), ::sauce::CircularDependencyException);
}

void IncompleteModule(Binder & binder) {
  binder.bind<C>();
}

TEST(BindingTest, shouldThrowExceptionOnPartialBinding) {
  ASSERT_THROW(
    Modules().add(&IncompleteModule).createInjector(),
    ::sauce::PartialBindingException);
}

void IncompleteNamedModule(Binder & binder) {
  binder.bind<A>().named<N>();
}

TEST(BindingTest, shouldThrowExceptionOnPartialNamedBinding) {
  ASSERT_THROW(
    Modules().add(&IncompleteNamedModule).createInjector(),
    ::sauce::PartialBindingException);
}

struct Animal {
  virtual std::string says() = 0;
};

struct Cat: Animal {
  std::string says() { return "Meow"; }
};

struct Water {};
struct Fish: Animal {
  std::string says() { return "Blub blub"; }
};

struct Farm {};
struct Cow: Animal {
  std::string says() { return "Moo"; }
};

struct Pond {
  sauce::shared_ptr<Animal> animal;

  Pond(sauce::shared_ptr<Animal> animal):
    animal(animal) {}
};

void AnimalModule(Binder & binder) {
  binder.bind<Animal>().to<Cat()>();
  binder.bind<Animal>().named<Water>().to<Fish()>();
  binder.bind<Animal>().named<Farm>().to<Cow()>();

  binder.bind<Pond>().to<Pond(Named<Animal, Water>)>();
}

TEST(BindingTest, shouldProvidedNamedDependencies) {
  sauce::shared_ptr<Injector> injector(Modules().add(&AnimalModule).createInjector());

  EXPECT_EQ("Meow",      (injector->get<Animal>()->says()));
  EXPECT_EQ("Blub blub", (injector->get<Animal, Water>()->says()));
  EXPECT_EQ("Moo",       (injector->get<Named<Animal, Farm> >()->says()));

  EXPECT_EQ("Blub blub", (injector->get<Pond>()->animal->says()));
}

void IncompleteScopeModule(Binder & binder) {
  binder.bind<A>().in<SingletonScope>();
}

TEST(BindingTest, shouldThrowExceptionOnPartialScopedBinding) {
  ASSERT_THROW(
    Modules().add(&IncompleteScopeModule).createInjector(),
    ::sauce::PartialBindingException);
}

TEST(BindingTest, shouldImplicitlyBindTheInjectorItself) {
  sauce::shared_ptr<Injector> expected = Modules().createInjector();
  sauce::shared_ptr<Injector> actual = expected->get<Injector>();
  ASSERT_EQ(expected, actual);
}

}
}
<commit_msg>Start ditching single-letter names in suite.<commit_after>#include <string>
#include <stdexcept>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <sauce/sauce.h>

using ::testing::Sequence;
using ::testing::Return;

using ::sauce::Binder;
using ::sauce::Named;

namespace sauce {
namespace test {

struct C {};
struct D {};
struct N {};

TEST(BindingTest, shouldThrowExceptionWhenGettingAnUnboundIface) {
  sauce::shared_ptr<Injector> injector(Modules().createInjector());
  ASSERT_THROW((injector->get<C>()), ::sauce::UnboundException);
}

struct Dog;

struct Tail {
  Tail(sauce::shared_ptr<Dog>) {}
};

struct Dog {
  Dog(sauce::shared_ptr<Tail>) {}
};

void CircularModule(Binder & binder) {
  binder.bind<Tail>().to<Tail(Dog)>();
  binder.bind<Dog>().to<Dog(Tail)>();
}

TEST(BindingTest, shouldThrowExceptionWhenResolvingCircularDependency) {
  sauce::shared_ptr<Injector> injector(Modules().add(&CircularModule).createInjector());
  ASSERT_THROW((injector->get<Tail>()), ::sauce::CircularDependencyException);
}

void IncompleteModule(Binder & binder) {
  binder.bind<C>();
}

TEST(BindingTest, shouldThrowExceptionOnPartialBinding) {
  ASSERT_THROW(
    Modules().add(&IncompleteModule).createInjector(),
    ::sauce::PartialBindingException);
}

void IncompleteNamedModule(Binder & binder) {
  binder.bind<C>().named<N>();
}

TEST(BindingTest, shouldThrowExceptionOnPartialNamedBinding) {
  ASSERT_THROW(
    Modules().add(&IncompleteNamedModule).createInjector(),
    ::sauce::PartialBindingException);
}

struct Animal {
  virtual std::string says() = 0;
};

struct Cat: Animal {
  std::string says() { return "Meow"; }
};

struct Water {};
struct Fish: Animal {
  std::string says() { return "Blub blub"; }
};

struct Farm {};
struct Cow: Animal {
  std::string says() { return "Moo"; }
};

struct Pond {
  sauce::shared_ptr<Animal> animal;

  Pond(sauce::shared_ptr<Animal> animal):
    animal(animal) {}
};

void AnimalModule(Binder & binder) {
  binder.bind<Animal>().to<Cat()>();
  binder.bind<Animal>().named<Water>().to<Fish()>();
  binder.bind<Animal>().named<Farm>().to<Cow()>();

  binder.bind<Pond>().to<Pond(Named<Animal, Water>)>();
}

TEST(BindingTest, shouldProvidedNamedDependencies) {
  sauce::shared_ptr<Injector> injector(Modules().add(&AnimalModule).createInjector());

  EXPECT_EQ("Meow",      (injector->get<Animal>()->says()));
  EXPECT_EQ("Blub blub", (injector->get<Animal, Water>()->says()));
  EXPECT_EQ("Moo",       (injector->get<Named<Animal, Farm> >()->says()));

  EXPECT_EQ("Blub blub", (injector->get<Pond>()->animal->says()));
}

void IncompleteScopeModule(Binder & binder) {
  binder.bind<C>().in<SingletonScope>();
}

TEST(BindingTest, shouldThrowExceptionOnPartialScopedBinding) {
  ASSERT_THROW(
    Modules().add(&IncompleteScopeModule).createInjector(),
    ::sauce::PartialBindingException);
}

TEST(BindingTest, shouldImplicitlyBindTheInjectorItself) {
  sauce::shared_ptr<Injector> expected = Modules().createInjector();
  sauce::shared_ptr<Injector> actual = expected->get<Injector>();
  ASSERT_EQ(expected, actual);
}

}
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006 Funambol
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/**
 * This code uses the ClientTest and FILESyncSource to test real
 * synchronization against a server. More than one FILESyncSource can
 * be active at once and each of them may (but does not have to be)
 * used for different kinds of data. The name of the source determines
 * which data is stored in it: it must be something supported by the
 * ClientTest class, because that is where the test data comes from.
 *
 * At least the following kinds of data are currently supported by the
 * ClientTest class (see ClientTest::getSourceConfig() for more
 * information):
 * - vcard30 = vCard 3.0 contacts
 * - ical20 = iCalendar 2.0 calendar events
 * - itodo20 = iCalendar 2.0 tasks
 *
 * Configuration is done by environment variables which indicate which
 * part below the root node "client-test" of the the configuration tree to use;
 * beyond that everything needed for synchronization is read from the
 * configuration tree.
 *
 * - CLIENT_TEST_SERVER = maps to name of root node in configuration tree
 * - CLIENT_TEST_SOURCES = comma separated list of active sources,
 *                         names as listed above
 * - CLIENT_TEST_DELAY = number of seconds to sleep between syncs, required
 *                       by some servers
 * - CLIENT_TEST_LOG = logfile name of a server, can be empty:
 *                     if given, then the content of that file will be
 *                     copied and stored together with the client log
 *                     (only works on Unix)
 *
 * For example, on Linux running
 *    CLIENT_TEST_SERVER=funambol CLIENT_TEST_SOURCES=vcard30,ical20 ./client-test
 * expects the following configuration layout:
 * ~/.sync4j/client-test/
 *                       funambol_1/spds/
 *                                       syncml/config.text
 *                                       sources/
 *                                               vcard30/config.txt
 *                                               ical20/config.txt
 *                       funambol_1/spds/
 *                                       <same as for funambol_1>
 *
 * If any of the configuration nodes does not exist yet, then it will
 * be created, but further information may have to be added, in
 * particular:
 * - server URL
 * - server user name, password
 * - sources uri
 *
 * The two configurations are used to simulate synchronization between
 * two different clients.
 *
 * The file sources will store their items in sub directories of
 * a "client-data" directory created in the current working directory.
 *
 * Here is an example of using the CLIENT_TEST_LOG:
 *    CLIENT_TEST_SERVER=funambol \
 *    CLIENT_TEST_LOG=/opt/Funambol-3.0/ds-server/logs/funambol_ds.log \
 *    CLIENT_TEST_SOURCES=vcard30 \
 *    ./client-test
 * will create files with the suffix .client.1.log for synchronizations with
 * the first client and .client.2.log for the second client. The base name
 * of these files is unique, so the corresponding part of the server log
 * is stored with the same base name and .server.log as suffix.
 */

#include "spdm/DeviceManagementNode.h"
#include "spds/RawFILESyncSource.h"
#include "spds/spdsutils.h"
#include "client/DMTClientConfig.h"
#include "client/SyncClient.h"
#include "test/ClientTest.h"
#include "base/test.h"

#include <string>
#include <vector>
#include <iomanip>
#include <memory>

#ifdef WIN32
#include <direct.h>
#endif
#include <sys/stat.h>

class TestFileSource : public ClientTest {
public:
    TestFileSource(const std::string &id) :
        ClientTest(getenv("CLIENT_TEST_DELAY") ? atoi(getenv("CLIENT_TEST_DELAY")) : 0,
                   getenv("CLIENT_TEST_LOG") ? getenv("CLIENT_TEST_LOG") : ""),
        clientID(id) {
        const char *sourcelist = getenv("CLIENT_TEST_SOURCES");
        const char *server = getenv("CLIENT_TEST_SERVER");

        /* set up source list */
        if (!sourcelist) {
            sourcelist = "";
        }
        const char *eostr = strchr(sourcelist, ',');
        const char *start = sourcelist;

        while (eostr) {
            sources.push_back(std::string(start, 0, eostr - start));
            start = eostr + 1;
            eostr = strchr(start, ',');
        }
        if (start[0]) {
            sources.push_back(start);
        }

        /* check server */
        if (!server) {
            server = "funambol";
        }

        // get configuration and set obligatory fields
        LOG.setLevel(LOG_LEVEL_DEBUG);
        std::string root = std::string("client-test/") + server + "_" + id;
        config.reset(new DMTClientConfig(root.c_str()));
        config->read();
        DeviceConfig &dc(config->getDeviceConfig());
        if (!strlen(dc.getDevID())) {
            // no configuration yet
            config->setClientDefaults();
            dc.setDevID(id == "A" ? "sc-api-nat" : "sc-pim-ppc");
        }
        for (int source = 0; source < (int)sources.size(); source++) {
            SyncSourceConfig* sc = config->getSyncSourceConfig(sources[source].c_str());
            if (!sc) {
                // no configuration yet
                config->setSourceDefaults(sources[source].c_str());
                sc = config->getSyncSourceConfig(sources[source].c_str());
                CPPUNIT_ASSERT(sc);
            }

            ClientTest::Config testconfig;
            getSourceConfig(source, testconfig);
            CPPUNIT_ASSERT(testconfig.type);
            sc->setType(testconfig.type);
        }
        config->save();
        config->open();

        if (id == "A") {
            /* we are the primary client, create a second one */
            clientB.reset(new TestFileSource("B"));
        }
    }

    virtual int getNumSources() {
        return (int)sources.size();
    }

    virtual void getSourceConfig(int source, Config &config) {
        memset(&config, 0, sizeof(config));

        getTestData(sources[source].c_str(), config);
        config.createSourceA =
            config.createSourceB = createSource;
    }

    virtual ClientTest* getClientB() {
        return clientB.get();
    }

    virtual bool isB64Enabled() {
        return false;
    }

    virtual int sync(
        const int *activeSources,
        SyncMode syncMode,
        long maxMsgSize,
        long maxObjSize,
        bool loSupport,
        const char *encoding = 0) {
        SyncSource **syncSources = new SyncSource *[sources.size() + 1];
        int source;
        memset(syncSources, 0, sizeof(syncSources[0]) * (sources.size() + 1));

        for (source = 0; activeSources[source] >= 0 && source < (int)sources.size(); source++) {
            // rewrite configuration as needed for test
            SyncSourceConfig *sourceConfig = config->getSyncSourceConfig(sources[source].c_str());
            CPPUNIT_ASSERT(sourceConfig);
            sourceConfig->setSync(syncModeKeyword(syncMode));
            sourceConfig->setEncoding(encoding);
            config->getAccessConfig().setMaxMsgSize(maxMsgSize);
            config->getDeviceConfig().setMaxObjSize(maxObjSize);
            config->getDeviceConfig().setLoSupport(loSupport);

            // create sync source using the third change tracking for syncs
            syncSources[source] = createSource(source, "S");
        }

        SyncClient client;
        int res = client.sync(*config, syncSources);

        for (source = 0; syncSources[source]; source++) {
            delete syncSources[source];
        }

        return res;
    }

private:
    /** either "A" or "B" for first respectively second client */
    std::string clientID;

    /** only in "A": pointer to second client */
    std::auto_ptr<TestFileSource> clientB;

    /** vector of enabled sync sources, identified by a name which SyncClient::getConfig() supports */
    std::vector<std::string> sources;

    /** configuration tree itself */
    std::auto_ptr<DMTClientConfig> config;

    static SyncSource *createSource(ClientTest &client, int source, bool isSourceA) {
        // hand work over to real member function
        return ((TestFileSource &)client).createSource(source, isSourceA ? "A" : "B");
    }

    SyncSource *createSource(int source, const char *trackingSuffix) {
        class RawFILESyncSourceWithReport : public RawFILESyncSource {
        public:
            RawFILESyncSourceWithReport(const char* nodeName, const WCHAR* name, SyncSourceConfig* sc) :
                RawFILESyncSource(name, sc),
                fileNode(nodeName) {
                setReport(&report);
                setFileNode(&fileNode);
                /*
                 * Keeping track if changes is done via time() with a resolution of seconds.
                 * Sleep a bit to ensure that enough time passes.
                 */
#ifdef WIN32
				Sleep(1000);
#else
                sleep(1);
#endif
            }
        private:
            SyncSourceReport report;
            DeviceManagementNode fileNode;
        };

        CPPUNIT_ASSERT(source < (int)sources.size());
        ManagementNode *sourceNode = config->getSyncSourceNode(sources[source].c_str());
        CPPUNIT_ASSERT(sourceNode);
        char *fullName = sourceNode->createFullName();
        std::string nodeName = std::string(fullName) + "/changes_" + trackingSuffix;
        std::string dirName = sources[source] + "_" + clientID;
		WCHAR *name = toWideChar(sources[source].c_str());
        delete [] fullName;
        FILESyncSource *ss = new RawFILESyncSourceWithReport(
            nodeName.c_str(),
            name,
            config->getSyncSourceConfig(sources[source].c_str()));
		delete [] name;
#ifdef WIN32
        _mkdir(dirName.c_str());
#else
		mkdir(dirName.c_str(), S_IRWXU);
#endif
        ss->setDir(dirName.c_str());

        return ss;
    }
};

/**
 * the only purpose of this class is to own the first TestFileSource
 * and to register its tests at program startup
 */
static class RegisterTest {
public:
    RegisterTest() :
        testFileSource("A") {
        testFileSource.registerTests();
    }

private:
    TestFileSource testFileSource;
} registerTest;
<commit_msg>fixed comments<commit_after>/*
 * Copyright (C) 2006 Funambol
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/**
 * This code uses the ClientTest and FILESyncSource to test real
 * synchronization against a server. More than one FILESyncSource can
 * be active at once and each of them may (but does not have to be)
 * used for different kinds of data. The name of the source determines
 * which data is stored in it: it must be something supported by the
 * ClientTest class, because that is where the test data comes from.
 *
 * At least the following kinds of data are currently supported by the
 * ClientTest class (see ClientTest::getSourceConfig() for more
 * information):
 * - vcard30 = vCard 3.0 contacts
 * - ical20 = iCalendar 2.0 calendar events
 * - itodo20 = iCalendar 2.0 tasks
 *
 * Configuration is done by environment variables which indicate which
 * part below the root node "client-test" of the the configuration tree to use;
 * beyond that everything needed for synchronization is read from the
 * configuration tree.
 *
 * - CLIENT_TEST_SERVER = maps to name of root node in configuration tree
 * - CLIENT_TEST_SOURCES = comma separated list of active sources,
 *                         names as listed above
 * - CLIENT_TEST_DELAY = number of seconds to sleep between syncs, required
 *                       by some servers
 * - CLIENT_TEST_LOG = logfile name of a server, can be empty:
 *                     if given, then the content of that file will be
 *                     copied and stored together with the client log
 *                     (only works on Unix)
 *
 * For example, on Linux running
 *    CLIENT_TEST_SERVER=funambol CLIENT_TEST_SOURCES=vcard30,ical20 ./client-test
 * expects the following configuration layout:
 * ~/.sync4j/client-test/
 *                       funambol_1/spds/
 *                                       syncml/config.text
 *                                       sources/
 *                                               vcard30/config.txt
 *                                               ical20/config.txt
 *                       funambol_1/spds/
 *                                       <same as for funambol_1>
 *
 * If any of the configuration nodes does not exist yet, then it will
 * be created, but further information may have to be added, in
 * particular:
 * - server URL
 * - server user name, password
 * - sources uri
 *
 * The two configurations are used to simulate synchronization between
 * two different clients.
 *
 * The file sources will store their items in sub directories of
 * a "client-data" directory created in the current working directory.
 *
 * Here is an example of using the CLIENT_TEST_LOG:
 *    CLIENT_TEST_SERVER=funambol \
 *    CLIENT_TEST_LOG=/opt/Funambol-3.0/ds-server/logs/funambol_ds.log \
 *    CLIENT_TEST_SOURCES=vcard30 \
 *    ./client-test
 * will create files with the suffix .client.A.log for synchronizations with
 * the first client and .client.B.log for the second client. The base name
 * of these files is unique, so the corresponding part of the server log
 * is stored with the same base name and .server.log as suffix.
 */

#include "spdm/DeviceManagementNode.h"
#include "spds/RawFILESyncSource.h"
#include "spds/spdsutils.h"
#include "client/DMTClientConfig.h"
#include "client/SyncClient.h"
#include "test/ClientTest.h"
#include "base/test.h"

#include <string>
#include <vector>
#include <iomanip>
#include <memory>

#ifdef WIN32
#include <direct.h>
#endif
#include <sys/stat.h>

class TestFileSource : public ClientTest {
public:
    TestFileSource(const std::string &id) :
        ClientTest(getenv("CLIENT_TEST_DELAY") ? atoi(getenv("CLIENT_TEST_DELAY")) : 0,
                   getenv("CLIENT_TEST_LOG") ? getenv("CLIENT_TEST_LOG") : ""),
        clientID(id) {
        const char *sourcelist = getenv("CLIENT_TEST_SOURCES");
        const char *server = getenv("CLIENT_TEST_SERVER");

        /* set up source list */
        if (!sourcelist) {
            sourcelist = "";
        }
        const char *eostr = strchr(sourcelist, ',');
        const char *start = sourcelist;

        while (eostr) {
            sources.push_back(std::string(start, 0, eostr - start));
            start = eostr + 1;
            eostr = strchr(start, ',');
        }
        if (start[0]) {
            sources.push_back(start);
        }

        /* check server */
        if (!server) {
            server = "funambol";
        }

        // get configuration and set obligatory fields
        LOG.setLevel(LOG_LEVEL_DEBUG);
        std::string root = std::string("client-test/") + server + "_" + id;
        config.reset(new DMTClientConfig(root.c_str()));
        config->read();
        DeviceConfig &dc(config->getDeviceConfig());
        if (!strlen(dc.getDevID())) {
            // no configuration yet
            config->setClientDefaults();
            dc.setDevID(id == "A" ? "sc-api-nat" : "sc-pim-ppc");
        }
        for (int source = 0; source < (int)sources.size(); source++) {
            SyncSourceConfig* sc = config->getSyncSourceConfig(sources[source].c_str());
            if (!sc) {
                // no configuration yet
                config->setSourceDefaults(sources[source].c_str());
                sc = config->getSyncSourceConfig(sources[source].c_str());
                CPPUNIT_ASSERT(sc);
            }

            ClientTest::Config testconfig;
            getSourceConfig(source, testconfig);
            CPPUNIT_ASSERT(testconfig.type);
            sc->setType(testconfig.type);
        }
        config->save();
        config->open();

        if (id == "A") {
            /* we are the primary client, create a second one */
            clientB.reset(new TestFileSource("B"));
        }
    }

    virtual int getNumSources() {
        return (int)sources.size();
    }

    virtual void getSourceConfig(int source, Config &config) {
        memset(&config, 0, sizeof(config));

        getTestData(sources[source].c_str(), config);
        config.createSourceA =
            config.createSourceB = createSource;
    }

    virtual ClientTest* getClientB() {
        return clientB.get();
    }

    virtual bool isB64Enabled() {
        return false;
    }

    virtual int sync(
        const int *activeSources,
        SyncMode syncMode,
        long maxMsgSize,
        long maxObjSize,
        bool loSupport,
        const char *encoding = 0) {
        SyncSource **syncSources = new SyncSource *[sources.size() + 1];
        int source;
        memset(syncSources, 0, sizeof(syncSources[0]) * (sources.size() + 1));

        for (source = 0; activeSources[source] >= 0 && source < (int)sources.size(); source++) {
            // rewrite configuration as needed for test
            SyncSourceConfig *sourceConfig = config->getSyncSourceConfig(sources[source].c_str());
            CPPUNIT_ASSERT(sourceConfig);
            sourceConfig->setSync(syncModeKeyword(syncMode));
            sourceConfig->setEncoding(encoding);
            config->getAccessConfig().setMaxMsgSize(maxMsgSize);
            config->getDeviceConfig().setMaxObjSize(maxObjSize);
            config->getDeviceConfig().setLoSupport(loSupport);

            // create sync source using the third change tracking for syncs
            syncSources[source] = createSource(source, "S");
        }

        SyncClient client;
        int res = client.sync(*config, syncSources);

        for (source = 0; syncSources[source]; source++) {
            delete syncSources[source];
        }

        return res;
    }

private:
    /** either "A" or "B" for first respectively second client */
    std::string clientID;

    /** only in "A": pointer to second client */
    std::auto_ptr<TestFileSource> clientB;

    /** vector of enabled sync sources, identified by a name which SyncClient::getConfig() supports */
    std::vector<std::string> sources;

    /** configuration tree itself */
    std::auto_ptr<DMTClientConfig> config;

    static SyncSource *createSource(ClientTest &client, int source, bool isSourceA) {
        // hand work over to real member function
        return ((TestFileSource &)client).createSource(source, isSourceA ? "A" : "B");
    }

    SyncSource *createSource(int source, const char *trackingSuffix) {
        class RawFILESyncSourceWithReport : public RawFILESyncSource {
        public:
            RawFILESyncSourceWithReport(const char* nodeName, const WCHAR* name, SyncSourceConfig* sc) :
                RawFILESyncSource(name, sc),
                fileNode(nodeName) {
                setReport(&report);
                setFileNode(&fileNode);
                /*
                 * Keeping track if changes is done via time() with a resolution of seconds.
                 * Sleep a bit to ensure that enough time passes.
                 */
#ifdef WIN32
				Sleep(1000);
#else
                sleep(1);
#endif
            }
        private:
            SyncSourceReport report;
            DeviceManagementNode fileNode;
        };

        CPPUNIT_ASSERT(source < (int)sources.size());
        ManagementNode *sourceNode = config->getSyncSourceNode(sources[source].c_str());
        CPPUNIT_ASSERT(sourceNode);
        char *fullName = sourceNode->createFullName();
        std::string nodeName = std::string(fullName) + "/changes_" + trackingSuffix;
        std::string dirName = sources[source] + "_" + clientID;
		WCHAR *name = toWideChar(sources[source].c_str());
        delete [] fullName;
        FILESyncSource *ss = new RawFILESyncSourceWithReport(
            nodeName.c_str(),
            name,
            config->getSyncSourceConfig(sources[source].c_str()));
		delete [] name;
#ifdef WIN32
        _mkdir(dirName.c_str());
#else
		mkdir(dirName.c_str(), S_IRWXU);
#endif
        ss->setDir(dirName.c_str());

        return ss;
    }
};

/**
 * the only purpose of this class is to own the first TestFileSource
 * and to register its tests at program startup
 */
static class RegisterTest {
public:
    RegisterTest() :
        testFileSource("A") {
        testFileSource.registerTests();
    }

private:
    TestFileSource testFileSource;
} registerTest;
<|endoftext|>


<commit_before>template<class G>
void naiveMulVec(G& out, const G *xVec, const Fr *yVec, size_t n)
{
	if (n == 1) {
		G::mul(out, xVec[0], yVec[0]);
		return;
	}
	G r, t;
	r.clear();
	for (size_t i = 0; i < n; i++) {
		G::mul(t, xVec[i], yVec[i]);
		r += t;
	}
	out = r;
}

template<class G>
void mulVecCopy(G& z, G *x, const Fr *y, size_t n, const G* x0)
{
	for (size_t i = 0; i < n; i++) x[i] = x0[i];
	G::mulVec(z, x, y, n);
}

template<class G>
void testMulVec(const G& P)
{
	using namespace mcl::bn;
	const int N = 4096;
	std::vector<G> x0Vec(N);
	std::vector<G> xVec(N);
	std::vector<Fr> yVec(N);

	for (size_t i = 0; i < N; i++) {
		G::mul(x0Vec[i], P, i + 3);
		xVec[i] = x0Vec[i];
		yVec[i].setByCSPRNG();
	}
	const size_t nTbl[] = { 1, 2, 3, 15, 16, 17, 32, 64, 128, 256, 512, 1024, 2048, N };
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(nTbl); i++) {
		const size_t n = nTbl[i];
		G Q1, Q2;
		CYBOZU_TEST_ASSERT(n <= N);
		naiveMulVec(Q1, xVec.data(), yVec.data(), n);
		G::mulVec(Q2, xVec.data(), yVec.data(), n);
		CYBOZU_TEST_EQUAL(Q1, Q2);
		Q2.clear();
#ifdef NDEBUG
		printf("n=%zd\n", n);
		const int C = 10;
		CYBOZU_BENCH_C("naive ", C, naiveMulVec, Q1, xVec.data(), yVec.data(), n);
		CYBOZU_BENCH_C("mulVec", C, G::mulVec, Q1, xVec.data(), yVec.data(), n);
		CYBOZU_BENCH_C("mulVecCopy", C, mulVecCopy, Q1, xVec.data(), yVec.data(), n, x0Vec.data());
#endif
	}
}

template<class G>
void naivePowVec(G& out, const G *xVec, const Fr *yVec, size_t n)
{
	if (n == 1) {
		G::pow(out, xVec[0], yVec[0]);
		return;
	}
	G r, t;
	r.setOne();
	for (size_t i = 0; i < n; i++) {
		G::pow(t, xVec[i], yVec[i]);
		r *= t;
	}
	out = r;
}

template<class G>
inline void testPowVec(const G& e)
{
	using namespace mcl::bn;
	const int N = 33;
	G xVec[N];
	Fr yVec[N];

	xVec[0] = e;
	for (size_t i = 0; i < N; i++) {
		if (i > 0) G::mul(xVec[i], xVec[i - 1], e);
		yVec[i].setByCSPRNG();
	}
	const size_t nTbl[] = { 1, 2, 3, 5, 7, 8, 9, 14, 15, 16, 30, 31, 32, 33 };
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(nTbl); i++) {
		const size_t n = nTbl[i];
		G Q1, Q2;
		CYBOZU_TEST_ASSERT(n <= N);
		naivePowVec(Q1, xVec, yVec, n);
		G::powVec(Q2, xVec, yVec, n);
		CYBOZU_TEST_EQUAL(Q1, Q2);
#if 0//#ifdef NDEBUG
		printf("n=%zd\n", n);
		const int C = 400;
		CYBOZU_BENCH_C("naive ", C, naivePowVec, Q1, xVec, yVec, n);
		CYBOZU_BENCH_C("mulVec", C, G::powVec, Q1, xVec, yVec, n);
#endif
	}
}

template<class G>
void testMulCT(const G& P)
{
	cybozu::XorShift rg;
	G Q1, Q2;
	for (int i = 0; i < 100; i++) {
		Fr x;
		x.setByCSPRNG(rg);
		G::mul(Q1, P, x);
		G::mulCT(Q2, P, x);
		CYBOZU_TEST_EQUAL(Q1, Q2);
	}
}

void testMul2()
{
	puts("testMul2");
	cybozu::XorShift rg;
	Fp x1, x2;
	x1.setByCSPRNG(rg);
	x2 = x1;
	for (int i = 0; i < 100; i++) {
		Fp::mul2(x1, x1);
		x2 += x2;
		CYBOZU_TEST_EQUAL(x1, x2);
	}
	Fp2 y1;
	y1.a = x1;
	y1.b = -x1;
	Fp2 y2 = y1;
	for (int i = 0; i < 100; i++) {
		Fp2::mul2(y1, y1);
		y2 += y2;
		CYBOZU_TEST_EQUAL(y1, y2);
	}
}

void testABCDsub(const Fp2& a, const Fp2& b, const Fp2& c, const Fp2& d)
{
	Fp2 t1, t2;
	Fp2::addPre(t1, a, b);
	Fp2::addPre(t2, c, d);
	Fp2Dbl T1, AC, BD;
	Fp2Dbl::mulPre(T1, t1, t2);
	Fp2Dbl::mulPre(AC, a, c);
	Fp2Dbl::mulPre(BD, b, d);
	Fp2Dbl::subSpecial(T1, AC);
	Fp2Dbl::subSpecial(T1, BD);
	Fp2Dbl::mod(t1, T1);
	CYBOZU_TEST_EQUAL(t1, a * d + b * c);
}

void testABCD()
{
	puts("testMisc1");
	// (a + b)(c + d) - ac - bd = ad + bc
	Fp2 a[4];
	a[0].a = -1;
	a[0].b = -1;
	a[1] = a[0];
	a[2] = a[0];
	a[3] = a[0];
	testABCDsub(a[0], a[1], a[2], a[3]);
	for (int i = 0; i < 100; i++) {
		for (int j = 0; j < 4; j++) {
			a[j].a.setByCSPRNG();
			a[j].b.setByCSPRNG();
		}
		testABCDsub(a[0], a[1], a[2], a[3]);
	}
}

void testFp2Dbl_mul_xi1()
{
	const uint32_t xi_a = Fp2::get_xi_a();
	if (xi_a != 1) return;
	puts("testFp2Dbl_mul_xi1");
	cybozu::XorShift rg;
	for (int i = 0; i < 10; i++) {
		Fp a1, a2;
		a1.setByCSPRNG(rg);
		a2.setByCSPRNG(rg);
		Fp2Dbl x;
		FpDbl::mulPre(x.a, a1, a2);
		a1.setByCSPRNG(rg);
		a2.setByCSPRNG(rg);
		FpDbl::mulPre(x.b, a1, a2);
		Fp2Dbl ok;
		{
			FpDbl::mulUnit(ok.a, x.a, xi_a);
			ok.a -= x.b;
			FpDbl::mulUnit(ok.b, x.b, xi_a);
			ok.b += x.a;
		}
		Fp2Dbl::mul_xi(x, x);
		CYBOZU_TEST_EQUAL_ARRAY(ok.a.getUnit(), x.a.getUnit(), ok.a.getUnitSize());
		CYBOZU_TEST_EQUAL_ARRAY(ok.b.getUnit(), x.b.getUnit(), ok.b.getUnitSize());
	}
}

void testMulSmall()
{
	puts("testMulSmall");
	cybozu::XorShift rg;
	for (int y = 0; y < 10; y++) {
		for (int i = 0; i < 40; i++) {
			Fp x, z1, z2;
			x.setByCSPRNG(rg);
			Fp::mulSmall(z1, x, y);
			z2 = x * y;
			CYBOZU_TEST_EQUAL(z1, z2);
		}
	}
}

void testCommon(const G1& P, const G2& Q)
{
	testMulSmall();
	testFp2Dbl_mul_xi1();
	testABCD();
	testMul2();
	puts("G1");
	testMulVec(P);
	puts("G2");
	testMulVec(Q);
	testMulCT(Q);
	GT e;
	mcl::bn::pairing(e, P, Q);
	puts("GT");
	testPowVec(e);
}
<commit_msg>disable bench of mulVec<commit_after>template<class G>
void naiveMulVec(G& out, const G *xVec, const Fr *yVec, size_t n)
{
	if (n == 1) {
		G::mul(out, xVec[0], yVec[0]);
		return;
	}
	G r, t;
	r.clear();
	for (size_t i = 0; i < n; i++) {
		G::mul(t, xVec[i], yVec[i]);
		r += t;
	}
	out = r;
}

template<class G>
void mulVecCopy(G& z, G *x, const Fr *y, size_t n, const G* x0)
{
	for (size_t i = 0; i < n; i++) x[i] = x0[i];
	G::mulVec(z, x, y, n);
}

template<class G>
void testMulVec(const G& P)
{
	using namespace mcl::bn;
	const int N = 4096;
	std::vector<G> x0Vec(N);
	std::vector<G> xVec(N);
	std::vector<Fr> yVec(N);

	for (size_t i = 0; i < N; i++) {
		G::mul(x0Vec[i], P, i + 3);
		xVec[i] = x0Vec[i];
		yVec[i].setByCSPRNG();
	}
	const size_t nTbl[] = { 1, 2, 3, 15, 16, 17, 32, 64, 128, 256,
#if 0
		512, 1024, 2048, N
#endif
	};
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(nTbl); i++) {
		const size_t n = nTbl[i];
		G Q1, Q2;
		CYBOZU_TEST_ASSERT(n <= N);
		naiveMulVec(Q1, xVec.data(), yVec.data(), n);
		G::mulVec(Q2, xVec.data(), yVec.data(), n);
		CYBOZU_TEST_EQUAL(Q1, Q2);
		Q2.clear();
#if 0 // #ifdef NDEBUG
		printf("n=%zd\n", n);
		const int C = 10;
		CYBOZU_BENCH_C("naive ", C, naiveMulVec, Q1, xVec.data(), yVec.data(), n);
		CYBOZU_BENCH_C("mulVec", C, G::mulVec, Q1, xVec.data(), yVec.data(), n);
		CYBOZU_BENCH_C("mulVecCopy", C, mulVecCopy, Q1, xVec.data(), yVec.data(), n, x0Vec.data());
#endif
	}
}

template<class G>
void naivePowVec(G& out, const G *xVec, const Fr *yVec, size_t n)
{
	if (n == 1) {
		G::pow(out, xVec[0], yVec[0]);
		return;
	}
	G r, t;
	r.setOne();
	for (size_t i = 0; i < n; i++) {
		G::pow(t, xVec[i], yVec[i]);
		r *= t;
	}
	out = r;
}

template<class G>
inline void testPowVec(const G& e)
{
	using namespace mcl::bn;
	const int N = 33;
	G xVec[N];
	Fr yVec[N];

	xVec[0] = e;
	for (size_t i = 0; i < N; i++) {
		if (i > 0) G::mul(xVec[i], xVec[i - 1], e);
		yVec[i].setByCSPRNG();
	}
	const size_t nTbl[] = { 1, 2, 3, 5, 7, 8, 9, 14, 15, 16, 30, 31, 32, 33 };
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(nTbl); i++) {
		const size_t n = nTbl[i];
		G Q1, Q2;
		CYBOZU_TEST_ASSERT(n <= N);
		naivePowVec(Q1, xVec, yVec, n);
		G::powVec(Q2, xVec, yVec, n);
		CYBOZU_TEST_EQUAL(Q1, Q2);
#if 0//#ifdef NDEBUG
		printf("n=%zd\n", n);
		const int C = 400;
		CYBOZU_BENCH_C("naive ", C, naivePowVec, Q1, xVec, yVec, n);
		CYBOZU_BENCH_C("mulVec", C, G::powVec, Q1, xVec, yVec, n);
#endif
	}
}

template<class G>
void testMulCT(const G& P)
{
	cybozu::XorShift rg;
	G Q1, Q2;
	for (int i = 0; i < 100; i++) {
		Fr x;
		x.setByCSPRNG(rg);
		G::mul(Q1, P, x);
		G::mulCT(Q2, P, x);
		CYBOZU_TEST_EQUAL(Q1, Q2);
	}
}

void testMul2()
{
	puts("testMul2");
	cybozu::XorShift rg;
	Fp x1, x2;
	x1.setByCSPRNG(rg);
	x2 = x1;
	for (int i = 0; i < 100; i++) {
		Fp::mul2(x1, x1);
		x2 += x2;
		CYBOZU_TEST_EQUAL(x1, x2);
	}
	Fp2 y1;
	y1.a = x1;
	y1.b = -x1;
	Fp2 y2 = y1;
	for (int i = 0; i < 100; i++) {
		Fp2::mul2(y1, y1);
		y2 += y2;
		CYBOZU_TEST_EQUAL(y1, y2);
	}
}

void testABCDsub(const Fp2& a, const Fp2& b, const Fp2& c, const Fp2& d)
{
	Fp2 t1, t2;
	Fp2::addPre(t1, a, b);
	Fp2::addPre(t2, c, d);
	Fp2Dbl T1, AC, BD;
	Fp2Dbl::mulPre(T1, t1, t2);
	Fp2Dbl::mulPre(AC, a, c);
	Fp2Dbl::mulPre(BD, b, d);
	Fp2Dbl::subSpecial(T1, AC);
	Fp2Dbl::subSpecial(T1, BD);
	Fp2Dbl::mod(t1, T1);
	CYBOZU_TEST_EQUAL(t1, a * d + b * c);
}

void testABCD()
{
	puts("testMisc1");
	// (a + b)(c + d) - ac - bd = ad + bc
	Fp2 a[4];
	a[0].a = -1;
	a[0].b = -1;
	a[1] = a[0];
	a[2] = a[0];
	a[3] = a[0];
	testABCDsub(a[0], a[1], a[2], a[3]);
	for (int i = 0; i < 100; i++) {
		for (int j = 0; j < 4; j++) {
			a[j].a.setByCSPRNG();
			a[j].b.setByCSPRNG();
		}
		testABCDsub(a[0], a[1], a[2], a[3]);
	}
}

void testFp2Dbl_mul_xi1()
{
	const uint32_t xi_a = Fp2::get_xi_a();
	if (xi_a != 1) return;
	puts("testFp2Dbl_mul_xi1");
	cybozu::XorShift rg;
	for (int i = 0; i < 10; i++) {
		Fp a1, a2;
		a1.setByCSPRNG(rg);
		a2.setByCSPRNG(rg);
		Fp2Dbl x;
		FpDbl::mulPre(x.a, a1, a2);
		a1.setByCSPRNG(rg);
		a2.setByCSPRNG(rg);
		FpDbl::mulPre(x.b, a1, a2);
		Fp2Dbl ok;
		{
			FpDbl::mulUnit(ok.a, x.a, xi_a);
			ok.a -= x.b;
			FpDbl::mulUnit(ok.b, x.b, xi_a);
			ok.b += x.a;
		}
		Fp2Dbl::mul_xi(x, x);
		CYBOZU_TEST_EQUAL_ARRAY(ok.a.getUnit(), x.a.getUnit(), ok.a.getUnitSize());
		CYBOZU_TEST_EQUAL_ARRAY(ok.b.getUnit(), x.b.getUnit(), ok.b.getUnitSize());
	}
}

void testMulSmall()
{
	puts("testMulSmall");
	cybozu::XorShift rg;
	for (int y = 0; y < 10; y++) {
		for (int i = 0; i < 40; i++) {
			Fp x, z1, z2;
			x.setByCSPRNG(rg);
			Fp::mulSmall(z1, x, y);
			z2 = x * y;
			CYBOZU_TEST_EQUAL(z1, z2);
		}
	}
}

void testCommon(const G1& P, const G2& Q)
{
	testMulSmall();
	testFp2Dbl_mul_xi1();
	testABCD();
	testMul2();
	puts("G1");
	testMulVec(P);
	puts("G2");
	testMulVec(Q);
	testMulCT(Q);
	GT e;
	mcl::bn::pairing(e, P, Q);
	puts("GT");
	testPowVec(e);
}
<|endoftext|>


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

#include <string>

#include <cpr.h>

// TODO: This uses public servers for proxies and endpoints. This should be replaced with a source
// code implementation inside server.cpp

#define HTTP_PROXY "104.131.214.38:3128"
#define HTTPS_PROXY "67.195.42.72:80"

TEST(ProxyTests, SingleProxyTest) {
    auto url = Url{"http://www.httpbin.org/get"};
    auto response = cpr::Get(url, Proxies{{"http", HTTP_PROXY}});
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

TEST(ProxyTests, MultipleProxyHttpTest) {
    auto url = Url{"http://www.httpbin.org/get"};
    auto response = cpr::Get(url, Proxies{{"http", HTTP_PROXY},
                                          {"https", HTTPS_PROXY}});
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

TEST(ProxyTests, MultipleProxyHttpsTest) {
    auto url = Url{"https://www.httpbin.org/get"};
    auto response = cpr::Get(url, Proxies{{"http", HTTP_PROXY},
                                          {"https", HTTPS_PROXY}});
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

TEST(ProxyTests, CopyProxyTest) {
    auto url = Url{"http://www.httpbin.org/get"};
    auto proxies = Proxies{{"http", HTTP_PROXY}};
    auto response = cpr::Get(url, proxies);
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

TEST(ProxyTests, ProxySessionTest) {
    auto url = Url{"http://www.httpbin.org/get"};
    Session session;
    session.SetUrl(url);
    session.SetProxies(Proxies{{"http", HTTP_PROXY}});
    auto response = session.Get();
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Try the same proxy server for both protocols References #5<commit_after>#include <gtest/gtest.h>

#include <string>

#include <cpr.h>

// TODO: This uses public servers for proxies and endpoints. This should be replaced with a source
// code implementation inside server.cpp

#define HTTP_PROXY "104.131.214.38:3128"
#define HTTPS_PROXY "104.131.214.38:3128"

TEST(ProxyTests, SingleProxyTest) {
    auto url = Url{"http://www.httpbin.org/get"};
    auto response = cpr::Get(url, Proxies{{"http", HTTP_PROXY}});
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

TEST(ProxyTests, MultipleProxyHttpTest) {
    auto url = Url{"http://www.httpbin.org/get"};
    auto response = cpr::Get(url, Proxies{{"http", HTTP_PROXY},
                                          {"https", HTTPS_PROXY}});
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

TEST(ProxyTests, MultipleProxyHttpsTest) {
    auto url = Url{"https://www.httpbin.org/get"};
    auto response = cpr::Get(url, Proxies{{"http", HTTP_PROXY},
                                          {"https", HTTPS_PROXY}});
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

TEST(ProxyTests, CopyProxyTest) {
    auto url = Url{"http://www.httpbin.org/get"};
    auto proxies = Proxies{{"http", HTTP_PROXY}};
    auto response = cpr::Get(url, proxies);
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

TEST(ProxyTests, ProxySessionTest) {
    auto url = Url{"http://www.httpbin.org/get"};
    Session session;
    session.SetUrl(url);
    session.SetProxies(Proxies{{"http", HTTP_PROXY}});
    auto response = session.Get();
    EXPECT_EQ(url, response.url);
    EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
    EXPECT_EQ(200, response.status_code);
}

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


<commit_before>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "server_test_base.hpp"
#include <boost/test/unit_test.hpp>

#include "mediaServer_constants.h"
#include "dataTypes_constants.h"

#include "UriEndPointType_constants.h"
#include "PlayerEndPointType_constants.h"
#include "RecorderEndPointType_constants.h"

#include "utils/marshalling.hpp"

#include <gst/gst.h>

#define GST_CAT_DEFAULT _server_test_
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "server_test"

using namespace kurento;

BOOST_FIXTURE_TEST_SUITE ( server_test_suite,  F)

static void
check_version (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  int32_t gotVersion;

  gotVersion = client->getVersion();
  BOOST_CHECK_EQUAL (gotVersion, g_mediaServer_constants.VERSION);
}

#if 0 /* Temporally disabled */
static void
check_no_handler (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();

  BOOST_CHECK_THROW (client->createMediaPipeline (mediaPipeline, 0), HandlerNotFoundException);
}

static void
check_add_handler_address (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  client->addHandlerAddress (0, "localhost", 2323);
  client->addHandlerAddress (0, "localhost", 3434);
}

static void
check_type (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);
  BOOST_CHECK (mediaPipeline.type.__isset.mediaObject);
  BOOST_CHECK_EQUAL (mediaPipeline.type.mediaObject, MediaObjectType::type::MEDIA_PIPELINE);

  client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::RTP_END_POINT);
  BOOST_CHECK (mo.type.__isset.sdpEndPoint);
  BOOST_CHECK_EQUAL (mo.type.sdpEndPoint, SdpEndPointType::type::RTP_END_POINT);

  client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::WEBRTC_END_POINT);
  BOOST_CHECK (mo.type.__isset.sdpEndPoint);
  BOOST_CHECK_EQUAL (mo.type.sdpEndPoint, SdpEndPointType::type::WEBRTC_END_POINT);

  client->createUriEndPoint (mo, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "");
  BOOST_CHECK (mo.type.__isset.uriEndPoint);
  BOOST_CHECK_EQUAL (mo.type.uriEndPoint, UriEndPointType::type::PLAYER_END_POINT);

  client->createUriEndPoint (mo, mediaPipeline, UriEndPointType::type::RECORDER_END_POINT, "");
  BOOST_CHECK (mo.type.__isset.uriEndPoint);
  BOOST_CHECK_EQUAL (mo.type.uriEndPoint, UriEndPointType::type::RECORDER_END_POINT);

  client->createHttpEndPoint (mo, mediaPipeline);
  BOOST_CHECK (mo.type.__isset.endPoint);
  BOOST_CHECK_EQUAL (mo.type.endPoint, EndPointType::type::HTTP_END_POINT);

  client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER);
  BOOST_CHECK (mo.type.__isset.mixerType);
  BOOST_CHECK_EQUAL (mo.type.mixerType, MixerType::type::MAIN_MIXER);

  client->release (mediaPipeline);
}

static void
check_same_token (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);

  client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER);
  BOOST_CHECK_EQUAL (mediaPipeline.token, mo.token);

  client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::RTP_END_POINT);
  BOOST_CHECK_EQUAL (mediaPipeline.token, mo.token);

  client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::WEBRTC_END_POINT);
  BOOST_CHECK_EQUAL (mediaPipeline.token, mo.token);

  client->release (mediaPipeline);
}

static void
check_use_released_media_pipeline (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);
  client->release (mediaPipeline);
  BOOST_CHECK_THROW (client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER), MediaObjectNotFoundException);
}

static void
check_parent (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  MediaObjectId parent = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);

  client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER);
  client->getParent (parent, mo);
  BOOST_CHECK_EQUAL (mediaPipeline.id, parent.id);

  client->release (mediaPipeline);
}

static void
check_get_parent_in_released_media_pipeline (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  MediaObjectId parent = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);
  client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER);
  client->release (mediaPipeline);

  BOOST_CHECK_THROW (client->getParent (parent, mo), MediaObjectNotFoundException);
}

static void
check_media_pipeline_no_parent (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId parent = MediaObjectId();

  GST_DEBUG ("check_media_pipeline_no_parent test");
  client->createMediaPipeline (mediaPipeline, 0);
  BOOST_CHECK_THROW (client->getParent (parent, mediaPipeline), NoParentException);

  client->release (mediaPipeline);
}
#endif

static void
check_player_end_point (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectRef mediaPipeline = MediaObjectRef();
  MediaObjectRef playerEndPoint = MediaObjectRef();
  Params params = Params ();
  Command command;
  CommandResult result;
  std::string originalUri = "file:///tmp/player_end_point_test.webm";
  std::string resultUri;

  params.__set_dataType (g_dataTypes_constants.STRING_DATA_TYPE);
  params.__set_data (marshalString (originalUri) );

  client->createMediaPipeline (mediaPipeline);
  client->createMediaElementWithParams (playerEndPoint, mediaPipeline, g_PlayerEndPointType_constants.TYPE_NAME, params);

  command.__set_name (g_UriEndPointType_constants.GET_URI);
  client->sendCommand (result, playerEndPoint, command);

  BOOST_CHECK_EQUAL (g_dataTypes_constants.STRING_DATA_TYPE, result.dataType);

  BOOST_REQUIRE_NO_THROW (resultUri = unmarshalString (result.data) );
  BOOST_CHECK_EQUAL (0, originalUri.compare (resultUri) );

  client->release (mediaPipeline);
}

static void
check_recorder_end_point (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectRef mediaPipeline = MediaObjectRef();
  MediaObjectRef recorderEndPoint = MediaObjectRef();
  Params params = Params ();
  Command command;
  CommandResult result;
  std::string originalUri = "file:///tmp/player_end_point_test.webm";
  std::string resultUri;

  params.__set_dataType (g_dataTypes_constants.STRING_DATA_TYPE);
  params.__set_data (marshalString (originalUri) );

  client->createMediaPipeline (mediaPipeline);
  client->createMediaElementWithParams (recorderEndPoint, mediaPipeline, g_RecorderEndPointType_constants.TYPE_NAME, params);

  command.__set_name (g_UriEndPointType_constants.GET_URI);
  client->sendCommand (result, recorderEndPoint, command);

  BOOST_CHECK_EQUAL (g_dataTypes_constants.STRING_DATA_TYPE, result.dataType);

  BOOST_REQUIRE_NO_THROW (resultUri = unmarshalString (result.data) );
  BOOST_CHECK_EQUAL (0, originalUri.compare (resultUri) );

  client->release (mediaPipeline);
}

#if 0 /* Temporally disabled */
static void
check_http_end_point (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId httpEp = MediaObjectId();
  std::string out;

  client->createMediaPipeline (mediaPipeline, 0);

  client->createHttpEndPoint (httpEp, mediaPipeline);
  client->getUrl (out, httpEp);

  client->release (mediaPipeline);
}

static void
check_zbar_filter (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId zbarFilter = MediaObjectId();
  std::string out;

  client->createMediaPipeline (mediaPipeline, 0);
  client->createFilter (zbarFilter, mediaPipeline, FilterType::type::ZBAR_FILTER);
  client->release (mediaPipeline);
}
#endif

static void
client_side (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  check_version (client);

#if 0 /* Temporally disabled */
  check_no_handler (client);
  check_add_handler_address (client);
  check_use_released_media_pipeline (client);
  check_type (client);
  check_same_token (client);
  check_parent (client);
  check_get_parent_in_released_media_pipeline (client);
  check_media_pipeline_no_parent (client);
#endif

  check_player_end_point (client);
  check_recorder_end_point (client);

#if 0 /* Temporally disabled */
  check_http_end_point (client);
  check_zbar_filter (client);
#endif
}

BOOST_AUTO_TEST_CASE ( server_test )
{
  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);
  client_side (client);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Add test for using a released MediaPipeline<commit_after>/*
 * (C) Copyright 2013 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "server_test_base.hpp"
#include <boost/test/unit_test.hpp>

#include "mediaServer_constants.h"
#include "dataTypes_constants.h"
#include "errorCodes_constants.h"

#include "UriEndPointType_constants.h"
#include "PlayerEndPointType_constants.h"
#include "RecorderEndPointType_constants.h"

#include "utils/marshalling.hpp"

#include <gst/gst.h>

#define GST_CAT_DEFAULT _server_test_
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "server_test"

using namespace kurento;

BOOST_FIXTURE_TEST_SUITE ( server_test_suite,  F)

static void
check_version (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  int32_t gotVersion;

  gotVersion = client->getVersion();
  BOOST_CHECK_EQUAL (gotVersion, g_mediaServer_constants.VERSION);
}

#if 0 /* Temporally disabled */
static void
check_no_handler (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();

  BOOST_CHECK_THROW (client->createMediaPipeline (mediaPipeline, 0), HandlerNotFoundException);
}

static void
check_add_handler_address (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  client->addHandlerAddress (0, "localhost", 2323);
  client->addHandlerAddress (0, "localhost", 3434);
}

static void
check_type (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);
  BOOST_CHECK (mediaPipeline.type.__isset.mediaObject);
  BOOST_CHECK_EQUAL (mediaPipeline.type.mediaObject, MediaObjectType::type::MEDIA_PIPELINE);

  client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::RTP_END_POINT);
  BOOST_CHECK (mo.type.__isset.sdpEndPoint);
  BOOST_CHECK_EQUAL (mo.type.sdpEndPoint, SdpEndPointType::type::RTP_END_POINT);

  client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::WEBRTC_END_POINT);
  BOOST_CHECK (mo.type.__isset.sdpEndPoint);
  BOOST_CHECK_EQUAL (mo.type.sdpEndPoint, SdpEndPointType::type::WEBRTC_END_POINT);

  client->createUriEndPoint (mo, mediaPipeline, UriEndPointType::type::PLAYER_END_POINT, "");
  BOOST_CHECK (mo.type.__isset.uriEndPoint);
  BOOST_CHECK_EQUAL (mo.type.uriEndPoint, UriEndPointType::type::PLAYER_END_POINT);

  client->createUriEndPoint (mo, mediaPipeline, UriEndPointType::type::RECORDER_END_POINT, "");
  BOOST_CHECK (mo.type.__isset.uriEndPoint);
  BOOST_CHECK_EQUAL (mo.type.uriEndPoint, UriEndPointType::type::RECORDER_END_POINT);

  client->createHttpEndPoint (mo, mediaPipeline);
  BOOST_CHECK (mo.type.__isset.endPoint);
  BOOST_CHECK_EQUAL (mo.type.endPoint, EndPointType::type::HTTP_END_POINT);

  client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER);
  BOOST_CHECK (mo.type.__isset.mixerType);
  BOOST_CHECK_EQUAL (mo.type.mixerType, MixerType::type::MAIN_MIXER);

  client->release (mediaPipeline);
}

static void
check_same_token (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);

  client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER);
  BOOST_CHECK_EQUAL (mediaPipeline.token, mo.token);

  client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::RTP_END_POINT);
  BOOST_CHECK_EQUAL (mediaPipeline.token, mo.token);

  client->createSdpEndPoint (mo, mediaPipeline, SdpEndPointType::type::WEBRTC_END_POINT);
  BOOST_CHECK_EQUAL (mediaPipeline.token, mo.token);

  client->release (mediaPipeline);
}
#endif

static void
check_use_released_media_pipeline (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectRef mediaPipeline = MediaObjectRef();
  MediaObjectRef mo = MediaObjectRef();
  Params params = Params ();

  params.__set_dataType (g_dataTypes_constants.STRING_DATA_TYPE);
  params.__set_data (marshalString ("file:///tmp/f.webm") );

  client->createMediaPipeline (mediaPipeline);
  client->release (mediaPipeline);

  try {
    client->createMediaElementWithParams (mo, mediaPipeline, g_PlayerEndPointType_constants.TYPE_NAME, params);
    BOOST_FAIL ("Use a released MediaPipeline must throw a MediaServerException");
  } catch (const MediaServerException &e) {
    BOOST_CHECK_EQUAL (g_errorCodes_constants.MEDIA_OBJECT_NOT_FOUND, e.errorCode);
  }
}

#if 0 /* Temporally disabled */
static void
check_parent (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  MediaObjectId parent = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);

  client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER);
  client->getParent (parent, mo);
  BOOST_CHECK_EQUAL (mediaPipeline.id, parent.id);

  client->release (mediaPipeline);
}

static void
check_get_parent_in_released_media_pipeline (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId mo = MediaObjectId();
  MediaObjectId parent = MediaObjectId();

  client->createMediaPipeline (mediaPipeline, 0);
  client->createMixer (mo, mediaPipeline, MixerType::type::MAIN_MIXER);
  client->release (mediaPipeline);

  BOOST_CHECK_THROW (client->getParent (parent, mo), MediaObjectNotFoundException);
}

static void
check_media_pipeline_no_parent (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId parent = MediaObjectId();

  GST_DEBUG ("check_media_pipeline_no_parent test");
  client->createMediaPipeline (mediaPipeline, 0);
  BOOST_CHECK_THROW (client->getParent (parent, mediaPipeline), NoParentException);

  client->release (mediaPipeline);
}
#endif

static void
check_player_end_point (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectRef mediaPipeline = MediaObjectRef();
  MediaObjectRef playerEndPoint = MediaObjectRef();
  Params params = Params ();
  Command command;
  CommandResult result;
  std::string originalUri = "file:///tmp/player_end_point_test.webm";
  std::string resultUri;

  params.__set_dataType (g_dataTypes_constants.STRING_DATA_TYPE);
  params.__set_data (marshalString (originalUri) );

  client->createMediaPipeline (mediaPipeline);
  client->createMediaElementWithParams (playerEndPoint, mediaPipeline, g_PlayerEndPointType_constants.TYPE_NAME, params);

  command.__set_name (g_UriEndPointType_constants.GET_URI);
  client->sendCommand (result, playerEndPoint, command);

  BOOST_CHECK_EQUAL (g_dataTypes_constants.STRING_DATA_TYPE, result.dataType);

  BOOST_REQUIRE_NO_THROW (resultUri = unmarshalString (result.data) );
  BOOST_CHECK_EQUAL (0, originalUri.compare (resultUri) );

  client->release (mediaPipeline);
}

static void
check_recorder_end_point (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectRef mediaPipeline = MediaObjectRef();
  MediaObjectRef recorderEndPoint = MediaObjectRef();
  Params params = Params ();
  Command command;
  CommandResult result;
  std::string originalUri = "file:///tmp/player_end_point_test.webm";
  std::string resultUri;

  params.__set_dataType (g_dataTypes_constants.STRING_DATA_TYPE);
  params.__set_data (marshalString (originalUri) );

  client->createMediaPipeline (mediaPipeline);
  client->createMediaElementWithParams (recorderEndPoint, mediaPipeline, g_RecorderEndPointType_constants.TYPE_NAME, params);

  command.__set_name (g_UriEndPointType_constants.GET_URI);
  client->sendCommand (result, recorderEndPoint, command);

  BOOST_CHECK_EQUAL (g_dataTypes_constants.STRING_DATA_TYPE, result.dataType);

  BOOST_REQUIRE_NO_THROW (resultUri = unmarshalString (result.data) );
  BOOST_CHECK_EQUAL (0, originalUri.compare (resultUri) );

  client->release (mediaPipeline);
}

#if 0 /* Temporally disabled */
static void
check_http_end_point (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId httpEp = MediaObjectId();
  std::string out;

  client->createMediaPipeline (mediaPipeline, 0);

  client->createHttpEndPoint (httpEp, mediaPipeline);
  client->getUrl (out, httpEp);

  client->release (mediaPipeline);
}

static void
check_zbar_filter (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  MediaObjectId mediaPipeline = MediaObjectId();
  MediaObjectId zbarFilter = MediaObjectId();
  std::string out;

  client->createMediaPipeline (mediaPipeline, 0);
  client->createFilter (zbarFilter, mediaPipeline, FilterType::type::ZBAR_FILTER);
  client->release (mediaPipeline);
}
#endif

static void
client_side (boost::shared_ptr<kurento::MediaServerServiceClient> client)
{
  check_version (client);

#if 0 /* Temporally disabled */
  check_no_handler (client);
  check_add_handler_address (client);
#endif

  check_use_released_media_pipeline (client);

#if 0 /* Temporally disabled */
  check_type (client);
  check_same_token (client);
  check_parent (client);
  check_get_parent_in_released_media_pipeline (client);
  check_media_pipeline_no_parent (client);
#endif

  check_player_end_point (client);
  check_recorder_end_point (client);

#if 0 /* Temporally disabled */
  check_http_end_point (client);
  check_zbar_filter (client);
#endif
}

BOOST_AUTO_TEST_CASE ( server_test )
{
  BOOST_REQUIRE_MESSAGE (initialized, "Cannot connect to the server");
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME);
  client_side (client);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>