List:Commits« Previous MessageNext Message »
From:Tor Didriksen Date:August 26 2011 7:07am
Subject:bzr push into mysql-trunk branch (tor.didriksen:3406 to 3407) Bug#12744991
View as plain text  
 3407 Tor Didriksen	2011-08-26
       Bug#12744991 - DECIMAL_ROUND(X,D) GIVES WRONG RESULTS WHEN D == N*(-9)
     @ mysql-test/r/func_math.result
        New test cases.
     @ mysql-test/t/func_math.test
        New test cases.
     @ strings/decimal.c
        Round up negative values for scale.
        Move main() program and tests to unit test.
     @ unittest/gunit/CMakeLists.txt
        Add decimal unit test.
     @ unittest/gunit/decimal-t.cc
        New unit test for decimal, based on main program from the decimal implementation.

    added:
      unittest/gunit/decimal-t.cc
    modified:
      mysql-test/r/func_math.result
      mysql-test/t/func_math.test
      strings/decimal.c
      unittest/gunit/CMakeLists.txt
 3406 Marc Alff	2011-08-25 [merge]
      Local merge

    modified:
      extra/innochecksum.c
=== modified file 'mysql-test/r/func_math.result'
--- a/mysql-test/r/func_math.result	2011-07-22 07:53:39 +0000
+++ b/mysql-test/r/func_math.result	2011-08-26 07:06:35 +0000
@@ -700,6 +700,21 @@ select (1.175494351E-37 div 1.7976931348
 Warnings:
 Warning	1292	Truncated incorrect DECIMAL value: ''
 #
+# Bug#12744991 - DECIMAL_ROUND(X,D) GIVES WRONG RESULTS WHEN D == N*(-9)
+#
+select round(999999999, -9);
+round(999999999, -9)
+1000000000
+select round(999999999.0, -9);
+round(999999999.0, -9)
+1000000000
+select round(999999999999999999, -18);
+round(999999999999999999, -18)
+1000000000000000000
+select round(999999999999999999.0, -18);
+round(999999999999999999.0, -18)
+1000000000000000000
+#
 # Bug#12537160 ASSERTION FAILED:
 # STOP0 <= &TO->BUF[TO->LEN] WITH LARGE NUMBER.
 #

=== modified file 'mysql-test/t/func_math.test'
--- a/mysql-test/t/func_math.test	2011-07-18 09:38:13 +0000
+++ b/mysql-test/t/func_math.test	2011-08-26 07:06:35 +0000
@@ -538,6 +538,16 @@ SELECT 1 div null;
 select (1.175494351E-37 div 1.7976931348623157E+308);
 
 --echo #
+--echo # Bug#12744991 - DECIMAL_ROUND(X,D) GIVES WRONG RESULTS WHEN D == N*(-9)
+--echo #
+
+select round(999999999, -9);
+select round(999999999.0, -9);
+select round(999999999999999999, -18);
+select round(999999999999999999.0, -18);
+
+
+--echo #
 --echo # Bug#12537160 ASSERTION FAILED:
 --echo # STOP0 <= &TO->BUF[TO->LEN] WITH LARGE NUMBER.
 --echo #

=== modified file 'strings/decimal.c'
--- a/strings/decimal.c	2011-07-18 08:06:21 +0000
+++ b/strings/decimal.c	2011-08-26 07:06:35 +0000
@@ -1474,7 +1474,7 @@ int
 decimal_round(const decimal_t *from, decimal_t *to, int scale,
               decimal_round_mode mode)
 {
-  int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
+  int frac0=scale>0 ? ROUND_UP(scale) : (scale + 1)/DIG_PER_DEC1,
     frac1=ROUND_UP(from->frac), UNINIT_VAR(round_digit),
       intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len,
       intg1=ROUND_UP(from->intg +
@@ -2409,734 +2409,7 @@ int decimal_mod(const decimal_t *from1, 
 }
 
 #ifdef MAIN
-
-int full= 0;
-decimal_t a, b, c;
-char buf1[100], buf2[100], buf3[100];
-
-void dump_decimal(decimal_t *d)
-{
-  int i;
-  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
-  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
-    printf("%09d, ", d->buf[i]);
-  printf("%09d} */ ", d->buf[i]);
-}
-
-
-void check_result_code(int actual, int want)
-{
-  if (actual != want)
-  {
-    printf("\n^^^^^^^^^^^^^ must return %d\n", want);
-    exit(1);
-  }
-}
-
-
-void print_decimal(decimal_t *d, const char *orig, int actual, int want)
-{
-  char s[100];
-  int slen=sizeof(s);
-
-  if (full) dump_decimal(d);
-  decimal2string(d, s, &slen, 0, 0, 0);
-  printf("'%s'", s);
-  check_result_code(actual, want);
-  if (orig && strcmp(orig, s))
-  {
-    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
-    exit(1);
-  }
-}
-
-void test_d2s()
-{
-  char s[100];
-  int slen, res;
-
-  /***********************************/
-  printf("==== decimal2string ====\n");
-  a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
-  slen=sizeof(s);
-  res=decimal2string(&a, s, &slen, 0, 0, 0);
-  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
-
-  a.buf[1]=987000000; a.frac=3;
-  slen=sizeof(s);
-  res=decimal2string(&a, s, &slen, 0, 0, 0);
-  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
-
-  a.sign=1;
-  slen=sizeof(s);
-  res=decimal2string(&a, s, &slen, 0, 0, 0);
-  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
-
-  slen=8;
-  res=decimal2string(&a, s, &slen, 0, 0, 0);
-  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
-
-  slen=5;
-  res=decimal2string(&a, s, &slen, 0, 0, 0);
-  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
-
-  a.buf[0]=987000000; a.frac=3; a.intg=0;
-  slen=sizeof(s);
-  res=decimal2string(&a, s, &slen, 0, 0, 0);
-  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
-}
-
-void test_s2d(const char *s, const char *orig, int ex)
-{
-  char s1[100], *end;
-  int res;
-  sprintf(s1, "'%s'", s);
-  end= strend(s);
-  printf("len=%2d %-30s => res=%d    ", a.len, s1,
-         (res= string2decimal(s, &a, &end)));
-  print_decimal(&a, orig, res, ex);
-  printf("\n");
-}
-
-void test_d2f(const char *s, int ex)
-{
-  char s1[100], *end;
-  double x;
-  int res;
-
-  sprintf(s1, "'%s'", s);
-  end= strend(s);
-  string2decimal(s, &a, &end);
-  res=decimal2double(&a, &x);
-  if (full) dump_decimal(&a);
-  printf("%-40s => res=%d    %.*g\n", s1, res, a.intg+a.frac, x);
-  check_result_code(res, ex);
-}
-
-void test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
-{
-  char s1[100], buf[100], *end;
-  int res, i, size=decimal_bin_size(p, s);
-
-  sprintf(s1, "'%s'", str);
-  end= strend(str);
-  string2decimal(str, &a, &end);
-  res=decimal2bin(&a, buf, p, s);
-  printf("%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
-  if (full)
-  {
-    printf("0x");
-    for (i=0; i < size; i++)
-      printf("%02x", ((uchar *)buf)[i]);
-  }
-  res=bin2decimal(buf, &a, p, s);
-  printf(" => res=%d ", res);
-  print_decimal(&a, orig, res, ex);
-  printf("\n");
-}
-
-void test_f2d(double from, int ex)
-{
-  int res;
-
-  res=double2decimal(from, &a);
-  printf("%-40.*f => res=%d    ", DBL_DIG-2, from, res);
-  print_decimal(&a, 0, res, ex);
-  printf("\n");
-}
-
-void test_ull2d(ulonglong from, const char *orig, int ex)
-{
-  char s[100];
-  int res;
-
-  res=ulonglong2decimal(from, &a);
-  longlong10_to_str(from,s,10);
-  printf("%-40s => res=%d    ", s, res);
-  print_decimal(&a, orig, res, ex);
-  printf("\n");
-}
-
-void test_ll2d(longlong from, const char *orig, int ex)
-{
-  char s[100];
-  int res;
-
-  res=longlong2decimal(from, &a);
-  longlong10_to_str(from,s,-10);
-  printf("%-40s => res=%d    ", s, res);
-  print_decimal(&a, orig, res, ex);
-  printf("\n");
-}
-
-void test_d2ull(const char *s, const char *orig, int ex)
-{
-  char s1[100], *end;
-  ulonglong x;
-  int res;
-
-  end= strend(s);
-  string2decimal(s, &a, &end);
-  res=decimal2ulonglong(&a, &x);
-  if (full) dump_decimal(&a);
-  longlong10_to_str(x,s1,10);
-  printf("%-40s => res=%d    %s\n", s, res, s1);
-  check_result_code(res, ex);
-  if (orig && strcmp(orig, s1))
-  {
-    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
-    exit(1);
-  }
-}
-
-void test_d2ll(const char *s, const char *orig, int ex)
-{
-  char s1[100], *end;
-  longlong x;
-  int res;
-
-  end= strend(s);
-  string2decimal(s, &a, &end);
-  res=decimal2longlong(&a, &x);
-  if (full) dump_decimal(&a);
-  longlong10_to_str(x,s1,-10);
-  printf("%-40s => res=%d    %s\n", s, res, s1);
-  check_result_code(res, ex);
-  if (orig && strcmp(orig, s1))
-  {
-    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
-    exit(1);
-  }
-}
-
-void test_da(const char *s1, const char *s2, const char *orig, int ex)
-{
-  char s[100], *end;
-  int res;
-  sprintf(s, "'%s' + '%s'", s1, s2);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  end= strend(s2);
-  string2decimal(s2, &b, &end);
-  res=decimal_add(&a, &b, &c);
-  printf("%-40s => res=%d    ", s, res);
-  print_decimal(&c, orig, res, ex);
-  printf("\n");
-}
-
-void test_ds(const char *s1, const char *s2, const char *orig, int ex)
-{
-  char s[100], *end;
-  int res;
-  sprintf(s, "'%s' - '%s'", s1, s2);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  end= strend(s2);
-  string2decimal(s2, &b, &end);
-  res=decimal_sub(&a, &b, &c);
-  printf("%-40s => res=%d    ", s, res);
-  print_decimal(&c, orig, res, ex);
-  printf("\n");
-}
-
-void test_dc(const char *s1, const char *s2, int orig)
-{
-  char s[100], *end;
-  int res;
-  sprintf(s, "'%s' <=> '%s'", s1, s2);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  end= strend(s2);
-  string2decimal(s2, &b, &end);
-  res=decimal_cmp(&a, &b);
-  printf("%-40s => res=%d\n", s, res);
-  if (orig != res)
-  {
-    printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
-    exit(1);
-  }
-}
-
-void test_dm(const char *s1, const char *s2, const char *orig, int ex)
-{
-  char s[100], *end;
-  int res;
-  sprintf(s, "'%s' * '%s'", s1, s2);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  end= strend(s2);
-  string2decimal(s2, &b, &end);
-  res=decimal_mul(&a, &b, &c);
-  printf("%-40s => res=%d    ", s, res);
-  print_decimal(&c, orig, res, ex);
-  printf("\n");
-}
-
-void test_dv(const char *s1, const char *s2, const char *orig, int ex)
-{
-  char s[100], *end;
-  int res;
-  sprintf(s, "'%s' / '%s'", s1, s2);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  end= strend(s2);
-  string2decimal(s2, &b, &end);
-  res=decimal_div(&a, &b, &c, 5);
-  printf("%-40s => res=%d    ", s, res);
-  check_result_code(res, ex);
-  if (res == E_DEC_DIV_ZERO)
-    printf("E_DEC_DIV_ZERO");
-  else
-    print_decimal(&c, orig, res, ex);
-  printf("\n");
-}
-
-void test_md(const char *s1, const char *s2, const char *orig, int ex)
-{
-  char s[100], *end;
-  int res;
-  sprintf(s, "'%s' %% '%s'", s1, s2);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  end= strend(s2);
-  string2decimal(s2, &b, &end);
-  res=decimal_mod(&a, &b, &c);
-  printf("%-40s => res=%d    ", s, res);
-  check_result_code(res, ex);
-  if (res == E_DEC_DIV_ZERO)
-    printf("E_DEC_DIV_ZERO");
-  else
-    print_decimal(&c, orig, res, ex);
-  printf("\n");
-}
-
-const char *round_mode[]=
-{"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
-
-void test_ro(const char *s1, int n, decimal_round_mode mode, const char *orig,
-             int ex)
-{
-  char s[100], *end;
-  int res;
-  sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  res=decimal_round(&a, &b, n, mode);
-  printf("%-40s => res=%d    ", s, res);
-  print_decimal(&b, orig, res, ex);
-  printf("\n");
-}
-
-
-void test_mx(int precision, int frac, const char *orig)
-{
-  char s[100];
-  sprintf(s, "%d, %d", precision, frac);
-  max_decimal(precision, frac, &a);
-  printf("%-40s =>          ", s);
-  print_decimal(&a, orig, 0, 0);
-  printf("\n");
-}
-
-
-void test_pr(const char *s1, int prec, int dec, char filler, const char *orig,
-             int ex)
-{
-  char s[100], *end;
-  char s2[100];
-  int slen= sizeof(s2);
-  int res;
-
-  sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
-          s1, prec, dec, filler);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  res= decimal2string(&a, s2, &slen, prec, dec, filler);
-  printf("%-40s => res=%d    '%s'", s, res, s2);
-  check_result_code(res, ex);
-  if (orig && strcmp(orig, s2))
-  {
-    printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
-    exit(1);
-  }
-  printf("\n");
-}
-
-
-void test_sh(const char *s1, int shift, const char *orig, int ex)
-{
-  char s[100], *end;
-  int res;
-  sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  res= decimal_shift(&a, shift);
-  printf("%-40s => res=%d    ", s, res);
-  print_decimal(&a, orig, res, ex);
-  printf("\n");
-}
-
-
-void test_fr(const char *s1, const char *orig)
-{
-  char s[100], *end;
-  sprintf(s, "'%s'", s1);
-  printf("%-40s =>          ", s);
-  end= strend(s1);
-  string2decimal(s1, &a, &end);
-  a.frac= decimal_actual_fraction(&a);
-  print_decimal(&a, orig, 0, 0);
-  printf("\n");
-}
-
-
-int main()
-{
-  a.buf=(void*)buf1;
-  a.len=sizeof(buf1)/sizeof(dec1);
-  b.buf=(void*)buf2;
-  b.len=sizeof(buf2)/sizeof(dec1);
-  c.buf=(void*)buf3;
-  c.len=sizeof(buf3)/sizeof(dec1);
-
-  if (full)
-    test_d2s();
-
-  printf("==== string2decimal ====\n");
-  test_s2d("12345", "12345", 0);
-  test_s2d("12345.", "12345", 0);
-  test_s2d("123.45", "123.45", 0);
-  test_s2d("-123.45", "-123.45", 0);
-  test_s2d(".00012345000098765", "0.00012345000098765", 0);
-  test_s2d(".12345000098765", "0.12345000098765", 0);
-  test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
-  test_s2d("1234500009876.5", "1234500009876.5", 0);
-  a.len=1;
-  test_s2d("123450000098765", "98765", 2);
-  test_s2d("123450.000098765", "123450", 1);
-  a.len=sizeof(buf1)/sizeof(dec1);
-  test_s2d("123E5", "12300000", 0);
-  test_s2d("123E-2", "1.23", 0);
-
-  printf("==== decimal2double ====\n");
-  test_d2f("12345", 0);
-  test_d2f("123.45", 0);
-  test_d2f("-123.45", 0);
-  test_d2f("0.00012345000098765", 0);
-  test_d2f("1234500009876.5", 0);
-
-  printf("==== double2decimal ====\n");
-  test_f2d(12345, 0);
-  test_f2d(1.0/3, 0);
-  test_f2d(-123.45, 0);
-  test_f2d(0.00012345000098765, 0);
-  test_f2d(1234500009876.5, 0);
-
-  printf("==== ulonglong2decimal ====\n");
-  test_ull2d(ULL(12345), "12345", 0);
-  test_ull2d(ULL(0), "0", 0);
-  test_ull2d(ULL(18446744073709551615), "18446744073709551615", 0);
-
-  printf("==== decimal2ulonglong ====\n");
-  test_d2ull("12345", "12345", 0);
-  test_d2ull("0", "0", 0);
-  test_d2ull("18446744073709551615", "18446744073709551615", 0);
-  test_d2ull("18446744073709551616", "18446744073", 2);
-  test_d2ull("-1", "0", 2);
-  test_d2ull("1.23", "1", 1);
-  test_d2ull("9999999999999999999999999.000", "9999999999999999", 2);
-
-  printf("==== longlong2decimal ====\n");
-  test_ll2d(LL(-12345), "-12345", 0);
-  test_ll2d(LL(-1), "-1", 0);
-  test_ll2d(LL(-9223372036854775807), "-9223372036854775807", 0);
-  test_ll2d(ULL(9223372036854775808), "-9223372036854775808", 0);
-
-  printf("==== decimal2longlong ====\n");
-  test_d2ll("18446744073709551615", "18446744073", 2);
-  test_d2ll("-1", "-1", 0);
-  test_d2ll("-1.23", "-1", 1);
-  test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
-  test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
-  test_d2ll("9223372036854775808", "9223372036854775807", 2);
-
-  printf("==== do_add ====\n");
-  test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
-  test_da(".1" ,".45", "0.55", 0);
-  test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
-  test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
-  test_da("99999999" ,"1", "100000000", 0);
-  test_da("989999999" ,"1", "990000000", 0);
-  test_da("999999999" ,"1", "1000000000", 0);
-  test_da("12345" ,"123.45", "12468.45", 0);
-  test_da("-12345" ,"-123.45", "-12468.45", 0);
-  test_ds("-12345" ,"123.45", "-12468.45", 0);
-  test_ds("12345" ,"-123.45", "12468.45", 0);
-
-  printf("==== do_sub ====\n");
-  test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
-  test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
-  test_ds("9999900000000.5", ".555","9999899999999.945", 0);
-  test_ds("1111.5551", "1111.555","0.0001", 0);
-  test_ds(".555", ".555","0", 0);
-  test_ds("10000000", "1","9999999", 0);
-  test_ds("1000001000", ".1","1000000999.9", 0);
-  test_ds("1000000000", ".1","999999999.9", 0);
-  test_ds("12345", "123.45","12221.55", 0);
-  test_ds("-12345", "-123.45","-12221.55", 0);
-  test_da("-12345", "123.45","-12221.55", 0);
-  test_da("12345", "-123.45","12221.55", 0);
-  test_ds("123.45", "12345","-12221.55", 0);
-  test_ds("-123.45", "-12345","12221.55", 0);
-  test_da("123.45", "-12345","-12221.55", 0);
-  test_da("-123.45", "12345","12221.55", 0);
-  test_da("5", "-6.0","-1.0", 0);
-
-  printf("==== decimal_mul ====\n");
-  test_dm("12", "10","120", 0);
-  test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
-  test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
-  test_dm("123456", "987654321","121931851853376", 0);
-  test_dm("123456", "9876543210","1219318518533760", 0);
-  test_dm("123", "0.01","1.23", 0);
-  test_dm("123", "0","0", 0);
-
-  printf("==== decimal_div ====\n");
-  test_dv("120", "10","12.000000000", 0);
-  test_dv("123", "0.01","12300.000000000", 0);
-  test_dv("120", "100000000000.00000","0.000000001200000000", 0);
-  test_dv("123", "0","", 4);
-  test_dv("0", "0", "", 4);
-  test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
-  test_dv("121931851853376", "987654321","123456.000000000", 0);
-  test_dv("0", "987","0", 0);
-  test_dv("1", "3","0.333333333", 0);
-  test_dv("1.000000000000", "3","0.333333333333333333", 0);
-  test_dv("1", "1","1.000000000", 0);
-  test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
-  test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
-  test_dv("10.000000000060", "2","5.000000000030000000", 0);
-
-  printf("==== decimal_mod ====\n");
-  test_md("234","10","4", 0);
-  test_md("234.567","10.555","2.357", 0);
-  test_md("-234.567","10.555","-2.357", 0);
-  test_md("234.567","-10.555","2.357", 0);
-  c.buf[1]=0x3ABECA;
-  test_md("99999999999999999999999999999999999999","3","0", 0);
-  if (c.buf[1] != 0x3ABECA)
-  {
-    printf("%X - overflow\n", c.buf[1]);
-    exit(1);
-  }
-
-  printf("==== decimal2bin/bin2decimal ====\n");
-  test_d2b2d("-10.55", 4, 2,"-10.55", 0);
-  test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
-  test_d2b2d("12345", 5, 0,"12345", 0);
-  test_d2b2d("12345", 10, 3,"12345.000", 0);
-  test_d2b2d("123.45", 10, 3,"123.450", 0);
-  test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
-  test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
-  test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
-  test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
-  test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
-  test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
-  test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
-  test_d2b2d("000000000.01", 7, 3,"0.010", 0);
-  test_d2b2d("123.4", 10, 2, "123.40", 0);
-
-
-  printf("==== decimal_cmp ====\n");
-  test_dc("12","13",-1);
-  test_dc("13","12",1);
-  test_dc("-10","10",-1);
-  test_dc("10","-10",1);
-  test_dc("-12","-13",1);
-  test_dc("0","12",-1);
-  test_dc("-10","0",-1);
-  test_dc("4","4",0);
-
-  printf("==== decimal_round ====\n");
-  test_ro("5678.123451",-4,TRUNCATE,"0", 0);
-  test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
-  test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
-  test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
-  test_ro("5678.123451",0,TRUNCATE,"5678", 0);
-  test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
-  test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
-  test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
-  test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
-  test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
-  test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
-  test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
-  memset(buf2, 33, sizeof(buf2));
-  test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
-  test_ro("15.1",0,HALF_UP,"15", 0);
-  test_ro("15.5",0,HALF_UP,"16", 0);
-  test_ro("15.9",0,HALF_UP,"16", 0);
-  test_ro("-15.1",0,HALF_UP,"-15", 0);
-  test_ro("-15.5",0,HALF_UP,"-16", 0);
-  test_ro("-15.9",0,HALF_UP,"-16", 0);
-  test_ro("15.1",1,HALF_UP,"15.1", 0);
-  test_ro("-15.1",1,HALF_UP,"-15.1", 0);
-  test_ro("15.17",1,HALF_UP,"15.2", 0);
-  test_ro("15.4",-1,HALF_UP,"20", 0);
-  test_ro("-15.4",-1,HALF_UP,"-20", 0);
-  test_ro("5.4",-1,HALF_UP,"10", 0);
-  test_ro(".999", 0, HALF_UP, "1", 0);
-  memset(buf2, 33, sizeof(buf2));
-  test_ro("999999999", -9, HALF_UP, "1000000000", 0);
-  test_ro("15.1",0,HALF_EVEN,"15", 0);
-  test_ro("15.5",0,HALF_EVEN,"16", 0);
-  test_ro("14.5",0,HALF_EVEN,"14", 0);
-  test_ro("15.9",0,HALF_EVEN,"16", 0);
-  test_ro("15.1",0,CEILING,"16", 0);
-  test_ro("-15.1",0,CEILING,"-15", 0);
-  test_ro("15.1",0,FLOOR,"15", 0);
-  test_ro("-15.1",0,FLOOR,"-16", 0);
-  test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
-  test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
-
-  b.buf[0]=DIG_BASE+1;
-  b.buf++;
-  test_ro(".3", 0, HALF_UP, "0", 0);
-  b.buf--;
-  if (b.buf[0] != DIG_BASE+1)
-  {
-    printf("%d - underflow\n", b.buf[0]);
-    exit(1);
-  }
-
-  printf("==== max_decimal ====\n");
-  test_mx(1,1,"0.9");
-  test_mx(1,0,"9");
-  test_mx(2,1,"9.9");
-  test_mx(4,2,"99.99");
-  test_mx(6,3,"999.999");
-  test_mx(8,4,"9999.9999");
-  test_mx(10,5,"99999.99999");
-  test_mx(12,6,"999999.999999");
-  test_mx(14,7,"9999999.9999999");
-  test_mx(16,8,"99999999.99999999");
-  test_mx(18,9,"999999999.999999999");
-  test_mx(20,10,"9999999999.9999999999");
-  test_mx(20,20,"0.99999999999999999999");
-  test_mx(20,0,"99999999999999999999");
-  test_mx(40,20,"99999999999999999999.99999999999999999999");
-
-  printf("==== decimal2string ====\n");
-  test_pr("123.123", 0, 0, 0, "123.123", 0);
-  test_pr("123.123", 7, 3, '0', "123.123", 0);
-  test_pr("123.123", 9, 3, '0', "00123.123", 0);
-  test_pr("123.123", 9, 4, '0', "0123.1230", 0);
-  test_pr("123.123", 9, 5, '0', "123.12300", 0);
-  test_pr("123.123", 9, 2, '0', "000123.12", 1);
-  test_pr("123.123", 9, 6, '0', "23.123000", 2);
-
-  printf("==== decimal_shift ====\n");
-  test_sh("123.123", 1, "1231.23", 0);
-  test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
-  test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
-  test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
-  test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
-  test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
-  test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
-  test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
-  test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
-  test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
-  test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
-  test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
-  test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
-  test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
-  test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
-  test_sh("123", 1, "1230", 0);
-  test_sh("123", 10, "1230000000000", 0);
-  test_sh(".123", 1, "1.23", 0);
-  test_sh(".123", 10, "1230000000", 0);
-  test_sh(".123", 14, "12300000000000", 0);
-  test_sh("000.000", 1000, "0", 0);
-  test_sh("000.", 1000, "0", 0);
-  test_sh(".000", 1000, "0", 0);
-  test_sh("1", 1000, "1", 2);
-  test_sh("123.123", -1, "12.3123", 0);
-  test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
-  test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
-  test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
-  test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
-  test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
-  test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
-  test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
-  test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
-  test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
-  test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
-  test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
-  a.len= 2;
-  test_sh("123.123", -2, "1.23123", 0);
-  test_sh("123.123", -3, "0.123123", 0);
-  test_sh("123.123", -6, "0.000123123", 0);
-  test_sh("123.123", -7, "0.0000123123", 0);
-  test_sh("123.123", -15, "0.000000000000123123", 0);
-  test_sh("123.123", -16, "0.000000000000012312", 1);
-  test_sh("123.123", -17, "0.000000000000001231", 1);
-  test_sh("123.123", -18, "0.000000000000000123", 1);
-  test_sh("123.123", -19, "0.000000000000000012", 1);
-  test_sh("123.123", -20, "0.000000000000000001", 1);
-  test_sh("123.123", -21, "0", 1);
-  test_sh(".000000000123", -1, "0.0000000000123", 0);
-  test_sh(".000000000123", -6, "0.000000000000000123", 0);
-  test_sh(".000000000123", -7, "0.000000000000000012", 1);
-  test_sh(".000000000123", -8, "0.000000000000000001", 1);
-  test_sh(".000000000123", -9, "0", 1);
-  test_sh(".000000000123", 1, "0.00000000123", 0);
-  test_sh(".000000000123", 8, "0.0123", 0);
-  test_sh(".000000000123", 9, "0.123", 0);
-  test_sh(".000000000123", 10, "1.23", 0);
-  test_sh(".000000000123", 17, "12300000", 0);
-  test_sh(".000000000123", 18, "123000000", 0);
-  test_sh(".000000000123", 19, "1230000000", 0);
-  test_sh(".000000000123", 20, "12300000000", 0);
-  test_sh(".000000000123", 21, "123000000000", 0);
-  test_sh(".000000000123", 22, "1230000000000", 0);
-  test_sh(".000000000123", 23, "12300000000000", 0);
-  test_sh(".000000000123", 24, "123000000000000", 0);
-  test_sh(".000000000123", 25, "1230000000000000", 0);
-  test_sh(".000000000123", 26, "12300000000000000", 0);
-  test_sh(".000000000123", 27, "123000000000000000", 0);
-  test_sh(".000000000123", 28, "0.000000000123", 2);
-  test_sh("123456789.987654321", -1, "12345678.998765432", 1);
-  test_sh("123456789.987654321", -2, "1234567.899876543", 1);
-  test_sh("123456789.987654321", -8, "1.234567900", 1);
-  test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
-  test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
-  test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
-  test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
-  test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
-  test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
-  test_sh("123456789.987654321", -27, "0", 1);
-  test_sh("123456789.987654321", 1, "1234567900", 1);
-  test_sh("123456789.987654321", 2, "12345678999", 1);
-  test_sh("123456789.987654321", 4, "1234567899877", 1);
-  test_sh("123456789.987654321", 8, "12345678998765432", 1);
-  test_sh("123456789.987654321", 9, "123456789987654321", 0);
-  test_sh("123456789.987654321", 10, "123456789.987654321", 2);
-  test_sh("123456789.987654321", 0, "123456789.987654321", 0);
-  a.len= sizeof(buf1)/sizeof(dec1);
-
-  printf("==== decimal_actual_fraction ====\n");
-  test_fr("1.123456789000000000", "1.123456789");
-  test_fr("1.12345678000000000", "1.12345678");
-  test_fr("1.1234567000000000", "1.1234567");
-  test_fr("1.123456000000000", "1.123456");
-  test_fr("1.12345000000000", "1.12345");
-  test_fr("1.1234000000000", "1.1234");
-  test_fr("1.123000000000", "1.123");
-  test_fr("1.12000000000", "1.12");
-  test_fr("1.1000000000", "1.1");
-  test_fr("1.000000000", "1");
-  test_fr("1.0", "1");
-  test_fr("10000000000000000000.0", "10000000000000000000");
-
-  return 0;
-}
+/*
+  The main() program has been converted into a unit test.
+ */
 #endif

=== modified file 'unittest/gunit/CMakeLists.txt'
--- a/unittest/gunit/CMakeLists.txt	2011-08-12 07:18:41 +0000
+++ b/unittest/gunit/CMakeLists.txt	2011-08-26 07:06:35 +0000
@@ -207,6 +207,7 @@ SET(TESTS
   bounded_queue
   bounds_checked_array
   dbug
+  decimal
   dynarray
   mdl
   mdl_mytap

=== added file 'unittest/gunit/decimal-t.cc'
--- a/unittest/gunit/decimal-t.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/decimal-t.cc	2011-08-26 07:06:35 +0000
@@ -0,0 +1,866 @@
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA */
+
+/*
+  NOTE: This is a more-or-less direct port of the main() program
+  in strings/decimal.c to a Google Test.
+ */
+
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include <my_global.h>
+#include <m_string.h>
+
+extern "C" {
+#include <decimal.h>
+int decimal_shift(decimal_t *dec, int shift);
+}
+
+
+namespace {
+
+#define DIG_PER_DEC1 9
+#define DIG_BASE     1000000000
+#define ROUND_UP(X)  (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
+typedef decimal_digit_t dec1;
+
+int full= 0;
+decimal_t a, b, c;
+decimal_digit_t buf1[25], buf2[25], buf3[25];
+
+void dump_decimal(decimal_t *d)
+{
+  int i;
+  printf("/* intg=%d, frac=%d, sign=%d, buf[]={", d->intg, d->frac, d->sign);
+  for (i=0; i < ROUND_UP(d->frac)+ROUND_UP(d->intg)-1; i++)
+    printf("%09d, ", d->buf[i]);
+  printf("%09d} */ ", d->buf[i]);
+}
+
+/*
+  The purpose of all these define wrappers is to get a "call stack"
+  whenever some EXPECT_XX generates a failure. A sample error message:
+
+  # .../unittest/gunit/decimal-t.cc:134: FailureValue of: s
+  #   Actual: "0"
+  # Expected: orig
+  # Which is: "1000000000"
+  #  arguments were: '999999999', -9, HALF_UP
+  # Google Test trace:
+  # .../unittest/gunit/decimal-t.cc:387: 
+  # .../unittest/gunit/decimal-t.cc:686: 
+ */
+
+#define check_result_code(p1, p2) \
+  { SCOPED_TRACE(""); do_check_result_code(p1, p2); }
+
+#define print_decimal(p1, p2, p3, p4, p5) \
+  { SCOPED_TRACE(""); do_print_decimal(p1, p2, p3, p4, p5); }
+
+#define test_s2d(p1, p2, p3) \
+  { SCOPED_TRACE(""); do_test_s2d(p1, p2, p3); }
+
+#define test_d2f(p1, p2) \
+  { SCOPED_TRACE(""); do_test_d2f(p1, p2); }
+
+#define test_d2b2d(p1, p2, p3, p4, p5) \
+  { SCOPED_TRACE(""); do_test_d2b2d(p1, p2, p3, p4, p5); }
+
+#define test_f2d(p1, p2) \
+  { SCOPED_TRACE(""); do_test_f2d(p1, p2); }
+
+#define test_ull2d(p1, p2, p3) \
+  { SCOPED_TRACE(""); do_test_ull2d(p1, p2, p3); }
+
+#define test_ll2d(p1, p2, p3) \
+  { SCOPED_TRACE(""); do_test_ll2d(p1, p2, p3); }
+
+#define test_d2ull(p1, p2, p3) \
+  { SCOPED_TRACE(""); do_test_d2ull(p1, p2, p3); }
+
+#define test_d2ll(p1, p2, p3) \
+  { SCOPED_TRACE(""); do_test_d2ll(p1, p2, p3); }
+
+#define test_da(p1, p2, p3, p4) \
+  { SCOPED_TRACE(""); do_test_da(p1, p2, p3, p4); }
+
+#define test_ds(p1, p2, p3, p4) \
+  { SCOPED_TRACE(""); do_test_ds(p1, p2, p3, p4); }
+
+#define test_dc(p1, p2, p3) \
+  { SCOPED_TRACE(""); do_test_dc(p1, p2, p3); }
+
+#define test_dm(p1, p2, p3, p4) \
+  { SCOPED_TRACE(""); do_test_dm(p1, p2, p3, p4); }
+
+#define test_dv(p1, p2, p3, p4) \
+  { SCOPED_TRACE(""); do_test_dv(p1, p2, p3, p4); }
+
+#define test_md(p1, p2, p3, p4) \
+  { SCOPED_TRACE(""); do_test_md(p1, p2, p3, p4); }
+
+#define test_ro(p1, p2, p3, p4, p5) \
+  { SCOPED_TRACE(""); do_test_ro(p1, p2, p3, p4, p5); }
+
+#define test_mx(p1, p2, p3) \
+  { SCOPED_TRACE(""); do_test_mx(p1, p2, p3); }
+
+#define test_pr(p1, p2, p3, p4, p5, p6) \
+  { SCOPED_TRACE(""); do_test_pr(p1, p2, p3, p4, p5, p6); }
+
+#define test_sh(p1, p2, p3, p4) \
+  { SCOPED_TRACE(""); do_test_sh(p1, p2, p3, p4); }
+
+#define test_fr(p1, p2) \
+  { SCOPED_TRACE(""); do_test_fr(p1, p2); }
+
+
+void do_check_result_code(int actual, int want)
+{
+  EXPECT_EQ(want, actual);
+}
+
+void do_print_decimal(decimal_t *d, const char *orig, int actual, int want,
+                      const char *msg)
+{
+  char s[100];
+  int slen=sizeof(s);
+
+  if (full) dump_decimal(d);
+  decimal2string(d, s, &slen, 0, 0, 0);
+  check_result_code(actual, want);
+  if (orig)
+  {
+    EXPECT_STREQ(orig, s) << " arguments were: " << msg;
+  }
+}
+
+void test_d2s()
+{
+  char s[100];
+  int slen, res;
+
+  /***********************************/
+  printf("==== decimal2string ====\n");
+  a.buf[0]=12345; a.intg=5; a.frac=0; a.sign=0;
+  slen=sizeof(s);
+  res=decimal2string(&a, s, &slen, 0, 0, 0);
+  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
+
+  a.buf[1]=987000000; a.frac=3;
+  slen=sizeof(s);
+  res=decimal2string(&a, s, &slen, 0, 0, 0);
+  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
+
+  a.sign=1;
+  slen=sizeof(s);
+  res=decimal2string(&a, s, &slen, 0, 0, 0);
+  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
+
+  slen=8;
+  res=decimal2string(&a, s, &slen, 0, 0, 0);
+  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
+
+  slen=5;
+  res=decimal2string(&a, s, &slen, 0, 0, 0);
+  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
+
+  a.buf[0]=987000000; a.frac=3; a.intg=0;
+  slen=sizeof(s);
+  res=decimal2string(&a, s, &slen, 0, 0, 0);
+  dump_decimal(&a); printf("  -->  res=%d str='%s' len=%d\n", res, s, slen);
+}
+
+void do_test_s2d(const char *s, const char *orig, int ex)
+{
+  char s1[100], *end;
+  int res;
+  sprintf(s1, "'%s'", s);
+  end= strend(s);
+  res= string2decimal(s, &a, &end);
+  print_decimal(&a, orig, res, ex, s1);
+}
+
+void do_test_d2f(const char *s, int ex)
+{
+  char s1[100], *end;
+  double x;
+  int res;
+
+  sprintf(s1, "'%s'", s);
+  end= strend(s);
+  string2decimal(s, &a, &end);
+  res=decimal2double(&a, &x);
+  if (full) dump_decimal(&a);
+  check_result_code(res, ex);
+}
+
+void do_test_d2b2d(const char *str, int p, int s, const char *orig, int ex)
+{
+  char s1[100];
+  char s2[100];
+  uchar buf[100];
+  char *end;
+  int res, i, size=decimal_bin_size(p, s);
+
+  sprintf(s1, "'%s'", str);
+  end= strend(str);
+  string2decimal(str, &a, &end);
+  res=decimal2bin(&a, buf, p, s);
+  sprintf(s2, "%-31s {%2d, %2d} => res=%d size=%-2d ", s1, p, s, res, size);
+  if (full)
+  {
+    printf("0x");
+    for (i=0; i < size; i++)
+      printf("%02x", ((uchar *)buf)[i]);
+  }
+  res=bin2decimal(buf, &a, p, s);
+  print_decimal(&a, orig, res, ex, s2);
+}
+
+void do_test_f2d(double from, int ex)
+{
+  int res;
+  char s1[100];
+
+  res=double2decimal(from, &a);
+  sprintf(s1, "%-40.*f => res=%d    ", DBL_DIG-2, from, res);
+  print_decimal(&a, 0, res, ex, s1);
+}
+
+void do_test_ull2d(ulonglong from, const char *orig, int ex)
+{
+  char s[100];
+  char s1[100];
+  int res;
+
+  res=ulonglong2decimal(from, &a);
+  longlong10_to_str(from,s,10);
+  sprintf(s1, "%-40s => res=%d    ", s, res);
+  print_decimal(&a, orig, res, ex, s1);
+}
+
+void do_test_ll2d(longlong from, const char *orig, int ex)
+{
+  char s[100];
+  char s1[100];
+  int res;
+
+  res=longlong2decimal(from, &a);
+  longlong10_to_str(from,s,-10);
+  sprintf(s1, "%-40s => res=%d    ", s, res);
+  print_decimal(&a, orig, res, ex, s1);
+}
+
+void do_test_d2ull(const char *s, const char *orig, int ex)
+{
+  char s1[100], *end;
+  char s2[100];
+  ulonglong x;
+  int res;
+
+  end= strend(s);
+  string2decimal(s, &a, &end);
+  res=decimal2ulonglong(&a, &x);
+  if (full) dump_decimal(&a);
+  longlong10_to_str(x,s1,10);
+  sprintf(s2, "%-40s => res=%d    %s\n", s, res, s1);
+  check_result_code(res, ex);
+  if (orig)
+  {
+    EXPECT_STREQ(orig, s1) << " arguments were: " << s2;
+  }
+}
+
+void do_test_d2ll(const char *s, const char *orig, int ex)
+{
+  char s1[100], *end;
+  char s2[100];
+  longlong x;
+  int res;
+
+  end= strend(s);
+  string2decimal(s, &a, &end);
+  res=decimal2longlong(&a, &x);
+  if (full) dump_decimal(&a);
+  longlong10_to_str(x,s1,-10);
+  sprintf(s2, "%-40s => res=%d    %s\n", s, res, s1);
+  check_result_code(res, ex);
+  if (orig)
+  {
+    EXPECT_STREQ(orig, s1) << " arguments were: " << s2;
+  }
+}
+
+void do_test_da(const char *s1, const char *s2, const char *orig, int ex)
+{
+  char s[100], *end;
+  int res;
+  sprintf(s, "'%s' + '%s'", s1, s2);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  end= strend(s2);
+  string2decimal(s2, &b, &end);
+  res=decimal_add(&a, &b, &c);
+  print_decimal(&c, orig, res, ex, s);
+}
+
+void do_test_ds(const char *s1, const char *s2, const char *orig, int ex)
+{
+  char s[100], *end;
+  int res;
+  sprintf(s, "'%s' - '%s'", s1, s2);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  end= strend(s2);
+  string2decimal(s2, &b, &end);
+  res=decimal_sub(&a, &b, &c);
+  print_decimal(&c, orig, res, ex, s);
+}
+
+void do_test_dc(const char *s1, const char *s2, int orig)
+{
+  char s[100], *end;
+  int res;
+  sprintf(s, "'%s' <=> '%s'", s1, s2);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  end= strend(s2);
+  string2decimal(s2, &b, &end);
+  res=decimal_cmp(&a, &b);
+  EXPECT_EQ(orig, res) << " arguments were: " << s;
+}
+
+void do_test_dm(const char *s1, const char *s2, const char *orig, int ex)
+{
+  char s[100], *end;
+  int res;
+  sprintf(s, "'%s' * '%s'", s1, s2);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  end= strend(s2);
+  string2decimal(s2, &b, &end);
+  res=decimal_mul(&a, &b, &c);
+  print_decimal(&c, orig, res, ex, s);
+}
+
+void do_test_dv(const char *s1, const char *s2, const char *orig, int ex)
+{
+  char s[100], *end;
+  int res;
+  sprintf(s, "'%s' / '%s'", s1, s2);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  end= strend(s2);
+  string2decimal(s2, &b, &end);
+  res=decimal_div(&a, &b, &c, 5);
+  check_result_code(res, ex);
+  if (res != E_DEC_DIV_ZERO)
+    print_decimal(&c, orig, res, ex, s);
+}
+
+void do_test_md(const char *s1, const char *s2, const char *orig, int ex)
+{
+  char s[100], *end;
+  int res;
+  sprintf(s, "'%s' %% '%s'", s1, s2);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  end= strend(s2);
+  string2decimal(s2, &b, &end);
+  res=decimal_mod(&a, &b, &c);
+  check_result_code(res, ex);
+  if (res != E_DEC_DIV_ZERO)
+    print_decimal(&c, orig, res, ex, s);
+}
+
+const char *round_mode[]=
+{"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
+
+void do_test_ro(const char *s1, int n, decimal_round_mode mode,
+                const char *orig, int ex)
+{
+  char s[100], *end;
+  int res;
+  sprintf(s, "'%s', %d, %s", s1, n, round_mode[mode]);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  res=decimal_round(&a, &b, n, mode);
+  print_decimal(&b, orig, res, ex, s);
+}
+
+
+void do_test_mx(int precision, int frac, const char *orig)
+{
+  char s[100];
+  sprintf(s, "%d, %d", precision, frac);
+  max_decimal(precision, frac, &a);
+  print_decimal(&a, orig, 0, 0, s);
+}
+
+
+void do_test_pr(const char *s1, int prec, int dec, char filler,
+                const char *orig, int ex)
+{
+  char s[100], *end;
+  char s2[100];
+  int slen= sizeof(s2);
+  int res;
+
+  sprintf(s, filler ? "'%s', %d, %d, '%c'" : "'%s', %d, %d, '\\0'",
+          s1, prec, dec, filler);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  res= decimal2string(&a, s2, &slen, prec, dec, filler);
+  check_result_code(res, ex);
+  if (orig)
+  {
+    EXPECT_STREQ(orig, s2) << " arguments were: " << s;
+  }
+}
+
+
+void do_test_sh(const char *s1, int shift, const char *orig, int ex)
+{
+  char s[100], *end;
+  int res;
+  sprintf(s, "'%s' %s %d", s1, ((shift < 0) ? ">>" : "<<"), abs(shift));
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  res= decimal_shift(&a, shift);
+  print_decimal(&a, orig, res, ex, s);
+}
+
+
+void do_test_fr(const char *s1, const char *orig)
+{
+  char s[100], *end;
+  sprintf(s, "'%s'", s1);
+  end= strend(s1);
+  string2decimal(s1, &a, &end);
+  a.frac= decimal_actual_fraction(&a);
+  print_decimal(&a, orig, 0, 0, s);
+}
+
+
+class DecimalTest : public ::testing::Test
+{
+protected:
+  virtual void SetUp()
+  {
+    a.buf= buf1;
+    a.len= sizeof(buf1)/sizeof(dec1);
+    b.buf= buf2;
+    b.len= sizeof(buf2)/sizeof(dec1);
+    c.buf= buf3;
+    c.len= sizeof(buf3)/sizeof(dec1);
+  }
+};
+
+
+TEST_F(DecimalTest, String2Decimal)
+{
+  test_s2d("12345", "12345", 0);
+  test_s2d("12345.", "12345", 0);
+  test_s2d("123.45", "123.45", 0);
+  test_s2d("-123.45", "-123.45", 0);
+  test_s2d(".00012345000098765", "0.00012345000098765", 0);
+  test_s2d(".12345000098765", "0.12345000098765", 0);
+  test_s2d("-.000000012345000098765", "-0.000000012345000098765", 0);
+  test_s2d("1234500009876.5", "1234500009876.5", 0);
+  a.len=1;
+  test_s2d("123450000098765", "98765", 2);
+  test_s2d("123450.000098765", "123450", 1);
+  a.len=sizeof(buf1)/sizeof(dec1);
+  test_s2d("123E5", "12300000", 0);
+  test_s2d("123E-2", "1.23", 0);
+}
+
+
+TEST_F(DecimalTest, Decimal2Double)
+{
+  test_d2f("12345", 0);
+  test_d2f("123.45", 0);
+  test_d2f("-123.45", 0);
+  test_d2f("0.00012345000098765", 0);
+  test_d2f("1234500009876.5", 0);
+}
+
+
+TEST_F(DecimalTest, Double2Decimal)
+{
+  test_f2d(12345, 0);
+  test_f2d(1.0/3, 0);
+  test_f2d(-123.45, 0);
+  test_f2d(0.00012345000098765, 0);
+  test_f2d(1234500009876.5, 0);
+}
+
+
+TEST_F(DecimalTest, Ulonglong2Decimal)
+{
+  test_ull2d(ULL(12345), "12345", 0);
+  test_ull2d(ULL(0), "0", 0);
+  test_ull2d(ULL(18446744073709551615), "18446744073709551615", 0);
+}
+
+
+TEST_F(DecimalTest, Decimal2Ulonglong)
+{
+  test_d2ull("12345", "12345", 0);
+  test_d2ull("0", "0", 0);
+  /* ULLONG_MAX = 18446744073709551615ULL */
+  test_d2ull("18446744073709551615", "18446744073709551615", 0);
+  test_d2ull("18446744073709551616", "18446744073709551615", 2);
+  test_d2ull("-1", "0", 2);
+  test_d2ull("1.23", "1", 1);
+  test_d2ull("9999999999999999999999999.000", "18446744073709551615", 2);
+}
+
+
+TEST_F(DecimalTest, Longlong2Decimal)
+{
+  test_ll2d(LL(-12345), "-12345", 0);
+  test_ll2d(LL(-1), "-1", 0);
+  test_ll2d(LL(-9223372036854775807), "-9223372036854775807", 0);
+  test_ll2d(ULL(9223372036854775808), "-9223372036854775808", 0);
+}
+
+
+TEST_F(DecimalTest, Decimal2Longlong)
+{
+  /* LLONG_MAX = 9223372036854775807LL */
+  test_d2ll("18446744073709551615", "9223372036854775807", 2);
+  test_d2ll("-1", "-1", 0);
+  test_d2ll("-1.23", "-1", 1);
+  test_d2ll("-9223372036854775807", "-9223372036854775807", 0);
+  test_d2ll("-9223372036854775808", "-9223372036854775808", 0);
+  test_d2ll("9223372036854775808", "9223372036854775807", 2);
+}
+
+
+TEST_F(DecimalTest, DoAdd)
+{
+  test_da(".00012345000098765" ,"123.45", "123.45012345000098765", 0);
+  test_da(".1" ,".45", "0.55", 0);
+  test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765", 0);
+  test_da("9999909999999.5" ,".555", "9999910000000.055", 0);
+  test_da("99999999" ,"1", "100000000", 0);
+  test_da("989999999" ,"1", "990000000", 0);
+  test_da("999999999" ,"1", "1000000000", 0);
+  test_da("12345" ,"123.45", "12468.45", 0);
+  test_da("-12345" ,"-123.45", "-12468.45", 0);
+  test_ds("-12345" ,"123.45", "-12468.45", 0);
+  test_ds("12345" ,"-123.45", "12468.45", 0);
+}
+
+
+TEST_F(DecimalTest, DoSub)
+{
+  test_ds(".00012345000098765", "123.45","-123.44987654999901235", 0);
+  test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235", 0);
+  test_ds("9999900000000.5", ".555","9999899999999.945", 0);
+  test_ds("1111.5551", "1111.555","0.0001", 0);
+  test_ds(".555", ".555","0", 0);
+  test_ds("10000000", "1","9999999", 0);
+  test_ds("1000001000", ".1","1000000999.9", 0);
+  test_ds("1000000000", ".1","999999999.9", 0);
+  test_ds("12345", "123.45","12221.55", 0);
+  test_ds("-12345", "-123.45","-12221.55", 0);
+  test_da("-12345", "123.45","-12221.55", 0);
+  test_da("12345", "-123.45","12221.55", 0);
+  test_ds("123.45", "12345","-12221.55", 0);
+  test_ds("-123.45", "-12345","12221.55", 0);
+  test_da("123.45", "-12345","-12221.55", 0);
+  test_da("-123.45", "12345","12221.55", 0);
+  test_da("5", "-6.0","-1.0", 0);
+}
+
+
+TEST_F(DecimalTest, DecimalMul)
+{
+  test_dm("12", "10","120", 0);
+  test_dm("-123.456", "98765.4321","-12193185.1853376", 0);
+  test_dm("-123456000000", "98765432100000","-12193185185337600000000000", 0);
+  test_dm("123456", "987654321","121931851853376", 0);
+  test_dm("123456", "9876543210","1219318518533760", 0);
+  test_dm("123", "0.01","1.23", 0);
+  test_dm("123", "0","0", 0);
+}
+
+
+TEST_F(DecimalTest, DecimalDiv)
+{
+  test_dv("120", "10","12.000000000", 0);
+  test_dv("123", "0.01","12300.000000000", 0);
+  test_dv("120", "100000000000.00000","0.000000001200000000", 0);
+  test_dv("123", "0","", 4);
+  test_dv("0", "0", "", 4);
+  test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
+  test_dv("121931851853376", "987654321","123456.000000000", 0);
+  test_dv("0", "987","0", 0);
+  test_dv("1", "3","0.333333333", 0);
+  test_dv("1.000000000000", "3","0.333333333333333333", 0);
+  test_dv("1", "1","1.000000000", 0);
+  test_dv("0.0123456789012345678912345", "9999999999","0.000000000001234567890246913578148141", 0);
+  test_dv("10.333000000", "12.34500","0.837019036046982584042122316", 0);
+  test_dv("10.000000000060", "2","5.000000000030000000", 0);
+}
+
+
+TEST_F(DecimalTest, DecimalMod)
+{
+  test_md("234","10","4", 0);
+  test_md("234.567","10.555","2.357", 0);
+  test_md("-234.567","10.555","-2.357", 0);
+  test_md("234.567","-10.555","2.357", 0);
+  c.buf[1]=0x3ABECA;
+  test_md("99999999999999999999999999999999999999","3","0", 0);
+  if (c.buf[1] != 0x3ABECA)
+  {
+    ADD_FAILURE() << "overflow " << c.buf[1];
+  }
+}
+
+
+TEST_F(DecimalTest, Decimal2BinBin2Decimal)
+{
+  test_d2b2d("-10.55", 4, 2,"-10.55", 0);
+  test_d2b2d("0.0123456789012345678912345", 30, 25,"0.0123456789012345678912345", 0);
+  test_d2b2d("12345", 5, 0,"12345", 0);
+  test_d2b2d("12345", 10, 3,"12345.000", 0);
+  test_d2b2d("123.45", 10, 3,"123.450", 0);
+  test_d2b2d("-123.45", 20, 10,"-123.4500000000", 0);
+  test_d2b2d(".00012345000098765", 15, 14,"0.00012345000098", 0);
+  test_d2b2d(".00012345000098765", 22, 20,"0.00012345000098765000", 0);
+  test_d2b2d(".12345000098765", 30, 20,"0.12345000098765000000", 0);
+  test_d2b2d("-.000000012345000098765", 30, 20,"-0.00000001234500009876", 0);
+  test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000", 0);
+  test_d2b2d("111111111.11", 10, 2,"11111111.11", 0);
+  test_d2b2d("000000000.01", 7, 3,"0.010", 0);
+  test_d2b2d("123.4", 10, 2, "123.40", 0);
+}
+
+
+TEST_F(DecimalTest, DecimalCmp)
+{
+  test_dc("12","13",-1);
+  test_dc("13","12",1);
+  test_dc("-10","10",-1);
+  test_dc("10","-10",1);
+  test_dc("-12","-13",1);
+  test_dc("0","12",-1);
+  test_dc("-10","0",-1);
+  test_dc("4","4",0);
+}
+
+
+TEST_F(DecimalTest, DecimalRound)
+{
+  test_ro("5678.123451",-4,TRUNCATE,"0", 0);
+  test_ro("5678.123451",-3,TRUNCATE,"5000", 0);
+  test_ro("5678.123451",-2,TRUNCATE,"5600", 0);
+  test_ro("5678.123451",-1,TRUNCATE,"5670", 0);
+  test_ro("5678.123451",0,TRUNCATE,"5678", 0);
+  test_ro("5678.123451",1,TRUNCATE,"5678.1", 0);
+  test_ro("5678.123451",2,TRUNCATE,"5678.12", 0);
+  test_ro("5678.123451",3,TRUNCATE,"5678.123", 0);
+  test_ro("5678.123451",4,TRUNCATE,"5678.1234", 0);
+  test_ro("5678.123451",5,TRUNCATE,"5678.12345", 0);
+  test_ro("5678.123451",6,TRUNCATE,"5678.123451", 0);
+  test_ro("-5678.123451",-4,TRUNCATE,"0", 0);
+  memset(buf2, 33, sizeof(buf2));
+  test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000", 0);
+  test_ro("15.1",0,HALF_UP,"15", 0);
+  test_ro("15.5",0,HALF_UP,"16", 0);
+  test_ro("15.9",0,HALF_UP,"16", 0);
+  test_ro("-15.1",0,HALF_UP,"-15", 0);
+  test_ro("-15.5",0,HALF_UP,"-16", 0);
+  test_ro("-15.9",0,HALF_UP,"-16", 0);
+  test_ro("15.1",1,HALF_UP,"15.1", 0);
+  test_ro("-15.1",1,HALF_UP,"-15.1", 0);
+  test_ro("15.17",1,HALF_UP,"15.2", 0);
+  test_ro("15.4",-1,HALF_UP,"20", 0);
+  test_ro("-15.4",-1,HALF_UP,"-20", 0);
+  test_ro("5.4",-1,HALF_UP,"10", 0);
+  test_ro(".999", 0, HALF_UP, "1", 0);
+  memset(buf2, 33, sizeof(buf2));
+  test_ro("999999999", -9, HALF_UP, "1000000000", 0);
+  test_ro("15.1",0,HALF_EVEN,"15", 0);
+  test_ro("15.5",0,HALF_EVEN,"16", 0);
+  test_ro("14.5",0,HALF_EVEN,"14", 0);
+  test_ro("15.9",0,HALF_EVEN,"16", 0);
+  test_ro("15.1",0,CEILING,"16", 0);
+  test_ro("-15.1",0,CEILING,"-15", 0);
+  test_ro("15.1",0,FLOOR,"15", 0);
+  test_ro("-15.1",0,FLOOR,"-16", 0);
+  test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0);
+  test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0);
+
+  b.buf[0]=DIG_BASE+1;
+  b.buf++;
+  test_ro(".3", 0, HALF_UP, "0", 0);
+  b.buf--;
+  if (b.buf[0] != DIG_BASE+1)
+  {
+    ADD_FAILURE() << "underflow " << b.buf[0];
+  }
+}
+
+
+TEST_F(DecimalTest, MaxDecimal)
+{
+  test_mx(1,1,"0.9");
+  test_mx(1,0,"9");
+  test_mx(2,1,"9.9");
+  test_mx(4,2,"99.99");
+  test_mx(6,3,"999.999");
+  test_mx(8,4,"9999.9999");
+  test_mx(10,5,"99999.99999");
+  test_mx(12,6,"999999.999999");
+  test_mx(14,7,"9999999.9999999");
+  test_mx(16,8,"99999999.99999999");
+  test_mx(18,9,"999999999.999999999");
+  test_mx(20,10,"9999999999.9999999999");
+  test_mx(20,20,"0.99999999999999999999");
+  test_mx(20,0,"99999999999999999999");
+  test_mx(40,20,"99999999999999999999.99999999999999999999");
+}
+
+
+TEST_F(DecimalTest, Decimal2String)
+{
+  test_pr("123.123", 0, 0, 0, "123.123", 0);
+  /* For fixed precision, we no longer count the '.' here. */
+  test_pr("123.123", 6, 3, '0', "123.123", 0);
+  test_pr("123.123", 8, 3, '0', "00123.123", 0);
+  test_pr("123.123", 8, 4, '0', "0123.1230", 0);
+  test_pr("123.123", 8, 5, '0', "123.12300", 0);
+  test_pr("123.123", 8, 2, '0', "000123.12", 1);
+  test_pr("123.123", 8, 6, '0', "23.123000", 2);
+}
+
+
+TEST_F(DecimalTest, DecimalShift)
+{
+  test_sh("123.123", 1, "1231.23", 0);
+  test_sh("123457189.123123456789000", 1, "1234571891.23123456789", 0);
+  test_sh("123457189.123123456789000", 4, "1234571891231.23456789", 0);
+  test_sh("123457189.123123456789000", 8, "12345718912312345.6789", 0);
+  test_sh("123457189.123123456789000", 9, "123457189123123456.789", 0);
+  test_sh("123457189.123123456789000", 10, "1234571891231234567.89", 0);
+  test_sh("123457189.123123456789000", 17, "12345718912312345678900000", 0);
+  test_sh("123457189.123123456789000", 18, "123457189123123456789000000", 0);
+  test_sh("123457189.123123456789000", 19, "1234571891231234567890000000", 0);
+  test_sh("123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
+  test_sh("123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
+  test_sh("123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
+  test_sh("000000000000000000000000123457189.123123456789000", 26, "12345718912312345678900000000000000", 0);
+  test_sh("00000000123457189.123123456789000", 27, "123457189123123456789000000000000000", 0);
+  test_sh("00000000000000000123457189.123123456789000", 28, "1234571891231234567890000000000000000", 0);
+  test_sh("123", 1, "1230", 0);
+  test_sh("123", 10, "1230000000000", 0);
+  test_sh(".123", 1, "1.23", 0);
+  test_sh(".123", 10, "1230000000", 0);
+  test_sh(".123", 14, "12300000000000", 0);
+  test_sh("000.000", 1000, "0", 0);
+  test_sh("000.", 1000, "0", 0);
+  test_sh(".000", 1000, "0", 0);
+  test_sh("1", 1000, "1", 2);
+  test_sh("123.123", -1, "12.3123", 0);
+  test_sh("123987654321.123456789000", -1, "12398765432.1123456789", 0);
+  test_sh("123987654321.123456789000", -2, "1239876543.21123456789", 0);
+  test_sh("123987654321.123456789000", -3, "123987654.321123456789", 0);
+  test_sh("123987654321.123456789000", -8, "1239.87654321123456789", 0);
+  test_sh("123987654321.123456789000", -9, "123.987654321123456789", 0);
+  test_sh("123987654321.123456789000", -10, "12.3987654321123456789", 0);
+  test_sh("123987654321.123456789000", -11, "1.23987654321123456789", 0);
+  test_sh("123987654321.123456789000", -12, "0.123987654321123456789", 0);
+  test_sh("123987654321.123456789000", -13, "0.0123987654321123456789", 0);
+  test_sh("123987654321.123456789000", -14, "0.00123987654321123456789", 0);
+  test_sh("00000087654321.123456789000", -14, "0.00000087654321123456789", 0);
+  a.len= 2;
+  test_sh("123.123", -2, "1.23123", 0);
+  test_sh("123.123", -3, "0.123123", 0);
+  test_sh("123.123", -6, "0.000123123", 0);
+  test_sh("123.123", -7, "0.0000123123", 0);
+  test_sh("123.123", -15, "0.000000000000123123", 0);
+  test_sh("123.123", -16, "0.000000000000012312", 1);
+  test_sh("123.123", -17, "0.000000000000001231", 1);
+  test_sh("123.123", -18, "0.000000000000000123", 1);
+  test_sh("123.123", -19, "0.000000000000000012", 1);
+  test_sh("123.123", -20, "0.000000000000000001", 1);
+  test_sh("123.123", -21, "0", 1);
+  test_sh(".000000000123", -1, "0.0000000000123", 0);
+  test_sh(".000000000123", -6, "0.000000000000000123", 0);
+  test_sh(".000000000123", -7, "0.000000000000000012", 1);
+  test_sh(".000000000123", -8, "0.000000000000000001", 1);
+  test_sh(".000000000123", -9, "0", 1);
+  test_sh(".000000000123", 1, "0.00000000123", 0);
+  test_sh(".000000000123", 8, "0.0123", 0);
+  test_sh(".000000000123", 9, "0.123", 0);
+  test_sh(".000000000123", 10, "1.23", 0);
+  test_sh(".000000000123", 17, "12300000", 0);
+  test_sh(".000000000123", 18, "123000000", 0);
+  test_sh(".000000000123", 19, "1230000000", 0);
+  test_sh(".000000000123", 20, "12300000000", 0);
+  test_sh(".000000000123", 21, "123000000000", 0);
+  test_sh(".000000000123", 22, "1230000000000", 0);
+  test_sh(".000000000123", 23, "12300000000000", 0);
+  test_sh(".000000000123", 24, "123000000000000", 0);
+  test_sh(".000000000123", 25, "1230000000000000", 0);
+  test_sh(".000000000123", 26, "12300000000000000", 0);
+  test_sh(".000000000123", 27, "123000000000000000", 0);
+  test_sh(".000000000123", 28, "0.000000000123", 2);
+  test_sh("123456789.987654321", -1, "12345678.998765432", 1);
+  test_sh("123456789.987654321", -2, "1234567.899876543", 1);
+  test_sh("123456789.987654321", -8, "1.234567900", 1);
+  test_sh("123456789.987654321", -9, "0.123456789987654321", 0);
+  test_sh("123456789.987654321", -10, "0.012345678998765432", 1);
+  test_sh("123456789.987654321", -17, "0.000000001234567900", 1);
+  test_sh("123456789.987654321", -18, "0.000000000123456790", 1);
+  test_sh("123456789.987654321", -19, "0.000000000012345679", 1);
+  test_sh("123456789.987654321", -26, "0.000000000000000001", 1);
+  test_sh("123456789.987654321", -27, "0", 1);
+  test_sh("123456789.987654321", 1, "1234567900", 1);
+  test_sh("123456789.987654321", 2, "12345678999", 1);
+  test_sh("123456789.987654321", 4, "1234567899877", 1);
+  test_sh("123456789.987654321", 8, "12345678998765432", 1);
+  test_sh("123456789.987654321", 9, "123456789987654321", 0);
+  test_sh("123456789.987654321", 10, "123456789.987654321", 2);
+  test_sh("123456789.987654321", 0, "123456789.987654321", 0);
+  a.len= sizeof(buf1)/sizeof(dec1);
+}
+
+
+TEST_F(DecimalTest, DecimalActualFraction)
+{
+  test_fr("1.123456789000000000", "1.123456789");
+  test_fr("1.12345678000000000", "1.12345678");
+  test_fr("1.1234567000000000", "1.1234567");
+  test_fr("1.123456000000000", "1.123456");
+  test_fr("1.12345000000000", "1.12345");
+  test_fr("1.1234000000000", "1.1234");
+  test_fr("1.123000000000", "1.123");
+  test_fr("1.12000000000", "1.12");
+  test_fr("1.1000000000", "1.1");
+  test_fr("1.000000000", "1");
+  test_fr("1.0", "1");
+  test_fr("10000000000000000000.0", "10000000000000000000");
+}
+
+
+}

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (tor.didriksen:3406 to 3407) Bug#12744991Tor Didriksen26 Aug