<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 peer.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Peer Network test functions.
 */

#include <boost/test/unit_test.hpp>
#include <chrono>
#include <thread>
#include <libp2p/Host.h>
#include <test/TestHelper.h>

using namespace std;
using namespace dev;
using namespace dev::p2p;

struct P2PFixture
{
	P2PFixture() { dev::p2p::NodeIPEndpoint::test_allowLocal = true; }
	~P2PFixture() { dev::p2p::NodeIPEndpoint::test_allowLocal = false; }
};

BOOST_FIXTURE_TEST_SUITE(p2p, P2PFixture)

BOOST_AUTO_TEST_CASE(host)
{
	if (test::Options::get().nonetwork)
		return;

	VerbosityHolder sentinel(10);

	NetworkPreferences host1prefs("127.0.0.1", 30301, false);
	NetworkPreferences host2prefs("127.0.0.1", 30302, false);

	Host host1("Test", host1prefs);
	host1.start();

	Host host2("Test", host2prefs);
	auto node2 = host2.id();
	host2.start();

	while (!host2.haveNetwork())
		this_thread::sleep_for(chrono::milliseconds(20));
	host1.addNode(node2, NodeIPEndpoint(bi::address::from_string("127.0.0.1"), host2prefs.listenPort, host2prefs.listenPort));

	this_thread::sleep_for(chrono::seconds(3));

	auto host1peerCount = host1.peerCount();
	auto host2peerCount = host2.peerCount();
	BOOST_REQUIRE_EQUAL(host1peerCount, 1);
	BOOST_REQUIRE_EQUAL(host2peerCount, 1);
}

BOOST_AUTO_TEST_CASE(networkConfig)
{
	if (test::Options::get().nonetwork)
		return;

	Host save("Test", NetworkPreferences(false));
	bytes store(save.saveNetwork());

	Host restore("Test", NetworkPreferences(false), bytesConstRef(&store));
	BOOST_REQUIRE(save.id() == restore.id());
}

BOOST_AUTO_TEST_CASE(saveNodes)
{
	if (test::Options::get().nonetwork)
		return;

	VerbosityHolder reduceVerbosity(2);

	std::list<Host*> hosts;
	unsigned const c_step = 10;
	unsigned const c_nodes = 6;
	unsigned const c_peers = c_nodes - 1;

	for (unsigned i = 0; i < c_nodes; ++i)
	{
		Host* h = new Host("Test", NetworkPreferences("127.0.0.1", 30300 + i, false));
		h->setIdealPeerCount(10);
		// starting host is required so listenport is available
		h->start();
		while (!h->haveNetwork())
			this_thread::sleep_for(chrono::milliseconds(c_step));
		hosts.push_back(h);
	}

	Host& host = *hosts.front();
	for (auto const& h: hosts)
		host.addNode(h->id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), h->listenPort(), h->listenPort()));

	for (unsigned i = 0; i < c_peers * 1000 && host.peerCount() < c_peers; i += c_step)
		this_thread::sleep_for(chrono::milliseconds(c_step));

	Host& host2 = *hosts.back();
	for (auto const& h: hosts)
		host2.addNode(h->id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), h->listenPort(), h->listenPort()));

	for (unsigned i = 0; i < c_peers * 1000 && host2.peerCount() < c_peers; i += c_step)
		this_thread::sleep_for(chrono::milliseconds(c_step));

	BOOST_CHECK_EQUAL(host.peerCount(), c_peers);
	BOOST_CHECK_EQUAL(host2.peerCount(), c_peers);

	bytes firstHostNetwork(host.saveNetwork());
	bytes secondHostNetwork(host.saveNetwork());
	BOOST_REQUIRE_EQUAL(sha3(firstHostNetwork), sha3(secondHostNetwork));

	RLP r(firstHostNetwork);
	BOOST_REQUIRE(r.itemCount() == 3);
	BOOST_REQUIRE(r[0].toInt<unsigned>() == dev::p2p::c_protocolVersion);
	BOOST_REQUIRE_EQUAL(r[1].toBytes().size(), 32); // secret
	BOOST_REQUIRE(r[2].itemCount() >= c_nodes);

	for (auto i: r[2])
	{
		BOOST_REQUIRE(i.itemCount() == 4 || i.itemCount() == 11);
		BOOST_REQUIRE(i[0].size() == 4 || i[0].size() == 16);
	}

	for (auto host: hosts)
		delete host;
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_FIXTURE_TEST_SUITE(p2pPeer, P2PFixture)

BOOST_AUTO_TEST_CASE(requirePeer)
{
	if (test::Options::get().nonetwork)
		return;

	VerbosityHolder reduceVerbosity(10);

	const char* const localhost = "127.0.0.1";
	NetworkPreferences prefs1(localhost, 30301, false);
	NetworkPreferences prefs2(localhost, 30302, false);
	Host host1("Test", prefs1);
	host1.start();

	Host host2("Test", prefs2);
	host2.start();

	auto node2 = host2.id();
	host1.requirePeer(node2, NodeIPEndpoint(bi::address::from_string(localhost), prefs2.listenPort, prefs2.listenPort));

	this_thread::sleep_for(chrono::seconds(3));

	auto host1peerCount = host1.peerCount();
	auto host2peerCount = host2.peerCount();
	BOOST_REQUIRE_EQUAL(host1peerCount, 1);
	BOOST_REQUIRE_EQUAL(host2peerCount, 1);

	PeerSessionInfos sis1 = host1.peerSessionInfo();
	PeerSessionInfos sis2 = host2.peerSessionInfo();

	BOOST_REQUIRE_EQUAL(sis1.size(), 1);
	BOOST_REQUIRE_EQUAL(sis2.size(), 1);

	Peers peers1 = host1.getPeers();
	Peers peers2 = host2.getPeers();
	BOOST_REQUIRE_EQUAL(peers1.size(), 1);
	BOOST_REQUIRE_EQUAL(peers2.size(), 1);

	DisconnectReason disconnect1 = peers1[0].lastDisconnect();
	DisconnectReason disconnect2 = peers2[0].lastDisconnect();
	BOOST_REQUIRE_EQUAL(disconnect1, disconnect2);

	host1.relinquishPeer(node2);

	this_thread::sleep_for(chrono::seconds(1));

	host1peerCount = host1.peerCount();
	host2peerCount = host2.peerCount();
	BOOST_REQUIRE_EQUAL(host1peerCount, 1);
	BOOST_REQUIRE_EQUAL(host2peerCount, 1);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(peerTypes)

BOOST_AUTO_TEST_CASE(emptySharedPeer)
{
	if (test::Options::get().nonetwork)
		return;

	shared_ptr<Peer> p;
	BOOST_REQUIRE(!p);

	std::map<NodeId, std::shared_ptr<Peer>> peers;
	p = peers[NodeId()];
	BOOST_REQUIRE(!p);

	p.reset(new Peer(UnspecifiedNode));
	BOOST_REQUIRE(!p->id);
	BOOST_REQUIRE(!*p);

	p.reset(new Peer(Node(NodeId(EmptySHA3), UnspecifiedNodeIPEndpoint)));
	BOOST_REQUIRE(!(!*p));
	BOOST_REQUIRE(*p);
	BOOST_REQUIRE(p);
}

BOOST_AUTO_TEST_SUITE_END()

int peerTest(int argc, char** argv)
{
	Public remoteAlias;
	short listenPort = 30303;
	string remoteHost;
	short remotePort = 30303;

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if (arg == "-l" && i + 1 < argc)
			listenPort = (short)atoi(argv[++i]);
		else if (arg == "-r" && i + 1 < argc)
			remoteHost = argv[++i];
		else if (arg == "-p" && i + 1 < argc)
			remotePort = (short)atoi(argv[++i]);
		else if (arg == "-ra" && i + 1 < argc)
			remoteAlias = Public(dev::fromHex(argv[++i]));
		else
			remoteHost = argv[i];
	}

	Host ph("Test", NetworkPreferences(listenPort));

	if (!remoteHost.empty() && !remoteAlias)
		ph.addNode(remoteAlias, NodeIPEndpoint(bi::address::from_string(remoteHost), remotePort, remotePort));

	this_thread::sleep_for(chrono::milliseconds(200));

	return 0;
}

<commit_msg>test fixed<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 peer.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Peer Network test functions.
 */

#include <boost/test/unit_test.hpp>
#include <chrono>
#include <thread>
#include <libp2p/Host.h>
#include <test/TestHelper.h>

using namespace std;
using namespace dev;
using namespace dev::p2p;

struct P2PFixture
{
	P2PFixture() { dev::p2p::NodeIPEndpoint::test_allowLocal = true; }
	~P2PFixture() { dev::p2p::NodeIPEndpoint::test_allowLocal = false; }
};

BOOST_FIXTURE_TEST_SUITE(p2p, P2PFixture)

