summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames E. King III <jking@apache.org>2018-03-24 16:32:02 -0400
committerJames E. King III <jking@apache.org>2018-04-05 10:25:19 -0400
commit6f8c99e98170dcd4f311e755b79f7013868c64c5 (patch)
tree0d8a7a41c707815ed86d624bf81be5317a70185b
parenta0cf38ed312a5342eb05574719485b725fa52eee (diff)
downloadthrift-6f8c99e98170dcd4f311e755b79f7013868c64c5.tar.gz
THRIFT-3118: add http (for non-ssl and for ssl) to the python cross tests
-rwxr-xr-xbuild/docker/scripts/sca.sh6
-rw-r--r--lib/py/src/server/THttpServer.py23
-rw-r--r--lib/py/src/transport/THttpClient.py32
-rw-r--r--test/crossrunner/run.py2
-rw-r--r--test/known_failures_Linux.json172
-rwxr-xr-xtest/py/TestClient.py21
-rwxr-xr-xtest/py/TestServer.py32
-rwxr-xr-xtest/test.py20
-rw-r--r--test/tests.json12
9 files changed, 283 insertions, 37 deletions
diff --git a/build/docker/scripts/sca.sh b/build/docker/scripts/sca.sh
index f17f7035d..f26ce9556 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 1b501a7aa..85cf4005e 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 @@ class THttpServer(TServer.TServer):
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 @@ class THttpServer(TServer.TServer):
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 fb33421d7..60ff226a9 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 @@ import six
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 @@ class THttpClient(TTransportBase):
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 @@ class THttpClient(TTransportBase):
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 25c58cef3..a7bc939ea 100644
--- a/test/crossrunner/run.py
+++ b/test/crossrunner/run.py
@@ -235,7 +235,7 @@ def run_test(testdir, logdir, test_dict, max_retry, async=True):
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 f7676498a..16ede2735 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 1ab8e78ae..edab610b1 100755
--- a/test/py/TestClient.py
+++ b/test/py/TestClient.py
@@ -32,8 +32,18 @@ SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
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 @@ if __name__ == "__main__":
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 @@ if __name__ == "__main__":
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 04ad62a95..4dc4c0744 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 @@ class TestHandler(object):
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 main(options):
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 @@ if __name__ == '__main__':
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 24e7c4e47..f59256a26 100755
--- a/test/test.py
+++ b/test/test.py
@@ -52,7 +52,7 @@ FEATURE_DIR_RELATIVE = path_join(TEST_DIR_RELATIVE, 'features')
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 4641f223b..ed38fea3b 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",