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/js/Gruntfile.js b/lib/js/Gruntfile.js
index 4aa450f..1dcead6 100644
--- a/lib/js/Gruntfile.js
+++ b/lib/js/Gruntfile.js
@@ -55,6 +55,9 @@
       ThriftGenDeepConstructor: {
         command: '../../compiler/cpp/thrift -gen js -o test ../../test/JsDeepConstructorTest.thrift'
       },
+      ThriftGenDoubleConstants: {
+        command: '../../compiler/cpp/thrift -gen js -o test ../../test/DoubleConstantsTest.thrift'
+      },
       ThriftGenES6: {
         command: '../../compiler/cpp/thrift -gen js -gen js:es6 -o test ../../test/ThriftTest.thrift'
       },
@@ -94,6 +97,14 @@
           ]
         }
       },
+      ThriftJS_DoubleRendering: {
+        options: {
+          '--ignore-ssl-errors': true,
+          urls: [
+            'http://localhost:8088/test-double-rendering.html'
+          ]
+        }
+      },
       ThriftWS: {
         options: {
           urls: [
diff --git a/lib/js/test/build.xml b/lib/js/test/build.xml
index 5b3b657..0ba3828 100755
--- a/lib/js/test/build.xml
+++ b/lib/js/test/build.xml
@@ -171,6 +171,9 @@
     <exec executable="${thrift.compiler}" failonerror="true">
       <arg line="--gen js:jquery ${thrift.dir}/test/ThriftTest.thrift" />
     </exec>
+    <exec executable="${thrift.compiler}" failonerror="true">
+      <arg line="--gen js:jquery ${thrift.dir}/test/DoubleConstantsTest.thrift" />
+    </exec>
   </target>
 
   <target name="test" description="run test suite (lint, unittest)" depends="lint, unittest"/>
diff --git a/lib/js/test/jsTestDriver.conf b/lib/js/test/jsTestDriver.conf
index b9702cd..eb1588c 100755
--- a/lib/js/test/jsTestDriver.conf
+++ b/lib/js/test/jsTestDriver.conf
@@ -7,6 +7,7 @@
 # dependencies
   - build/js/lib/jquery.js
   - build/js/thrift.js
+  - gen-js/DoubleConstantsTest_constants.js
   - gen-js/ThriftTest_types.js
   - gen-js/ThriftTest.js
 # the test suite
diff --git a/lib/js/test/test-double-rendering.html b/lib/js/test/test-double-rendering.html
new file mode 100644
index 0000000..240cb39
--- /dev/null
+++ b/lib/js/test/test-double-rendering.html
@@ -0,0 +1,55 @@
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+  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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+      <title>Rendering Double Constants in JS: Unit Test</title>
+
+      <script src="build/js/thrift.js"         type="text/javascript" charset="utf-8"></script>
+      <script src="gen-js/ThriftTest_types.js" type="text/javascript" charset="utf-8"></script>
+      <script src="gen-js/ThriftTest.js"       type="text/javascript" charset="utf-8"></script>
+      <!-- double constants to check -->
+      <script src="gen-js/DoubleConstantsTest_types.js"         type="text/javascript" charset="utf-8"></script>
+
+      <!-- jQuery -->
+      <script type="text/javascript" src="../node_modules/jquery/dist/jquery.js" charset="utf-8"></script>
+
+      <!-- QUnit Test framework-->
+      <script type="text/javascript" src="../node_modules/qunit/qunit/qunit.js" charset="utf-8"></script>
+      <link rel="stylesheet" href="../node_modules/qunit/qunit/qunit.css" type="text/css" media="screen" />
+
+      <!-- the Test Suite-->
+      <script type="text/javascript" src="test-double-rendering.js" charset="utf-8"></script>
+    </head>
+<body>
+  <h1 id="qunit-header">Rendering Double Constants in JS: Unit Test</h1>
+  <h2 id="qunit-banner"></h2>
+  <div id="qunit-testrunner-toolbar"></div>
+  <h2 id="qunit-userAgent"></h2>
+  <ol id="qunit-tests"><li><!-- get valid xhtml strict--></li></ol>
+  <!-- Uncomment this to check the validity. This significantly slows down the test.
+  <p>
+      <a href="http://validator.w3.org/check/referer"><img
+          src="http://www.w3.org/Icons/valid-xhtml10"
+          alt="Valid XHTML 1.0!" height="31" width="88" /></a>
+  </p>
+  -->
+</body>
+</html>
diff --git a/lib/js/test/test-double-rendering.js b/lib/js/test/test-double-rendering.js
new file mode 100644
index 0000000..5d9cd2a
--- /dev/null
+++ b/lib/js/test/test-double-rendering.js
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+ /* jshint -W100 */
+
+/*
+ * JavaScript test suite for double constants inside
+ * DebugProtoTest.thrift. These tests will run against Normal (-gen js)
+ * Apache Thrift interfaces.
+ *
+ * Synchronous blocking calls should be identical in both
+ * Normal and jQuery interfaces. All synchronous tests belong
+ * here.
+ *
+ * Asynchronous success callbacks passed as the last parameter
+ * of an RPC call should be identical in both Normal and jQuery
+ * interfaces. Async success tests belong here.
+ *
+ * Asynchronous exception processing is different in Normal
+ * and jQuery interfaces. Such tests belong in the test-nojq.js
+ * or test-jq.js files respectively. jQuery specific XHR object
+ * tests also belong in test-jq.js. Do not create any jQuery
+ * dependencies in this file or in test-nojq.js
+ *
+ * To compile client code for this test use:
+ *      $ thrift -gen js ThriftTest.thrift
+ *      $ thrift -gen js DebugProtoTest.thrift
+ *
+ * See also:
+ * ++ test-nojq.js for "-gen js" only tests
+ */
+
+// double assertion threshold
+var EPSILON = 0.0000001;
+
+// Work around for old API used by QUnitAdapter of jsTestDriver
+if (typeof QUnit.log == 'function') {
+  // When using real QUnit (fron PhantomJS) log failures to console
+  QUnit.log(function(details) {
+    if (!details.result) {
+      console.log('======== FAIL ========');
+      console.log('TestName: ' + details.name);
+      if (details.message) console.log(details.message);
+      console.log('Expected: ' + details.expected);
+      console.log('Actual  : ' + details.actual);
+      console.log('======================');
+    }
+  });
+}
+
+QUnit.module('Double rendering');
+
+  QUnit.test('Double (rendering)', function(assert) {
+    console.log('Double rendering test -- starts');
+    var EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308;
+    var EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43;
+    assert.ok(
+        Math.abs(EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT - DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT -
+            DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT -
+            DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT -
+            DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS -
+            DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE -
+            DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST) <= EPSILON);
+    assert.ok(
+        Math.abs(
+            EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE -
+            DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST) <= EPSILON);
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, 'number');
+    assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, 'number');
+    var EXPECTED_DOUBLE_LIST =
+        [1,-100,100,9223372036854775807,-9223372036854775807,3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,
+            9223372036854775816.43,-9223372036854775816.43];
+    assert.equal(DOUBLE_LIST_TEST.length, EXPECTED_DOUBLE_LIST.length);
+    for (var i = 0; i < EXPECTED_DOUBLE_LIST.length; ++i) {
+           assert.ok(Math.abs(EXPECTED_DOUBLE_LIST[i] - DOUBLE_LIST_TEST[i]) <= EPSILON);
+    }
+    console.log('Double rendering test -- ends');
+  });
+