BOOST_AUTO_TEST_CASE(host)
{
	if (test::Options::get().nonetwork)
		return;

	VerbosityHolder setTemporaryLevel(10);
	NetworkPreferences host1prefs("127.0.0.1", 30301, false);
	NetworkPreferences host2prefs("127.0.0.1", 30302, false);
	Host host1("Test", host1prefs);
	Host host2("Test", host2prefs);
	host1.start();
	host2.start();
	auto node2 = host2.id();
	int const step = 10;

	for (int i = 0; i < 3000 && (!host1.isStarted() || !host2.isStarted()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(host1.isStarted() && host2.isStarted());
	host1.addNode(node2, NodeIPEndpoint(bi::address::from_string("127.0.0.1"), host2prefs.listenPort, host2prefs.listenPort));

	for (int i = 0; i < 3000 && (!host1.haveNetwork() || !host2.haveNetwork()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE(host1.haveNetwork() && host2.haveNetwork());

	for (int i = 0; i < 3000 && (!host1.peerCount() || !host2.peerCount()); i += step)
		this_thread::sleep_for(chrono::milliseconds(step));

	BOOST_REQUIRE_EQUAL(host1.peerCount(), 1);
	BOOST_REQUIRE_EQUAL(host2.peerCount(), 1);
}

BOOST_AUTO_TEST_CASE(networkConfig)
{
	if (test::Options::get().nonetwork)
		return;

	Host save("Test", NetworkPreferences(false));
	bytes store(save.saveNetwork());

	Host restore("Test", NetworkPreferences(false), bytesConstRef(&store));
	BOOST_REQUIRE(save.id() == restore.id());
}

BOOST_AUTO_TEST_CASE(saveNodes)
{
	if (test::Options::get().nonetwork)
		return;

	VerbosityHolder reduceVerbosity(2);

	std::list<Host*> hosts;
	unsigned const c_step = 10;
	unsigned const c_nodes = 6;
	unsigned const c_peers = c_nodes - 1;

	for (unsigned i = 0; i < c_nodes; ++i)
	{
		Host* h = new Host("Test", NetworkPreferences("127.0.0.1", 30300 + i, false));
		h->setIdealPeerCount(10);
		// starting host is required so listenport is available
		h->start();
		while (!h->haveNetwork())
			this_thread::sleep_for(chrono::milliseconds(c_step));
		hosts.push_back(h);
	}

	Host& host = *hosts.front();
	for (auto const& h: hosts)
		host.addNode(h->id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), h->listenPort(), h->listenPort()));

	for (unsigned i = 0; i < c_peers * 1000 && host.peerCount() < c_peers; i += c_step)
		this_thread::sleep_for(chrono::milliseconds(c_step));

	Host& host2 = *hosts.back();
	for (auto const& h: hosts)
		host2.addNode(h->id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), h->listenPort(), h->listenPort()));

	for (unsigned i = 0; i < c_peers * 1000 && host2.peerCount() < c_peers; i += c_step)
		this_thread::sleep_for(chrono::milliseconds(c_step));

	BOOST_CHECK_EQUAL(host.peerCount(), c_peers);
	BOOST_CHECK_EQUAL(host2.peerCount(), c_peers);

	bytes firstHostNetwork(host.saveNetwork());
	bytes secondHostNetwork(host.saveNetwork());
	BOOST_REQUIRE_EQUAL(sha3(firstHostNetwork), sha3(secondHostNetwork));

	RLP r(firstHostNetwork);
	BOOST_REQUIRE(r.itemCount() == 3);
	BOOST_REQUIRE(r[0].toInt<unsigned>() == dev::p2p::c_protocolVersion);
	BOOST_REQUIRE_EQUAL(r[1].toBytes().size(), 32); // secret
	BOOST_REQUIRE(r[2].itemCount() >= c_nodes);

	for (auto i: r[2])
	{
		BOOST_REQUIRE(i.itemCount() == 4 || i.itemCount() == 11);
		BOOST_REQUIRE(i[0].size() == 4 || i[0].size() == 16);
	}

	for (auto host: hosts)
		delete host;
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_FIXTURE_TEST_SUITE(p2pPeer, P2PFixture)

BOOST_AUTO_TEST_CASE(requirePeer)
{
	if (test::Options::get().nonetwork)
		return;

	VerbosityHolder reduceVerbosity(10);

	const char* const localhost = "127.0.0.1";
	NetworkPreferences prefs1(localhost, 30301, false);
	NetworkPreferences prefs2(localhost, 30302, false);
	Host host1("Test", prefs1);
	host1.start();

	Host host2("Test", prefs2);
	host2.start();

	auto node2 = host2.id();
	host1.requirePeer(node2, NodeIPEndpoint(bi::address::from_string(localhost), prefs2.listenPort, prefs2.listenPort));

	this_thread::sleep_for(chrono::seconds(3));

	auto host1peerCount = host1.peerCount();
	auto host2peerCount = host2.peerCount();
	BOOST_REQUIRE_EQUAL(host1peerCount, 1);
	BOOST_REQUIRE_EQUAL(host2peerCount, 1);

	PeerSessionInfos sis1 = host1.peerSessionInfo();
	PeerSessionInfos sis2 = host2.peerSessionInfo();

	BOOST_REQUIRE_EQUAL(sis1.size(), 1);
	BOOST_REQUIRE_EQUAL(sis2.size(), 1);

	Peers peers1 = host1.getPeers();
	Peers peers2 = host2.getPeers();
	BOOST_REQUIRE_EQUAL(peers1.size(), 1);
	BOOST_REQUIRE_EQUAL(peers2.size(), 1);

	DisconnectReason disconnect1 = peers1[0].lastDisconnect();
	DisconnectReason disconnect2 = peers2[0].lastDisconnect();
	BOOST_REQUIRE_EQUAL(disconnect1, disconnect2);

	host1.relinquishPeer(node2);

	this_thread::sleep_for(chrono::seconds(1));

	host1peerCount = host1.peerCount();
	host2peerCount = host2.peerCount();
	BOOST_REQUIRE_EQUAL(host1peerCount, 1);
	BOOST_REQUIRE_EQUAL(host2peerCount, 1);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(peerTypes)

BOOST_AUTO_TEST_CASE(emptySharedPeer)
{
	if (test::Options::get().nonetwork)
		return;

	shared_ptr<Peer> p;
	BOOST_REQUIRE(!p);

	std::map<NodeId, std::shared_ptr<Peer>> peers;
	p = peers[NodeId()];
	BOOST_REQUIRE(!p);

	p.reset(new Peer(UnspecifiedNode));
	BOOST_REQUIRE(!p->id);
	BOOST_REQUIRE(!*p);

	p.reset(new Peer(Node(NodeId(EmptySHA3), UnspecifiedNodeIPEndpoint)));
	BOOST_REQUIRE(!(!*p));
	BOOST_REQUIRE(*p);
	BOOST_REQUIRE(p);
}

BOOST_AUTO_TEST_SUITE_END()

int peerTest(int argc, char** argv)
{
	Public remoteAlias;
	short listenPort = 30303;
	string remoteHost;
	short remotePort = 30303;

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if (arg == "-l" && i + 1 < argc)
			listenPort = (short)atoi(argv[++i]);
		else if (arg == "-r" && i + 1 < argc)
			remoteHost = argv[++i];
		else if (arg == "-p" && i + 1 < argc)
			remotePort = (short)atoi(argv[++i]);
		else if (arg == "-ra" && i + 1 < argc)
			remoteAlias = Public(dev::fromHex(argv[++i]));
		else
			remoteHost = argv[i];
	}

	Host ph("Test", NetworkPreferences(listenPort));

	if (!remoteHost.empty() && !remoteAlias)
		ph.addNode(remoteAlias, NodeIPEndpoint(bi::address::from_string(remoteHost), remotePort, remotePort));

	this_thread::sleep_for(chrono::milliseconds(200));

	return 0;
}

<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

// work around "uninitialized" warnings and give that option some testing
#define EIGEN_INITIALIZE_MATRICES_BY_ZERO

#ifndef EIGEN_NO_STATIC_ASSERT
#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
#endif

// #ifndef EIGEN_DONT_VECTORIZE
// #define EIGEN_DONT_VECTORIZE // SSE intrinsics aren't designed to allow mixing types
// #endif

#include "main.h"

using namespace std;

template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
{
  typedef std::complex<float>   CF;
  typedef std::complex<double>  CD;
  typedef Matrix<float, SizeAtCompileType, SizeAtCompileType> Mat_f;
  typedef Matrix<double, SizeAtCompileType, SizeAtCompileType> Mat_d;
  typedef Matrix<std::complex<float>, SizeAtCompileType, SizeAtCompileType> Mat_cf;
  typedef Matrix<std::complex<double>, SizeAtCompileType, SizeAtCompileType> Mat_cd;
  typedef Matrix<float, SizeAtCompileType, 1> Vec_f;
  typedef Matrix<double, SizeAtCompileType, 1> Vec_d;
  typedef Matrix<std::complex<float>, SizeAtCompileType, 1> Vec_cf;
  typedef Matrix<std::complex<double>, SizeAtCompileType, 1> Vec_cd;

  Mat_f mf    = Mat_f::Random(size,size);
  Mat_d md    = mf.template cast<double>();
  Mat_cf mcf  = Mat_cf::Random(size,size);
  Mat_cd mcd  = mcf.template cast<complex<double> >();
  Vec_f vf    = Vec_f::Random(size,1);
  Vec_d vd    = vf.template cast<double>();
  Vec_cf vcf  = Vec_cf::Random(size,1);
  Vec_cd vcd  = vcf.template cast<complex<double> >();
  float           sf  = internal::random<float>();
  double          sd  = internal::random<double>();
  complex<float>  scf = internal::random<complex<float> >();
  complex<double> scd = internal::random<complex<double> >();

  mf+mf;
  VERIFY_RAISES_ASSERT(mf+md);
  VERIFY_RAISES_ASSERT(mf+mcf);
  VERIFY_RAISES_ASSERT(vf=vd);
  VERIFY_RAISES_ASSERT(vf+=vd);
  VERIFY_RAISES_ASSERT(mcd=md);

  // check scalar products
  VERIFY_IS_APPROX(vcf * sf , vcf * complex<float>(sf));
  VERIFY_IS_APPROX(sd * vcd, complex<double>(sd) * vcd);
  VERIFY_IS_APPROX(vf * scf , vf.template cast<complex<float> >() * scf);
  VERIFY_IS_APPROX(scd * vd, scd * vd.template cast<complex<double> >());

  // check dot product
  vf.dot(vf);
#if 0 // we get other compilation errors here than just static asserts
  VERIFY_RAISES_ASSERT(vd.dot(vf));
#endif
  VERIFY_IS_APPROX(vcf.dot(vf), vcf.dot(vf.template cast<complex<float> >()));

  // check diagonal product
  VERIFY_IS_APPROX(vf.asDiagonal() * mcf, vf.template cast<complex<float> >().asDiagonal() * mcf);
  VERIFY_IS_APPROX(vcd.asDiagonal() * md, vcd.asDiagonal() * md.template cast<complex<double> >());
  VERIFY_IS_APPROX(mcf * vf.asDiagonal(), mcf * vf.template cast<complex<float> >().asDiagonal());
  VERIFY_IS_APPROX(md * vcd.asDiagonal(), md.template cast<complex<double> >() * vcd.asDiagonal());
//   vd.asDiagonal() * mf;    // does not even compile
//   vcd.asDiagonal() * mf;   // does not even compile

  // check inner product
  VERIFY_IS_APPROX((vf.transpose() * vcf).value(), (vf.template cast<complex<float> >().transpose() * vcf).value());

  // check outer product
  VERIFY_IS_APPROX((vf * vcf.transpose()).eval(), (vf.template cast<complex<float> >() * vcf.transpose()).eval());

  // coeff wise product

  VERIFY_IS_APPROX((vf * vcf.transpose()).eval(), (vf.template cast<complex<float> >() * vcf.transpose()).eval());

  Mat_cd mcd2 = mcd;
  VERIFY_IS_APPROX(mcd.array() *= md.array(), mcd2.array() *= md.array().template cast<std::complex<double> >());

  // check matrix-matrix products

  VERIFY_IS_APPROX(sd*md*mcd, (sd*md).template cast<CD>().eval()*mcd);
  VERIFY_IS_APPROX(sd*mcd*md, sd*mcd*md.template cast<CD>());
  VERIFY_IS_APPROX(scd*md*mcd, scd*md.template cast<CD>().eval()*mcd);
  VERIFY_IS_APPROX(scd*mcd*md, scd*mcd*md.template cast<CD>());

  VERIFY_IS_APPROX(sf*mf*mcf, sf*mf.template cast<CF>()*mcf);
  VERIFY_IS_APPROX(sf*mcf*mf, sf*mcf*mf.template cast<CF>());
  VERIFY_IS_APPROX(scf*mf*mcf, scf*mf.template cast<CF>()*mcf);
  VERIFY_IS_APPROX(scf*mcf*mf, scf*mcf*mf.template cast<CF>());

  VERIFY_IS_APPROX(sf*mf*vcf, (sf*mf).template cast<CF>().eval()*vcf);
  VERIFY_IS_APPROX(scf*mf*vcf,(scf*mf.template cast<CF>()).eval()*vcf);
  VERIFY_IS_APPROX(sf*mcf*vf, sf*mcf*vf.template cast<CF>());
  VERIFY_IS_APPROX(scf*mcf*vf,scf*mcf*vf.template cast<CF>());

  VERIFY_IS_APPROX(sf*vcf.adjoint()*mf,  sf*vcf.adjoint()*mf.template cast<CF>().eval());
  VERIFY_IS_APPROX(scf*vcf.adjoint()*mf, scf*vcf.adjoint()*mf.template cast<CF>().eval());
  VERIFY_IS_APPROX(sf*vf.adjoint()*mcf,  sf*vf.adjoint().template cast<CF>().eval()*mcf);
  VERIFY_IS_APPROX(scf*vf.adjoint()*mcf, scf*vf.adjoint().template cast<CF>().eval()*mcf);

  VERIFY_IS_APPROX(sd*md*vcd, (sd*md).template cast<CD>().eval()*vcd);
  VERIFY_IS_APPROX(scd*md*vcd,(scd*md.template cast<CD>()).eval()*vcd);
  VERIFY_IS_APPROX(sd*mcd*vd, sd*mcd*vd.template cast<CD>().eval());
  VERIFY_IS_APPROX(scd*mcd*vd,scd*mcd*vd.template cast<CD>().eval());

  VERIFY_IS_APPROX(sd*vcd.adjoint()*md,  sd*vcd.adjoint()*md.template cast<CD>().eval());
  VERIFY_IS_APPROX(scd*vcd.adjoint()*md, scd*vcd.adjoint()*md.template cast<CD>().eval());
  VERIFY_IS_APPROX(sd*vd.adjoint()*mcd,  sd*vd.adjoint().template cast<CD>().eval()*mcd);
  VERIFY_IS_APPROX(scd*vd.adjoint()*mcd, scd*vd.adjoint().template cast<CD>().eval()*mcd);
}

void test_mixingtypes()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1(mixingtypes<3>());
    CALL_SUBTEST_2(mixingtypes<4>());
    CALL_SUBTEST_3(mixingtypes<Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)));
  }
}
<commit_msg>Extend mixingtype unit test to check transposed cases.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

