Browse Source

add test for hexutil, add necessary testutils

pull/4/head
masterjedy 5 years ago
parent
commit
13bcd44cd1
  1. 1
      test/CMakeLists.txt
  2. 11
      test/p2p/common/CMakeLists.txt
  3. 63
      test/p2p/common/hexutil_test.cpp
  4. 9
      test/testutil/CMakeLists.txt
  5. 77
      test/testutil/gmock_actions.hpp
  6. 17
      test/testutil/libp2p/CMakeLists.txt
  7. 77
      test/testutil/libp2p/message_read_writer_helper.cpp
  8. 44
      test/testutil/libp2p/message_read_writer_helper.hpp
  9. 22
      test/testutil/libp2p/peer.cpp
  10. 24
      test/testutil/libp2p/peer.hpp
  11. 58
      test/testutil/literals.hpp
  12. 34
      test/testutil/ma_generator.hpp
  13. 97
      test/testutil/outcome.hpp
  14. 28
      test/testutil/testparam.hpp

1
test/CMakeLists.txt

@ -7,3 +7,4 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(acceptance)
add_subdirectory(p2p)
add_subdirectory(testutil)

11
test/p2p/common/CMakeLists.txt

@ -0,0 +1,11 @@
##
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
##
addtest(hexutil_test
hexutil_test.cpp
)
target_link_libraries(hexutil_test
hexutil
)

63
test/p2p/common/hexutil_test.cpp

@ -0,0 +1,63 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include "common/hexutil.hpp"
#include <gtest/gtest.h>
#include "testutil/literals.hpp"
using namespace libp2p::common;
using namespace std::string_literals;
/**
* @given Array of bytes
* @when hex it
* @then hex matches expected encoding
*/
TEST(Common, Hexutil_Hex) {
auto bin = "00010204081020FF"_unhex;
auto hexed = hex_upper(bin);
ASSERT_EQ(hexed, "00010204081020FF"s);
}
/**
* @given Hexencoded string of even length
* @when unhex
* @then no exception, result matches expected value
*/
TEST(Common, Hexutil_UnhexEven) {
auto s = "00010204081020ff"s;
std::vector<uint8_t> actual;
ASSERT_NO_THROW(
actual = unhex(s).value())
<< "unhex result does not contain expected std::vector<uint8_t>";
auto expected = "00010204081020ff"_unhex;
ASSERT_EQ(actual, expected);
}
/**
* @given Hexencoded string of odd length
* @when unhex
* @then unhex result contains error
*/
TEST(Common, Hexutil_UnhexOdd) {
ASSERT_NO_THROW({
unhex("0").error();
}) << "unhex did not return an error as expected";
}
/**
* @given Hexencoded string with non-hex letter
* @when unhex
* @then unhex result contains error
*/
TEST(Common, Hexutil_UnhexInvalid) {
ASSERT_NO_THROW({
unhex("keks").error();
}) << "unhex did not return an error as expected";
}

9
test/testutil/CMakeLists.txt

@ -0,0 +1,9 @@
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
add_subdirectory(libp2p)
add_library(testutil INTERFACE)
target_link_libraries(testutil INTERFACE
testutil_peer
)

77
test/testutil/gmock_actions.hpp

