THRIFT-4476: Typecasting problem on double list items,
emitting doubles with high precision
Client: cpp
Client: erl
Client: java
Client: js
Client: py

This closes #1511
diff --git a/lib/java/gradle/generateTestThrift.gradle b/lib/java/gradle/generateTestThrift.gradle
index 9673e5b..c347917 100644
--- a/lib/java/gradle/generateTestThrift.gradle
+++ b/lib/java/gradle/generateTestThrift.gradle
@@ -74,6 +74,7 @@
     thriftCompile(it, 'ThriftTest.thrift')
     thriftCompile(it, 'JavaTypes.thrift')
     thriftCompile(it, 'DebugProtoTest.thrift')
+    thriftCompile(it, 'DoubleConstantsTest.thrift')
     thriftCompile(it, 'OptionalRequiredTest.thrift')
     thriftCompile(it, 'ManyOptionals.thrift')
     thriftCompile(it, 'JavaDeepCopyTest.thrift')
diff --git a/lib/java/test/org/apache/thrift/TestRenderedDoubleConstants.java b/lib/java/test/org/apache/thrift/TestRenderedDoubleConstants.java
new file mode 100644
index 0000000..d691fe3
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/TestRenderedDoubleConstants.java
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.thrift;
+
+import java.util.List;
+import junit.framework.TestCase;
+import static org.junit.Assert.*;
+import org.junit.Test;
+import thrift.test.DoubleConstantsTestConstants;
+
+public class TestRenderedDoubleConstants extends TestCase {
+    private static final double EPSILON = 0.0000001;
+    private static final String ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST =
+        "failed to verify a double constant generated by Thrift (expected = %f, got = %f)";
+    private static final String ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST =
+        "failed to verify a list item by Thrift (expected = %f, got = %f)";
+    private static final String ASSERTION_MESSAGE_FOR_TYPE_CHECKS =
+        "the rendered variable with name %s is not of double type";
+
+    // to make sure lists containing doubles are generated correctly
+    public void testRenderedDoubleList() throws Exception {
+        final double[] EXPECTED_LIST =
+            {1d,-100d,100d,9223372036854775807d,-9223372036854775807d,3.14159265359,1000000.1,-1000000.1,1.7e+308,
+             -1.7e+308,9223372036854775816.43,-9223372036854775816.43};
+        assertEquals(EXPECTED_LIST.length, DoubleConstantsTestConstants.DOUBLE_LIST_TEST.size());
+        for (int i = 0; i < EXPECTED_LIST.length; ++i) {
+            assertEquals(
+                String.format(
+                    ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST,
+                    EXPECTED_LIST[i],
+                    DoubleConstantsTestConstants.DOUBLE_LIST_TEST.get(i)),
+                EXPECTED_LIST[i], DoubleConstantsTestConstants.DOUBLE_LIST_TEST.get(i), EPSILON);
+        }
+    }
+
+    // to make sure the variables inside Thrift files are generated correctly
+    public void testRenderedDoubleConstants() throws Exception {
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308;
+        final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43;
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, EPSILON);
+        assertEquals(
+            String.format(
+                ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST,
+                EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE,
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST),
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE,
+            DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, EPSILON);
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST));
+        //assertTrue(
+        //    String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST"),
+        //    Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST));
+        assertTrue(
+            String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST"),
+            Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST));
+        //assertTrue(
+        //    String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST"),
+        //    Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST));
+        assertTrue(
+            String.format(
+                ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST"),
+            Double.class.isInstance(
+                DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST));
+    }
+}
diff --git a/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java
index 0b9c732..b8c4657 100644
--- a/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java
+++ b/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java
@@ -84,7 +84,7 @@
     struct.unsetDouble_byte_map();
     struct.unsetString_byte_map();
     struct.write(proto);
-    assertEquals("{\"a_byte\":127,\"a_i16\":32000,\"a_i32\":1000000000,\"a_i64\":1099511627775,\"a_double\":5.6789,\"a_string\":\"my string\",\"a_binary\":\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\",\"true_field\":1,\"false_field\":0,\"empty_struct_field\":{},\"byte_list\":[-127,-1,0,1,127],\"i16_list\":[-1,0,1,32767],\"i32_list\":[-1,0,255,65535,16777215,2147483647],\"i64_list\":[-1,0,255,65535,16777215,4294967295,1099511627775,281474976710655,72057594037927935,9223372036854775807],\"double_list\":[0.1,0.2,0.3],\"string_list\":[\"first\",\"second\",\"third\"],\"boolean_list\":[1,1,1,0,0,0],\"struct_list\":[{},{}],\"i32_set\":[1,2,3],\"boolean_set\":[0,1],\"struct_set\":[{}],\"byte_byte_map\":{\"1\":2},\"boolean_byte_map\":{\"0\":0,\"1\":1},\"byte_i16_map\":{\"1\":1,\"2\":-1,\"3\":32767},\"byte_i32_map\":{\"1\":1,\"2\":-1,\"3\":2147483647},\"byte_i64_map\":{\"1\":1,\"2\":-1,\"3\":9223372036854775807},\"byte_double_map\":{\"1\":0.1,\"2\":-0.1,\"3\":1000000.0},\"byte_string_map\":{\"1\":\"\",\"2\":\"blah\",\"3\":\"loooooooooooooong string\"},\"byte_boolean_map\":{\"1\":1,\"2\":0},\"byte_map_map\":{\"0\":{},\"1\":{\"1\":1},\"2\":{\"1\":1,\"2\":2}},\"byte_set_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]},\"byte_list_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]}}", bufToString());
+    assertEquals("{\"a_byte\":127,\"a_i16\":32000,\"a_i32\":1000000000,\"a_i64\":1099511627775,\"a_double\":5.6789,\"a_string\":\"my string\",\"a_binary\":\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\",\"true_field\":1,\"false_field\":0,\"empty_struct_field\":{},\"byte_list\":[-127,-1,0,1,127],\"i16_list\":[-1,0,1,32767],\"i32_list\":[-1,0,255,65535,16777215,2147483647],\"i64_list\":[-1,0,255,65535,16777215,4294967295,1099511627775,281474976710655,72057594037927935,9223372036854775807],\"double_list\":[0.1,0.2,0.3],\"string_list\":[\"first\",\"second\",\"third\"],\"boolean_list\":[1,1,1,0,0,0],\"struct_list\":[{},{}],\"i32_set\":[1,2,3],\"boolean_set\":[0,1],\"struct_set\":[{}],\"byte_byte_map\":{\"1\":2},\"boolean_byte_map\":{\"0\":0,\"1\":1},\"byte_i16_map\":{\"1\":1,\"2\":-1,\"3\":32767},\"byte_i32_map\":{\"1\":1,\"2\":-1,\"3\":2147483647},\"byte_i64_map\":{\"1\":1,\"2\":-1,\"3\":9223372036854775807},\"byte_double_map\":{\"1\":0.1,\"2\":-0.1,\"3\":1000000.1},\"byte_string_map\":{\"1\":\"\",\"2\":\"blah\",\"3\":\"loooooooooooooong string\"},\"byte_boolean_map\":{\"1\":1,\"2\":0},\"byte_map_map\":{\"0\":{},\"1\":{\"1\":1},\"2\":{\"1\":1,\"2\":2}},\"byte_set_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]},\"byte_list_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]}}", bufToString());
   }
 
   public void testThrowsOnCollectionKeys() throws TException {