PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ProtocolBuffers.Test/TestRpcForMimeTypes.cs

https://code.google.com/p/protobuf-csharp-port/
C# | 386 lines | 240 code | 52 blank | 94 comment | 2 complexity | b824559ee5423ceb64f35e2eb9e41ad8 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, GPL-2.0
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // http://github.com/jskeet/dotnet-protobufs/
  5. // Original C++/Java/Python code:
  6. // http://code.google.com/p/protobuf/
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. //
  12. // * Redistributions of source code must retain the above copyright
  13. // notice, this list of conditions and the following disclaimer.
  14. // * Redistributions in binary form must reproduce the above
  15. // copyright notice, this list of conditions and the following disclaimer
  16. // in the documentation and/or other materials provided with the
  17. // distribution.
  18. // * Neither the name of Google Inc. nor the names of its
  19. // contributors may be used to endorse or promote products derived from
  20. // this software without specific prior written permission.
  21. //
  22. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  26. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  27. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  28. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. #endregion
  34. using System;
  35. using Google.ProtocolBuffers;
  36. using Google.ProtocolBuffers.Serialization.Http;
  37. using Google.ProtocolBuffers.TestProtos;
  38. using Microsoft.VisualStudio.TestTools.UnitTesting;
  39. using System.IO;
  40. using Google.ProtocolBuffers.Serialization;
  41. using System.Text;
  42. namespace Google.ProtocolBuffers
  43. {
  44. /// <summary>
  45. /// This class verifies the correct code is generated from unittest_rpc_interop.proto and provides a small demonstration
  46. /// of using the new IRpcDispatch to write a client/server
  47. /// </summary>
  48. [TestClass]
  49. public class TestRpcForMimeTypes
  50. {
  51. /// <summary>
  52. /// A sample implementation of the ISearchService for testing
  53. /// </summary>
  54. private class ExampleSearchImpl : ISearchService
  55. {
  56. SearchResponse ISearchService.Search(SearchRequest searchRequest)
  57. {
  58. if (searchRequest.CriteriaCount == 0)
  59. {
  60. throw new ArgumentException("No criteria specified.", new InvalidOperationException());
  61. }
  62. SearchResponse.Builder resp = SearchResponse.CreateBuilder();
  63. foreach (string criteria in searchRequest.CriteriaList)
  64. {
  65. resp.AddResults(
  66. SearchResponse.Types.ResultItem.CreateBuilder().SetName(criteria).SetUrl("http://search.com").
  67. Build());
  68. }
  69. return resp.Build();
  70. }
  71. SearchResponse ISearchService.RefineSearch(RefineSearchRequest refineSearchRequest)
  72. {
  73. SearchResponse.Builder resp = refineSearchRequest.PreviousResults.ToBuilder();
  74. foreach (string criteria in refineSearchRequest.CriteriaList)
  75. {
  76. resp.AddResults(
  77. SearchResponse.Types.ResultItem.CreateBuilder().SetName(criteria).SetUrl("http://refine.com").
  78. Build());
  79. }
  80. return resp.Build();
  81. }
  82. }
  83. /// <summary>
  84. /// An example extraction of the wire protocol
  85. /// </summary>
  86. private interface IHttpTransfer
  87. {
  88. void Execute(string method, string contentType, Stream input, string acceptType, Stream output);
  89. }
  90. /// <summary>
  91. /// An example of a server responding to a web/http request
  92. /// </summary>
  93. private class ExampleHttpServer : IHttpTransfer
  94. {
  95. public readonly MessageFormatOptions Options =
  96. new MessageFormatOptions
  97. {
  98. ExtensionRegistry = ExtensionRegistry.Empty,
  99. FormattedOutput = true,
  100. XmlReaderOptions = XmlReaderOptions.ReadNestedArrays,
  101. XmlReaderRootElementName = "request",
  102. XmlWriterOptions = XmlWriterOptions.OutputNestedArrays,
  103. XmlWriterRootElementName = "response"
  104. };
  105. private readonly IRpcServerStub _stub;
  106. public ExampleHttpServer(ISearchService implementation)
  107. {
  108. //on the server, we create a dispatch to call the appropriate method by name
  109. IRpcDispatch dispatch = new SearchService.Dispatch(implementation);
  110. //we then wrap that dispatch in a server stub which will deserialize the wire bytes to the message
  111. //type appropriate for the method name being invoked.
  112. _stub = new SearchService.ServerStub(dispatch);
  113. }
  114. void IHttpTransfer.Execute(string method, string contentType, Stream input, string acceptType, Stream output)
  115. {
  116. //3.5: _stub.HttpCallMethod(
  117. Extensions.HttpCallMethod(_stub,
  118. method, Options,
  119. contentType, input,
  120. acceptType, output
  121. );
  122. }
  123. }
  124. /// <summary>
  125. /// An example of a client sending a wire request
  126. /// </summary>
  127. private class ExampleClient : IRpcDispatch
  128. {
  129. public readonly MessageFormatOptions Options =
  130. new MessageFormatOptions
  131. {
  132. ExtensionRegistry = ExtensionRegistry.Empty,
  133. FormattedOutput = true,
  134. XmlReaderOptions = XmlReaderOptions.ReadNestedArrays,
  135. XmlReaderRootElementName = "response",
  136. XmlWriterOptions = XmlWriterOptions.OutputNestedArrays,
  137. XmlWriterRootElementName = "request"
  138. };
  139. private readonly IHttpTransfer _wire;
  140. private readonly string _mimeType;
  141. public ExampleClient(IHttpTransfer wire, string mimeType)
  142. {
  143. _wire = wire;
  144. _mimeType = mimeType;
  145. }
  146. TMessage IRpcDispatch.CallMethod<TMessage, TBuilder>(string method, IMessageLite request,
  147. IBuilderLite<TMessage, TBuilder> response)
  148. {
  149. MemoryStream input = new MemoryStream();
  150. MemoryStream output = new MemoryStream();
  151. //Write to _mimeType format
  152. Extensions.WriteTo(request, Options, _mimeType, input);
  153. input.Position = 0;
  154. _wire.Execute(method, _mimeType, input, _mimeType, output);
  155. //Read from _mimeType format
  156. output.Position = 0;
  157. Extensions.MergeFrom(response, Options, _mimeType, output);
  158. return response.Build();
  159. }
  160. }
  161. /// <summary>
  162. /// Test sending and recieving messages via text/json
  163. /// </summary>
  164. [TestMethod]
  165. public void TestClientServerWithJsonFormat()
  166. {
  167. ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
  168. //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
  169. IHttpTransfer wire = server;
  170. ISearchService client = new SearchService(new ExampleClient(wire, "text/json"));
  171. //now the client has a real, typed, interface to work with:
  172. SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
  173. Assert.AreEqual(1, result.ResultsCount);
  174. Assert.AreEqual("Test", result.ResultsList[0].Name);
  175. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  176. //The test part of this, call the only other method
  177. result =
  178. client.RefineSearch(
  179. RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
  180. Assert.AreEqual(2, result.ResultsCount);
  181. Assert.AreEqual("Test", result.ResultsList[0].Name);
  182. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  183. Assert.AreEqual("Refine", result.ResultsList[1].Name);
  184. Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
  185. }
  186. /// <summary>
  187. /// Test sending and recieving messages via text/json
  188. /// </summary>
  189. [TestMethod]
  190. public void TestClientServerWithXmlFormat()
  191. {
  192. ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
  193. //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
  194. IHttpTransfer wire = server;
  195. ISearchService client = new SearchService(new ExampleClient(wire, "text/xml"));
  196. //now the client has a real, typed, interface to work with:
  197. SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
  198. Assert.AreEqual(1, result.ResultsCount);
  199. Assert.AreEqual("Test", result.ResultsList[0].Name);
  200. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  201. //The test part of this, call the only other method
  202. result =
  203. client.RefineSearch(
  204. RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
  205. Assert.AreEqual(2, result.ResultsCount);
  206. Assert.AreEqual("Test", result.ResultsList[0].Name);
  207. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  208. Assert.AreEqual("Refine", result.ResultsList[1].Name);
  209. Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
  210. }
  211. /// <summary>
  212. /// Test sending and recieving messages via text/json
  213. /// </summary>
  214. [TestMethod]
  215. public void TestClientServerWithProtoFormat()
  216. {
  217. ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
  218. //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
  219. IHttpTransfer wire = server;
  220. ISearchService client = new SearchService(new ExampleClient(wire, "application/x-protobuf"));
  221. //now the client has a real, typed, interface to work with:
  222. SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
  223. Assert.AreEqual(1, result.ResultsCount);
  224. Assert.AreEqual("Test", result.ResultsList[0].Name);
  225. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  226. //The test part of this, call the only other method
  227. result =
  228. client.RefineSearch(
  229. RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
  230. Assert.AreEqual(2, result.ResultsCount);
  231. Assert.AreEqual("Test", result.ResultsList[0].Name);
  232. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  233. Assert.AreEqual("Refine", result.ResultsList[1].Name);
  234. Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
  235. }
  236. /// <summary>
  237. /// Test sending and recieving messages via text/json
  238. /// </summary>
  239. [TestMethod]
  240. public void TestClientServerWithCustomFormat()
  241. {
  242. ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
  243. //Setup our custom mime-type format as the only format supported:
  244. server.Options.MimeInputTypes.Clear();
  245. server.Options.MimeInputTypes.Add("foo/bar", CodedInputStream.CreateInstance);
  246. server.Options.MimeOutputTypes.Clear();
  247. server.Options.MimeOutputTypes.Add("foo/bar", CodedOutputStream.CreateInstance);
  248. //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
  249. IHttpTransfer wire = server;
  250. ExampleClient exclient = new ExampleClient(wire, "foo/bar");
  251. //Add our custom mime-type format
  252. exclient.Options.MimeInputTypes.Add("foo/bar", CodedInputStream.CreateInstance);
  253. exclient.Options.MimeOutputTypes.Add("foo/bar", CodedOutputStream.CreateInstance);
  254. ISearchService client = new SearchService(exclient);
  255. //now the client has a real, typed, interface to work with:
  256. SearchResponse result = client.Search(SearchRequest.CreateBuilder().AddCriteria("Test").Build());
  257. Assert.AreEqual(1, result.ResultsCount);
  258. Assert.AreEqual("Test", result.ResultsList[0].Name);
  259. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  260. //The test part of this, call the only other method
  261. result =
  262. client.RefineSearch(
  263. RefineSearchRequest.CreateBuilder().SetPreviousResults(result).AddCriteria("Refine").Build());
  264. Assert.AreEqual(2, result.ResultsCount);
  265. Assert.AreEqual("Test", result.ResultsList[0].Name);
  266. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  267. Assert.AreEqual("Refine", result.ResultsList[1].Name);
  268. Assert.AreEqual("http://refine.com", result.ResultsList[1].Url);
  269. }
  270. /// <summary>
  271. /// Test sending and recieving messages via text/json
  272. /// </summary>
  273. [TestMethod]
  274. public void TestServerWithUriFormat()
  275. {
  276. ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
  277. //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
  278. IHttpTransfer wire = server;
  279. MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes("?Criteria=Test&Criteria=Test+of%20URI"));
  280. MemoryStream output = new MemoryStream();
  281. //Call the server
  282. wire.Execute("Search",
  283. MessageFormatOptions.ContentFormUrlEncoded, input,
  284. MessageFormatOptions.ContentTypeProtoBuffer, output
  285. );
  286. SearchResponse result = SearchResponse.ParseFrom(output.ToArray());
  287. Assert.AreEqual(2, result.ResultsCount);
  288. Assert.AreEqual("Test", result.ResultsList[0].Name);
  289. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  290. Assert.AreEqual("Test of URI", result.ResultsList[1].Name);
  291. Assert.AreEqual("http://search.com", result.ResultsList[1].Url);
  292. }
  293. /// <summary>
  294. /// Test sending and recieving messages via text/json
  295. /// </summary>
  296. [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
  297. public void TestInvalidMimeType()
  298. {
  299. ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
  300. //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
  301. IHttpTransfer wire = server;
  302. MemoryStream input = new MemoryStream();
  303. MemoryStream output = new MemoryStream();
  304. //Call the server
  305. wire.Execute("Search",
  306. "bad/mime", input,
  307. MessageFormatOptions.ContentTypeProtoBuffer, output
  308. );
  309. Assert.Fail();
  310. }
  311. /// <summary>
  312. /// Test sending and recieving messages via text/json
  313. /// </summary>
  314. [TestMethod]
  315. public void TestDefaultMimeType()
  316. {
  317. ExampleHttpServer server = new ExampleHttpServer(new ExampleSearchImpl());
  318. //obviously if this was a 'real' transport we would not use the server, rather the server would be listening, the client transmitting
  319. IHttpTransfer wire = server;
  320. MemoryStream input = new MemoryStream(new SearchRequest.Builder().AddCriteria("Test").Build().ToByteArray());
  321. MemoryStream output = new MemoryStream();
  322. //With this default set, any invalid/unknown mime-type will be mapped to use that format
  323. server.Options.DefaultContentType = MessageFormatOptions.ContentTypeProtoBuffer;
  324. wire.Execute("Search",
  325. "foo", input,
  326. "bar", output
  327. );
  328. SearchResponse result = SearchResponse.ParseFrom(output.ToArray());
  329. Assert.AreEqual(1, result.ResultsCount);
  330. Assert.AreEqual("Test", result.ResultsList[0].Name);
  331. Assert.AreEqual("http://search.com", result.ResultsList[0].Url);
  332. }
  333. }
  334. }