<commit_before>/*
	This file is part of cpp-ethereum.

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

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file transaction.cpp
 * @author Dmitrii Khokhlov <winsvega@mail.ru>
 * @date 2015
 * Transaaction test functions.
 */

#include "TestHelper.h"

using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;

namespace dev {  namespace test {

void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
	for (auto& i: _v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		if (_fillin)
		{
			BOOST_REQUIRE(o.count("transaction") > 0);
			mObject tObj = o["transaction"].get_obj();

			//Construct Rlp of the given transaction
			RLPStream rlpStream = createRLPStreamFromTransactionFields(tObj);
			o["rlp"] = "0x" + toHex(rlpStream.out());

			try
			{
				Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything);
				if (!txFromFields.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );

				o["sender"] = toString(txFromFields.sender());
				o["transaction"] = ImportTest::makeAllFieldsHex(tObj);
			}
			catch(Exception const& _e)
			{
				//Transaction is InValid
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				o.erase(o.find("transaction"));
				if (o.count("expect") > 0)
				{
					bool expectInValid = (o["expect"].get_str() == "invalid");
					if (Options::get().checkState)
							BOOST_CHECK_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");
						else
							BOOST_WARN_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");

					o.erase(o.find("expect"));
				}
			}

			//Transaction is Valid
			if (o.count("expect") > 0)
			{
				bool expectValid = (o["expect"].get_str() == "valid");
				if (Options::get().checkState)
						BOOST_CHECK_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");
					else
						BOOST_WARN_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");

				o.erase(o.find("expect"));
			}

		}
		else
		{
			BOOST_REQUIRE(o.count("rlp") > 0);
			Transaction txFromRlp;
			try
			{
				bytes stream = importByteArray(o["rlp"].get_str());
				RLP rlp(stream);
				txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything);
				if (!txFromRlp.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
			}
			catch(Exception const& _e)
			{
				cnote << i.first;
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}
			catch(...)
			{
				BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}

			BOOST_REQUIRE(o.count("transaction") > 0);

			mObject tObj = o["transaction"].get_obj();
			Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckTransaction::Everything);

			//Check the fields restored from RLP to original fields
			BOOST_CHECK_MESSAGE(txFromFields.data() == txFromRlp.data(), "Data in given RLP not matching the Transaction data!");
			BOOST_CHECK_MESSAGE(txFromFields.value() == txFromRlp.value(), "Value in given RLP not matching the Transaction value!");
			BOOST_CHECK_MESSAGE(txFromFields.gasPrice() == txFromRlp.gasPrice(), "GasPrice in given RLP not matching the Transaction gasPrice!");
			BOOST_CHECK_MESSAGE(txFromFields.gas() == txFromRlp.gas(),"Gas in given RLP not matching the Transaction gas!");
			BOOST_CHECK_MESSAGE(txFromFields.nonce() == txFromRlp.nonce(),"Nonce in given RLP not matching the Transaction nonce!");
			BOOST_CHECK_MESSAGE(txFromFields.receiveAddress() == txFromRlp.receiveAddress(), "Receive address in given RLP not matching the Transaction 'to' address!");
			BOOST_CHECK_MESSAGE(txFromFields.sender() == txFromRlp.sender(), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
			BOOST_CHECK_MESSAGE(txFromFields == txFromRlp, "However, txFromFields != txFromRlp!");
			BOOST_REQUIRE (o.count("sender") > 0);

			Address addressReaded = Address(o["sender"].get_str());
			BOOST_CHECK_MESSAGE(txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded, "Signature address of sender does not match given sender address!");
		}
	}//for
}//doTransactionTests

} }// Namespace Close

BOOST_AUTO_TEST_SUITE(TransactionTests)

