diff --git a/bindings/python/dummy_data.py b/bindings/python/dummy_data.py new file mode 100644 index 000000000..9803163d7 --- /dev/null +++ b/bindings/python/dummy_data.py @@ -0,0 +1,34 @@ +import libtorrent as lt + +import hashlib +import random + +PIECE_LENGTH = 16384 +NAME = b"test.txt" +LEN = PIECE_LENGTH * 9 + 1000 +# Use 7-bit data so we can test piece data as either bytes or str +DATA = bytes(random.getrandbits(7) for _ in range(LEN)) +PIECES = [DATA[i:i + PIECE_LENGTH] for i in range(0, LEN, PIECE_LENGTH)] + +INFO_DICT = { + b"name": NAME, + b"piece length": PIECE_LENGTH, + b"length": len(DATA), + b"pieces": b"".join(hashlib.sha1(p).digest() for p in PIECES), + } + +DICT = { + b"info": INFO_DICT, +} + + +def get_infohash_bytes(): + return hashlib.sha1(lt.bencode(INFO_DICT)).digest() + + +def get_infohash(): + return get_infohash_bytes().hex() + + +def get_sha1_hash(): + return lt.sha1_hash(get_infohash_bytes()) diff --git a/bindings/python/src/torrent_handle.cpp b/bindings/python/src/torrent_handle.cpp index 386330312..3fb4fe5dc 100644 --- a/bindings/python/src/torrent_handle.cpp +++ b/bindings/python/src/torrent_handle.cpp @@ -5,6 +5,7 @@ #include "boost_python.hpp" #include #include +#include "bytes.hpp" #include #include #include @@ -405,10 +406,16 @@ std::shared_ptr get_torrent_info(torrent_handle const& h) #endif // TORRENT_ABI_VERSION -void add_piece(torrent_handle& th, piece_index_t piece, char const *data +void add_piece_str(torrent_handle& th, piece_index_t piece, char const *data , add_piece_flags_t const flags) { - th.add_piece(piece, data, flags); + th.add_piece(piece, data, flags); +} + +void add_piece_bytes(torrent_handle& th, piece_index_t piece, bytes data + , add_piece_flags_t const flags) +{ + th.add_piece(piece, data.arr.c_str(), flags); } class dummy5 {}; @@ -492,7 +499,8 @@ void bind_torrent_handle() .def("queue_position_top", _(&torrent_handle::queue_position_top)) .def("queue_position_bottom", _(&torrent_handle::queue_position_bottom)) - .def("add_piece", add_piece) + .def("add_piece", add_piece_str) + .def("add_piece", add_piece_bytes) .def("read_piece", _(&torrent_handle::read_piece)) .def("have_piece", _(&torrent_handle::have_piece)) .def("set_piece_deadline", _(&torrent_handle::set_piece_deadline) diff --git a/bindings/python/test.py b/bindings/python/test.py index 74c34bffe..0e03434c3 100644 --- a/bindings/python/test.py +++ b/bindings/python/test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 @@ -14,6 +14,9 @@ import subprocess as sub import sys import pickle import threading +import tempfile + +import dummy_data # include terminal interface for travis parallel executions of scripts which use # terminal features: fix multiple stdin assignment at termios.tcgetattr @@ -311,6 +314,45 @@ class test_torrent_handle(unittest.TestCase): self.assertEqual(self.st.verified_pieces, []) +class TestAddPiece(unittest.TestCase): + + def setUp(self): + self.dir = tempfile.TemporaryDirectory() + self.session = lt.session(settings) + self.ti = lt.torrent_info(dummy_data.DICT) + self.atp = lt.add_torrent_params() + self.atp.ti = self.ti + self.atp.save_path = self.dir.name + self.handle = self.session.add_torrent(self.atp) + + def wait_for(self, condition, msg="condition", timeout=5): + deadline = time.time() + timeout + while not condition(): + self.assertLess(time.time(), deadline, msg="%s timed out" % msg) + time.sleep(0.1) + + def wait_until_torrent_finished(self): + self.wait_for(lambda: self.handle.status().progress == 1.0, msg="progress") + + def file_written(): + with open(os.path.join(self.dir.name.encode(), dummy_data.NAME), mode="rb") as f: + return f.read() == dummy_data.DATA + + self.wait_for(file_written, msg="file write") + + def test_with_str(self): + for i, data in enumerate(dummy_data.PIECES): + self.handle.add_piece(i, data.decode(), 0) + + self.wait_until_torrent_finished() + + def test_with_bytes(self): + for i, data in enumerate(dummy_data.PIECES): + self.handle.add_piece(i, data, 0) + + self.wait_until_torrent_finished() + + class test_torrent_info(unittest.TestCase): def test_bencoded_constructor(self):