THRIFT-4434: .NET Core cleanup and the beginnings of compiler unit tests
Client: netcore

This closes #1449
diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift
index 24dcbb9..bff4e52 100644
--- a/test/ThriftTest.thrift
+++ b/test/ThriftTest.thrift
@@ -37,7 +37,7 @@
 namespace cocoa ThriftTest
 namespace lua ThriftTest
 namespace xsd test (uri = 'http://thrift.apache.org/ns/ThriftTest')
-namespace netcore ThriftAsync.Test
+namespace netcore ThriftTest
 
 // Presence of namespaces and sub-namespaces for which there is
 // no generator should compile with warnings only
diff --git a/test/csharp/TestClient.cs b/test/csharp/TestClient.cs
index 17e5978..949c06e 100644
--- a/test/csharp/TestClient.cs
+++ b/test/csharp/TestClient.cs
@@ -62,7 +62,9 @@
                         {
                             string certPath = "../keys/client.p12";
                             X509Certificate cert = new X509Certificate2(certPath, "thrift");
-                            trans = new TTLSSocket(host, port, 0, cert, (o, c, chain, errors) => true, null, SslProtocols.Tls);
+                            trans = new TTLSSocket(host, port, 0, cert, 
+                                (o, c, chain, errors) => true, 
+                                null, SslProtocols.Tls);
                         }
                         else
                         {
diff --git a/test/csharp/TestServer.cs b/test/csharp/TestServer.cs
index e9c7168..bf645c2 100644
--- a/test/csharp/TestServer.cs
+++ b/test/csharp/TestServer.cs
@@ -455,7 +455,9 @@
                     if (useEncryption)
                     {
                         string certPath = "../keys/server.p12";
-                        trans = new TTLSServerSocket(port, 0, useBufferedSockets, new X509Certificate2(certPath, "thrift"), null, null, SslProtocols.Tls);
+                        trans = new TTLSServerSocket(port, 0, useBufferedSockets, new X509Certificate2(certPath, "thrift"), 
+                            null,
+                            null, SslProtocols.Tls);
                     }
                     else
                     {
diff --git a/test/features/known_failures_Linux.json b/test/features/known_failures_Linux.json
index f96356d..6d1ed1f 100644
--- a/test/features/known_failures_Linux.json
+++ b/test/features/known_failures_Linux.json
@@ -1,46 +1,48 @@
 [
-  "c_glib-limit_container_length_binary_buffered-ip",
-  "c_glib-limit_string_length_binary_buffered-ip",
-  "cpp-theader_framed_binary_multih-header_buffered-ip",
-  "cpp-theader_framed_compact_multih-header_buffered-ip",
-  "cpp-theader_unframed_binary_multih-header_buffered-ip",
-  "cpp-theader_unframed_compact_multih-header_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",
-  "d-limit_container_length_binary_buffered-ip",
-  "d-limit_container_length_compact_buffered-ip",
-  "d-limit_string_length_binary_buffered-ip",
-  "d-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",
-  "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",
-  "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",
-  "rs-limit_container_length_binary_buffered-ip",
-  "rs-limit_container_length_compact_buffered-ip",
-  "rs-limit_container_length_multic-compact_buffered-ip",
-  "rs-limit_string_length_binary_buffered-ip",
-  "rs-limit_string_length_compact_buffered-ip",
-  "rs-limit_string_length_multic-compact_buffered-ip"
+    "c_glib-limit_container_length_binary_buffered-ip",
+    "c_glib-limit_string_length_binary_buffered-ip",
+    "cpp-theader_framed_binary_multih-header_buffered-ip",
+    "cpp-theader_framed_compact_multih-header_buffered-ip",
+    "cpp-theader_unframed_binary_multih-header_buffered-ip",
+    "cpp-theader_unframed_compact_multih-header_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",
+    "d-limit_container_length_binary_buffered-ip",
+    "d-limit_container_length_compact_buffered-ip",
+    "d-limit_string_length_binary_buffered-ip",
+    "d-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",
+    "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",
+    "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",
+    "rs-limit_container_length_binary_buffered-ip",
+    "rs-limit_container_length_compact_buffered-ip",
+    "rs-limit_container_length_multic-compact_buffered-ip",
+    "rs-limit_string_length_binary_buffered-ip",
+    "rs-limit_string_length_compact_buffered-ip",
+    "rs-limit_string_length_multic-compact_buffered-ip",
+    "netcore-limit_string_length_compact_buffered-ip",
+    "netcore-limit_container_length_compact_buffered-ip"
 ]
\ No newline at end of file
diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json
index 658577d..a142796 100644
--- a/test/known_failures_Linux.json
+++ b/test/known_failures_Linux.json
@@ -215,6 +215,12 @@
   "java-d_compact_buffered-ip",
   "java-d_compact_buffered-ip-ssl",
   "java-d_compact_framed-ip",
+  "netcore-csharp_binary_buffered-ip-ssl",
+  "netcore-csharp_binary_framed-ip-ssl",
+  "netcore-csharp_json_framed-ip-ssl",
+  "netcore-csharp_json_buffered-ip-ssl",
+  "netcore-csharp_compact_buffered-ip-ssl",
+  "netcore-csharp_compact_framed-ip-ssl",
   "nodejs-cpp_binary_http-ip",
   "nodejs-cpp_binary_http-ip-ssl",
   "nodejs-cpp_compact_http-ip",
diff --git a/test/netcore/Client/.gitignore b/test/netcore/Client/.gitignore
new file mode 100644
index 0000000..67d5510
--- /dev/null
+++ b/test/netcore/Client/.gitignore
@@ -0,0 +1,2 @@
+# ignore for autogenerated files
+/ThriftTest
diff --git a/test/netcore/Client/Client.csproj b/test/netcore/Client/Client.csproj
new file mode 100644
index 0000000..4b31a7d
--- /dev/null
+++ b/test/netcore/Client/Client.csproj
@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <AssemblyName>Client</AssemblyName>
+    <PackageId>Client</PackageId>
+    <OutputType>Exe</OutputType>
+    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
+    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="System.Net.Http.WinHttpHandler" Version="[4.4,)" />
+    <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
+    <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" />
+    <PackageReference Include="System.Threading" Version="[4.3,)" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" />
+  </ItemGroup>
+  <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile">
+    <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/test/netcore/ThriftTest/Program.cs b/test/netcore/Client/Program.cs
similarity index 82%
copy from test/netcore/ThriftTest/Program.cs
copy to test/netcore/Client/Program.cs
index 94ed9d9..72139d9 100644
--- a/test/netcore/ThriftTest/Program.cs
+++ b/test/netcore/Client/Program.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// Licensed to the Apache Software Foundation(ASF) under one
 // or more contributor license agreements.See the NOTICE file
 // distributed with this work for additional information
 // regarding copyright ownership.The ASF licenses this file
@@ -17,9 +17,9 @@
 
 using System;
 using System.Collections.Generic;
-using Test;
+using ThriftTest;
 
-namespace ThriftTest
+namespace Client
 {
     public class Program
     {
@@ -48,8 +48,6 @@
             {
                 case "client":
                     return TestClient.Execute(subArgs);
-                case "server":
-                    return TestServer.Execute(subArgs);
                 case "--help":
                     PrintHelp();
                     return 0;
@@ -62,12 +60,10 @@
         private static void PrintHelp()
         {
             Console.WriteLine("Usage:");
-            Console.WriteLine("  ThriftTest  server  [options]'");
-            Console.WriteLine("  ThriftTest  client  [options]'");
-            Console.WriteLine("  ThriftTest  --help");
+            Console.WriteLine("  Client  client  [options]'");
+            Console.WriteLine("  Client  --help");
             Console.WriteLine("");
 
-            TestServer.PrintOptionsHelp();
             TestClient.PrintOptionsHelp();
         }
     }
diff --git a/test/netcore/ThriftTest/Properties/AssemblyInfo.cs b/test/netcore/Client/Properties/AssemblyInfo.cs
similarity index 97%
copy from test/netcore/ThriftTest/Properties/AssemblyInfo.cs
copy to test/netcore/Client/Properties/AssemblyInfo.cs
index efc9e33..157152b 100644
--- a/test/netcore/ThriftTest/Properties/AssemblyInfo.cs
+++ b/test/netcore/Client/Properties/AssemblyInfo.cs
@@ -22,7 +22,7 @@
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
 
-[assembly: AssemblyTitle("ThriftTest")]
+[assembly: AssemblyTitle("Client")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("The Apache Software Foundation")]
diff --git a/test/netcore/ThriftTest/TestClient.cs b/test/netcore/Client/TestClient.cs
similarity index 92%
rename from test/netcore/ThriftTest/TestClient.cs
rename to test/netcore/Client/TestClient.cs
index f6cc900..8be198c 100644
--- a/test/netcore/ThriftTest/TestClient.cs
+++ b/test/netcore/Client/TestClient.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// Licensed to the Apache Software Foundation(ASF) under one
 // or more contributor license agreements.See the NOTICE file
 // distributed with this work for additional information
 // regarding copyright ownership.The ASF licenses this file
@@ -18,28 +18,29 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
 using System.Linq;
 using System.Net;
 using System.Reflection;
 using System.Security.Authentication;
 using System.Security.Cryptography.X509Certificates;
+using System.ServiceModel;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
-using ThriftAsync.Test;
 using Thrift.Collections;
 using Thrift.Protocols;
 using Thrift.Transports;
 using Thrift.Transports.Client;
 
-namespace Test
+namespace ThriftTest
 {
     public class TestClient
     {
         private class TestParams
         {
             public int numIterations = 1;
-            public IPAddress host = IPAddress.Loopback;
+            public IPAddress host = IPAddress.Any;
             public int port = 9090;
             public int numThreads = 1;
             public string url;
@@ -111,11 +112,43 @@
                     }
                     else
                     {
-                        throw new ArgumentException(args[i]);
+                        //throw new ArgumentException(args[i]);
                     }
                 }
             }
 
+            private static X509Certificate2 GetClientCert()
+            {
+                var clientCertName = "client.p12";
+                var possiblePaths = new List<string>
+                {
+                    "../../../keys/",
+                    "../../keys/",
+                    "../keys/",
+                    "keys/",
+                };
+
+                string existingPath = null;
+                foreach (var possiblePath in possiblePaths)
+                {
+                    var path = Path.GetFullPath(possiblePath + clientCertName);
+                    if (File.Exists(path))
+                    {
+                        existingPath = path;
+                        break;
+                    }
+                }
+
+                if (string.IsNullOrEmpty(existingPath))
+                {
+                    throw new FileNotFoundException($"Cannot find file: {clientCertName}");
+                }
+            
+                var cert = new X509Certificate2(existingPath, "thrift");
+
+                return cert;
+            }
+            
             public TClientTransport CreateTransport()
             {
                 if (url == null)
@@ -131,9 +164,16 @@
                     {
                         if (encrypted)
                         {
-                            var certPath = "../../keys/client.p12";
-                            var cert = new X509Certificate2(certPath, "thrift");
-                            trans = new TTlsSocketClientTransport(host, port, 0, cert, (o, c, chain, errors) => true, null, SslProtocols.Tls);
+                           var cert = GetClientCert();
+                        
+                            if (cert == null || !cert.HasPrivateKey)
+                            {
+                                throw new InvalidOperationException("Certificate doesn't contain private key");
+                            }
+                            
+                            trans = new TTlsSocketClientTransport(host, port, 0, cert, 
+                                (sender, certificate, chain, errors) => true,
+                                null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12);
                         }
                         else
                         {
@@ -184,7 +224,7 @@
         private class ClientTest
         {
             private readonly TClientTransport transport;
-            private readonly ThriftAsync.Test.ThriftTest.Client client;
+            private readonly ThriftTest.Client client;
             private readonly int numIterations;
             private bool done;
 
@@ -193,7 +233,7 @@
             public ClientTest(TestParams param)
             {
                 transport = param.CreateTransport();
-                client = new ThriftAsync.Test.ThriftTest.Client(param.CreateProtocol(transport));
+                client = new ThriftTest.Client(param.CreateProtocol(transport));
                 numIterations = param.numIterations;
             }
 
@@ -224,6 +264,14 @@
                         Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
                         continue;
                     }
+                    catch (Exception ex)
+                    {
+                        Console.WriteLine("*** FAILED ***");
+                        Console.WriteLine("Connect failed: " + ex.Message);
+                        ReturnCode |= ErrorUnknown;
+                        Console.WriteLine(ex.Message + " ST: " + ex.StackTrace);
+                        continue;
+                    }
 
                     try
                     {
@@ -285,17 +333,14 @@
                 var tests = Enumerable.Range(0, param.numThreads).Select(_ => new ClientTest(param)).ToArray();
 
                 //issue tests on separate threads simultaneously
-                var threads = tests.Select(test => new Thread(test.Execute)).ToArray();
+                var threads = tests.Select(test => new Task(test.Execute)).ToArray();
                 var start = DateTime.Now;
                 foreach (var t in threads)
                 {
                     t.Start();
                 }
 
-                foreach (var t in threads)
-                {
-                    t.Join();
-                }
+                Task.WaitAll(threads);
 
                 Console.WriteLine("Total time: " + (DateTime.Now - start));
                 Console.WriteLine();
@@ -351,7 +396,7 @@
             return retval;
         }
 
-        public static async Task<int> ExecuteClientTestAsync(ThriftAsync.Test.ThriftTest.Client client)
+        public static async Task<int> ExecuteClientTestAsync(ThriftTest.Client client)
         {
             var token = CancellationToken.None;
             var returnCode = 0;
diff --git a/test/netcore/Makefile.am b/test/netcore/Makefile.am
index e029a24..65833b9 100644
--- a/test/netcore/Makefile.am
+++ b/test/netcore/Makefile.am
@@ -19,41 +19,28 @@
 
 SUBDIRS = . 
 
-THRIFT = $(top_builddir)/compiler/cpp/thrift
-
-GENDIR = ThriftTest/gen-netcore
-
 THRIFTCODE = \
-			ThriftTest/TestClient.cs \
-			ThriftTest/TestServer.cs \
-			ThriftTest/Properties/AssemblyInfo.cs \
-			ThriftTest/Program.cs 
+			ThriftTest.sln 
 
 all-local: \
-	ThriftTest/stage/ThriftTest.dll
+	ThriftTest/stage/binaries
 
-ThriftTest/stage/ThriftTest.dll: $(THRIFTCODE)
-	$(MKDIR_P) $(GENDIR)
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/test/ThriftTest.thrift
-	$(DOTNETCORE) --info
-	$(DOTNETCORE) restore
+ThriftTest/stage/binaries: $(THRIFTCODE)
 	$(DOTNETCORE) build
 
 precross: \
-	ThriftTest/stage/ThriftTest.dll
+	ThriftTest/stage/binaries
 
 clean-local:
-	$(RM) ThriftTest.exe
-	$(RM) -r $(GENDIR)
-	$(RM) -r ThriftTest/bin
-	$(RM) -r ThriftTest/obj
+	$(RM) -r Client/bin
+	$(RM) -r Server/bin
+	$(RM) -r Client/obj
+	$(RM) -r Server/obj
+	$(RM) -r ThriftTest/ThriftTest
 
 EXTRA_DIST = \
-			 $(THRIFTCODE) \
 			 ThriftTest.sln \
-			 ThriftTest/ThriftTest.csproj \
-			 ThriftTest/Properties/launchSettings.json \
-			 build.cmd \
-			 build.sh \
+			 Server \
+			 Client \
 			 README.md
 			 
diff --git a/test/netcore/README.md b/test/netcore/README.md
index 05eb0e2..ed728d1 100644
--- a/test/netcore/README.md
+++ b/test/netcore/README.md
@@ -9,7 +9,10 @@
 - NET Core Standard 1.6 (SDK 2.0.0)
 
 # How to build on Windows
+- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable
 - Open ThriftTest.sln in Visual Studio and build
+or 
+- Build with scripts
 
 # How to build on Unix
 - Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image
diff --git a/test/netcore/Server/.gitignore b/test/netcore/Server/.gitignore
new file mode 100644
index 0000000..67d5510
--- /dev/null
+++ b/test/netcore/Server/.gitignore
@@ -0,0 +1,2 @@
+# ignore for autogenerated files
+/ThriftTest
diff --git a/test/netcore/ThriftTest/Program.cs b/test/netcore/Server/Program.cs
similarity index 82%
rename from test/netcore/ThriftTest/Program.cs
rename to test/netcore/Server/Program.cs
index 94ed9d9..e647e5b 100644
--- a/test/netcore/ThriftTest/Program.cs
+++ b/test/netcore/Server/Program.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// Licensed to the Apache Software Foundation(ASF) under one
 // or more contributor license agreements.See the NOTICE file
 // distributed with this work for additional information
 // regarding copyright ownership.The ASF licenses this file
@@ -17,9 +17,9 @@
 
 using System;
 using System.Collections.Generic;
-using Test;
+using ThriftTest;
 
-namespace ThriftTest
+namespace Server
 {
     public class Program
     {
@@ -46,8 +46,6 @@
             // run whatever mode is choosen
             switch(firstArg)
             {
-                case "client":
-                    return TestClient.Execute(subArgs);
                 case "server":
                     return TestServer.Execute(subArgs);
                 case "--help":
@@ -62,13 +60,11 @@
         private static void PrintHelp()
         {
             Console.WriteLine("Usage:");
-            Console.WriteLine("  ThriftTest  server  [options]'");
-            Console.WriteLine("  ThriftTest  client  [options]'");
-            Console.WriteLine("  ThriftTest  --help");
+            Console.WriteLine("  Server  server  [options]'");
+            Console.WriteLine("  Server  --help");
             Console.WriteLine("");
 
             TestServer.PrintOptionsHelp();
-            TestClient.PrintOptionsHelp();
         }
     }
 }
diff --git a/test/netcore/ThriftTest/Properties/AssemblyInfo.cs b/test/netcore/Server/Properties/AssemblyInfo.cs
similarity index 97%
rename from test/netcore/ThriftTest/Properties/AssemblyInfo.cs
rename to test/netcore/Server/Properties/AssemblyInfo.cs
index efc9e33..265495c 100644
--- a/test/netcore/ThriftTest/Properties/AssemblyInfo.cs
+++ b/test/netcore/Server/Properties/AssemblyInfo.cs
@@ -22,7 +22,7 @@
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
 
-[assembly: AssemblyTitle("ThriftTest")]
+[assembly: AssemblyTitle("Server")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("The Apache Software Foundation")]
diff --git a/test/netcore/Server/Server.csproj b/test/netcore/Server/Server.csproj
new file mode 100644
index 0000000..ad2fb7c
--- /dev/null
+++ b/test/netcore/Server/Server.csproj
@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <AssemblyName>Server</AssemblyName>
+    <PackageId>Server</PackageId>
+    <OutputType>Exe</OutputType>
+    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
+    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="System.Net.Http.WinHttpHandler" Version="[4.4,)" />
+    <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
+    <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" />
+    <PackageReference Include="System.Threading" Version="[4.3,)" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" />
+  </ItemGroup>
+  <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile">
+    <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../ThriftTest.thrift" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/test/netcore/ThriftTest/TestServer.cs b/test/netcore/Server/TestServer.cs
similarity index 89%
rename from test/netcore/ThriftTest/TestServer.cs
rename to test/netcore/Server/TestServer.cs
index aa25c91..bfd3335 100644
--- a/test/netcore/ThriftTest/TestServer.cs
+++ b/test/netcore/Server/TestServer.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// Licensed to the Apache Software Foundation(ASF) under one
 // or more contributor license agreements.See the NOTICE file
 // distributed with this work for additional information
 // regarding copyright ownership.The ASF licenses this file
@@ -17,13 +17,14 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
+using System.Linq;
 using System.Security.Authentication;
 using System.Security.Cryptography.X509Certificates;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Logging;
-using ThriftAsync.Test;
 using Thrift;
 using Thrift.Collections;
 using Thrift.Protocols;
@@ -31,7 +32,7 @@
 using Thrift.Transports;
 using Thrift.Transports.Server;
 
-namespace Test
+namespace ThriftTest
 {
     internal class ServerParam
     {
@@ -93,7 +94,7 @@
                 }
                 else
                 {
-                    throw new ArgumentException(args[i]);
+                    //throw new ArgumentException(args[i]);
                 }
             }
 
@@ -132,9 +133,9 @@
                 callCount++;
                 return Task.CompletedTask;
             }
-        };
+        }
 
-        public class TestHandlerAsync : ThriftAsync.Test.ThriftTest.IAsync
+        public class TestHandlerAsync : ThriftTest.IAsync
         {
             public TBaseServer server { get; set; }
             private int handlerID;
@@ -439,20 +440,13 @@
             public Task testOnewayAsync(int secondsToSleep, CancellationToken cancellationToken)
             {
                 logger.Invoke("testOneway({0}), sleeping...", secondsToSleep);
-                Thread.Sleep(secondsToSleep * 1000);
+                Task.Delay(secondsToSleep * 1000, cancellationToken).GetAwaiter().GetResult();
                 logger.Invoke("testOneway finished");
 
                 return Task.CompletedTask;
             }
         }
 
-
-        private enum ProcessorFactoryType
-        {
-            TSingletonProcessorFactory,
-            TPrototypeProcessorFactory,
-        }
-
         internal static void PrintOptionsHelp()
         {
             Console.WriteLine("Server options:");
@@ -466,8 +460,41 @@
             Console.WriteLine();
         }
 
+        private static X509Certificate2 GetServerCert()
+        {
+            var serverCertName = "server.p12";
+            var possiblePaths = new List<string>
+            {
+                "../../../keys/",
+                "../../keys/",
+                "../keys/",
+                "keys/",
+            };
+                        
+            string existingPath = null;
+            foreach (var possiblePath in possiblePaths)
+            {
+                var path = Path.GetFullPath(possiblePath + serverCertName);
+                if (File.Exists(path))
+                {
+                    existingPath = path;
+                    break;
+                }
+            }
+                        
+            if (string.IsNullOrEmpty(existingPath))
+            {
+                throw new FileNotFoundException($"Cannot find file: {serverCertName}");
+            }
+                                    
+            var cert = new X509Certificate2(existingPath, "thrift");
+                        
+            return cert;
+        }
+
         public static int Execute(List<string> args)
         {
+            var loggerFactory = new LoggerFactory();//.AddConsole().AddDebug();
             var logger = new LoggerFactory().CreateLogger("Test");
 
             try
@@ -493,16 +520,28 @@
                 {
                     trans = new TNamedPipeServerTransport(param.pipe);
                 }
+//                else if (param.useFramed)
+//                {
+//                    trans = new TServerFramedTransport(param.port);
+//                }
                 else
                 {
                     if (param.useEncryption)
                     {
-                        var certPath = "../../keys/server.p12";
-                        trans = new TTlsServerSocketTransport(param.port, param.useBufferedSockets, new X509Certificate2(certPath, "thrift"), null, null, SslProtocols.Tls);
+                        var cert = GetServerCert();
+                        
+                        if (cert == null || !cert.HasPrivateKey)
+                        {
+                            throw new InvalidOperationException("Certificate doesn't contain private key");
+                        }
+                        
+                        trans = new TTlsServerSocketTransport(param.port, param.useBufferedSockets, param.useFramed, cert, 
+                            (sender, certificate, chain, errors) => true, 
+                            null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12);
                     }
                     else
                     {
-                        trans = new TServerSocketTransport(param.port, 0, param.useBufferedSockets);
+                        trans = new TServerSocketTransport(param.port, 0, param.useBufferedSockets, param.useFramed);
                     }
                 }
 
@@ -518,15 +557,10 @@
 
                 // Processor
                 var testHandler = new TestHandlerAsync();
-                var testProcessor = new ThriftAsync.Test.ThriftTest.AsyncProcessor(testHandler);
+                var testProcessor = new ThriftTest.AsyncProcessor(testHandler);
                 processorFactory = new SingletonTProcessorFactory(testProcessor);
 
-
-                TTransportFactory transFactory;
-                if (param.useFramed)
-                    throw new NotImplementedException("framed"); // transFactory = new TFramedTransport.Factory();
-                else
-                    transFactory = new TTransportFactory();
+                TTransportFactory transFactory = new TTransportFactory(); 
 
                 TBaseServer serverEngine = new AsyncBaseServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger);
 
diff --git a/test/netcore/ThriftTest.sln b/test/netcore/ThriftTest.sln
index c3f194b..2ab241a 100644
--- a/test/netcore/ThriftTest.sln
+++ b/test/netcore/ThriftTest.sln
@@ -1,11 +1,13 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
 VisualStudioVersion = 15.0.26730.12
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThriftTest", "ThriftTest\ThriftTest.csproj", "{DDED46FF-F359-47B4-BA7E-9B70F216BD44}"
-EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netcore\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -16,18 +18,6 @@
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|x64.Build.0 = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Debug|x86.Build.0 = Debug|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|Any CPU.Build.0 = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|x64.ActiveCfg = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|x64.Build.0 = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|x86.ActiveCfg = Release|Any CPU
-		{DDED46FF-F359-47B4-BA7E-9B70F216BD44}.Release|x86.Build.0 = Release|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -40,6 +30,30 @@
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU
 		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.Build.0 = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.Build.0 = Debug|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.ActiveCfg = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.Build.0 = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.ActiveCfg = Release|Any CPU
+		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.Build.0 = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.Build.0 = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.Build.0 = Debug|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|x64.ActiveCfg = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|x64.Build.0 = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|x86.ActiveCfg = Release|Any CPU
+		{0C6E8685-F191-4479-9842-882A38961127}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/test/netcore/ThriftTest/Properties/launchSettings.json b/test/netcore/ThriftTest/Properties/launchSettings.json
deleted file mode 100644
index ddafa79..0000000
--- a/test/netcore/ThriftTest/Properties/launchSettings.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "profiles": {
-    "ThriftTest": {
-      "commandName": "Project"
-    }
-  }
-}
\ No newline at end of file
diff --git a/test/netcore/ThriftTest/ThriftTest.csproj b/test/netcore/ThriftTest/ThriftTest.csproj
deleted file mode 100644
index 6647101..0000000
--- a/test/netcore/ThriftTest/ThriftTest.csproj
+++ /dev/null
@@ -1,27 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>netcoreapp2.0</TargetFramework>
-    <AssemblyName>ThriftTest</AssemblyName>
-    <PackageId>ThriftTest</PackageId>
-    <OutputType>Exe</OutputType>
-    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
-    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
-    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
-    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
-    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
-    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="System.Net.Http.WinHttpHandler" Version="[4.4,)" />
-    <PackageReference Include="System.Runtime.Serialization.Primitives" Version="[4.3,)" />
-    <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" />
-    <PackageReference Include="System.Threading" Version="[4.3,)" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" />
-  </ItemGroup>
-
-</Project>
diff --git a/test/netcore/build.cmd b/test/netcore/build.cmd
index e971799..9b84ef2 100644
--- a/test/netcore/build.cmd
+++ b/test/netcore/build.cmd
@@ -19,12 +19,7 @@
 rem  */
 setlocal
 
-cd Interfaces
-thrift  -gen netcore:wcf   -r  ..\..\tutorial.thrift
-cd ..
-
 dotnet --info
-dotnet restore
 dotnet build
 
 :eof
diff --git a/test/netcore/build.sh b/test/netcore/build.sh
index 626635c..c97e310 100755
--- a/test/netcore/build.sh
+++ b/test/netcore/build.sh
@@ -22,10 +22,5 @@
 #exit if any command fails
 set -e
 
-cd ThriftTest
-../../../compiler/cpp/thrift  -gen netcore:wcf   -r  ../../ThriftTest.thrift
-cd ..
-
 dotnet --info
-dotnet restore
 dotnet build
diff --git a/test/tests.json b/test/tests.json
index c4e07ee..fd79a9b 100644
--- a/test/tests.json
+++ b/test/tests.json
@@ -1,689 +1,686 @@
-[
-  {
-    "name": "c_glib",
-    "platforms": [
-      "Linux"
-    ],
-    "server": {
-      "command": [
-        "test_server",
-        "--lt-debug"
-      ],
-      "protocols": [
-        "binary:multi",
-        "compact:multic"
-      ]
+[{
+        "name": "c_glib",
+        "platforms": [
+            "Linux"
+        ],
+        "server": {
+            "command": [
+                "test_server",
+                "--lt-debug"
+            ],
+            "protocols": [
+                "binary:multi",
+                "compact:multic"
+            ]
+        },
+        "client": {
+            "command": [
+                "test_client",
+                "--lt-debug"
+            ],
+            "protocols": [
+                "multi:binary",
+                "multic:compact"
+            ],
+            "sockets": [
+                "ip-ssl"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip"
+        ],
+        "protocols": [
+            "binary",
+            "compact",
+            "multi",
+            "multic"
+        ],
+        "workdir": "c_glib"
     },
-    "client": {
-      "command": [
-        "test_client",
-        "--lt-debug"
-      ],
-      "protocols": [
-        "multi:binary",
-        "multic:compact"
-      ],
-      "sockets": [
-        "ip-ssl"
-      ]
+    {
+        "name": "d",
+        "server": {
+            "command": [
+                "thrift_test_server"
+            ]
+        },
+        "client": {
+            "command": [
+                "thrift_test_client"
+            ]
+        },
+        "transports": [
+            "http",
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl"
+        ],
+        "protocols": [
+            "binary",
+            "compact",
+            "json"
+        ],
+        "workdir": "../lib/d/test"
     },
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip"
-    ],
-    "protocols": [
-      "binary",
-      "compact",
-      "multi",
-      "multic"
-    ],
-    "workdir": "c_glib"
-  },
-  {
-    "name": "d",
-    "server": {
-      "command": [
-        "thrift_test_server"
-      ]
+    {
+        "name": "go",
+        "server": {
+            "command": [
+                "testserver",
+                "--certPath=../../keys"
+            ]
+        },
+        "client": {
+            "timeout": 6,
+            "command": [
+                "testclient"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "framed",
+            "http"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl"
+        ],
+        "protocols": [
+            "binary",
+            "compact",
+            "json"
+        ],
+        "workdir": "go/bin"
     },
-    "client": {
-      "command": [
-        "thrift_test_client"
-      ]
+    {
+        "name": "java",
+        "join_args": true,
+        "command": [
+            "ant",
+            "-f",
+            "build.xml",
+            "-Dno-gen-thrift=\"\"",
+            "-Dtestargs"
+        ],
+        "prepare": [
+            "ant",
+            "-f",
+            "build.xml",
+            "compile-test"
+        ],
+        "server": {
+            "delay": 10,
+            "extra_args": ["run-testserver"],
+            "protocols": [
+                "binary:multi",
+                "compact:multic",
+                "json:multij"
+            ]
+        },
+        "client": {
+            "timeout": 13,
+            "extra_args": ["run-testclient"],
+            "transports": [
+                "http"
+            ],
+            "protocols": [
+                "multi:binary",
+                "multic:compact",
+                "multij:json"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "framed",
+            "framed:fastframed"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl"
+        ],
+        "protocols": [
+            "binary",
+            "compact",
+            "json",
+            "multi",
+            "multic",
+            "multij"
+        ],
+        "workdir": "../lib/java"
     },
-    "transports": [
-      "http",
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl"
-    ],
-    "protocols": [
-      "binary",
-      "compact",
-      "json"
-    ],
-    "workdir": "../lib/d/test"
-  },
-  {
-    "name": "go",
-    "server": {
-      "command": [
-        "testserver",
-        "--certPath=../../keys"
-      ]
+    {
+        "name": "nodejs",
+        "env": {
+            "NODE_PATH": "../lib"
+        },
+        "server": {
+            "command": [
+                "node",
+                "server.js",
+                "--type=tcp"
+            ]
+        },
+        "client": {
+            "timeout": 6,
+            "command": [
+                "node",
+                "client.js",
+                "--type=tcp"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "framed",
+            "http"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl"
+        ],
+        "protocols": [
+            "compact",
+            "binary",
+            "json"
+        ],
+        "workdir": "../lib/nodejs/test"
     },
-    "client": {
-      "timeout": 6,
-      "command": [
-        "testclient"
-      ]
+    {
+        "name": "hs",
+        "server": {
+            "command": [
+                "TestServer"
+            ]
+        },
+        "client": {
+            "timeout": 6,
+            "transports": [
+                "http"
+            ],
+            "command": [
+                "TestClient"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip"
+        ],
+        "protocols": [
+            "header",
+            "compact",
+            "binary",
+            "json"
+        ],
+        "workdir": "hs"
     },
-    "transports": [
-      "buffered",
-      "framed",
-      "http"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl"
-    ],
-    "protocols": [
-      "binary",
-      "compact",
-      "json"
-    ],
-    "workdir": "go/bin"
-  },
-  {
-    "name": "java",
-    "join_args": true,
-    "command": [
-      "ant",
-      "-f",
-      "build.xml",
-      "-Dno-gen-thrift=\"\"",
-      "-Dtestargs"
-    ],
-    "prepare": [
-      "ant",
-      "-f",
-      "build.xml",
-      "compile-test"
-    ],
-    "server": {
-      "delay": 10,
-      "extra_args": ["run-testserver"],
-      "protocols": [
-        "binary:multi",
-        "compact:multic",
-        "json:multij"
-      ]
+    {
+        "name": "py",
+        "server": {
+            "extra_args": ["TSimpleServer"],
+            "command": [
+                "TestServer.py",
+                "--verbose",
+                "--genpydir=gen-py"
+            ]
+        },
+        "client": {
+            "timeout": 10,
+            "command": [
+                "TestClient.py",
+                "--verbose",
+                "--host=localhost",
+                "--genpydir=gen-py"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl"
+        ],
+        "protocols": [
+            "compact",
+            "binary",
+            "json",
+            "binary:accel",
+            "compact:accelc"
+        ],
+        "workdir": "py"
     },
-    "client": {
-      "timeout": 13,
-      "extra_args": ["run-testclient"],
-      "transports": [
-        "http"
-      ],
-      "protocols": [
-        "multi:binary",
-        "multic:compact",
-        "multij:json"
-      ]
+    {
+        "comment": "Using 'python3' executable to test py2 and 3 at once",
+        "name": "py3",
+        "server": {
+            "extra_args": ["TSimpleServer"],
+            "command": [
+                "python3",
+                "TestServer.py",
+                "--verbose",
+                "--genpydir=gen-py"
+            ]
+        },
+        "client": {
+            "timeout": 10,
+            "command": [
+                "python3",
+                "TestClient.py",
+                "--host=localhost",
+                "--genpydir=gen-py"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip-ssl",
+            "ip"
+        ],
+        "protocols": [
+            "compact",
+            "binary",
+            "json",
+            "binary:accel",
+            "compact:accelc"
+        ],
+        "workdir": "py"
     },
-    "transports": [
-      "buffered",
-      "framed",
-      "framed:fastframed"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl"
-    ],
-    "protocols": [
-      "binary",
-      "compact",
-      "json",
-      "multi",
-      "multic",
-      "multij"
-    ],
-    "workdir": "../lib/java"
-  },
-  {
-    "name": "nodejs",
-    "env": {
-      "NODE_PATH": "../lib"
+    {
+        "name": "cpp",
+        "server": {
+            "command": [
+                "TestServer"
+            ],
+            "protocols": [
+                "binary:multi",
+                "compact:multic",
+                "header:multih",
+                "json:multij"
+            ]
+        },
+        "client": {
+            "timeout": 8,
+            "command": [
+                "TestClient"
+            ],
+            "protocols": [
+                "multi:binary",
+                "multic:compact",
+                "multih:header",
+                "multij:json"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "http",
+            "framed"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl",
+            "domain"
+        ],
+        "protocols": [
+            "compact",
+            "binary",
+            "json",
+            "header",
+            "multi",
+            "multic",
+            "multih",
+            "multij"
+        ],
+        "workdir": "cpp"
     },
-    "server": {
-      "command": [
-        "node",
-        "server.js",
-        "--type=tcp"
-      ]
+    {
+        "name": "rb",
+        "server": {
+            "command": [
+                "ruby",
+                "../integration/TestServer.rb"
+            ]
+        },
+        "client": {
+            "timeout": 5,
+            "command": [
+                "ruby",
+                "../integration/TestClient.rb"
+            ]
+        },
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip"
+        ],
+        "protocols": [
+            "compact",
+            "binary",
+            "json",
+            "binary:accel"
+        ],
+        "workdir": "rb/gen-rb"
     },
-    "client": {
-      "timeout": 6,
-      "command": [
-        "node",
-        "client.js",
-        "--type=tcp"
-      ]
+    {
+        "name": "csharp",
+        "env": {
+            "MONO_PATH": "../../lib/csharp/"
+        },
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl"
+        ],
+        "protocols": [
+            "binary",
+            "compact",
+            "json"
+        ],
+        "server": {
+            "command": [
+                "mono",
+                "TestClientServer.exe",
+                "server"
+            ]
+        },
+        "client": {
+            "timeout": 9,
+            "command": [
+                "mono",
+                "TestClientServer.exe",
+                "client"
+            ],
+            "protocols": [
+                "multi",
+                "multic",
+                "multi:binary",
+                "multic:compact"
+            ]
+        },
+        "workdir": "csharp"
     },
-    "transports": [
-      "buffered",
-      "framed",
-      "http"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl"
-    ],
-    "protocols": [
-      "compact",
-      "binary",
-      "json"
-    ],
-    "workdir": "../lib/nodejs/test"
-  },
-  {
-    "name": "hs",
-    "server": {
-      "command": [
-        "TestServer"
-      ]
+    {
+        "name": "netcore",
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl"
+        ],
+        "protocols": [
+            "binary",
+            "compact",
+            "json"
+        ],
+        "server": {
+            "command": [
+                "dotnet",
+                "run",
+                "--no-build",
+                "--project=Server/Server.csproj",
+                "server"
+            ]
+        },
+        "client": {
+            "timeout": 10,
+            "command": [
+                "dotnet",
+                "run",
+                "--no-build",
+                "--project=Client/Client.csproj",
+                "client"
+            ]
+        },
+        "workdir": "netcore"
     },
-    "client": {
-      "timeout": 6,
-      "transports": [
-        "http"
-      ],
-      "command": [
-        "TestClient"
-      ]
+    {
+        "name": "perl",
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl",
+            "domain"
+        ],
+        "protocols": [
+            "binary",
+            "multi"
+        ],
+        "client": {
+            "command": [
+                "perl",
+                "-Igen-perl/",
+                "-I../../lib/perl/lib/",
+                "TestClient.pl",
+                "--ca=../keys/CA.pem",
+                "--cert=../keys/client.crt",
+                "--key=../keys/client.key"
+            ],
+            "protocols": [
+                "multi:binary"
+            ]
+        },
+        "server": {
+            "command": [
+                "perl",
+                "-Igen-perl/",
+                "-I../../lib/perl/lib/",
+                "TestServer.pl",
+                "--cert=../keys/server.crt",
+                "--key=../keys/server.key"
+            ],
+            "protocols": [
+                "binary:multi"
+            ]
+        },
+        "workdir": "perl"
     },
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip"
-    ],
-    "protocols": [
-      "header",
-      "compact",
-      "binary",
-      "json"
-    ],
-    "workdir": "hs"
-  },
-  {
-    "name": "py",
-    "server": {
-      "extra_args": ["TSimpleServer"],
-      "command": [
-        "TestServer.py",
-        "--verbose",
-        "--genpydir=gen-py"
-      ]
+    {
+        "name": "php",
+        "client": {
+            "timeout": 6,
+            "transports": [
+                "buffered",
+                "framed"
+            ],
+            "sockets": [
+                "ip"
+            ],
+            "protocols": [
+                "binary",
+                "compact",
+                "binary:accel"
+            ],
+            "command": [
+                "php",
+                "-dextension_dir=php_ext_dir",
+                "--php-ini=test_php.ini",
+                "--no-php-ini",
+                "-ddisplay_errors=stderr",
+                "-dlog_errors=0",
+                "-derror_reporting=E_ALL",
+                "TestClient.php"
+            ]
+        },
+        "workdir": "php"
     },
-    "client": {
-      "timeout": 10,
-      "command": [
-        "TestClient.py",
-        "--verbose",
-        "--host=localhost",
-        "--genpydir=gen-py"
-      ]
+    {
+        "name": "dart",
+        "client": {
+            "transports": [
+                "buffered",
+                "framed",
+                "http"
+            ],
+            "sockets": [
+                "ip"
+            ],
+            "protocols": [
+                "binary",
+                "compact",
+                "json"
+            ],
+            "command": [
+                "dart",
+                "test_client/bin/main.dart"
+            ]
+        },
+        "workdir": "dart"
     },
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl"
-    ],
-    "protocols": [
-      "compact",
-      "binary",
-      "json",
-      "binary:accel",
-      "compact:accelc"
-    ],
-    "workdir": "py"
-  },
-  {
-    "comment": "Using 'python3' executable to test py2 and 3 at once",
-    "name": "py3",
-    "server": {
-      "extra_args": ["TSimpleServer"],
-      "command": [
-        "python3",
-        "TestServer.py",
-        "--verbose",
-        "--genpydir=gen-py"
-      ]
+    {
+        "name": "erl",
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "sockets": [
+            "ip",
+            "ip-ssl"
+        ],
+        "protocols": [
+            "binary",
+            "compact"
+        ],
+        "client": {
+            "command": [
+                "erl",
+                "+K",
+                "true",
+                "-noshell",
+                "-pa",
+                "../../lib/erl/ebin/",
+                "-pa",
+                "./ebin",
+                "-s",
+                "test_client",
+                "-s",
+                "init",
+                "stop",
+                "-extra"
+            ]
+        },
+        "server": {
+            "command": [
+                "erl",
+                "+K",
+                "true",
+                "-noshell",
+                "-pa",
+                "../../lib/erl/ebin/",
+                "-pa",
+                "./ebin",
+                "-s",
+                "test_thrift_server",
+                "-extra"
+            ]
+        },
+        "workdir": "erl"
     },
-    "client": {
-      "timeout": 10,
-      "command": [
-        "python3",
-        "TestClient.py",
-        "--host=localhost",
-        "--genpydir=gen-py"
-      ]
+    {
+        "name": "js",
+        "transports": [
+            "http"
+        ],
+        "sockets": [
+            "ip"
+        ],
+        "protocols": [
+            "json"
+        ],
+        "client": {
+            "command": [
+                "phantomjs",
+                "test/phantom-client.js"
+            ]
+        },
+        "workdir": "../lib/js"
     },
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip-ssl",
-      "ip"
-    ],
-    "protocols": [
-      "compact",
-      "binary",
-      "json",
-      "binary:accel",
-      "compact:accelc"
-    ],
-    "workdir": "py"
-  },
-  {
-    "name": "cpp",
-    "server": {
-      "command": [
-        "TestServer"
-      ],
-      "protocols": [
-        "binary:multi",
-        "compact:multic",
-        "header:multih",
-        "json:multij"
-      ]
+    {
+        "name": "lua",
+        "TODO": "Add dll to LUA_CPATH",
+        "env": {
+            "LUA_PATH": ";;gen-lua/?.lua;../../lib/lua/?.lua",
+            "LUA_CPATH": ";;../../lib/lua/.libs/?.so"
+        },
+        "client": {
+            "timeout": 5,
+            "transports": [
+                "buffered",
+                "framed",
+                "http"
+            ],
+            "sockets": [
+                "ip"
+            ],
+            "protocols": [
+                "binary",
+                "compact",
+                "json"
+            ],
+            "command": [
+                "lua",
+                "test_basic_client.lua"
+            ]
+        },
+        "workdir": "lua"
     },
-    "client": {
-      "timeout": 8,
-      "command": [
-        "TestClient"
-      ],
-      "protocols": [
-        "multi:binary",
-        "multic:compact",
-        "multih:header",
-        "multij:json"
-      ]
-    },
-    "transports": [
-      "buffered",
-      "http",
-      "framed"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl",
-      "domain"
-    ],
-    "protocols": [
-      "compact",
-      "binary",
-      "json",
-      "header",
-      "multi",
-      "multic",
-      "multih",
-      "multij"
-    ],
-    "workdir": "cpp"
-  },
-  {
-    "name": "rb",
-    "server": {
-      "command": [
-        "ruby",
-        "../integration/TestServer.rb"
-      ]
-    },
-    "client": {
-      "timeout": 5,
-      "command": [
-        "ruby",
-        "../integration/TestClient.rb"
-      ]
-    },
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip"
-    ],
-    "protocols": [
-      "compact",
-      "binary",
-      "json",
-      "binary:accel"
-    ],
-    "workdir": "rb/gen-rb"
-  },
-  {
-    "name": "csharp",
-    "env": {
-      "MONO_PATH": "../../lib/csharp/"
-    },
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl"
-    ],
-    "protocols": [
-      "binary",
-      "compact",
-      "json"
-    ],
-    "server": {
-      "command": [
-        "mono",
-        "TestClientServer.exe",
-        "server"
-      ]
-    },
-    "client": {
-      "timeout": 9,
-      "command": [
-        "mono",
-        "TestClientServer.exe",
-        "client"
-      ],
-      "protocols": [
-        "multi",
-        "multic",
-        "multi:binary",
-        "multic:compact"
-      ]
-    },
-    "workdir": "csharp"
-  },
-  {
-    "name": "netcore",
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl"
-    ],
-    "protocols": [
-      "binary",
-      "compact",
-      "json"
-    ],
-    "server-disabled": {
-      "command": [
-        "dotnet",
-        "run",
-  "--no-build",
-  "--no-restore",
-  "--",
-        "server"
-      ]
-    },
-    "client": {
-      "timeout": 10,
-      "command": [
-        "dotnet",
-        "run",
-  "--no-build",
-  "--no-restore",
-  "--",
-        "client"
-      ]
-    },
-    "workdir": "netcore/ThriftTest"
-  },
-  {
-    "name": "perl",
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl",
-      "domain"
-    ],
-    "protocols": [
-      "binary",
-      "multi"
-    ],
-    "client": {
-      "command": [
-        "perl",
-        "-Igen-perl/",
-        "-I../../lib/perl/lib/",
-        "TestClient.pl",
-        "--ca=../keys/CA.pem",
-        "--cert=../keys/client.crt",
-        "--key=../keys/client.key"
-      ],
-      "protocols": [
-        "multi:binary"
-      ]
-    },
-    "server": {
-      "command": [
-        "perl",
-        "-Igen-perl/",
-        "-I../../lib/perl/lib/",
-        "TestServer.pl",
-        "--cert=../keys/server.crt",
-        "--key=../keys/server.key"
-      ],
-      "protocols": [
-        "binary:multi"
-      ]
-    },
-    "workdir": "perl"
-  },
-  {
-    "name": "php",
-    "client": {
-      "timeout": 6,
-      "transports": [
-        "buffered",
-        "framed"
-      ],
-      "sockets": [
-        "ip"
-      ],
-      "protocols": [
-        "binary",
-        "compact",
-        "binary:accel"
-      ],
-      "command": [
-        "php",
-        "-dextension_dir=php_ext_dir",
-        "--php-ini=test_php.ini",
-        "--no-php-ini",
-        "-ddisplay_errors=stderr",
-        "-dlog_errors=0",
-        "-derror_reporting=E_ALL",
-        "TestClient.php"
-      ]
-    },
-    "workdir": "php"
-  },
-  {
-    "name": "dart",
-    "client": {
-      "transports": [
-        "buffered",
-        "framed",
-        "http"
-      ],
-      "sockets": [
-        "ip"
-      ],
-      "protocols": [
-        "binary",
-        "compact",
-        "json"
-      ],
-      "command": [
-        "dart",
-        "test_client/bin/main.dart"
-      ]
-    },
-    "workdir": "dart"
-  },
-  {
-    "name": "erl",
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "sockets": [
-      "ip",
-      "ip-ssl"
-    ],
-    "protocols": [
-      "binary",
-      "compact"
-    ],
-    "client": {
-      "command": [
-        "erl",
-        "+K",
-        "true",
-        "-noshell",
-        "-pa",
-        "../../lib/erl/ebin/",
-        "-pa",
-        "./ebin",
-        "-s",
-        "test_client",
-        "-s",
-        "init",
-        "stop",
-        "-extra"
-      ]
-    },
-    "server": {
-      "command": [
-        "erl",
-        "+K",
-        "true",
-        "-noshell",
-        "-pa",
-        "../../lib/erl/ebin/",
-        "-pa",
-        "./ebin",
-        "-s",
-        "test_thrift_server",
-        "-extra"
-      ]
-    },
-    "workdir": "erl"
-  },
-  {
-    "name": "js",
-    "transports": [
-      "http"
-    ],
-    "sockets": [
-      "ip"
-    ],
-    "protocols": [
-      "json"
-    ],
-    "client": {
-      "command": [
-        "phantomjs",
-        "test/phantom-client.js"
-      ]
-    },
-    "workdir": "../lib/js"
-  },
-  {
-    "name": "lua",
-    "TODO": "Add dll to LUA_CPATH",
-    "env": {
-      "LUA_PATH": ";;gen-lua/?.lua;../../lib/lua/?.lua",
-      "LUA_CPATH": ";;../../lib/lua/.libs/?.so"
-    },
-    "client": {
-      "timeout": 5,
-      "transports": [
-        "buffered",
-        "framed",
-        "http"
-      ],
-      "sockets": [
-        "ip"
-      ],
-      "protocols": [
-        "binary",
-        "compact",
-        "json"
-      ],
-      "command": [
-        "lua",
-        "test_basic_client.lua"
-      ]
-    },
-    "workdir": "lua"
-  },
-  {
-    "name": "rs",
-    "env": {
-      "RUST_BACKTRACE": "1",
-      "RUST_LOG": "info"
-    },
-    "server": {
-      "command": [
-        "test_server"
-      ],
-      "protocols": [
-        "binary:multi",
-        "compact:multic"
-      ]
-    },
-    "client": {
-      "timeout": 6,
-      "command": [
-        "test_client"
-      ],
-      "protocols": [
-        "multi:binary",
-        "multic:compact"
-      ]
-    },
-    "sockets": [
-      "ip"
-    ],
-    "transports": [
-      "buffered",
-      "framed"
-    ],
-    "protocols": [
-      "binary",
-      "compact",
-      "multi",
-      "multic"
-    ],
-    "workdir": "rs/bin"
-  }
-]
+    {
+        "name": "rs",
+        "env": {
+            "RUST_BACKTRACE": "1",
+            "RUST_LOG": "info"
+        },
+        "server": {
+            "command": [
+                "test_server"
+            ],
+            "protocols": [
+                "binary:multi",
+                "compact:multic"
+            ]
+        },
+        "client": {
+            "timeout": 6,
+            "command": [
+                "test_client"
+            ],
+            "protocols": [
+                "multi:binary",
+                "multic:compact"
+            ]
+        },
+        "sockets": [
+            "ip"
+        ],
+        "transports": [
+            "buffered",
+            "framed"
+        ],
+        "protocols": [
+            "binary",
+            "compact",
+            "multi",
+            "multic"
+        ],
+        "workdir": "rs/bin"
+    }
+]
\ No newline at end of file