// work around "uninitialized" warnings and give that option some testing
#define EIGEN_INITIALIZE_MATRICES_BY_ZERO

#ifndef EIGEN_NO_STATIC_ASSERT
#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
#endif

// #ifndef EIGEN_DONT_VECTORIZE
// #define EIGEN_DONT_VECTORIZE // SSE intrinsics aren't designed to allow mixing types
// #endif

#include "main.h"

using namespace std;

template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
{
  typedef std::complex<float>   CF;
  typedef std::complex<double>  CD;
  typedef Matrix<float, SizeAtCompileType, SizeAtCompileType> Mat_f;
  typedef Matrix<double, SizeAtCompileType, SizeAtCompileType> Mat_d;
  typedef Matrix<std::complex<float>, SizeAtCompileType, SizeAtCompileType> Mat_cf;
  typedef Matrix<std::complex<double>, SizeAtCompileType, SizeAtCompileType> Mat_cd;
  typedef Matrix<float, SizeAtCompileType, 1> Vec_f;
  typedef Matrix<double, SizeAtCompileType, 1> Vec_d;
  typedef Matrix<std::complex<float>, SizeAtCompileType, 1> Vec_cf;
  typedef Matrix<std::complex<double>, SizeAtCompileType, 1> Vec_cd;

  Mat_f mf    = Mat_f::Random(size,size);
  Mat_d md    = mf.template cast<double>();
  Mat_cf mcf  = Mat_cf::Random(size,size);
  Mat_cd mcd  = mcf.template cast<complex<double> >();
  Vec_f vf    = Vec_f::Random(size,1);
  Vec_d vd    = vf.template cast<double>();
  Vec_cf vcf  = Vec_cf::Random(size,1);
  Vec_cd vcd  = vcf.template cast<complex<double> >();
  float           sf  = internal::random<float>();
  double          sd  = internal::random<double>();
  complex<float>  scf = internal::random<complex<float> >();
  complex<double> scd = internal::random<complex<double> >();

  mf+mf;
  VERIFY_RAISES_ASSERT(mf+md);
  VERIFY_RAISES_ASSERT(mf+mcf);
  VERIFY_RAISES_ASSERT(vf=vd);
  VERIFY_RAISES_ASSERT(vf+=vd);
  VERIFY_RAISES_ASSERT(mcd=md);

  // check scalar products
  VERIFY_IS_APPROX(vcf * sf , vcf * complex<float>(sf));
  VERIFY_IS_APPROX(sd * vcd, complex<double>(sd) * vcd);
  VERIFY_IS_APPROX(vf * scf , vf.template cast<complex<float> >() * scf);
  VERIFY_IS_APPROX(scd * vd, scd * vd.template cast<complex<double> >());

  // check dot product
  vf.dot(vf);
#if 0 // we get other compilation errors here than just static asserts
  VERIFY_RAISES_ASSERT(vd.dot(vf));
#endif
  VERIFY_IS_APPROX(vcf.dot(vf), vcf.dot(vf.template cast<complex<float> >()));

  // check diagonal product
  VERIFY_IS_APPROX(vf.asDiagonal() * mcf, vf.template cast<complex<float> >().asDiagonal() * mcf);
  VERIFY_IS_APPROX(vcd.asDiagonal() * md, vcd.asDiagonal() * md.template cast<complex<double> >());
  VERIFY_IS_APPROX(mcf * vf.asDiagonal(), mcf * vf.template cast<complex<float> >().asDiagonal());
  VERIFY_IS_APPROX(md * vcd.asDiagonal(), md.template cast<complex<double> >() * vcd.asDiagonal());
//   vd.asDiagonal() * mf;    // does not even compile
//   vcd.asDiagonal() * mf;   // does not even compile

  // check inner product
  VERIFY_IS_APPROX((vf.transpose() * vcf).value(), (vf.template cast<complex<float> >().transpose() * vcf).value());

  // check outer product
  VERIFY_IS_APPROX((vf * vcf.transpose()).eval(), (vf.template cast<complex<float> >() * vcf.transpose()).eval());

  // coeff wise product

  VERIFY_IS_APPROX((vf * vcf.transpose()).eval(), (vf.template cast<complex<float> >() * vcf.transpose()).eval());

  Mat_cd mcd2 = mcd;
  VERIFY_IS_APPROX(mcd.array() *= md.array(), mcd2.array() *= md.array().template cast<std::complex<double> >());

  // check matrix-matrix products

  VERIFY_IS_APPROX(sd*md*mcd, (sd*md).template cast<CD>().eval()*mcd);
  VERIFY_IS_APPROX(sd*mcd*md, sd*mcd*md.template cast<CD>());
  VERIFY_IS_APPROX(scd*md*mcd, scd*md.template cast<CD>().eval()*mcd);
  VERIFY_IS_APPROX(scd*mcd*md, scd*mcd*md.template cast<CD>());

  VERIFY_IS_APPROX(sf*mf*mcf, sf*mf.template cast<CF>()*mcf);
  VERIFY_IS_APPROX(sf*mcf*mf, sf*mcf*mf.template cast<CF>());
  VERIFY_IS_APPROX(scf*mf*mcf, scf*mf.template cast<CF>()*mcf);
  VERIFY_IS_APPROX(scf*mcf*mf, scf*mcf*mf.template cast<CF>());

  VERIFY_IS_APPROX(sd*md.adjoint()*mcd, (sd*md).template cast<CD>().eval().adjoint()*mcd);
  VERIFY_IS_APPROX(sd*mcd.adjoint()*md, sd*mcd.adjoint()*md.template cast<CD>());
  VERIFY_IS_APPROX(sd*md.adjoint()*mcd.adjoint(), (sd*md).template cast<CD>().eval().adjoint()*mcd.adjoint());
  VERIFY_IS_APPROX(sd*mcd.adjoint()*md.adjoint(), sd*mcd.adjoint()*md.template cast<CD>().adjoint());
  VERIFY_IS_APPROX(sd*md*mcd.adjoint(), (sd*md).template cast<CD>().eval()*mcd.adjoint());
  VERIFY_IS_APPROX(sd*mcd*md.adjoint(), sd*mcd*md.template cast<CD>().adjoint());

  VERIFY_IS_APPROX(sf*mf.adjoint()*mcf, (sf*mf).template cast<CF>().eval().adjoint()*mcf);
  VERIFY_IS_APPROX(sf*mcf.adjoint()*mf, sf*mcf.adjoint()*mf.template cast<CF>());
  VERIFY_IS_APPROX(sf*mf.adjoint()*mcf.adjoint(), (sf*mf).template cast<CF>().eval().adjoint()*mcf.adjoint());
  VERIFY_IS_APPROX(sf*mcf.adjoint()*mf.adjoint(), sf*mcf.adjoint()*mf.template cast<CF>().adjoint());
  VERIFY_IS_APPROX(sf*mf*mcf.adjoint(), (sf*mf).template cast<CF>().eval()*mcf.adjoint());
  VERIFY_IS_APPROX(sf*mcf*mf.adjoint(), sf*mcf*mf.template cast<CF>().adjoint());

  VERIFY_IS_APPROX(sf*mf*vcf, (sf*mf).template cast<CF>().eval()*vcf);
  VERIFY_IS_APPROX(scf*mf*vcf,(scf*mf.template cast<CF>()).eval()*vcf);
  VERIFY_IS_APPROX(sf*mcf*vf, sf*mcf*vf.template cast<CF>());
  VERIFY_IS_APPROX(scf*mcf*vf,scf*mcf*vf.template cast<CF>());

  VERIFY_IS_APPROX(sf*vcf.adjoint()*mf,  sf*vcf.adjoint()*mf.template cast<CF>().eval());
  VERIFY_IS_APPROX(scf*vcf.adjoint()*mf, scf*vcf.adjoint()*mf.template cast<CF>().eval());
  VERIFY_IS_APPROX(sf*vf.adjoint()*mcf,  sf*vf.adjoint().template cast<CF>().eval()*mcf);
  VERIFY_IS_APPROX(scf*vf.adjoint()*mcf, scf*vf.adjoint().template cast<CF>().eval()*mcf);

  VERIFY_IS_APPROX(sd*md*vcd, (sd*md).template cast<CD>().eval()*vcd);
  VERIFY_IS_APPROX(scd*md*vcd,(scd*md.template cast<CD>()).eval()*vcd);
  VERIFY_IS_APPROX(sd*mcd*vd, sd*mcd*vd.template cast<CD>().eval());
  VERIFY_IS_APPROX(scd*mcd*vd,scd*mcd*vd.template cast<CD>().eval());

  VERIFY_IS_APPROX(sd*vcd.adjoint()*md,  sd*vcd.adjoint()*md.template cast<CD>().eval());
  VERIFY_IS_APPROX(scd*vcd.adjoint()*md, scd*vcd.adjoint()*md.template cast<CD>().eval());
  VERIFY_IS_APPROX(sd*vd.adjoint()*mcd,  sd*vd.adjoint().template cast<CD>().eval()*mcd);
  VERIFY_IS_APPROX(scd*vd.adjoint()*mcd, scd*vd.adjoint().template cast<CD>().eval()*mcd);
}

void test_mixingtypes()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1(mixingtypes<3>());
    CALL_SUBTEST_2(mixingtypes<4>());
    CALL_SUBTEST_3(mixingtypes<Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)));
  }
}
<|endoftext|>


<commit_before>/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * AVR Software Framework (ASF).
 */

extern "C" {
	#include "led.h"
	#include "delay.h"
	#include "print_util.h"
	#include "central_data.h"
	#include "boardsupport.h"
	#include "tasks.h"
	#include "mavlink_telemetry.h"
	#include "piezo_speaker.h"

	#include "gpio.h"
	#include "spi.h"
	#include "sd_spi.h"

	#include "FatFs/ff.h"
	#include "FatFs/diskio.h"
}

central_data_t *central_data;

void initialisation()
{
	central_data = central_data_get_pointer_to_struct();
	boardsupport_init(central_data);
	central_data_init();

	mavlink_telemetry_init();
	onboard_parameters_read_parameters_from_flashc(&central_data->mavlink_communication.onboard_parameters);

	LED_On(LED1);

	piezo_speaker_startup_melody();

	print_util_dbg_print("OK. Starting up.\r");

	//sd_spi_test();

	central_data->state.mav_state = MAV_STATE_STANDBY;

	central_data->imu.calibration_level = OFF;
}

int main (void)
{
	initialisation();
	tasks_create_tasks();

	while (1 == 1)
	{
		scheduler_update(&central_data->scheduler);
	}

	return 0;
}<commit_msg>FatFs via diskio test functions<commit_after>/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * AVR Software Framework (ASF).
 */