@ -0,0 +1,77 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_GMOCK_ACTIONS_HPP
#define LIBP2P_GMOCK_ACTIONS_HPP
#include <gmock/gmock.h>
#include <boost/system/error_code.hpp>
/**
* @code
* const int size = 1;
* EXPECT_CALL(*connection_, read(_, _, _)).WillOnce(AsioSuccess(size));
* auto buf = std::make_shared<std::vector<uint8_t>>(size, 0);
* secure_connection_->read(*buf, size, [&size, buf](auto &&res) mutable {
* ASSERT_TRUE(res) << res.error().message();
* ASSERT_EQ(read, size);
* });
* @endcode
*/
ACTION_P(AsioSuccess, size) {
// arg0 - buffer
// arg1 - bytes
// arg2 - callback
arg2(size);
}
/**
* @code
* const int size = 1;
* boost::system::error_code ec = ...;
* EXPECT_CALL(*connection_, read(_, _, _)).WillOnce(AsioCallback(ec, size));
* auto buf = std::make_shared<std::vector<uint8_t>>(size, 0);
* secure_connection_->read(*buf, size, [&size, buf, e=ec](auto &&ec, size_t
* read) mutable { ASSERT_EQ(ec.value(), e.value()); ASSERT_EQ(read, size);
* });
* @endcode
*/
ACTION_P2(AsioCallback, ec, size) {
// arg0 - buffer
// arg1 - bytes
// arg2 - callback
arg2(ec, size);
}
ACTION_P(Arg0CallbackWithArg, in) {
arg0(in);
}
ACTION_P(Arg1CallbackWithArg, in) {
arg1(in);
}
ACTION_P(Arg2CallbackWithArg, in) {
arg2(in);
}
ACTION_P(Arg3CallbackWithArg, in) {
arg3(in);
}
ACTION_P(UpgradeToSecureInbound, do_upgrade) {
arg1(do_upgrade(arg0));
}
ACTION_P(UpgradeToSecureOutbound, do_upgrade) {
arg2(do_upgrade(arg0));
}
ACTION_P(UpgradeToMuxed, do_upgrade) {
arg1(do_upgrade(arg0));
}
#endif // LIBP2P_GMOCK_ACTIONS_HPP

17
test/testutil/libp2p/CMakeLists.txt

@ -0,0 +1,17 @@
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
add_library(testutil_peer
peer.cpp
)
target_link_libraries(testutil_peer
libp2p_peer_id
)
add_library(testutil_read_writer_helper
message_read_writer_helper.cpp
message_read_writer_helper.hpp
)
target_link_libraries(testutil_read_writer_helper
uvarint
)

77
test/testutil/libp2p/message_read_writer_helper.cpp

@ -0,0 +1,77 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include "testutil/libp2p/message_read_writer_helper.hpp"
#include "p2p/multi/uvarint.hpp"
ACTION_P(PutBytes, bytes) { // NOLINT
std::copy(bytes.begin(), bytes.end(), arg0.begin());
arg2(bytes.size());
}
ACTION_P(CheckBytes, bytes) { // NOLINT
ASSERT_EQ((std::vector<uint8_t>{arg0.begin(), arg0.end()}), bytes); // NOLINT
arg2(bytes.size());
}
namespace libp2p::basic {
using multi::UVarint;
using testing::_;
void setReadExpectations(
const std::shared_ptr<ReadWriterMock> &read_writer_mock,
const std::vector<uint8_t> &msg) {
// read varint
UVarint varint_to_read{msg.size()};
for (size_t i = 0; i < varint_to_read.size(); ++i) {
EXPECT_CALL(*read_writer_mock, read(_, 1, _))
.WillOnce(
PutBytes(std::vector<uint8_t>{varint_to_read.toVector()[i]}));
}
// read message
EXPECT_CALL(*read_writer_mock, read(_, msg.size(), _))
.WillOnce(PutBytes(msg));
}
void setReadExpectations(
const std::shared_ptr<connection::StreamMock> &stream_mock,
const std::vector<uint8_t> &msg) {
// read varint
UVarint varint_to_read{msg.size()};
for (size_t i = 0; i < varint_to_read.size(); ++i) {
EXPECT_CALL(*stream_mock, read(_, 1, _))
.WillOnce(
PutBytes(std::vector<uint8_t>{varint_to_read.toVector()[i]}));
}
// read message
EXPECT_CALL(*stream_mock, read(_, msg.size(), _)).WillOnce(PutBytes(msg));
}
void setWriteExpectations(
const std::shared_ptr<ReadWriterMock> &read_writer_mock,
std::vector<uint8_t> msg) {
UVarint varint_to_write{msg.size()};
msg.insert(msg.begin(),
varint_to_write.toVector().begin(),
varint_to_write.toVector().end());
EXPECT_CALL(*read_writer_mock, write(_, msg.size(), _))
.WillOnce(CheckBytes(msg));
}
void setWriteExpectations(
const std::shared_ptr<connection::StreamMock> &stream_mock,
std::vector<uint8_t> msg) {
UVarint varint_to_write{msg.size()};
msg.insert(msg.begin(),
varint_to_write.toVector().begin(),
varint_to_write.toVector().end());
EXPECT_CALL(*stream_mock, write(_, msg.size(), _))
.WillOnce(CheckBytes(msg));
}
} // namespace libp2p::basic

