1 /* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 #ifndef UNITTEST_GUNIT_XPLUGIN_XPL_ENCODER_VALIDATOR_H_ 24 #define UNITTEST_GUNIT_XPLUGIN_XPL_ENCODER_VALIDATOR_H_ 25 26 #include <gtest/gtest.h> 27 #include <stddef.h> 28 #include <string> 29 30 #include "plugin/x/protocol/encoders/encoding_xprotocol.h" 31 32 namespace protocol { 33 34 namespace test { 35 36 class Encoder_validator { 37 private: get_location()38 std::string get_location() { 39 if (m_message_started) { 40 return "(field: " + std::to_string(m_field_number) + ")"; 41 } 42 return "(operation-index:" + 43 std::to_string(m_field_number + m_raw_data_number) + ")"; 44 } 45 check_size(const char * info)46 void check_size(const char *info) { 47 if (m_buffer_left < 0) 48 FAIL() << "Buffer underflow at " << info << get_location() 49 << ", please increase the buffer in begin_xmessage or " 50 "ensure_buffer_size call"; 51 } 52 53 public: summarize_buffer(const char * info)54 void summarize_buffer(const char *info) { 55 if (m_buffer_left > 0 && !m_allow_not_used_data) { 56 FAIL() << "Buffer was not filled to its boundaries at " << info 57 << ", not used space: " << m_buffer_left; 58 } 59 60 if (m_buffer_left < 0) { 61 FAIL() << "Buffer is too small at " << info 62 << ", we need additional: " << -m_buffer_left 63 << " bytes, in total: " << -m_buffer_left + m_buffer_size; 64 } 65 } 66 67 using Position = XProtocol_encoder::Position; 68 69 template <uint32_t t> 70 using Field_delimiter = XProtocol_encoder::Field_delimiter<t>; 71 configure_allow_bigger_buffers(const bool allow_bigger_buffers)72 void configure_allow_bigger_buffers(const bool allow_bigger_buffers) { 73 m_allow_not_used_data = allow_bigger_buffers; 74 } 75 76 template <uint32_t size> ensure_buffer_size()77 void ensure_buffer_size() { 78 m_buffer_size = m_buffer_left = size; 79 } 80 81 template <uint32_t id, uint32_t needed_size> begin_xmessage()82 Position begin_xmessage() { 83 if (m_message_started) { 84 ADD_FAILURE() << "Message already started"; 85 return {}; 86 } 87 88 m_buffer_size = m_buffer_left = needed_size; 89 m_buffer_left -= k_xmsg_header_size; 90 91 return {}; 92 } 93 94 template <uint32_t id, uint32_t needed_size> begin_xmessage(Position * position)95 void begin_xmessage(Position *position) { 96 *position = begin_xmessage<id, needed_size>(); 97 } 98 end_xmessage(const Position &)99 void end_xmessage(const Position &) { 100 if (m_message_ended) { 101 FAIL() << "Message already finished"; 102 } 103 104 summarize_buffer("end_xmessage"); 105 } 106 abort_xmessage(const Position & position)107 void abort_xmessage(const Position &position) { end_xmessage(position); } 108 encode_fixed_uint32(const uint32_t)109 void encode_fixed_uint32(const uint32_t) { 110 ++m_raw_data_number; 111 m_buffer_left -= k_fixed32_size; 112 113 check_size("encode_raw_data_fixed_uint32"); 114 } 115 encode_fixed_uint64(const uint64_t)116 void encode_fixed_uint64(const uint64_t) { 117 ++m_raw_data_number; 118 m_buffer_left -= k_fixed64_size; 119 120 check_size("encode_raw_data_fixed_uint64"); 121 } 122 encode_fixedvar16_uint32(const uint32_t)123 void encode_fixedvar16_uint32(const uint32_t) { 124 ++m_raw_data_number; 125 m_buffer_left -= k_fixed16_size; 126 127 check_size("encode_raw_data_fixedvar16_uint32"); 128 } 129 encode_fixedvar8_uint8(const uint8_t)130 void encode_fixedvar8_uint8(const uint8_t) { 131 ++m_raw_data_number; 132 m_buffer_left -= k_fixed8_size; 133 134 check_size("encode_raw_data_fixedvar8_uint8"); 135 } 136 encode_var_uint32(const uint32_t)137 void encode_var_uint32(const uint32_t) { 138 ++m_raw_data_number; 139 m_buffer_left -= (k_varint32_size); 140 141 check_size("encode_raw_data_uint32"); 142 } 143 encode_var_uint64(const uint64_t)144 void encode_var_uint64(const uint64_t) { 145 ++m_raw_data_number; 146 m_buffer_left -= (k_varint64_size); 147 148 check_size("encode_raw_data_uint64"); 149 } 150 encode_var_sint64(const int64_t)151 void encode_var_sint64(const int64_t) { 152 ++m_raw_data_number; 153 m_buffer_left -= (k_varint64_size); 154 155 check_size("encode_raw_data_sint64"); 156 } 157 158 template <uint64_t value> encode_const_var_uint()159 void encode_const_var_uint() { 160 ++m_raw_data_number; 161 m_buffer_left -= (k_varint64_size); 162 163 check_size("encode_raw_data_uint64_template"); 164 } 165 166 template <uint32_t field_id> encode_field_delimited_header()167 void encode_field_delimited_header() { 168 ++m_field_number; 169 m_buffer_left -= (k_varint_field_prefix_size); 170 171 check_size("encode_field_delimited"); 172 } 173 174 template <uint32_t field_id> encode_field_enum(const int32_t)175 void encode_field_enum(const int32_t) { 176 ++m_field_number; 177 m_buffer_left -= (k_varint_field_prefix_size + k_varint32_size); 178 179 check_size("encode_field_enum"); 180 } 181 182 template <uint32_t field_id> encode_optional_field_var_uint64(const uint64_t *)183 void encode_optional_field_var_uint64(const uint64_t *) { 184 ++m_field_number; 185 m_buffer_left -= (k_varint_field_prefix_size + k_varint64_size); 186 187 check_size("encode_optional_field_var_uint64"); 188 } 189 190 template <uint32_t field_id> encode_optional_field_var_uint32(const uint32_t *)191 void encode_optional_field_var_uint32(const uint32_t *) { 192 ++m_field_number; 193 m_buffer_left -= (k_varint_field_prefix_size + k_varint32_size); 194 195 check_size("encode_optional_field_var_uint32"); 196 } 197 198 template <uint32_t field_id> encode_field_string(const std::string &)199 void encode_field_string(const std::string &) { 200 ++m_field_number; 201 summarize_buffer("encode_field_string"); 202 m_buffer_left = 0; 203 } 204 205 template <uint32_t field_id, uint64_t value> encode_field_const_var_uint()206 void encode_field_const_var_uint() { 207 ++m_field_number; 208 m_buffer_left -= (k_varint_field_prefix_size + k_varint64_size); 209 210 check_size("encode_field_const_var_uint"); 211 } 212 213 template <uint32_t field_id, int64_t value> encode_field_const_enum()214 void encode_field_const_enum() { 215 ++m_field_number; 216 m_buffer_left -= (k_varint_field_prefix_size + k_varint64_size); 217 218 check_size("encode_field_const_enum"); 219 } 220 221 template <uint32_t field_id> encode_field_var_uint32(const uint32_t)222 void encode_field_var_uint32(const uint32_t) { 223 ++m_field_number; 224 m_buffer_left -= (k_varint_field_prefix_size + k_varint64_size); 225 226 check_size("k_varint32_size"); 227 } 228 229 template <uint32_t id, uint32_t delimiter_length = 1> begin_delimited_field()230 Field_delimiter<delimiter_length> begin_delimited_field() { 231 ++m_field_number; 232 m_buffer_left -= (k_varint_field_prefix_size + k_varint64_size); 233 234 check_size("begin_delimited_field"); 235 236 return {}; 237 } 238 239 template <uint32_t delimiter_length> end_delimited_field(const Field_delimiter<delimiter_length> &)240 void end_delimited_field(const Field_delimiter<delimiter_length> &) { 241 // check_size("end_delimited_field"); 242 } 243 244 template <uint32_t field_id> encode_field_var_uint64(const uint64_t)245 void encode_field_var_uint64(const uint64_t) { 246 ++m_field_number; 247 m_buffer_left -= (k_varint_field_prefix_size + k_varint64_size); 248 249 check_size("encode_field_var_uint64"); 250 } 251 encode_raw(const uint8_t *,uint32_t)252 void encode_raw(const uint8_t *, uint32_t) { m_buffer_left = 0; } 253 254 template <uint32_t id> empty_xmessage()255 void empty_xmessage() { 256 if (m_message_started) { 257 FAIL() << "Message already started"; 258 } 259 260 if (m_message_ended) { 261 FAIL() << "Message already ended"; 262 } 263 264 m_message_started = true; 265 m_message_ended = true; 266 check_size("empty_xmessage"); 267 } 268 269 private: 270 const int k_varint_field_prefix_size = 10; 271 const int k_varint32_size = 5; 272 const int k_varint64_size = 10; 273 const int k_fixed8_size = 1; 274 const int k_fixed16_size = 2; 275 const int k_fixed32_size = 4; 276 const int k_fixed64_size = 8; 277 const int k_xmsg_header_size = 5; 278 279 bool m_message_started = false; 280 bool m_message_ended = false; 281 int64_t m_buffer_left = 0; 282 int64_t m_buffer_size = 0; 283 int m_field_number = 0; 284 int m_raw_data_number = 0; 285 bool m_allow_not_used_data = false; 286 }; 287 288 } // namespace test 289 290 } // namespace protocol 291 292 #endif // UNITTEST_GUNIT_XPLUGIN_XPL_ENCODER_VALIDATOR_H_ 293