extern "C" {
	#include "led.h"
	#include "delay.h"
	#include "print_util.h"
	#include "central_data.h"
	#include "boardsupport.h"
	#include "tasks.h"
	#include "mavlink_telemetry.h"
	#include "piezo_speaker.h"

	#include "gpio.h"
	#include "spi.h"
	#include "sd_spi.h"

	#include "FatFs/ff.h"
	#include "FatFs/diskio.h"
}

central_data_t *central_data;

void test_sd_spi()
{
	char write_data[] = "0123456789xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxedcba";
	 //"0123456789abcde";
	char buffer[1025];

	while (!sd_spi_mem_check())
	{
		print_util_dbg_print("No card detected yet!\r");
		delay_ms(15);
	}

	print_util_dbg_print("\rCard detected!");

	delay_ms(500);
	if(sd_spi_write_given_sector_from_ram((void*)&write_data,2,2))
	{
		print_util_dbg_print("Write in sector 1\r");
	}

	delay_ms(500);
	if(sd_spi_write_given_sector_from_ram((void*)&write_data,5,2))
	{
		print_util_dbg_print("Write in sector 5\r");
	}

	delay_ms(500);
	if (sd_spi_read_given_sector_to_ram((void*)&buffer,1,2))
	{
		print_util_dbg_print("Read in sector 1");
		print_util_dbg_print_num(sizeof(write_data),10);
		print_util_dbg_print("\r");
		for (uint16_t i = 0;i<sizeof(write_data); i++)
		{
			print_util_dbg_print_num((U8)*(buffer + i), 10);
			delay_ms(25);
		}
	}
	else
	{
		print_util_dbg_print("Read error in sector 1\r");
	}

	delay_ms(500);
	if (sd_spi_read_given_sector_to_ram((void*)&buffer,5,2))
	{
		print_util_dbg_print("Read in sector 5, size of ");
		print_util_dbg_print_num(sizeof(write_data),10);
		print_util_dbg_print("\r");
		for (uint16_t i = 0;i<sizeof(write_data); i++)
		{
			print_util_dbg_print_num((U8)*(buffer + i), 10);
			delay_ms(25);
		}
	}
	else
	{
		print_util_dbg_print("Read error in sector 5\r");
	}

	//delay_ms(500);
	//if (sd_spi_read_sector_to_ram_pcda((void*)&buffer,1,1))
	//{
		//print_util_dbg_print("Read pcda in sector 1");
		//print_util_dbg_print_num(sizeof(write_data),10);
		//print_util_dbg_print("\r");
		//for (uint16_t i = 0;i<sizeof(write_data); i++)
		//{
			//print_util_dbg_print_num((U8)*(buffer + i), 10);
			//delay_ms(25);
		//}
	//}
	//else
	//{
		//print_util_dbg_print("Read pcda error in sector 1\r");
	//}
	//
	//delay_ms(500);
	//if (sd_spi_read_sector_to_ram_pcda((void*)&buffer,5,1))
	//{
		//print_util_dbg_print("Read pcda in sector 5");
		//print_util_dbg_print_num(sizeof(write_data),10);
		//print_util_dbg_print("\r");
		//for (uint16_t i = 0;i<sizeof(write_data); i++)
		//{
			//print_util_dbg_print_num((U8)*(buffer + i), 10);
			//delay_ms(25);
		//}
	//}
	//else
	//{
		//print_util_dbg_print("Read pcda error in sector 5\r");
	//}

	print_util_dbg_print("End test\r");
	delay_ms(25);
}

FRESULT open_append (
FIL* fp,            /* [OUT] File object to create */
const char* path    /* [IN]  File name to be opened */
)
{
	FRESULT fr;

	/* Opens an existing file. If not exist, creates a new file. */
	fr = f_open(fp, path, FA_WRITE | FA_OPEN_ALWAYS);
	if (fr == FR_OK) {
		/* Seek to end of the file to append data */
		fr = f_lseek(fp, f_size(fp));
		if (fr != FR_OK)
		f_close(fp);
	}
	return fr;
}

static
DWORD pn (
DWORD pns
)
{
	static DWORD lfsr;
	UINT n;

	if (pns) {
		lfsr = pns;
		for (n = 0; n < 32; n++) pn(0);
	}
	if (lfsr & 1) {
		lfsr >>= 1;
		lfsr ^= 0x80200003;
		} else {
		lfsr >>= 1;
	}
	return lfsr;
}

int test_diskio (
BYTE pdrv,      /* Physical drive number to be checked (all data on the drive will be lost) */
UINT ncyc,      /* Number of test cycles */
DWORD* buff,    /* Pointer to the working buffer */
UINT sz_buff    /* Size of the working buffer in unit of byte */
)
{
	UINT n, cc, ns;
	DWORD sz_drv, lba, lba2, pns = 1;
	WORD sz_sect, sz_eblk;
	BYTE *pbuff = (BYTE*)buff;
	DSTATUS ds;
	DRESULT dr;

	print_util_dbg_print("test_diskio(");
	print_util_dbg_print_num(pdrv,10);
	print_util_dbg_print(", ");
	print_util_dbg_print_num(ncyc,10);
	print_util_dbg_print(", 0x");
	print_util_dbg_print_num((UINT)buff,10);
	print_util_dbg_print(", ");
	print_util_dbg_print_num(sz_buff,10);

	if (sz_buff < _MAX_SS + 4) {
		print_util_dbg_print("Insufficient work area to test.\r");
		return 1;
	}

	for (cc = 1; cc <= ncyc; cc++) {
		print_util_dbg_print("**** Test cycle");
		print_util_dbg_print_num(cc,10);
		print_util_dbg_print(" of ");
		print_util_dbg_print_num(ncyc,10);
		print_util_dbg_print(" start ****\r");
		delay_ms(25);

		/* Initialization */
		print_util_dbg_print(" disk_initalize(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(")\r");
		delay_ms(25);

		ds = disk_initialize(pdrv);
		if (ds & STA_NOINIT) {
			print_util_dbg_print(" - failed.\r");
			return 2;
		} else {
			print_util_dbg_print(" - ok.\r");
		}
		delay_ms(25);

		/* Get drive size */
		print_util_dbg_print("**** Get drive size ****\r");
		print_util_dbg_print(" disk_ioctl(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", GET_SECTOR_COUNT, 0x");
		print_util_dbg_print_num((UINT)&sz_drv,10);
		print_util_dbg_print(")\r");
		delay_ms(25);

		sz_drv = 0;
		dr = disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_drv);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 3;
		}
		delay_ms(25);

		if (sz_drv < 128) {
			print_util_dbg_print("Failed: Insufficient drive size to test.\r");
			return 4;
		}
		print_util_dbg_print(" Number of sectors on the drive ");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(" is ");
		print_util_dbg_print_num(sz_drv,10);
		print_util_dbg_print(".\r");
		delay_ms(25);

		#if _MAX_SS != _MIN_SS
		/* Get sector size */
		print_util_dbg_print("**** Get sector size ****\r");
		print_util_dbg_print(" disk_ioctl(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", GET_SECTOR_SIZE, 0x");
		print_util_dbg_print_num((UINT)&sz_sect,10);
		print_util_dbg_print(")\r");
		delay_ms(25);

		sz_sect = 0;
		dr = disk_ioctl(pdrv, GET_SECTOR_SIZE, &sz_sect);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 5;
		}
		delay_ms(25);

		print_util_dbg_print(" Size of sector is ");
		print_util_dbg_print_num(sz_sect,10);
		print_util_dbg_print("bytes.\r");

		#else
		sz_sect = _MAX_SS;
		#endif

		/* Get erase block size */
		print_util_dbg_print("**** Get block size ****\r");
		print_util_dbg_print(" disk_ioctl(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", GET_BLOCK_SIZE, 0x");
		print_util_dbg_print_num((UINT)&sz_eblk,10);
		print_util_dbg_print(")\r");
		delay_ms(25);

		sz_eblk = 0;
		dr = disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_eblk);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
		}
		delay_ms(25);

		if (dr == RES_OK || sz_eblk >= 2) {
			print_util_dbg_print(" Size of the erase block is ");
			print_util_dbg_print_num(sz_eblk,10);
			print_util_dbg_print(" sectors.\r");
		} else {
			print_util_dbg_print(" Size of the erase block is unknown.\r");
		}
		delay_ms(25);

		/* Single sector write test */
		print_util_dbg_print("**** Single sector write test 1 ****\r");
		lba = 0;
		for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n] = (BYTE)pn(0);
		print_util_dbg_print(" disk_write(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", 0x");
		print_util_dbg_print_num((UINT)pbuff,10);
		print_util_dbg_print(", ");
		print_util_dbg_print_num(lba,10);
		print_util_dbg_print(", 1)");
		delay_ms(25);

		dr = disk_write(pdrv, pbuff, lba, 1);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 6;
		}
		delay_ms(25);

		print_util_dbg_print(" disk_ioctl(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", CTRL_SYNC, NULL)");
		delay_ms(25);

		dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 7;
		}
		delay_ms(25);

		memset(pbuff, 0, sz_sect);
		print_util_dbg_print(" disk_read(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", 0x");
		print_util_dbg_print_num((UINT)pbuff,10);
		print_util_dbg_print(", ");
		print_util_dbg_print_num(lba,10);
		print_util_dbg_print(", 1)");
		delay_ms(25);

		dr = disk_read(pdrv, pbuff, lba, 1);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 8;
		}
		delay_ms(25);

		for (n = 0, pn(pns); n < sz_sect && pbuff[n] == (BYTE)pn(0); n++) ;
		if (n == sz_sect) {
			print_util_dbg_print(" Data matched.\r");
		} else {
			print_util_dbg_print("Failed: Read data differs from the data written.\r");
			return 10;
		}
		pns++;
		delay_ms(25);

		/* Multiple sector write test */
		print_util_dbg_print("**** Multiple sector write test ****\r");
		lba = 1; ns = sz_buff / sz_sect;
		if (ns > 4) ns = 4;
		for (n = 0, pn(pns); n < (UINT)(sz_sect * ns); n++) pbuff[n] = (BYTE)pn(0);
		print_util_dbg_print(" disk_write(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", 0x");
		print_util_dbg_print_num((UINT)pbuff,10);
		print_util_dbg_print(", ");
		print_util_dbg_print_num(lba,10);
		print_util_dbg_print(", ");
		print_util_dbg_print_num(ns, 10);
		print_util_dbg_print(")\r");
		delay_ms(25);

		dr = disk_write(pdrv, pbuff, lba, ns);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 11;
		}
		delay_ms(25);

		print_util_dbg_print(" disk_ioctl(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", CTRL_SYNC, NULL)");
		delay_ms(25);

		dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 12;
		}
		memset(pbuff, 0, sz_sect * ns);
		print_util_dbg_print(" disk_read(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", 0x");
		print_util_dbg_print_num((UINT)pbuff,10);
		print_util_dbg_print(", ");
		print_util_dbg_print_num(lba,10);
		print_util_dbg_print(", ");
		print_util_dbg_print_num(ns, 10);
		print_util_dbg_print(")\r");
		delay_ms(25);

		dr = disk_read(pdrv, pbuff, lba, ns);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 13;
		}
		delay_ms(25);

		for (n = 0, pn(pns); n < (UINT)(sz_sect * ns) && pbuff[n] == (BYTE)pn(0); n++) ;
		if (n == (UINT)(sz_sect * ns)) {
			print_util_dbg_print(" Data matched.\r");
		} else {
			print_util_dbg_print("Failed: Read data differs from the data written.\r");
			return 14;
		}
		pns++;
		delay_ms(25);

		/* Single sector write test (misaligned memory address) */
		print_util_dbg_print("**** Single sector write test 2 ****\r");
		lba = 5;
		for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n+3] = (BYTE)pn(0);
		print_util_dbg_print(" disk_write(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", 0x");
		print_util_dbg_print_num((UINT)(pbuff+3),10);
		print_util_dbg_print(", ");
		print_util_dbg_print_num(lba,10);
		print_util_dbg_print(", 1)\r");
		delay_ms(25);

		dr = disk_write(pdrv, pbuff+3, lba, 1);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 15;
		}
		print_util_dbg_print(" disk_ioctl(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", CTRL_SYNC, NULL)");
		delay_ms(25);

		dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 16;
		}
		delay_ms(25);

		memset(pbuff+5, 0, sz_sect);
		print_util_dbg_print(" disk_read(");
		print_util_dbg_print_num(pdrv,10);
		print_util_dbg_print(", 0x");
		print_util_dbg_print_num((UINT)(pbuff+5),10);
		print_util_dbg_print(", ");
		print_util_dbg_print_num(lba,10);
		print_util_dbg_print(", 1)\r");
		delay_ms(25);

		dr = disk_write(pdrv, pbuff+3, lba, 1);
		dr = disk_read(pdrv, pbuff+5, lba, 1);
		if (dr == RES_OK) {
			print_util_dbg_print(" - ok.\r");
		} else {
			print_util_dbg_print(" - failed.\r");
			return 17;
		delay_ms(25);

		}
		for (n = 0, pn(pns); n < sz_sect && pbuff[n+5] == (BYTE)pn(0); n++) ;
		if (n == sz_sect) {
			print_util_dbg_print(" Data matched.\r");
			print_util_dbg_print_num(n,10);
			print_util_dbg_print_num(sz_sect,10);
		} else {
			print_util_dbg_print("Failed: Read data differs from the data written.\r");
			print_util_dbg_print_num(n,10);
			print_util_dbg_print_num(sz_sect,10);
			return 18;
		}
		pns++;
		delay_ms(25);

		/* 4GB barrier test */
		print_util_dbg_print("**** 4GB barrier test ****\r");
		if (sz_drv >= 128 + 0x80000000 / (sz_sect / 2)) {
			lba = 6; lba2 = lba + 0x80000000 / (sz_sect / 2);
			for (n = 0, pn(pns); n < (UINT)(sz_sect * 2); n++) pbuff[n] = (BYTE)pn(0);
			print_util_dbg_print(" disk_write(");
			print_util_dbg_print_num(pdrv,10);
			print_util_dbg_print(", 0x");
			print_util_dbg_print_num((UINT)pbuff,10);
			print_util_dbg_print(", ");
			print_util_dbg_print_num(lba,10);
			print_util_dbg_print(")\r");
			delay_ms(25);

			dr = disk_write(pdrv, pbuff, lba, 1);
			if (dr == RES_OK) {
				print_util_dbg_print(" - ok.\r");
			} else {
				print_util_dbg_print(" - failed.\r");
				return 19;
			}
			delay_ms(25);

			print_util_dbg_print(" disk_write(");
			print_util_dbg_print_num(pdrv,10);
			print_util_dbg_print(", 0x");
			print_util_dbg_print_num((UINT)(pbuff+sz_sect),10);
			print_util_dbg_print(", ");
			print_util_dbg_print_num(lba2,10);
			print_util_dbg_print(", 1)\r");
			delay_ms(25);

			dr = disk_write(pdrv, pbuff+sz_sect, lba2, 1);
			if (dr == RES_OK) {
				print_util_dbg_print(" - ok.\r");
			} else {
				print_util_dbg_print(" - failed.\r");
				return 20;
			}
			delay_ms(25);

			print_util_dbg_print(" disk_ioctl(");
			print_util_dbg_print_num(pdrv,10);
			print_util_dbg_print(", CTRL_SYNC, NULL)");
			delay_ms(25);

			dr = disk_ioctl(pdrv, CTRL_SYNC, 0);
			if (dr == RES_OK) {
				print_util_dbg_print(" - ok.\r");
			} else {
				print_util_dbg_print(" - failed.\r");
				return 21;
			}
			delay_ms(25);

			memset(pbuff, 0, sz_sect * 2);
			print_util_dbg_print(" disk_read(");
			print_util_dbg_print_num(pdrv,10);
			print_util_dbg_print(", 0x");
			print_util_dbg_print_num((UINT)pbuff,10);
			print_util_dbg_print(", ");
			print_util_dbg_print_num(lba,10);
			print_util_dbg_print(", 1)\r");
			delay_ms(25);

			dr = disk_read(pdrv, pbuff, lba, 1);
			if (dr == RES_OK) {
				print_util_dbg_print(" - ok.\r");
			} else {
				print_util_dbg_print(" - failed.\r");
				return 22;
			}
			delay_ms(25);

			print_util_dbg_print(" disk_read(");
			print_util_dbg_print_num(pdrv,10);
			print_util_dbg_print(", 0x");
			print_util_dbg_print_num((UINT)(pbuff+sz_sect),10);
			print_util_dbg_print(", ");
			print_util_dbg_print_num(lba2,10);
			print_util_dbg_print(")\r");
			delay_ms(25);

			dr = disk_read(pdrv, pbuff+sz_sect, lba2, 1);
			if (dr == RES_OK) {
				print_util_dbg_print(" - ok.\r");
			} else {
				print_util_dbg_print(" - failed.\r");
				return 23;
			}
			delay_ms(25);

			for (n = 0, pn(pns); pbuff[n] == (BYTE)pn(0) && n < (UINT)(sz_sect * 2); n++) ;
			if (n == (UINT)(sz_sect * 2)) {
				print_util_dbg_print(" Data matched.\r");
			} else {
				print_util_dbg_print("Failed: Read data differs from the data written.\r");
				return 24;
			}
		} else {
			print_util_dbg_print(" Test skipped.\r");

		}
		pns++;
		delay_ms(25);

		print_util_dbg_print("**** Test cycle");
		print_util_dbg_print_num(cc,10);
		print_util_dbg_print(" of ");
		print_util_dbg_print_num(ncyc,10);
		print_util_dbg_print(" completed ****\r");
		delay_ms(25);
	}

	return 0;
}

void test_fatfs()
{
	int rc;
	DWORD buff[512];  /* 2048 byte working buffer */

	/* Check function/compatibility of the physical drive #0 */
	rc = test_diskio(1, 1, buff, sizeof buff);
	if (rc) {
		print_util_dbg_print("Sorry the function/compatibility test failed.\rFatFs will not work on this disk driver.\r");
		print_util_dbg_print_num(rc,10);
	} else {
		print_util_dbg_print("Congratulations! The disk I/O layer works well.\r");
	}

	FRESULT fr;
	FATFS fs;
	FIL fil;

	fr = f_mount(&fs, "", 0);
	print_util_dbg_print("Result mounting:");
	print_util_dbg_print_num(fr,10);
	print_util_dbg_print("\r");

	fr = open_append(&fil,"License.txt");
	if (fr == FR_OK)
	{
		print_util_dbg_print("Opening okay!\r");
	}
	else
	{
		print_util_dbg_print("Opening not okay... Error number:");
		print_util_dbg_print_num(fr,10);
		print_util_dbg_print("\r");
	}
	fr = f_close(&fil);
	print_util_dbg_print("Result closing:");
	print_util_dbg_print_num(fr,10);
	print_util_dbg_print("\r");

	fr = f_mkdir("Nicolas");
	print_util_dbg_print("Result mkdir:");
	print_util_dbg_print_num(fr,10);
	print_util_dbg_print("\r");

	print_util_dbg_print("Yeah!");
}

void initialisation()
{
	central_data = central_data_get_pointer_to_struct();
	boardsupport_init(central_data);
	central_data_init();

	mavlink_telemetry_init();
	onboard_parameters_read_parameters_from_flashc(&central_data->mavlink_communication.onboard_parameters);

	LED_On(LED1);

	piezo_speaker_startup_melody();

	print_util_dbg_print("OK. Starting up.\r");

	//sd_spi_test();

	//test_sd_spi();

	test_fatfs();

	central_data->state.mav_state = MAV_STATE_STANDBY;

	central_data->imu.calibration_level = OFF;
}

int main (void)
{
	initialisation();
	tasks_create_tasks();

	while (1 == 1)
	{
		scheduler_update(&central_data->scheduler);
	}

	return 0;
}<|endoftext|>


<commit_before>#include <stdexcept>

#include <xorg/gtest/xorg-gtest.h>

#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>

/**
 * A test fixture for testing the XInput 2.x extension.
 *
 * @tparam The XInput 2.x minor version
 */
class XInput2Test : public xorg::testing::Test,
                    public ::testing::WithParamInterface<int> {
protected:
    virtual void SetUp()
    {
        ASSERT_NO_FATAL_FAILURE(xorg::testing::Test::SetUp());

        int event_start;
        int error_start;

        ASSERT_TRUE(XQueryExtension(Display(), "XInputExtension", &xi2_opcode_,
                                    &event_start, &error_start));

        int major = 2;
        int minor = GetParam();

        ASSERT_EQ(Success, XIQueryVersion(Display(), &major, &minor));
    }

    int xi2_opcode_;
};

TEST_P(XInput2Test, XIQueryPointerTouchscreen)
{
    SCOPED_TRACE("\n"
                 "XIQueryPointer for XInput 2.1 and earlier should report the\n"
                 "first button pressed if a touch is physically active. For \n"
                 "XInput 2.2 and later clients, the first button should not be\n"
                 "reported.");
    XIEventMask mask;
    mask.deviceid = XIAllDevices;
    mask.mask_len = XIMaskLen(XI_HierarchyChanged);
    mask.mask = reinterpret_cast<unsigned char*>(calloc(mask.mask_len, 1));
    XISetMask(mask.mask, XI_HierarchyChanged);

    ASSERT_EQ(Success,
              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
                             1));

    mask.deviceid = XIAllMasterDevices;
    XIClearMask(mask.mask, XI_HierarchyChanged);
    XISetMask(mask.mask, XI_ButtonPress);

    ASSERT_EQ(Success,
              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
                             1));

    free(mask.mask);

    XFlush(Display());

    std::auto_ptr<xorg::testing::evemu::Device> device;
    try {
      device = std::auto_ptr<xorg::testing::evemu::Device>(
          new xorg::testing::evemu::Device(
              RECORDINGS_DIR "tablets/N-Trig MultiTouch.device")
          );
    } catch (std::runtime_error &error) {
      std::cerr << "Failed to create evemu device, skipping test.\n";
      return;
    }

    ASSERT_TRUE(xorg::testing::XServer::WaitForDevice(Display(), "N-Trig MultiTouch"));

    device->Play(RECORDINGS_DIR "tablets/N-Trig MultiTouch.touch_1_begin.events");

    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode_,
                                                           XI_ButtonPress));

    XEvent event;
    ASSERT_EQ(Success, XNextEvent(Display(), &event));

    XGenericEventCookie *xcookie = &event.xcookie;
    ASSERT_TRUE(XGetEventData(Display(), xcookie));

    XIDeviceEvent *device_event =
        reinterpret_cast<XIDeviceEvent*>(xcookie->data);

    Window root;
    Window child;
    double root_x;
    double root_y;
    double win_x;
    double win_y;
    XIButtonState buttons;
    XIModifierState modifiers;
    XIGroupState group;
    ASSERT_TRUE(XIQueryPointer(Display(), device_event->deviceid,
                               DefaultRootWindow(Display()), &root, &child,
                               &root_x, &root_y, &win_x, &win_y, &buttons,
                               &modifiers, &group));

    /* Test if button 1 is pressed */
    ASSERT_GE(buttons.mask_len, XIMaskLen(2));
    if (GetParam() < 2)
        EXPECT_TRUE(XIMaskIsSet(buttons.mask, 1));
    else
        EXPECT_FALSE(XIMaskIsSet(buttons.mask, 1));

    XFreeEventData(Display(), xcookie);
}

