#region Copyright notice and license // Copyright 2018 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #endregion using System.IO; using Microsoft.Build.Framework; using Moq; using NUnit.Framework; namespace Grpc.Tools.Tests { public class ProtoCompileCommandLineGeneratorTest : ProtoCompileBasicTest { [SetUp] public new void SetUp() { _task.Generator = "csharp"; _task.OutputDir = "outdir"; _task.ProtoBuf = Utils.MakeSimpleItems("a.proto"); } void ExecuteExpectSuccess() { _mockEngine .Setup(me => me.LogErrorEvent(It.IsAny())) .Callback((BuildErrorEventArgs e) => Assert.Fail($"Error logged by build engine:\n{e.Message}")); bool result = _task.Execute(); Assert.IsTrue(result); } [Test] public void MinimalCompile() { ExecuteExpectSuccess(); Assert.That(_task.LastPathToTool, Does.Match(@"protoc(.exe)?$")); Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { "--csharp_out=outdir", "a.proto" })); } [Test] public void CompileTwoFiles() { _task.ProtoBuf = Utils.MakeSimpleItems("a.proto", "foo/b.proto"); ExecuteExpectSuccess(); Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { "--csharp_out=outdir", "a.proto", "foo/b.proto" })); } [Test] public void CompileWithProtoPaths() { _task.ProtoPath = new[] { "/path1", "/path2" }; ExecuteExpectSuccess(); Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { "--csharp_out=outdir", "--proto_path=/path1", "--proto_path=/path2", "a.proto" })); } [TestCase("Cpp")] [TestCase("CSharp")] [TestCase("Java")] [TestCase("Javanano")] [TestCase("Js")] [TestCase("Objc")] [TestCase("Php")] [TestCase("Python")] [TestCase("Ruby")] public void CompileWithOptions(string gen) { _task.Generator = gen; _task.OutputOptions = new[] { "foo", "bar" }; ExecuteExpectSuccess(); gen = gen.ToLowerInvariant(); Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { $"--{gen}_out=outdir", $"--{gen}_opt=foo,bar", "a.proto" })); } [Test] public void OutputDependencyFile() { _task.DependencyOut = "foo/my.protodep"; // Task fails trying to read the non-generated file; we ignore that. _task.Execute(); Assert.That(_task.LastResponseFile, Does.Contain("--dependency_out=foo/my.protodep")); } [Test] public void OutputDependencyWithProtoDepDir() { _task.ProtoDepDir = "foo"; // Task fails trying to read the non-generated file; we ignore that. _task.Execute(); Assert.That(_task.LastResponseFile, Has.One.Match(@"^--dependency_out=foo[/\\].+_a.protodep$")); } [Test] public void GenerateGrpc() { _task.GrpcPluginExe = "/foo/grpcgen"; ExecuteExpectSuccess(); Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { "--csharp_out=outdir", "--grpc_out=outdir", "--plugin=protoc-gen-grpc=/foo/grpcgen" })); } [Test] public void GenerateGrpcWithOutDir() { _task.GrpcPluginExe = "/foo/grpcgen"; _task.GrpcOutputDir = "gen-out"; ExecuteExpectSuccess(); Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { "--csharp_out=outdir", "--grpc_out=gen-out" })); } [Test] public void GenerateGrpcWithOptions() { _task.GrpcPluginExe = "/foo/grpcgen"; _task.GrpcOutputOptions = new[] { "baz", "quux" }; ExecuteExpectSuccess(); Assert.That(_task.LastResponseFile, Does.Contain("--grpc_opt=baz,quux")); } [Test] public void DirectoryArgumentsSlashTrimmed() { _task.GrpcPluginExe = "/foo/grpcgen"; _task.GrpcOutputDir = "gen-out/"; _task.OutputDir = "outdir/"; _task.ProtoPath = new[] { "/path1/", "/path2/" }; ExecuteExpectSuccess(); Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { "--proto_path=/path1", "--proto_path=/path2", "--csharp_out=outdir", "--grpc_out=gen-out" })); } [TestCase(".", ".")] [TestCase("/", "/")] [TestCase("//", "/")] [TestCase("/foo/", "/foo")] [TestCase("/foo", "/foo")] [TestCase("foo/", "foo")] [TestCase("foo//", "foo")] [TestCase("foo/\\", "foo")] [TestCase("foo\\/", "foo")] [TestCase("C:\\foo", "C:\\foo")] [TestCase("C:", "C:")] [TestCase("C:\\", "C:\\")] [TestCase("C:\\\\", "C:\\")] public void DirectorySlashTrimmingCases(string given, string expect) { if (Path.DirectorySeparatorChar == '/') expect = expect.Replace('\\', '/'); _task.OutputDir = given; ExecuteExpectSuccess(); Assert.That(_task.LastResponseFile, Does.Contain("--csharp_out=" + expect)); } }; }