This is an automated email from the ASF dual-hosted git repository. wangdan pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-pegasus.git
The following commit(s) were added to refs/heads/master by this push: new 18e8aeb74 test: enable validation logic in debug-only code to run during unit tests (#2262) 18e8aeb74 is described below commit 18e8aeb744228a01247fe3970e375785ddcda4db Author: Dan Wang <wang...@apache.org> AuthorDate: Tue Jul 1 19:01:07 2025 +0800 test: enable validation logic in debug-only code to run during unit tests (#2262) In Pegasus, unit tests are not necessarily executed in debug mode (i.e., with the `NDEBUG` macro undefined). For example, the GitHub CI workflow builds and runs unit tests in release mode. As a result, certain test-related code paths that are only enabled in debug builds are not actually executed during CI testing. To address this, we now allow such debug-only validation logic to be compiled and executed when building test code (i.e., executing `./run.sh build --test` where `--test` defines the `MOCK_TEST` macro). This ensures that debug-mode test logic is included and exercised during unit test runs, improving test coverage in CI and other environments. --- src/meta/server_state.cpp | 7 ++-- src/rpc/dsn_message_parser.cpp | 79 ++++++++++++++++++++++-------------------- src/server/result_writer.cpp | 1 - src/task/task_worker.cpp | 10 +++--- src/utils/alloc.h | 9 +++-- src/utils/blob.h | 8 +++-- src/utils/errors.h | 2 +- src/utils/fmt_logging.h | 5 +++ src/utils/test/blob_test.cpp | 4 --- 9 files changed, 70 insertions(+), 55 deletions(-) diff --git a/src/meta/server_state.cpp b/src/meta/server_state.cpp index 1b1257a88..4e504ff24 100644 --- a/src/meta/server_state.cpp +++ b/src/meta/server_state.cpp @@ -1829,9 +1829,11 @@ void server_state::update_configuration_locally( ns = get_node_state(_nodes, node, false); CHECK_NOTNULL(ns, "invalid node: {}", node); } -#ifndef NDEBUG + +#if defined(MOCK_TEST) || !defined(NDEBUG) request_check(old_pc, *config_request); #endif + switch (config_request->type) { case config_type::CT_ASSIGN_PRIMARY: case config_type::CT_UPGRADE_TO_PRIMARY: @@ -1940,9 +1942,10 @@ void server_state::update_configuration_locally( boost::lexical_cast<std::string>(*config_request)); } -#ifndef NDEBUG +#if defined(MOCK_TEST) || !defined(NDEBUG) check_consistency(gpid); #endif + if (_config_change_subscriber) { _config_change_subscriber(_all_apps); } diff --git a/src/rpc/dsn_message_parser.cpp b/src/rpc/dsn_message_parser.cpp index 178a60273..d475318b5 100644 --- a/src/rpc/dsn_message_parser.cpp +++ b/src/rpc/dsn_message_parser.cpp @@ -26,9 +26,10 @@ #include "dsn_message_parser.h" -#include <stddef.h> -#include <stdint.h> +#include <cstddef> +#include <cstdint> #include <memory> +#include <numeric> #include <vector> #include "rpc/rpc_message.h" @@ -102,50 +103,52 @@ message_ex *dsn_message_parser::get_message_on_receive(message_reader *reader, void dsn_message_parser::prepare_on_send(message_ex *msg) { auto &header = msg->header; - auto &buffers = msg->buffers; - -#ifndef NDEBUG - int i_max = (int)buffers.size() - 1; - size_t len = 0; - for (int i = 0; i <= i_max; i++) { - len += (size_t)buffers[i].length(); + const auto &buffers = msg->buffers; + +#if defined(MOCK_TEST) || !defined(NDEBUG) + { + const size_t len = + std::accumulate(buffers.begin(), buffers.end(), 0UL, [](size_t sum, const auto &buf) { + return sum + buf.length(); + }); + CHECK_EQ(len, header->body_length + sizeof(message_header)); } - CHECK_EQ(len, header->body_length + sizeof(message_header)); #endif - if (task_spec::get(msg->local_rpc_code)->rpc_message_crc_required) { - // compute data crc if necessary (only once for the first time) - if (header->body_crc32 == CRC_INVALID) { - int i_max = (int)buffers.size() - 1; - uint32_t crc32 = 0; - size_t len = 0; - for (int i = 0; i <= i_max; i++) { - uint32_t lcrc; - const void *ptr; - size_t sz; - - if (i == 0) { - ptr = (const void *)(buffers[i].data() + sizeof(message_header)); - sz = (size_t)buffers[i].length() - sizeof(message_header); - } else { - ptr = (const void *)buffers[i].data(); - sz = (size_t)buffers[i].length(); - } - - lcrc = dsn::utils::crc32_calc(ptr, sz, crc32); - crc32 = dsn::utils::crc32_concat(0, 0, crc32, len, crc32, lcrc, sz); - - len += sz; + if (!task_spec::get(msg->local_rpc_code)->rpc_message_crc_required) { + return; + } + + // compute data crc if necessary (only once for the first time) + if (header->body_crc32 == CRC_INVALID) { + uint32_t crc32 = 0; + size_t len = 0; + + for (size_t i = 0; i < buffers.size(); ++i) { + const auto &buf = buffers[i]; + const char *ptr = buf.data(); + size_t sz = buf.length(); + + if (i == 0) { + ptr += sizeof(message_header); + + // TODO(wangdan): CHECK_GE(sz, sizeof(message_header)) ? + sz -= sizeof(message_header); } - CHECK_EQ(len, header->body_length); - header->body_crc32 = crc32; + const auto lcrc = dsn::utils::crc32_calc(ptr, sz, crc32); + crc32 = dsn::utils::crc32_concat(0, 0, crc32, len, crc32, lcrc, sz); + + len += sz; } - // always compute header crc - header->hdr_crc32 = CRC_INVALID; - header->hdr_crc32 = dsn::utils::crc32_calc(header, sizeof(message_header), 0); + CHECK_EQ(len, header->body_length); + header->body_crc32 = crc32; } + + // always compute header crc + header->hdr_crc32 = CRC_INVALID; + header->hdr_crc32 = dsn::utils::crc32_calc(header, sizeof(message_header), 0); } int dsn_message_parser::get_buffers_on_send(message_ex *msg, /*out*/ send_buf *buffers) diff --git a/src/server/result_writer.cpp b/src/server/result_writer.cpp index df78172e9..4d3a9160e 100644 --- a/src/server/result_writer.cpp +++ b/src/server/result_writer.cpp @@ -21,7 +21,6 @@ #include <pegasus/error.h> #include <chrono> -#include <type_traits> #include <utility> #include "pegasus/client.h" diff --git a/src/task/task_worker.cpp b/src/task/task_worker.cpp index 01fec9887..d5606d2a8 100644 --- a/src/task/task_worker.cpp +++ b/src/task/task_worker.cpp @@ -236,20 +236,22 @@ void task_worker::loop() q->decrease_count(batch_size); -#ifndef NDEBUG +#if defined(MOCK_TEST) || !defined(NDEBUG) int count = 0; #endif + while (task != nullptr) { next = task->next; task->next = nullptr; task->exec_internal(); task = next; -#ifndef NDEBUG - count++; + +#if defined(MOCK_TEST) || !defined(NDEBUG) + ++count; #endif } -#ifndef NDEBUG +#if defined(MOCK_TEST) || !defined(NDEBUG) CHECK_EQ_MSG(count, batch_size, "returned task count and batch size do not match"); #endif diff --git a/src/utils/alloc.h b/src/utils/alloc.h index fdb799117..fa078cd8c 100644 --- a/src/utils/alloc.h +++ b/src/utils/alloc.h @@ -30,8 +30,13 @@ // where CACHELINE_SIZE is defined. #ifdef CACHELINE_SIZE -#ifndef NDEBUG +#if defined(MOCK_TEST) || !defined(NDEBUG) + +#include <cstdint> +#include <fmt/format.h> + #include "utils/fmt_logging.h" + #endif namespace dsn { @@ -53,7 +58,7 @@ cacheline_aligned_ptr<T> cacheline_aligned_alloc_array(size_t len) T *array = new (buffer) T[len]; -#ifndef NDEBUG +#if defined(MOCK_TEST) || !defined(NDEBUG) if (sizeof(T) <= CACHELINE_SIZE && (sizeof(T) & (sizeof(T) - 1)) == 0) { for (size_t i = 0; i < len; ++i) { T *elem = &(array[i]); diff --git a/src/utils/blob.h b/src/utils/blob.h index c1212afb4..d07ac7df5 100644 --- a/src/utils/blob.h +++ b/src/utils/blob.h @@ -114,9 +114,11 @@ public: /// NOTE: this operation is not efficient since it involves a memory copy. [[nodiscard]] static blob create_from_bytes(const char *s, size_t len) { - DCHECK(s != nullptr || len == 0, - "null source pointer with non-zero length would lead to " - "undefined behaviour"); +#if defined(MOCK_TEST) || !defined(NDEBUG) + CHECK(s != nullptr || len == 0, + "null source pointer with non-zero length would lead to " + "undefined behaviour"); +#endif std::shared_ptr<char> s_arr(new char[len], std::default_delete<char[]>()); memcpy(s_arr.get(), s, len); diff --git a/src/utils/errors.h b/src/utils/errors.h index d262f2241..36b99d070 100644 --- a/src/utils/errors.h +++ b/src/utils/errors.h @@ -294,7 +294,7 @@ USER_DEFINED_STRUCTURE_FORMATTER(::dsn::error_s); } \ } while (false) -#ifndef NDEBUG +#if defined(MOCK_TEST) || !defined(NDEBUG) #define DCHECK_OK CHECK_OK #else #define DCHECK_OK(s, ...) diff --git a/src/utils/fmt_logging.h b/src/utils/fmt_logging.h index 97e751a48..6360bbfb9 100644 --- a/src/utils/fmt_logging.h +++ b/src/utils/fmt_logging.h @@ -324,6 +324,11 @@ inline const char *null_str_printer(const char *s) { return s == nullptr ? "(nul } \ } while (0) +// TODO(wangdan): currently enable `DCHECK` for test code (via `MOCK_TEST`) causes many unit +// tests to fail; it will be enabled after the issues are resolved. +// +// After resolved, enable `DCHECK` for test code by: +// #if defined(MOCK_TEST) || !defined(NDEBUG) #ifndef NDEBUG #define DCHECK CHECK #define DCHECK_NOTNULL CHECK_NOTNULL diff --git a/src/utils/test/blob_test.cpp b/src/utils/test/blob_test.cpp index 586a7d68d..37a7f502d 100644 --- a/src/utils/test/blob_test.cpp +++ b/src/utils/test/blob_test.cpp @@ -32,8 +32,6 @@ TEST(BlobTest, CreateFromZeroLengthNullptr) EXPECT_EQ(0, obj.size()); } -#ifndef NDEBUG - TEST(BlobTest, CreateFromNonZeroLengthNullptr) { ASSERT_DEATH({ const auto &obj = blob::create_from_bytes(nullptr, 1); }, @@ -41,8 +39,6 @@ TEST(BlobTest, CreateFromNonZeroLengthNullptr) "undefined behaviour"); } -#endif - struct blob_base_case { std::string expected_str; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pegasus.apache.org For additional commands, e-mail: commits-h...@pegasus.apache.org