THRIFT-3531 Create cross lang feature test for string and container read length limit
This closes #780
diff --git a/test/features/container_limit.py b/test/features/container_limit.py
new file mode 100644
index 0000000..4a7da60
--- /dev/null
+++ b/test/features/container_limit.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+
+from util import add_common_args, init_protocol
+from local_thrift import thrift
+from thrift.Thrift import TMessageType, TType
+
+
+# TODO: generate from ThriftTest.thrift
+def test_list(proto, value):
+ method_name = 'testList'
+ ttype = TType.LIST
+ etype = TType.I32
+ proto.writeMessageBegin(method_name, TMessageType.CALL, 3)
+ proto.writeStructBegin(method_name + '_args')
+ proto.writeFieldBegin('thing', ttype, 1)
+ proto.writeListBegin(etype, len(value))
+ for e in value:
+ proto.writeI32(e)
+ proto.writeListEnd()
+ proto.writeFieldEnd()
+ proto.writeFieldStop()
+ proto.writeStructEnd()
+ proto.writeMessageEnd()
+ proto.trans.flush()
+
+ _, mtype, _ = proto.readMessageBegin()
+ assert mtype == TMessageType.REPLY
+ proto.readStructBegin()
+ _, ftype, fid = proto.readFieldBegin()
+ assert fid == 0
+ assert ftype == ttype
+ etype2, len2 = proto.readListBegin()
+ assert etype == etype2
+ assert len2 == len(value)
+ for i in range(len2):
+ v = proto.readI32()
+ assert v == value[i]
+ proto.readListEnd()
+ proto.readFieldEnd()
+ _, ftype, _ = proto.readFieldBegin()
+ assert ftype == TType.STOP
+ proto.readStructEnd()
+ proto.readMessageEnd()
+
+
+def main(argv):
+ p = argparse.ArgumentParser()
+ add_common_args(p)
+ p.add_argument('--limit', type=int)
+ args = p.parse_args()
+ proto = init_protocol(args)
+ # TODO: test set and map
+ test_list(proto, list(range(args.limit - 1)))
+ test_list(proto, list(range(args.limit - 1)))
+ print('[OK]: limit - 1')
+ test_list(proto, list(range(args.limit)))
+ test_list(proto, list(range(args.limit)))
+ print('[OK]: just limit')
+ try:
+ test_list(proto, list(range(args.limit + 1)))
+ except:
+ print('[OK]: limit + 1')
+ else:
+ print('[ERROR]: limit + 1')
+ assert False
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/test/features/known_failures_Linux.json b/test/features/known_failures_Linux.json
new file mode 100644
index 0000000..edff41a
--- /dev/null
+++ b/test/features/known_failures_Linux.json
@@ -0,0 +1,46 @@
+[
+ "c_glib-limit_container_length_binary_buffered-ip",
+ "c_glib-limit_string_length_binary_buffered-ip",
+ "csharp-limit_container_length_binary_buffered-ip",
+ "csharp-limit_container_length_compact_buffered-ip",
+ "csharp-limit_string_length_binary_buffered-ip",
+ "csharp-limit_string_length_compact_buffered-ip",
+ "erl-limit_container_length_binary_buffered-ip",
+ "erl-limit_container_length_compact_buffered-ip",
+ "erl-limit_string_length_binary_buffered-ip",
+ "erl-limit_string_length_compact_buffered-ip",
+ "go-limit_container_length_binary_buffered-ip",
+ "go-limit_container_length_compact_buffered-ip",
+ "go-limit_string_length_binary_buffered-ip",
+ "go-limit_string_length_compact_buffered-ip",
+ "hs-limit_container_length_binary_buffered-ip",
+ "hs-limit_container_length_compact_buffered-ip",
+ "hs-limit_string_length_binary_buffered-ip",
+ "hs-limit_string_length_compact_buffered-ip",
+ "java-limit_container_length_binary_buffered-ip",
+ "java-limit_container_length_compact_buffered-ip",
+ "java-limit_string_length_binary_buffered-ip",
+ "java-limit_string_length_compact_buffered-ip",
+ "nodejs-limit_container_length_binary_buffered-ip",
+ "nodejs-limit_container_length_compact_buffered-ip",
+ "nodejs-limit_string_length_binary_buffered-ip",
+ "nodejs-limit_string_length_compact_buffered-ip",
+ "perl-limit_container_length_binary_buffered-ip",
+ "perl-limit_string_length_binary_buffered-ip",
+ "py-limit_container_length_accel-binary_buffered-ip",
+ "py-limit_container_length_binary_buffered-ip",
+ "py-limit_container_length_compact_buffered-ip",
+ "py-limit_string_length_accel-binary_buffered-ip",
+ "py-limit_string_length_binary_buffered-ip",
+ "py-limit_string_length_compact_buffered-ip",
+ "py3-limit_container_length_binary_buffered-ip",
+ "py3-limit_container_length_compact_buffered-ip",
+ "py3-limit_string_length_binary_buffered-ip",
+ "py3-limit_string_length_compact_buffered-ip",
+ "rb-limit_container_length_accel-binary_buffered-ip",
+ "rb-limit_container_length_binary_buffered-ip",
+ "rb-limit_container_length_compact_buffered-ip",
+ "rb-limit_string_length_accel-binary_buffered-ip",
+ "rb-limit_string_length_binary_buffered-ip",
+ "rb-limit_string_length_compact_buffered-ip"
+]
\ No newline at end of file
diff --git a/test/features/string_limit.py b/test/features/string_limit.py
new file mode 100644
index 0000000..b4d48ac
--- /dev/null
+++ b/test/features/string_limit.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+
+from util import add_common_args, init_protocol
+from local_thrift import thrift
+from thrift.Thrift import TMessageType, TType
+
+
+# TODO: generate from ThriftTest.thrift
+def test_string(proto, value):
+ method_name = 'testString'
+ ttype = TType.STRING
+ proto.writeMessageBegin(method_name, TMessageType.CALL, 3)
+ proto.writeStructBegin(method_name + '_args')
+ proto.writeFieldBegin('thing', ttype, 1)
+ proto.writeString(value)
+ proto.writeFieldEnd()
+ proto.writeFieldStop()
+ proto.writeStructEnd()
+ proto.writeMessageEnd()
+ proto.trans.flush()
+
+ _, mtype, _ = proto.readMessageBegin()
+ assert mtype == TMessageType.REPLY
+ proto.readStructBegin()
+ _, ftype, fid = proto.readFieldBegin()
+ assert fid == 0
+ assert ftype == ttype
+ result = proto.readString()
+ proto.readFieldEnd()
+ _, ftype, _ = proto.readFieldBegin()
+ assert ftype == TType.STOP
+ proto.readStructEnd()
+ proto.readMessageEnd()
+ assert value == result
+
+
+def main(argv):
+ p = argparse.ArgumentParser()
+ add_common_args(p)
+ p.add_argument('--limit', type=int)
+ args = p.parse_args()
+ proto = init_protocol(args)
+ test_string(proto, 'a' * (args.limit - 1))
+ test_string(proto, 'a' * (args.limit - 1))
+ print('[OK]: limit - 1')
+ test_string(proto, 'a' * args.limit)
+ test_string(proto, 'a' * args.limit)
+ print('[OK]: just limit')
+ try:
+ test_string(proto, 'a' * (args.limit + 1))
+ except:
+ print('[OK]: limit + 1')
+ else:
+ print('[ERROR]: limit + 1')
+ assert False
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/test/features/tests.json b/test/features/tests.json
index 0836309..f726dad 100644
--- a/test/features/tests.json
+++ b/test/features/tests.json
@@ -23,5 +23,41 @@
"transports": ["buffered"],
"sockets": ["ip"],
"workdir": "features"
+ },
+ {
+ "name": "limit_string_length",
+ "command": [
+ "python",
+ "string_limit.py",
+ "--limit=50"
+ ],
+ "remote_args": [
+ "--string-limit=50"
+ ],
+ "protocols": [
+ "binary",
+ "compact"
+ ],
+ "transports": ["buffered"],
+ "sockets": ["ip"],
+ "workdir": "features"
+ },
+ {
+ "name": "limit_container_length",
+ "command": [
+ "python",
+ "container_limit.py",
+ "--limit=50"
+ ],
+ "remote_args": [
+ "--container-limit=50"
+ ],
+ "protocols": [
+ "binary",
+ "compact"
+ ],
+ "transports": ["buffered"],
+ "sockets": ["ip"],
+ "workdir": "features"
}
]
diff --git a/test/features/util.py b/test/features/util.py
index cff7ff8..e364136 100644
--- a/test/features/util.py
+++ b/test/features/util.py
@@ -1,11 +1,20 @@
import argparse
+import socket
+
+from local_thrift import thrift
+from thrift.transport.TSocket import TSocket
+from thrift.transport.TTransport import TBufferedTransport, TFramedTransport
+from thrift.transport.THttpClient import THttpClient
+from thrift.protocol.TBinaryProtocol import TBinaryProtocol
+from thrift.protocol.TCompactProtocol import TCompactProtocol
+from thrift.protocol.TJSONProtocol import TJSONProtocol
def add_common_args(p):
p.add_argument('--host', default='localhost')
- p.add_argument('--port', type=int)
- p.add_argument('--protocol')
- p.add_argument('--transport')
+ p.add_argument('--port', type=int, default=9090)
+ p.add_argument('--protocol', default='binary')
+ p.add_argument('--transport', default='buffered')
p.add_argument('--ssl', action='store_true')
@@ -13,3 +22,19 @@
p = argparse.ArgumentParser()
add_common_args(p)
return p.parse_args(argv)
+
+
+def init_protocol(args):
+ sock = TSocket(args.host, args.port, socket_family=socket.AF_INET)
+ sock.setTimeout(500)
+ trans = {
+ 'buffered': TBufferedTransport,
+ 'framed': TFramedTransport,
+ 'http': THttpClient,
+ }[args.transport](sock)
+ trans.open()
+ return {
+ 'binary': TBinaryProtocol,
+ 'compact': TCompactProtocol,
+ 'json': TJSONProtocol,
+ }[args.protocol](trans)