extend some unit tests. primarily test_alert_manager and fixed a bug in alert_manager

This commit is contained in:
Arvid Norberg 2015-04-11 22:02:30 +00:00
parent baaeac7809
commit 6f839a6d66
1 changed files with 129 additions and 20 deletions

View File

@ -38,6 +38,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#include "libtorrent/peer_info.hpp" #include "libtorrent/peer_info.hpp"
#include "libtorrent/bdecode.hpp" #include "libtorrent/bdecode.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/entry.hpp"
#include <cstring> #include <cstring>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <iostream> #include <iostream>
@ -58,8 +60,7 @@ int read_message(stream_socket& s, char* buffer)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) if (ec)
{ {
std::cout << aux::time_now_string() << ": " << ec.message() << std::endl; if (ec) TEST_ERROR(ec.message());
TEST_ERROR("read_message: " + ec.message());
return 0; return 0;
} }
char* ptr = buffer; char* ptr = buffer;
@ -69,13 +70,25 @@ int read_message(stream_socket& s, char* buffer)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) if (ec)
{ {
std::cout << aux::time_now_string() << ": " << ec.message() << std::endl; if (ec) TEST_ERROR(ec.message());
TEST_ERROR("read_message: " + ec.message());
return 0; return 0;
} }
return length; return length;
} }
void log(char const* fmt, ...)
{
va_list v;
va_start(v, fmt);
char buf[1024];
vsnprintf(buf, sizeof(buf), fmt, v);
va_end(v);
fprintf(stderr, "\x1b[34m%s: %s\x1b[0m\n"
, aux::time_now_string(), buf);
}
void print_message(char const* buffer, int len) void print_message(char const* buffer, int len)
{ {
char const* message_name[] = {"choke", "unchoke", "interested", "not_interested" char const* message_name[] = {"choke", "unchoke", "interested", "not_interested"
@ -116,12 +129,12 @@ void print_message(char const* buffer, int len)
} }
} }
fprintf(stderr, "%s <== %s %s\n", aux::time_now_string(), message, extra); log("<== %s %s", message, extra);
} }
void send_allow_fast(stream_socket& s, int piece) void send_allow_fast(stream_socket& s, int piece)
{ {
std::cout << aux::time_now_string() << " ==> allow fast: " << piece << std::endl; log(" ==> allow fast: %d", piece);
using namespace libtorrent::detail; using namespace libtorrent::detail;
char msg[] = "\0\0\0\x05\x11\0\0\0\0"; char msg[] = "\0\0\0\x05\x11\0\0\0\0";
char* ptr = msg + 5; char* ptr = msg + 5;
@ -129,11 +142,12 @@ void send_allow_fast(stream_socket& s, int piece)
error_code ec; error_code ec;
libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 9) libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 9)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
} }
void send_suggest_piece(stream_socket& s, int piece) void send_suggest_piece(stream_socket& s, int piece)
{ {
std::cout << aux::time_now_string() << " ==> suggest piece: " << piece << std::endl; log(" ==> suggest piece: %d", piece);
using namespace libtorrent::detail; using namespace libtorrent::detail;
char msg[] = "\0\0\0\x05\x0d\0\0\0\0"; char msg[] = "\0\0\0\x05\x0d\0\0\0\0";
char* ptr = msg + 5; char* ptr = msg + 5;
@ -141,42 +155,47 @@ void send_suggest_piece(stream_socket& s, int piece)
error_code ec; error_code ec;
libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 9) libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 9)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
} }
void send_keepalive(stream_socket& s) void send_keepalive(stream_socket& s)
{ {
std::cout << aux::time_now_string() << " ==> keepalive" << std::endl; log(" ==> keepalive");
char msg[] = "\0\0\0\0"; char msg[] = "\0\0\0\0";
error_code ec; error_code ec;
libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 4) libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 4)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
} }
void send_unchoke(stream_socket& s) void send_unchoke(stream_socket& s)
{ {
std::cout << aux::time_now_string() << " ==> unchoke" << std::endl; log(" ==> unchoke");
char msg[] = "\0\0\0\x01\x01"; char msg[] = "\0\0\0\x01\x01";
error_code ec; error_code ec;
libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 5) libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 5)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
} }
void send_have_all(stream_socket& s) void send_have_all(stream_socket& s)
{ {
std::cout << aux::time_now_string() << " ==> have_all" << std::endl; log(" ==> have_all");
char msg[] = "\0\0\0\x01\x0e"; // have_all char msg[] = "\0\0\0\x01\x0e"; // have_all
error_code ec; error_code ec;
libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 5) libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 5)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
} }
void send_have_none(stream_socket& s) void send_have_none(stream_socket& s)
{ {
std::cout << aux::time_now_string() << " ==> have_none" << std::endl; log(" ==> have_none");
char msg[] = "\0\0\0\x01\x0f"; // have_none char msg[] = "\0\0\0\x01\x0f"; // have_none
error_code ec; error_code ec;
libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 5) libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 5)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
} }
void send_bitfield(stream_socket& s, char const* bits) void send_bitfield(stream_socket& s, char const* bits)
@ -190,7 +209,7 @@ void send_bitfield(stream_socket& s, char const* bits)
char* ptr = msg; char* ptr = msg;
write_int32(packet_size-4, ptr); write_int32(packet_size-4, ptr);
write_int8(5, ptr); write_int8(5, ptr);
std::cout << aux::time_now_string() << " ==> bitfield [" << bits << "]" << std::endl;; log(" ==> bitfield [%s]");
for (int i = 0; i < num_pieces; ++i) for (int i = 0; i < num_pieces; ++i)
{ {
ptr[i/8] |= (bits[i] == '1' ? 1 : 0) << i % 8; ptr[i/8] |= (bits[i] == '1' ? 1 : 0) << i % 8;
@ -198,6 +217,7 @@ void send_bitfield(stream_socket& s, char const* bits)
error_code ec; error_code ec;
libtorrent::asio::write(s, libtorrent::asio::buffer(msg, packet_size) libtorrent::asio::write(s, libtorrent::asio::buffer(msg, packet_size)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
} }
void do_handshake(stream_socket& s, sha1_hash const& ih, char* buffer) void do_handshake(stream_socket& s, sha1_hash const& ih, char* buffer)
@ -205,11 +225,16 @@ void do_handshake(stream_socket& s, sha1_hash const& ih, char* buffer)
char handshake[] = "\x13" "BitTorrent protocol\0\0\0\0\0\x10\0\x04" char handshake[] = "\x13" "BitTorrent protocol\0\0\0\0\0\x10\0\x04"
" " // space for info-hash " " // space for info-hash
"aaaaaaaaaaaaaaaaaaaa"; // peer-id "aaaaaaaaaaaaaaaaaaaa"; // peer-id
std::cout << aux::time_now_string() << " ==> handshake" << std::endl; log(" ==> handshake");
error_code ec; error_code ec;
std::memcpy(handshake + 28, ih.begin(), 20); std::memcpy(handshake + 28, ih.begin(), 20);
libtorrent::asio::write(s, libtorrent::asio::buffer(handshake, sizeof(handshake) - 1) libtorrent::asio::write(s, libtorrent::asio::buffer(handshake, sizeof(handshake) - 1)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec)
{
TEST_ERROR(ec.message());
return;
}
// read handshake // read handshake
libtorrent::asio::read(s, libtorrent::asio::buffer(buffer, 68) libtorrent::asio::read(s, libtorrent::asio::buffer(buffer, 68)
@ -219,7 +244,7 @@ void do_handshake(stream_socket& s, sha1_hash const& ih, char* buffer)
TEST_ERROR(ec.message()); TEST_ERROR(ec.message());
return; return;
} }
std::cout << aux::time_now_string() << " <== handshake" << std::endl; log(" <== handshake");
TEST_CHECK(buffer[0] == 19); TEST_CHECK(buffer[0] == 19);
TEST_CHECK(std::memcmp(buffer + 1, "BitTorrent protocol", 19) == 0); TEST_CHECK(std::memcmp(buffer + 1, "BitTorrent protocol", 19) == 0);
@ -241,13 +266,39 @@ void do_handshake(stream_socket& s, sha1_hash const& ih, char* buffer)
TEST_CHECK(std::memcmp(buffer + 28, ih.begin(), 20) == 0); TEST_CHECK(std::memcmp(buffer + 28, ih.begin(), 20) == 0);
} }
void send_extension_handshake(stream_socket& s, entry const& e)
{
std::vector<char> buf;
// reserve space for the message header
// uint32: packet-length
// uint8: 20 (extension message)
// uint8: 0 (handshake)
buf.resize(4 + 1 + 1);
bencode(std::back_inserter(buf), e);
using namespace libtorrent::detail;
char* ptr = &buf[0];
write_uint32(buf.size() - 4, ptr);
write_uint8(20, ptr);
write_uint8(0, ptr);
error_code ec;
libtorrent::asio::write(s, libtorrent::asio::buffer(&buf[0], buf.size())
, libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
}
boost::shared_ptr<torrent_info> setup_peer(stream_socket& s, sha1_hash& ih boost::shared_ptr<torrent_info> setup_peer(stream_socket& s, sha1_hash& ih
, boost::shared_ptr<lt::session>& ses, torrent_handle* th = NULL) , boost::shared_ptr<lt::session>& ses, torrent_handle* th = NULL)
{ {
boost::shared_ptr<torrent_info> t = ::create_torrent(); boost::shared_ptr<torrent_info> t = ::create_torrent();
ih = t->info_hash(); ih = t->info_hash();
ses.reset(new lt::session(fingerprint("LT", 0, 1, 0, 0) ses.reset(new lt::session(fingerprint("LT", 0, 1, 0, 0)
, std::make_pair(48900, 49000), "0.0.0.0", 0, alert::all_categories)); , std::make_pair(48900, 49000), "0.0.0.0", session::add_default_plugins
, alert::all_categories));
error_code ec; error_code ec;
add_torrent_params p; add_torrent_params p;
@ -257,7 +308,7 @@ boost::shared_ptr<torrent_info> setup_peer(stream_socket& s, sha1_hash& ih
p.save_path = "./tmp1_fast"; p.save_path = "./tmp1_fast";
remove("./tmp1_fast/temporary", ec); remove("./tmp1_fast/temporary", ec);
if (ec) fprintf(stderr, "remove(): %s\n", ec.message().c_str()); if (ec) log("remove(): %s", ec.message().c_str());
ec.clear(); ec.clear();
torrent_handle ret = ses->add_torrent(p, ec); torrent_handle ret = ses->add_torrent(p, ec);
if (th) *th = ret; if (th) *th = ret;
@ -266,6 +317,7 @@ boost::shared_ptr<torrent_info> setup_peer(stream_socket& s, sha1_hash& ih
wait_for_downloading(*ses, "ses"); wait_for_downloading(*ses, "ses");
s.connect(tcp::endpoint(address::from_string("127.0.0.1", ec), ses->listen_port()), ec); s.connect(tcp::endpoint(address::from_string("127.0.0.1", ec), ses->listen_port()), ec);
if (ec) TEST_ERROR(ec.message());
print_session_log(*ses); print_session_log(*ses);
@ -320,11 +372,21 @@ void test_reject_fast()
// send reject request // send reject request
recv_buffer[0] = 0x10; recv_buffer[0] = 0x10;
error_code ec; error_code ec;
std::cerr << aux::time_now_string() << " ==> reject" << std::endl; log(" ==> reject");
libtorrent::asio::write(s, libtorrent::asio::buffer("\0\0\0\x0d", 4) libtorrent::asio::write(s, libtorrent::asio::buffer("\0\0\0\x0d", 4)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec)
{
TEST_ERROR(ec.message());
break;
}
libtorrent::asio::write(s, libtorrent::asio::buffer(recv_buffer, 13) libtorrent::asio::write(s, libtorrent::asio::buffer(recv_buffer, 13)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec)
{
TEST_ERROR(ec.message());
break;
}
} }
print_session_log(*ses); print_session_log(*ses);
s.close(); s.close();
@ -386,11 +448,21 @@ void test_respect_suggest()
// send reject request // send reject request
recv_buffer[0] = 0x10; recv_buffer[0] = 0x10;
error_code ec; error_code ec;
std::cerr << aux::time_now_string() << " ==> reject" << std::endl; log(" ==> reject");
libtorrent::asio::write(s, libtorrent::asio::buffer("\0\0\0\x0d", 4) libtorrent::asio::write(s, libtorrent::asio::buffer("\0\0\0\x0d", 4)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec)
{
TEST_ERROR(ec.message());
break;
}
libtorrent::asio::write(s, libtorrent::asio::buffer(recv_buffer, 13) libtorrent::asio::write(s, libtorrent::asio::buffer(recv_buffer, 13)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec)
{
TEST_ERROR(ec.message());
break;
}
} }
print_session_log(*ses); print_session_log(*ses);
TEST_CHECK(fail_counter > 0); TEST_CHECK(fail_counter > 0);
@ -515,12 +587,12 @@ void test_dont_have()
int ret = bdecode(recv_buffer + 2, recv_buffer + len, e, ec, &pos); int ret = bdecode(recv_buffer + 2, recv_buffer + len, e, ec, &pos);
if (ret != 0) if (ret != 0)
{ {
fprintf(stderr, "failed to parse extension handshake: %s at pos %d\n" log("failed to parse extension handshake: %s at pos %d"
, ec.message().c_str(), pos); , ec.message().c_str(), pos);
} }
TEST_EQUAL(ret, 0); TEST_EQUAL(ret, 0);
printf("extension handshake: %s\n", print_entry(e).c_str()); log("extension handshake: %s", print_entry(e).c_str());
bdecode_node m = e.dict_find_dict("m"); bdecode_node m = e.dict_find_dict("m");
TEST_CHECK(m); TEST_CHECK(m);
if (!m) return; if (!m) return;
@ -540,6 +612,7 @@ void test_dont_have()
libtorrent::asio::write(s, libtorrent::asio::buffer(recv_buffer, 10) libtorrent::asio::write(s, libtorrent::asio::buffer(recv_buffer, 10)
, libtorrent::asio::transfer_all(), ec); , libtorrent::asio::transfer_all(), ec);
if (ec) TEST_ERROR(ec.message());
print_session_log(*ses); print_session_log(*ses);
@ -562,6 +635,41 @@ void test_dont_have()
print_session_log(*ses); print_session_log(*ses);
} }
// TEST metadata extension messages and edge cases
// this tests sending a request for a metadata piece that's too high. This is
// pos
void test_invalid_metadata_requests()
{
using namespace libtorrent::detail;
std::cerr << " === test invalid metadata ===" << std::endl;
sha1_hash ih;
boost::shared_ptr<lt::session> ses;
io_service ios;
stream_socket s(ios);
boost::shared_ptr<torrent_info> ti = setup_peer(s, ih, ses);
char recv_buffer[1000];
do_handshake(s, ih, recv_buffer);
print_session_log(*ses);
send_have_all(s);
print_session_log(*ses);
entry extensions;
extensions["m"]["ut_metadata"] = 1;
send_extension_handshake(s, extensions);
#error read messages until we get the extension handshake back. extract the \
message code for ut_metadata
test_sleep(1000);
print_session_log(*ses);
TEST_ERROR("test");
}
int test_main() int test_main()
{ {
test_reject_fast(); test_reject_fast();
@ -569,6 +677,7 @@ int test_main()
test_multiple_bitfields(); test_multiple_bitfields();
test_multiple_have_all(); test_multiple_have_all();
test_dont_have(); test_dont_have();
test_invalid_metadata_requests();
return 0; return 0;
} }