Skip to content

Commit 20b672e

Browse files
author
Tor Didriksen
committed
Merge 5.5 => trunk.
Add unit tests for my_decimal_mod().
2 parents 6f5ec43 + 7fddcd0 commit 20b672e

5 files changed

Lines changed: 179 additions & 2 deletions

File tree

mysql-test/r/func_math.result

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,13 @@ select (1.175494351E-37 div 1.7976931348623157E+308);
699699
0
700700
Warnings:
701701
Warning 1292 Truncated incorrect DECIMAL value: ''
702+
#
703+
# Bug#12537160 ASSERTION FAILED:
704+
# STOP0 <= &TO->BUF[TO->LEN] WITH LARGE NUMBER.
705+
#
706+
select 999999999999999999999999999999999999999999999999999999999999999999999999999999999 % 0.1 as foo;
707+
foo
708+
0.0
709+
select 999999999999999999999999999999999999999999999999999999999999999999999999999999999 % 0.0 as foo;
710+
foo
711+
NULL

mysql-test/t/func_math.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,3 +536,14 @@ SELECT 1 div null;
536536
--echo # Bug #11792200 - DIVIDING LARGE NUMBERS CAUSES STACK CORRUPTIONS
537537
--echo #
538538
select (1.175494351E-37 div 1.7976931348623157E+308);
539+
540+
--echo #
541+
--echo # Bug#12537160 ASSERTION FAILED:
542+
--echo # STOP0 <= &TO->BUF[TO->LEN] WITH LARGE NUMBER.
543+
--echo #
544+
545+
let $nine_81=
546+
999999999999999999999999999999999999999999999999999999999999999999999999999999999;
547+
548+
eval select $nine_81 % 0.1 as foo;
549+
eval select $nine_81 % 0.0 as foo;

strings/decimal.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2191,7 +2191,6 @@ static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
21912191
}
21922192
buf0=to->buf;
21932193
stop0=buf0+intg0+frac0;
2194-
DBUG_ASSERT(stop0 <= &to->buf[to->len]);
21952194
if (likely(div_mod))
21962195
while (dintg++ < 0 && buf0 < &to->buf[to->len])
21972196
{
@@ -2286,7 +2285,10 @@ static int do_div_mod(const decimal_t *from1, const decimal_t *from2,
22862285
}
22872286
}
22882287
if (likely(div_mod))
2288+
{
2289+
DBUG_ASSERT(buf0 < to->buf + to->len);
22892290
*buf0=(dec1)guess;
2291+
}
22902292
dcarry= *start1;
22912293
start1++;
22922294
}

