forked from premiere/premiere-libtorrent
split up test_primitives into more tests (in an attempt to get the link-time down within the regression test time limit)
This commit is contained in:
parent
fcdd839e87
commit
dd192cfd3c
|
@ -323,7 +323,10 @@ if(build_tests)
|
|||
test_peer_priority
|
||||
test_bencoding
|
||||
test_bdecode_performance
|
||||
test_xml
|
||||
test_string
|
||||
test_primitives
|
||||
test_http_parser
|
||||
test_ip_filter
|
||||
test_hasher
|
||||
test_metadata_extension
|
||||
|
|
|
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <cctype>
|
||||
#include <cstring>
|
||||
|
||||
#include "libtorrent/assert.hpp"
|
||||
#include "libtorrent/escape_string.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
|
|
|
@ -70,6 +70,9 @@ test-suite libtorrent :
|
|||
[ run test_bencoding.cpp ]
|
||||
[ run test_fast_extension.cpp ]
|
||||
[ run test_primitives.cpp ]
|
||||
[ run test_http_parser.cpp ]
|
||||
[ run test_string.cpp ]
|
||||
[ run test_xml.cpp ]
|
||||
[ run test_ip_filter.cpp ]
|
||||
[ run test_hasher.cpp ]
|
||||
[ run test_dht.cpp ]
|
||||
|
|
|
@ -19,7 +19,10 @@ test_programs = \
|
|||
test_peer_priority \
|
||||
test_pex \
|
||||
test_piece_picker \
|
||||
test_xml \
|
||||
test_string \
|
||||
test_primitives \
|
||||
test_http_parser \
|
||||
test_rss \
|
||||
test_storage \
|
||||
test_swarm \
|
||||
|
|
|
@ -38,6 +38,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket_io.hpp" // for hash_address
|
||||
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6
|
||||
#include "libtorrent/alert_dispatcher.hpp"
|
||||
|
||||
#include "libtorrent/kademlia/node_id.hpp"
|
||||
#include "libtorrent/kademlia/routing_table.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#include "test.hpp"
|
||||
|
@ -46,6 +49,33 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
using namespace libtorrent;
|
||||
using namespace libtorrent::dht;
|
||||
|
||||
sha1_hash to_hash(char const* s)
|
||||
{
|
||||
sha1_hash ret;
|
||||
from_hex(s, 40, (char*)&ret[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void add_and_replace(libtorrent::dht::node_id& dst, libtorrent::dht::node_id const& add)
|
||||
{
|
||||
bool carry = false;
|
||||
for (int k = 19; k >= 0; --k)
|
||||
{
|
||||
int sum = dst[k] + add[k] + (carry?1:0);
|
||||
dst[k] = sum & 255;
|
||||
carry = sum > 255;
|
||||
}
|
||||
}
|
||||
|
||||
void node_push_back(void* userdata, libtorrent::dht::node_entry const& n)
|
||||
{
|
||||
using namespace libtorrent::dht;
|
||||
std::vector<node_entry>* nv = (std::vector<node_entry>*)userdata;
|
||||
nv->push_back(n);
|
||||
}
|
||||
|
||||
void nop(void* userdata, libtorrent::dht::node_entry const& n) {}
|
||||
|
||||
std::list<std::pair<udp::endpoint, entry> > g_responses;
|
||||
|
||||
struct mock_socket : udp_socket_interface
|
||||
|
@ -651,6 +681,327 @@ int test_main()
|
|||
#endif
|
||||
}
|
||||
|
||||
// test verify_message
|
||||
const static key_desc_t msg_desc[] = {
|
||||
{"A", lazy_entry::string_t, 4, 0},
|
||||
{"B", lazy_entry::dict_t, 0, key_desc_t::optional | key_desc_t::parse_children},
|
||||
{"B1", lazy_entry::string_t, 0, 0},
|
||||
{"B2", lazy_entry::string_t, 0, key_desc_t::last_child},
|
||||
{"C", lazy_entry::dict_t, 0, key_desc_t::optional | key_desc_t::parse_children},
|
||||
{"C1", lazy_entry::string_t, 0, 0},
|
||||
{"C2", lazy_entry::string_t, 0, key_desc_t::last_child},
|
||||
};
|
||||
|
||||
lazy_entry const* msg_keys[7];
|
||||
|
||||
lazy_entry ent;
|
||||
|
||||
error_code ec;
|
||||
char const test_msg[] = "d1:A4:test1:Bd2:B15:test22:B25:test3ee";
|
||||
lazy_bdecode(test_msg, test_msg + sizeof(test_msg)-1, ent, ec);
|
||||
fprintf(stderr, "%s\n", print_entry(ent).c_str());
|
||||
|
||||
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
|
||||
TEST_CHECK(ret);
|
||||
TEST_CHECK(msg_keys[0]);
|
||||
if (msg_keys[0]) TEST_EQUAL(msg_keys[0]->string_value(), "test");
|
||||
TEST_CHECK(msg_keys[1]);
|
||||
TEST_CHECK(msg_keys[2]);
|
||||
if (msg_keys[2]) TEST_EQUAL(msg_keys[2]->string_value(), "test2");
|
||||
TEST_CHECK(msg_keys[3]);
|
||||
if (msg_keys[3]) TEST_EQUAL(msg_keys[3]->string_value(), "test3");
|
||||
TEST_CHECK(msg_keys[4] == 0);
|
||||
TEST_CHECK(msg_keys[5] == 0);
|
||||
TEST_CHECK(msg_keys[6] == 0);
|
||||
|
||||
char const test_msg2[] = "d1:A4:test1:Cd2:C15:test22:C25:test3ee";
|
||||
lazy_bdecode(test_msg2, test_msg2 + sizeof(test_msg2)-1, ent, ec);
|
||||
fprintf(stderr, "%s\n", print_entry(ent).c_str());
|
||||
|
||||
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
|
||||
TEST_CHECK(ret);
|
||||
TEST_CHECK(msg_keys[0]);
|
||||
if (msg_keys[0]) TEST_EQUAL(msg_keys[0]->string_value(), "test");
|
||||
TEST_CHECK(msg_keys[1] == 0);
|
||||
TEST_CHECK(msg_keys[2] == 0);
|
||||
TEST_CHECK(msg_keys[3] == 0);
|
||||
TEST_CHECK(msg_keys[4]);
|
||||
TEST_CHECK(msg_keys[5]);
|
||||
if (msg_keys[5]) TEST_EQUAL(msg_keys[5]->string_value(), "test2");
|
||||
TEST_CHECK(msg_keys[6]);
|
||||
if (msg_keys[6]) TEST_EQUAL(msg_keys[6]->string_value(), "test3");
|
||||
|
||||
|
||||
char const test_msg3[] = "d1:Cd2:C15:test22:C25:test3ee";
|
||||
lazy_bdecode(test_msg3, test_msg3 + sizeof(test_msg3)-1, ent, ec);
|
||||
fprintf(stderr, "%s\n", print_entry(ent).c_str());
|
||||
|
||||
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
|
||||
TEST_CHECK(!ret);
|
||||
fprintf(stderr, "%s\n", error_string);
|
||||
TEST_EQUAL(error_string, std::string("missing 'A' key"));
|
||||
|
||||
char const test_msg4[] = "d1:A6:foobare";
|
||||
lazy_bdecode(test_msg4, test_msg4 + sizeof(test_msg4)-1, ent, ec);
|
||||
fprintf(stderr, "%s\n", print_entry(ent).c_str());
|
||||
|
||||
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
|
||||
TEST_CHECK(!ret);
|
||||
fprintf(stderr, "%s\n", error_string);
|
||||
TEST_EQUAL(error_string, std::string("invalid value for 'A'"));
|
||||
|
||||
char const test_msg5[] = "d1:A4:test1:Cd2:C15:test2ee";
|
||||
lazy_bdecode(test_msg5, test_msg5 + sizeof(test_msg5)-1, ent, ec);
|
||||
fprintf(stderr, "%s\n", print_entry(ent).c_str());
|
||||
|
||||
ret = verify_message(&ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string));
|
||||
TEST_CHECK(!ret);
|
||||
fprintf(stderr, "%s\n", error_string);
|
||||
TEST_EQUAL(error_string, std::string("missing 'C2' key"));
|
||||
|
||||
// test empty strings [ { "":1 }, "" ]
|
||||
char const test_msg6[] = "ld0:i1ee0:e";
|
||||
lazy_bdecode(test_msg6, test_msg6 + sizeof(test_msg6)-1, ent, ec);
|
||||
fprintf(stderr, "%s\n", print_entry(ent).c_str());
|
||||
TEST_CHECK(ent.type() == lazy_entry::list_t);
|
||||
if (ent.type() == lazy_entry::list_t)
|
||||
{
|
||||
TEST_CHECK(ent.list_size() == 2);
|
||||
if (ent.list_size() == 2)
|
||||
{
|
||||
TEST_CHECK(ent.list_at(0)->dict_find_int_value("") == 1);
|
||||
TEST_CHECK(ent.list_at(1)->string_value() == "");
|
||||
}
|
||||
}
|
||||
|
||||
// test kademlia functions
|
||||
|
||||
using namespace libtorrent::dht;
|
||||
|
||||
for (int i = 0; i < 160; i += 8)
|
||||
{
|
||||
for (int j = 0; j < 160; j += 8)
|
||||
{
|
||||
node_id a(0);
|
||||
a[(159-i) / 8] = 1 << (i & 7);
|
||||
node_id b(0);
|
||||
b[(159-j) / 8] = 1 << (j & 7);
|
||||
int dist = distance_exp(a, b);
|
||||
|
||||
TEST_CHECK(dist >= 0 && dist < 160);
|
||||
TEST_CHECK(dist == ((i == j)?0:(std::max)(i, j)));
|
||||
|
||||
for (int k = 0; k < 160; k += 8)
|
||||
{
|
||||
node_id c(0);
|
||||
c[(159-k) / 8] = 1 << (k & 7);
|
||||
|
||||
bool cmp = compare_ref(a, b, c);
|
||||
TEST_CHECK(cmp == (distance(a, c) < distance(b, c)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// test kademlia routing table
|
||||
dht_settings s;
|
||||
// s.restrict_routing_ips = false;
|
||||
node_id id = to_hash("3123456789abcdef01232456789abcdef0123456");
|
||||
dht::routing_table table(id, 10, s);
|
||||
std::vector<node_entry> nodes;
|
||||
TEST_EQUAL(table.size().get<0>(), 0);
|
||||
|
||||
node_id tmp = id;
|
||||
node_id diff = to_hash("15764f7459456a9453f8719b09547c11d5f34061");
|
||||
|
||||
// test a node with the same IP:port changing ID
|
||||
add_and_replace(tmp, diff);
|
||||
table.node_seen(tmp, udp::endpoint(address::from_string("4.4.4.4"), 4), 10);
|
||||
table.find_node(id, nodes, 0, 10);
|
||||
TEST_EQUAL(table.bucket_size(0), 1);
|
||||
TEST_EQUAL(table.size().get<0>(), 1);
|
||||
TEST_EQUAL(nodes.size(), 1);
|
||||
if (!nodes.empty())
|
||||
{
|
||||
TEST_EQUAL(nodes[0].id, tmp);
|
||||
TEST_EQUAL(nodes[0].addr(), address_v4::from_string("4.4.4.4"));
|
||||
TEST_EQUAL(nodes[0].port(), 4);
|
||||
TEST_EQUAL(nodes[0].timeout_count, 0);
|
||||
}
|
||||
|
||||
// set timeout_count to 1
|
||||
table.node_failed(tmp, udp::endpoint(address_v4::from_string("4.4.4.4"), 4));
|
||||
|
||||
nodes.clear();
|
||||
table.for_each_node(node_push_back, nop, &nodes);
|
||||
TEST_EQUAL(nodes.size(), 1);
|
||||
if (!nodes.empty())
|
||||
{
|
||||
TEST_EQUAL(nodes[0].id, tmp);
|
||||
TEST_EQUAL(nodes[0].addr(), address_v4::from_string("4.4.4.4"));
|
||||
TEST_EQUAL(nodes[0].port(), 4);
|
||||
TEST_EQUAL(nodes[0].timeout_count, 1);
|
||||
}
|
||||
|
||||
// add the exact same node again, it should set the timeout_count to 0
|
||||
table.node_seen(tmp, udp::endpoint(address::from_string("4.4.4.4"), 4), 10);
|
||||
nodes.clear();
|
||||
table.for_each_node(node_push_back, nop, &nodes);
|
||||
TEST_EQUAL(nodes.size(), 1);
|
||||
if (!nodes.empty())
|
||||
{
|
||||
TEST_EQUAL(nodes[0].id, tmp);
|
||||
TEST_EQUAL(nodes[0].addr(), address_v4::from_string("4.4.4.4"));
|
||||
TEST_EQUAL(nodes[0].port(), 4);
|
||||
TEST_EQUAL(nodes[0].timeout_count, 0);
|
||||
}
|
||||
|
||||
// test adding the same IP:port again with a new node ID (should replace the old one)
|
||||
add_and_replace(tmp, diff);
|
||||
table.node_seen(tmp, udp::endpoint(address::from_string("4.4.4.4"), 4), 10);
|
||||
table.find_node(id, nodes, 0, 10);
|
||||
TEST_EQUAL(table.bucket_size(0), 1);
|
||||
TEST_EQUAL(nodes.size(), 1);
|
||||
if (!nodes.empty())
|
||||
{
|
||||
TEST_EQUAL(nodes[0].id, tmp);
|
||||
TEST_EQUAL(nodes[0].addr(), address_v4::from_string("4.4.4.4"));
|
||||
TEST_EQUAL(nodes[0].port(), 4);
|
||||
}
|
||||
|
||||
// test adding the same node ID again with a different IP (should be ignored)
|
||||
table.node_seen(tmp, udp::endpoint(address::from_string("4.4.4.4"), 5), 10);
|
||||
table.find_node(id, nodes, 0, 10);
|
||||
TEST_EQUAL(table.bucket_size(0), 1);
|
||||
if (!nodes.empty())
|
||||
{
|
||||
TEST_EQUAL(nodes[0].id, tmp);
|
||||
TEST_EQUAL(nodes[0].addr(), address_v4::from_string("4.4.4.4"));
|
||||
TEST_EQUAL(nodes[0].port(), 4);
|
||||
}
|
||||
|
||||
// test adding a node that ends up in the same bucket with an IP
|
||||
// very close to the current one (should be ignored)
|
||||
// if restrict_routing_ips == true
|
||||
table.node_seen(tmp, udp::endpoint(address::from_string("4.4.4.5"), 5), 10);
|
||||
table.find_node(id, nodes, 0, 10);
|
||||
TEST_EQUAL(table.bucket_size(0), 1);
|
||||
if (!nodes.empty())
|
||||
{
|
||||
TEST_EQUAL(nodes[0].id, tmp);
|
||||
TEST_EQUAL(nodes[0].addr(), address_v4::from_string("4.4.4.4"));
|
||||
TEST_EQUAL(nodes[0].port(), 4);
|
||||
}
|
||||
|
||||
s.restrict_routing_ips = false;
|
||||
|
||||
add_and_replace(tmp, diff);
|
||||
table.node_seen(id, udp::endpoint(rand_v4(), rand()), 10);
|
||||
|
||||
nodes.clear();
|
||||
for (int i = 0; i < 7000; ++i)
|
||||
{
|
||||
table.node_seen(tmp, udp::endpoint(rand_v4(), rand()), 10);
|
||||
add_and_replace(tmp, diff);
|
||||
}
|
||||
TEST_EQUAL(table.num_active_buckets(), 11);
|
||||
TEST_CHECK(table.size().get<0>() > 10 * 10);
|
||||
//#error test num_global_nodes
|
||||
//#error test need_refresh
|
||||
|
||||
#if defined TORRENT_DHT_VERBOSE_LOGGING || defined TORRENT_DEBUG
|
||||
table.print_state(std::cerr);
|
||||
#endif
|
||||
|
||||
table.for_each_node(node_push_back, nop, &nodes);
|
||||
|
||||
std::cout << "nodes: " << nodes.size() << std::endl;
|
||||
|
||||
std::vector<node_entry> temp;
|
||||
|
||||
std::generate(tmp.begin(), tmp.end(), &std::rand);
|
||||
table.find_node(tmp, temp, 0, nodes.size() * 2);
|
||||
std::cout << "returned: " << temp.size() << std::endl;
|
||||
TEST_EQUAL(temp.size(), nodes.size());
|
||||
|
||||
std::generate(tmp.begin(), tmp.end(), &std::rand);
|
||||
table.find_node(tmp, temp, 0, 7);
|
||||
std::cout << "returned: " << temp.size() << std::endl;
|
||||
TEST_EQUAL(temp.size(), 7);
|
||||
|
||||
std::sort(nodes.begin(), nodes.end(), boost::bind(&compare_ref
|
||||
, boost::bind(&node_entry::id, _1)
|
||||
, boost::bind(&node_entry::id, _2), tmp));
|
||||
|
||||
int hits = 0;
|
||||
// This makes sure enough of the nodes returned are actually
|
||||
// part of the closest nodes
|
||||
for (std::vector<node_entry>::iterator i = temp.begin()
|
||||
, end(temp.end()); i != end; ++i)
|
||||
{
|
||||
int hit = std::find_if(nodes.begin(), nodes.end()
|
||||
, boost::bind(&node_entry::id, _1) == i->id) - nodes.begin();
|
||||
// std::cerr << hit << std::endl;
|
||||
if (hit < int(temp.size())) ++hits;
|
||||
}
|
||||
std::cout << "hits: " << hits << std::endl;
|
||||
TEST_CHECK(hits == int(temp.size()));
|
||||
|
||||
std::generate(tmp.begin(), tmp.end(), &std::rand);
|
||||
table.find_node(tmp, temp, 0, 15);
|
||||
std::cout << "returned: " << temp.size() << std::endl;
|
||||
TEST_EQUAL(int(temp.size()), (std::min)(15, int(nodes.size())));
|
||||
|
||||
std::sort(nodes.begin(), nodes.end(), boost::bind(&compare_ref
|
||||
, boost::bind(&node_entry::id, _1)
|
||||
, boost::bind(&node_entry::id, _2), tmp));
|
||||
|
||||
hits = 0;
|
||||
// This makes sure enough of the nodes returned are actually
|
||||
// part of the closest nodes
|
||||
for (std::vector<node_entry>::iterator i = temp.begin()
|
||||
, end(temp.end()); i != end; ++i)
|
||||
{
|
||||
int hit = std::find_if(nodes.begin(), nodes.end()
|
||||
, boost::bind(&node_entry::id, _1) == i->id) - nodes.begin();
|
||||
// std::cerr << hit << std::endl;
|
||||
if (hit < int(temp.size())) ++hits;
|
||||
}
|
||||
std::cout << "hits: " << hits << std::endl;
|
||||
TEST_CHECK(hits == int(temp.size()));
|
||||
|
||||
using namespace libtorrent::dht;
|
||||
|
||||
char const* ips[] = {
|
||||
"124.31.75.21",
|
||||
"21.75.31.124",
|
||||
"65.23.51.170",
|
||||
"84.124.73.14",
|
||||
"43.213.53.83",
|
||||
};
|
||||
|
||||
int rs[] = { 1,86,22,65,90 };
|
||||
|
||||
boost::uint8_t prefixes[][4] =
|
||||
{
|
||||
{ 0x17, 0x12, 0xf6, 0xc7 },
|
||||
{ 0x94, 0x64, 0x06, 0xc1 },
|
||||
{ 0xfe, 0xfd, 0x92, 0x20 },
|
||||
{ 0xaf, 0x15, 0x46, 0xdd },
|
||||
{ 0xa9, 0xe9, 0x20, 0xbf }
|
||||
};
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
address a = address_v4::from_string(ips[i]);
|
||||
node_id id = generate_id_impl(a, rs[i]);
|
||||
for (int j = 0; j < 4; ++j)
|
||||
TEST_CHECK(id[j] == prefixes[i][j]);
|
||||
TEST_CHECK(id[19] == rs[i]);
|
||||
fprintf(stderr, "IP address: %s r: %d node ID: %s\n", ips[i]
|
||||
, rs[i], to_hex(id.to_string()).c_str());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,132 @@ int test_main()
|
|||
remove_all("file_test_dir2", ec);
|
||||
if (ec) fprintf(stderr, "remove_all: %s\n", ec.message().c_str());
|
||||
|
||||
// test path functions
|
||||
TEST_EQUAL(combine_path("test1/", "test2"), "test1/test2");
|
||||
#ifdef TORRENT_WINDOWS
|
||||
TEST_EQUAL(combine_path("test1\\", "test2"), "test1\\test2");
|
||||
TEST_EQUAL(combine_path("test1", "test2"), "test1\\test2");
|
||||
#else
|
||||
TEST_EQUAL(combine_path("test1", "test2"), "test1/test2");
|
||||
#endif
|
||||
|
||||
#if TORRENT_USE_UNC_PATHS
|
||||
TEST_EQUAL(canonicalize_path("c:\\a\\..\\b"), "c:\\b");
|
||||
TEST_EQUAL(canonicalize_path("a\\..\\b"), "b");
|
||||
TEST_EQUAL(canonicalize_path("a\\..\\.\\b"), "b");
|
||||
TEST_EQUAL(canonicalize_path("\\.\\a"), "\\a");
|
||||
TEST_EQUAL(canonicalize_path("\\\\bla\\.\\a"), "\\\\bla\\a");
|
||||
TEST_EQUAL(canonicalize_path("c:\\bla\\a"), "c:\\bla\\a");
|
||||
#endif
|
||||
|
||||
TEST_EQUAL(extension("blah"), "");
|
||||
TEST_EQUAL(extension("blah.exe"), ".exe");
|
||||
TEST_EQUAL(extension("blah.foo.bar"), ".bar");
|
||||
TEST_EQUAL(extension("blah.foo."), ".");
|
||||
|
||||
TEST_EQUAL(filename("blah"), "blah");
|
||||
TEST_EQUAL(filename("/blah/foo/bar"), "bar");
|
||||
TEST_EQUAL(filename("/blah/foo/bar/"), "bar");
|
||||
TEST_EQUAL(filename("blah/"), "blah");
|
||||
|
||||
#ifdef TORRENT_WINDOWS
|
||||
TEST_EQUAL(is_root_path("c:\\blah"), false);
|
||||
TEST_EQUAL(is_root_path("c:\\"), true);
|
||||
TEST_EQUAL(is_root_path("\\\\"), true);
|
||||
TEST_EQUAL(is_root_path("\\\\foobar"), true);
|
||||
TEST_EQUAL(is_root_path("\\\\foobar\\"), true);
|
||||
TEST_EQUAL(is_root_path("\\\\foobar/"), true);
|
||||
TEST_EQUAL(is_root_path("\\\\foo/bar"), false);
|
||||
TEST_EQUAL(is_root_path("\\\\foo\\bar\\"), false);
|
||||
#else
|
||||
TEST_EQUAL(is_root_path("/blah"), false);
|
||||
TEST_EQUAL(is_root_path("/"), true);
|
||||
#endif
|
||||
|
||||
// if has_parent_path() returns false
|
||||
// parent_path() should return the empty string
|
||||
TEST_EQUAL(parent_path("blah"), "");
|
||||
TEST_EQUAL(has_parent_path("blah"), false);
|
||||
TEST_EQUAL(parent_path("/blah/foo/bar"), "/blah/foo/");
|
||||
TEST_EQUAL(has_parent_path("/blah/foo/bar"), true);
|
||||
TEST_EQUAL(parent_path("/blah/foo/bar/"), "/blah/foo/");
|
||||
TEST_EQUAL(has_parent_path("/blah/foo/bar/"), true);
|
||||
TEST_EQUAL(parent_path("/a"), "/");
|
||||
TEST_EQUAL(has_parent_path("/a"), true);
|
||||
TEST_EQUAL(parent_path("/"), "");
|
||||
TEST_EQUAL(has_parent_path("/"), false);
|
||||
TEST_EQUAL(parent_path(""), "");
|
||||
TEST_EQUAL(has_parent_path(""), false);
|
||||
#ifdef TORRENT_WINDOWS
|
||||
TEST_EQUAL(parent_path("\\\\"), "");
|
||||
TEST_EQUAL(has_parent_path("\\\\"), false);
|
||||
TEST_EQUAL(parent_path("c:\\"), "");
|
||||
TEST_EQUAL(has_parent_path("c:\\"), false);
|
||||
TEST_EQUAL(parent_path("c:\\a"), "c:\\");
|
||||
TEST_EQUAL(has_parent_path("c:\\a"), true);
|
||||
TEST_EQUAL(has_parent_path("\\\\a"), false);
|
||||
TEST_EQUAL(has_parent_path("\\\\foobar/"), false);
|
||||
TEST_EQUAL(has_parent_path("\\\\foobar\\"), false);
|
||||
TEST_EQUAL(has_parent_path("\\\\foo/bar\\"), true);
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_WINDOWS
|
||||
TEST_EQUAL(is_complete("c:\\"), true);
|
||||
TEST_EQUAL(is_complete("c:\\foo\\bar"), true);
|
||||
TEST_EQUAL(is_complete("\\\\foo\\bar"), true);
|
||||
TEST_EQUAL(is_complete("foo/bar"), false);
|
||||
TEST_EQUAL(is_complete("\\\\"), true);
|
||||
#else
|
||||
TEST_EQUAL(is_complete("/foo/bar"), true);
|
||||
TEST_EQUAL(is_complete("foo/bar"), false);
|
||||
TEST_EQUAL(is_complete("/"), true);
|
||||
TEST_EQUAL(is_complete(""), false);
|
||||
#endif
|
||||
|
||||
// test split_string
|
||||
|
||||
char const* tags[10];
|
||||
char tags_str[] = " this is\ta test\t string\x01to be split and it cannot "
|
||||
"extend over the limit of elements \t";
|
||||
int ret = split_string(tags, 10, tags_str);
|
||||
|
||||
TEST_CHECK(ret == 10);
|
||||
TEST_CHECK(strcmp(tags[0], "this") == 0);
|
||||
TEST_CHECK(strcmp(tags[1], "is") == 0);
|
||||
TEST_CHECK(strcmp(tags[2], "a") == 0);
|
||||
TEST_CHECK(strcmp(tags[3], "test") == 0);
|
||||
TEST_CHECK(strcmp(tags[4], "string") == 0);
|
||||
TEST_CHECK(strcmp(tags[5], "to") == 0);
|
||||
TEST_CHECK(strcmp(tags[6], "be") == 0);
|
||||
TEST_CHECK(strcmp(tags[7], "split") == 0);
|
||||
TEST_CHECK(strcmp(tags[8], "and") == 0);
|
||||
TEST_CHECK(strcmp(tags[9], "it") == 0);
|
||||
|
||||
// replace_extension
|
||||
std::string test = "foo.bar";
|
||||
replace_extension(test, "txt");
|
||||
TEST_EQUAL(test, "foo.txt");
|
||||
|
||||
// file class
|
||||
file f;
|
||||
#if TORRENT_USE_UNC_PATHS || !defined WIN32
|
||||
TEST_CHECK(f.open("con", file::read_write, ec));
|
||||
#else
|
||||
TEST_CHECK(f.open("test_file", file::read_write, ec));
|
||||
#endif
|
||||
TEST_CHECK(!ec);
|
||||
if (ec) fprintf(stderr, "%s\n", ec.message().c_str());
|
||||
file::iovec_t b = {(void*)"test", 4};
|
||||
TEST_CHECK(f.writev(0, &b, 1, ec) == 4);
|
||||
TEST_CHECK(!ec);
|
||||
char test_buf[5] = {0};
|
||||
b.iov_base = test_buf;
|
||||
b.iov_len = 4;
|
||||
TEST_CHECK(f.readv(0, &b, 1, ec) == 4);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(strcmp(test_buf, "test") == 0);
|
||||
f.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2012, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "test.hpp"
|
||||
#include "libtorrent/http_parser.hpp"
|
||||
#include "libtorrent/parse_url.hpp"
|
||||
#include "libtorrent/size_type.hpp"
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/tuple/tuple_comparison.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
using boost::tuple;
|
||||
using boost::make_tuple;
|
||||
using boost::tie;
|
||||
|
||||
tuple<int, int, bool> feed_bytes(http_parser& parser, char const* str)
|
||||
{
|
||||
tuple<int, int, bool> ret(0, 0, false);
|
||||
tuple<int, int, bool> prev(0, 0, false);
|
||||
for (int chunks = 1; chunks < 70; ++chunks)
|
||||
{
|
||||
ret = make_tuple(0, 0, false);
|
||||
parser.reset();
|
||||
buffer::const_interval recv_buf(str, str);
|
||||
for (; *str;)
|
||||
{
|
||||
int chunk_size = (std::min)(chunks, int(strlen(recv_buf.end)));
|
||||
if (chunk_size == 0) break;
|
||||
recv_buf.end += chunk_size;
|
||||
int payload, protocol;
|
||||
bool error = false;
|
||||
tie(payload, protocol) = parser.incoming(recv_buf, error);
|
||||
ret.get<0>() += payload;
|
||||
ret.get<1>() += protocol;
|
||||
ret.get<2>() |= error;
|
||||
// std::cerr << payload << ", " << protocol << ", " << chunk_size << std::endl;
|
||||
TORRENT_ASSERT(payload + protocol == chunk_size);
|
||||
}
|
||||
TEST_CHECK(prev == make_tuple(0, 0, false) || ret == prev);
|
||||
TEST_EQUAL(ret.get<0>() + ret.get<1>(), strlen(str));
|
||||
prev = ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_main()
|
||||
{
|
||||
// HTTP request parser
|
||||
http_parser parser;
|
||||
boost::tuple<int, int, bool> received;
|
||||
|
||||
received = feed_bytes(parser
|
||||
, "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Length: 4\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"test");
|
||||
|
||||
TEST_CHECK(received == make_tuple(4, 64, false));
|
||||
TEST_CHECK(parser.finished());
|
||||
TEST_CHECK(std::equal(parser.get_body().begin, parser.get_body().end, "test"));
|
||||
TEST_CHECK(parser.header("content-type") == "text/plain");
|
||||
TEST_CHECK(atoi(parser.header("content-length").c_str()) == 4);
|
||||
|
||||
parser.reset();
|
||||
|
||||
TEST_CHECK(!parser.finished());
|
||||
|
||||
char const* upnp_response =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"ST:upnp:rootdevice\r\n"
|
||||
"USN:uuid:000f-66d6-7296000099dc::upnp:rootdevice\r\n"
|
||||
"Location: http://192.168.1.1:5431/dyndev/uuid:000f-66d6-7296000099dc\r\n"
|
||||
"Server: Custom/1.0 UPnP/1.0 Proc/Ver\r\n"
|
||||
"EXT:\r\n"
|
||||
"Cache-Control:max-age=180\r\n"
|
||||
"DATE: Fri, 02 Jan 1970 08:10:38 GMT\r\n\r\n";
|
||||
|
||||
received = feed_bytes(parser, upnp_response);
|
||||
|
||||
TEST_CHECK(received == make_tuple(0, int(strlen(upnp_response)), false));
|
||||
TEST_CHECK(parser.get_body().left() == 0);
|
||||
TEST_CHECK(parser.header("st") == "upnp:rootdevice");
|
||||
TEST_CHECK(parser.header("location")
|
||||
== "http://192.168.1.1:5431/dyndev/uuid:000f-66d6-7296000099dc");
|
||||
TEST_CHECK(parser.header("ext") == "");
|
||||
TEST_CHECK(parser.header("date") == "Fri, 02 Jan 1970 08:10:38 GMT");
|
||||
|
||||
parser.reset();
|
||||
TEST_CHECK(!parser.finished());
|
||||
|
||||
char const* upnp_notify =
|
||||
"NOTIFY * HTTP/1.1\r\n"
|
||||
"Host:239.255.255.250:1900\r\n"
|
||||
"NT:urn:schemas-upnp-org:device:MediaServer:1\r\n"
|
||||
"NTS:ssdp:alive\r\n"
|
||||
"Location:http://10.0.1.15:2353/upnphost/udhisapi.dll?content=uuid:c17f2c31-d19b-4912-af94-651945c8a84e\r\n"
|
||||
"USN:uuid:c17f0c32-d1db-4be8-ae94-25f94583026e::urn:schemas-upnp-org:device:MediaServer:1\r\n"
|
||||
"Cache-Control:max-age=900\r\n"
|
||||
"Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0\r\n";
|
||||
|
||||
received = feed_bytes(parser, upnp_notify);
|
||||
|
||||
TEST_CHECK(received == make_tuple(0, int(strlen(upnp_notify)), false));
|
||||
TEST_CHECK(parser.method() == "notify");
|
||||
TEST_CHECK(parser.path() == "*");
|
||||
|
||||
parser.reset();
|
||||
TEST_CHECK(!parser.finished());
|
||||
|
||||
char const* bt_lsd = "BT-SEARCH * HTTP/1.1\r\n"
|
||||
"Host: 239.192.152.143:6771\r\n"
|
||||
"Port: 6881\r\n"
|
||||
"Infohash: 12345678901234567890\r\n"
|
||||
"\r\n";
|
||||
|
||||
received = feed_bytes(parser, bt_lsd);
|
||||
|
||||
TEST_CHECK(received == make_tuple(0, int(strlen(bt_lsd)), false));
|
||||
TEST_CHECK(parser.method() == "bt-search");
|
||||
TEST_CHECK(parser.path() == "*");
|
||||
TEST_CHECK(atoi(parser.header("port").c_str()) == 6881);
|
||||
TEST_CHECK(parser.header("infohash") == "12345678901234567890");
|
||||
|
||||
TEST_CHECK(parser.finished());
|
||||
|
||||
parser.reset();
|
||||
TEST_CHECK(!parser.finished());
|
||||
|
||||
// test chunked encoding
|
||||
char const* chunked_test = "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Length: 20\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"\r\n"
|
||||
"4\r\n"
|
||||
"test\r\n"
|
||||
"10\r\n"
|
||||
"0123456789abcdef\r\n"
|
||||
"0\r\n"
|
||||
"Test-header: foobar\r\n"
|
||||
"\r\n";
|
||||
|
||||
received = feed_bytes(parser, chunked_test);
|
||||
|
||||
printf("payload: %d protocol: %d\n", received.get<0>(), received.get<1>());
|
||||
TEST_CHECK(received == make_tuple(20, strlen(chunked_test) - 20, false));
|
||||
TEST_CHECK(parser.finished());
|
||||
TEST_CHECK(std::equal(parser.get_body().begin, parser.get_body().end
|
||||
, "4\r\ntest\r\n10\r\n0123456789abcdef"));
|
||||
TEST_CHECK(parser.header("test-header") == "foobar");
|
||||
TEST_CHECK(parser.header("content-type") == "text/plain");
|
||||
TEST_CHECK(atoi(parser.header("content-length").c_str()) == 20);
|
||||
TEST_CHECK(parser.chunked_encoding());
|
||||
typedef std::pair<size_type, size_type> chunk_range;
|
||||
std::vector<chunk_range> cmp;
|
||||
cmp.push_back(chunk_range(96, 100));
|
||||
cmp.push_back(chunk_range(106, 122));
|
||||
TEST_CHECK(cmp == parser.chunks());
|
||||
|
||||
// make sure we support trackers with incorrect line endings
|
||||
char const* tracker_response =
|
||||
"HTTP/1.1 200 OK\n"
|
||||
"content-length: 5\n"
|
||||
"content-type: test/plain\n"
|
||||
"\n"
|
||||
"\ntest";
|
||||
|
||||
received = feed_bytes(parser, tracker_response);
|
||||
|
||||
TEST_CHECK(received == make_tuple(5, int(strlen(tracker_response) - 5), false));
|
||||
TEST_CHECK(parser.get_body().left() == 5);
|
||||
|
||||
parser.reset();
|
||||
|
||||
// make sure we support content-range responses
|
||||
// and that we're case insensitive
|
||||
char const* web_seed_response =
|
||||
"HTTP/1.1 206 OK\n"
|
||||
"contEnt-rAngE: bYTes 0-4\n"
|
||||
"conTent-TyPe: test/plain\n"
|
||||
"\n"
|
||||
"\ntest";
|
||||
|
||||
received = feed_bytes(parser, web_seed_response);
|
||||
|
||||
TEST_CHECK(received == make_tuple(5, int(strlen(web_seed_response) - 5), false));
|
||||
TEST_CHECK(parser.content_range() == (std::pair<size_type, size_type>(0, 4)));
|
||||
TEST_CHECK(parser.content_length() == 5);
|
||||
|
||||
parser.reset();
|
||||
|
||||
// make sure we support content-range responses
|
||||
// and that we're case insensitive
|
||||
char const* one_hundred_response =
|
||||
"HTTP/1.1 100 Continue\n"
|
||||
"\r\n"
|
||||
"HTTP/1.1 200 OK\n"
|
||||
"Content-Length: 4\r\n"
|
||||
"Content-Type: test/plain\r\n"
|
||||
"\r\n"
|
||||
"test";
|
||||
|
||||
received = feed_bytes(parser, one_hundred_response);
|
||||
|
||||
TEST_CHECK(received == make_tuple(4, int(strlen(one_hundred_response) - 4), false));
|
||||
TEST_EQUAL(parser.content_length(), 4);
|
||||
|
||||
{
|
||||
// test chunked encoding parser
|
||||
char const chunk_header1[] = "f;this is a comment\r\n";
|
||||
size_type chunk_size;
|
||||
int header_size;
|
||||
bool ret = parser.parse_chunk_header(buffer::const_interval(chunk_header1, chunk_header1 + 10)
|
||||
, &chunk_size, &header_size);
|
||||
TEST_EQUAL(ret, false);
|
||||
ret = parser.parse_chunk_header(buffer::const_interval(chunk_header1, chunk_header1 + sizeof(chunk_header1))
|
||||
, &chunk_size, &header_size);
|
||||
TEST_EQUAL(ret, true);
|
||||
TEST_EQUAL(chunk_size, 15);
|
||||
TEST_EQUAL(header_size, sizeof(chunk_header1) - 1);
|
||||
|
||||
char const chunk_header2[] =
|
||||
"0;this is a comment\r\n"
|
||||
"test1: foo\r\n"
|
||||
"test2: bar\r\n"
|
||||
"\r\n";
|
||||
|
||||
ret = parser.parse_chunk_header(buffer::const_interval(chunk_header2, chunk_header2 + sizeof(chunk_header2))
|
||||
, &chunk_size, &header_size);
|
||||
TEST_EQUAL(ret, true);
|
||||
TEST_EQUAL(chunk_size, 0);
|
||||
TEST_EQUAL(header_size, sizeof(chunk_header2) - 1);
|
||||
|
||||
TEST_EQUAL(parser.headers().find("test1")->second, "foo");
|
||||
TEST_EQUAL(parser.headers().find("test2")->second, "bar");
|
||||
}
|
||||
|
||||
// test url parsing
|
||||
|
||||
error_code ec;
|
||||
TEST_CHECK(parse_url_components("http://foo:bar@host.com:80/path/to/file", ec)
|
||||
== make_tuple("http", "foo:bar", "host.com", 80, "/path/to/file"));
|
||||
|
||||
TEST_CHECK(parse_url_components("http://host.com/path/to/file", ec)
|
||||
== make_tuple("http", "", "host.com", -1, "/path/to/file"));
|
||||
|
||||
TEST_CHECK(parse_url_components("ftp://host.com:21/path/to/file", ec)
|
||||
== make_tuple("ftp", "", "host.com", 21, "/path/to/file"));
|
||||
|
||||
TEST_CHECK(parse_url_components("http://host.com/path?foo:bar@foo:", ec)
|
||||
== make_tuple("http", "", "host.com", -1, "/path?foo:bar@foo:"));
|
||||
|
||||
TEST_CHECK(parse_url_components("http://192.168.0.1/path/to/file", ec)
|
||||
== make_tuple("http", "", "192.168.0.1", -1, "/path/to/file"));
|
||||
|
||||
TEST_CHECK(parse_url_components("http://[2001:ff00::1]:42/path/to/file", ec)
|
||||
== make_tuple("http", "", "[2001:ff00::1]", 42, "/path/to/file"));
|
||||
|
||||
// leading spaces are supposed to be stripped
|
||||
TEST_CHECK(parse_url_components(" \thttp://[2001:ff00::1]:42/path/to/file", ec)
|
||||
== make_tuple("http", "", "[2001:ff00::1]", 42, "/path/to/file"));
|
||||
|
||||
parse_url_components("http://[2001:ff00::1:42/path/to/file", ec);
|
||||
TEST_CHECK(ec == error_code(errors::expected_close_bracket_in_address));
|
||||
|
||||
parse_url_components("http:/", ec);
|
||||
TEST_CHECK(ec == error_code(errors::unsupported_url_protocol));
|
||||
ec.clear();
|
||||
|
||||
parse_url_components("http:", ec);
|
||||
TEST_CHECK(ec == error_code(errors::unsupported_url_protocol));
|
||||
ec.clear();
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2012, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "test.hpp"
|
||||
#include "libtorrent/escape_string.hpp"
|
||||
#include "libtorrent/string_util.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
int test_main()
|
||||
{
|
||||
// test maybe_url_encode
|
||||
TEST_EQUAL(maybe_url_encode("http://test:test@abc.com/abc<>abc"), "http://test:test@abc.com/abc%3c%3eabc");
|
||||
TEST_EQUAL(maybe_url_encode("http://abc.com/foo bar"), "http://abc.com/foo%20bar");
|
||||
TEST_EQUAL(maybe_url_encode("http://abc.com:80/foo bar"), "http://abc.com:80/foo%20bar");
|
||||
TEST_EQUAL(maybe_url_encode("http://abc.com:8080/foo bar"), "http://abc.com:8080/foo%20bar");
|
||||
TEST_EQUAL(maybe_url_encode("abc"), "abc");
|
||||
TEST_EQUAL(maybe_url_encode("http://abc.com/abc"), "http://abc.com/abc");
|
||||
|
||||
// test to/from hex conversion
|
||||
|
||||
char const* str = "0123456789012345678901234567890123456789";
|
||||
char bin[20];
|
||||
TEST_CHECK(from_hex(str, 40, bin));
|
||||
char hex[41];
|
||||
to_hex(bin, 20, hex);
|
||||
TEST_CHECK(strcmp(hex, str) == 0);
|
||||
|
||||
// test is_space
|
||||
|
||||
TEST_CHECK(!is_space('C'));
|
||||
TEST_CHECK(!is_space('\b'));
|
||||
TEST_CHECK(!is_space('8'));
|
||||
TEST_CHECK(!is_space('='));
|
||||
TEST_CHECK(is_space(' '));
|
||||
TEST_CHECK(is_space('\t'));
|
||||
TEST_CHECK(is_space('\n'));
|
||||
TEST_CHECK(is_space('\r'));
|
||||
|
||||
// test to_lower
|
||||
|
||||
TEST_CHECK(to_lower('C') == 'c');
|
||||
TEST_CHECK(to_lower('c') == 'c');
|
||||
TEST_CHECK(to_lower('-') == '-');
|
||||
TEST_CHECK(to_lower('&') == '&');
|
||||
|
||||
// test string_equal_no_case
|
||||
|
||||
TEST_CHECK(string_equal_no_case("foobar", "FoobAR"));
|
||||
TEST_CHECK(string_equal_no_case("foobar", "foobar"));
|
||||
TEST_CHECK(!string_equal_no_case("foobar", "foobar "));
|
||||
TEST_CHECK(!string_equal_no_case("foobar", "F00"));
|
||||
|
||||
// test string_begins_no_case
|
||||
|
||||
TEST_CHECK(string_begins_no_case("foobar", "FoobAR --"));
|
||||
TEST_CHECK(!string_begins_no_case("foobar", "F00"));
|
||||
|
||||
// test itoa
|
||||
|
||||
TEST_CHECK(to_string(345).elems == std::string("345"));
|
||||
TEST_CHECK(to_string(-345).elems == std::string("-345"));
|
||||
TEST_CHECK(to_string(0).elems == std::string("0"));
|
||||
TEST_CHECK(to_string(1000000000).elems == std::string("1000000000"));
|
||||
|
||||
// base64 test vectors from http://www.faqs.org/rfcs/rfc4648.html
|
||||
|
||||
TEST_CHECK(base64encode("") == "");
|
||||
TEST_CHECK(base64encode("f") == "Zg==");
|
||||
TEST_CHECK(base64encode("fo") == "Zm8=");
|
||||
TEST_CHECK(base64encode("foo") == "Zm9v");
|
||||
TEST_CHECK(base64encode("foob") == "Zm9vYg==");
|
||||
TEST_CHECK(base64encode("fooba") == "Zm9vYmE=");
|
||||
TEST_CHECK(base64encode("foobar") == "Zm9vYmFy");
|
||||
|
||||
// base32 test vectors from http://www.faqs.org/rfcs/rfc4648.html
|
||||
|
||||
TEST_CHECK(base32encode("") == "");
|
||||
TEST_CHECK(base32encode("f") == "MY======");
|
||||
TEST_CHECK(base32encode("fo") == "MZXQ====");
|
||||
TEST_CHECK(base32encode("foo") == "MZXW6===");
|
||||
TEST_CHECK(base32encode("foob") == "MZXW6YQ=");
|
||||
TEST_CHECK(base32encode("fooba") == "MZXW6YTB");
|
||||
TEST_CHECK(base32encode("foobar") == "MZXW6YTBOI======");
|
||||
|
||||
TEST_CHECK(base32decode("") == "");
|
||||
TEST_CHECK(base32decode("MY======") == "f");
|
||||
TEST_CHECK(base32decode("MZXQ====") == "fo");
|
||||
TEST_CHECK(base32decode("MZXW6===") == "foo");
|
||||
TEST_CHECK(base32decode("MZXW6YQ=") == "foob");
|
||||
TEST_CHECK(base32decode("MZXW6YTB") == "fooba");
|
||||
TEST_CHECK(base32decode("MZXW6YTBOI======") == "foobar");
|
||||
|
||||
TEST_CHECK(base32decode("MY") == "f");
|
||||
TEST_CHECK(base32decode("MZXW6YQ") == "foob");
|
||||
TEST_CHECK(base32decode("MZXW6YTBOI") == "foobar");
|
||||
TEST_CHECK(base32decode("mZXw6yTBO1======") == "foobar");
|
||||
|
||||
std::string test;
|
||||
for (int i = 0; i < 255; ++i)
|
||||
test += char(i);
|
||||
|
||||
TEST_CHECK(base32decode(base32encode(test)) == test);
|
||||
|
||||
// escape_string
|
||||
char const* test_string = "!@#$%^&*()-_=+/,. %?";
|
||||
TEST_EQUAL(escape_string(test_string, strlen(test_string))
|
||||
, "!%40%23%24%25%5e%26*()-_%3d%2b%2f%2c.%20%25%3f");
|
||||
|
||||
// escape_path
|
||||
TEST_EQUAL(escape_path(test_string, strlen(test_string))
|
||||
, "!%40%23%24%25%5e%26*()-_%3d%2b/%2c.%20%25%3f");
|
||||
|
||||
error_code ec;
|
||||
TEST_CHECK(unescape_string(escape_path(test_string, strlen(test_string)), ec) == test_string);
|
||||
TEST_CHECK(!ec);
|
||||
if (ec) fprintf(stderr, "%s\n", ec.message().c_str());
|
||||
|
||||
// need_encoding
|
||||
char const* test_string2 = "!@$&()-_/,.%?";
|
||||
TEST_CHECK(need_encoding(test_string, strlen(test_string)) == true);
|
||||
TEST_CHECK(need_encoding(test_string2, strlen(test_string2)) == false);
|
||||
TEST_CHECK(need_encoding("\n", 1) == true);
|
||||
|
||||
// maybe_url_encode
|
||||
TEST_EQUAL(maybe_url_encode("http://bla.com/\n"), "http://bla.com/%0a");
|
||||
TEST_EQUAL(maybe_url_encode("http://bla.com/foo%20bar"), "http://bla.com/foo%20bar");
|
||||
TEST_EQUAL(maybe_url_encode("http://bla.com/foo%20bar?k=v&k2=v2"), "http://bla.com/foo%20bar?k=v&k2=v2");
|
||||
TEST_EQUAL(maybe_url_encode("?&"), "?&");
|
||||
|
||||
// unescape_string
|
||||
TEST_CHECK(unescape_string(escape_string(test_string, strlen(test_string)), ec)
|
||||
== test_string);
|
||||
std::cerr << unescape_string(escape_string(test_string, strlen(test_string)), ec) << std::endl;
|
||||
// prematurely terminated string
|
||||
unescape_string("%", ec);
|
||||
TEST_CHECK(ec == error_code(errors::invalid_escaped_string));
|
||||
unescape_string("%0", ec);
|
||||
TEST_CHECK(ec == error_code(errors::invalid_escaped_string));
|
||||
|
||||
// invalid hex character
|
||||
unescape_string("%GE", ec);
|
||||
TEST_CHECK(ec == error_code(errors::invalid_escaped_string));
|
||||
unescape_string("%eg", ec);
|
||||
TEST_CHECK(ec == error_code(errors::invalid_escaped_string));
|
||||
ec.clear();
|
||||
|
||||
char hex_chars[] = "0123456789abcdefABCDEF";
|
||||
|
||||
for (int i = 1; i < 255; ++i)
|
||||
{
|
||||
bool hex = strchr(hex_chars, i) != NULL;
|
||||
char c = i;
|
||||
TEST_EQUAL(is_hex(&c, 1), hex);
|
||||
}
|
||||
|
||||
TEST_EQUAL(hex_to_int('0'), 0);
|
||||
TEST_EQUAL(hex_to_int('7'), 7);
|
||||
TEST_EQUAL(hex_to_int('a'), 10);
|
||||
TEST_EQUAL(hex_to_int('f'), 15);
|
||||
TEST_EQUAL(hex_to_int('b'), 11);
|
||||
TEST_EQUAL(hex_to_int('t'), -1);
|
||||
TEST_EQUAL(hex_to_int('g'), -1);
|
||||
|
||||
std::string path = "a\\b\\c";
|
||||
convert_path_to_posix(path);
|
||||
TEST_EQUAL(path, "a/b/c");
|
||||
|
||||
// url_has_argument
|
||||
|
||||
TEST_CHECK(url_has_argument("http://127.0.0.1/test", "test") == "");
|
||||
TEST_CHECK(url_has_argument("http://127.0.0.1/test?foo=24", "bar") == "");
|
||||
TEST_CHECK(url_has_argument("http://127.0.0.1/test?foo=24", "foo") == "24");
|
||||
TEST_CHECK(url_has_argument("http://127.0.0.1/test?foo=24&bar=23", "foo") == "24");
|
||||
TEST_CHECK(url_has_argument("http://127.0.0.1/test?foo=24&bar=23", "bar") == "23");
|
||||
TEST_CHECK(url_has_argument("http://127.0.0.1/test?foo=24&bar=23&a=e", "bar") == "23");
|
||||
TEST_CHECK(url_has_argument("http://127.0.0.1/test?foo=24&bar=23&a=e", "a") == "e");
|
||||
TEST_CHECK(url_has_argument("http://127.0.0.1/test?foo=24&bar=23&a=e", "b") == "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2012, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/xml_parse.hpp"
|
||||
#include "libtorrent/upnp.hpp"
|
||||
#include "test.hpp"
|
||||
#include <iostream>
|
||||
|
||||
char upnp_xml[] =
|
||||
"<root>"
|
||||
"<specVersion>"
|
||||
"<major>1</major>"
|
||||
"<minor>0</minor>"
|
||||
"</specVersion>"
|
||||
"<URLBase>http://192.168.0.1:5678</URLBase>"
|
||||
"<device>"
|
||||
"<deviceType>"
|
||||
"urn:schemas-upnp-org:device:InternetGatewayDevice:1"
|
||||
"</deviceType>"
|
||||
"<presentationURL>http://192.168.0.1:80</presentationURL>"
|
||||
"<friendlyName>D-Link Router</friendlyName>"
|
||||
"<manufacturer>D-Link</manufacturer>"
|
||||
"<manufacturerURL>http://www.dlink.com</manufacturerURL>"
|
||||
"<modelDescription>Internet Access Router</modelDescription>"
|
||||
"<modelName>D-Link Router</modelName>"
|
||||
"<UDN>uuid:upnp-InternetGatewayDevice-1_0-12345678900001</UDN>"
|
||||
"<UPC>123456789001</UPC>"
|
||||
"<serviceList>"
|
||||
"<service>"
|
||||
"<serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType>"
|
||||
"<serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId>"
|
||||
"<controlURL>/Layer3Forwarding</controlURL>"
|
||||
"<eventSubURL>/Layer3Forwarding</eventSubURL>"
|
||||
"<SCPDURL>/Layer3Forwarding.xml</SCPDURL>"
|
||||
"</service>"
|
||||
"</serviceList>"
|
||||
"<deviceList>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>"
|
||||
"<friendlyName>WANDevice</friendlyName>"
|
||||
"<manufacturer>D-Link</manufacturer>"
|
||||
"<manufacturerURL>http://www.dlink.com</manufacturerURL>"
|
||||
"<modelDescription>Internet Access Router</modelDescription>"
|
||||
"<modelName>D-Link Router</modelName>"
|
||||
"<modelNumber>1</modelNumber>"
|
||||
"<modelURL>http://support.dlink.com</modelURL>"
|
||||
"<serialNumber>12345678900001</serialNumber>"
|
||||
"<UDN>uuid:upnp-WANDevice-1_0-12345678900001</UDN>"
|
||||
"<UPC>123456789001</UPC>"
|
||||
"<serviceList>"
|
||||
"<service>"
|
||||
"<serviceType>"
|
||||
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"
|
||||
"</serviceType>"
|
||||
"<serviceId>urn:upnp-org:serviceId:WANCommonInterfaceConfig</serviceId>"
|
||||
"<controlURL>/WANCommonInterfaceConfig</controlURL>"
|
||||
"<eventSubURL>/WANCommonInterfaceConfig</eventSubURL>"
|
||||
"<SCPDURL>/WANCommonInterfaceConfig.xml</SCPDURL>"
|
||||
"</service>"
|
||||
"</serviceList>"
|
||||
"<deviceList>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>"
|
||||
"<friendlyName>WAN Connection Device</friendlyName>"
|
||||
"<manufacturer>D-Link</manufacturer>"
|
||||
"<manufacturerURL>http://www.dlink.com</manufacturerURL>"
|
||||
"<modelDescription>Internet Access Router</modelDescription>"
|
||||
"<modelName>D-Link Router</modelName>"
|
||||
"<modelNumber>1</modelNumber>"
|
||||
"<modelURL>http://support.dlink.com</modelURL>"
|
||||
"<serialNumber>12345678900001</serialNumber>"
|
||||
"<UDN>uuid:upnp-WANConnectionDevice-1_0-12345678900001</UDN>"
|
||||
"<UPC>123456789001</UPC>"
|
||||
"<serviceList>"
|
||||
"<service>"
|
||||
"<serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType>"
|
||||
"<serviceId>urn:upnp-org:serviceId:WANIPConnection</serviceId>"
|
||||
"<controlURL>/WANIPConnection</controlURL>"
|
||||
"<eventSubURL>/WANIPConnection</eventSubURL>"
|
||||
"<SCPDURL>/WANIPConnection.xml</SCPDURL>"
|
||||
"</service>"
|
||||
"</serviceList>"
|
||||
"</device>"
|
||||
"</deviceList>"
|
||||
"</device>"
|
||||
"</deviceList>"
|
||||
"</device>"
|
||||
"</root>";
|
||||
|
||||
char upnp_xml2[] =
|
||||
"<root>"
|
||||
"<specVersion>"
|
||||
"<major>1</major>"
|
||||
"<minor>0</minor>"
|
||||
"</specVersion>"
|
||||
"<URLBase>http://192.168.1.1:49152</URLBase>"
|
||||
"<device>"
|
||||
"<deviceType>"
|
||||
"urn:schemas-upnp-org:device:InternetGatewayDevice:1"
|
||||
"</deviceType>"
|
||||
"<friendlyName>LINKSYS WAG200G Gateway</friendlyName>"
|
||||
"<manufacturer>LINKSYS</manufacturer>"
|
||||
"<manufacturerURL>http://www.linksys.com</manufacturerURL>"
|
||||
"<modelDescription>LINKSYS WAG200G Gateway</modelDescription>"
|
||||
"<modelName>Wireless-G ADSL Home Gateway</modelName>"
|
||||
"<modelNumber>WAG200G</modelNumber>"
|
||||
"<modelURL>http://www.linksys.com</modelURL>"
|
||||
"<serialNumber>123456789</serialNumber>"
|
||||
"<UDN>uuid:8d401597-1dd2-11b2-a7d4-001ee5947cac</UDN>"
|
||||
"<UPC>WAG200G</UPC>"
|
||||
"<serviceList>"
|
||||
"<service>"
|
||||
"<serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType>"
|
||||
"<serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId>"
|
||||
"<controlURL>/upnp/control/L3Forwarding1</controlURL>"
|
||||
"<eventSubURL>/upnp/event/L3Forwarding1</eventSubURL>"
|
||||
"<SCPDURL>/l3frwd.xml</SCPDURL>"
|
||||
"</service>"
|
||||
"</serviceList>"
|
||||
"<deviceList>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>"
|
||||
"<friendlyName>WANDevice</friendlyName>"
|
||||
"<manufacturer>LINKSYS</manufacturer>"
|
||||
"<manufacturerURL>http://www.linksys.com/</manufacturerURL>"
|
||||
"<modelDescription>Residential Gateway</modelDescription>"
|
||||
"<modelName>Internet Connection Sharing</modelName>"
|
||||
"<modelNumber>1</modelNumber>"
|
||||
"<modelURL>http://www.linksys.com/</modelURL>"
|
||||
"<serialNumber>0000001</serialNumber>"
|
||||
"<UDN>uuid:8d401596-1dd2-11b2-a7d4-001ee5947cac</UDN>"
|
||||
"<UPC>WAG200G</UPC>"
|
||||
"<serviceList>"
|
||||
"<service>"
|
||||
"<serviceType>"
|
||||
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"
|
||||
"</serviceType>"
|
||||
"<serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId>"
|
||||
"<controlURL>/upnp/control/WANCommonIFC1</controlURL>"
|
||||
"<eventSubURL>/upnp/event/WANCommonIFC1</eventSubURL>"
|
||||
"<SCPDURL>/cmnicfg.xml</SCPDURL>"
|
||||
"</service>"
|
||||
"</serviceList>"
|
||||
"<deviceList>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>"
|
||||
"<friendlyName>WANConnectionDevice</friendlyName>"
|
||||
"<manufacturer>LINKSYS</manufacturer>"
|
||||
"<manufacturerURL>http://www.linksys.com/</manufacturerURL>"
|
||||
"<modelDescription>Residential Gateway</modelDescription>"
|
||||
"<modelName>Internet Connection Sharing</modelName>"
|
||||
"<modelNumber>1</modelNumber>"
|
||||
"<modelURL>http://www.linksys.com/</modelURL>"
|
||||
"<serialNumber>0000001</serialNumber>"
|
||||
"<UDN>uuid:8d401597-1dd2-11b2-a7d3-001ee5947cac</UDN>"
|
||||
"<UPC>WAG200G</UPC>"
|
||||
"<serviceList>"
|
||||
"<service>"
|
||||
"<serviceType>"
|
||||
"urn:schemas-upnp-org:service:WANEthernetLinkConfig:1"
|
||||
"</serviceType>"
|
||||
"<serviceId>urn:upnp-org:serviceId:WANEthLinkC1</serviceId>"
|
||||
"<controlURL>/upnp/control/WANEthLinkC1</controlURL>"
|
||||
"<eventSubURL>/upnp/event/WANEthLinkC1</eventSubURL>"
|
||||
"<SCPDURL>/wanelcfg.xml</SCPDURL>"
|
||||
"</service>"
|
||||
"<service>"
|
||||
"<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>"
|
||||
"<serviceId>urn:upnp-org:serviceId:WANPPPConn1</serviceId>"
|
||||
"<controlURL>/upnp/control/WANPPPConn1</controlURL>"
|
||||
"<eventSubURL>/upnp/event/WANPPPConn1</eventSubURL>"
|
||||
"<SCPDURL>/pppcfg.xml</SCPDURL>"
|
||||
"</service>"
|
||||
"</serviceList>"
|
||||
"</device>"
|
||||
"</deviceList>"
|
||||
"</device>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:LANDevice:1</deviceType>"
|
||||
"<friendlyName>LANDevice</friendlyName>"
|
||||
"<manufacturer>LINKSYS</manufacturer>"
|
||||
"<manufacturerURL>http://www.linksys.com/</manufacturerURL>"
|
||||
"<modelDescription>Residential Gateway</modelDescription>"
|
||||
"<modelName>Residential Gateway</modelName>"
|
||||
"<modelNumber>1</modelNumber>"
|
||||
"<modelURL>http://www.linksys.com/</modelURL>"
|
||||
"<serialNumber>0000001</serialNumber>"
|
||||
"<UDN>uuid:8d401596-1dd2-11b2-a7d3-001ee5947cac</UDN>"
|
||||
"<UPC>WAG200G</UPC>"
|
||||
"<serviceList>"
|
||||
"<service>"
|
||||
"<serviceType>"
|
||||
"urn:schemas-upnp-org:service:LANHostConfigManagement:1"
|
||||
"</serviceType>"
|
||||
"<serviceId>urn:upnp-org:serviceId:LANHostCfg1</serviceId>"
|
||||
"<controlURL>/upnp/control/LANHostCfg1</controlURL>"
|
||||
"<eventSubURL>/upnp/event/LANHostCfg1</eventSubURL>"
|
||||
"<SCPDURL>/lanhostc.xml</SCPDURL>"
|
||||
"</service>"
|
||||
"</serviceList>"
|
||||
"</device>"
|
||||
"</deviceList>"
|
||||
"<presentationURL>http://192.168.1.1/index.htm</presentationURL>"
|
||||
"</device>"
|
||||
"</root>";
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
struct parse_state
|
||||
{
|
||||
parse_state(): in_service(false) {}
|
||||
void reset(char const* st)
|
||||
{
|
||||
in_service = false;
|
||||
service_type = st;
|
||||
tag_stack.clear();
|
||||
control_url.clear();
|
||||
model.clear();
|
||||
url_base.clear();
|
||||
}
|
||||
bool in_service;
|
||||
std::list<std::string> tag_stack;
|
||||
std::string control_url;
|
||||
char const* service_type;
|
||||
std::string model;
|
||||
std::string url_base;
|
||||
};
|
||||
|
||||
TORRENT_EXPORT void find_control_url(int type, char const* string, parse_state& state);
|
||||
|
||||
void parser_callback(std::string& out, int token, char const* s, char const* val)
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
case xml_start_tag: out += "B"; break;
|
||||
case xml_end_tag: out += "F"; break;
|
||||
case xml_empty_tag: out += "E"; break;
|
||||
case xml_declaration_tag: out += "D"; break;
|
||||
case xml_comment: out += "C"; break;
|
||||
case xml_string: out += "S"; break;
|
||||
case xml_attribute: out += "A"; break;
|
||||
case xml_parse_error: out += "P"; break;
|
||||
case xml_tag_content: out += "T"; break;
|
||||
default: TEST_CHECK(false);
|
||||
}
|
||||
out += s;
|
||||
if (token == xml_attribute)
|
||||
{
|
||||
TEST_CHECK(val != 0);
|
||||
out += "V";
|
||||
out += val;
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_CHECK(val == 0);
|
||||
}
|
||||
}
|
||||
|
||||
int test_main()
|
||||
{
|
||||
// test upnp xml parser
|
||||
|
||||
parse_state xml_s;
|
||||
xml_s.reset("urn:schemas-upnp-org:service:WANIPConnection:1");
|
||||
xml_parse(upnp_xml, upnp_xml + sizeof(upnp_xml)
|
||||
, boost::bind(&find_control_url, _1, _2, boost::ref(xml_s)));
|
||||
|
||||
std::cerr << "namespace " << xml_s.service_type << std::endl;
|
||||
std::cerr << "url_base: " << xml_s.url_base << std::endl;
|
||||
std::cerr << "control_url: " << xml_s.control_url << std::endl;
|
||||
std::cerr << "model: " << xml_s.model << std::endl;
|
||||
TEST_CHECK(xml_s.url_base == "http://192.168.0.1:5678");
|
||||
TEST_CHECK(xml_s.control_url == "/WANIPConnection");
|
||||
TEST_CHECK(xml_s.model == "D-Link Router");
|
||||
|
||||
xml_s.reset("urn:schemas-upnp-org:service:WANPPPConnection:1");
|
||||
xml_parse(upnp_xml2, upnp_xml2 + sizeof(upnp_xml2)
|
||||
, boost::bind(&find_control_url, _1, _2, boost::ref(xml_s)));
|
||||
|
||||
std::cerr << "namespace " << xml_s.service_type << std::endl;
|
||||
std::cerr << "url_base: " << xml_s.url_base << std::endl;
|
||||
std::cerr << "control_url: " << xml_s.control_url << std::endl;
|
||||
std::cerr << "model: " << xml_s.model << std::endl;
|
||||
TEST_CHECK(xml_s.url_base == "http://192.168.1.1:49152");
|
||||
TEST_CHECK(xml_s.control_url == "/upnp/control/WANPPPConn1");
|
||||
TEST_CHECK(xml_s.model == "Wireless-G ADSL Home Gateway");
|
||||
|
||||
// test xml parser
|
||||
char xml1[] = "<a>foo<b/>bar</a>";
|
||||
std::string out1;
|
||||
|
||||
xml_parse(xml1, xml1 + sizeof(xml1) - 1, boost::bind(&parser_callback
|
||||
, boost::ref(out1), _1, _2, _3));
|
||||
std::cerr << out1 << std::endl;
|
||||
TEST_CHECK(out1 == "BaSfooEbSbarFa");
|
||||
|
||||
char xml2[] = "<?xml version = \"1.0\"?><c x=\"1\" \t y=\"3\"/><d foo='bar'></d boo='foo'><!--comment-->";
|
||||
std::string out2;
|
||||
|
||||
xml_parse(xml2, xml2 + sizeof(xml2) - 1, boost::bind(&parser_callback
|
||||
, boost::ref(out2), _1, _2, _3));
|
||||
std::cerr << out2 << std::endl;
|
||||
TEST_CHECK(out2 == "DxmlAversionV1.0EcAxV1AyV3BdAfooVbarFdAbooVfooCcomment");
|
||||
|
||||
char xml3[] = "<a f=1>foo</a f='b>";
|
||||
std::string out3;
|
||||
|
||||
xml_parse(xml3, xml3 + sizeof(xml3) - 1, boost::bind(&parser_callback
|
||||
, boost::ref(out3), _1, _2, _3));
|
||||
std::cerr << out3 << std::endl;
|
||||
TEST_CHECK(out3 == "BaPunquoted attribute valueSfooFaPmissing end quote on attribute");
|
||||
|
||||
char xml4[] = "<a f>foo</a v >";
|
||||
std::string out4;
|
||||
|
||||
xml_parse(xml4, xml4 + sizeof(xml4) - 1, boost::bind(&parser_callback
|
||||
, boost::ref(out4), _1, _2, _3));
|
||||
std::cerr << out4 << std::endl;
|
||||
TEST_CHECK(out4 == "BaTfSfooFaTv ");
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue