/* 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 . */ #include "catch2/catch_test_macros.hpp" #include "ducktorrent/parser.hpp" #define INPUT1_BINARY_BLOB "NjˆwŒ\0XL”óPOˆ_æ5iÄ@\\#ú· void check_map_entry ( const std::map& 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(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& main_map = boost::get< boost::spirit::x3::forward_ast< std::map > >(root).get(); check_map_entry(main_map, "announce", "http://bttracker.debian.org:6969/announce", 1); check_map_entry(main_map, "comment", "Debian CD from cdimage.debian.org", 1); check_map_entry(main_map, "created by", "mktorrent 1.1", 1); check_map_entry(main_map, "creation date", 1742039925, 0); REQUIRE(main_map.contains("info")); REQUIRE(main_map.at("info").get().which() == 3); const std::map& info_map = boost::get< boost::spirit::x3::forward_ast< std::map > >(main_map.at("info")).get(); check_map_entry(info_map, "name", "debian-12.10.0-amd64-netinst.iso", 1); check_map_entry(info_map, "piece length", 262144, 0); check_map_entry(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); }