1 /* Copyright (c) 2012, 2021, Oracle and/or its affiliates.
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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
22
23 // First include (the generated) my_config.h, to get correct platform defines.
24 #include "my_config.h"
25 #include <gtest/gtest.h>
26
27 #include "test_utils.h"
28 #include "fake_table.h"
29
30 #include "field.h"
31
32 namespace field_long_unittest {
33
34 using my_testing::Server_initializer;
35 using my_testing::Mock_error_handler;
36
37 class FieldLongTest : public ::testing::Test
38 {
39 protected:
SetUp()40 virtual void SetUp() { initializer.SetUp(); }
TearDown()41 virtual void TearDown() { initializer.TearDown(); }
42
thd()43 THD *thd() { return initializer.thd(); }
44
45 Server_initializer initializer;
46
47 Field_set *create_field_set(TYPELIB *tl);
48 };
49
50 class Mock_field_long : public Field_long
51 {
52 uchar buffer[PACK_LENGTH];
53 uchar null_byte;
initialize()54 void initialize()
55 {
56 ptr= buffer;
57 memset(buffer, 0, PACK_LENGTH);
58 null_byte= '\0';
59 set_null_ptr(&null_byte, 1);
60 }
61 public:
Mock_field_long()62 Mock_field_long()
63 : Field_long(0, // ptr_arg
64 8, // len_arg
65 NULL, // null_ptr_arg
66 1, // null_bit_arg
67 Field::NONE, // unireg_check_arg
68 "field_name", // field_name_arg
69 false, // zero_arg
70 false) // unsigned_arg
71 {
72 initialize();
73 }
74
make_writable()75 void make_writable() { bitmap_set_bit(table->write_set, field_index); }
make_readable()76 void make_readable() { bitmap_set_bit(table->read_set, field_index); }
77
78 };
79
test_store_long(Field_long * field,const longlong store_value,const longlong expected_result,const int expected_error_no,const type_conversion_status expected_status)80 void test_store_long(Field_long *field,
81 const longlong store_value,
82 const longlong expected_result,
83 const int expected_error_no,
84 const type_conversion_status expected_status)
85 {
86 Mock_error_handler error_handler(field->table->in_use, expected_error_no);
87 type_conversion_status err= field->store(store_value, false); // signed
88 EXPECT_EQ(expected_result, field->val_int());
89 EXPECT_FALSE(field->is_null());
90 EXPECT_EQ(expected_status, err);
91 EXPECT_EQ((expected_error_no == 0 ? 0 : 1), error_handler.handle_called());
92 }
93
test_store_string(Field_long * field,const char * store_value,const int length,const longlong expected_result,const int expected_error_no,const type_conversion_status expected_status)94 void test_store_string(Field_long *field,
95 const char *store_value, const int length,
96 const longlong expected_result,
97 const int expected_error_no,
98 const type_conversion_status expected_status)
99 {
100 Mock_error_handler error_handler(field->table->in_use, expected_error_no);
101 type_conversion_status err= field->store(store_value, length,
102 &my_charset_latin1);
103 EXPECT_EQ(expected_result, field->val_int());
104 EXPECT_FALSE(field->is_null());
105 EXPECT_EQ(expected_status, err);
106 EXPECT_EQ((expected_error_no == 0 ? 0 : 1), error_handler.handle_called());
107 }
108
109
TEST_F(FieldLongTest,StoreLegalIntValues)110 TEST_F(FieldLongTest, StoreLegalIntValues)
111 {
112 Mock_field_long field_long;
113 Fake_TABLE table(&field_long);
114 table.in_use= thd();
115 field_long.make_writable();
116 field_long.make_readable();
117 thd()->count_cuted_fields= CHECK_FIELD_WARN;
118
119 SCOPED_TRACE(""); test_store_long(&field_long, 0, 0, 0, TYPE_OK);
120 SCOPED_TRACE(""); test_store_long(&field_long, 5, 5, 0, TYPE_OK);
121 SCOPED_TRACE(""); test_store_long(&field_long, -1, -1, 0, TYPE_OK);
122
123 {
124 SCOPED_TRACE("");
125 test_store_long(&field_long, INT_MIN32, INT_MIN32, 0, TYPE_OK);
126 }
127 {
128 SCOPED_TRACE("");
129 test_store_long(&field_long, INT_MAX32, INT_MAX32, 0, TYPE_OK);
130 }
131
132 {
133 Mock_error_handler error_handler(thd(), 0);
134 type_conversion_status err;
135 err= set_field_to_null(&field_long);
136
137 EXPECT_EQ(0, field_long.val_int());
138 EXPECT_TRUE(field_long.is_null());
139 EXPECT_EQ(TYPE_OK, err);
140
141 field_long.set_notnull();
142 EXPECT_EQ(0, field_long.val_int());
143 EXPECT_FALSE(field_long.is_null());
144
145 // None of the above should generate warnings
146 EXPECT_EQ(0, error_handler.handle_called());
147 }
148 }
149
150 // Values higher and lower than valid range for the Field_long
TEST_F(FieldLongTest,StoreOutOfRangeIntValues)151 TEST_F(FieldLongTest, StoreOutOfRangeIntValues)
152 {
153 Mock_field_long field_long;
154 Fake_TABLE table(&field_long);
155 table.in_use= thd();
156 field_long.make_writable();
157 field_long.make_readable();
158 thd()->count_cuted_fields= CHECK_FIELD_WARN;
159
160
161 // Field_long is signed
162 {
163 SCOPED_TRACE("");
164 test_store_long(&field_long, INT_MAX32 + 1LL, INT_MAX32,
165 ER_WARN_DATA_OUT_OF_RANGE,
166 TYPE_WARN_OUT_OF_RANGE);
167 }
168 {
169 SCOPED_TRACE("");
170 test_store_long(&field_long, INT_MIN32 - 1LL, INT_MIN32,
171 ER_WARN_DATA_OUT_OF_RANGE,
172 TYPE_WARN_OUT_OF_RANGE);
173 }
174
175 // Field_long is unsigned
176 {
177 SCOPED_TRACE("");
178 field_long.unsigned_flag= true;
179 }
180 {
181 SCOPED_TRACE("");
182 test_store_long(&field_long, -1LL, 0, ER_WARN_DATA_OUT_OF_RANGE,
183 TYPE_WARN_OUT_OF_RANGE);
184 }
185 {
186 SCOPED_TRACE("");
187 test_store_long(&field_long, INT_MIN32, 0, ER_WARN_DATA_OUT_OF_RANGE,
188 TYPE_WARN_OUT_OF_RANGE);
189 }
190
191 }
192
193
TEST_F(FieldLongTest,StoreLegalStringValues)194 TEST_F(FieldLongTest, StoreLegalStringValues)
195 {
196 Mock_field_long field_long;
197
198 Fake_TABLE table(&field_long);
199 table.in_use= thd();
200 field_long.make_writable();
201 field_long.make_readable();
202 thd()->count_cuted_fields= CHECK_FIELD_WARN;
203
204 const char min_int[]= "-2147483648";
205 const char max_int[]= "2147483647";
206 const char max_int_plus1[]= "2147483648";
207 const char max_uint[]= "4294967295";
208
209 // Field_long is signed
210 {
211 SCOPED_TRACE("");
212 test_store_string(&field_long, STRING_WITH_LEN("0"), 0, 0, TYPE_OK);
213 }
214 {
215 SCOPED_TRACE("");
216 test_store_string(&field_long, STRING_WITH_LEN("1"), 1, 0, TYPE_OK);
217 }
218 {
219 SCOPED_TRACE("");
220 test_store_string(&field_long, STRING_WITH_LEN("-1"), -1, 0, TYPE_OK);
221 }
222 {
223 SCOPED_TRACE("");
224 test_store_string(&field_long, STRING_WITH_LEN(max_int), INT_MAX32,
225 0, TYPE_OK);
226 }
227 {
228 SCOPED_TRACE("");
229 test_store_string(&field_long, STRING_WITH_LEN(min_int), INT_MIN32,
230 0, TYPE_OK);
231 }
232
233 // Field_long is unsigned
234 field_long.unsigned_flag= true;
235 {
236 SCOPED_TRACE("");
237 test_store_string(&field_long, STRING_WITH_LEN(max_int_plus1),
238 INT_MAX32 + 1LL,
239 0, TYPE_OK);
240 }
241 {
242 SCOPED_TRACE("");
243 test_store_string(&field_long, STRING_WITH_LEN(max_uint), UINT_MAX32,
244 0, TYPE_OK);
245 }
246 }
247
248
TEST_F(FieldLongTest,StoreIllegalStringValues)249 TEST_F(FieldLongTest, StoreIllegalStringValues)
250 {
251 Mock_field_long field_long;
252
253 Fake_TABLE table(&field_long);
254 table.in_use= thd();
255 field_long.make_writable();
256 field_long.make_readable();
257 thd()->count_cuted_fields= CHECK_FIELD_WARN;
258
259 const char max_int_plus1[]= "2147483648";
260 const char min_int_minus1[]= "-2147483649";
261 const char very_high[]= "999999999999999";
262 const char very_low[]= "-999999999999999";
263
264 // Field_long is signed - Stored value is INT_MIN32/INT_MAX32
265 // depending on sign of string to store
266 {
267 SCOPED_TRACE("");
268 test_store_string(&field_long, STRING_WITH_LEN(max_int_plus1), INT_MAX32,
269 ER_WARN_DATA_OUT_OF_RANGE,
270 TYPE_WARN_OUT_OF_RANGE);
271 }
272 {
273 SCOPED_TRACE("");
274 test_store_string(&field_long, STRING_WITH_LEN(very_high), INT_MAX32,
275 ER_WARN_DATA_OUT_OF_RANGE,
276 TYPE_WARN_OUT_OF_RANGE);
277
278 }
279 {
280 SCOPED_TRACE("");
281 test_store_string(&field_long, STRING_WITH_LEN(min_int_minus1), INT_MIN32,
282 ER_WARN_DATA_OUT_OF_RANGE,
283 TYPE_WARN_OUT_OF_RANGE);
284 }
285 {
286 SCOPED_TRACE("");
287 test_store_string(&field_long, STRING_WITH_LEN(very_low), INT_MIN32,
288 ER_WARN_DATA_OUT_OF_RANGE,
289 TYPE_WARN_OUT_OF_RANGE);
290 }
291
292 // Field_long is unsigned - Stored value is 0/UINT_MAX32
293 // depending on sign of string to store
294 const char min_int[]= "-2147483648";
295 const char max_uint_plus1[]= "4294967296";
296 field_long.unsigned_flag= true;
297
298 {
299 SCOPED_TRACE("");
300 test_store_string(&field_long, STRING_WITH_LEN(max_uint_plus1), UINT_MAX32,
301 ER_WARN_DATA_OUT_OF_RANGE,
302 TYPE_WARN_OUT_OF_RANGE);
303 }
304 {
305 SCOPED_TRACE("");
306 test_store_string(&field_long, STRING_WITH_LEN(very_high), UINT_MAX32,
307 ER_WARN_DATA_OUT_OF_RANGE,
308 TYPE_WARN_OUT_OF_RANGE);
309 }
310 {
311 SCOPED_TRACE("");
312 test_store_string(&field_long, STRING_WITH_LEN("-1"), 0,
313 ER_WARN_DATA_OUT_OF_RANGE,
314 TYPE_WARN_OUT_OF_RANGE);
315 }
316 {
317 SCOPED_TRACE("");
318 test_store_string(&field_long, STRING_WITH_LEN(min_int), 0,
319 ER_WARN_DATA_OUT_OF_RANGE,
320 TYPE_WARN_OUT_OF_RANGE);
321 }
322 {
323 SCOPED_TRACE("");
324 test_store_string(&field_long, STRING_WITH_LEN(very_low), 0,
325 ER_WARN_DATA_OUT_OF_RANGE,
326 TYPE_WARN_OUT_OF_RANGE);
327 }
328
329 // Invalid value
330 {
331 SCOPED_TRACE("");
332 test_store_string(&field_long, STRING_WITH_LEN("foo"), 0,
333 ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
334 TYPE_ERR_BAD_VALUE);
335 }
336 }
337
TEST_F(FieldLongTest,StoreNullValue)338 TEST_F(FieldLongTest, StoreNullValue)
339 {
340 Mock_field_long field_long;
341
342 Fake_TABLE table(&field_long);
343 table.in_use= thd();
344 field_long.make_writable();
345 field_long.make_readable();
346 thd()->count_cuted_fields= CHECK_FIELD_WARN;
347
348 type_conversion_status err;
349
350 // Save NULL value in a field that can have NULL value
351 {
352 Mock_error_handler error_handler(thd(), 0);
353 err= set_field_to_null(&field_long);
354 EXPECT_EQ(0, field_long.val_int());
355 EXPECT_EQ(TYPE_OK, err);
356
357 err= set_field_to_null_with_conversions(&field_long, true);
358 EXPECT_EQ(0, field_long.val_int());
359 EXPECT_EQ(TYPE_OK, err);
360
361 err= set_field_to_null_with_conversions(&field_long, false);
362 EXPECT_EQ(0, field_long.val_int());
363 EXPECT_EQ(TYPE_OK, err);
364
365 EXPECT_EQ(0, error_handler.handle_called());
366 }
367
368 // Save NULL value in a field that can NOT have NULL value
369 field_long.set_null_ptr(NULL, 0);
370 {
371 Mock_error_handler error_handler(thd(), 0);
372 // Save NULL value in a field that can be set to NULL temporary
373 field_long.set_tmp_nullable();
374 err= set_field_to_null(&field_long);
375 EXPECT_EQ(0, field_long.val_int());
376 EXPECT_EQ(TYPE_OK, err);
377 EXPECT_EQ(0, error_handler.handle_called());
378 field_long.reset_tmp_nullable();
379 }
380
381 {
382 Mock_error_handler error_handler(thd(), 0);
383 err= set_field_to_null_with_conversions(&field_long, true);
384 EXPECT_EQ(0, field_long.val_int());
385 EXPECT_EQ(TYPE_ERR_NULL_CONSTRAINT_VIOLATION, err);
386 EXPECT_EQ(0, error_handler.handle_called());
387 }
388
389 {
390 Mock_error_handler error_handler(thd(), ER_BAD_NULL_ERROR);
391 err= set_field_to_null_with_conversions(&field_long, false);
392 EXPECT_EQ(0, field_long.val_int());
393 EXPECT_EQ(TYPE_OK, err);
394 EXPECT_EQ(1, error_handler.handle_called());
395 }
396 }
397
398 }
399