From e2f8bce539d9fa6f6bdd0badab1473f467efd8c5 Mon Sep 17 00:00:00 2001 From: arvidn Date: Tue, 6 Nov 2018 23:36:35 +0100 Subject: [PATCH] add tests for low level I/O functions, read_* and write_*. also turn some raw for loops into range-for loops in the I/O functions --- include/libtorrent/aux_/io.hpp | 17 +- test/Jamfile | 1 + test/Makefile.am | 2 + test/test_io.cpp | 292 +++++++++++++++++++++++++++++++++ 4 files changed, 302 insertions(+), 10 deletions(-) create mode 100644 test/test_io.cpp diff --git a/include/libtorrent/aux_/io.hpp b/include/libtorrent/aux_/io.hpp index dabd102a3..21df9a3f5 100644 --- a/include/libtorrent/aux_/io.hpp +++ b/include/libtorrent/aux_/io.hpp @@ -50,10 +50,10 @@ namespace libtorrent { namespace aux { read_impl(span& view, type) { T ret = 0; - for (std::size_t i = 0; i < sizeof(T); ++i) + for (Byte const b : view.first(sizeof(T))) { ret <<= 8; - ret |= static_cast(view[i]); + ret |= static_cast(b); } view = view.subspan(sizeof(T)); return ret; @@ -68,10 +68,10 @@ namespace libtorrent { namespace aux { T val = static_cast(data); TORRENT_ASSERT(data == static_cast(val)); int shift = int(sizeof(T)) * 8; - for (std::size_t i = 0; i < sizeof(T); ++i) + for (Byte& b : view.first(sizeof(T))) { shift -= 8; - view[i] = static_cast((val >> shift) & 0xff); + b = static_cast((val >> shift) & 0xff); } view = view.subspan(sizeof(T)); } @@ -167,12 +167,9 @@ namespace libtorrent { namespace aux { template inline int write_string(std::string const& str, span& view) { - std::size_t const len = str.size(); - for (std::size_t i = 0; i < len; ++i) - view[i] = str[i]; - - view = view.subspan(len); - return int(len); + std::copy(str.begin(), str.end(), view.begin()); + view = view.subspan(str.size()); + return int(str.size()); } }} diff --git a/test/Jamfile b/test/Jamfile index 5d27fbd62..b1bb8dfb1 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -104,6 +104,7 @@ explicit stage_enum_if ; test-suite libtorrent : [ run test_primitives.cpp + test_io.cpp test_create_torrent.cpp test_packet_buffer.cpp test_timestamp_history.cpp diff --git a/test/Makefile.am b/test/Makefile.am index 93cf90047..f91a65645 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -49,6 +49,7 @@ test_programs = \ test_ffs \ test_session_params \ test_span \ + test_io \ test_alloca if ENABLE_TESTS @@ -272,6 +273,7 @@ test_direct_dht_SOURCES = test_direct_dht.cpp test_ffs_SOURCES = test_ffs.cpp test_session_params_SOURCES = test_session_params.cpp test_span_SOURCES = test_span.cpp +test_io_SOURCES = test_io.cpp test_alloca_SOURCES = test_alloca.cpp LDADD = libtest.la $(top_builddir)/src/libtorrent-rasterbar.la diff --git a/test/test_io.cpp b/test/test_io.cpp new file mode 100644 index 000000000..869c10b32 --- /dev/null +++ b/test/test_io.cpp @@ -0,0 +1,292 @@ +/* + +Copyright (c) 2018, 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/io.hpp" +#include "libtorrent/aux_/io.hpp" +#include "libtorrent/span.hpp" + +using namespace lt::detail; +using namespace lt::aux; +using lt::span; + +TORRENT_TEST(write_uint8) +{ + std::array buf; + buf.fill(0x55); + char* ptr = buf.data(); + write_uint8(0x10, ptr); + TEST_CHECK(ptr == buf.data() + 1); + TEST_CHECK(buf[0] == 0x10); + TEST_CHECK(buf[1] == 0x55); +} + +TORRENT_TEST(write_uint16) +{ + std::array buf; + buf.fill(0x55); + char* ptr = buf.data(); + write_uint16(0x2010, ptr); + TEST_CHECK(ptr == buf.data() + 2); + TEST_CHECK(buf[0] == 0x20); + TEST_CHECK(buf[1] == 0x10); + TEST_CHECK(buf[2] == 0x55); +} + +TORRENT_TEST(write_uint32) +{ + std::array buf; + buf.fill(0x55); + char* ptr = buf.data(); + write_uint32(0x40302010, ptr); + TEST_CHECK(ptr == buf.data() + 4); + TEST_CHECK(buf[0] == 0x40); + TEST_CHECK(buf[1] == 0x30); + TEST_CHECK(buf[2] == 0x20); + TEST_CHECK(buf[3] == 0x10); + TEST_CHECK(buf[4] == 0x55); +} + +TORRENT_TEST(write_int32) +{ + std::array buf; + buf.fill(0x55); + char* ptr = buf.data(); + write_int32(0x40302010, ptr); + TEST_CHECK(ptr == buf.data() + 4); + TEST_CHECK(buf[0] == 0x40); + TEST_CHECK(buf[1] == 0x30); + TEST_CHECK(buf[2] == 0x20); + TEST_CHECK(buf[3] == 0x10); + TEST_CHECK(buf[4] == 0x55); +} + +TORRENT_TEST(write_uint64) +{ + std::array buf; + buf.fill(0x55); + std::uint8_t* ptr = buf.data(); + write_uint64(0x8070605040302010ull, ptr); + TEST_CHECK(ptr == buf.data() + 8); + TEST_CHECK(buf[0] == 0x80); + TEST_CHECK(buf[1] == 0x70); + TEST_CHECK(buf[2] == 0x60); + TEST_CHECK(buf[3] == 0x50); + TEST_CHECK(buf[4] == 0x40); + TEST_CHECK(buf[5] == 0x30); + TEST_CHECK(buf[6] == 0x20); + TEST_CHECK(buf[7] == 0x10); + TEST_CHECK(buf[8] == 0x55); +} + +TORRENT_TEST(read_uint8) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x10; + char const* ptr = buf.data(); + TEST_CHECK(read_uint8(ptr) == 0x10); + TEST_CHECK(ptr == buf.data() + 1); +} + +TORRENT_TEST(read_uint16) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x20; + buf[1] = 0x10; + char const* ptr = buf.data(); + TEST_CHECK(read_uint16(ptr) == 0x2010); + TEST_CHECK(ptr == buf.data() + 2); +} + +TORRENT_TEST(read_uint32) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x40; + buf[1] = 0x30; + buf[2] = 0x20; + buf[3] = 0x10; + char const* ptr = buf.data(); + TEST_CHECK(read_uint32(ptr) == 0x40302010); + TEST_CHECK(ptr == buf.data() + 4); +} + +TORRENT_TEST(read_uint64) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x80; + buf[1] = 0x70; + buf[2] = 0x60; + buf[3] = 0x50; + buf[4] = 0x40; + buf[5] = 0x30; + buf[6] = 0x20; + buf[7] = 0x10; + std::uint8_t const* ptr = buf.data(); + TEST_CHECK(read_uint64(ptr) == 0x8070605040302010ull); + TEST_CHECK(ptr == buf.data() + 8); +} + +TORRENT_TEST(read_int32) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x40; + buf[1] = 0x30; + buf[2] = 0x20; + buf[3] = 0x10; + std::uint8_t const* ptr = buf.data(); + TEST_CHECK(read_int32(ptr) == 0x40302010); + TEST_CHECK(ptr == buf.data() + 4); +} + +TORRENT_TEST(write_uint8_span) +{ + std::array buf; + buf.fill(0x55); + span view(buf); + write_uint8(0x10, view); + TEST_CHECK(view == span(buf).subspan(1)); + TEST_CHECK(buf[0] == 0x10); + TEST_CHECK(buf[1] == 0x55); +} + +TORRENT_TEST(write_uint16_span) +{ + std::array buf; + buf.fill(0x55); + span view(buf); + write_uint16(0x2010, view); + TEST_CHECK(view == span(buf).subspan(2)); + TEST_CHECK(buf[0] == 0x20); + TEST_CHECK(buf[1] == 0x10); + TEST_CHECK(buf[2] == 0x55); +} + +TORRENT_TEST(write_uint32_span) +{ + std::array buf; + buf.fill(0x55); + span view(buf); + write_uint32(0x40302010, view); + TEST_CHECK(view == span(buf).subspan(4)); + TEST_CHECK(buf[0] == 0x40); + TEST_CHECK(buf[1] == 0x30); + TEST_CHECK(buf[2] == 0x20); + TEST_CHECK(buf[3] == 0x10); + TEST_CHECK(buf[4] == 0x55); +} + +TORRENT_TEST(write_uint64_span) +{ + std::array buf; + buf.fill(0x55); + span view(buf); + write_uint64(0x8070605040302010ull, view); + TEST_CHECK(view == span(buf).subspan(8)); + TEST_CHECK(buf[0] == 0x80); + TEST_CHECK(buf[1] == 0x70); + TEST_CHECK(buf[2] == 0x60); + TEST_CHECK(buf[3] == 0x50); + TEST_CHECK(buf[4] == 0x40); + TEST_CHECK(buf[5] == 0x30); + TEST_CHECK(buf[6] == 0x20); + TEST_CHECK(buf[7] == 0x10); + TEST_CHECK(buf[8] == 0x55); +} + +TORRENT_TEST(read_uint8_span) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x10; + span view(buf); + TEST_CHECK(read_uint8(view) == 0x10); + TEST_CHECK(view == span(buf).subspan(1)); +} + +TORRENT_TEST(read_uint16_span) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x20; + buf[1] = 0x10; + span view(buf); + TEST_CHECK(read_uint16(view) == 0x2010); + TEST_CHECK(view == span(buf).subspan(2)); +} + +TORRENT_TEST(read_uint32_span) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x40; + buf[1] = 0x30; + buf[2] = 0x20; + buf[3] = 0x10; + span view(buf); + TEST_CHECK(read_uint32(view) == 0x40302010); + TEST_CHECK(view == span(buf).subspan(4)); +} + +TORRENT_TEST(read_int32_span) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x40; + buf[1] = 0x30; + buf[2] = 0x20; + buf[3] = 0x10; + span view(buf); + TEST_CHECK(read_int32(view) == 0x40302010); + TEST_CHECK(view == span(buf).subspan(4)); +} + +TORRENT_TEST(read_uint64_span) +{ + std::array buf; + buf.fill(0x55); + buf[0] = 0x80; + buf[1] = 0x70; + buf[2] = 0x60; + buf[3] = 0x50; + buf[4] = 0x40; + buf[5] = 0x30; + buf[6] = 0x20; + buf[7] = 0x10; + span view(buf); + TEST_CHECK(read_uint64(view) == 0x8070605040302010ull); + TEST_CHECK(view == span(buf).subspan(8)); +}