unittest/gunit/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ SET(TESTS
211211
mdl
212212
mdl_mytap
213213
my_bitmap
214-
my_decimal
215214
my_regex
216215
sql_list
217216
sql_plist
@@ -221,6 +220,7 @@ SET(TESTS
221220
# Add tests (link them with gunit library and the server libraries)
222221
SET(SERVER_TESTS
223222
item
223+
my_decimal
224224
opt_range
225225
)
226226

unittest/gunit/my_decimal-t.cc

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,47 @@
1616
#include "my_config.h"
1717
#include <gtest/gtest.h>
1818

19+
#include "test_utils.h"
20+
1921
#include <my_decimal.h>
2022

2123
namespace {
2224

25+
using my_testing::Server_initializer;
26+
using my_testing::Mock_error_handler;
27+
2328
class DecimalTest : public ::testing::Test
2429
{
2530
protected:
31+
static void SetUpTestCase()
32+
{
33+
Server_initializer::SetUpTestCase();
34+
}
35+
36+
static void TearDownTestCase()
37+
{
38+
Server_initializer::TearDownTestCase();
39+
}
40+
41+
virtual void SetUp()
42+
{
43+
initializer.SetUp();
44+
}
45+
46+
virtual void TearDown()
47+
{
48+
initializer.TearDown();
49+
}
50+
51+
THD *thd() { return initializer.thd(); }
52+
53+
Server_initializer initializer;
54+
2655
my_decimal d1;
2756
my_decimal d2;
2857
};
2958

59+
3060
TEST_F(DecimalTest, CopyAndCompare)
3161
{
3262
ulonglong val= 42;
@@ -70,4 +100,128 @@ TEST_F(DecimalTest, Swap)
70100
EXPECT_EQ(0, my_decimal_cmp(&d1, &d2copy));
71101
}
72102

103+
104+
105+
int chars_2_decimal(const char *chars, my_decimal *to)
106+
{
107+
char *end= strend(chars);
108+
return string2decimal(chars, to, &end);
109+
}
110+
111+
112+
/*
113+
This is a simple iterative implementation based on addition and subtraction,
114+
for verifying the result of decimal_mod().
115+
116+
decimal_mod() says:
117+
DESCRIPTION
118+
the modulus R in R = M mod N
119+
is defined as
120+
121+
0 <= |R| < |M|
122+
sign R == sign M
123+
R = M - k*N, where k is integer
124+
125+
thus, there's no requirement for M or N to be integers
126+
*/
127+
int decimal_modulo(uint mask,
128+
my_decimal *res,
129+
const my_decimal *m,
130+
const my_decimal *n)
131+
{
132+
my_decimal abs_m(*m);
133+
my_decimal abs_n(*n);
134+
abs_m.sign(false);
135+
abs_n.sign(false);
136+
137+
my_decimal r;
138+
my_decimal k1(abs_n);
139+
my_decimal kn(decimal_zero);
140+
my_decimal next_r(abs_m);
141+
int ret;
142+
do
143+
{
144+
r= next_r;
145+
146+
my_decimal res;
147+
if ((ret= my_decimal_add(E_DEC_FATAL_ERROR, &res, &k1, &kn)) != E_DEC_OK)
148+
{
149+
ADD_FAILURE();
150+
return ret;
151+
}
152+
kn= res;
153+
154+
if ((ret= my_decimal_sub(E_DEC_FATAL_ERROR,
155+
&next_r, &abs_m, &kn) != E_DEC_OK))
156+
{
157+
ADD_FAILURE();
158+
return ret;
159+
}
160+
} while (my_decimal_cmp(&next_r, &decimal_zero) >= 0);
161+
r.sign(m->sign());
162+
*res= r;
163+
return 0;
164+
}
165+
166+
167+
struct Mod_data
168+
{
169+
const char *a;
170+
const char *b;
171+
const char *result;
172+
};
173+
174+
Mod_data mod_test_input[]=
175+
{
176+
{ "234" , "10", "4" },
177+
{ "234.567" , "10.555", "2.357" },
178+
{ "-234.567", "10.555", "-2.357" },
179+
{ "234.567" , "-10.555", "2.357" },
180+
{ "-234.567", "-10.555", "-2.357" },
181+
{ "999" , "0.1", "0.0" },
182+
{ "999" , "0.7", "0.1" },
183+
{ "10" , "123", "10" },
184+
{ NULL, NULL, NULL}
185+
};
186+
187+
188+
TEST_F(DecimalTest, Modulo)
189+
{
190+
my_decimal expected_result;
191+
my_decimal xxx_result;
192+
my_decimal mod_result;
193+
char buff_x[DECIMAL_MAX_STR_LENGTH];
194+
char buff_m[DECIMAL_MAX_STR_LENGTH];
195+
196+
for (Mod_data *pd= mod_test_input; pd->a; ++pd)
197+
{
198+
int bufsz_x= sizeof(buff_x);
199+
int bufsz_m= sizeof(buff_m);
200+
201+
EXPECT_EQ(0, chars_2_decimal(pd->a, &d1));
202+
EXPECT_EQ(0, chars_2_decimal(pd->b, &d2));
203+
EXPECT_EQ(0, chars_2_decimal(pd->result, &expected_result));
204+
205+
EXPECT_EQ(0, my_decimal_mod(E_DEC_FATAL_ERROR, &mod_result, &d1, &d2));
206+
EXPECT_EQ(0, decimal2string(&mod_result, buff_m, &bufsz_m, 0, 0, 0));
207+
EXPECT_EQ(0, my_decimal_cmp(&expected_result, &mod_result))
208+
<< " a:" << pd->a
209+
<< " b:" << pd->b
210+
<< " expected:" << pd->result
211+
<< " got mod:" << buff_m
212+
;
213+
214+
EXPECT_EQ(0, decimal_modulo(E_DEC_FATAL_ERROR, &xxx_result, &d1, &d2));
215+
EXPECT_EQ(0, decimal2string(&xxx_result, buff_x, &bufsz_x, 0, 0, 0));
216+
EXPECT_EQ(0, my_decimal_cmp(&expected_result, &xxx_result))
217+
<< " a:" << pd->a
218+
<< " b:" << pd->b
219+
<< " expected:" << pd->result
220+
<< " got mod:" << buff_m
221+
<< " got xxx:" << buff_x
222+
;
223+
}
224+
225+
}
226+
73227
}

0 commit comments

Comments
 (0)