|
16 | 16 | #include "my_config.h" |
17 | 17 | #include <gtest/gtest.h> |
18 | 18 |
|
| 19 | +#include "test_utils.h" |
| 20 | + |
19 | 21 | #include <my_decimal.h> |
20 | 22 |
|
21 | 23 | namespace { |
22 | 24 |
|
| 25 | +using my_testing::Server_initializer; |
| 26 | +using my_testing::Mock_error_handler; |
| 27 | + |
23 | 28 | class DecimalTest : public ::testing::Test |
24 | 29 | { |
25 | 30 | protected: |
| 31 | + static void SetUpTestCase() |
| 32 | + { |
| 33 | + Server_initializer::SetUpTestCase(); |
| 34 | + } |
| 35 | + |
| 36 | + static void TearDownTestCase() |
| 37 | + { |
| 38 | + Server_initializer::TearDownTestCase(); |
| 39 | + } |
| 40 | + |
| 41 | + virtual void SetUp() |
| 42 | + { |
| 43 | + initializer.SetUp(); |
| 44 | + } |
| 45 | + |
| 46 | + virtual void TearDown() |
| 47 | + { |
| 48 | + initializer.TearDown(); |
| 49 | + } |
| 50 | + |
| 51 | + THD *thd() { return initializer.thd(); } |
| 52 | + |
| 53 | + Server_initializer initializer; |
| 54 | + |
26 | 55 | my_decimal d1; |
27 | 56 | my_decimal d2; |
28 | 57 | }; |
29 | 58 |
|
| 59 | + |
30 | 60 | TEST_F(DecimalTest, CopyAndCompare) |
31 | 61 | { |
32 | 62 | ulonglong val= 42; |
@@ -70,4 +100,128 @@ TEST_F(DecimalTest, Swap) |
70 | 100 | EXPECT_EQ(0, my_decimal_cmp(&d1, &d2copy)); |
71 | 101 | } |
72 | 102 |
|
| 103 | + |
| 104 | + |
| 105 | +int chars_2_decimal(const char *chars, my_decimal *to) |
| 106 | +{ |
| 107 | + char *end= strend(chars); |
| 108 | + return string2decimal(chars, to, &end); |
| 109 | +} |
| 110 | + |
| 111 | + |
| 112 | +/* |
| 113 | + This is a simple iterative implementation based on addition and subtraction, |
| 114 | + for verifying the result of decimal_mod(). |
| 115 | +
|
| 116 | + decimal_mod() says: |
| 117 | + DESCRIPTION |
| 118 | + the modulus R in R = M mod N |
| 119 | + is defined as |
| 120 | +
|
| 121 | + 0 <= |R| < |M| |
| 122 | + sign R == sign M |
| 123 | + R = M - k*N, where k is integer |
| 124 | +
|
| 125 | + thus, there's no requirement for M or N to be integers |
| 126 | + */ |
| 127 | +int decimal_modulo(uint mask, |
| 128 | + my_decimal *res, |
| 129 | + const my_decimal *m, |
| 130 | + const my_decimal *n) |
| 131 | +{ |
| 132 | + my_decimal abs_m(*m); |
| 133 | + my_decimal abs_n(*n); |
| 134 | + abs_m.sign(false); |
| 135 | + abs_n.sign(false); |
| 136 | + |
| 137 | + my_decimal r; |
| 138 | + my_decimal k1(abs_n); |
| 139 | + my_decimal kn(decimal_zero); |
| 140 | + my_decimal next_r(abs_m); |
| 141 | + int ret; |
| 142 | + do |
| 143 | + { |
| 144 | + r= next_r; |
| 145 | + |
| 146 | + my_decimal res; |
| 147 | + if ((ret= my_decimal_add(E_DEC_FATAL_ERROR, &res, &k1, &kn)) != E_DEC_OK) |
| 148 | + { |
| 149 | + ADD_FAILURE(); |
| 150 | + return ret; |
| 151 | + } |
| 152 | + kn= res; |
| 153 | + |
| 154 | + if ((ret= my_decimal_sub(E_DEC_FATAL_ERROR, |
| 155 | + &next_r, &abs_m, &kn) != E_DEC_OK)) |
| 156 | + { |
| 157 | + ADD_FAILURE(); |
| 158 | + return ret; |
| 159 | + } |
| 160 | + } while (my_decimal_cmp(&next_r, &decimal_zero) >= 0); |
| 161 | + r.sign(m->sign()); |
| 162 | + *res= r; |
| 163 | + return 0; |
| 164 | +} |
| 165 | + |
| 166 | + |
| 167 | +struct Mod_data |
| 168 | +{ |
| 169 | + const char *a; |
| 170 | + const char *b; |
| 171 | + const char *result; |
| 172 | +}; |
| 173 | + |
| 174 | +Mod_data mod_test_input[]= |
| 175 | +{ |
| 176 | + { "234" , "10", "4" }, |
| 177 | + { "234.567" , "10.555", "2.357" }, |
| 178 | + { "-234.567", "10.555", "-2.357" }, |
| 179 | + { "234.567" , "-10.555", "2.357" }, |
| 180 | + { "-234.567", "-10.555", "-2.357" }, |
| 181 | + { "999" , "0.1", "0.0" }, |
| 182 | + { "999" , "0.7", "0.1" }, |
| 183 | + { "10" , "123", "10" }, |
| 184 | + { NULL, NULL, NULL} |
| 185 | +}; |
| 186 | + |
| 187 | + |
| 188 | +TEST_F(DecimalTest, Modulo) |
| 189 | +{ |
| 190 | + my_decimal expected_result; |
| 191 | + my_decimal xxx_result; |
| 192 | + my_decimal mod_result; |
| 193 | + char buff_x[DECIMAL_MAX_STR_LENGTH]; |
| 194 | + char buff_m[DECIMAL_MAX_STR_LENGTH]; |
| 195 | + |
| 196 | + for (Mod_data *pd= mod_test_input; pd->a; ++pd) |
| 197 | + { |
| 198 | + int bufsz_x= sizeof(buff_x); |
| 199 | + int bufsz_m= sizeof(buff_m); |
| 200 | + |
| 201 | + EXPECT_EQ(0, chars_2_decimal(pd->a, &d1)); |
| 202 | + EXPECT_EQ(0, chars_2_decimal(pd->b, &d2)); |
| 203 | + EXPECT_EQ(0, chars_2_decimal(pd->result, &expected_result)); |
| 204 | + |
| 205 | + EXPECT_EQ(0, my_decimal_mod(E_DEC_FATAL_ERROR, &mod_result, &d1, &d2)); |
| 206 | + EXPECT_EQ(0, decimal2string(&mod_result, buff_m, &bufsz_m, 0, 0, 0)); |
| 207 | + EXPECT_EQ(0, my_decimal_cmp(&expected_result, &mod_result)) |
| 208 | + << " a:" << pd->a |
| 209 | + << " b:" << pd->b |
| 210 | + << " expected:" << pd->result |
| 211 | + << " got mod:" << buff_m |
| 212 | + ; |
| 213 | + |
| 214 | + EXPECT_EQ(0, decimal_modulo(E_DEC_FATAL_ERROR, &xxx_result, &d1, &d2)); |
| 215 | + EXPECT_EQ(0, decimal2string(&xxx_result, buff_x, &bufsz_x, 0, 0, 0)); |
| 216 | + EXPECT_EQ(0, my_decimal_cmp(&expected_result, &xxx_result)) |
| 217 | + << " a:" << pd->a |
| 218 | + << " b:" << pd->b |
| 219 | + << " expected:" << pd->result |
| 220 | + << " got mod:" << buff_m |
| 221 | + << " got xxx:" << buff_x |
| 222 | + ; |
| 223 | + } |
| 224 | + |
| 225 | +} |
| 226 | + |
73 | 227 | } |
0 commit comments