using System; using System.IO; using System.Xml; using System.Text; using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Threading; using System.Security.Principal; using Microsoft.TeamFoundation; using Microsoft.TeamFoundation.Client; class CheckinNotificationTest { static void Main(string[] args) { if (args.Length < 2) { Console.Error.Write("Usage: CheckinNotificationTest "); Environment.Exit(1); } try { // Access the Team Foundation Server proxy TeamFoundationServer m_tfs = TeamFoundationServerFactory.GetServer(args[0]); // Access the Team Foundation Eventing web service proxy m_eventServiceProxy = (IEventService)m_tfs.GetService(typeof(IEventService)); Assert.IsNotNull(m_eventServiceProxy, "Eventing service proxy is null"); // Initialize TCP socket listener to receive checkin alert as SOAP notification InitializeListener(); // Blocking wait for TCP socket listener bind to a port m_obtainedPort.WaitOne(); // Subscribe for checkin alerts, specifying SOAP notification as delivery preference. DeliveryPreference pref = new DeliveryPreference(); pref.Address = "http://" + Environment.MachineName + ":" + m_port; pref.Type = DeliveryType.Soap; pref.Schedule = DeliverySchedule.Immediate; // Now susbcribe using Eventing web service API string filter = String.Empty; m_alertId = m_eventServiceProxy.SubscribeEvent(workspace.OwnerName, "CheckinEvent", filter, pref); Assert.IsTrue(m_alertId != -1); /////////////////////////////////////////////////////////////////////// // Add code here to perform the checkin. This will trigger the alert // /////////////////////////////////////////////////////////////////////// // Verify that notification has been received. int limit = 60; int i = 0; for (i = 0; i < limit; i++) { Trace.WriteLine("Waiting to receive notification ..."); Thread.Sleep(1000); if (m_notificationReceived) { break; } } Assert.IsTrue(m_notificationReceived); } finally { // Unsubscribe from alerts. Notifications sent to this port after we close the // socket produce unnecessary event logs. if (m_alertId != -1) { m_eventServiceProxy.UnsubscribeEvent(m_alertId); } } } // TCP socket listener to receive checkin alert as SOAP notification private void InitializeListener() { ThreadStart processorDelegate = new ThreadStart(ProcessRequests); processorDelegate.BeginInvoke(null, null); } private void ProcessRequests() { // Buffer for reading data Byte[] bytes = new Byte[8192]; String alert = String.Empty; // Scan for available TCP port for (m_port = 1300; m_port < 1305; m_port++) { try { m_server = new TcpListener(IPAddress.Any, m_port); m_server.Start(); break; } catch (SocketException) { //try another port number } } Trace.WriteLine("Server initialized"); Trace.WriteLine("Waiting for a connection... "); // Signal that listener is bound to a port m_obtainedPort.Set(); //Enter the listening loop while (true) { // Perform a blocking call to accept requests. TcpClient client = m_server.AcceptTcpClient(); Trace.WriteLine("Connected"); // Get a stream object for reading and writing NetworkStream stream = client.GetStream(); int bytesRead = stream.Read(bytes, 0, bytes.Length); while ((!m_notificationReceived) && (bytesRead != 0)) { Trace.WriteLine("Received {0} bytes", bytesRead.ToString()); // Translate data bytes to a ASCII string. alert = System.Text.Encoding.ASCII.GetString(bytes, 0, bytesRead); // Event notification in Xml format String startToken = ""; String endToken = ""; int start = alert.IndexOf(startToken); int end = alert.IndexOf(endToken); if ((start != -1) && (end != -1)) { XmlDocument doc = new XmlDocument(); doc.LoadXml(alert.Substring(start, end + endToken.Length - start)); // Check notification contents for files, work items, etc. // Add code here to verify expected content in detail. if (doc.InnerXml.IndexOf("") != -1) { m_notificationReceived = true; Trace.WriteLine("Received checkin notification!"); } // Send response back to server byte[] responseBytes = System.Text.Encoding.ASCII.GetBytes(response); stream.Write(responseBytes, 0, responseBytes.Length); } else if ((alert.IndexOf("Notify") != -1) && alert.IndexOf("continue") != -1) { byte[] responseBytes = System.Text.Encoding.ASCII.GetBytes(continueResponse); stream.Write(responseBytes, 0, responseBytes.Length); } else { Trace.WriteLine("Received unknown message!"); break; } // Read next chunk bytesRead = stream.Read(bytes, 0, bytes.Length); } // Shutdown and end connection client.Close(); Trace.WriteLine("Done receiving"); } } private static string body = "" + "" + " " + " " + " " + " " + ""; private static string response = "HTTP/1.1 200 OK\r\n" + "Content-Length:" + body.Length + "\r\n" + "Cache-Control:private, max-age=0\r\n" + "Content-Type:text/xml; charset=utf-8\r\n" + "Date:Tue, 29 Mar 2005 18:16:13 GMT\r\n" + "Server:Microsoft-IIS/6.0\r\n" + "X-AspNet-Version:2.0.50727\r\n" + "X-Powered-By:ASP.NET\r\n" + "\r\n" + body; private static string continueResponse = "HTTP/1.1 100 Continue\r\n\r\n"; IEventService m_eventServiceProxy; TcpListener m_server; volatile bool m_notificationReceived = false; volatile bool m_testPassed = false; volatile Int32 m_port; ManualResetEvent m_obtainedPort = new ManualResetEvent(false); int m_alertId = -1; }