public void Only_one_thread_can_acquire_the_lock_at_a_time() { var l = new Lock <int>(1); var trigger = new ManualResetEvent(false); var first = AsyncUtil.Fork(() => { trigger.WaitOne(); Thread.Sleep(200); l.Capture(new Result()).Wait(); }, new Result()); Result secondInternal = null; var second = AsyncUtil.Fork(() => { trigger.WaitOne(); secondInternal = l.Capture(new Result()); }, new Result()); trigger.Set(); Assert.IsFalse(first.HasValue); second.Wait(); l.Release(); Assert.IsTrue(secondInternal.HasValue); Assert.IsFalse(first.HasValue); secondInternal.Wait(); first.Wait(); Assert.IsTrue(first.HasValue); }
public void Forked_thread_has_copy_of_current_state() { var state = new State(); TaskEnv.Current.SetState(state); Assert.IsTrue(AsyncUtil.Fork(() => (state == TaskEnv.Current.GetState <State>()), new Result <bool>()).Wait()); }
/// <summary> /// Asynchronous copying of one stream to another. /// </summary> /// <param name="source">Source <see cref="Stream"/>.</param> /// <param name="target">Target <see cref="Stream"/>.</param> /// <param name="length">Number of bytes to copy from source to target.</param> /// <param name="result">The <see cref="Result"/> instance to be returned by the call.</param> /// <returns>Synchronization handle for the number of bytes copied.</returns> public static Result <long> CopyToStream(this Stream source, Stream target, long length, Result <long> result) { if (!SysUtil.UseAsyncIO) { return(AsyncUtil.Fork(() => CopyToStream(source, target, length), result)); } // NOTE (steveb): intermediary copy steps already have a timeout operation, no need to limit the duration of the entire copy operation if ((source == Stream.Null) || (length == 0)) { result.Return(0); } else if (source.IsStreamMemorized() && target.IsStreamMemorized()) { // source & target are memory streams; let's do the copy inline as fast as we can result.Return(CopyToStream(source, target, length)); } else { // use new task environment so we don't copy the task state over and over again TaskEnv.ExecuteNew(() => Coroutine.Invoke(CopyTo_Helper, source, target, length, result)); } return(result); }
public void Matches_request_doc_to_expectations() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect().Verb("POST").Uri(new XUri("http://auto/plug/a")).RequestDocument(new XDoc("foo")); AsyncUtil.Fork(() => Plug.New("http://auto/plug/a").PostAsync(new XDoc("foo")), new Result()); Assert.IsTrue(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); }
public void Ignores_excess_headers() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect().Verb("POST").Uri(new XUri("http://auto/plug/a")); AsyncUtil.Fork(() => Plug.New("http://auto/plug/a").WithHeader("Foo", "123").PostAsync(), new Result()); Assert.IsTrue(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); }
public void Can_match_request_DreamMessages_for_expectation() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect().Verb("POST").Uri(new XUri("http://auto/plug/a")).Request(DreamMessage.Ok(MimeType.TEXT_UTF8, "blah")); AsyncUtil.Fork(() => Plug.New("http://auto/plug/a").PostAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, "blah")), new Result()); Assert.IsTrue(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); }
/// <summary> /// Asynchronously read from a <see cref="Stream"/> /// </summary> /// <param name="stream">Source <see cref="Stream"/></param> /// <param name="buffer">Byte array to fill from the source</param> /// <param name="offset">Position in buffer to start writing to</param> /// <param name="count">Number of bytes to read from the <see cref="Stream"/></param> /// <param name="result">The <see cref="Result"/> instance to be returned by the call.</param> /// <returns>Synchronization handle for the number of bytes read.</returns> public static Result <int> Read(this Stream stream, byte[] buffer, int offset, int count, Result <int> result) { if (SysUtil.UseAsyncIO) { return(AsyncUtil.From(stream.BeginRead, stream.EndRead, buffer, offset, count, null, result)); } return(AsyncUtil.Fork(() => SyncRead_Helper(stream, buffer, offset, count), result)); }
/// <summary> /// Asynchronously write to a <see cref="Stream"/>. /// </summary> /// <param name="stream">Target <see cref="Stream"/>.</param> /// <param name="buffer">Byte array to write to the target.</param> /// <param name="offset">Position in buffer to start reading from.</param> /// <param name="count">Number of bytes to read from buffer.</param> /// <param name="result">The <see cref="Result"/> instance to be returned by the call.</param> /// <returns>Synchronization handle for the number of bytes read.</returns> public static Result Write(this Stream stream, byte[] buffer, int offset, int count, Result result) { if (SysUtil.UseAsyncIO) { return(AsyncUtil.From(stream.BeginWrite, stream.EndWrite, buffer, offset, count, null, result)); } return(AsyncUtil.Fork(() => stream.Write(buffer, offset, count), result)); }
public Yield Spawn(DreamContext context, DreamMessage request, Result <DreamMessage> response) { var guid = Guid.NewGuid(); ContextVar = new ContextLifeSpan(guid); context.SetState(guid); context.SetState(ContextVar); ContextLifeSpan capturedInner = null; yield return(AsyncUtil.Fork(() => { var innerContextVar = DreamContext.Current.GetState <ContextLifeSpan>(); capturedInner = innerContextVar; if (innerContextVar == ContextVar) { throw new Exception("spawned context instances were same"); } if (innerContextVar.Guid != guid) { throw new Exception("spawned context guid is wrong"); } if (innerContextVar.IsDisposed) { throw new Exception("subcall: context is disposed"); } }, new Result())); var contextVar = context.GetState <ContextLifeSpan>(); if (contextVar == null) { throw new Exception("context instance is gone"); } if (capturedInner == contextVar) { throw new Exception("outer instance was changed to inner"); } if (!capturedInner.IsDisposed) { throw new Exception("inner instance wasn't disposed after closure completion"); } if (contextVar.Guid != guid) { throw new Exception("context guid is wrong"); } if (contextVar != ContextVar) { throw new Exception("context instance changed"); } if (contextVar.IsDisposed) { throw new Exception("context is disposed"); } response.Return(DreamMessage.Ok()); yield break; }
public void Catches_missing_headers() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect().Verb("GET").Uri(new XUri("http://auto/plug/a")) .RequestHeader("Foo", "123") .RequestHeader("Bar", "required"); AsyncUtil.Fork(() => Plug.New("http://auto/plug/a").WithHeader("Foo", "123").GetAsync(), new Result()); Assert.IsFalse(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); Assert.AreEqual("Expectations were unmet:\r\nExpectation #1: Expected header 'Bar', got none\r\n", autoPlug.VerificationFailure); }
public void Autoplug_without_expectations_should_still_fail_on_excess() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); AsyncUtil.Fork(() => { Plug.New("http://auto/plug/b").PutAsync(new XDoc("foo")); Plug.New("http://auto/plug/a").PostAsync(); }, new Result()); Assert.IsFalse(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); Assert.AreEqual(2, autoPlug.ExcessInterceptions.Length); }
public void Catches_mismatched_request_headers() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect().Verb("GET").Uri(new XUri("http://auto/plug/a")) .RequestHeader("Foo", "123") .RequestHeader("Bar", "right"); AsyncUtil.Fork(() => Plug.New("http://auto/plug/a").WithHeader("Foo", "123").WithHeader("Bar", "wrong").Get(new Result <DreamMessage>()), new Result()); Assert.IsFalse(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); Assert.AreEqual("Expectations were unmet:\r\nExpectation #1: Expected header 'Bar:\r\nExpected: right\r\nGot: wrong\r\n", autoPlug.VerificationFailure); }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { var asyncResult = new MockAsyncResult { AsyncState = state, Buffer = buffer, Count = count, Offset = offset }; AsyncUtil.Fork(() => callback(asyncResult)); return(asyncResult); }
public void Considers_missordered_expectations_as_unmet() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plugx")); autoPlug.Expect("POST", new XUri("http://auto/plugx/a")); autoPlug.Expect("PUT", new XUri("http://auto/plugx/b"), new XDoc("foo")); AsyncUtil.Fork(() => { Plug.New("http://auto/plugx/b").Put(new XDoc("foo")); Plug.New("http://auto/plugx/a").Post(); }, new Result()); Assert.IsFalse(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); Assert.AreEqual(0, autoPlug.MetExpectationCount); }
public void ExclusiveFileAccess() { // create the test file using (StreamWriter writer = new StreamWriter(File.OpenWrite("test.test"))) { writer.Write("Hello World!"); writer.Close(); } // kick off the thread to do the second open ManualResetEvent first = new ManualResetEvent(false); ManualResetEvent second = new ManualResetEvent(false); ManualResetEvent third = new ManualResetEvent(false); ManualResetEvent fourth = new ManualResetEvent(false); AsyncUtil.Fork(delegate() { first.WaitOne(); try { using (Stream f = StreamUtil.FileOpenExclusive("test.test")) { Assert.IsNull(f, "file open succeeded when it was expected to fail"); } } catch { third.Set(); fourth.Set(); throw; } second.WaitOne(); third.Set(); try { using (Stream f = StreamUtil.FileOpenExclusive("test.test")) { Assert.IsNotNull(f, "file open failed when it was expected to succeed"); } } catch { fourth.Set(); throw; } fourth.Set(); }, null); // open the file first using (Stream g = StreamUtil.FileOpenExclusive("test.test")) { first.Set(); Thread.Sleep(2000); second.Set(); Thread.Sleep(500); third.WaitOne(); g.Close(); } fourth.WaitOne(); File.Delete("test.test"); }
public void Should_be_able_to_call_same_url_with_different_headers() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect().Verb("GET").Uri(new XUri("http://auto/plug/a")).RequestHeader("Foo", ""); autoPlug.Expect().Verb("GET").Uri(new XUri("http://auto/plug/a")).RequestHeader("Foo", "baz"); Plug p = Plug.New("http://auto/plug/a"); AsyncUtil.Fork(() => { p.WithHeader("Foo", "").GetAsync().Block(); p.WithHeader("Foo", "baz").GetAsync().Block(); }, new Result()); Assert.IsTrue(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); }
//--- Methods --- /// <summary> /// Start listening for SQS messages with the provided settings. /// </summary> /// <param name="settings">Polling settings.</param> /// <returns>Object to dispose listener when no longer needed.</returns> public IDisposable Listen(SqsPollingClientSettings settings) { if (settings == null) { throw new ArgumentNullException("settings"); } var listener = new Listener(this); lock (_listeners) { _listeners.Add(listener); } AsyncUtil.Fork(() => listener.LongPollSqs(settings)); return(listener); }
public void Complains_about_unmet_expectations_after_timeout() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect("POST", new XUri("http://auto/plug/a")); autoPlug.Expect("PUT", new XUri("http://auto/plug/b"), new XDoc("foo")); Assert.IsFalse(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); autoPlug.Reset(); autoPlug.Expect("POST", new XUri("http://auto/plug/a")); autoPlug.Expect("PUT", new XUri("http://auto/plug/b"), new XDoc("foo")); AsyncUtil.Fork(() => Plug.New("http://auto/plug/a").Post(), new Result()); Assert.IsFalse(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(1)), autoPlug.VerificationFailure); Assert.AreEqual(1, autoPlug.MetExpectationCount); }
public void PostAsync_from_nested_async_workers() { AutoResetEvent resetEvent = new AutoResetEvent(false); MockPlug.Register(new XUri("http://foo/bar"), delegate(Plug p, string v, XUri u, DreamMessage r, Result <DreamMessage> r2) { resetEvent.Set(); r2.Return(DreamMessage.Ok()); }); Plug.New("http://foo/bar").PostAsync(); Assert.IsTrue(resetEvent.WaitOne(1000, false), "no async failed"); AsyncUtil.Fork(() => AsyncUtil.Fork(() => Plug.New("http://foo/bar").PostAsync(), new Result()), new Result()); Assert.IsTrue(resetEvent.WaitOne(1000, false), "async failed"); AsyncUtil.Fork(() => AsyncUtil.Fork(() => Plug.New("http://foo/bar").PostAsync(), new Result()), new Result()); Assert.IsTrue(resetEvent.WaitOne(1000, false), "nested async failed"); AsyncUtil.Fork(() => AsyncUtil.Fork(() => AsyncUtil.Fork(() => Plug.New("http://foo/bar").PostAsync(), new Result()), new Result()), new Result()); Assert.IsTrue(resetEvent.WaitOne(1000, false), "double async failed"); }
public Result <Production> Produce(int messages) { var production = new Production(); var final = new Result <Production>(); AsyncUtil.Fork(() => { try { _log.DebugFormat("{0}: Producing {1} messages", production.Id, messages); var responses = new List <Result <string> >(); var client = new AwsSqsClient(_clientConfig); for (var i = 0; i < messages; i++) { var result = new Result <string>(); responses.Add(result); var msg = production.Id + ":" + messages; client.Send(_queue, AwsSqsMessage.FromBody(msg), new Result <AwsSqsSendResponse>()).WhenDone(r => { if (r.HasException) { result.Throw(r.Exception); return; } result.Return(msg); }); } responses.Join(new Result()).WhenDone(r => { if (r.HasException) { final.Throw(r.Exception); return; } production.Stopwatch.Stop(); production.Sent.AddRange(responses.Select(x => x.Value)); _log.DebugFormat("{0}: Sent {1} messages in {2:0.00}s @ {3:0.00}msg/sec", production.Id, production.Sent.Count, production.Stopwatch.Elapsed.TotalSeconds, production.Sent.Count / production.Stopwatch.Elapsed.TotalSeconds ); final.Return(production); }); } catch (Exception e) { final.Throw(e); } }); return(final); }
public void Collects_excess_expectations() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect("POST"); AsyncUtil.Fork(() => { Plug.New("http://auto/plug/a").PostAsync().Block(); Plug.New("http://auto/plug/b").PostAsync().Block(); Plug.New("http://auto/plug/c").PostAsync().Block(); Plug.New("http://auto/plug/d").PostAsync().Block(); }, new Result()); Assert.IsFalse(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(15)), autoPlug.VerificationFailure); Assert.IsTrue(autoPlug.HasInterceptsInExcessOfExpectations); Assert.AreEqual(3, autoPlug.ExcessInterceptions.Length); Assert.AreEqual("http://auto/plug/b", autoPlug.ExcessInterceptions[0].Uri.ToString()); Assert.AreEqual("http://auto/plug/c", autoPlug.ExcessInterceptions[1].Uri.ToString()); Assert.AreEqual("http://auto/plug/d", autoPlug.ExcessInterceptions[2].Uri.ToString()); }
public void PipeTest3() { Stream writer; Stream reader; StreamUtil.CreatePipe(1, out writer, out reader); byte[] write = new byte[] { 1, 2, 3, 4 }; AsyncUtil.Fork(delegate() { writer.Write(write, 0, write.Length); writer.Close(); }, null); byte[] read = new byte[10]; int count = reader.Read(read, 0, read.Length); reader.Close(); Assert.AreEqual(write.Length, count); Assert.AreEqual(write, ArrayUtil.SubArray(read, 0, count)); }
public void Async_Result_WhenDone_does_not_get_executed_task_state() { var state = new TaskLifeSpanState("baz"); var allgood = false; var resetEvent = new ManualResetEvent(false); AsyncUtil.Fork(() => { _log.Debug("setting inner state"); TaskEnv.Current.SetState("foo", state); }, new Result()).WhenDone(r => { _log.Debug("executing whendone"); allgood = !r.HasException && state != TaskEnv.Current.GetState <TaskLifeSpanState>("foo"); resetEvent.Set(); }); _log.Debug("waiting for fork"); resetEvent.WaitOne(); _log.Debug("done"); Assert.IsTrue(allgood); }
public void Waits_until_expectations_are_met_after_each_reset() { AutoMockPlug autoPlug = MockPlug.Register(new XUri("http://auto/plug")); autoPlug.Expect("POST", new XUri("http://auto/plug/a")); autoPlug.Expect("PUT", new XUri("http://auto/plug/b"), new XDoc("foo")); AsyncUtil.Fork(() => { Plug.New("http://auto/plug/a").Post(); Plug.New("http://auto/plug/b").Put(new XDoc("foo")); }, new Result()); Assert.IsTrue(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(2)), autoPlug.VerificationFailure); autoPlug.Reset(); autoPlug.Expect("GET", new XUri("http://auto/plug/c")); autoPlug.Expect("GET", new XUri("http://auto/plug/d")); AsyncUtil.Fork(() => { Plug.New("http://auto/plug/c").Get(); Plug.New("http://auto/plug/d").Get(); }, new Result()); Assert.IsTrue(autoPlug.WaitAndVerify(TimeSpan.FromSeconds(2)), autoPlug.VerificationFailure); }
public void Copied_state_on_another_thread_is_independent_of_original() { var state = new State(); TaskEnv.Current.SetState(state); var resetEvent = new AutoResetEvent(true); var result = AsyncUtil.Fork(() => { resetEvent.WaitOne(); TaskEnv.Current.SetState(new State()); resetEvent.WaitOne(); }, new Result()); Assert.AreEqual(state, TaskEnv.Current.GetState <State>()); resetEvent.Set(); Thread.Sleep(100); Assert.AreEqual(state, TaskEnv.Current.GetState <State>()); resetEvent.Set(); result.Wait(); Assert.AreEqual(state, TaskEnv.Current.GetState <State>()); }
//--- Methods --- protected override Yield Start(XDoc config, Result result) { yield return(Coroutine.Invoke(base.Start, config, new Result())); // are we a private storage service? _private = config["sid"].Contents == "sid://mindtouch.com/2007/07/dream/storage.private"; _log.DebugFormat("storage is {0}", _private ? "private" : "public"); // is the root blocked from access? _privateRoot = config["private-root"].AsBool.GetValueOrDefault(); _log.DebugFormat("storage root is {0}accessible", _privateRoot ? "not " : ""); _expirationEntries = new ExpiringHashSet <string>(TimerFactory); _expirationEntries.EntryExpired += OnDelete; // check if folder exists _path = Environment.ExpandEnvironmentVariables(config["folder"].Contents); _log.DebugFormat("storage path: {0}", _path); if (!Path.IsPathRooted(_path)) { throw new ArgumentException(string.Format("storage path must be absolute: {0}", _path)); } // make sure path ends with a '\' as it makes processing simpler later on if ((_path.Length != 0) && ((_path[_path.Length - 1] != '/') || (_path[_path.Length - 1] != '\\'))) { _path += Path.DirectorySeparatorChar; } if (!_private && !Directory.Exists(_path)) { throw new ArgumentException(string.Format("storage path does not exist: {0}", _path)); } // Fire off meta data scanning AsyncUtil.Fork(ScanMetaData); result.Return(); }
public void LIVE_STRESS_TEST_multiple_producers_multiple_queues_one_consumer_per_queue() { var messagesPerProducer = 100; var producerCount = 1; var client = CreateLiveClient(); var queues = new List <string>(); foreach (var x in new[] { "a", "b", "c", "d" }) { var queue = "test-" + x + "-" + StringUtil.CreateAlphaNumericKey(4); client.CreateQueue(queue, new Result <AwsSqsResponse>()).Wait(); queues.Add(queue); } try { var producers = new List <Result <List <string> > >(); for (var i = 0; i < producerCount; i++) { var producer = i; producers.Add(AsyncUtil.Fork(() => { _log.DebugFormat("producer {0} started", producer); var c = CreateLiveClient(); var msgs = new List <string>(); for (var j = 0; j < messagesPerProducer; j++) { var msg = StringUtil.CreateAlphaNumericKey(1024); foreach (var queue in queues) { c.Send(queue, AwsSqsMessage.FromBody(msg), new Result <AwsSqsSendResponse>()).Wait(); } msgs.Add(msg); if (msgs.Count % 10 == 0) { _log.DebugFormat("producer {0} sent {1}/{2} msgs", producer, msgs.Count, messagesPerProducer); } } _log.DebugFormat("producer {0} finished", producer); return(msgs); }, new Result <List <string> >())); } var consumers = queues.ToDictionary(queue => queue, queue => AsyncUtil.Fork(() => { _log.DebugFormat("consumer {0} started", queue); var c = CreateLiveClient(); var msgs = new List <string>(); var expected = messagesPerProducer * producerCount; var lastReport = 0; while (msgs.Count < expected) { var received = c.ReceiveMax(queue, new Result <IEnumerable <AwsSqsMessage> >()).Wait(); var count = 0; foreach (var msg in received) { count++; msgs.Add(msg.Body); c.Delete(msg, new Result <AwsSqsResponse>()).Wait(); } if (count > 0 && msgs.Count > lastReport + 10) { _log.DebugFormat("consumer '{0}' received: {1}/{2}", queue, msgs.Count, expected); lastReport = msgs.Count; } } return(msgs); }, new Result <List <string> >())); producers.Join(new Result()).Wait(); consumers.Values.Join(new Result()).Wait(); var allMessages = producers.SelectMany(x => x.Value).OrderBy(x => x).ToArray(); foreach (var consumed in consumers) { var queue = consumed.Key; var messages = consumed.Value.Value.OrderBy(x => x).ToArray(); Assert.AreEqual(allMessages, messages, string.Format("message list for queue '{0}' is wrong", queue)); } } finally { foreach (var queue in queues) { _log.DebugFormat("cleaning up queue '{0}'", queue); client.DeleteQueue(queue, new Result <AwsSqsResponse>()).Wait(); } } }
public IEnumerator <IYield> Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result <DreamMessage> response) { var match = GetBestMatch(uri); yield return(AsyncUtil.Fork(() => match.Invoke(plug, verb, uri, MemorizeAndClone(request), response), new Result(TimeSpan.MaxValue))); }