1
/* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
// First include (the generated) my_config.h, to get correct platform defines.
17
#include "my_config.h"
18
#include <gtest/gtest.h>
20
#include "test_utils.h"
21
#include "fake_table.h"
25
type_conversion_status
26
store_internal_with_error_check(Field_new_decimal *field,
27
int conversion_err, my_decimal *value);
28
namespace field_newdecimal_unittest {
30
using my_testing::chars_2_decimal;
31
using my_testing::Server_initializer;
32
using my_testing::Mock_error_handler;
34
class FieldNewDecimalTest : public ::testing::Test
37
virtual void SetUp() { initializer.SetUp(); }
38
virtual void TearDown() { initializer.TearDown(); }
40
THD *thd() { return initializer.thd(); }
42
Server_initializer initializer;
44
Field_set *create_field_set(TYPELIB *tl);
48
class Mock_field_new_decimal : public Field_new_decimal
50
uchar buffer[MAX_FIELD_WIDTH];
56
memset(buffer, 0, MAX_FIELD_WIDTH);
61
Mock_field_new_decimal(int decimals)
62
: Field_new_decimal(0, // ptr_arg
66
Field::NONE, // unireg_check_arg
67
"field_name", // field_name_arg
70
false) // unsigned_arg
75
void make_writable() { bitmap_set_bit(table->write_set, field_index); }
77
void test_store_string(const char *store_value, const int length,
78
const char *expected_string_result,
79
const longlong expected_int_result,
80
const double expected_real_result,
81
const int expected_error_no,
82
const type_conversion_status expected_status)
84
char buff[MAX_FIELD_WIDTH];
85
String str(buff, sizeof(buff), &my_charset_bin);
88
Mock_error_handler error_handler(table->in_use, expected_error_no);
89
type_conversion_status err= store(store_value, length, &my_charset_latin1);
90
val_str(&str, &unused);
91
EXPECT_STREQ(expected_string_result, str.ptr());
92
EXPECT_EQ(expected_int_result, val_int());
93
EXPECT_EQ(expected_real_result, val_real());
95
EXPECT_FALSE(is_null());
96
EXPECT_EQ(expected_status, err);
97
EXPECT_EQ((expected_error_no == 0 ? 0 : 1), error_handler.handle_called());
103
TEST_F(FieldNewDecimalTest, StoreLegalStringValues)
105
// Alows storing this range [-999.999, 999.999]
106
Mock_field_new_decimal field_dec(3);
107
Fake_TABLE table(&field_dec);
109
field_dec.make_writable();
110
thd()->count_cuted_fields= CHECK_FIELD_WARN;
114
field_dec.test_store_string(STRING_WITH_LEN("10.01"), "10.010", 10, 10.01,
119
field_dec.test_store_string(STRING_WITH_LEN("0"), "0.000", 0, 0,
125
TEST_F(FieldNewDecimalTest, StoreIllegalStringValues)
127
// Alows storing this range [-999.999, 999.999]
128
Mock_field_new_decimal field_dec(3);
129
Fake_TABLE table(&field_dec);
131
field_dec.make_writable();
132
thd()->count_cuted_fields= CHECK_FIELD_WARN;
134
// Truncated (precision beyond 3 decimals is lost)
137
field_dec.test_store_string(STRING_WITH_LEN("10.0101"), "10.010",
139
WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
143
field_dec.test_store_string(STRING_WITH_LEN("10.0109"), "10.011",
145
WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
147
// Values higher and lower than valid range for the decimal
150
field_dec.test_store_string(STRING_WITH_LEN("10000"), "999.999",
152
ER_WARN_DATA_OUT_OF_RANGE,
153
TYPE_WARN_OUT_OF_RANGE);
156
// Values higher and lower than valid range for the decimal
159
field_dec.test_store_string(STRING_WITH_LEN("-10000"), "-999.999",
161
ER_WARN_DATA_OUT_OF_RANGE,
162
TYPE_WARN_OUT_OF_RANGE);
167
static void test_store_internal(Field_new_decimal *field,
169
const char *expected_string_result,
170
const longlong expected_int_result,
171
const double expected_real_result,
172
const int conversion_error,
173
const int expected_error_no,
174
const type_conversion_status expected_status)
176
char buff[MAX_FIELD_WIDTH];
177
String str(buff, sizeof(buff), &my_charset_bin);
180
Mock_error_handler error_handler(field->table->in_use, expected_error_no);
181
type_conversion_status err=
182
store_internal_with_error_check(field, conversion_error, value);
183
field->val_str(&str, &unused);
184
EXPECT_STREQ(expected_string_result, str.ptr());
185
EXPECT_EQ(expected_int_result, field->val_int());
186
EXPECT_EQ(expected_real_result, field->val_real());
188
EXPECT_EQ(expected_status, err);
193
Test store_internal_with_error_check(). This is an internal store
194
function for Field_new_decimal. The function does not modify the
195
NULL value of the field so we don't test field.is_null()
197
TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckLegalValues)
199
// Alows storing this range [-99.9999, 99.9999]
200
Mock_field_new_decimal field_dec(4);
201
Fake_TABLE table(&field_dec);
203
field_dec.make_writable();
204
thd()->count_cuted_fields= CHECK_FIELD_WARN;
207
my_decimal dMin10_01;
208
my_decimal d10_01001;
209
my_decimal d10_01009;
210
my_decimal dInsignificant;
212
EXPECT_EQ(0, chars_2_decimal("10.01", &d10_01));
213
EXPECT_EQ(0, chars_2_decimal("-10.01", &dMin10_01));
214
EXPECT_EQ(0, chars_2_decimal("10.01001", &d10_01001));
215
EXPECT_EQ(0, chars_2_decimal("10.01009", &d10_01009));
216
EXPECT_EQ(0, chars_2_decimal("0.00000000001", &dInsignificant));
221
test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
222
E_DEC_OK, 0, TYPE_OK);
226
test_store_internal(&field_dec, &dMin10_01, "-10.0100", -10, -10.01,
227
E_DEC_OK, 0, TYPE_OK);
230
// Legal values, but rounded
233
test_store_internal(&field_dec, &d10_01001, "10.0100", 10, 10.01,
234
E_DEC_OK, WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
238
test_store_internal(&field_dec, &d10_01009, "10.0101", 10, 10.0101,
239
E_DEC_OK, WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
243
test_store_internal(&field_dec, &dInsignificant, "0.0000", 0, 0, E_DEC_OK,
244
WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
250
Test store_internal_with_error_check() - out of range valuse
252
TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckOutOfRange)
254
// Alows storing this range [-99.9999, 99.9999]
255
Mock_field_new_decimal field_dec(4);
256
Fake_TABLE table(&field_dec);
258
field_dec.make_writable();
259
thd()->count_cuted_fields= CHECK_FIELD_WARN;
264
EXPECT_EQ(0, chars_2_decimal("1000", &dTooHigh));
265
EXPECT_EQ(0, chars_2_decimal("-1000", &dTooLow));
269
test_store_internal(&field_dec, &dTooHigh, "99.9999", 100, 99.9999,
270
E_DEC_OK, ER_WARN_DATA_OUT_OF_RANGE,
271
TYPE_WARN_OUT_OF_RANGE);
275
test_store_internal(&field_dec, &dTooLow, "-99.9999", -100, -99.9999,
276
E_DEC_OK, ER_WARN_DATA_OUT_OF_RANGE,
277
TYPE_WARN_OUT_OF_RANGE);
284
Test store_internal_with_error_check() - Test first parameter: the error.
286
When E_DEC_OVERFLOW is specified, the min/max value (depends on
287
the sign of the input value) of the field is used to overwrite the
288
input decimal value because E_DEC_OVERFLOW indicates that the decimal
289
conversion got a number that was too high/low.
291
TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckEDecOverflow)
293
// Alows storing this range [-99.9999, 99.9999]
294
Mock_field_new_decimal field_dec(4);
295
Fake_TABLE table(&field_dec);
297
field_dec.make_writable();
298
thd()->count_cuted_fields= CHECK_FIELD_WARN;
301
my_decimal dMin10_01;
302
my_decimal dInsignificant;
306
EXPECT_EQ(0, chars_2_decimal("10.01", &d10_01));
307
EXPECT_EQ(0, chars_2_decimal("-10.01", &dMin10_01));
308
EXPECT_EQ(0, chars_2_decimal("0.00000000001", &dInsignificant));
309
EXPECT_EQ(0, chars_2_decimal("1000", &dTooHigh));
310
EXPECT_EQ(0, chars_2_decimal("-1000", &dTooLow));
312
// Positive number - the field's MAX value is used
315
test_store_internal(&field_dec, &d10_01, "99.9999", 100, 99.9999,
316
E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
317
TYPE_WARN_OUT_OF_RANGE);
321
test_store_internal(&field_dec, &dInsignificant, "99.9999", 100, 99.9999,
322
E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
323
TYPE_WARN_OUT_OF_RANGE);
328
test_store_internal(&field_dec, &dTooHigh, "99.9999", 100, 99.9999,
329
E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
330
TYPE_WARN_OUT_OF_RANGE);
333
// Negative number - the field's MIN value is used
336
test_store_internal(&field_dec, &dMin10_01, "-99.9999", -100, -99.9999,
337
E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
338
TYPE_WARN_OUT_OF_RANGE);
343
test_store_internal(&field_dec, &dTooLow, "-99.9999", -100, -99.9999,
344
E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
345
TYPE_WARN_OUT_OF_RANGE);
351
Test store_internal_with_error_check() - Test first parameter: the error.
353
When E_DEC_TRUNCATED is specified, a truncation warning will
354
appear iff Field_new_decimal::store_value() would otherwise not
355
issue a warning. The rationale is that E_DEC_TRUNCATED indicates
356
that the value to store has already been truncated, something that
357
will not be noticed by store_value(). However, the value is not
358
automatically changed like in the E_DEC_OVERFLOW case tested
361
TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckEDecTrunkated)
363
// Alows storing this range [-99.9999, 99.9999]
364
Mock_field_new_decimal field_dec(4);
365
Fake_TABLE table(&field_dec);
367
field_dec.make_writable();
368
thd()->count_cuted_fields= CHECK_FIELD_WARN;
371
my_decimal dMin10_01;
372
my_decimal dInsignificant;
376
EXPECT_EQ(0, chars_2_decimal("10.01", &d10_01));
377
EXPECT_EQ(0, chars_2_decimal("-10.01", &dMin10_01));
378
EXPECT_EQ(0, chars_2_decimal("0.00000000001", &dInsignificant));
379
EXPECT_EQ(0, chars_2_decimal("1000", &dTooHigh));
380
EXPECT_EQ(0, chars_2_decimal("-1000", &dTooLow));
383
// Conversion went fine
386
test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
387
E_DEC_TRUNCATED, WARN_DATA_TRUNCATED,
388
TYPE_NOTE_TRUNCATED);
392
test_store_internal(&field_dec, &dMin10_01, "-10.0100", -10, -10.01,
393
E_DEC_TRUNCATED, WARN_DATA_TRUNCATED,
394
TYPE_NOTE_TRUNCATED);
399
test_store_internal(&field_dec, &dInsignificant, "0.0000", 0, 0,
400
E_DEC_TRUNCATED, WARN_DATA_TRUNCATED,
401
TYPE_NOTE_TRUNCATED);
405
In what follows, the values are out of range causing warning
406
ER_WARN_DATA_OUT_OF_RANGE instead of WARN_DATA_TRUNCATED.
410
test_store_internal(&field_dec, &dTooHigh, "99.9999", 100, 99.9999,
411
E_DEC_TRUNCATED, ER_WARN_DATA_OUT_OF_RANGE,
412
TYPE_WARN_OUT_OF_RANGE);
416
test_store_internal(&field_dec, &dTooLow, "-99.9999", -100, -99.9999,
417
E_DEC_TRUNCATED, ER_WARN_DATA_OUT_OF_RANGE,
418
TYPE_WARN_OUT_OF_RANGE);
424
Test store_internal_with_error_check() - Test first parameter: the error.
426
Any E_DEC_* value other than E_DEC_OK, E_DEC_TRUNCATED and
427
E_DEC_OVERFLOW will be ignored.
429
TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckRestOfParams)
431
// Alows storing this range [-99.9999, 99.9999]
432
Mock_field_new_decimal field_dec(4);
433
Fake_TABLE table(&field_dec);
435
field_dec.make_writable();
436
thd()->count_cuted_fields= CHECK_FIELD_WARN;
439
EXPECT_EQ(0, chars_2_decimal("10.01", &d10_01));
441
test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
442
E_DEC_DIV_ZERO, 0, TYPE_OK);
444
test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
445
E_DEC_BAD_NUM, 0, TYPE_OK);
447
test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
448
E_DEC_OOM, 0, TYPE_OK);