Click here to Skip to main content
15,892,746 members
Articles / Programming Languages / C#

WCF over Twitter

Rate me:
Please Sign up or sign in to vote.
4.97/5 (32 votes)
20 Sep 2009Ms-PL7 min read 58K   393   42  
How to code a TransportBindingElement.
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TwitterApi;
using TwitterApi.MiniTwitter;
using System.ServiceModel.Channels;
using TwitterTransportBinding;
using System.ServiceModel;
using System.Threading;
using System.IO;
using System.Net;

namespace Tests
{
	[ServiceContract]
	public interface HelloWorldService
	{
		[OperationContract(IsOneWay = true)]
		void SayHello(String name);
	}
	public class SpyTwitterProvider : TwitterProvider
	{
		string _UserName;
		public SpyTwitterProvider(string userName)
		{
			_UserName = userName;
		}

		#region TwitterProvider Members

		public string UserName
		{
			get
			{
				return _UserName;
			}
		}

		public List<Twit> SendedMessages = new List<Twit>();
		public Queue<Twit> ReceivedMessages = new Queue<Twit>();

		public void Send(Twit[] messages)
		{
			SendedMessages.AddRange(messages);
		}

		public Twit[] Receive()
		{
			List<Twit> result = new List<Twit>();
			while(ReceivedMessages.Count != 0)
				result.Add(ReceivedMessages.Dequeue());
			return result.ToArray();
		}

		#endregion
	}
	[TestClass]
	public class TwitterApiTest
	{
		NetworkCredential ServerCredentials = new NetworkCredential(ConfigHelper.ServerAccount, ConfigHelper.ServerPassword);
		NetworkCredential ClientCredentials = new NetworkCredential(ConfigHelper.ClientAccount, ConfigHelper.ClientPassword);

		[TestMethod]
		public void ShouldOnlyReceiveLastMessages()
		{
			string sentMessage = "@" + ClientCredentials.UserName + " hello world at " + DateTime.Now.ToString();
			MiniTwitterProvider provServer = new MiniTwitterProvider(ServerCredentials.UserName, ServerCredentials.Password);
			MiniTwitterProvider provClient = new MiniTwitterProvider(ClientCredentials.UserName, ClientCredentials.Password);
			provClient.Open();
			provServer.Send(new Twit[] { new Twit(sentMessage) });
			Thread.Sleep(3000);
			var results = provClient.Receive();
			Assert.AreEqual(1, results.Length);
			Assert.AreEqual(sentMessage, results[0].Content);
		}

		[TestMethod]
		public void TwitterBindingElementShouldSendTwit()
		{
			CustomBinding binding = new CustomBinding(new TextMessageEncodingBindingElement(), new TwitterTransportBindingElement()
			{
				Credentials = new System.Net.NetworkCredential(ClientCredentials.UserName, ClientCredentials.Password)
			});
			ChannelFactory<HelloWorldService> facto = new ChannelFactory<HelloWorldService>(binding, "twitter://" + ServerCredentials.UserName);
			var channel = facto.CreateChannel();
			channel.SayHello("nico");
		}

		[TestMethod]
		public void ShouldRetrieveUsername()
		{
			MiniTwitterProvider prov = new MiniTwitterProvider(ServerCredentials.UserName, ServerCredentials.Password);
			Assert.AreEqual(ServerCredentials.UserName, prov.UserName);
		}

		[TestMethod]
		public void ShouldSendThenReceiveMessage()
		{
			DateTime now = DateTime.Now;
			string sentMessage = "@" + ServerCredentials.UserName + " hello world at " + now.ToString();
			MiniTwitterProvider provServer = new MiniTwitterProvider(ServerCredentials.UserName, ServerCredentials.Password);
			MiniTwitterProvider provClient = new MiniTwitterProvider(ClientCredentials.UserName, ClientCredentials.Password);
			provServer.Open();
			provClient.Send(new Twit[] { new Twit(sentMessage) });
			Thread.Sleep(3000);
			var ReceivedMessages = provServer.Receive();
			Assert.AreEqual(1, ReceivedMessages.Length);
			Assert.IsTrue(ReceivedMessages.Any(t => t.Content == sentMessage));
		}

		[TestMethod]
		[ExpectedException(typeof(TwitterConnectionException))]
		public void BadPassShouldThrowTwitterConnectionException()
		{
			var prov = new MiniTwitterProvider(ServerCredentials.UserName, "badpass");
			prov.Receive();
		}


		[TestMethod]
		public void TwitterAPIShouldCutMessagesBeforeSendingToItsProvider()
		{
			var spy = new SpyTwitterProvider("nico");
			var text = "this is a super long message long message long message long message long message";
			TwitterApi.TwitterApi api = new TwitterApi.TwitterApi(spy);
			api.MaxTwitSize = 20;
			api.Send(text, "other");
			var tooBigMessage = spy.SendedMessages.FirstOrDefault(m => m.Content.Length > api.MaxTwitSize);
			string spyText = spy.SendedMessages.Select(t => t.Content).Aggregate((a, b) => a + b);
			Assert.IsTrue(text.Length < spyText.Length);
			Assert.IsNull(tooBigMessage, "a too big message was sent to the provider");
		}


