You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2017/07/18 13:08:58 UTC

[06/43] tinkerpop git commit: Add Gremlin-CSharp and Gremlin-DotNet

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.CSharp.IntegrationTest/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.CSharp.IntegrationTest/Properties/AssemblyInfo.cs b/gremlin-dotnet/test/Gremlin.CSharp.IntegrationTest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..579426b
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.CSharp.IntegrationTest/Properties/AssemblyInfo.cs
@@ -0,0 +1,44 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Gremlin.CSharp.IntegrationTest")]
+[assembly: AssemblyTrademark("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("232f0f2b-178e-4214-99c7-cc4dc6710f44")]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.CSharp.IntegrationTest/appsettings.json
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.CSharp.IntegrationTest/appsettings.json b/gremlin-dotnet/test/Gremlin.CSharp.IntegrationTest/appsettings.json
new file mode 100644
index 0000000..38007ec
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.CSharp.IntegrationTest/appsettings.json
@@ -0,0 +1,4 @@
+{
+  "TestServerIpAddress": "localhost",
+  "TestServerPort": 45950
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/GraphTraversalSourceTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/GraphTraversalSourceTests.cs b/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/GraphTraversalSourceTests.cs
new file mode 100644
index 0000000..bac2d55
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/GraphTraversalSourceTests.cs
@@ -0,0 +1,68 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.CSharp.Structure;
+using Xunit;
+
+namespace Gremlin.CSharp.UnitTest
+{
+    public class GraphTraversalSourceTests
+    {
+        [Fact]
+        public void ShouldBeIndependentFromReturnedGraphTraversalModififyingBytecode()
+        {
+            var graph = new Graph();
+            var g = graph.Traversal();
+
+            g.V().Has("someKey", "someValue").Drop();
+
+            Assert.Equal(0, g.Bytecode.StepInstructions.Count);
+            Assert.Equal(0, g.Bytecode.SourceInstructions.Count);
+        }
+
+        [Fact]
+        public void ShouldBeIndependentFromReturnedGraphTraversalSourceModififyingBytecode()
+        {
+            var graph = new Graph();
+            var g1 = graph.Traversal();
+
+            var g2 = g1.WithSideEffect("someSideEffectKey", "someSideEffectValue");
+
+            Assert.Equal(0, g1.Bytecode.SourceInstructions.Count);
+            Assert.Equal(0, g1.Bytecode.StepInstructions.Count);
+            Assert.Equal(1, g2.Bytecode.SourceInstructions.Count);
+        }
+
+        [Fact]
+        public void ShouldBeIndependentFromReturnedGraphTraversalSourceModififyingTraversalStrategies()
+        {
+            var graph = new Graph();
+            var gLocal = graph.Traversal();
+
+            var gRemote = gLocal.WithRemote(null);
+
+            Assert.Equal(0, gLocal.TraversalStrategies.Count);
+            Assert.Equal(1, gRemote.TraversalStrategies.Count);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/Gremlin.CSharp.UnitTest.csproj
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/Gremlin.CSharp.UnitTest.csproj b/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/Gremlin.CSharp.UnitTest.csproj
new file mode 100644
index 0000000..ea81928
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/Gremlin.CSharp.UnitTest.csproj
@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>    
+    <TargetFramework>netcoreapp1.1</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
+    <PackageReference Include="xunit" Version="2.2.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Gremlin.CSharp\Gremlin.CSharp.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+
+</Project>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/PredicateTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/PredicateTests.cs b/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/PredicateTests.cs
new file mode 100644
index 0000000..c06fb68
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.CSharp.UnitTest/PredicateTests.cs
@@ -0,0 +1,50 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.CSharp.Process;
+using Xunit;
+
+namespace Gremlin.CSharp.UnitTest
+{
+    public class PredicateTests
+    {
+        [Fact]
+        public void ShouldKeepOrderForNestedPredicate()
+        {
+            Assert.Equal("and(eq(a),lt(b))", P.Eq("a").And(P.Lt("b")).ToString());
+        }
+
+        [Fact]
+        public void ShouldKeepOrderForDoubleNestedPredicate()
+        {
+            Assert.Equal("and(or(lt(b),gt(c)),neq(d))", P.Lt("b").Or(P.Gt("c")).And(P.Neq("d")).ToString());
+        }
+
+        [Fact]
+        public void ShouldKeepOrderForTripleNestedPredicate()
+        {
+            Assert.Equal("and(or(lt(b),gt(c)),or(neq(d),gte(e)))",
+                P.Lt("b").Or(P.Gt("c")).And(P.Neq("d").Or(P.Gte("e"))).ToString());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/ConfigProvider.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/ConfigProvider.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/ConfigProvider.cs
new file mode 100644
index 0000000..b7afe74
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/ConfigProvider.cs
@@ -0,0 +1,47 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.IO;
+using Microsoft.Extensions.Configuration;
+
+namespace Gremlin.Net.IntegrationTest
+{
+    public static class ConfigProvider
+    {
+        static ConfigProvider()
+        {
+            Configuration = GetConfig();
+        }
+
+        public static IConfiguration Configuration { get; }
+
+        private static IConfiguration GetConfig()
+        {
+            var configFile = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json");
+            var builder = new ConfigurationBuilder()
+                .AddJsonFile(configFile, false, false);
+
+            return builder.Build();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/ConnectionPoolTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/ConnectionPoolTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/ConnectionPoolTests.cs
new file mode 100644
index 0000000..21a2627
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/ConnectionPoolTests.cs
@@ -0,0 +1,90 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Gremlin.Net.Driver;
+using Gremlin.Net.IntegrationTest.Util;
+using Xunit;
+
+namespace Gremlin.Net.IntegrationTest.Driver
+{
+    public class ConnectionPoolTests
+    {
+        private readonly RequestMessageProvider _requestMessageProvider = new RequestMessageProvider();
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
+
+        private async Task ExecuteMultipleLongRunningRequestsInParallel(IGremlinClient gremlinClient, int nrRequests,
+            int requestRunningTimeInMs)
+        {
+            var longRunningRequestMsg = _requestMessageProvider.GetSleepMessage(requestRunningTimeInMs);
+            var tasks = new List<Task>(nrRequests);
+            for (var i = 0; i < nrRequests; i++)
+                tasks.Add(gremlinClient.SubmitAsync(longRunningRequestMsg));
+            await Task.WhenAll(tasks);
+        }
+
+        [Fact]
+        public async Task ShouldReuseConnectionForSequentialRequests()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                await gremlinClient.SubmitAsync("");
+                await gremlinClient.SubmitAsync("");
+
+                var nrConnections = gremlinClient.NrConnections;
+                Assert.Equal(1, nrConnections);
+            }
+        }
+
+        [Fact]
+        public void ShouldOnlyCreateConnectionWhenNecessary()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var nrConnections = gremlinClient.NrConnections;
+                Assert.Equal(0, nrConnections);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldExecuteParallelRequestsOnDifferentConnections()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var sleepTime = 50;
+                var nrParallelRequests = 5;
+
+                await ExecuteMultipleLongRunningRequestsInParallel(gremlinClient, nrParallelRequests, sleepTime);
+
+                var nrConnections = gremlinClient.NrConnections;
+                Assert.Equal(nrParallelRequests, nrConnections);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
new file mode 100644
index 0000000..351b83d
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
@@ -0,0 +1,212 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Exceptions;
+using Gremlin.Net.Driver.Messages;
+using Gremlin.Net.IntegrationTest.Util;
+using Xunit;
+
+namespace Gremlin.Net.IntegrationTest.Driver
+{
+    public class GremlinClientTests
+    {
+        private readonly RequestMessageProvider _requestMessageProvider = new RequestMessageProvider();
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
+
+        [Theory]
+        [InlineData("'justAString'", "justAString")]
+        [InlineData("'Hello' + 'World'", "HelloWorld")]
+        public async Task ShouldSendScriptForEvaluationAndReturnCorrectResult(string requestMsg, string expectedResponse)
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var response = await gremlinClient.SubmitWithSingleResultAsync<string>(requestMsg);
+
+                Assert.Equal(expectedResponse, response);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldHandleBigResponse()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var responseMsgSize = 5000;
+                var requestMsg = $"'1'*{responseMsgSize}";
+
+                var response = await gremlinClient.SubmitWithSingleResultAsync<string>(requestMsg);
+
+                Assert.Equal(responseMsgSize, response.Length);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldHandleResponseWithoutContent()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var gremlinScript = "g.V().has(propertyKey, propertyValue);";
+                var bindings = new Dictionary<string, object>
+                {
+                    {"propertyKey", "name"},
+                    {"propertyValue", "unknownTestName"}
+                };
+
+                var response =
+                    await gremlinClient.SubmitWithSingleResultAsync<object>(gremlinScript, bindings);
+
+                Assert.Null(response);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldThrowExceptionForInvalidScript()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var requestMsg = "invalid";
+
+                var exception =
+                    await Assert.ThrowsAsync<ResponseException>(() => gremlinClient.SubmitAsync(requestMsg));
+
+                Assert.Equal(typeof(ResponseException), exception.GetType());
+                Assert.Contains($"ScriptEvaluationError: No such property: {requestMsg}",
+                    exception.Message);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldReassembleResponseBatches()
+        {
+            const int batchSize = 2;
+            var expectedResult = new List<int> {1, 2, 3, 4, 5};
+            var requestScript = $"{nameof(expectedResult)}";
+            var bindings = new Dictionary<string, object> {{nameof(expectedResult), expectedResult}};
+            var requestMessage =
+                RequestMessage.Build(Tokens.OpsEval)
+                    .AddArgument(Tokens.ArgsBatchSize, batchSize)
+                    .AddArgument(Tokens.ArgsGremlin, requestScript)
+                    .AddArgument(Tokens.ArgsBindings, bindings)
+                    .Create();
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var response = await gremlinClient.SubmitAsync<int>(requestMessage);
+
+                Assert.Equal(expectedResult, response);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldCorrectlyAssignResponsesToRequests()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var sleepTime = 100;
+                var expectedFirstResult = 1;
+                var gremlinScript = _requestMessageProvider.GetSleepGremlinScript(sleepTime);
+                gremlinScript += $"{expectedFirstResult}";
+                var firstRequestMsg = RequestMessage.Build(Tokens.OpsEval)
+                    .AddArgument(Tokens.ArgsGremlin, gremlinScript).Create();
+                var expectedSecondResponse = 2;
+                var secondScript = $"{expectedSecondResponse}";
+
+                var firstResponseTask = gremlinClient.SubmitWithSingleResultAsync<int>(firstRequestMsg);
+                var secondResponseTask = gremlinClient.SubmitWithSingleResultAsync<int>(secondScript);
+
+                var secondResponse = await secondResponseTask;
+                Assert.Equal(expectedSecondResponse, secondResponse);
+                var firstResponse = await firstResponseTask;
+                Assert.Equal(expectedFirstResult, firstResponse);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldReturnEnumerableResult()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var expectedResult = new List<int> {1, 2, 3, 4, 5};
+                var requestMsg = $"{nameof(expectedResult)}";
+                var bindings = new Dictionary<string, object> {{nameof(expectedResult), expectedResult}};
+
+                var response = await gremlinClient.SubmitAsync<int>(requestMsg, bindings);
+
+                Assert.Equal(expectedResult, response);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldThrowOnExecutionOfSimpleInvalidScript()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var invalidRequestScript = "invalid";
+
+                await Assert.ThrowsAsync<ResponseException>(() => gremlinClient.SubmitAsync(invalidRequestScript));
+            }
+        }
+
+        [Fact]
+        public async Task ShouldHandleSimpleScriptWithoutErrors()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var requestMsg = _requestMessageProvider.GetDummyMessage();
+
+                await gremlinClient.SubmitAsync(requestMsg);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldUseBindingsForScript()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var requestMsg = "a + b";
+                var a = 1;
+                var b = 2;
+                var bindings = new Dictionary<string, object> {{"a", a}, {"b", b}};
+
+                var response =
+                    await gremlinClient.SubmitWithSingleResultAsync<int>(requestMsg, bindings);
+
+                Assert.Equal(a + b, response);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
new file mode 100644
index 0000000..6f6505f
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
@@ -0,0 +1,147 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Exceptions;
+using Gremlin.Net.Driver.Messages;
+using Gremlin.Net.IntegrationTest.Util;
+using Xunit;
+
+namespace Gremlin.Net.IntegrationTest.Driver
+{
+    public class MessagesTests
+    {
+        private readonly RequestMessageProvider _requestMessageProvider = new RequestMessageProvider();
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
+
+        [Fact]
+        public async Task ShouldUseAliasForTraversalSource()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var aliasTraversalSource = "g2";
+                var aliases = new Dictionary<string, string> {{aliasTraversalSource, "g"}};
+                var gremlinScript = $"{aliasTraversalSource}.V().count()";
+                var requestMsg =
+                    RequestMessage.Build(Tokens.OpsEval)
+                        .AddArgument(Tokens.ArgsAliases, aliases)
+                        .AddArgument(Tokens.ArgsGremlin, gremlinScript)
+                        .Create();
+
+                var result = await gremlinClient.SubmitWithSingleResultAsync<long>(requestMsg);
+
+                Assert.NotNull(result);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldThrowForInvalidOperation()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var ivalidOperationName = "invalid";
+                var requestMsg = RequestMessage.Build(ivalidOperationName).Create();
+
+                var thrownException =
+                    await Assert.ThrowsAsync<ResponseException>(() => gremlinClient.SubmitAsync<dynamic>(requestMsg));
+
+                Assert.Contains("MalformedRequest", thrownException.Message);
+                Assert.Contains(ivalidOperationName, thrownException.Message);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldThrowForInvalidProcessor()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var invalidProcessorName = "invalid";
+                var requestMsg = RequestMessage.Build("").Processor(invalidProcessorName).Create();
+
+                var thrownException =
+                    await Assert.ThrowsAsync<ResponseException>(() => gremlinClient.SubmitAsync<dynamic>(requestMsg));
+
+                Assert.Contains("InvalidRequestArguments", thrownException.Message);
+                Assert.Contains(invalidProcessorName, thrownException.Message);
+                Assert.Contains("OpProcessor", thrownException.Message);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldUseSpecifiedScriptEvaluationTimeout()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                const int timeOutInMs = 1;
+                const int scriptSleepTimeInMs = 5000;
+                var sleepScript = _requestMessageProvider.GetSleepGremlinScript(scriptSleepTimeInMs);
+
+                var requestMsg =
+                    RequestMessage.Build(Tokens.OpsEval)
+                        .AddArgument(Tokens.ArgsGremlin, sleepScript)
+                        .AddArgument(Tokens.ArgsEvalTimeout, timeOutInMs)
+                        .Create();
+                var evaluationStopWatch = new Stopwatch();
+                evaluationStopWatch.Start();
+
+                var thrownException =
+                    await Assert.ThrowsAsync<ResponseException>(() => gremlinClient.SubmitAsync(requestMsg));
+
+                evaluationStopWatch.Stop();
+                Assert.Contains("ServerTimeout", thrownException.Message);
+                Assert.Contains(timeOutInMs.ToString(), thrownException.Message);
+                Assert.True(evaluationStopWatch.ElapsedMilliseconds < scriptSleepTimeInMs);
+            }
+        }
+
+        [Fact]
+        public async Task ShouldThrowForUnsupportedLanguage()
+        {
+            var gremlinServer = new GremlinServer(TestHost, TestPort);
+            using (var gremlinClient = new GremlinClient(gremlinServer))
+            {
+                var unknownLanguage = "unknown";
+                var requestMsg =
+                    RequestMessage.Build(Tokens.OpsEval)
+                        .AddArgument(Tokens.ArgsGremlin, "1")
+                        .AddArgument(Tokens.ArgsLanguage, unknownLanguage)
+                        .Create();
+
+                var thrownException =
+                    await Assert.ThrowsAsync<ResponseException>(() => gremlinClient.SubmitAsync(requestMsg));
+
+                Assert.Contains("ScriptEvaluationError", thrownException.Message);
+                Assert.Contains(unknownLanguage, thrownException.Message);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
new file mode 100644
index 0000000..f8407a9
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
@@ -0,0 +1,41 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp1.0</TargetFramework>
+    <DebugType>portable</DebugType>
+    <AssemblyName>Gremlin.Net.IntegrationTest</AssemblyName>
+    <PackageId>Gremlin.Net.IntegrationTest</PackageId>
+    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
+    <RuntimeFrameworkVersion>1.0.4</RuntimeFrameworkVersion>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <None Update="appsettings.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Gremlin.Net.Process\Gremlin.Net.Process.csproj" />
+    <ProjectReference Include="..\..\src\Gremlin.Net\Gremlin.Net.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+    <PackageReference Include="xunit" Version="2.2.0" />
+    <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.1" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
+    <PackageReference Include="xunit.runner.console" Version="2.2.0" />
+    <PackageReference Include="OpenCover" Version="4.6.519" />
+    <PackageReference Include="coveralls.io" Version="1.3.4" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+
+</Project>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
new file mode 100644
index 0000000..de91152
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
@@ -0,0 +1,85 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Threading.Tasks;
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Remote;
+using Gremlin.Net.Process.Remote;
+using Gremlin.Net.Process.Traversal;
+using Xunit;
+
+namespace Gremlin.Net.IntegrationTest.Process.Remote
+{
+    public class RemoteStrategyTests
+    {
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
+
+        [Fact]
+        public void ShouldSendBytecodeToGremlinServer()
+        {
+            const string expectedResult = "gremlin";
+            var testBytecode = new Bytecode();
+            testBytecode.AddStep("V");
+            testBytecode.AddStep("has", "test");
+            testBytecode.AddStep("inject", expectedResult);
+            var testTraversal = CreateTraversalWithRemoteStrategy(testBytecode);
+
+            var actualResult = testTraversal.Next();
+
+            Assert.Equal(expectedResult, actualResult);
+        }
+
+        [Fact]
+        public async Task ShouldSendBytecodeToGremlinServerAsynchronouslyForTraversalPromise()
+        {
+            const string expectedResult = "gremlin";
+            var testBytecode = new Bytecode();
+            testBytecode.AddStep("V");
+            testBytecode.AddStep("has", "test");
+            testBytecode.AddStep("inject", expectedResult);
+            var testTraversal = CreateTraversalWithRemoteStrategy(testBytecode);
+
+            var actualResult = await testTraversal.Promise(t => t.Next());
+
+            Assert.Equal(expectedResult, actualResult);
+        }
+
+        private DefaultTraversal CreateTraversalWithRemoteStrategy(Bytecode bytecode)
+        {
+            var remoteStrategy =
+                new RemoteStrategy(new DriverRemoteConnection(new GremlinClient(new GremlinServer(TestHost, TestPort))));
+            return new TestTraversal(remoteStrategy, bytecode);
+        }
+    }
+
+    internal class TestTraversal : DefaultTraversal
+    {
+        public TestTraversal(ITraversalStrategy traversalStrategy, Bytecode bytecode)
+        {
+            TraversalStrategies.Add(traversalStrategy);
+            Bytecode = bytecode;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Properties/AssemblyInfo.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..5dea6f0
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Properties/AssemblyInfo.cs
@@ -0,0 +1,44 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Gremlin.Net.IntegrationTest")]
+[assembly: AssemblyTrademark("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("cc54abe3-13d2-491c-81e2-4d0355abfa93")]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Util/RequestMessageProvider.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Util/RequestMessageProvider.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Util/RequestMessageProvider.cs
new file mode 100644
index 0000000..eb8735f
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Util/RequestMessageProvider.cs
@@ -0,0 +1,54 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Messages;
+
+namespace Gremlin.Net.IntegrationTest.Util
+{
+    internal class RequestMessageProvider
+    {
+        public string GetSleepGremlinScript(int sleepTimeInMs)
+        {
+            return $"Thread.sleep({sleepTimeInMs});";
+        }
+
+        public RequestMessage GetSleepMessage(int sleepTimeInMs)
+        {
+            var gremlinScript = $"Thread.sleep({nameof(sleepTimeInMs)});";
+            var bindings = new Dictionary<string, object> {{nameof(sleepTimeInMs), sleepTimeInMs}};
+            return
+                RequestMessage.Build(Tokens.OpsEval)
+                    .AddArgument(Tokens.ArgsGremlin, gremlinScript)
+                    .AddArgument(Tokens.ArgsBindings, bindings)
+                    .Create();
+        }
+
+        public RequestMessage GetDummyMessage()
+        {
+            var gremlinScript = "1";
+            return RequestMessage.Build(Tokens.OpsEval).AddArgument(Tokens.ArgsGremlin, gremlinScript).Create();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/appsettings.json
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/appsettings.json b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/appsettings.json
new file mode 100644
index 0000000..38007ec
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/appsettings.json
@@ -0,0 +1,4 @@
+{
+  "TestServerIpAddress": "localhost",
+  "TestServerPort": 45950
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Gremlin.Net.Process.UnitTest.csproj
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Gremlin.Net.Process.UnitTest.csproj b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Gremlin.Net.Process.UnitTest.csproj
new file mode 100644
index 0000000..2345f31
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Gremlin.Net.Process.UnitTest.csproj
@@ -0,0 +1,22 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>    
+    <TargetFramework>netcoreapp1.1</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
+    <PackageReference Include="Moq" Version="4.7.1" />
+    <PackageReference Include="xunit" Version="2.2.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Gremlin.Net.Process\Gremlin.Net.Process.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+
+</Project>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/BytecodeTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/BytecodeTests.cs b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/BytecodeTests.cs
new file mode 100644
index 0000000..de0a0b7
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/BytecodeTests.cs
@@ -0,0 +1,44 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.Net.Process.Traversal;
+using Xunit;
+
+namespace Gremlin.Net.Process.UnitTest.Traversal
+{
+    public class BytecodeTests
+    {
+        [Fact]
+        public void ShouldUseBingings()
+        {
+            var bytecode = new Bytecode();
+            var bindings = new Bindings();
+
+            bytecode.AddStep("hasLabel", bindings.Of("label", "testLabel"));
+
+            var arg = bytecode.StepInstructions[0].Arguments[0];
+            var binding = arg as Binding;
+            Assert.Equal(new Binding("label", "testLabel"), binding);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/Strategy/StrategyTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/Strategy/StrategyTests.cs b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/Strategy/StrategyTests.cs
new file mode 100644
index 0000000..2e7dc5e
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/Strategy/StrategyTests.cs
@@ -0,0 +1,109 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.Net.Process.Traversal.Strategy;
+using Gremlin.Net.Process.Traversal.Strategy.Optimization;
+using Gremlin.Net.Process.Traversal.Strategy.Verification;
+using Xunit;
+
+namespace Gremlin.Net.Process.UnitTest.Traversal.Strategy
+{
+    public class StrategyTests
+    {
+        [Fact]
+        public void ShouldReturnFalseForEqualsOfStrategiesWithDifferentStrategyNames()
+        {
+            var firstStrategy = new TestStrategy("aConfigKey", "aConfigValue");
+            var secondStrategy = new IncidentToAdjacentStrategy();
+
+            var areEqual = firstStrategy.Equals(secondStrategy);
+
+            Assert.False(areEqual);
+        }
+
+        [Fact]
+        public void ShouldReturnTrueForEqualsOfStrategiesWithEqualNamesButDifferentConfigurations()
+        {
+            var firstStrategy = new TestStrategy("aConfigKey", "aConfigValue");
+            var secondStrategy = new TestStrategy("anotherKey", "anotherValue");
+
+            var areEqual = firstStrategy.Equals(secondStrategy);
+
+            Assert.True(areEqual);
+        }
+
+        [Fact]
+        public void ShouldReturnDifferentHashcodesForStrategiesWithDifferentNames()
+        {
+            var firstStrategy = new TestStrategy();
+            var secondStrategy = new ReadOnlyStrategy();
+
+            var firstHashCode = firstStrategy.GetHashCode();
+            var secondHashCode = secondStrategy.GetHashCode();
+
+            Assert.NotEqual(firstHashCode, secondHashCode);
+        }
+
+        [Fact]
+        public void ShouldReturnEqualHashcodesForStrategiesWithEqualNamesButDifferentConfigurations()
+        {
+            var firstStrategy = new TestStrategy("aConfigKey", "aConfigValue");
+            var secondStrategy = new TestStrategy("anotherKey", "anotherValue");
+
+            var firstHashCode = firstStrategy.GetHashCode();
+            var secondHashCode = secondStrategy.GetHashCode();
+
+            Assert.Equal(firstHashCode, secondHashCode);
+        }
+
+        [Fact]
+        public void ShouldReturnClassNameForStrategyNameProperty()
+        {
+            var testStrategy = new TestStrategy();
+
+            Assert.Equal("TestStrategy", testStrategy.StrategyName);
+        }
+
+        [Fact]
+        public void ShouldReturnStrategyNameWhenForToString()
+        {
+            var testStrategy = new TestStrategy();
+
+            var strategyStr = testStrategy.ToString();
+
+            Assert.Equal("TestStrategy", strategyStr);
+        }
+    }
+
+    internal class TestStrategy : AbstractTraversalStrategy
+    {
+        public TestStrategy()
+        {
+        }
+
+        public TestStrategy(string configKey, dynamic configValue)
+        {
+            Configuration[configKey] = configValue;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TestTraversal.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TestTraversal.cs b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TestTraversal.cs
new file mode 100644
index 0000000..34f88df
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TestTraversal.cs
@@ -0,0 +1,51 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.Process.UnitTest.Traversal
+{
+    public class TestTraversal : Process.Traversal.DefaultTraversal
+    {
+        public TestTraversal(List<object> traverserObjs)
+        {
+            var traversers = new List<Traverser>(traverserObjs.Count);
+            traverserObjs.ForEach(o => traversers.Add(new Traverser(o)));
+            Traversers = traversers;
+        }
+
+        public TestTraversal(IReadOnlyList<object> traverserObjs, IReadOnlyList<long> traverserBulks)
+        {
+            var traversers = new List<Traverser>(traverserObjs.Count);
+            traversers.AddRange(traverserObjs.Select((t, i) => new Traverser(t, traverserBulks[i])));
+            Traversers = traversers;
+        }
+
+        public TestTraversal(IList<ITraversalStrategy> traversalStrategies)
+        {
+            TraversalStrategies = traversalStrategies;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TestTraversalStrategy.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TestTraversalStrategy.cs b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TestTraversalStrategy.cs
new file mode 100644
index 0000000..d643440
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TestTraversalStrategy.cs
@@ -0,0 +1,50 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.Process.UnitTest.Traversal
+{
+    public class TestTraversalStrategy : ITraversalStrategy
+    {
+        private readonly IEnumerable<Traverser> _traversers;
+
+        public TestTraversalStrategy(IEnumerable<Traverser> traversersToAddOnApplication)
+        {
+            _traversers = traversersToAddOnApplication;
+        }
+
+        public void Apply(ITraversal traversal)
+        {
+            traversal.Traversers = _traversers;
+        }
+
+        public Task ApplyAsync(ITraversal traversal)
+        {
+            traversal.Traversers = _traversers;
+            return Task.CompletedTask;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TraversalTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TraversalTests.cs b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TraversalTests.cs
new file mode 100644
index 0000000..a823a5d
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TraversalTests.cs
@@ -0,0 +1,177 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Gremlin.Net.Process.Traversal;
+using Moq;
+using Xunit;
+
+namespace Gremlin.Net.Process.UnitTest.Traversal
+{
+    public class TraversalTests
+    {
+        [Theory]
+        [InlineData(1)]
+        [InlineData("test")]
+        public void ShouldReturnAvailableTraverserObjWhenNextIsCalled(object traverserObj)
+        {
+            var traversal = new TestTraversal(new List<object> {traverserObj});
+
+            var actualObj = traversal.Next();
+
+            Assert.Equal(traverserObj, actualObj);
+        }
+
+        [Theory]
+        [InlineData(3)]
+        [InlineData(10)]
+        public void ShouldReturnCorrectNrOfResultObjsWhenNextIsCalledWithAmountArgument(int nrOfResults)
+        {
+            var objs = new List<object>(20);
+            for (var i = 0; i < 20; i++)
+                objs.Add(i);
+            var traversal = new TestTraversal(objs);
+
+            var traversedObjs = traversal.Next(nrOfResults);
+
+            var traversedObjsList = traversedObjs.ToList();
+            Assert.Equal(nrOfResults, traversedObjsList.Count);
+            for (var i = 0; i < nrOfResults; i++)
+                Assert.Equal(objs[i], traversedObjsList[i]);
+        }
+
+        private List<object> UnfoldBulks(IReadOnlyList<object> objs, IReadOnlyList<long> bulks)
+        {
+            var unfoldedObjs = new List<object>();
+            for (var traverserIdx = 0; traverserIdx < objs.Count; traverserIdx++)
+            for (var currentBulkObjIdx = 0; currentBulkObjIdx < bulks[traverserIdx]; currentBulkObjIdx++)
+                unfoldedObjs.Add(objs[traverserIdx]);
+            return unfoldedObjs;
+        }
+
+        [Fact]
+        public void ShouldDrainAllTraversersWhenIterateIsCalled()
+        {
+            var someObjs = new List<object> {1, 2, 3};
+            var traversal = new TestTraversal(someObjs);
+
+            var drainedTraversal = traversal.Iterate();
+
+            Assert.Null(drainedTraversal.Next());
+        }
+
+        [Fact]
+        public void ShouldReturnNullWhenNextIsCalledAndNoTraverserIsAvailable()
+        {
+            var expectedFirstObj = 1;
+            var traversal = new TestTraversal(new List<object> {expectedFirstObj});
+
+            var actualFirstObj = traversal.Next();
+            var actualSecondObj = traversal.Next();
+
+            Assert.Equal(expectedFirstObj, actualFirstObj);
+            Assert.Null(actualSecondObj);
+        }
+
+        [Fact]
+        public void ShouldReturnTraversalsTraverserWhenNextTraverserIsCalled()
+        {
+            var someObjs = new List<object> {1, 2, 3};
+            var traversal = new TestTraversal(someObjs);
+
+            var traverser = traversal.NextTraverser();
+
+            Assert.Equal(traversal.Traversers.First(), traverser);
+        }
+
+        [Fact]
+        public void ShouldThrowNotSupportedExceptionWhenResetIsCalled()
+        {
+            var someObjs = new List<object> {1, 2, 3};
+            var traversal = new TestTraversal(someObjs);
+
+            Assert.Throws<NotSupportedException>(() => traversal.Reset());
+        }
+
+        [Fact]
+        public void ShouldReturnAllTraverserObjsWhenToListIsCalled()
+        {
+            var expectedObjs = new List<object> {1, 2, 3};
+            var traversal = new TestTraversal(expectedObjs);
+
+            var traversedObjs = traversal.ToList();
+
+            Assert.Equal(expectedObjs, traversedObjs);
+        }
+
+        [Fact]
+        public void ShouldReturnAllTraverserObjWithoutDuplicatesWhenToSetIsCalled()
+        {
+            var traverserObjs = new List<object> {1, 1, 2, 3};
+            var traversal = new TestTraversal(traverserObjs);
+
+            var traversedObjSet = traversal.ToSet();
+
+            Assert.Equal(3, traversedObjSet.Count);
+            Assert.Equal(new HashSet<object>(traverserObjs), traversedObjSet);
+        }
+
+        [Fact]
+        public void ShouldApplyStrategiesWhenNextIsCalledAndNoTraversersPresent()
+        {
+            const int expectedObj = 531;
+            var testStrategy = new TestTraversalStrategy(new List<Traverser> {new Traverser(expectedObj)});
+            var testTraversal = new TestTraversal(new List<ITraversalStrategy> {testStrategy});
+
+            var actualObj = testTraversal.Next();
+
+            Assert.Equal(expectedObj, actualObj);
+        }
+
+        [Fact]
+        public void ShouldBeUnfoldTraverserBulksWhenToListIsCalled()
+        {
+            var objs = new List<object> {1, 2, 3};
+            var bulks = new List<long> {3, 2, 1};
+            var traversal = new TestTraversal(objs, bulks);
+
+            var traversedObjs = traversal.ToList();
+
+            var expectedObjs = UnfoldBulks(objs, bulks);
+            Assert.Equal(expectedObjs, traversedObjs);
+        }
+
+        [Fact]
+        public void ShouldDisposeSideEffectsWhenDisposeIsCalled()
+        {
+            var sideEffectsMock = new Mock<ITraversalSideEffects>();
+            var traversal = new TestTraversal(new List<object>()) {SideEffects = sideEffectsMock.Object};
+
+            traversal.Dispose();
+
+            sideEffectsMock.Verify(m => m.Dispose());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TraverserTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TraverserTests.cs b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TraverserTests.cs
new file mode 100644
index 0000000..4f6d2b5
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.Process.UnitTest/Traversal/TraverserTests.cs
@@ -0,0 +1,75 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.Net.Process.Traversal;
+using Xunit;
+
+namespace Gremlin.Net.Process.UnitTest.Traversal
+{
+    public class TraverserTests
+    {
+        [Fact]
+        public void ShouldReturnFalseForEqualsWhereOtherIsNull()
+        {
+            var traverser = new Traverser("anObject");
+
+            var areEqual = traverser.Equals(null);
+
+            Assert.False(areEqual);
+        }
+
+        [Fact]
+        public void ShouldReturnTrueForEqualsWithSameObjectAndDifferentBulk()
+        {
+            var firstTraverser = new Traverser("anObject", 1234);
+            var secondTraverser = new Traverser("anObject", 9876);
+
+            var areEqual = firstTraverser.Equals(secondTraverser);
+
+            Assert.True(areEqual);
+        }
+
+        [Fact]
+        public void ShouldReturnTrueForEqualsObjectWithSameObjectAndDifferentBulk()
+        {
+            var firstTraverser = new Traverser("anObject", 1234);
+            object secondTraverser = new Traverser("anObject", 9876);
+
+            var areEqual = firstTraverser.Equals(secondTraverser);
+
+            Assert.True(areEqual);
+        }
+
+        [Fact]
+        public void ShouldReturnEqualHashcodesForTraversersWithSameObjectAndDifferentBulk()
+        {
+            var firstTraverser = new Traverser("anObject", 1234);
+            var secondTraverser = new Traverser("anObject", 9876);
+
+            var firstHashCode = firstTraverser.GetHashCode();
+            var secondHashCode = secondTraverser.GetHashCode();
+
+            Assert.Equal(firstHashCode, secondHashCode);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs
new file mode 100644
index 0000000..7ed9c96
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs
@@ -0,0 +1,51 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Remote;
+using Moq;
+using Xunit;
+
+namespace Gremlin.Net.UnitTest.Driver
+{
+    public class DriverRemoteConnectionTests
+    {
+        [Fact]
+        public void ShouldDisposeProvidedGremlinClientOnDispose()
+        {
+            var gremlinClientMock = new Mock<IGremlinClient>();
+            var driverRemoteConnection = new DriverRemoteConnection(gremlinClientMock.Object);
+
+            driverRemoteConnection.Dispose();
+
+            gremlinClientMock.Verify(m => m.Dispose());
+        }
+
+        [Fact]
+        public void ShouldThrowWhenGivenNullAsGremlinClient()
+        {
+            Assert.Throws<ArgumentNullException>(() => new DriverRemoteConnection(null));
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/GremlinServerTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/GremlinServerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/GremlinServerTests.cs
new file mode 100644
index 0000000..54c5a06
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/GremlinServerTests.cs
@@ -0,0 +1,66 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.Net.Driver;
+using Xunit;
+
+namespace Gremlin.Net.UnitTest.Driver
+{
+    public class GremlinServerTests
+    {
+        [Theory]
+        [InlineData("localhost", 8182)]
+        [InlineData("1.2.3.4", 5678)]
+        public void ShouldBuildCorrectUri(string host, int port)
+        {
+            var gremlinServer = new GremlinServer(host, port);
+
+            var uri = gremlinServer.Uri;
+
+            Assert.Equal($"ws://{host}:{port}/gremlin", uri.AbsoluteUri);
+        }
+
+        [Fact]
+        public void ShouldBuildCorrectUriForSsl()
+        {
+            var host = "localhost";
+            var port = 8181;
+            var gremlinServer = new GremlinServer(host, port, true);
+
+            var uri = gremlinServer.Uri;
+
+            Assert.Equal($"wss://{host}:{port}/gremlin", uri.AbsoluteUri);
+        }
+
+        [Fact]
+        public void ShouldUseCorrectDefaultPortWhenNoneProvided()
+        {
+            var host = "testHost";
+            var gremlinServer = new GremlinServer(host);
+
+            var uri = gremlinServer.Uri;
+
+            Assert.Equal(8182, uri.Port);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/RequestMessageBuilderTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/RequestMessageBuilderTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/RequestMessageBuilderTests.cs
new file mode 100644
index 0000000..cc5d2ee
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/RequestMessageBuilderTests.cs
@@ -0,0 +1,41 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Messages;
+using Xunit;
+
+namespace Gremlin.Net.UnitTest.Driver
+{
+    public class RequestMessageBuilderTests
+    {
+        [Fact]
+        public void ShouldUseUniqueRequestIds()
+        {
+            var firstMsg = RequestMessage.Build(Tokens.OpsEval).Create();
+            var secondMsg = RequestMessage.Build(Tokens.OpsEval).Create();
+
+            Assert.NotEqual(firstMsg.RequestId, secondMsg.RequestId);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj
new file mode 100644
index 0000000..3d2da0d
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj
@@ -0,0 +1,35 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp1.0</TargetFramework>
+    <DebugType>portable</DebugType>
+    <AssemblyName>Gremlin.Net.UnitTest</AssemblyName>
+    <PackageId>Gremlin.Net.UnitTest</PackageId>
+    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
+    <RuntimeFrameworkVersion>1.0.4</RuntimeFrameworkVersion>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Gremlin.Net.Process\Gremlin.Net.Process.csproj" />
+    <ProjectReference Include="..\..\src\Gremlin.Net\Gremlin.Net.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
+    <PackageReference Include="Moq" Version="4.7.1" />
+    <PackageReference Include="System.Runtime" Version="4.3.0" />
+    <PackageReference Include="System.Runtime.InteropServices" Version="4.3.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
+    <PackageReference Include="xunit" Version="2.2.0" />
+    <PackageReference Include="OpenCover" Version="4.6.519" />
+    <PackageReference Include="coveralls.io" Version="1.3.4" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+
+</Project>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.UnitTest/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Properties/AssemblyInfo.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f339aa0
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Properties/AssemblyInfo.cs
@@ -0,0 +1,44 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Gremlin.Net.UnitTest")]
+[assembly: AssemblyTrademark("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("1fab781b-b857-4ad2-bec8-e20c214d9e21")]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/EdgeTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/EdgeTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/EdgeTests.cs
new file mode 100644
index 0000000..e636580
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/EdgeTests.cs
@@ -0,0 +1,57 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.Net.Structure;
+using Xunit;
+
+namespace Gremlin.Net.UnitTest.Structure
+{
+    public class EdgeTests
+    {
+        [Fact]
+        public void ShouldAssignPropertiesCorrectly()
+        {
+            const int id = 2;
+            var outV = new Vertex(1);
+            const string edgeLabel = "said";
+            var inV = new Vertex("hello", "phrase");
+
+            var edge = new Edge(id, outV, edgeLabel, inV);
+
+            Assert.Equal(outV, edge.OutV);
+            Assert.Equal(inV, edge.InV);
+            Assert.Equal(edgeLabel, edge.Label);
+            Assert.NotEqual(edge.InV, edge.OutV);
+        }
+
+        [Fact]
+        public void ShouldReturnCommonStringRepresentationForToString()
+        {
+            var edge = new Edge(2, new Vertex(1), "said", new Vertex("hello", "phrase"));
+
+            var edgeStr = edge.ToString();
+
+            Assert.Equal("e[2][1-said->hello]", edgeStr);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/37a24719/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
new file mode 100644
index 0000000..e367124
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
@@ -0,0 +1,153 @@
+#region License
+
+/*
+ * 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
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+using Gremlin.Net.Process.Traversal;
+using Gremlin.Net.Structure.IO.GraphSON;
+using Xunit;
+
+namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
+{
+    public class BytecodeGraphSONSerializerTests
+    {
+        private GraphSONWriter CreateGraphSONWriter()
+        {
+            return new GraphSONWriter();
+        }
+
+        [Fact]
+        public void ShouldSerializeByteCodeWithNestedTraversal()
+        {
+            var bytecode = new Bytecode();
+            bytecode.AddStep("V");
+            var nestedBytecode = new Bytecode();
+            var nestedTraversal = new TestTraversal(nestedBytecode);
+            nestedBytecode.AddStep("out");
+            bytecode.AddStep("repeat", nestedTraversal);
+            var graphsonWriter = CreateGraphSONWriter();
+
+            var graphSON = graphsonWriter.WriteObject(bytecode);
+
+            var expectedGraphSon =
+                "{\"@type\":\"g:Bytecode\",\"@value\":{\"step\":[[\"V\"],[\"repeat\",{\"@type\":\"g:Bytecode\",\"@value\":{\"step\":[[\"out\"]]}}]]}}";
+            Assert.Equal(expectedGraphSon, graphSON);
+        }
+
+        [Fact]
+        public void ShouldSerializeBytecodeWithNumbers()
+        {
+            var bytecode = new Bytecode();
+            bytecode.AddStep("V", (long) 1);
+            bytecode.AddStep("has", "age", 20);
+            bytecode.AddStep("has", "height", 6.5);
+            var graphsonWriter = CreateGraphSONWriter();
+
+            var graphSON = graphsonWriter.WriteObject(bytecode);
+
+            var expectedGraphSon =
+                "{\"@type\":\"g:Bytecode\",\"@value\":{\"step\":[[\"V\",{\"@type\":\"g:Int64\",\"@value\":1}],[\"has\",\"age\",{\"@type\":\"g:Int32\",\"@value\":20}],[\"has\",\"height\",{\"@type\":\"g:Double\",\"@value\":6.5}]]}}";
+            Assert.Equal(expectedGraphSon, graphSON);
+        }
+
+        [Fact]
+        public void ShouldSerialize_g_V()
+        {
+            var bytecode = new Bytecode();
+            bytecode.AddStep("V");
+            var graphsonWriter = CreateGraphSONWriter();
+
+            var graphSON = graphsonWriter.WriteObject(bytecode);
+
+            Assert.Equal("{\"@type\":\"g:Bytecode\",\"@value\":{\"step\":[[\"V\"]]}}", graphSON);
+        }
+
+        [Fact]
+        public void ShouldSerialize_g_V_Count()
+        {
+            var bytecode = new Bytecode();
+            bytecode.AddStep("V");
+            bytecode.AddStep("count");
+            var graphsonWriter = CreateGraphSONWriter();
+
+            var graphSON = graphsonWriter.WriteObject(bytecode);
+
+            var expectedGraphSon = "{\"@type\":\"g:Bytecode\",\"@value\":{\"step\":[[\"V\"],[\"count\"]]}}";
+            Assert.Equal(expectedGraphSon, graphSON);
+        }
+
+        [Fact]
+        public void ShouldSerialize_g_V_HasXPerson_Name_GremlinX_Count()
+        {
+            var bytecode = new Bytecode();
+            bytecode.AddStep("V");
+            bytecode.AddStep("has", "Person", "Name", "Gremlin");
+            bytecode.AddStep("count");
+            var graphsonWriter = CreateGraphSONWriter();
+
+            var graphSON = graphsonWriter.WriteObject(bytecode);
+
+            var expectedGraphSon =
+                "{\"@type\":\"g:Bytecode\",\"@value\":{\"step\":[[\"V\"],[\"has\",\"Person\",\"Name\",\"Gremlin\"],[\"count\"]]}}";
+            Assert.Equal(expectedGraphSon, graphSON);
+        }
+
+        [Fact]
+        public void ShouldSerializeBytecodeWithSourcesStep()
+        {
+            var bytecode = new Bytecode();
+            bytecode.AddSource("withSideEffect", "a", new List<string> {"josh", "peter"});
+            bytecode.AddStep("V", 1);
+            bytecode.AddStep("values", "name");
+            bytecode.AddStep("where", new TraversalPredicate("within", "a"));
+            var graphsonWriter = CreateGraphSONWriter();
+
+            var graphSON = graphsonWriter.WriteObject(bytecode);
+
+            var expectedGraphSon =
+                "{\"@type\":\"g:Bytecode\",\"@value\":{\"source\":[[\"withSideEffect\",\"a\",[\"josh\",\"peter\"]]],\"step\":[[\"V\",{\"@type\":\"g:Int32\",\"@value\":1}],[\"values\",\"name\"],[\"where\",{\"@type\":\"g:P\",\"@value\":{\"predicate\":\"within\",\"value\":\"a\"}}]]}}";
+            Assert.Equal(expectedGraphSon, graphSON);
+        }
+
+        [Fact]
+        public void ShouldSerializeBytecodeWithBindings()
+        {
+            var bytecode = new Bytecode();
+            bytecode.AddStep("V", new Binding("id", 123));
+            var graphsonWriter = CreateGraphSONWriter();
+
+            var graphSon = graphsonWriter.WriteObject(bytecode);
+
+            var expectedGraphSon =
+                "{\"@type\":\"g:Bytecode\",\"@value\":{\"step\":[[\"V\",{\"@type\":\"g:Binding\",\"@value\":{\"value\":{\"@type\":\"g:Int32\",\"@value\":123},\"key\":\"id\"}}]]}}";
+            Assert.Equal(expectedGraphSon, graphSon);
+        }
+    }
+
+    internal class TestTraversal : DefaultTraversal
+    {
+        public TestTraversal(Bytecode bytecode)
+        {
+            Bytecode = bytecode;
+        }
+    }
+}
\ No newline at end of file