Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
halo
libcore
Commits
972b7282
Commit
972b7282
authored
10 years ago
by
Neil Fuller
Committed by
Gerrit Code Review
10 years ago
Browse files
Options
Download
Plain Diff
Merge "Rewrite tests and add tests that demonstrate a bug"
parents
37fcc48b
4e92b626
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
229 additions
and
58 deletions
+229
-58
expectations/knownfailures.txt
expectations/knownfailures.txt
+8
-0
harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java
...org/apache/harmony/tests/java/text/DecimalFormatTest.java
+221
-58
No files found.
expectations/knownfailures.txt
View file @
972b7282
...
...
@@ -1435,6 +1435,14 @@
"com.android.org.apache.harmony.beans.tests.java.beans.PropertyChangeSupportTest#testSerializationCompatibility"
]
},
{
description: "Known precision issue in DecimalFormat",
bug: 17656132,
names: [
"org.apache.harmony.tests.java.text.DecimalFormatTest#test_formatDouble_bug17656132",
"org.apache.harmony.tests.java.text.DecimalFormatTest#test_formatDouble_roundingProblemCases"
]
},
{
description: "Known failure in GregorianCalendarTest",
bug: 12778197,
...
...
This diff is collapsed.
Click to expand it.
harmony-tests/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java
View file @
972b7282
...
...
@@ -1465,78 +1465,241 @@ public class DecimalFormatTest extends TestCase {
formatTester
.
throwFailures
();
}
public
void
test_formatDouble_wideRange
()
{
// Demonstrates that fraction digit rounding occurs as expected with 1, 10 and 14 fraction
// digits, using numbers that are well within the precision of IEEE 754.
public
void
test_formatDouble_maxFractionDigits
()
{
final
DecimalFormatSymbols
dfs
=
new
DecimalFormatSymbols
(
Locale
.
US
);
DecimalFormat
format
=
new
DecimalFormat
(
"#0.#"
,
dfs
);
format
.
setGroupingUsed
(
false
);
format
.
setMaximumIntegerDigits
(
400
);
format
.
setMaximumFractionDigits
(
400
);
for
(
int
i
=
0
;
i
<
309
;
i
++)
{
String
tval
=
"1"
;
for
(
int
j
=
0
;
j
<
i
;
j
++)
{
tval
+=
"0"
;
}
double
d
=
Double
.
parseDouble
(
tval
);
String
result
=
format
.
format
(
d
);
assertEquals
(
i
+
") e:"
+
tval
+
" r:"
+
result
,
tval
,
result
);
}
for
(
int
i
=
0
;
i
<
322
;
i
++)
{
String
tval
=
"0."
;
for
(
int
j
=
0
;
j
<
i
;
j
++)
{
tval
+=
"0"
;
}
tval
+=
"1"
;
double
d
=
Double
.
parseDouble
(
tval
);
String
result
=
format
.
format
(
d
);
assertEquals
(
i
+
") e:"
+
tval
+
" r:"
+
result
,
tval
,
result
);
format
.
setMaximumFractionDigits
(
1
);
assertEquals
(
"1"
,
format
.
format
(
0.99
));
assertEquals
(
"1"
,
format
.
format
(
0.95
));
assertEquals
(
"0.9"
,
format
.
format
(
0.94
));
assertEquals
(
"0.9"
,
format
.
format
(
0.90
));
assertEquals
(
"0.2"
,
format
.
format
(
0.19
));
assertEquals
(
"0.2"
,
format
.
format
(
0.15
));
assertEquals
(
"0.1"
,
format
.
format
(
0.14
));
assertEquals
(
"0.1"
,
format
.
format
(
0.10
));
format
.
setMaximumFractionDigits
(
10
);
assertEquals
(
"1"
,
format
.
format
(
0.99999999999
));
assertEquals
(
"1"
,
format
.
format
(
0.99999999995
));
assertEquals
(
"0.9999999999"
,
format
.
format
(
0.99999999994
));
assertEquals
(
"0.9999999999"
,
format
.
format
(
0.99999999990
));
assertEquals
(
"0.1111111112"
,
format
.
format
(
0.11111111119
));
assertEquals
(
"0.1111111112"
,
format
.
format
(
0.11111111115
));
assertEquals
(
"0.1111111111"
,
format
.
format
(
0.11111111114
));
assertEquals
(
"0.1111111111"
,
format
.
format
(
0.11111111110
));
format
.
setMaximumFractionDigits
(
14
);
assertEquals
(
"1"
,
format
.
format
(
0.999999999999999
));
assertEquals
(
"1"
,
format
.
format
(
0.999999999999995
));
assertEquals
(
"0.99999999999999"
,
format
.
format
(
0.999999999999994
));
assertEquals
(
"0.99999999999999"
,
format
.
format
(
0.999999999999990
));
assertEquals
(
"0.11111111111112"
,
format
.
format
(
0.111111111111119
));
assertEquals
(
"0.11111111111112"
,
format
.
format
(
0.111111111111115
));
assertEquals
(
"0.11111111111111"
,
format
.
format
(
0.111111111111114
));
assertEquals
(
"0.11111111111111"
,
format
.
format
(
0.111111111111110
));
}
// This demonstrates rounding at the 15th decimal digit. By setting the maximum fraction digits
// we force rounding at a point just below the full IEEE 754 precision. IEEE 754 should be
// precise to just above 15 decimal digits.
// df.format() with no limits always emits up to 16 decimal digits, slightly above what IEEE 754
// can store precisely.
public
void
test_formatDouble_roundingTo15Digits
()
throws
Exception
{
final
DecimalFormatSymbols
dfs
=
new
DecimalFormatSymbols
(
Locale
.
US
);
DecimalFormat
df
=
new
DecimalFormat
(
"#.#"
,
dfs
);
df
.
setMaximumIntegerDigits
(
400
);
df
.
setGroupingUsed
(
false
);
df
.
setMaximumFractionDigits
(
0
);
assertEquals
(
"1000000000000000"
,
df
.
format
(
999999999999999.9
));
df
.
setMaximumFractionDigits
(
1
);
assertEquals
(
"100000000000000"
,
df
.
format
(
99999999999999.99
));
df
.
setMaximumFractionDigits
(
2
);
assertEquals
(
"10000000000000"
,
df
.
format
(
9999999999999.999
));
df
.
setMaximumFractionDigits
(
3
);
assertEquals
(
"1000000000000"
,
df
.
format
(
999999999999.9999
));
df
.
setMaximumFractionDigits
(
4
);
assertEquals
(
"100000000000"
,
df
.
format
(
99999999999.99999
));
df
.
setMaximumFractionDigits
(
5
);
assertEquals
(
"10000000000"
,
df
.
format
(
9999999999.999999
));
df
.
setMaximumFractionDigits
(
6
);
assertEquals
(
"1000000000"
,
df
.
format
(
999999999.9999999
));
df
.
setMaximumFractionDigits
(
7
);
assertEquals
(
"100000000"
,
df
.
format
(
99999999.99999999
));
df
.
setMaximumFractionDigits
(
8
);
assertEquals
(
"10000000"
,
df
.
format
(
9999999.999999999
));
df
.
setMaximumFractionDigits
(
9
);
assertEquals
(
"1000000"
,
df
.
format
(
999999.9999999999
));
df
.
setMaximumFractionDigits
(
10
);
assertEquals
(
"100000"
,
df
.
format
(
99999.99999999999
));
df
.
setMaximumFractionDigits
(
11
);
assertEquals
(
"10000"
,
df
.
format
(
9999.999999999999
));
df
.
setMaximumFractionDigits
(
12
);
assertEquals
(
"1000"
,
df
.
format
(
999.9999999999999
));
df
.
setMaximumFractionDigits
(
13
);
assertEquals
(
"100"
,
df
.
format
(
99.99999999999999
));
df
.
setMaximumFractionDigits
(
14
);
assertEquals
(
"10"
,
df
.
format
(
9.999999999999999
));
df
.
setMaximumFractionDigits
(
15
);
assertEquals
(
"1"
,
df
.
format
(
0.9999999999999999
));
}
// This checks formatting over most of the representable IEEE 754 range using a formatter that
// should be performing no lossy rounding.
// It checks that the formatted double can be parsed to get the original double.
// IEEE 754 can represent values from (decimal) ~2.22507E−308 to ~1.79769E308 to full precision.
// Close to zero it can go down to 4.94066E-324 with a loss of precision.
// At the extremes of the double range this test will not be testing doubles that exactly
// represent powers of 10. The test is only interested in whether the doubles closest
// to powers of 10 that can be represented can each be turned into a string and read back again
// to arrive at the original double.
public
void
test_formatDouble_wideRange
()
throws
Exception
{
for
(
int
i
=
-
324
;
i
<
309
;
i
++)
{
// Generate a decimal number we are interested in: 1 * 10^i
String
stringForm
=
"1e"
+
i
;
BigDecimal
bigDecimal
=
new
BigDecimal
(
stringForm
);
// Obtain the nearest double representation of the decimal number.
// This is lossy because going from BigDecimal -> double is inexact, but we should
// arrive at a number that is as close as possible to the decimal value. We assume that
// BigDecimal is capable of this, but it is not critical to this test if it gets it a
// little wrong, though it may mean we are testing a double value different from the one
// we thought we were.
double
d
=
bigDecimal
.
doubleValue
();
assertDecimalFormatIsLossless
(
d
);
}
}
public
void
test_formatDouble_varyingScaleProblemCases
()
throws
Exception
{
// This test is a regression test for http://b/17656132.
// It checks hand-picked values can be formatted and parsed to get the original double.
// The formatter as configured should perform no rounding.
public
void
test_formatDouble_roundingProblemCases
()
throws
Exception
{
// Most of the double literals below are not exactly representable in IEEE 754 but
// it should not matter to this test.
assertDecimalFormatIsLossless
(
999999999999999.9
);
assertDecimalFormatIsLossless
(
99999999999999.99
);
assertDecimalFormatIsLossless
(
9999999999999.999
);
assertDecimalFormatIsLossless
(
999999999999.9999
);
assertDecimalFormatIsLossless
(
99999999999.99999
);
assertDecimalFormatIsLossless
(
9999999999.999999
);
assertDecimalFormatIsLossless
(
999999999.9999999
);
assertDecimalFormatIsLossless
(
99999999.99999999
);
assertDecimalFormatIsLossless
(
9999999.999999999
);
assertDecimalFormatIsLossless
(
999999.9999999999
);
assertDecimalFormatIsLossless
(
99999.99999999999
);
assertDecimalFormatIsLossless
(
9999.999999999999
);
assertDecimalFormatIsLossless
(
999.9999999999999
);
assertDecimalFormatIsLossless
(
99.99999999999999
);
assertDecimalFormatIsLossless
(
9.999999999999999
);
assertDecimalFormatIsLossless
(
0.9999999999999999
);
}
// This test checks hand-picked values can be formatted and parsed to get the original double.
// The formatter as configured should perform no rounding.
// These numbers are not affected by http://b/17656132.
public
void
test_formatDouble_varyingScale
()
throws
Exception
{
// Most of the double literals below are not exactly representable in IEEE 754 but
// it should not matter to this test.
assertDecimalFormatIsLossless
(
999999999999999
.);
assertDecimalFormatIsLossless
(
123456789012345
.);
assertDecimalFormatIsLossless
(
12345678901234.5
);
assertDecimalFormatIsLossless
(
1234567890123.25
);
assertDecimalFormatIsLossless
(
999999999999.375
);
assertDecimalFormatIsLossless
(
99999999999.0625
);
assertDecimalFormatIsLossless
(
9999999999.03125
);
assertDecimalFormatIsLossless
(
999999999.015625
);
assertDecimalFormatIsLossless
(
99999999.0078125
);
assertDecimalFormatIsLossless
(
9999999.00390625
);
assertDecimalFormatIsLossless
(
999999.001953125
);
assertDecimalFormatIsLossless
(
9999.00048828125
);
assertDecimalFormatIsLossless
(
999.000244140625
);
assertDecimalFormatIsLossless
(
99.0001220703125
);
assertDecimalFormatIsLossless
(
9.00006103515625
);
assertDecimalFormatIsLossless
(
0.000030517578125
);
}
private
static
void
assertDecimalFormatIsLossless
(
double
d
)
throws
Exception
{
final
DecimalFormatSymbols
dfs
=
new
DecimalFormatSymbols
(
Locale
.
US
);
DecimalFormat
format
=
new
DecimalFormat
(
"#0.#"
,
dfs
);
format
.
setGroupingUsed
(
false
);
format
.
setMaximumIntegerDigits
(
400
);
format
.
setMaximumFractionDigits
(
400
);
assertEquals
(
"999999999999999"
,
format
.
format
(
999999999999999
.));
assertEquals
(
"999999999999999.9"
,
format
.
format
(
999999999999999.9
));
assertEquals
(
"99999999999999.98"
,
format
.
format
(
99999999999999.99
));
assertEquals
(
"9999999999999.998"
,
format
.
format
(
9999999999999.999
));
assertEquals
(
"999999999999.9999"
,
format
.
format
(
999999999999.9999
));
assertEquals
(
"99999999999.99998"
,
format
.
format
(
99999999999.99999
));
assertEquals
(
"9999999999.999998"
,
format
.
format
(
9999999999.999999
));
assertEquals
(
"999999999.9999999"
,
format
.
format
(
999999999.9999999
));
assertEquals
(
"99999999.99999999"
,
format
.
format
(
99999999.99999999
));
assertEquals
(
"9999999.999999998"
,
format
.
format
(
9999999.999999999
));
assertEquals
(
"99999.99999999999"
,
format
.
format
(
99999.99999999999
));
assertEquals
(
"9999.999999999998"
,
format
.
format
(
9999.999999999999
));
assertEquals
(
"999.9999999999999"
,
format
.
format
(
999.9999999999999
));
assertEquals
(
"99.99999999999999"
,
format
.
format
(
99.99999999999999
));
assertEquals
(
"9.999999999999998"
,
format
.
format
(
9.999999999999999
));
assertEquals
(
"0.9999999999999999"
,
format
.
format
(.
9999999999999999
));
// Every floating point binary can be represented exactly in decimal if you have enough
// digits. This shows the value actually being tested.
String
testId
=
"decimalValue: "
+
new
BigDecimal
(
d
);
// As a sanity check we try out parseDouble() with the string generated by
// Double.toString(). Strictly speaking Double.toString() is probably not guaranteed to be
// lossless, but in reality it probably is, or at least is close enough.
assertDoubleEqual
(
testId
+
" failed parseDouble(toString()) sanity check"
,
d
,
Double
.
parseDouble
(
Double
.
toString
(
d
)));
// Format the number: If this is lossy it is a problem. We are trying to check that it
// doesn't lose any unnecessary precision.
String
result
=
format
.
format
(
d
);
// Here we use Double.parseDouble() which should able to parse a number we know was
// representable as a double into the original double. If parseDouble() is not implemented
// correctly the test is invalid.
double
doubleParsed
=
Double
.
parseDouble
(
result
);
assertDoubleEqual
(
testId
+
" (format() produced "
+
result
+
")"
,
d
,
doubleParsed
);
// For completeness we try to parse using the formatter too. If this fails but the format
// above didn't it may be a problem with parse(), or with format() that we didn't spot.
assertDoubleEqual
(
testId
+
" failed parse(format()) check"
,
d
,
format
.
parse
(
result
).
doubleValue
());
}
public
void
test_formatDouble_varyingScale
()
throws
Exception
{
final
DecimalFormatSymbols
dfs
=
new
DecimalFormatSymbols
(
Locale
.
US
);
DecimalFormat
format
=
new
DecimalFormat
(
"#0.#"
,
dfs
);
format
.
setMaximumIntegerDigits
(
400
);
format
.
setMaximumFractionDigits
(
400
);
private
static
void
assertDoubleEqual
(
String
message
,
double
d
,
double
doubleParsed
)
{
assertEquals
(
message
,
createPrintableDouble
(
d
),
createPrintableDouble
(
doubleParsed
));
}
assertEquals
(
"123456789012345"
,
format
.
format
(
123456789012345
.));
assertEquals
(
"12345678901234.5"
,
format
.
format
(
12345678901234.5
));
assertEquals
(
"1234567890123.25"
,
format
.
format
(
1234567890123.25
));
assertEquals
(
"999999999999.375"
,
format
.
format
(
999999999999.375
));
assertEquals
(
"99999999999.0625"
,
format
.
format
(
99999999999.0625
));
assertEquals
(
"9999999999.03125"
,
format
.
format
(
9999999999.03125
));
assertEquals
(
"999999999.015625"
,
format
.
format
(
999999999.015625
));
assertEquals
(
"99999999.0078125"
,
format
.
format
(
99999999.0078125
));
assertEquals
(
"9999999.00390625"
,
format
.
format
(
9999999.00390625
));
assertEquals
(
"999999.001953125"
,
format
.
format
(
999999.001953125
));
assertEquals
(
"9999.00048828125"
,
format
.
format
(
9999.00048828125
));
assertEquals
(
"999.000244140625"
,
format
.
format
(
999.000244140625
));
assertEquals
(
"99.0001220703125"
,
format
.
format
(
99.0001220703125
));
assertEquals
(
"9.00006103515625"
,
format
.
format
(
9.00006103515625
));
assertEquals
(
"0.000030517578125"
,
format
.
format
(
0.000030517578125
));
private
static
String
createPrintableDouble
(
double
d
)
{
return
Double
.
toString
(
d
)
+
"("
+
Long
.
toHexString
(
Double
.
doubleToRawLongBits
(
d
))
+
")"
;
}
// Concise demonstration of http://b/17656132 using hard-coded expected values.
public
void
test_formatDouble_bug17656132
()
{
final
DecimalFormatSymbols
dfs
=
new
DecimalFormatSymbols
(
Locale
.
US
);
DecimalFormat
df
=
new
DecimalFormat
(
"#0.#"
,
dfs
);
df
.
setGroupingUsed
(
false
);
df
.
setMaximumIntegerDigits
(
400
);
df
.
setMaximumFractionDigits
(
400
);
// The expected values below come from the RI and are correct 16 decimal digit
// representations of the formatted value. Android does something different.
// The decimal value given in each comment is the actual double value as represented by
// IEEE 754. See new BigDecimal(double).
// double: 999999999999999.9 is decimal 999999999999999.875
assertEquals
(
"999999999999999.9"
,
df
.
format
(
999999999999999.9
));
// double: 99999999999999.98 is decimal 99999999999999.984375
assertEquals
(
"99999999999999.98"
,
df
.
format
(
99999999999999.98
));
// double 9999999999999.998 is decimal 9999999999999.998046875
assertEquals
(
"9999999999999.998"
,
df
.
format
(
9999999999999.998
));
// double 999999999999.9999 is decimal 999999999999.9998779296875
assertEquals
(
"999999999999.9999"
,
df
.
format
(
999999999999.9999
));
// double 99999999999.99998 is decimal 99999999999.9999847412109375
assertEquals
(
"99999999999.99998"
,
df
.
format
(
99999999999.99998
));
// double 9999999999.999998 is decimal 9999999999.9999980926513671875
assertEquals
(
"9999999999.999998"
,
df
.
format
(
9999999999.999998
));
// double 1E23 is decimal 99999999999999991611392
assertEquals
(
"9999999999999999"
,
df
.
format
(
1
E23
));
}
public
void
test_getDecimalFormatSymbols
()
{
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment