THRIFT-3361 Improve C# library
Client: C#
Patch: Nobuaki Sukegawa <nsukeg@gmail.com>
This closes #630
diff --git a/lib/csharp/Makefile.am b/lib/csharp/Makefile.am
index 611405d..a8b275e 100644
--- a/lib/csharp/Makefile.am
+++ b/lib/csharp/Makefile.am
@@ -87,7 +87,7 @@
clean-local:
$(RM) Thrift.dll
-precross:
+precross: all-local
$(MAKE) -C test/ThriftTest precross
# run csharp tests?
diff --git a/lib/csharp/src/Transport/TBufferedTransport.cs b/lib/csharp/src/Transport/TBufferedTransport.cs
index 89b9ca7..e88800f 100644
--- a/lib/csharp/src/Transport/TBufferedTransport.cs
+++ b/lib/csharp/src/Transport/TBufferedTransport.cs
@@ -22,105 +22,144 @@
namespace Thrift.Transport
{
- public class TBufferedTransport : TTransport, IDisposable
+ public class TBufferedTransport : TTransport, IDisposable
{
- private BufferedStream inputBuffer;
- private BufferedStream outputBuffer;
- private int bufSize;
- private TStreamTransport transport;
+ private readonly int bufSize;
+ private readonly MemoryStream inputBuffer = new MemoryStream(0);
+ private readonly MemoryStream outputBuffer = new MemoryStream(0);
+ private readonly TTransport transport;
- public TBufferedTransport(TStreamTransport transport)
- :this(transport, 1024)
+ public TBufferedTransport(TTransport transport, int bufSize = 1024)
{
-
- }
-
- public TBufferedTransport(TStreamTransport transport, int bufSize)
- {
- this.bufSize = bufSize;
+ if (transport == null)
+ throw new ArgumentNullException("transport");
+ if (bufSize <= 0)
+ throw new ArgumentException("bufSize", "Buffer size must be a positive number.");
this.transport = transport;
- InitBuffers();
- }
-
- private void InitBuffers()
- {
- if (transport.InputStream != null)
- {
- inputBuffer = new BufferedStream(transport.InputStream, bufSize);
- }
- if (transport.OutputStream != null)
- {
- outputBuffer = new BufferedStream(transport.OutputStream, bufSize);
- }
- }
-
- private void CloseBuffers()
- {
- if (inputBuffer != null && inputBuffer.CanRead)
- {
- inputBuffer.Close();
- }
- if (outputBuffer != null && outputBuffer.CanWrite)
- {
- outputBuffer.Close();
- }
+ this.bufSize = bufSize;
}
public TTransport UnderlyingTransport
{
- get { return transport; }
+ get
+ {
+ CheckNotDisposed();
+ return transport;
+ }
}
public override bool IsOpen
{
- get { return transport.IsOpen; }
+ get
+ {
+ // We can legitimately throw here but be nice a bit.
+ // CheckNotDisposed();
+ return !_IsDisposed && transport.IsOpen;
+ }
}
public override void Open()
{
+ CheckNotDisposed();
transport.Open();
- InitBuffers();
}
public override void Close()
{
- CloseBuffers();
+ CheckNotDisposed();
transport.Close();
}
public override int Read(byte[] buf, int off, int len)
{
- return inputBuffer.Read(buf, off, len);
+ CheckNotDisposed();
+ ValidateBufferArgs(buf, off, len);
+ if (!IsOpen)
+ throw new InvalidOperationException("Transport is not open.");
+ if (inputBuffer.Capacity < bufSize)
+ inputBuffer.Capacity = bufSize;
+ int got = inputBuffer.Read(buf, off, len);
+ if (got > 0)
+ return got;
+
+ inputBuffer.Seek(0, SeekOrigin.Begin);
+ inputBuffer.SetLength(inputBuffer.Capacity);
+ int filled = transport.Read(inputBuffer.GetBuffer(), 0, (int)inputBuffer.Length);
+ inputBuffer.SetLength(filled);
+ if (filled == 0)
+ return 0;
+ return Read(buf, off, len);
}
public override void Write(byte[] buf, int off, int len)
{
- outputBuffer.Write(buf, off, len);
+ CheckNotDisposed();
+ ValidateBufferArgs(buf, off, len);
+ if (!IsOpen)
+ throw new InvalidOperationException("Transport is not open.");
+ // Relative offset from "off" argument
+ int offset = 0;
+ if (outputBuffer.Length > 0)
+ {
+ int capa = (int)(outputBuffer.Capacity - outputBuffer.Length);
+ int writeSize = capa <= len ? capa : len;
+ outputBuffer.Write(buf, off, writeSize);
+ offset += writeSize;
+ if (writeSize == capa)
+ {
+ transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length);
+ outputBuffer.SetLength(0);
+ }
+ }
+ while (len - offset >= bufSize)
+ {
+ transport.Write(buf, off + offset, bufSize);
+ offset += bufSize;
+ }
+ int remain = len - offset;
+ if (remain > 0)
+ {
+ if (outputBuffer.Capacity < bufSize)
+ outputBuffer.Capacity = bufSize;
+ outputBuffer.Write(buf, off + offset, remain);
+ }
}
public override void Flush()
{
- outputBuffer.Flush();
+ CheckNotDisposed();
+ if (!IsOpen)
+ throw new InvalidOperationException("Transport is not open.");
+ if (outputBuffer.Length > 0)
+ {
+ transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length);
+ outputBuffer.SetLength(0);
+ }
+ transport.Flush();
}
- #region " IDisposable Support "
- private bool _IsDisposed;
-
- // IDisposable
- protected override void Dispose(bool disposing)
- {
- if (!_IsDisposed)
- {
- if (disposing)
+ private void CheckNotDisposed()
{
- if (inputBuffer != null)
- inputBuffer.Dispose();
- if (outputBuffer != null)
- outputBuffer.Dispose();
+ if (_IsDisposed)
+ throw new ObjectDisposedException("TBufferedTransport");
}
- }
- _IsDisposed = true;
+
+ #region " IDisposable Support "
+ private bool _IsDisposed;
+
+ // IDisposable
+ protected override void Dispose(bool disposing)
+ {
+ if (!_IsDisposed)
+ {
+ if (disposing)
+ {
+ inputBuffer.Dispose();
+ outputBuffer.Dispose();
+ }
+ }
+ _IsDisposed = true;
+ }
+ #endregion
}
- #endregion
- }
}
diff --git a/lib/csharp/src/Transport/TFramedTransport.cs b/lib/csharp/src/Transport/TFramedTransport.cs
index 8af227f..9c6a794 100644
--- a/lib/csharp/src/Transport/TFramedTransport.cs
+++ b/lib/csharp/src/Transport/TFramedTransport.cs
@@ -21,14 +21,14 @@
namespace Thrift.Transport
{
- public class TFramedTransport : TTransport, IDisposable
+ public class TFramedTransport : TTransport, IDisposable
{
- protected TTransport transport = null;
- protected MemoryStream writeBuffer;
- protected MemoryStream readBuffer = null;
+ private readonly TTransport transport;
+ private readonly MemoryStream writeBuffer = new MemoryStream(1024);
+ private readonly MemoryStream readBuffer = new MemoryStream(1024);
- private const int header_size = 4;
- private static byte[] header_dummy = new byte[header_size]; // used as header placeholder while initilizing new write buffer
+ private const int HeaderSize = 4;
+ private readonly byte[] headerBuf = new byte[HeaderSize];
public class Factory : TTransportFactory
{
@@ -38,18 +38,17 @@
}
}
- protected TFramedTransport()
+ public TFramedTransport(TTransport transport)
{
- InitWriteBuffer();
- }
-
- public TFramedTransport(TTransport transport) : this()
- {
+ if (transport == null)
+ throw new ArgumentNullException("transport");
this.transport = transport;
+ InitWriteBuffer();
}
public override void Open()
{
+ CheckNotDisposed();
transport.Open();
}
@@ -57,24 +56,28 @@
{
get
{
- return transport.IsOpen;
+ // We can legitimately throw here but be nice a bit.
+ // CheckNotDisposed();
+ return !_IsDisposed && transport.IsOpen;
}
}
public override void Close()
{
+ CheckNotDisposed();
transport.Close();
}
public override int Read(byte[] buf, int off, int len)
{
- if (readBuffer != null)
+ CheckNotDisposed();
+ ValidateBufferArgs(buf, off, len);
+ if (!IsOpen)
+ throw new InvalidOperationException("Transport is not open.");
+ int got = readBuffer.Read(buf, off, len);
+ if (got > 0)
{
- int got = readBuffer.Read(buf, off, len);
- if (got > 0)
- {
- return got;
- }
+ return got;
}
// Read another frame of data
@@ -85,49 +88,56 @@
private void ReadFrame()
{
- byte[] i32rd = new byte[header_size];
- transport.ReadAll(i32rd, 0, header_size);
- int size = DecodeFrameSize(i32rd);
+ transport.ReadAll(headerBuf, 0, HeaderSize);
+ int size = DecodeFrameSize(headerBuf);
- byte[] buff = new byte[size];
+ readBuffer.SetLength(size);
+ readBuffer.Seek(0, SeekOrigin.Begin);
+ byte[] buff = readBuffer.GetBuffer();
transport.ReadAll(buff, 0, size);
- readBuffer = new MemoryStream(buff);
}
public override void Write(byte[] buf, int off, int len)
{
+ CheckNotDisposed();
+ ValidateBufferArgs(buf, off, len);
+ if (!IsOpen)
+ throw new InvalidOperationException("Transport is not open.");
+ if (writeBuffer.Length + (long)len > (long)int.MaxValue)
+ Flush();
writeBuffer.Write(buf, off, len);
}
public override void Flush()
{
+ CheckNotDisposed();
+ if (!IsOpen)
+ throw new InvalidOperationException("Transport is not open.");
byte[] buf = writeBuffer.GetBuffer();
int len = (int)writeBuffer.Length;
- int data_len = len - header_size;
+ int data_len = len - HeaderSize;
if ( data_len < 0 )
throw new System.InvalidOperationException (); // logic error actually
- InitWriteBuffer();
-
// Inject message header into the reserved buffer space
- EncodeFrameSize(data_len,ref buf);
+ EncodeFrameSize(data_len, buf);
// Send the entire message at once
transport.Write(buf, 0, len);
+ InitWriteBuffer();
+
transport.Flush();
}
private void InitWriteBuffer ()
{
- // Create new buffer instance
- writeBuffer = new MemoryStream(1024);
-
// Reserve space for message header to be put right before sending it out
- writeBuffer.Write ( header_dummy, 0, header_size );
+ writeBuffer.SetLength(HeaderSize);
+ writeBuffer.Seek(0, SeekOrigin.End);
}
- private static void EncodeFrameSize(int frameSize, ref byte[] buf)
+ private static void EncodeFrameSize(int frameSize, byte[] buf)
{
buf[0] = (byte)(0xff & (frameSize >> 24));
buf[1] = (byte)(0xff & (frameSize >> 16));
@@ -145,6 +155,12 @@
}
+ private void CheckNotDisposed()
+ {
+ if (_IsDisposed)
+ throw new ObjectDisposedException("TFramedTransport");
+ }
+
#region " IDisposable Support "
private bool _IsDisposed;
@@ -155,8 +171,8 @@
{
if (disposing)
{
- if (readBuffer != null)
- readBuffer.Dispose();
+ readBuffer.Dispose();
+ writeBuffer.Dispose();
}
}
_IsDisposed = true;
diff --git a/lib/csharp/src/Transport/TTLSSocket.cs b/lib/csharp/src/Transport/TTLSSocket.cs
index 5652556..833b792 100644
--- a/lib/csharp/src/Transport/TTLSSocket.cs
+++ b/lib/csharp/src/Transport/TTLSSocket.cs
@@ -33,43 +33,43 @@
/// <summary>
/// Internal TCP Client
/// </summary>
- private TcpClient client = null;
+ private TcpClient client;
/// <summary>
/// The host
/// </summary>
- private string host = null;
+ private string host;
/// <summary>
/// The port
/// </summary>
- private int port = 0;
+ private int port;
/// <summary>
/// The timeout for the connection
/// </summary>
- private int timeout = 0;
+ private int timeout;
/// <summary>
/// Internal SSL Stream for IO
/// </summary>
- private SslStream secureStream = null;
+ private SslStream secureStream;
/// <summary>
/// Defines wheter or not this socket is a server socket<br/>
/// This is used for the TLS-authentication
/// </summary>
- private bool isServer = false;
+ private bool isServer;
/// <summary>
/// The certificate
/// </summary>
- private X509Certificate certificate = null;
+ private X509Certificate certificate;
/// <summary>
/// User defined certificate validator.
/// </summary>
- private RemoteCertificateValidationCallback certValidator = null;
+ private RemoteCertificateValidationCallback certValidator;
/// <summary>
/// The function to determine which certificate to use.
@@ -96,6 +96,10 @@
this.certValidator = certValidator;
this.localCertificateSelectionCallback = localCertificateSelectionCallback;
this.isServer = isServer;
+ if (isServer && certificate == null)
+ {
+ throw new ArgumentException("TTLSSocket needs certificate to be used for server", "certificate");
+ }
if (IsOpen)
{
@@ -133,7 +137,7 @@
public TTLSSocket(
string host,
int port,
- X509Certificate certificate,
+ X509Certificate certificate = null,
RemoteCertificateValidationCallback certValidator = null,
LocalCertificateSelectionCallback localCertificateSelectionCallback = null)
: this(host, port, 0, certificate, certValidator, localCertificateSelectionCallback)
@@ -315,7 +319,8 @@
else
{
// Client authentication
- this.secureStream.AuthenticateAsClient(host, new X509CertificateCollection { certificate }, SslProtocols.Tls, true);
+ X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection();
+ this.secureStream.AuthenticateAsClient(host, certs, SslProtocols.Tls, true);
}
}
catch (Exception)
diff --git a/lib/csharp/src/Transport/TTransport.cs b/lib/csharp/src/Transport/TTransport.cs
index 2811399..a3639d2 100644
--- a/lib/csharp/src/Transport/TTransport.cs
+++ b/lib/csharp/src/Transport/TTransport.cs
@@ -34,7 +34,7 @@
}
private byte[] _peekBuffer = new byte[1];
- private bool _hasPeekByte = false;
+ private bool _hasPeekByte;
public bool Peek()
{
@@ -66,10 +66,23 @@
public abstract void Close();
+ protected static void ValidateBufferArgs(byte[] buf, int off, int len)
+ {
+ if (buf == null)
+ throw new ArgumentNullException("buf");
+ if (off < 0)
+ throw new ArgumentOutOfRangeException("Buffer offset is smaller than zero.");
+ if (len < 0)
+ throw new ArgumentOutOfRangeException("Buffer length is smaller than zero.");
+ if (off + len > buf.Length)
+ throw new ArgumentOutOfRangeException("Not enough data.");
+ }
+
public abstract int Read(byte[] buf, int off, int len);
public int ReadAll(byte[] buf, int off, int len)
{
+ ValidateBufferArgs(buf, off, len);
int got = 0;
//If we previously peeked a byte, we need to use that first.
diff --git a/lib/csharp/test/ThriftTest/Makefile.am b/lib/csharp/test/ThriftTest/Makefile.am
index 7125c90..c0014e6 100644
--- a/lib/csharp/test/ThriftTest/Makefile.am
+++ b/lib/csharp/test/ThriftTest/Makefile.am
@@ -30,7 +30,7 @@
precross: TestClientServer.exe
ThriftImpl.dll: stubs
- $(CSC) /t:library /out:./ThriftImpl.dll /recurse:./gen-csharp/* /reference:../../Thrift.dll
+ $(CSC) /t:library /out:./ThriftImpl.dll /recurse:./gen-csharp/Thrift/Test/*.cs /reference:../../Thrift.dll
TestClientServer.exe: TestClient.cs TestServer.cs Program.cs ThriftImpl.dll
$(CSC) /out:TestClientServer.exe /reference:../../Thrift.dll /reference:ThriftImpl.dll TestClient.cs TestServer.cs Program.cs
diff --git a/lib/csharp/test/ThriftTest/Program.cs b/lib/csharp/test/ThriftTest/Program.cs
index 5a4245b..2bfc73e 100644
--- a/lib/csharp/test/ThriftTest/Program.cs
+++ b/lib/csharp/test/ThriftTest/Program.cs
@@ -46,7 +46,7 @@
}
if (args[0] == "client")
{
- return TestClient.Execute(subArgs) ? 0 : 1;
+ return TestClient.Execute(subArgs);
}
else if (args[0] == "server")
{
diff --git a/lib/csharp/test/ThriftTest/TestClient.cs b/lib/csharp/test/ThriftTest/TestClient.cs
index 68949ac..c09a801 100644
--- a/lib/csharp/test/ThriftTest/TestClient.cs
+++ b/lib/csharp/test/ThriftTest/TestClient.cs
@@ -18,8 +18,11 @@
*/
using System;
+using System.Linq;
+using System.Diagnostics;
using System.Collections.Generic;
using System.Threading;
+using System.Security.Cryptography.X509Certificates;
using Thrift.Collections;
using Thrift.Protocol;
using Thrift.Transport;
@@ -29,53 +32,176 @@
{
public class TestClient
{
- private static int numIterations = 1;
- private static string protocol = "";
+ private class TestParams
+ {
+ public int numIterations = 1;
+ public string host = "localhost";
+ public int port = 9090;
+ public string url;
+ public string pipe;
+ public bool buffered;
+ public bool framed;
+ public string protocol;
+ public bool encrypted = false;
- public static bool Execute(string[] args)
+ public TTransport CreateTransport()
+ {
+ if (url == null)
+ {
+ // endpoint transport
+ TTransport trans = null;
+ if (pipe != null)
+ trans = new TNamedPipeClientTransport(pipe);
+ else
+ {
+ if (encrypted)
+ {
+ string certPath = "../../../../test/keys/client.p12";
+ X509Certificate cert = new X509Certificate2(certPath, "thrift");
+ trans = new TTLSSocket(host, port, cert, (o, c, chain, errors) => true);
+ }
+ else
+ {
+ trans = new TSocket(host, port);
+ }
+ }
+
+ // layered transport
+ if (buffered)
+ trans = new TBufferedTransport(trans);
+ if (framed)
+ trans = new TFramedTransport(trans);
+
+ //ensure proper open/close of transport
+ trans.Open();
+ trans.Close();
+ return trans;
+ }
+ else
+ {
+ return new THttpClient(new Uri(url));
+ }
+ }
+
+ public TProtocol CreateProtocol(TTransport transport)
+ {
+ if (protocol == "compact")
+ return new TCompactProtocol(transport);
+ else if (protocol == "json")
+ return new TJSONProtocol(transport);
+ else
+ return new TBinaryProtocol(transport);
+ }
+ };
+
+ private const int ErrorBaseTypes = 1;
+ private const int ErrorStructs = 2;
+ private const int ErrorContainers = 4;
+ private const int ErrorExceptions = 8;
+ private const int ErrorUnknown = 64;
+
+ private class ClientTest
+ {
+ private readonly TTransport transport;
+ private readonly ThriftTest.Client client;
+ private readonly int numIterations;
+ private bool done;
+
+ public int ReturnCode { get; set; }
+
+ public ClientTest(TestParams param)
+ {
+ transport = param.CreateTransport();
+ client = new ThriftTest.Client(param.CreateProtocol(transport));
+ numIterations = param.numIterations;
+ }
+ public void Execute()
+ {
+ if (done)
+ {
+ Console.WriteLine("Execute called more than once");
+ throw new InvalidOperationException();
+ }
+
+ for (int i = 0; i < numIterations; i++)
+ {
+ try
+ {
+ if (!transport.IsOpen)
+ transport.Open();
+ }
+ catch (TTransportException ex)
+ {
+ Console.WriteLine("*** FAILED ***");
+ Console.WriteLine("Connect failed: " + ex.Message);
+ ReturnCode |= ErrorUnknown;
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ continue;
+ }
+
+ try
+ {
+ ReturnCode |= ExecuteClientTest(client);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("*** FAILED ***");
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ ReturnCode |= ErrorUnknown;
+ }
+ }
+ try
+ {
+ transport.Close();
+ }
+ catch(Exception ex)
+ {
+ Console.WriteLine("Error while closing transport");
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ }
+ done = true;
+ }
+ }
+
+ public static int Execute(string[] args)
{
try
{
- string host = "localhost";
- int port = 9090;
- string url = null, pipe = null;
+ TestParams param = new TestParams();
int numThreads = 1;
- bool buffered = false, framed = false, encrypted = false;
- string certPath = "../../../../../keys/server.pem";
-
try
{
for (int i = 0; i < args.Length; i++)
{
if (args[i] == "-u")
{
- url = args[++i];
+ param.url = args[++i];
}
else if (args[i] == "-n")
{
- numIterations = Convert.ToInt32(args[++i]);
+ param.numIterations = Convert.ToInt32(args[++i]);
}
else if (args[i] == "-pipe") // -pipe <name>
{
- pipe = args[++i];
+ param.pipe = args[++i];
Console.WriteLine("Using named pipes transport");
}
else if (args[i].Contains("--host="))
{
- host = args[i].Substring(args[i].IndexOf("=") + 1);
+ param.host = args[i].Substring(args[i].IndexOf("=") + 1);
}
else if (args[i].Contains("--port="))
{
- port = int.Parse(args[i].Substring(args[i].IndexOf("=")+1));
+ param.port = int.Parse(args[i].Substring(args[i].IndexOf("=")+1));
}
else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered")
{
- buffered = true;
+ param.buffered = true;
Console.WriteLine("Using buffered sockets");
}
else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed")
{
- framed = true;
+ param.framed = true;
Console.WriteLine("Using framed transport");
}
else if (args[i] == "-t")
@@ -84,94 +210,48 @@
}
else if (args[i] == "--compact" || args[i] == "--protocol=compact")
{
- protocol = "compact";
+ param.protocol = "compact";
Console.WriteLine("Using compact protocol");
}
else if (args[i] == "--json" || args[i] == "--protocol=json")
{
- protocol = "json";
+ param.protocol = "json";
Console.WriteLine("Using JSON protocol");
}
else if (args[i] == "--ssl")
{
- encrypted = true;
+ param.encrypted = true;
Console.WriteLine("Using encrypted transport");
}
- else if (args[i].StartsWith("--cert="))
- {
- certPath = args[i].Substring("--cert=".Length);
- }
}
}
- catch (Exception e)
+ catch (Exception ex)
{
- Console.WriteLine(e.StackTrace);
+ Console.WriteLine("*** FAILED ***");
+ Console.WriteLine("Error while parsing arguments");
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ return ErrorUnknown;
}
+ var tests = Enumerable.Range(0, numThreads).Select(_ => new ClientTest(param)).ToArray();
//issue tests on separate threads simultaneously
- Thread[] threads = new Thread[numThreads];
+ var threads = tests.Select(test => new Thread(test.Execute)).ToArray();
DateTime start = DateTime.Now;
- for (int test = 0; test < numThreads; test++)
- {
- Thread t = new Thread(new ParameterizedThreadStart(ClientThread));
- threads[test] = t;
- if (url == null)
- {
- // endpoint transport
- TTransport trans = null;
- if (pipe != null)
- trans = new TNamedPipeClientTransport(pipe);
- else
- {
- if (encrypted)
- trans = new TTLSSocket(host, port, certPath);
- else
- trans = new TSocket(host, port);
- }
-
- // layered transport
- if (buffered)
- trans = new TBufferedTransport(trans as TStreamTransport);
- if (framed)
- trans = new TFramedTransport(trans);
-
- //ensure proper open/close of transport
- trans.Open();
- trans.Close();
- t.Start(trans);
- }
- else
- {
- THttpClient http = new THttpClient(new Uri(url));
- t.Start(http);
- }
- }
-
- for (int test = 0; test < numThreads; test++)
- {
- threads[test].Join();
- }
- Console.Write("Total time: " + (DateTime.Now - start));
+ foreach (var t in threads)
+ t.Start();
+ foreach (var t in threads)
+ t.Join();
+ Console.WriteLine("Total time: " + (DateTime.Now - start));
+ Console.WriteLine();
+ return tests.Select(t => t.ReturnCode).Aggregate((r1, r2) => r1 | r2);
}
catch (Exception outerEx)
{
+ Console.WriteLine("*** FAILED ***");
+ Console.WriteLine("Unexpected error");
Console.WriteLine(outerEx.Message + " ST: " + outerEx.StackTrace);
- return false;
+ return ErrorUnknown;
}
-
- Console.WriteLine();
- Console.WriteLine();
- return true;
- }
-
- public static void ClientThread(object obj)
- {
- TTransport transport = (TTransport)obj;
- for (int i = 0; i < numIterations; i++)
- {
- ClientTest(transport);
- }
- transport.Close();
}
public static string BytesToHex(byte[] data) {
@@ -185,14 +265,14 @@
// linear distribution, unless random is requested
if (!randomDist) {
- for (var i = 0; i < initLen; ++i) {
+ for (var i = 0; i < initLen; ++i) {
retval[i] = (byte)i;
}
return retval;
}
// random distribution
- for (var i = 0; i < initLen; ++i) {
+ for (var i = 0; i < initLen; ++i) {
retval[i] = (byte)0;
}
var rnd = new Random();
@@ -208,31 +288,9 @@
return retval;
}
- public static void ClientTest(TTransport transport)
+ public static int ExecuteClientTest(ThriftTest.Client client)
{
- TProtocol proto;
- if (protocol == "compact")
- proto = new TCompactProtocol(transport);
- else if (protocol == "json")
- proto = new TJSONProtocol(transport);
- else
- proto = new TBinaryProtocol(transport);
-
- ThriftTest.Client client = new ThriftTest.Client(proto);
- try
- {
- if (!transport.IsOpen)
- {
- transport.Open();
- }
- }
- catch (TTransportException ttx)
- {
- Console.WriteLine("Connect failed: " + ttx.Message);
- return;
- }
-
- long start = DateTime.Now.ToFileTime();
+ int returnCode = 0;
Console.Write("testVoid()");
client.testVoid();
@@ -241,29 +299,65 @@
Console.Write("testString(\"Test\")");
string s = client.testString("Test");
Console.WriteLine(" = \"" + s + "\"");
+ if ("Test" != s)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
Console.Write("testBool(true)");
bool t = client.testBool((bool)true);
Console.WriteLine(" = " + t);
+ if (!t)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
Console.Write("testBool(false)");
bool f = client.testBool((bool)false);
Console.WriteLine(" = " + f);
+ if (f)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
Console.Write("testByte(1)");
sbyte i8 = client.testByte((sbyte)1);
Console.WriteLine(" = " + i8);
+ if (1 != i8)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
Console.Write("testI32(-1)");
int i32 = client.testI32(-1);
Console.WriteLine(" = " + i32);
+ if (-1 != i32)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
Console.Write("testI64(-34359738368)");
long i64 = client.testI64(-34359738368);
Console.WriteLine(" = " + i64);
+ if (-34359738368 != i64)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
+ // TODO: Validate received message
Console.Write("testDouble(5.325098235)");
double dub = client.testDouble(5.325098235);
Console.WriteLine(" = " + dub);
+ if (5.325098235 != dub)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
byte[] binOut = PrepareTestData(true);
Console.Write("testBinary(" + BytesToHex(binOut) + ")");
@@ -272,18 +366,27 @@
byte[] binIn = client.testBinary(binOut);
Console.WriteLine(" = " + BytesToHex(binIn));
if (binIn.Length != binOut.Length)
- throw new Exception("testBinary: length mismatch");
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
for (int ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs)
if (binIn[ofs] != binOut[ofs])
- throw new Exception("testBinary: content mismatch at offset " + ofs.ToString());
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
}
- catch (Thrift.TApplicationException e)
+ catch (Thrift.TApplicationException ex)
{
- Console.Write("testBinary(" + BytesToHex(binOut) + "): "+e.Message);
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
}
// binary equals? only with hashcode option enabled ...
- if( typeof(CrazyNesting).GetMethod("Equals").DeclaringType == typeof(CrazyNesting))
+ Console.WriteLine("Test CrazyNesting");
+ if( typeof(CrazyNesting).GetMethod("Equals").DeclaringType == typeof(CrazyNesting))
{
CrazyNesting one = new CrazyNesting();
CrazyNesting two = new CrazyNesting();
@@ -292,9 +395,14 @@
one.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF };
two.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF };
if (!one.Equals(two))
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorContainers;
throw new Exception("CrazyNesting.Equals failed");
+ }
}
+ // TODO: Validate received message
Console.Write("testStruct({\"Zero\", 1, -3, -5})");
Xtruct o = new Xtruct();
o.String_thing = "Zero";
@@ -304,6 +412,7 @@
Xtruct i = client.testStruct(o);
Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}");
+ // TODO: Validate received message
Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})");
Xtruct2 o2 = new Xtruct2();
o2.Byte_thing = (sbyte)1;
@@ -352,6 +461,7 @@
}
Console.WriteLine("}");
+ // TODO: Validate received message
List<int> listout = new List<int>();
for (int j = -2; j < 3; j++)
{
@@ -392,6 +502,7 @@
Console.WriteLine("}");
//set
+ // TODO: Validate received message
THashSet<int> setout = new THashSet<int>();
for (int j = -2; j < 3; j++)
{
@@ -435,27 +546,58 @@
Console.Write("testEnum(ONE)");
Numberz ret = client.testEnum(Numberz.ONE);
Console.WriteLine(" = " + ret);
+ if (Numberz.ONE != ret)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorStructs;
+ }
Console.Write("testEnum(TWO)");
ret = client.testEnum(Numberz.TWO);
Console.WriteLine(" = " + ret);
+ if (Numberz.TWO != ret)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorStructs;
+ }
Console.Write("testEnum(THREE)");
ret = client.testEnum(Numberz.THREE);
Console.WriteLine(" = " + ret);
+ if (Numberz.THREE != ret)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorStructs;
+ }
Console.Write("testEnum(FIVE)");
ret = client.testEnum(Numberz.FIVE);
Console.WriteLine(" = " + ret);
+ if (Numberz.FIVE != ret)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorStructs;
+ }
Console.Write("testEnum(EIGHT)");
ret = client.testEnum(Numberz.EIGHT);
Console.WriteLine(" = " + ret);
+ if (Numberz.EIGHT != ret)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorStructs;
+ }
Console.Write("testTypedef(309858235082523)");
long uid = client.testTypedef(309858235082523L);
Console.WriteLine(" = " + uid);
+ if (309858235082523L != uid)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorStructs;
+ }
+ // TODO: Validate received message
Console.Write("testMapMap(1)");
Dictionary<int, Dictionary<int, int>> mm = client.testMapMap(1);
Console.Write(" = {");
@@ -471,6 +613,7 @@
}
Console.WriteLine("}");
+ // TODO: Validate received message
Insanity insane = new Insanity();
insane.UserMap = new Dictionary<Numberz, long>();
insane.UserMap[Numberz.FIVE] = 5000L;
@@ -544,14 +687,132 @@
Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing
+ ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n");
+ try
+ {
+ Console.WriteLine("testException(\"Xception\")");
+ client.testException("Xception");
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ }
+ catch (Xception ex)
+ {
+ if (ex.ErrorCode != 1001 || ex.Message != "Xception")
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ }
+ try
+ {
+ Console.WriteLine("testException(\"TException\")");
+ client.testException("TException");
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ }
+ catch (Thrift.TException)
+ {
+ // OK
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ }
+ try
+ {
+ Console.WriteLine("testException(\"ok\")");
+ client.testException("ok");
+ // OK
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ }
+
+ try
+ {
+ Console.WriteLine("testMultiException(\"Xception\", ...)");
+ client.testMultiException("Xception", "ignore");
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ }
+ catch (Xception ex)
+ {
+ if (ex.ErrorCode != 1001 || ex.Message != "This is an Xception")
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ }
+ try
+ {
+ Console.WriteLine("testMultiException(\"Xception2\", ...)");
+ client.testMultiException("Xception2", "ignore");
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ }
+ catch (Xception2 ex)
+ {
+ if (ex.ErrorCode != 2002 || ex.Struct_thing.String_thing != "This is an Xception2")
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ }
+ try
+ {
+ Console.WriteLine("testMultiException(\"success\", \"OK\")");
+ if ("OK" != client.testMultiException("success", "OK").String_thing)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorExceptions;
+ Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+ }
+
+ Stopwatch sw = new Stopwatch();
+ sw.Start();
Console.WriteLine("Test Oneway(1)");
client.testOneway(1);
+ sw.Stop();
+ if (sw.ElapsedMilliseconds > 1000)
+ {
+ Console.WriteLine("*** FAILED ***");
+ returnCode |= ErrorBaseTypes;
+ }
Console.Write("Test Calltime()");
var startt = DateTime.UtcNow;
for ( int k=0; k<1000; ++k )
client.testVoid();
Console.WriteLine(" = " + (DateTime.UtcNow - startt).TotalSeconds.ToString() + " ms a testVoid() call" );
+ return returnCode;
}
}
}
diff --git a/lib/csharp/test/ThriftTest/TestServer.cs b/lib/csharp/test/ThriftTest/TestServer.cs
index b5cc73c..b3a8e42 100644
--- a/lib/csharp/test/ThriftTest/TestServer.cs
+++ b/lib/csharp/test/ThriftTest/TestServer.cs
@@ -69,7 +69,7 @@
public string testString(string thing)
{
- Console.WriteLine("teststring(\"" + thing + "\")");
+ Console.WriteLine("testString(\"" + thing + "\")");
return thing;
}
@@ -145,9 +145,9 @@
}
else
{
- Console.WriteLine(", ");
+ Console.Write(", ");
}
- Console.WriteLine(key + " => " + thing[key]);
+ Console.Write(key + " => " + thing[key]);
}
Console.WriteLine("})");
return thing;
@@ -165,9 +165,9 @@
}
else
{
- Console.WriteLine(", ");
+ Console.Write(", ");
}
- Console.WriteLine(key + " => " + thing[key]);
+ Console.Write(key + " => " + thing[key]);
}
Console.WriteLine("})");
return thing;
@@ -185,9 +185,9 @@
}
else
{
- Console.WriteLine(", ");
+ Console.Write(", ");
}
- Console.WriteLine(elem);
+ Console.Write(elem);
}
Console.WriteLine("})");
return thing;
@@ -205,9 +205,9 @@
}
else
{
- Console.WriteLine(", ");
+ Console.Write(", ");
}
- Console.WriteLine(elem);
+ Console.Write(elem);
}
Console.WriteLine("})");
return thing;
@@ -371,7 +371,6 @@
bool useBufferedSockets = false, useFramed = false, useEncryption = false, compact = false, json = false;
int port = 9090;
string pipe = null;
- string certPath = "../../../../../keys/server.pem";
for (int i = 0; i < args.Length; i++)
{
if (args[i] == "-pipe") // -pipe name
@@ -402,10 +401,6 @@
{
useEncryption = true;
}
- else if (args[i].StartsWith("--cert="))
- {
- certPath = args[i].Substring("--cert=".Length);
- }
}
// Processor
@@ -422,7 +417,8 @@
{
if (useEncryption)
{
- trans = new TTLSServerSocket(port, 0, useBufferedSockets, new X509Certificate2(certPath));
+ string certPath = "../../../../test/keys/server.p12";
+ trans = new TTLSServerSocket(port, 0, useBufferedSockets, new X509Certificate2(certPath, "thrift"));
}
else
{