BOOST_AUTO_TEST_CASE(ttTransactionTest)
{
	dev::test::executeTests("ttTransactionTest", "/TransactionTests", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_CASE(ttWrongRLPTransaction)
{
	dev::test::executeTests("ttWrongRLPTransaction", "/TransactionTests", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_CASE(tt10mbDataField)
{
	if (test::Options::get().bigData)
	{
		auto start = chrono::steady_clock::now();

		dev::test::executeTests("tt10mbDataField", "/TransactionTests", dev::test::doTransactionTests);

		auto end = chrono::steady_clock::now();
		auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
		cnote << "test duration: " << duration.count() << " milliseconds.\n";
	}
}

BOOST_AUTO_TEST_CASE(ttCreateTest)
{
	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	{
		string arg = boost::unit_test::framework::master_test_suite().argv[i];
		if (arg == "--createtest")
		{
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
			{
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
				return;
			}
			try
			{
				cnote << "Populating tests...";
				json_spirit::mValue v;
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
				json_spirit::read_string(s, v);
				dev::test::doTransactionTests(v, true);
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
			}
			catch (Exception const& _e)
			{
				BOOST_ERROR("Failed transaction test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed transaction test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFile)
{
	dev::test::userDefinedTest("--singletest", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>All Fields Hex: remove line<commit_after>/*
	This file is part of cpp-ethereum.

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

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file transaction.cpp
 * @author Dmitrii Khokhlov <winsvega@mail.ru>
 * @date 2015
 * Transaaction test functions.
 */

#include "TestHelper.h"

using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;

namespace dev {  namespace test {

void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
	for (auto& i: _v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		if (_fillin)
		{
			BOOST_REQUIRE(o.count("transaction") > 0);
			mObject tObj = o["transaction"].get_obj();

			//Construct Rlp of the given transaction
			RLPStream rlpStream = createRLPStreamFromTransactionFields(tObj);
			o["rlp"] = "0x" + toHex(rlpStream.out());

			try
			{
				Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything);
				if (!txFromFields.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );

				o["sender"] = toString(txFromFields.sender());
				o["transaction"] = ImportTest::makeAllFieldsHex(tObj);
			}
			catch(Exception const& _e)
			{
				//Transaction is InValid
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				o.erase(o.find("transaction"));
				if (o.count("expect") > 0)
				{
					bool expectInValid = (o["expect"].get_str() == "invalid");
					if (Options::get().checkState)
							BOOST_CHECK_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");
						else
							BOOST_WARN_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");

					o.erase(o.find("expect"));
				}
			}

			//Transaction is Valid
			if (o.count("expect") > 0)
			{
				bool expectValid = (o["expect"].get_str() == "valid");
				if (Options::get().checkState)
						BOOST_CHECK_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");
					else
						BOOST_WARN_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");

				o.erase(o.find("expect"));
			}
		}
		else
		{
			BOOST_REQUIRE(o.count("rlp") > 0);
			Transaction txFromRlp;
			try
			{
				bytes stream = importByteArray(o["rlp"].get_str());
				RLP rlp(stream);
				txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything);
				if (!txFromRlp.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
			}
			catch(Exception const& _e)
			{
				cnote << i.first;
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}
			catch(...)
			{
				BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}

			BOOST_REQUIRE(o.count("transaction") > 0);

			mObject tObj = o["transaction"].get_obj();
			Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckTransaction::Everything);

			//Check the fields restored from RLP to original fields
			BOOST_CHECK_MESSAGE(txFromFields.data() == txFromRlp.data(), "Data in given RLP not matching the Transaction data!");
			BOOST_CHECK_MESSAGE(txFromFields.value() == txFromRlp.value(), "Value in given RLP not matching the Transaction value!");
			BOOST_CHECK_MESSAGE(txFromFields.gasPrice() == txFromRlp.gasPrice(), "GasPrice in given RLP not matching the Transaction gasPrice!");
			BOOST_CHECK_MESSAGE(txFromFields.gas() == txFromRlp.gas(),"Gas in given RLP not matching the Transaction gas!");
			BOOST_CHECK_MESSAGE(txFromFields.nonce() == txFromRlp.nonce(),"Nonce in given RLP not matching the Transaction nonce!");
			BOOST_CHECK_MESSAGE(txFromFields.receiveAddress() == txFromRlp.receiveAddress(), "Receive address in given RLP not matching the Transaction 'to' address!");
			BOOST_CHECK_MESSAGE(txFromFields.sender() == txFromRlp.sender(), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
			BOOST_CHECK_MESSAGE(txFromFields == txFromRlp, "However, txFromFields != txFromRlp!");
			BOOST_REQUIRE (o.count("sender") > 0);

			Address addressReaded = Address(o["sender"].get_str());
			BOOST_CHECK_MESSAGE(txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded, "Signature address of sender does not match given sender address!");
		}
	}//for
}//doTransactionTests

} }// Namespace Close

BOOST_AUTO_TEST_SUITE(TransactionTests)

BOOST_AUTO_TEST_CASE(ttTransactionTest)
{
	dev::test::executeTests("ttTransactionTest", "/TransactionTests", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_CASE(ttWrongRLPTransaction)
{
	dev::test::executeTests("ttWrongRLPTransaction", "/TransactionTests", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_CASE(tt10mbDataField)
{
	if (test::Options::get().bigData)
	{
		auto start = chrono::steady_clock::now();

		dev::test::executeTests("tt10mbDataField", "/TransactionTests", dev::test::doTransactionTests);

		auto end = chrono::steady_clock::now();
		auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
		cnote << "test duration: " << duration.count() << " milliseconds.\n";
	}
}

BOOST_AUTO_TEST_CASE(ttCreateTest)
{
	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	{
		string arg = boost::unit_test::framework::master_test_suite().argv[i];
		if (arg == "--createtest")
		{
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
			{
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
				return;
			}
			try
			{
				cnote << "Populating tests...";
				json_spirit::mValue v;
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
				json_spirit::read_string(s, v);
				dev::test::doTransactionTests(v, true);
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
			}
			catch (Exception const& _e)
			{
				BOOST_ERROR("Failed transaction test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed transaction test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFile)
{
	dev::test::userDefinedTest("--singletest", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE RankFilterVigraModule
#include <boost/test/included/unit_test.hpp>

#include "rank_filter_vigra.hxx"

struct RankFilterVigraFixture
{
    public:

        const unsigned long size = 10;

        vigra::MultiArray< 1, double >::difference_type size_1;

        vigra::MultiArray< 1, double > array_1;
        vigra::MultiArray< 1, double > reverse_array_1;

        vigra::MultiArray< 1, double > expected_result_1;
        vigra::MultiArray< 1, double > result_1;

        vigra::MultiArray< 2, double >::difference_type size_2;

        vigra::MultiArray< 2, double > array_2;
        vigra::MultiArray< 2, double > reverse_array_2;

        vigra::MultiArray< 2, double > expected_result_2;
        vigra::MultiArray< 2, double > result_2;

    public:

        RankFilterVigraFixture() : size_1(size), array_1(size_1), reverse_array_1(size_1), expected_result_1(size_1), result_1(size_1),
        size_2(size, size), array_2(size_2), reverse_array_2(size_2), expected_result_2(size_2), result_2(size_2)
        {
            for (int i = 0; i < array_1.shape(0); i++)
            {
                array_1[i] = i;
            }

            for (int i = 0; i < reverse_array_1.shape(0); i++)
            {
                reverse_array_1[i] = reverse_array_1.shape(0) - i - 1;
            }

            for (int i = 0; i < array_2.shape(0); i++)
            {
                for (int j = 0; j < array_2.shape(1); j++)
                {
                    array_2(i, j) = array_2.shape(1)*i + j;
                }
            }

            for (int i = 0; i < reverse_array_2.shape(0); i++)
            {
                for (int j = 0; j < reverse_array_2.shape(1); j++)
                {
                    reverse_array_2(i, j) = reverse_array_2.shape(1) * (reverse_array_2.shape(0) - i - 1) + (reverse_array_2.shape(1) - j - 1);
                }
            }
        };

        ~RankFilterVigraFixture()
        {
        };
};

BOOST_AUTO_TEST_SUITE( RankFilterVigraSuite )

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_1, RankFilterVigraFixture)
{
    expected_result_1 = array_1;

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, 0, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_2, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1, result_1, 0, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_3, RankFilterVigraFixture)
{
    expected_result_1 = array_1;
    expected_result_1[0] = expected_result_1[1];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, 1, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_4, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;
    expected_result_1[0] = expected_result_1[1];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1, result_1, 1, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_5, RankFilterVigraFixture)
{
    expected_result_1 = array_1;
    expected_result_1[0] = expected_result_1[1];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, 2, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_6, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;
    expected_result_1[0] = expected_result_1[1];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1, result_1, 2, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_7, RankFilterVigraFixture)
{
    expected_result_1 = array_1;
    expected_result_1[0] = expected_result_1[1] = expected_result_1[2];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2] = expected_result_1[expected_result_1.size() - 3];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, 3, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_8, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;
    expected_result_1[0] = expected_result_1[1] = expected_result_1[2];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2] = expected_result_1[expected_result_1.size() - 3];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1, result_1, 3, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_9, RankFilterVigraFixture)
{
    expected_result_1 = array_1;
    expected_result_1[0] = expected_result_1[1] = expected_result_1[2];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2] = expected_result_1[expected_result_1.size() - 3];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1.insertSingletonDimension(0), result_1.insertSingletonDimension(0), 3, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_10, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;
    expected_result_1[0] = expected_result_1[1] = expected_result_1[2];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2] = expected_result_1[expected_result_1.size() - 3];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1.insertSingletonDimension(0), result_1.insertSingletonDimension(0), 3, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_11, RankFilterVigraFixture)
{
    expected_result_2 = array_2;

    result_2 = 0;

    rank_filter::lineRankOrderFilter(array_2, result_2, 0, 0.5);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_12, RankFilterVigraFixture)
{
    expected_result_2 = reverse_array_2;

    result_2 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_2, result_2, 0, 0.5);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_13, RankFilterVigraFixture)
{
    expected_result_2 = array_2;
    expected_result_2.bindInner(0) = expected_result_2.bindInner(1);
    expected_result_2.bindInner(expected_result_2.shape(0) - 1) = expected_result_2.bindInner(expected_result_2.shape(0) - 2);

    result_2 = 0;

    rank_filter::lineRankOrderFilter(array_2, result_2, 1, 0.5);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_14, RankFilterVigraFixture)
{
    expected_result_2 = reverse_array_2;
    expected_result_2.bindInner(0) = expected_result_2.bindInner(1);
    expected_result_2.bindInner(expected_result_2.shape(0) - 1) = expected_result_2.bindInner(expected_result_2.shape(0) - 2);

    result_2 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_2, result_2, 1, 0.5);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_15, RankFilterVigraFixture)
{
    expected_result_2 = array_2;
    expected_result_2.bindOuter(0) = expected_result_2.bindOuter(1);
    expected_result_2.bindOuter(expected_result_2.shape(0) - 1) = expected_result_2.bindOuter(expected_result_2.shape(0) - 2);

    result_2 = 0;

    rank_filter::lineRankOrderFilter(array_2, result_2, 1, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_16, RankFilterVigraFixture)
{
    expected_result_2 = reverse_array_2;
    expected_result_2.bindOuter(0) = expected_result_2.bindOuter(1);
    expected_result_2.bindOuter(expected_result_2.shape(0) - 1) = expected_result_2.bindOuter(expected_result_2.shape(0) - 2);

    result_2 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_2, result_2, 1, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_17, RankFilterVigraFixture)
{
    expected_result_2 = reverse_array_2;
    expected_result_2.bindOuter(0) = expected_result_2.bindOuter(1);
    expected_result_2.bindOuter(expected_result_2.shape(0) - 1) = expected_result_2.bindOuter(expected_result_2.shape(0) - 2);

    result_2 = reverse_array_2;

    rank_filter::lineRankOrderFilter(result_2, result_2, 1, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_18, RankFilterVigraFixture)
{
    for (size_t i = 0; i < array_1.size(); i++)
    {
        expected_result_1[i] = (i < 5) ? array_1[5] : array_1[4];
    }

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, size - 1, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>test/test_rank_filter_vigra.cxx: Make constant member variable static.<commit_after>#define BOOST_TEST_MODULE RankFilterVigraModule
#include <boost/test/included/unit_test.hpp>

#include "rank_filter_vigra.hxx"

struct RankFilterVigraFixture
{
    public:

        static const unsigned long size = 10;

        vigra::MultiArray< 1, double >::difference_type size_1;

        vigra::MultiArray< 1, double > array_1;
        vigra::MultiArray< 1, double > reverse_array_1;

        vigra::MultiArray< 1, double > expected_result_1;
        vigra::MultiArray< 1, double > result_1;

        vigra::MultiArray< 2, double >::difference_type size_2;

        vigra::MultiArray< 2, double > array_2;
        vigra::MultiArray< 2, double > reverse_array_2;

        vigra::MultiArray< 2, double > expected_result_2;
        vigra::MultiArray< 2, double > result_2;

    public:

        RankFilterVigraFixture() : size_1(size), array_1(size_1), reverse_array_1(size_1), expected_result_1(size_1), result_1(size_1),
        size_2(size, size), array_2(size_2), reverse_array_2(size_2), expected_result_2(size_2), result_2(size_2)
        {
            for (int i = 0; i < array_1.shape(0); i++)
            {
                array_1[i] = i;
            }

            for (int i = 0; i < reverse_array_1.shape(0); i++)
            {
                reverse_array_1[i] = reverse_array_1.shape(0) - i - 1;
            }

            for (int i = 0; i < array_2.shape(0); i++)
            {
                for (int j = 0; j < array_2.shape(1); j++)
                {
                    array_2(i, j) = array_2.shape(1)*i + j;
                }
            }

            for (int i = 0; i < reverse_array_2.shape(0); i++)
            {
                for (int j = 0; j < reverse_array_2.shape(1); j++)
                {
                    reverse_array_2(i, j) = reverse_array_2.shape(1) * (reverse_array_2.shape(0) - i - 1) + (reverse_array_2.shape(1) - j - 1);
                }
            }
        };

        ~RankFilterVigraFixture()
        {
        };
};

BOOST_AUTO_TEST_SUITE( RankFilterVigraSuite )

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_1, RankFilterVigraFixture)
{
    expected_result_1 = array_1;

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, 0, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_2, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1, result_1, 0, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_3, RankFilterVigraFixture)
{
    expected_result_1 = array_1;
    expected_result_1[0] = expected_result_1[1];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, 1, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_4, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;
    expected_result_1[0] = expected_result_1[1];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1, result_1, 1, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_5, RankFilterVigraFixture)
{
    expected_result_1 = array_1;
    expected_result_1[0] = expected_result_1[1];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, 2, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_6, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;
    expected_result_1[0] = expected_result_1[1];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1, result_1, 2, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_7, RankFilterVigraFixture)
{
    expected_result_1 = array_1;
    expected_result_1[0] = expected_result_1[1] = expected_result_1[2];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2] = expected_result_1[expected_result_1.size() - 3];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, 3, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_8, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;
    expected_result_1[0] = expected_result_1[1] = expected_result_1[2];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2] = expected_result_1[expected_result_1.size() - 3];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1, result_1, 3, 0.5);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_9, RankFilterVigraFixture)
{
    expected_result_1 = array_1;
    expected_result_1[0] = expected_result_1[1] = expected_result_1[2];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2] = expected_result_1[expected_result_1.size() - 3];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1.insertSingletonDimension(0), result_1.insertSingletonDimension(0), 3, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_10, RankFilterVigraFixture)
{
    expected_result_1 = reverse_array_1;
    expected_result_1[0] = expected_result_1[1] = expected_result_1[2];
    expected_result_1[expected_result_1.size()  - 1] = expected_result_1[expected_result_1.size() - 2] = expected_result_1[expected_result_1.size() - 3];

    result_1 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_1.insertSingletonDimension(0), result_1.insertSingletonDimension(0), 3, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_11, RankFilterVigraFixture)
{
    expected_result_2 = array_2;

    result_2 = 0;

    rank_filter::lineRankOrderFilter(array_2, result_2, 0, 0.5);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_12, RankFilterVigraFixture)
{
    expected_result_2 = reverse_array_2;

    result_2 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_2, result_2, 0, 0.5);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_13, RankFilterVigraFixture)
{
    expected_result_2 = array_2;
    expected_result_2.bindInner(0) = expected_result_2.bindInner(1);
    expected_result_2.bindInner(expected_result_2.shape(0) - 1) = expected_result_2.bindInner(expected_result_2.shape(0) - 2);

    result_2 = 0;

    rank_filter::lineRankOrderFilter(array_2, result_2, 1, 0.5);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_14, RankFilterVigraFixture)
{
    expected_result_2 = reverse_array_2;
    expected_result_2.bindInner(0) = expected_result_2.bindInner(1);
    expected_result_2.bindInner(expected_result_2.shape(0) - 1) = expected_result_2.bindInner(expected_result_2.shape(0) - 2);

    result_2 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_2, result_2, 1, 0.5);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_15, RankFilterVigraFixture)
{
    expected_result_2 = array_2;
    expected_result_2.bindOuter(0) = expected_result_2.bindOuter(1);
    expected_result_2.bindOuter(expected_result_2.shape(0) - 1) = expected_result_2.bindOuter(expected_result_2.shape(0) - 2);

    result_2 = 0;

    rank_filter::lineRankOrderFilter(array_2, result_2, 1, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_16, RankFilterVigraFixture)
{
    expected_result_2 = reverse_array_2;
    expected_result_2.bindOuter(0) = expected_result_2.bindOuter(1);
    expected_result_2.bindOuter(expected_result_2.shape(0) - 1) = expected_result_2.bindOuter(expected_result_2.shape(0) - 2);

    result_2 = 0;

    rank_filter::lineRankOrderFilter(reverse_array_2, result_2, 1, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_17, RankFilterVigraFixture)
{
    expected_result_2 = reverse_array_2;
    expected_result_2.bindOuter(0) = expected_result_2.bindOuter(1);
    expected_result_2.bindOuter(expected_result_2.shape(0) - 1) = expected_result_2.bindOuter(expected_result_2.shape(0) - 2);

    result_2 = reverse_array_2;

    rank_filter::lineRankOrderFilter(result_2, result_2, 1, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_2, result_2);
}

BOOST_FIXTURE_TEST_CASE(test_rank_filter_vigra_18, RankFilterVigraFixture)
{
    for (size_t i = 0; i < array_1.size(); i++)
    {
        expected_result_1[i] = (i < 5) ? array_1[5] : array_1[4];
    }

    result_1 = 0;

    rank_filter::lineRankOrderFilter(array_1, result_1, size - 1, 0.5, 1);

    BOOST_CHECK_EQUAL(expected_result_1, result_1);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include "test.hpp"
#include "setup_transfer.hpp"
#include "web_seed_suite.hpp"
#include "libtorrent/create_torrent.hpp"

using namespace libtorrent;

const int proxy = libtorrent::proxy_settings::none;

//static unsigned char random_byte()
//{ return std::rand() & 0xff; }

int test_main()
{
	using namespace libtorrent;

	error_code ec;

	file_storage fs;
	int piece_size = 0x4000;

	char random_data[16000];
	std::generate(random_data, random_data + sizeof(random_data), random_byte);
	file f("test_file", file::write_only, ec);
	if (ec)
	{
		fprintf(stderr, "failed to create file \"test_file\": (%d) %s\n"
			, ec.value(), ec.message().c_str());
		return 1;
	}
	file::iovec_t b = { random_data, size_t(16000)};
	f.writev(0, &b, 1, ec);
	fs.add_file("test_file", 16000);

	int port = start_web_server();

	// generate a torrent with pad files to make sure they
	// are not requested web seeds
	libtorrent::create_torrent t(fs, piece_size, 0x4000);

	char tmp[512];
	snprintf(tmp, sizeof(tmp), "http://127.0.0.1:%d/redirect", port);
	t.add_url_seed(tmp);

	// calculate the hash for all pieces
	set_piece_hashes(t, ".", ec);

	if (ec)
	{
		fprintf(stderr, "error creating hashes for test torrent: %s\n"
			, ec.message().c_str());
		TEST_CHECK(false);
		return 0;
	}

	std::vector<char> buf;
	bencode(std::back_inserter(buf), t.generate());
	boost::shared_ptr<torrent_info> torrent_file(new torrent_info(&buf[0]
		, buf.size(), ec));

	{
		session ses(fingerprint("  ", 0,0,0,0), 0);
		session_settings settings;
		settings.max_queued_disk_bytes = 256 * 1024;
		ses.set_settings(settings);
		ses.set_alert_mask(~(alert::progress_notification | alert::stats_notification));

		// disable keep-alive because otherwise the test will choke on seeing
		// the disconnect (from the redirect)
		test_transfer(ses, torrent_file, 0, 0, "http", true, false, false, false);
	}

	stop_web_server();
	return 0;
}

<commit_msg>test build fix<commit_after>/*

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

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

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

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

*/

#include "test.hpp"
#include "setup_transfer.hpp"
#include "web_seed_suite.hpp"
#include "libtorrent/create_torrent.hpp"

using namespace libtorrent;

const int proxy = libtorrent::proxy_settings::none;

//static unsigned char random_byte()
//{ return std::rand() & 0xff; }

int test_main()
{
	using namespace libtorrent;

	error_code ec;

	file_storage fs;
	int piece_size = 0x4000;

	char random_data[16000];
	std::generate(random_data, random_data + sizeof(random_data), random_byte);
	file f("test_file", file::write_only, ec);
	if (ec)
	{
		fprintf(stderr, "failed to create file \"test_file\": (%d) %s\n"
			, ec.value(), ec.message().c_str());
		return 1;
	}
	file::iovec_t b = { random_data, size_t(16000)};
	f.writev(0, &b, 1, ec);
	fs.add_file("test_file", 16000);

	int port = start_web_server();

	// generate a torrent with pad files to make sure they
	// are not requested web seeds
	libtorrent::create_torrent t(fs, piece_size, 0x4000);

	char tmp[512];
	snprintf(tmp, sizeof(tmp), "http://127.0.0.1:%d/redirect", port);
	t.add_url_seed(tmp);

	// calculate the hash for all pieces
	set_piece_hashes(t, ".", ec);

	if (ec)
	{
		fprintf(stderr, "error creating hashes for test torrent: %s\n"
			, ec.message().c_str());
		TEST_CHECK(false);
		return 0;
	}

	std::vector<char> buf;
	bencode(std::back_inserter(buf), t.generate());
	boost::shared_ptr<torrent_info> torrent_file(new torrent_info(&buf[0]
		, buf.size(), ec));

	{
		libtorrent::session ses(fingerprint("  ", 0,0,0,0), 0);
		session_settings settings;
		settings.max_queued_disk_bytes = 256 * 1024;
		ses.set_settings(settings);
		ses.set_alert_mask(~(alert::progress_notification | alert::stats_notification));

		// disable keep-alive because otherwise the test will choke on seeing
		// the disconnect (from the redirect)
		test_transfer(ses, torrent_file, 0, 0, "http", true, false, false, false);
	}

	stop_web_server();
	return 0;
}

<|endoftext|>


<commit_before>#include <iostream>

#include "format.hpp"

int main(int argc, char* argv[]);

int main(int argc, char* argv[])
{
	using namespace utils;

	{
		int a = 1000;
		format("%d\n") % a;
	}

	{
		static const char* t = { "Asdfg" };
		format("'%s'\n") % t;
	}

	{
		char tmp[100];
		strcpy(tmp, "Qwert");
		format("'%s'\n") % tmp;
	}

	{
		char str[] = { "Asdfg" };
		int i = 123;
		float a = 1000.105f;
		float b = 0.0f;
		format("%d, '%s', %7.3f, %6.2f\n") % i % str % a % b;
	}

	{
		float x = 1.0f;
		float y = 2.0f;
		float z = 3.0f;
		char tmp[512];
		sformat("Value: %f, %f, %f\n", tmp, sizeof(tmp)) % x % y % z;
		sformat("Value: %f, %f, %f\n", tmp, sizeof(tmp), true) % y % z % x;
		sformat("Value: %f, %f, %f\n", tmp, sizeof(tmp), true) % z % x % y;
		int size = sformat::chaout().size();
		format("(%d)\n%s") % size % tmp;
	}

	{
		format("0o%03o, 0b%08b\n") % static_cast<int16_t>(-1) %  static_cast<int16_t>(-1);
	}
}
<commit_msg>update: add test pattern<commit_after>#include <iostream>

#include "format.hpp"

int main(int argc, char* argv[]);

int main(int argc, char* argv[])
{
	using namespace utils;

	{
		int a = 1000;
		format("%d\n") % a;
	}

	{
		static const char* t = { "Asdfg" };
		format("'%s'\n") % t;
	}

	{
		char tmp[100];
		strcpy(tmp, "Qwert");
		format("'%s'\n") % tmp;
	}

	{
		char str[] = { "Asdfg" };
		int i = 123;
		float a = 1000.105f;
		float b = 0.0f;
		format("%d, '%s', %7.3f, %6.2f\n") % i % str % a % b;
	}

	{
		float x = 1.0f;
		float y = 2.0f;
		float z = 3.0f;
		char tmp[512];
		sformat("Value: %f, %f, %f\n", tmp, sizeof(tmp)) % x % y % z;
		sformat("Value: %f, %f, %f\n", tmp, sizeof(tmp), true) % y % z % x;
		sformat("Value: %f, %f, %f\n", tmp, sizeof(tmp), true) % z % x % y;
		int size = sformat::chaout().size();
		format("(%d)\n%s") % size % tmp;
	}

	{  // 10進、16進、8進、2進
		int16_t n = -1;
		format("%d, 0x%04x, 0o%03o, 0b%04b\n") % n % n % n % n;
		n = 1;
		format("%d, 0x%04x, 0o%03o, 0b%04b\n") % n % n % n % n;
	}

	{  // 異なったプロトタイプ
		static const char* str = { "Poiuytrewq" };
		int val = 1921;
		format("%s, %d\n") % val % str;
	}
}
<|endoftext|>


<commit_before>#include <ctime>
#include <cstring>
#include <algorithm>
#include <locale>
#include <sstream>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <float.h> // DBL_MIN, DBL_MAX

#include <unistd.h> // link, unlink

#include <tightdb/util/file.hpp>

#include "timer.hpp"
#include "benchmark_results.hpp"

using namespace std;
using namespace tightdb;
using namespace test_util;

namespace {

string format_elapsed_time(double seconds)
{
    ostringstream out;
    Timer::format(seconds, out);
    return out.str();
}

string format_change_percent(double baseline, double seconds)
{
    ostringstream out;
    double percent = (seconds - baseline) / baseline * 100;
    out.precision(3);
    out.setf(ios_base::showpos);
    out << percent << "%";
    return out.str();
}

string format_drop_factor(double baseline, double seconds)
{
    ostringstream out;
    double factor = baseline / seconds;
    out.precision(3);
    out << factor << ":1";
    return out.str();
}

string format_rise_factor(double baseline, double seconds)
{
    ostringstream out;
    double factor = seconds / baseline;
    out.precision(3);
    out << "1:" << factor;
    return out.str();
}

string format_change(double baseline, double input, BenchmarkResults::ChangeType change_type)
{
    switch (change_type) {
        case BenchmarkResults::change_Percent:
            return format_change_percent(baseline, input);
        case BenchmarkResults::change_DropFactor:
            return format_drop_factor(baseline, input);
        case BenchmarkResults::change_RiseFactor:
            return format_rise_factor(baseline, input);
    }
    TIGHTDB_ASSERT(false);
    return string();
}

} // anonymous namespace

BenchmarkResults::Result::Result():
    min(DBL_MAX), max(DBL_MIN), total(0), rep(0)
{
}

double BenchmarkResults::Result::avg() const
{
    return total / rep;
}

void BenchmarkResults::submit_single(const char* ident, const char* lead_text,
    double seconds, ChangeType change_type)
{
    submit(ident, seconds);
    finish(ident, lead_text, change_type);
}

void BenchmarkResults::submit(const char* ident, double seconds)
{
    Results::iterator it = m_results.find(ident);
    if (it == m_results.end()) {
        it = m_results.insert(std::make_pair(ident, Result())).first;
    }
    Result& r = it->second;
    if (r.min > seconds) r.min = seconds;
    if (r.max < seconds) r.max = seconds;
    r.total += seconds;
    r.rep += 1;
}

void BenchmarkResults::finish(const std::string& ident, const std::string& lead_text, ChangeType change_type)
{
    /*
        OUTPUT FOR RESULTS WITHOUT BASELINE:
        Lead Text             min 0.0s     max 0.0s    avg 0.0s
        Lead Text 2           min 123.0s   max 32.0s   avg 1.0s

        OUTPUT FOR RESULTS WITH BASELINE:
        Lead Text             min 0.0s (+10%)   max 0.0s (-20%)   avg 0.0s (0%)
        Lead Text 2           min 0.0s (+10%)   max 0.0s (-20%)   avg 0.0s (0%)
    */

    BaselineResults::const_iterator baseline_iter = m_baseline_results.find(ident);

    std::ostream& out = std::cout;

    // Print Lead Text
    out.setf(ios_base::left, ios_base::adjustfield);
    m_max_lead_text_width = max(m_max_lead_text_width, int(lead_text.size()));
    std::string lead_text_2 = lead_text + ":";
    out << setw(m_max_lead_text_width + 1 + 3) << lead_text_2;

    Results::const_iterator it = m_results.find(ident);
    if (it == m_results.end()) {
        out << "(no measurements)" << endl;
        return;
    }

    const Result& r = it->second;

    const size_t time_width = 8;

    out.setf(ios_base::right, ios_base::adjustfield);
    if (baseline_iter != m_baseline_results.end()) {
        const Result& br = baseline_iter->second;
        out << "min " << setw(time_width) << format_elapsed_time(r.min)   << " (" << format_change(br.min, r.min, change_type) << ")     ";
        out << "max " << setw(time_width) << format_elapsed_time(r.max)   << " (" << format_change(br.max, r.max, change_type) << ")     ";
        out << "avg " << setw(time_width) << format_elapsed_time(r.avg()) << " (" << format_change(br.avg(), r.avg(), change_type) << ")     ";
        out << "reps " << r.rep;
    }
    else {
        out << "min " << setw(time_width) << format_elapsed_time(r.min)   << "     ";
        out << "max " << setw(time_width) << format_elapsed_time(r.max)   << "     ";
        out << "avg " << setw(time_width) << format_elapsed_time(r.avg()) << "     ";
        out << "reps " << r.rep;
    }
    out << endl;
}

void BenchmarkResults::try_load_baseline_results()
{
    string baseline_file = m_results_file_stem;
    baseline_file += ".baseline";
    if (util::File::exists(baseline_file)) {
        ifstream in(baseline_file.c_str());
        BaselineResults baseline_results;
        bool error = false;
        string line;
        while (getline(in, line)) {
            istringstream line_in(line);
            string ident;
            char space;
            Result r;
            line_in >> ident >> noskipws >> space >> skipws >> r.min >> space >> r.max >> space >> r.total >> r.rep;
            if (!line_in || !isspace(space, line_in.getloc()))
                error = true;
            if (!line_in.eof()) {
                line_in >> space;
                if (line_in.rdstate() != (ios_base::failbit | ios_base::eofbit))
                    error = true;
            }
            if (error)
                break;
            baseline_results[ident] = r;
        }
        if (error) {
            cerr << "WARNING: Failed to parse '"<<baseline_file<<"'\n";
        }
        else {
            m_baseline_results = baseline_results;
        }
    }
}

void BenchmarkResults::save_results()
{
    time_t now = time(0);
    localtime(&now);
    struct tm local;
    localtime_r(&now,  &local);
    ostringstream name_out;
    name_out << m_results_file_stem << ".";
    // Format: YYYYMMDD_hhmmss;
    name_out.fill('0');
    name_out << (1900 + local.tm_year) << ""
        "" << setw(2) << (1 + local.tm_mon) << ""
        "" << setw(2) << local.tm_mday << "_"
        "" << setw(2) << local.tm_hour << ""
        "" << setw(2) << local.tm_min << ""
        "" << setw(2) << local.tm_sec;
    string name = name_out.str();
    string csv_name = name + ".csv";
    {
        ofstream out(name.c_str());
        ofstream csv_out(csv_name.c_str());

        csv_out << "ident,min,max,avg,reps,total" << '\n';
        csv_out.setf(std::ios_base::fixed, std::ios_base::floatfield);

        typedef Results::const_iterator iter;
        for (iter it = m_results.begin(); it != m_results.end(); ++it) {
            const Result& r = it->second;

            out << it->first << ' ';
            out << r.min << " " << r.max << " " << r.total << " " << r.rep << '\n';

            csv_out << '"' << it->first << "\",";
            csv_out << r.min << ',' << r.max << ',' << r.avg() << ',' << r.rep << ',' << r.total << '\n';
        }
    }

    string baseline_file = m_results_file_stem;
    string latest_csv_file = m_results_file_stem + ".latest.csv";
    baseline_file += ".baseline";
    if (!util::File::exists(baseline_file)) {
        link(name.c_str(), baseline_file.c_str());
    }
    if (util::File::exists(latest_csv_file)) {
        unlink(latest_csv_file.c_str());
    }
    link(csv_name.c_str(), latest_csv_file.c_str());
}

<commit_msg>Fixed warning<commit_after>#include <ctime>
#include <cstring>
#include <algorithm>
#include <locale>
#include <sstream>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <float.h> // DBL_MIN, DBL_MAX

#include <unistd.h> // link, unlink

#include <tightdb/util/file.hpp>

#include "timer.hpp"
#include "benchmark_results.hpp"

using namespace std;
using namespace tightdb;
using namespace test_util;

namespace {

string format_elapsed_time(double seconds)
{
    ostringstream out;
    Timer::format(seconds, out);
    return out.str();
}

string format_change_percent(double baseline, double seconds)
{
    ostringstream out;
    double percent = (seconds - baseline) / baseline * 100;
    out.precision(3);
    out.setf(ios_base::showpos);
    out << percent << "%";
    return out.str();
}

string format_drop_factor(double baseline, double seconds)
{
    ostringstream out;
    double factor = baseline / seconds;
    out.precision(3);
    out << factor << ":1";
    return out.str();
}

string format_rise_factor(double baseline, double seconds)
{
    ostringstream out;
    double factor = seconds / baseline;
    out.precision(3);
    out << "1:" << factor;
    return out.str();
}

string format_change(double baseline, double input, BenchmarkResults::ChangeType change_type)
{
    switch (change_type) {
        case BenchmarkResults::change_Percent:
            return format_change_percent(baseline, input);
        case BenchmarkResults::change_DropFactor:
            return format_drop_factor(baseline, input);
        case BenchmarkResults::change_RiseFactor:
            return format_rise_factor(baseline, input);
    }
    TIGHTDB_ASSERT(false);
    return string();
}

} // anonymous namespace

BenchmarkResults::Result::Result():
    min(DBL_MAX), max(DBL_MIN), total(0), rep(0)
{
}

double BenchmarkResults::Result::avg() const
{
    return total / rep;
}

void BenchmarkResults::submit_single(const char* ident, const char* lead_text,
    double seconds, ChangeType change_type)
{
    submit(ident, seconds);
    finish(ident, lead_text, change_type);
}

void BenchmarkResults::submit(const char* ident, double seconds)
{
    Results::iterator it = m_results.find(ident);
    if (it == m_results.end()) {
        it = m_results.insert(std::make_pair(ident, Result())).first;
    }
    Result& r = it->second;
    if (r.min > seconds) r.min = seconds;
    if (r.max < seconds) r.max = seconds;
    r.total += seconds;
    r.rep += 1;
}

void BenchmarkResults::finish(const std::string& ident, const std::string& lead_text, ChangeType change_type)
{
    /*
        OUTPUT FOR RESULTS WITHOUT BASELINE:
        Lead Text             min 0.0s     max 0.0s    avg 0.0s
        Lead Text 2           min 123.0s   max 32.0s   avg 1.0s

        OUTPUT FOR RESULTS WITH BASELINE:
        Lead Text             min 0.0s (+10%)   max 0.0s (-20%)   avg 0.0s (0%)
        Lead Text 2           min 0.0s (+10%)   max 0.0s (-20%)   avg 0.0s (0%)
    */

    BaselineResults::const_iterator baseline_iter = m_baseline_results.find(ident);

    std::ostream& out = std::cout;

    // Print Lead Text
    out.setf(ios_base::left, ios_base::adjustfield);
    m_max_lead_text_width = max(m_max_lead_text_width, int(lead_text.size()));
    std::string lead_text_2 = lead_text + ":";
    out << setw(m_max_lead_text_width + 1 + 3) << lead_text_2;

    Results::const_iterator it = m_results.find(ident);
    if (it == m_results.end()) {
        out << "(no measurements)" << endl;
        return;
    }

    const Result& r = it->second;

    const size_t time_width = 8;

    out.setf(ios_base::right, ios_base::adjustfield);
    if (baseline_iter != m_baseline_results.end()) {
        const Result& br = baseline_iter->second;
        out << "min " << setw(time_width) << format_elapsed_time(r.min)   << " (" << format_change(br.min, r.min, change_type) << ")     ";
        out << "max " << setw(time_width) << format_elapsed_time(r.max)   << " (" << format_change(br.max, r.max, change_type) << ")     ";
        out << "avg " << setw(time_width) << format_elapsed_time(r.avg()) << " (" << format_change(br.avg(), r.avg(), change_type) << ")     ";
        out << "reps " << r.rep;
    }
    else {
        out << "min " << setw(time_width) << format_elapsed_time(r.min)   << "     ";
        out << "max " << setw(time_width) << format_elapsed_time(r.max)   << "     ";
        out << "avg " << setw(time_width) << format_elapsed_time(r.avg()) << "     ";
        out << "reps " << r.rep;
    }
    out << endl;
}

void BenchmarkResults::try_load_baseline_results()
{
    string baseline_file = m_results_file_stem;
    baseline_file += ".baseline";
    if (util::File::exists(baseline_file)) {
        ifstream in(baseline_file.c_str());
        BaselineResults baseline_results;
        bool error = false;
        string line;
        while (getline(in, line)) {
            istringstream line_in(line);
            string ident;
            char space;
            Result r;
            line_in >> ident >> noskipws >> space >> skipws >> r.min >> space >> r.max >> space >> r.total >> r.rep;
            if (!line_in || !isspace(space, line_in.getloc()))
                error = true;
            if (!line_in.eof()) {
                line_in >> space;
                if (line_in.rdstate() != (ios_base::failbit | ios_base::eofbit))
                    error = true;
            }
            if (error)
                break;
            baseline_results[ident] = r;
        }
        if (error) {
            cerr << "WARNING: Failed to parse '"<<baseline_file<<"'\n";
        }
        else {
            m_baseline_results = baseline_results;
        }
    }
}

void BenchmarkResults::save_results()
{
    time_t now = time(0);
    localtime(&now);
    struct tm local;
    localtime_r(&now,  &local);
    ostringstream name_out;
    name_out << m_results_file_stem << ".";
    // Format: YYYYMMDD_hhmmss;
    name_out.fill('0');
    name_out << (1900 + local.tm_year) << ""
        "" << setw(2) << (1 + local.tm_mon) << ""
        "" << setw(2) << local.tm_mday << "_"
        "" << setw(2) << local.tm_hour << ""
        "" << setw(2) << local.tm_min << ""
        "" << setw(2) << local.tm_sec;
    string name = name_out.str();
    string csv_name = name + ".csv";
    {
        ofstream out(name.c_str());
        ofstream csv_out(csv_name.c_str());

        csv_out << "ident,min,max,avg,reps,total" << '\n';
        csv_out.setf(std::ios_base::fixed, std::ios_base::floatfield);

        typedef Results::const_iterator iter;
        for (iter it = m_results.begin(); it != m_results.end(); ++it) {
            const Result& r = it->second;

            out << it->first << ' ';
            out << r.min << " " << r.max << " " << r.total << " " << r.rep << '\n';

            csv_out << '"' << it->first << "\",";
            csv_out << r.min << ',' << r.max << ',' << r.avg() << ',' << r.rep << ',' << r.total << '\n';
        }
    }

    string baseline_file = m_results_file_stem;
    string latest_csv_file = m_results_file_stem + ".latest.csv";
    baseline_file += ".baseline";
    int r;
    if (!util::File::exists(baseline_file)) {
        r = link(name.c_str(), baseline_file.c_str());
    }
    if (util::File::exists(latest_csv_file)) {
        r = unlink(latest_csv_file.c_str());
    }
    r = link(csv_name.c_str(), latest_csv_file.c_str());
    static_cast<void>(r); // FIXME: Display if error
}

<|endoftext|>


<commit_before>/*
 *
 * Copyright (c) 2018, Livio
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "transport_manager/cloud/websocket_client_connection.h"
#include "transport_manager/cloud/cloud_device.h"

#include "transport_manager/transport_adapter/transport_adapter_controller.h"

#include "utils/logger.h"

namespace transport_manager {
namespace transport_adapter {
CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager")

WebsocketClientConnection::WebsocketClientConnection(
    const DeviceUID& device_uid,
    const ApplicationHandle& app_handle,
    TransportAdapterController* controller)
    : controller_(controller)
    , ctx_(ssl::context::sslv23_client)
    , resolver_(ioc_)
    , ws_(ioc_)
    , wss_(ioc_, ctx_)
    , shutdown_(false)
    , thread_delegate_(new LoopThreadDelegate(&message_queue_, this))
    , write_thread_(threads::CreateThread("WS Async Send", thread_delegate_))
    , device_uid_(device_uid)
    , app_handle_(app_handle)
    , io_pool_(1) {}

WebsocketClientConnection::~WebsocketClientConnection() {
  ioc_.stop();
  io_pool_.join();
}

void WebsocketClientConnection::AddCertificateAuthority(
    const std::string cert, boost::system::error_code& ec) {
  ctx_.add_certificate_authority(boost::asio::buffer(cert.data(), cert.size()),
                                 ec);
  if (ec) {
    return;
  }

  wss_.next_layer().set_verify_mode(ssl::verify_peer);
}

TransportAdapter::Error WebsocketClientConnection::Start() {
  LOG4CXX_AUTO_TRACE(logger_);
  DeviceSptr device = controller_->FindDevice(device_uid_);
  CloudDevice* cloud_device = static_cast<CloudDevice*>(device.get());
  CloudWebsocketTransportAdapter* cloud_ta =
      static_cast<CloudWebsocketTransportAdapter*>(controller_);
  cloud_properties = cloud_ta->GetAppCloudTransportConfig(device_uid_);
  auto const host = cloud_device->GetHost();
  auto const port = cloud_device->GetPort();
  boost::system::error_code ec;

  LOG4CXX_DEBUG(logger_, "Cloud app endpoint: " << cloud_properties.endpoint);
  LOG4CXX_DEBUG(logger_,
                "Cloud app certificate: " << cloud_properties.certificate);
  LOG4CXX_DEBUG(
      logger_,
      "Cloud app authentication token: " << cloud_properties.auth_token);
  LOG4CXX_DEBUG(
      logger_,
      "Cloud app transport type: " << cloud_properties.cloud_transport_type);
  LOG4CXX_DEBUG(logger_,
                "Cloud app hybrid app preference: "
                    << cloud_properties.hybrid_app_preference);

  auto const results = resolver_.resolve(host, port, ec);
  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_, "Could not resolve host/port: " << str_err);
    return TransportAdapter::FAIL;
  }

  // Make Connection to host IP Address over TCP
  if (cloud_properties.cloud_transport_type == "WSS") {
    boost::asio::connect(
        wss_.next_layer().next_layer(), results.begin(), results.end(), ec);
  } else {
    boost::asio::connect(ws_.next_layer(), results.begin(), results.end(), ec);
  }
  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_,
                  "Could not connect to websocket: " << host << ":" << port);
    LOG4CXX_ERROR(logger_, str_err);
    return TransportAdapter::FAIL;
  }

  if (cloud_properties.cloud_transport_type == "WSS") {
    AddCertificateAuthority(cloud_properties.certificate, ec);

    if (ec) {
      std::string str_err = "ErrorMessage: " + ec.message();
      LOG4CXX_ERROR(logger_,
                    "Failed to add certificate authority: "
                        << cloud_properties.certificate);
      LOG4CXX_ERROR(logger_, str_err);
      Shutdown();
      return TransportAdapter::FAIL;
    }

    // Perform SSL Handshake
    wss_.next_layer().handshake(ssl::stream_base::client, ec);

    if (ec) {
      std::string str_err = "ErrorMessage: " + ec.message();
      LOG4CXX_ERROR(logger_,
                    "Could not complete SSL Handshake failed with host/port: "
                        << host << ":" << port);
      LOG4CXX_ERROR(logger_, str_err);
      Shutdown();
      return TransportAdapter::FAIL;
    }
  }

  // Perform websocket handshake
  if (cloud_properties.cloud_transport_type == "WSS") {
    wss_.handshake(host, "/", ec);
  } else {
    ws_.handshake(host, "/", ec);
  }
  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_,
                  "Could not complete handshake with host/port: " << host << ":"
                                                                  << port);
    LOG4CXX_ERROR(logger_, str_err);
    return TransportAdapter::FAIL;
  }

  // Set the binary message write option
  if (cloud_properties.cloud_transport_type == "WSS") {
    wss_.binary(true);
  } else {
    ws_.binary(true);
  }
  write_thread_->start(threads::ThreadOptions());
  controller_->ConnectDone(device_uid_, app_handle_);

  // Start async read
  if (cloud_properties.cloud_transport_type == "WSS") {
    wss_.async_read(buffer_,
                    std::bind(&WebsocketClientConnection::OnRead,
                              this,
                              std::placeholders::_1,
                              std::placeholders::_2));
  } else {
    ws_.async_read(buffer_,
                   std::bind(&WebsocketClientConnection::OnRead,
                             this,
                             std::placeholders::_1,
                             std::placeholders::_2));
  }

  boost::asio::post(io_pool_, [&]() { ioc_.run(); });

  LOG4CXX_DEBUG(logger_,
                "Successfully started websocket connection @: " << host << ":"
                                                                << port);
  return TransportAdapter::OK;
}

void WebsocketClientConnection::Recv(boost::system::error_code ec) {
  if (shutdown_) {
    return;
  }

  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_, str_err);
    Shutdown();
    return;
  }
  if (cloud_properties.cloud_transport_type == "WSS") {
    wss_.async_read(buffer_,
                    std::bind(&WebsocketClientConnection::OnRead,
                              this,
                              std::placeholders::_1,
                              std::placeholders::_2));
  } else {
    ws_.async_read(buffer_,
                   std::bind(&WebsocketClientConnection::OnRead,
                             this,
                             std::placeholders::_1,
                             std::placeholders::_2));
  }
}

void WebsocketClientConnection::OnRead(boost::system::error_code ec,
                                       std::size_t bytes_transferred) {
  boost::ignore_unused(bytes_transferred);
  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_, str_err);
    ws_.lowest_layer().close();
    ioc_.stop();
    Shutdown();
    return;
  }
  std::string data_str = boost::beast::buffers_to_string(buffer_.data());

  ssize_t size = (ssize_t)buffer_.size();
  const uint8_t* data = boost::asio::buffer_cast<const uint8_t*>(
      boost::beast::buffers_front(buffer_.data()));

  ::protocol_handler::RawMessagePtr frame(
      new protocol_handler::RawMessage(0, 0, data, size));

  controller_->DataReceiveDone(device_uid_, app_handle_, frame);

  buffer_.consume(buffer_.size());
  Recv(ec);
}

TransportAdapter::Error WebsocketClientConnection::SendData(
    ::protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);
  sync_primitives::AutoLock auto_lock(frames_to_send_mutex_);
  message_queue_.push(message);
  return TransportAdapter::OK;
}

TransportAdapter::Error WebsocketClientConnection::Disconnect() {
  LOG4CXX_AUTO_TRACE(logger_);
  Shutdown();
  return TransportAdapter::OK;
}

void WebsocketClientConnection::Shutdown() {
  shutdown_ = true;

  if (thread_delegate_) {
    thread_delegate_->SetShutdown();
    write_thread_->join();
    delete thread_delegate_;
    threads::DeleteThread(write_thread_);
  }
  if (buffer_.size()) {
    buffer_.consume(buffer_.size());
  }
  controller_->DisconnectDone(device_uid_, app_handle_);
}

WebsocketClientConnection::LoopThreadDelegate::LoopThreadDelegate(
    MessageQueue<Message, AsyncQueue>* message_queue,
    WebsocketClientConnection* handler)
    : message_queue_(*message_queue), handler_(*handler), shutdown_(false) {}

void WebsocketClientConnection::LoopThreadDelegate::threadMain() {
  while (!message_queue_.IsShuttingDown() && !shutdown_) {
    DrainQueue();
    message_queue_.wait();
  }
  DrainQueue();
}

void WebsocketClientConnection::LoopThreadDelegate::exitThreadMain() {
  shutdown_ = true;
  if (!message_queue_.IsShuttingDown()) {
    message_queue_.Shutdown();
  }
}

void WebsocketClientConnection::LoopThreadDelegate::DrainQueue() {
  while (!message_queue_.empty()) {
    Message message_ptr;
    message_queue_.pop(message_ptr);
    if (!shutdown_) {
      boost::system::error_code ec;
      if (handler_.cloud_properties.cloud_transport_type == "WSS") {
        handler_.wss_.write(
            boost::asio::buffer(message_ptr->data(), message_ptr->data_size()));
      } else {
        handler_.ws_.write(
            boost::asio::buffer(message_ptr->data(), message_ptr->data_size()));
      }
      if (ec) {
        LOG4CXX_ERROR(logger_, "Error writing to websocket");
        handler_.controller_->DataSendFailed(handler_.device_uid_,
                                             handler_.app_handle_,
                                             message_ptr,
                                             DataSendError());
      }
    }
  }
}

void WebsocketClientConnection::LoopThreadDelegate::SetShutdown() {
  shutdown_ = true;
  if (!message_queue_.IsShuttingDown()) {
    message_queue_.Shutdown();
  }
}

}  // namespace transport_adapter
}  // namespace transport_manager
<commit_msg>Set deleted pointers to null<commit_after>/*
 *
 * Copyright (c) 2018, Livio
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "transport_manager/cloud/websocket_client_connection.h"
#include "transport_manager/cloud/cloud_device.h"

#include "transport_manager/transport_adapter/transport_adapter_controller.h"

#include "utils/logger.h"

namespace transport_manager {
namespace transport_adapter {
CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager")

WebsocketClientConnection::WebsocketClientConnection(
    const DeviceUID& device_uid,
    const ApplicationHandle& app_handle,
    TransportAdapterController* controller)
    : controller_(controller)
    , ctx_(ssl::context::sslv23_client)
    , resolver_(ioc_)
    , ws_(ioc_)
    , wss_(ioc_, ctx_)
    , shutdown_(false)
    , thread_delegate_(new LoopThreadDelegate(&message_queue_, this))
    , write_thread_(threads::CreateThread("WS Async Send", thread_delegate_))
    , device_uid_(device_uid)
    , app_handle_(app_handle)
    , io_pool_(1) {}

WebsocketClientConnection::~WebsocketClientConnection() {
  ioc_.stop();
  io_pool_.join();
}

void WebsocketClientConnection::AddCertificateAuthority(
    const std::string cert, boost::system::error_code& ec) {
  ctx_.add_certificate_authority(boost::asio::buffer(cert.data(), cert.size()),
                                 ec);
  if (ec) {
    return;
  }

  wss_.next_layer().set_verify_mode(ssl::verify_peer);
}

TransportAdapter::Error WebsocketClientConnection::Start() {
  LOG4CXX_AUTO_TRACE(logger_);
  DeviceSptr device = controller_->FindDevice(device_uid_);
  CloudDevice* cloud_device = static_cast<CloudDevice*>(device.get());
  CloudWebsocketTransportAdapter* cloud_ta =
      static_cast<CloudWebsocketTransportAdapter*>(controller_);
  cloud_properties = cloud_ta->GetAppCloudTransportConfig(device_uid_);
  auto const host = cloud_device->GetHost();
  auto const port = cloud_device->GetPort();
  boost::system::error_code ec;

  LOG4CXX_DEBUG(logger_, "Cloud app endpoint: " << cloud_properties.endpoint);
  LOG4CXX_DEBUG(logger_,
                "Cloud app certificate: " << cloud_properties.certificate);
  LOG4CXX_DEBUG(
      logger_,
      "Cloud app authentication token: " << cloud_properties.auth_token);
  LOG4CXX_DEBUG(
      logger_,
      "Cloud app transport type: " << cloud_properties.cloud_transport_type);
  LOG4CXX_DEBUG(logger_,
                "Cloud app hybrid app preference: "
                    << cloud_properties.hybrid_app_preference);

  auto const results = resolver_.resolve(host, port, ec);
  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_, "Could not resolve host/port: " << str_err);
    return TransportAdapter::FAIL;
  }

  // Make Connection to host IP Address over TCP
  if (cloud_properties.cloud_transport_type == "WSS") {
    boost::asio::connect(
        wss_.next_layer().next_layer(), results.begin(), results.end(), ec);
  } else {
    boost::asio::connect(ws_.next_layer(), results.begin(), results.end(), ec);
  }
  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_,
                  "Could not connect to websocket: " << host << ":" << port);
    LOG4CXX_ERROR(logger_, str_err);
    return TransportAdapter::FAIL;
  }

  if (cloud_properties.cloud_transport_type == "WSS") {
    AddCertificateAuthority(cloud_properties.certificate, ec);

    if (ec) {
      std::string str_err = "ErrorMessage: " + ec.message();
      LOG4CXX_ERROR(logger_,
                    "Failed to add certificate authority: "
                        << cloud_properties.certificate);
      LOG4CXX_ERROR(logger_, str_err);
      Shutdown();
      return TransportAdapter::FAIL;
    }

    // Perform SSL Handshake
    wss_.next_layer().handshake(ssl::stream_base::client, ec);

    if (ec) {
      std::string str_err = "ErrorMessage: " + ec.message();
      LOG4CXX_ERROR(logger_,
                    "Could not complete SSL Handshake failed with host/port: "
                        << host << ":" << port);
      LOG4CXX_ERROR(logger_, str_err);
      Shutdown();
      return TransportAdapter::FAIL;
    }
  }

  // Perform websocket handshake
  if (cloud_properties.cloud_transport_type == "WSS") {
    wss_.handshake(host, "/", ec);
  } else {
    ws_.handshake(host, "/", ec);
  }
  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_,
                  "Could not complete handshake with host/port: " << host << ":"
                                                                  << port);
    LOG4CXX_ERROR(logger_, str_err);
    return TransportAdapter::FAIL;
  }

  // Set the binary message write option
  if (cloud_properties.cloud_transport_type == "WSS") {
    wss_.binary(true);
  } else {
    ws_.binary(true);
  }
  write_thread_->start(threads::ThreadOptions());
  controller_->ConnectDone(device_uid_, app_handle_);

  // Start async read
  if (cloud_properties.cloud_transport_type == "WSS") {
    wss_.async_read(buffer_,
                    std::bind(&WebsocketClientConnection::OnRead,
                              this,
                              std::placeholders::_1,
                              std::placeholders::_2));
  } else {
    ws_.async_read(buffer_,
                   std::bind(&WebsocketClientConnection::OnRead,
                             this,
                             std::placeholders::_1,
                             std::placeholders::_2));
  }

  boost::asio::post(io_pool_, [&]() { ioc_.run(); });

  LOG4CXX_DEBUG(logger_,
                "Successfully started websocket connection @: " << host << ":"
                                                                << port);
  return TransportAdapter::OK;
}

void WebsocketClientConnection::Recv(boost::system::error_code ec) {
  if (shutdown_) {
    return;
  }

  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_, str_err);
    Shutdown();
    return;
  }
  if (cloud_properties.cloud_transport_type == "WSS") {
    wss_.async_read(buffer_,
                    std::bind(&WebsocketClientConnection::OnRead,
                              this,
                              std::placeholders::_1,
                              std::placeholders::_2));
  } else {
    ws_.async_read(buffer_,
                   std::bind(&WebsocketClientConnection::OnRead,
                             this,
                             std::placeholders::_1,
                             std::placeholders::_2));
  }
}

void WebsocketClientConnection::OnRead(boost::system::error_code ec,
                                       std::size_t bytes_transferred) {
  boost::ignore_unused(bytes_transferred);
  if (ec) {
    std::string str_err = "ErrorMessage: " + ec.message();
    LOG4CXX_ERROR(logger_, str_err);
    ws_.lowest_layer().close();
    ioc_.stop();
    Shutdown();
    return;
  }
  std::string data_str = boost::beast::buffers_to_string(buffer_.data());

  ssize_t size = (ssize_t)buffer_.size();
  const uint8_t* data = boost::asio::buffer_cast<const uint8_t*>(
      boost::beast::buffers_front(buffer_.data()));

  ::protocol_handler::RawMessagePtr frame(
      new protocol_handler::RawMessage(0, 0, data, size));

  controller_->DataReceiveDone(device_uid_, app_handle_, frame);

  buffer_.consume(buffer_.size());
  Recv(ec);
}

TransportAdapter::Error WebsocketClientConnection::SendData(
    ::protocol_handler::RawMessagePtr message) {
  LOG4CXX_AUTO_TRACE(logger_);
  sync_primitives::AutoLock auto_lock(frames_to_send_mutex_);
  message_queue_.push(message);
  return TransportAdapter::OK;
}

TransportAdapter::Error WebsocketClientConnection::Disconnect() {
  LOG4CXX_AUTO_TRACE(logger_);
  Shutdown();
  return TransportAdapter::OK;
}

void WebsocketClientConnection::Shutdown() {
  shutdown_ = true;

  if (thread_delegate_) {
    thread_delegate_->SetShutdown();
    write_thread_->join();
    delete thread_delegate_;
    thread_delegate_ = NULL;
    threads::DeleteThread(write_thread_);
    write_thread_ = NULL;
  }
  if (buffer_.size()) {
    buffer_.consume(buffer_.size());
  }
  controller_->DisconnectDone(device_uid_, app_handle_);
}

WebsocketClientConnection::LoopThreadDelegate::LoopThreadDelegate(
    MessageQueue<Message, AsyncQueue>* message_queue,
    WebsocketClientConnection* handler)
    : message_queue_(*message_queue), handler_(*handler), shutdown_(false) {}

void WebsocketClientConnection::LoopThreadDelegate::threadMain() {
  while (!message_queue_.IsShuttingDown() && !shutdown_) {
    DrainQueue();
    message_queue_.wait();
  }
  DrainQueue();
}

void WebsocketClientConnection::LoopThreadDelegate::exitThreadMain() {
  shutdown_ = true;
  if (!message_queue_.IsShuttingDown()) {
    message_queue_.Shutdown();
  }
}

void WebsocketClientConnection::LoopThreadDelegate::DrainQueue() {
  while (!message_queue_.empty()) {
    Message message_ptr;
    message_queue_.pop(message_ptr);
    if (!shutdown_) {
      boost::system::error_code ec;
      if (handler_.cloud_properties.cloud_transport_type == "WSS") {
        handler_.wss_.write(
            boost::asio::buffer(message_ptr->data(), message_ptr->data_size()));
      } else {
        handler_.ws_.write(
            boost::asio::buffer(message_ptr->data(), message_ptr->data_size()));
      }
      if (ec) {
        LOG4CXX_ERROR(logger_, "Error writing to websocket");
        handler_.controller_->DataSendFailed(handler_.device_uid_,
                                             handler_.app_handle_,
                                             message_ptr,
                                             DataSendError());
      }
    }
  }
}

void WebsocketClientConnection::LoopThreadDelegate::SetShutdown() {
  shutdown_ = true;
  if (!message_queue_.IsShuttingDown()) {
    message_queue_.Shutdown();
  }
}

}  // namespace transport_adapter
}  // namespace transport_manager
<|endoftext|>