44
test/testutil/libp2p/message_read_writer_helper.hpp

@ -0,0 +1,44 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_MESSAGE_READ_WRITER_HELPER_HPP
#define LIBP2P_MESSAGE_READ_WRITER_HELPER_HPP
#include <memory>
#include <vector>
#include "mock/p2p/basic/read_writer_mock.hpp"
#include "mock/p2p/connection/stream_mock.hpp"
/**
* Basically, methods in this file do the same thing as
* libp2p::basic::MessageReadWriter, but with a mock
*/
namespace libp2p::basic {
/**
* Set read expectations for the provided (\param read_writer_mock) to read
* (\param msg) with a prepended varint
*/
void setReadExpectations(
const std::shared_ptr<ReadWriterMock> &read_writer_mock,
const std::vector<uint8_t> &msg);
void setReadExpectations(
const std::shared_ptr<connection::StreamMock> &stream_mock,
const std::vector<uint8_t> &msg);
/**
* Set write expectations for the provided (\param read_writer_mock) to write
* (\param msg) with a prepended varint
*/
void setWriteExpectations(
const std::shared_ptr<ReadWriterMock> &read_writer_mock,
std::vector<uint8_t> msg);
void setWriteExpectations(
const std::shared_ptr<connection::StreamMock> &stream_mock,
std::vector<uint8_t> msg);
} // namespace libp2p::basic
#endif // LIBP2P_MESSAGE_READ_WRITER_HELPER_HPP

22
test/testutil/libp2p/peer.cpp

@ -0,0 +1,22 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include "testutil/libp2p/peer.hpp"
namespace testutil {
PeerId randomPeerId() {
PublicKey k;
k.type = T::ED25519;
k.data.resize(32u);
for (auto i = 0u; i < 32u; i++) {
k.data[i] = (rand() & 0xff);
}
return PeerId::fromPublicKey(k);
}
} // namespace testutil

24
test/testutil/libp2p/peer.hpp

@ -0,0 +1,24 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_TESTUTIL_PEER_HPP
#define LIBP2P_TESTUTIL_PEER_HPP
#include "p2p/crypto/key.hpp"
#include "p2p/multi/multihash.hpp"
#include "p2p/peer/peer_id.hpp"
namespace testutil {
using libp2p::crypto::PublicKey;
using libp2p::multi::Multihash;
using libp2p::peer::PeerId;
using T = libp2p::crypto::PublicKey::Type;
PeerId randomPeerId();
} // namespace testutil
#endif // LIBP2P_TESTUTIL_PEER_HPP

58
test/testutil/literals.hpp

@ -0,0 +1,58 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_TEST_TESTUTIL_LITERALS_HPP_
#define LIBP2P_TEST_TESTUTIL_LITERALS_HPP_
#include "p2p/common/types.hpp"
#include "p2p/common/hexutil.hpp"
#include "p2p/multi/multiaddress.hpp"
#include "p2p/multi/multihash.hpp"
#include "p2p/peer/peer_id.hpp"
/// creates a buffer filled with characters from the original string
/// mind that it does not perform unhexing, there is ""_unhex for it
//inline kagome::common::Buffer operator"" _buf(const char *c, size_t s) {
// std::vector<uint8_t> chars(c, c + s);
// return kagome::common::Buffer(std::move(chars));
//}
inline libp2p::common::Hash256 operator"" _hash256(const char *c, size_t s) {
libp2p::common::Hash256 hash{};
std::copy_n(c, std::min(s, 32ul), hash.rbegin());
return hash;
}
inline std::vector<uint8_t> operator"" _v(const char *c, size_t s) {
std::vector<uint8_t> chars(c, c + s);
return chars;
}
//inline kagome::common::Buffer operator"" _hex2buf(const char *c, size_t s) {
// return kagome::common::Buffer::fromHex(std::string_view(c, s)).value();
//}
inline std::vector<uint8_t> operator""_unhex(const char *c, size_t s) {
return libp2p::common::unhex(std::string_view(c, s)).value();
}
inline libp2p::multi::Multiaddress operator""_multiaddr(const char *c,
size_t s) {
return libp2p::multi::Multiaddress::create(std::string_view(c, s)).value();
}
/// creates a multihash instance from a hex string
inline libp2p::multi::Multihash operator""_multihash(const char *c, size_t s) {
return libp2p::multi::Multihash::createFromHex(std::string_view(c, s))
.value();
}
inline libp2p::peer::PeerId operator""_peerid(const char *c, size_t s) {
libp2p::crypto::PublicKey p;
p.data = std::vector<uint8_t>(c, c + s);
return libp2p::peer::PeerId::fromPublicKey(p);
}
#endif // LIBP2P_TEST_TESTUTIL_LITERALS_HPP_

34
test/testutil/ma_generator.hpp

@ -0,0 +1,34 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_TEST_TESTUTIL_LIBP2P_MA_GENERATOR_HPP
#define LIBP2P_TEST_TESTUTIL_LIBP2P_MA_GENERATOR_HPP
#include <iostream>
#include "libp2p/multi/multiaddress.hpp"
#include "testutil/outcome.hpp"
namespace testutil {
class MultiaddressGenerator {
using Multiaddress = libp2p::multi::Multiaddress;
public:
inline MultiaddressGenerator(std::string prefix, uint16_t start_port)
: prefix_{std::move(prefix)}, current_port_{start_port} {}
inline Multiaddress nextMultiaddress() {
std::string ma = prefix_ + std::to_string(current_port_++);
EXPECT_OUTCOME_TRUE(res, Multiaddress::create(ma));
return res;
}
private:
std::string prefix_;
uint16_t current_port_;
};
} // namespace testutil
#endif // LIBP2P_TEST_TESTUTIL_LIBP2P_MA_GENERATOR_HPP

97
test/testutil/outcome.hpp

