From 250b690a546f296fa480cf61ad796a36b66a78c6 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sat, 21 Mar 2015 01:05:31 -0700 Subject: tests: Work around fp issues in various runtime libraries Disable/change some tests for some compilers; use binary float comparison for early MSVC versions. --- tests/test_dom_modify.cpp | 65 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 11 deletions(-) (limited to 'tests') diff --git a/tests/test_dom_modify.cpp b/tests/test_dom_modify.cpp index 5167358..c06c141 100644 --- a/tests/test_dom_modify.cpp +++ b/tests/test_dom_modify.cpp @@ -5,6 +5,10 @@ #include +#ifdef __BORLANDC__ +using std::ldexpf; +#endif + TEST_XML(dom_attr_assign, "") { xml_node node = doc.child(STR("node")); @@ -101,15 +105,28 @@ TEST_XML(dom_attr_set_value_llong, "") } #endif -TEST_XML(dom_attr_assign_large_number, "") +TEST_XML(dom_attr_assign_large_number_float, "") { xml_node node = doc.child(STR("node")); - node.attribute(STR("attr1")) = std::numeric_limits::max(); - node.attribute(STR("attr2")) = std::numeric_limits::max(); + node.attribute(STR("attr")) = std::numeric_limits::max(); - CHECK(test_node(node, STR(""), STR(""), pugi::format_raw) || - test_node(node, STR(""), STR(""), pugi::format_raw)); + CHECK(test_node(node, STR(""), STR(""), pugi::format_raw) || + test_node(node, STR(""), STR(""), pugi::format_raw)); +} + +TEST_XML(dom_attr_assign_large_number_double, "") +{ + xml_node node = doc.child(STR("node")); + + node.attribute(STR("attr")) = std::numeric_limits::max(); + + // Borland C does not print double values with enough precision +#ifdef __BORLANDC__ + CHECK_NODE(node, STR("")); +#else + CHECK_NODE(node, STR("")); +#endif } TEST_XML(dom_node_set_name, "text") @@ -1447,6 +1464,17 @@ TEST(dom_node_copy_declaration_empty_name) CHECK_STRING(decl2.name(), STR("")); } +template bool fp_equal(T lhs, T rhs) +{ + // Several compilers compare float/double values on x87 stack without proper rounding + // This causes roundtrip tests to fail, although they correctly preserve the data. +#if (defined(_MSC_VER) && _MSC_VER < 1400) + return memcmp(&lhs, &rhs, sizeof(T)) == 0; +#else + return lhs == rhs; +#endif +} + TEST(dom_fp_roundtrip_min_max) { xml_document doc; @@ -1454,16 +1482,16 @@ TEST(dom_fp_roundtrip_min_max) xml_attribute attr = node.append_attribute(STR("attr")); node.text().set(std::numeric_limits::min()); - CHECK(node.text().as_float() == std::numeric_limits::min()); + CHECK(fp_equal(node.text().as_float(), std::numeric_limits::min())); attr.set_value(std::numeric_limits::max()); - CHECK(attr.as_float() == std::numeric_limits::max()); + CHECK(fp_equal(attr.as_float(), std::numeric_limits::max())); attr.set_value(std::numeric_limits::min()); - CHECK(attr.as_double() == std::numeric_limits::min()); + CHECK(fp_equal(attr.as_double(), std::numeric_limits::min())); node.text().set(std::numeric_limits::max()); - CHECK(node.text().as_double() == std::numeric_limits::max()); + CHECK(fp_equal(node.text().as_double(), std::numeric_limits::max())); } const double fp_roundtrip_base[] = @@ -1487,11 +1515,13 @@ TEST(dom_fp_roundtrip_float) float value = ldexpf(static_cast(fp_roundtrip_base[i]), e); doc.text().set(value); - CHECK(doc.text().as_float() == value); + CHECK(fp_equal(doc.text().as_float(), value)); } } } +// Borland C does not print double values with enough precision +#ifndef __BORLANDC__ TEST(dom_fp_roundtrip_double) { xml_document doc; @@ -1500,10 +1530,23 @@ TEST(dom_fp_roundtrip_double) { for (size_t i = 0; i < sizeof(fp_roundtrip_base) / sizeof(fp_roundtrip_base[0]); ++i) { + #if defined(_MSC_VER) && _MSC_VER < 1400 + // Not all runtime libraries guarantee roundtripping for denormals + if (e == -1021 && fp_roundtrip_base[i] < 0.5) + continue; + #endif + + #ifdef __DMC__ + // Digital Mars C does not roundtrip on exactly one combination + if (e == -12 && i == 1) + continue; + #endif + double value = ldexp(fp_roundtrip_base[i], e); doc.text().set(value); - CHECK(doc.text().as_double() == value); + CHECK(fp_equal(doc.text().as_double(), value)); } } } +#endif -- cgit v1.2.3