PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ProtoGen.Test/TestPreprocessing.cs

https://code.google.com/p/protobuf-csharp-port/
C# | 763 lines | 638 code | 43 blank | 82 comment | 1 complexity | 0feee41eb6fcacd03b75c2681d7bf634 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 System.Collections.Generic;
  36. using System.Diagnostics;
  37. using System.IO;
  38. using System.Reflection;
  39. using NUnit.Framework;
  40. namespace Google.ProtocolBuffers.ProtoGen
  41. {
  42. [TestFixture]
  43. [Category("Preprocessor")]
  44. public partial class TestPreprocessing
  45. {
  46. private static readonly string TempPath = Path.Combine(Path.GetTempPath(), "proto-gen-test");
  47. private const string DefaultProto =
  48. @"
  49. package nunit.simple;
  50. // Test a very simple message.
  51. message MyMessage {
  52. optional string name = 1;
  53. }";
  54. #region TestFixture SetUp/TearDown
  55. private static readonly string OriginalWorkingDirectory = Environment.CurrentDirectory;
  56. [TestFixtureSetUp]
  57. public virtual void Setup()
  58. {
  59. Teardown();
  60. Directory.CreateDirectory(TempPath);
  61. Environment.CurrentDirectory = TempPath;
  62. }
  63. [TestFixtureTearDown]
  64. public virtual void Teardown()
  65. {
  66. Environment.CurrentDirectory = OriginalWorkingDirectory;
  67. if (Directory.Exists(TempPath))
  68. {
  69. Directory.Delete(TempPath, true);
  70. }
  71. }
  72. #endregion
  73. #region Helper Methods RunProtoGen / RunCsc
  74. private void RunProtoGen(int expect, params string[] args)
  75. {
  76. TextWriter tout = Console.Out, terr = Console.Error;
  77. StringWriter temp = new StringWriter();
  78. Console.SetOut(temp);
  79. Console.SetError(temp);
  80. try
  81. {
  82. Assert.AreEqual(expect, ProgramPreprocess.Run(args), "ProtoGen Failed: {0}", temp);
  83. }
  84. finally
  85. {
  86. Console.SetOut(tout);
  87. Console.SetError(terr);
  88. }
  89. }
  90. private Assembly RunCsc(int expect, params string[] sources)
  91. {
  92. using (TempFile tempDll = new TempFile(String.Empty))
  93. {
  94. tempDll.ChangeExtension(".dll");
  95. List<string> args = new List<string>();
  96. args.Add("/nologo");
  97. args.Add("/target:library");
  98. args.Add("/debug-");
  99. args.Add(String.Format(@"""/out:{0}""", tempDll.TempPath));
  100. args.Add("/r:System.dll");
  101. args.Add(String.Format(@"""/r:{0}""",
  102. typeof (Google.ProtocolBuffers.DescriptorProtos.DescriptorProto).Assembly.
  103. Location));
  104. args.AddRange(sources);
  105. string exe = Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(),
  106. "csc.exe");
  107. ProcessStartInfo psi = new ProcessStartInfo(exe);
  108. psi.CreateNoWindow = true;
  109. psi.UseShellExecute = false;
  110. psi.RedirectStandardOutput = true;
  111. psi.RedirectStandardError = true;
  112. psi.Arguments = string.Join(" ", args.ToArray());
  113. Process p = Process.Start(psi);
  114. p.WaitForExit();
  115. string errorText = p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd();
  116. Assert.AreEqual(expect, p.ExitCode, "CSC.exe Failed: {0}", errorText);
  117. Assembly asm = null;
  118. if (p.ExitCode == 0)
  119. {
  120. byte[] allbytes = File.ReadAllBytes(tempDll.TempPath);
  121. asm = Assembly.Load(allbytes);
  122. foreach (Type t in asm.GetTypes())
  123. {
  124. Debug.WriteLine(t.FullName, asm.FullName);
  125. }
  126. }
  127. return asm;
  128. }
  129. }
  130. #endregion
  131. // *******************************************************************
  132. // The following tests excercise options for protogen.exe
  133. // *******************************************************************
  134. [Test]
  135. public void TestProtoFile()
  136. {
  137. string test = new StackFrame(false).GetMethod().Name;
  138. Setup();
  139. using (TempFile source = TempFile.Attach(test + ".cs"))
  140. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  141. {
  142. RunProtoGen(0, proto.TempPath);
  143. Assembly a = RunCsc(0, source.TempPath);
  144. //assert that the message type is in the expected namespace
  145. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  146. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  147. //assert that we can find the static descriptor type
  148. a.GetType("nunit.simple." + test, true, true);
  149. }
  150. }
  151. [Test]
  152. public void TestProtoFileWithConflictingType()
  153. {
  154. string test = new StackFrame(false).GetMethod().Name;
  155. Setup();
  156. using (TempFile source = TempFile.Attach(test + ".cs"))
  157. using (
  158. ProtoFile proto = new ProtoFile(test + ".proto",
  159. @"
  160. package nunit.simple;
  161. // Test a very simple message.
  162. message " +
  163. test + @" {
  164. optional string name = 1;
  165. } "))
  166. {
  167. RunProtoGen(0, proto.TempPath);
  168. Assembly a = RunCsc(0, source.TempPath);
  169. //assert that the message type is in the expected namespace
  170. Type t = a.GetType("nunit.simple." + test, true, true);
  171. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  172. //assert that we can find the static descriptor type
  173. a.GetType("nunit.simple.Proto." + test, true, true);
  174. }
  175. }
  176. [Test]
  177. public void TestProtoFileWithNamespace()
  178. {
  179. string test = new StackFrame(false).GetMethod().Name;
  180. Setup();
  181. using (TempFile source = TempFile.Attach(test + ".cs"))
  182. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  183. {
  184. RunProtoGen(0, proto.TempPath, "-namespace:MyNewNamespace");
  185. Assembly a = RunCsc(0, source.TempPath);
  186. //assert that the message type is in the expected namespace
  187. Type t = a.GetType("MyNewNamespace.MyMessage", true, true);
  188. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  189. //assert that we can find the static descriptor type
  190. a.GetType("MyNewNamespace." + test, true, true);
  191. }
  192. }
  193. [Test]
  194. public void TestProtoFileWithUmbrellaClassName()
  195. {
  196. string test = new StackFrame(false).GetMethod().Name;
  197. Setup();
  198. using (TempFile source = TempFile.Attach("MyUmbrellaClassname.cs"))
  199. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  200. {
  201. RunProtoGen(0, proto.TempPath, "/umbrella_classname=MyUmbrellaClassname");
  202. Assembly a = RunCsc(0, source.TempPath);
  203. //assert that the message type is in the expected namespace
  204. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  205. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  206. //assert that we can find the static descriptor type
  207. a.GetType("nunit.simple.MyUmbrellaClassname", true, true);
  208. }
  209. }
  210. [Test]
  211. public void TestProtoFileWithNestedClass()
  212. {
  213. string test = new StackFrame(false).GetMethod().Name;
  214. Setup();
  215. using (TempFile source = TempFile.Attach(test + ".cs"))
  216. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  217. {
  218. RunProtoGen(0, proto.TempPath, "-nest_classes:true");
  219. Assembly a = RunCsc(0, source.TempPath);
  220. //assert that the message type is in the expected namespace
  221. Type t = a.GetType("nunit.simple." + test + "+MyMessage", true, true);
  222. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  223. //assert that we can find the static descriptor type
  224. a.GetType("nunit.simple." + test, true, true);
  225. }
  226. }
  227. [Test]
  228. public void TestProtoFileWithExpandedNsDirectories()
  229. {
  230. string test = new StackFrame(false).GetMethod().Name;
  231. Setup();
  232. using (TempFile source = TempFile.Attach(@"nunit\simple\" + test + ".cs"))
  233. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  234. {
  235. RunProtoGen(0, proto.TempPath, "-expand_namespace_directories:true");
  236. Assembly a = RunCsc(0, source.TempPath);
  237. //assert that the message type is in the expected namespace
  238. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  239. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  240. //assert that we can find the static descriptor type
  241. a.GetType("nunit.simple." + test, true, true);
  242. }
  243. }
  244. [Test]
  245. public void TestProtoFileDisablingClsComplianceFlags()
  246. {
  247. string test = new StackFrame(false).GetMethod().Name;
  248. Setup();
  249. using (TempFile source = TempFile.Attach(test + ".cs"))
  250. using (
  251. ProtoFile proto = new ProtoFile(test + ".proto",
  252. @"
  253. package nunit.simple;
  254. // Test a very simple message.
  255. message MyMessage {
  256. optional uint32 name = 1;
  257. } ")
  258. )
  259. {
  260. //CS3021: Warning as Error: xx does not need a CLSCompliant attribute because the assembly does not have a CLSCompliant attribute
  261. RunProtoGen(0, proto.TempPath);
  262. RunCsc(1, source.TempPath, "/warnaserror+");
  263. //Now we know it fails, make it pass by turning off cls_compliance generation
  264. RunProtoGen(0, proto.TempPath, "-cls_compliance:false");
  265. Assembly a = RunCsc(0, source.TempPath, "/warnaserror+");
  266. //assert that the message type is in the expected namespace
  267. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  268. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  269. //assert that we can find the static descriptor type
  270. a.GetType("nunit.simple." + test, true, true);
  271. }
  272. }
  273. [Test]
  274. public void TestProtoFileWithNewExtension()
  275. {
  276. string test = new StackFrame(false).GetMethod().Name;
  277. Setup();
  278. using (TempFile source = TempFile.Attach(test + ".Generated.cs"))
  279. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  280. {
  281. RunProtoGen(0, proto.TempPath, "-file_extension:.Generated.cs");
  282. Assembly a = RunCsc(0, source.TempPath);
  283. //assert that the message type is in the expected namespace
  284. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  285. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  286. //assert that we can find the static descriptor type
  287. a.GetType("nunit.simple." + test, true, true);
  288. }
  289. }
  290. [Test]
  291. public void TestProtoFileWithUmbrellaNamespace()
  292. {
  293. string test = new StackFrame(false).GetMethod().Name;
  294. Setup();
  295. using (TempFile source = TempFile.Attach(test + ".cs"))
  296. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  297. {
  298. RunProtoGen(0, proto.TempPath, "-umbrella_namespace:MyUmbrella.Namespace");
  299. Assembly a = RunCsc(0, source.TempPath);
  300. //assert that the message type is in the expected namespace
  301. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  302. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  303. //assert that we can find the static descriptor type
  304. a.GetType("nunit.simple.MyUmbrella.Namespace." + test, true, true);
  305. }
  306. }
  307. [Test]
  308. public void TestProtoFileWithIgnoredUmbrellaNamespaceDueToNesting()
  309. {
  310. string test = new StackFrame(false).GetMethod().Name;
  311. Setup();
  312. using (TempFile source = TempFile.Attach(test + ".cs"))
  313. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  314. {
  315. RunProtoGen(0, proto.TempPath, "-nest_classes:true", "-umbrella_namespace:MyUmbrella.Namespace");
  316. Assembly a = RunCsc(0, source.TempPath);
  317. //assert that the message type is in the expected namespace
  318. Type t = a.GetType("nunit.simple." + test + "+MyMessage", true, true);
  319. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  320. //assert that we can find the static descriptor type
  321. a.GetType("nunit.simple." + test, true, true);
  322. }
  323. }
  324. [Test]
  325. public void TestProtoFileWithExplicitEmptyUmbrellaNamespace()
  326. {
  327. string test = new StackFrame(false).GetMethod().Name;
  328. Setup();
  329. using (TempFile source = TempFile.Attach(test + ".cs"))
  330. using (
  331. ProtoFile proto = new ProtoFile(test + ".proto",
  332. @"
  333. package nunit.simple;
  334. // Test a very simple message.
  335. message " +
  336. test + @" {
  337. optional string name = 1;
  338. } "))
  339. {
  340. //Forces the umbrella class to not use a namespace even if a collision with a type is detected.
  341. RunProtoGen(0, proto.TempPath, "-umbrella_namespace:");
  342. //error CS0441: 'nunit.simple.TestProtoFileWithExplicitEmptyUmbrellaNamespace': a class cannot be both static and sealed
  343. RunCsc(1, source.TempPath);
  344. }
  345. }
  346. [Test]
  347. public void TestProtoFileWithNewOutputFolder()
  348. {
  349. string test = new StackFrame(false).GetMethod().Name;
  350. Setup();
  351. using (TempFile source = TempFile.Attach(@"generated-code\" + test + ".cs"))
  352. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  353. {
  354. RunProtoGen(1, proto.TempPath, "-output_directory:generated-code");
  355. Directory.CreateDirectory("generated-code");
  356. RunProtoGen(0, proto.TempPath, "-output_directory:generated-code");
  357. Assembly a = RunCsc(0, source.TempPath);
  358. //assert that the message type is in the expected namespace
  359. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  360. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  361. //assert that we can find the static descriptor type
  362. a.GetType("nunit.simple." + test, true, true);
  363. }
  364. }
  365. [Test]
  366. public void TestProtoFileAndIgnoreGoogleProtobuf()
  367. {
  368. string test = new StackFrame(false).GetMethod().Name;
  369. Setup();
  370. using (TempFile source = TempFile.Attach(test + ".cs"))
  371. using (
  372. ProtoFile proto = new ProtoFile(test + ".proto",
  373. @"
  374. import ""google/protobuf/csharp_options.proto"";
  375. option (google.protobuf.csharp_file_options).namespace = ""MyNewNamespace"";
  376. " +
  377. DefaultProto))
  378. {
  379. string google = Path.Combine(TempPath, "google\\protobuf");
  380. Directory.CreateDirectory(google);
  381. foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf")))
  382. {
  383. File.Copy(file, Path.Combine(google, Path.GetFileName(file)));
  384. }
  385. Assert.AreEqual(0, Directory.GetFiles(TempPath, "*.cs").Length);
  386. RunProtoGen(0, proto.TempPath, "-ignore_google_protobuf:true");
  387. Assert.AreEqual(1, Directory.GetFiles(TempPath, "*.cs").Length);
  388. Assembly a = RunCsc(0, source.TempPath);
  389. //assert that the message type is in the expected namespace
  390. Type t = a.GetType("MyNewNamespace.MyMessage", true, true);
  391. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  392. //assert that we can find the static descriptor type
  393. a.GetType("MyNewNamespace." + test, true, true);
  394. }
  395. }
  396. [Test]
  397. public void TestProtoFileWithoutIgnoreGoogleProtobuf()
  398. {
  399. string test = new StackFrame(false).GetMethod().Name;
  400. Setup();
  401. using (TempFile source = TempFile.Attach(test + ".cs"))
  402. using (
  403. ProtoFile proto = new ProtoFile(test + ".proto",
  404. @"
  405. import ""google/protobuf/csharp_options.proto"";
  406. option (google.protobuf.csharp_file_options).namespace = ""MyNewNamespace"";
  407. " +
  408. DefaultProto))
  409. {
  410. string google = Path.Combine(TempPath, "google\\protobuf");
  411. Directory.CreateDirectory(google);
  412. foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf")))
  413. {
  414. File.Copy(file, Path.Combine(google, Path.GetFileName(file)));
  415. }
  416. Assert.AreEqual(0, Directory.GetFiles(TempPath, "*.cs").Length);
  417. //Without the option this fails due to being unable to resolve google/protobuf descriptors
  418. RunProtoGen(1, proto.TempPath, "-ignore_google_protobuf:false");
  419. }
  420. }
  421. // *******************************************************************
  422. // The following tests excercise options for protoc.exe
  423. // *******************************************************************
  424. [Test]
  425. public void TestProtoFileWithIncludeImports()
  426. {
  427. string test = new StackFrame(false).GetMethod().Name;
  428. Setup();
  429. using (TempFile source = TempFile.Attach(test + ".cs"))
  430. using (
  431. ProtoFile proto = new ProtoFile(test + ".proto",
  432. @"
  433. import ""google/protobuf/csharp_options.proto"";
  434. option (google.protobuf.csharp_file_options).namespace = ""MyNewNamespace"";
  435. package nunit.simple;
  436. // Test a very simple message.
  437. message MyMessage {
  438. optional string name = 1;
  439. } ")
  440. )
  441. {
  442. string google = Path.Combine(TempPath, "google\\protobuf");
  443. Directory.CreateDirectory(google);
  444. foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf")))
  445. {
  446. File.Copy(file, Path.Combine(google, Path.GetFileName(file)));
  447. }
  448. Assert.AreEqual(0, Directory.GetFiles(TempPath, "*.cs").Length);
  449. //if you specify the protoc option --include_imports this should build three source files
  450. RunProtoGen(0, proto.TempPath, "--include_imports");
  451. Assert.AreEqual(3, Directory.GetFiles(TempPath, "*.cs").Length);
  452. //you can (and should) simply omit the inclusion of the extra source files in your project
  453. Assembly a = RunCsc(0, source.TempPath);
  454. //assert that the message type is in the expected namespace
  455. Type t = a.GetType("MyNewNamespace.MyMessage", true, true);
  456. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  457. //assert that we can find the static descriptor type
  458. a.GetType("MyNewNamespace." + test, true, true);
  459. }
  460. }
  461. [Test]
  462. public void TestProtoFileWithIncludeImportsAndIgnoreGoogleProtobuf()
  463. {
  464. string test = new StackFrame(false).GetMethod().Name;
  465. Setup();
  466. using (TempFile source = TempFile.Attach(test + ".cs"))
  467. using (
  468. ProtoFile proto = new ProtoFile(test + ".proto",
  469. @"
  470. import ""google/protobuf/csharp_options.proto"";
  471. option (google.protobuf.csharp_file_options).namespace = ""MyNewNamespace"";
  472. package nunit.simple;
  473. // Test a very simple message.
  474. message MyMessage {
  475. optional string name = 1;
  476. } ")
  477. )
  478. {
  479. string google = Path.Combine(TempPath, "google\\protobuf");
  480. Directory.CreateDirectory(google);
  481. foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf")))
  482. File.Copy(file, Path.Combine(google, Path.GetFileName(file)));
  483. Assert.AreEqual(0, Directory.GetFiles(TempPath, "*.cs").Length);
  484. //Even with --include_imports, if you provide -ignore_google_protobuf:true you only get the one source file
  485. RunProtoGen(0, proto.TempPath, "-ignore_google_protobuf:true", "--include_imports");
  486. Assert.AreEqual(1, Directory.GetFiles(TempPath, "*.cs").Length);
  487. //you can (and should) simply omit the inclusion of the extra source files in your project
  488. Assembly a = RunCsc(0, source.TempPath);
  489. //assert that the message type is in the expected namespace
  490. Type t = a.GetType("MyNewNamespace.MyMessage", true, true);
  491. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  492. //assert that we can find the static descriptor type
  493. a.GetType("MyNewNamespace." + test, true, true);
  494. }
  495. }
  496. [Test]
  497. public void TestProtoFileKeepingTheProtoBuffer()
  498. {
  499. string test = new StackFrame(false).GetMethod().Name;
  500. Setup();
  501. using (TempFile protobuf = TempFile.Attach(test + ".pb"))
  502. using (TempFile source = TempFile.Attach(test + ".cs"))
  503. using (
  504. ProtoFile proto = new ProtoFile(test + ".proto",
  505. @"
  506. package nunit.simple;
  507. // Test a very simple message.
  508. message MyMessage {
  509. optional string name = 1;
  510. } ")
  511. )
  512. {
  513. RunProtoGen(0, proto.TempPath, "--descriptor_set_out=" + protobuf.TempPath);
  514. Assert.IsTrue(File.Exists(protobuf.TempPath), "Missing: " + protobuf.TempPath);
  515. Assembly a = RunCsc(0, source.TempPath);
  516. //assert that the message type is in the expected namespace
  517. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  518. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  519. //assert that we can find the static descriptor type
  520. a.GetType("nunit.simple." + test, true, true);
  521. }
  522. }
  523. //Seems the --proto_path or -I option is non-functional for me. Maybe others have luck?
  524. [Test, Ignore("http://code.google.com/p/protobuf/issues/detail?id=40")]
  525. public void TestProtoFileInDifferentDirectory()
  526. {
  527. string test = new StackFrame(false).GetMethod().Name;
  528. Setup();
  529. using (TempFile source = TempFile.Attach(test + ".cs"))
  530. using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto))
  531. {
  532. Environment.CurrentDirectory = OriginalWorkingDirectory;
  533. RunProtoGen(0, proto.TempPath, "--proto_path=" + TempPath);
  534. Assembly a = RunCsc(0, source.TempPath);
  535. //assert that the message type is in the expected namespace
  536. Type t = a.GetType("nunit.simple.MyMessage", true, true);
  537. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t), "Expect an IMessage");
  538. //assert that we can find the static descriptor type
  539. a.GetType("nunit.simple." + test, true, true);
  540. }
  541. }
  542. // *******************************************************************
  543. // Handling of mutliple input files
  544. // *******************************************************************
  545. [Test]
  546. public void TestMultipleProtoFiles()
  547. {
  548. Setup();
  549. using (TempFile source1 = TempFile.Attach("MyMessage.cs"))
  550. using (
  551. ProtoFile proto1 = new ProtoFile("MyMessage.proto",
  552. @"
  553. package nunit.simple;
  554. // Test a very simple message.
  555. message MyMessage {
  556. optional string name = 1;
  557. }")
  558. )
  559. using (TempFile source2 = TempFile.Attach("MyMessageList.cs"))
  560. using (
  561. ProtoFile proto2 = new ProtoFile("MyMessageList.proto",
  562. @"
  563. package nunit.simple;
  564. import ""MyMessage.proto"";
  565. // Test a very simple message.
  566. message MyMessageList {
  567. repeated MyMessage messages = 1;
  568. }")
  569. )
  570. {
  571. RunProtoGen(0, proto1.TempPath, proto2.TempPath);
  572. Assembly a = RunCsc(0, source1.TempPath, source2.TempPath);
  573. //assert that the message type is in the expected namespace
  574. Type t1 = a.GetType("nunit.simple.MyMessage", true, true);
  575. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t1), "Expect an IMessage");
  576. //assert that the message type is in the expected namespace
  577. Type t2 = a.GetType("nunit.simple.MyMessageList", true, true);
  578. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t2), "Expect an IMessage");
  579. //assert that we can find the static descriptor type
  580. a.GetType("nunit.simple.Proto.MyMessage", true, true);
  581. a.GetType("nunit.simple.Proto.MyMessageList", true, true);
  582. }
  583. }
  584. [Test]
  585. public void TestOneProtoFileWithBufferFile()
  586. {
  587. Setup();
  588. using (TempFile source1 = TempFile.Attach("MyMessage.cs"))
  589. using (TempFile protobuf = TempFile.Attach("MyMessage.pb"))
  590. using (
  591. ProtoFile proto1 = new ProtoFile("MyMessage.proto",
  592. @"
  593. package nunit.simple;
  594. // Test a very simple message.
  595. message MyMessage {
  596. optional string name = 1;
  597. }")
  598. )
  599. using (TempFile source2 = TempFile.Attach("MyMessageList.cs"))
  600. using (
  601. ProtoFile proto2 = new ProtoFile("MyMessageList.proto",
  602. @"
  603. package nunit.simple;
  604. import ""MyMessage.proto"";
  605. // Test a very simple message.
  606. message MyMessageList {
  607. repeated MyMessage messages = 1;
  608. }")
  609. )
  610. {
  611. //build the proto buffer for MyMessage
  612. RunProtoGen(0, proto1.TempPath, "--descriptor_set_out=" + protobuf.TempPath);
  613. //build the MyMessageList proto-buffer and generate code by including MyMessage.pb
  614. RunProtoGen(0, proto2.TempPath, protobuf.TempPath);
  615. Assembly a = RunCsc(0, source1.TempPath, source2.TempPath);
  616. //assert that the message type is in the expected namespace
  617. Type t1 = a.GetType("nunit.simple.MyMessage", true, true);
  618. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t1), "Expect an IMessage");
  619. //assert that the message type is in the expected namespace
  620. Type t2 = a.GetType("nunit.simple.MyMessageList", true, true);
  621. Assert.IsTrue(typeof (IMessage).IsAssignableFrom(t2), "Expect an IMessage");
  622. //assert that we can find the static descriptor type
  623. a.GetType("nunit.simple.Proto.MyMessage", true, true);
  624. a.GetType("nunit.simple.Proto.MyMessageList", true, true);
  625. }
  626. }
  627. [Test]
  628. public void TestProtoFileWithService()
  629. {
  630. string test = new StackFrame(false).GetMethod().Name;
  631. Setup();
  632. using (TempFile source = TempFile.Attach(test + ".cs"))
  633. using (ProtoFile proto = new ProtoFile(test + ".proto",
  634. @"
  635. import ""google/protobuf/csharp_options.proto"";
  636. option (google.protobuf.csharp_file_options).service_generator_type = GENERIC;
  637. package nunit.simple;
  638. // Test a very simple message.
  639. message MyMessage {
  640. optional string name = 1;
  641. }
  642. // test a very simple service.
  643. service TestService {
  644. rpc Execute (MyMessage) returns (MyMessage);
  645. }"))
  646. {
  647. CopyInGoogleProtoFiles();
  648. RunProtoGen(0, proto.TempPath, "-ignore_google_protobuf:true", "-nest_classes=false");
  649. Assert.AreEqual(1, Directory.GetFiles(TempPath, "*.cs").Length);
  650. Assembly a = RunCsc(0, source.TempPath);
  651. //assert that the service type is in the expected namespace
  652. Type t1 = a.GetType("nunit.simple.TestService", true, true);
  653. Assert.IsTrue(typeof(IService).IsAssignableFrom(t1), "Expect an IService");
  654. Assert.IsTrue(t1.IsAbstract, "Expect abstract class");
  655. //assert that the Stub subclass type is in the expected namespace
  656. Type t2 = a.GetType("nunit.simple.TestService+Stub", true, true);
  657. Assert.IsTrue(t1.IsAssignableFrom(t2), "Expect a sub of TestService");
  658. Assert.IsFalse(t2.IsAbstract, "Expect concrete class");
  659. }
  660. }
  661. [Test]
  662. public void TestProtoFileWithServiceInternal()
  663. {
  664. string test = new StackFrame(false).GetMethod().Name;
  665. Setup();
  666. using (TempFile source = TempFile.Attach(test + ".cs"))
  667. using (ProtoFile proto = new ProtoFile(test + ".proto",
  668. @"
  669. import ""google/protobuf/csharp_options.proto"";
  670. option (google.protobuf.csharp_file_options).service_generator_type = GENERIC;
  671. package nunit.simple;
  672. // Test a very simple message.
  673. message MyMessage {
  674. optional string name = 1;
  675. }
  676. // test a very simple service.
  677. service TestService {
  678. rpc Execute (MyMessage) returns (MyMessage);
  679. }"))
  680. {
  681. CopyInGoogleProtoFiles();
  682. RunProtoGen(0, proto.TempPath, "-ignore_google_protobuf:true", "-nest_classes=false", "-public_classes=false");
  683. Assert.AreEqual(1, Directory.GetFiles(TempPath, "*.cs").Length);
  684. Assembly a = RunCsc(0, source.TempPath);
  685. //assert that the service type is in the expected namespace
  686. Type t1 = a.GetType("nunit.simple.TestService", true, true);
  687. Assert.IsTrue(typeof(IService).IsAssignableFrom(t1), "Expect an IService");
  688. Assert.IsTrue(t1.IsAbstract, "Expect abstract class");
  689. //assert that the Stub subclass type is in the expected namespace
  690. Type t2 = a.GetType("nunit.simple.TestService+Stub", true, true);
  691. Assert.IsTrue(t1.IsAssignableFrom(t2), "Expect a sub of TestService");
  692. Assert.IsFalse(t2.IsAbstract, "Expect concrete class");
  693. }
  694. }
  695. private static void CopyInGoogleProtoFiles()
  696. {
  697. string google = Path.Combine(TempPath, "google\\protobuf");
  698. Directory.CreateDirectory(google);
  699. foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf")))
  700. {
  701. File.Copy(file, Path.Combine(google, Path.GetFileName(file)));
  702. }
  703. }
  704. }
  705. }