1 /* Copyright (c) 2011, 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 St, Fifth Floor, Boston, MA  02110-1301  USA */
22 
23 /*
24   NOTE: This is a more-or-less direct port of the main() program
25   in strings/decimal.c to a Google Test.
26  */
27 
28 #include "my_config.h"
29 #include <gtest/gtest.h>
30 
31 #include <my_global.h>
32 #include <m_string.h>
33 
34 extern "C" {
35 #include <decimal.h>
36 int decimal_shift(decimal_t *dec, int shift);
37 }
38 
39 
40 namespace decimal_unittest {
41 
42 #define DIG_PER_DEC1 9
43 #define DIG_BASE     1000000000
44 #define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
45 typedef decimal_digit_t dec1;
46 
47 int full= 0;
48 decimal_t a, b, c;
49 decimal_digit_t buf1[50], buf2[50], buf3[50];
50 
dump_decimal(decimal_t * d)51 void dump_decimal(decimal_t *d)
52 {
53   int i;
54   printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
55   for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
56     printf("%09d, ", d->buf[i]);
57   printf("%09d} */ ", d->buf[i]);
58 }
59 
60 /*
61   The purpose of all these define wrappers is to get a "call stack"
62   whenever some EXPECT_XX generates a failure. A sample error message:
63 
64   # .../unittest/gunit/decimal-t.cc:134: FailureValue of: s
65   #   Actual: "0"
66   # Expected: orig
67   # Which is: "1000000000"
68   #  arguments were: '999999999', -9, HALF_UP
69   # Google Test trace:
70   # .../unittest/gunit/decimal-t.cc:387:
71   # .../unittest/gunit/decimal-t.cc:686:
72  */
73 
74 #define check_result_code(p1, p2) \
75   { SCOPED_TRACE(""); do_check_result_code(p1, p2); }
76 
77 #define print_decimal(p1, p2, p3, p4, p5) \
78   { SCOPED_TRACE(""); do_print_decimal(p1, p2, p3, p4, p5); }
79 
80 #define test_s2d(p1, p2, p3) \
81   { SCOPED_TRACE(""); do_test_s2d(p1, p2, p3); }
82 
83 #define test_d2f(p1, p2) \
84   { SCOPED_TRACE(""); do_test_d2f(p1, p2); }
85 
86 #define test_d2b2d(p1, p2, p3, p4, p5) \
87   { SCOPED_TRACE(""); do_test_d2b2d(p1, p2, p3, p4, p5); }
88 
89 #define test_f2d(p1, p2) \
90   { SCOPED_TRACE(""); do_test_f2d(p1, p2); }
91 
92 #define test_ull2d(p1, p2, p3) \
93   { SCOPED_TRACE(""); do_test_ull2d(p1, p2, p3); }
94 
95 #define test_ll2d(p1, p2, p3) \
96   { SCOPED_TRACE(""); do_test_ll2d(p1, p2, p3); }
97 
98 #define test_d2ull(p1, p2, p3) \
99   { SCOPED_TRACE(""); do_test_d2ull(p1, p2, p3); }
100 
101 #define test_d2ll(p1, p2, p3) \
102   { SCOPED_TRACE(""); do_test_d2ll(p1, p2, p3); }
103 
104 #define test_da(p1, p2, p3, p4) \
105   { SCOPED_TRACE(""); do_test_da(p1, p2, p3, p4); }
106 
107 #define test_ds(p1, p2, p3, p4) \
108   { SCOPED_TRACE(""); do_test_ds(p1, p2, p3, p4); }
109 
110 #define test_dc(p1, p2, p3) \
111   { SCOPED_TRACE(""); do_test_dc(p1, p2, p3); }
112 
113 #define test_dm(p1, p2, p3, p4) \
114   { SCOPED_TRACE(""); do_test_dm(p1, p2, p3, p4); }
115 
116 #define test_dv(p1, p2, p3, p4) \
117   { SCOPED_TRACE(""); do_test_dv(p1, p2, p3, p4); }
118 
119 #define test_md(p1, p2, p3, p4) \
120   { SCOPED_TRACE(""); do_test_md(p1, p2, p3, p4); }
121 
122 #define test_ro(p1, p2, p3, p4, p5) \
123   { SCOPED_TRACE(""); do_test_ro(p1, p2, p3, p4, p5); }
124 
125 #define test_format(p1, p2, p3, p4, p5) \
126   { SCOPED_TRACE(""); do_test_format(p1, p2, p3, p4, p5); }
127 
128 #define test_mx(p1, p2, p3) \
129   { SCOPED_TRACE(""); do_test_mx(p1, p2, p3); }
130 
131 #define test_pr(p1, p2, p3, p4, p5, p6) \
132   { SCOPED_TRACE(""); do_test_pr(p1, p2, p3, p4, p5, p6); }
133 
134 #define test_sh(p1, p2, p3, p4) \
135   { SCOPED_TRACE(""); do_test_sh(p1, p2, p3, p4); }
136 
137 #define test_fr(p1, p2) \
138   { SCOPED_TRACE(""); do_test_fr(p1, p2); }
139 
140 
do_check_result_code(int actual,int want)141 void do_check_result_code(int actual, int want)
142 {
143   EXPECT_EQ(want, actual);
144 }
145 
do_print_decimal(decimal_t * d,const char * orig,int actual,int want,const char * msg)146 void do_print_decimal(decimal_t *d, const char *orig, int actual, int want,
147                       const char *msg)
148 {
149   char s[100];
150   int slen=sizeof(s);
151 
152   if (full) dump_decimal(d);
153   decimal2string(d, s, &slen, 0, 0, 0);
154   check_result_code(actual, want);
155   if (orig)
156   {
157     EXPECT_STREQ(orig, s) << " arguments were: " << msg;
158   }
159 }
160 
test_d2s()161 void test_d2s()
162 {
163   char s[100];
164   int slen, res;
165 
166   /***********************************/
167   printf("==== decimal2string ====\n");
168   a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
169   slen=sizeof(s);
170   res=decimal2string(&a, s, &slen, 0, 0, 0);
171   dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
172 
173   a.buf[1]=987000000; a.frac=3;
174   slen=sizeof(s);
175   res=decimal2string(&a, s, &slen, 0, 0, 0);
176   dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
177 
178   a.sign=1;
179   slen=sizeof(s);
180   res=decimal2string(&a, s, &slen, 0, 0, 0);
181   dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
182 
183   slen=8;
184   res=decimal2string(&a, s, &slen, 0, 0, 0);
185   dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
186 
187   slen=5;
188   res=decimal2string(&a, s, &slen, 0, 0, 0);
189   dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
190 
191   a.buf[0]=987000000; a.frac=3; a.intg=0;
192   slen=sizeof(s);
193   res=decimal2string(&a, s, &slen, 0, 0, 0);
194   dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
195 }
196 
do_test_s2d(const char * s,const char * orig,int ex)197 void do_test_s2d(const char *s, const char *orig, int ex)
198 {
199   char s1[100], *end;
200   int res;
201   sprintf(s1, "'%s'", s);
202   end= strend(s);
203   res= string2decimal(s, &a, &end);
204   print_decimal(&a, orig, res, ex, s1);
205 }
206 
do_test_d2f(const char * s,int ex)207 void do_test_d2f(const char *s, int ex)
208 {
209   char s1[100], *end;
210   double x;
211   int res;
212 
213   sprintf(s1, "'%s'", s);
214   end= strend(s);
215   string2decimal(s, &a, &end);
216   res=decimal2double(&a, &x);
217   if (full) dump_decimal(&a);
218   check_result_code(res, ex);
219 }
220 
do_test_d2b2d(const char * str,int p,int s,const char * orig,int ex)221 void do_test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
222 {
223   char s1[100];
224   char s2[100 * 2];
225   uchar buf[100];
226   char *end;
227   int res, i, size=decimal_bin_size(p, s);
228 
229   sprintf(s1, "'%s'", str);
230   end= strend(str);
231   string2decimal(str, &a, &end);
232   res=decimal2bin(&a, buf, p, s);
233   sprintf(s2, "%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
234   if (full)
235   {
236     printf("0x");
237     for (i=0; i < size; i++)
238       printf("%02x", ((uchar *)buf)[i]);
239   }
240   res=bin2decimal(buf, &a, p, s);
241   print_decimal(&a, orig, res, ex, s2);
242 }
243 
do_test_f2d(double from,int ex)244 void do_test_f2d(double from, int ex)
245 {
246   int res;
247   char s1[100];
248 
249   res=double2decimal(from, &a);
250   sprintf(s1, "%-40.*f => res=%d    ", DBL_DIG-2, from, res);
251   print_decimal(&a, 0, res, ex, s1);
252 }
253 
do_test_ull2d(ulonglong from,const char * orig,int ex)254 void do_test_ull2d(ulonglong from, const char *orig, int ex)
255 {
256   char s[100];
257   char s1[100 * 2];
258   int res;
259 
260   res=ulonglong2decimal(from, &a);
261   longlong10_to_str(from,s,10);
262   sprintf(s1, "%-40s => res=%d    ", s, res);
263   print_decimal(&a, orig, res, ex, s1);
264 }
265 
do_test_ll2d(longlong from,const char * orig,int ex)266 void do_test_ll2d(longlong from, const char *orig, int ex)
267 {
268   char s[100];
269   char s1[100 * 2];
270   int res;
271 
272   res=longlong2decimal(from, &a);
273   longlong10_to_str(from,s,-10);
274   sprintf(s1, "%-40s => res=%d    ", s, res);
275   print_decimal(&a, orig, res, ex, s1);
276 }
277 
do_test_d2ull(const char * s,const char * orig,int ex)278 void do_test_d2ull(const char *s, const char *orig, int ex)
279 {
280   char s1[100], *end;
281   char s2[100 * 2];
282   ulonglong x;
283   int res;
284 
285   end= strend(s);
286   string2decimal(s, &a, &end);
287   res=decimal2ulonglong(&a, &x);
288   if (full) dump_decimal(&a);
289   longlong10_to_str(x,s1,10);
290   sprintf(s2, "%-40s => res=%d    %s\n", s, res, s1);
291   check_result_code(res, ex);
292   if (orig)
293   {
294     EXPECT_STREQ(orig, s1) << " arguments were: " << s2;
295   }
296 }
297 
do_test_d2ll(const char * s,const char * orig,int ex)298 void do_test_d2ll(const char *s, const char *orig, int ex)
299 {
300   char s1[100], *end;
301   char s2[100 * 2];
302   longlong x;
303   int res;
304 
305   end= strend(s);
306   string2decimal(s, &a, &end);
307   res=decimal2longlong(&a, &x);
308   if (full) dump_decimal(&a);
309   longlong10_to_str(x,s1,-10);
310   sprintf(s2, "%-40s => res=%d    %s\n", s, res, s1);
311   check_result_code(res, ex);
312   if (orig)
313   {
314     EXPECT_STREQ(orig, s1) << " arguments were: " << s2;
315   }
316 }
317 
do_test_da(const char * s1,const char * s2,const char * orig,int ex)318 void do_test_da(const char *s1, const char *s2, const char *orig, int ex)
319 {
320   char s[100], *end;
321   int res;
322   sprintf(s, "'%s' + '%s'", s1, s2);
323   end= strend(s1);
324   string2decimal(s1, &a, &end);
325   end= strend(s2);
326   string2decimal(s2, &b, &end);
327   res=decimal_add(&a, &b, &c);
328   print_decimal(&c, orig, res, ex, s);
329 }
330 
do_test_ds(const char * s1,const char * s2,const char * orig,int ex)331 void do_test_ds(const char *s1, const char *s2, const char *orig, int ex)
332 {
333   char s[100], *end;
334   int res;
335   sprintf(s, "'%s' - '%s'", s1, s2);
336   end= strend(s1);
337   string2decimal(s1, &a, &end);
338   end= strend(s2);
339   string2decimal(s2, &b, &end);
340   res=decimal_sub(&a, &b, &c);
341   print_decimal(&c, orig, res, ex, s);
342 }
343 
do_test_dc(const char * s1,const char * s2,int orig)344 void do_test_dc(const char *s1, const char *s2, int orig)
345 {
346   char s[100], *end;
347   int res;
348   sprintf(s, "'%s' <=> '%s'", s1, s2);
349   end= strend(s1);
350   string2decimal(s1, &a, &end);
351   end= strend(s2);
352   string2decimal(s2, &b, &end);
353   res=decimal_cmp(&a, &b);
354   EXPECT_EQ(orig, res) << " arguments were: " << s;
355 }
356 
do_test_dm(const char * s1,const char * s2,const char * orig,int ex)357 void do_test_dm(const char *s1, const char *s2, const char *orig, int ex)
358 {
359   char s[100], *end;
360   int res;
361   sprintf(s, "'%s' * '%s'", s1, s2);
362   end= strend(s1);
363   string2decimal(s1, &a, &end);
364   end= strend(s2);
365   string2decimal(s2, &b, &end);
366   res=decimal_mul(&a, &b, &c);
367   print_decimal(&c, orig, res, ex, s);
368 }
369 
do_test_dv(const char * s1,const char * s2,const char * orig,int ex)370 void do_test_dv(const char *s1, const char *s2, const char *orig, int ex)
371 {
372   char s[100], *end;
373   int res;
374   sprintf(s, "'%s' / '%s'", s1, s2);
375   end= strend(s1);
376   string2decimal(s1, &a, &end);
377   end= strend(s2);
378   string2decimal(s2, &b, &end);
379   res=decimal_div(&a, &b, &c, 5);
380   check_result_code(res, ex);
381   if (res != E_DEC_DIV_ZERO)
382     print_decimal(&c, orig, res, ex, s);
383 }
384 
do_test_md(const char * s1,const char * s2,const char * orig,int ex)385 void do_test_md(const char *s1, const char *s2, const char *orig, int ex)
386 {
387   char s[100], *end;
388   int res;
389   sprintf(s, "'%s' %% '%s'", s1, s2);
390   end= strend(s1);
391   string2decimal(s1, &a, &end);
392   end= strend(s2);
393   string2decimal(s2, &b, &end);
394   res=decimal_mod(&a, &b, &c);
395   check_result_code(res, ex);
396   if (res != E_DEC_DIV_ZERO)
397     print_decimal(&c, orig, res, ex, s);
398 }
399 
400 const char *round_mode[]=
401 {"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
402 
do_test_ro(const char * s1,int n,decimal_round_mode mode,const char * orig,int ex)403 void do_test_ro(const char *s1, int n, decimal_round_mode mode,
404                 const char *orig, int ex)
405 {
406   char s[100], *end;
407   int res;
408   sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
409   end= strend(s1);
410   string2decimal(s1, &a, &end);
411   res=decimal_round(&a, &b, n, mode);
412   print_decimal(&b, orig, res, ex, s);
413 }
414 
415 
do_test_format(const char * s1,const char * s2,int n,const char * orig,int ex)416 void do_test_format(const char *s1, const char *s2, int n, const char *orig,
417                     int ex)
418 {
419   char s[200], *end;
420   decimal_t a,b,c,d;
421   decimal_digit_t buf1[9],buf2[9],buf3[9],buf4[9];
422   int res;
423   a.buf= buf1;
424   b.buf= buf2;
425   c.buf= buf3;
426   d.buf= buf4;
427   a.len= sizeof(buf1)/sizeof(dec1);
428   b.len= sizeof(buf2)/sizeof(dec1);
429   c.len= sizeof(buf3)/sizeof(dec1);
430   d.len= sizeof(buf4)/sizeof(dec1);
431 
432   sprintf(s, "'%s' %% '%s'", s1, s2);
433   end= strend(s1);
434   string2decimal(s1, &a, &end);
435   end= strend(s2);
436   string2decimal(s2, &b, &end);
437   decimal_mod(&a, &b, &c);
438   res=decimal_round(&c, &d, n, HALF_UP);
439   print_decimal(&d, orig, res, ex, s);
440 
441 }
do_test_mx(int precision,int frac,const char * orig)442 void do_test_mx(int precision, int frac, const char *orig)
443 {
444   char s[100];
445   sprintf(s, "%d, %d", precision, frac);
446   max_decimal(precision, frac, &a);
447   print_decimal(&a, orig, 0, 0, s);
448 }
449 
450 
do_test_pr(const char * s1,int prec,int dec,char filler,const char * orig,int ex)451 void do_test_pr(const char *s1, int prec, int dec, char filler,
452                 const char *orig, int ex)
453 {
454   char s[100], *end;
455   char s2[100];
456   int slen= sizeof(s2);
457   int res;
458 
459   if (filler)
460     sprintf(s, "'%s', %d, %d, '%c'", s1, prec, dec, filler);
461   else
462     sprintf(s, "'%s', %d, %d, '\\0'", s1, prec, dec);
463   end= strend(s1);
464   string2decimal(s1, &a, &end);
465   res= decimal2string(&a, s2, &slen, prec, dec, filler);
466   check_result_code(res, ex);
467   if (orig)
468   {
469     EXPECT_STREQ(orig, s2) << " arguments were: " << s;
470   }
471 }
472 
473 
do_test_sh(const char * s1,int shift,const char * orig,int ex)474 void do_test_sh(const char *s1, int shift, const char *orig, int ex)
475 {
476   char s[100], *end;
477   int res;
478   sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
479   end= strend(s1);
480   string2decimal(s1, &a, &end);
481   res= decimal_shift(&a, shift);
482   print_decimal(&a, orig, res, ex, s);
483 }
484 
485 
do_test_fr(const char * s1,const char * orig)486 void do_test_fr(const char *s1, const char *orig)
487 {
488   char s[100], *end;
489   sprintf(s, "'%s'", s1);
490   end= strend(s1);
491   string2decimal(s1, &a, &end);
492   a.frac= decimal_actual_fraction(&a);
493   print_decimal(&a, orig, 0, 0, s);
494 }
495 
496 
497 class DecimalTest : public ::testing::Test
498 {
499 protected:
SetUp()500   virtual void SetUp()
501   {
502     a.buf= buf1;
503     a.len= sizeof(buf1)/sizeof(dec1);
504     b.buf= buf2;
505     b.len= sizeof(buf2)/sizeof(dec1);
506     c.buf= buf3;
507     c.len= sizeof(buf3)/sizeof(dec1);
508   }
509 };
510 
511 
TEST_F(DecimalTest,String2Decimal)512 TEST_F(DecimalTest, String2Decimal)
513 {
514   test_s2d("12345", "12345", 0);
515   test_s2d("12345.", "12345", 0);
516   test_s2d("123.45", "123.45", 0);
517   test_s2d("-123.45", "-123.45", 0);
518   test_s2d(".00012345000098765", "0.00012345000098765", 0);
519   test_s2d(".12345000098765", "0.12345000098765", 0);
520   test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
521   test_s2d("1234500009876.5", "1234500009876.5", 0);
522   a.len=1;
523   test_s2d("123450000098765", "98765", 2);
524   test_s2d("123450.000098765", "123450", 1);
525   a.len=sizeof(buf1)/sizeof(dec1);
526   test_s2d("123E5", "12300000", 0);
527   test_s2d("123E-2", "1.23", 0);
528 }
529 
530 
TEST_F(DecimalTest,Decimal2Double)531 TEST_F(DecimalTest, Decimal2Double)
532 {
533   test_d2f("12345", 0);
534   test_d2f("123.45", 0);
535   test_d2f("-123.45", 0);
536   test_d2f("0.00012345000098765", 0);
537   test_d2f("1234500009876.5", 0);
538 }
539 
540 
TEST_F(DecimalTest,Double2Decimal)541 TEST_F(DecimalTest, Double2Decimal)
542 {
543   test_f2d(12345, 0);
544   test_f2d(1.0/3, 0);
545   test_f2d(-123.45, 0);
546   test_f2d(0.00012345000098765, 0);
547   test_f2d(1234500009876.5, 0);
548 }
549 
550 
TEST_F(DecimalTest,Ulonglong2Decimal)551 TEST_F(DecimalTest, Ulonglong2Decimal)
552 {
553   test_ull2d(12345ULL, "12345", 0);
554   test_ull2d(0ULL, "0", 0);
555   test_ull2d(18446744073709551615ULL, "18446744073709551615", 0);
556 }
557 
558 
TEST_F(DecimalTest,Decimal2Ulonglong)559 TEST_F(DecimalTest, Decimal2Ulonglong)
560 {
561   test_d2ull("12345", "12345", 0);
562   test_d2ull("0", "0", 0);
563   /* ULLONG_MAX = 18446744073709551615ULL */
564   test_d2ull("18446744073709551615", "18446744073709551615", 0);
565   test_d2ull("18446744073709551616", "18446744073709551615", 2);
566   test_d2ull("-1", "0", 2);
567   test_d2ull("1.23", "1", 1);
568   test_d2ull("9999999999999999999999999.000", "18446744073709551615", 2);
569 }
570 
571 
TEST_F(DecimalTest,Longlong2Decimal)572 TEST_F(DecimalTest, Longlong2Decimal)
573 {
574   test_ll2d(-12345LL, "-12345", 0);
575   test_ll2d(-1LL, "-1", 0);
576   test_ll2d(-9223372036854775807LL, "-9223372036854775807", 0);
577   test_ll2d(9223372036854775808ULL, "-9223372036854775808", 0);
578 }
579 
580 
TEST_F(DecimalTest,Decimal2Longlong)581 TEST_F(DecimalTest, Decimal2Longlong)
582 {
583   /* LLONG_MAX = 9223372036854775807LL */
584   test_d2ll("18446744073709551615", "9223372036854775807", 2);
585   test_d2ll("-1", "-1", 0);
586   test_d2ll("-1.23", "-1", 1);
587   test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
588   test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
589   test_d2ll("9223372036854775808", "9223372036854775807", 2);
590 }
591 
592 
TEST_F(DecimalTest,DoAdd)593 TEST_F(DecimalTest, DoAdd)
594 {
595   test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
596   test_da(".1" ,".45", "0.55", 0);
597   test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
598   test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
599   test_da("99999999" ,"1", "100000000", 0);
600   test_da("989999999" ,"1", "990000000", 0);
601   test_da("999999999" ,"1", "1000000000", 0);
602   test_da("12345" ,"123.45", "12468.45", 0);
603   test_da("-12345" ,"-123.45", "-12468.45", 0);
604   test_ds("-12345" ,"123.45", "-12468.45", 0);
605   test_ds("12345" ,"-123.45", "12468.45", 0);
606 }
607 
608 
TEST_F(DecimalTest,DoSub)609 TEST_F(DecimalTest, DoSub)
610 {
611   test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
612   test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
613   test_ds("9999900000000.5", ".555","9999899999999.945", 0);
614   test_ds("1111.5551", "1111.555","0.0001", 0);
615   test_ds(".555", ".555","0", 0);
616   test_ds("10000000", "1","9999999", 0);
617   test_ds("1000001000", ".1","1000000999.9", 0);
618   test_ds("1000000000", ".1","999999999.9", 0);
619   test_ds("12345", "123.45","12221.55", 0);
620   test_ds("-12345", "-123.45","-12221.55", 0);
621   test_da("-12345", "123.45","-12221.55", 0);
622   test_da("12345", "-123.45","12221.55", 0);
623   test_ds("123.45", "12345","-12221.55", 0);
624   test_ds("-123.45", "-12345","12221.55", 0);
625   test_da("123.45", "-12345","-12221.55", 0);
626   test_da("-123.45", "12345","12221.55", 0);
627   test_da("5", "-6.0","-1.0", 0);
628 }
629 
630 
TEST_F(DecimalTest,DecimalMul)631 TEST_F(DecimalTest, DecimalMul)
632 {
633   test_dm("12", "10","120", 0);
634   test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
635   test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
636   test_dm("123456", "987654321","121931851853376", 0);
637   test_dm("123456", "9876543210","1219318518533760", 0);
638   test_dm("123", "0.01","1.23", 0);
639   test_dm("123", "0","0", 0);
640 }
641 
642 
TEST_F(DecimalTest,DecimalDiv)643 TEST_F(DecimalTest, DecimalDiv)
644 {
645   test_dv("120", "10","12.000000000", 0);
646   test_dv("123", "0.01","12300.000000000", 0);
647   test_dv("120", "100000000000.00000","0.000000001200000000", 0);
648   test_dv("123", "0","", 4);
649   test_dv("0", "0", "", 4);
650   test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
651   test_dv("121931851853376", "987654321","123456.000000000", 0);
652   test_dv("0", "987","0", 0);
653   test_dv("1", "3","0.333333333", 0);
654   test_dv("1.000000000000", "3","0.333333333333333333", 0);
655   test_dv("1", "1","1.000000000", 0);
656   test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
657   test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
658   test_dv("10.000000000060", "2","5.000000000030000000", 0);
659 }
660 
661 
TEST_F(DecimalTest,DecimalMod)662 TEST_F(DecimalTest, DecimalMod)
663 {
664   test_md("234","10","4", 0);
665   test_md("234.567","10.555","2.357", 0);
666   test_md("-234.567","10.555","-2.357", 0);
667   test_md("234.567","-10.555","2.357", 0);
668   c.buf[1]=0x3ABECA;
669   test_md("99999999999999999999999999999999999999","3","0", 0);
670   if (c.buf[1] != 0x3ABECA)
671   {
672     ADD_FAILURE() << "overflow " << c.buf[1];
673   }
674 }
675 
676 
TEST_F(DecimalTest,Decimal2BinBin2Decimal)677 TEST_F(DecimalTest, Decimal2BinBin2Decimal)
678 {
679   test_d2b2d("-10.55", 4, 2,"-10.55", 0);
680   test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
681   test_d2b2d("12345", 5, 0,"12345", 0);
682   test_d2b2d("12345", 10, 3,"12345.000", 0);
683   test_d2b2d("123.45", 10, 3,"123.450", 0);
684   test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
685   test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
686   test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
687   test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
688   test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
689   test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
690   test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
691   test_d2b2d("000000000.01", 7, 3,"0.010", 0);
692   test_d2b2d("123.4", 10, 2, "123.40", 0);
693 }
694 
695 
TEST_F(DecimalTest,DecimalCmp)696 TEST_F(DecimalTest, DecimalCmp)
697 {
698   test_dc("12","13",-1);
699   test_dc("13","12",1);
700   test_dc("-10","10",-1);
701   test_dc("10","-10",1);
702   test_dc("-12","-13",1);
703   test_dc("0","12",-1);
704   test_dc("-10","0",-1);
705   test_dc("4","4",0);
706 }
707 
708 
TEST_F(DecimalTest,DecimalRound)709 TEST_F(DecimalTest, DecimalRound)
710 {
711   test_ro("5678.123451",-4,TRUNCATE,"0", 0);
712   test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
713   test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
714   test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
715   test_ro("5678.123451",0,TRUNCATE,"5678", 0);
716   test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
717   test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
718   test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
719   test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
720   test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
721   test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
722   test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
723   memset(buf2, 33, sizeof(buf2));
724   test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
725   test_ro("15.1",0,HALF_UP,"15", 0);
726   test_ro("15.5",0,HALF_UP,"16", 0);
727   test_ro("15.9",0,HALF_UP,"16", 0);
728   test_ro("-15.1",0,HALF_UP,"-15", 0);
729   test_ro("-15.5",0,HALF_UP,"-16", 0);
730   test_ro("-15.9",0,HALF_UP,"-16", 0);
731   test_ro("15.1",1,HALF_UP,"15.1", 0);
732   test_ro("-15.1",1,HALF_UP,"-15.1", 0);
733   test_ro("15.17",1,HALF_UP,"15.2", 0);
734   test_ro("15.4",-1,HALF_UP,"20", 0);
735   test_ro("-15.4",-1,HALF_UP,"-20", 0);
736   test_ro("5.4",-1,HALF_UP,"10", 0);
737   test_ro(".999", 0, HALF_UP, "1", 0);
738   memset(buf2, 33, sizeof(buf2));
739   test_ro("999999999", -9, HALF_UP, "1000000000", 0);
740   test_ro("15.1",0,HALF_EVEN,"15", 0);
741   test_ro("15.5",0,HALF_EVEN,"16", 0);
742   test_ro("14.5",0,HALF_EVEN,"14", 0);
743   test_ro("15.9",0,HALF_EVEN,"16", 0);
744   test_ro("15.1",0,CEILING,"16", 0);
745   test_ro("-15.1",0,CEILING,"-15", 0);
746   test_ro("15.1",0,FLOOR,"15", 0);
747   test_ro("-15.1",0,FLOOR,"-16", 0);
748   test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
749   test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
750 
751   b.buf[0]=DIG_BASE+1;
752   b.buf++;
753   test_ro(".3", 0, HALF_UP, "0", 0);
754   b.buf--;
755   if (b.buf[0] != DIG_BASE+1)
756   {
757     ADD_FAILURE() << "underflow " << b.buf[0];
758   }
759 }
760 
761 
TEST_F(DecimalTest,FormatFunc)762 TEST_F(DecimalTest, FormatFunc)
763 {
764   test_format("999999999999999999999999999999999999999999999999999999999999999",
765               "999999999999999999999999999999999999999999999999999999999999999",
766               42,"0.000000000000000000000000000000000000000000",0);
767 }
768 
769 
TEST_F(DecimalTest,MaxDecimal)770 TEST_F(DecimalTest, MaxDecimal)
771 {
772   test_mx(1,1,"0.9");
773   test_mx(1,0,"9");
774   test_mx(2,1,"9.9");
775   test_mx(4,2,"99.99");
776   test_mx(6,3,"999.999");
777   test_mx(8,4,"9999.9999");
778   test_mx(10,5,"99999.99999");
779   test_mx(12,6,"999999.999999");
780   test_mx(14,7,"9999999.9999999");
781   test_mx(16,8,"99999999.99999999");
782   test_mx(18,9,"999999999.999999999");
783   test_mx(20,10,"9999999999.9999999999");
784   test_mx(20,20,"0.99999999999999999999");
785   test_mx(20,0,"99999999999999999999");
786   test_mx(40,20,"99999999999999999999.99999999999999999999");
787 }
788 
789 
TEST_F(DecimalTest,Decimal2String)790 TEST_F(DecimalTest, Decimal2String)
791 {
792   test_pr("123.123", 0, 0, 0, "123.123", 0);
793   /* For fixed precision, we no longer count the '.' here. */
794   test_pr("123.123", 6, 3, '0', "123.123", 0);
795   test_pr("123.123", 8, 3, '0', "00123.123", 0);
796   test_pr("123.123", 8, 4, '0', "0123.1230", 0);
797   test_pr("123.123", 8, 5, '0', "123.12300", 0);
798   test_pr("123.123", 8, 2, '0', "000123.12", 1);
799   test_pr("123.123", 8, 6, '0', "23.123000", 2);
800 }
801 
802 
TEST_F(DecimalTest,DecimalShift)803 TEST_F(DecimalTest, DecimalShift)
804 {
805   test_sh("123.123", 1, "1231.23", 0);
806   test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
807   test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
808   test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
809   test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
810   test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
811   test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
812   test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
813   test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
814   test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
815   test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
816   test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
817   test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
818   test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
819   test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
820   test_sh("123", 1, "1230", 0);
821   test_sh("123", 10, "1230000000000", 0);
822   test_sh(".123", 1, "1.23", 0);
823   test_sh(".123", 10, "1230000000", 0);
824   test_sh(".123", 14, "12300000000000", 0);
825   test_sh("000.000", 1000, "0", 0);
826   test_sh("000.", 1000, "0", 0);
827   test_sh(".000", 1000, "0", 0);
828   test_sh("1", 1000, "1", 2);
829   test_sh("123.123", -1, "12.3123", 0);
830   test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
831   test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
832   test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
833   test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
834   test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
835   test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
836   test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
837   test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
838   test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
839   test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
840   test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
841   a.len= 2;
842   test_sh("123.123", -2, "1.23123", 0);
843   test_sh("123.123", -3, "0.123123", 0);
844   test_sh("123.123", -6, "0.000123123", 0);
845   test_sh("123.123", -7, "0.0000123123", 0);
846   test_sh("123.123", -15, "0.000000000000123123", 0);
847   test_sh("123.123", -16, "0.000000000000012312", 1);
848   test_sh("123.123", -17, "0.000000000000001231", 1);
849   test_sh("123.123", -18, "0.000000000000000123", 1);
850   test_sh("123.123", -19, "0.000000000000000012", 1);
851   test_sh("123.123", -20, "0.000000000000000001", 1);
852   test_sh("123.123", -21, "0", 1);
853   test_sh(".000000000123", -1, "0.0000000000123", 0);
854   test_sh(".000000000123", -6, "0.000000000000000123", 0);
855   test_sh(".000000000123", -7, "0.000000000000000012", 1);
856   test_sh(".000000000123", -8, "0.000000000000000001", 1);
857   test_sh(".000000000123", -9, "0", 1);
858   test_sh(".000000000123", 1, "0.00000000123", 0);
859   test_sh(".000000000123", 8, "0.0123", 0);
860   test_sh(".000000000123", 9, "0.123", 0);
861   test_sh(".000000000123", 10, "1.23", 0);
862   test_sh(".000000000123", 17, "12300000", 0);
863   test_sh(".000000000123", 18, "123000000", 0);
864   test_sh(".000000000123", 19, "1230000000", 0);
865   test_sh(".000000000123", 20, "12300000000", 0);
866   test_sh(".000000000123", 21, "123000000000", 0);
867   test_sh(".000000000123", 22, "1230000000000", 0);
868   test_sh(".000000000123", 23, "12300000000000", 0);
869   test_sh(".000000000123", 24, "123000000000000", 0);
870   test_sh(".000000000123", 25, "1230000000000000", 0);
871   test_sh(".000000000123", 26, "12300000000000000", 0);
872   test_sh(".000000000123", 27, "123000000000000000", 0);
873   test_sh(".000000000123", 28, "0.000000000123", 2);
874   test_sh("123456789.987654321", -1, "12345678.998765432", 1);
875   test_sh("123456789.987654321", -2, "1234567.899876543", 1);
876   test_sh("123456789.987654321", -8, "1.234567900", 1);
877   test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
878   test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
879   test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
880   test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
881   test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
882   test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
883   test_sh("123456789.987654321", -27, "0", 1);
884   test_sh("123456789.987654321", 1, "1234567900", 1);
885   test_sh("123456789.987654321", 2, "12345678999", 1);
886   test_sh("123456789.987654321", 4, "1234567899877", 1);
887   test_sh("123456789.987654321", 8, "12345678998765432", 1);
888   test_sh("123456789.987654321", 9, "123456789987654321", 0);
889   test_sh("123456789.987654321", 10, "123456789.987654321", 2);
890   test_sh("123456789.987654321", 0, "123456789.987654321", 0);
891   a.len= sizeof(buf1)/sizeof(dec1);
892 }
893 
894 
TEST_F(DecimalTest,DecimalActualFraction)895 TEST_F(DecimalTest, DecimalActualFraction)
896 {
897   test_fr("1.123456789000000000", "1.123456789");
898   test_fr("1.12345678000000000", "1.12345678");
899   test_fr("1.1234567000000000", "1.1234567");
900   test_fr("1.123456000000000", "1.123456");
901   test_fr("1.12345000000000", "1.12345");
902   test_fr("1.1234000000000", "1.1234");
903   test_fr("1.123000000000", "1.123");
904   test_fr("1.12000000000", "1.12");
905   test_fr("1.1000000000", "1.1");
906   test_fr("1.000000000", "1");
907   test_fr("1.0", "1");
908   test_fr("10000000000000000000.0", "10000000000000000000");
909 }
910 
911 
912 }
913