YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/decimal-test.cc
Line
Count
Source
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include "yb/util/decimal.h"
15
#include "yb/util/result.h"
16
#include "yb/util/test_macros.h"
17
#include "yb/util/test_util.h"
18
19
namespace yb {
20
namespace util {
21
22
class DecimalTest : public YBTest {
23
 protected:
24
  // Note that the following test cases are only used for testing encodings. The other tests should
25
  // verify that Decimal representation is perfect, and only the conversion to the encoding and
26
  // its comparison need to be tested.
27
  const std::vector<std::string> test_cases = {
28
      // The purpose of these tests is to verify various aspects of comparisons for different cases.
29
      // The priority order for comparing two decimals is sign > exponent > mantissa. The mantissa
30
      // must be compared lexicographically while exponent must be compared in absolute value.
31
32
      // -2147483648 is the smallest signed int, so BigDecimal Encoding fails below this scale.
33
      "-9847.236776e+2147483654", // Note that the scale is -2147483648.
34
      "-9847.236780e+2147483653",
35
      // Testing numbers with close by digits to make sure comparison is correct.
36
      "-1.34",
37
      "-13.37e-1",
38
      "-13.34e-1",
39
      "-13.3e-1",
40
      // Checking the higher boundary of the scale.
41
      "-1.36e-2147483645", // Note that the scale is 2147483647, largest signed int.
42
      "-0",
43
      "0.05",
44
      "1.15",
45
      "1.2",
46
      "120e0",
47
      "1.2e+100",
48
      "2638.2e+3624"
49
  };
50
51
  const std::vector<size_t> kComparableEncodingLengths =
52
      {10, 10, 3, 3, 3, 3, 7, 1, 2, 3, 2, 2, 3, 6};
53
  const std::vector<size_t> kBigDecimalEncodingLengths =
54
      {9, 8, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 6};
55
};
56
57
1
TEST_F(DecimalTest, TestToStringFunctions) {
58
1
  std::string string;
59
1
  Decimal decimal0({}, VarInt(0), /* is_positive = */ false);
60
1
  Decimal decimal1({9, 0, 1, 2}, VarInt(-2), false);
61
1
  Decimal decimal2({9, 0, 1, 2}, VarInt(2), true);
62
1
  Decimal decimal3({9, 0, 1, 2}, VarInt(8), false);
63
1
  Decimal decimal4(
64
1
      {9, 0, 1, 2}, ASSERT_RESULT(VarInt::CreateFromString("-36546632732954564789")), true);
65
1
  Decimal decimal5(
66
1
      {9, 0, 1, 2}, ASSERT_RESULT(VarInt::CreateFromString("+36546632732954564789")), true);
67
68
1
  EXPECT_EQ("[ + 10^+0 * 0. ]", decimal0.ToDebugString());
69
1
  EXPECT_OK(decimal0.ToPointString(&string));
70
1
  EXPECT_EQ("0", string);
71
1
  EXPECT_EQ("0", decimal0.ToScientificString());
72
1
  EXPECT_EQ("0", decimal0.ToString());
73
74
1
  EXPECT_EQ("[ - 10^-2 * 0.9012 ]", decimal1.ToDebugString());
75
1
  EXPECT_OK(decimal1.ToPointString(&string));
76
1
  EXPECT_EQ("-0.009012", string);
77
1
  EXPECT_EQ("-9.012e-3", decimal1.ToScientificString());
78
1
  EXPECT_EQ("-0.009012", decimal1.ToString());
79
80
1
  EXPECT_EQ("[ + 10^+2 * 0.9012 ]", decimal2.ToDebugString());
81
1
  EXPECT_OK(decimal2.ToPointString(&string));
82
1
  EXPECT_EQ("90.12", string);
83
1
  EXPECT_EQ("9.012e+1", decimal2.ToScientificString());
84
1
  EXPECT_EQ("90.12", decimal2.ToString());
85
86
1
  EXPECT_EQ("[ - 10^+8 * 0.9012 ]", decimal3.ToDebugString());
87
1
  EXPECT_OK(decimal3.ToPointString(&string));
88
1
  EXPECT_EQ("-90120000", string);
89
1
  EXPECT_EQ("-9.012e+7", decimal3.ToScientificString());
90
1
  EXPECT_EQ("-90120000", decimal3.ToString());
91
92
1
  EXPECT_EQ("[ + 10^-36546632732954564789 * 0.9012 ]", decimal4.ToDebugString());
93
1
  EXPECT_FALSE(decimal4.ToPointString(&string).ok());
94
1
  EXPECT_EQ("9.012e-36546632732954564790", decimal4.ToScientificString());
95
1
  EXPECT_EQ("9.012e-36546632732954564790", decimal4.ToString());
96
97
1
  EXPECT_EQ("[ + 10^+36546632732954564789 * 0.9012 ]", decimal5.ToDebugString());
98
1
  EXPECT_FALSE(decimal5.ToPointString(&string).ok());
99
1
  EXPECT_EQ("9.012e+36546632732954564788", decimal5.ToScientificString());
100
1
  EXPECT_EQ("9.012e+36546632732954564788", decimal5.ToString());
101
1
}
102
103
1
TEST_F(DecimalTest, TestFromStringFunctions) {
104
1
  Decimal decimal;
105
106
1
  EXPECT_OK(decimal.FromString("0"));
107
1
  EXPECT_EQ("[ + 10^+0 * 0. ]", decimal.ToDebugString());
108
1
  EXPECT_OK(decimal.FromString("+0"));
109
1
  EXPECT_EQ("[ + 10^+0 * 0. ]", decimal.ToDebugString());
110
1
  EXPECT_OK(decimal.FromString("+00"));
111
1
  EXPECT_EQ("[ + 10^+0 * 0. ]", decimal.ToDebugString());
112
1
  EXPECT_OK(decimal.FromString("0.1"));
113
1
  EXPECT_EQ("[ + 10^+0 * 0.1 ]", decimal.ToDebugString());
114
1
  EXPECT_OK(decimal.FromString(".1"));
115
1
  EXPECT_EQ("[ + 10^+0 * 0.1 ]", decimal.ToDebugString());
116
1
  EXPECT_OK(decimal.FromString("0.02"));
117
1
  EXPECT_EQ("[ + 10^-1 * 0.2 ]", decimal.ToDebugString());
118
1
  EXPECT_OK(decimal.FromString("12.02"));
119
1
  EXPECT_EQ("[ + 10^+2 * 0.1202 ]", decimal.ToDebugString());
120
1
  EXPECT_OK(decimal.FromString("+0120."));
121
1
  EXPECT_EQ("[ + 10^+3 * 0.12 ]", decimal.ToDebugString());
122
1
  EXPECT_OK(decimal.FromString("-0"));
123
1
  EXPECT_EQ("[ + 10^+0 * 0. ]", decimal.ToDebugString());
124
1
  EXPECT_OK(decimal.FromString("-0.0"));
125
1
  EXPECT_EQ("[ + 10^+0 * 0. ]", decimal.ToDebugString());
126
1
  EXPECT_OK(decimal.FromString("-9.012e-4"));
127
1
  EXPECT_EQ("[ - 10^-3 * 0.9012 ]", decimal.ToDebugString());
128
1
  EXPECT_OK(decimal.FromString("9.012e-36546632732954564791"));
129
1
  EXPECT_EQ("[ + 10^-36546632732954564790 * 0.9012 ]", decimal.ToDebugString());
130
131
1
  EXPECT_FALSE(decimal.FromString("").ok());
132
1
  EXPECT_FALSE(decimal.FromString("-").ok());
133
1
  EXPECT_FALSE(decimal.FromString("1.1a").ok());
134
1
  EXPECT_FALSE(decimal.FromString("1.1a1").ok());
135
1
  EXPECT_FALSE(decimal.FromString("1.1e").ok());
136
1
  EXPECT_FALSE(decimal.FromString("1.1e1a2").ok());
137
1
}
138
139
1
TEST_F(DecimalTest, IsIntegerTest) {
140
1
  EXPECT_TRUE(Decimal({}, VarInt(0), false).is_integer());
141
142
1
  EXPECT_FALSE(Decimal({3}, VarInt(-1), false).is_integer());
143
1
  EXPECT_FALSE(Decimal({3}, VarInt(0), false).is_integer());
144
1
  EXPECT_TRUE(Decimal({3}, VarInt(1), false).is_integer());
145
1
  auto big_positive = ASSERT_RESULT(VarInt::CreateFromString("328763771921201932786301"));
146
1
  auto big_negative = ASSERT_RESULT(VarInt::CreateFromString("-328763771921201932786301"));
147
1
  EXPECT_TRUE(Decimal({3}, big_positive, false).is_integer());
148
1
  EXPECT_FALSE(Decimal(
149
1
      {3}, big_negative, false).is_integer());
150
151
1
  EXPECT_FALSE(Decimal({3, 0, 7, 8}, VarInt(-1), false).is_integer());
152
1
  EXPECT_FALSE(Decimal({3, 0, 7, 8}, VarInt(3), false).is_integer());
153
1
  EXPECT_TRUE(Decimal({3, 0, 7, 8}, VarInt(4), false).is_integer());
154
1
  EXPECT_TRUE(Decimal({3, 0, 7, 8}, big_positive, false).is_integer());
155
1
  EXPECT_FALSE(Decimal({3, 0, 7, 8}, big_negative, false).is_integer());
156
1
}
157
158
1
TEST_F(DecimalTest, TestDoubleConversions) {
159
  // Note: Rounding errors are expected
160
161
1
  auto dbl = Decimal("12.301").ToDouble();
162
1
  EXPECT_OK(dbl);
163
1
  EXPECT_EQ("1.2301000000000000156e+1", Decimal(*dbl).ToString());
164
165
1
  EXPECT_OK(dbl = Decimal("-0").ToDouble());
166
1
  EXPECT_EQ("0", Decimal(*dbl).ToString());
167
168
1
  EXPECT_OK(dbl = Decimal("1236.8642261937127309271040921").ToDouble());
169
1
  EXPECT_EQ("1.2368642261937127387e+3", Decimal(*dbl).ToString());
170
171
1
  EXPECT_OK(dbl = Decimal("1.236864226e3").ToDouble());
172
1
  EXPECT_EQ("1.2368642259999999169e+3", Decimal(*dbl).ToString());
173
174
  // Test large exponent
175
1
  EXPECT_OK(dbl = Decimal("1.236864226e-33").ToDouble());
176
1
  EXPECT_EQ("1.2368642260000000385e-33", Decimal(*dbl).ToString());
177
178
  // Exponent too large
179
1
  EXPECT_NOT_OK(Decimal("1.236864226e-782323").ToDouble());
180
181
1
  Decimal decimal;
182
183
1
  EXPECT_OK(decimal.FromDouble(std::numeric_limits<double>::epsilon()));
184
1
  EXPECT_OK(dbl = decimal.ToDouble());
185
1
  EXPECT_EQ(std::numeric_limits<double>::epsilon(), *dbl);
186
1
  EXPECT_EQ("2.2204460492503130808e-16", decimal.ToString());
187
188
1
  EXPECT_OK(decimal.FromDouble(std::numeric_limits<double>::lowest()));
189
1
  EXPECT_OK(dbl = decimal.ToDouble());
190
1
  EXPECT_EQ(std::numeric_limits<double>::lowest(), *dbl);
191
1
  EXPECT_EQ("-1.7976931348623157081e+308", decimal.ToString());
192
193
1
  EXPECT_OK(decimal.FromDouble(std::numeric_limits<double>::max()));
194
1
  EXPECT_OK(dbl = decimal.ToDouble());
195
1
  EXPECT_EQ(std::numeric_limits<double>::max(), *dbl);
196
1
  EXPECT_EQ("1.7976931348623157081e+308", decimal.ToString());
197
198
  // Can convert from denorm values.
199
1
  EXPECT_OK(decimal.FromDouble(std::numeric_limits<double>::denorm_min()));
200
  // Can convert to denorm values.
201
1
  EXPECT_OK(decimal.ToDouble());
202
1
  EXPECT_EQ("4.9406564584124654418e-324", decimal.ToString());
203
204
1
  EXPECT_TRUE(decimal.FromDouble(std::numeric_limits<double>::infinity()).IsCorruption());
205
1
  EXPECT_TRUE(decimal.FromDouble(-std::numeric_limits<double>::infinity()).IsCorruption());
206
1
  EXPECT_TRUE(decimal.FromDouble(std::numeric_limits<double>::signaling_NaN()).IsCorruption());
207
1
  EXPECT_TRUE(decimal.FromDouble(std::numeric_limits<double>::quiet_NaN()).IsCorruption());
208
1
}
209
210
1
TEST_F(DecimalTest, TestComparableEncoding) {
211
1
  std::vector<Decimal> test_decimals;
212
1
  std::vector<std::string> encoded_strings;
213
1
  std::vector<Decimal> decoded_decimals;
214
15
  for (size_t i = 0; i < test_cases.size(); i++) {
215
14
    SCOPED_TRACE(Format("Index: $0, value: $1", i, test_cases[i]));
216
14
    test_decimals.emplace_back(test_cases[i]);
217
14
    encoded_strings.push_back(test_decimals[i].EncodeToComparable());
218
14
    EXPECT_EQ(kComparableEncodingLengths[i], encoded_strings[i].size());
219
14
    decoded_decimals.emplace_back();
220
14
    size_t length;
221
14
    EXPECT_OK(decoded_decimals[i].DecodeFromComparable(encoded_strings[i], &length));
222
14
    EXPECT_EQ(kComparableEncodingLengths[i], length);
223
14
    EXPECT_EQ(test_decimals[i], decoded_decimals[i]);
224
14
    if (i > 0) {
225
13
      EXPECT_GT(decoded_decimals[i], decoded_decimals[i-1]);
226
13
      EXPECT_GT(decoded_decimals[i], test_decimals[i-1]);
227
13
      EXPECT_GT(test_decimals[i], decoded_decimals[i-1]);
228
13
      EXPECT_GT(test_decimals[i], test_decimals[i-1]);
229
13
      EXPECT_GT(encoded_strings[i], encoded_strings[i-1]);
230
13
    }
231
14
  }
232
1
}
233
234
1
TEST_F(DecimalTest, TestBigDecimalEncoding) {
235
1
  std::vector<Decimal> test_decimals;
236
1
  std::vector<std::string> encoded_strings;
237
1
  std::vector<Decimal> decoded_decimals;
238
1
  bool is_out_of_range = false;
239
15
  for (size_t i = 0; i < test_cases.size(); i++) {
240
14
    SCOPED_TRACE(Format("Index: $0, value: $1", i, test_cases[i]));
241
14
    test_decimals.emplace_back(test_cases[i]);
242
14
    encoded_strings.push_back(test_decimals[i].EncodeToSerializedBigDecimal(&is_out_of_range));
243
14
    EXPECT_FALSE(is_out_of_range);
244
14
    EXPECT_EQ(kBigDecimalEncodingLengths[i], encoded_strings[i].size());
245
14
    decoded_decimals.emplace_back();
246
14
    EXPECT_OK(decoded_decimals[i].DecodeFromSerializedBigDecimal(encoded_strings[i]));
247
14
    EXPECT_EQ(decoded_decimals[i], test_decimals[i]);
248
14
    if (i > 0) {
249
13
      EXPECT_GT(decoded_decimals[i], decoded_decimals[i-1]);
250
13
      EXPECT_GT(decoded_decimals[i], test_decimals[i-1]);
251
13
      EXPECT_GT(test_decimals[i], decoded_decimals[i-1]);
252
13
      EXPECT_GT(test_decimals[i], test_decimals[i-1]);
253
      // This is not necessarily true for BigDecimal Serialization
254
      // EXPECT_TRUE(encoded_strings[i] > encoded_strings[i-1]);
255
13
    }
256
14
  }
257
258
  // Testing just outside the scale limits.
259
1
  Decimal("-9847.236780e+2147483654").EncodeToSerializedBigDecimal(&is_out_of_range);
260
1
  EXPECT_TRUE(is_out_of_range);
261
1
  Decimal("-1.36e-2147483646").EncodeToSerializedBigDecimal(&is_out_of_range);
262
1
  EXPECT_TRUE(is_out_of_range);
263
1
}
264
265
1
TEST_F(DecimalTest, TestFloatDoubleCanonicalization) {
266
1
  const float float_nan_0 = CreateFloat(1, 0b11111111, (1 << 22));
267
1
  const float float_nan_1 = CreateFloat(0, 0b11111111, 1);
268
1
  const float float_not_nan_0 = CreateFloat(0, 0b11111110, 1);
269
1
  const float float_not_nan_1 = CreateFloat(0, 0b11111111, 0);
270
271
1
  const double double_nan_0 = CreateDouble(1, 0b11111111111, (1l << 51));
272
1
  const double double_nan_1 = CreateDouble(0, 0b11111111111, 1);
273
1
  const double double_not_nan_0 = CreateDouble(0, 0b11111111110, 1);
274
1
  const double double_not_nan_1 = CreateDouble(0, 0b11111111111, 0);
275
276
1
  EXPECT_TRUE(IsNanFloat(float_nan_0));
277
1
  EXPECT_TRUE(IsNanFloat(float_nan_1));
278
1
  EXPECT_FALSE(IsNanFloat(float_not_nan_0));
279
1
  EXPECT_FALSE(IsNanFloat(float_not_nan_1));
280
281
1
  EXPECT_TRUE(IsNanDouble(double_nan_0));
282
1
  EXPECT_TRUE(IsNanDouble(double_nan_1));
283
1
  EXPECT_FALSE(IsNanDouble(double_not_nan_0));
284
1
  EXPECT_FALSE(IsNanDouble(double_not_nan_1));
285
286
1
  float f1 = CanonicalizeFloat(float_nan_0);
287
1
  float f2 = CanonicalizeFloat(float_nan_1);
288
1
  EXPECT_EQ(*(reinterpret_cast<int32_t *>(&f1)), *(reinterpret_cast<int32_t *>(&f2)));
289
290
1
  double d1 = CanonicalizeDouble(double_nan_0);
291
1
  double d2 = CanonicalizeDouble(double_nan_1);
292
1
  EXPECT_EQ(*(reinterpret_cast<int64_t *>(&d1)), *(reinterpret_cast<int64_t *>(&d2)));
293
1
}
294
295
} // namespace util
296
} // namespace yb