From d93eaeb7c399488b16753b1786a30ec6a59761c7 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Mon, 9 Jul 2018 12:16:40 +0000 Subject: [Support] Make JSON handle doubles and int64s losslessly Summary: This patch adds a new "integer" ValueType, and renames Number -> Double. This allows us to preserve the full precision of int64_t when parsing integers from the wire, or constructing from an integer. The API is unchanged, other than giving asInteger() a clearer contract. In addition, always output doubles with enough precision that parsing will reconstruct the same double. Reviewers: simon_tatham Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D46209 llvm-svn: 336541 --- llvm/unittests/Support/JSONTest.cpp | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'llvm/unittests/Support/JSONTest.cpp') diff --git a/llvm/unittests/Support/JSONTest.cpp b/llvm/unittests/Support/JSONTest.cpp index bf7f4ae96d0..08307c10d2d 100644 --- a/llvm/unittests/Support/JSONTest.cpp +++ b/llvm/unittests/Support/JSONTest.cpp @@ -227,6 +227,66 @@ TEST(JSONTest, Inspection) { } } +// Verify special integer handling - we try to preserve exact int64 values. +TEST(JSONTest, Integers) { + struct { + const char *Desc; + Value Val; + const char *Str; + llvm::Optional AsInt; + llvm::Optional AsNumber; + } TestCases[] = { + { + "Non-integer. Stored as double, not convertible.", + double{1.5}, + "1.5", + llvm::None, + 1.5, + }, + + { + "Integer, not exact double. Stored as int64, convertible.", + int64_t{0x4000000000000001}, + "4611686018427387905", + int64_t{0x4000000000000001}, + double{0x4000000000000000}, + }, + + { + "Negative integer, not exact double. Stored as int64, convertible.", + int64_t{-0x4000000000000001}, + "-4611686018427387905", + int64_t{-0x4000000000000001}, + double{-0x4000000000000000}, + }, + + { + "Dynamically exact integer. Stored as double, convertible.", + double{0x6000000000000000}, + "6.9175290276410819e+18", + int64_t{0x6000000000000000}, + double{0x6000000000000000}, + }, + + { + "Dynamically integer, >64 bits. Stored as double, not convertible.", + 1.5 * double{0x8000000000000000}, + "1.3835058055282164e+19", + llvm::None, + 1.5 * double{0x8000000000000000}, + }, + }; + for (const auto &T : TestCases) { + EXPECT_EQ(T.Str, s(T.Val)) << T.Desc; + llvm::Expected Doc = parse(T.Str); + EXPECT_TRUE(!!Doc) << T.Desc; + EXPECT_EQ(Doc->getAsInteger(), T.AsInt) << T.Desc; + EXPECT_EQ(Doc->getAsNumber(), T.AsNumber) << T.Desc; + EXPECT_EQ(T.Val, *Doc) << T.Desc; + EXPECT_EQ(T.Str, s(*Doc)) << T.Desc; + } +} + // Sample struct with typical JSON-mapping rules. struct CustomStruct { CustomStruct() : B(false) {} -- cgit v1.2.3