Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@ build/
conanbuildinfo.*
conaninfo.txt

# Default CLion Cmake build folder
cmake-build-debug
cmake-build-releas

# CLion IDE settings directory
.idea

35 changes: 35 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)

project(ProtocolSession CXX)

option(build_tests "build tests" OFF)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_STANDARD 11)

Expand Down Expand Up @@ -31,3 +33,36 @@ set(

# === build library ===
add_library(extension ${library_sources})

# === build tests ===
if(build_tests)

# test library prepared,
# mock headers not included, as they
set(
test_lib_source
test/Swarm.cpp
test/AbstractSessionController.cpp
test/BasicObserver.cpp
test/Utilities.cpp
#test/TorrentClient.cpp
#test/TorrentClientSwarm.cpp
)

# === test library ===
include_directories("${CMAKE_SOURCE_DIR}/test")

add_library(test_lib ${test_lib_source})

file(GLOB tests RELATIVE "${CMAKE_SOURCE_DIR}" "test/test_*.cpp")

enable_testing()

foreach(s ${tests})
get_filename_component (sn ${s} NAME_WE)
add_executable(${sn} ${s})
target_link_libraries(${sn} test_lib extension ${CONAN_LIBS})
add_test(${sn} "bin/${sn}")
endforeach(s)

endif()
13 changes: 13 additions & 0 deletions test/AbstractSessionController.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Created by bedeho on 09.03.17.
//

#include "AbstractSessionController.hpp"

AbstractSessionController::AbstractSessionController(const std::string & name)
: _name(name) {
}

std::string AbstractSessionController::name() const noexcept {
return _name;
}
63 changes: 63 additions & 0 deletions test/AbstractSessionController.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// Created by bedeho on 09.03.17.
//

#ifndef SESSIONCONTROLLER_HPP
#define SESSIONCONTROLLER_HPP

#include "PollableInterface.hpp"

#include <libtorrent/socket.hpp>

#include <boost/shared_ptr.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <unordered_map>
#include <boost/optional.hpp>

namespace libtorrent {
class session;
class alert;
struct torrent_info;

}

class AbstractSessionController : public PollableInterface {

public:

AbstractSessionController(const std::string & name);

/**
* Invitation to join the swarm for the given (ti) torrent
* @param ti torrent file information
* @param working_directory clean working directory which can be used
*/
virtual void join(const boost::shared_ptr<libtorrent::torrent_info> & ti,
const std::string & working_directory,
const std::string & payload_directory) = 0;

/**
* Returns endpoint upon which this session is listenning. An unset
* optional indicates it is not listening.
* @return
*/
virtual boost::optional<libtorrent::tcp::endpoint> session_endpoint() const = 0;

/**
* Notify controller about full peer list for swarm.
*/
virtual void swarm_peer_list_ready(const std::unordered_map<std::string, libtorrent::tcp::endpoint> &) = 0; // <= give list of endpoints and names, in order to have capcity to connect with howmever it wants, at the desired time in the future? simple policy is just to connect to all of them

/**
* Timeout processing
*/
virtual void poll() = 0;

std::string name() const noexcept;

private:

const std::string _name;
};

#endif //SESSIONCONTROLLER_HPP
5 changes: 5 additions & 0 deletions test/BasicBuyer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//
// Created by bedeho on 09.03.17.
//

#include "BasicBuyer.hpp"
8 changes: 8 additions & 0 deletions test/BasicBuyer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//
// Created by bedeho on 09.03.17.
//

#ifndef BASICBUYER_HPP
#define BASICBUYER_HPP

#endif //BASICBUYER_HPP
101 changes: 101 additions & 0 deletions test/BasicObserver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//
// Created by bedeho on 09.03.17.
//

#include "BasicObserver.hpp"
#include "Utilities.hpp"

BasicObserver::BasicObserver(const std::string & name)
: AbstractSessionController(name)
, _state(Init())
, _plugin(boost::make_shared<joystream::extension::Plugin>(1000)){

_session.add_extension(boost::static_pointer_cast<libtorrent::plugin>(_plugin));
}

void BasicObserver::join(const boost::shared_ptr<libtorrent::torrent_info> & ti, const std::string & working_directory, const std::string & payload_directory) {

if(boost::get<Init>(&_state)) {

// Update state
_state = AddingTorrent();

libtorrent::add_torrent_params params;
params.ti = ti;
params.save_path = working_directory; // since payload is not here, libtorrent will - by default, attempt to download content from peers

// We start a poller to allow blocking here,
// while still servicing this observers alert processing,
// until response from adding torrent returns

Poller poller;
poller.add(this);

// Add torrent using plugin
_plugin->submit(joystream::extension::request::AddTorrent(params, [this, params, &poller](libtorrent::error_code &ec,
libtorrent::torrent_handle &h) -> void {

assert(boost::get<AddingTorrent>(&_state));

if(ec)
this->_state = AddingTorrentFailed();
else {

this->_state = AddedTorrent(params, h);

// If swarm peers were provided prior to torrent being added, then connect now
if(_swarm_peers)
connect_to_all(h, _swarm_peers.get());


// bug ******** here *********

}

// Signal that poller can stop
poller.stop();

}));

// Start blocking poller
poller.start(); // add something about max time?

} else
throw std::runtime_error("Cannot join, no longer in Init state.");
}

boost::optional<libtorrent::tcp::endpoint> BasicObserver::session_endpoint() const {
return listening_endpoint(&_session);
}

void BasicObserver::swarm_peer_list_ready(const std::unordered_map<std::string, libtorrent::tcp::endpoint> & swarm_peers) {

// We can only process leer plist if torrent has been added successfully, if
// that has not yet occured, then we just hold on to list.

if (auto *added_torrent_state = boost::get<AddedTorrent>(&_state)) {

// For now, we simply connect to all, in the future,
// user can supply block/accept name list

connect_to_all(added_torrent_state->handle, swarm_peers);

} else
_swarm_peers = swarm_peers;

}

void BasicObserver::poll() {

// should some of this really be in based class??

process_pending_alert(&_session,
[this](libtorrent::alert * a) -> void {


if() {

}

});
}
74 changes: 74 additions & 0 deletions test/BasicObserver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// Created by bedeho on 09.03.17.
//

#ifndef BASICOBSERVER_HPP
#define BASICOBSERVER_HPP

#include "AbstractSessionController.hpp"

#include <extension/extension.hpp>

class BasicObserver : public AbstractSessionController {

public:

struct Init {};
struct AddingTorrent {};
struct AddingTorrentFailed {};
struct AddedTorrent {

struct StartingObserveMode {};
struct StartingObserveModeFailed {};

struct StartingPlugin {};
struct StartingPluginFailed {};
struct PluginStarted {};

typedef boost::variant<
StartingObserveMode,
StartingObserveModeFailed,
StartingPlugin,
StartingPluginFailed,
PluginStarted> State;

AddedTorrent(const libtorrent::add_torrent_params & params,
const libtorrent::torrent_handle & handle)
: state(StartingObserveMode())
, params(params)
, handle(handle) {}

State state;
libtorrent::add_torrent_params params;
libtorrent::torrent_handle handle;
};

typedef boost::variant<
Init,
AddingTorrent,
AddingTorrentFailed,
AddedTorrent> State;

BasicObserver(const std::string & name);

virtual void join(const boost::shared_ptr<libtorrent::torrent_info> & ti,
const std::string & working_directory,
const std::string & payload_directory);

virtual boost::optional<libtorrent::tcp::endpoint> session_endpoint() const;

virtual void swarm_peer_list_ready(const std::unordered_map<std::string, libtorrent::tcp::endpoint> &);

virtual void poll();

private:

State _state;
libtorrent::session _session;
boost::shared_ptr<joystream::extension::Plugin> _plugin;


boost::optional<std::unordered_map<std::string, libtorrent::tcp::endpoint>> _swarm_peers;
};

#endif //BASICOBSERVER_HPP
35 changes: 35 additions & 0 deletions test/MockAlertManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef EXTENSION_MOCK_ALERT_MANAGER_HPP
#define EXTENSION_MOCK_ALERT_MANAGER_HPP

#include <gmock/gmock.h>

#include <libtorrent/socket.hpp>

#include <extension/alert.hpp>
#include <extension/interface/AlertManagerInterface.hpp>

namespace joystream {
namespace test {
namespace extension {

class MockAlertManager : public interface::AlertManagerInterface {
public:
MOCK_METHOD0(native_handle, libtorrent::alert_manager*());
/*
* Template methods can't be mocked directly in gmock.
* We hence mock overloaded methods as per our use.
*/
MOCK_METHOD1(plugin_emplace_alert, void(extension::status::Plugin));
MOCK_METHOD1(request_emplace_alert, void(extension::alert::LoadedCallBack&));
MOCK_METHOD6(anchorAnnounced_emplace_alert, void(
libtorrent::torrent_handle, libtorrent::tcp::endpoint&,
quint64, const Coin::typesafeOutPoint&,
const Coin::PublicKey&, const Coin::PubKeyHash&
));
};

}
}
}

#endif // EXTENSION_MOCK_ALERT_MANAGER_HPP
27 changes: 27 additions & 0 deletions test/MockPeer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef GMOCK_MOCK_PEER_HPP
#define GMOCK_MOCK_PEER_HPP

#include <gmock/gmock.h>

#include <extension/interface/PeerInterface.hpp>

namespace joystream {
namespace test {
namespace extension {

class MockPeer : public interface::PeerInterface {
public:
MOCK_CONST_METHOD0(isOutgoing, bool());
MOCK_CONST_METHOD0(connect, void());
MOCK_CONST_METHOD1(getPeerInfo, void(libtorrent::peer_info &));
MOCK_CONST_METHOD3(sendBuffer, void(char const*, int, int=0));
MOCK_CONST_METHOD3(disconnect, void(libtorrent::error_code const&, libtorrent::operation_t, int=0));
MOCK_CONST_METHOD0(pid, libtorrent::peer_id const&());
MOCK_CONST_METHOD0(native_handle, libtorrent::peer_connection_handle());
};

}
}
}

#endif // GMOCK_MOCK_PEER_HPP
Loading