TEST_P(XInput2Test, DisableDeviceEndTouches)
{
    SCOPED_TRACE("When a device is disabled, any physically active touches\n"
                 "should end.");
    /* This is an XInput 2.2 and later test only */
    if (GetParam() < 2)
        return;

    XIEventMask mask;
    mask.deviceid = XIAllDevices;
    mask.mask_len = XIMaskLen(XI_TouchEnd);
    mask.mask = reinterpret_cast<unsigned char*>(calloc(mask.mask_len, 1));
    XISetMask(mask.mask, XI_HierarchyChanged);

    ASSERT_EQ(Success,
              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
                             1));

    mask.deviceid = XIAllMasterDevices;
    XIClearMask(mask.mask, XI_HierarchyChanged);
    XISetMask(mask.mask, XI_TouchBegin);
    XISetMask(mask.mask, XI_TouchUpdate);
    XISetMask(mask.mask, XI_TouchEnd);

    ASSERT_EQ(Success,
              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
                             1));

    free(mask.mask);

    XFlush(Display());

    std::auto_ptr<xorg::testing::evemu::Device> device;
    try {
      device = std::auto_ptr<xorg::testing::evemu::Device>(
          new xorg::testing::evemu::Device(
              RECORDINGS_DIR "tablets/N-Trig MultiTouch.device")
          );
    } catch (std::runtime_error &error) {
      std::cerr << "Failed to create evemu device, skipping test.\n";
      return;
    }

    ASSERT_TRUE(xorg::testing::XServer::WaitForDevice(Display(), "N-Trig MultiTouch"));

    device->Play(RECORDINGS_DIR "tablets/N-Trig MultiTouch.touch_1_begin.events");

    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode_,
                                                           XI_TouchBegin));

    XEvent event;
    ASSERT_EQ(Success, XNextEvent(Display(), &event));

    XGenericEventCookie *xcookie = &event.xcookie;
    ASSERT_TRUE(XGetEventData(Display(), xcookie));

    XIDeviceEvent *device_event =
        reinterpret_cast<XIDeviceEvent*>(xcookie->data);

    XDevice *xdevice = XOpenDevice(Display(), device_event->sourceid);
    XFreeEventData(Display(), xcookie);
    ASSERT_TRUE(xdevice != NULL);

    XDeviceEnableControl enable_control;
    enable_control.enable = false;
    XDeviceControl *control =
        reinterpret_cast<XDeviceControl*>(&enable_control);
    ASSERT_TRUE(XChangeDeviceControl(Display(), xdevice, DEVICE_ENABLE,
                                     control));
    XCloseDevice(Display(), xdevice);
    XFlush(Display());

    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode_,
                                                           XI_TouchEnd));
}

INSTANTIATE_TEST_CASE_P(, XInput2Test, ::testing::Range(0, 3));
<commit_msg>server/xi2: only build touch tests for XI 2.2<commit_after>#include <stdexcept>

#include <xorg/gtest/xorg-gtest.h>

#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>

/**
 * A test fixture for testing the XInput 2.x extension.
 *
 * @tparam The XInput 2.x minor version
 */
class XInput2Test : public xorg::testing::Test,
                    public ::testing::WithParamInterface<int> {
protected:
    virtual void SetUp()
    {
        ASSERT_NO_FATAL_FAILURE(xorg::testing::Test::SetUp());

        int event_start;
        int error_start;

        ASSERT_TRUE(XQueryExtension(Display(), "XInputExtension", &xi2_opcode_,
                                    &event_start, &error_start));

        int major = 2;
        int minor = GetParam();

        ASSERT_EQ(Success, XIQueryVersion(Display(), &major, &minor));
    }

    int xi2_opcode_;
};

TEST_P(XInput2Test, XIQueryPointerTouchscreen)
{
    SCOPED_TRACE("\n"
                 "XIQueryPointer for XInput 2.1 and earlier should report the\n"
                 "first button pressed if a touch is physically active. For \n"
                 "XInput 2.2 and later clients, the first button should not be\n"
                 "reported.");
    XIEventMask mask;
    mask.deviceid = XIAllDevices;
    mask.mask_len = XIMaskLen(XI_HierarchyChanged);
    mask.mask = reinterpret_cast<unsigned char*>(calloc(mask.mask_len, 1));
    XISetMask(mask.mask, XI_HierarchyChanged);

    ASSERT_EQ(Success,
              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
                             1));

    mask.deviceid = XIAllMasterDevices;
    XIClearMask(mask.mask, XI_HierarchyChanged);
    XISetMask(mask.mask, XI_ButtonPress);

    ASSERT_EQ(Success,
              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
                             1));

    free(mask.mask);

    XFlush(Display());

    std::auto_ptr<xorg::testing::evemu::Device> device;
    try {
      device = std::auto_ptr<xorg::testing::evemu::Device>(
          new xorg::testing::evemu::Device(
              RECORDINGS_DIR "tablets/N-Trig MultiTouch.device")
          );
    } catch (std::runtime_error &error) {
      std::cerr << "Failed to create evemu device, skipping test.\n";
      return;
    }

    ASSERT_TRUE(xorg::testing::XServer::WaitForDevice(Display(), "N-Trig MultiTouch"));

    device->Play(RECORDINGS_DIR "tablets/N-Trig MultiTouch.touch_1_begin.events");

    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode_,
                                                           XI_ButtonPress));

    XEvent event;
    ASSERT_EQ(Success, XNextEvent(Display(), &event));

    XGenericEventCookie *xcookie = &event.xcookie;
    ASSERT_TRUE(XGetEventData(Display(), xcookie));

    XIDeviceEvent *device_event =
        reinterpret_cast<XIDeviceEvent*>(xcookie->data);

    Window root;
    Window child;
    double root_x;
    double root_y;
    double win_x;
    double win_y;
    XIButtonState buttons;
    XIModifierState modifiers;
    XIGroupState group;
    ASSERT_TRUE(XIQueryPointer(Display(), device_event->deviceid,
                               DefaultRootWindow(Display()), &root, &child,
                               &root_x, &root_y, &win_x, &win_y, &buttons,
                               &modifiers, &group));

    /* Test if button 1 is pressed */
    ASSERT_GE(buttons.mask_len, XIMaskLen(2));
    if (GetParam() < 2)
        EXPECT_TRUE(XIMaskIsSet(buttons.mask, 1));
    else
        EXPECT_FALSE(XIMaskIsSet(buttons.mask, 1));

    XFreeEventData(Display(), xcookie);
}

#ifdef HAVE_XI22
TEST_P(XInput2Test, DisableDeviceEndTouches)
{
    SCOPED_TRACE("When a device is disabled, any physically active touches\n"
                 "should end.");
    /* This is an XInput 2.2 and later test only */
    if (GetParam() < 2)
        return;

    XIEventMask mask;
    mask.deviceid = XIAllDevices;
    mask.mask_len = XIMaskLen(XI_TouchEnd);
    mask.mask = reinterpret_cast<unsigned char*>(calloc(mask.mask_len, 1));
    XISetMask(mask.mask, XI_HierarchyChanged);

    ASSERT_EQ(Success,
              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
                             1));

    mask.deviceid = XIAllMasterDevices;
    XIClearMask(mask.mask, XI_HierarchyChanged);
    XISetMask(mask.mask, XI_TouchBegin);
    XISetMask(mask.mask, XI_TouchUpdate);
    XISetMask(mask.mask, XI_TouchEnd);

    ASSERT_EQ(Success,
              XISelectEvents(Display(), DefaultRootWindow(Display()), &mask,
                             1));

    free(mask.mask);

    XFlush(Display());

    std::auto_ptr<xorg::testing::evemu::Device> device;
    try {
      device = std::auto_ptr<xorg::testing::evemu::Device>(
          new xorg::testing::evemu::Device(
              RECORDINGS_DIR "tablets/N-Trig MultiTouch.device")
          );
    } catch (std::runtime_error &error) {
      std::cerr << "Failed to create evemu device, skipping test.\n";
      return;
    }

    ASSERT_TRUE(xorg::testing::XServer::WaitForDevice(Display(), "N-Trig MultiTouch"));

    device->Play(RECORDINGS_DIR "tablets/N-Trig MultiTouch.touch_1_begin.events");

    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode_,
                                                           XI_TouchBegin));

    XEvent event;
    ASSERT_EQ(Success, XNextEvent(Display(), &event));

    XGenericEventCookie *xcookie = &event.xcookie;
    ASSERT_TRUE(XGetEventData(Display(), xcookie));

    XIDeviceEvent *device_event =
        reinterpret_cast<XIDeviceEvent*>(xcookie->data);

    XDevice *xdevice = XOpenDevice(Display(), device_event->sourceid);
    XFreeEventData(Display(), xcookie);
    ASSERT_TRUE(xdevice != NULL);

    XDeviceEnableControl enable_control;
    enable_control.enable = false;
    XDeviceControl *control =
        reinterpret_cast<XDeviceControl*>(&enable_control);
    ASSERT_TRUE(XChangeDeviceControl(Display(), xdevice, DEVICE_ENABLE,
                                     control));
    XCloseDevice(Display(), xdevice);
    XFlush(Display());

    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode_,
                                                           XI_TouchEnd));
}
#endif

INSTANTIATE_TEST_CASE_P(, XInput2Test, ::testing::Range(0, 3));
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#include "core/reactor.hh"
#include "core/shared_ptr.hh"
#include "core/do_with.hh"
#include "test-utils.hh"

using namespace seastar;

extern "C" {
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
}

SEASTAR_TEST_CASE(test_sighup) {
    return do_with(make_lw_shared<promise<>>(), false, [](auto const& p, bool& signaled) {
        engine().handle_signal(SIGHUP, [p, &signaled] {
            signaled = true;
            p->set_value();
        });

        kill(getpid(), SIGHUP);

        return p->get_future().then([&] {
            BOOST_REQUIRE_EQUAL(signaled, true);
            return make_ready_future<>();
        });
    });
}
<commit_msg>tests: Remove unnecessary `return`<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#include "core/reactor.hh"
#include "core/shared_ptr.hh"
#include "core/do_with.hh"
#include "test-utils.hh"

using namespace seastar;

extern "C" {
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
}

