[ 
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:
us...@infra.apache.org


> 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)

Reply via email to