From ad0333daa4fdd46db32b2f960d0ee96e7678eced Mon Sep 17 00:00:00 2001 From: Ozan Can Altiok Date: Mon, 19 Feb 2018 16:55:09 +0300 Subject: [PATCH] - high precision double rendering in JS, Java, Python and C++ - testing double rendering in JS, Java, Python and C++ - a comment added (about setprecision) - BOOST_TEST -> BOOST_CHECK double rendering in erlang, fixed (some additional tests added) less than operator - correction in erlang test style changes, some fixes in erlang test some fixes in erlang test some fixes in erlang test - no need for including lists library more style changes - something overlooked expected 2 lines before main - fixed (not seen locally) noticed that test cases should be added manually in Python DoubleConstantTest thrift compilation directive is now given in generate.cmake render_double_to_string -> emit_double_as_string added assertion error messages to see the problems inside Java tests in more detail RDP access to AppVeyor build workers THRIFT-82: Add Common Lisp support Client: cl There's framed and buffered socket transport, binary protocol, multiplex, simple server, cross-tests, self-tests, tutorial, CL library, CL code generator. Only SBCL is supported for now. This closes #1412 THRIFT-82: follow-up to common lisp to stabilize the linux build environment and update some docs THRIFT-82: fix cl test server to return the correct SecondService string and enable multi tests THRIFT-4503: fix dlang server logging on client disconnect so it does not report an error for normal operation THRIFT-4498: add phpcs back Client: php This closes #1498 THFIFT-4486: golang: support https from generated clients golang: don't generate -remote.go clients when there are no functions golang: support for http headers in -remote clients golang: serialize cli requests with TJsonProtocol since serialization is not supported with TSimpleJsonProtocol Client: golang This closes #1488 duplicate key problem in appveyor settings ignore the test cases with (-+)1.7e+308 in Java tests ignore the test cases with (-+)1.7e+308 in Java tests - 2 pyflakes8 style changes disabling the test named 'TestRenderedDoubleConstants' on machines with the MSVC2010 configuration msvc.profile parameter existence check passing "msvc profile" on build stage "MSVC_PROFILE" as a cache variable wrong usage of cache variables let's see whether the MSVC_PROFILE parameter is passed correctly let's see whether the MSVC_PROFILE parameter is passed correctly let's see whether TestRenderedDoubleConstants is excluded or not msvc.profile access - fixed msvc.profile access - fixed THRIFT-4436: port nodejs changes from THRIFT-3748 to js lib, test for serialization of nested list, run all tests when building js lib Client: js This closes #1457 THRIFT-4505: Fix python build on Vagrant Windows boxes Client: py This closes #1499 THRIFT-4506: fix use of assert for correctness in Java SASL negotiation Client: java Updated the languages matrix markdown documentation. Minor tweaks to the language matrix markdown documentation. THRIFT-4508: Fix node.js to be the desired version in docker ubuntu-artful image THRIFT-4354: fix php socket blocking behavior Patch: Robert Lu Client: php This closes #1384 THRIFT-4508: end trusty CI builds; handle nodejs 4.x LTS EOL; update docs THRIFT-4508: change windows CI builds to use current MSVC, one cygwin and one mingw build THRIFT-4480 - Handle seqid = 0 Client: js This closes #1487 THRIFT-4509: remove nodejs browser test Client: nodejs This closes #1501 fix wrong document @param in TBase.h Client: cocoa This closes #1504 THRIFT-4024: Skip() throws TProtocolException.INVALID_DATA on unknown data types Client: js This closes #1503 THRIFT-4495: Allow `undefined` for non-required Erlang records fields. Client: erl As of Erlang 19, the dialyzer static type-analysis tool no longer implicitly adds `undefined` to the allowed types for a field. This means that dialyzer will now complain about any non-required fields that are not explicitly initialed when creating a new record. This closes #1494 THRIFT-4497: Use `map()` field type for Erlang type for map struct fields. Client: erl The Thrift Erlang code generator previously generated fields with the `#{}` Erlang type for maps fields. In the Erlang type specification languages, however, `#{}` specifically means an empty map. This commit fixes the code to emit `map()` instead, which means the maps keys and values may be of any type. It would be possible to emit a field type such as `${keytype() => maptype()}`, but this commit does not do that. This closes #1495 THRIFT-4515: fix up nonblocking options and enable ssl for nonblocking in cpp server cross Client: cpp THRIFT-4465: Fix C++ TNonblockingServer and THRIFT_EAGAIN issues Client: cpp This closes #1497 THRIFT-4337: Able to set keyStore and trustStore as InputStream in the TSSLTransportFactory.TSSLTransportParameters Client: java This closes #1486 THRIFT-4515: fix windows build Client: cpp THRIFT-4448: Golang: do something with context.Context. Remove Go1.6 compatibility. Client: go This closes #1459 THRIFT-4517: disable ocaml in xenial because it is broken THRIFT-4337: fix javadoc build error related to changes THRIFT-4508: remove cygwin64 build in favor of MSVC2013 TestRenderedDoubleConstants (in Java/Python) has been disabled on MSVC2013 builders THRIFT-4509: * switch from grunt-external-daemon and grunt-shell to grunt-shell-spawn * update grunt to 1.0.2 * always use local copy of jquery and qunit * commit the package-lock files for npm keep versions stable Client: js This closes #1506 THRIFT-4509: add jslint and fix build script output THRIFT-4429: Make TThreadPoolServer.executorService_ available in inherited classes and refactor methods to be able customization Client: java This closes #1485 THRIFT-4513: Fix thrift compiler to generate constants in stable order. This closes #1505 reverting changes on disabling a test depending on the MSVC compiler double emitting operation depending on the compiler version THRIFT-4474: Use PSR-4 autoloader by default Client: php This closes #1479 THRIFT-4516: Fix "go vet" warnings for Go 1.10 Client: go THRIFT-4419: Fix bug where framed messages > 4K could not be read Client: rs This closes #1508 emit_double_as_string refactored unnecessary carat has been removed THRIFT-82: Add Common Lisp support Client: cl There's framed and buffered socket transport, binary protocol, multiplex, simple server, cross-tests, self-tests, tutorial, CL library, CL code generator. Only SBCL is supported for now. This closes #1412 THRIFT-82: follow-up to common lisp to stabilize the linux build environment and update some docs THRIFT-82: fix cl test server to return the correct SecondService string and enable multi tests THRIFT-4503: fix dlang server logging on client disconnect so it does not report an error for normal operation THRIFT-4498: add phpcs back Client: php This closes #1498 THFIFT-4486: golang: support https from generated clients golang: don't generate -remote.go clients when there are no functions golang: support for http headers in -remote clients golang: serialize cli requests with TJsonProtocol since serialization is not supported with TSimpleJsonProtocol Client: golang This closes #1488 THRIFT-4436: port nodejs changes from THRIFT-3748 to js lib, test for serialization of nested list, run all tests when building js lib Client: js This closes #1457 THRIFT-4505: Fix python build on Vagrant Windows boxes Client: py This closes #1499 THRIFT-4506: fix use of assert for correctness in Java SASL negotiation Client: java Updated the languages matrix markdown documentation. Minor tweaks to the language matrix markdown documentation. THRIFT-4508: Fix node.js to be the desired version in docker ubuntu-artful image THRIFT-4354: fix php socket blocking behavior Patch: Robert Lu Client: php This closes #1384 THRIFT-4508: end trusty CI builds; handle nodejs 4.x LTS EOL; update docs THRIFT-4508: change windows CI builds to use current MSVC, one cygwin and one mingw build THRIFT-4480 - Handle seqid = 0 Client: js This closes #1487 THRIFT-4509: remove nodejs browser test Client: nodejs This closes #1501 fix wrong document @param in TBase.h Client: cocoa This closes #1504 THRIFT-4024: Skip() throws TProtocolException.INVALID_DATA on unknown data types Client: js This closes #1503 THRIFT-4495: Allow `undefined` for non-required Erlang records fields. Client: erl As of Erlang 19, the dialyzer static type-analysis tool no longer implicitly adds `undefined` to the allowed types for a field. This means that dialyzer will now complain about any non-required fields that are not explicitly initialed when creating a new record. This closes #1494 THRIFT-4497: Use `map()` field type for Erlang type for map struct fields. Client: erl The Thrift Erlang code generator previously generated fields with the `#{}` Erlang type for maps fields. In the Erlang type specification languages, however, `#{}` specifically means an empty map. This commit fixes the code to emit `map()` instead, which means the maps keys and values may be of any type. It would be possible to emit a field type such as `${keytype() => maptype()}`, but this commit does not do that. This closes #1495 THRIFT-4515: fix up nonblocking options and enable ssl for nonblocking in cpp server cross Client: cpp THRIFT-4465: Fix C++ TNonblockingServer and THRIFT_EAGAIN issues Client: cpp This closes #1497 THRIFT-4337: Able to set keyStore and trustStore as InputStream in the TSSLTransportFactory.TSSLTransportParameters Client: java This closes #1486 THRIFT-4515: fix windows build Client: cpp THRIFT-4448: Golang: do something with context.Context. Remove Go1.6 compatibility. Client: go This closes #1459 THRIFT-4517: disable ocaml in xenial because it is broken THRIFT-4337: fix javadoc build error related to changes THRIFT-4508: remove cygwin64 build in favor of MSVC2013 THRIFT-4509: * switch from grunt-external-daemon and grunt-shell to grunt-shell-spawn * update grunt to 1.0.2 * always use local copy of jquery and qunit * commit the package-lock files for npm keep versions stable Client: js This closes #1506 THRIFT-4509: add jslint and fix build script output THRIFT-4429: Make TThreadPoolServer.executorService_ available in inherited classes and refactor methods to be able customization Client: java This closes #1485 THRIFT-4513: Fix thrift compiler to generate constants in stable order. This closes #1505 THRIFT-4474: Use PSR-4 autoloader by default Client: php This closes #1479 THRIFT-4516: Fix "go vet" warnings for Go 1.10 Client: go THRIFT-4419: Fix bug where framed messages > 4K could not be read Client: rs This closes #1508 THRIFT-4523 TStreamTransportImpl.GetOutputStream broken Client: Delphi Patch: Jens Geyer THRIFT-4515: cross server test improvement: graceful test server shutdown This closes #1509 THRIFT-82: move to SBCL 1.4.5 (hopefully will address 1.4.4 sporadic build errors) --- .gitignore | 13 +- .travis.yml | 32 +- LANGUAGES.md | 87 +- Makefile.am | 2 +- appveyor.yml | 57 +- build/appveyor/CYGW-appveyor-build.bat | 36 + build/appveyor/CYGW-appveyor-install.bat | 34 + build/appveyor/CYGW-appveyor-test.bat | 21 + build/appveyor/MING-appveyor-build.bat | 11 +- build/appveyor/MING-appveyor-install.bat | 42 +- build/appveyor/MING-appveyor-test.bat | 10 +- build/appveyor/MSVC-appveyor-install.bat | 46 +- build/appveyor/MSVC-appveyor-test.bat | 13 +- build/appveyor/MSYS-appveyor-build.bat | 3 +- build/appveyor/MSYS-appveyor-install.bat | 21 +- build/appveyor/build-libevent.bat | 17 +- build/appveyor/build-zlib.bat | 15 +- build/appveyor/cl_setcompiler.bat | 10 +- build/appveyor/cl_setenv.bat | 125 +- build/appveyor/cl_setgenerator.bat | 11 +- build/appveyor/cl_showenv.bat | 15 +- build/appveyor/simulate-appveyor.bat | 2 +- build/cmake/ConfigureChecks.cmake | 4 +- build/cmake/DefinePlatformSpecifc.cmake | 1 + build/cmake/config.h.in | 10 +- build/docker/README.md | 98 +- build/docker/scripts/autotools.sh | 4 - build/docker/scripts/sca.sh | 5 +- build/docker/ubuntu-artful/Dockerfile | 59 +- build/docker/ubuntu-trusty/Dockerfile | 12 +- build/docker/ubuntu-xenial/Dockerfile | 44 +- compiler/cpp/Makefile.am | 3 +- compiler/cpp/src/thrift/audit/t_audit.cpp | 4 +- .../src/thrift/generate/t_as3_generator.cc | 8 +- .../src/thrift/generate/t_c_glib_generator.cc | 8 +- .../cpp/src/thrift/generate/t_cl_generator.cc | 556 ++++ .../src/thrift/generate/t_cocoa_generator.cc | 16 +- .../src/thrift/generate/t_cpp_generator.cc | 16 +- .../src/thrift/generate/t_csharp_generator.cc | 10 +- .../cpp/src/thrift/generate/t_d_generator.cc | 8 +- .../src/thrift/generate/t_dart_generator.cc | 8 +- .../src/thrift/generate/t_delphi_generator.cc | 38 +- .../src/thrift/generate/t_erl_generator.cc | 46 +- .../cpp/src/thrift/generate/t_generator.h | 29 +- .../cpp/src/thrift/generate/t_go_generator.cc | 85 +- .../cpp/src/thrift/generate/t_gv_generator.cc | 4 +- .../src/thrift/generate/t_haxe_generator.cc | 8 +- .../cpp/src/thrift/generate/t_hs_generator.cc | 8 +- .../src/thrift/generate/t_html_generator.cc | 8 +- .../src/thrift/generate/t_java_generator.cc | 18 +- .../src/thrift/generate/t_javame_generator.cc | 8 +- .../cpp/src/thrift/generate/t_js_generator.cc | 12 +- .../src/thrift/generate/t_json_generator.cc | 4 +- .../src/thrift/generate/t_lua_generator.cc | 8 +- .../thrift/generate/t_netcore_generator.cc | 64 +- .../src/thrift/generate/t_ocaml_generator.cc | 8 +- .../src/thrift/generate/t_perl_generator.cc | 8 +- .../src/thrift/generate/t_php_generator.cc | 72 +- .../cpp/src/thrift/generate/t_py_generator.cc | 14 +- .../cpp/src/thrift/generate/t_rb_generator.cc | 8 +- .../cpp/src/thrift/generate/t_rs_generator.cc | 4 +- .../cpp/src/thrift/generate/t_st_generator.cc | 8 +- .../src/thrift/generate/t_swift_generator.cc | 16 +- .../src/thrift/generate/t_xml_generator.cc | 4 +- .../thrift-t_php_generator.o-a60a38e9 | 0 compiler/cpp/src/thrift/main.cc | 8 +- compiler/cpp/src/thrift/parse/t_const_value.h | 62 +- compiler/cpp/src/thrift/parse/t_scope.h | 12 +- compiler/cpp/src/thrift/thrifty.yy | 1 + compiler/cpp/test/plugin/conversion_test.cc | 4 +- configure.ac | 25 + lib/Makefile.am | 4 + lib/cl/Makefile.am | 40 + lib/cl/README.md | 253 ++ lib/cl/READMES/readme-cassandra.lisp | 64 + lib/cl/ensure-externals.sh | 16 + lib/cl/load-locally.lisp | 23 + lib/cl/test/make-test-binary.lisp | 31 + lib/cocoa/src/protocol/TBase.h | 4 +- lib/cpp/src/thrift/TOutput.cpp | 2 +- .../src/thrift/server/TNonblockingServer.cpp | 25 +- lib/cpp/src/thrift/transport/PlatformSocket.h | 4 + .../thrift/transport/TBufferTransports.cpp | 4 +- lib/cpp/src/thrift/transport/TSSLSocket.cpp | 19 + lib/cpp/src/thrift/transport/TSSLSocket.h | 1 + lib/cpp/src/thrift/transport/TSocket.cpp | 35 +- lib/cpp/src/thrift/transport/TSocket.h | 15 +- lib/cpp/test/CMakeLists.txt | 5 +- lib/cpp/test/Makefile.am | 11 + lib/cpp/test/RenderedDoubleConstantsTest.cpp | 122 + lib/cpp/test/TNonblockingServerTest.cpp | 2 +- lib/cpp/test/concurrency/Tests.cpp | 2 +- lib/cpp/test/concurrency/TimerManagerTests.h | 34 +- lib/d/src/thrift/server/simple.d | 4 +- lib/d/src/thrift/server/taskpool.d | 4 +- lib/d/src/thrift/server/threaded.d | 4 +- lib/d/test/thrift_test_server.d | 58 +- lib/delphi/src/Thrift.Transport.pas | 2 +- lib/erl/Makefile.am | 1 + .../test/test_rendered_double_constants.erl | 68 + lib/go/Makefile.am | 2 - lib/go/README.md | 2 + lib/go/test/Makefile.am | 5 - lib/go/test/dontexportrwtest/compile_test.go | 9 +- lib/go/test/tests/client_error_test.go | 17 +- .../go17.go => lib/go/test/tests/context.go | 8 +- lib/go/test/tests/go17.go | 47 - .../test/tests/multiplexed_protocol_test.go | 13 + lib/go/test/tests/one_way_test.go | 8 + lib/go/test/tests/pre_go17.go | 48 - lib/go/test/tests/protocol_mock.go | 5 +- lib/go/test/tests/thrifttest_handler.go | 5 +- lib/go/test/tests/thrifttest_handler_go17.go | 212 -- lib/go/thrift/application_exception_test.go | 4 +- lib/go/thrift/binary_protocol.go | 5 +- lib/go/thrift/buffered_transport.go | 5 +- lib/go/thrift/client.go | 17 +- lib/go/thrift/client_go17.go | 13 - lib/go/thrift/client_pre_go17.go | 13 - .../{common_test_go17.go => common_test.go} | 2 - lib/go/thrift/common_test_pre_go17.go | 32 - lib/go/thrift/compact_protocol.go | 7 +- lib/go/thrift/{go17.go => context.go} | 2 - lib/go/thrift/debug_protocol.go | 5 +- lib/go/thrift/framed_transport.go | 5 +- lib/go/thrift/http_client.go | 6 +- lib/go/thrift/http_transport.go | 12 + lib/go/thrift/http_transport_go17.go | 38 - lib/go/thrift/http_transport_pre_go17.go | 40 - lib/go/thrift/iostream_transport.go | 3 +- lib/go/thrift/json_protocol.go | 5 +- lib/go/thrift/json_protocol_test.go | 41 +- lib/go/thrift/memory_buffer.go | 3 +- lib/go/thrift/multiplexed_protocol.go | 31 + lib/go/thrift/multiplexed_protocol_go17.go | 53 - .../thrift/multiplexed_protocol_pre_go17.go | 54 - lib/go/thrift/pre_go17.go | 26 - lib/go/thrift/processor.go | 34 - lib/go/thrift/processor_factory.go | 12 + lib/go/thrift/processor_go17.go | 34 - lib/go/thrift/protocol.go | 3 +- lib/go/thrift/protocol_test.go | 51 +- lib/go/thrift/serializer.go | 16 +- lib/go/thrift/serializer_test.go | 5 +- lib/go/thrift/simple_json_protocol.go | 5 +- lib/go/thrift/simple_json_protocol_test.go | 49 +- lib/go/thrift/socket.go | 3 +- lib/go/thrift/ssl_socket.go | 3 +- lib/go/thrift/transport.go | 9 +- lib/go/thrift/transport_test.go | 7 +- lib/go/thrift/zlib_transport.go | 5 +- lib/java/gradle/generateTestThrift.gradle | 1 + .../apache/thrift/AsyncProcessFunction.java | 1 - .../org/apache/thrift/TAsyncProcessor.java | 9 +- .../src/org/apache/thrift/TEnumHelper.java | 1 - .../thrift/server/TThreadPoolServer.java | 35 +- .../transport/TSSLTransportFactory.java | 68 +- .../thrift/transport/TSaslTransport.java | 4 +- lib/java/test/org/apache/thrift/Fixtures.java | 2 +- .../thrift/TestRenderedDoubleConstants.java | 179 ++ .../test/org/apache/thrift/TestReuse.java | 3 - .../thrift/protocol/TestTProtocolUtil.java | 14 - .../protocol/TestTSimpleJSONProtocol.java | 2 +- .../apache/thrift/server/ServerTestBase.java | 7 +- .../transport/TestTSSLTransportFactory.java | 10 +- ...TestTSSLTransportFactoryStreamedStore.java | 62 + lib/js/Gruntfile.js | 76 +- lib/js/package-lock.json | 2285 +++++++++++++++++ lib/js/package.json | 8 +- lib/js/src/thrift.js | 10 +- lib/js/test/build.xml | 10 +- lib/js/test/deep-constructor.test.js | 22 +- lib/js/test/jsTestDriver.conf | 1 + lib/js/test/test-deep-constructor.html | 6 +- lib/js/test/test-double-rendering.html | 55 + lib/js/test/test-double-rendering.js | 143 ++ lib/nodejs/README.md | 2 +- lib/nodejs/lib/thrift/binary_protocol.js | 5 +- lib/nodejs/test/browser_client.js | 45 - lib/nodejs/test/testAll.sh | 14 - lib/perl/lib/Thrift/Server.pm | 38 +- lib/perl/lib/Thrift/ServerSocket.pm | 15 +- lib/php/README.md | 33 +- lib/php/lib/Transport/TSocket.php | 1 + .../test/JsonSerialize/JsonSerializeTest.php | 9 +- lib/php/test/Makefile.am | 4 +- .../test/Protocol/BinarySerializerTest.php | 9 +- lib/php/test/Protocol/TJSONProtocolTest.php | 9 +- .../test/Protocol/TSimpleJSONProtocolTest.php | 10 +- lib/php/test/Validator/ValidatorTest.php | 9 +- lib/php/test/Validator/ValidatorTestOop.php | 7 +- lib/py/setup.py | 5 +- lib/rs/src/transport/framed.rs | 318 ++- package-lock.json | 2028 +++++++++++++++ package.json | 16 +- test/DoubleConstantsTest.thrift | 17 + test/Makefile.am | 7 + test/cl/Makefile.am | 42 + test/cl/implementation.lisp | 136 + test/cl/make-test-client.lisp | 93 + test/cl/make-test-server.lisp | 80 + test/cl/tests.lisp | 240 ++ test/cpp/src/TestServer.cpp | 64 +- test/crossrunner/collect.py | 4 +- test/crossrunner/report.py | 10 +- test/crossrunner/run.py | 206 +- test/crossrunner/test.py | 10 +- test/crossrunner/util.py | 4 + test/features/known_failures_Linux.json | 4 +- test/go/Makefile.am | 4 - test/go/src/bin/stress/go17.go | 62 - test/go/src/bin/stress/main.go | 36 + test/go/src/bin/stress/pre_go17.go | 63 - test/go/src/bin/testclient/go17.go | 26 - test/go/src/bin/testclient/main.go | 2 + test/go/src/bin/testclient/pre_go17.go | 26 - test/go/src/common/clientserver_test.go | 46 +- test/go/src/common/context_test.go | 98 + test/go/src/common/go17.go | 26 - test/go/src/common/pre_go17.go | 26 - test/go/src/common/printing_handler.go | 11 +- test/go/src/common/printing_handler_go17.go | 386 --- test/known_failures_Linux.json | 44 +- test/perl/TestServer.pl | 8 + test/php/Makefile.am | 6 +- test/php/{TestPsr4.php => TestClassmap.php} | 2 +- test/php/TestClient.php | 14 +- test/py/Makefile.am | 7 + test/py/RunClientServer.py | 1 + test/py/TestRenderedDoubleConstants.py | 177 ++ test/py/generate.cmake | 7 + test/test.py | 21 +- test/tests.json | 30 +- tutorial/Makefile.am | 4 + tutorial/cl/Makefile.am | 47 + tutorial/cl/make-tutorial-client.lisp | 51 + tutorial/cl/make-tutorial-server.lisp | 29 + tutorial/cl/shared-implementation.lisp | 25 + tutorial/cl/thrift-tutorial.asd | 17 + tutorial/cl/tutorial-implementation.lisp | 41 + tutorial/go/Makefile.am | 10 - tutorial/go/src/client.go | 3 + tutorial/go/src/handler.go | 5 +- tutorial/go/src/handler_go17.go | 104 - tutorial/go/src/pre_go17.go | 26 - tutorial/shared.thrift | 1 + tutorial/tutorial.thrift | 2 + 247 files changed, 9349 insertions(+), 2640 deletions(-) create mode 100644 build/appveyor/CYGW-appveyor-build.bat create mode 100644 build/appveyor/CYGW-appveyor-install.bat create mode 100644 build/appveyor/CYGW-appveyor-test.bat create mode 100644 compiler/cpp/src/thrift/generate/t_cl_generator.cc create mode 100644 compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9 create mode 100644 lib/cl/Makefile.am create mode 100644 lib/cl/README.md create mode 100644 lib/cl/READMES/readme-cassandra.lisp create mode 100755 lib/cl/ensure-externals.sh create mode 100644 lib/cl/load-locally.lisp create mode 100644 lib/cl/test/make-test-binary.lisp create mode 100644 lib/cpp/test/RenderedDoubleConstantsTest.cpp create mode 100644 lib/erl/test/test_rendered_double_constants.erl rename tutorial/go/src/go17.go => lib/go/test/tests/context.go (94%) delete mode 100644 lib/go/test/tests/go17.go delete mode 100644 lib/go/test/tests/pre_go17.go delete mode 100644 lib/go/test/tests/thrifttest_handler_go17.go delete mode 100644 lib/go/thrift/client_go17.go delete mode 100644 lib/go/thrift/client_pre_go17.go rename lib/go/thrift/{common_test_go17.go => common_test.go} (98%) delete mode 100644 lib/go/thrift/common_test_pre_go17.go rename lib/go/thrift/{go17.go => context.go} (98%) delete mode 100644 lib/go/thrift/http_transport_go17.go delete mode 100644 lib/go/thrift/http_transport_pre_go17.go delete mode 100644 lib/go/thrift/multiplexed_protocol_go17.go delete mode 100644 lib/go/thrift/multiplexed_protocol_pre_go17.go delete mode 100644 lib/go/thrift/pre_go17.go delete mode 100644 lib/go/thrift/processor.go delete mode 100644 lib/go/thrift/processor_go17.go create mode 100644 lib/java/test/org/apache/thrift/TestRenderedDoubleConstants.java create mode 100644 lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactoryStreamedStore.java create mode 100644 lib/js/package-lock.json create mode 100644 lib/js/test/test-double-rendering.html create mode 100644 lib/js/test/test-double-rendering.js delete mode 100644 lib/nodejs/test/browser_client.js create mode 100644 package-lock.json create mode 100644 test/DoubleConstantsTest.thrift create mode 100755 test/cl/Makefile.am create mode 100644 test/cl/implementation.lisp create mode 100644 test/cl/make-test-client.lisp create mode 100644 test/cl/make-test-server.lisp create mode 100644 test/cl/tests.lisp delete mode 100644 test/go/src/bin/stress/go17.go delete mode 100644 test/go/src/bin/stress/pre_go17.go delete mode 100644 test/go/src/bin/testclient/go17.go delete mode 100644 test/go/src/bin/testclient/pre_go17.go create mode 100644 test/go/src/common/context_test.go delete mode 100644 test/go/src/common/go17.go delete mode 100644 test/go/src/common/pre_go17.go delete mode 100644 test/go/src/common/printing_handler_go17.go rename test/php/{TestPsr4.php => TestClassmap.php} (96%) create mode 100644 test/py/TestRenderedDoubleConstants.py create mode 100755 tutorial/cl/Makefile.am create mode 100644 tutorial/cl/make-tutorial-client.lisp create mode 100644 tutorial/cl/make-tutorial-server.lisp create mode 100644 tutorial/cl/shared-implementation.lisp create mode 100644 tutorial/cl/thrift-tutorial.asd create mode 100644 tutorial/cl/tutorial-implementation.lisp delete mode 100644 tutorial/go/src/handler_go17.go delete mode 100644 tutorial/go/src/pre_go17.go diff --git a/.gitignore b/.gitignore index 03e3e9e61de..66193db3ede 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,6 @@ node_modules compile test-driver erl_crash.dump -package-lock.json project.lock.json .sonar @@ -101,6 +100,9 @@ project.lock.json /contrib/fb303/py/fb303/ttypes.py /depcomp /install-sh +/lib/cl/backport-update.zip +/lib/cl/lib +/lib/cl/run-tests /lib/cpp/Debug/ /lib/cpp/Debug-mt/ /lib/cpp/Release/ @@ -235,7 +237,6 @@ project.lock.json /lib/java/target /lib/js/dist /lib/js/doc -/lib/js/package-lock.json /lib/js/test/build /lib/netcore/**/.vs /lib/netcore/**/bin @@ -307,6 +308,8 @@ project.lock.json /test/results.json /test/c_glib/test_client /test/c_glib/test_server +/test/cl/TestServer +/test/cl/TestClient /test/cpp/StressTest /test/cpp/StressTestNonBlocking /test/cpp/TestClient @@ -348,6 +351,8 @@ project.lock.json /test/rs/target/ /test/rs/*.iml /test/rs/**/*.iml +/tutorial/cl/TutorialClient +/tutorial/cl/TutorialServer /tutorial/cpp/TutorialClient /tutorial/cpp/TutorialServer /tutorial/c_glib/tutorial_client @@ -395,3 +400,7 @@ project.lock.json /tutorial/rs/target /tutorial/rs/Cargo.lock /ylwrap +/lib/cl/quicklisp.lisp +/lib/cl/externals/ +/lib/cl/run-tests +/lib/cl/quicklisp/ diff --git a/.travis.yml b/.travis.yml index 9735f43e474..2816facc9d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,6 @@ install: - if [[ `uname` == "Linux" ]]; then build/docker/refresh.sh; fi stages: -# - osx # up front for now (for testing) - docker # docker images - thrift # thrift build jobs @@ -44,7 +43,7 @@ env: - SCRIPT="cmake.sh" - BUILD_ARG="" - BUILD_ENV="-e CC=gcc -e CXX=g++ -e THRIFT_CROSSTEST_CONCURRENCY=4" - - DISTRO=ubuntu-xenial + - DISTRO=ubuntu-artful - BUILD_LIBS="CPP C_GLIB HASKELL JAVA PYTHON TESTING TUTORIALS" # only meaningful for CMake builds - TRAVIS_BUILD_STAGE=test # DOCKER_REPO (this works for all builds as a source for docker images - you can override for fork builds in your Travis settings) @@ -54,20 +53,9 @@ env: jobs: include: - # ------------------------- phase: osx -------------------------- - # - stage: osx - # os: osx - # osx_image: xcode9 - # script: build/docker/scripts/autotools.sh - # ========================= stage: docker ========================= - stage: docker script: true - env: - - JOB="Docker Build ubuntu-trusty 14.04" - - DISTRO=ubuntu-trusty - - TRAVIS_BUILD_STAGE=docker - - script: true env: - JOB="Docker Build ubuntu-xenial 16.04" - DISTRO=ubuntu-xenial @@ -120,7 +108,6 @@ jobs: env: - JOB="Static Code Analysis" - SCRIPT="sca.sh" - - DISTRO=ubuntu-artful # C and C++ undefined behavior. # A binary crashes if undefined behavior occurs and produces a stack trace. @@ -129,13 +116,12 @@ jobs: env: - JOB="UBSan" - SCRIPT="ubsan.sh" - - DISTRO=ubuntu-artful - BUILD_ARG="--without-python --without-py3" # ------------------------- phase: cmake ------------------------ - script: build/docker/run.sh env: - - JOB="CMake (Ubuntu Xenial)" + - JOB="CMake" # C++ specific options: compiler plug-in, threading model - script: build/docker/run.sh @@ -168,20 +154,22 @@ jobs: - DISTRO=ubuntu-xenial - SCRIPT="autotools.sh" - - script: build/docker/run.sh - env: - - JOB="Autotools (Ubuntu Trusty)" - - DISTRO=ubuntu-trusty - - SCRIPT="autotools.sh" - # ------------------------- phase: dist ------------------------- - script: build/docker/run.sh env: - JOB="make dist" + - DISTRO=ubuntu-xenial - SCRIPT="make-dist.sh" - script: build/docker/run.sh env: - JOB="Debian Packages" + - DISTRO=ubuntu-xenial - SCRIPT="dpkg.sh" + ### ------------------------- phase: osx ------------------------- + # disabled due to the time delays it imposes on build jobs + # - os: osx + # osx_image: xcode9 + # script: build/docker/scripts/autotools.sh + diff --git a/LANGUAGES.md b/LANGUAGES.md index 7f6194e9a12..10b2e153d9c 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -1,20 +1,20 @@ # Apache Thrift Language Support # -Last Modified: 2017-10-05
-Version: 0.10.0+ +Last Modified: 2018-03-06 Thrift supports many programming languages and has an impressive test suite that exercises most of the languages, protocols, and transports that represents a matrix of thousands of possible combinations. Each language typically has a minimum required version as well as support libraries - some mandatory and some optional. All of this information is provided below to help you assess whether you can use Apache Thrift with your project. Obviously this is a complex matrix to maintain and may not be correct in all cases - if you spot an error please inform the developers using the mailing list. -Apache Thrift has a choice of two build systems. The `autoconf` build system is the most complete build and is used to build all supported languages. The `cmake` build system has been designated by the project to replace `autoconf` however this transition will take quite some time to complete. +Apache Thrift has a choice of two build systems. The `autoconf` build system is the most complete build and is used to build all supported languages. The `cmake` build system has been designated by the project to replace `autoconf` however this transition will take quite some time to complete. -The Language/Library Levels indicate the minimum and maximum versions that are used in the [continuous integration environments](build/docker/README.md) (Appveyor, Travis) for Apache Thrift. Note that while a language may contain support for protocols, transports, and servers, the extent to which each is tested as part of the overall build process varies. The definitive integration test for the project is called the "cross" test which executes a test matrix with clients and servers communicating across languages. +The Language/Library Levels indicate the minimum and maximum versions that are used in the [continuous integration environments](build/docker/README.md) (Appveyor, Travis) for Apache Thrift. Other language levels may be supported for each language, however tested less thoroughly; check the README file inside each lib directory for additional details. Note that while a language may contain support for protocols, transports, and servers, the extent to which each is tested as part of the overall build process varies. The definitive integration test for the project is called the "cross" test which executes a test matrix with clients and servers communicating across languages. - +
+ - + @@ -33,6 +33,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -43,8 +44,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -53,8 +55,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -63,6 +66,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -73,6 +77,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -82,9 +87,21 @@ The Language/Library Levels indicate the minimum and maximum versions that are u - + + - + + + + + + + + + + + + @@ -93,8 +110,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -103,6 +121,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -113,8 +132,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u - - + + + @@ -123,8 +143,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -133,8 +154,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -143,8 +165,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -153,6 +176,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -163,8 +187,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -173,6 +198,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -183,6 +209,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -193,6 +220,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -203,8 +231,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -213,8 +242,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -223,8 +253,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -233,8 +264,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -243,8 +275,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -253,8 +286,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -263,8 +297,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + - + @@ -273,6 +308,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -285,6 +321,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u + @@ -295,7 +332,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u - + diff --git a/Makefile.am b/Makefile.am index 3d71fd4b73a..205ea8258f2 100755 --- a/Makefile.am +++ b/Makefile.am @@ -54,7 +54,7 @@ empty := space := $(empty) $(empty) comma := , -CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_DOTNETCORE@ +CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_DOTNETCORE@ CROSS_LANGS_COMMA_SEPARATED = $(subst $(space),$(comma),$(CROSS_LANGS)) if WITH_PY3 diff --git a/appveyor.yml b/appveyor.yml index 4c2e36496ca..f56d65453be 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,40 +24,51 @@ version: '1.0.0-dev.{build}' shallow_clone: true os: - - Visual Studio 2015 + - Visual Studio 2017 -cache: - - C:\projects\thrift\buildcache -> build\appveyor\MSVC-appveyor-install.bat - - C:\ProgramData\chocolatey\lib -> build\appveyor\MSVC-appveyor-install.bat - - C:\msys64\var\cache\pacman -> build\appveyor\MSYS-appveyor-install.bat +matrix: + allow_failures: + - PROFILE: CYGWIN + fast_finish: true environment: matrix: - - PROFILE: MSVC2010 - PLATFORM: x86 - CONFIGURATION: Debug - BOOST_VERSION: 1.54.0 - LIBEVENT_VERSION: 2.0.22 - QT_VERSION: 5.6 - ZLIB_VERSION: 1.2.8 + - PROFILE: MSVC2017 + PLATFORM: x64 + CONFIGURATION: Release + BOOST_VERSION: 1.65.1 + LIBEVENT_VERSION: 2.1.8 + PYTHON_VERSION: 3.6 + QT_VERSION: 5.10 + ZLIB_VERSION: 1.2.11 DISABLED_TESTS: StressTestNonBlocking + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - - PROFILE: MSVC2015 - PLATFORM: x64 + - PROFILE: MSVC2013 + PLATFORM: x86 CONFIGURATION: Release - BOOST_VERSION: 1.64.0 + BOOST_VERSION: 1.58.0 LIBEVENT_VERSION: 2.0.22 - PYTHON_VERSION: 3.6 + PYTHON_VERSION: 3.5 QT_VERSION: 5.8 - ZLIB_VERSION: 1.2.11 + ZLIB_VERSION: 1.2.8 DISABLED_TESTS: StressTestNonBlocking + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - PROFILE: MINGW PLATFORM: x64 - CONFIGURATION: Release + CONFIGURATION: RelWithDebInfo + DISABLED_TESTS: StressTestNonBlocking -matrix: - fast_finish: true + - PROFILE: CYGWIN + PLATFORM: x86 + CONFIGURATION: RelWithDebInfo + DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) + +# - PROFILE: CYGWIN +# PLATFORM: x64 +# CONFIGURATION: RelWithDebInfo +# DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) install: - cd %APPVEYOR_BUILD_FOLDER% @@ -88,14 +99,14 @@ test_script: # # enables RDP for each build job so you can inspect the environment at the beginning of the job: # init: -# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) # # enables RDP at the end of the build job so you can login and re-run # commands to see why something failed... #on_finish: # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) # -# also need: +# also need # environment: -# APPVEYOR_RDP_PASSWORD: thr1FT2345$xyzZ +# APPVEYOR_RDP_PASSWORD: thr1FT2345$xyzZ diff --git a/build/appveyor/CYGW-appveyor-build.bat b/build/appveyor/CYGW-appveyor-build.bat new file mode 100644 index 00000000000..c226222941e --- /dev/null +++ b/build/appveyor/CYGW-appveyor-build.bat @@ -0,0 +1,36 @@ +:: +:: Licensed 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. +:: + +@ECHO OFF +SETLOCAL EnableDelayedExpansion + +CD build\appveyor || EXIT /B +CALL cl_banner_build.bat || EXIT /B +CALL cl_setenv.bat || EXIT /B + +SET CMAKEARGS=^ + -G'%GENERATOR%' ^ + -DCMAKE_BUILD_TYPE=%CONFIGURATION% ^ + -DCMAKE_INSTALL_PREFIX=%INSTDIR% ^ + -DCMAKE_CXX_EXTENSIONS=ON ^ + -DCMAKE_CXX_FLAGS="-D_GNU_SOURCE" ^ + -DCMAKE_CXX_STANDARD=11 ^ + -DWITH_PYTHON=OFF ^ + -DWITH_SHARED_LIB=OFF ^ + -DWITH_STATIC_LIB=ON ^ + -DWITH_STDTHREADS=ON + +@ECHO ON +%BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B +@ECHO OFF diff --git a/build/appveyor/CYGW-appveyor-install.bat b/build/appveyor/CYGW-appveyor-install.bat new file mode 100644 index 00000000000..77db7d40a7e --- /dev/null +++ b/build/appveyor/CYGW-appveyor-install.bat @@ -0,0 +1,34 @@ +:: +:: Licensed 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. +:: + +:: +:: Appveyor install script for CYGWIN +:: Installs third party packages we need for a cmake build +:: + +@ECHO OFF +SETLOCAL EnableDelayedExpansion + +CD build\appveyor || EXIT /B +CALL cl_banner_install.bat || EXIT /B +CALL cl_setenv.bat || EXIT /B +CALL cl_showenv.bat || EXIT /B + +:: +:: Install apt-cyg for package management +:: + +%BASH% -lc "wget rawgit.com/transcode-open/apt-cyg/master/apt-cyg && install apt-cyg /bin && rm -f apt-cyg" || EXIT /B +%BASH% -lc "apt-cyg update" || EXIT /B +%BASH% -lc "apt-cyg install bison cmake flex gcc-g++ libboost-devel libevent-devel make openssl-devel zlib-devel" diff --git a/build/appveyor/CYGW-appveyor-test.bat b/build/appveyor/CYGW-appveyor-test.bat new file mode 100644 index 00000000000..b667f9bb1e4 --- /dev/null +++ b/build/appveyor/CYGW-appveyor-test.bat @@ -0,0 +1,21 @@ +:: +:: Licensed 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. +:: + +@ECHO OFF +SETLOCAL EnableDelayedExpansion +CD build\appveyor || EXIT /B +CALL cl_banner_test.bat || EXIT /B +CALL cl_setenv.bat || EXIT /B + +%BASH% -lc "cd %BUILDDIR% && ctest.exe -C %CONFIGURATION% --timeout 300 -VV -E '%DISABLED_TESTS%'" || EXIT /B diff --git a/build/appveyor/MING-appveyor-build.bat b/build/appveyor/MING-appveyor-build.bat index 838e42880c6..6ebdb906e7f 100644 --- a/build/appveyor/MING-appveyor-build.bat +++ b/build/appveyor/MING-appveyor-build.bat @@ -22,15 +22,14 @@ CALL cl_setenv.bat || EXIT /B SET CMAKEARGS=^ -G'%GENERATOR%' ^ -DCMAKE_BUILD_TYPE=%CONFIGURATION% ^ - -DCMAKE_INSTALL_PREFIX=%INSTDIR_MSYS% ^ - -DCMAKE_MAKE_PROGRAM=/mingw64/bin/mingw32-make ^ - -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc.exe ^ - -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++.exe ^ - -DWITH_LIBEVENT=OFF ^ + -DCMAKE_INSTALL_PREFIX=%INSTDIR% ^ + -DCMAKE_MAKE_PROGRAM=/mingw%NORM_PLATFORM%/bin/mingw32-make ^ + -DCMAKE_C_COMPILER=/mingw%NORM_PLATFORM%/bin/gcc.exe ^ + -DCMAKE_CXX_COMPILER=/mingw%NORM_PLATFORM%/bin/g++.exe ^ -DWITH_PYTHON=OFF ^ -DWITH_SHARED_LIB=OFF ^ -DWITH_STATIC_LIB=ON @ECHO ON -%BASH% -lc "mkdir -p %BUILDDIR_MSYS% && cd %BUILDDIR_MSYS% && cmake.exe %SRCDIR_MSYS% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B +%BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B @ECHO OFF diff --git a/build/appveyor/MING-appveyor-install.bat b/build/appveyor/MING-appveyor-install.bat index 0d5f99e4d04..ce8fc7d120f 100644 --- a/build/appveyor/MING-appveyor-install.bat +++ b/build/appveyor/MING-appveyor-install.bat @@ -13,9 +13,43 @@ :: :: -:: Appveyor install script for MinGW -:: Installs (or builds) third party packages we need +:: Appveyor install script for MINGW on MSYS2 +:: Installs third party packages we need for a cmake build :: -:: Same as the MSYS installation requirements -CALL build\appveyor\MSYS-appveyor-install.bat +@ECHO OFF +SETLOCAL EnableDelayedExpansion + +CD build\appveyor || EXIT /B +CALL cl_banner_install.bat || EXIT /B +CALL cl_setenv.bat || EXIT /B +CALL cl_showenv.bat || EXIT /B + +:: We're going to keep boost at a version cmake understands +SET BOOSTVER=1.64.0-3 +SET BOOSTPKG=mingw-w64-%MINGWPLAT%-boost-%BOOSTVER%-any.pkg.tar.xz +SET IGNORE=--ignore mingw-w64-x86_64-boost --ignore mingw-w64-i686-boost + +SET PACKAGES=^ + --needed -S bison flex make ^ + mingw-w64-%MINGWPLAT%-cmake ^ + mingw-w64-%MINGWPLAT%-libevent ^ + mingw-w64-%MINGWPLAT%-openssl ^ + mingw-w64-%MINGWPLAT%-toolchain ^ + mingw-w64-%MINGWPLAT%-zlib + +::mingw-w64-%MINGWPLAT%-qt5 : WAY too large (1GB download!) - tested in cygwin builds anyway + +:: Remove old packages that no longer exist to avoid an error +%BASH% -lc "pacman --noconfirm --remove libcatgets catgets || true" || EXIT /B + +:: Upgrade things +%BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B +%BASH% -lc "pacman --noconfirm -Su %IGNORE%" || EXIT /B +%BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B + +:: Install a slightly older boost (BOOSTVER) as cmake in mingw +:: does not have built-in dependencies for boost 1.66.0 yet +:: -- this cuts down on build warning output -- + +%BASH% -lc "if [[ $(pacman --query | grep '%MINGWPLAT%-boost') ^!= *"%BOOSTVER%"* ]]; then wget http://repo.msys2.org/mingw/%MINGWPLAT%/%BOOSTPKG% && pacman --noconfirm --needed -U %BOOSTPKG% && rm %BOOSTPKG%; fi" || EXIT /B diff --git a/build/appveyor/MING-appveyor-test.bat b/build/appveyor/MING-appveyor-test.bat index c37c72a9c87..499c1ff8048 100644 --- a/build/appveyor/MING-appveyor-test.bat +++ b/build/appveyor/MING-appveyor-test.bat @@ -12,5 +12,11 @@ :: limitations under the License. :: -:: Same as MSYS2 -CALL build\appveyor\MSYS-appveyor-test.bat +@ECHO OFF +SETLOCAL EnableDelayedExpansion + +CD build\appveyor || EXIT /B +CALL cl_banner_test.bat || EXIT /B +CALL cl_setenv.bat || EXIT /B + +%BASH% -lc "cd %BUILDDIR% && ctest.exe -C %CONFIGURATION% --timeout 300 -VV -E '%DISABLED_TESTS%'" || EXIT /B diff --git a/build/appveyor/MSVC-appveyor-install.bat b/build/appveyor/MSVC-appveyor-install.bat index 573700e0cc3..95008bd523d 100644 --- a/build/appveyor/MSVC-appveyor-install.bat +++ b/build/appveyor/MSVC-appveyor-install.bat @@ -26,47 +26,35 @@ CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B MKDIR "%WIN3P%" || EXIT /B -:: Install ant - this also installs the latest JDK as a dependency -:: The installation of JDK requires us to pick up PATH and JAVE_HOME from the registry -cinst -c "%BUILDCACHE%" -y ant || EXIT /B +choco feature enable -n allowGlobalConfirmation || EXIT /B + +:: Things to install when NOT running in appveyor: +IF "%APPVEYOR_BUILD_ID%" == "" ( + cup -y chocolatey || EXIT /B + cinst -c "%BUILDCACHE%" -y curl || EXIT /B + cinst -c "%BUILDCACHE%" -y 7zip || EXIT /B + cinst -c "%BUILDCACHE%" -y python3 || EXIT /B + cinst -c "%BUILDCACHE%" -y openssl.light || EXIT /B +) -:: Install bison and flex +cinst -c "%BUILDCACHE%" -y jdk8 || EXIT /B cinst -c "%BUILDCACHE%" -y winflexbison3 || EXIT /B -:: zlib +:: zlib - not available through chocolatey CD "%APPVEYOR_SCRIPTS%" || EXIT /B call build-zlib.bat || EXIT /B -:: libevent +:: libevent - not available through chocolatey CD "%APPVEYOR_SCRIPTS%" || EXIT /B call build-libevent.bat || EXIT /B -:: python packages -pip install backports.ssl_match_hostname ^ +:: python packages (correct path to pip set in cl_setenv.bat) +pip.exe ^ + install backports.ssl_match_hostname ^ ipaddress ^ + six ^ tornado ^ twisted || EXIT /B -:: msinttypes - for MSVC2010 only -SET MSINTTYPESURL=https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/msinttypes/msinttypes-r26.zip -IF "%COMPILER%" == "vc100" ( - MKDIR "%WIN3P%\msinttypes" || EXIT /B - CD "%WIN3P%\msinttypes" || EXIT /B - appveyor DownloadFile "%MSINTTYPESURL%" || EXIT /B - 7z x "msinttypes-r26.zip" || EXIT /B -) - -:: appveyor build slaves do not have MSVC2010 Boost installed -IF "%COMPILER%" == "vc100" ( - SET BITS=64 - IF "%PLATFORM%" == "x86" ( - SET BITS=32 - ) - SET BOOSTEXEURL=https://downloads.sourceforge.net/project/boost/boost-binaries/%BOOST_VERSION%/boost_%BOOST_VERSION:.=_%-msvc-10.0-!BITS!.exe - SET BOOSTEXE=C:\projects\thrift\buildcache\boost_%BOOST_VERSION:.=_%-msvc-10.0-!BITS!.exe - appveyor DownloadFile "!BOOSTEXEURL!" -FileName "!BOOSTEXE!" || EXIT /B - "!BOOSTEXE!" /dir=C:\Libraries\boost_%BOOST_VERSION:.=_% /silent || EXIT /B -) - :: Haskell (GHC) and cabal cinst -c "%BUILDCACHE%" -y ghc || EXIT /B diff --git a/build/appveyor/MSVC-appveyor-test.bat b/build/appveyor/MSVC-appveyor-test.bat index 16ee2078e37..35945792adb 100644 --- a/build/appveyor/MSVC-appveyor-test.bat +++ b/build/appveyor/MSVC-appveyor-test.bat @@ -12,14 +12,21 @@ :: limitations under the License. :: -@ECHO OFF +@ECHO ON SETLOCAL EnableDelayedExpansion CD build\appveyor || EXIT /B CALL cl_banner_test.bat || EXIT /B CALL cl_setenv.bat || EXIT /B CD "%BUILDDIR%" || EXIT /B -:: Add directories to the path to find DLLs of third party libraries so tests run -SET PATH=%BOOST_LIBRARYDIR%;%OPENSSL_ROOT%\bin;%WIN3P%\zlib-inst\bin;%PATH% +DIR C:\libraries +DIR C:\libraries\boost_1_59_0 +DIR C:\libraries\boost_1_60_0 +DIR C:\libraries\boost_1_62_0 +DIR C:\libraries\boost_1_63_0 +DIR C:\libraries\boost_1_64_0 + +:: Add directories to the path to find DLLs of third party libraries so tests run properly! +SET PATH=%BOOST_LIBRARYDIR:/=\%;%OPENSSL_ROOT%\bin;%WIN3P%\zlib-inst\bin;%PATH% ctest -C %CONFIGURATION% --timeout 300 -VV -E "(%DISABLED_TESTS%)" || EXIT /B diff --git a/build/appveyor/MSYS-appveyor-build.bat b/build/appveyor/MSYS-appveyor-build.bat index b9d8955e23d..44017295e52 100644 --- a/build/appveyor/MSYS-appveyor-build.bat +++ b/build/appveyor/MSYS-appveyor-build.bat @@ -33,12 +33,13 @@ SET CMAKEARGS=-G\"%GENERATOR%\" ^ -DCMAKE_CXX_COMPILER=g++.exe ^ -DCMAKE_MAKE_PROGRAM=make.exe ^ -DCMAKE_INSTALL_PREFIX=%INSTDIR_MSYS% ^ + -DLIBEVENT_ROOT=%LIBEVENT_ROOT% ^ -DOPENSSL_LIBRARIES=%OPENSSL_LIBRARIES% ^ -DOPENSSL_ROOT_DIR=%OPENSSL_ROOT% ^ -DOPENSSL_USE_STATIC_LIBS=ON ^ -DWITH_BOOST_STATIC=ON ^ -DWITH_JAVA=OFF ^ - -DWITH_LIBEVENT=OFF ^ + -DWITH_LIBEVENT=ON ^ -DWITH_PYTHON=%WITH_PYTHON% ^ -DWITH_SHARED_LIB=OFF ^ -DWITH_STATIC_LIB=ON diff --git a/build/appveyor/MSYS-appveyor-install.bat b/build/appveyor/MSYS-appveyor-install.bat index ff43cd37120..a818df30513 100644 --- a/build/appveyor/MSYS-appveyor-install.bat +++ b/build/appveyor/MSYS-appveyor-install.bat @@ -25,17 +25,24 @@ CALL cl_banner_install.bat || EXIT /B CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B +:: We're going to keep boost at a version cmake understands +SET BOOSTPKG=mingw-w64-x86_64-boost-1.64.0-3-any.pkg.tar.xz +SET IGNORE=--ignore mingw-w64-x86_64-boost + SET PACKAGES=^ - --needed -S bison flex ^ - make ^ - mingw-w64-x86_64-boost ^ + --needed -S bison flex make ^ mingw-w64-x86_64-cmake ^ + mingw-w64-x86_64-libevent ^ mingw-w64-x86_64-openssl ^ mingw-w64-x86_64-toolchain ^ mingw-w64-x86_64-zlib -:: omitting libevent-devel for now it is version 2.1.4 and doesn't play nice with MinGW +%BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B +%BASH% -lc "pacman --noconfirm -Su %IGNORE%" || EXIT /B +%BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B + +:: Install a slightly older boost (1.64.0) as cmake 3.10 +:: does not have built-in dependencies for boost 1.66.0 yet +:: -- this cuts down on build warning output -- +%BASH% -lc "wget http://repo.msys2.org/mingw/x86_64/%BOOSTPKG% && pacman --noconfirm --needed -U %BOOSTPKG% && rm %BOOSTPKG%" || EXIT /B -%BASH% -lc "pacman --noconfirm -Syu" || EXIT /B -%BASH% -lc "pacman --noconfirm -Su" || EXIT /B -%BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B diff --git a/build/appveyor/build-libevent.bat b/build/appveyor/build-libevent.bat index 13c74ee15f8..64b635b1e87 100644 --- a/build/appveyor/build-libevent.bat +++ b/build/appveyor/build-libevent.bat @@ -17,14 +17,21 @@ SETLOCAL EnableDelayedExpansion SET URLFILE=libevent-%LIBEVENT_VERSION%-stable.tar.gz SET URL=https://github.com/libevent/libevent/releases/download/release-%LIBEVENT_VERSION%-stable/%URLFILE% -CD %WIN3P% || EXIT /B -appveyor DownloadFile %URL% || EXIT /B -7z x %URLFILE% -so | 7z x -si -ttar > nul || EXIT /B +:: Download - support running a local build or a build in appveyor +CD "%WIN3P%" || EXIT /B +IF "%APPVEYOR_BUILD_ID%" == "" ( + curl -L -f -o "%URLFILE%" "%URL%" +) ELSE ( + appveyor DownloadFile "%URL%" +) +7z x "%URLFILE%" -so | 7z x -si -ttar > nul || EXIT /B CD "libevent-%LIBEVENT_VERSION%-stable" || EXIT /B -nmake -f Makefile.nmake || EXIT /B +nmake -f Makefile.nmake static_libs || EXIT /B + +:: in libevent 2.0 there is no nmake subdirectory in WIN32-Code, but in 2.1 there is mkdir lib || EXIT /B move *.lib lib\ || EXIT /B -move WIN32-Code\event2\* include\event2\ || EXIT /B +move WIN32-Code\event2\* include\event2\ || move WIN32-Code\nmake\event2\* include\event2\ || EXIT /B move *.h include\ || EXIT /B ENDLOCAL diff --git a/build/appveyor/build-zlib.bat b/build/appveyor/build-zlib.bat index d8811a1538f..9195726d5b7 100644 --- a/build/appveyor/build-zlib.bat +++ b/build/appveyor/build-zlib.bat @@ -24,11 +24,18 @@ SET URLFILE=%PACKAGE%.tar.gz SET URL=http://zlib.net/%URLFILE% SET FURL=http://zlib.net/fossils/%URLFILE% -:: Download +:: Download - support running a local build or a build in appveyor CD "%WIN3P%" || EXIT /B -appveyor DownloadFile "%URL%" -IF ERRORLEVEL 1 ( - appveyor DownloadFile "%FURL%" || EXIT /B +IF "%APPVEYOR_BUILD_ID%" == "" ( + curl -L -f -o "%URLFILE%" "%URL%" + IF ERRORLEVEL 1 ( + curl -L -f -o "%URLFILE%" "%FURL%" + ) +) ELSE ( + appveyor DownloadFile "%URL%" + IF ERRORLEVEL 1 ( + appveyor DownloadFile "%FURL%" || EXIT /B + ) ) 7z x "%URLFILE%" -so | 7z x -si -ttar > nul || EXIT /B diff --git a/build/appveyor/cl_setcompiler.bat b/build/appveyor/cl_setcompiler.bat index b97da7359ee..733ffc53845 100644 --- a/build/appveyor/cl_setcompiler.bat +++ b/build/appveyor/cl_setcompiler.bat @@ -20,7 +20,7 @@ :: vc110 = Visual Studio 2012 :: vc120 = Visual Studio 2013 :: vc140 = Visual Studio 2015 -:: vc150 = Visual Studio 2017 +:: vc141 = Visual Studio 2017 :: :: Honors any existing COMPILER environment variable :: setting instead of overwriting it, to allow it @@ -44,10 +44,10 @@ IF NOT "%PROFILE:~0,4%" == "MSVC" ( IF !ERRORLEVEL! == 0 (SET COMPILER=vc110) CALL :CHECK 18 IF !ERRORLEVEL! == 0 (SET COMPILER=vc120) - CALL :CHECK 19.00 + CALL :CHECK 19.0 IF !ERRORLEVEL! == 0 (SET COMPILER=vc140) - CALL :CHECK 19.10 - IF !ERRORLEVEL! == 0 (SET COMPILER=vc150) + CALL :CHECK 19.1 + IF !ERRORLEVEL! == 0 (SET COMPILER=vc141) ) IF NOT DEFINED COMPILER ( @@ -59,5 +59,5 @@ ECHO [info ] detected compiler edition %COMPILER% EXIT /B 0 :CHECK -cl /? 2>&1 | findstr /C:"Version %1%." > nul +cl /? 2>&1 | findstr /C:"Version %1%" > nul EXIT /B diff --git a/build/appveyor/cl_setenv.bat b/build/appveyor/cl_setenv.bat index e80d6b569ae..10af2d3477e 100644 --- a/build/appveyor/cl_setenv.bat +++ b/build/appveyor/cl_setenv.bat @@ -12,6 +12,8 @@ :: limitations under the License. :: +@ECHO OFF + IF "%PROFILE%" == "MSVC2010" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" %PLATFORM% ) ELSE IF "%PROFILE%" == "MSVC2012" ( @@ -21,11 +23,11 @@ ) ELSE IF "%PROFILE%" == "MSVC2015" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %PLATFORM% ) ELSE IF "%PROFILE%" == "MSVC2017" ( - CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat" %PLATFORM% + CALL :SETUPNEWERMSVC || EXIT /B ) ELSE IF "%PROFILE%" == "MINGW" ( - SET MSYS2_PATH_TYPE=stock -) ELSE IF "%PROFILE%" == "MSYS" ( - SET MSYS2_PATH_TYPE=stock + REM Supported, nothing special to do here. +) ELSE IF "%PROFILE%" == "CYGWIN" ( + REM Supported, nothing special to do here. ) ELSE ( ECHO Unsupported PROFILE=%PROFILE% or PLATFORM=%PLATFORM% EXIT /B 1 @@ -35,58 +37,93 @@ CALL cl_setcompiler.bat || EXIT /B CALL cl_setgenerator.bat || EXIT /B SET APPVEYOR_SCRIPTS=%APPVEYOR_BUILD_FOLDER%\build\appveyor -SET BUILDCACHE=%APPVEYOR_BUILD_FOLDER%\buildcache -SET BUILDDIR=%APPVEYOR_BUILD_FOLDER%\local-thrift-build -SET INSTDIR=%APPVEYOR_BUILD_FOLDER%\local-thrift-inst +SET BUILDCACHE=%APPVEYOR_BUILD_FOLDER%\..\build\cache +SET BUILDDIR=%APPVEYOR_BUILD_FOLDER%\..\build\%PROFILE%\%PLATFORM% +SET INSTDIR=%APPVEYOR_BUILD_FOLDER%\..\build\%PROFILE%\%PLATFORM% SET SRCDIR=%APPVEYOR_BUILD_FOLDER% -: PLATFORM is x64 or x86, but we want x86 to become "32" when we strip it down for paths: +:: PLATFORM is x64 or x86 +:: NORM_PLATFORM is 64 or 32 SET NORM_PLATFORM=%PLATFORM:~-2,2% IF "%NORM_PLATFORM%" == "86" (SET NORM_PLATFORM=32) -:: FindBoost needs forward slashes so cmake doesn't see something as an escaped character -SET BOOST_ROOT=C:/Libraries/boost_%BOOST_VERSION:.=_% -SET BOOST_LIBRARYDIR=%BOOST_ROOT%/lib%NORM_PLATFORM%-msvc-%COMPILER:~-3,2%.0 -SET OPENSSL_ROOT=C:\OpenSSL-Win%NORM_PLATFORM% -SET WIN3P=%APPVEYOR_BUILD_FOLDER%\thirdparty +IF "%PROFILE:~0,4%" == "MSVC" ( -:: MSVC2010 doesn't "do" std::thread -IF "%COMPILER%" == "vc100" ( - SET THREADMODEL=BOOST -) ELSE ( - SET THREADMODEL=STD -) + :: FindBoost needs forward slashes so cmake doesn't see something as an escaped character + SET BOOST_ROOT=C:/Libraries/boost_%BOOST_VERSION:.=_% + SET BOOST_LIBRARYDIR=!BOOST_ROOT!/lib%NORM_PLATFORM%-msvc-%COMPILER:~-3,2%.%COMPILER:~-1,1% + SET OPENSSL_ROOT=C:\OpenSSL-Win%NORM_PLATFORM% + SET WIN3P=%APPVEYOR_BUILD_FOLDER%\thirdparty -IF "%PYTHON_VERSION%" == "" ( - SET WITH_PYTHON=OFF -) ELSE ( - SET WITH_PYTHON=ON - SET PATH=C:\Python%PYTHON_VERSION:.=%\scripts;C:\Python%PYTHON_VERSION:.=%;!PATH! -) -IF "%CONFIGURATION%" == "Debug" (SET ZLIB_LIB_SUFFIX=d) + :: MSVC2010 doesn't "do" std::thread + IF "%COMPILER%" == "vc100" ( + SET THREADMODEL=BOOST + ) ELSE ( + SET THREADMODEL=STD + ) -IF NOT "%QT_VERSION%" == "" ( - IF /i "%PLATFORM%" == "x64" SET QTEXT=_64 - SET PATH=C:\Qt\%QT_VERSION%\%PROFILE%!QTEXT!\bin;!PATH! -) + IF "%PYTHON_VERSION%" == "" ( + SET WITH_PYTHON=OFF + ) ELSE ( + SET WITH_PYTHON=ON + IF /i "%PLATFORM%" == "x64" SET PTEXT=-x64 + SET PATH=C:\Python%PYTHON_VERSION:.=%!PTEXT!\scripts;C:\Python%PYTHON_VERSION:.=%!PTEXT!;!PATH! + ) + IF "%CONFIGURATION%" == "Debug" (SET ZLIB_LIB_SUFFIX=d) + + IF NOT "%QT_VERSION%" == "" ( + IF /i "%PLATFORM%" == "x64" SET QTEXT=_64 + SET PATH=C:\Qt\%QT_VERSION%\%PROFILE%!QTEXT!\bin;!PATH! + ) + +) ELSE IF "%PROFILE:~0,4%" == "MING" ( -IF NOT "%PROFILE:~0,4%" == "MSVC" ( + :: PLATFORM = x86 means MINGWPLAT i686 + :: PLATFORM = x64 means MINGWPLAT x86_64 + SET MINGWPLAT=x86_64 + IF "%PLATFORM%" == "x86" (SET MINGWPLAT=i686) SET BASH=C:\msys64\usr\bin\bash.exe - SET BOOST_ROOT= - SET BOOST_INCLUDEDIR=/mingw64/include - SET BOOST_LIBRARYDIR=/mingw64/lib - SET OPENSSL_LIBRARIES=/mingw64/lib - SET OPENSSL_ROOT=/mingw64 - SET WIN3P= + !BASH! -lc "sed -i '/export PATH=\/mingw32\/bin/d' ~/.bash_profile && sed -i '/export PATH=\/mingw64\/bin/d' ~/.bash_profile && echo 'export PATH=/mingw%NORM_PLATFORM%/bin:$PATH' >> ~/.bash_profile" || EXIT /B - !BASH! -lc "sed -i '/export PATH=\/mingw64\/bin/d' ~/.bash_profile && echo 'export PATH=/mingw64/bin:$PATH' >> ~/.bash_profile" || EXIT /B + SET BUILDDIR=%BUILDDIR:\=/% + SET BUILDDIR=/c!BUILDDIR:~2! + SET INSTDIR=%INSTDIR:\=/% + SET INSTDIR=/c!INSTDIR:~2! + SET SRCDIR=%SRCDIR:\=/% + SET SRCDIR=/c!SRCDIR:~2! + +) ELSE IF "%PROFILE:~0,4%" == "CYGW" ( + + SET CYGWINROOT=C:\cygwin + IF "%PLATFORM%" == "x64" (SET CYGWINROOT=!CYGWINROOT!64) + + SET BASH=!CYGWINROOT!\bin\bash.exe + SET SETUP=!CYGWINROOT!\setup-x86 + IF "%PLATFORM%" == "x64" (SET SETUP=!SETUP!_64) + SET SETUP=!SETUP!.exe + + SET BUILDDIR=%BUILDDIR:\=/% + SET BUILDDIR=/cygdrive/c!BUILDDIR:~2! + SET INSTDIR=%INSTDIR:\=/% + SET INSTDIR_CYG=/cygdrive/c!INSTDIR:~2! + SET SRCDIR=%SRCDIR:\=/% + SET SRCDIR=/cygdrive/c!SRCDIR:~2! ) -SET BUILDDIR_MSYS=%BUILDDIR:\=/% -SET BUILDDIR_MSYS=/c%BUILDDIR_MSYS:~2% -SET INSTDIR_MSYS=%INSTDIR:\=/% -SET INSTDIR_MSYS=/c%INSTDIR_MSYS:~2% -SET SRCDIR_MSYS=%SRCDIR:\=/% -SET SRCDIR_MSYS=/c%SRCDIR_MSYS:~2% +GOTO :EOF + +:SETUPNEWERMSVC + FOR /F "USEBACKQ TOKENS=*" %%i IN (`call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version "[15.0,16.0)" -property installationPath`) DO ( + IF "%MSVCROOT%" == "" (SET MSVCROOT=%%i) + ) + SET MSVCPLAT=x86 + IF "%PLATFORM%" == "x64" (SET MSVCPLAT=amd64) + + SET CURRENTDIR=%CD% + CALL "!MSVCROOT!\Common7\Tools\VsDevCmd.bat" -arch=!MSVCPLAT! || EXIT /B + CD %CURRENTDIR% + EXIT /B + +:EOF diff --git a/build/appveyor/cl_setgenerator.bat b/build/appveyor/cl_setgenerator.bat index 7ca98530f30..5eb6ff31f85 100644 --- a/build/appveyor/cl_setgenerator.bat +++ b/build/appveyor/cl_setgenerator.bat @@ -28,6 +28,7 @@ :: Optional [arch] can be "Win64" or "IA64". :: MinGW Makefiles = Generates makefiles for MinGW :: MSYS Makefiles = Generates makefiles for MSYS +:: Unix Makefiles = Generates makefiles for CYGWIN :: :: Honors any existing GENERATOR environment variable :: setting instead of overwriting it, to allow it @@ -45,6 +46,10 @@ IF DEFINED GENERATOR ( IF "%PROFILE:~0,4%" == "MING" ( SET GENERATOR=MinGW Makefiles + +) ELSE IF "%PROFILE:~0,4%" == "CYGW" ( + SET GENERATOR=Unix Makefiles + ) ELSE IF "%PROFILE:~0,4%" == "MSYS" ( SET GENERATOR=MSYS Makefiles ) ELSE ( @@ -55,9 +60,9 @@ IF "%PROFILE:~0,4%" == "MING" ( IF !ERRORLEVEL! == 0 SET GENERATOR=Visual Studio 11 2012!GENARCH! CALL :CHECK 18 IF !ERRORLEVEL! == 0 SET GENERATOR=Visual Studio 12 2013!GENARCH! - CALL :CHECK 19.00 + CALL :CHECK 19.0 IF !ERRORLEVEL! == 0 SET GENERATOR=Visual Studio 14 2015!GENARCH! - CALL :CHECK 19.10 + CALL :CHECK 19.1 IF !ERRORLEVEL! == 0 SET GENERATOR=Visual Studio 15 2017!GENARCH! ) @@ -70,5 +75,5 @@ ECHO [info ] using CMake generator %GENERATOR% EXIT /B 0 :CHECK -cl /? 2>&1 | findstr /C:"Version %1%." > nul +cl /? 2>&1 | findstr /C:"Version %1%" > nul EXIT /B diff --git a/build/appveyor/cl_showenv.bat b/build/appveyor/cl_showenv.bat index 33dd66072dd..3dda546e503 100644 --- a/build/appveyor/cl_showenv.bat +++ b/build/appveyor/cl_showenv.bat @@ -34,6 +34,7 @@ ECHO/ ECHO Our Variables ECHO ------------------------------------------------------------------------------- ECHO APPVEYOR_SCRIPTS = %APPVEYOR_SCRIPTS% +ECHO BASH = %BASH% ECHO BOOST_ROOT = %BOOST_ROOT% ECHO BOOST_INCLUDEDIR = %BOOST_INCLUDEDIR% ECHO BOOST_LIBRARYDIR = %BOOST_LIBRARYDIR% @@ -44,20 +45,16 @@ ECHO GENERATOR = %GENERATOR% ECHO INSTDIR = %INSTDIR% ECHO JAVA_HOME = %JAVA_HOME% ECHO OPENSSL_ROOT = %OPENSSL_ROOT% +ECHO SETUP = %SETUP% ECHO SRCDIR = %SRCDIR% ECHO WIN3P = %WIN3P% ECHO WITH_PYTHON = %WITH_PYTHON% ECHO ZLIB_STATIC_SUFFIX = %ZLIB_STATIC_SUFFIX% IF NOT "%PROFILE:~0,4%" == "MSVC" ( -ECHO/ -ECHO MSYS2/MinGW -ECHO ------------------------------------------------------------------------------- -ECHO BUILDDIR_MSYS = %BUILDDIR_MSYS% -ECHO INSTDIR_MSYS = %INSTDIR_MSYS% -ECHO MSYS2_PATH_TYPE = %MSYS2_PATH_TYPE% -ECHO SRCDIR_MSYS = %SRCDIR_MSYS% -ECHO PATH = -C:\msys64\usr\bin\bash -lc "echo $PATH" + ECHO/ + ECHO UNIXy PATH + ECHO ------------------------------------------------------------------------------- + %BASH% -lc "echo $PATH" ) ECHO/ ECHO Windows PATH diff --git a/build/appveyor/simulate-appveyor.bat b/build/appveyor/simulate-appveyor.bat index b32c0da1263..8674f40b7a0 100644 --- a/build/appveyor/simulate-appveyor.bat +++ b/build/appveyor/simulate-appveyor.bat @@ -16,7 +16,7 @@ :: Helps build thrift by pretending to be appveyor :: Usage: :: cd build\appveyor -:: simulate-appveyor.bat [Debug|Release] [x86|x64] [MINGW|MSVC2015] +:: simulate-appveyor.bat [Debug|Release] [x86|x64] [CYGWIN|MINGW|MSVC201?] :: @ECHO OFF diff --git a/build/cmake/ConfigureChecks.cmake b/build/cmake/ConfigureChecks.cmake index 12a50df910d..6b9c6a32f97 100644 --- a/build/cmake/ConfigureChecks.cmake +++ b/build/cmake/ConfigureChecks.cmake @@ -34,14 +34,16 @@ check_include_file(getopt.h HAVE_GETOPT_H) check_include_file(inttypes.h HAVE_INTTYPES_H) check_include_file(netdb.h HAVE_NETDB_H) check_include_file(netinet/in.h HAVE_NETINET_IN_H) +check_include_file(signal.h HAVE_SIGNAL_H) check_include_file(stdint.h HAVE_STDINT_H) check_include_file(unistd.h HAVE_UNISTD_H) check_include_file(pthread.h HAVE_PTHREAD_H) -check_include_file(sys/time.h HAVE_SYS_TIME_H) +check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H) check_include_file(sys/param.h HAVE_SYS_PARAM_H) check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H) check_include_file(sys/socket.h HAVE_SYS_SOCKET_H) check_include_file(sys/stat.h HAVE_SYS_STAT_H) +check_include_file(sys/time.h HAVE_SYS_TIME_H) check_include_file(sys/un.h HAVE_SYS_UN_H) check_include_file(sys/poll.h HAVE_SYS_POLL_H) check_include_file(sys/select.h HAVE_SYS_SELECT_H) diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index f4434891c82..8af4b6c91b5 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -90,6 +90,7 @@ elseif(UNIX) endif() add_definitions("-D__STDC_FORMAT_MACROS") +add_definitions("-D__STDC_LIMIT_MACROS") # WITH_*THREADS selects which threading library to use if(WITH_BOOSTTHREADS) diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 083bc55ec5e..c5d4d307d4b 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -91,6 +91,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_IN_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 @@ -100,8 +103,8 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PTHREAD_H 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_TIME_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_PARAM_H 1 @@ -124,6 +127,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SELECT_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SCHED_H 1 diff --git a/build/docker/README.md b/build/docker/README.md index bc6c36ab9ed..cae4577b937 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -31,9 +31,8 @@ The Travis CI (continuous integration) builds use the Ubuntu Trusty, Xenial, and ### Ubuntu ### -* trusty (legacy) * xenial (stable) -* artful (latest) +* artful (current) ## Unsupported Containers ## @@ -115,54 +114,53 @@ Open a command prompt in the image: Last updated: October 1, 2017 -| Tool | ubuntu-trusty | ubuntu-xenial | ubuntu-artful | Notes | -| :-------- | :------------ | :------------ | :------------ | :---- | -| ant | 1.9.3 | 1.9.6 | 1.9.9 | | -| autoconf | 2.69 | 2.69 | 2.69 | | -| automake | 1.14.1 | 1.15 | 1.15 | | -| bison | 3.0.2 | 3.0.4 | 3.0.4 | | -| boost | 1.54.0 | 1.58.0 | 1.63.0 | artful: stock boost 1.62.0 has problems running unit tests | -| cmake | 3.2.2 | 3.5.1 | 3.9.1 | | -| cppcheck | 1.61 | 1.72 | 1.80 | | -| flex | 2.5.35 | 2.6.0 | 2.6.1 | | -| glibc | 2.19 | 2.23 | 2.26 | | -| libevent | 2.0.21 | 2.0.21 | 2.1 | | -| libstdc++ | 4.8.4 | 5.4.0 | 7.2.0 | | -| make | 3.81 | 4.1 | 4.1 | | -| openssl | 1.0.1f | 1.0.2g | 1.0.2g | | -| qt5 | 5.2.1 | 5.5.1 | 5.9.1 | | +| Tool | ubuntu-xenial | ubuntu-artful | Notes | +| :-------- | :------------ | :------------ | :---- | +| ant | 1.9.6 | 1.9.9 | | +| autoconf | 2.69 | 2.69 | | +| automake | 1.15 | 1.15 | | +| bison | 3.0.4 | 3.0.4 | | +| boost | 1.58.0 | 1.63.0 | artful: stock boost 1.62.0 has problems running unit tests | +| cmake | 3.5.1 | 3.9.1 | | +| cppcheck | 1.72 | 1.80 | | +| flex | 2.6.0 | 2.6.1 | | +| glibc | 2.23 | 2.26 | | +| libevent | 2.0.21 | 2.1 | | +| libstdc++ | 5.4.0 | 7.2.0 | | +| make | 4.1 | 4.1 | | +| openssl | 1.0.2g | 1.0.2g | | +| qt5 | 5.5.1 | 5.9.1 | | ## Compiler/Language Versions per Dockerfile ## -| Language | ubuntu-trusty | ubuntu-xenial | ubuntu-artful | Notes | -| :-------- | :------------ | :------------ | :------------ | :---- | -| as of | Oct 01, 2017 | Jan 29, 2018 | Jan 29, 2018 | | -| as3 | | | | Not in CI | -| C++ gcc | 4.8.4 | 5.4.0 | 7.2.0 | | -| C++ clang | 3.4 | 3.8 | 4.0 | | -| C# (mono) | 3.2.8.0 | 4.2.1.0 | 4.6.2.7 | | -| c_glib | 2.40.2 | 2.48.2 | 2.54.0 | | -| cocoa | | | | Not in CI | -| d | 2.070.2 | 2.073.2 | 2.077.1 | | -| dart | 1.20.1 | 1.22.1 | 1.24.3 | | -| delphi | | | | Not in CI | -| dotnet | | 2.1.4 | 2.1.4 | v2.1.4 SDK uses v2.0.5 Runtime | -| erlang | R16B03 | 18.3 | 20.0.4 | | -| go | 1.2.1 | 1.6.2 | 1.8.3 | | -| haskell | 7.6.3 | 7.10.3 | 8.0.2 | | -| haxe | | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 | -| java | 1.7.0_151 | 1.8.0_151 | 1.8.0_151 | | -| js | | | | Unsure how to look for version info? | -| lua | 5.1.5 | 5.2.4 | 5.2.4 | Lua 5.3: see THRIFT-4386 | -| nodejs | | 4.2.6 | 8.9.4 | trusty has node.js 0.10.0 which is too old | -| ocaml | | 4.02.3 | 4.04.0 | | -| perl | 5.18.2 | 5.22.1 | 5.26.0 | | -| php | 5.5.9 | 7.0.22 | 7.1.11 | | -| python | 2.7.6 | 2.7.12 | 2.7.14 | | -| python3 | 3.4.3 | 3.5.2 | 3.6.3 | | -| ruby | 1.9.3p484 | 2.3.1p112 | 2.3.3p222 | | -| rust | 1.15.1 | 1.17.0 | 1.21.0 | | -| smalltalk | | | | Not in CI | -| swift | | | | Not in CI | - - +| Language | ubuntu-xenial | ubuntu-artful | Notes | +| :-------- | :------------ | :------------ | :---- | +| as of | Mar 06, 2018 | Mar 19, 2018 | | +| as3 | | | Not in CI | +| C++ gcc | 5.4.0 | 7.2.0 | | +| C++ clang | 3.8 | 4.0 | | +| C# (mono) | 4.2.1.0 | 4.6.2.7 | | +| c_glib | 2.48.2 | 2.54.0 | | +| cl (sbcl) | | 1.4.5 | | +| cocoa | | | Not in CI | +| d | 2.073.2 | 2.077.1 | | +| dart | 1.22.1 | 1.24.3 | | +| delphi | | | Not in CI | +| dotnet | 2.1.4 | 2.1.4 | v2.1.4 SDK uses v2.0.5 Runtime | +| erlang | 18.3 | 20.0.4 | | +| go | 1.7.6 | 1.10 | | +| haskell | 7.10.3 | 8.0.2 | | +| haxe | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 | +| java | 1.8.0_151 | 1.8.0_151 | | +| js | | | Unsure how to look for version info? | +| lua | 5.2.4 | 5.2.4 | Lua 5.3: see THRIFT-4386 | +| nodejs | 6.13.0 | 8.9.4 | | +| ocaml | | 4.04.0 | THRIFT-4517: ocaml 4.02.3 on xenial appears broken | +| perl | 5.22.1 | 5.26.0 | | +| php | 7.0.22 | 7.1.11 | | +| python | 2.7.12 | 2.7.14 | | +| python3 | 3.5.2 | 3.6.3 | | +| ruby | 2.3.1p112 | 2.3.3p222 | | +| rust | 1.17.0 | 1.21.0 | | +| smalltalk | | | Not in CI | +| swift | | | Not in CI | diff --git a/build/docker/scripts/autotools.sh b/build/docker/scripts/autotools.sh index 67e4f2d1928..8388f728ce2 100755 --- a/build/docker/scripts/autotools.sh +++ b/build/docker/scripts/autotools.sh @@ -1,10 +1,6 @@ #!/bin/sh set -ev -# haxe hxcpp > 3.4.188 will enable c++11 by default, and break the -# build when compiling C files with clang++ by adding -std=c++11 -export HXCPP_NO_CPP11=1 - ./bootstrap.sh ./configure $* make check -j3 diff --git a/build/docker/scripts/sca.sh b/build/docker/scripts/sca.sh index 886548cf746..f17f7035dc4 100755 --- a/build/docker/scripts/sca.sh +++ b/build/docker/scripts/sca.sh @@ -50,9 +50,8 @@ flake8 --ignore=E501,E722 test/crossrunner flake8 test/features # PHP code style -### causing build failures like https://travis-ci.org/apache/thrift/jobs/341109387 -### composer install --quiet -### ./vendor/bin/phpcs +composer install --quiet +./vendor/bin/phpcs # TODO etc echo FIXMEs: `grep -r FIXME * | wc -l` diff --git a/build/docker/ubuntu-artful/Dockerfile b/build/docker/ubuntu-artful/Dockerfile index d8e7e12f1f0..78d97611e7a 100644 --- a/build/docker/ubuntu-artful/Dockerfile +++ b/build/docker/ubuntu-artful/Dockerfile @@ -18,7 +18,9 @@ # - dart: does not come with Ubuntu # - dotnet: does not come with Ubuntu # - haxe: version 3.4.2 that comes with Ubuntu cores in our CI build +# - go: xenial comes with 1.8, we want the latest (supported) # - nodejs: want v8, Ubuntu comes with v6 +# FROM buildpack-deps:artful-scm MAINTAINER Apache Thrift @@ -41,11 +43,6 @@ RUN apt-get update && \ # RUN echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \ # apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF -# D -RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \ - wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \ - wget -qO - https://dlang.org/d-keyring.gpg | apt-key add - - # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ @@ -60,7 +57,7 @@ RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /et RUN add-apt-repository ppa:haxe/releases -y # node.js -RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - \ +RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ echo "deb https://deb.nodesource.com/node_8.x artful main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies @@ -95,25 +92,30 @@ RUN apt-get install -y --no-install-recommends \ `# csharp (mono) dependencies` \ mono-devel -ENV D_VERSION 2.077.1-0.1 -RUN apt-get install -y --no-install-recommends \ - `# D dependencies` \ - dmd-bin=$D_VERSION \ - libphobos2-dev=$D_VERSION \ - dmd-compiler=$D_VERSION \ - dmd-tools=$D_VERSION \ - dub \ - dfmt \ - dscanner \ - libevent-dev \ - libssl-dev \ - xdg-utils -RUN mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ +ENV SBCL_VERSION 1.4.5 +RUN \ +`# Common Lisp (sbcl) dependencies` \ + curl --version && \ + curl -O -J -L https://kent.dl.sourceforge.net/project/sbcl/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ + tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ + cd sbcl-${SBCL_VERSION}-x86-64-linux && \ + ./install.sh && \ + sbcl --version && \ + rm -rf sbcl* + +ENV D_VERSION 2.077.1 +ENV DMD_DEB dmd_2.077.1-0_amd64.deb +RUN \ +`# D dependencies` \ + wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ + dpkg --install ${DMD_DEB} && \ + rm -f ${DMD_DEB} && \ + mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \ mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \ - rm -rf libevent-master -RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \ + rm -rf libevent-master && \ + curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \ mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf openssl-master @@ -139,10 +141,15 @@ RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev -RUN apt-get install -y --no-install-recommends \ -`# golang (go) dependencies` \ - golang-go \ - golang-race-detector-runtime +# golang +ENV GOLANG_VERSION 1.10 +ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz +ENV GOLANG_DOWNLOAD_SHA256 b5a64335f1490277b585832d1f6c7f8c6c11206cba5cd3f771dcb87b98ad1a33 +RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ + echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ + tar -C /usr/local -xzf golang.tar.gz && \ + ln -s /usr/local/go/bin/go /usr/local/bin && \ + rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haskell dependencies` \ diff --git a/build/docker/ubuntu-trusty/Dockerfile b/build/docker/ubuntu-trusty/Dockerfile index 40f9c55c62a..a8e4d3baa25 100644 --- a/build/docker/ubuntu-trusty/Dockerfile +++ b/build/docker/ubuntu-trusty/Dockerfile @@ -113,9 +113,15 @@ RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev -RUN apt-get install -y --no-install-recommends \ -`# golang (go) dependencies` \ - golang-go +# golang +ENV GOLANG_VERSION 1.7.6 +ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz +ENV GOLANG_DOWNLOAD_SHA256 ad5808bf42b014c22dd7646458f631385003049ded0bb6af2efc7f1f79fa29ea +RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ + echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ + tar -C /usr/local -xzf golang.tar.gz && \ + ln -s /usr/local/go/bin/go /usr/local/bin && \ + rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haskell dependencies` \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index b37434bb7dc..ec2c849af28 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -15,12 +15,12 @@ # Using all stock Ubuntu Xenial packaging except for: # - d: does not come with Ubuntu so we're installing 2.073.2 for coverage # - dart: does not come with Ubuntu so we're installing 1.22.1 for coverage +# - dotnet: does not come with Ubuntu +# - go: Xenial comes with 1.6, but we need 1.7 or later +# - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 6.x +# - ocaml: causes stack overflow error, just started March 2018 not sure why # -# -# Known missing or disabled libraries: -# - d: deimos for libevent and openssl omitted - not compatible / build errors - FROM buildpack-deps:xenial-scm MAINTAINER Apache Thrift ENV DEBIAN_FRONTEND noninteractive @@ -58,6 +58,10 @@ RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /et echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > \ /etc/apt/sources.list.d/dotnetdev.list +# node.js +RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ + echo "deb https://deb.nodesource.com/node_6.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list + ### install general dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ `# General dependencies` \ @@ -137,10 +141,15 @@ RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev -RUN apt-get install -y --no-install-recommends \ -`# golang (go) dependencies` \ - golang-go \ - golang-race-detector-runtime +# golang +ENV GOLANG_VERSION 1.7.6 +ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz +ENV GOLANG_DOWNLOAD_SHA256 ad5808bf42b014c22dd7646458f631385003049ded0bb6af2efc7f1f79fa29ea +RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ + echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ + tar -C /usr/local -xzf golang.tar.gz && \ + ln -s /usr/local/go/bin/go /usr/local/bin && \ + rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haskell dependencies` \ @@ -173,16 +182,15 @@ RUN apt-get install -y --no-install-recommends \ RUN apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ - nodejs \ - npm && \ - ln -s /usr/bin/nodejs /usr/bin/node - -RUN apt-get install -y --no-install-recommends \ -`# OCaml dependencies` \ - ocaml \ - opam && \ - opam init --yes && \ - opam install --yes oasis + nodejs + +# THRIFT-4517: causes stack overflows; version too old; skip ocaml in xenial +# RUN apt-get install -y --no-install-recommends \ +# `# OCaml dependencies` \ +# ocaml \ +# opam && \ +# opam init --yes && \ +# opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index bd2ba800ef2..0b8ef2e7e19 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -109,7 +109,8 @@ thrift_SOURCES += src/thrift/generate/t_c_glib_generator.cc \ src/thrift/generate/t_gv_generator.cc \ src/thrift/generate/t_d_generator.cc \ src/thrift/generate/t_lua_generator.cc \ - src/thrift/generate/t_rs_generator.cc + src/thrift/generate/t_rs_generator.cc \ + src/thrift/generate/t_cl_generator.cc thrift_CPPFLAGS = -I$(srcdir)/src thrift_CXXFLAGS = -Wall -Wextra -pedantic -Werror diff --git a/compiler/cpp/src/thrift/audit/t_audit.cpp b/compiler/cpp/src/thrift/audit/t_audit.cpp index 1386f3bd1e6..ef39d60c302 100644 --- a/compiler/cpp/src/thrift/audit/t_audit.cpp +++ b/compiler/cpp/src/thrift/audit/t_audit.cpp @@ -202,8 +202,8 @@ bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructD } case t_const_value::CV_MAP: { - const std::map newMap = newStructDefault->get_map(); - const std::map oldMap = oldStructDefault->get_map(); + const std::map newMap = newStructDefault->get_map(); + const std::map oldMap = oldStructDefault->get_map(); bool defaultValuesCompare = (oldMap.size() == newMap.size()); diff --git a/compiler/cpp/src/thrift/generate/t_as3_generator.cc b/compiler/cpp/src/thrift/generate/t_as3_generator.cc index fc92de954d6..87089b44e0e 100644 --- a/compiler/cpp/src/thrift/generate/t_as3_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_as3_generator.cc @@ -471,8 +471,8 @@ void t_as3_generator::print_const_value(std::ofstream& out, } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();" << endl; if (!in_static) { @@ -516,8 +516,8 @@ void t_as3_generator::print_const_value(std::ofstream& out, } t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string val = render_const_value(out, name, vtype, v_iter->second); diff --git a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc index a7beca757a0..3ae7854f98b 100644 --- a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc @@ -997,8 +997,8 @@ void t_c_glib_generator::generate_const_initializer(string name, if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; ostringstream initializers; // initialize any constants that may be referenced by this initializer @@ -1171,8 +1171,8 @@ void t_c_glib_generator::generate_const_initializer(string name, } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; ostringstream initializers; ostringstream appenders; diff --git a/compiler/cpp/src/thrift/generate/t_cl_generator.cc b/compiler/cpp/src/thrift/generate/t_cl_generator.cc new file mode 100644 index 00000000000..e6ca177702b --- /dev/null +++ b/compiler/cpp/src/thrift/generate/t_cl_generator.cc @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2008- Patrick Collison + * Copyright (c) 2006- Facebook + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "thrift/platform.h" +#include "t_oop_generator.h" +using namespace std; + + +/** + * Common Lisp code generator. + * + * @author Patrick Collison + */ +class t_cl_generator : public t_oop_generator { + public: + t_cl_generator( + t_program* program, + const std::map& parsed_options, + const std::string& option_string) + : t_oop_generator(program) + { + no_asd = false; + system_prefix = "thrift-gen-"; + + std::map::const_iterator iter; + + for(iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { + if(iter->first.compare("no_asd") == 0) { + no_asd = true; + } else if (iter->first.compare("sys_pref") == 0) { + system_prefix = iter->second; + } else { + throw "unknown option cl:" + iter->first; + } + } + + out_dir_base_ = "gen-cl"; + copy_options_ = option_string; + } + + void init_generator(); + void close_generator(); + + void generate_typedef (t_typedef* ttypedef); + void generate_enum (t_enum* tenum); + void generate_const (t_const* tconst); + void generate_struct (t_struct* tstruct); + void generate_xception (t_struct* txception); + void generate_service (t_service* tservice); + void generate_cl_struct (std::ofstream& out, t_struct* tstruct, bool is_exception); + void generate_cl_struct_internal (std::ofstream& out, t_struct* tstruct, bool is_exception); + void generate_exception_sig(std::ofstream& out, t_function* f); + std::string render_const_value(t_type* type, t_const_value* value); + + std::string cl_autogen_comment(); + void asdf_def(std::ofstream &out); + void package_def(std::ofstream &out); + void package_in(std::ofstream &out); + std::string generated_package(); + std::string prefix(std::string name); + std::string package_of(t_program* program); + std::string package(); + std::string render_includes(); + + std::string type_name(t_type* ttype); + std::string typespec (t_type *t); + std::string function_signature(t_function* tfunction); + std::string argument_list(t_struct* tstruct); + + std::string cl_docstring(std::string raw); + + private: + + int temporary_var; + /** + * Isolate the variable definitions, as they can require structure definitions + */ + std::ofstream f_asd_; + std::ofstream f_types_; + std::ofstream f_vars_; + + std::string copy_options_; + + bool no_asd; + std::string system_prefix; +}; + + +void t_cl_generator::init_generator() { + MKDIR(get_out_dir().c_str()); + string program_dir = get_out_dir() + "/" + program_name_; + MKDIR(program_dir.c_str()); + + temporary_var = 0; + + string f_types_name = program_dir + "/" + program_name_ + "-types.lisp"; + string f_vars_name = program_dir + "/" + program_name_ + "-vars.lisp"; + + f_types_.open(f_types_name.c_str()); + f_types_ << cl_autogen_comment() << endl; + f_vars_.open(f_vars_name.c_str()); + f_vars_ << cl_autogen_comment() << endl; + + package_def(f_types_); + package_in(f_types_); + package_in(f_vars_); + + if (!no_asd) { + string f_asd_name = program_dir + "/" + system_prefix + program_name_ + ".asd"; + f_asd_.open(f_asd_name.c_str()); + f_asd_ << cl_autogen_comment() << endl; + asdf_def(f_asd_); + } +} + +/** + * Renders all the imports necessary for including another Thrift program + */ +string t_cl_generator::render_includes() { + const vector& includes = program_->get_includes(); + string result = ""; + result += ":depends-on (:thrift"; + for (size_t i = 0; i < includes.size(); ++i) { + result += " :" + system_prefix + underscore(includes[i]->get_name()); + } + result += ")\n"; + return result; +} + +string t_cl_generator::package_of(t_program* program) { + string prefix = program->get_namespace("cl"); + return prefix.empty() ? "thrift-generated" : prefix; +} + +string t_cl_generator::package() { + return package_of(program_); +} + +string t_cl_generator::prefix(string symbol) { + return "\"" + symbol + "\""; +} + +string t_cl_generator::cl_autogen_comment() { + return + std::string(";;; ") + "Autogenerated by Thrift\n" + + ";;; DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + + ";;; options string: " + copy_options_ + "\n"; +} + +string t_cl_generator::cl_docstring(string raw) { + replace(raw.begin(), raw.end(), '"', '\''); + return raw; +} + + +void t_cl_generator::close_generator() { + f_asd_.close(); + f_types_.close(); + f_vars_.close(); +} + +string t_cl_generator::generated_package() { + return program_->get_namespace("cpp"); +} + +void t_cl_generator::asdf_def(std::ofstream &out) { + out << "(asdf:defsystem #:" << system_prefix << program_name_ << endl; + indent_up(); + out << indent() << render_includes() + << indent() << ":serial t" << endl + << indent() << ":components (" + << "(:file \"" << program_name_ << "-types\") " + << "(:file \"" << program_name_ << "-vars\")))" << endl; + indent_down(); +} + +/*** + * Generate a package definition. Add use references equivalent to the idl file's include statements. + */ +void t_cl_generator::package_def(std::ofstream &out) { + const vector& includes = program_->get_includes(); + + out << "(thrift:def-package :" << package(); + if ( includes.size() > 0 ) { + out << " :use ("; + for (size_t i = 0; i < includes.size(); ++i) { + out << " :" << includes[i]->get_name(); + } + out << ")"; + } + out << ")" << endl << endl; +} + +void t_cl_generator::package_in(std::ofstream &out) { + out << "(cl:in-package :" << package() << ")" << endl << endl; +} + +/** + * Generates a typedef. This is not done in Common Lisp, types are all implicit. + * + * @param ttypedef The type definition + */ +void t_cl_generator::generate_typedef(t_typedef* ttypedef) { + (void)ttypedef; +} + +void t_cl_generator::generate_enum(t_enum* tenum) { + f_types_ << "(thrift:def-enum " << prefix(tenum->get_name()) << endl; + + vector constants = tenum->get_constants(); + vector::iterator c_iter; + int value = -1; + + indent_up(); + f_types_ << indent() << "("; + for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { + value = (*c_iter)->get_value(); + + if(c_iter != constants.begin()) f_types_ << endl << indent() << " "; + + f_types_ << "(\"" << (*c_iter)->get_name() << "\" . " << value << ")"; + } + indent_down(); + f_types_ << "))" << endl << endl; +} + +/** + * Generate a constant value + */ +void t_cl_generator::generate_const(t_const* tconst) { + t_type* type = tconst->get_type(); + string name = tconst->get_name(); + t_const_value* value = tconst->get_value(); + + f_vars_ << "(thrift:def-constant " << prefix(name) << " " << render_const_value(type, value) << ")" + << endl << endl; +} + +/** + * Prints the value of a constant with the given type. Note that type checking + * is NOT performed in this function as it is always run beforehand using the + * validate_types method in main.cc + */ +string t_cl_generator::render_const_value(t_type* type, t_const_value* value) { + type = get_true_type(type); + std::ostringstream out; + if (type->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); + switch (tbase) { + case t_base_type::TYPE_STRING: + out << "\"" << value->get_string() << "\""; + break; + case t_base_type::TYPE_BOOL: + out << (value->get_integer() > 0 ? "t" : "nil"); + break; + case t_base_type::TYPE_I8: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_I64: + out << value->get_integer(); + break; + case t_base_type::TYPE_DOUBLE: + if (value->get_type() == t_const_value::CV_INTEGER) { + out << value->get_integer(); + } else { + out << value->get_double(); + } + break; + default: + throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); + } + } else if (type->is_enum()) { + indent(out) << value->get_integer(); + } else if (type->is_struct() || type->is_xception()) { + out << (type->is_struct() ? "(make-instance '" : "(make-exception '") << + lowercase(type->get_name()) << " " << endl; + indent_up(); + + const vector& fields = ((t_struct*)type)->get_members(); + vector::const_iterator f_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; + + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + t_type* field_type = NULL; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + if ((*f_iter)->get_name() == v_iter->first->get_string()) { + field_type = (*f_iter)->get_type(); + } + } + if (field_type == NULL) { + throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); + } + + out << indent() << ":" << v_iter->first->get_string() << " " << + render_const_value(field_type, v_iter->second) << endl; + } + out << indent() << ")"; + + indent_down(); + } else if (type->is_map()) { + // emit an hash form with both keys and values to be evaluated + t_type* ktype = ((t_map*)type)->get_key_type(); + t_type* vtype = ((t_map*)type)->get_val_type(); + out << "(thrift:map "; + indent_up(); + const map& val = value->get_map(); + map::const_iterator v_iter; + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + out << endl << indent() + << "(cl:cons " << render_const_value(ktype, v_iter->first) << " " + << render_const_value(vtype, v_iter->second) << ")"; + } + indent_down(); + out << indent() << ")"; + } else if (type->is_list() || type->is_set()) { + t_type* etype; + if (type->is_list()) { + etype = ((t_list*)type)->get_elem_type(); + } else { + etype = ((t_set*)type)->get_elem_type(); + } + if (type->is_set()) { + out << "(thrift:set" << endl; + } else { + out << "(thrift:list" << endl; + } + indent_up(); + indent_up(); + const vector& val = value->get_list(); + vector::const_iterator v_iter; + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + out << indent() << render_const_value(etype, *v_iter) << endl; + } + out << indent() << ")"; + indent_down(); + indent_down(); + } else { + throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); + } + return out.str(); +} + +void t_cl_generator::generate_struct(t_struct* tstruct) { + generate_cl_struct(f_types_, tstruct, false); +} + +void t_cl_generator::generate_xception(t_struct* txception) { + generate_cl_struct(f_types_, txception, true); +} + +void t_cl_generator::generate_cl_struct_internal(std::ofstream& out, t_struct* tstruct, bool is_exception) { + (void)is_exception; + const vector& members = tstruct->get_members(); + vector::const_iterator m_iter; + + out << "("; + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_const_value* value = (*m_iter)->get_value(); + t_type* type = (*m_iter)->get_type(); + + if (m_iter != members.begin()) { + out << endl << indent() << " "; + } + out << "(" << prefix((*m_iter)->get_name()) << " " << + ( (NULL != value) ? render_const_value(type, value) : "nil" ) << + " :id " << (*m_iter)->get_key(); + if ( type->is_base_type() && "string" == typespec(type) ) + if ( ((t_base_type*)type)->is_binary() ) + out << " :type binary"; + else + out << " :type string"; + else + out << " :type " << typespec(type); + if ( (*m_iter)->get_req() == t_field::T_OPTIONAL ) { + out << " :optional t"; + } + if ( (*m_iter)->has_doc()) { + out << " :documentation \"" << cl_docstring((*m_iter)->get_doc()) << "\""; + } + out <<")"; + } + + out << ")"; +} + +void t_cl_generator::generate_cl_struct(std::ofstream& out, t_struct* tstruct, bool is_exception = false) { + std::string name = type_name(tstruct); + out << (is_exception ? "(thrift:def-exception " : "(thrift:def-struct ") << + prefix(name) << endl; + indent_up(); + if ( tstruct->has_doc() ) { + out << indent() ; + out << "\"" << cl_docstring(tstruct->get_doc()) << "\"" << endl; + } + out << indent() ; + generate_cl_struct_internal(out, tstruct, is_exception); + indent_down(); + out << ")" << endl << endl; +} + +void t_cl_generator::generate_exception_sig(std::ofstream& out, t_function* f) { + generate_cl_struct_internal(out, f->get_xceptions(), true); +} + +void t_cl_generator::generate_service(t_service* tservice) { + string extends_client; + vector functions = tservice->get_functions(); + vector::iterator f_iter; + + if (tservice->get_extends() != NULL) { + extends_client = type_name(tservice->get_extends()); + } + + extends_client = extends_client.empty() ? "nil" : prefix(extends_client); + + f_types_ << "(thrift:def-service " << prefix(service_name_) << " " + << extends_client; + + indent_up(); + + if ( tservice->has_doc()) { + f_types_ << endl << indent() + << "(:documentation \"" << cl_docstring(tservice->get_doc()) << "\")"; + } + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + t_function* function = *f_iter; + string fname = function->get_name(); + string signature = function_signature(function); + t_struct* exceptions = function->get_xceptions(); + const vector& xmembers = exceptions->get_members(); + + f_types_ << endl << indent() << "(:method " << prefix(fname); + f_types_ << " (" << signature << " " << typespec((*f_iter)->get_returntype()) << ")"; + if (xmembers.size() > 0) { + f_types_ << endl << indent() << " :exceptions " ; + generate_exception_sig(f_types_, function); + } + if ( (*f_iter)->is_oneway() ) { + f_types_ << endl << indent() << " :oneway t"; + } + if ( (*f_iter)->has_doc() ) { + f_types_ << endl << indent() << " :documentation \"" + << cl_docstring((*f_iter)->get_doc()) << "\""; + } + f_types_ << ")"; + } + + f_types_ << ")" << endl << endl; + + indent_down(); +} + +string t_cl_generator::typespec(t_type *t) { + t = get_true_type(t); + + if (t -> is_binary()){ + return "binary"; + } else if (t->is_base_type()) { + return type_name(t); + } else if (t->is_map()) { + t_map *m = (t_map*) t; + return "(thrift:map " + typespec(m->get_key_type()) + " " + + typespec(m->get_val_type()) + ")"; + } else if (t->is_struct() || t->is_xception()) { + return "(struct " + prefix(type_name(t)) + ")"; + } else if (t->is_list()) { + return "(thrift:list " + typespec(((t_list*) t)->get_elem_type()) + ")"; + } else if (t->is_set()) { + return "(thrift:set " + typespec(((t_set*) t)->get_elem_type()) + ")"; + } else if (t->is_enum()) { + return "(enum \"" + ((t_enum*) t)->get_name() + "\")"; + } else { + throw "Sorry, I don't know how to generate this: " + type_name(t); + } +} + +string t_cl_generator::function_signature(t_function* tfunction) { + return argument_list(tfunction->get_arglist()); +} + +string t_cl_generator::argument_list(t_struct* tstruct) { + stringstream res; + res << "("; + + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + bool first = true; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + if (first) { + first = false; + } else { + res << " "; + } + res << "(" + prefix((*f_iter)->get_name()) << " " << + typespec((*f_iter)->get_type()) << " " << + (*f_iter)->get_key() << ")"; + } + res << ")"; + return res.str(); +} + +string t_cl_generator::type_name(t_type* ttype) { + string prefix = ""; + t_program* program = ttype->get_program(); + + if (program != NULL && program != program_) + prefix = package_of(program) == package() ? "" : package_of(program) + ":"; + + string name = ttype->get_name(); + + if (ttype->is_struct() || ttype->is_xception()) + name = lowercase(ttype->get_name()); + + return prefix + name; +} + +THRIFT_REGISTER_GENERATOR( + cl, + "Common Lisp", + " no_asd: Do not define ASDF systems for each generated Thrift program.\n" + " sys_pref= The prefix to give ASDF system names. Default: thrift-gen-\n") diff --git a/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc b/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc index c2f09e8e68d..0c0e1e0d44c 100644 --- a/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc @@ -2733,8 +2733,8 @@ void t_cocoa_generator::print_const_value(ostream& out, indent(out); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; if (defval) out << type_name(type) << " "; out << name << " = [" << type_name(type, true) << " new];" @@ -2758,8 +2758,8 @@ void t_cocoa_generator::print_const_value(ostream& out, indent(mapout); t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; if (defval) mapout << type_name(type) << " "; mapout << name << " = @{"; @@ -2904,8 +2904,8 @@ string t_cocoa_generator::render_const_value(string name, } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; if (val.size() > 0) render << "[[" << type_name(type, true) << " alloc] initWith"; else @@ -2937,8 +2937,8 @@ string t_cocoa_generator::render_const_value(string name, render << "[[NSDictionary alloc] initWithObjectsAndKeys: "; t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; bool first = true; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(name, ktype, v_iter->first, true); diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index 1c9395715e1..c78b806ed10 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -24,7 +24,9 @@ #include #include +#include #include +#include #include #include #include @@ -703,8 +705,8 @@ void t_cpp_generator::print_const_value(ofstream& out, } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; bool is_nonrequired_field = false; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; @@ -728,8 +730,8 @@ void t_cpp_generator::print_const_value(ofstream& out, } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string val = render_const_value(out, name, vtype, v_iter->second); @@ -788,9 +790,9 @@ string t_cpp_generator::render_const_value(ofstream& out, break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { - render << value->get_integer(); + render << "static_cast(" << value->get_integer() << ")"; } else { - render << value->get_double(); + render << emit_double_as_string(value->get_double()); } break; default: @@ -1796,7 +1798,7 @@ void t_cpp_generator::generate_service(t_service* tservice) { if (!gen_no_skeleton_) { generate_service_async_skeleton(tservice); } - + } f_header_ << "#ifdef _MSC_VER\n" diff --git a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc index a6cb09d1f53..b108c45643e 100644 --- a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc @@ -511,8 +511,8 @@ void t_csharp_generator::print_const_def_value(std::ofstream& out, if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; prepare_member_name_mapping((t_struct*)type); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_field* field = NULL; @@ -532,8 +532,8 @@ void t_csharp_generator::print_const_def_value(std::ofstream& out, } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string val = render_const_value(out, name, vtype, v_iter->second); @@ -988,7 +988,7 @@ void t_csharp_generator::generate_csharp_struct_reader(ofstream& out, t_struct* indent_up(); out << indent() << "throw new TProtocolException(TProtocolException.INVALID_DATA, " - << "\"required field " << prop_name((*f_iter)) << " not set\");" + << "\"required field " << prop_name((*f_iter)) << " not set\");" << endl; indent_down(); } diff --git a/compiler/cpp/src/thrift/generate/t_d_generator.cc b/compiler/cpp/src/thrift/generate/t_d_generator.cc index 35f611d9310..bbef639aea9 100644 --- a/compiler/cpp/src/thrift/generate/t_d_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_d_generator.cc @@ -557,8 +557,8 @@ class t_d_generator : public t_oop_generator { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -576,8 +576,8 @@ class t_d_generator : public t_oop_generator { } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(ktype, v_iter->first); string val = render_const_value(vtype, v_iter->second); diff --git a/compiler/cpp/src/thrift/generate/t_dart_generator.cc b/compiler/cpp/src/thrift/generate/t_dart_generator.cc index f7bd1c28b32..c2d07e92ab1 100644 --- a/compiler/cpp/src/thrift/generate/t_dart_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_dart_generator.cc @@ -594,8 +594,8 @@ void t_dart_generator::print_const_value(std::ofstream& out, } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; out << type_name(type) << " " << name << " = new " << type_name(type) << "()"; indent_up(); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { @@ -623,8 +623,8 @@ void t_dart_generator::print_const_value(std::ofstream& out, t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index 4650a8a1921..4db1cf7dad5 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -727,14 +727,14 @@ void t_delphi_generator::init_generator() { has_enum = false; has_const = false; create_keywords(); - + add_delphi_uses_list("Classes"); add_delphi_uses_list("SysUtils"); add_delphi_uses_list("Generics.Collections"); if(async_) { add_delphi_uses_list("System.Threading"); } - + add_delphi_uses_list("Thrift"); add_delphi_uses_list("Thrift.Utils"); add_delphi_uses_list("Thrift.Collections"); @@ -1205,8 +1205,8 @@ void t_delphi_generator::print_const_def_value(std::ostream& vars, if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -1225,8 +1225,8 @@ void t_delphi_generator::print_const_def_value(std::ostream& vars, } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(vars, out, name, ktype, v_iter->first); string val = render_const_value(vars, out, name, vtype, v_iter->second); @@ -1917,7 +1917,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_client = "TInterfacedObject"; string implements = async_ ? "Iface, IAsync" : "Iface"; - + generate_delphi_doc(s_service, tservice); if (tservice->get_extends() != NULL) { extends = type_name(tservice->get_extends(), true, true); @@ -1974,7 +1974,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { indent(s_service) << "protected" << endl; indent_up(); - + indent(s_service) << "// Iface" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = (*f_iter)->get_name(); @@ -1991,7 +1991,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { indent(s_service) << function_signature(*f_iter, true) << endl; } } - + indent_down(); indent(s_service) << "public" << endl; @@ -2015,22 +2015,22 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { indent_impl(s_service_impl) << function_signature(*f_iter, for_async, full_cls) << endl; indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); - + t_type* ttype = (*f_iter)->get_returntype(); if( for_async) { - if (is_void(ttype)) { + if (is_void(ttype)) { // Delphi forces us to specify a type with IFuture, so we use Integer=0 for void methods indent_impl(s_service_impl) << "result := TTask.Future(function: Integer" << endl; - } else { - string rettype = type_name(ttype, false, true, false, true); + } else { + string rettype = type_name(ttype, false, true, false, true); indent_impl(s_service_impl) << "result := TTask.Future<" << rettype << ">(function: " << rettype << endl; } indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); } - + indent_impl(s_service_impl) << "send_" << funname << "("; - + bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { @@ -2041,7 +2041,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { s_service_impl << normalize_name((*fld_iter)->get_name()); } s_service_impl << ");" << endl; - + if (!(*f_iter)->is_oneway()) { s_service_impl << indent_impl(); if (!(*f_iter)->get_returntype()->is_void()) { @@ -2049,7 +2049,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { } s_service_impl << "recv_" << funname << "();" << endl; } - + if( for_async) { if (is_void(ttype)) { indent_impl(s_service_impl) << "Result := 0;" << endl; // no IFuture in Delphi @@ -2057,11 +2057,11 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { indent_down_impl(); indent_impl(s_service_impl) << "end);" << endl; } - + indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; } - + t_function send_function(g_type_void, string("send_") + (*f_iter)->get_name(), (*f_iter)->get_arglist()); diff --git a/compiler/cpp/src/thrift/generate/t_erl_generator.cc b/compiler/cpp/src/thrift/generate/t_erl_generator.cc index 372c78bf704..768db139d3b 100644 --- a/compiler/cpp/src/thrift/generate/t_erl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_erl_generator.cc @@ -384,6 +384,36 @@ void t_erl_generator::close_generator() { f_consts_hrl_file_.close(); } +const std::string emit_double_as_string(const double value) { + std::stringstream double_output_stream; + // sets the maximum precision: http://en.cppreference.com/w/cpp/io/manip/setprecision + // sets the output format to fixed: http://en.cppreference.com/w/cpp/io/manip/fixed (not in scientific notation) + double_output_stream << std::setprecision(std::numeric_limits::digits10 + 1); + + #ifdef _MSC_VER + // strtod is broken in MSVC compilers older than 2015, so std::fixed fails to format a double literal. + // more details: https://blogs.msdn.microsoft.com/vcblog/2014/06/18/ + // c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/ + // and + // http://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/ + #if _MSC_VER >= MSC_2015_VER + double_output_stream << std::fixed; + #else + // note that if this function is called from the erlang generator and the MSVC compiler is older than 2015, + // the double literal must be output in the scientific format. There can be some cases where the + // mantissa of the output does not have fractionals, which is illegal in Erlang. + // example => 10000000000000000.0 being output as 1e+16 + double_output_stream << std::scientific; + #endif + #else + double_output_stream << std::fixed; + #endif + + double_output_stream << value; + + return double_output_stream.str(); +} + void t_erl_generator::generate_type_metadata(std::string function_name, vector names) { vector::iterator s_iter; size_t num_structs = names.size(); @@ -430,7 +460,7 @@ void t_erl_generator::generate_const_function(t_const* tconst, ostringstream& ex exports << const_fun_name << "/1, " << const_fun_name << "/2"; // Emit const function definition. - map::const_iterator i, end = value->get_map().end(); + map::const_iterator i, end = value->get_map().end(); // The one-argument form throws an error if the key does not exist in the map. for (i = value->get_map().begin(); i != end;) { functions << const_fun_name << "(" << render_const_value(ktype, i->first) << ") -> " @@ -575,9 +605,9 @@ string t_erl_generator::render_const_value(t_type* type, t_const_value* value) { break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { - out << value->get_integer(); + out << "float(" << value->get_integer() << ")"; } else { - out << value->get_double(); + out << emit_double_as_string(value->get_double()); } break; default: @@ -590,8 +620,8 @@ string t_erl_generator::render_const_value(t_type* type, t_const_value* value) { out << "#" << type_name(type) << "{"; const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; bool first = true; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { @@ -626,7 +656,7 @@ string t_erl_generator::render_const_value(t_type* type, t_const_value* value) { } else { out << "dict:from_list(["; } - map::const_iterator i, end = value->get_map().end(); + map::const_iterator i, end = value->get_map().end(); for (i = value->get_map().begin(); i != end;) { out << "{" << render_const_value(ktype, i->first) << "," << render_const_value(vtype, i->second) << "}"; @@ -717,7 +747,7 @@ string t_erl_generator::render_member_type(t_field* field) { return type_name(type) + "()"; } else if (type->is_map()) { if (maps_) { - return "#{}"; + return "map()"; } else if (otp16_) { return "dict()"; } else { @@ -810,6 +840,8 @@ void t_erl_generator::generate_erl_struct_member(ostream& out, t_field* tmember) if (has_default_value(tmember)) out << " = " << render_member_value(tmember); out << " :: " << render_member_type(tmember); + if (tmember->get_req() != t_field::T_REQUIRED) + out << " | 'undefined'"; } bool t_erl_generator::has_default_value(t_field* field) { diff --git a/compiler/cpp/src/thrift/generate/t_generator.h b/compiler/cpp/src/thrift/generate/t_generator.h index fc3f3232190..cbbfcb9fa1f 100644 --- a/compiler/cpp/src/thrift/generate/t_generator.h +++ b/compiler/cpp/src/thrift/generate/t_generator.h @@ -19,10 +19,13 @@ #ifndef T_GENERATOR_H #define T_GENERATOR_H +#define MSC_2015_VER 1900 #include +#include #include #include +#include #include #include "thrift/common.h" #include "thrift/version.h" @@ -93,7 +96,7 @@ class t_generator { protected: /** - * Optional methods that may be imlemented by subclasses to take necessary + * Optional methods that may be implemented by subclasses to take necessary * steps at the beginning or end of code generation. */ @@ -268,6 +271,30 @@ class t_generator { return out.str(); } + const std::string emit_double_as_string(const double value) { + std::stringstream double_output_stream; + // sets the maximum precision: http://en.cppreference.com/w/cpp/io/manip/setprecision + // sets the output format to fixed: http://en.cppreference.com/w/cpp/io/manip/fixed (not in scientific notation) + double_output_stream << std::setprecision(std::numeric_limits::digits10 + 1); + + #ifdef _MSC_VER + // strtod is broken in MSVC compilers older than 2015, so std::fixed fails to format a double literal. + // more details: https://blogs.msdn.microsoft.com/vcblog/2014/06/18/ + // c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/ + // and + // http://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/ + #if _MSC_VER >= MSC_2015_VER + double_output_stream << std::fixed; + #endif + #else + double_output_stream << std::fixed; + #endif + + double_output_stream << value; + + return double_output_stream.str(); + } + public: /** * Get the true type behind a series of typedefs. diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 7727118e8c6..f3c7fee3150 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -81,7 +81,6 @@ class t_go_generator : public t_generator { gen_package_prefix_ = ""; package_flag = ""; read_write_private_ = false; - legacy_context_ = false; ignore_initialisms_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("package_prefix") == 0) { @@ -92,8 +91,6 @@ class t_go_generator : public t_generator { package_flag = (iter->second); } else if( iter->first.compare("read_write_private") == 0) { read_write_private_ = true; - } else if( iter->first.compare("legacy_context") == 0) { - legacy_context_ = true; } else if( iter->first.compare("ignore_initialisms") == 0) { ignore_initialisms_ = true; } else { @@ -287,7 +284,6 @@ class t_go_generator : public t_generator { std::string gen_package_prefix_; std::string gen_thrift_import_; bool read_write_private_; - bool legacy_context_; bool ignore_initialisms_; /** @@ -753,14 +749,6 @@ void t_go_generator::init_generator() { f_consts_name_ = package_dir_ + "/" + program_name_ + "-consts.go"; f_consts_.open(f_consts_name_.c_str()); - vector services = program_->get_services(); - vector::iterator sv_iter; - - for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { - string service_dir = package_dir_ + "/" + underscore((*sv_iter)->get_name()) + "-remote"; - MKDIR(service_dir.c_str()); - } - // Print header f_types_ << go_autogen_comment() << go_package() << render_includes(false); @@ -883,16 +871,10 @@ string t_go_generator::go_imports_begin(bool consts) { "\t\"database/sql/driver\"\n" "\t\"errors\"\n"; } - if (legacy_context_) { - extra += - "\t\"golang.org/x/net/context\"\n"; - } else { - extra += - "\t\"context\"\n"; - } return string( "import (\n" "\t\"bytes\"\n" + "\t\"context\"\n" "\t\"reflect\"\n" + extra + "\t\"fmt\"\n" @@ -1115,8 +1097,8 @@ string t_go_generator::render_const_value(t_type* type, t_const_value* value, co indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; @@ -1141,10 +1123,10 @@ string t_go_generator::render_const_value(t_type* type, t_const_value* value, co } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); + const map& val = value->get_map(); out << "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype) << "{" << endl; indent_up(); - map::const_iterator v_iter; + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent() << render_const_value(ktype, v_iter->first, name) << ": " @@ -2055,8 +2037,16 @@ void t_go_generator::generate_service_remote(t_service* tservice) { parent = parent->get_extends(); } + // This file is not useful if there are no functions; don't generate it + if (functions.size() == 0) { + return; + } + + string f_remote_dir = package_dir_ + "/" + underscore(service_name_) + "-remote"; + MKDIR(f_remote_dir.c_str()); + vector::iterator f_iter; - string f_remote_name = package_dir_ + "/" + underscore(service_name_) + "-remote/" + string f_remote_name = f_remote_dir + "/" + underscore(service_name_) + "-remote.go"; ofstream f_remote; f_remote.open(f_remote_name.c_str()); @@ -2073,9 +2063,6 @@ void t_go_generator::generate_service_remote(t_service* tservice) { string unused_protection; string ctxPackage = "context"; - if (legacy_context_) { - ctxPackage = "golang.org/x/net/context"; - } f_remote << go_autogen_comment(); f_remote << indent() << "package main" << endl << endl; @@ -2129,6 +2116,24 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << " os.Exit(0)" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << endl; + + f_remote << indent() << "type httpHeaders map[string]string" << endl; + f_remote << indent() << endl; + f_remote << indent() << "func (h httpHeaders) String() string {" << endl; + f_remote << indent() << " var m map[string]string = h" << endl; + f_remote << indent() << " return fmt.Sprintf(\"%s\", m)" << endl; + f_remote << indent() << "}" << endl; + f_remote << indent() << endl; + f_remote << indent() << "func (h httpHeaders) Set(value string) error {" << endl; + f_remote << indent() << " parts := strings.Split(value, \": \")" << endl; + f_remote << indent() << " if len(parts) != 2 {" << endl; + f_remote << indent() << " return fmt.Errorf(\"header should be of format 'Key: Value'\")" << endl; + f_remote << indent() << " }" << endl; + f_remote << indent() << " h[parts[0]] = parts[1]" << endl; + f_remote << indent() << " return nil" << endl; + f_remote << indent() << "}" << endl; + f_remote << indent() << endl; + f_remote << indent() << "func main() {" << endl; indent_up(); f_remote << indent() << "flag.Usage = Usage" << endl; @@ -2138,6 +2143,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << "var urlString string" << endl; f_remote << indent() << "var framed bool" << endl; f_remote << indent() << "var useHttp bool" << endl; + f_remote << indent() << "headers := make(httpHeaders)" << endl; f_remote << indent() << "var parsedUrl *url.URL" << endl; f_remote << indent() << "var trans thrift.TTransport" << endl; f_remote << indent() << "_ = strconv.Atoi" << endl; @@ -2152,6 +2158,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << "flag.BoolVar(&framed, \"framed\", false, \"Use framed transport\")" << endl; f_remote << indent() << "flag.BoolVar(&useHttp, \"http\", false, \"Use http\")" << endl; + f_remote << indent() << "flag.Var(headers, \"H\", \"Headers to set on the http(s) request (e.g. -H \\\"Key: Value\\\")\")" << endl; f_remote << indent() << "flag.Parse()" << endl; f_remote << indent() << endl; f_remote << indent() << "if len(urlString) > 0 {" << endl; @@ -2162,7 +2169,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << " flag.Usage()" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << " host = parsedUrl.Host" << endl; - f_remote << indent() << " useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == \"http\"" + f_remote << indent() << " useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == \"http\" || parsedUrl.Scheme == \"https\"" << endl; f_remote << indent() << "} else if useHttp {" << endl; f_remote << indent() << " _, err := url.Parse(fmt.Sprint(\"http://\", host, \":\", port))" @@ -2177,6 +2184,12 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << "var err error" << endl; f_remote << indent() << "if useHttp {" << endl; f_remote << indent() << " trans, err = thrift.NewTHttpClient(parsedUrl.String())" << endl; + f_remote << indent() << " if len(headers) > 0 {" << endl; + f_remote << indent() << " httptrans := trans.(*thrift.THttpClient)" << endl; + f_remote << indent() << " for key, value := range headers {" << endl; + f_remote << indent() << " httptrans.SetHeader(key, value)" << endl; + f_remote << indent() << " }" << endl; + f_remote << indent() << " }" << endl; f_remote << indent() << "} else {" << endl; f_remote << indent() << " portStr := fmt.Sprint(port)" << endl; f_remote << indent() << " if strings.Contains(host, \":\") {" << endl; @@ -2363,7 +2376,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; - f_remote << indent() << factory << " := thrift.NewTSimpleJSONProtocolFactory()" << endl; + f_remote << indent() << factory << " := thrift.NewTJSONProtocolFactory()" << endl; f_remote << indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl; f_remote << indent() << "argvalue" << i << " := " << tstruct_module << ".New" << tstruct_name @@ -2391,7 +2404,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; - f_remote << indent() << factory << " := thrift.NewTSimpleJSONProtocolFactory()" << endl; + f_remote << indent() << factory << " := thrift.NewTJSONProtocolFactory()" << endl; f_remote << indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl; f_remote << indent() << "containerStruct" << i << " := " << package_name_ << ".New" @@ -2576,7 +2589,7 @@ void t_go_generator::generate_service_server(t_service* tservice) { f_types_ << indent() << " oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)" << endl; f_types_ << indent() << " " << x << ".Write(oprot)" << endl; f_types_ << indent() << " oprot.WriteMessageEnd()" << endl; - f_types_ << indent() << " oprot.Flush()" << endl; + f_types_ << indent() << " oprot.Flush(ctx)" << endl; f_types_ << indent() << " return false, " << x << endl; f_types_ << indent() << "" << endl; f_types_ << indent() << "}" << endl << endl; @@ -2641,7 +2654,7 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* << "\", thrift.EXCEPTION, seqId)" << endl; f_types_ << indent() << " x.Write(oprot)" << endl; f_types_ << indent() << " oprot.WriteMessageEnd()" << endl; - f_types_ << indent() << " oprot.Flush()" << endl; + f_types_ << indent() << " oprot.Flush(ctx)" << endl; } f_types_ << indent() << " return false, err" << endl; f_types_ << indent() << "}" << endl << endl; @@ -2709,7 +2722,7 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* << "\", thrift.EXCEPTION, seqId)" << endl; f_types_ << indent() << " x.Write(oprot)" << endl; f_types_ << indent() << " oprot.WriteMessageEnd()" << endl; - f_types_ << indent() << " oprot.Flush()" << endl; + f_types_ << indent() << " oprot.Flush(ctx)" << endl; } f_types_ << indent() << " return true, err2" << endl; @@ -2746,7 +2759,7 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* << endl; f_types_ << indent() << " err = err2" << endl; f_types_ << indent() << "}" << endl; - f_types_ << indent() << "if err2 = oprot.Flush(); err == nil && err2 != nil {" << endl; + f_types_ << indent() << "if err2 = oprot.Flush(ctx); err == nil && err2 != nil {" << endl; f_types_ << indent() << " err = err2" << endl; f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err != nil {" << endl; @@ -3642,6 +3655,4 @@ THRIFT_REGISTER_GENERATOR(go, "Go", " ignore_initialisms\n" " Disable automatic spelling correction of initialisms (e.g. \"URL\")\n" \ " read_write_private\n" - " Make read/write methods private, default is public Read/Write\n" \ - " legacy_context\n" - " Use legacy x/net/context instead of context in go<1.7.\n") + " Make read/write methods private, default is public Read/Write\n") diff --git a/compiler/cpp/src/thrift/generate/t_gv_generator.cc b/compiler/cpp/src/thrift/generate/t_gv_generator.cc index 14b5377126e..c2f8b5a9cbc 100644 --- a/compiler/cpp/src/thrift/generate/t_gv_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_gv_generator.cc @@ -249,8 +249,8 @@ void t_gv_generator::print_const_value(t_type* type, t_const_value* tvalue) { break; case t_const_value::CV_MAP: { f_out_ << "\\{ "; - map map_elems = tvalue->get_map(); - map::iterator map_iter; + map map_elems = tvalue->get_map(); + map::iterator map_iter; for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) { if (!first) { f_out_ << ", "; diff --git a/compiler/cpp/src/thrift/generate/t_haxe_generator.cc b/compiler/cpp/src/thrift/generate/t_haxe_generator.cc index 97c7d19a3ff..ce3816d3a3b 100644 --- a/compiler/cpp/src/thrift/generate/t_haxe_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_haxe_generator.cc @@ -503,8 +503,8 @@ void t_haxe_generator::print_const_value(std::ofstream& out, } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();" << endl; if (!in_static) { @@ -548,8 +548,8 @@ void t_haxe_generator::print_const_value(std::ofstream& out, } t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string val = render_const_value(out, name, vtype, v_iter->second); diff --git a/compiler/cpp/src/thrift/generate/t_hs_generator.cc b/compiler/cpp/src/thrift/generate/t_hs_generator.cc index d0a8cb2d6bf..6c8cb7fc9d6 100644 --- a/compiler/cpp/src/thrift/generate/t_hs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_hs_generator.cc @@ -424,10 +424,10 @@ string t_hs_generator::render_const_value(t_type* type, t_const_value* value) { out << "default_" << cname << "{"; const vector& fields = ((t_struct*)type)->get_members(); - const map& val = value->get_map(); + const map& val = value->get_map(); bool first = true; - for (map::const_iterator v_iter = val.begin(); + for (map::const_iterator v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_field* field = NULL; @@ -458,8 +458,8 @@ string t_hs_generator::render_const_value(t_type* type, t_const_value* value) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; out << "(Map.fromList ["; diff --git a/compiler/cpp/src/thrift/generate/t_html_generator.cc b/compiler/cpp/src/thrift/generate/t_html_generator.cc index dfd5df31182..5b063707f5c 100644 --- a/compiler/cpp/src/thrift/generate/t_html_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_html_generator.cc @@ -777,8 +777,8 @@ void t_html_generator::print_const_value(t_type* type, t_const_value* tvalue) { f_out_ << "{ "; const vector& fields = ((t_struct*)truetype)->get_members(); vector::const_iterator f_iter; - const map& val = tvalue->get_map(); - map::const_iterator v_iter; + const map& val = tvalue->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -800,8 +800,8 @@ void t_html_generator::print_const_value(t_type* type, t_const_value* tvalue) { f_out_ << " }"; } else if (truetype->is_map()) { f_out_ << "{ "; - map map_elems = tvalue->get_map(); - map::iterator map_iter; + map map_elems = tvalue->get_map(); + map::iterator map_iter; for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) { if (!first) { f_out_ << ", "; diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc index ebc83505ad1..3c7b75309d9 100644 --- a/compiler/cpp/src/thrift/generate/t_java_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -596,6 +597,7 @@ void t_java_generator::generate_consts(std::vector consts) { f_consts.close(); } + /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the @@ -619,10 +621,12 @@ void t_java_generator::print_const_value(std::ofstream& out, } else if (type->is_enum()) { out << name << " = " << render_const_value(out, type, value) << ";" << endl << endl; } else if (type->is_struct() || type->is_xception()) { - const vector& fields = ((t_struct*)type)->get_members(); + const vector& unsorted_fields = ((t_struct*)type)->get_members(); + vector fields = unsorted_fields; + std::sort(fields.begin(), fields.end(), t_field::key_compare()); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; out << name << " = new " << type_name(type, false, true) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; @@ -660,8 +664,8 @@ void t_java_generator::print_const_value(std::ofstream& out, } t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, ktype, v_iter->first); string val = render_const_value(out, vtype, v_iter->second); @@ -731,9 +735,9 @@ string t_java_generator::render_const_value(ofstream& out, t_type* type, t_const break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { - render << "(double)" << value->get_integer(); + render << value->get_integer() << "d"; } else { - render << value->get_double(); + render << emit_double_as_string(value->get_double()); } break; default: diff --git a/compiler/cpp/src/thrift/generate/t_javame_generator.cc b/compiler/cpp/src/thrift/generate/t_javame_generator.cc index 24b75600482..0f4181dc3b5 100644 --- a/compiler/cpp/src/thrift/generate/t_javame_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_javame_generator.cc @@ -454,8 +454,8 @@ void t_javame_generator::print_const_value(std::ofstream& out, } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; out << name << " = new " << type_name(type, false, true) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; @@ -489,8 +489,8 @@ void t_javame_generator::print_const_value(std::ofstream& out, } t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string val = render_const_value(out, name, vtype, v_iter->second); diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index 269e46a9bfc..7d160b91199 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -20,7 +20,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -564,7 +566,7 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { - out << value->get_double(); + out << emit_double_as_string(value->get_double()); } break; default: @@ -577,8 +579,8 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -604,8 +606,8 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { out << "{" << endl; indent_up(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (v_iter != val.begin()) out << "," << endl; diff --git a/compiler/cpp/src/thrift/generate/t_json_generator.cc b/compiler/cpp/src/thrift/generate/t_json_generator.cc index 153ec35d294..cf5f80185f1 100644 --- a/compiler/cpp/src/thrift/generate/t_json_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_json_generator.cc @@ -510,8 +510,8 @@ void t_json_generator::write_const_value(t_const_value* value, bool should_force case t_const_value::CV_MAP: { start_object(NO_INDENT); - std::map map = value->get_map(); - std::map::iterator mit; + std::map map = value->get_map(); + std::map::iterator mit; for (mit = map.begin(); mit != map.end(); ++mit) { write_comma_if_needed(); f_json_ << indent(); diff --git a/compiler/cpp/src/thrift/generate/t_lua_generator.cc b/compiler/cpp/src/thrift/generate/t_lua_generator.cc index 92e6749de7a..b4a6793eb0d 100644 --- a/compiler/cpp/src/thrift/generate/t_lua_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_lua_generator.cc @@ -276,8 +276,8 @@ string t_lua_generator::render_const_value(t_type* type, t_const_value* value) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -308,8 +308,8 @@ string t_lua_generator::render_const_value(t_type* type, t_const_value* value) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { indent(out) << "[" << render_const_value(ktype, v_iter->first) << "] = " << render_const_value(vtype, v_iter->second); diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc index 9334f5fe787..dbf2fd0cef7 100644 --- a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc @@ -44,7 +44,7 @@ using std::string; using std::stringstream; using std::vector; -//TODO: check for indentation +//TODO: check for indentation //TODO: Do we need seqId_ in generation? t_netcore_generator::t_netcore_generator(t_program* program, const map& parsed_options, const string& option_string) @@ -328,7 +328,7 @@ void t_netcore_generator::init_keywords() netcore_keywords["var"] = 1; netcore_keywords["where"] = 1; netcore_keywords["yield"] = 1; - + netcore_keywords["when"] = 1; } @@ -400,7 +400,7 @@ void t_netcore_generator::generate_enum(t_enum* tenum) ofstream f_enum; f_enum.open(f_enum_name.c_str()); - + generate_enum(f_enum, tenum); f_enum.close(); @@ -428,7 +428,7 @@ void t_netcore_generator::generate_enum(ofstream& out, t_enum* tenum) } scope_down(out); - end_netcore_namespace(out); + end_netcore_namespace(out); } void t_netcore_generator::generate_consts(vector consts) @@ -443,7 +443,7 @@ void t_netcore_generator::generate_consts(vector consts) f_consts.open(f_consts_name.c_str()); generate_consts(f_consts, consts); - + f_consts.close(); } @@ -487,15 +487,15 @@ void t_netcore_generator::print_const_def_value(ofstream& out, string name, t_ty if (type->is_struct() || type->is_xception()) { const vector& fields = static_cast(type)->get_members(); - const map& val = value->get_map(); + const map& val = value->get_map(); vector::const_iterator f_iter; - map::const_iterator v_iter; + map::const_iterator v_iter; prepare_member_name_mapping(static_cast(type)); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_field* field = NULL; - + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) @@ -510,7 +510,7 @@ void t_netcore_generator::print_const_def_value(ofstream& out, string name, t_ty } t_type* field_type = field->get_type(); - + string val = render_const_value(out, name, field_type, v_iter->second); out << indent() << name << "." << prop_name(field) << " = " << val << ";" << endl; } @@ -521,8 +521,8 @@ void t_netcore_generator::print_const_def_value(ofstream& out, string name, t_ty { t_type* ktype = static_cast(type)->get_key_type(); t_type* vtype = static_cast(type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); @@ -723,7 +723,7 @@ void t_netcore_generator::generate_netcore_struct_definition(ofstream& out, t_st out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << sharp_struct_name << " : "; - if (is_exception) + if (is_exception) { out << "TException, "; } @@ -786,7 +786,7 @@ void t_netcore_generator::generate_netcore_struct_definition(ofstream& out, t_st out << indent() << "public struct Isset" << endl << indent() << "{" << endl; indent_up(); - + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { bool is_required = field_is_required((*m_iter)); @@ -912,7 +912,7 @@ void t_netcore_generator::generate_netcore_struct_definition(ofstream& out, t_st generate_netcore_struct_hashcode(out, tstruct); } generate_netcore_struct_tostring(out, tstruct); - + indent_down(); out << indent() << "}" << endl << endl; @@ -968,7 +968,7 @@ void t_netcore_generator::generate_netcore_struct_reader(ofstream& out, t_struct << indent() << "try" << endl << indent() << "{" << endl; indent_up(); - + const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; @@ -981,7 +981,7 @@ void t_netcore_generator::generate_netcore_struct_reader(ofstream& out, t_struct } } - out << indent() << "TField field;" << endl + out << indent() << "TField field;" << endl << indent() << "await iprot.ReadStructBeginAsync(cancellationToken);" << endl << indent() << "while (true)" << endl << indent() << "{" << endl; @@ -996,7 +996,7 @@ void t_netcore_generator::generate_netcore_struct_reader(ofstream& out, t_struct << indent() << "switch (field.ID)" << endl << indent() << "{" << endl; indent_up(); - + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool is_required = field_is_required(*f_iter); @@ -1050,7 +1050,7 @@ void t_netcore_generator::generate_netcore_struct_reader(ofstream& out, t_struct out << indent() << "}" << endl; } } - + indent_down(); out << indent() << "}" << endl; out << indent() << "finally" << endl @@ -1147,7 +1147,7 @@ void t_netcore_generator::generate_netcore_struct_result_writer(ofstream& out, t indent_up(); out << indent() << "oprot.IncrementRecursionDepth();" << endl - << indent() << "try" << endl + << indent() << "try" << endl << indent() << "{" << endl; indent_up(); @@ -1333,7 +1333,7 @@ void t_netcore_generator::generate_netcore_union(t_struct* tunion) generate_netcore_union_definition(f_union, tunion); f_union.close(); - + indent_validate(ic, "generate_netcore_union."); } @@ -1720,7 +1720,7 @@ void t_netcore_generator::generate_service_client(ofstream& out, t_service* tser << indent() << "throw x;" << endl; indent_down(); - out << indent() << "}" << endl + out << indent() << "}" << endl << endl << indent() << "var result = new " << resultname << "();" << endl << indent() << "await result.ReadAsync(InputProtocol, cancellationToken);" << endl @@ -1741,7 +1741,7 @@ void t_netcore_generator::generate_service_client(ofstream& out, t_service* tser } else { - out << indent() << "if (result.Success.HasValue)" << endl + out << indent() << "if (result.Success.HasValue)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "return result.Success.Value;" << endl; @@ -1827,7 +1827,7 @@ void t_netcore_generator::generate_service_server(ofstream& out, t_service* tser indent_up(); - out << indent() << "private IAsync _iAsync;" << endl + out << indent() << "private IAsync _iAsync;" << endl << endl << indent() << "public AsyncProcessor(IAsync iAsync)"; @@ -1839,7 +1839,7 @@ void t_netcore_generator::generate_service_server(ofstream& out, t_service* tser out << endl << indent() << "{" << endl; indent_up(); - + out << indent() << "if (iAsync == null) throw new ArgumentNullException(nameof(iAsync));" << endl << endl << indent() << "_iAsync = iAsync;" << endl; @@ -1965,7 +1965,7 @@ void t_netcore_generator::generate_function_helpers(ofstream& out, t_function* t void t_netcore_generator::generate_process_function_async(ofstream& out, t_service* tservice, t_function* tfunction) { (void)tservice; - out << indent() << "public async Task " << tfunction->get_name() + out << indent() << "public async Task " << tfunction->get_name() << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl << indent() << "{" << endl; indent_up(); @@ -2029,7 +2029,7 @@ void t_netcore_generator::generate_process_function_async(ofstream& out, t_servi } cleanup_member_name_mapping(arg_struct); - + if (!first) { out << ", "; @@ -2044,7 +2044,7 @@ void t_netcore_generator::generate_process_function_async(ofstream& out, t_servi { indent_down(); out << indent() << "}" << endl; - + for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " " << (*x_iter)->get_name() << ")" << endl @@ -2062,7 +2062,7 @@ void t_netcore_generator::generate_process_function_async(ofstream& out, t_servi if (!tfunction->is_oneway()) { - out << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" + out << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" << correct_function_name_for_async(tfunction->get_name()) << "\", TMessageType.Reply, seqid), cancellationToken); " << endl << indent() << "await result.WriteAsync(oprot, cancellationToken);" << endl; } @@ -2274,7 +2274,7 @@ void t_netcore_generator::generate_deserialize_struct(ofstream& out, t_struct* t } else { - out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl + out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent() << "await " << prefix << ".ReadAsync(iprot, cancellationToken);" << endl; } } @@ -3074,17 +3074,17 @@ void t_netcore_generator::docstring_comment(ofstream& out, const string& comment stringstream docs(contents, std::ios_base::in); - while (!(docs.eof() || docs.fail())) + while (!(docs.eof() || docs.fail())) { char line[1024]; docs.getline(line, 1024); // Just prnt a newline when the line & prefix are empty. - if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) + if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) { out << endl; } - else if (strlen(line) > 0 || !docs.eof()) + else if (strlen(line) > 0 || !docs.eof()) { // skip the empty last line out << indent() << line_prefix << line << endl; } diff --git a/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc b/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc index 594219ae513..2bf85d1c2d1 100644 --- a/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc @@ -401,8 +401,8 @@ string t_ocaml_generator::render_const_value(t_type* type, t_const_value* value) indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -425,8 +425,8 @@ string t_ocaml_generator::render_const_value(t_type* type, t_const_value* value) } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; string hm = tmp("_hm"); out << endl; indent_up(); diff --git a/compiler/cpp/src/thrift/generate/t_perl_generator.cc b/compiler/cpp/src/thrift/generate/t_perl_generator.cc index 0c05cda04cc..76d343e8984 100644 --- a/compiler/cpp/src/thrift/generate/t_perl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_perl_generator.cc @@ -359,8 +359,8 @@ string t_perl_generator::render_const_value(t_type* type, t_const_value* value) const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -385,8 +385,8 @@ string t_perl_generator::render_const_value(t_type* type, t_const_value* value) out << "{" << endl; indent_up(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { indent(out) << render_const_value(ktype, v_iter->first); out << " => "; diff --git a/compiler/cpp/src/thrift/generate/t_php_generator.cc b/compiler/cpp/src/thrift/generate/t_php_generator.cc index 5166d0337c1..6ab6bf8eb2a 100644 --- a/compiler/cpp/src/thrift/generate/t_php_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_php_generator.cc @@ -62,7 +62,7 @@ class t_php_generator : public t_oop_generator { validate_ = false; json_serializable_ = false; nsglobal_ = ""; // by default global namespace is empty - psr4_ = false; + classmap_ = false; for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if (iter->first.compare("inlined") == 0) { binary_inline_ = true; @@ -78,8 +78,14 @@ class t_php_generator : public t_oop_generator { json_serializable_ = true; } else if (iter->first.compare("nsglobal") == 0) { nsglobal_ = iter->second; + } else if (iter->first.compare("classmap") == 0) { + classmap_ = true; } else if (iter->first.compare("psr4") == 0) { - psr4_ = true; + if(classmap_){ + throw "psr4 and classmap are mutually exclusive."; + } else { + pwarning(0, "psr4 is default option! needn't add psr4 option!\n"); + } } else { throw "unknown option php:" + iter->first; } @@ -376,9 +382,9 @@ class t_php_generator : public t_oop_generator { bool oop_; /** - * Whether to hold each class in separate file to allow PSR4-autoloading + * Whether to generate old-style PHP file to use classmap autoloading */ - bool psr4_; + bool classmap_; /** * Whether to generate validator code @@ -419,8 +425,8 @@ void t_php_generator::init_generator() { MKDIR(package_dir_.c_str()); } - // Prepare output file for all the types in non-psr4 mode - if (!psr4_) { + // Prepare output file for all the types in classmap mode + if (classmap_) { // Make output file string f_types_name = package_dir_ + "Types.php"; f_types_.open(f_types_name.c_str()); @@ -453,7 +459,7 @@ string t_php_generator::php_includes() { * Close up (or down) some filez. */ void t_php_generator::close_generator() { - if (!psr4_) { + if (classmap_) { // Close types file f_types_.close(); } @@ -504,7 +510,7 @@ void t_php_generator::generate_program_header(std::ofstream& file) { */ void t_php_generator::generate_enum(t_enum* tenum) { std::ofstream& f_enum = f_types_; - if (psr4_) { + if (!classmap_) { string f_enum_name = package_dir_ + tenum->get_name() + ".php"; f_enum.open(f_enum_name.c_str()); generate_program_header(f_enum); @@ -541,7 +547,7 @@ void t_php_generator::generate_enum(t_enum* tenum) { indent_down(); f_enum << "}" << endl << endl; - if (psr4_) { + if (!classmap_) { f_enum.close(); } } @@ -558,7 +564,7 @@ void t_php_generator::generate_consts(vector consts) { if (consts.size() > 0) { std::ofstream& f_consts = f_types_; - if (psr4_) { + if (!classmap_) { string f_consts_name = package_dir_ + "Constant.php"; f_consts.open(f_consts_name.c_str()); generate_program_header(f_consts); @@ -596,7 +602,7 @@ void t_php_generator::generate_consts(vector consts) { indent_down(); f_consts << "}" << endl; - if (psr4_) { + if (!classmap_) { f_consts.close(); } } @@ -642,8 +648,8 @@ string t_php_generator::render_const_value(t_type* type, t_const_value* value) { indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -667,8 +673,8 @@ string t_php_generator::render_const_value(t_type* type, t_const_value* value) { t_type* vtype = ((t_map*)type)->get_val_type(); out << "array(" << endl; indent_up(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent(); out << render_const_value(ktype, v_iter->first); @@ -725,13 +731,13 @@ void t_php_generator::generate_xception(t_struct* txception) { */ void t_php_generator::generate_php_struct(t_struct* tstruct, bool is_exception) { std::ofstream& f_struct = f_types_; - if (psr4_) { + if (!classmap_) { string f_struct_name = package_dir_ + tstruct->get_name() + ".php"; f_struct.open(f_struct_name.c_str()); generate_program_header(f_struct); } generate_php_struct_definition(f_struct, tstruct, is_exception); - if (psr4_) { + if (!classmap_) { f_struct.close(); } } @@ -1244,7 +1250,7 @@ bool t_php_generator::needs_php_read_validator(t_struct* tstruct, bool is_result * @param tservice The service definition */ void t_php_generator::generate_service(t_service* tservice) { - if(!psr4_) { + if(classmap_) { string f_service_name = package_dir_ + service_name_ + ".php"; f_service_.open(f_service_name.c_str()); generate_service_header(tservice, f_service_); @@ -1261,7 +1267,7 @@ void t_php_generator::generate_service(t_service* tservice) { generate_service_processor(tservice); } - if(!psr4_) { + if(classmap_) { // Close service file f_service_ << endl; f_service_.close(); @@ -1275,7 +1281,7 @@ void t_php_generator::generate_service(t_service* tservice) { */ void t_php_generator::generate_service_processor(t_service* tservice) { std::ofstream& f_service_processor = f_service_; - if (psr4_) { + if (!classmap_) { string f_service_processor_name = package_dir_ + service_name_ + "Processor.php"; f_service_processor.open(f_service_processor_name.c_str()); generate_service_header(tservice, f_service_processor); @@ -1370,7 +1376,7 @@ void t_php_generator::generate_service_processor(t_service* tservice) { indent_down(); f_service_processor << "}" << endl; - if (psr4_) { + if (!classmap_) { f_service_processor.close(); } } @@ -1539,7 +1545,7 @@ void t_php_generator::generate_service_helpers(t_service* tservice) { vector::iterator f_iter; std::ofstream& f_struct_definition = f_service_; - if (!psr4_) { + if (classmap_) { f_struct_definition << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl; } @@ -1548,14 +1554,14 @@ void t_php_generator::generate_service_helpers(t_service* tservice) { string name = ts->get_name(); ts->set_name(service_name_ + "_" + name); - if (psr4_) { + if (!classmap_) { string f_struct_definition_name = package_dir_ + service_name_ + "_" + name + ".php"; f_struct_definition.open(f_struct_definition_name.c_str()); generate_service_header(tservice, f_struct_definition); } generate_php_struct_definition(f_struct_definition, ts); - if (psr4_) { + if (!classmap_) { f_struct_definition.close(); } @@ -1585,13 +1591,13 @@ void t_php_generator::generate_php_function_helpers(t_service* tservice, t_funct } std::ofstream& f_struct_helper = f_service_; - if (psr4_) { + if (!classmap_) { string f_struct_helper_name = package_dir_ + result.get_name() + ".php"; f_struct_helper.open(f_struct_helper_name.c_str()); generate_service_header(tservice, f_struct_helper); } generate_php_struct_definition(f_struct_helper, &result, false, true); - if (psr4_) { + if (!classmap_) { f_struct_helper.close(); } } @@ -1604,7 +1610,7 @@ void t_php_generator::generate_php_function_helpers(t_service* tservice, t_funct */ void t_php_generator::generate_service_interface(t_service* tservice) { std::ofstream& f_service_interface = f_service_; - if (psr4_) { + if (!classmap_) { string f_service_interface_name = package_dir_ + service_name_ + "If.php"; f_service_interface.open(f_service_interface_name.c_str()); generate_service_header(tservice, f_service_interface); @@ -1633,7 +1639,7 @@ void t_php_generator::generate_service_interface(t_service* tservice) { f_service_interface << "}" << endl; // Close service interface file - if (psr4_) { + if (!classmap_) { f_service_interface.close(); } } @@ -1643,7 +1649,7 @@ void t_php_generator::generate_service_interface(t_service* tservice) { */ void t_php_generator::generate_service_rest(t_service* tservice) { std::ofstream& f_service_rest = f_service_; - if (psr4_) { + if (!classmap_) { string f_service_rest_name = package_dir_ + service_name_ + "Rest.php"; f_service_rest.open(f_service_rest_name.c_str()); generate_service_header(tservice, f_service_rest); @@ -1712,7 +1718,7 @@ void t_php_generator::generate_service_rest(t_service* tservice) { // Close service rest file f_service_rest << endl; - if (psr4_) { + if (!classmap_) { f_service_rest.close(); } } @@ -1724,7 +1730,7 @@ void t_php_generator::generate_service_rest(t_service* tservice) { */ void t_php_generator::generate_service_client(t_service* tservice) { std::ofstream& f_service_client = f_service_; - if (psr4_) { + if (!classmap_) { string f_service_client_name = package_dir_ + service_name_ + "Client.php"; f_service_client.open(f_service_client_name.c_str()); generate_service_header(tservice, f_service_client); @@ -1979,7 +1985,7 @@ void t_php_generator::generate_service_client(t_service* tservice) { f_service_client << "}" << endl; // Close service client file - if (psr4_) { + if (!classmap_) { f_service_client.close(); } } @@ -2772,7 +2778,7 @@ THRIFT_REGISTER_GENERATOR( " inlined: Generate PHP inlined files\n" " server: Generate PHP server stubs\n" " oop: Generate PHP with object oriented subclasses\n" - " psr4: Generate each PHP class in separate file (allows PSR4 autoloading)\n" + " classmap: Generate old-style PHP files (use classmap autoloading)\n" " rest: Generate PHP REST processors\n" " nsglobal=NAME: Set global namespace\n" " validate: Generate PHP validator methods\n" diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc index 9078da842ba..caa04a86991 100644 --- a/compiler/cpp/src/thrift/generate/t_py_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc @@ -19,7 +19,9 @@ #include #include +#include #include +#include #include #include @@ -541,9 +543,9 @@ string t_py_generator::render_const_value(t_type* type, t_const_value* value) { break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { - out << value->get_integer(); + out << "float(" << value->get_integer() << ")"; } else { - out << value->get_double(); + out << emit_double_as_string(value->get_double()); } break; default: @@ -556,8 +558,8 @@ string t_py_generator::render_const_value(t_type* type, t_const_value* value) { indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -581,8 +583,8 @@ string t_py_generator::render_const_value(t_type* type, t_const_value* value) { } out << "{" << endl; indent_up(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { indent(out) << render_const_value(ktype, v_iter->first) << ": " << render_const_value(vtype, v_iter->second) << "," << endl; diff --git a/compiler/cpp/src/thrift/generate/t_rb_generator.cc b/compiler/cpp/src/thrift/generate/t_rb_generator.cc index 924f6f6eb2d..3f2b78e6ad8 100644 --- a/compiler/cpp/src/thrift/generate/t_rb_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_rb_generator.cc @@ -455,8 +455,8 @@ t_rb_ofstream& t_rb_generator::render_const_value(t_rb_ofstream& out, out.indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -478,8 +478,8 @@ t_rb_ofstream& t_rb_generator::render_const_value(t_rb_ofstream& out, t_type* vtype = ((t_map*)type)->get_val_type(); out << "{" << endl; out.indent_up(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out.indent(); render_const_value(out, ktype, v_iter->first) << " => "; diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc b/compiler/cpp/src/thrift/generate/t_rs_generator.cc index 28c57f83623..6001d8f660e 100644 --- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc @@ -781,8 +781,8 @@ void t_rs_generator::render_const_map(t_type* ttype, t_const_value* tvalue) { << to_rust_type(key_type) << ", " << to_rust_type(val_type) << "> = BTreeMap::new();" << endl; - const map& elems = tvalue->get_map(); - map::const_iterator elem_iter; + const map& elems = tvalue->get_map(); + map::const_iterator elem_iter; for (elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { t_const_value* key_value = elem_iter->first; t_const_value* val_value = elem_iter->second; diff --git a/compiler/cpp/src/thrift/generate/t_st_generator.cc b/compiler/cpp/src/thrift/generate/t_st_generator.cc index 69ed776a7f8..c45666ad94f 100644 --- a/compiler/cpp/src/thrift/generate/t_st_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_st_generator.cc @@ -402,8 +402,8 @@ string t_st_generator::render_const_value(t_type* type, t_const_value* value) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = NULL; @@ -428,8 +428,8 @@ string t_st_generator::render_const_value(t_type* type, t_const_value* value) { out << "(Dictionary new" << endl; indent_up(); indent_up(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent() << indent(); out << "at: " << render_const_value(ktype, v_iter->first); diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc index 87dd2f02076..7b4d22451b3 100644 --- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc @@ -1900,8 +1900,8 @@ void t_swift_generator::render_const_value(ostream& out, const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (f_iter = fields.begin(); f_iter != fields.end();) { t_field* tfield = *f_iter; @@ -1934,8 +1934,8 @@ void t_swift_generator::render_const_value(ostream& out, t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { @@ -1956,8 +1956,8 @@ void t_swift_generator::render_const_value(ostream& out, t_type* etype = ((t_list*)type)->get_elem_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { @@ -1976,8 +1976,8 @@ void t_swift_generator::render_const_value(ostream& out, t_type* etype = ((t_set*)type)->get_elem_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { diff --git a/compiler/cpp/src/thrift/generate/t_xml_generator.cc b/compiler/cpp/src/thrift/generate/t_xml_generator.cc index e7e01fd8c35..a832afd5864 100644 --- a/compiler/cpp/src/thrift/generate/t_xml_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_xml_generator.cc @@ -483,8 +483,8 @@ void t_xml_generator::write_const_value(t_const_value* value) { case t_const_value::CV_MAP: { write_element_start("map"); - std::map map = value->get_map(); - std::map::iterator mit; + std::map map = value->get_map(); + std::map::iterator mit; for (mit = map.begin(); mit != map.end(); ++mit) { write_element_start("entry"); write_element_start("key"); diff --git a/compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9 b/compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/compiler/cpp/src/thrift/main.cc b/compiler/cpp/src/thrift/main.cc index 84218405be2..0c21e0281aa 100644 --- a/compiler/cpp/src/thrift/main.cc +++ b/compiler/cpp/src/thrift/main.cc @@ -805,8 +805,8 @@ void validate_const_rec(std::string name, t_type* type, t_const_value* value) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (v_iter->first->get_type() != t_const_value::CV_STRING) { throw "type error: " + name + " struct key must be string"; @@ -826,8 +826,8 @@ void validate_const_rec(std::string name, t_type* type, t_const_value* value) { } else if (type->is_map()) { t_type* k_type = ((t_map*)type)->get_key_type(); t_type* v_type = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; + const map& val = value->get_map(); + map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { validate_const_rec(name + "", k_type, v_iter->first); validate_const_rec(name + "", v_type, v_iter->second); diff --git a/compiler/cpp/src/thrift/parse/t_const_value.h b/compiler/cpp/src/thrift/parse/t_const_value.h index fc2f648e880..f4416e9f487 100644 --- a/compiler/cpp/src/thrift/parse/t_const_value.h +++ b/compiler/cpp/src/thrift/parse/t_const_value.h @@ -38,6 +38,17 @@ void convert(From*, To&); */ class t_const_value { public: + /** + * Comparator to sort fields in ascending order by key. + * Make this a functor instead of a function to help GCC inline it. + */ + struct value_compare { + public: + bool operator()(t_const_value const* const& left, t_const_value const* const& right) const { + return *left < *right; + } + }; + enum t_const_value_type { CV_INTEGER, CV_DOUBLE, CV_STRING, CV_MAP, CV_LIST, CV_IDENTIFIER, CV_UNKNOWN }; t_const_value() : intVal_(0), doubleVal_(0.0f), enum_((t_enum*)0), valType_(CV_UNKNOWN) {} @@ -90,7 +101,7 @@ class t_const_value { void add_map(t_const_value* key, t_const_value* val) { mapVal_[key] = val; } - const std::map& get_map() const { return mapVal_; } + const std::map& get_map() const { return mapVal_; } void set_list() { valType_ = CV_LIST; } @@ -136,8 +147,55 @@ class t_const_value { t_const_value_type get_type() const { if (valType_ == CV_UNKNOWN) { throw std::string("unknown t_const_value"); } return valType_; } + /** + * Comparator to sort map fields in ascending order by key and then value. + * This is used for map comparison in lexicographic order. + */ + struct map_entry_compare { + private: + typedef std::pair ConstPair; + public: + bool operator()(ConstPair left, ConstPair right) const { + if (*(left.first) < *(right.first)) { + return true; + } else { + if (right.first < left.first) { + return *(left.second) < *(right.second); + } else { + return false; + } + } + } + }; + + bool operator < (const t_const_value& that) const { + ::t_const_value::t_const_value_type t1 = get_type(); + ::t_const_value::t_const_value_type t2 = that.get_type(); + if (t1 != t2) + return t1 < t2; + switch (t1) { + case ::t_const_value::CV_INTEGER: + return intVal_ < that.intVal_; + case ::t_const_value::CV_DOUBLE: + return doubleVal_ < that.doubleVal_; + case ::t_const_value::CV_STRING: + return stringVal_ < that.stringVal_; + case ::t_const_value::CV_IDENTIFIER: + return identifierVal_ < that.identifierVal_; + case ::t_const_value::CV_MAP: + return std::lexicographical_compare( + mapVal_.begin(), mapVal_.end(), that.mapVal_.begin(), that.mapVal_.end(), map_entry_compare()); + case ::t_const_value::CV_LIST: + return std::lexicographical_compare( + listVal_.begin(), listVal_.end(), that.listVal_.begin(), that.listVal_.end(), value_compare()); + case ::t_const_value::CV_UNKNOWN: + default: + throw "unknown value type"; + } + } + private: - std::map mapVal_; + std::map mapVal_; std::vector listVal_; std::string stringVal_; int64_t intVal_; diff --git a/compiler/cpp/src/thrift/parse/t_scope.h b/compiler/cpp/src/thrift/parse/t_scope.h index 02aa550bfda..6f160a5cc8b 100644 --- a/compiler/cpp/src/thrift/parse/t_scope.h +++ b/compiler/cpp/src/thrift/parse/t_scope.h @@ -76,8 +76,8 @@ class t_scope { void resolve_const_value(t_const_value* const_val, t_type* ttype) { if (ttype->is_map()) { - const std::map& map = const_val->get_map(); - std::map::const_iterator v_iter; + const std::map& map = const_val->get_map(); + std::map::const_iterator v_iter; for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { resolve_const_value(v_iter->first, ((t_map*)ttype)->get_key_type()); resolve_const_value(v_iter->second, ((t_map*)ttype)->get_val_type()); @@ -96,8 +96,8 @@ class t_scope { } } else if (ttype->is_struct()) { t_struct* tstruct = (t_struct*)ttype; - const std::map& map = const_val->get_map(); - std::map::const_iterator v_iter; + const std::map& map = const_val->get_map(); + std::map::const_iterator v_iter; for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { t_field* field = tstruct->get_field_by_name(v_iter->first->get_string()); if (field == NULL) { @@ -137,8 +137,8 @@ class t_scope { throw "Constants cannot be of type VOID"; } } else if (const_type->is_map()) { - const std::map& map = constant->get_value()->get_map(); - std::map::const_iterator v_iter; + const std::map& map = constant->get_value()->get_map(); + std::map::const_iterator v_iter; const_val->set_map(); for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { diff --git a/compiler/cpp/src/thrift/thrifty.yy b/compiler/cpp/src/thrift/thrifty.yy index e4cae0c29cf..df34adf0452 100644 --- a/compiler/cpp/src/thrift/thrifty.yy +++ b/compiler/cpp/src/thrift/thrifty.yy @@ -35,6 +35,7 @@ #define __STDC_FORMAT_MACROS #endif #include +#include #ifndef _MSC_VER #include #else diff --git a/compiler/cpp/test/plugin/conversion_test.cc b/compiler/cpp/test/plugin/conversion_test.cc index e73aa168d94..3c8d812cfba 100644 --- a/compiler/cpp/test/plugin/conversion_test.cc +++ b/compiler/cpp/test/plugin/conversion_test.cc @@ -277,12 +277,12 @@ void test_const_value(t_const_value* sut) { BOOST_CHECK_EQUAL(sut->get_map().size(), sut2->get_map().size()); { std::map sut_values; - for (std::map::const_iterator it = sut->get_map().begin(); + for (std::map::const_iterator it = sut->get_map().begin(); it != sut->get_map().end(); it++) { sut_values[it->first->get_type()] = it->second->get_type(); } std::map sut2_values; - for (std::map::const_iterator it = sut2->get_map().begin(); + for (std::map::const_iterator it = sut2->get_map().begin(); it != sut2->get_map().end(); it++) { sut2_values[it->first->get_type()] = it->second->get_type(); } diff --git a/configure.ac b/configure.ac index b20312fd1f0..917f6fa2262 100755 --- a/configure.ac +++ b/configure.ac @@ -119,6 +119,7 @@ if test "$enable_libs" = "no"; then have_libs="no" with_cpp="no" with_c_glib="no" + with_cl="no" with_java="no" with_csharp="no" with_python="no" @@ -453,6 +454,16 @@ if test "$with_rs" = "yes"; then fi AM_CONDITIONAL(WITH_RS, [test "$have_rs" = "yes"]) +AX_THRIFT_LIB(cl, [Common Lisp], yes) +have_cl="no" +if test "$with_cl" = "yes"; then + AC_PATH_PROG([SBCL], [sbcl]) + if test "x$SBCL" != "x"; then + have_cl="yes" + fi +fi +AM_CONDITIONAL(WITH_CL, [test "$have_cl" = "yes"]) + AX_THRIFT_LIB(haxe, [Haxe], yes) if test "$with_haxe" = "yes"; then AC_PATH_PROG([HAXE], [haxe]) @@ -622,8 +633,10 @@ AC_CHECK_HEADERS([limits.h]) AC_CHECK_HEADERS([netdb.h]) AC_CHECK_HEADERS([netinet/in.h]) AC_CHECK_HEADERS([pthread.h]) +AC_CHECK_HEADERS([signal.h]) AC_CHECK_HEADERS([stddef.h]) AC_CHECK_HEADERS([stdlib.h]) +AC_CHECK_HEADERS([sys/ioctl.h]) AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([sys/un.h]) @@ -784,6 +797,7 @@ AC_CONFIG_FILES([ compiler/cpp/test/Makefile compiler/cpp/src/thrift/version.h lib/Makefile + lib/cl/Makefile lib/cpp/Makefile lib/cpp/test/Makefile lib/cpp/thrift-nb.pc @@ -825,6 +839,7 @@ AC_CONFIG_FILES([ test/Makefile test/features/Makefile test/c_glib/Makefile + test/cl/Makefile test/cpp/Makefile test/csharp/Makefile test/erl/Makefile @@ -843,6 +858,7 @@ AC_CONFIG_FILES([ test/rs/Makefile tutorial/Makefile tutorial/c_glib/Makefile + tutorial/cl/Makefile tutorial/cpp/Makefile tutorial/d/Makefile tutorial/go/Makefile @@ -896,6 +912,8 @@ if test "$have_rs" = "yes" ; then MAYBE_RS="rs" ; else MAYBE_RS="" ; fi AC_SUBST([MAYBE_RS]) if test "$have_dotnetcore" = "yes" ; then MAYBE_DOTNETCORE="netcore" ; else MAYBE_DOTNETCORE="" ; fi AC_SUBST([MAYBE_DOTNETCORE]) +if test "$have_cl" = "yes" ; then MAYBE_CL="cl" ; else MAYBE_CL="" ; fi +AC_SUBST([MAYBE_CL]) AC_OUTPUT @@ -906,6 +924,7 @@ echo echo "Building C (GLib) Library .... : $have_c_glib" echo "Building C# (Mono) Library ... : $have_csharp" echo "Building C++ Library ......... : $have_cpp" +echo "Building Common Lisp Library.. : $have_cl" echo "Building D Library ........... : $have_d" echo "Building Dart Library ........ : $have_dart" echo "Building dotnetcore Library .. : $have_dotnetcore" @@ -940,6 +959,12 @@ if test "$have_cpp" = "yes" ; then echo " Build TQTcpServer (Qt5) ... : $have_qt5" echo " C++ compiler version ...... : $($CXX --version | head -1)" fi +if test "$have_cl" = "yes" ; then + echo + echo "Common Lisp Library:" + echo " Using Common Lisp ......... : $SBCL" + echo " Using Common Lisp version . : $($SBCL --version)" +fi if test "$have_d" = "yes" ; then echo echo "D Library:" diff --git a/lib/Makefile.am b/lib/Makefile.am index 636f42cfc50..0401c99e112 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -97,6 +97,10 @@ if WITH_RS SUBDIRS += rs endif +if WITH_CL +SUBDIRS += cl +endif + # All of the libs that don't use Automake need to go in here # so they will end up in our release tarballs. EXTRA_DIST = \ diff --git a/lib/cl/Makefile.am b/lib/cl/Makefile.am new file mode 100644 index 00000000000..34b38861d23 --- /dev/null +++ b/lib/cl/Makefile.am @@ -0,0 +1,40 @@ +# +# 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. +# + +THRIFT = $(top_builddir)/compiler/cpp/thrift + +all-local: + bash ensure-externals.sh + +run-tests: test/make-test-binary.lisp + $(SBCL) --script test/make-test-binary.lisp + +check-local: run-tests + ./run-tests + +clean-local: + $(RM) run-tests quicklisp.lisp backport-update.zip + $(RM) -rf lib externals quicklisp + +EXTRA_DIST = \ + README.md \ + READMES \ + load-locally.lisp \ + test \ + ensure-externals.sh diff --git a/lib/cl/README.md b/lib/cl/README.md new file mode 100644 index 00000000000..1d6eafbd793 --- /dev/null +++ b/lib/cl/README.md @@ -0,0 +1,253 @@ +Thrift Common Lisp Library + +License +======= + +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. + + + +Using Thrift with Common Lisp +============================ + + Thrift is a protocol and library for language-independent communication between cooperating + processes. The communication takes the form of request and response messages, of which the forms + are specified in advance throufh a shared interface definition. A Thrift definition file is translated + into Lisp source files, which comprise several definitions: + + * Three packages, one for the namespace of the implementation operators, and one each for request and + response operators. + * Various type definitions as implementations for Thrift typedef and enum definitions. + * DEF-STRUCT and DEF-EXCEPTION forms for Thrift struct and exception definitions. + * DEF-SERVICE forms for thrift service definitions. + + Each service definition expands in a collection of generic function definitions. For each `op` + in the service definition, two functions are defined + + * `op`-request is defined for use by a client. It accepts an additional initial `protocol` argument, + to act as the client proxy for the operation and mediate the interaction with a remote process + through a Thrift-encoded transport stream. + * `op`-response is defined for use by a server. It accepts a single `protocol` argument. A server + uses it to decode the request message, invoke the base `op` function with the message arguments, + encode and send the the result as a response, and handles exceptions. + + The client interface is one operator + + * `with-client (variable location) . body` : creates a connection in a dynamic context and closes it + upon exit. The variable is bound to a client proxy stream/protocol instance, which wraps the + base i/o stream - socket, file, etc, with an operators which implement the Thrift protocol + and transport mechanisms. + + The server interface combines server and service objects + + * `serve (location service)` : accepts connections on the designated port and responds to + requests of the service's operations. + + +Building +-------- + +The Thrift Common Lisp library is packaged as the ASDF[[1]] system `thrift`. +It depends on the systems + +* puri[[2]] : for the thrift uri class +* closer-mop[[3]] : for class metadata +* trivial-utf-8[[4]] : for string codecs +* usocket[[5]] : for the socket transport +* ieee-floats[[6]] : for conversion between ints and floats +* trivial-gray-streams[[7]] : an abstraction layer for gray streams +* alexandria[[8]] : handy utilities + +The dependencies are bundled for local builds of tests and tutorial binaries - +it is possible to use those bundles to load the library, too. + +In order to build it, register those systems with ASDF and evaluate: + + (asdf:load-system :thrift) + +This will compile and load the Lisp compiler for Thrift definition files, the +transport and protocol implementations, and the client and server interface +functions. In order to use Thrift in an application, one must also author and/or +load the interface definitions for the remote service.[[9]] If one is implementing a service, +one must also define the actual functions to which Thrift is to act as the proxy +interface. The remainder of this document follows the Thrift tutorial to illustrate how +to perform the steps + + * implement the service + * translate the Thrift IDL + * load the Lisp service interfaces + * run a server for the service + * use a client to access the service remotely + +Note that, if one is to implement a new service, one will also need to author the +IDL files, as there is no facility to generate them from a service implementation. + + +Implement the Service +--------------------- + +The tutorial comprises serveral functions: `add`, `ping`, `zip`, and `calculate`. +Each translated IDL file generates three packages for every service. In the case of +the tutorial file, the relevant packages are: + + * tutorial.calculator + * tutorial.calculator-implementation + * tutorial.calculator-response + +This is to separate the request (generated), response (generated) and implementation +(meant to be implemented by the programmer) functions for defined Thrift methods. + +It is suggested to work in the `tutorial-implementation` package while implementing +the services - it imports the `common-lisp` package, while the service-specific ones +don't (to avoid conflicts between Thrift method names and function names in `common-lisp`). + + ;; define the base operations + + (in-package :tutorial-implementation) + + (defun tutorial.calculator-implementation:add (num1 num2) + (format t "~&Asked to add ~A and ~A." num1 num2) + (+ num1 num2)) + + (defun tutorial.calculator-implementation:ping () + (print :ping)) + + (defun tutorial.calculator-implementation:zip () + (print :zip)) + + (defun tutorial.calculator-implementation:calculate (logid task) + (calculate-op (work-op task) (work-num1 task) (work-num2 task))) + + (defgeneric calculate-op (op arg1 arg2) + (:method :around (op arg1 arg2) + (let ((result (call-next-method))) + (format t "~&Asked to calculate: ~d on ~A and ~A = ~d." op arg1 arg2 result) + result)) + + (:method ((op (eql operation.add)) arg1 arg2) + (+ arg1 arg2)) + (:method ((op (eql operation.subtract)) arg1 arg2) + (- arg1 arg2)) + (:method ((op (eql operation.multiply)) arg1 arg2) + (* arg1 arg2)) + (:method ((op (eql operation.divide)) arg1 arg2) + (/ arg1 arg2))) + + (defun zip () (print 'zip)) + + +Translate the Thrift IDL +------------------------ + +IDL files employ the file extension `thrift`. In this case, there are two files to translate + * `tutorial.thrift` + * `shared.thrift` +As the former includes the latter, one uses it to generate the interfaces: + + $THRIFT/bin/thrift -r --gen cl $THRIFT/tutorial/tutorial.thrift + +`-r` stands for recursion, while `--gen` lets one choose the language to translate to. + + +Load the Lisp translated service interfaces +------------------------------------------- + +The translator generates three files for each IDL file. For example `tutorial-types.lisp`, +`tutorial-vars.lisp` and an `.asd` file that can be used to load them both and pull in +other includes (like `shared` within the tutorial) as dependencies. + + +Run a Server for the Service +---------------------------- + +The actual service name, as specified in the `def-service` form in `tutorial.lisp`, is `calculator`. +Each service definition defines a global variable with the service name and binds it to a +service instance whch describes the operations. + +In order to start a service, specify a location and the service instance. + + (in-package :tutorial) + (serve #u"thrift://127.0.0.1:9091" calculator) + + +Use a Client to Access the Service Remotely +------------------------------------------- + + +[in some other process] run the client + + (in-package :cl-user) + + (macrolet ((show (form) + `(format *trace-output* "~%~s =>~{ ~s~}" + ',form + (multiple-value-list (ignore-errors ,form))))) + (with-client (protocol #u"thrift://127.0.0.1:9091") + (show (tutorial.calculator:ping protocol)) + (show (tutorial.calculator:add protocol 1 2)) + (show (tutorial.calculator:add protocol 1 4)) + + (let ((task (make-instance 'tutorial:work + :op operation.subtract :num1 15 :num2 10))) + (show (tutorial.calculator:calculate protocol 1 task)) + + (setf (tutorial:work-op task) operation.divide + (tutorial:work-num1 task) 1 + (tutorial:work-num2 task) 0) + (show (tutorial.calculator:calculate protocol 1 task))) + + (show (shared.shared-service:get-struct protocol 1)) + + (show (zip protocol)))) + +Issues +------ + +### optional fields + Where the IDL declares a field options, the def-struct form includes no + initform for the slot and the encoding operator skips an unbound slot. This leave some ambiguity + with bool fields. + +### instantiation protocol : + struct classes are standard classes and exception classes are + whatever the implementation prescribes. decoders apply make-struct to an initargs list. + particularly at the service end, there are advantages to resourcing structs and decoding + with direct side-effects on slot-values + +### maps: + Maps are now represented as hash tables. As data through the call/reply interface is all statically + typed, it is not necessary for the objects to themselves indicate the coding form. Association lists + would be sufficient. As the key type is arbitrary, property lists offer no additional convenience: + as `getf` operates with `eq` a new access interface would be necessary and they would not be + available for function application. + + + [1]: www.common-lisp.net/asdf + [2]: http://github.com/lisp/com.b9.puri.ppcre + [3]: www.common-lisp.net/closer-mop + [4]: trivial-utf-8 + [5]: https://github.com/usocket/usocket + [6]: https://github.com/marijnh/ieee-floats + [7]: https://github.com/trivial-gray-streams/trivial-gray-streams + [8]: https://gitlab.common-lisp.net/alexandria/alexandria + [9]: http://wiki.apache.org/thrift/ThriftGeneration + +* usocket[[5]] : for the socket transport +* ieee-floats[[6]] : for conversion between ints and floats +* trivial-gray-streams[[7]] : an abstraction layer for gray streams +* alexandria[[8]] : handy utilities diff --git a/lib/cl/READMES/readme-cassandra.lisp b/lib/cl/READMES/readme-cassandra.lisp new file mode 100644 index 00000000000..72744ea99ca --- /dev/null +++ b/lib/cl/READMES/readme-cassandra.lisp @@ -0,0 +1,64 @@ +(in-package :cl-user) + +#+(or ccl sbcl) /development/source/library/ +(load "build-init.lisp") + +;;; ! first, select the api version in the cassandra system definition +;;; as only one should be loaded at a time. +(asdf:load-system :de.setf.cassandra) + +(in-package :de.setf.cassandra) + +(defparameter *c-location* + ;; remote + ;; #u"thrift://ec2-174-129-66-148.compute-1.amazonaws.com:9160" + ;; local + #u"thrift://127.0.0.1:9160" + "A cassandra service location - either the local one or a remote service + - always a 'thrift' uri.") + +(defparameter *c* (thrift:client *c-location*)) + + +(cassandra:describe-keyspaces *c*) +;; => ("Keyspace1" "system") + +(cassandra:describe-cluster-name *c*) +;; =>"Test Cluster" + +(cassandra:describe-version *c*) +;; => "2.1.0" + +(loop for space in (cassandra:describe-keyspaces *c*) + collect (loop for key being each hash-key of (cassandra:describe-keyspace *c* space) + using (hash-value value) + collect (cons key + (loop for key being each hash-key of value + using (hash-value value) + collect (cons key value))))) + + +(close *c*) + +(defun describe-cassandra (location &optional (stream *standard-output*)) + "Print the first-order store metadata for a cassandra LOCATION." + + (thrift:with-client (cassandra location) + (let* ((keyspace-names (cassandra:describe-keyspaces cassandra)) + (cluster (cassandra:describe-cluster-name cassandra)) + (version (cassandra:describe-version cassandra)) + (keyspace-descriptions (loop for space in keyspace-names + collect (cons space + (loop for key being each hash-key + of (cassandra:describe-keyspace cassandra space) + using (hash-value value) + collect (cons key + (loop for key being each hash-key of value + using (hash-value value) + collect (cons key value)))))))) + (format stream "~&connection to : ~a" cassandra) + (format stream "~&version : ~a" version) + (format stream "~&cluster : ~a" cluster) + (format stream "~&keyspaces~{~{~%~%space: ~a~@{~% ~{~a :~@{~20t~:w~^~%~}~}~}~}~}" keyspace-descriptions)))) + +;;; (describe-cassandra *c-location*) diff --git a/lib/cl/ensure-externals.sh b/lib/cl/ensure-externals.sh new file mode 100755 index 00000000000..0495f030c66 --- /dev/null +++ b/lib/cl/ensure-externals.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e + +if [[ ! -e quicklisp.lisp ]]; then curl -O https://beta.quicklisp.org/quicklisp.lisp; fi +sbcl --load quicklisp.lisp \ + --eval "(ignore-errors (quicklisp-quickstart:install :path \"quicklisp/\"))" \ + --eval "(load \"quicklisp/setup.lisp\")" \ + --eval "(quicklisp:bundle-systems '(#:puri #:usocket #:closer-mop #:trivial-utf-8 #:ieee-floats #:trivial-gray-streams #:alexandria #:bordeaux-threads #:cl-ppcre #:fiasco #:net.didierverna.clon) :to \"externals/\")" \ + --eval "(quit)" \ + --no-userinit +if [[ ! -e backport-update.zip ]]; then + curl -O -L https://github.com/TurtleWarePL/de.setf.thrift/archive/backport-update.zip; +fi +mkdir -p lib +unzip -u backport-update.zip -d lib diff --git a/lib/cl/load-locally.lisp b/lib/cl/load-locally.lisp new file mode 100644 index 00000000000..d12c70476a5 --- /dev/null +++ b/lib/cl/load-locally.lisp @@ -0,0 +1,23 @@ +(in-package #:cl-user) + +;;;; Licensed 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. + +;;;; Just a script for loading the library itself, using bundled dependencies. +;;;; This is here for when we want to build the self-test and cross-test +;;;; binaries. + +(require "asdf") + +(load (merge-pathnames "externals/bundle.lisp" *load-truename*)) +(asdf:load-asd (merge-pathnames "lib/de.setf.thrift-backport-update/thrift.asd" *load-truename*)) +(asdf:load-system :thrift) diff --git a/lib/cl/test/make-test-binary.lisp b/lib/cl/test/make-test-binary.lisp new file mode 100644 index 00000000000..4e7a58cc43d --- /dev/null +++ b/lib/cl/test/make-test-binary.lisp @@ -0,0 +1,31 @@ +;;;; Licensed 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. + +;;;; This file is used to build the binary that runs all self-tests. The +;;;; binary is then meant to be hooked up to Thrift's `make check` facility, +;;;; but can easily be run on its own as well. + +(in-package #:cl-user) + +(require "asdf") +(load (merge-pathnames "../load-locally.lisp" *load-truename*)) +(asdf:load-asd (merge-pathnames "../lib/de.setf.thrift-backport-update/test/thrift-test.asd" *load-truename*)) +(asdf:load-system :thrift-test) +(asdf:load-system :net.didierverna.clon) + +(net.didierverna.clon:nickname-package) + +(defun main () + (let ((result (if (fiasco:run-tests 'thrift-test) 0 -1))) + (clon:exit result))) + +(clon:dump "run-tests" main) diff --git a/lib/cocoa/src/protocol/TBase.h b/lib/cocoa/src/protocol/TBase.h index b31061ec0cd..9935d506842 100644 --- a/lib/cocoa/src/protocol/TBase.h +++ b/lib/cocoa/src/protocol/TBase.h @@ -26,14 +26,14 @@ /** * De-serialize object from the given input protocol * - * @param input protocol used for reading + * @param inProtocol protocol used for reading */ -(BOOL) read:(id )inProtocol error:(NSError **)error; /** * Serialize object to the given protocol * - * @param buf output protocol used for writing + * @param outProtocol output protocol used for writing */ -(BOOL) write:(id )outProtocol error:(NSError **)error; diff --git a/lib/cpp/src/thrift/TOutput.cpp b/lib/cpp/src/thrift/TOutput.cpp index bb46263b8af..ae3a9e28220 100644 --- a/lib/cpp/src/thrift/TOutput.cpp +++ b/lib/cpp/src/thrift/TOutput.cpp @@ -94,7 +94,7 @@ void TOutput::errorTimeWrapper(const char* msg) { } void TOutput::perror(const char* message, int errno_copy) { - std::string out = message + strerror_s(errno_copy); + std::string out = message + std::string(": ") + strerror_s(errno_copy); f_(out.c_str()); } diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp index d17f77c1922..f89b5f79359 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp +++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp @@ -472,6 +472,18 @@ void TNonblockingServer::TConnection::workSocket() { } // size known; now get the rest of the frame transition(); + + // If the socket has more data than the frame header, continue to work on it. This is not strictly necessary for + // regular sockets, because if there is more data, libevent will fire the event handler registered for read + // readiness, which will in turn call workSocket(). However, some socket types (such as TSSLSocket) may have the + // data sitting in their internal buffers and from libevent's perspective, there is no further data available. In + // that case, not having this workSocket() call here would result in a hang as we will never get to work the socket, + // despite having more data. + if (tSocket_->hasPendingDataToRead()) + { + workSocket(); + } + return; case SOCKET_RECV: @@ -647,6 +659,7 @@ void TNonblockingServer::TConnection::transition() { return; } } + // fallthrough // Intentionally fall through here, the call to process has written into // the writeBuffer_ @@ -677,9 +690,6 @@ void TNonblockingServer::TConnection::transition() { appState_ = APP_SEND_RESULT; setWrite(); - // Try to work the socket immediately - // workSocket(); - return; } @@ -698,6 +708,7 @@ void TNonblockingServer::TConnection::transition() { server_->getIdleWriteBufferLimit()); callsForResize_ = 0; } + // fallthrough // N.B.: We also intentionally fall through here into the INIT state! @@ -718,9 +729,6 @@ void TNonblockingServer::TConnection::transition() { // Register read event setRead(); - // Try to work the socket right away - // workSocket(); - return; case APP_READ_FRAME_SIZE: @@ -753,9 +761,6 @@ void TNonblockingServer::TConnection::transition() { socketState_ = SOCKET_RECV; appState_ = APP_READ_REQUEST; - // Work the socket right away - workSocket(); - return; case APP_CLOSE_CONNECTION: @@ -1063,7 +1068,7 @@ void TNonblockingServer::expireClose(stdcxx::shared_ptr task) { connection->forceClose(); } -void TNonblockingServer::stop() { +void TNonblockingServer::stop() { // Breaks the event loop in all threads so that they end ASAP. for (uint32_t i = 0; i < ioThreads_.size(); ++i) { ioThreads_[i]->stop(); diff --git a/lib/cpp/src/thrift/transport/PlatformSocket.h b/lib/cpp/src/thrift/transport/PlatformSocket.h index 1890b607de4..95910580613 100644 --- a/lib/cpp/src/thrift/transport/PlatformSocket.h +++ b/lib/cpp/src/thrift/transport/PlatformSocket.h @@ -51,6 +51,8 @@ # define THRIFT_LSEEK _lseek # define THRIFT_WRITE _write # define THRIFT_READ _read +# define THRIFT_IOCTL_SOCKET ioctlsocket +# define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE u_long # define THRIFT_FSTAT _fstat # define THRIFT_STAT _stat # ifdef _WIN32_WCE @@ -111,6 +113,8 @@ # define THRIFT_LSEEK lseek # define THRIFT_WRITE write # define THRIFT_READ read +# define THRIFT_IOCTL_SOCKET ioctl +# define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE int # define THRIFT_STAT stat # define THRIFT_FSTAT fstat # define THRIFT_GAI_STRERROR gai_strerror diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.cpp b/lib/cpp/src/thrift/transport/TBufferTransports.cpp index 1d2692dca54..9ac2f844b90 100644 --- a/lib/cpp/src/thrift/transport/TBufferTransports.cpp +++ b/lib/cpp/src/thrift/transport/TBufferTransports.cpp @@ -368,7 +368,7 @@ void TMemoryBuffer::ensureCanWrite(uint32_t len) { throw TTransportException(TTransportException::BAD_ARGS, "Internal buffer size overflow"); } - avail = available_write() + (new_size - bufferSize_); + avail = available_write() + (static_cast(new_size) - bufferSize_); } // Allocate into a new pointer so we don't bork ours if it fails. @@ -382,7 +382,7 @@ void TMemoryBuffer::ensureCanWrite(uint32_t len) { wBase_ = new_buffer + (wBase_ - buffer_); wBound_ = new_buffer + new_size; buffer_ = new_buffer; - bufferSize_ = new_size; + bufferSize_ = static_cast(new_size); } void TMemoryBuffer::writeSlow(const uint8_t* buf, uint32_t len) { diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp index 3f0e28ed8c9..7071698ac62 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp @@ -249,6 +249,17 @@ TSSLSocket::~TSSLSocket() { close(); } +bool TSSLSocket::hasPendingDataToRead() { + if (!isOpen()) { + return false; + } + initializeHandshake(); + if (!checkHandshake()) + throw TSSLException("TSSLSocket::hasPendingDataToRead: Handshake is not completed"); + // data may be available in SSL buffers (note: SSL_pending does not have a failure mode) + return SSL_pending(ssl_) > 0 || TSocket::hasPendingDataToRead(); +} + void TSSLSocket::init() { handshakeCompleted_ = false; readRetryCount_ = 0; @@ -293,6 +304,7 @@ bool TSSLSocket::peek() { && (errno_copy != THRIFT_EAGAIN)) { break; } + // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: // in the case of SSL_ERROR_SYSCALL we want to wait for an read event again @@ -339,6 +351,7 @@ void TSSLSocket::close() { && (errno_copy != THRIFT_EAGAIN)) { break; } + // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: // in the case of SSL_ERROR_SYSCALL we want to wait for an write/read event again @@ -404,6 +417,8 @@ uint32_t TSSLSocket::read(uint8_t* buf, uint32_t len) { // a certain number break; } + // fallthrough + case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { @@ -460,6 +475,7 @@ void TSSLSocket::write(const uint8_t* buf, uint32_t len) { && (errno_copy != THRIFT_EAGAIN)) { break; } + // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { @@ -504,6 +520,7 @@ uint32_t TSSLSocket::write_partial(const uint8_t* buf, uint32_t len) { && (errno_copy != THRIFT_EAGAIN)) { break; } + // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { @@ -591,6 +608,7 @@ void TSSLSocket::initializeHandshake() { && (errno_copy != THRIFT_EAGAIN)) { break; } + // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { @@ -623,6 +641,7 @@ void TSSLSocket::initializeHandshake() { && (errno_copy != THRIFT_EAGAIN)) { break; } + // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h index 852720930b4..ec30cc1491f 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLSocket.h @@ -78,6 +78,7 @@ class TSSLSocket : public TSocket { bool peek(); void open(); void close(); + bool hasPendingDataToRead(); uint32_t read(uint8_t* buf, uint32_t len); void write(const uint8_t* buf, uint32_t len); uint32_t write_partial(const uint8_t* buf, uint32_t len); diff --git a/lib/cpp/src/thrift/transport/TSocket.cpp b/lib/cpp/src/thrift/transport/TSocket.cpp index d93d0ffd401..18cadbc0611 100644 --- a/lib/cpp/src/thrift/transport/TSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSocket.cpp @@ -21,6 +21,9 @@ #include #include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif #ifdef HAVE_SYS_SOCKET_H #include #endif @@ -167,6 +170,26 @@ TSocket::~TSocket() { close(); } +bool TSocket::hasPendingDataToRead() { + if (!isOpen()) { + return false; + } + + int32_t retries = 0; + THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE numBytesAvailable; +try_again: + int r = THRIFT_IOCTL_SOCKET(socket_, FIONREAD, &numBytesAvailable); + if (r == -1) { + int errno_copy = THRIFT_GET_SOCKET_ERROR; + if (errno_copy == THRIFT_EINTR && (retries++ < maxRecvRetries_)) { + goto try_again; + } + GlobalOutput.perror("TSocket::hasPendingDataToRead() THRIFT_IOCTL_SOCKET() " + getSocketInfo(), errno_copy); + throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); + } + return numBytesAvailable > 0; +} + bool TSocket::isOpen() { return (socket_ != THRIFT_INVALID_SOCKET); } @@ -786,11 +809,15 @@ void TSocket::setMaxRecvRetries(int maxRecvRetries) { string TSocket::getSocketInfo() { std::ostringstream oss; - if (host_.empty() || port_ == 0) { - oss << ""; + if (path_.empty()) { + if (host_.empty() || port_ == 0) { + oss << ""; + } else { + oss << ""; + } } else { - oss << ""; + oss << ""; } return oss.str(); } diff --git a/lib/cpp/src/thrift/transport/TSocket.h b/lib/cpp/src/thrift/transport/TSocket.h index 1f95e68bd95..66d9e6cd37d 100644 --- a/lib/cpp/src/thrift/transport/TSocket.h +++ b/lib/cpp/src/thrift/transport/TSocket.h @@ -84,7 +84,9 @@ class TSocket : public TVirtualTransport { virtual bool isOpen(); /** - * Calls select on the socket to see if there is more data available. + * Checks whether there is more data available in the socket to read. + * + * This call blocks until at least one byte is available or the socket is closed. */ virtual bool peek(); @@ -100,6 +102,17 @@ class TSocket : public TVirtualTransport { */ virtual void close(); + /** + * Determines whether there is pending data to read or not. + * + * This call does not block. + * \throws TTransportException of types: + * NOT_OPEN means the socket has been closed + * UNKNOWN means something unexpected happened + * \returns true if there is pending data to read, false otherwise + */ + virtual bool hasPendingDataToRead(); + /** * Reads from the underlying socket. * \returns the number of bytes read or 0 indicates EOF diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt index 9b62cc9524c..261382f6584 100644 --- a/lib/cpp/test/CMakeLists.txt +++ b/lib/cpp/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# +# # 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 @@ -19,9 +19,6 @@ include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") -add_definitions("-D__STDC_FORMAT_MACROS") -add_definitions("-D__STDC_LIMIT_MACROS") - if (WITH_DYN_LINK_TEST) add_definitions( -DBOOST_TEST_DYN_LINK ) endif() diff --git a/lib/cpp/test/Makefile.am b/lib/cpp/test/Makefile.am index 587e2be58f1..4b9f77d2142 100755 --- a/lib/cpp/test/Makefile.am +++ b/lib/cpp/test/Makefile.am @@ -39,6 +39,8 @@ nodist_libtestgencpp_la_SOURCES = \ gen-cpp/AnnotationTest_types.h \ gen-cpp/DebugProtoTest_types.cpp \ gen-cpp/DebugProtoTest_types.h \ + gen-cpp/DoubleConstantsTest_constants.cpp \ + gen-cpp/DoubleConstantsTest_constants.h \ gen-cpp/EnumTest_types.cpp \ gen-cpp/EnumTest_types.h \ gen-cpp/OptionalRequiredTest_types.cpp \ @@ -102,6 +104,7 @@ check_PROGRAMS = \ link_test \ OpenSSLManualInitTest \ EnumTest \ + RenderedDoubleConstantsTest \ AnnotationTest if AMX_HAVE_LIBEVENT @@ -202,6 +205,10 @@ EnumTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) +RenderedDoubleConstantsTest_SOURCES = RenderedDoubleConstantsTest.cpp + +RenderedDoubleConstantsTest_LDADD = libtestgencpp.la $(BOOST_TEST_LDADD) + AnnotationTest_SOURCES = \ AnnotationTest.cpp @@ -379,6 +386,10 @@ gen-cpp/AnnotationTest_constants.cpp gen-cpp/AnnotationTest_constants.h gen-cpp/ gen-cpp/DebugProtoTest_types.cpp gen-cpp/DebugProtoTest_types.h gen-cpp/EmptyService.cpp gen-cpp/EmptyService.h: $(top_srcdir)/test/DebugProtoTest.thrift $(THRIFT) --gen cpp $< +gen-cpp/DoubleConstantsTest_constants.cpp gen-cpp/DoubleConstantsTest_constants.h: $(top_srcdir)/test/DoubleConstantsTest.thrift + $(THRIFT) --gen cpp $< + + gen-cpp/EnumTest_types.cpp gen-cpp/EnumTest_types.h: $(top_srcdir)/test/EnumTest.thrift $(THRIFT) --gen cpp $< diff --git a/lib/cpp/test/RenderedDoubleConstantsTest.cpp b/lib/cpp/test/RenderedDoubleConstantsTest.cpp new file mode 100644 index 00000000000..0ca042b7396 --- /dev/null +++ b/lib/cpp/test/RenderedDoubleConstantsTest.cpp @@ -0,0 +1,122 @@ +/* + * 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. + */ +#define EPSILON 0.0000001 +#include +#include +#include + +#include "gen-cpp/DoubleConstantsTest_constants.h" +using namespace thrift::test; + +#define BOOST_TEST_MODULE RenderedDoubleConstantsTest +#include + +BOOST_AUTO_TEST_SUITE(RenderedDoubleConstantsTest) + +BOOST_AUTO_TEST_CASE(test_rendered_double_constants) { + const double EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0; + const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0; + const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0; + const double EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0; + const double EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359; + const double EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1; + const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1; + const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308; + const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43; + const double EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308; + const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43; + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, EPSILON); + BOOST_CHECK_CLOSE( + g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, EPSILON); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST).hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE).hash_code()); + BOOST_CHECK( + typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST) + .hash_code() == + typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE).hash_code()); +} + +BOOST_AUTO_TEST_CASE(test_rendered_double_list) { + const std::vector EXPECTED_DOUBLE_LIST{1.0,-100.0,100.0,9223372036854775807.0,-9223372036854775807.0, + 3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,9223372036854775816.43,-9223372036854775816.43}; + BOOST_CHECK_EQUAL(g_DoubleConstantsTest_constants.DOUBLE_LIST_TEST.size(), EXPECTED_DOUBLE_LIST.size()); + for (unsigned int i = 0; i < EXPECTED_DOUBLE_LIST.size(); ++i) { + BOOST_CHECK_CLOSE(g_DoubleConstantsTest_constants.DOUBLE_LIST_TEST[i], EXPECTED_DOUBLE_LIST[i], EPSILON); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/lib/cpp/test/TNonblockingServerTest.cpp b/lib/cpp/test/TNonblockingServerTest.cpp index 74ffd1d546b..63d8a046133 100644 --- a/lib/cpp/test/TNonblockingServerTest.cpp +++ b/lib/cpp/test/TNonblockingServerTest.cpp @@ -178,7 +178,7 @@ class Fixture { protected: shared_ptr server; private: - shared_ptr thread; + shared_ptr thread; }; diff --git a/lib/cpp/test/concurrency/Tests.cpp b/lib/cpp/test/concurrency/Tests.cpp index df5099d8bc2..fc0ba7f1567 100644 --- a/lib/cpp/test/concurrency/Tests.cpp +++ b/lib/cpp/test/concurrency/Tests.cpp @@ -27,7 +27,7 @@ // The test weight, where 10 is 10 times more threads than baseline // and the baseline is optimized for running in valgrind -static size_t WEIGHT = 10; +static int WEIGHT = 10; int main(int argc, char** argv) { diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h index 3779b0d18f0..1c52c470b54 100644 --- a/lib/cpp/test/concurrency/TimerManagerTests.h +++ b/lib/cpp/test/concurrency/TimerManagerTests.h @@ -79,14 +79,13 @@ class TimerManagerTests { = shared_ptr(new TimerManagerTests::Task(_monitor, 10 * timeout)); { - TimerManager timerManager; - timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); - timerManager.start(); - - assert(timerManager.state() == TimerManager::STARTED); + if (timerManager.state() != TimerManager::STARTED) { + std::cerr << "timerManager is not in the STARTED state, but should be" << std::endl; + return false; + } // Don't create task yet, because its constructor sets the expected completion time, and we // need to delay between inserting the two tasks into the run queue. @@ -94,34 +93,27 @@ class TimerManagerTests { { Synchronized s(_monitor); - timerManager.add(orphanTask, 10 * timeout); - try { - // Wait for 1 second in order to give timerManager a chance to start sleeping in response - // to adding orphanTask. We need to do this so we can verify that adding the second task - // kicks the dispatcher out of the current wait and starts the new 1 second wait. - _monitor.wait(1000); - assert( - 0 == "ERROR: This wait should time out. TimerManager dispatcher may have a problem."); - } catch (TimedOutException&) { - } + THRIFT_SLEEP_USEC(timeout * 1000); task.reset(new TimerManagerTests::Task(_monitor, timeout)); - timerManager.add(task, timeout); - _monitor.wait(); } - assert(task->_done); + if (!task->_done) { + std::cerr << "task is not done, but it should have executed" << std::endl; + return false; + } std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl; } - // timerManager.stop(); This is where it happens via destructor - - assert(!orphanTask->_done); + if (orphanTask->_done) { + std::cerr << "orphan task is done, but it should not have executed" << std::endl; + return false; + } return true; } diff --git a/lib/d/src/thrift/server/simple.d b/lib/d/src/thrift/server/simple.d index f7183a75199..5aba4c16900 100644 --- a/lib/d/src/thrift/server/simple.d +++ b/lib/d/src/thrift/server/simple.d @@ -140,7 +140,9 @@ class TSimpleServer : TServer { } } } catch (TTransportException ttx) { - logError("Client died: %s", ttx); + if (ttx.type() != TTransportException.Type.END_OF_FILE) { + logError("Client died unexpectedly: %s", ttx); + } } catch (Exception e) { logError("Uncaught exception: %s", e); } diff --git a/lib/d/src/thrift/server/taskpool.d b/lib/d/src/thrift/server/taskpool.d index b4720a48ead..670e720fcfd 100644 --- a/lib/d/src/thrift/server/taskpool.d +++ b/lib/d/src/thrift/server/taskpool.d @@ -268,7 +268,9 @@ protected: } } } catch (TTransportException ttx) { - logError("Client died: %s", ttx); + if (ttx.type() != TTransportException.Type.END_OF_FILE) { + logError("Client died unexpectedly: %s", ttx); + } } catch (Exception e) { logError("Uncaught exception: %s", e); } diff --git a/lib/d/src/thrift/server/threaded.d b/lib/d/src/thrift/server/threaded.d index 1cde983a44a..300cc845702 100644 --- a/lib/d/src/thrift/server/threaded.d +++ b/lib/d/src/thrift/server/threaded.d @@ -173,7 +173,9 @@ private class WorkerThread : Thread { } } } catch (TTransportException ttx) { - logError("Client died: %s", ttx); + if (ttx.type() != TTransportException.Type.END_OF_FILE) { + logError("Client died unexpectedly: %s", ttx); + } } catch (Exception e) { logError("Uncaught exception: %s", e); } diff --git a/lib/d/test/thrift_test_server.d b/lib/d/test/thrift_test_server.d index 71ab9175d4b..b582253c77a 100644 --- a/lib/d/test/thrift_test_server.d +++ b/lib/d/test/thrift_test_server.d @@ -16,8 +16,11 @@ * specific language governing permissions and limitations * under the License. */ + module thrift_test_server; +import core.stdc.errno : errno; +import core.stdc.signal : signal, sigfn_t, SIGINT, SIG_DFL, SIG_ERR; import core.thread : dur, Thread; import std.algorithm; import std.exception : enforce; @@ -40,6 +43,7 @@ import thrift.transport.buffered; import thrift.transport.framed; import thrift.transport.http; import thrift.transport.ssl; +import thrift.util.cancellation; import thrift.util.hashset; import test_utils; @@ -205,14 +209,44 @@ private: bool trace_; } +shared(bool) gShutdown = false; + +nothrow @nogc extern(C) void handleSignal(int sig) { + gShutdown = true; +} + +// Runs a thread that waits for shutdown to be +// signaled and then triggers cancellation, +// causing the server to stop. While we could +// use a signalfd for this purpose, we are instead +// opting for a busy waiting scheme for maximum +// portability since signalfd is a linux thing. + +class ShutdownThread : Thread { + this(TCancellationOrigin cancellation) { + cancellation_ = cancellation; + super(&run); + } + +private: + void run() { + while (!gShutdown) { + Thread.sleep(dur!("msecs")(25)); + } + cancellation_.trigger(); + } + + TCancellationOrigin cancellation_; +} + void main(string[] args) { ushort port = 9090; ServerType serverType; ProtocolType protocolType; size_t numIOThreads = 1; TransportType transportType; - bool ssl; - bool trace; + bool ssl = false; + bool trace = true; size_t taskPoolSize = totalCPUs; getopt(args, "port", &port, "protocol", &protocolType, "server-type", @@ -279,8 +313,26 @@ void main(string[] args) { auto server = createServer(serverType, numIOThreads, taskPoolSize, processor, serverSocket, transportFactory, protocolFactory); + // Set up SIGINT signal handling + sigfn_t oldHandler = signal(SIGINT, &handleSignal); + enforce(oldHandler != SIG_ERR, + "Could not replace the SIGINT signal handler: errno {0}".format(errno())); + + // Set up a server cancellation trigger + auto cancel = new TCancellationOrigin(); + + // Set up a listener for the shutdown condition - this will + // wake up when the signal occurs and trigger cancellation. + auto shutdown = new ShutdownThread(cancel); + shutdown.start(); + + // Serve from this thread; the signal will stop the server + // and control will return here writefln("Starting %s/%s %s ThriftTest server %son port %s...", protocolType, transportType, serverType, ssl ? "(using SSL) ": "", port); - server.serve(); + server.serve(cancel); + shutdown.join(); + signal(SIGINT, SIG_DFL); + writeln("done."); } diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index d02f0a32dbc..ea25c4ba16f 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -1072,7 +1072,7 @@ function TStreamTransportImpl.GetIsOpen: Boolean; function TStreamTransportImpl.GetOutputStream: IThriftStream; begin - Result := FInputStream; + Result := FOutputStream; end; procedure TStreamTransportImpl.Open; diff --git a/lib/erl/Makefile.am b/lib/erl/Makefile.am index 8867f884e65..06323b4a7d2 100644 --- a/lib/erl/Makefile.am +++ b/lib/erl/Makefile.am @@ -23,6 +23,7 @@ THRIFT_FILES = $(wildcard test/*.thrift) \ $(THRIFT_OMIT_FILE) \ ../../test/ConstantsDemo.thrift \ ../../test/NameConflictTest.thrift \ + ../../test/DoubleConstantsTest.thrift \ ../../test/ThriftTest.thrift if ERLANG_OTP16 diff --git a/lib/erl/test/test_rendered_double_constants.erl b/lib/erl/test/test_rendered_double_constants.erl new file mode 100644 index 00000000000..87fce8130d9 --- /dev/null +++ b/lib/erl/test/test_rendered_double_constants.erl @@ -0,0 +1,68 @@ +%% +%% 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. +%% + +-module(test_rendered_double_constants). + +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). + +-include("gen-erl/double_constants_test_constants.hrl"). + +-define(EPSILON, 0.0000001). + +rendered_double_constants_test() -> + ?assert(abs(1.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST) =< ?EPSILON), + ?assert(abs(-100.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST) =< ?EPSILON), + ?assert(abs(9223372036854775807.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST) =< ?EPSILON), + ?assert(abs(-9223372036854775807.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST) =< ?EPSILON), + ?assert(abs(3.14159265359 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST) =< ?EPSILON), + ?assert(abs(1000000.1 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON), + ?assert(abs(-1000000.1 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON), + ?assert(abs(1.7e+308 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST) =< ?EPSILON), + ?assert(abs(9223372036854775816.43 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON), + ?assert(abs(-1.7e+308 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST) =< ?EPSILON), + ?assert(abs(-9223372036854775816.43 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST)), + ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST)). + +rendered_double_list_test() -> + ?assertEqual(12, length(?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)), + ?assert(abs(1.0 - lists:nth(1, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(-100.0 - lists:nth(2, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(100.0 - lists:nth(3, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(9223372036854775807.0 - lists:nth(4, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(-9223372036854775807.0 - lists:nth(5, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(3.14159265359 - lists:nth(6, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(1000000.1 - lists:nth(7, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(-1000000.1 - lists:nth(8, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(1.7e+308 - lists:nth(9, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(-1.7e+308 - lists:nth(10, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(9223372036854775816.43 - lists:nth(11, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), + ?assert(abs(-9223372036854775816.43 - lists:nth(12, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON). + +-endif. %% TEST \ No newline at end of file diff --git a/lib/go/Makefile.am b/lib/go/Makefile.am index 0d597101447..0dfa5fadca7 100644 --- a/lib/go/Makefile.am +++ b/lib/go/Makefile.am @@ -31,14 +31,12 @@ install: @echo '##############################################################' check-local: - GOPATH=`pwd` $(GO) get golang.org/x/net/context GOPATH=`pwd` $(GO) test -race ./thrift clean-local: $(RM) -rf pkg all-local: - GOPATH=`pwd` $(GO) get golang.org/x/net/context GOPATH=`pwd` $(GO) build ./thrift EXTRA_DIST = \ diff --git a/lib/go/README.md b/lib/go/README.md index 7440474c325..debc9ac680e 100644 --- a/lib/go/README.md +++ b/lib/go/README.md @@ -24,6 +24,8 @@ under the License. Using Thrift with Go ==================== +Thrift supports Go 1.7+ + In following Go conventions, we recommend you use the 'go' tool to install Thrift for go. diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am index 842f2de6180..e93ec5caf5a 100644 --- a/lib/go/test/Makefile.am +++ b/lib/go/test/Makefile.am @@ -17,10 +17,6 @@ # under the License. # -if GOVERSION_LT_17 -COMPILER_EXTRAFLAG=",legacy_context" -endif - THRIFTARGS = -out gopath/src/ --gen go:thrift_import=thrift$(COMPILER_EXTRAFLAG) THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift @@ -59,7 +55,6 @@ gopath: $(THRIFT) $(THRIFTTEST) \ $(THRIFT) $(THRIFTARGS) InitialismsTest.thrift $(THRIFT) $(THRIFTARGS),read_write_private DontExportRWTest.thrift $(THRIFT) $(THRIFTARGS),ignore_initialisms IgnoreInitialismsTest.thrift - GOPATH=`pwd`/gopath $(GO) get golang.org/x/net/context GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock || true sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' gopath/src/github.com/golang/mock/gomock/controller.go || true GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock diff --git a/lib/go/test/dontexportrwtest/compile_test.go b/lib/go/test/dontexportrwtest/compile_test.go index 2b877e3b0dd..cf6763e297e 100644 --- a/lib/go/test/dontexportrwtest/compile_test.go +++ b/lib/go/test/dontexportrwtest/compile_test.go @@ -20,7 +20,6 @@ package dontexportrwtest import ( - "fmt" "testing" ) @@ -29,10 +28,10 @@ import ( func TestReadWriteMethodsArePrivate(t *testing.T) { // This will only compile if read/write methods exist s := NewTestStruct() - fmt.Sprintf("%v", s.read) - fmt.Sprintf("%v", s.write) + _ = s.read + _ = s.write is := NewInnerStruct() - fmt.Sprintf("%v", is.read) - fmt.Sprintf("%v", is.write) + _ = is.read + _ = is.write } diff --git a/lib/go/test/tests/client_error_test.go b/lib/go/test/tests/client_error_test.go index 5dec472eba7..fdec4ea57f2 100644 --- a/lib/go/test/tests/client_error_test.go +++ b/lib/go/test/tests/client_error_test.go @@ -20,6 +20,7 @@ package tests import ( + "context" "errors" "errortest" "testing" @@ -212,7 +213,7 @@ func prepareClientCallReply(protocol *MockTProtocol, failAt int, failWith error) if failAt == 25 { err = failWith } - last = protocol.EXPECT().Flush().Return(err).After(last) + last = protocol.EXPECT().Flush(context.Background()).Return(err).After(last) if failAt == 25 { return true } @@ -536,7 +537,7 @@ func prepareClientCallException(protocol *MockTProtocol, failAt int, failWith er last = protocol.EXPECT().WriteFieldStop().After(last) last = protocol.EXPECT().WriteStructEnd().After(last) last = protocol.EXPECT().WriteMessageEnd().After(last) - last = protocol.EXPECT().Flush().After(last) + last = protocol.EXPECT().Flush(context.Background()).After(last) // Reading the exception, might fail. if failAt == 0 { @@ -704,7 +705,7 @@ func TestClientSeqIdMismatch(t *testing.T) { protocol.EXPECT().WriteFieldStop(), protocol.EXPECT().WriteStructEnd(), protocol.EXPECT().WriteMessageEnd(), - protocol.EXPECT().Flush(), + protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.REPLY, int32(2), nil), ) @@ -735,7 +736,7 @@ func TestClientSeqIdMismatchLegeacy(t *testing.T) { protocol.EXPECT().WriteFieldStop(), protocol.EXPECT().WriteStructEnd(), protocol.EXPECT().WriteMessageEnd(), - protocol.EXPECT().Flush(), + protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.REPLY, int32(2), nil), ) @@ -764,7 +765,7 @@ func TestClientWrongMethodName(t *testing.T) { protocol.EXPECT().WriteFieldStop(), protocol.EXPECT().WriteStructEnd(), protocol.EXPECT().WriteMessageEnd(), - protocol.EXPECT().Flush(), + protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin().Return("unknown", thrift.REPLY, int32(1), nil), ) @@ -795,7 +796,7 @@ func TestClientWrongMethodNameLegacy(t *testing.T) { protocol.EXPECT().WriteFieldStop(), protocol.EXPECT().WriteStructEnd(), protocol.EXPECT().WriteMessageEnd(), - protocol.EXPECT().Flush(), + protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin().Return("unknown", thrift.REPLY, int32(1), nil), ) @@ -824,7 +825,7 @@ func TestClientWrongMessageType(t *testing.T) { protocol.EXPECT().WriteFieldStop(), protocol.EXPECT().WriteStructEnd(), protocol.EXPECT().WriteMessageEnd(), - protocol.EXPECT().Flush(), + protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.INVALID_TMESSAGE_TYPE, int32(1), nil), ) @@ -855,7 +856,7 @@ func TestClientWrongMessageTypeLegacy(t *testing.T) { protocol.EXPECT().WriteFieldStop(), protocol.EXPECT().WriteStructEnd(), protocol.EXPECT().WriteMessageEnd(), - protocol.EXPECT().Flush(), + protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.INVALID_TMESSAGE_TYPE, int32(1), nil), ) diff --git a/tutorial/go/src/go17.go b/lib/go/test/tests/context.go similarity index 94% rename from tutorial/go/src/go17.go rename to lib/go/test/tests/context.go index a6003a9174f..a93a82b8fc9 100644 --- a/tutorial/go/src/go17.go +++ b/lib/go/test/tests/context.go @@ -1,5 +1,3 @@ -// +build go1.7 - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -19,8 +17,10 @@ * under the License. */ -package main +package tests -import "context" +import ( + "context" +) var defaultCtx = context.Background() diff --git a/lib/go/test/tests/go17.go b/lib/go/test/tests/go17.go deleted file mode 100644 index dc3c9d598e1..00000000000 --- a/lib/go/test/tests/go17.go +++ /dev/null @@ -1,47 +0,0 @@ -// +build go1.7 - -/* - * 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 tests - -import ( - "context" - "fmt" -) - -var defaultCtx = context.Background() - -type FirstImpl struct{} - -func (f *FirstImpl) ReturnOne(ctx context.Context) (r int64, err error) { - return 1, nil -} - -type SecondImpl struct{} - -func (s *SecondImpl) ReturnTwo(ctx context.Context) (r int64, err error) { - return 2, nil -} - -type impl struct{} - -func (i *impl) Hi(ctx context.Context, in int64, s string) (err error) { fmt.Println("Hi!"); return } -func (i *impl) Emptyfunc(ctx context.Context) (err error) { return } -func (i *impl) EchoInt(ctx context.Context, param int64) (r int64, err error) { return param, nil } diff --git a/lib/go/test/tests/multiplexed_protocol_test.go b/lib/go/test/tests/multiplexed_protocol_test.go index 0b5896b6065..61ac62828d4 100644 --- a/lib/go/test/tests/multiplexed_protocol_test.go +++ b/lib/go/test/tests/multiplexed_protocol_test.go @@ -20,6 +20,7 @@ package tests import ( + "context" "multiplexedprotocoltest" "net" "testing" @@ -36,6 +37,18 @@ func FindAvailableTCPServerPort() net.Addr { } } +type FirstImpl struct{} + +func (f *FirstImpl) ReturnOne(ctx context.Context) (r int64, err error) { + return 1, nil +} + +type SecondImpl struct{} + +func (s *SecondImpl) ReturnTwo(ctx context.Context) (r int64, err error) { + return 2, nil +} + func createTransport(addr net.Addr) (thrift.TTransport, error) { socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT) transport := thrift.NewTFramedTransport(socket) diff --git a/lib/go/test/tests/one_way_test.go b/lib/go/test/tests/one_way_test.go index 8abd671e617..48d0bbe3890 100644 --- a/lib/go/test/tests/one_way_test.go +++ b/lib/go/test/tests/one_way_test.go @@ -20,6 +20,8 @@ package tests import ( + "context" + "fmt" "net" "onewaytest" "testing" @@ -36,6 +38,12 @@ func findPort() net.Addr { } } +type impl struct{} + +func (i *impl) Hi(ctx context.Context, in int64, s string) (err error) { fmt.Println("Hi!"); return } +func (i *impl) Emptyfunc(ctx context.Context) (err error) { return } +func (i *impl) EchoInt(ctx context.Context, param int64) (r int64, err error) { return param, nil } + const TIMEOUT = time.Second var addr net.Addr diff --git a/lib/go/test/tests/pre_go17.go b/lib/go/test/tests/pre_go17.go deleted file mode 100644 index 8ab433121f2..00000000000 --- a/lib/go/test/tests/pre_go17.go +++ /dev/null @@ -1,48 +0,0 @@ -// +build !go1.7 - -/* - * 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 tests - -import ( - "fmt" - - "golang.org/x/net/context" -) - -var defaultCtx = context.Background() - -type FirstImpl struct{} - -func (f *FirstImpl) ReturnOne(ctx context.Context) (r int64, err error) { - return 1, nil -} - -type SecondImpl struct{} - -func (s *SecondImpl) ReturnTwo(ctx context.Context) (r int64, err error) { - return 2, nil -} - -type impl struct{} - -func (i *impl) Hi(ctx context.Context, in int64, s string) (err error) { fmt.Println("Hi!"); return } -func (i *impl) Emptyfunc(ctx context.Context) (err error) { return } -func (i *impl) EchoInt(ctx context.Context, param int64) (r int64, err error) { return param, nil } diff --git a/lib/go/test/tests/protocol_mock.go b/lib/go/test/tests/protocol_mock.go index 8476c8661a6..51d7a02ff7b 100644 --- a/lib/go/test/tests/protocol_mock.go +++ b/lib/go/test/tests/protocol_mock.go @@ -23,6 +23,7 @@ package tests import ( + "context" thrift "thrift" gomock "github.com/golang/mock/gomock" @@ -49,13 +50,13 @@ func (_m *MockTProtocol) EXPECT() *_MockTProtocolRecorder { return _m.recorder } -func (_m *MockTProtocol) Flush() error { +func (_m *MockTProtocol) Flush(ctx context.Context) error { ret := _m.ctrl.Call(_m, "Flush") ret0, _ := ret[0].(error) return ret0 } -func (_mr *_MockTProtocolRecorder) Flush() *gomock.Call { +func (_mr *_MockTProtocolRecorder) Flush(ctx context.Context) *gomock.Call { return _mr.mock.ctrl.RecordCall(_mr.mock, "Flush") } diff --git a/lib/go/test/tests/thrifttest_handler.go b/lib/go/test/tests/thrifttest_handler.go index 6542fac584d..31b9ee23eca 100644 --- a/lib/go/test/tests/thrifttest_handler.go +++ b/lib/go/test/tests/thrifttest_handler.go @@ -1,5 +1,3 @@ -// +build !go1.7 - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -22,12 +20,11 @@ package tests import ( + "context" "errors" "thrift" "thrifttest" "time" - - "golang.org/x/net/context" ) type SecondServiceHandler struct { diff --git a/lib/go/test/tests/thrifttest_handler_go17.go b/lib/go/test/tests/thrifttest_handler_go17.go deleted file mode 100644 index e022a3df1fb..00000000000 --- a/lib/go/test/tests/thrifttest_handler_go17.go +++ /dev/null @@ -1,212 +0,0 @@ -// +build go1.7 - -/* - * 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 tests - -import ( - "context" - "errors" - "thrift" - "thrifttest" - "time" -) - -type SecondServiceHandler struct { -} - -func NewSecondServiceHandler() *SecondServiceHandler { - return &SecondServiceHandler{} -} - -func (p *SecondServiceHandler) BlahBlah(ctx context.Context) (err error) { - return nil -} - -func (p *SecondServiceHandler) SecondtestString(ctx context.Context, thing string) (r string, err error) { - return thing, nil -} - -type ThriftTestHandler struct { -} - -func NewThriftTestHandler() *ThriftTestHandler { - return &ThriftTestHandler{} -} - -func (p *ThriftTestHandler) TestVoid(ctx context.Context) (err error) { - return nil -} - -func (p *ThriftTestHandler) TestString(ctx context.Context, thing string) (r string, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestBool(ctx context.Context, thing bool) (r bool, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestByte(ctx context.Context, thing int8) (r int8, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestI32(ctx context.Context, thing int32) (r int32, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestI64(ctx context.Context, thing int64) (r int64, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestDouble(ctx context.Context, thing float64) (r float64, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestBinary(ctx context.Context, thing []byte) (r []byte, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestStruct(ctx context.Context, thing *thrifttest.Xtruct) (r *thrifttest.Xtruct, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestNest(ctx context.Context, thing *thrifttest.Xtruct2) (r *thrifttest.Xtruct2, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestMap(ctx context.Context, thing map[int32]int32) (r map[int32]int32, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestStringMap(ctx context.Context, thing map[string]string) (r map[string]string, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestSet(ctx context.Context, thing []int32) (r []int32, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestList(ctx context.Context, thing []int32) (r []int32, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestEnum(ctx context.Context, thing thrifttest.Numberz) (r thrifttest.Numberz, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestTypedef(ctx context.Context, thing thrifttest.UserId) (r thrifttest.UserId, err error) { - return thing, nil -} - -func (p *ThriftTestHandler) TestMapMap(ctx context.Context, hello int32) (r map[int32]map[int32]int32, err error) { - r = make(map[int32]map[int32]int32) - pos := make(map[int32]int32) - neg := make(map[int32]int32) - - for i := int32(1); i < 5; i++ { - pos[i] = i - neg[-i] = -i - } - r[4] = pos - r[-4] = neg - - return r, nil -} - -func (p *ThriftTestHandler) TestInsanity(ctx context.Context, argument *thrifttest.Insanity) (r map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity, err error) { - hello := thrifttest.NewXtruct() - hello.StringThing = "Hello2" - hello.ByteThing = 2 - hello.I32Thing = 2 - hello.I64Thing = 2 - - goodbye := thrifttest.NewXtruct() - goodbye.StringThing = "Goodbye4" - goodbye.ByteThing = 4 - goodbye.I32Thing = 4 - goodbye.I64Thing = 4 - - crazy := thrifttest.NewInsanity() - crazy.UserMap = make(map[thrifttest.Numberz]thrifttest.UserId) - crazy.UserMap[thrifttest.Numberz_EIGHT] = 8 - crazy.UserMap[thrifttest.Numberz_FIVE] = 5 - crazy.Xtructs = []*thrifttest.Xtruct{goodbye, hello} - - first_map := make(map[thrifttest.Numberz]*thrifttest.Insanity) - second_map := make(map[thrifttest.Numberz]*thrifttest.Insanity) - - first_map[thrifttest.Numberz_TWO] = crazy - first_map[thrifttest.Numberz_THREE] = crazy - - looney := thrifttest.NewInsanity() - second_map[thrifttest.Numberz_SIX] = looney - - var insane = make(map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity) - insane[1] = first_map - insane[2] = second_map - - return insane, nil -} - -func (p *ThriftTestHandler) TestMulti(ctx context.Context, arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 thrifttest.Numberz, arg5 thrifttest.UserId) (r *thrifttest.Xtruct, err error) { - r = thrifttest.NewXtruct() - r.StringThing = "Hello2" - r.ByteThing = arg0 - r.I32Thing = arg1 - r.I64Thing = arg2 - return r, nil -} - -func (p *ThriftTestHandler) TestException(ctx context.Context, arg string) (err error) { - if arg == "Xception" { - x := thrifttest.NewXception() - x.ErrorCode = 1001 - x.Message = arg - return x - } else if arg == "TException" { - return thrift.TException(errors.New(arg)) - } else { - return nil - } -} - -func (p *ThriftTestHandler) TestMultiException(ctx context.Context, arg0 string, arg1 string) (r *thrifttest.Xtruct, err error) { - if arg0 == "Xception" { - x := thrifttest.NewXception() - x.ErrorCode = 1001 - x.Message = "This is an Xception" - return nil, x - } else if arg0 == "Xception2" { - x2 := thrifttest.NewXception2() - x2.ErrorCode = 2002 - x2.StructThing = thrifttest.NewXtruct() - x2.StructThing.StringThing = "This is an Xception2" - return nil, x2 - } - - res := thrifttest.NewXtruct() - res.StringThing = arg1 - return res, nil -} - -func (p *ThriftTestHandler) TestOneway(ctx context.Context, secondsToSleep int32) (err error) { - time.Sleep(time.Second * time.Duration(secondsToSleep)) - return nil -} diff --git a/lib/go/thrift/application_exception_test.go b/lib/go/thrift/application_exception_test.go index b2687a6c847..77433575d5d 100644 --- a/lib/go/thrift/application_exception_test.go +++ b/lib/go/thrift/application_exception_test.go @@ -29,13 +29,13 @@ func TestTApplicationException(t *testing.T) { t.Fatalf("Expected empty string for exception but found '%s'", exc.Error()) } if exc.TypeId() != UNKNOWN_APPLICATION_EXCEPTION { - t.Fatalf("Expected type UNKNOWN for exception but found '%s'", exc.TypeId()) + t.Fatalf("Expected type UNKNOWN for exception but found '%v'", exc.TypeId()) } exc = NewTApplicationException(WRONG_METHOD_NAME, "junk_method") if exc.Error() != "junk_method" { t.Fatalf("Expected 'junk_method' for exception but found '%s'", exc.Error()) } if exc.TypeId() != WRONG_METHOD_NAME { - t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%s'", exc.TypeId()) + t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%v'", exc.TypeId()) } } diff --git a/lib/go/thrift/binary_protocol.go b/lib/go/thrift/binary_protocol.go index 690d341111b..de0f6a7a5cb 100644 --- a/lib/go/thrift/binary_protocol.go +++ b/lib/go/thrift/binary_protocol.go @@ -21,6 +21,7 @@ package thrift import ( "bytes" + "context" "encoding/binary" "errors" "fmt" @@ -457,8 +458,8 @@ func (p *TBinaryProtocol) ReadBinary() ([]byte, error) { return buf, NewTProtocolException(err) } -func (p *TBinaryProtocol) Flush() (err error) { - return NewTProtocolException(p.trans.Flush()) +func (p *TBinaryProtocol) Flush(ctx context.Context) (err error) { + return NewTProtocolException(p.trans.Flush(ctx)) } func (p *TBinaryProtocol) Skip(fieldType TType) (err error) { diff --git a/lib/go/thrift/buffered_transport.go b/lib/go/thrift/buffered_transport.go index b754f925d08..96702061b2f 100644 --- a/lib/go/thrift/buffered_transport.go +++ b/lib/go/thrift/buffered_transport.go @@ -21,6 +21,7 @@ package thrift import ( "bufio" + "context" ) type TBufferedTransportFactory struct { @@ -78,12 +79,12 @@ func (p *TBufferedTransport) Write(b []byte) (int, error) { return n, err } -func (p *TBufferedTransport) Flush() error { +func (p *TBufferedTransport) Flush(ctx context.Context) error { if err := p.ReadWriter.Flush(); err != nil { p.ReadWriter.Writer.Reset(p.tp) return err } - return p.tp.Flush() + return p.tp.Flush(ctx) } func (p *TBufferedTransport) RemainingBytes() (num_bytes uint64) { diff --git a/lib/go/thrift/client.go b/lib/go/thrift/client.go index 8bdb53d8d9f..28791ccd0c0 100644 --- a/lib/go/thrift/client.go +++ b/lib/go/thrift/client.go @@ -1,6 +1,13 @@ package thrift -import "fmt" +import ( + "context" + "fmt" +) + +type TClient interface { + Call(ctx context.Context, method string, args, result TStruct) error +} type TStandardClient struct { seqId int32 @@ -16,7 +23,7 @@ func NewTStandardClient(inputProtocol, outputProtocol TProtocol) *TStandardClien } } -func (p *TStandardClient) Send(oprot TProtocol, seqId int32, method string, args TStruct) error { +func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32, method string, args TStruct) error { if err := oprot.WriteMessageBegin(method, CALL, seqId); err != nil { return err } @@ -26,7 +33,7 @@ func (p *TStandardClient) Send(oprot TProtocol, seqId int32, method string, args if err := oprot.WriteMessageEnd(); err != nil { return err } - return oprot.Flush() + return oprot.Flush(ctx) } func (p *TStandardClient) Recv(iprot TProtocol, seqId int32, method string, result TStruct) error { @@ -61,11 +68,11 @@ func (p *TStandardClient) Recv(iprot TProtocol, seqId int32, method string, resu return iprot.ReadMessageEnd() } -func (p *TStandardClient) call(method string, args, result TStruct) error { +func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error { p.seqId++ seqId := p.seqId - if err := p.Send(p.oprot, seqId, method, args); err != nil { + if err := p.Send(ctx, p.oprot, seqId, method, args); err != nil { return err } diff --git a/lib/go/thrift/client_go17.go b/lib/go/thrift/client_go17.go deleted file mode 100644 index 15c1c52ca69..00000000000 --- a/lib/go/thrift/client_go17.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build go1.7 - -package thrift - -import "context" - -type TClient interface { - Call(ctx context.Context, method string, args, result TStruct) error -} - -func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error { - return p.call(method, args, result) -} diff --git a/lib/go/thrift/client_pre_go17.go b/lib/go/thrift/client_pre_go17.go deleted file mode 100644 index d2e99ef2af9..00000000000 --- a/lib/go/thrift/client_pre_go17.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !go1.7 - -package thrift - -import "golang.org/x/net/context" - -type TClient interface { - Call(ctx context.Context, method string, args, result TStruct) error -} - -func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error { - return p.call(method, args, result) -} diff --git a/lib/go/thrift/common_test_go17.go b/lib/go/thrift/common_test.go similarity index 98% rename from lib/go/thrift/common_test_go17.go rename to lib/go/thrift/common_test.go index 2c729a2269e..93597ff8a2a 100644 --- a/lib/go/thrift/common_test_go17.go +++ b/lib/go/thrift/common_test.go @@ -1,5 +1,3 @@ -// +build go1.7 - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git a/lib/go/thrift/common_test_pre_go17.go b/lib/go/thrift/common_test_pre_go17.go deleted file mode 100644 index e6d0c4d9afb..00000000000 --- a/lib/go/thrift/common_test_pre_go17.go +++ /dev/null @@ -1,32 +0,0 @@ -// +build !go1.7 - -/* - * 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 thrift - -import "golang.org/x/net/context" - -type mockProcessor struct { - ProcessFunc func(in, out TProtocol) (bool, TException) -} - -func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { - return m.ProcessFunc(in, out) -} diff --git a/lib/go/thrift/compact_protocol.go b/lib/go/thrift/compact_protocol.go index 0bc5fddeb38..66fbf5c3359 100644 --- a/lib/go/thrift/compact_protocol.go +++ b/lib/go/thrift/compact_protocol.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "encoding/binary" "fmt" "io" @@ -599,8 +600,8 @@ func (p *TCompactProtocol) ReadBinary() (value []byte, err error) { return buf, NewTProtocolException(e) } -func (p *TCompactProtocol) Flush() (err error) { - return NewTProtocolException(p.trans.Flush()) +func (p *TCompactProtocol) Flush(ctx context.Context) (err error) { + return NewTProtocolException(p.trans.Flush(ctx)) } func (p *TCompactProtocol) Skip(fieldType TType) (err error) { @@ -806,7 +807,7 @@ func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) { case COMPACT_STRUCT: return STRUCT, nil } - return STOP, TException(fmt.Errorf("don't know what type: %s", t&0x0f)) + return STOP, TException(fmt.Errorf("don't know what type: %v", t&0x0f)) } // Given a TType value, find the appropriate TCompactProtocol.Types constant. diff --git a/lib/go/thrift/go17.go b/lib/go/thrift/context.go similarity index 98% rename from lib/go/thrift/go17.go rename to lib/go/thrift/context.go index e3b21c4b731..d15c1bcf894 100644 --- a/lib/go/thrift/go17.go +++ b/lib/go/thrift/context.go @@ -1,5 +1,3 @@ -// +build go1.7 - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git a/lib/go/thrift/debug_protocol.go b/lib/go/thrift/debug_protocol.go index d37252cc61d..57943e0f35d 100644 --- a/lib/go/thrift/debug_protocol.go +++ b/lib/go/thrift/debug_protocol.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "log" ) @@ -258,8 +259,8 @@ func (tdp *TDebugProtocol) Skip(fieldType TType) (err error) { log.Printf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err) return } -func (tdp *TDebugProtocol) Flush() (err error) { - err = tdp.Delegate.Flush() +func (tdp *TDebugProtocol) Flush(ctx context.Context) (err error) { + err = tdp.Delegate.Flush(ctx) log.Printf("%sFlush() (err=%#v)", tdp.LogPrefix, err) return } diff --git a/lib/go/thrift/framed_transport.go b/lib/go/thrift/framed_transport.go index 60b1249915a..81fa65aaae5 100644 --- a/lib/go/thrift/framed_transport.go +++ b/lib/go/thrift/framed_transport.go @@ -22,6 +22,7 @@ package thrift import ( "bufio" "bytes" + "context" "encoding/binary" "fmt" "io" @@ -135,7 +136,7 @@ func (p *TFramedTransport) WriteString(s string) (n int, err error) { return p.buf.WriteString(s) } -func (p *TFramedTransport) Flush() error { +func (p *TFramedTransport) Flush(ctx context.Context) error { size := p.buf.Len() buf := p.buffer[:4] binary.BigEndian.PutUint32(buf, uint32(size)) @@ -151,7 +152,7 @@ func (p *TFramedTransport) Flush() error { return NewTTransportExceptionFromError(err) } } - err = p.transport.Flush() + err = p.transport.Flush(ctx) return NewTTransportExceptionFromError(err) } diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go index 33f2aa4b594..5c82bf53875 100644 --- a/lib/go/thrift/http_client.go +++ b/lib/go/thrift/http_client.go @@ -21,6 +21,7 @@ package thrift import ( "bytes" + "context" "io" "io/ioutil" "net/http" @@ -181,7 +182,7 @@ func (p *THttpClient) WriteString(s string) (n int, err error) { return p.requestBuffer.WriteString(s) } -func (p *THttpClient) Flush() error { +func (p *THttpClient) Flush(ctx context.Context) error { // Close any previous response body to avoid leaking connections. p.closeResponse() @@ -190,6 +191,9 @@ func (p *THttpClient) Flush() error { return NewTTransportExceptionFromError(err) } req.Header = p.header + if ctx != nil { + req = req.WithContext(ctx) + } response, err := p.client.Do(req) if err != nil { return NewTTransportExceptionFromError(err) diff --git a/lib/go/thrift/http_transport.go b/lib/go/thrift/http_transport.go index 601855b926c..66f0f388a09 100644 --- a/lib/go/thrift/http_transport.go +++ b/lib/go/thrift/http_transport.go @@ -26,6 +26,18 @@ import ( "strings" ) +// NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function +func NewThriftHandlerFunc(processor TProcessor, + inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) { + + return gz(func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/x-thrift") + + transport := NewStreamTransport(r.Body, w) + processor.Process(r.Context(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport)) + }) +} + // gz transparently compresses the HTTP response if the client supports it. func gz(handler http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { diff --git a/lib/go/thrift/http_transport_go17.go b/lib/go/thrift/http_transport_go17.go deleted file mode 100644 index 1313ac225ba..00000000000 --- a/lib/go/thrift/http_transport_go17.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.7 - -/* - * 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 thrift - -import ( - "net/http" -) - -// NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function -func NewThriftHandlerFunc(processor TProcessor, - inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) { - - return gz(func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("Content-Type", "application/x-thrift") - - transport := NewStreamTransport(r.Body, w) - processor.Process(r.Context(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport)) - }) -} diff --git a/lib/go/thrift/http_transport_pre_go17.go b/lib/go/thrift/http_transport_pre_go17.go deleted file mode 100644 index 13aa1c11d1a..00000000000 --- a/lib/go/thrift/http_transport_pre_go17.go +++ /dev/null @@ -1,40 +0,0 @@ -// +build !go1.7 - -/* - * 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 thrift - -import ( - "net/http" - - "golang.org/x/net/context" -) - -// NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function -func NewThriftHandlerFunc(processor TProcessor, - inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) { - - return gz(func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("Content-Type", "application/x-thrift") - - transport := NewStreamTransport(r.Body, w) - processor.Process(context.Background(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport)) - }) -} diff --git a/lib/go/thrift/iostream_transport.go b/lib/go/thrift/iostream_transport.go index b18be81c46f..fea93bceffa 100644 --- a/lib/go/thrift/iostream_transport.go +++ b/lib/go/thrift/iostream_transport.go @@ -21,6 +21,7 @@ package thrift import ( "bufio" + "context" "io" ) @@ -138,7 +139,7 @@ func (p *StreamTransport) Close() error { } // Flushes the underlying output stream if not null. -func (p *StreamTransport) Flush() error { +func (p *StreamTransport) Flush(ctx context.Context) error { if p.Writer == nil { return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream") } diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go index 442fa9144d4..7be685d43f2 100644 --- a/lib/go/thrift/json_protocol.go +++ b/lib/go/thrift/json_protocol.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "encoding/base64" "fmt" ) @@ -438,10 +439,10 @@ func (p *TJSONProtocol) ReadBinary() ([]byte, error) { return v, p.ParsePostValue() } -func (p *TJSONProtocol) Flush() (err error) { +func (p *TJSONProtocol) Flush(ctx context.Context) (err error) { err = p.writer.Flush() if err == nil { - err = p.trans.Flush() + err = p.trans.Flush(ctx) } return NewTProtocolException(err) } diff --git a/lib/go/thrift/json_protocol_test.go b/lib/go/thrift/json_protocol_test.go index 7104ce3a02e..59c4d64a260 100644 --- a/lib/go/thrift/json_protocol_test.go +++ b/lib/go/thrift/json_protocol_test.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "encoding/base64" "encoding/json" "fmt" @@ -36,7 +37,7 @@ func TestWriteJSONProtocolBool(t *testing.T) { if e := p.WriteBool(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -68,7 +69,7 @@ func TestReadJSONProtocolBool(t *testing.T) { } else { trans.Write([]byte{'0'}) // not JSON_FALSE } - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadBool() if e != nil { @@ -94,7 +95,7 @@ func TestWriteJSONProtocolByte(t *testing.T) { if e := p.WriteByte(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -116,7 +117,7 @@ func TestReadJSONProtocolByte(t *testing.T) { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadByte() if e != nil { @@ -141,7 +142,7 @@ func TestWriteJSONProtocolI16(t *testing.T) { if e := p.WriteI16(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -163,7 +164,7 @@ func TestReadJSONProtocolI16(t *testing.T) { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI16() if e != nil { @@ -188,7 +189,7 @@ func TestWriteJSONProtocolI32(t *testing.T) { if e := p.WriteI32(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -210,7 +211,7 @@ func TestReadJSONProtocolI32(t *testing.T) { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI32() if e != nil { @@ -235,7 +236,7 @@ func TestWriteJSONProtocolI64(t *testing.T) { if e := p.WriteI64(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -257,7 +258,7 @@ func TestReadJSONProtocolI64(t *testing.T) { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(strconv.FormatInt(value, 10)) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI64() if e != nil { @@ -282,7 +283,7 @@ func TestWriteJSONProtocolDouble(t *testing.T) { if e := p.WriteDouble(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -319,7 +320,7 @@ func TestReadJSONProtocolDouble(t *testing.T) { p := NewTJSONProtocol(trans) n := NewNumericFromDouble(value) trans.WriteString(n.String()) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadDouble() if e != nil { @@ -358,7 +359,7 @@ func TestWriteJSONProtocolString(t *testing.T) { if e := p.WriteString(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -380,7 +381,7 @@ func TestReadJSONProtocolString(t *testing.T) { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(jsonQuote(value)) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadString() if e != nil { @@ -409,7 +410,7 @@ func TestWriteJSONProtocolBinary(t *testing.T) { if e := p.WriteBinary(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -441,7 +442,7 @@ func TestReadJSONProtocolBinary(t *testing.T) { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(jsonQuote(b64String)) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadBinary() if e != nil { @@ -474,7 +475,7 @@ func TestWriteJSONProtocolList(t *testing.T) { } } p.WriteListEnd() - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() @@ -528,7 +529,7 @@ func TestWriteJSONProtocolSet(t *testing.T) { } } p.WriteSetEnd() - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() @@ -585,12 +586,12 @@ func TestWriteJSONProtocolMap(t *testing.T) { } } p.WriteMapEnd() - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() if str[0] != '[' || str[len(str)-1] != ']' { - t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES) + t.Fatalf("Bad value for %s, wrote: %v, in go: %v", thetype, str, DOUBLE_VALUES) } expectedKeyType, expectedValueType, expectedSize, err := p.ReadMapBegin() if err != nil { diff --git a/lib/go/thrift/memory_buffer.go b/lib/go/thrift/memory_buffer.go index 97a4edfa5db..5936d273037 100644 --- a/lib/go/thrift/memory_buffer.go +++ b/lib/go/thrift/memory_buffer.go @@ -21,6 +21,7 @@ package thrift import ( "bytes" + "context" ) // Memory buffer-based implementation of the TTransport interface. @@ -70,7 +71,7 @@ func (p *TMemoryBuffer) Close() error { } // Flushing a memory buffer is a no-op -func (p *TMemoryBuffer) Flush() error { +func (p *TMemoryBuffer) Flush(ctx context.Context) error { return nil } diff --git a/lib/go/thrift/multiplexed_protocol.go b/lib/go/thrift/multiplexed_protocol.go index b7f4f8a1ccc..d028a30b333 100644 --- a/lib/go/thrift/multiplexed_protocol.go +++ b/lib/go/thrift/multiplexed_protocol.go @@ -19,6 +19,12 @@ package thrift +import ( + "context" + "fmt" + "strings" +) + /* TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift client to communicate with a multiplexing Thrift server, @@ -122,6 +128,31 @@ func (t *TMultiplexedProcessor) RegisterProcessor(name string, processor TProces t.serviceProcessorMap[name] = processor } +func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { + name, typeId, seqid, err := in.ReadMessageBegin() + if err != nil { + return false, err + } + if typeId != CALL && typeId != ONEWAY { + return false, fmt.Errorf("Unexpected message type %v", typeId) + } + //extract the service name + v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2) + if len(v) != 2 { + if t.DefaultProcessor != nil { + smb := NewStoredMessageProtocol(in, name, typeId, seqid) + return t.DefaultProcessor.Process(ctx, smb, out) + } + return false, fmt.Errorf("Service name not found in message name: %s. Did you forget to use a TMultiplexProtocol in your client?", name) + } + actualProcessor, ok := t.serviceProcessorMap[v[0]] + if !ok { + return false, fmt.Errorf("Service name not found: %s. Did you forget to call registerProcessor()?", v[0]) + } + smb := NewStoredMessageProtocol(in, v[1], typeId, seqid) + return actualProcessor.Process(ctx, smb, out) +} + //Protocol that use stored message for ReadMessageBegin type storedMessageProtocol struct { TProtocol diff --git a/lib/go/thrift/multiplexed_protocol_go17.go b/lib/go/thrift/multiplexed_protocol_go17.go deleted file mode 100644 index c71035e680c..00000000000 --- a/lib/go/thrift/multiplexed_protocol_go17.go +++ /dev/null @@ -1,53 +0,0 @@ -// +build go1.7 - -/* - * 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 thrift - -import ( - "context" - "fmt" - "strings" -) - -func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { - name, typeId, seqid, err := in.ReadMessageBegin() - if err != nil { - return false, err - } - if typeId != CALL && typeId != ONEWAY { - return false, fmt.Errorf("Unexpected message type %v", typeId) - } - //extract the service name - v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2) - if len(v) != 2 { - if t.DefaultProcessor != nil { - smb := NewStoredMessageProtocol(in, name, typeId, seqid) - return t.DefaultProcessor.Process(ctx, smb, out) - } - return false, fmt.Errorf("Service name not found in message name: %s. Did you forget to use a TMultiplexProtocol in your client?", name) - } - actualProcessor, ok := t.serviceProcessorMap[v[0]] - if !ok { - return false, fmt.Errorf("Service name not found: %s. Did you forget to call registerProcessor()?", v[0]) - } - smb := NewStoredMessageProtocol(in, v[1], typeId, seqid) - return actualProcessor.Process(ctx, smb, out) -} diff --git a/lib/go/thrift/multiplexed_protocol_pre_go17.go b/lib/go/thrift/multiplexed_protocol_pre_go17.go deleted file mode 100644 index 5c27b38755c..00000000000 --- a/lib/go/thrift/multiplexed_protocol_pre_go17.go +++ /dev/null @@ -1,54 +0,0 @@ -// +build !go1.7 - -/* - * 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 thrift - -import ( - "fmt" - "strings" - - "golang.org/x/net/context" -) - -func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { - name, typeId, seqid, err := in.ReadMessageBegin() - if err != nil { - return false, err - } - if typeId != CALL && typeId != ONEWAY { - return false, fmt.Errorf("Unexpected message type %v", typeId) - } - //extract the service name - v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2) - if len(v) != 2 { - if t.DefaultProcessor != nil { - smb := NewStoredMessageProtocol(in, name, typeId, seqid) - return t.DefaultProcessor.Process(ctx, smb, out) - } - return false, fmt.Errorf("Service name not found in message name: %s. Did you forget to use a TMultiplexProtocol in your client?", name) - } - actualProcessor, ok := t.serviceProcessorMap[v[0]] - if !ok { - return false, fmt.Errorf("Service name not found: %s. Did you forget to call registerProcessor()?", v[0]) - } - smb := NewStoredMessageProtocol(in, v[1], typeId, seqid) - return actualProcessor.Process(ctx, smb, out) -} diff --git a/lib/go/thrift/pre_go17.go b/lib/go/thrift/pre_go17.go deleted file mode 100644 index cb564b8dbd6..00000000000 --- a/lib/go/thrift/pre_go17.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build !go1.7 - -/* - * 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 thrift - -import "golang.org/x/net/context" - -var defaultCtx = context.Background() diff --git a/lib/go/thrift/processor.go b/lib/go/thrift/processor.go deleted file mode 100644 index 566aaaf7182..00000000000 --- a/lib/go/thrift/processor.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build !go1.7 - -/* - * 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 thrift - -import "golang.org/x/net/context" - -// A processor is a generic object which operates upon an input stream and -// writes to some output stream. -type TProcessor interface { - Process(ctx context.Context, in, out TProtocol) (bool, TException) -} - -type TProcessorFunction interface { - Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) -} diff --git a/lib/go/thrift/processor_factory.go b/lib/go/thrift/processor_factory.go index 9d645df2446..e4b132b307c 100644 --- a/lib/go/thrift/processor_factory.go +++ b/lib/go/thrift/processor_factory.go @@ -19,6 +19,18 @@ package thrift +import "context" + +// A processor is a generic object which operates upon an input stream and +// writes to some output stream. +type TProcessor interface { + Process(ctx context.Context, in, out TProtocol) (bool, TException) +} + +type TProcessorFunction interface { + Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) +} + // The default processor factory just returns a singleton // instance. type TProcessorFactory interface { diff --git a/lib/go/thrift/processor_go17.go b/lib/go/thrift/processor_go17.go deleted file mode 100644 index fb0b165dcc7..00000000000 --- a/lib/go/thrift/processor_go17.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build go1.7 - -/* - * 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 thrift - -import "context" - -// A processor is a generic object which operates upon an input stream and -// writes to some output stream. -type TProcessor interface { - Process(ctx context.Context, in, out TProtocol) (bool, TException) -} - -type TProcessorFunction interface { - Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) -} diff --git a/lib/go/thrift/protocol.go b/lib/go/thrift/protocol.go index 25e6d24b904..615b7a4a8f3 100644 --- a/lib/go/thrift/protocol.go +++ b/lib/go/thrift/protocol.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "errors" "fmt" ) @@ -74,7 +75,7 @@ type TProtocol interface { ReadBinary() (value []byte, err error) Skip(fieldType TType) (err error) - Flush() (err error) + Flush(ctx context.Context) (err error) Transport() TTransport } diff --git a/lib/go/thrift/protocol_test.go b/lib/go/thrift/protocol_test.go index 2573312d1d3..e9118da88f0 100644 --- a/lib/go/thrift/protocol_test.go +++ b/lib/go/thrift/protocol_test.go @@ -21,6 +21,7 @@ package thrift import ( "bytes" + "context" "io/ioutil" "math" "net" @@ -227,17 +228,17 @@ func ReadWriteBool(t testing.TB, p TProtocol, trans TTransport) { for k, v := range BOOL_VALUES { err = p.WriteBool(v) if err != nil { - t.Errorf("%s: %T %T %q Error writing bool in list at index %d: %q", "ReadWriteBool", p, trans, err, k, v) + t.Errorf("%s: %T %T %v Error writing bool in list at index %v: %v", "ReadWriteBool", p, trans, err, k, v) } } p.WriteListEnd() if err != nil { - t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES) + t.Errorf("%s: %T %T %v Error writing list end: %v", "ReadWriteBool", p, trans, err, BOOL_VALUES) } - p.Flush() + p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin() if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES) + t.Errorf("%s: %T %T %v Error reading list: %v", "ReadWriteBool", p, trans, err, BOOL_VALUES) } _, ok := p.(*TSimpleJSONProtocol) if !ok { @@ -245,16 +246,16 @@ func ReadWriteBool(t testing.TB, p TProtocol, trans TTransport) { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteBool", p, trans, thetype, thetype2) } if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteBool", p, trans, thelen, thelen2) + t.Errorf("%s: %T %T len %v != len %v", "ReadWriteBool", p, trans, thelen, thelen2) } } for k, v := range BOOL_VALUES { value, err := p.ReadBool() if err != nil { - t.Errorf("%s: %T %T %q Error reading bool at index %d: %q", "ReadWriteBool", p, trans, err, k, v) + t.Errorf("%s: %T %T %v Error reading bool at index %v: %v", "ReadWriteBool", p, trans, err, k, v) } if v != value { - t.Errorf("%s: index %d %q %q %q != %q", "ReadWriteBool", k, p, trans, v, value) + t.Errorf("%s: index %v %v %v %v != %v", "ReadWriteBool", k, p, trans, v, value) } } err = p.ReadListEnd() @@ -280,7 +281,7 @@ func ReadWriteByte(t testing.TB, p TProtocol, trans TTransport) { if err != nil { t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) } - err = p.Flush() + err = p.Flush(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error flushing list of bytes: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) } @@ -294,7 +295,7 @@ func ReadWriteByte(t testing.TB, p TProtocol, trans TTransport) { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteByte", p, trans, thetype, thetype2) } if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteByte", p, trans, thelen, thelen2) + t.Errorf("%s: %T %T len %v != len %v", "ReadWriteByte", p, trans, thelen, thelen2) } } for k, v := range BYTE_VALUES { @@ -320,7 +321,7 @@ func ReadWriteI16(t testing.TB, p TProtocol, trans TTransport) { p.WriteI16(v) } p.WriteListEnd() - p.Flush() + p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin() if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI16", p, trans, err, INT16_VALUES) @@ -331,7 +332,7 @@ func ReadWriteI16(t testing.TB, p TProtocol, trans TTransport) { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI16", p, trans, thetype, thetype2) } if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI16", p, trans, thelen, thelen2) + t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI16", p, trans, thelen, thelen2) } } for k, v := range INT16_VALUES { @@ -357,7 +358,7 @@ func ReadWriteI32(t testing.TB, p TProtocol, trans TTransport) { p.WriteI32(v) } p.WriteListEnd() - p.Flush() + p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin() if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI32", p, trans, err, INT32_VALUES) @@ -368,7 +369,7 @@ func ReadWriteI32(t testing.TB, p TProtocol, trans TTransport) { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI32", p, trans, thetype, thetype2) } if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI32", p, trans, thelen, thelen2) + t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI32", p, trans, thelen, thelen2) } } for k, v := range INT32_VALUES { @@ -393,7 +394,7 @@ func ReadWriteI64(t testing.TB, p TProtocol, trans TTransport) { p.WriteI64(v) } p.WriteListEnd() - p.Flush() + p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin() if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI64", p, trans, err, INT64_VALUES) @@ -404,7 +405,7 @@ func ReadWriteI64(t testing.TB, p TProtocol, trans TTransport) { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI64", p, trans, thetype, thetype2) } if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI64", p, trans, thelen, thelen2) + t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI64", p, trans, thelen, thelen2) } } for k, v := range INT64_VALUES { @@ -429,28 +430,28 @@ func ReadWriteDouble(t testing.TB, p TProtocol, trans TTransport) { p.WriteDouble(v) } p.WriteListEnd() - p.Flush() + p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin() if err != nil { - t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES) + t.Errorf("%s: %T %T %v Error reading list: %v", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES) } if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteDouble", p, trans, thetype, thetype2) } if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteDouble", p, trans, thelen, thelen2) + t.Errorf("%s: %T %T len %v != len %v", "ReadWriteDouble", p, trans, thelen, thelen2) } for k, v := range DOUBLE_VALUES { value, err := p.ReadDouble() if err != nil { - t.Errorf("%s: %T %T %q Error reading double at index %d: %q", "ReadWriteDouble", p, trans, err, k, v) + t.Errorf("%s: %T %T %q Error reading double at index %d: %v", "ReadWriteDouble", p, trans, err, k, v) } if math.IsNaN(v) { if !math.IsNaN(value) { - t.Errorf("%s: %T %T math.IsNaN(%q) != math.IsNaN(%q)", "ReadWriteDouble", p, trans, v, value) + t.Errorf("%s: %T %T math.IsNaN(%v) != math.IsNaN(%v)", "ReadWriteDouble", p, trans, v, value) } } else if v != value { - t.Errorf("%s: %T %T %v != %q", "ReadWriteDouble", p, trans, v, value) + t.Errorf("%s: %T %T %v != %v", "ReadWriteDouble", p, trans, v, value) } } err = p.ReadListEnd() @@ -467,7 +468,7 @@ func ReadWriteString(t testing.TB, p TProtocol, trans TTransport) { p.WriteString(v) } p.WriteListEnd() - p.Flush() + p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin() if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteString", p, trans, err, STRING_VALUES) @@ -478,7 +479,7 @@ func ReadWriteString(t testing.TB, p TProtocol, trans TTransport) { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteString", p, trans, thetype, thetype2) } if thelen != thelen2 { - t.Errorf("%s: %T %T len %s != len %s", "ReadWriteString", p, trans, thelen, thelen2) + t.Errorf("%s: %T %T len %v != len %v", "ReadWriteString", p, trans, thelen, thelen2) } } for k, v := range STRING_VALUES { @@ -487,7 +488,7 @@ func ReadWriteString(t testing.TB, p TProtocol, trans TTransport) { t.Errorf("%s: %T %T %q Error reading string at index %d: %q", "ReadWriteString", p, trans, err, k, v) } if v != value { - t.Errorf("%s: %T %T %d != %d", "ReadWriteString", p, trans, v, value) + t.Errorf("%s: %T %T %v != %v", "ReadWriteString", p, trans, v, value) } } if err != nil { @@ -498,7 +499,7 @@ func ReadWriteString(t testing.TB, p TProtocol, trans TTransport) { func ReadWriteBinary(t testing.TB, p TProtocol, trans TTransport) { v := protocol_bdata p.WriteBinary(v) - p.Flush() + p.Flush(context.Background()) value, err := p.ReadBinary() if err != nil { t.Errorf("%s: %T %T Unable to read binary: %s", "ReadWriteBinary", p, trans, err.Error()) diff --git a/lib/go/thrift/serializer.go b/lib/go/thrift/serializer.go index 77122299909..1ff4d37545a 100644 --- a/lib/go/thrift/serializer.go +++ b/lib/go/thrift/serializer.go @@ -19,6 +19,10 @@ package thrift +import ( + "context" +) + type TSerializer struct { Transport *TMemoryBuffer Protocol TProtocol @@ -38,35 +42,35 @@ func NewTSerializer() *TSerializer { protocol} } -func (t *TSerializer) WriteString(msg TStruct) (s string, err error) { +func (t *TSerializer) WriteString(ctx context.Context, msg TStruct) (s string, err error) { t.Transport.Reset() if err = msg.Write(t.Protocol); err != nil { return } - if err = t.Protocol.Flush(); err != nil { + if err = t.Protocol.Flush(ctx); err != nil { return } - if err = t.Transport.Flush(); err != nil { + if err = t.Transport.Flush(ctx); err != nil { return } return t.Transport.String(), nil } -func (t *TSerializer) Write(msg TStruct) (b []byte, err error) { +func (t *TSerializer) Write(ctx context.Context, msg TStruct) (b []byte, err error) { t.Transport.Reset() if err = msg.Write(t.Protocol); err != nil { return } - if err = t.Protocol.Flush(); err != nil { + if err = t.Protocol.Flush(ctx); err != nil { return } - if err = t.Transport.Flush(); err != nil { + if err = t.Transport.Flush(ctx); err != nil { return } diff --git a/lib/go/thrift/serializer_test.go b/lib/go/thrift/serializer_test.go index 06d27a16b7b..32227ef4922 100644 --- a/lib/go/thrift/serializer_test.go +++ b/lib/go/thrift/serializer_test.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "errors" "fmt" "testing" @@ -88,7 +89,7 @@ func ProtocolTest1(test *testing.T, pf ProtocolFactory) (bool, error) { m.StringSet = make(map[string]struct{}, 5) m.E = 2 - s, err := t.WriteString(&m) + s, err := t.WriteString(context.Background(), &m) if err != nil { return false, errors.New(fmt.Sprintf("Unable to Serialize struct\n\t %s", err)) } @@ -122,7 +123,7 @@ func ProtocolTest2(test *testing.T, pf ProtocolFactory) (bool, error) { m.StringSet = make(map[string]struct{}, 5) m.E = 2 - s, err := t.WriteString(&m) + s, err := t.WriteString(context.Background(), &m) if err != nil { return false, errors.New(fmt.Sprintf("Unable to Serialize struct\n\t %s", err)) diff --git a/lib/go/thrift/simple_json_protocol.go b/lib/go/thrift/simple_json_protocol.go index 73533223182..2e8a71112a4 100644 --- a/lib/go/thrift/simple_json_protocol.go +++ b/lib/go/thrift/simple_json_protocol.go @@ -22,6 +22,7 @@ package thrift import ( "bufio" "bytes" + "context" "encoding/base64" "encoding/json" "fmt" @@ -552,7 +553,7 @@ func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, error) { return v, p.ParsePostValue() } -func (p *TSimpleJSONProtocol) Flush() (err error) { +func (p *TSimpleJSONProtocol) Flush(ctx context.Context) (err error) { return NewTProtocolException(p.writer.Flush()) } @@ -1064,7 +1065,7 @@ func (p *TSimpleJSONProtocol) ParseListEnd() error { for _, char := range line { switch char { default: - e := fmt.Errorf("Expecting end of list \"]\", but found: \"", line, "\"") + e := fmt.Errorf("Expecting end of list \"]\", but found: \"%v\"", line) return NewTProtocolExceptionWithType(INVALID_DATA, e) case ' ', '\n', '\r', '\t', rune(JSON_RBRACKET[0]): break diff --git a/lib/go/thrift/simple_json_protocol_test.go b/lib/go/thrift/simple_json_protocol_test.go index 8f0dcc9dfe2..7b98082a4ee 100644 --- a/lib/go/thrift/simple_json_protocol_test.go +++ b/lib/go/thrift/simple_json_protocol_test.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "encoding/base64" "encoding/json" "fmt" @@ -37,7 +38,7 @@ func TestWriteSimpleJSONProtocolBool(t *testing.T) { if e := p.WriteBool(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -63,7 +64,7 @@ func TestReadSimpleJSONProtocolBool(t *testing.T) { } else { trans.Write(JSON_FALSE) } - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadBool() if e != nil { @@ -88,7 +89,7 @@ func TestWriteSimpleJSONProtocolByte(t *testing.T) { if e := p.WriteByte(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -110,7 +111,7 @@ func TestReadSimpleJSONProtocolByte(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadByte() if e != nil { @@ -135,7 +136,7 @@ func TestWriteSimpleJSONProtocolI16(t *testing.T) { if e := p.WriteI16(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -157,7 +158,7 @@ func TestReadSimpleJSONProtocolI16(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI16() if e != nil { @@ -182,7 +183,7 @@ func TestWriteSimpleJSONProtocolI32(t *testing.T) { if e := p.WriteI32(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -204,7 +205,7 @@ func TestReadSimpleJSONProtocolI32(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI32() if e != nil { @@ -228,7 +229,7 @@ func TestReadSimpleJSONProtocolI32Null(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(value) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI32() @@ -250,7 +251,7 @@ func TestWriteSimpleJSONProtocolI64(t *testing.T) { if e := p.WriteI64(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -272,7 +273,7 @@ func TestReadSimpleJSONProtocolI64(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(strconv.FormatInt(value, 10)) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI64() if e != nil { @@ -296,7 +297,7 @@ func TestReadSimpleJSONProtocolI64Null(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(value) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI64() @@ -318,7 +319,7 @@ func TestWriteSimpleJSONProtocolDouble(t *testing.T) { if e := p.WriteDouble(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -355,7 +356,7 @@ func TestReadSimpleJSONProtocolDouble(t *testing.T) { p := NewTSimpleJSONProtocol(trans) n := NewNumericFromDouble(value) trans.WriteString(n.String()) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadDouble() if e != nil { @@ -394,7 +395,7 @@ func TestWriteSimpleJSONProtocolString(t *testing.T) { if e := p.WriteString(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -416,7 +417,7 @@ func TestReadSimpleJSONProtocolString(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(jsonQuote(value)) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadString() if e != nil { @@ -440,7 +441,7 @@ func TestReadSimpleJSONProtocolStringNull(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(value) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadString() if e != nil { @@ -464,7 +465,7 @@ func TestWriteSimpleJSONProtocolBinary(t *testing.T) { if e := p.WriteBinary(value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() @@ -487,7 +488,7 @@ func TestReadSimpleJSONProtocolBinary(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(jsonQuote(b64String)) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() v, e := p.ReadBinary() if e != nil { @@ -516,7 +517,7 @@ func TestReadSimpleJSONProtocolBinaryNull(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(value) - trans.Flush() + trans.Flush(context.Background()) s := trans.String() b, e := p.ReadBinary() v := string(b) @@ -542,7 +543,7 @@ func TestWriteSimpleJSONProtocolList(t *testing.T) { } } p.WriteListEnd() - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() @@ -596,7 +597,7 @@ func TestWriteSimpleJSONProtocolSet(t *testing.T) { } } p.WriteSetEnd() - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() @@ -653,12 +654,12 @@ func TestWriteSimpleJSONProtocolMap(t *testing.T) { } } p.WriteMapEnd() - if e := p.Flush(); e != nil { + if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() if str[0] != '[' || str[len(str)-1] != ']' { - t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES) + t.Fatalf("Bad value for %s, wrote: %v, in go: %v", thetype, str, DOUBLE_VALUES) } l := strings.Split(str[1:len(str)-1], ",") if len(l) < 3 { diff --git a/lib/go/thrift/socket.go b/lib/go/thrift/socket.go index 383b1fe3e97..8854279651f 100644 --- a/lib/go/thrift/socket.go +++ b/lib/go/thrift/socket.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "net" "time" ) @@ -148,7 +149,7 @@ func (p *TSocket) Write(buf []byte) (int, error) { return p.conn.Write(buf) } -func (p *TSocket) Flush() error { +func (p *TSocket) Flush(ctx context.Context) error { return nil } diff --git a/lib/go/thrift/ssl_socket.go b/lib/go/thrift/ssl_socket.go index c3bd72cc467..ba63377263a 100644 --- a/lib/go/thrift/ssl_socket.go +++ b/lib/go/thrift/ssl_socket.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "crypto/tls" "net" "time" @@ -158,7 +159,7 @@ func (p *TSSLSocket) Write(buf []byte) (int, error) { return p.conn.Write(buf) } -func (p *TSSLSocket) Flush() error { +func (p *TSSLSocket) Flush(ctx context.Context) error { return nil } diff --git a/lib/go/thrift/transport.go b/lib/go/thrift/transport.go index 70a85a84895..ba2738a8df1 100644 --- a/lib/go/thrift/transport.go +++ b/lib/go/thrift/transport.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "errors" "io" ) @@ -30,6 +31,10 @@ type Flusher interface { Flush() (err error) } +type ContextFlusher interface { + Flush(ctx context.Context) (err error) +} + type ReadSizeProvider interface { RemainingBytes() (num_bytes uint64) } @@ -37,7 +42,7 @@ type ReadSizeProvider interface { // Encapsulates the I/O layer type TTransport interface { io.ReadWriteCloser - Flusher + ContextFlusher ReadSizeProvider // Opens the transport for communication @@ -60,6 +65,6 @@ type TRichTransport interface { io.ByteReader io.ByteWriter stringWriter - Flusher + ContextFlusher ReadSizeProvider } diff --git a/lib/go/thrift/transport_test.go b/lib/go/thrift/transport_test.go index 864958a9da0..01278038efa 100644 --- a/lib/go/thrift/transport_test.go +++ b/lib/go/thrift/transport_test.go @@ -20,6 +20,7 @@ package thrift import ( + "context" "io" "net" "strconv" @@ -54,7 +55,7 @@ func TransportTest(t *testing.T, writeTrans TTransport, readTrans TTransport) { if err != nil { t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err) } - err = writeTrans.Flush() + err = writeTrans.Flush(context.Background()) if err != nil { t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err) } @@ -74,7 +75,7 @@ func TransportTest(t *testing.T, writeTrans TTransport, readTrans TTransport) { if err != nil { t.Fatalf("Transport %T cannot write binary data 2 of length %d: %s", writeTrans, len(transport_bdata), err) } - err = writeTrans.Flush() + err = writeTrans.Flush(context.Background()) if err != nil { t.Fatalf("Transport %T cannot flush write binary data 2: %s", writeTrans, err) } @@ -113,7 +114,7 @@ func TransportHeaderTest(t *testing.T, writeTrans TTransport, readTrans TTranspo if err != nil { t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err) } - err = writeTrans.Flush() + err = writeTrans.Flush(context.Background()) if err != nil { t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err) } diff --git a/lib/go/thrift/zlib_transport.go b/lib/go/thrift/zlib_transport.go index f2f07322217..f3d42673af9 100644 --- a/lib/go/thrift/zlib_transport.go +++ b/lib/go/thrift/zlib_transport.go @@ -21,6 +21,7 @@ package thrift import ( "compress/zlib" + "context" "io" "log" ) @@ -91,11 +92,11 @@ func (z *TZlibTransport) Close() error { } // Flush flushes the writer and its underlying transport. -func (z *TZlibTransport) Flush() error { +func (z *TZlibTransport) Flush(ctx context.Context) error { if err := z.writer.Flush(); err != nil { return err } - return z.transport.Flush() + return z.transport.Flush(ctx) } // IsOpen returns true if the transport is open diff --git a/lib/java/gradle/generateTestThrift.gradle b/lib/java/gradle/generateTestThrift.gradle index 9673e5bbf58..c3479179b13 100644 --- a/lib/java/gradle/generateTestThrift.gradle +++ b/lib/java/gradle/generateTestThrift.gradle @@ -74,6 +74,7 @@ task generateJava(group: 'Build') { 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/src/org/apache/thrift/AsyncProcessFunction.java b/lib/java/src/org/apache/thrift/AsyncProcessFunction.java index 550ebd532b7..483c8d054a5 100644 --- a/lib/java/src/org/apache/thrift/AsyncProcessFunction.java +++ b/lib/java/src/org/apache/thrift/AsyncProcessFunction.java @@ -20,7 +20,6 @@ import org.apache.thrift.async.AsyncMethodCallback; import org.apache.thrift.protocol.TMessage; -import org.apache.thrift.protocol.TMessageType; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.server.AbstractNonblockingServer; diff --git a/lib/java/src/org/apache/thrift/TAsyncProcessor.java b/lib/java/src/org/apache/thrift/TAsyncProcessor.java index 0a069ea005a..533e74d86c7 100644 --- a/lib/java/src/org/apache/thrift/TAsyncProcessor.java +++ b/lib/java/src/org/apache/thrift/TAsyncProcessor.java @@ -18,14 +18,7 @@ */ package org.apache.thrift; -import org.apache.thrift.protocol.*; - -import org.apache.thrift.server.AbstractNonblockingServer.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.Map; +import org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer; public interface TAsyncProcessor { /** diff --git a/lib/java/src/org/apache/thrift/TEnumHelper.java b/lib/java/src/org/apache/thrift/TEnumHelper.java index c17d661c283..fbc778751e2 100644 --- a/lib/java/src/org/apache/thrift/TEnumHelper.java +++ b/lib/java/src/org/apache/thrift/TEnumHelper.java @@ -19,7 +19,6 @@ package org.apache.thrift; -import java.lang.InstantiationException; import java.lang.NoSuchMethodException; import java.lang.IllegalAccessException; import java.lang.reflect.InvocationTargetException; diff --git a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java index 90d5e5b0457..53c20e98fe6 100644 --- a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java +++ b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java @@ -145,22 +145,40 @@ private static ExecutorService createDefaultExecutorService(Args args) { executorQueue); } - - public void serve() { - try { + protected ExecutorService getExecutorService() { + return executorService_; + } + + protected boolean preServe() { + try { serverTransport_.listen(); } catch (TTransportException ttx) { LOGGER.error("Error occurred during listening.", ttx); - return; + return false; } // Run the preServe event if (eventHandler_ != null) { eventHandler_.preServe(); } - stopped_ = false; setServing(true); + + return true; + } + + public void serve() { + if (!preServe()) { + return; + } + + execute(); + waitForShutdown(); + + setServing(false); + } + + protected void execute() { int failureCount = 0; while (!stopped_) { try { @@ -213,8 +231,10 @@ public void serve() { } } } - - executorService_.shutdown(); + } + + protected void waitForShutdown() { + executorService_.shutdown(); // Loop until awaitTermination finally does return without a interrupted // exception. If we don't do this, then we'll shut down prematurely. We want @@ -232,7 +252,6 @@ public void serve() { now = newnow; } } - setServing(false); } public void stop() { diff --git a/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java b/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java index 9c60ed1ab6b..2232a315c12 100644 --- a/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java +++ b/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java @@ -186,7 +186,11 @@ private static SSLContext createSSLContext(TSSLTransportParameters params) throw if (params.isTrustStoreSet) { tmf = TrustManagerFactory.getInstance(params.trustManagerType); KeyStore ts = KeyStore.getInstance(params.trustStoreType); - in = getStoreAsStream(params.trustStore); + if (params.trustStoreStream != null) { + in = params.trustStoreStream; + } else { + in = getStoreAsStream(params.trustStore); + } ts.load(in, (params.trustPass != null ? params.trustPass.toCharArray() : null)); tmf.init(ts); @@ -195,7 +199,11 @@ private static SSLContext createSSLContext(TSSLTransportParameters params) throw if (params.isKeyStoreSet) { kmf = KeyManagerFactory.getInstance(params.keyManagerType); KeyStore ks = KeyStore.getInstance(params.keyStoreType); - is = getStoreAsStream(params.keyStore); + if (params.keyStoreStream != null) { + is = params.keyStoreStream; + } else { + is = getStoreAsStream(params.keyStore); + } ks.load(is, params.keyPass.toCharArray()); kmf.init(ks, params.keyPass.toCharArray()); } @@ -273,10 +281,12 @@ private static TSocket createClient(SSLSocketFactory factory, String host, int p public static class TSSLTransportParameters { protected String protocol = "TLS"; protected String keyStore; + protected InputStream keyStoreStream; protected String keyPass; protected String keyManagerType = KeyManagerFactory.getDefaultAlgorithm(); protected String keyStoreType = "JKS"; protected String trustStore; + protected InputStream trustStoreStream; protected String trustPass; protected String trustManagerType = TrustManagerFactory.getDefaultAlgorithm(); protected String trustStoreType = "JKS"; @@ -332,7 +342,20 @@ public void setKeyStore(String keyStore, String keyPass, String keyManagerType, } isKeyStoreSet = true; } - + + /** + * Set the keystore, password, certificate type and the store type + * + * @param keyStoreStream Keystore content input stream + * @param keyPass Keystore password + * @param keyManagerType The default is X509 + * @param keyStoreType The default is JKS + */ + public void setKeyStore(InputStream keyStoreStream, String keyPass, String keyManagerType, String keyStoreType) { + this.keyStoreStream = keyStoreStream; + setKeyStore("", keyPass, keyManagerType, keyStoreType); + } + /** * Set the keystore and password * @@ -342,7 +365,17 @@ public void setKeyStore(String keyStore, String keyPass, String keyManagerType, public void setKeyStore(String keyStore, String keyPass) { setKeyStore(keyStore, keyPass, null, null); } - + + /** + * Set the keystore and password + * + * @param keyStoreStream Keystore content input stream + * @param keyPass Keystore password + */ + public void setKeyStore(InputStream keyStoreStream, String keyPass) { + setKeyStore(keyStoreStream, keyPass, null, null); + } + /** * Set the truststore, password, certificate type and the store type * @@ -362,6 +395,19 @@ public void setTrustStore(String trustStore, String trustPass, String trustManag } isTrustStoreSet = true; } + + /** + * Set the truststore, password, certificate type and the store type + * + * @param trustStoreStream Truststore content input stream + * @param trustPass Truststore password + * @param trustManagerType The default is X509 + * @param trustStoreType The default is JKS + */ + public void setTrustStore(InputStream trustStoreStream, String trustPass, String trustManagerType, String trustStoreType) { + this.trustStoreStream = trustStoreStream; + setTrustStore("", trustPass, trustManagerType, trustStoreType); + } /** * Set the truststore and password @@ -372,6 +418,16 @@ public void setTrustStore(String trustStore, String trustPass, String trustManag public void setTrustStore(String trustStore, String trustPass) { setTrustStore(trustStore, trustPass, null, null); } + + /** + * Set the truststore and password + * + * @param trustStoreStream Truststore content input stream + * @param trustPass Truststore password + */ + public void setTrustStore(InputStream trustStoreStream, String trustPass) { + setTrustStore(trustStoreStream, trustPass, null, null); + } /** * Set if client authentication is required @@ -380,6 +436,6 @@ public void setTrustStore(String trustStore, String trustPass) { */ public void requireClientAuth(boolean clientAuth) { this.clientAuth = clientAuth; - } - } + } + } } diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java index a94d9a77604..bbd3f9a34a6 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java @@ -287,7 +287,7 @@ public void open() throws TTransportException { if (message.status == NegotiationStatus.COMPLETE && getRole() == SaslRole.CLIENT) { LOGGER.debug("{}: All done!", getRole()); - break; + continue; } sendSaslMessage(sasl.isComplete() ? NegotiationStatus.COMPLETE : NegotiationStatus.OK, @@ -295,8 +295,6 @@ public void open() throws TTransportException { } LOGGER.debug("{}: Main negotiation loop complete", getRole()); - assert sasl.isComplete(); - // If we're the client, and we're complete, but the server isn't // complete yet, we need to wait for its response. This will occur // with ANONYMOUS auth, for example, where we send an initial response diff --git a/lib/java/test/org/apache/thrift/Fixtures.java b/lib/java/test/org/apache/thrift/Fixtures.java index 9f28124b77f..81671d8de56 100644 --- a/lib/java/test/org/apache/thrift/Fixtures.java +++ b/lib/java/test/org/apache/thrift/Fixtures.java @@ -277,7 +277,7 @@ public class Fixtures { nesting = new Nesting(bonk, oneOfEach); holyMoley = new HolyMoley(); - ArrayList big = new ArrayList(); + List big = new ArrayList(); big.add(new OneOfEach(oneOfEach)); big.add(nesting.my_ooe); holyMoley.setBig(big); 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 00000000000..d691fe356e7 --- /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/TestReuse.java b/lib/java/test/org/apache/thrift/TestReuse.java index db16c74aba6..b44abd0d209 100644 --- a/lib/java/test/org/apache/thrift/TestReuse.java +++ b/lib/java/test/org/apache/thrift/TestReuse.java @@ -21,10 +21,7 @@ import java.util.HashSet; -import junit.framework.TestCase; - import org.apache.thrift.protocol.TBinaryProtocol; -import org.apache.thrift.protocol.TType; import thrift.test.Reuse; diff --git a/lib/java/test/org/apache/thrift/protocol/TestTProtocolUtil.java b/lib/java/test/org/apache/thrift/protocol/TestTProtocolUtil.java index 199c7075310..89cf5366e7b 100644 --- a/lib/java/test/org/apache/thrift/protocol/TestTProtocolUtil.java +++ b/lib/java/test/org/apache/thrift/protocol/TestTProtocolUtil.java @@ -18,24 +18,10 @@ */ package org.apache.thrift.protocol; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.List; - import junit.framework.TestCase; -import org.apache.thrift.Fixtures; -import org.apache.thrift.TBase; -import org.apache.thrift.TDeserializer; -import org.apache.thrift.TException; import org.apache.thrift.TSerializer; -import org.apache.thrift.transport.TMemoryBuffer; -import thrift.test.CompactProtoTestStruct; -import thrift.test.HolyMoley; -import thrift.test.Nesting; -import thrift.test.OneOfEach; -import thrift.test.Srv; import thrift.test.GuessProtocolStruct; public class TestTProtocolUtil extends TestCase { diff --git a/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java index 0b9c73286c3..b8c4657489a 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 @@ public void testSanePartsOfCompactProtoTestStruct() throws TException { 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 { diff --git a/lib/java/test/org/apache/thrift/server/ServerTestBase.java b/lib/java/test/org/apache/thrift/server/ServerTestBase.java index e245963d69a..1dee22d1717 100644 --- a/lib/java/test/org/apache/thrift/server/ServerTestBase.java +++ b/lib/java/test/org/apache/thrift/server/ServerTestBase.java @@ -267,7 +267,7 @@ public void testOneway(int sleepFor) { System.out.println("testOneway(" + Integer.toString(sleepFor) + ") => sleeping..."); try { - Thread.sleep(sleepFor * 1000); + Thread.sleep(sleepFor * SLEEP_DELAY); System.out.println("Done sleeping!"); } catch (InterruptedException ie) { throw new RuntimeException(ie); @@ -282,6 +282,7 @@ public void testOneway(int sleepFor) { public static final String HOST = "localhost"; public static final int PORT = Integer.valueOf( System.getProperty("test.port", "9090")); + protected static final int SLEEP_DELAY = 1000; protected static final int SOCKET_TIMEOUT = 1500; private static final Xtruct XSTRUCT = new Xtruct("Zero", (byte) 1, -3, -5); private static final Xtruct2 XSTRUCT2 = new Xtruct2((byte)1, XSTRUCT, 5); @@ -388,7 +389,7 @@ public boolean useAsyncProcessor() { public void testIt() throws Exception { for (TProtocolFactory protoFactory : getProtocols()) { - TProcessor processor = useAsyncProcessor() ? new ThriftTest.AsyncProcessor(new AsyncTestHandler()) : new ThriftTest.Processor(new TestHandler()); + TProcessor processor = useAsyncProcessor() ? new ThriftTest.AsyncProcessor(new AsyncTestHandler()) : new ThriftTest.Processor(new TestHandler()); startServer(processor, protoFactory); @@ -537,7 +538,7 @@ public TTransport getTransport(TTransport trans) { public void testTransportFactory() throws Exception { for (TProtocolFactory protoFactory : getProtocols()) { TestHandler handler = new TestHandler(); - ThriftTest.Processor processor = new ThriftTest.Processor(handler); + ThriftTest.Processor processor = new ThriftTest.Processor(handler); final CallCountingTransportFactory factory = new CallCountingTransportFactory(new TFramedTransport.Factory()); diff --git a/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java index 478407a2f63..032c2eb710d 100644 --- a/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java +++ b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java @@ -45,6 +45,10 @@ public TTransport getClientTransport(TTransport underlyingTransport) throws Exception { return TSSLTransportFactory.getClientSocket(HOST, PORT); } + + protected TServerSocket getServerTransport() throws Exception { + return TSSLTransportFactory.getServerSocket(PORT); + } @Override public void startServer(final TProcessor processor, final TProtocolFactory protoFactory, final TTransportFactory factory) @@ -52,11 +56,11 @@ public void startServer(final TProcessor processor, final TProtocolFactory proto serverThread = new Thread() { public void run() { try { - TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(PORT); + TServerTransport serverTransport = getServerTransport(); final Args args = new Args(serverTransport).processor(processor); server = new TSimpleServer(args); server.serve(); - } catch (TTransportException e) { + } catch (Exception e) { e.printStackTrace(); assert false; } @@ -64,7 +68,7 @@ public void run() { }; serverThread.start(); - Thread.sleep(1000); + Thread.sleep(SLEEP_DELAY); } @Override diff --git a/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactoryStreamedStore.java b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactoryStreamedStore.java new file mode 100644 index 00000000000..25bf5cebb67 --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactoryStreamedStore.java @@ -0,0 +1,62 @@ +/* + * 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.transport; + +import java.io.FileInputStream; +import java.net.InetAddress; + +public class TestTSSLTransportFactoryStreamedStore extends TestTSSLTransportFactory { + private static String keyStoreLocation = System.getProperty("javax.net.ssl.keyStore"); + private static String trustStoreLocation = System.getProperty("javax.net.ssl.trustStore"); + + public TestTSSLTransportFactoryStreamedStore() { + super(); + + /** + * Override system properties to be able to test passing + * the trustStore and keyStore as input stream + */ + System.setProperty("javax.net.ssl.trustStore", ""); + System.setProperty("javax.net.ssl.keyStore", ""); + } + + @Override + public TTransport getClientTransport(TTransport underlyingTransport) + throws Exception { + TSSLTransportFactory.TSSLTransportParameters params = new + TSSLTransportFactory.TSSLTransportParameters(); + + params.setTrustStore(new FileInputStream(trustStoreLocation), + System.getProperty("javax.net.ssl.trustStorePassword")); + + return TSSLTransportFactory.getClientSocket(HOST, PORT, 0/*timeout*/, params); + } + + @Override + protected TServerSocket getServerTransport() throws Exception { + TSSLTransportFactory.TSSLTransportParameters params = new + TSSLTransportFactory.TSSLTransportParameters(); + + params.setKeyStore(new FileInputStream(keyStoreLocation), + System.getProperty("javax.net.ssl.keyStorePassword")); + + return TSSLTransportFactory.getServerSocket(PORT, 0/*timeout*/, InetAddress.getByName(HOST), params); + } +} \ No newline at end of file diff --git a/lib/js/Gruntfile.js b/lib/js/Gruntfile.js index 577a39323fa..1dcead6505d 100644 --- a/lib/js/Gruntfile.js +++ b/lib/js/Gruntfile.js @@ -38,11 +38,14 @@ module.exports = function(grunt) { }, shell: { InstallThriftJS: { - command: 'mkdir test/build; mkdir test/build/js; cp src/thrift.js test/build/js/thrift.js' + command: 'mkdir test/build; mkdir test/build/js; mkdir test/build/js/lib; cp src/thrift.js test/build/js/thrift.js' }, InstallThriftNodeJSDep: { command: 'cd ../..; npm install' }, + InstallTestLibs: { + command: 'cd test; ant download_jslibs' + }, ThriftGen: { command: '../../compiler/cpp/thrift -gen js -gen js:node -o test ../../test/ThriftTest.thrift' }, @@ -52,37 +55,32 @@ module.exports = function(grunt) { 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' }, - }, - external_daemon: { ThriftTestServer: { options: { - startCheck: function(stdout, stderr) { - return (/Thrift Server running on port/).test(stdout); - }, - nodeSpawnOptions: { - cwd: "test", - env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} - } + async: true, + execOptions: { + cwd: "./test", + env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} + } }, - cmd: "node", - args: ["server_http.js"] + command: "node server_http.js", }, ThriftTestServer_TLS: { options: { - startCheck: function(stdout, stderr) { - return (/Thrift Server running on port/).test(stdout); - }, - nodeSpawnOptions: { - cwd: "test", - env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} - } + async: true, + execOptions: { + cwd: "./test", + env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} + } }, - cmd: "node", - args: ["server_https.js"] - } + command: "node server_https.js", + }, }, qunit: { ThriftJS: { @@ -99,6 +97,14 @@ module.exports = function(grunt) { ] } }, + ThriftJS_DoubleRendering: { + options: { + '--ignore-ssl-errors': true, + urls: [ + 'http://localhost:8088/test-double-rendering.html' + ] + } + }, ThriftWS: { options: { urls: [ @@ -164,23 +170,25 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-jsdoc'); - grunt.loadNpmTasks('grunt-external-daemon'); - grunt.loadNpmTasks('grunt-shell'); + grunt.loadNpmTasks('grunt-shell-spawn'); + + grunt.registerTask('wait', 'Wait just one second for server to start', function () { + var done = this.async(); + setTimeout(function() { + done(true); + }, 1000); + }); grunt.registerTask('test', ['jshint', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', - 'external_daemon:ThriftTestServer', 'external_daemon:ThriftTestServer_TLS', + 'shell:InstallTestLibs', + 'shell:ThriftTestServer', 'shell:ThriftTestServer_TLS', + 'wait', 'shell:ThriftGenDeepConstructor', 'qunit:ThriftDeepConstructor', 'qunit:ThriftJS', 'qunit:ThriftJS_TLS', 'qunit:ThriftWS', 'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS', - 'shell:ThriftGenES6', 'qunit:ThriftWSES6' + 'shell:ThriftGenES6', 'qunit:ThriftWSES6', + 'shell:ThriftTestServer:kill', 'shell:ThriftTestServer_TLS:kill', ]); - grunt.registerTask('default', ['jshint', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', - 'external_daemon:ThriftTestServer', 'external_daemon:ThriftTestServer_TLS', - 'qunit:ThriftJS', 'qunit:ThriftJS_TLS', - 'qunit:ThriftWS', - 'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS', - 'shell:ThriftGenES6', 'qunit:ThriftWSES6', - 'concat', 'uglify', 'jsdoc' - ]); + grunt.registerTask('default', ['test', 'concat', 'uglify', 'jsdoc']); }; diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json new file mode 100644 index 00000000000..02347cfa5cb --- /dev/null +++ b/lib/js/package-lock.json @@ -0,0 +1,2285 @@ +{ + "name": "thrift", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } + } + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "babylon": { + "version": "7.0.0-beta.19", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", + "integrity": "sha1-6SjH6AfpcOBTaweKs+DEj54FJQM=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=" + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "catharsis": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", + "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "requires": { + "underscore-contrib": "0.3.0" + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "7.1.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "coffeescript": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", + "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.5", + "typedarray": "0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "which": "1.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + } + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extract-zip": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz", + "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "debug": "2.6.9", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "5.0.15" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" + }, + "dependencies": { + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grunt": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.2.tgz", + "integrity": "sha1-TmpeaVtwRy/VME9fqeNCNoNqc7w=", + "dev": true, + "requires": { + "coffeescript": "1.10.0", + "dateformat": "1.0.12", + "eventemitter2": "0.4.14", + "exit": "0.1.2", + "findup-sync": "0.3.0", + "glob": "7.0.6", + "grunt-cli": "1.2.0", + "grunt-known-options": "1.1.0", + "grunt-legacy-log": "1.0.1", + "grunt-legacy-util": "1.0.0", + "iconv-lite": "0.4.19", + "js-yaml": "3.5.5", + "minimatch": "3.0.4", + "nopt": "3.0.6", + "path-is-absolute": "1.0.1", + "rimraf": "2.2.8" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + } + } + }, + "grunt-cli": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", + "dev": true, + "requires": { + "findup-sync": "0.3.0", + "grunt-known-options": "1.1.0", + "nopt": "3.0.6", + "resolve": "1.1.7" + }, + "dependencies": { + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "5.0.15" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + } + } + }, + "grunt-contrib-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz", + "integrity": "sha1-YVCYYwhOhx1+ht5IwBUlntl3Rb0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "source-map": "0.5.7" + } + }, + "grunt-contrib-jshint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-1.1.0.tgz", + "integrity": "sha1-Np2QmyWTxA6L55lAshNAhQx5Oaw=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "hooker": "0.2.3", + "jshint": "2.9.5" + } + }, + "grunt-contrib-qunit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-1.3.0.tgz", + "integrity": "sha1-naxijP1OyBWZhjPbc7Ur2z3byZ4=", + "dev": true, + "requires": { + "grunt-lib-phantomjs": "1.1.0" + } + }, + "grunt-contrib-uglify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-1.0.2.tgz", + "integrity": "sha1-rmekb5FT7dTLEYE6Vetpxw19svs=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "lodash": "4.17.5", + "maxmin": "1.1.0", + "uglify-js": "2.6.4", + "uri-path": "1.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + } + } + }, + "grunt-jsdoc": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.2.1.tgz", + "integrity": "sha512-33QZYBYjv2Ph3H2ygqXHn/o0ttfptw1f9QciOTgvzhzUeiPrnvzMNUApTPtw22T6zgReE5FZ1RR58U2wnK/l+w==", + "dev": true, + "requires": { + "cross-spawn": "3.0.1", + "jsdoc": "3.5.5", + "marked": "0.3.17" + } + }, + "grunt-known-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz", + "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=", + "dev": true + }, + "grunt-legacy-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.1.tgz", + "integrity": "sha512-rwuyqNKlI0IPz0DvxzJjcEiQEBaBNVeb1LFoZKxSmHLETFUwhwUrqOsPIxURTKSwNZHZ4ht1YLBYmVU0YZAzHQ==", + "dev": true, + "requires": { + "colors": "1.1.2", + "grunt-legacy-log-utils": "1.0.0", + "hooker": "0.2.3", + "lodash": "4.17.5", + "underscore.string": "3.3.4" + } + }, + "grunt-legacy-log-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz", + "integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "lodash": "4.3.0" + }, + "dependencies": { + "lodash": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz", + "integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=", + "dev": true, + "requires": { + "async": "1.5.2", + "exit": "0.1.2", + "getobject": "0.1.0", + "hooker": "0.2.3", + "lodash": "4.3.0", + "underscore.string": "3.2.3", + "which": "1.2.14" + }, + "dependencies": { + "lodash": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", + "dev": true + }, + "underscore.string": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz", + "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=", + "dev": true + } + } + }, + "grunt-lib-phantomjs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-lib-phantomjs/-/grunt-lib-phantomjs-1.1.0.tgz", + "integrity": "sha1-np7c3Z/S3UDgwYHJQ3HVcqpe6tI=", + "dev": true, + "requires": { + "eventemitter2": "0.4.14", + "phantomjs-prebuilt": "2.1.16", + "rimraf": "2.6.2", + "semver": "5.5.0", + "temporary": "0.0.8" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + } + } + }, + "grunt-shell-spawn": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.10.tgz", + "integrity": "sha1-gbuNRX7EfTGCqH1jCO+EXd+5SI8=", + "dev": true, + "requires": { + "grunt": "1.0.2", + "sync-exec": "0.6.2" + } + }, + "gzip-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", + "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", + "dev": true, + "requires": { + "browserify-zlib": "0.1.4", + "concat-stream": "1.6.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", + "dev": true, + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.3.0", + "domutils": "1.5.1", + "entities": "1.0.0", + "readable-stream": "1.1.14" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-yaml": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", + "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "2.7.3" + } + }, + "js2xmlparser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", + "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "requires": { + "xmlcreate": "1.0.2" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsdoc": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", + "integrity": "sha1-SEUhsSboGQTWMv+D7JqqCWcI+k0=", + "requires": { + "babylon": "7.0.0-beta.19", + "bluebird": "3.5.1", + "catharsis": "0.8.9", + "escape-string-regexp": "1.0.5", + "js2xmlparser": "3.0.0", + "klaw": "2.0.0", + "marked": "0.3.17", + "mkdirp": "0.5.1", + "requizzle": "0.2.1", + "strip-json-comments": "2.0.1", + "taffydb": "2.6.2", + "underscore": "1.8.3" + } + }, + "jshint": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", + "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", + "dev": true, + "requires": { + "cli": "1.0.1", + "console-browserify": "1.1.0", + "exit": "0.1.2", + "htmlparser2": "3.8.3", + "lodash": "3.7.0", + "minimatch": "3.0.4", + "shelljs": "0.3.0", + "strip-json-comments": "1.0.4" + }, + "dependencies": { + "lodash": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", + "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + } + } + }, + "jslint": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/jslint/-/jslint-0.12.0.tgz", + "integrity": "sha512-RoCsyICcKA+6TFsbys9DpKTfPVaC71Mm5QSjvrWA0lDVN+LIvx6apa42FFisMqmCTvJ8DxkcoQGJ0j7m3kTVow==", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "7.1.2", + "nopt": "3.0.6", + "readable-stream": "2.1.5" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", + "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "marked": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.17.tgz", + "integrity": "sha512-+AKbNsjZl6jFfLPwHhWmGTqE009wTKn3RTmn9K8oUKHrX/abPJjtcRtXpYB/FFrwPJRUA86LX/de3T0knkPCmQ==" + }, + "maxmin": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", + "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "figures": "1.7.0", + "gzip-size": "1.0.0", + "pretty-bytes": "1.0.4" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "package": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package/-/package-1.0.1.tgz", + "integrity": "sha1-0lofmeJQbcsn1nBLg9yooxLk7cw=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "phantomjs-prebuilt": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", + "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", + "dev": true, + "requires": { + "es6-promise": "4.2.4", + "extract-zip": "1.6.6", + "fs-extra": "1.0.0", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.83.0", + "request-progress": "2.0.1", + "which": "1.3.0" + }, + "dependencies": { + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "1.0.0" + } + }, + "requizzle": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", + "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "sync-exec": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz", + "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=", + "dev": true + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=" + }, + "temporary": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/temporary/-/temporary-0.0.8.tgz", + "integrity": "sha1-oYqYHSi6jKNgJ/s8MFOMPst0CsA=", + "dev": true, + "requires": { + "package": "1.0.1" + } + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", + "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "underscore-contrib": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", + "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "underscore.string": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", + "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=", + "dev": true, + "requires": { + "sprintf-js": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "uri-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", + "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xmlcreate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", + "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/lib/js/package.json b/lib/js/package.json index 526528dd5c6..f3ed3e1e87c 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -2,15 +2,15 @@ "name": "thrift", "version": "1.0.0", "devDependencies": { - "grunt": "^0.4.5", + "grunt": "^1.0.2", "grunt-cli": "^1.2.0", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-jshint": "^1.0.0", "grunt-contrib-qunit": "^1.2.0", "grunt-contrib-uglify": "^1.0.1", - "grunt-external-daemon": "^1.1.0", - "grunt-jsdoc": "^2.2.0", - "grunt-shell": "^1.3.0" + "grunt-jsdoc": "^2.2.1", + "grunt-shell-spawn": "^0.3.10", + "jslint": "^0.12.0" }, "dependencies": { "jsdoc": "^3.5.5", diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 5d420a25635..2b385a3a712 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -1258,7 +1258,12 @@ Thrift.Protocol.prototype = { /** Deserializes the end of a list. */ readListEnd: function() { - this.readFieldEnd(); + var pos = this.rpos.pop() - 2; + var st = this.rstack; + st.pop(); + if (st instanceof Array && st.length > pos && st[pos].length > 0) { + st.push(st[pos].shift()); + } }, /** @@ -1433,6 +1438,9 @@ Thrift.Protocol.prototype = { } this.readListEnd(); return null; + + default: + throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA); } } }; diff --git a/lib/js/test/build.xml b/lib/js/test/build.xml index 109c62fcccf..0ba382891fb 100755 --- a/lib/js/test/build.xml +++ b/lib/js/test/build.xml @@ -72,7 +72,7 @@ You need libthrift*.jar and libthrift*test.jar located at - ${thrift.java.dir}/build + ${thrift.java.dir}/build/libs Did you compile Thrift Java library and its test suite by "ant compile-test"? @@ -98,13 +98,16 @@ - + + + + @@ -168,6 +171,9 @@ + + + diff --git a/lib/js/test/deep-constructor.test.js b/lib/js/test/deep-constructor.test.js index 336fc15aceb..f349e466fd5 100644 --- a/lib/js/test/deep-constructor.test.js +++ b/lib/js/test/deep-constructor.test.js @@ -61,7 +61,13 @@ function createThriftObj() { DB: new Simple({value: 'k'}) } ] - } + }, + + list_of_list_field: [ + ['one', 'two'], + ['three', 'four'], + ['five', 'six'] + ] } ); } @@ -108,7 +114,13 @@ function createJsObj() { DB: {value: 'k'} } ] - } + }, + + list_of_list_field: [ + ['one', 'two'], + ['three', 'four'], + ['five', 'six'] + ] }; } @@ -125,6 +137,12 @@ function assertValues(obj, assert) { assert.equal(obj.struct_nested_containers_field[0][0].C[1].value, 'i'); assert.equal(obj.struct_nested_containers_field2.D[0].DA.value, 'j'); assert.equal(obj.struct_nested_containers_field2.D[1].DB.value, 'k'); + assert.equal(obj.list_of_list_field[0][0], 'one'); + assert.equal(obj.list_of_list_field[0][1], 'two'); + assert.equal(obj.list_of_list_field[1][0], 'three'); + assert.equal(obj.list_of_list_field[1][1], 'four'); + assert.equal(obj.list_of_list_field[2][0], 'five'); + assert.equal(obj.list_of_list_field[2][1], 'six'); } var cases = { diff --git a/lib/js/test/jsTestDriver.conf b/lib/js/test/jsTestDriver.conf index b9702cd3a0a..eb1588c8284 100755 --- a/lib/js/test/jsTestDriver.conf +++ b/lib/js/test/jsTestDriver.conf @@ -7,6 +7,7 @@ load: # 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-deep-constructor.html b/lib/js/test/test-deep-constructor.html index 5835dc84bb2..4c5fb02e4ef 100755 --- a/lib/js/test/test-deep-constructor.html +++ b/lib/js/test/test-deep-constructor.html @@ -25,11 +25,11 @@ - + - - + + diff --git a/lib/js/test/test-double-rendering.html b/lib/js/test/test-double-rendering.html new file mode 100644 index 00000000000..240cb3946c3 --- /dev/null +++ b/lib/js/test/test-double-rendering.html @@ -0,0 +1,55 @@ ++ + + + + + Rendering Double Constants in JS: Unit Test + + + + + + + + + + + + + + + + + + +

Rendering Double Constants in JS: Unit Test

+

+
+

+
+ + + diff --git a/lib/js/test/test-double-rendering.js b/lib/js/test/test-double-rendering.js new file mode 100644 index 00000000000..5d9cd2a8d0f --- /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'); + }); + diff --git a/lib/nodejs/README.md b/lib/nodejs/README.md index 8c25380d1a0..5b15ce647d7 100644 --- a/lib/nodejs/README.md +++ b/lib/nodejs/README.md @@ -22,7 +22,7 @@ under the License. ## Compatibility -node version 4 or later is required +node version 6 or later is required ## Install diff --git a/lib/nodejs/lib/thrift/binary_protocol.js b/lib/nodejs/lib/thrift/binary_protocol.js index 0c0ee50be66..b57c8c57635 100644 --- a/lib/nodejs/lib/thrift/binary_protocol.js +++ b/lib/nodejs/lib/thrift/binary_protocol.js @@ -37,6 +37,7 @@ function TBinaryProtocol(trans, strictRead, strictWrite) { this.trans = trans; this.strictRead = (strictRead !== undefined ? strictRead : false); this.strictWrite = (strictWrite !== undefined ? strictWrite : true); + this._seqid = null; }; TBinaryProtocol.prototype.flush = function() { @@ -54,7 +55,7 @@ TBinaryProtocol.prototype.writeMessageBegin = function(name, type, seqid) { this.writeI32(seqid); } // Record client seqid to find callback again - if (this._seqid) { + if (this._seqid !== null) { log.warning('SeqId already set', { 'name': name }); } else { this._seqid = seqid; @@ -63,7 +64,7 @@ TBinaryProtocol.prototype.writeMessageBegin = function(name, type, seqid) { }; TBinaryProtocol.prototype.writeMessageEnd = function() { - if (this._seqid) { + if (this._seqid !== null) { this._seqid = null; } else { log.warning('No seqid to unset'); diff --git a/lib/nodejs/test/browser_client.js b/lib/nodejs/test/browser_client.js deleted file mode 100644 index 72fd8375bb1..00000000000 --- a/lib/nodejs/test/browser_client.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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. - */ - -var assert = require('assert'); -var thrift = require('thrift'); -var helpers = require('./helpers'); -var ThriftTest = require('./gen-nodejs/ThriftTest'); -var ThriftTestDriver = require('./test_driver').ThriftTestDriver; - -// createXHRConnection createWSConnection -var connection = thrift.createXHRConnection("localhost", 9090, { - transport: helpers.transports['buffered'], - protocol: helpers.protocols['json'], - path: '/test' -}); - -connection.on('error', function(err) { - assert(false, err); -}); - -// Uncomment the following line to start a websockets connection -// connection.open(); - -// createWSClient createXHRClient -var client = thrift.createXHRClient(ThriftTest, connection); - -ThriftTestDriver(client, function (status) { - console.log('Browser:', status); -}); diff --git a/lib/nodejs/test/testAll.sh b/lib/nodejs/test/testAll.sh index aae451a4810..ac22b64e82b 100755 --- a/lib/nodejs/test/testAll.sh +++ b/lib/nodejs/test/testAll.sh @@ -24,7 +24,6 @@ fi DIR="$( cd "$( dirname "$0" )" && pwd )" ISTANBUL="$DIR/../../../node_modules/istanbul/lib/cli.js" -RUNBROWSER="$DIR/../../../node_modules/run-browser/bin/cli.js" REPORT_PREFIX="${DIR}/../coverage/report" @@ -55,17 +54,6 @@ testServer() return $RET } -testBrowser() -{ - echo " Testing browser client with http server with json protocol and buffered transport"; - RET=0 - node ${DIR}/server.js --type http -p json -t buffered & - SERVERPID=$! - sleep 1 - ${RUNBROWSER} ${DIR}/browser_client.js --phantom || RET=1 - kill -2 $SERVERPID || RET=1 - return $RET -} TESTOK=0 @@ -96,8 +84,6 @@ do done done -# XHR only until phantomjs 2 is released. -# testBrowser if [ -n "${COVER}" ]; then ${ISTANBUL} report --dir "${DIR}/../coverage" --include "${DIR}/../coverage/report*/coverage.json" lcov cobertura html diff --git a/lib/perl/lib/Thrift/Server.pm b/lib/perl/lib/Thrift/Server.pm index fc9ca30a9bc..f265d45f94e 100644 --- a/lib/perl/lib/Thrift/Server.pm +++ b/lib/perl/lib/Thrift/Server.pm @@ -150,27 +150,31 @@ sub new sub serve { my $self = shift; - + my $stop = 0; + $self->{serverTransport}->listen(); - while (1) - { + while (!$stop) { my $client = $self->{serverTransport}->accept(); - my $itrans = $self->{inputTransportFactory}->getTransport($client); - my $otrans = $self->{outputTransportFactory}->getTransport($client); - my $iprot = $self->{inputProtocolFactory}->getProtocol($itrans); - my $oprot = $self->{outputProtocolFactory}->getProtocol($otrans); - eval { - $self->_clientBegin($iprot, $oprot); - while (1) - { - $self->{processor}->process($iprot, $oprot); + if (defined $client) { + my $itrans = $self->{inputTransportFactory}->getTransport($client); + my $otrans = $self->{outputTransportFactory}->getTransport($client); + my $iprot = $self->{inputProtocolFactory}->getProtocol($itrans); + my $oprot = $self->{outputProtocolFactory}->getProtocol($otrans); + eval { + $self->_clientBegin($iprot, $oprot); + while (1) + { + $self->{processor}->process($iprot, $oprot); + } + }; if($@) { + $self->_handleException($@); } - }; if($@) { - $self->_handleException($@); - } - $itrans->close(); - $otrans->close(); + $itrans->close(); + $otrans->close(); + } else { + $stop = 1; + } } } diff --git a/lib/perl/lib/Thrift/ServerSocket.pm b/lib/perl/lib/Thrift/ServerSocket.pm index 51f83b42ff5..2c4d906c47d 100644 --- a/lib/perl/lib/Thrift/ServerSocket.pm +++ b/lib/perl/lib/Thrift/ServerSocket.pm @@ -81,15 +81,24 @@ sub accept { my $self = shift; - if ( exists $self->{handle} and defined $self->{handle} ) - { + if ( exists $self->{handle} and defined $self->{handle} ) { my $client = $self->{handle}->accept(); my $result = $self->__client(); $result->{handle} = new IO::Select($client); return $result; } - return 0; + return undef; +} + +sub close +{ + my $self = shift; + + if ( exists $self->{handle} and defined $self->{handle} ) + { + $self->{handle}->close(); + } } ### diff --git a/lib/php/README.md b/lib/php/README.md index c24ee2c0c2a..7170104dff4 100644 --- a/lib/php/README.md +++ b/lib/php/README.md @@ -1,7 +1,6 @@ Thrift PHP Software Library -License -======= +# License Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -20,8 +19,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -Using Thrift with PHP -===================== +# Using Thrift with PHP Thrift requires PHP 5. Thrift makes as few assumptions about your PHP environment as possible while trying to make some more advanced PHP @@ -29,25 +27,34 @@ features (i.e. APC cacheing using asbolute path URLs) as simple as possible. To use Thrift in your PHP codebase, take the following steps: -#1) Copy all of thrift/lib/php/lib into your PHP codebase -#2) Configure Symfony Autoloader (or whatever you usually use) +1. Copy all of thrift/lib/php/lib into your PHP codebase +2. Configure Symfony Autoloader (or whatever you usually use) After that, you have to manually include the Thrift package created by the compiler: +``` require_once 'packages/Service/Service.php'; require_once 'packages/Service/Types.php'; +``` -Dependencies -============ +# Dependencies PHP_INT_SIZE - This built-in signals whether your architecture is 32 or 64 bit and is - used by the TBinaryProtocol to properly use pack() and unpack() to - serialize data. + This built-in signals whether your architecture is 32 or 64 bit and is + used by the TBinaryProtocol to properly use pack() and unpack() to + serialize data. apc_fetch(), apc_store() - APC cache is used by the TSocketPool class. If you do not have APC installed, - Thrift will fill in null stub function definitions. + APC cache is used by the TSocketPool class. If you do not have APC installed, + Thrift will fill in null stub function definitions. + +# Breaking Changes + +## 0.12.0 + +1. [PSR-4](https://www.php-fig.org/psr/psr-4/) loader is now the default. If you want to use class maps instead, use `-gen php:classmap`. + +2. If using PSR-4, use `$thriftClassLoader->registerNamespace('namespace', '')` instead of `$thriftClassLoader->registerDefinition('namespace', '')`. diff --git a/lib/php/lib/Transport/TSocket.php b/lib/php/lib/Transport/TSocket.php index 93bd1cfb8f5..5147efa6301 100644 --- a/lib/php/lib/Transport/TSocket.php +++ b/lib/php/lib/Transport/TSocket.php @@ -138,6 +138,7 @@ public function __construct( public function setHandle($handle) { $this->handle_ = $handle; + stream_set_blocking($this->handle_, false); } /** diff --git a/lib/php/test/JsonSerialize/JsonSerializeTest.php b/lib/php/test/JsonSerialize/JsonSerializeTest.php index 8c645956032..c6686525fac 100644 --- a/lib/php/test/JsonSerialize/JsonSerializeTest.php +++ b/lib/php/test/JsonSerialize/JsonSerializeTest.php @@ -22,9 +22,8 @@ use PHPUnit\Framework\TestCase; use stdClass; -use Thrift\ClassLoader\ThriftClassLoader; -require_once __DIR__ . '/../../../../vendor/autoload.php'; +require __DIR__ . '/../../../../vendor/autoload.php'; /** * @runTestsInSeparateProcesses @@ -36,9 +35,9 @@ protected function setUp() if (version_compare(phpversion(), '5.4', '<')) { $this->markTestSkipped('Requires PHP 5.4 or newer!'); } - $loader = new ThriftClassLoader(); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages/phpjs'); - $loader->register(); + /** @var \Composer\Autoload\ClassLoader $loader */ + $loader = require __DIR__ . '/../../../../vendor/autoload.php'; + $loader->addPsr4('', __DIR__ . '/../packages/phpjs'); } public function testEmptyStruct() diff --git a/lib/php/test/Makefile.am b/lib/php/test/Makefile.am index 5c86e35645f..48246882647 100755 --- a/lib/php/test/Makefile.am +++ b/lib/php/test/Makefile.am @@ -20,8 +20,8 @@ PHPUNIT=php $(top_srcdir)/vendor/bin/phpunit stubs: ../../../test/ThriftTest.thrift TestValidators.thrift - mkdir -p ./packages - $(THRIFT) --gen php -r --out ./packages ../../../test/ThriftTest.thrift + mkdir -p ./packages/php + $(THRIFT) --gen php -r --out ./packages/php ../../../test/ThriftTest.thrift mkdir -p ./packages/phpv mkdir -p ./packages/phpvo mkdir -p ./packages/phpjs diff --git a/lib/php/test/Protocol/BinarySerializerTest.php b/lib/php/test/Protocol/BinarySerializerTest.php index 7e8728012b2..71b0bb5066a 100644 --- a/lib/php/test/Protocol/BinarySerializerTest.php +++ b/lib/php/test/Protocol/BinarySerializerTest.php @@ -24,10 +24,9 @@ namespace Test\Thrift\Protocol; use PHPUnit\Framework\TestCase; -use Thrift\ClassLoader\ThriftClassLoader; use Thrift\Serializer\TBinarySerializer; -require_once __DIR__ . '/../../../../vendor/autoload.php'; +require __DIR__ . '/../../../../vendor/autoload.php'; /*** * This test suite depends on running the compiler against the @@ -42,9 +41,9 @@ class BinarySerializerTest extends TestCase { public function setUp() { - $loader = new ThriftClassLoader(); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages'); - $loader->register(); + /** @var \Composer\Autoload\ClassLoader $loader */ + $loader = require __DIR__ . '/../../../../vendor/autoload.php'; + $loader->addPsr4('', __DIR__ . '/../packages/php'); } /** diff --git a/lib/php/test/Protocol/TJSONProtocolTest.php b/lib/php/test/Protocol/TJSONProtocolTest.php index bab4389a057..bf0ecce4293 100644 --- a/lib/php/test/Protocol/TJSONProtocolTest.php +++ b/lib/php/test/Protocol/TJSONProtocolTest.php @@ -25,11 +25,10 @@ use PHPUnit\Framework\TestCase; use Test\Thrift\Fixtures; -use Thrift\ClassLoader\ThriftClassLoader; use Thrift\Protocol\TJSONProtocol; use Thrift\Transport\TMemoryBuffer; -require_once __DIR__ . '/../../../../vendor/autoload.php'; +require __DIR__ . '/../../../../vendor/autoload.php'; /*** * This test suite depends on running the compiler against the @@ -47,9 +46,9 @@ class TJSONProtocolTest extends TestCase public static function setUpBeforeClass() { - $loader = new ThriftClassLoader(); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages'); - $loader->register(); + /** @var \Composer\Autoload\ClassLoader $loader */ + $loader = require __DIR__ . '/../../../../vendor/autoload.php'; + $loader->addPsr4('', __DIR__ . '/../packages/php'); Fixtures::populateTestArgs(); TJSONProtocolFixtures::populateTestArgsJSON(); diff --git a/lib/php/test/Protocol/TSimpleJSONProtocolTest.php b/lib/php/test/Protocol/TSimpleJSONProtocolTest.php index ec64321472b..e4a13736ed7 100644 --- a/lib/php/test/Protocol/TSimpleJSONProtocolTest.php +++ b/lib/php/test/Protocol/TSimpleJSONProtocolTest.php @@ -25,11 +25,10 @@ use PHPUnit\Framework\TestCase; use Test\Thrift\Fixtures; -use Thrift\ClassLoader\ThriftClassLoader; use Thrift\Protocol\TSimpleJSONProtocol; use Thrift\Transport\TMemoryBuffer; -require_once __DIR__ . '/../../../../vendor/autoload.php'; +require __DIR__ . '/../../../../vendor/autoload.php'; /*** * This test suite depends on running the compiler against the @@ -47,9 +46,10 @@ class TSimpleJSONProtocolTest extends TestCase public static function setUpBeforeClass() { - $loader = new ThriftClassLoader(); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages'); - $loader->register(); + + /** @var \Composer\Autoload\ClassLoader $loader */ + $loader = require __DIR__ . '/../../../../vendor/autoload.php'; + $loader->addPsr4('', __DIR__ . '/../packages/php'); Fixtures::populateTestArgs(); TSimpleJSONProtocolFixtures::populateTestArgsSimpleJSON(); diff --git a/lib/php/test/Validator/ValidatorTest.php b/lib/php/test/Validator/ValidatorTest.php index ace3075de5a..fa6c7a9f7e0 100644 --- a/lib/php/test/Validator/ValidatorTest.php +++ b/lib/php/test/Validator/ValidatorTest.php @@ -20,7 +20,7 @@ namespace Test\Thrift; -require_once __DIR__ . '/../../../../vendor/autoload.php'; +require __DIR__ . '/../../../../vendor/autoload.php'; use Thrift\ClassLoader\ThriftClassLoader; @@ -34,9 +34,8 @@ class ValidatorTest extends BaseValidatorTest { public function setUp() { - $loader = new ThriftClassLoader(); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages/phpv'); - $loader->registerDefinition('TestValidators', __DIR__ . '/../packages/phpv'); - $loader->register(); + /** @var \Composer\Autoload\ClassLoader $loader */ + $loader = require __DIR__ . '/../../../../vendor/autoload.php'; + $loader->addPsr4('', __DIR__ . '/../packages/phpv'); } } diff --git a/lib/php/test/Validator/ValidatorTestOop.php b/lib/php/test/Validator/ValidatorTestOop.php index 5a8e3bfb9a3..93bca4d0cbc 100644 --- a/lib/php/test/Validator/ValidatorTestOop.php +++ b/lib/php/test/Validator/ValidatorTestOop.php @@ -34,9 +34,8 @@ class ValidatorTestOop extends BaseValidatorTest { public function setUp() { - $loader = new ThriftClassLoader(); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages/phpvo'); - $loader->registerDefinition('TestValidators', __DIR__ . '/../packages/phpvo'); - $loader->register(); + /** @var \Composer\Autoload\ClassLoader $loader */ + $loader = require __DIR__ . '/../../../../vendor/autoload.php'; + $loader->addPsr4('', __DIR__ . '/../packages/phpvo'); } } diff --git a/lib/py/setup.py b/lib/py/setup.py index 4056b9b9038..4c2877abcea 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -31,7 +31,10 @@ # Fix to build sdist under vagrant import os if 'vagrant' in str(os.environ): - del os.link + try: + del os.link + except AttributeError: + pass include_dirs = ['src'] if sys.platform == 'win32': diff --git a/lib/rs/src/transport/framed.rs b/lib/rs/src/transport/framed.rs index d78d2f7a195..7e0f8b6c3c3 100644 --- a/lib/rs/src/transport/framed.rs +++ b/lib/rs/src/transport/framed.rs @@ -18,7 +18,7 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use std::cmp; use std::io; -use std::io::{ErrorKind, Read, Write}; +use std::io::{Read, Write}; use super::{TReadTransport, TReadTransportFactory, TWriteTransport, TWriteTransportFactory}; @@ -57,7 +57,7 @@ pub struct TFramedReadTransport where C: Read, { - buf: Box<[u8]>, + buf: Vec, pos: usize, cap: usize, chan: C, @@ -67,18 +67,17 @@ impl TFramedReadTransport where C: Read, { - /// Create a `TFramedTransport` with default-sized internal read and - /// write buffers that wraps the given `TIoChannel`. + /// Create a `TFramedReadTransport` with a default-sized + /// internal read buffer that wraps the given `TIoChannel`. pub fn new(channel: C) -> TFramedReadTransport { TFramedReadTransport::with_capacity(READ_CAPACITY, channel) } - /// Create a `TFramedTransport` with an internal read buffer of size - /// `read_capacity` and an internal write buffer of size - /// `write_capacity` that wraps the given `TIoChannel`. + /// Create a `TFramedTransport` with an internal read buffer + /// of size `read_capacity` that wraps the given `TIoChannel`. pub fn with_capacity(read_capacity: usize, channel: C) -> TFramedReadTransport { TFramedReadTransport { - buf: vec![0; read_capacity].into_boxed_slice(), + buf: vec![0; read_capacity], // FIXME: do I actually have to do this? pos: 0, cap: 0, chan: channel, @@ -93,22 +92,13 @@ where fn read(&mut self, b: &mut [u8]) -> io::Result { if self.cap - self.pos == 0 { let message_size = self.chan.read_i32::()? as usize; - if message_size > self.buf.len() { - return Err( - io::Error::new( - ErrorKind::Other, - format!( - "bytes to be read ({}) exceeds buffer \ - capacity ({})", - message_size, - self.buf.len() - ), - ), - ); - } + + let buf_capacity = cmp::max(message_size, READ_CAPACITY); + self.buf.resize(buf_capacity, 0); + self.chan.read_exact(&mut self.buf[..message_size])?; - self.pos = 0; self.cap = message_size as usize; + self.pos = 0; } let nread = cmp::min(b.len(), self.cap - self.pos); @@ -165,8 +155,7 @@ pub struct TFramedWriteTransport where C: Write, { - buf: Box<[u8]>, - pos: usize, + buf: Vec, channel: C, } @@ -174,20 +163,18 @@ impl TFramedWriteTransport where C: Write, { - /// Create a `TFramedTransport` with default-sized internal read and - /// write buffers that wraps the given `TIoChannel`. + /// Create a `TFramedWriteTransport` with default-sized internal + /// write buffer that wraps the given `TIoChannel`. pub fn new(channel: C) -> TFramedWriteTransport { TFramedWriteTransport::with_capacity(WRITE_CAPACITY, channel) } - /// Create a `TFramedTransport` with an internal read buffer of size - /// `read_capacity` and an internal write buffer of size - /// `write_capacity` that wraps the given `TIoChannel`. + /// Create a `TFramedWriteTransport` with an internal write buffer + /// of size `write_capacity` that wraps the given `TIoChannel`. pub fn with_capacity(write_capacity: usize, channel: C) -> TFramedWriteTransport { TFramedWriteTransport { - buf: vec![0; write_capacity].into_boxed_slice(), - pos: 0, - channel: channel, + buf: Vec::with_capacity(write_capacity), + channel, } } } @@ -197,28 +184,19 @@ where C: Write, { fn write(&mut self, b: &[u8]) -> io::Result { - if b.len() > (self.buf.len() - self.pos) { - return Err( - io::Error::new( - ErrorKind::Other, - format!( - "bytes to be written ({}) exceeds buffer \ - capacity ({})", - b.len(), - self.buf.len() - self.pos - ), - ), - ); + let current_capacity = self.buf.capacity(); + let available_space = current_capacity - self.buf.len(); + if b.len() > available_space { + let additional_space = cmp::max(b.len() - available_space, current_capacity); + self.buf.reserve(additional_space); } - let nwrite = b.len(); // always less than available write buffer capacity - self.buf[self.pos..(self.pos + nwrite)].clone_from_slice(b); - self.pos += nwrite; - Ok(nwrite) + self.buf.extend_from_slice(b); + Ok(b.len()) } fn flush(&mut self) -> io::Result<()> { - let message_size = self.pos; + let message_size = self.buf.len(); if let 0 = message_size { return Ok(()); @@ -227,13 +205,17 @@ where .write_i32::(message_size as i32)?; } + // will spin if the underlying channel can't be written to let mut byte_index = 0; - while byte_index < self.pos { - let nwrite = self.channel.write(&self.buf[byte_index..self.pos])?; - byte_index = cmp::min(byte_index + nwrite, self.pos); + while byte_index < message_size { + let nwrite = self.channel.write(&self.buf[byte_index..message_size])?; + byte_index = cmp::min(byte_index + nwrite, message_size); } - self.pos = 0; + let buf_capacity = cmp::min(self.buf.capacity(), WRITE_CAPACITY); + self.buf.resize(buf_capacity, 0); + self.buf.clear(); + self.channel.flush() } } @@ -257,8 +239,230 @@ impl TWriteTransportFactory for TFramedWriteTransportFactory { #[cfg(test)] mod tests { - // use std::io::{Read, Write}; - // - // use super::*; - // use ::transport::mem::TBufferChannel; + use super::*; + use ::transport::mem::TBufferChannel; + + // FIXME: test a forced reserve + + #[test] + fn must_read_message_smaller_than_initial_buffer_size() { + let c = TBufferChannel::with_capacity(10, 10); + let mut t = TFramedReadTransport::with_capacity(8, c); + + t.chan.set_readable_bytes( + &[ + 0x00, 0x00, 0x00, 0x04, /* message size */ + 0x00, 0x01, 0x02, 0x03 /* message body */ + ] + ); + + let mut buf = vec![0; 8]; + + // we've read exactly 4 bytes + assert_eq!(t.read(&mut buf).unwrap(), 4); + assert_eq!(&buf[..4], &[0x00, 0x01, 0x02, 0x03]); + } + + #[test] + fn must_read_message_greater_than_initial_buffer_size() { + let c = TBufferChannel::with_capacity(10, 10); + let mut t = TFramedReadTransport::with_capacity(2, c); + + t.chan.set_readable_bytes( + &[ + 0x00, 0x00, 0x00, 0x04, /* message size */ + 0x00, 0x01, 0x02, 0x03 /* message body */ + ] + ); + + let mut buf = vec![0; 8]; + + // we've read exactly 4 bytes + assert_eq!(t.read(&mut buf).unwrap(), 4); + assert_eq!(&buf[..4], &[0x00, 0x01, 0x02, 0x03]); + } + + #[test] + fn must_read_multiple_messages_in_sequence_correctly() { + let c = TBufferChannel::with_capacity(10, 10); + let mut t = TFramedReadTransport::with_capacity(2, c); + + // + // 1st message + // + + t.chan.set_readable_bytes( + &[ + 0x00, 0x00, 0x00, 0x04, /* message size */ + 0x00, 0x01, 0x02, 0x03 /* message body */ + ] + ); + + let mut buf = vec![0; 8]; + + // we've read exactly 4 bytes + assert_eq!(t.read(&mut buf).unwrap(), 4); + assert_eq!(&buf, &[0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00]); + + // + // 2nd message + // + + t.chan.set_readable_bytes( + &[ + 0x00, 0x00, 0x00, 0x01, /* message size */ + 0x04 /* message body */ + ] + ); + + let mut buf = vec![0; 8]; + + // we've read exactly 1 byte + assert_eq!(t.read(&mut buf).unwrap(), 1); + assert_eq!(&buf, &[0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + } + + #[test] + fn must_write_message_smaller_than_buffer_size() { + let mem = TBufferChannel::with_capacity(0, 0); + let mut t = TFramedWriteTransport::with_capacity(20, mem); + + let b = vec![0; 10]; + + // should have written 10 bytes + assert_eq!(t.write(&b).unwrap(), 10); + } + + #[test] + fn must_return_zero_if_caller_calls_write_with_empty_buffer() { + let mem = TBufferChannel::with_capacity(0, 10); + let mut t = TFramedWriteTransport::with_capacity(10, mem); + + let expected: [u8; 0] = []; + + assert_eq!(t.write(&[]).unwrap(), 0); + assert_eq_transport_written_bytes!(t, expected); + } + + #[test] + fn must_write_to_inner_transport_on_flush() { + let mem = TBufferChannel::with_capacity(10, 10); + let mut t = TFramedWriteTransport::new(mem); + + let b: [u8; 5] = [0x00, 0x01, 0x02, 0x03, 0x04]; + assert_eq!(t.write(&b).unwrap(), 5); + assert_eq_transport_num_written_bytes!(t, 0); + + assert!(t.flush().is_ok()); + + let expected_bytes = [ + 0x00, 0x00, 0x00, 0x05, /* message size */ + 0x00, 0x01, 0x02, 0x03, 0x04 /* message body */ + ]; + + assert_eq_transport_written_bytes!(t, expected_bytes); + } + + #[test] + fn must_write_message_greater_than_buffer_size_00() { + let mem = TBufferChannel::with_capacity(0, 10); + + // IMPORTANT: DO **NOT** CHANGE THE WRITE_CAPACITY OR THE NUMBER OF BYTES TO BE WRITTEN! + // these lengths were chosen to be just long enough + // that doubling the capacity is a **worse** choice than + // simply resizing the buffer to b.len() + + let mut t = TFramedWriteTransport::with_capacity(1, mem); + let b = [0x00, 0x01, 0x02]; + + // should have written 3 bytes + assert_eq!(t.write(&b).unwrap(), 3); + assert_eq_transport_num_written_bytes!(t, 0); + + assert!(t.flush().is_ok()); + + let expected_bytes = [ + 0x00, 0x00, 0x00, 0x03, /* message size */ + 0x00, 0x01, 0x02 /* message body */ + ]; + + assert_eq_transport_written_bytes!(t, expected_bytes); + } + + #[test] + fn must_write_message_greater_than_buffer_size_01() { + let mem = TBufferChannel::with_capacity(0, 10); + + // IMPORTANT: DO **NOT** CHANGE THE WRITE_CAPACITY OR THE NUMBER OF BYTES TO BE WRITTEN! + // these lengths were chosen to be just long enough + // that doubling the capacity is a **better** choice than + // simply resizing the buffer to b.len() + + let mut t = TFramedWriteTransport::with_capacity(2, mem); + let b = [0x00, 0x01, 0x02]; + + // should have written 3 bytes + assert_eq!(t.write(&b).unwrap(), 3); + assert_eq_transport_num_written_bytes!(t, 0); + + assert!(t.flush().is_ok()); + + let expected_bytes = [ + 0x00, 0x00, 0x00, 0x03, /* message size */ + 0x00, 0x01, 0x02 /* message body */ + ]; + + assert_eq_transport_written_bytes!(t, expected_bytes); + } + + #[test] + fn must_return_error_if_nothing_can_be_written_to_inner_transport_on_flush() { + let mem = TBufferChannel::with_capacity(0, 0); + let mut t = TFramedWriteTransport::with_capacity(1, mem); + + let b = vec![0; 10]; + + // should have written 10 bytes + assert_eq!(t.write(&b).unwrap(), 10); + + // let's flush + let r = t.flush(); + + // this time we'll error out because the flush can't write to the underlying channel + assert!(r.is_err()); + } + + #[test] + fn must_write_successfully_after_flush() { + // IMPORTANT: write capacity *MUST* be greater + // than message sizes used in this test + 4-byte frame header + let mem = TBufferChannel::with_capacity(0, 10); + let mut t = TFramedWriteTransport::with_capacity(5, mem); + + // write and flush + let first_message: [u8; 5] = [0x00, 0x01, 0x02, 0x03, 0x04]; + assert_eq!(t.write(&first_message).unwrap(), 5); + assert!(t.flush().is_ok()); + + let mut expected = Vec::new(); + expected.write_all(&[0x00, 0x00, 0x00, 0x05]).unwrap(); // message size + expected.extend_from_slice(&first_message); + + // check the flushed bytes + assert_eq!(t.channel.write_bytes(), expected); + + // reset our underlying transport + t.channel.empty_write_buffer(); + + let second_message: [u8; 3] = [0x05, 0x06, 0x07]; + assert_eq!(t.write(&second_message).unwrap(), 3); + assert!(t.flush().is_ok()); + + expected.clear(); + expected.write_all(&[0x00, 0x00, 0x00, 0x03]).unwrap(); // message size + expected.extend_from_slice(&second_message); + + // check the flushed bytes + assert_eq!(t.channel.write_bytes(), expected); + } } diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000000..27bd5e92dd1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2028 @@ +{ + "name": "thrift", + "version": "1.0.0-dev", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.5" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "babylon": { + "version": "7.0.0-beta.19", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", + "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==", + "dev": true + }, + "bl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz", + "integrity": "sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4=", + "dev": true, + "requires": { + "readable-stream": "2.0.6" + }, + "dependencies": { + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-equals": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", + "integrity": "sha1-A1O1T9B/2VZBcGca5vZrnPENJ/U=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "catharsis": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", + "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "dev": true, + "requires": { + "underscore-contrib": "0.3.0" + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.5", + "typedarray": "0.0.6" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "1.3.2", + "utils-merge": "1.0.1" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "optional": true + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + }, + "dependencies": { + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "expand-template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.0.tgz", + "integrity": "sha512-kkjwkMqj0h4w/sb32ERCDxCQkREMCAgS39DscDnSwDsbxnwwM1BTZySdC3Bn1lhY7vL08n9GoO/fVTynjDgRyQ==", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extract-zip": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz", + "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "debug": "2.6.9", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } + }, + "for-each": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", + "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "dev": true, + "requires": { + "is-function": "1.0.1" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" + }, + "dependencies": { + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "dev": true, + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.11.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + } + }, + "js-yaml": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "js2xmlparser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", + "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "dev": true, + "requires": { + "xmlcreate": "1.0.2" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsdoc": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", + "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==", + "dev": true, + "requires": { + "babylon": "7.0.0-beta.19", + "bluebird": "3.5.1", + "catharsis": "0.8.9", + "escape-string-regexp": "1.0.5", + "js2xmlparser": "3.0.0", + "klaw": "2.0.0", + "marked": "0.3.17", + "mkdirp": "0.5.1", + "requizzle": "0.2.1", + "strip-json-comments": "2.0.1", + "taffydb": "2.6.2", + "underscore": "1.8.3" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", + "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "marked": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.17.tgz", + "integrity": "sha512-+AKbNsjZl6jFfLPwHhWmGTqE009wTKn3RTmn9K8oUKHrX/abPJjtcRtXpYB/FFrwPJRUA86LX/de3T0knkPCmQ==", + "dev": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true + }, + "node-abi": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.3.0.tgz", + "integrity": "sha512-zwm6vU3SsVgw3e9fu48JBaRBCJGIvAgysDsqtf5+vEexFE71bEOtaMWb5zr/zODZNzTPtQlqUUpC79k68Hspow==", + "dev": true, + "requires": { + "semver": "5.5.0" + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-inspect": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.5.0.tgz", + "integrity": "sha512-UmOFbHbwvv+XHj7BerrhVq+knjceBdkvU5AriwLMvhv2qi+e7DJzxfBeFpILEjVzCp+xA+W/pIf06RGPWlZNfw==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "phantomjs-prebuilt": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", + "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", + "dev": true, + "requires": { + "es6-promise": "4.2.4", + "extract-zip": "1.6.6", + "fs-extra": "1.0.0", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.83.0", + "request-progress": "2.0.1", + "which": "1.3.0" + } + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "prebuild-install": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.3.0.tgz", + "integrity": "sha512-gzjq2oHB8oMbzJSsSh9MQ64zrXZGt092/uT4TLZlz2qnrPxpWqp4vYB7LZrDxnlxf5RfbCjkgDI/z0EIVuYzAw==", + "dev": true, + "requires": { + "expand-template": "1.1.0", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.3.0", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "1.0.3", + "rc": "1.2.5", + "simple-get": "1.4.3", + "tar-fs": "1.16.0", + "tunnel-agent": "0.6.0", + "xtend": "4.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + }, + "rc": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.5.tgz", + "integrity": "sha1-J1zWh/bjs2zHVrqibf7oCnkDAf0=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "1.0.0" + } + }, + "requizzle": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", + "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "dev": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-get": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-1.4.3.tgz", + "integrity": "sha1-6XVe2kB+ltpAxeUVjJ6jezO+y+s=", + "dev": true, + "requires": { + "once": "1.4.0", + "unzip-response": "1.0.2", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0", + "function-bind": "1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "tape": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.0.tgz", + "integrity": "sha512-j0jO9BiScfqtPBb9QmPLL0qvxXMz98xjkMb7x8lKipFlJZwNJkqkWPou+NU4V6T9RnVh1kuSthLE8gLrN8bBfw==", + "dev": true, + "requires": { + "deep-equal": "1.0.1", + "defined": "1.0.0", + "for-each": "0.3.2", + "function-bind": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "inherits": "2.0.3", + "minimist": "1.2.0", + "object-inspect": "1.5.0", + "resolve": "1.5.0", + "resumer": "0.0.0", + "string.prototype.trim": "1.1.2", + "through": "2.3.8" + }, + "dependencies": { + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + } + } + }, + "tar-fs": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.0.tgz", + "integrity": "sha512-I9rb6v7mjWLtOfCau9eH5L7sLJyU2BnxtEZRQ5Mt+eRKmf1F0ohXmT/Jc3fr52kDvjJ/HV5MH3soQfPL5bQ0Yg==", + "dev": true, + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.5.5" + } + }, + "tar-stream": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", + "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", + "dev": true, + "requires": { + "bl": "1.0.3", + "end-of-stream": "1.4.1", + "readable-stream": "2.3.5", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true + }, + "underscore-contrib": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", + "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", + "dev": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", + "dev": true + }, + "utf-8-validate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-4.0.0.tgz", + "integrity": "sha512-JS/c6nR/qauqSdvTksgDO1142kYddTXz42y5X/he188B/kgcFLLB4l9CfZd+hGic/ORgsL+pPfwr9lYsL/80Fw==", + "dev": true, + "requires": { + "bindings": "1.3.0", + "nan": "2.8.0", + "prebuild-install": "2.3.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.0.0.tgz", + "integrity": "sha512-XXG4S0b771C68AeTHebBsJJBZMguxj7Em+D657RViuj6ppRd3tfuOhIK8eGwZGNb76C8MjQfCTfH2NN50rJN4w==", + "requires": { + "async-limiter": "1.0.0" + } + }, + "xmlcreate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", + "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/package.json b/package.json index cd6c7106c3a..b03fc575826 100644 --- a/package.json +++ b/package.json @@ -37,19 +37,17 @@ "dependencies": { "node-int64": "^0.4.0", "q": "^1.5.0", - "ws": ">= 2.2.3" + "ws": "^5.0.0" }, "devDependencies": { "buffer-equals": "^1.0.4", - "commander": "^2.11.0", - "connect": "^3.6.4", + "commander": "^2.14.1", + "connect": "^3.6.6", "istanbul": "^0.4.5", - "jsdoc": ">=3.5.5", - "minimatch": "^3.0.4", - "phantomjs-prebuilt": "^2.1.7", - "run-browser": "^2.0.2", - "tape": "^4.8.0", - "utf-8-validate": "^3.0.0" + "jsdoc": "^3.5.5", + "phantomjs-prebuilt": "^2.1.16", + "tape": "^4.9.0", + "utf-8-validate": "^4.0.0" }, "scripts": { "cover": "lib/nodejs/test/testAll.sh COVER", diff --git a/test/DoubleConstantsTest.thrift b/test/DoubleConstantsTest.thrift new file mode 100644 index 00000000000..c9212abbb4f --- /dev/null +++ b/test/DoubleConstantsTest.thrift @@ -0,0 +1,17 @@ +namespace java thrift.test +namespace cpp thrift.test + +// more tests on double constants (precision and type checks) +const double DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST = 1 +const double DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST = -100 +const double DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST = 9223372036854775807 +const double DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST = -9223372036854775807 +const double DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST = 3.14159265359 +const double DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST = 1000000.1 +const double DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST = -1000000.1 +const double DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST = 1.7e+308 +const double DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST = 9223372036854775816.43 +const double DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST = -1.7e+308 +const double DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST = -9223372036854775816.43 + +const list DOUBLE_LIST_TEST = [1,-100,100,9223372036854775807,-9223372036854775807,3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,9223372036854775816.43,-9223372036854775816.43] diff --git a/test/Makefile.am b/test/Makefile.am index 335bae63a48..7267066b7bc 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -25,6 +25,11 @@ SUBDIRS += c_glib PRECROSS_TARGET += precross-c_glib endif +if WITH_CL +SUBDIRS += cl +PRECROSS_TARGET += precross-cl +endif + if WITH_MONO SUBDIRS += csharp PRECROSS_TARGET += precross-csharp @@ -110,6 +115,7 @@ EXTRA_DIST = \ crossrunner \ keys \ c_glib \ + cl \ cpp \ dart \ erl \ @@ -128,6 +134,7 @@ EXTRA_DIST = \ BrokenConstants.thrift \ ConstantsDemo.thrift \ DebugProtoTest.thrift \ + DoubleConstantsTest.thrift \ DenseLinkingTest.thrift \ DocTest.thrift \ EnumTest.thrift \ diff --git a/test/cl/Makefile.am b/test/cl/Makefile.am new file mode 100755 index 00000000000..b5e72bcbbb9 --- /dev/null +++ b/test/cl/Makefile.am @@ -0,0 +1,42 @@ +# +# 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. +# + +THRIFT = $(top_builddir)/compiler/cpp/thrift + +stubs: ../ThriftTest.thrift + $(THRIFT) --gen cl ../ThriftTest.thrift + +TestServer: make-test-server.lisp + $(SBCL) --script make-test-server.lisp + +TestClient: make-test-client.lisp + $(SBCL) --script make-test-client.lisp + +precross: stubs TestServer TestClient + +clean-local: + $(RM) -r gen-cl + $(RM) TestServer + $(RM) TestClient + +EXTRA_DIST = \ + implementation.lisp \ + make-test-client.lisp \ + make-test-server.lisp \ + tests.lisp diff --git a/test/cl/implementation.lisp b/test/cl/implementation.lisp new file mode 100644 index 00000000000..0caf7beb565 --- /dev/null +++ b/test/cl/implementation.lisp @@ -0,0 +1,136 @@ +(in-package #:thrift.test-implementation) + +;;;; Licensed 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. + +(defun thrift.test.thrift-test-implementation:test-void () + (format t "testVoid()~%")) + +(defun thrift.test.thrift-test-implementation:test-string (thing) + (format t "testString(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-bool (thing) + (format t "testBool(~a)~%" (if thing "true" "false")) + thing) + +(defun thrift.test.thrift-test-implementation:test-byte (thing) + (format t "testByte(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-i32 (thing) + (format t "testI32(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-i64 (thing) + (format t "testI64(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-double (thing) + (format t "testDouble(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-binary (thing) + (format t "testBinary(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-struct (thing) + (format t "testStruct(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-nest (thing) + (format t "testNest(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-map (thing) + (format t "testMap(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-string-map (thing) + (format t "testStringMap(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-set (thing) + (format t "testSet(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-list (thing) + (format t "testList(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-enum (thing) + (format t "testEnum(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-typedef (thing) + (format t "testTypedef(~a)~%" thing) + thing) + +(defun thrift.test.thrift-test-implementation:test-map-map (hello) + (format t "testMapMap(~a)~%" hello) + '((-4 . ((-4 . -4) (-3 . -3) (-2 . -2) (-1 . -1))) (4 . ((1 . 1) (2 . 2) (3 . 3) (4 . 4))))) + +(defun thrift.test.thrift-test-implementation:test-insanity (argument) + (let ((result `((1 . ((2 . ,argument) (3 . ,argument))) + (2 . ((6 . ,(thrift.test::make-insanity :user-map nil :xtructs nil))))))) + (format t "~a~%" result) + result)) + +(defun thrift.test.thrift-test-implementation:test-multi (arg0 arg1 arg2 arg3 arg4 arg5) + (declare (ignorable arg3 arg4 arg5)) + (format t "testMulti()~%") + (thrift.test:make-xtruct :string-thing "Hello2" + :byte-thing arg0 + :i32-thing arg1 + :i64-thing arg2)) + +(defun thrift.test.thrift-test-implementation:test-exception (arg) + (format t "testException(~a)~%" arg) + (cond + ((string= arg "Xception") (error 'thrift.test:xception + :error-code 1001 + :message arg)) + ((string= arg "TException") (error 'thrift.test:xception + :error-code 0 + :message "Stuff!")))) + +(defun thrift.test.thrift-test-implementation:test-multi-exception (arg0 arg1) + (format t "testMultiException(~a, ~a)~%" arg0 arg1) + (cond + ((string= arg0 "Xception") (error 'thrift.test:xception + :error-code 1001 + :message "This is an Xception")) + ((string= arg0 "Xception2") (error 'thrift.test:xception2 + :error-code 2002 + :struct-thing (thrift.test:make-xtruct :string-thing "This is an Xception2" + :byte-thing 0 + :i32-thing 0 + :i64-thing 0)))) + (thrift.test:make-xtruct :string-thing arg1 + :byte-thing 0 + :i32-thing 0 + :i64-thing 0)) + +(defun thrift.test.thrift-test-implementation:test-oneway (seconds) + (format t "testOneway(~a): Sleeping...~%" seconds) + (sleep seconds) + (format t "testOneway(~a): done sleeping!~%" seconds)) + +;;; Removed from the IDL definition. +#+(or) +(defun thrift.test.second-service-implementation:blah-blah () + (format t "blahBlah()~%")) + +(defun thrift.test.second-service-implementation:secondtest-string (thing) + (format t "secondtestString(~a)~%" thing) + (concatenate 'string "testString(\"" thing "\")")) + diff --git a/test/cl/make-test-client.lisp b/test/cl/make-test-client.lisp new file mode 100644 index 00000000000..509669dd8bf --- /dev/null +++ b/test/cl/make-test-client.lisp @@ -0,0 +1,93 @@ +(in-package #:cl-user) + +;;;; Licensed 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. + +#+(or) (when (not (boundp 'sb-impl::default-external-format) + (setf sb-impl::default-external-format :UTF-8))) + +(require "asdf") +(load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*)) +(asdf:load-system :net.didierverna.clon) +(asdf:load-system :fiasco) +(asdf:load-asd (merge-pathnames "gen-cl/ThriftTest/thrift-gen-ThriftTest.asd" *load-truename*)) +(asdf:load-system :thrift-gen-thrifttest) + +(net.didierverna.clon:nickname-package) + +(defpackage #:thrift-cross + (:use #:common-lisp #:fiasco) + (:export #:cross-test)) + +(in-package #:thrift-cross) + +(defparameter *prot* nil) + +(load (merge-pathnames "tests.lisp" *load-truename*) :external-format :UTF-8) + +(clon:defsynopsis () + (text :contents "The Common Lisp client for Thrift's cross-language test suite.") + (group (:header "Allowed options:") + (flag :short-name "h" :long-name "help" + :description "Print this help and exit.") + (stropt :long-name "host" + :description "The host to connect to." + :default-value "localhost" + :argument-name "ARG") + (stropt :long-name "port" + :description "Number of the port to listen for connections on." + :default-value "9090" + :argument-name "ARG" + :argument-type :optional) + (stropt :long-name "transport" + :description "Transport: transport to use (\"buffered\", \"framed\")" + :default-value "buffered" + :argument-name "ARG") + (stropt :long-name "protocol" + :description "Protocol: protocol to use (\"binary\", \"multi\")" + :default-value "binary" + :argument-name "ARG"))) + +(defun main () + "Entry point for our standalone application." + (clon:make-context) + (when (clon:getopt :short-name "h") + (clon:help) + (clon:exit)) + (let ((port "9090") + (host "localhost") + (framed nil) + (multiplexed nil)) + (clon:do-cmdline-options (option name value source) + (print (list option name value source)) + (if (string= name "host") + (setf host value)) + (if (string= name "port") + (setf port value)) + (if (string= name "transport") + (cond ((string= value "buffered") (setf framed nil)) + ((string= value "framed") (setf framed t)) + (t (error "Unsupported transport.")))) + (if (string= name "protocol") + (cond ((string= value "binary") (setf multiplexed nil)) + ((string= value "multi") (setf multiplexed t)) + (t (error "Unsupported protocol."))))) + (terpri) + (setf *prot* (thrift.implementation::client (puri:parse-uri + (concatenate 'string "thrift://" host ":" port)) + :framed framed + :multiplexed multiplexed)) + (let ((result (cross-test :multiplexed multiplexed))) + (thrift.implementation::close *prot*) + (clon:exit result)))) + +(clon:dump "TestClient" main) diff --git a/test/cl/make-test-server.lisp b/test/cl/make-test-server.lisp new file mode 100644 index 00000000000..293c8792869 --- /dev/null +++ b/test/cl/make-test-server.lisp @@ -0,0 +1,80 @@ +(in-package #:cl-user) + +;;;; Licensed 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. + +(require "asdf") +(load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*)) +(asdf:load-system :net.didierverna.clon) +(asdf:load-asd (merge-pathnames "gen-cl/ThriftTest/thrift-gen-ThriftTest.asd" *load-truename*)) +(asdf:load-system :thrift-gen-thrifttest) +(load (merge-pathnames "implementation.lisp" *load-truename*)) + +(net.didierverna.clon:nickname-package) + +(clon:defsynopsis () + (text :contents "The Common Lisp server for Thrift's cross-language test suite.") + (group (:header "Allowed options:") + (flag :short-name "h" :long-name "help" + :description "Print this help and exit.") + (stropt :long-name "port" + :description "Number of the port to listen for connections on." + :default-value "9090" + :argument-name "ARG" + :argument-type :optional) + (stropt :long-name "server-type" + :description "The type of server, currently only \"simple\" is available." + :default-value "simple" + :argument-name "ARG") + (stropt :long-name "transport" + :description "Transport: transport to use (\"buffered\" or \"framed\")" + :default-value "buffered" + :argument-name "ARG") + (stropt :long-name "protocol" + :description "Protocol: protocol to use (\"binary\" or \"multi\")" + :default-value "binary" + :argument-name "ARG"))) + +(defun main () + "Entry point for our standalone application." + (clon:make-context) + (when (clon:getopt :short-name "h") + (clon:help) + (clon:exit)) + (let ((port "9090") + (framed nil) + (multiplexed nil)) + (clon:do-cmdline-options (option name value source) + (print (list option name value source)) + (if (string= name "port") + (setf port value)) + (if (string= name "transport") + (cond ((string= value "buffered") (setf framed nil)) + ((string= value "framed") (setf framed t)) + (t (error "Unsupported transport.")))) + (if (string= name "protocol") + (cond ((string= value "binary") (setf multiplexed nil)) + ((string= value "multi") (setf multiplexed t)) + (t (error "Unsupported protocol."))))) + (terpri) + (let ((services (if multiplexed + (list thrift.test:thrift-test thrift.test:second-service) + thrift.test:thrift-test))) + (thrift:serve (puri:parse-uri (concatenate 'string + "thrift://127.0.0.1:" + port)) + services + :framed framed + :multiplexed multiplexed))) + (clon:exit)) + +(clon:dump "TestServer" main) diff --git a/test/cl/tests.lisp b/test/cl/tests.lisp new file mode 100644 index 00000000000..c5035fd98b2 --- /dev/null +++ b/test/cl/tests.lisp @@ -0,0 +1,240 @@ +(in-package #:thrift-cross) + +;;;; Licensed 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. + +;;;; The tests here only make sense in the context of a TestServer +;;;; running and the dynamic variable thrift-cross::*prot* +;;;; being set with a client connection to the TestServer. Normally, +;;;; this is handled in make-test-client.lisp. + + +;;; Standard Thrift cross-test error codes +(defparameter *test_basetypes* 1) +(defparameter *test_structs* 2) +(defparameter *test_containers* 4) +(defparameter *test_exceptions* 8) +(defparameter *test_unknown* 64) +(defparameter *test_timeout* 128) + +(defun cross-test (&key (multiplexed nil)) + "The main cross-test runner." + (let ((result nil)) + (handler-case + (progn + (unless (run-package-tests :package :base-types) + (pushnew *test_basetypes* result)) + (unless (run-package-tests :package :structs) + (pushnew *test_structs* result)) + (unless (run-package-tests :package :containers) + (pushnew *test_containers* result)) + (unless (run-package-tests :package :exceptions) + (pushnew *test_exceptions* result)) + (unless (run-package-tests :package :misc) + (pushnew *test_unknown* result)) + + ;; It doesn't seem like anyone actually uses + ;; the second test service when testing multiplexing, + ;; so this would fail against servers in other + ;; languages. For now, anyway. + #+(or) + (when multiplexed + (unless (run-package-tests :package :multiplex) + (pushnew *test_unknown* result)))) + (error (e) (pushnew *test_unknown* result))) + (apply #'+ result))) + +(fiasco:define-test-package #:base-types) + +(in-package #:base-types) + +(defconstant *lang-string* "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語") + +(defparameter *trick-string* (format nil "quote: \" backslash: \\ newline: ~% backspace: ~C ~ + tab: ~T junk: !@#$%&()(&%$#{}{}<><><" #\backspace)) + +(defconstant *binary-sequence* #(128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127)) + +(deftest void-test () + (is (null (thrift.test.thrift-test:test-void thrift-cross::*prot*)))) + +(deftest boolean-test () + (is (thrift.test.thrift-test:test-bool thrift-cross::*prot* t)) + (is (not (thrift.test.thrift-test:test-bool thrift-cross::*prot* nil)))) + +(deftest integer-test () + (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 127) 127)) + (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* -128) -128)) + (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 42) 42)) + (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 0) 0)) + (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* 0) 0)) + (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* 2147483647) 2147483647)) + (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* -2147483648) -2147483648)) + (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* 0) 0)) + (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* 9223372036854775807) 9223372036854775807)) + (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* -9223372036854775808) -9223372036854775808))) + +(deftest double-test () + (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* 0.0) 0)) + (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* 42.0) 42)) + (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* -555.0) -555)) + (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* -52.3678) -52.3678))) + +(deftest string-test () + (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* "") "")) + (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* "(defun botsbuildbots () (botsbuilsbots))") + "(defun botsbuildbots () (botsbuilsbots))")) + (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* *lang-string*) *lang-string*)) + (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* *trick-string*) *trick-string*))) + +(deftest binary-test () + (is (equalp (thrift.test.thrift-test:test-binary thrift-cross::*prot* #()) #())) + (is (equalp (thrift.test.thrift-test:test-binary thrift-cross::*prot* *binary-sequence*) *binary-sequence*))) + +(deftest enum-test () + (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.five) thrift.test:numberz.five)) + (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.eight) thrift.test:numberz.eight)) + (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.one) thrift.test:numberz.one))) + +(deftest typedef-test () + (is (= (thrift.test.thrift-test:test-typedef thrift-cross::*prot* 309858235082523) 309858235082523))) + +(fiasco:define-test-package #:structs) + +(in-package #:structs) + +(defparameter *test-struct* (thrift.test:make-xtruct :string-thing "Hell is empty." + :byte-thing -2 + :i32-thing 42 + :i64-thing 42424242)) + +(defparameter *test-nest* (thrift.test:make-xtruct2 :byte-thing 42 + :struct-thing *test-struct* + :i32-thing -42)) + +(deftest struct-test () + (let ((rec-struct (thrift.test.thrift-test:test-struct thrift-cross::*prot* *test-struct*))) + (is (string= (thrift.test:xtruct-string-thing *test-struct*) + (thrift.test:xtruct-string-thing rec-struct))) + (is (= (thrift.test:xtruct-byte-thing *test-struct*) + (thrift.test:xtruct-byte-thing rec-struct))) + (is (= (thrift.test:xtruct-i32-thing *test-struct*) + (thrift.test:xtruct-i32-thing rec-struct))) + (is (= (thrift.test:xtruct-i64-thing *test-struct*) + (thrift.test:xtruct-i64-thing rec-struct))))) + +(deftest nest-test () + (let* ((rec-nest (thrift.test.thrift-test:test-nest thrift-cross::*prot* *test-nest*)) + (rec-struct (thrift.test:xtruct2-struct-thing rec-nest))) + (is (string= (thrift.test:xtruct-string-thing *test-struct*) + (thrift.test:xtruct-string-thing rec-struct))) + (is (= (thrift.test:xtruct-byte-thing *test-struct*) + (thrift.test:xtruct-byte-thing rec-struct))) + (is (= (thrift.test:xtruct-i32-thing *test-struct*) + (thrift.test:xtruct-i32-thing rec-struct))) + (is (= (thrift.test:xtruct-i64-thing *test-struct*) + (thrift.test:xtruct-i64-thing rec-struct))) + (is (= (thrift.test:xtruct2-byte-thing *test-nest*) + (thrift.test:xtruct2-byte-thing rec-nest))) + (is (= (thrift.test:xtruct2-i32-thing *test-nest*) + (thrift.test:xtruct2-i32-thing rec-nest))))) + +(fiasco:define-test-package #:containers) + +(in-package #:containers) + +(deftest list-test () + (is (null (thrift.test.thrift-test:test-list thrift-cross::*prot* nil))) + (is (equal (thrift.test.thrift-test:test-list thrift-cross::*prot* '(42 -42 0 5)) '(42 -42 0 5)))) + +(deftest set-test () + (is (null (thrift.test.thrift-test:test-set thrift-cross::*prot* nil))) + (is (equal (sort (thrift.test.thrift-test:test-set thrift-cross::*prot* (list 42 -42 0 5)) #'<) + '(-42 0 5 42)))) + +(defun map= (map1 map2 &key (car-predicate #'equal) (cdr-predicate #'equal)) + "Compare two assoc maps according to the predicates given." + (not (set-exclusive-or map1 map2 :test (lambda (el1 el2) + (and (funcall car-predicate + (car el1) + (car el2)) + (funcall cdr-predicate + (cdr el1) + (cdr el2))))))) + +(deftest map-test () + (is (null (thrift.test.thrift-test:test-map thrift-cross::*prot* nil))) + (is (map= (thrift.test.thrift-test:test-map thrift-cross::*prot* '((0 . 1) (42 . -42) (5 . 5))) + '((0 . 1) (42 . -42) (5 . 5)))) + (is (map= (thrift.test.thrift-test:test-map-map thrift-cross::*prot* 42) + '((-4 . ((-4 . -4) (-3 . -3) (-2 . -2) (-1 . -1))) + (4 . ((1 . 1) (2 . 2) (3 . 3) (4 . 4)))) + :cdr-predicate #'map=))) + +(fiasco:define-test-package #:exceptions) + +(in-package #:exceptions) + +(defun test-xception (expected-code expected-message function &rest args) + "A helper function to test whether xception is signalled, and whether its fields have the expected values." + (handler-case (progn (apply function args) + nil) + (thrift.test:xception (ex) (and (= (thrift.test::xception-error-code ex) expected-code) + (string= (thrift.test::xception-message ex) expected-message))))) + +(defun test-xception2 (expected-code expected-message function &rest args) + "A helper function to test whether xception2 is signalled, and whether its fields have the expected values." + (handler-case (progn (apply function args) + nil) + (thrift.test:xception2 (ex) (and (= (thrift.test::xception2-error-code ex) expected-code) + (string= (thrift.test::xtruct-string-thing + (thrift.test::xception2-struct-thing ex)) + expected-message))))) + +(deftest exception-test () + (is (test-xception 1001 "Xception" #'thrift.test.thrift-test:test-exception thrift-cross::*prot* "Xception")) + (signals thrift:application-error (thrift.test.thrift-test:test-exception thrift-cross::*prot* "TException")) + (finishes (thrift.test.thrift-test:test-exception thrift-cross::*prot* "success"))) + +(deftest multi-exception-test () + (is (test-xception 1001 + "This is an Xception" + #'thrift.test.thrift-test:test-multi-exception + thrift-cross::*prot* + "Xception" + "meaningless")) + (is (test-xception2 2002 + "This is an Xception2" + #'thrift.test.thrift-test:test-multi-exception + thrift-cross::*prot* + "Xception2" + "meaningless too!")) + (is (string= "foobar" (thrift.test:xtruct-string-thing + (thrift.test.thrift-test:test-multi-exception thrift-cross::*prot* + "success!" + "foobar"))))) + +(fiasco:define-test-package #:misc) + +(in-package #:misc) + +(deftest oneway-test () + (is (null (thrift.test.thrift-test:test-oneway thrift-cross::*prot* 1)))) + +(fiasco:define-test-package #:multiplex) + +(in-package #:multiplex) + +(deftest multiplex-test () + ;; Removed from the IDL definition. + ;; (finishes (thrift.test.second-service:blah-blah thrift-cross::*prot*)) + (is (string= "asd" (thrift.test.second-service:secondtest-string thrift-cross::*prot* "asd")))) diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp index 78b0a742b4f..1c381241027 100644 --- a/test/cpp/src/TestServer.cpp +++ b/test/cpp/src/TestServer.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,9 @@ #ifdef HAVE_INTTYPES_H #include #endif +#ifdef HAVE_SIGNAL_H +#include +#endif #include #include @@ -58,7 +62,6 @@ #include #include -#include #if _WIN32 #include #endif @@ -74,6 +77,17 @@ using namespace apache::thrift::server; using namespace thrift::test; +// to handle a controlled shutdown, signal handling is mandatory +#ifdef HAVE_SIGNAL_H +apache::thrift::concurrency::Monitor gMonitor; +void signal_handler(int signum) +{ + if (signum == SIGINT) { + gMonitor.notifyAll(); + } +} +#endif + class TestHandler : public ThriftTestIf { public: TestHandler() {} @@ -113,7 +127,7 @@ class TestHandler : public ThriftTestIf { void testBinary(std::string& _return, const std::string& thing) { std::ostringstream hexstr; hexstr << std::hex << thing; - printf("testBinary(%lu: %s)\n", thing.size(), hexstr.str().c_str()); + printf("testBinary(%lu: %s)\n", safe_numeric_cast(thing.size()), hexstr.str().c_str()); _return = thing; } @@ -634,6 +648,12 @@ int main(int argc, char** argv) { ssl = true; } +#if defined(HAVE_SIGNAL_H) && defined(SIGPIPE) + if (ssl) { + signal(SIGPIPE, SIG_IGN); // for OpenSSL, otherwise we end abruptly + } +#endif + if (vm.count("abstract-namespace")) { abstract_namespace = true; } @@ -676,7 +696,9 @@ int main(int argc, char** argv) { sslSocketFactory->loadCertificate(certPath.c_str()); sslSocketFactory->loadPrivateKey(keyPath.c_str()); sslSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); - serverSocket = stdcxx::shared_ptr(new TSSLServerSocket(port, sslSocketFactory)); + if (server_type != "nonblocking") { + serverSocket = stdcxx::shared_ptr(new TSSLServerSocket(port, sslSocketFactory)); + } } else { if (domain_socket != "") { if (abstract_namespace) { @@ -738,13 +760,11 @@ int main(int argc, char** argv) { server.reset(new TSimpleServer(testProcessor, serverSocket, transportFactory, protocolFactory)); } else if (server_type == "thread-pool") { - stdcxx::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workers); - stdcxx::shared_ptr threadFactory = stdcxx::shared_ptr(new PlatformThreadFactory()); + stdcxx::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workers); threadManager->threadFactory(threadFactory); - threadManager->start(); server.reset(new TThreadPoolServer(testProcessor, @@ -753,7 +773,6 @@ int main(int argc, char** argv) { protocolFactory, threadManager)); } else if (server_type == "threaded") { - server.reset( new TThreadedServer(testProcessor, serverSocket, transportFactory, protocolFactory)); } else if (server_type == "nonblocking") { @@ -769,10 +788,15 @@ int main(int argc, char** argv) { // provide a stop method. TEvhttpServer nonblockingServer(testBufferProcessor, port); nonblockingServer.serve(); - } else { - stdcxx::shared_ptr nbSocket; - nbSocket.reset(new transport::TNonblockingServerSocket(port)); + } else if (transport_type == "framed") { + stdcxx::shared_ptr nbSocket; + nbSocket.reset( + ssl ? new transport::TNonblockingSSLServerSocket(port, sslSocketFactory) + : new transport::TNonblockingServerSocket(port)); server.reset(new TNonblockingServer(testProcessor, protocolFactory, nbSocket)); + } else { + cerr << "server-type nonblocking requires transport of http or framed" << endl; + exit(1); } } @@ -782,20 +806,23 @@ int main(int argc, char** argv) { // if using header server->setOutputProtocolFactory(stdcxx::shared_ptr()); } + apache::thrift::concurrency::PlatformThreadFactory factory; factory.setDetached(false); stdcxx::shared_ptr serverThreadRunner(server); stdcxx::shared_ptr thread = factory.newThread(serverThreadRunner); - thread->start(); - // HACK: cross language test suite is unable to handle cin properly - // that's why we stay in a endless loop here - while (1) { - } - // FIXME: find another way to stop the server (e.g. a signal) - // cout<<"Press enter to stop the server."<start(); + gMonitor.waitForever(); // wait for a shutdown signal + +#ifdef HAVE_SIGNAL_H + signal(SIGINT, SIG_DFL); +#endif server->stop(); thread->join(); @@ -805,3 +832,4 @@ int main(int argc, char** argv) { cout << "done." << endl; return 0; } + diff --git a/test/crossrunner/collect.py b/test/crossrunner/collect.py index 03b0c36c994..e2d89782800 100644 --- a/test/crossrunner/collect.py +++ b/test/crossrunner/collect.py @@ -51,6 +51,7 @@ ] DEFAULT_MAX_DELAY = 5 +DEFAULT_SIGNAL = 1 DEFAULT_TIMEOUT = 5 @@ -112,7 +113,7 @@ def to_spec_impl_tuples(values): yield name, impl1, impl2 def maybe_max(key, o1, o2, default): - """maximum of two if present, otherwise defult value""" + """maximum of two if present, otherwise default value""" v1 = o1.get(key) v2 = o2.get(key) return max(v1, v2) if v1 and v2 else v1 or v2 or default @@ -138,6 +139,7 @@ def merge_metadata(o, **ret): 'server': merge_metadata(sv, **{'protocol': proto1, 'transport': trans1}), 'client': merge_metadata(cl, **{'protocol': proto2, 'transport': trans2}), 'delay': maybe_max('delay', sv, cl, DEFAULT_MAX_DELAY), + 'stop_signal': maybe_max('stop_signal', sv, cl, DEFAULT_SIGNAL), 'timeout': maybe_max('timeout', sv, cl, DEFAULT_TIMEOUT), 'protocol': proto, 'transport': trans, diff --git a/test/crossrunner/report.py b/test/crossrunner/report.py index 76324ede114..75f36db75f5 100644 --- a/test/crossrunner/report.py +++ b/test/crossrunner/report.py @@ -157,8 +157,10 @@ def died(self): ])), 'client': list(map(re.compile, [ '[Cc]onnection refused', - 'Could not connect to localhost', + 'Could not connect to', 'ECONNREFUSED', + 'econnrefused', # erl + 'CONNECTION-REFUSED-ERROR', # cl 'No such file or directory', # domain socket ])), } @@ -174,6 +176,7 @@ def maybe_false_positive(self): def match(line): for expr in exprs: if expr.search(line): + self._log.info("maybe false positive: %s" % line) return True with logfile_open(self.logpath, 'r') as fp: @@ -204,7 +207,7 @@ def _print_header(self): def _print_footer(self, returncode=None): self._print_bar() if returncode is not None: - print('Return code: %d' % returncode, file=self.out) + print('Return code: %d (negative values indicate kill by signal)' % returncode, file=self.out) else: print('Process is killed.', file=self.out) self._print_exec_time() @@ -261,7 +264,8 @@ def _format_test(self, test, with_result=True): if not with_result: return '{:24s}{:18s}{:25s}'.format(name[:23], test.protocol[:17], trans[:24]) else: - return '{:24s}{:18s}{:25s}{:s}\n'.format(name[:23], test.protocol[:17], trans[:24], self._result_string(test)) + return '{:24s}{:18s}{:25s}{:s}\n'.format(name[:23], test.protocol[:17], + trans[:24], self._result_string(test)) def _print_test_header(self): self._print_bar() diff --git a/test/crossrunner/run.py b/test/crossrunner/run.py index f522bb19e67..25c58cef3ec 100644 --- a/test/crossrunner/run.py +++ b/test/crossrunner/run.py @@ -23,19 +23,20 @@ import os import platform import random -import signal import socket import subprocess import sys -import threading import time from .compat import str_join -from .test import TestEntry, domain_socket_path from .report import ExecReporter, SummaryReporter +from .test import TestEntry +from .util import domain_socket_path -RESULT_TIMEOUT = 128 RESULT_ERROR = 64 +RESULT_TIMEOUT = 128 +SIGNONE = 0 +SIGKILL = 15 # globals ports = None @@ -43,35 +44,18 @@ class ExecutionContext(object): - def __init__(self, cmd, cwd, env, report): + def __init__(self, cmd, cwd, env, stop_signal, is_server, report): self._log = multiprocessing.get_logger() - self.report = report self.cmd = cmd self.cwd = cwd self.env = env - self.timer = None + self.stop_signal = stop_signal + self.is_server = is_server + self.report = report self.expired = False self.killed = False self.proc = None - def _expire(self): - self._log.info('Timeout') - self.expired = True - self.kill() - - def kill(self): - self._log.debug('Killing process : %d' % self.proc.pid) - self.killed = True - if platform.system() != 'Windows': - try: - os.killpg(self.proc.pid, signal.SIGKILL) - except Exception: - self._log.info('Failed to kill process group', exc_info=sys.exc_info()) - try: - self.proc.kill() - except Exception: - self._log.info('Failed to kill process', exc_info=sys.exc_info()) - def _popen_args(self): args = { 'cwd': self.cwd, @@ -87,75 +71,125 @@ def _popen_args(self): args.update(preexec_fn=os.setsid) return args - def start(self, timeout=0): + def start(self): joined = str_join(' ', self.cmd) self._log.debug('COMMAND: %s', joined) self._log.debug('WORKDIR: %s', self.cwd) self._log.debug('LOGFILE: %s', self.report.logpath) self.report.begin() self.proc = subprocess.Popen(self.cmd, **self._popen_args()) - if timeout > 0: - self.timer = threading.Timer(timeout, self._expire) - self.timer.start() + self._log.debug(' PID: %d', self.proc.pid) + self._log.debug(' PGID: %d', os.getpgid(self.proc.pid)) return self._scoped() @contextlib.contextmanager def _scoped(self): yield self - self._log.debug('Killing scoped process') - if self.proc.poll() is None: - self.kill() - self.report.killed() + if self.is_server: + # the server is supposed to run until we stop it + if self.returncode is not None: + self.report.died() + else: + if self.stop_signal != SIGNONE: + if self.sigwait(self.stop_signal): + self.report.end(self.returncode) + else: + self.report.killed() + else: + self.sigwait(SIGKILL) else: - self._log.debug('Process died unexpectedly') - self.report.died() - - def wait(self): - self.proc.communicate() - if self.timer: - self.timer.cancel() - self.report.end(self.returncode) + # the client is supposed to exit normally + if self.returncode is not None: + self.report.end(self.returncode) + else: + self.sigwait(SIGKILL) + self.report.killed() + self._log.debug('[{0}] exited with return code {1}'.format(self.proc.pid, self.returncode)) + + # Send a signal to the process and then wait for it to end + # If the signal requested is SIGNONE, no signal is sent, and + # instead we just wait for the process to end; further if it + # does not end normally with SIGNONE, we mark it as expired. + # If the process fails to end and the signal is not SIGKILL, + # it re-runs with SIGKILL so that a real process kill occurs + # returns True if the process ended, False if it may not have + def sigwait(self, sig=SIGKILL, timeout=2): + try: + if sig != SIGNONE: + self._log.debug('[{0}] send signal {1}'.format(self.proc.pid, sig)) + if sig == SIGKILL: + self.killed = True + try: + if platform.system() != 'Windows': + os.killpg(os.getpgid(self.proc.pid), sig) + else: + self.proc.send_signal(sig) + except Exception: + self._log.info('[{0}] Failed to kill process'.format(self.proc.pid), exc_info=sys.exc_info()) + self._log.debug('[{0}] wait begin, timeout {1} sec(s)'.format(self.proc.pid, timeout)) + self.proc.communicate(timeout=timeout) + self._log.debug('[{0}] process ended with return code {1}'.format(self.proc.pid, self.returncode)) + self.report.end(self.returncode) + return True + except subprocess.TimeoutExpired: + self._log.info('[{0}] timeout waiting for process to end'.format(self.proc.pid)) + if sig == SIGNONE: + self.expired = True + return False if sig == SIGKILL else self.sigwait(SIGKILL, 1) + + # called on the client process to wait for it to end naturally + def wait(self, timeout): + self.sigwait(SIGNONE, timeout) @property def returncode(self): return self.proc.returncode if self.proc else None -def exec_context(port, logdir, test, prog): +def exec_context(port, logdir, test, prog, is_server): report = ExecReporter(logdir, test, prog) prog.build_command(port) - return ExecutionContext(prog.command, prog.workdir, prog.env, report) + return ExecutionContext(prog.command, prog.workdir, prog.env, prog.stop_signal, is_server, report) def run_test(testdir, logdir, test_dict, max_retry, async=True): logger = multiprocessing.get_logger() - def ensure_socket_open(proc, port, max_delay): - sleeped = 0.1 - time.sleep(sleeped) - sleep_step = 0.2 + def ensure_socket_open(sv, port, test): + slept = 0.1 + time.sleep(slept) + sleep_step = 0.1 while True: - # Create sockets every iteration because refused sockets cannot be - # reused on some systems. - sock4 = socket.socket() - sock6 = socket.socket(family=socket.AF_INET6) - try: - if sock4.connect_ex(('127.0.0.1', port)) == 0 \ - or sock6.connect_ex(('::1', port)) == 0: - return True - if proc.poll() is not None: - logger.warn('server process is exited') - return False - if sleeped > max_delay: - logger.warn('sleeped for %f seconds but server port is not open' % sleeped) - return False - time.sleep(sleep_step) - sleeped += sleep_step - finally: - sock4.close() - sock6.close() - logger.debug('waited %f sec for server port open' % sleeped) - return True + if slept > test.delay: + logger.warn('[{0}] slept for {1} seconds but server is not open'.format(sv.proc.pid, slept)) + return False + if test.socket == 'domain': + if not os.path.exists(domain_socket_path(port)): + logger.debug('[{0}] domain(unix) socket not available yet. slept for {1} seconds so far'.format(sv.proc.pid, slept)) + time.sleep(sleep_step) + slept += sleep_step + elif test.socket == 'abstract': + return True + else: + # Create sockets every iteration because refused sockets cannot be + # reused on some systems. + sock4 = socket.socket() + sock6 = socket.socket(family=socket.AF_INET6) + try: + if sock4.connect_ex(('127.0.0.1', port)) == 0 \ + or sock6.connect_ex(('::1', port)) == 0: + return True + if sv.proc.poll() is not None: + logger.warn('[{0}] server process is exited'.format(sv.proc.pid)) + return False + logger.debug('[{0}] socket not available yet. slept for {1} seconds so far'.format(sv.proc.pid, slept)) + time.sleep(sleep_step) + slept += sleep_step + finally: + sock4.close() + sock6.close() + logger.debug('[{0}] server ready - waited for {1} seconds'.format(sv.proc.pid, slept)) + return True try: max_bind_retry = 3 @@ -169,31 +203,27 @@ def ensure_socket_open(proc, port, max_delay): logger.debug('Start') with PortAllocator.alloc_port_scoped(ports, test.socket) as port: logger.debug('Start with port %d' % port) - sv = exec_context(port, logdir, test, test.server) - cl = exec_context(port, logdir, test, test.client) + sv = exec_context(port, logdir, test, test.server, True) + cl = exec_context(port, logdir, test, test.client, False) logger.debug('Starting server') with sv.start(): - if test.socket in ('domain', 'abstract'): - time.sleep(0.1) - port_ok = True - else: - port_ok = ensure_socket_open(sv.proc, port, test.delay) + port_ok = ensure_socket_open(sv, port, test) if port_ok: connect_retry_count = 0 - max_connect_retry = 3 - connect_retry_wait = 0.5 + max_connect_retry = 12 + connect_retry_wait = 0.25 while True: if sv.proc.poll() is not None: logger.info('not starting client because server process is absent') break logger.debug('Starting client') - cl.start(test.timeout) - logger.debug('Waiting client') - cl.wait() + cl.start() + logger.debug('Waiting client (up to %d secs)' % test.timeout) + cl.wait(test.timeout) if not cl.report.maybe_false_positive() or connect_retry_count >= max_connect_retry: if connect_retry_count > 0 and connect_retry_count < max_connect_retry: - logger.warn('[%s]: Connected after %d retry (%.2f sec each)' % (test.server.name, connect_retry_count, connect_retry_wait)) + logger.info('[%s]: Connected after %d retry (%.2f sec each)' % (test.server.name, connect_retry_count, connect_retry_wait)) # Wait for 50ms to see if server does not die at the end. time.sleep(0.05) break @@ -205,12 +235,18 @@ def ensure_socket_open(proc, port, max_delay): logger.warn('[%s]: Detected socket bind failure, retrying...', test.server.name) bind_retry_count += 1 else: - if cl.expired: - result = RESULT_TIMEOUT + result = RESULT_TIMEOUT if cl.expired else cl.returncode if cl.proc.poll() is not None else RESULT_ERROR + + # For servers that handle a controlled shutdown by signal + # if they are killed, or return an error code, that is a + # problem. For servers that are not signal-aware, we simply + # kill them off; if we didn't kill them off, something else + # happened (crashed?) + if test.server.stop_signal != 0: + if sv.killed or sv.returncode > 0: + result |= RESULT_ERROR else: - result = cl.proc.returncode if cl.proc else RESULT_ERROR if not sv.killed: - # Server died without being killed. result |= RESULT_ERROR if result == 0 or retry_count >= max_retry: diff --git a/test/crossrunner/test.py b/test/crossrunner/test.py index 74fd916ec74..633e9261691 100644 --- a/test/crossrunner/test.py +++ b/test/crossrunner/test.py @@ -22,22 +22,20 @@ import os import sys from .compat import path_join -from .util import merge_dict - - -def domain_socket_path(port): - return '/tmp/ThriftTest.thrift.%d' % port +from .util import merge_dict, domain_socket_path class TestProgram(object): - def __init__(self, kind, name, protocol, transport, socket, workdir, command, env=None, + def __init__(self, kind, name, protocol, transport, socket, workdir, stop_signal, command, env=None, extra_args=[], extra_args2=[], join_args=False, **kwargs): + self.kind = kind self.name = name self.protocol = protocol self.transport = transport self.socket = socket self.workdir = workdir + self.stop_signal = stop_signal self.command = None self._base_command = self._fix_cmd_path(command) if env: diff --git a/test/crossrunner/util.py b/test/crossrunner/util.py index e2d195a2250..c214df85a52 100644 --- a/test/crossrunner/util.py +++ b/test/crossrunner/util.py @@ -20,6 +20,10 @@ import copy +def domain_socket_path(port): + return '/tmp/ThriftTest.thrift.%d' % port + + def merge_dict(base, update): """Update dict concatenating list values""" res = copy.deepcopy(base) diff --git a/test/features/known_failures_Linux.json b/test/features/known_failures_Linux.json index 6d1ed1f8aff..83769682f5f 100644 --- a/test/features/known_failures_Linux.json +++ b/test/features/known_failures_Linux.json @@ -1,6 +1,8 @@ [ "c_glib-limit_container_length_binary_buffered-ip", "c_glib-limit_string_length_binary_buffered-ip", + "cl-limit_string_length_binary_buffered-ip", + "cl-limit_container_length_binary_buffered-ip", "cpp-theader_framed_binary_multih-header_buffered-ip", "cpp-theader_framed_compact_multih-header_buffered-ip", "cpp-theader_unframed_binary_multih-header_buffered-ip", @@ -45,4 +47,4 @@ "rs-limit_string_length_multic-compact_buffered-ip", "netcore-limit_string_length_compact_buffered-ip", "netcore-limit_container_length_compact_buffered-ip" -] \ No newline at end of file +] diff --git a/test/go/Makefile.am b/test/go/Makefile.am index 6bc97f582c5..6da83394bea 100644 --- a/test/go/Makefile.am +++ b/test/go/Makefile.am @@ -18,9 +18,6 @@ # BUILT_SOURCES = gopath -if GOVERSION_LT_17 -COMPILER_EXTRAFLAG=",legacy_context" -endif THRIFTCMD = $(THRIFT) -out src/gen --gen go:thrift_import=thrift$(COMPILER_EXTRAFLAG) THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift @@ -37,7 +34,6 @@ gopath: $(THRIFT) ThriftTest.thrift mkdir -p src/gen $(THRIFTCMD) ThriftTest.thrift $(THRIFTCMD) ../StressTest.thrift - GOPATH=`pwd` $(GO) get golang.org/x/net/context GOPATH=`pwd` $(GO) get github.com/golang/mock/gomock || true sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' src/github.com/golang/mock/gomock/controller.go || true GOPATH=`pwd` $(GO) get github.com/golang/mock/gomock diff --git a/test/go/src/bin/stress/go17.go b/test/go/src/bin/stress/go17.go deleted file mode 100644 index 81f1ad8ee6b..00000000000 --- a/test/go/src/bin/stress/go17.go +++ /dev/null @@ -1,62 +0,0 @@ -// +build go1.7 - -/* - * 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 main - -import ( - "context" - "sync/atomic" -) - -type handler struct{} - -func (h *handler) EchoVoid(ctx context.Context) (err error) { - atomic.AddInt64(&counter, 1) - return nil -} -func (h *handler) EchoByte(ctx context.Context, arg int8) (r int8, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoI32(ctx context.Context, arg int32) (r int32, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoI64(ctx context.Context, arg int64) (r int64, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoString(ctx context.Context, arg string) (r string, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoList(ctx context.Context, arg []int8) (r []int8, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoSet(ctx context.Context, arg map[int8]struct{}) (r map[int8]struct{}, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoMap(ctx context.Context, arg map[int8]int8) (r map[int8]int8, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} diff --git a/test/go/src/bin/stress/main.go b/test/go/src/bin/stress/main.go index e8e6b2a2072..f2e0f20730d 100644 --- a/test/go/src/bin/stress/main.go +++ b/test/go/src/bin/stress/main.go @@ -20,6 +20,7 @@ package main import ( + "context" "flag" "fmt" "gen/stress" @@ -216,3 +217,38 @@ func client(protocolFactory thrift.TProtocolFactory) { done.Done() } + +type handler struct{} + +func (h *handler) EchoVoid(ctx context.Context) (err error) { + atomic.AddInt64(&counter, 1) + return nil +} +func (h *handler) EchoByte(ctx context.Context, arg int8) (r int8, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoI32(ctx context.Context, arg int32) (r int32, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoI64(ctx context.Context, arg int64) (r int64, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoString(ctx context.Context, arg string) (r string, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoList(ctx context.Context, arg []int8) (r []int8, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoSet(ctx context.Context, arg map[int8]struct{}) (r map[int8]struct{}, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} +func (h *handler) EchoMap(ctx context.Context, arg map[int8]int8) (r map[int8]int8, err error) { + atomic.AddInt64(&counter, 1) + return arg, nil +} diff --git a/test/go/src/bin/stress/pre_go17.go b/test/go/src/bin/stress/pre_go17.go deleted file mode 100644 index 07ae5c6a282..00000000000 --- a/test/go/src/bin/stress/pre_go17.go +++ /dev/null @@ -1,63 +0,0 @@ -// +build !go1.7 - -/* - * 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 main - -import ( - "sync/atomic" - - "golang.org/x/net/context" -) - -type handler struct{} - -func (h *handler) EchoVoid(ctx context.Context) (err error) { - atomic.AddInt64(&counter, 1) - return nil -} -func (h *handler) EchoByte(ctx context.Context, arg int8) (r int8, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoI32(ctx context.Context, arg int32) (r int32, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoI64(ctx context.Context, arg int64) (r int64, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoString(ctx context.Context, arg string) (r string, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoList(ctx context.Context, arg []int8) (r []int8, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoSet(ctx context.Context, arg map[int8]struct{}) (r map[int8]struct{}, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} -func (h *handler) EchoMap(ctx context.Context, arg map[int8]int8) (r map[int8]int8, err error) { - atomic.AddInt64(&counter, 1) - return arg, nil -} diff --git a/test/go/src/bin/testclient/go17.go b/test/go/src/bin/testclient/go17.go deleted file mode 100644 index a6003a9174f..00000000000 --- a/test/go/src/bin/testclient/go17.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build go1.7 - -/* - * 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 main - -import "context" - -var defaultCtx = context.Background() diff --git a/test/go/src/bin/testclient/main.go b/test/go/src/bin/testclient/main.go index ab24cbfc744..20104f9e12e 100644 --- a/test/go/src/bin/testclient/main.go +++ b/test/go/src/bin/testclient/main.go @@ -21,6 +21,7 @@ package main import ( "common" + "context" "flag" "gen/thrifttest" t "log" @@ -60,6 +61,7 @@ var xxs = &thrifttest.Xtruct{ } var xcept = &thrifttest.Xception{ErrorCode: 1001, Message: "Xception"} +var defaultCtx = context.Background() func callEverything(client *thrifttest.ThriftTestClient) { var err error diff --git a/test/go/src/bin/testclient/pre_go17.go b/test/go/src/bin/testclient/pre_go17.go deleted file mode 100644 index 10a6fb8d932..00000000000 --- a/test/go/src/bin/testclient/pre_go17.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build !go1.7 - -/* - * 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 main - -import "golang.org/x/net/context" - -var defaultCtx = context.Background() diff --git a/test/go/src/common/clientserver_test.go b/test/go/src/common/clientserver_test.go index c4cfd44f303..9f93c4c6cc8 100644 --- a/test/go/src/common/clientserver_test.go +++ b/test/go/src/common/clientserver_test.go @@ -20,6 +20,7 @@ package common import ( + "context" "errors" "gen/thrifttest" "reflect" @@ -95,6 +96,7 @@ var xxs = &thrifttest.Xtruct{ } var xcept = &thrifttest.Xception{ErrorCode: 1001, Message: "some"} +var defaultCtx = context.Background() func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, handler *MockThriftTest) { gomock.InOrder( @@ -127,12 +129,12 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h ) var err error if err = client.TestVoid(defaultCtx); err != nil { - t.Errorf("Unexpected error in TestVoid() call: ", err) + t.Errorf("Unexpected error in TestVoid() call: %s", err) } thing, err := client.TestString(defaultCtx, "thing") if err != nil { - t.Errorf("Unexpected error in TestString() call: ", err) + t.Errorf("Unexpected error in TestString() call: %s", err) } if thing != "thing" { t.Errorf("Unexpected TestString() result, expected 'thing' got '%s' ", thing) @@ -140,22 +142,22 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h bl, err := client.TestBool(defaultCtx, true) if err != nil { - t.Errorf("Unexpected error in TestBool() call: ", err) + t.Errorf("Unexpected error in TestBool() call: %s", err) } if !bl { - t.Errorf("Unexpected TestBool() result expected true, got %f ", bl) + t.Errorf("Unexpected TestBool() result expected true, got %v ", bl) } bl, err = client.TestBool(defaultCtx, false) if err != nil { - t.Errorf("Unexpected error in TestBool() call: ", err) + t.Errorf("Unexpected error in TestBool() call: %s", err) } if bl { - t.Errorf("Unexpected TestBool() result expected false, got %f ", bl) + t.Errorf("Unexpected TestBool() result expected false, got %v ", bl) } b, err := client.TestByte(defaultCtx, 42) if err != nil { - t.Errorf("Unexpected error in TestByte() call: ", err) + t.Errorf("Unexpected error in TestByte() call: %s", err) } if b != 42 { t.Errorf("Unexpected TestByte() result expected 42, got %d ", b) @@ -163,7 +165,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h i32, err := client.TestI32(defaultCtx, 4242) if err != nil { - t.Errorf("Unexpected error in TestI32() call: ", err) + t.Errorf("Unexpected error in TestI32() call: %s", err) } if i32 != 4242 { t.Errorf("Unexpected TestI32() result expected 4242, got %d ", i32) @@ -171,7 +173,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h i64, err := client.TestI64(defaultCtx, 424242) if err != nil { - t.Errorf("Unexpected error in TestI64() call: ", err) + t.Errorf("Unexpected error in TestI64() call: %s", err) } if i64 != 424242 { t.Errorf("Unexpected TestI64() result expected 424242, got %d ", i64) @@ -179,7 +181,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h d, err := client.TestDouble(defaultCtx, 42.42) if err != nil { - t.Errorf("Unexpected error in TestDouble() call: ", err) + t.Errorf("Unexpected error in TestDouble() call: %s", err) } if d != 42.42 { t.Errorf("Unexpected TestDouble() result expected 42.42, got %f ", d) @@ -194,7 +196,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h xs.I64Thing = 424242 xsret, err := client.TestStruct(defaultCtx, xs) if err != nil { - t.Errorf("Unexpected error in TestStruct() call: ", err) + t.Errorf("Unexpected error in TestStruct() call: %s", err) } if *xs != *xsret { t.Errorf("Unexpected TestStruct() result expected %#v, got %#v ", xs, xsret) @@ -204,7 +206,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h x2.StructThing = xs x2ret, err := client.TestNest(defaultCtx, x2) if err != nil { - t.Errorf("Unexpected error in TestNest() call: ", err) + t.Errorf("Unexpected error in TestNest() call: %s", err) } if !reflect.DeepEqual(x2, x2ret) { t.Errorf("Unexpected TestNest() result expected %#v, got %#v ", x2, x2ret) @@ -213,7 +215,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h m := map[int32]int32{1: 2, 3: 4, 5: 42} mret, err := client.TestMap(defaultCtx, m) if err != nil { - t.Errorf("Unexpected error in TestMap() call: ", err) + t.Errorf("Unexpected error in TestMap() call: %s", err) } if !reflect.DeepEqual(m, mret) { t.Errorf("Unexpected TestMap() result expected %#v, got %#v ", m, mret) @@ -222,7 +224,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h sm := map[string]string{"a": "2", "b": "blah", "some": "thing"} smret, err := client.TestStringMap(defaultCtx, sm) if err != nil { - t.Errorf("Unexpected error in TestStringMap() call: ", err) + t.Errorf("Unexpected error in TestStringMap() call: %s", err) } if !reflect.DeepEqual(sm, smret) { t.Errorf("Unexpected TestStringMap() result expected %#v, got %#v ", sm, smret) @@ -231,7 +233,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h s := []int32{1, 2, 42} sret, err := client.TestSet(defaultCtx, s) if err != nil { - t.Errorf("Unexpected error in TestSet() call: ", err) + t.Errorf("Unexpected error in TestSet() call: %s", err) } // Sets can be in any order, but Go slices are ordered, so reflect.DeepEqual won't work. stemp := map[int32]struct{}{} @@ -247,7 +249,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h l := []int32{1, 2, 42} lret, err := client.TestList(defaultCtx, l) if err != nil { - t.Errorf("Unexpected error in TestList() call: ", err) + t.Errorf("Unexpected error in TestList() call: %s", err) } if !reflect.DeepEqual(l, lret) { t.Errorf("Unexpected TestList() result expected %#v, got %#v ", l, lret) @@ -255,7 +257,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h eret, err := client.TestEnum(defaultCtx, thrifttest.Numberz_TWO) if err != nil { - t.Errorf("Unexpected error in TestEnum() call: ", err) + t.Errorf("Unexpected error in TestEnum() call: %s", err) } if eret != thrifttest.Numberz_TWO { t.Errorf("Unexpected TestEnum() result expected %#v, got %#v ", thrifttest.Numberz_TWO, eret) @@ -263,7 +265,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h tret, err := client.TestTypedef(defaultCtx, thrifttest.UserId(42)) if err != nil { - t.Errorf("Unexpected error in TestTypedef() call: ", err) + t.Errorf("Unexpected error in TestTypedef() call: %s", err) } if tret != thrifttest.UserId(42) { t.Errorf("Unexpected TestTypedef() result expected %#v, got %#v ", thrifttest.UserId(42), tret) @@ -271,7 +273,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h mapmap, err := client.TestMapMap(defaultCtx, 42) if err != nil { - t.Errorf("Unexpected error in TestMapmap() call: ", err) + t.Errorf("Unexpected error in TestMapmap() call: %s", err) } if !reflect.DeepEqual(mapmap, rmapmap) { t.Errorf("Unexpected TestMapmap() result expected %#v, got %#v ", rmapmap, mapmap) @@ -279,7 +281,7 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h xxsret, err := client.TestMulti(defaultCtx, 42, 4242, 424242, map[int16]string{1: "blah", 2: "thing"}, thrifttest.Numberz_EIGHT, thrifttest.UserId(24)) if err != nil { - t.Errorf("Unexpected error in TestMulti() call: %v", err) + t.Errorf("Unexpected error in TestMulti() call: %s", err) } if !reflect.DeepEqual(xxs, xxsret) { t.Errorf("Unexpected TestMulti() result expected %#v, got %#v ", xxs, xxsret) @@ -323,11 +325,11 @@ func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, h err = client.TestOneway(defaultCtx, 2) if err != nil { - t.Errorf("Unexpected error in TestOneway() call: ", err) + t.Errorf("Unexpected error in TestOneway() call: %s", err) } //Make sure the connection still alive if err = client.TestVoid(defaultCtx); err != nil { - t.Errorf("Unexpected error in TestVoid() call: ", err) + t.Errorf("Unexpected error in TestVoid() call: %s", err) } } diff --git a/test/go/src/common/context_test.go b/test/go/src/common/context_test.go new file mode 100644 index 00000000000..e64dbb9adb0 --- /dev/null +++ b/test/go/src/common/context_test.go @@ -0,0 +1,98 @@ +/* + * 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 common + +import ( + "context" + "fmt" + "net" + "net/http" + "net/url" + "os" + "syscall" + "testing" + "thrift" + "time" +) + +type slowHttpHandler struct{} + +func (slowHttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + time.Sleep(1 * time.Second) +} + +func TestHttpContextTimeout(t *testing.T) { + certPath = "../../../keys" + + unit := test_unit{"127.0.0.1", 9096, "", "http", "binary", false} + + server := &http.Server{Addr: unit.host + fmt.Sprintf(":%d", unit.port), Handler: slowHttpHandler{}} + go server.ListenAndServe() + + client, trans, err := StartClient(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl) + if err != nil { + t.Errorf("Unable to start client: %v", err) + return + } + defer trans.Close() + + unwrapErr := func(err error) error { + for { + switch err.(type) { + case thrift.TTransportException: + err = err.(thrift.TTransportException).Err() + case *url.Error: + err = err.(*url.Error).Err + case *net.OpError: + err = err.(*net.OpError).Err + case *os.SyscallError: + err = err.(*os.SyscallError).Err + default: + return err + } + } + } + + serverStartupDeadline := time.Now().Add(5 * time.Second) + for { + ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond) + err = client.TestVoid(ctx) + err = unwrapErr(err) + if err != syscall.ECONNREFUSED || time.Now().After(serverStartupDeadline) { + break + } + time.Sleep(time.Millisecond) + } + + if err == nil { + t.Errorf("Request completed (should have timed out)") + return + } + + // We've got to switch on `err.Error()` here since go1.7 doesn't properly return + // `context.DeadlineExceeded` error and `http.errRequestCanceled` is not exported. + // See https://github.com/golang/go/issues/17711 + switch err.Error() { + case context.DeadlineExceeded.Error(), "net/http: request canceled": + // Expected error + default: + t.Errorf("Unexpected error: %s", err) + } +} diff --git a/test/go/src/common/go17.go b/test/go/src/common/go17.go deleted file mode 100644 index 9aca4075c74..00000000000 --- a/test/go/src/common/go17.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build go1.7 - -/* - * 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 common - -import "context" - -var defaultCtx = context.Background() diff --git a/test/go/src/common/pre_go17.go b/test/go/src/common/pre_go17.go deleted file mode 100644 index 6c14579d299..00000000000 --- a/test/go/src/common/pre_go17.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build !go1.7 - -/* - * 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 common - -import "golang.org/x/net/context" - -var defaultCtx = context.Background() diff --git a/test/go/src/common/printing_handler.go b/test/go/src/common/printing_handler.go index c0a28626788..2b22d0c9773 100644 --- a/test/go/src/common/printing_handler.go +++ b/test/go/src/common/printing_handler.go @@ -1,5 +1,3 @@ -// +build !go1.7 - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -22,13 +20,12 @@ package common import ( + "context" + "encoding/hex" "errors" "fmt" - "encoding/hex" . "gen/thrifttest" "time" - - "golang.org/x/net/context" ) var PrintingHandler = &printingHandler{} @@ -280,11 +277,11 @@ func (p *printingHandler) TestMapMap(ctx context.Context, hello int32) (r map[in func (p *printingHandler) TestInsanity(ctx context.Context, argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) { fmt.Printf("testInsanity()\n") r = make(map[UserId]map[Numberz]*Insanity) - r[1] = map[Numberz]*Insanity { + r[1] = map[Numberz]*Insanity{ 2: argument, 3: argument, } - r[2] = map[Numberz]*Insanity { + r[2] = map[Numberz]*Insanity{ 6: NewInsanity(), } return diff --git a/test/go/src/common/printing_handler_go17.go b/test/go/src/common/printing_handler_go17.go deleted file mode 100644 index 1efae8676c5..00000000000 --- a/test/go/src/common/printing_handler_go17.go +++ /dev/null @@ -1,386 +0,0 @@ -// +build go1.7 - -/* - * 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 common - -import ( - "context" - "errors" - "fmt" - "encoding/hex" - . "gen/thrifttest" - "time" -) - -var PrintingHandler = &printingHandler{} - -type printingHandler struct{} - -// Prints "testVoid()" and returns nothing. -func (p *printingHandler) TestVoid(ctx context.Context) (err error) { - fmt.Println("testVoid()") - return nil -} - -// Prints 'testString("%s")' with thing as '%s' -// @param string thing - the string to print -// @return string - returns the string 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestString(ctx context.Context, thing string) (r string, err error) { - fmt.Printf("testString(\"%s\")\n", thing) - return thing, nil -} - -// Prints 'testBool("%t")' with thing as 'true' or 'false' -// @param bool thing - the bool to print -// @return bool - returns the bool 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestBool(ctx context.Context, thing bool) (r bool, err error) { - fmt.Printf("testBool(%t)\n", thing) - return thing, nil -} - -// Prints 'testByte("%d")' with thing as '%d' -// @param byte thing - the byte to print -// @return byte - returns the byte 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestByte(ctx context.Context, thing int8) (r int8, err error) { - fmt.Printf("testByte(%d)\n", thing) - return thing, nil -} - -// Prints 'testI32("%d")' with thing as '%d' -// @param i32 thing - the i32 to print -// @return i32 - returns the i32 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestI32(ctx context.Context, thing int32) (r int32, err error) { - fmt.Printf("testI32(%d)\n", thing) - return thing, nil -} - -// Prints 'testI64("%d")' with thing as '%d' -// @param i64 thing - the i64 to print -// @return i64 - returns the i64 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestI64(ctx context.Context, thing int64) (r int64, err error) { - fmt.Printf("testI64(%d)\n", thing) - return thing, nil -} - -// Prints 'testDouble("%f")' with thing as '%f' -// @param double thing - the double to print -// @return double - returns the double 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestDouble(ctx context.Context, thing float64) (r float64, err error) { - fmt.Printf("testDouble(%f)\n", thing) - return thing, nil -} - -// Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data -// @param []byte thing - the binary to print -// @return []byte - returns the binary 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestBinary(ctx context.Context, thing []byte) (r []byte, err error) { - fmt.Printf("testBinary(%s)\n", hex.EncodeToString(thing)) - return thing, nil -} - -// Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values -// @param Xtruct thing - the Xtruct to print -// @return Xtruct - returns the Xtruct 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestStruct(ctx context.Context, thing *Xtruct) (r *Xtruct, err error) { - fmt.Printf("testStruct({\"%s\", %d, %d, %d})\n", thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing) - return thing, err -} - -// Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct -// @param Xtruct2 thing - the Xtruct2 to print -// @return Xtruct2 - returns the Xtruct2 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestNest(ctx context.Context, nest *Xtruct2) (r *Xtruct2, err error) { - thing := nest.StructThing - fmt.Printf("testNest({%d, {\"%s\", %d, %d, %d}, %d})\n", nest.ByteThing, thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing, nest.I32Thing) - return nest, nil -} - -// Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs -// separated by commas and new lines -// @param map thing - the map to print -// @return map - returns the map 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestMap(ctx context.Context, thing map[int32]int32) (r map[int32]int32, err error) { - fmt.Printf("testMap({") - first := true - for k, v := range thing { - if first { - first = false - } else { - fmt.Printf(", ") - } - fmt.Printf("%d => %d", k, v) - } - fmt.Printf("})\n") - return thing, nil -} - -// Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs -// separated by commas and new lines -// @param map thing - the map to print -// @return map - returns the map 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestStringMap(ctx context.Context, thing map[string]string) (r map[string]string, err error) { - fmt.Printf("testStringMap({") - first := true - for k, v := range thing { - if first { - first = false - } else { - fmt.Printf(", ") - } - fmt.Printf("%s => %s", k, v) - } - fmt.Printf("})\n") - return thing, nil -} - -// Prints 'testSet("{%s}")' where thing has been formatted into a string of values -// separated by commas and new lines -// @param set thing - the set to print -// @return set - returns the set 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestSet(ctx context.Context, thing []int32) (r []int32, err error) { - fmt.Printf("testSet({") - first := true - for k, _ := range thing { - if first { - first = false - } else { - fmt.Printf(", ") - } - fmt.Printf("%d", k) - } - fmt.Printf("})\n") - return thing, nil -} - -// Prints 'testList("{%s}")' where thing has been formatted into a string of values -// separated by commas and new lines -// @param list thing - the list to print -// @return list - returns the list 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestList(ctx context.Context, thing []int32) (r []int32, err error) { - fmt.Printf("testList({") - for i, v := range thing { - if i != 0 { - fmt.Printf(", ") - } - fmt.Printf("%d", v) - } - fmt.Printf("})\n") - return thing, nil -} - -// Prints 'testEnum("%d")' where thing has been formatted into it's numeric value -// @param Numberz thing - the Numberz to print -// @return Numberz - returns the Numberz 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestEnum(ctx context.Context, thing Numberz) (r Numberz, err error) { - fmt.Printf("testEnum(%d)\n", thing) - return thing, nil -} - -// Prints 'testTypedef("%d")' with thing as '%d' -// @param UserId thing - the UserId to print -// @return UserId - returns the UserId 'thing' -// -// Parameters: -// - Thing -func (p *printingHandler) TestTypedef(ctx context.Context, thing UserId) (r UserId, err error) { - fmt.Printf("testTypedef(%d)\n", thing) - return thing, nil -} - -// Prints 'testMapMap("%d")' with hello as '%d' -// @param i32 hello - the i32 to print -// @return map> - returns a dictionary with these values: -// {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } -// -// Parameters: -// - Hello -func (p *printingHandler) TestMapMap(ctx context.Context, hello int32) (r map[int32]map[int32]int32, err error) { - fmt.Printf("testMapMap(%d)\n", hello) - - r = map[int32]map[int32]int32{ - -4: map[int32]int32{-4: -4, -3: -3, -2: -2, -1: -1}, - 4: map[int32]int32{4: 4, 3: 3, 2: 2, 1: 1}, - } - return -} - -// So you think you've got this all worked, out eh? -// -// Creates a the returned map with these values and prints it out: -// { 1 => { 2 => argument, -// 3 => argument, -// }, -// 2 => { 6 => , }, -// } -// @return map> - a map with the above values -// -// Parameters: -// - Argument -func (p *printingHandler) TestInsanity(ctx context.Context, argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) { - fmt.Printf("testInsanity()\n") - r = make(map[UserId]map[Numberz]*Insanity) - r[1] = map[Numberz]*Insanity { - 2: argument, - 3: argument, - } - r[2] = map[Numberz]*Insanity { - 6: NewInsanity(), - } - return -} - -// Prints 'testMulti()' -// @param byte arg0 - -// @param i32 arg1 - -// @param i64 arg2 - -// @param map arg3 - -// @param Numberz arg4 - -// @param UserId arg5 - -// @return Xtruct - returns an Xtruct with StringThing = "Hello2, ByteThing = arg0, I32Thing = arg1 -// and I64Thing = arg2 -// -// Parameters: -// - Arg0 -// - Arg1 -// - Arg2 -// - Arg3 -// - Arg4 -// - Arg5 -func (p *printingHandler) TestMulti(ctx context.Context, arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 Numberz, arg5 UserId) (r *Xtruct, err error) { - fmt.Printf("testMulti()\n") - r = NewXtruct() - - r.StringThing = "Hello2" - r.ByteThing = arg0 - r.I32Thing = arg1 - r.I64Thing = arg2 - return -} - -// Print 'testException(%s)' with arg as '%s' -// @param string arg - a string indication what type of exception to throw -// if arg == "Xception" throw Xception with errorCode = 1001 and message = arg -// elsen if arg == "TException" throw TException -// else do not throw anything -// -// Parameters: -// - Arg -func (p *printingHandler) TestException(ctx context.Context, arg string) (err error) { - fmt.Printf("testException(%s)\n", arg) - switch arg { - case "Xception": - e := NewXception() - e.ErrorCode = 1001 - e.Message = arg - return e - case "TException": - return errors.New("Just TException") - } - return -} - -// Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' -// @param string arg - a string indication what type of exception to throw -// if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" -// elsen if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and message = "This is an Xception2" -// else do not throw anything -// @return Xtruct - an Xtruct with StringThing = arg1 -// -// Parameters: -// - Arg0 -// - Arg1 -func (p *printingHandler) TestMultiException(ctx context.Context, arg0 string, arg1 string) (r *Xtruct, err error) { - fmt.Printf("testMultiException(%s, %s)\n", arg0, arg1) - switch arg0 { - - case "Xception": - e := NewXception() - e.ErrorCode = 1001 - e.Message = "This is an Xception" - return nil, e - case "Xception2": - e := NewXception2() - e.ErrorCode = 2002 - e.StructThing = NewXtruct() - e.StructThing.StringThing = "This is an Xception2" - return nil, e - default: - r = NewXtruct() - r.StringThing = arg1 - return - } -} - -// Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' -// sleep 'secondsToSleep' -// Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' -// @param i32 secondsToSleep - the number of seconds to sleep -// -// Parameters: -// - SecondsToSleep -func (p *printingHandler) TestOneway(ctx context.Context, secondsToSleep int32) (err error) { - fmt.Printf("testOneway(%d): Sleeping...\n", secondsToSleep) - time.Sleep(time.Second * time.Duration(secondsToSleep)) - fmt.Printf("testOneway(%d): done sleeping!\n", secondsToSleep) - return -} diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index a14279646c8..a8d00ece4f5 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -11,6 +11,24 @@ "c_glib-rs_multi_framed-ip", "c_glib-rs_multic_buffered-ip", "c_glib-rs_multic_framed-ip", + "cl-c_glib_binary_buffered-ip", + "cl-c_glib_binary_framed-ip", + "cl-c_glib_multi-binary_buffered-ip", + "cl-c_glib_multi-binary_framed-ip", + "cl-c_glib_multi_buffered-ip", + "cl-c_glib_multi_framed-ip", + "cl-go_binary_buffered-ip", + "cl-go_binary_framed-ip", + "cl-rb_binary-accel_buffered-ip", + "cl-rb_binary-accel_framed-ip", + "cl-rb_binary_buffered-ip", + "cl-rb_binary_framed-ip", + "cl-rs_binary_buffered-ip", + "cl-rs_binary_framed-ip", + "cl-rs_multi-binary_buffered-ip", + "cl-rs_multi-binary_framed-ip", + "cl-rs_multi_buffered-ip", + "cl-rs_multi_framed-ip", "cpp-dart_binary_http-ip", "cpp-dart_compact_http-ip", "cpp-dart_json_http-ip", @@ -73,6 +91,8 @@ "csharp-erl_binary_framed-ip-ssl", "csharp-erl_compact_buffered-ip-ssl", "csharp-erl_compact_framed-ip-ssl", + "d-cl_binary_buffered-ip", + "d-cl_binary_framed-ip", "d-cpp_binary_buffered-ip", "d-cpp_binary_buffered-ip-ssl", "d-cpp_binary_framed-ip", @@ -113,8 +133,6 @@ "d-java_json_http-ip", "d-java_json_http-ip-ssl", "d-js_json_http-ip", - "d-lua_json_buffered-ip", - "d-lua_json_framed-ip", "d-nodejs_binary_buffered-ip", "d-nodejs_binary_buffered-ip-ssl", "d-nodejs_binary_framed-ip", @@ -217,32 +235,20 @@ "java-d_compact_framed-ip", "netcore-csharp_binary_buffered-ip-ssl", "netcore-csharp_binary_framed-ip-ssl", - "netcore-csharp_json_framed-ip-ssl", - "netcore-csharp_json_buffered-ip-ssl", "netcore-csharp_compact_buffered-ip-ssl", "netcore-csharp_compact_framed-ip-ssl", + "netcore-csharp_json_buffered-ip-ssl", + "netcore-csharp_json_framed-ip-ssl", "nodejs-cpp_binary_http-ip", "nodejs-cpp_binary_http-ip-ssl", "nodejs-cpp_compact_http-ip", "nodejs-cpp_compact_http-ip-ssl", "nodejs-cpp_json_http-ip", "nodejs-cpp_json_http-ip-ssl", - "nodejs-d_binary_buffered-ip", - "nodejs-d_binary_buffered-ip-ssl", - "nodejs-d_binary_framed-ip", - "nodejs-d_binary_framed-ip-ssl", "nodejs-d_binary_http-ip", "nodejs-d_binary_http-ip-ssl", - "nodejs-d_compact_buffered-ip", - "nodejs-d_compact_buffered-ip-ssl", - "nodejs-d_compact_framed-ip", - "nodejs-d_compact_framed-ip-ssl", "nodejs-d_compact_http-ip", "nodejs-d_compact_http-ip-ssl", - "nodejs-d_json_buffered-ip", - "nodejs-d_json_buffered-ip-ssl", - "nodejs-d_json_framed-ip", - "nodejs-d_json_framed-ip-ssl", "nodejs-d_json_http-ip", "nodejs-d_json_http-ip-ssl", "nodejs-dart_binary_buffered-ip", @@ -301,12 +307,6 @@ "rs-cpp_multic-compact_framed-ip", "rs-cpp_multic_buffered-ip", "rs-cpp_multic_framed-ip", - "rs-csharp_binary_framed-ip", - "rs-csharp_compact_framed-ip", - "rs-csharp_multi-binary_framed-ip", - "rs-csharp_multi_framed-ip", - "rs-csharp_multic-compact_framed-ip", - "rs-csharp_multic_framed-ip", "rs-dart_binary_framed-ip", "rs-dart_compact_framed-ip", "rs-dart_multi-binary_framed-ip", diff --git a/test/perl/TestServer.pl b/test/perl/TestServer.pl index 7d8f929b447..e8c1cfa9e33 100644 --- a/test/perl/TestServer.pl +++ b/test/perl/TestServer.pl @@ -26,6 +26,8 @@ use Getopt::Long qw(GetOptions); use Time::HiRes qw(gettimeofday); +$SIG{INT} = \&sigint_handler; + use lib '../../lib/perl/lib'; use lib 'gen-perl'; @@ -146,6 +148,12 @@ sub usage { my $server = new Thrift::SimpleServer($processor, $serversocket, $transport, $protocol); print "Starting \"simple\" server ($opts{transport}/$opts{protocol}) listen on: $listening_on\n"; $server->serve(); +print "done.\n"; + +sub sigint_handler { + print "received SIGINT, stopping...\n"; + $server->stop(); +} ### ### Test server implementation diff --git a/test/php/Makefile.am b/test/php/Makefile.am index 28357f6bea5..72f7fc58142 100755 --- a/test/php/Makefile.am +++ b/test/php/Makefile.am @@ -20,8 +20,8 @@ stubs: ../ThriftTest.thrift $(THRIFT) --gen php ../ThriftTest.thrift $(THRIFT) --gen php:inlined ../ThriftTest.thrift - $(MKDIR_P) gen-php-psr4 - $(THRIFT) -out gen-php-psr4 --gen php:psr4 ../ThriftTest.thrift + $(MKDIR_P) gen-php-classmap + $(THRIFT) -out gen-php-classmap --gen php ../ThriftTest.thrift php_ext_dir: mkdir -p php_ext_dir @@ -33,7 +33,7 @@ precross: stubs php_ext_dir check: stubs php_ext_dir clean-local: - $(RM) -r gen-php gen-phpi gen-php-psr4 php_ext_dir + $(RM) -r gen-php gen-phpi gen-php-classmap php_ext_dir client: stubs php_ext_dir php TestClient.php diff --git a/test/php/TestPsr4.php b/test/php/TestClassmap.php similarity index 96% rename from test/php/TestPsr4.php rename to test/php/TestClassmap.php index d30bf1c49b0..6fd159437af 100644 --- a/test/php/TestPsr4.php +++ b/test/php/TestClassmap.php @@ -18,6 +18,6 @@ */ diff --git a/test/php/TestClient.php b/test/php/TestClient.php index aa42e09d33f..acd901d883b 100755 --- a/test/php/TestClient.php +++ b/test/php/TestClient.php @@ -2,7 +2,8 @@ namespace test\php; -require_once __DIR__.'/../../vendor/autoload.php'; +/** @var \Composer\Autoload\ClassLoader $loader */ +$loader = require __DIR__ . '/../../vendor/autoload.php'; use Thrift\ClassLoader\ThriftClassLoader; @@ -13,13 +14,14 @@ $MODE = 'normal'; } -$loader = new ThriftClassLoader(); -if ($GEN_DIR === 'gen-php-psr4') { - $loader->registerNamespace('ThriftTest', $GEN_DIR); + +if ($GEN_DIR == 'gen-php') { + $loader->addPsr4('', $GEN_DIR); } else { + $loader = new ThriftClassLoader(); $loader->registerDefinition('ThriftTest', $GEN_DIR); + $loader->register(); } -$loader->register(); /* * Licensed to the Apache Software Foundation (ASF) under one @@ -93,7 +95,7 @@ function makeProtocol($transport, $PROTO) $MODE = substr($arg, 12); } else if (substr($arg, 0, 11) == '--protocol=') { $PROTO = substr($arg, 11); - } + } } $hosts = array('localhost'); diff --git a/test/py/Makefile.am b/test/py/Makefile.am index b3513dd7e64..829620055b3 100644 --- a/test/py/Makefile.am +++ b/test/py/Makefile.am @@ -23,24 +23,31 @@ py_unit_tests = RunClientServer.py thrift_gen = \ gen-py/ThriftTest/__init__.py \ gen-py/DebugProtoTest/__init__.py \ + gen-py/DoubleConstantsTest/__init__.py \ gen-py/Recursive/__init__.py \ gen-py-default/ThriftTest/__init__.py \ gen-py-default/DebugProtoTest/__init__.py \ + gen-py-default/DoubleConstantsTest/__init__.py \ gen-py-default/Recursive/__init__.py \ gen-py-slots/ThriftTest/__init__.py \ gen-py-slots/DebugProtoTest/__init__.py \ + gen-py-slots/DoubleConstantsTest/__init__.py \ gen-py-slots/Recursive/__init__.py \ gen-py-oldstyle/ThriftTest/__init__.py \ gen-py-oldstyle/DebugProtoTest/__init__.py \ + gen-py-oldstyle/DoubleConstantsTest/__init__.py \ gen-py-oldstyle/Recursive/__init__.py \ gen-py-no_utf8strings/ThriftTest/__init__.py \ gen-py-no_utf8strings/DebugProtoTest/__init__.py \ + gen-py-no_utf8strings/DoubleConstantsTest/__init__.py \ gen-py-no_utf8strings/Recursive/__init__.py \ gen-py-dynamic/ThriftTest/__init__.py \ gen-py-dynamic/DebugProtoTest/__init__.py \ + gen-py-dynamic/DoubleConstantsTest/__init__.py \ gen-py-dynamic/Recursive/__init__.py \ gen-py-dynamicslots/ThriftTest/__init__.py \ gen-py-dynamicslots/DebugProtoTest/__init__.py \ + gen-py-dynamicslots/DoubleConstantsTest/__init__.py \ gen-py-dynamicslots/Recursive/__init__.py diff --git a/test/py/RunClientServer.py b/test/py/RunClientServer.py index 7c0f7873924..b213d1acc5d 100755 --- a/test/py/RunClientServer.py +++ b/test/py/RunClientServer.py @@ -38,6 +38,7 @@ SCRIPTS = [ 'FastbinaryTest.py', 'TestFrozen.py', + 'TestRenderedDoubleConstants.py', 'TSimpleJSONProtocolTest.py', 'SerializationTest.py', 'TestEof.py', diff --git a/test/py/TestRenderedDoubleConstants.py b/test/py/TestRenderedDoubleConstants.py new file mode 100644 index 00000000000..20903d81b2c --- /dev/null +++ b/test/py/TestRenderedDoubleConstants.py @@ -0,0 +1,177 @@ +# +# 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. +# + +import unittest + +from DoubleConstantsTest import constants + +# +# In order to run the test under Windows. We need to create symbolic link +# name 'thrift' to '../src' folder by using: +# +# mklink /D thrift ..\src +# + + +class TestRenderedDoubleConstants(unittest.TestCase): + ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST = \ + "failed to verify a double constant generated by Thrift (expected = %f, got = %f)" + ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST =\ + "failed to verify a list item by Thrift (expected = %f, got = %f)" + ASSERTION_MESSAGE_FOR_TYPE_CHECKS = "the rendered variable with name %s is not of double type" + + # to make sure the variables inside Thrift files are generated correctly + def test_rendered_double_constants(self): + EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0 + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0 + EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0 + EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0 + EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359 + EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1 + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1 + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308 + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43 + EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308 + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43 + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, + places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, + places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, + constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, + places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, + constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, + constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, + places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST)) + self.assertAlmostEqual( + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, places=7, + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( + EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, + constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST)) + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST") + self.assertTrue( + isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, float), + msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % + "DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST") + + # to make sure the variables inside Thrift files are generated correctly + def test_rendered_double_list(self): + EXPECTED_DOUBLE_LIST = [1.0, -100.0, 100.0, 9223372036854775807.0, -9223372036854775807.0, 3.14159265359, + 1000000.1, -1000000.1, 1.7e+308, -1.7e+308, 9223372036854775816.43, + -9223372036854775816.43] + self.assertEqual(len(constants.DOUBLE_LIST_TEST), len(EXPECTED_DOUBLE_LIST)) + for i, expectedValue in enumerate(EXPECTED_DOUBLE_LIST): + self.assertAlmostEqual(constants.DOUBLE_LIST_TEST[i], expectedValue, places=7) + + +def suite(): + suite = unittest.TestSuite() + loader = unittest.TestLoader() + suite.addTest(loader.loadTestsFromTestCase(TestRenderedDoubleConstants)) + return suite + + +if __name__ == "__main__": + unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) diff --git a/test/py/generate.cmake b/test/py/generate.cmake index 46263c84a1a..4ed14cc52ce 100644 --- a/test/py/generate.cmake +++ b/test/py/generate.cmake @@ -21,6 +21,13 @@ generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:no_utf8strings gen-py-n generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:dynamic gen-py-dynamic) generate(${MY_PROJECT_DIR}/test/DebugProtoTest.thrift py:dynamic,slots gen-py-dynamicslots) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py gen-py-default) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:slots gen-py-slots) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:old_style gen-py-oldstyle) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:no_utf8strings gen-py-no_utf8strings) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:dynamic gen-py-dynamic) +generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:dynamic,slots gen-py-dynamicslots) + generate(${MY_PROJECT_DIR}/test/Recursive.thrift py gen-py-default) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:slots gen-py-slots) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:old_style gen-py-oldstyle) diff --git a/test/test.py b/test/test.py index 5a015eac7df..24e7c4e47b6 100755 --- a/test/test.py +++ b/test/test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -18,12 +18,13 @@ # under the License. # -# Apache Thrift - integration test suite +# +# Apache Thrift - integration (cross) test suite # # tests different server-client, protocol and transport combinations # -# This script supports python 2.7 and later. -# python 3.x is recommended for better stability. +# This script requires python 3.x due to the improvements in +# subprocess management that are needed for reliability. # from __future__ import print_function @@ -38,6 +39,12 @@ import crossrunner from crossrunner.compat import path_join +# 3.3 introduced subprocess timeouts on waiting for child +req_version = (3, 3) +cur_version = sys.version_info +assert (cur_version >= req_version), "Python 3.3 or later is required for proper operation." + + ROOT_DIR = os.path.dirname(os.path.realpath(os.path.dirname(__file__))) TEST_DIR_RELATIVE = 'test' TEST_DIR = path_join(ROOT_DIR, TEST_DIR_RELATIVE) @@ -161,9 +168,11 @@ def main(argv): options.update_failures, options.print_failures) elif options.features is not None: features = options.features or ['.*'] - res = run_feature_tests(server_match, features, options.jobs, options.skip_known_failures, options.retry_count, options.regex) + res = run_feature_tests(server_match, features, options.jobs, + options.skip_known_failures, options.retry_count, options.regex) else: - res = run_cross_tests(server_match, client_match, options.jobs, options.skip_known_failures, options.retry_count, options.regex) + res = run_cross_tests(server_match, client_match, options.jobs, + options.skip_known_failures, options.retry_count, options.regex) return 0 if res else 1 diff --git a/test/tests.json b/test/tests.json index 1640eac4b16..9c7668dcfa6 100644 --- a/test/tests.json +++ b/test/tests.json @@ -42,11 +42,29 @@ ], "workdir": "c_glib" }, + { + "name": "cl", + "server": { + "command": ["TestServer"], + "workdir": "cl", + "protocols": ["binary", "multi"], + "transports": ["buffered", "framed"], + "sockets": ["ip"] + }, + "client": { + "command": ["TestClient"], + "workdir": "cl", + "protocols": ["binary", "multi"], + "transports": ["buffered", "framed"], + "sockets": ["ip"] + } + }, { "name": "d", "server": { "command": [ - "thrift_test_server" + "thrift_test_server", + "--trace" ] }, "client": { @@ -421,12 +439,12 @@ "compact", "json" ], - "server": { + "server": { "command": [ "dotnet", "run", - "--no-build", - "--project=Server/Server.csproj", + "--no-build", + "--project=Server/Server.csproj", "server" ] }, @@ -435,8 +453,8 @@ "command": [ "dotnet", "run", - "--no-build", - "--project=Client/Client.csproj", + "--no-build", + "--project=Client/Client.csproj", "client" ] }, diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index d8ad09c6039..0499460aaf4 100755 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -78,6 +78,10 @@ if WITH_RS SUBDIRS += rs endif +if WITH_CL +SUBDIRS += cl +endif + # # generate html for ThriftTest.thrift # diff --git a/tutorial/cl/Makefile.am b/tutorial/cl/Makefile.am new file mode 100755 index 00000000000..fb6e83a4201 --- /dev/null +++ b/tutorial/cl/Makefile.am @@ -0,0 +1,47 @@ +# +# 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. +# + +gen-cl: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen cl -r $< + +TutorialServer: make-tutorial-server.lisp + $(SBCL) --script make-tutorial-server.lisp + +TutorialClient: make-tutorial-client.lisp + $(SBCL) --script make-tutorial-client.lisp + +all-local: gen-cl TutorialClient TutorialServer + +tutorialserver: all + ./TutorialServer + +tutorialclient: all + ./TutorialClient + +clean-local: + $(RM) -r gen-* + $(RM) TutorialServer + $(RM) TutorialClient + +EXTRA_DIST = \ + tutorial-implementation.lisp \ + shared-implementation.lisp \ + thrift-tutorial.asd \ + make-tutorial-server.lisp \ + make-tutorial-client.lisp diff --git a/tutorial/cl/make-tutorial-client.lisp b/tutorial/cl/make-tutorial-client.lisp new file mode 100644 index 00000000000..59450a2eae3 --- /dev/null +++ b/tutorial/cl/make-tutorial-client.lisp @@ -0,0 +1,51 @@ +(in-package #:cl-user) + +;;;; Licensed 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. + +(require "asdf") +(load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*)) +(asdf:load-system :net.didierverna.clon) +(asdf:load-asd (merge-pathnames "gen-cl/shared/thrift-gen-shared.asd" *load-truename*)) +(asdf:load-asd (merge-pathnames "gen-cl/tutorial/thrift-gen-tutorial.asd" *load-truename*)) +(asdf:load-asd (merge-pathnames "thrift-tutorial.asd" *load-truename*)) +(asdf:load-system :thrift-tutorial) + +(net.didierverna.clon:nickname-package) + +(defun main () + "Entry point for the binary." + (thrift:with-client (prot #u"thrift://127.0.0.1:9090") + (tutorial.calculator:ping prot) + (format t "ping()~%") + (format t "1 + 1 = ~a~%" (tutorial.calculator:add prot 1 1)) + (let ((work-instance (tutorial:make-work :num1 5 + :num2 0 + :op tutorial:operation.divide + :comment "Booya!"))) + (handler-case (format t + "5 / 0 = ~a - Oh, really? An exception should have been thrown here.~%" + (tutorial.calculator:calculate prot 1 work-instance)) + (tutorial:invalidoperation (e) + (format t "---~%(Expected) Invalid Operation caught: ~%~a~%---~%" e)))) + (let ((work-instance (tutorial:make-work :num1 15 + :num2 10 + :op tutorial:operation.subtract + :comment "Playing nice this time."))) + (handler-case (format t + "15 - 10 = ~a~%" + (tutorial.calculator:calculate prot 1 work-instance)) + (tutorial:invalidoperation (e) + (format t "---~%(Unexpected) Invalid Operation caught: ~%~a~%---~%" e)))) + (format t "Check log: ~a~%" (shared.shared-service:get-struct prot 1)))) + +(clon:dump "TutorialClient" main) diff --git a/tutorial/cl/make-tutorial-server.lisp b/tutorial/cl/make-tutorial-server.lisp new file mode 100644 index 00000000000..5621ff36698 --- /dev/null +++ b/tutorial/cl/make-tutorial-server.lisp @@ -0,0 +1,29 @@ +(in-package #:cl-user) + +;;;; Licensed 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. + +(require "asdf") +(load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*)) +(asdf:load-system :net.didierverna.clon) +(asdf:load-asd (merge-pathnames "gen-cl/shared/thrift-gen-shared.asd" *load-truename*)) +(asdf:load-asd (merge-pathnames "gen-cl/tutorial/thrift-gen-tutorial.asd" *load-truename*)) +(asdf:load-asd (merge-pathnames "thrift-tutorial.asd" *load-truename*)) +(asdf:load-system :thrift-tutorial) + +(net.didierverna.clon:nickname-package) + +(defun main () + "Entry point for the binary." + (thrift:serve #u"thrift://127.0.0.1:9090" tutorial:calculator)) + +(clon:dump "TutorialServer" main) diff --git a/tutorial/cl/shared-implementation.lisp b/tutorial/cl/shared-implementation.lisp new file mode 100644 index 00000000000..c197626a56e --- /dev/null +++ b/tutorial/cl/shared-implementation.lisp @@ -0,0 +1,25 @@ +(in-package #:shared-implementation) + +;;;; Licensed 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. + +(defvar *structs* (make-hash-table)) + +(defun shared.shared-service-implementation:get-struct (key) + (format t "getStruct(~a)~%" key) + (gethash key *structs*)) + +(defun add-log (key value) + (setf (gethash key *structs*) + (make-instance 'shared:sharedstruct + :key key + :value (write-to-string value)))) diff --git a/tutorial/cl/thrift-tutorial.asd b/tutorial/cl/thrift-tutorial.asd new file mode 100644 index 00000000000..8a03537639c --- /dev/null +++ b/tutorial/cl/thrift-tutorial.asd @@ -0,0 +1,17 @@ +;;;; Licensed 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. + +(asdf:defsystem #:thrift-tutorial + :depends-on (#:thrift-gen-tutorial) + :serial t + :components ((:file "shared-implementation") + (:file "tutorial-implementation"))) diff --git a/tutorial/cl/tutorial-implementation.lisp b/tutorial/cl/tutorial-implementation.lisp new file mode 100644 index 00000000000..5c92fe40538 --- /dev/null +++ b/tutorial/cl/tutorial-implementation.lisp @@ -0,0 +1,41 @@ +(in-package #:tutorial-implementation) + +;;;; Licensed 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. + +(defun tutorial.calculator-implementation:ping () + (format t "ping()~%")) + +(defun tutorial.calculator-implementation:add (num1 num2) + (format t "add(~a, ~a)~%" num1 num2) + (+ num1 num2)) + +(defun tutorial.calculator-implementation:calculate (logid work) + (format t "calculate(~a, ~a)~%" logid work) + (handler-case + (let* ((num1 (tutorial:work-num1 work)) + (num2 (tutorial:work-num2 work)) + (op (tutorial:work-op work)) + (result + (cond + ((= op tutorial:operation.add) (+ num1 num2)) + ((= op tutorial:operation.subtract) (- num1 num2)) + ((= op tutorial:operation.multiply) (* num1 num2)) + ((= op tutorial:operation.divide) (/ num1 num2))))) + (shared-implementation::add-log logid result) + result) + (division-by-zero () (error 'tutorial:invalidoperation + :why "Division by zero." + :what-op (tutorial:work-op work))))) + +(defun tutorial.calculator-implementation:zip () + (format t "zip()~%")) diff --git a/tutorial/go/Makefile.am b/tutorial/go/Makefile.am index a146d5c9fa9..87a8f5a71ed 100644 --- a/tutorial/go/Makefile.am +++ b/tutorial/go/Makefile.am @@ -17,10 +17,6 @@ # under the License. # -if GOVERSION_LT_17 -COMPILER_EXTRAFLAG=":legacy_context" -endif - gen-go/tutorial/calculator.go gen-go/shared/shared_service.go: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen go$(COMPILER_EXTRAFLAG) -r $< @@ -37,9 +33,6 @@ src/git.apache.org/thrift.git/lib/go/thrift: ln -sf $(realpath $(top_srcdir)/lib/go/thrift) src/git.apache.org/thrift.git/lib/go/thrift thirdparty-dep: - mkdir -p src/golang.org/x/net - GOPATH=`pwd`/gopath $(GO) get golang.org/x/net/context - ln -sf `pwd`/gopath/src/golang.org/x/net/context src/golang.org/x/net/context tutorialserver: all GOPATH=`pwd` $(GO) run src/*.go -server=true @@ -61,9 +54,6 @@ EXTRA_DIST = \ src/handler.go \ src/server.go \ src/main.go \ - src/go17.go \ - src/handler_go17.go \ - src/pre_go17.go \ server.crt \ server.key diff --git a/tutorial/go/src/client.go b/tutorial/go/src/client.go index 25616bf4ecc..1d658b9542f 100644 --- a/tutorial/go/src/client.go +++ b/tutorial/go/src/client.go @@ -20,6 +20,7 @@ package main */ import ( + "context" "crypto/tls" "fmt" "tutorial" @@ -27,6 +28,8 @@ import ( "git.apache.org/thrift.git/lib/go/thrift" ) +var defaultCtx = context.Background() + func handleClient(client *tutorial.CalculatorClient) (err error) { client.Ping(defaultCtx) fmt.Println("ping()") diff --git a/tutorial/go/src/handler.go b/tutorial/go/src/handler.go index 783b43267d4..5c0eed0060a 100644 --- a/tutorial/go/src/handler.go +++ b/tutorial/go/src/handler.go @@ -1,5 +1,3 @@ -// +build !go1.7 - package main /* @@ -22,12 +20,11 @@ package main */ import ( + "context" "fmt" "shared" "strconv" "tutorial" - - "golang.org/x/net/context" ) type CalculatorHandler struct { diff --git a/tutorial/go/src/handler_go17.go b/tutorial/go/src/handler_go17.go deleted file mode 100644 index d6752cc783e..00000000000 --- a/tutorial/go/src/handler_go17.go +++ /dev/null @@ -1,104 +0,0 @@ -// +build go1.7 - -package main - -/* - * 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. - */ - -import ( - "context" - "fmt" - "shared" - "strconv" - "tutorial" -) - -type CalculatorHandler struct { - log map[int]*shared.SharedStruct -} - -func NewCalculatorHandler() *CalculatorHandler { - return &CalculatorHandler{log: make(map[int]*shared.SharedStruct)} -} - -func (p *CalculatorHandler) Ping(ctx context.Context) (err error) { - fmt.Print("ping()\n") - return nil -} - -func (p *CalculatorHandler) Add(ctx context.Context, num1 int32, num2 int32) (retval17 int32, err error) { - fmt.Print("add(", num1, ",", num2, ")\n") - return num1 + num2, nil -} - -func (p *CalculatorHandler) Calculate(ctx context.Context, logid int32, w *tutorial.Work) (val int32, err error) { - fmt.Print("calculate(", logid, ", {", w.Op, ",", w.Num1, ",", w.Num2, "})\n") - switch w.Op { - case tutorial.Operation_ADD: - val = w.Num1 + w.Num2 - break - case tutorial.Operation_SUBTRACT: - val = w.Num1 - w.Num2 - break - case tutorial.Operation_MULTIPLY: - val = w.Num1 * w.Num2 - break - case tutorial.Operation_DIVIDE: - if w.Num2 == 0 { - ouch := tutorial.NewInvalidOperation() - ouch.WhatOp = int32(w.Op) - ouch.Why = "Cannot divide by 0" - err = ouch - return - } - val = w.Num1 / w.Num2 - break - default: - ouch := tutorial.NewInvalidOperation() - ouch.WhatOp = int32(w.Op) - ouch.Why = "Unknown operation" - err = ouch - return - } - entry := shared.NewSharedStruct() - entry.Key = logid - entry.Value = strconv.Itoa(int(val)) - k := int(logid) - /* - oldvalue, exists := p.log[k] - if exists { - fmt.Print("Replacing ", oldvalue, " with ", entry, " for key ", k, "\n") - } else { - fmt.Print("Adding ", entry, " for key ", k, "\n") - } - */ - p.log[k] = entry - return val, err -} - -func (p *CalculatorHandler) GetStruct(ctx context.Context, key int32) (*shared.SharedStruct, error) { - fmt.Print("getStruct(", key, ")\n") - v, _ := p.log[int(key)] - return v, nil -} - -func (p *CalculatorHandler) Zip(ctx context.Context) (err error) { - fmt.Print("zip()\n") - return nil -} diff --git a/tutorial/go/src/pre_go17.go b/tutorial/go/src/pre_go17.go deleted file mode 100644 index 10a6fb8d932..00000000000 --- a/tutorial/go/src/pre_go17.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build !go1.7 - -/* - * 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 main - -import "golang.org/x/net/context" - -var defaultCtx = context.Background() diff --git a/tutorial/shared.thrift b/tutorial/shared.thrift index 3cc1bb34e5c..f1685bd1618 100644 --- a/tutorial/shared.thrift +++ b/tutorial/shared.thrift @@ -22,6 +22,7 @@ * these definitions. */ +namespace cl shared namespace cpp shared namespace d share // "shared" would collide with the eponymous D keyword. namespace dart shared diff --git a/tutorial/tutorial.thrift b/tutorial/tutorial.thrift index f8c5320d9aa..e0275464440 100644 --- a/tutorial/tutorial.thrift +++ b/tutorial/tutorial.thrift @@ -62,6 +62,8 @@ include "shared.thrift" * Thrift files can namespace, package, or prefix their output in various * target languages. */ + +namespace cl tutorial namespace cpp tutorial namespace d tutorial namespace dart tutorial
LanguageSince Build SystemsLang/Lib LevelsLang/Lib Levels (Tested) Low-Level Transports Transport Wrappers Protocols
ActionScript0.3.0 ActionScript 3 Yes
C (glib)0.6.0 YesYes2.40.22.54.02.48.22.54.0 YesYesYesYes Yes YesYesYes
C++0.2.0 YesYesC++98, gcc C++98 YesYesYesYesYesYes YesYesYes YesYesYesYes
C#0.2.0 Yes .NET 3.5 / mono 3.2.8.0.NET 4.6.1 / mono 4.6.2.7 YesYesYesYes
Cocoa0.2.0 unknown YesYesYesYesCocoa
DCommon Lisp0.12.0 Yes2.070.22.077.1SBCL 1.4.5YesYesYesYesYesYesYesCommon Lisp
Dlang0.9.0Yes2.073.22.077.1 YesYesYesYesYes YesYesYes YesYesYes
Dart0.10.0 Yes1.20.11.24.31.22.11.24.3 Yes YesYes YesYesYesYes
Delphi0.8.0 2010unknown Yes
.NET Core2.0.02.0.50.11.0Yes2.1.4 YesYesYesYes YesYes YesYesYesYes
Erlang0.3.0 YesR16B0320.0.418.320.0.4 YesYesYesYes YesYes YesYesYesYes
Go0.7.0 Yes1.2.11.8.31.7.61.10 YesYesYes YesYesYes YesYesYesYes
Haskell0.5.0 YesYes7.6.38.0.27.10.38.0.2 YesYesYesYes YesYes YesYesYes
Haxe0.9.3 Yes 3.2.13.4.4 YesYes
Java (SE)0.2.0 YesYes1.7.0_1511.8.0_1441.8.0_151 YesYesYesYes YesYesYes YesYesYesYes
Java (ME)0.5.0 unknown YesYesYes
Javascript0.3.0 Yes unknown YesYes
Lua0.9.2 Yes 5.1.55.2.4 YesYes
node.js0.6.0 Yes4.2.68.9.16.x8.x YesYes YesYes YesYesYesYes
OCaml0.2.0 4.02.34.04.04.04.0 Yes Yes Yes
Perl0.2.0 Yes5.18.25.26.05.22.15.26.0 YesYesYesYes YesYes YesYesYes
PHP0.2.0 Yes5.5.97.1.87.0.227.1.8 YesYesYes YesYes YesYesYesYes
Python0.2.0 YesYes2.7.6, 3.4.32.7.14, 3.6.32.7.12, 3.5.22.7.14, 3.6.3 YesYes YesYes YesYesYesYes
Ruby0.2.0 Yes1.9.3p4842.3.3p2222.3.1p1122.3.3p222 YesYesYesYes YesYes YesYesYesYes
Rust0.11.0 Yes1.15.11.18.01.17.01.21.0 YesYes Yes YesYesYes
Smalltalk0.2.0 unknown Yes
LanguageSince autoconfcmake MinMax Domain File Memory Pipe Socket TLS 
Build SystemsLang/Lib LevelsLang/Lib Levels (Tested) Low-Level Transports Transport Wrappers Protocols