SEASTAR_TEST_CASE(test_sighup) {
    return do_with(make_lw_shared<promise<>>(), false, [](auto const& p, bool& signaled) {
        engine().handle_signal(SIGHUP, [p, &signaled] {
            signaled = true;
            p->set_value();
        });

        kill(getpid(), SIGHUP);

        return p->get_future().then([&] {
            BOOST_REQUIRE_EQUAL(signaled, true);
        });
    });
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads

// LWG 2056 changed the values of future_errc, so if we're using new headers
// with an old library we'll get incorrect messages.
//
// XFAIL: with_system_cxx_lib=x86_64-apple-darwin11
// XFAIL: with_system_cxx_lib=x86_64-apple-darwin12
// XFAIL: with_system_cxx_lib=x86_64-apple-darwin13

// <future>

// class future_error

// const char* what() const throw();

#include <future>
#include <cstring>
#include <cassert>

int main()
{
    {
        std::future_error f(std::make_error_code(std::future_errc::broken_promise));
        assert(std::strcmp(f.what(), "The associated promise has been destructed prior "
                      "to the associated state becoming ready.") == 0);
    }
    {
        std::future_error f(std::make_error_code(std::future_errc::future_already_retrieved));
        assert(std::strcmp(f.what(), "The future has already been retrieved from "
                      "the promise or packaged_task.") == 0);
    }
    {
        std::future_error f(std::make_error_code(std::future_errc::promise_already_satisfied));
        assert(std::strcmp(f.what(), "The state of the promise has already been set.") == 0);
    }
    {
        std::future_error f(std::make_error_code(std::future_errc::no_state));
        assert(std::strcmp(f.what(), "Operation not permitted on an object without "
                      "an associated state.") == 0);
    }
}
<commit_msg>[libcxx] [test] D26625: future_error::what() is implementation-defined.<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads

// LWG 2056 changed the values of future_errc, so if we're using new headers
// with an old library we'll get incorrect messages.
//
// XFAIL: with_system_cxx_lib=x86_64-apple-darwin11
// XFAIL: with_system_cxx_lib=x86_64-apple-darwin12
// XFAIL: with_system_cxx_lib=x86_64-apple-darwin13

// <future>

// class future_error

// const char* what() const throw();

#include <future>
#include <cstring>
#include <cassert>

#include "test_macros.h"

int main()
{
    {
        std::future_error f(std::make_error_code(std::future_errc::broken_promise));
        LIBCPP_ASSERT(std::strcmp(f.what(), "The associated promise has been destructed prior "
                      "to the associated state becoming ready.") == 0);
    }
    {
        std::future_error f(std::make_error_code(std::future_errc::future_already_retrieved));
        LIBCPP_ASSERT(std::strcmp(f.what(), "The future has already been retrieved from "
                      "the promise or packaged_task.") == 0);
    }
    {
        std::future_error f(std::make_error_code(std::future_errc::promise_already_satisfied));
        LIBCPP_ASSERT(std::strcmp(f.what(), "The state of the promise has already been set.") == 0);
    }
    {
        std::future_error f(std::make_error_code(std::future_errc::no_state));
        LIBCPP_ASSERT(std::strcmp(f.what(), "Operation not permitted on an object without "
                      "an associated state.") == 0);
    }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "ReportBuilder.h"
#include <thread>

using namespace fnord;

namespace cm {

ReportBuilder::ReportBuilder() :
    max_threads_(8),
    num_threads_(0),
    running_(true) {}

void ReportBuilder::addReport(RefPtr<Report> report) {
  reports_.emplace_back(report);
}

void ReportBuilder::buildAll() {
  size_t r;
  while ((r = buildSome()) > 0) {
    std::unique_lock<std::mutex> lk(m_);
    while (num_threads_ >= (r > max_threads_ ? max_threads_ : r)) {
      cv_.wait(lk);
    }
  }

  std::unique_lock<std::mutex> lk(m_);
  while (num_threads_ > 0) {
    cv_.wait(lk);
  }
}

void ReportBuilder::buildLoop(const Duration& interval) {
  while (running_) {
    if (buildSome() == 0) {
      usleep(interval.microseconds());
    }
  }

  std::unique_lock<std::mutex> lk(m_);
  while (num_threads_ > 0) {
    cv_.wait(lk);
  }
}

size_t ReportBuilder::buildSome() {
  Set<String> existing_files;
  fnord::logInfo("cm.reportbuild", "Scanning dependencies...");

  uint64_t reports_waiting = 0;
  uint64_t reports_runnable = 0;
  uint64_t reports_running = 0;
  uint64_t reports_completed = 0;

  HashMap<ReportSource*, List<RefPtr<Report>>> runnables;
  for (const auto& r : reports_) {
    bool already_completed = true;
    for (const auto& f : r->output()->outputFiles()) {
      if (existing_files.count(f) > 0 || FileUtil::exists(f)) {
        existing_files.emplace(f);
      } else {
        fnord::logDebug(
            "cm.reportbuild",
            "Marking report '$0' as runnable because output '$1' doesn't exist",
            "FIXME",
            f);

        already_completed = false;
        break;
      }
    }

    if (already_completed) {
      ++reports_completed;
      continue;
    }

    if (r->running) {
      ++reports_running;
      continue;
    }

    bool inputs_ready = true;
    for (const auto& f : r->input()->inputFiles()) {
      if (existing_files.count(f) > 0 || FileUtil::exists(f)) {
        existing_files.emplace(f);
      } else {
        fnord::logDebug(
            "cm.reportbuild",
            "Marking report '$0' as waiting because input '$1' doesn't exist",
            "FIXME",
            f);

        inputs_ready = false;
        break;
      }
    }

    if (inputs_ready) {
      ++reports_runnable;
      r->running = true;
      runnables[r->input().get()].emplace_back(r);
    } else {
      ++reports_waiting;
    }
  }

  fnord::logInfo(
      "cm.reportbuild",
      "Found $0 report(s) - $1 waiting, $2 runnable, $3 running, $4 completed",
      reports_.size(),
      reports_waiting,
      reports_runnable,
      reports_running,
      reports_completed);

  if (runnables.size() > 0) {
    fnord::logInfo(
        "cm.reportbuild",
        "Running $0 report pipeline(s)", runnables.size());

    buildParallel(runnables);
  }

  return reports_runnable + reports_running;
}

void ReportBuilder::buildParallel(
    const HashMap<ReportSource*, List<RefPtr<Report>>>& runnables) {
  std::unique_lock<std::mutex> lk(m_);

  for (auto runnable : runnables) {
    while (num_threads_ >= max_threads_) {
      cv_.wait(lk);
    }

    ++num_threads_;
    auto thread = std::thread([this, runnable] () {
      fnord::logInfo(
          "cm.reportbuild",
          "Running report pipline with $1 report(s) for inputs: $0",
          inspect(runnable.first->inputFiles()),
          runnable.second.size());

      for (const auto& r : runnable.second) {
        r->output()->open();
        r->onInit();
      }

      runnable.first->read();

      for (const auto& r : runnable.second) {
        r->onFinish();
        r->output()->close();
      }

      std::unique_lock<std::mutex> wakeup_lk(m_);
      --num_threads_;
      wakeup_lk.unlock();
      cv_.notify_one();
    });

    thread.detach();
  }
}

} // namespace cm

<commit_msg>ReportBuilder wait logic<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "ReportBuilder.h"
#include <thread>

using namespace fnord;

namespace cm {

ReportBuilder::ReportBuilder() :
    max_threads_(8),
    num_threads_(0),
    running_(true) {}

void ReportBuilder::addReport(RefPtr<Report> report) {
  reports_.emplace_back(report);
}

void ReportBuilder::buildAll() {
  size_t r;

  while ((r = buildSome()) > 0) {
    std::unique_lock<std::mutex> lk(m_);
    cv_.wait(lk);
  }

  std::unique_lock<std::mutex> lk(m_);
  while (num_threads_ > 0) {
    cv_.wait(lk);
  }
}

void ReportBuilder::buildLoop(const Duration& interval) {
  while (running_) {
    if (buildSome() == 0) {
      usleep(interval.microseconds());
    }
  }

  std::unique_lock<std::mutex> lk(m_);
  while (num_threads_ > 0) {
    cv_.wait(lk);
  }
}

size_t ReportBuilder::buildSome() {
  Set<String> existing_files;
  fnord::logInfo("cm.reportbuild", "Scanning dependencies...");

  uint64_t reports_waiting = 0;
  uint64_t reports_runnable = 0;
  uint64_t reports_running = 0;
  uint64_t reports_completed = 0;

  HashMap<ReportSource*, List<RefPtr<Report>>> runnables;
  for (const auto& r : reports_) {
    bool already_completed = true;
    for (const auto& f : r->output()->outputFiles()) {
      if (existing_files.count(f) > 0 || FileUtil::exists(f)) {
        existing_files.emplace(f);
      } else {
        fnord::logDebug(
            "cm.reportbuild",
            "Marking report '$0' as runnable because output '$1' doesn't exist",
            "FIXME",
            f);

        already_completed = false;
        break;
      }
    }

    if (already_completed) {
      ++reports_completed;
      continue;
    }

    if (r->running) {
      ++reports_running;
      continue;
    }

    bool inputs_ready = true;
    for (const auto& f : r->input()->inputFiles()) {
      if (existing_files.count(f) > 0 || FileUtil::exists(f)) {
        existing_files.emplace(f);
      } else {
        fnord::logDebug(
            "cm.reportbuild",
            "Marking report '$0' as waiting because input '$1' doesn't exist",
            "FIXME",
            f);

        inputs_ready = false;
        break;
      }
    }

    if (inputs_ready) {
      ++reports_runnable;
      r->running = true;
      runnables[r->input().get()].emplace_back(r);
    } else {
      ++reports_waiting;
    }
  }

  fnord::logInfo(
      "cm.reportbuild",
      "Found $0 report(s) - $1 waiting, $2 runnable, $3 running, $4 completed",
      reports_.size(),
      reports_waiting,
      reports_runnable,
      reports_running,
      reports_completed);

  if (runnables.size() > 0) {
    fnord::logInfo(
        "cm.reportbuild",
        "Running $0 report pipeline(s)", runnables.size());

    buildParallel(runnables);
  }

  return reports_runnable + reports_running;
}

void ReportBuilder::buildParallel(
    const HashMap<ReportSource*, List<RefPtr<Report>>>& runnables) {
  std::unique_lock<std::mutex> lk(m_);

  for (auto runnable : runnables) {
    while (num_threads_ >= max_threads_) {
      cv_.wait(lk);
    }

    ++num_threads_;
    auto thread = std::thread([this, runnable] () {
      fnord::logInfo(
          "cm.reportbuild",
          "Running report pipline with $1 report(s) for inputs: $0",
          inspect(runnable.first->inputFiles()),
          runnable.second.size());

      for (const auto& r : runnable.second) {
        r->output()->open();
        r->onInit();
      }

      runnable.first->read();

      for (const auto& r : runnable.second) {
        r->onFinish();
        r->output()->close();
      }

      std::unique_lock<std::mutex> wakeup_lk(m_);
      --num_threads_;
      wakeup_lk.unlock();
      cv_.notify_all();
    });

    thread.detach();
  }
}

} // namespace cm

<|endoftext|>


<commit_before>/*
 * Segment.cpp
 *****************************************************************************
 * Copyright (C) 2010 - 2011 Klagenfurt University
 *
 * Created on: Aug 10, 2010
 * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
 *          Christian Timmerer  <christian.timmerer@itec.uni-klu.ac.at>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "Segment.h"
#include "BaseRepresentation.h"
#include "AbstractPlaylist.hpp"
#include "SegmentChunk.hpp"
#include "../http/BytesRange.hpp"
#include "../http/HTTPConnectionManager.h"
#include "../http/Downloader.hpp"
#include <cassert>

using namespace adaptive::http;
using namespace adaptive::playlist;

const int ISegment::SEQUENCE_INVALID = 0;
const int ISegment::SEQUENCE_FIRST   = 1;

ISegment::ISegment(const ICanonicalUrl *parent):
    ICanonicalUrl( parent ),
    startByte  (0),
    endByte    (0)
{
    debugName = "Segment";
    classId = CLASSID_ISEGMENT;
    startTime.Set(0);
    duration.Set(0);
    chunksuse.Set(0);
    sequence = SEQUENCE_INVALID;
    templated = false;
    discontinuity = false;
}

ISegment::~ISegment()
{
    assert(chunksuse.Get() == 0);
}

SegmentChunk * ISegment::getChunk(const std::string &url, HTTPConnectionManager *connManager)
{
    HTTPChunkBufferedSource *source = new HTTPChunkBufferedSource(url, connManager);
    if(startByte != endByte)
        source->setBytesRange(BytesRange(startByte, endByte));
    connManager->downloader->schedule(source);
    return new (std::nothrow) SegmentChunk(this, source);
}

void ISegment::onChunkDownload(block_t **, SegmentChunk *, BaseRepresentation *)
{

}

SegmentChunk* ISegment::toChunk(size_t index, BaseRepresentation *ctxrep, HTTPConnectionManager *connManager)
{
    SegmentChunk *chunk;
    try
    {
        chunk = getChunk(getUrlSegment().toString(index, ctxrep), connManager);
        if (!chunk)
            return NULL;
    }
    catch (int)
    {
        return NULL;
    };

    chunk->setRepresentation(ctxrep);

    return chunk;
}

bool ISegment::isTemplate() const
{
    return templated;
}

void ISegment::setByteRange(size_t start, size_t end)
{
    startByte = start;
    endByte   = end;
}

void ISegment::setSequenceNumber(uint64_t seq)
{
    sequence = SEQUENCE_FIRST + seq;
}

uint64_t ISegment::getSequenceNumber() const
{
    return sequence;
}

size_t ISegment::getOffset() const
{
    return startByte;
}

void ISegment::debug(vlc_object_t *obj, int indent) const
{
    std::stringstream ss;
    ss.imbue(std::locale("C"));
    ss << std::string(indent, ' ') << debugName << " #" << getSequenceNumber();
    ss << " url=" << getUrlSegment().toString();
    if(startByte!=endByte)
        ss << " @" << startByte << ".." << endByte;
    if(startTime.Get() > 0)
    	 ss << " stime " << startTime.Get();
    msg_Dbg(obj, "%s", ss.str().c_str());
}

bool ISegment::contains(size_t byte) const
{
    if (startByte == endByte)
        return false;
    return (byte >= startByte &&
            (!endByte || byte <= endByte) );
}

int ISegment::compare(ISegment *other) const
{
    if(duration.Get())
    {
        stime_t diff = startTime.Get() - other->startTime.Get();
        if(diff)
            return diff / diff;
    }

    size_t diff = startByte - other->startByte;
    if(diff)
        return diff / diff;

    diff = endByte - other->endByte;
    if(diff)
        return diff / diff;

    return 0;
}

int ISegment::getClassId() const
{
    return classId;
}

Segment::Segment(ICanonicalUrl *parent) :
        ISegment(parent)
{
    size = -1;
    classId = CLASSID_SEGMENT;
}

void Segment::addSubSegment(SubSegment *subsegment)
{
    if(!subsegments.empty())
    {
        /* Use our own sequence number, and since it it now
           uneffective, also for next subsegments numbering */
        subsegment->setSequenceNumber(getSequenceNumber());
        setSequenceNumber(getSequenceNumber());
    }
    subsegments.push_back(subsegment);
}