		[TestMethod]
		public void EncoderErrorTest()
		{
			var message = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><a:Action s:mustUnderstand=\"1\">http://tempuri.org/IHelloWorldService/SayHello</a:Action></s:Header><s:Body><SayHello xmlns=\"http://tempuri.org/\"><name>Nico</name></SayHello></s:Body></s:Envelope>";
			MemoryStream stream = new MemoryStream();
			StreamWriter writer = new StreamWriter(stream);
			writer.Write(message);
			writer.Flush();
			stream.Position = 0;
			StreamReader reader = new StreamReader(stream);
			var soapMessage = new TextMessageEncodingBindingElement().CreateMessageEncoderFactory().Encoder.ReadMessage(stream, 99999);
			Assert.IsNotNull(soapMessage);
		}

		[TestMethod]
		public void TwitterAPIShouldJoinMessagesFromItsProvider()
		{
			var spy = new SpyTwitterProvider("nico");
			var text = "this is a super long message long message long message long message long message";
			TwitterApi.TwitterApi api = new TwitterApi.TwitterApi(spy);
			api.MaxTwitSize = 20;
			api.Send(text, "nico");
			foreach(var sendedMessage in spy.SendedMessages)
				spy.ReceivedMessages.Enqueue(sendedMessage);
			var ReceivedText = api.Receive();
			Assert.AreEqual(text, ReceivedText);
		}

		[TestMethod]
		public void ChainShouldBeCompleteWhenLastMessageDontHaveContinuationString()
		{
			var twit1 = ParseRawTwit("nico", "@nico hello[...]");
			var twit2 = ParseRawTwit("nico", "@nico World!");
			TwitterChainMessage chain = new TwitterChainMessage();
			Assert.IsFalse(chain.IsComplete, "an empty chain should not be complete");
			chain.Append(twit1);
			Assert.IsFalse(chain.IsComplete, "a chain with a twit to be continued should not be complete");
			chain.Append(twit2);
			Assert.IsTrue(chain.IsComplete, "a chain with a twit NOT to be continued should be complete");
			try
			{
				chain.Append(twit1);
				Assert.Fail("should not be able to add a tweet after chain is completed");
			}
			catch(InvalidOperationException)
			{
			}
		}

		[TestMethod]
		public void ChainShouldRenderTheConcatenationOfMessages()
		{
			var twit1 = ParseRawTwit("nico", "@nico hello[...]");
			var twit2 = ParseRawTwit("nico", "@nico World!");
			TwitterChainMessage chain = new TwitterChainMessage();
			chain.Append(twit1);
			chain.Append(twit2);
			Assert.AreEqual("helloWorld!", chain.GetFullMessage());
		}

		[TestMethod]
		public void MessageCreationShouldTruncateMessageIfTooLong()
		{
			var text = "some content very long aye aye aye hey hey....";
			String contentLeft = null;
			var twit = TwitterMessage.Create("header", text, "[...]", 20, out contentLeft);
			Assert.IsNotNull(contentLeft, "The message should be truncated");
			Assert.AreEqual(text, twit.Content + contentLeft, "The content left and the twit content should construct original message");
		}

		[TestMethod]
		public void VeryLongMessageShouldBeSplitInSeveralTwit()
		{
			var text = "this is a really long long long message long long long message long long long message long long long message long long long message";
			var maxMessageSize = 20;
			var chain = TwitterMessage.CreateMessages(new TwitterMessageContext("nico")
			{
				MaxMessageSize = maxMessageSize
			}, text);
			Assert.AreEqual(text, chain.GetFullMessage());
			Assert.AreEqual(chain.Count(), chain.Count(m => m.IsFinalMessage || m.FullMessage.Length == maxMessageSize), "Every message should have the max size except the final message");
		}

		[TestMethod]
		public void ShouldParseARawTwit()
		{
			var twit = ParseRawTwit("nico", "@nico helloWorld");
			Assert.AreEqual("@nico helloWorld", twit.FullMessage);
			Assert.AreEqual("@nico ", twit.Header);
			Assert.AreEqual("", twit.Bottom);
			Assert.IsTrue(twit.IsFinalMessage);
			twit = ParseRawTwit("nico", "@nico helloWorld[...]");
			Assert.AreEqual("@nico helloWorld[...]", twit.FullMessage);
			Assert.AreEqual("@nico ", twit.Header);
			Assert.AreEqual("[...]", twit.Bottom);
			Assert.IsFalse(twit.IsFinalMessage);
		}

		TwitterMessage ParseRawTwit(string user, string rawContent)
		{
			TwitterMessage twit;
			if(!TwitterMessage.TryParseMessage(new TwitterMessageContext(user), rawContent, out twit))
			{
				Assert.Fail("Should be able to parse this tweet");
			}
			return twit;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Software Developer Freelance
France France
I am currently the CTO of Metaco, we are leveraging the Bitcoin Blockchain for delivering financial services.

I also developed a tool to make IaaS on Azure more easy to use IaaS Management Studio.

If you want to contact me, go this way Smile | :)

Comments and Discussions