[
https://issues.apache.org/jira/browse/THRIFT-3118?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16428227#comment-16428227
]
ASF GitHub Bot commented on THRIFT-3118:
----------------------------------------
jeking3 closed pull request #1533: THRIFT-3118: add http and https cross test
support for python
URL: https://github.com/apache/thrift/pull/1533
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/build/appveyor/MSVC-appveyor-build.bat
b/build/appveyor/MSVC-appveyor-build.bat
index a4b92a29cd..31aac57c99 100644
--- a/build/appveyor/MSVC-appveyor-build.bat
+++ b/build/appveyor/MSVC-appveyor-build.bat
@@ -21,6 +21,8 @@ CALL cl_setenv.bat || EXIT /B
MKDIR "%BUILDDIR%" || EXIT /B
CD "%BUILDDIR%" || EXIT /B
+:: Haskell is disabled for cmake (Windows), see Jira THRIFT-4545
+
@ECHO ON
cmake "%SRCDIR%" ^
-G"%GENERATOR%" ^
@@ -36,6 +38,7 @@ CD "%BUILDDIR%" || EXIT /B
-DOPENSSL_USE_STATIC_LIBS=OFF ^
-DZLIB_LIBRARY="%WIN3P%\zlib-inst\lib\zlib%ZLIB_LIB_SUFFIX%.lib" ^
-DZLIB_ROOT="%WIN3P%\zlib-inst" ^
+ -DWITH_HASKELL=OFF ^
-DWITH_PYTHON=%WITH_PYTHON% ^
-DWITH_%THREADMODEL%THREADS=ON ^
-DWITH_SHARED_LIB=OFF ^
diff --git a/build/appveyor/MSVC-appveyor-install.bat
b/build/appveyor/MSVC-appveyor-install.bat
index 95008bd523..f9eb0c67da 100644
--- a/build/appveyor/MSVC-appveyor-install.bat
+++ b/build/appveyor/MSVC-appveyor-install.bat
@@ -56,5 +56,5 @@ pip.exe ^
tornado ^
twisted || EXIT /B
-:: Haskell (GHC) and cabal
-cinst -c "%BUILDCACHE%" -y ghc || EXIT /B
+:: Haskell (GHC) and cabal (disabled: see Jira THRIFT-4545)
+:: cinst -c "%BUILDCACHE%" -y ghc || EXIT /B
diff --git a/build/docker/scripts/sca.sh b/build/docker/scripts/sca.sh
index f17f7035dc..f26ce9556d 100755
--- a/build/docker/scripts/sca.sh
+++ b/build/docker/scripts/sca.sh
@@ -39,10 +39,10 @@ cppcheck --force --quiet --inline-suppr --error-exitcode=1
-j2 lib/cpp/src lib/c
cppcheck --force --quiet --inline-suppr --error-exitcode=1 -j2 lib/c_glib/src
lib/c_glib/test test/c_glib/src tutorial/c_glib
# Python code style
-flake8 --ignore=E501 lib/py
-flake8 tutorial/py
+flake8 --ignore=E501 --exclude=lib/py/build lib/py
+flake8 --exclude=tutorial/py/build tutorial/py
# THRIFT-4371 : generated files are excluded because they haven't been
scrubbed yet
-flake8 --ignore=E501 --exclude="*/gen-py*/*" test/py
+flake8 --ignore=E501 --exclude="*/gen-py*/*",test/py/build test/py
flake8 test/py.twisted
flake8 test/py.tornado
flake8 --ignore=E501 test/test.py
diff --git a/lib/py/src/server/THttpServer.py b/lib/py/src/server/THttpServer.py
index 1b501a7aa5..85cf4005ea 100644
--- a/lib/py/src/server/THttpServer.py
+++ b/lib/py/src/server/THttpServer.py
@@ -17,6 +17,8 @@
# under the License.
#
+import ssl
+
from six.moves import BaseHTTPServer
from thrift.server import TServer
@@ -47,11 +49,17 @@ def __init__(self,
server_address,
inputProtocolFactory,
outputProtocolFactory=None,
- server_class=BaseHTTPServer.HTTPServer):
- """Set up protocol factories and HTTP server.
+ server_class=BaseHTTPServer.HTTPServer,
+ **kwargs):
+ """Set up protocol factories and HTTP (or HTTPS) server.
See BaseHTTPServer for server_address.
See TServer for protocol factories.
+
+ To make a secure server, provide the named arguments:
+ * cafile - to validate clients [optional]
+ * cert_file - the server cert
+ * key_file - the server's key
"""
if outputProtocolFactory is None:
outputProtocolFactory = inputProtocolFactory
@@ -83,5 +91,16 @@ def do_POST(self):
self.httpd = server_class(server_address, RequestHander)
+ if (kwargs.get('cafile') or kwargs.get('cert_file') or
kwargs.get('key_file')):
+ context = ssl.create_default_context(cafile=kwargs.get('cafile'))
+ context.check_hostname = False
+ context.load_cert_chain(kwargs.get('cert_file'),
kwargs.get('key_file'))
+ context.verify_mode = ssl.CERT_REQUIRED if kwargs.get('cafile')
else ssl.CERT_NONE
+ self.httpd.socket = context.wrap_socket(self.httpd.socket,
server_side=True)
+
def serve(self):
self.httpd.serve_forever()
+
+ def shutdown(self):
+ self.httpd.socket.close()
+ # self.httpd.shutdown() # hangs forever, python doesn't handle
POLLNVAL properly!
diff --git a/lib/py/src/transport/THttpClient.py
b/lib/py/src/transport/THttpClient.py
index fb33421d75..60ff226a90 100644
--- a/lib/py/src/transport/THttpClient.py
+++ b/lib/py/src/transport/THttpClient.py
@@ -20,6 +20,7 @@
from io import BytesIO
import os
import socket
+import ssl
import sys
import warnings
import base64
@@ -34,17 +35,20 @@
class THttpClient(TTransportBase):
"""Http implementation of TTransport base."""
- def __init__(self, uri_or_host, port=None, path=None):
- """THttpClient supports two different types constructor parameters.
+ def __init__(self, uri_or_host, port=None, path=None, cafile=None,
cert_file=None, key_file=None, ssl_context=None):
+ """THttpClient supports two different types of construction:
THttpClient(host, port, path) - deprecated
- THttpClient(uri)
+ THttpClient(uri, [port=<n>, path=<s>, cafile=<filename>,
cert_file=<filename>, key_file=<filename>, ssl_context=<context>])
- Only the second supports https.
+ Only the second supports https. To properly authenticate against the
server,
+ provide the client's identity by specifying cert_file and key_file.
To properly
+ authenticate the server, specify either cafile or ssl_context with a
CA defined.
+ NOTE: if both cafile and ssl_context are defined, ssl_context will
override cafile.
"""
if port is not None:
warnings.warn(
- "Please use the THttpClient('http://host:port/path') syntax",
+ "Please use the THttpClient('http{s}://host:port/path')
constructor",
DeprecationWarning,
stacklevel=2)
self.host = uri_or_host
@@ -60,6 +64,9 @@ def __init__(self, uri_or_host, port=None, path=None):
self.port = parsed.port or http_client.HTTP_PORT
elif self.scheme == 'https':
self.port = parsed.port or http_client.HTTPS_PORT
+ self.certfile = cert_file
+ self.keyfile = key_file
+ self.context = ssl.create_default_context(cafile=cafile) if
(cafile and not ssl_context) else ssl_context
self.host = parsed.hostname
self.path = parsed.path
if parsed.query:
@@ -100,12 +107,17 @@ def using_proxy(self):
def open(self):
if self.scheme == 'http':
- self.__http = http_client.HTTPConnection(self.host, self.port)
+ self.__http = http_client.HTTPConnection(self.host, self.port,
+ timeout=self.__timeout)
elif self.scheme == 'https':
- self.__http = http_client.HTTPSConnection(self.host, self.port)
- if self.using_proxy():
- self.__http.set_tunnel(self.realhost, self.realport,
- {"Proxy-Authorization":
self.proxy_auth})
+ self.__http = http_client.HTTPSConnection(self.host, self.port,
+ key_file=self.keyfile,
+ cert_file=self.certfile,
+ timeout=self.__timeout,
+ context=self.context)
+ if self.using_proxy():
+ self.__http.set_tunnel(self.realhost, self.realport,
+ {"Proxy-Authorization": self.proxy_auth})
def close(self):
self.__http.close()
diff --git a/test/crossrunner/run.py b/test/crossrunner/run.py
index 25c58cef3e..a7bc939ea9 100644
--- a/test/crossrunner/run.py
+++ b/test/crossrunner/run.py
@@ -235,7 +235,7 @@ def ensure_socket_open(sv, port, test):
logger.warn('[%s]: Detected socket bind failure, retrying...',
test.server.name)
bind_retry_count += 1
else:
- result = RESULT_TIMEOUT if cl.expired else cl.returncode if
cl.proc.poll() is not None else RESULT_ERROR
+ result = RESULT_TIMEOUT if cl.expired else cl.returncode if
(cl.proc and 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
diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json
index f7676498af..16ede27357 100644
--- a/test/known_failures_Linux.json
+++ b/test/known_failures_Linux.json
@@ -83,6 +83,46 @@
"cpp-nodejs_multij-json_http-domain",
"cpp-nodejs_multij-json_http-ip",
"cpp-nodejs_multij-json_http-ip-ssl",
+ "cpp-py3_binary-accel_http-ip",
+ "cpp-py3_binary-accel_http-ip-ssl",
+ "cpp-py3_binary_http-ip",
+ "cpp-py3_binary_http-ip-ssl",
+ "cpp-py3_compact-accelc_http-ip",
+ "cpp-py3_compact-accelc_http-ip-ssl",
+ "cpp-py3_compact_http-ip",
+ "cpp-py3_compact_http-ip-ssl",
+ "cpp-py3_json_http-ip",
+ "cpp-py3_json_http-ip-ssl",
+ "cpp-py3_multi-accel_http-ip",
+ "cpp-py3_multi-accel_http-ip-ssl",
+ "cpp-py3_multi-binary_http-ip",
+ "cpp-py3_multi-binary_http-ip-ssl",
+ "cpp-py3_multic-accelc_http-ip",
+ "cpp-py3_multic-accelc_http-ip-ssl",
+ "cpp-py3_multic-compact_http-ip",
+ "cpp-py3_multic-compact_http-ip-ssl",
+ "cpp-py3_multij-json_http-ip",
+ "cpp-py3_multij-json_http-ip-ssl",
+ "cpp-py_binary-accel_http-ip",
+ "cpp-py_binary-accel_http-ip-ssl",
+ "cpp-py_binary_http-ip",
+ "cpp-py_binary_http-ip-ssl",
+ "cpp-py_compact-accelc_http-ip",
+ "cpp-py_compact-accelc_http-ip-ssl",
+ "cpp-py_compact_http-ip",
+ "cpp-py_compact_http-ip-ssl",
+ "cpp-py_json_http-ip",
+ "cpp-py_json_http-ip-ssl",
+ "cpp-py_multi-accel_http-ip",
+ "cpp-py_multi-accel_http-ip-ssl",
+ "cpp-py_multi-binary_http-ip",
+ "cpp-py_multi-binary_http-ip-ssl",
+ "cpp-py_multic-accelc_http-ip",
+ "cpp-py_multic-accelc_http-ip-ssl",
+ "cpp-py_multic-compact_http-ip",
+ "cpp-py_multic-compact_http-ip-ssl",
+ "cpp-py_multij-json_http-ip",
+ "cpp-py_multij-json_http-ip-ssl",
"cpp-rs_multi_buffered-ip",
"cpp-rs_multi_framed-ip",
"cpp-rs_multic_buffered-ip",
@@ -166,42 +206,62 @@
"d-py3_binary-accel_buffered-ip-ssl",
"d-py3_binary-accel_framed-ip",
"d-py3_binary-accel_framed-ip-ssl",
+ "d-py3_binary-accel_http-ip",
+ "d-py3_binary-accel_http-ip-ssl",
"d-py3_binary_buffered-ip",
"d-py3_binary_buffered-ip-ssl",
"d-py3_binary_framed-ip",
"d-py3_binary_framed-ip-ssl",
+ "d-py3_binary_http-ip",
+ "d-py3_binary_http-ip-ssl",
"d-py3_compact-accelc_buffered-ip",
"d-py3_compact-accelc_buffered-ip-ssl",
"d-py3_compact-accelc_framed-ip",
"d-py3_compact-accelc_framed-ip-ssl",
+ "d-py3_compact-accelc_http-ip",
+ "d-py3_compact-accelc_http-ip-ssl",
"d-py3_compact_buffered-ip",
"d-py3_compact_buffered-ip-ssl",
"d-py3_compact_framed-ip",
"d-py3_compact_framed-ip-ssl",
+ "d-py3_compact_http-ip",
+ "d-py3_compact_http-ip-ssl",
"d-py3_json_buffered-ip",
"d-py3_json_buffered-ip-ssl",
"d-py3_json_framed-ip",
"d-py3_json_framed-ip-ssl",
+ "d-py3_json_http-ip",
+ "d-py3_json_http-ip-ssl",
"d-py_binary-accel_buffered-ip",
"d-py_binary-accel_buffered-ip-ssl",
"d-py_binary-accel_framed-ip",
"d-py_binary-accel_framed-ip-ssl",
+ "d-py_binary-accel_http-ip",
+ "d-py_binary-accel_http-ip-ssl",
"d-py_binary_buffered-ip",
"d-py_binary_buffered-ip-ssl",
"d-py_binary_framed-ip",
"d-py_binary_framed-ip-ssl",
+ "d-py_binary_http-ip",
+ "d-py_binary_http-ip-ssl",
"d-py_compact-accelc_buffered-ip",
"d-py_compact-accelc_buffered-ip-ssl",
"d-py_compact-accelc_framed-ip",
"d-py_compact-accelc_framed-ip-ssl",
+ "d-py_compact-accelc_http-ip",
+ "d-py_compact-accelc_http-ip-ssl",
"d-py_compact_buffered-ip",
"d-py_compact_buffered-ip-ssl",
"d-py_compact_framed-ip",
"d-py_compact_framed-ip-ssl",
+ "d-py_compact_http-ip",
+ "d-py_compact_http-ip-ssl",
"d-py_json_buffered-ip",
"d-py_json_buffered-ip-ssl",
"d-py_json_framed-ip",
"d-py_json_framed-ip-ssl",
+ "d-py_json_http-ip",
+ "d-py_json_http-ip-ssl",
"erl-cpp_binary_buffered-ip",
"erl-cpp_compact_buffered-ip",
"erl-csharp_binary_buffered-ip",
@@ -302,8 +362,118 @@
"nodejs-netcore_json_buffered-ip-ssl",
"nodejs-netcore_json_framed-ip",
"nodejs-netcore_json_framed-ip-ssl",
+ "nodejs-py3_binary-accel_http-ip",
+ "nodejs-py3_binary-accel_http-ip-ssl",
+ "nodejs-py3_binary_http-ip",
+ "nodejs-py3_binary_http-ip-ssl",
+ "nodejs-py3_compact-accelc_http-ip",
+ "nodejs-py3_compact-accelc_http-ip-ssl",
+ "nodejs-py3_compact_http-ip",
+ "nodejs-py3_compact_http-ip-ssl",
+ "nodejs-py3_json_http-ip",
+ "nodejs-py3_json_http-ip-ssl",
+ "nodejs-py_binary-accel_http-ip",
+ "nodejs-py_binary-accel_http-ip-ssl",
+ "nodejs-py_binary_http-ip",
+ "nodejs-py_binary_http-ip-ssl",
+ "nodejs-py_compact-accelc_http-ip",
+ "nodejs-py_compact-accelc_http-ip-ssl",
+ "nodejs-py_compact_http-ip",
+ "nodejs-py_compact_http-ip-ssl",
+ "nodejs-py_json_http-ip",
+ "nodejs-py_json_http-ip-ssl",
"perl-rs_multi_buffered-ip",
"perl-rs_multi_framed-ip",
+ "py-cpp_accel-binary_http-ip",
+ "py-cpp_accel-binary_http-ip-ssl",
+ "py-cpp_accelc-compact_http-ip",
+ "py-cpp_accelc-compact_http-ip-ssl",
+ "py-cpp_binary_http-ip",
+ "py-cpp_binary_http-ip-ssl",
+ "py-cpp_compact_http-ip",
+ "py-cpp_compact_http-ip-ssl",
+ "py-cpp_json_http-ip",
+ "py-cpp_json_http-ip-ssl",
+ "py-d_accel-binary_http-ip",
+ "py-d_accel-binary_http-ip-ssl",
+ "py-d_accelc-compact_http-ip",
+ "py-d_accelc-compact_http-ip-ssl",
+ "py-d_binary_http-ip",
+ "py-d_binary_http-ip-ssl",
+ "py-d_compact_http-ip",
+ "py-d_compact_http-ip-ssl",
+ "py-d_json_http-ip",
+ "py-d_json_http-ip-ssl",
+ "py-dart_accel-binary_http-ip",
+ "py-dart_accelc-compact_http-ip",
+ "py-dart_binary_http-ip",
+ "py-dart_compact_http-ip",
+ "py-dart_json_http-ip",
+ "py-hs_accel-binary_http-ip",
+ "py-hs_accelc-compact_http-ip",
+ "py-hs_binary_http-ip",
+ "py-hs_compact_http-ip",
+ "py-hs_json_http-ip",
+ "py-java_accel-binary_http-ip",
+ "py-java_accel-binary_http-ip-ssl",
+ "py-java_accelc-compact_http-ip",
+ "py-java_accelc-compact_http-ip-ssl",
+ "py-java_binary_http-ip",
+ "py-java_binary_http-ip-ssl",
+ "py-java_compact_http-ip",
+ "py-java_compact_http-ip-ssl",
+ "py-java_json_http-ip",
+ "py-java_json_http-ip-ssl",
+ "py-lua_accel-binary_http-ip",
+ "py-lua_accelc-compact_http-ip",
+ "py-lua_binary_http-ip",
+ "py-lua_compact_http-ip",
+ "py-lua_json_http-ip",
+ "py3-cpp_accel-binary_http-ip",
+ "py3-cpp_accel-binary_http-ip-ssl",
+ "py3-cpp_accelc-compact_http-ip",
+ "py3-cpp_accelc-compact_http-ip-ssl",
+ "py3-cpp_binary_http-ip",
+ "py3-cpp_binary_http-ip-ssl",
+ "py3-cpp_compact_http-ip",
+ "py3-cpp_compact_http-ip-ssl",
+ "py3-cpp_json_http-ip",
+ "py3-cpp_json_http-ip-ssl",
+ "py3-d_accel-binary_http-ip",
+ "py3-d_accel-binary_http-ip-ssl",
+ "py3-d_accelc-compact_http-ip",
+ "py3-d_accelc-compact_http-ip-ssl",
+ "py3-d_binary_http-ip",
+ "py3-d_binary_http-ip-ssl",
+ "py3-d_compact_http-ip",
+ "py3-d_compact_http-ip-ssl",
+ "py3-d_json_http-ip",
+ "py3-d_json_http-ip-ssl",
+ "py3-dart_accel-binary_http-ip",
+ "py3-dart_accelc-compact_http-ip",
+ "py3-dart_binary_http-ip",
+ "py3-dart_compact_http-ip",
+ "py3-dart_json_http-ip",
+ "py3-hs_accel-binary_http-ip",
+ "py3-hs_accelc-compact_http-ip",
+ "py3-hs_binary_http-ip",
+ "py3-hs_compact_http-ip",
+ "py3-hs_json_http-ip",
+ "py3-java_accel-binary_http-ip",
+ "py3-java_accel-binary_http-ip-ssl",
+ "py3-java_accelc-compact_http-ip",
+ "py3-java_accelc-compact_http-ip-ssl",
+ "py3-java_binary_http-ip",
+ "py3-java_binary_http-ip-ssl",
+ "py3-java_compact_http-ip",
+ "py3-java_compact_http-ip-ssl",
+ "py3-java_json_http-ip",
+ "py3-java_json_http-ip-ssl",
+ "py3-lua_accel-binary_http-ip",
+ "py3-lua_accelc-compact_http-ip",
+ "py3-lua_binary_http-ip",
+ "py3-lua_compact_http-ip",
+ "py3-lua_json_http-ip",
"rb-cpp_json_buffered-domain",
"rb-cpp_json_buffered-ip",
"rb-cpp_json_buffered-ip-ssl",
@@ -322,4 +492,4 @@
"rs-cpp_multic-compact_framed-ip",
"rs-cpp_multic_buffered-ip",
"rs-cpp_multic_framed-ip"
-]
+]
\ No newline at end of file
diff --git a/test/py/TestClient.py b/test/py/TestClient.py
index 1ab8e78aed..edab610b15 100755
--- a/test/py/TestClient.py
+++ b/test/py/TestClient.py
@@ -32,8 +32,18 @@
class AbstractTest(unittest.TestCase):
def setUp(self):
- if options.http_path:
- self.transport = THttpClient.THttpClient(options.host,
port=options.port, path=options.http_path)
+ if options.trans == 'http':
+ uri = '{0}://{1}:{2}{3}'.format(('https' if options.ssl else
'http'),
+ options.host,
+ options.port,
+ (options.http_path if
options.http_path else '/'))
+ if options.ssl:
+ __cafile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys",
"CA.pem")
+ __certfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys",
"client.crt")
+ __keyfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys",
"client.key")
+ self.transport = THttpClient.THttpClient(uri, cafile=__cafile,
cert_file=__certfile, key_file=__keyfile)
+ else:
+ self.transport = THttpClient.THttpClient(uri)
else:
if options.ssl:
from thrift.transport import TSSLSocket
@@ -325,9 +335,9 @@ def parseArgs(self, argv):
dest="verbose", const=0,
help="minimal output")
parser.add_option('--protocol', dest="proto", type="string",
- help="protocol to use, one of: accel, binary, compact,
json")
+ help="protocol to use, one of: accel, accelc, binary,
compact, json")
parser.add_option('--transport', dest="trans", type="string",
- help="transport to use, one of: buffered, framed")
+ help="transport to use, one of: buffered, framed, http")
parser.set_defaults(framed=False, http_path=None, verbose=1,
host='localhost', port=9090, proto='binary')
options, args = parser.parse_args()
@@ -335,6 +345,9 @@ def parseArgs(self, argv):
sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir))
sys.path.insert(0, local_libpath())
+ if options.http_path:
+ options.trans = 'http'
+
from ThriftTest import ThriftTest
from ThriftTest.ttypes import Xtruct, Xtruct2, Numberz, Xception, Xception2
from thrift.Thrift import TException
diff --git a/test/py/TestServer.py b/test/py/TestServer.py
index 04ad62a955..4dc4c0744e 100755
--- a/test/py/TestServer.py
+++ b/test/py/TestServer.py
@@ -21,6 +21,7 @@
from __future__ import division
import logging
import os
+import signal
import sys
import time
from optparse import OptionParser
@@ -180,11 +181,11 @@ def testMulti(self, arg0, arg1, arg2, arg3, arg4, arg5):
def main(options):
# set up the protocol factory form the --protocol option
prot_factories = {
- 'binary': TBinaryProtocol.TBinaryProtocolFactory,
'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory,
- 'compact': TCompactProtocol.TCompactProtocolFactory,
'accelc': TCompactProtocol.TCompactProtocolAcceleratedFactory,
- 'json': TJSONProtocol.TJSONProtocolFactory,
+ 'binary': TBinaryProtocol.TBinaryProtocolFactory,
+ 'compact': TCompactProtocol.TCompactProtocolFactory,
+ 'json': TJSONProtocol.TJSONProtocolFactory
}
pfactory_cls = prot_factories.get(options.proto, None)
if pfactory_cls is None:
@@ -201,14 +202,23 @@ def main(options):
if len(args) > 1:
raise AssertionError('Only one server type may be specified, not
multiple types.')
server_type = args[0]
+ if options.trans == 'http':
+ server_type = 'THttpServer'
# Set up the handler and processor objects
handler = TestHandler()
processor = ThriftTest.Processor(handler)
+ global server
+
# Handle THttpServer as a special case
if server_type == 'THttpServer':
- server = THttpServer.THttpServer(processor, ('', options.port),
pfactory)
+ if options.ssl:
+ __certfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys",
"server.crt")
+ __keyfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys",
"server.key")
+ server = THttpServer.THttpServer(processor, ('', options.port),
pfactory, cert_file=__certfile, key_file=__keyfile)
+ else:
+ server = THttpServer.THttpServer(processor, ('', options.port),
pfactory)
server.serve()
sys.exit(0)
@@ -268,7 +278,15 @@ def clean_shutdown(signum, frame):
server.serve()
+def exit_gracefully(signum, frame):
+ print("SIGINT received\n")
+ server.shutdown() # doesn't work properly, yet
+ sys.exit(0)
+
+
if __name__ == '__main__':
+ signal.signal(signal.SIGINT, exit_gracefully)
+
parser = OptionParser()
parser.add_option('--libpydir', type='string', dest='libpydir',
help='include this directory to sys.path for locating
library code')
@@ -288,12 +306,12 @@ def clean_shutdown(signum, frame):
dest="verbose", const=0,
help="minimal output")
parser.add_option('--protocol', dest="proto", type="string",
- help="protocol to use, one of: accel, binary, compact,
json")
+ help="protocol to use, one of: accel, accelc, binary,
compact, json")
parser.add_option('--transport', dest="trans", type="string",
- help="transport to use, one of: buffered, framed")
+ help="transport to use, one of: buffered, framed, http")
parser.add_option('--container-limit', dest='container_limit', type='int',
default=None)
parser.add_option('--string-limit', dest='string_limit', type='int',
default=None)
- parser.set_defaults(port=9090, verbose=1, proto='binary')
+ parser.set_defaults(port=9090, verbose=1, proto='binary',
transport='buffered')
options, args = parser.parse_args()
# Print TServer log to stdout so that the test-runner can redirect it to
log files
diff --git a/test/test.py b/test/test.py
index 24e7c4e47b..f59256a26e 100755
--- a/test/test.py
+++ b/test/test.py
@@ -52,7 +52,7 @@
CONFIG_FILE = 'tests.json'
-def run_cross_tests(server_match, client_match, jobs, skip_known_failures,
retry_count, regex):
+def run_cross_tests(server_match, client_match, jobs, skip_known_failures,
only_known_failures, retry_count, regex):
logger = multiprocessing.get_logger()
logger.debug('Collecting tests')
with open(path_join(TEST_DIR, CONFIG_FILE), 'r') as fp:
@@ -63,6 +63,10 @@ def run_cross_tests(server_match, client_match, jobs,
skip_known_failures, retry
print(' servers: %s' % server_match, file=sys.stderr)
print(' clients: %s' % client_match, file=sys.stderr)
return False
+ if only_known_failures:
+ logger.debug('Only running known failures')
+ known = crossrunner.load_known_failures(TEST_DIR)
+ tests = list(filter(lambda t: crossrunner.test_name(**t) in known,
tests))
if skip_known_failures:
logger.debug('Skipping known failures')
known = crossrunner.load_known_failures(TEST_DIR)
@@ -81,7 +85,7 @@ def run_cross_tests(server_match, client_match, jobs,
skip_known_failures, retry
return False
-def run_feature_tests(server_match, feature_match, jobs, skip_known_failures,
retry_count, regex):
+def run_feature_tests(server_match, feature_match, jobs, skip_known_failures,
only_known_failures, retry_count, regex):
basedir = path_join(ROOT_DIR, FEATURE_DIR_RELATIVE)
logger = multiprocessing.get_logger()
logger.debug('Collecting tests')
@@ -95,6 +99,10 @@ def run_feature_tests(server_match, feature_match, jobs,
skip_known_failures, re
print(' servers: %s' % server_match, file=sys.stderr)
print(' features: %s' % feature_match, file=sys.stderr)
return False
+ if only_known_failures:
+ logger.debug('Only running known failures')
+ known = crossrunner.load_known_failures(basedir)
+ tests = list(filter(lambda t: crossrunner.test_name(**t) in known,
tests))
if skip_known_failures:
logger.debug('Skipping known failures')
known = crossrunner.load_known_failures(basedir)
@@ -130,6 +138,8 @@ def main(argv):
parser.add_argument('-F', '--features', nargs='*', default=None,
help='run server feature tests instead of cross
language tests')
parser.add_argument('-R', '--regex', help='test name pattern to run')
+ parser.add_argument('-o', '--only-known_failures', action='store_true',
dest='only_known_failures',
+ help='only execute tests that are known to fail')
parser.add_argument('-s', '--skip-known-failures', action='store_true',
dest='skip_known_failures',
help='do not execute tests that are known to fail')
parser.add_argument('-r', '--retry-count', type=int,
@@ -169,10 +179,12 @@ def main(argv):
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)
+ options.skip_known_failures,
options.only_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)
+ options.skip_known_failures,
options.only_known_failures,
+ options.retry_count, options.regex)
return 0 if res else 1
diff --git a/test/tests.json b/test/tests.json
index 4641f223b8..ed38fea3b0 100644
--- a/test/tests.json
+++ b/test/tests.json
@@ -64,7 +64,7 @@
"server": {
"command": [
"thrift_test_server",
- "--trace"
+ "--trace"
]
},
"client": {
@@ -254,7 +254,8 @@
},
"transports": [
"buffered",
- "framed"
+ "framed",
+ "http"
],
"sockets": [
"ip",
@@ -292,11 +293,12 @@
},
"transports": [
"buffered",
- "framed"
+ "framed",
+ "http"
],
"sockets": [
- "ip-ssl",
- "ip"
+ "ip",
+ "ip-ssl"
],
"protocols": [
"compact",
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> Python MemoryError in THttpClient when using an SSL endpoint
> ------------------------------------------------------------
>
> Key: THRIFT-3118
> URL: https://issues.apache.org/jira/browse/THRIFT-3118
> Project: Thrift
> Issue Type: Bug
> Components: Python - Library
> Affects Versions: 0.9
> Reporter: Jean-Baptiste Quenot
> Assignee: James E. King, III
> Priority: Major
>
> When using the Python Thrift HTTP client, a MemoryError is raised by the
> underlying socket when using SSL:
> {noformat}
> File
> "/path/to/local/lib/python2.7/site-packages/thrift/transport/THttpClient.py",
> line 116, in read
> return self.__http.file.read(sz)
> File "/usr/lib/python2.7/socket.py", line 380, in read
> data = self._sock.recv(left)
> File "/usr/lib/python2.7/ssl.py", line 241, in recv
> return self.read(buflen)
> File "/usr/lib/python2.7/ssl.py", line 160, in read
> return self._sslobj.read(len)
> MemoryError
> {noformat}
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)