public void TestFailureDetection1() { Failure?failure = null; var handler = new Mock <IFailureHandler>(); handler.Setup(x => x.OnFailure(It.IsAny <Failure>())) .Callback((Failure x) => failure = x); using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(failureHandler: handler.Object)) { silo.Start(); var proxy = silo.CreateGrain <IVoidMethodNoParameters>(typeof(KillsProcess)); new Action(proxy.Do) .ShouldThrow <ConnectionLostException>( "Because the host process is lost while the method is invoked and therefore the connection to the host process was lost and is the reason for the method to not execute properly"); WaitFor(() => silo.HasProcessFailed, TimeSpan.FromSeconds(1)) .Should() .BeTrue( "Because an aborted thread that is currently invoking a remote method call should cause SharpRemote to kill the host process and report failure"); silo.IsProcessRunning.Should().BeFalse(); WaitFor(() => failure != null, TimeSpan.FromSeconds(1)) .Should().BeTrue("Because the IFailureHandler should've been notified in time"); (failure == Failure.ConnectionFailure || failure == Failure.HostProcessExited).Should().BeTrue(); } }
public void TestFailureDetection4() { using (var handle = new ManualResetEvent(false)) { Resolution?resolution = null; var handler = new Mock <IFailureHandler>(); handler.Setup(x => x.OnResolutionFinished(It.IsAny <Failure>(), It.IsAny <Decision>(), It.IsAny <Resolution>())) .Callback((Failure f, Decision d, Resolution r) => { resolution = r; handle.Set(); }); using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(failureHandler: handler.Object)) { silo.Start(); IVoidMethodNoParameters proxy = silo.CreateGrain <IVoidMethodNoParameters, CausesAccessViolation>(); new Action(proxy.Do).ShouldThrow <ConnectionLostException>(); handle.WaitOne(TimeSpan.FromSeconds(5)).Should().BeTrue(); resolution.Should().Be(Resolution.Stopped); } } }
public void TestFailureDetection2() { Failure? failure = null; Decision? decision = null; Resolution?resolution = null; var handler = new Mock <IFailureHandler>(); handler.Setup(x => x.OnResolutionFinished(It.IsAny <Failure>(), It.IsAny <Decision>(), It.IsAny <Resolution>())) .Callback((Failure f, Decision d, Resolution r) => { failure = f; decision = d; resolution = r; }); using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(failureHandler: handler.Object)) { silo.Start(); var proxy = silo.CreateGrain <IVoidMethodNoParameters>(typeof(AbortsThread)); new Action(proxy.Do) .ShouldThrow <ConnectionLostException>( "Because the host process is lost while the method is invoked and therefore the connection to the host process was lost and is the reason for the method to not execute properly"); WaitFor(() => silo.HasProcessFailed, TimeSpan.FromSeconds(1)) .Should().BeTrue("Because an unexpected exit of the host process counts as a failure"); silo.IsProcessRunning.Should().BeFalse(); WaitFor(() => resolution != null, TimeSpan.FromSeconds(1)).Should().BeTrue(); (failure == Failure.ConnectionFailure || failure == Failure.HostProcessExited).Should().BeTrue("because we expected either a ConnectionFailure or HostProcessExited, but found: {0}", failure); resolution.Should().Be(Resolution.Stopped); } }
public void TestPerformanceManyClients() { TimeSpan time = TimeSpan.FromSeconds(5); int num = 0; using (var silo = new SharpRemote.Hosting.OutOfProcessSilo()) { silo.Start(); IVoidMethod grain = silo.CreateGrain <IVoidMethod, DoesNothing>(); // Optimization phase const int numOptPasses = 100; for (int i = 0; i < numOptPasses; ++i) { grain.DoStuff(); } // Measurement phase const int numClients = 16; var clients = new Thread[numClients]; for (int clientIndex = 0; clientIndex < numClients; ++clientIndex) { clients[clientIndex] = new Thread(() => { var watch = new Stopwatch(); const int batchSize = 64; watch.Start(); while (watch.Elapsed < time) { for (int i = 0; i < batchSize; ++i) { grain.DoStuff(); } num += batchSize; } watch.Stop(); }); clients[clientIndex].Start(); } foreach (Thread thread in clients) { thread.Join(); } int numSeconds = 5; double ops = 1.0 * num / numSeconds; Console.WriteLine("Total calls: {0}", num); Console.WriteLine("OP/s: {0:F2}k/s", ops / 1000); Console.WriteLine("Sent: {0}, {1}/s", FormatSize(silo.NumBytesSent), FormatSize(silo.NumBytesSent / numSeconds)); Console.WriteLine("Received: {0}, {1}/s", FormatSize(silo.NumBytesReceived), FormatSize(silo.NumBytesReceived / numSeconds)); Console.WriteLine("Latency: {0}ns", (int)silo.RoundtripTime.Ticks * 100); } }
public void TestFailureDetection9() { using (var handle = new ManualResetEvent(false)) { Resolution?resolution = null; var handler = new Mock <IFailureHandler>(); handler.Setup(x => x.OnResolutionFinished(It.IsAny <Failure>(), It.IsAny <Decision>(), It.IsAny <Resolution>())) .Callback((Failure f, Decision d, Resolution r) => { resolution = r; handle.Set(); }); var settings = new PostMortemSettings { CollectMinidumps = true, SuppressErrorWindows = true, HandleCrtPureVirtualFunctionCalls = true, #if DEBUG RuntimeVersions = CRuntimeVersions._110 | CRuntimeVersions.Debug, #else RuntimeVersions = CRuntimeVersions._110 | CRuntimeVersions.Release, #endif NumMinidumpsRetained = 1, MinidumpFolder = Path.Combine(Path.GetTempPath(), "SharpRemote", "dumps"), MinidumpName = "Host" }; if (Directory.Exists(settings.MinidumpFolder)) { Directory.Delete(settings.MinidumpFolder, true); } using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(postMortemSettings: settings)) { silo.Start(); IVoidMethodNoParameters proxy = silo.CreateGrain <IVoidMethodNoParameters, CausesPureVirtualFunctionCall>(); DateTime beforeFailure = DateTime.Now; new Action(proxy.Do).ShouldThrow <ConnectionLostException>(); DateTime afterFailure = DateTime.Now; // Not only should a failure have been detected, but a dump should've been created and stored // on disk.. List <string> files = Directory.EnumerateFiles(settings.MinidumpFolder).ToList(); files.Count.Should().Be(1, "Because exactly one minidump should've been created"); var file = new FileInfo(files[0]); file.Name.Should().EndWith(".dmp"); file.LastWriteTime.Should().BeOnOrAfter(beforeFailure); file.LastWriteTime.Should().BeOnOrBefore(afterFailure); } } }
public void TestGetProperty() { using (var silo = new SharpRemote.Hosting.OutOfProcessSilo()) { silo.Start(); IGetInt64Property grain = silo.CreateGrain <IGetInt64Property, ReturnsInt64Max>(); grain.Value.Should().Be(Int64.MaxValue); grain.Value.Should().Be(Int64.MaxValue); } }
public void TestCreateGrain1() { using (var silo = new SharpRemote.Hosting.OutOfProcessSilo()) { silo.Start(); var proxy = silo.CreateGrain <IGetStringProperty>(typeof(GetStringPropertyImplementation)); proxy.Value.Should().Be("Foobar"); } }
public void TestFailureDetection3() { Failure? failure1 = null; Failure? failure2 = null; Decision? decision = null; Resolution?resolution = null; var handler = new Mock <IFailureHandler>(); handler.Setup(x => x.OnFailure(It.IsAny <Failure>())) .Callback((Failure f) => failure1 = f); handler.Setup(x => x.OnResolutionFinished(It.IsAny <Failure>(), It.IsAny <Decision>(), It.IsAny <Resolution>())) .Callback((Failure f, Decision d, Resolution r) => { failure2 = f; decision = d; resolution = r; }); var settings = new FailureSettings { HeartbeatSettings = { ReportSkippedHeartbeatsAsFailureWithDebuggerAttached = true, Interval = TimeSpan.FromMilliseconds(100), SkippedHeartbeatThreshold = 4 } }; using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(failureSettings: settings, failureHandler: handler.Object)) { silo.Start(); var proxy = silo.CreateGrain <IVoidMethodNoParameters>(typeof(DeadlocksProcess)); new Action(() => { Task.Factory.StartNew(proxy.Do, TaskCreationOptions.LongRunning) .Wait(TimeSpan.FromSeconds(10)) .Should().BeTrue("Because the silo should've detected the deadlock in time"); }) .ShouldThrow <ConnectionLostException>( "Because the host process is lost while the method is invoked and therefore the connection to the host process was lost and is the reason for the method to not execute properly"); WaitFor(() => silo.HasProcessFailed, TimeSpan.FromSeconds(1)) .Should() .BeTrue("Because the heartbeat mechanism should have detected that the endpoint doesn't respond anymore"); WaitFor(() => failure1 != null, TimeSpan.FromSeconds(1)).Should().BeTrue(); WaitFor(() => failure2 != null, TimeSpan.FromSeconds(1)).Should().BeTrue(); silo.IsProcessRunning.Should().BeFalse(); failure1.Should().Be(Failure.HeartbeatFailure); failure2.Should().Be(failure1); resolution.Should().Be(Resolution.Stopped); } }
public void TestUseByReferenceTypeAfterRestart() { using (var logCollector = new LogCollector(new [] { "SharpRemote.EndPoints.ProxyStorage" }, new [] { Level.Debug })) using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(failureHandler: new RestartOnFailureStrategy())) { logCollector.AutoPrint(TestContext.Progress); silo.Start(); var factory = silo.CreateGrain <IAdvancedFactory>(typeof(AdvancedFactory)); var proxyToByReferenceClass = factory.Create(typeof(ByReferenceClass)); var id = GetIdOf(proxyToByReferenceClass); Console.WriteLine("ObjectId: {0}", id); RestartHost(silo); factory = silo.CreateGrain <IAdvancedFactory>(typeof(AdvancedFactory)); var proxyToObject = factory.Create(typeof(Handle)); var otherId = GetIdOf(proxyToObject); Console.WriteLine("ObjectId: {0}", otherId); } }
public void TestStartStopStart2() { using (var silo = new SharpRemote.Hosting.OutOfProcessSilo()) { silo.Start(); var proxy = silo.CreateGrain <IReturnsType>(typeof(ReturnsTypeofString)); proxy.Do().Should().Be <string>(); silo.Stop(); new Action(() => proxy.Do()) .ShouldThrow <RemoteProcedureCallCanceledException>(); new Action(() => silo.CreateGrain <IReturnsType>(typeof(ReturnsTypeofString))) .ShouldThrow <RemoteProcedureCallCanceledException>(); silo.Start(); var newProxy = silo.CreateGrain <IReturnsType>(typeof(ReturnsTypeofString)); newProxy.Do().Should().Be <string>(); } }
public void TestPerformanceOneClientAsync() { TimeSpan time = TimeSpan.FromSeconds(5); var watch = new Stopwatch(); int num = 0; using (var silo = new SharpRemote.Hosting.OutOfProcessSilo()) { silo.Start(); IReturnsTask grain = silo.CreateGrain <IReturnsTask, ReturnsTask>(); // Optimization phase const int numOptPasses = 100; var opts = new Task[numOptPasses]; for (int i = 0; i < numOptPasses; ++i) { opts[i] = grain.DoStuff(); } Task.WaitAll(opts); // Measurement phase const int batchSize = 1000; var tasks = new Task[batchSize]; watch.Start(); while (watch.Elapsed < time) { for (int i = 0; i < batchSize; ++i) { tasks[i] = grain.DoStuff(); } Task.WaitAll(tasks); num += batchSize; } watch.Stop(); double numSeconds = watch.Elapsed.TotalSeconds; double ops = 1.0 * num / numSeconds; Console.WriteLine("Total calls: {0}", num); Console.WriteLine("OP/s: {0:F2}k/s", ops / 1000); Console.WriteLine("Sent: {0}, {1}/s", FormatSize(silo.NumBytesSent), FormatSize((long)(silo.NumBytesSent / numSeconds))); Console.WriteLine("Received: {0}, {1}/s", FormatSize(silo.NumBytesReceived), FormatSize((long)(silo.NumBytesReceived / numSeconds))); Console.WriteLine("Latency: {0}ns", (int)silo.RoundtripTime.Ticks * 100); } }
public void TestCreate() { var customTypeResolver = new CustomTypeResolver1(); using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(codeGenerator: new CodeGenerator(customTypeResolver))) { silo.Start(); customTypeResolver.GetTypeCalled.Should().Be(0); var grain = silo.CreateGrain <IReturnsType>(typeof(ReturnsTypeofString)); customTypeResolver.GetTypeCalled.Should() .Be(0, "because the custom type resolver in this process didn't need to resolve anything yet"); grain.Do().Should().Be <string>(); customTypeResolver.GetTypeCalled.Should() .Be(1, "Because the custom type resolver in this process should've been used to resolve typeof(string)"); } }
public void TestPerformanceOneClientSync() { TimeSpan time = TimeSpan.FromSeconds(5); var watch = new Stopwatch(); int num = 0; using (var silo = new SharpRemote.Hosting.OutOfProcessSilo()) { silo.Start(); IVoidMethod grain = silo.CreateGrain <IVoidMethod, DoesNothing>(); // Optimization phase for (int i = 0; i < 100; ++i) { grain.DoStuff(); } // Measurement phase watch.Start(); while (watch.Elapsed < time) { for (int i = 0; i < 100; ++i) { grain.DoStuff(); } num += 100; } watch.Stop(); double numSeconds = watch.Elapsed.TotalSeconds; double ops = 1.0 * num / numSeconds; Console.WriteLine("Total calls: {0}", num); Console.WriteLine("OP/s: {0:F2}k/s", ops / 1000); Console.WriteLine("Sent: {0}, {1}/s", FormatSize(silo.NumBytesSent), FormatSize((long)(silo.NumBytesSent / numSeconds))); Console.WriteLine("Received: {0}, {1}/s", FormatSize(silo.NumBytesReceived), FormatSize((long)(silo.NumBytesReceived / numSeconds))); Console.WriteLine("Latency: {0}ns", (int)silo.RoundtripTime.Ticks * 100); } }
public void TestFailureDetection8() { using (var handle = new ManualResetEvent(false)) { Resolution?resolution = null; var handler = new Mock <IFailureHandler>(); handler.Setup(x => x.OnResolutionFinished(It.IsAny <Failure>(), It.IsAny <Decision>(), It.IsAny <Resolution>())) .Callback((Failure f, Decision d, Resolution r) => { resolution = r; handle.Set(); }); var settings = new PostMortemSettings { SuppressErrorWindows = true, HandleCrtPureVirtualFunctionCalls = true, #if DEBUG RuntimeVersions = CRuntimeVersions._110 | CRuntimeVersions.Debug, #else RuntimeVersions = CRuntimeVersions._110 | CRuntimeVersions.Release, #endif }; using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(postMortemSettings: settings)) { silo.Start(); IVoidMethodNoParameters proxy = silo.CreateGrain <IVoidMethodNoParameters, CausesPureVirtualFunctionCall>(); Task task = Task.Factory.StartNew(() => { new Action(proxy.Do).ShouldThrow <ConnectionLostException>(); }); //task.Wait(TimeSpan.FromSeconds(5)).Should().BeTrue(); task.Wait(); handle.WaitOne(TimeSpan.FromSeconds(5)).Should().BeTrue(); resolution.Should().Be(Resolution.Stopped); } } }
public void TestFailureDetection5() { var settings = new PostMortemSettings { CollectMinidumps = true, SuppressErrorWindows = true, HandleAccessViolations = true, NumMinidumpsRetained = 1, MinidumpFolder = Path.Combine(Path.GetTempPath(), "SharpRemote", "dumps"), MinidumpName = "Host" }; if (Directory.Exists(settings.MinidumpFolder)) { Directory.Delete(settings.MinidumpFolder, true); } using (var silo = new SharpRemote.Hosting.OutOfProcessSilo(postMortemSettings: settings)) { silo.Start(); IVoidMethodNoParameters proxy = silo.CreateGrain <IVoidMethodNoParameters, CausesAccessViolation>(); DateTime beforeFailure = DateTime.Now; new Action(proxy.Do).ShouldThrow <ConnectionLostException>(); DateTime afterFailure = DateTime.Now; // Not only should a failure have been detected, but a dump should've been created and stored // on disk.. List <string> files = Directory.EnumerateFiles(settings.MinidumpFolder).ToList(); files.Count.Should().Be(1, "Because exactly one minidump should've been created"); var file = new FileInfo(files[0]); file.Name.Should().EndWith(".dmp"); file.LastWriteTime.Should().BeOnOrAfter(beforeFailure); file.LastWriteTime.Should().BeOnOrBefore(afterFailure); } }