ducktorrent/test/unit/test_parser.cpp
2025-04-07 22:57:15 +01:00

115 lines
4.6 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Copyright 2025, Michele "King_DuckZ" Santullo
* This file is part of ducktorrent.
*
* Ducktorrent 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.
*
* Ducktorrent 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 ducktorrent. If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "ducktorrent/parser.hpp"
#define INPUT1_BINARY_BLOB "NjˆwŒ\0XL”óPOˆ_æ5iÄ@\\#ú·<jâ"
namespace {
constexpr char g_input1_binary_blob[] = INPUT1_BINARY_BLOB;
constexpr auto g_input1_binary_blob_size = sizeof(g_input1_binary_blob) / sizeof(g_input1_binary_blob[0]) - 1;
constexpr char g_input1[] = "d8:announce41:http://bttracker.debian.org:6969/ann"
"ounce7:comment33:Debian CD from cdimage.debian.org10:created by13:mktorren"
"t 1.113:creation datei1742039925e4:infod6:lengthi663748608e4:name32:debian"
"-12.10.0-amd64-netinst.iso12:piece lengthi262144e6:pieces40:"
INPUT1_BINARY_BLOB "ee";
constexpr auto g_input1_size = sizeof(g_input1) / sizeof(g_input1[0]) - 1u;
constexpr char g_input2[] = "hello world";
constexpr auto g_input2_size = sizeof(g_input2) / sizeof(g_input2[0]) - 1u;
constexpr char g_input3[] = "d5:helloe";
constexpr auto g_input3_size = sizeof(g_input3) / sizeof(g_input3[0]) - 1u;
constexpr char g_input4[] = "d5:hello5:worldee";
constexpr auto g_input4_size = sizeof(g_input4) / sizeof(g_input4[0]) - 1u;
constexpr char g_input5[] = "d5:hello5:world";
constexpr auto g_input5_size = sizeof(g_input5) / sizeof(g_input5[0]) - 1u;
constexpr char g_input6[] = "d5:hello100:worlde";
constexpr auto g_input6_size = sizeof(g_input6) / sizeof(g_input6[0]) - 1u;
template <typename T>
void check_map_entry (
const std::map<duck::TorrentStringType, duck::TorrentValue>& map,
duck::TorrentStringType key,
T expected,
int expected_var_which
) {
REQUIRE(map.contains(key));
REQUIRE(map.at(key).get().which() == expected_var_which);
const auto& val = boost::get<T>(map.at(key));
CHECK(val == expected);
}
} //unnamed namespace
TEST_CASE ("Parse valid bencoded test input", "[parse][bencoding]") {
using duck::TorrentStringType;
using duck::TorrentIntType;
auto res = duck::parse_torrent(std::string_view{g_input1, g_input1_size});
REQUIRE(res.size() == 1);
const duck::TorrentValue& root = res.front();
REQUIRE(root.get().which() == 3);
const std::map<TorrentStringType, duck::TorrentValue>& main_map =
boost::get<
boost::spirit::x3::forward_ast< std::map<TorrentStringType, duck::TorrentValue> >
>(root).get();
check_map_entry<TorrentStringType>(main_map, "announce", "http://bttracker.debian.org:6969/announce", 1);
check_map_entry<TorrentStringType>(main_map, "comment", "Debian CD from cdimage.debian.org", 1);
check_map_entry<TorrentStringType>(main_map, "created by", "mktorrent 1.1", 1);
check_map_entry<TorrentIntType>(main_map, "creation date", 1742039925, 0);
REQUIRE(main_map.contains("info"));
REQUIRE(main_map.at("info").get().which() == 3);
const std::map<TorrentStringType, duck::TorrentValue>& info_map =
boost::get<
boost::spirit::x3::forward_ast< std::map<TorrentStringType, duck::TorrentValue> >
>(main_map.at("info")).get();
check_map_entry<TorrentStringType>(info_map, "name", "debian-12.10.0-amd64-netinst.iso", 1);
check_map_entry<TorrentIntType>(info_map, "piece length", 262144, 0);
check_map_entry<TorrentStringType>(info_map, "pieces", TorrentStringType{g_input1_binary_blob, g_input1_binary_blob_size}, 1);
}
TEST_CASE ("Parse empty test input", "[parse][bencoding]") {
CHECK_THROWS_AS(duck::parse_torrent(""), duck::ParseError);
}
TEST_CASE ("Parse invalid test input", "[parse][bencoding]") {
std::string_view input;
input = std::string_view{g_input2, g_input2_size};
CHECK_THROWS_AS(duck::parse_torrent(input), duck::ParseError);
input = std::string_view{g_input3, g_input3_size};
CHECK_THROWS_AS(duck::parse_torrent(input), duck::ParseError);
input = std::string_view{g_input4, g_input4_size};
CHECK_THROWS_AS(duck::parse_torrent(input), duck::ParseError);
input = std::string_view{g_input5, g_input5_size};
CHECK_THROWS_AS(duck::parse_torrent(input), duck::ParseError);
input = std::string_view{g_input6, g_input6_size};
CHECK_THROWS_AS(duck::parse_torrent(input), duck::ParseError);
}