| 1 | // |
|---|---|
| 2 | // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) |
| 3 | // |
| 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 6 | // |
| 7 | |
| 8 | #ifndef BOOST_MYSQL_TEST_UNIT_INCLUDE_TEST_UNIT_MOCK_EXECUTION_PROCESSOR_HPP |
| 9 | #define BOOST_MYSQL_TEST_UNIT_INCLUDE_TEST_UNIT_MOCK_EXECUTION_PROCESSOR_HPP |
| 10 | |
| 11 | #include <boost/mysql/diagnostics.hpp> |
| 12 | #include <boost/mysql/error_code.hpp> |
| 13 | #include <boost/mysql/field_view.hpp> |
| 14 | #include <boost/mysql/metadata.hpp> |
| 15 | #include <boost/mysql/string_view.hpp> |
| 16 | |
| 17 | #include <boost/mysql/detail/access.hpp> |
| 18 | #include <boost/mysql/detail/execution_processor/execution_processor.hpp> |
| 19 | |
| 20 | #include <boost/mysql/impl/internal/protocol/protocol.hpp> |
| 21 | |
| 22 | #include <boost/config.hpp> |
| 23 | #include <boost/test/unit_test.hpp> |
| 24 | |
| 25 | #include <cstddef> |
| 26 | |
| 27 | #include "test_unit/fail_count.hpp" |
| 28 | |
| 29 | namespace boost { |
| 30 | namespace mysql { |
| 31 | namespace test { |
| 32 | |
| 33 | class mock_execution_processor : public detail::execution_processor |
| 34 | { |
| 35 | struct num_calls_t |
| 36 | { |
| 37 | std::size_t reset{}; |
| 38 | std::size_t on_num_meta{}; |
| 39 | std::size_t on_meta{}; |
| 40 | std::size_t on_head_ok_packet{}; |
| 41 | std::size_t on_row_batch_start{}; |
| 42 | std::size_t on_row_batch_finish{}; |
| 43 | std::size_t on_row{}; |
| 44 | std::size_t on_row_ok_packet{}; |
| 45 | }; |
| 46 | |
| 47 | public: |
| 48 | // Validate the number of calls safely |
| 49 | class num_calls_validator |
| 50 | { |
| 51 | num_calls_t expected_{}; |
| 52 | num_calls_t actual_{}; |
| 53 | |
| 54 | public: |
| 55 | num_calls_validator(num_calls_t actual) noexcept : actual_(actual) {} |
| 56 | |
| 57 | BOOST_ATTRIBUTE_NODISCARD |
| 58 | num_calls_validator& reset(std::size_t v) noexcept |
| 59 | { |
| 60 | expected_.reset = v; |
| 61 | return *this; |
| 62 | } |
| 63 | |
| 64 | BOOST_ATTRIBUTE_NODISCARD |
| 65 | num_calls_validator& on_num_meta(std::size_t v) noexcept |
| 66 | { |
| 67 | expected_.on_num_meta = v; |
| 68 | return *this; |
| 69 | } |
| 70 | |
| 71 | BOOST_ATTRIBUTE_NODISCARD |
| 72 | num_calls_validator& on_meta(std::size_t v) noexcept |
| 73 | { |
| 74 | expected_.on_meta = v; |
| 75 | return *this; |
| 76 | } |
| 77 | |
| 78 | BOOST_ATTRIBUTE_NODISCARD |
| 79 | num_calls_validator& on_head_ok_packet(std::size_t v) noexcept |
| 80 | { |
| 81 | expected_.on_head_ok_packet = v; |
| 82 | return *this; |
| 83 | } |
| 84 | |
| 85 | BOOST_ATTRIBUTE_NODISCARD |
| 86 | num_calls_validator& on_row_batch_start(std::size_t v) noexcept |
| 87 | { |
| 88 | expected_.on_row_batch_start = v; |
| 89 | return *this; |
| 90 | } |
| 91 | |
| 92 | BOOST_ATTRIBUTE_NODISCARD |
| 93 | num_calls_validator& on_row_batch_finish(std::size_t v) noexcept |
| 94 | { |
| 95 | expected_.on_row_batch_finish = v; |
| 96 | return *this; |
| 97 | } |
| 98 | |
| 99 | BOOST_ATTRIBUTE_NODISCARD |
| 100 | num_calls_validator& on_row(std::size_t v) noexcept |
| 101 | { |
| 102 | expected_.on_row = v; |
| 103 | return *this; |
| 104 | } |
| 105 | |
| 106 | BOOST_ATTRIBUTE_NODISCARD |
| 107 | num_calls_validator& on_row_ok_packet(std::size_t v) noexcept |
| 108 | { |
| 109 | expected_.on_row_ok_packet = v; |
| 110 | return *this; |
| 111 | } |
| 112 | |
| 113 | void validate() |
| 114 | { |
| 115 | BOOST_TEST(expected_.reset == actual_.reset); |
| 116 | BOOST_TEST(expected_.on_num_meta == actual_.on_num_meta); |
| 117 | BOOST_TEST(expected_.on_meta == actual_.on_meta); |
| 118 | BOOST_TEST(expected_.on_head_ok_packet == actual_.on_head_ok_packet); |
| 119 | BOOST_TEST(expected_.on_row_batch_start == actual_.on_row_batch_start); |
| 120 | BOOST_TEST(expected_.on_row_batch_finish == actual_.on_row_batch_finish); |
| 121 | BOOST_TEST(expected_.on_row == actual_.on_row); |
| 122 | BOOST_TEST(expected_.on_row_ok_packet == actual_.on_row_ok_packet); |
| 123 | } |
| 124 | }; |
| 125 | |
| 126 | mock_execution_processor() = default; |
| 127 | std::uint64_t affected_rows() const noexcept { return ok_packet_.affected_rows; } |
| 128 | std::uint64_t last_insert_id() const noexcept { return ok_packet_.last_insert_id; } |
| 129 | string_view info() const noexcept { return ok_packet_.info; } |
| 130 | std::size_t num_meta() const noexcept { return num_meta_; } |
| 131 | const std::vector<metadata>& meta() const noexcept { return meta_; } |
| 132 | const std::vector<detail::output_ref>& refs() const noexcept { return refs_; } |
| 133 | |
| 134 | BOOST_ATTRIBUTE_NODISCARD |
| 135 | num_calls_validator num_calls() noexcept { return num_calls_validator(num_calls_); } |
| 136 | |
| 137 | void set_fail_count(fail_count fc, diagnostics diag = diagnostics()) |
| 138 | { |
| 139 | fc_ = fc; |
| 140 | diag_ = std::move(diag); |
| 141 | } |
| 142 | |
| 143 | private: |
| 144 | // Data |
| 145 | num_calls_t num_calls_; |
| 146 | struct |
| 147 | { |
| 148 | std::uint64_t affected_rows{}; |
| 149 | std::uint64_t last_insert_id{}; |
| 150 | std::string info; |
| 151 | } ok_packet_{}; |
| 152 | std::size_t num_meta_{}; |
| 153 | std::vector<metadata> meta_; |
| 154 | std::vector<detail::output_ref> refs_; |
| 155 | fail_count fc_; |
| 156 | diagnostics diag_; |
| 157 | |
| 158 | // Helpers |
| 159 | error_code maybe_fail(diagnostics& diag) |
| 160 | { |
| 161 | auto err = fc_.maybe_fail(); |
| 162 | if (err) |
| 163 | { |
| 164 | diag = diag_; |
| 165 | } |
| 166 | return err; |
| 167 | } |
| 168 | |
| 169 | void handle_ok(const detail::ok_view& pack) |
| 170 | { |
| 171 | ok_packet_.affected_rows = pack.affected_rows; |
| 172 | ok_packet_.last_insert_id = pack.last_insert_id; |
| 173 | ok_packet_.info = pack.info; |
| 174 | } |
| 175 | |
| 176 | protected: |
| 177 | void reset_impl() noexcept override { ++num_calls_.reset; } |
| 178 | error_code on_head_ok_packet_impl(const detail::ok_view& pack, diagnostics& diag) override |
| 179 | { |
| 180 | ++num_calls_.on_head_ok_packet; |
| 181 | handle_ok(pack); |
| 182 | return maybe_fail(diag); |
| 183 | } |
| 184 | void on_num_meta_impl(std::size_t num_meta) override |
| 185 | { |
| 186 | ++num_calls_.on_num_meta; |
| 187 | num_meta_ = num_meta; |
| 188 | } |
| 189 | error_code on_meta_impl(const detail::coldef_view& coldef, bool is_last, diagnostics& diag) override |
| 190 | { |
| 191 | ++num_calls_.on_meta; |
| 192 | meta_.push_back(x: detail::access::construct<metadata>(args: coldef, args: true)); |
| 193 | return is_last ? maybe_fail(diag) : error_code(); |
| 194 | } |
| 195 | void on_row_batch_start_impl() override { ++num_calls_.on_row_batch_start; } |
| 196 | void on_row_batch_finish_impl() override { ++num_calls_.on_row_batch_finish; } |
| 197 | error_code on_row_impl(span<const std::uint8_t>, const detail::output_ref& ref, std::vector<field_view>&) |
| 198 | override |
| 199 | { |
| 200 | ++num_calls_.on_row; |
| 201 | refs_.push_back(x: ref); |
| 202 | return fc_.maybe_fail(); |
| 203 | } |
| 204 | error_code on_row_ok_packet_impl(const detail::ok_view& pack) override |
| 205 | { |
| 206 | ++num_calls_.on_row_ok_packet; |
| 207 | handle_ok(pack); |
| 208 | return fc_.maybe_fail(); |
| 209 | } |
| 210 | }; |
| 211 | |
| 212 | } // namespace test |
| 213 | } // namespace mysql |
| 214 | } // namespace boost |
| 215 | |
| 216 | #endif |
| 217 |
