#region Copyright notice and license // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // http://github.com/jskeet/dotnet-protobufs/ // Original C++/Java/Python code: // http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using NUnit.Framework; namespace Google.ProtocolBuffers.ProtoGen { [TestFixture] [Category("Preprocessor")] public partial class TestPreprocessing { private static readonly string TempPath = Path.Combine(Path.GetTempPath(), "proto-gen-test"); private const string DefaultProto = @" package nunit.simple; // Test a very simple message. message MyMessage { optional string name = 1; }"; #region TestFixture SetUp/TearDown private static readonly string OriginalWorkingDirectory = Environment.CurrentDirectory; [TestFixtureSetUp] public virtual void Setup() { Teardown(); Directory.CreateDirectory(TempPath); Environment.CurrentDirectory = TempPath; } [TestFixtureTearDown] public virtual void Teardown() { Environment.CurrentDirectory = OriginalWorkingDirectory; if (Directory.Exists(TempPath)) { Directory.Delete(TempPath, true); } } #endregion #region Helper Methods RunProtoGen / RunCsc private void RunProtoGen(int expect, params string[] args) { TextWriter tout = Console.Out, terr = Console.Error; StringWriter temp = new StringWriter(); Console.SetOut(temp); Console.SetError(temp); try { Assert.AreEqual(expect, ProgramPreprocess.Run(args), "ProtoGen Failed: {0}", temp); } finally { Console.SetOut(tout); Console.SetError(terr); } } private Assembly RunCsc(int expect, params string[] sources) { using (TempFile tempDll = new TempFile(String.Empty)) { tempDll.ChangeExtension(".dll"); List args = new List(); args.Add("/nologo"); args.Add("/target:library"); args.Add("/debug-"); args.Add(String.Format(@"""/out:{0}""", tempDll.TempPath)); args.Add("/r:System.dll"); args.Add(String.Format(@"""/r:{0}""", typeof(Google.ProtocolBuffers.DescriptorProtos.DescriptorProto).Assembly. Location)); args.AddRange(sources); string exe = Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "csc.exe"); ProcessStartInfo psi = new ProcessStartInfo(exe); psi.CreateNoWindow = true; psi.UseShellExecute = false; psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; psi.Arguments = string.Join(" ", args.ToArray()); Process p = Process.Start(psi); p.WaitForExit(); string errorText = p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd(); Assert.AreEqual(expect, p.ExitCode, "CSC.exe Failed: {0}", errorText); Assembly asm = null; if (p.ExitCode == 0) { byte[] allbytes = File.ReadAllBytes(tempDll.TempPath); asm = Assembly.Load(allbytes); foreach (Type t in asm.GetTypes()) { Debug.WriteLine(t.FullName, asm.FullName); } } return asm; } } #endregion // ******************************************************************* // The following tests excercise options for protogen.exe // ******************************************************************* [Test] public void TestProtoFile() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(0, proto.TempPath); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple." + test, true, true); } } [Test] public void TestProtoFileWithConflictingType() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using ( ProtoFile proto = new ProtoFile(test + ".proto", @" package nunit.simple; // Test a very simple message. message " + test + @" { optional string name = 1; } ")) { RunProtoGen(0, proto.TempPath); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple." + test, true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple.Proto." + test, true, true); } } [Test] public void TestProtoFileWithNamespace() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(0, proto.TempPath, "-namespace:MyNewNamespace"); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("MyNewNamespace.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("MyNewNamespace." + test, true, true); } } [Test] public void TestProtoFileWithUmbrellaClassName() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach("MyUmbrellaClassname.cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(0, proto.TempPath, "/umbrella_classname=MyUmbrellaClassname"); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple.MyUmbrellaClassname", true, true); } } [Test] public void TestProtoFileWithNestedClass() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(0, proto.TempPath, "-nest_classes:true"); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple." + test + "+MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple." + test, true, true); } } [Test] public void TestProtoFileWithExpandedNsDirectories() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(@"nunit\simple\" + test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(0, proto.TempPath, "-expand_namespace_directories:true"); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple." + test, true, true); } } [Test] public void TestProtoFileWithNewExtension() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".Generated.cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(0, proto.TempPath, "-file_extension:.Generated.cs"); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple." + test, true, true); } } [Test] public void TestProtoFileWithUmbrellaNamespace() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(0, proto.TempPath, "-umbrella_namespace:MyUmbrella.Namespace"); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple.MyUmbrella.Namespace." + test, true, true); } } [Test] public void TestProtoFileWithIgnoredUmbrellaNamespaceDueToNesting() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(0, proto.TempPath, "-nest_classes:true", "-umbrella_namespace:MyUmbrella.Namespace"); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple." + test + "+MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple." + test, true, true); } } [Test] public void TestProtoFileWithExplicitEmptyUmbrellaNamespace() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using ( ProtoFile proto = new ProtoFile(test + ".proto", @" package nunit.simple; // Test a very simple message. message " + test + @" { optional string name = 1; } ")) { //Forces the umbrella class to not use a namespace even if a collision with a type is detected. RunProtoGen(0, proto.TempPath, "-umbrella_namespace:"); //error CS0441: 'nunit.simple.TestProtoFileWithExplicitEmptyUmbrellaNamespace': a class cannot be both static and sealed RunCsc(1, source.TempPath); } } [Test] public void TestProtoFileWithNewOutputFolder() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(@"generated-code\" + test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { RunProtoGen(1, proto.TempPath, "-output_directory:generated-code"); Directory.CreateDirectory("generated-code"); RunProtoGen(0, proto.TempPath, "-output_directory:generated-code"); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple." + test, true, true); } } [Test] public void TestProtoFileAndIgnoreGoogleProtobuf() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using ( ProtoFile proto = new ProtoFile(test + ".proto", @" import ""google/protobuf/csharp_options.proto""; option (google.protobuf.csharp_file_options).namespace = ""MyNewNamespace""; " + DefaultProto)) { string google = Path.Combine(TempPath, "google\\protobuf"); Directory.CreateDirectory(google); foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf"))) { File.Copy(file, Path.Combine(google, Path.GetFileName(file))); } Assert.AreEqual(0, Directory.GetFiles(TempPath, "*.cs").Length); RunProtoGen(0, proto.TempPath, "-ignore_google_protobuf:true"); Assert.AreEqual(1, Directory.GetFiles(TempPath, "*.cs").Length); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("MyNewNamespace.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("MyNewNamespace." + test, true, true); } } [Test] public void TestProtoFileWithoutIgnoreGoogleProtobuf() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using ( ProtoFile proto = new ProtoFile(test + ".proto", @" import ""google/protobuf/csharp_options.proto""; option (google.protobuf.csharp_file_options).namespace = ""MyNewNamespace""; " + DefaultProto)) { string google = Path.Combine(TempPath, "google\\protobuf"); Directory.CreateDirectory(google); foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf"))) { File.Copy(file, Path.Combine(google, Path.GetFileName(file))); } Assert.AreEqual(0, Directory.GetFiles(TempPath, "*.cs").Length); //Without the option this fails due to being unable to resolve google/protobuf descriptors RunProtoGen(1, proto.TempPath, "-ignore_google_protobuf:false"); } } // ******************************************************************* // The following tests excercise options for protoc.exe // ******************************************************************* [Test] public void TestProtoFileWithIncludeImports() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using ( ProtoFile proto = new ProtoFile(test + ".proto", @" import ""google/protobuf/csharp_options.proto""; option (google.protobuf.csharp_file_options).namespace = ""MyNewNamespace""; package nunit.simple; // Test a very simple message. message MyMessage { optional string name = 1; } ") ) { string google = Path.Combine(TempPath, "google\\protobuf"); Directory.CreateDirectory(google); foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf"))) { File.Copy(file, Path.Combine(google, Path.GetFileName(file))); } Assert.AreEqual(0, Directory.GetFiles(TempPath, "*.cs").Length); //if you specify the protoc option --include_imports this should build three source files RunProtoGen(0, proto.TempPath, "--include_imports"); Assert.AreEqual(3, Directory.GetFiles(TempPath, "*.cs").Length); //you can (and should) simply omit the inclusion of the extra source files in your project Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("MyNewNamespace.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("MyNewNamespace." + test, true, true); } } [Test] public void TestProtoFileWithIncludeImportsAndIgnoreGoogleProtobuf() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using ( ProtoFile proto = new ProtoFile(test + ".proto", @" import ""google/protobuf/csharp_options.proto""; option (google.protobuf.csharp_file_options).namespace = ""MyNewNamespace""; package nunit.simple; // Test a very simple message. message MyMessage { optional string name = 1; } ") ) { string google = Path.Combine(TempPath, "google\\protobuf"); Directory.CreateDirectory(google); foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf"))) File.Copy(file, Path.Combine(google, Path.GetFileName(file))); Assert.AreEqual(0, Directory.GetFiles(TempPath, "*.cs").Length); //Even with --include_imports, if you provide -ignore_google_protobuf:true you only get the one source file RunProtoGen(0, proto.TempPath, "-ignore_google_protobuf:true", "--include_imports"); Assert.AreEqual(1, Directory.GetFiles(TempPath, "*.cs").Length); //you can (and should) simply omit the inclusion of the extra source files in your project Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("MyNewNamespace.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("MyNewNamespace." + test, true, true); } } [Test] public void TestProtoFileKeepingTheProtoBuffer() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile protobuf = TempFile.Attach(test + ".pb")) using (TempFile source = TempFile.Attach(test + ".cs")) using ( ProtoFile proto = new ProtoFile(test + ".proto", @" package nunit.simple; // Test a very simple message. message MyMessage { optional string name = 1; } ") ) { RunProtoGen(0, proto.TempPath, "--descriptor_set_out=" + protobuf.TempPath); Assert.IsTrue(File.Exists(protobuf.TempPath), "Missing: " + protobuf.TempPath); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple." + test, true, true); } } //Seems the --proto_path or -I option is non-functional for me. Maybe others have luck? [Test] public void TestProtoFileInDifferentDirectory() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", DefaultProto)) { Environment.CurrentDirectory = OriginalWorkingDirectory; RunProtoGen(0, proto.TempPath, "--proto_path=" + TempPath); Assembly a = RunCsc(0, source.TempPath); //assert that the message type is in the expected namespace Type t = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple." + test, true, true); } } // ******************************************************************* // Handling of mutliple input files // ******************************************************************* [Test] public void TestMultipleProtoFiles() { Setup(); using (TempFile source1 = TempFile.Attach("MyMessage.cs")) using ( ProtoFile proto1 = new ProtoFile("MyMessage.proto", @" package nunit.simple; // Test a very simple message. message MyMessage { optional string name = 1; }") ) using (TempFile source2 = TempFile.Attach("MyMessageList.cs")) using ( ProtoFile proto2 = new ProtoFile("MyMessageList.proto", @" package nunit.simple; import ""MyMessage.proto""; // Test a very simple message. message MyMessageList { repeated MyMessage messages = 1; }") ) { RunProtoGen(0, proto1.TempPath, proto2.TempPath); Assembly a = RunCsc(0, source1.TempPath, source2.TempPath); //assert that the message type is in the expected namespace Type t1 = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t1), "Expect an IMessage"); //assert that the message type is in the expected namespace Type t2 = a.GetType("nunit.simple.MyMessageList", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t2), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple.Proto.MyMessage", true, true); a.GetType("nunit.simple.Proto.MyMessageList", true, true); } } [Test] public void TestOneProtoFileWithBufferFile() { Setup(); using (TempFile source1 = TempFile.Attach("MyMessage.cs")) using (TempFile protobuf = TempFile.Attach("MyMessage.pb")) using ( ProtoFile proto1 = new ProtoFile("MyMessage.proto", @" package nunit.simple; // Test a very simple message. message MyMessage { optional string name = 1; }") ) using (TempFile source2 = TempFile.Attach("MyMessageList.cs")) using ( ProtoFile proto2 = new ProtoFile("MyMessageList.proto", @" package nunit.simple; import ""MyMessage.proto""; // Test a very simple message. message MyMessageList { repeated MyMessage messages = 1; }") ) { //build the proto buffer for MyMessage RunProtoGen(0, proto1.TempPath, "--descriptor_set_out=" + protobuf.TempPath); //build the MyMessageList proto-buffer and generate code by including MyMessage.pb RunProtoGen(0, proto2.TempPath, protobuf.TempPath); Assembly a = RunCsc(0, source1.TempPath, source2.TempPath); //assert that the message type is in the expected namespace Type t1 = a.GetType("nunit.simple.MyMessage", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t1), "Expect an IMessage"); //assert that the message type is in the expected namespace Type t2 = a.GetType("nunit.simple.MyMessageList", true, true); Assert.IsTrue(typeof(IMessage).IsAssignableFrom(t2), "Expect an IMessage"); //assert that we can find the static descriptor type a.GetType("nunit.simple.Proto.MyMessage", true, true); a.GetType("nunit.simple.Proto.MyMessageList", true, true); } } [Test] public void TestProtoFileWithService() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", @" import ""google/protobuf/csharp_options.proto""; option (google.protobuf.csharp_file_options).service_generator_type = GENERIC; package nunit.simple; // Test a very simple message. message MyMessage { optional string name = 1; } // test a very simple service. service TestService { rpc Execute (MyMessage) returns (MyMessage); }")) { CopyInGoogleProtoFiles(); RunProtoGen(0, proto.TempPath, "-ignore_google_protobuf:true", "-nest_classes=false"); Assert.AreEqual(1, Directory.GetFiles(TempPath, "*.cs").Length); Assembly a = RunCsc(0, source.TempPath); //assert that the service type is in the expected namespace Type t1 = a.GetType("nunit.simple.TestService", true, true); Assert.IsTrue(typeof(IService).IsAssignableFrom(t1), "Expect an IService"); Assert.IsTrue(t1.IsAbstract, "Expect abstract class"); //assert that the Stub subclass type is in the expected namespace Type t2 = a.GetType("nunit.simple.TestService+Stub", true, true); Assert.IsTrue(t1.IsAssignableFrom(t2), "Expect a sub of TestService"); Assert.IsFalse(t2.IsAbstract, "Expect concrete class"); } } [Test] public void TestProtoFileWithServiceInternal() { string test = new StackFrame(false).GetMethod().Name; Setup(); using (TempFile source = TempFile.Attach(test + ".cs")) using (ProtoFile proto = new ProtoFile(test + ".proto", @" import ""google/protobuf/csharp_options.proto""; option (google.protobuf.csharp_file_options).service_generator_type = GENERIC; package nunit.simple; // Test a very simple message. message MyMessage { optional string name = 1; } // test a very simple service. service TestService { rpc Execute (MyMessage) returns (MyMessage); }")) { CopyInGoogleProtoFiles(); RunProtoGen(0, proto.TempPath, "-ignore_google_protobuf:true", "-nest_classes=false", "-public_classes=false"); Assert.AreEqual(1, Directory.GetFiles(TempPath, "*.cs").Length); Assembly a = RunCsc(0, source.TempPath); //assert that the service type is in the expected namespace Type t1 = a.GetType("nunit.simple.TestService", true, true); Assert.IsTrue(typeof(IService).IsAssignableFrom(t1), "Expect an IService"); Assert.IsTrue(t1.IsAbstract, "Expect abstract class"); //assert that the Stub subclass type is in the expected namespace Type t2 = a.GetType("nunit.simple.TestService+Stub", true, true); Assert.IsTrue(t1.IsAssignableFrom(t2), "Expect a sub of TestService"); Assert.IsFalse(t2.IsAbstract, "Expect concrete class"); } } private static void CopyInGoogleProtoFiles() { string google = Path.Combine(TempPath, "google\\protobuf"); Directory.CreateDirectory(google); foreach (string file in Directory.GetFiles(Path.Combine(OriginalWorkingDirectory, "google\\protobuf"))) { File.Copy(file, Path.Combine(google, Path.GetFileName(file))); } } } }