Segment::~Segment()
{
    std::vector<SubSegment*>::iterator it;
    for(it=subsegments.begin();it!=subsegments.end();++it)
        delete *it;
}

void                    Segment::setSourceUrl   ( const std::string &url )
{
    if ( url.empty() == false )
        this->sourceUrl = Url(url);
}

void Segment::debug(vlc_object_t *obj, int indent) const
{
    if (subsegments.empty())
    {
        ISegment::debug(obj, indent);
    }
    else
    {
        std::string text(indent, ' ');
        text.append("Segment");
        msg_Dbg(obj, "%s", text.c_str());
        std::vector<SubSegment *>::const_iterator l;
        for(l = subsegments.begin(); l != subsegments.end(); ++l)
            (*l)->debug(obj, indent + 1);
    }
}

Url Segment::getUrlSegment() const
{
    if(sourceUrl.hasScheme())
    {
        return sourceUrl;
    }
    else
    {
        Url ret = getParentUrlSegment();
        if (!sourceUrl.empty())
            ret.append(sourceUrl);
        return ret;
    }
}

std::vector<ISegment*> Segment::subSegments()
{
    std::vector<ISegment*> list;
    if(!subsegments.empty())
    {
        std::vector<SubSegment*>::iterator it;
        for(it=subsegments.begin();it!=subsegments.end();++it)
            list.push_back(*it);
    }
    else
    {
        list.push_back(this);
    }
    return list;
}

InitSegment::InitSegment(ICanonicalUrl *parent) :
    Segment(parent)
{
    debugName = "InitSegment";
    classId = CLASSID_INITSEGMENT;
}

IndexSegment::IndexSegment(ICanonicalUrl *parent) :
    Segment(parent)
{
    debugName = "IndexSegment";
    classId = CLASSID_INDEXSEGMENT;
}

SubSegment::SubSegment(ISegment *main, size_t start, size_t end) :
    ISegment(main), parent(main)
{
    setByteRange(start, end);
    debugName = "SubSegment";
    classId = CLASSID_SUBSEGMENT;
}

Url SubSegment::getUrlSegment() const
{
    return getParentUrlSegment();
}

std::vector<ISegment*> SubSegment::subSegments()
{
    std::vector<ISegment*> list;
    list.push_back(this);
    return list;
}

void SubSegment::addSubSegment(SubSegment *)
{

}
<commit_msg>demux: adaptive: debug segment duration<commit_after>/*
 * Segment.cpp
 *****************************************************************************
 * Copyright (C) 2010 - 2011 Klagenfurt University
 *
 * Created on: Aug 10, 2010
 * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
 *          Christian Timmerer  <christian.timmerer@itec.uni-klu.ac.at>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "Segment.h"
#include "BaseRepresentation.h"
#include "AbstractPlaylist.hpp"
#include "SegmentChunk.hpp"
#include "../http/BytesRange.hpp"
#include "../http/HTTPConnectionManager.h"
#include "../http/Downloader.hpp"
#include <cassert>

using namespace adaptive::http;
using namespace adaptive::playlist;

const int ISegment::SEQUENCE_INVALID = 0;
const int ISegment::SEQUENCE_FIRST   = 1;

ISegment::ISegment(const ICanonicalUrl *parent):
    ICanonicalUrl( parent ),
    startByte  (0),
    endByte    (0)
{
    debugName = "Segment";
    classId = CLASSID_ISEGMENT;
    startTime.Set(0);
    duration.Set(0);
    chunksuse.Set(0);
    sequence = SEQUENCE_INVALID;
    templated = false;
    discontinuity = false;
}

ISegment::~ISegment()
{
    assert(chunksuse.Get() == 0);
}

SegmentChunk * ISegment::getChunk(const std::string &url, HTTPConnectionManager *connManager)
{
    HTTPChunkBufferedSource *source = new HTTPChunkBufferedSource(url, connManager);
    if(startByte != endByte)
        source->setBytesRange(BytesRange(startByte, endByte));
    connManager->downloader->schedule(source);
    return new (std::nothrow) SegmentChunk(this, source);
}

void ISegment::onChunkDownload(block_t **, SegmentChunk *, BaseRepresentation *)
{

}

SegmentChunk* ISegment::toChunk(size_t index, BaseRepresentation *ctxrep, HTTPConnectionManager *connManager)
{
    SegmentChunk *chunk;
    try
    {
        chunk = getChunk(getUrlSegment().toString(index, ctxrep), connManager);
        if (!chunk)
            return NULL;
    }
    catch (int)
    {
        return NULL;
    };

    chunk->setRepresentation(ctxrep);

    return chunk;
}

bool ISegment::isTemplate() const
{
    return templated;
}

void ISegment::setByteRange(size_t start, size_t end)
{
    startByte = start;
    endByte   = end;
}

void ISegment::setSequenceNumber(uint64_t seq)
{
    sequence = SEQUENCE_FIRST + seq;
}

uint64_t ISegment::getSequenceNumber() const
{
    return sequence;
}

size_t ISegment::getOffset() const
{
    return startByte;
}

void ISegment::debug(vlc_object_t *obj, int indent) const
{
    std::stringstream ss;
    ss.imbue(std::locale("C"));
    ss << std::string(indent, ' ') << debugName << " #" << getSequenceNumber();
    ss << " url=" << getUrlSegment().toString();
    if(startByte!=endByte)
        ss << " @" << startByte << ".." << endByte;
    if(startTime.Get() > 0)
    	 ss << " stime " << startTime.Get();
    ss << " duration " << duration.Get();
    msg_Dbg(obj, "%s", ss.str().c_str());
}

bool ISegment::contains(size_t byte) const
{
    if (startByte == endByte)
        return false;
    return (byte >= startByte &&
            (!endByte || byte <= endByte) );
}

int ISegment::compare(ISegment *other) const
{
    if(duration.Get())
    {
        stime_t diff = startTime.Get() - other->startTime.Get();
        if(diff)
            return diff / diff;
    }

    size_t diff = startByte - other->startByte;
    if(diff)
        return diff / diff;

    diff = endByte - other->endByte;
    if(diff)
        return diff / diff;

    return 0;
}

int ISegment::getClassId() const
{
    return classId;
}

Segment::Segment(ICanonicalUrl *parent) :
        ISegment(parent)
{
    size = -1;
    classId = CLASSID_SEGMENT;
}

void Segment::addSubSegment(SubSegment *subsegment)
{
    if(!subsegments.empty())
    {
        /* Use our own sequence number, and since it it now
           uneffective, also for next subsegments numbering */
        subsegment->setSequenceNumber(getSequenceNumber());
        setSequenceNumber(getSequenceNumber());
    }
    subsegments.push_back(subsegment);
}

Segment::~Segment()
{
    std::vector<SubSegment*>::iterator it;
    for(it=subsegments.begin();it!=subsegments.end();++it)
        delete *it;
}

void                    Segment::setSourceUrl   ( const std::string &url )
{
    if ( url.empty() == false )
        this->sourceUrl = Url(url);
}

void Segment::debug(vlc_object_t *obj, int indent) const
{
    if (subsegments.empty())
    {
        ISegment::debug(obj, indent);
    }
    else
    {
        std::string text(indent, ' ');
        text.append("Segment");
        msg_Dbg(obj, "%s", text.c_str());
        std::vector<SubSegment *>::const_iterator l;
        for(l = subsegments.begin(); l != subsegments.end(); ++l)
            (*l)->debug(obj, indent + 1);
    }
}

Url Segment::getUrlSegment() const
{
    if(sourceUrl.hasScheme())
    {
        return sourceUrl;
    }
    else
    {
        Url ret = getParentUrlSegment();
        if (!sourceUrl.empty())
            ret.append(sourceUrl);
        return ret;
    }
}

std::vector<ISegment*> Segment::subSegments()
{
    std::vector<ISegment*> list;
    if(!subsegments.empty())
    {
        std::vector<SubSegment*>::iterator it;
        for(it=subsegments.begin();it!=subsegments.end();++it)
            list.push_back(*it);
    }
    else
    {
        list.push_back(this);
    }
    return list;
}

InitSegment::InitSegment(ICanonicalUrl *parent) :
    Segment(parent)
{
    debugName = "InitSegment";
    classId = CLASSID_INITSEGMENT;
}

IndexSegment::IndexSegment(ICanonicalUrl *parent) :
    Segment(parent)
{
    debugName = "IndexSegment";
    classId = CLASSID_INDEXSEGMENT;
}

SubSegment::SubSegment(ISegment *main, size_t start, size_t end) :
    ISegment(main), parent(main)
{
    setByteRange(start, end);
    debugName = "SubSegment";
    classId = CLASSID_SUBSEGMENT;
}

Url SubSegment::getUrlSegment() const
{
    return getParentUrlSegment();
}

std::vector<ISegment*> SubSegment::subSegments()
{
    std::vector<ISegment*> list;
    list.push_back(this);
    return list;
}

void SubSegment::addSubSegment(SubSegment *)
{

}
<|endoftext|>