Merge pull request #3328 from BrzVlad/finalizer-thread-exited2
[mono.git] / mcs / class / System / Test / System.Net.Mail / SmtpClientTest.cs
index 0d1d124835d0abb745e346751e34c6e8dd0b12d2..909beb4988c8873dc7a6cd85d2b383443f1b290a 100644 (file)
@@ -16,6 +16,7 @@ using System.Threading;
 namespace MonoTests.System.Net.Mail
 {
        [TestFixture]
+       [Category ("RequiresBSDSockets")]
        public class SmtpClientTest
        {
                SmtpClient smtp;
@@ -389,5 +390,51 @@ namespace MonoTests.System.Net.Mail
                        Assert.AreEqual ("<bar@example.com>", server.rcpt_to);
                }
 
+               [Test]
+               public void Deliver_Async ()
+               {
+                       // SmtpClient uses BackgroundWorker and listens for the RunWorkerCompleted
+                       // to mark an async task as completed. The problem is that BackgroundWorker uses
+                       // System.ComponentModel.AsyncOperationManager to get the synchronization
+                       // context, and in monotouch that returns by default a synchronization
+                       // context for the main thread. Since tests are also run on the main thread,
+                       // we'll block the main thread while waiting for the async send to complete,
+                       // while the async completion is waiting for the main thread to process it.
+                       // So instead use a SynchronizationContext that uses the threadpool instead
+                       // of the main thread.
+                       var existing_context = global::System.ComponentModel.AsyncOperationManager.SynchronizationContext;
+                       global::System.ComponentModel.AsyncOperationManager.SynchronizationContext = new ThreadPoolSynchronizationContext ();
+                       try {
+                               var server = new SmtpServer ();
+                               var client = new SmtpClient ("localhost", server.EndPoint.Port);
+                               var msg = new MailMessage ("foo@example.com", "bar@example.com", "hello", "howdydoo\r\n");
+
+                               Thread t = new Thread (server.Run);
+                               t.Start ();
+                               var task = client.SendMailAsync (msg);
+                               t.Join ();
+
+                               Assert.AreEqual ("<foo@example.com>", server.mail_from);
+                               Assert.AreEqual ("<bar@example.com>", server.rcpt_to);
+
+                               Assert.IsTrue (task.Wait (1000));
+                               Assert.IsTrue (task.IsCompleted, "task");
+                       } finally {
+                               global::System.ComponentModel.AsyncOperationManager.SynchronizationContext = existing_context;
+                       }
+               }
+
+               internal class ThreadPoolSynchronizationContext : SynchronizationContext
+               {
+                       public override void Post (SendOrPostCallback d, object state)
+                       {
+                               ThreadPool.QueueUserWorkItem ((v) => d (state));
+                       }
+
+                       public override void Send (SendOrPostCallback d, object state)
+                       {
+                               d (state);
+                       }
+               }
        }
 }