MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_decimal-t.cc
1 /* Copyright (c) 2011, 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 as published by
5  the Free Software Foundation; version 2 of the License.
6 
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.
11 
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 */
15 
16 #include "my_config.h"
17 #include <gtest/gtest.h>
18 
19 #include "test_utils.h"
20 
21 #include <my_decimal.h>
22 
23 namespace my_decimal_unittest {
24 
25 using my_testing::chars_2_decimal;
28 
29 class DecimalTest : public ::testing::Test
30 {
31 protected:
32  virtual void SetUp() { initializer.SetUp(); }
33  virtual void TearDown() { initializer.TearDown(); }
34 
35  THD *thd() { return initializer.thd(); }
36 
37  Server_initializer initializer;
38 
39  my_decimal d1;
40  my_decimal d2;
41 };
42 
43 
44 TEST_F(DecimalTest, CopyAndCompare)
45 {
46  ulonglong val= 42;
47  EXPECT_EQ(0, ulonglong2decimal(val, &d1));
48 
49  d2= d1; // operator=()
50  my_decimal d3(d1); // Copy constructor.
51 
52  EXPECT_EQ(0, my_decimal_cmp(&d1, &d2));
53  EXPECT_EQ(0, my_decimal_cmp(&d2, &d3));
54  EXPECT_EQ(0, my_decimal_cmp(&d3, &d1));
55 
56  ulonglong val1, val2, val3;
57  EXPECT_EQ(0, decimal2ulonglong(&d1, &val1));
58  EXPECT_EQ(0, decimal2ulonglong(&d2, &val2));
59  EXPECT_EQ(0, decimal2ulonglong(&d3, &val3));
60  EXPECT_EQ(val, val1);
61  EXPECT_EQ(val, val2);
62  EXPECT_EQ(val, val3);
63 
64  // The CTOR/operator=() generated by the compiler would fail here:
65  val= 45;
66  EXPECT_EQ(0, ulonglong2decimal(val, &d1));
67  EXPECT_EQ(1, my_decimal_cmp(&d1, &d2));
68  EXPECT_EQ(1, my_decimal_cmp(&d1, &d3));
69 }
70 
71 
72 TEST_F(DecimalTest, RoundOverflow)
73 {
74  const char arg_str[]= "999999999";
75  String str(arg_str, &my_charset_bin);
76 
77  EXPECT_EQ(E_DEC_OK,
78  string2my_decimal(E_DEC_FATAL_ERROR, &str, &d1));
79  d1.sanity_check();
80 
81  for (int ix= 0; ix < DECIMAL_MAX_POSSIBLE_PRECISION; ++ix)
82  {
83  my_decimal d3;
84  const int expect=
85  (ix + str.length() <= DECIMAL_MAX_POSSIBLE_PRECISION) ?
86  E_DEC_OK : E_DEC_TRUNCATED;
87  const bool do_truncate= true;
88  EXPECT_EQ(expect,
89  my_decimal_round(E_DEC_FATAL_ERROR, &d1, ix, do_truncate, &d3))
90  << "ix:" << ix;
91  d3.sanity_check();
92  EXPECT_EQ(0, my_decimal_cmp(&d1, &d3));
93  }
94 }
95 
96 
97 TEST_F(DecimalTest, Swap)
98 {
99  ulonglong val1= 1;
100  ulonglong val2= 2;
101  EXPECT_EQ(0, ulonglong2decimal(val1, &d1));
102  EXPECT_EQ(0, ulonglong2decimal(val2, &d2));
103  my_decimal d1copy(d1);
104  my_decimal d2copy(d2);
105  EXPECT_EQ(0, my_decimal_cmp(&d1, &d1copy));
106  EXPECT_EQ(0, my_decimal_cmp(&d2, &d2copy));
107  d1.swap(d2);
108  EXPECT_EQ(0, my_decimal_cmp(&d2, &d1copy));
109  EXPECT_EQ(0, my_decimal_cmp(&d1, &d2copy));
110 }
111 
112 
113 
114 TEST_F(DecimalTest, Multiply)
115 {
116  const char arg1[]=
117  "000000001."
118  "10000000000000000000" "00000000000000000000" "00000000000000000000"
119  "000000000000";
120  const char arg2[]= "1.75";
121  char buff[DECIMAL_MAX_STR_LENGTH];
122  int bufsz;
123  my_decimal prod;
124 
125  EXPECT_EQ(E_DEC_OK, chars_2_decimal(arg1, &d1));
126  EXPECT_EQ(E_DEC_OK, chars_2_decimal(arg2, &d2));
127 
128  // Limit the precision, otherwise "1.75" will be truncated to "1."
129  set_if_smaller(d1.frac, NOT_FIXED_DEC);
130  set_if_smaller(d2.frac, NOT_FIXED_DEC);
131  EXPECT_EQ(0, my_decimal_mul(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
132  &prod, &d1, &d2));
133  EXPECT_EQ(NOT_FIXED_DEC, d1.frac);
134  EXPECT_EQ(2, d2.frac);
135  EXPECT_EQ(NOT_FIXED_DEC, prod.frac);
136  bufsz= sizeof(buff);
137  EXPECT_EQ(0, decimal2string(&prod, buff, &bufsz, 0, 0, 0));
138  EXPECT_STREQ("1.9250000000000000000000000000000", buff);
139 }
140 
141 
142 /*
143  This is a simple iterative implementation based on addition and subtraction,
144  for verifying the result of decimal_mod().
145 
146  decimal_mod() says:
147  DESCRIPTION
148  the modulus R in R = M mod N
149  is defined as
150 
151  0 <= |R| < |M|
152  sign R == sign M
153  R = M - k*N, where k is integer
154 
155  thus, there's no requirement for M or N to be integers
156  */
157 int decimal_modulo(uint mask,
158  my_decimal *res,
159  const my_decimal *m,
160  const my_decimal *n)
161 {
162  my_decimal abs_m(*m);
163  my_decimal abs_n(*n);
164  abs_m.sign(false);
165  abs_n.sign(false);
166 
167  my_decimal r;
168  my_decimal k1(abs_n);
169  my_decimal kn(decimal_zero);
170  my_decimal next_r(abs_m);
171  int ret;
172  do
173  {
174  r= next_r;
175 
176  my_decimal res;
177  if ((ret= my_decimal_add(E_DEC_FATAL_ERROR, &res, &k1, &kn)) != E_DEC_OK)
178  {
179  ADD_FAILURE();
180  return ret;
181  }
182  kn= res;
183 
184  if ((ret= my_decimal_sub(E_DEC_FATAL_ERROR,
185  &next_r, &abs_m, &kn) != E_DEC_OK))
186  {
187  ADD_FAILURE();
188  return ret;
189  }
190  } while (my_decimal_cmp(&next_r, &decimal_zero) >= 0);
191  r.sign(m->sign());
192  *res= r;
193  return 0;
194 }
195 
196 
197 struct Mod_data
198 {
199  const char *a;
200  const char *b;
201  const char *result;
202 };
203 
204 Mod_data mod_test_input[]=
205 {
206  { "234" , "10", "4" },
207  { "234.567" , "10.555", "2.357" },
208  { "-234.567", "10.555", "-2.357" },
209  { "234.567" , "-10.555", "2.357" },
210  { "-234.567", "-10.555", "-2.357" },
211  { "999" , "0.1", "0.0" },
212  { "999" , "0.7", "0.1" },
213  { "10" , "123", "10" },
214  { NULL, NULL, NULL}
215 };
216 
217 
218 TEST_F(DecimalTest, Modulo)
219 {
220  my_decimal expected_result;
221  my_decimal xxx_result;
222  my_decimal mod_result;
223  char buff_x[DECIMAL_MAX_STR_LENGTH];
224  char buff_m[DECIMAL_MAX_STR_LENGTH];
225 
226  for (Mod_data *pd= mod_test_input; pd->a; ++pd)
227  {
228  int bufsz_x= sizeof(buff_x);
229  int bufsz_m= sizeof(buff_m);
230 
231  EXPECT_EQ(0, chars_2_decimal(pd->a, &d1));
232  EXPECT_EQ(0, chars_2_decimal(pd->b, &d2));
233  EXPECT_EQ(0, chars_2_decimal(pd->result, &expected_result));
234 
235  EXPECT_EQ(0, my_decimal_mod(E_DEC_FATAL_ERROR, &mod_result, &d1, &d2));
236  EXPECT_EQ(0, decimal2string(&mod_result, buff_m, &bufsz_m, 0, 0, 0));
237  EXPECT_EQ(0, my_decimal_cmp(&expected_result, &mod_result))
238  << " a:" << pd->a
239  << " b:" << pd->b
240  << " expected:" << pd->result
241  << " got mod:" << buff_m
242  ;
243 
244  EXPECT_EQ(0, decimal_modulo(E_DEC_FATAL_ERROR, &xxx_result, &d1, &d2));
245  EXPECT_EQ(0, decimal2string(&xxx_result, buff_x, &bufsz_x, 0, 0, 0));
246  EXPECT_EQ(0, my_decimal_cmp(&expected_result, &xxx_result))
247  << " a:" << pd->a
248  << " b:" << pd->b
249  << " expected:" << pd->result
250  << " got mod:" << buff_m
251  << " got xxx:" << buff_x
252  ;
253  }
254 }
255 
256 
257 TEST_F(DecimalTest, BinaryConversion)
258 {
259  const int prec= 60;
260  const int scale= 0;
261  EXPECT_EQ(E_DEC_OK, chars_2_decimal("000000000", &d1));
262  int binary_size= my_decimal_get_binary_size(prec, scale);
263  uchar *bin= new uchar[binary_size];
264 
265  // Convert to binary, and back.
266  EXPECT_EQ(E_DEC_OK, my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
267  &d1, bin, prec, scale));
268  EXPECT_EQ(E_DEC_OK, binary2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
269  bin, &d2, prec, scale));
270  EXPECT_GT(d2.precision(), 0U);
271  EXPECT_EQ(0, my_decimal_cmp(&d1, &d2));
272 
273  // 0.0 * 0.0
274  my_decimal product;
275  EXPECT_EQ(E_DEC_OK, my_decimal_mul(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
276  &product, &d2, &d2));
277  // 0.0 * (-0.0)
278  my_decimal neg_prod;
279  my_decimal d3(d2);
280  d3.sign(true);
281  EXPECT_EQ(E_DEC_OK, my_decimal_mul(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
282  &neg_prod, &d2, &d3));
283  delete[] bin;
284 }
285 
286 }