@ -0,0 +1,97 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_GTEST_OUTCOME_UTIL_HPP
#define LIBP2P_GTEST_OUTCOME_UTIL_HPP
#include <gtest/gtest.h>
#include <outcome/outcome.hpp>
#include "common/visitor.hpp"
#define PP_CAT(a, b) PP_CAT_I(a, b)
#define PP_CAT_I(a, b) PP_CAT_II(~, a##b)
#define PP_CAT_II(p, res) res
#define UNIQUE_NAME(base) PP_CAT(base, __LINE__)
#define EXPECT_OUTCOME_TRUE_void(var, expr) \
auto &&var = expr; \
EXPECT_TRUE(var) << "Line " << __LINE__ << ": " << var.error().message();
#define EXPECT_OUTCOME_TRUE_name(var, val, expr) \
auto &&var = expr; \
EXPECT_TRUE(var) << "Line " << __LINE__ << ": " << var.error().message(); \
auto &&val = var.value();
#define EXPECT_OUTCOME_FALSE_void(var, expr) \
auto &&var = expr; \
EXPECT_FALSE(var) << "Line " << __LINE__ << ": " << var.error().message();
#define EXPECT_OUTCOME_FALSE_name(var, val, expr) \
auto &&var = expr; \
EXPECT_FALSE(var) << "Line " << __LINE__ << ": " << var.error().message(); \
auto &&val = var.error();
#define EXPECT_OUTCOME_TRUE_3(var, val, expr) \
EXPECT_OUTCOME_TRUE_name(var, val, expr)
#define EXPECT_OUTCOME_TRUE_2(val, expr) \
EXPECT_OUTCOME_TRUE_3(UNIQUE_NAME(_r), val, expr)
#define EXPECT_OUTCOME_TRUE_1(expr) \
EXPECT_OUTCOME_TRUE_void(UNIQUE_NAME(_v), expr)
#define EXPECT_OUTCOME_FALSE_3(var, val, expr) \
EXPECT_OUTCOME_FALSE_name(var, val, expr)
#define EXPECT_OUTCOME_FALSE_2(val, expr) \
EXPECT_OUTCOME_FALSE_3(UNIQUE_NAME(_r), val, expr)
#define EXPECT_OUTCOME_FALSE_1(expr) \
EXPECT_OUTCOME_FALSE_void(UNIQUE_NAME(_v), expr)
/**
* Use this macro in GTEST with 2 arguments to assert that getResult()
* returned VALUE and immediately get this value.
* EXPECT_OUTCOME_TRUE(val, getResult());
*/
#define EXPECT_OUTCOME_TRUE(val, expr) \
EXPECT_OUTCOME_TRUE_name(UNIQUE_NAME(_r), val, expr)
#define EXPECT_OUTCOME_FALSE(val, expr) \
EXPECT_OUTCOME_FALSE_name(UNIQUE_NAME(_f), val, expr)
#define EXPECT_OUTCOME_TRUE_MSG_void(var, expr, msg) \
auto &&var = expr; \
EXPECT_TRUE(var) << "Line " << __LINE__ << ": " << var.error().message() \
<< "\t" << (msg);
#define EXPECT_OUTCOME_TRUE_MSG_name(var, val, expr, msg) \
auto &&var = expr; \
EXPECT_TRUE(var) << "Line " << __LINE__ << ": " << var.error().message() \
<< "\t" << (msg); \
auto &&val = var.value();
/**
* Use this macro in GTEST with 2 arguments to assert that
* result of expression as outcome::result<T> is value and,
* but the value itself is not necessary.
* If result is error, macro prints corresponding error message
* and appends custom error message specified in msg.
*/
#define EXPECT_OUTCOME_TRUE_MSG_1(expr, msg) \
EXPECT_OUTCOME_TRUE_MSG_void(UNIQUE_NAME(_v), expr, msg)
/**
* Use this macro in GTEST with 3 arguments to assert that
* result of expression as outcome::result<T> is value and
* immediately get access to this value.
* If result is error, macro prints corresponding error message
* and appends custom error message specified in msg.
*/
#define EXPECT_OUTCOME_TRUE_MSG(val, expr, msg) \
EXPECT_OUTCOME_TRUE_MSG_name(UNIQUE_NAME(_r), val, expr, msg)
#endif // LIBP2P_GTEST_OUTCOME_UTIL_HPP

28
test/testutil/testparam.hpp

@ -0,0 +1,28 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_TEST_TESTUTIL_TESTPARAM_HPP
#define LIBP2P_TEST_TESTUTIL_TESTPARAM_HPP
#include <cstdint>
#include <vector>
namespace testutil {
template <typename T>
struct TestParam {
std::vector<uint8_t> encoded_value{};
bool should_fail{false};
T value{};
};
template <typename T>
TestParam<T> make_param(std::vector<uint8_t> &&buffer,
bool should_fail,
T &&value) {
return {buffer, should_fail, std::forward<T>(value)};
};
} // namespace testutil
#endif // LIBP2P_TEST_TESTUTIL_TESTPARAM_HPP
Loading…
Cancel
Save