Add more Grpc.Tools integration tests (#32311)
Further Grpc.Tools tests
- TestCharactersInName - proto files with dots and numbers in their
names
- TestExtraOptions - test setting AdditionalProtocArguments,
OutputOptions and GrpcOutputOptions
- TestGrpcServices - test setting GrpcServices to "none", "client",
"server" and "both"
- TestSetOutputDirs - test setting OutputDir and GrpcOutputDir
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/Program.cs b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/Program.cs
new file mode 100644
index 0000000..15e3506
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/Program.cs
@@ -0,0 +1,30 @@
+#region Copyright notice and license
+
+// Copyright 2023 The 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;
+
+namespace TestApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("test app");
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/expected.json b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/expected.json
new file mode 100644
index 0000000..50dc354
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/expected.json
@@ -0,0 +1,55 @@
+{
+ "Files": {
+ "protos/hello.world.proto": {
+ "--csharp_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0/protos"
+ ],
+ "--plugin": [
+ "protoc-gen-grpc=dummy-plugin-not-used"
+ ],
+ "--grpc_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0/protos"
+ ],
+ "--proto_path": [
+ "../../../Grpc.Tools/build/native/include",
+ "."
+ ],
+ "--dependency_out": [
+ "REGEX:${TEST_OUT_DIR}/obj/Debug/netstandard2.0/.*_hello.world.protodep"
+ ],
+ "--error_format": [
+ "msvs"
+ ],
+ "protofile": [
+ "protos/hello.world.proto"
+ ]
+ },
+ "protos/m_double_2d.proto": {
+ "--csharp_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0/protos"
+ ],
+ "--plugin": [
+ "protoc-gen-grpc=dummy-plugin-not-used"
+ ],
+ "--grpc_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0/protos"
+ ],
+ "--proto_path": [
+ "../../../Grpc.Tools/build/native/include",
+ "."
+ ],
+ "--dependency_out": [
+ "REGEX:${TEST_OUT_DIR}/obj/Debug/netstandard2.0/.*_m_double_2d.protodep"
+ ],
+ "--error_format": [
+ "msvs"
+ ],
+ "protofile": [
+ "protos/m_double_2d.proto"
+ ]
+ }
+ },
+ "Metadata": {
+ "timestamp": "IGNORE:"
+ }
+}
\ No newline at end of file
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/msbuildtest.csproj b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/msbuildtest.csproj
new file mode 100644
index 0000000..4cb726a
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/msbuildtest.csproj
@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <!--
+ Note: common properties and targets for tests are imported from the
+ Directory.Build.props and Directory.Build.targets files in the parent directoty
+ -->
+
+ <!-- The protobuf compiler settings to test -->
+ <ItemGroup>
+ <Protobuf Include="**/*.proto" />
+ </ItemGroup>
+
+</Project>
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/protos/hello.world.proto b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/protos/hello.world.proto
new file mode 100644
index 0000000..104d370
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/protos/hello.world.proto
@@ -0,0 +1,35 @@
+// Copyright 2022 The 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.
+
+syntax = "proto3";
+
+package grpc_tools_tests.integration_tests.test_characters_in_name_dot;
+
+// The greeting service definition.
+service Greeter {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {}
+ rpc SayHelloSlowly (HelloRequest) returns (HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+ int32 delay = 2;
+}
+
+// The response message containing the greetings
+message HelloReply {
+ string message = 1;
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/protos/m_double_2d.proto b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/protos/m_double_2d.proto
new file mode 100644
index 0000000..e07d30c
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestCharactersInName/protos/m_double_2d.proto
@@ -0,0 +1,27 @@
+// Copyright 2023 The 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.
+
+syntax = "proto3";
+
+package grpc_tools_tests.integration_tests.test_characters_in_name_numbers;
+
+message MDouble2D
+{
+ double x = 1;
+ double y = 2;
+}
+
+service MyService {
+ rpc MyFunction (MDouble2D) returns (MDouble2D) {}
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/Program.cs b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/Program.cs
new file mode 100644
index 0000000..f1d9726
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/Program.cs
@@ -0,0 +1,30 @@
+#region Copyright notice and license
+
+// Copyright 2022 The 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;
+
+namespace TestApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("test app");
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/expected.json b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/expected.json
new file mode 100644
index 0000000..323368c
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/expected.json
@@ -0,0 +1,41 @@
+{
+ "Files": {
+ "file.proto": {
+ "--csharp_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--csharp_opt": [
+ "--outOpt1=foo,--outOpt2=bar"
+ ],
+ "--plugin": [
+ "protoc-gen-grpc=dummy-plugin-not-used",
+ "REGEX:protoc-gen-myplugin=.*myplugin.exe"
+ ],
+ "--grpc_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--grpc_opt": [
+ "--grpcOpt1=one,--grpcOpt2=two,--grpcOpt3=three"
+ ],
+ "--proto_path": [
+ "../../../Grpc.Tools/build/native/include",
+ "."
+ ],
+ "--dependency_out": [
+ "REGEX:${TEST_OUT_DIR}/obj/Debug/netstandard2.0/.*_file.protodep"
+ ],
+ "--error_format": [
+ "msvs"
+ ],
+ "--myplugin_out": [
+ "."
+ ],
+ "protofile": [
+ "file.proto"
+ ]
+ }
+ },
+ "Metadata": {
+ "timestamp": "IGNORE:"
+ }
+}
\ No newline at end of file
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/file.proto b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/file.proto
new file mode 100644
index 0000000..650ee04
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/file.proto
@@ -0,0 +1,35 @@
+// Copyright 202 The 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.
+
+syntax = "proto3";
+
+package grpc_tools_tests.integration_tests.test_extra_options;
+
+// The greeting service definition.
+service Greeter {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {}
+ rpc SayHelloSlowly (HelloRequest) returns (HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+ int32 delay = 2;
+}
+
+// The response message containing the greetings
+message HelloReply {
+ string message = 1;
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/msbuildtest.csproj b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/msbuildtest.csproj
new file mode 100644
index 0000000..7d3ac23
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestExtraOptions/msbuildtest.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <!--
+ Note: common properties and targets for tests are imported from the
+ Directory.Build.props and Directory.Build.targets files in the parent directoty
+ -->
+
+ <!-- The protobuf compiler settings to test -->
+ <!-- Test various optional options are passed to protoc and plugin -->
+ <ItemGroup>
+ <Protobuf Include="file.proto"
+ AdditionalProtocArguments="--plugin=protoc-gen-myplugin=D:\myplugin.exe;--myplugin_out=."
+ OutputOptions="--outOpt1=foo;--outOpt2=bar"
+ GrpcOutputOptions="--grpcOpt1=one;--grpcOpt2=two;--grpcOpt3=three"
+ />
+ </ItemGroup>
+
+</Project>
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/Program.cs b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/Program.cs
new file mode 100644
index 0000000..f1d9726
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/Program.cs
@@ -0,0 +1,30 @@
+#region Copyright notice and license
+
+// Copyright 2022 The 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;
+
+namespace TestApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("test app");
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/clientandserver.proto b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/clientandserver.proto
new file mode 100644
index 0000000..457d7cf
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/clientandserver.proto
@@ -0,0 +1,26 @@
+// Copyright 2023 The 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.
+
+syntax = "proto3";
+
+package grpc_tools_tests.integration_tests.test_grpc_services;
+
+import "messages.proto";
+
+// For testing client and server code generation.
+service ClientAndServer {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {}
+ rpc SayHelloSlowly (HelloRequest) returns (HelloReply) {}
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/clientonly.proto b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/clientonly.proto
new file mode 100644
index 0000000..b056805
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/clientonly.proto
@@ -0,0 +1,26 @@
+// Copyright 2023 The 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.
+
+syntax = "proto3";
+
+package grpc_tools_tests.integration_tests.test_grpc_services;
+
+import "messages.proto";
+
+// For testing client only code generation.
+service ClientOnly {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {}
+ rpc SayHelloSlowly (HelloRequest) returns (HelloReply) {}
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/expected.json b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/expected.json
new file mode 100644
index 0000000..25d2e0b
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/expected.json
@@ -0,0 +1,103 @@
+{
+ "Files": {
+ "messages.proto": {
+ "--csharp_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--proto_path": [
+ "../../../Grpc.Tools/build/native/include",
+ "."
+ ],
+ "--dependency_out": [
+ "REGEX:${TEST_OUT_DIR}/obj/Debug/netstandard2.0/.*_messages.protodep"
+ ],
+ "--error_format": [
+ "msvs"
+ ],
+ "protofile": [
+ "messages.proto"
+ ]
+ },
+ "serveronly.proto": {
+ "--csharp_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--plugin": [
+ "protoc-gen-grpc=dummy-plugin-not-used"
+ ],
+ "--grpc_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--grpc_opt": [
+ "no_client"
+ ],
+ "--proto_path": [
+ "../../../Grpc.Tools/build/native/include",
+ "."
+ ],
+ "--dependency_out": [
+ "REGEX:${TEST_OUT_DIR}/obj/Debug/netstandard2.0/.*_serveronly.protodep"
+ ],
+ "--error_format": [
+ "msvs"
+ ],
+ "protofile": [
+ "serveronly.proto"
+ ]
+ },
+ "clientonly.proto": {
+ "--csharp_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--plugin": [
+ "protoc-gen-grpc=dummy-plugin-not-used"
+ ],
+ "--grpc_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--grpc_opt": [
+ "no_server"
+ ],
+ "--proto_path": [
+ "../../../Grpc.Tools/build/native/include",
+ "."
+ ],
+ "--dependency_out": [
+ "REGEX:${TEST_OUT_DIR}/obj/Debug/netstandard2.0/.*_clientonly.protodep"
+ ],
+ "--error_format": [
+ "msvs"
+ ],
+ "protofile": [
+ "clientonly.proto"
+ ]
+ },
+ "clientandserver.proto": {
+ "--csharp_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--plugin": [
+ "protoc-gen-grpc=dummy-plugin-not-used"
+ ],
+ "--grpc_out": [
+ "${TEST_OUT_DIR}/obj/Debug/netstandard2.0"
+ ],
+ "--proto_path": [
+ "../../../Grpc.Tools/build/native/include",
+ "."
+ ],
+ "--dependency_out": [
+ "REGEX:${TEST_OUT_DIR}/obj/Debug/netstandard2.0/.*_clientandserver.protodep"
+ ],
+ "--error_format": [
+ "msvs"
+ ],
+ "protofile": [
+ "clientandserver.proto"
+ ]
+ }
+ },
+ "Metadata": {
+ "timestamp": "IGNORE:"
+ }
+}
\ No newline at end of file
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/messages.proto b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/messages.proto
new file mode 100644
index 0000000..a8f23f3
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/messages.proto
@@ -0,0 +1,30 @@
+// Copyright 2023 The 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.
+
+syntax = "proto3";
+
+package grpc_tools_tests.integration_tests.test_grpc_services;
+
+// No service defintions in this file
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+ int32 delay = 2;
+}
+
+// The response message containing the greetings
+message HelloReply {
+ string message = 1;
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/msbuildtest.csproj b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/msbuildtest.csproj
new file mode 100644
index 0000000..370e5e8
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/msbuildtest.csproj
@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <!--
+ Note: common properties and targets for tests are imported from the
+ Directory.Build.props and Directory.Build.targets files in the parent directoty
+ -->
+
+ <!-- The protobuf compiler settings to test -->
+ <ItemGroup>
+ <Protobuf Include="messages.proto" GrpcServices="none" />
+ <Protobuf Include="serveronly.proto" GrpcServices="server" />
+ <Protobuf Include="clientonly.proto" GrpcServices="client" />
+ <Protobuf Include="clientandserver.proto" GrpcServices="both" />
+ </ItemGroup>
+
+</Project>
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/serveronly.proto b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/serveronly.proto
new file mode 100644
index 0000000..d7ada7d
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestGrpcServicesMetadata/serveronly.proto
@@ -0,0 +1,26 @@
+// Copyright 2023 The 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.
+
+syntax = "proto3";
+
+package grpc_tools_tests.integration_tests.test_grpc_services;
+
+import "messages.proto";
+
+// For testing server only code generation.
+service ServerOnly {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {}
+ rpc SayHelloSlowly (HelloRequest) returns (HelloReply) {}
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/Program.cs b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/Program.cs
new file mode 100644
index 0000000..f1d9726
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/Program.cs
@@ -0,0 +1,30 @@
+#region Copyright notice and license
+
+// Copyright 2022 The 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;
+
+namespace TestApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("test app");
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/expected.json b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/expected.json
new file mode 100644
index 0000000..b732a6a
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/expected.json
@@ -0,0 +1,31 @@
+{
+ "Files": {
+ "file.proto": {
+ "--csharp_out": [
+ "${TEST_OUT_DIR}/myOutput"
+ ],
+ "--plugin": [
+ "protoc-gen-grpc=dummy-plugin-not-used"
+ ],
+ "--grpc_out": [
+ "${TEST_OUT_DIR}/myGrpcOutput"
+ ],
+ "--proto_path": [
+ "../../../Grpc.Tools/build/native/include",
+ "."
+ ],
+ "--dependency_out": [
+ "REGEX:${TEST_OUT_DIR}/obj/Debug/netstandard2.0/.*_file.protodep"
+ ],
+ "--error_format": [
+ "msvs"
+ ],
+ "protofile": [
+ "file.proto"
+ ]
+ }
+ },
+ "Metadata": {
+ "timestamp": "IGNORE:"
+ }
+}
\ No newline at end of file
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/file.proto b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/file.proto
new file mode 100644
index 0000000..4d4cfa2
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/file.proto
@@ -0,0 +1,35 @@
+// Copyright 2023 The 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.
+
+syntax = "proto3";
+
+package grpc_tools_tests.integration_tests.test_set_output_dirs;
+
+// The greeting service definition.
+service Greeter {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply) {}
+ rpc SayHelloSlowly (HelloRequest) returns (HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+ int32 delay = 2;
+}
+
+// The response message containing the greetings
+message HelloReply {
+ string message = 1;
+}
diff --git a/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/msbuildtest.csproj b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/msbuildtest.csproj
new file mode 100644
index 0000000..c1fdebc
--- /dev/null
+++ b/src/csharp/Grpc.Tools.Tests/IntegrationTests/TestSetOutputDirs/msbuildtest.csproj
@@ -0,0 +1,15 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <!--
+ Note: common properties and targets for tests are imported from the
+ Directory.Build.props and Directory.Build.targets files in the parent directoty
+ -->
+
+ <!-- The protobuf compiler settings to test -->
+ <ItemGroup>
+ <Protobuf Include="**/*.proto"
+ OutputDir="$(TestOutDir)\myOutput"
+ GrpcOutputDir="$(TestOutDir)\myGrpcOutput" />
+ </ItemGroup>
+
+</Project>
diff --git a/src/csharp/Grpc.Tools.Tests/MsBuildIntegrationTest.cs b/src/csharp/Grpc.Tools.Tests/MsBuildIntegrationTest.cs
index bca480e..465a2a9 100644
--- a/src/csharp/Grpc.Tools.Tests/MsBuildIntegrationTest.cs
+++ b/src/csharp/Grpc.Tools.Tests/MsBuildIntegrationTest.cs
@@ -126,6 +126,61 @@
TryRunMsBuild("TestProtoOutsideProject/project", expectedFiles.ToString());
}
+ [Test]
+ public void TestCharactersInName()
+ {
+ // see https://github.com/grpc/grpc/issues/17661 - dot in name
+ // and https://github.com/grpc/grpc/issues/18698 - numbers in name
+ SetUpForTest(nameof(TestCharactersInName));
+
+ var expectedFiles = new ExpectedFilesBuilder();
+ expectedFiles.Add("protos/hello.world.proto", "HelloWorld.cs", "Hello.worldGrpc.cs");
+ expectedFiles.Add("protos/m_double_2d.proto", "MDouble2D.cs", "MDouble2dGrpc.cs");
+
+ TryRunMsBuild("TestCharactersInName", expectedFiles.ToString());
+ }
+
+ [Test]
+ public void TestExtraOptions()
+ {
+ // Test various extra options passed to protoc and plugin
+ // See https://github.com/grpc/grpc/issues/25950
+ // Tests setting AdditionalProtocArguments, OutputOptions and GrpcOutputOptions
+ SetUpForTest(nameof(TestExtraOptions));
+
+ var expectedFiles = new ExpectedFilesBuilder();
+ expectedFiles.Add("file.proto", "File.cs", "FileGrpc.cs");
+
+ TryRunMsBuild("TestExtraOptions", expectedFiles.ToString());
+ }
+
+ [Test]
+ public void TestGrpcServicesMetadata()
+ {
+ // Test different values for GrpcServices item metadata
+ SetUpForTest(nameof(TestGrpcServicesMetadata));
+
+ var expectedFiles = new ExpectedFilesBuilder();
+ expectedFiles.Add("messages.proto", "Messages.cs");
+ expectedFiles.Add("serveronly.proto", "Serveronly.cs", "ServeronlyGrpc.cs");
+ expectedFiles.Add("clientonly.proto", "Clientonly.cs", "ClientonlyGrpc.cs");
+ expectedFiles.Add("clientandserver.proto", "Clientandserver.cs", "ClientandserverGrpc.cs");
+
+ TryRunMsBuild("TestGrpcServicesMetadata", expectedFiles.ToString());
+ }
+
+ [Test]
+ public void TestSetOutputDirs()
+ {
+ // Test setting different GrpcOutputDir and OutputDir
+ SetUpForTest(nameof(TestSetOutputDirs));
+
+ var expectedFiles = new ExpectedFilesBuilder();
+ expectedFiles.Add("file.proto", "File.cs", "FileGrpc.cs");
+
+ TryRunMsBuild("TestSetOutputDirs", expectedFiles.ToString());
+ }
+
/// <summary>
/// Set up common paths for all the tests
/// </summary>
diff --git a/src/csharp/Grpc.Tools.Tests/scripts/fakeprotoc.py b/src/csharp/Grpc.Tools.Tests/scripts/fakeprotoc.py
index 78c42d3..29fb9f0 100755
--- a/src/csharp/Grpc.Tools.Tests/scripts/fakeprotoc.py
+++ b/src/csharp/Grpc.Tools.Tests/scripts/fakeprotoc.py
@@ -220,7 +220,15 @@
return cs_files_to_generate
-def _generate_cs_files(protofile, cs_files_to_generate, out_dir, projectdir):
+def _is_grpc_out_file(csfile):
+ """Return true if the file is one that would be generated by gRPC plugin"""
+ # This is using the heuristics of checking that the name of the file
+ # matches *Grpc.cs which is the name that the gRPC plugin would produce.
+ return csfile.endswith("Grpc.cs")
+
+
+def _generate_cs_files(protofile, cs_files_to_generate, grpc_out_dir,
+ csharp_out_dir, projectdir):
"""Create expected cs files."""
_write_debug("\ngenerate_cs_files")
@@ -228,24 +236,34 @@
_write_debug("No .cs files matching proto file name %s" % protofile)
return
- if not os.path.isabs(out_dir):
+ if not os.path.isabs(grpc_out_dir):
# if not absolute, it is relative to project directory
- out_dir = os.path.abspath("%s/%s" % (projectdir, out_dir))
+ grpc_out_dir = os.path.abspath("%s/%s" % (projectdir, grpc_out_dir))
- # Ensure out_dir exists
- if not os.path.isdir(out_dir):
- os.makedirs(out_dir)
+ if not os.path.isabs(csharp_out_dir):
+ # if not absolute, it is relative to project directory
+ csharp_out_dir = os.path.abspath("%s/%s" % (projectdir, csharp_out_dir))
+
+ # Ensure directories exist
+ if not os.path.isdir(grpc_out_dir):
+ os.makedirs(grpc_out_dir)
+
+ if not os.path.isdir(csharp_out_dir):
+ os.makedirs(csharp_out_dir)
timestamp = str(datetime.datetime.now())
for csfile in cs_files_to_generate:
- csfile_fullpath = "%s/%s" % (out_dir, csfile)
+ if csfile.endswith("Grpc.cs"):
+ csfile_fullpath = "%s/%s" % (grpc_out_dir, csfile)
+ else:
+ csfile_fullpath = "%s/%s" % (csharp_out_dir, csfile)
_write_debug("Creating: %s" % csfile_fullpath)
with open(csfile_fullpath, "w") as fout:
print("// Generated by fake protoc: %s" % timestamp, file=fout)
def _create_dependency_file(protofile, cs_files_to_generate, dependencyfile,
- grpcout):
+ grpc_out_dir, csharp_out_dir):
"""Create the expected dependency file."""
_write_debug("\ncreate_dependency_file")
@@ -261,7 +279,11 @@
with open(dependencyfile, "w") as out:
nfiles = len(cs_files_to_generate)
for i in range(0, nfiles):
- cs_filename = os.path.join(grpcout, cs_files_to_generate[i])
+ csfile = cs_files_to_generate[i]
+ if csfile.endswith("Grpc.cs"):
+ cs_filename = os.path.join(grpc_out_dir, csfile)
+ else:
+ cs_filename = os.path.join(csharp_out_dir, csfile)
if i == nfiles - 1:
print("%s: %s" % (cs_filename, protofile), file=out)
else:
@@ -278,6 +300,15 @@
return value
+def _get_argument_last_occurrence_or_none(protoc_arg_dict, name):
+ # If argument was passed multiple times, take the last occurrence.
+ # If the value does not exist then return None
+ values = protoc_arg_dict.get(name)
+ if values is not None:
+ return values[-1]
+ return None
+
+
def main():
# Check environment variables for the additional arguments used in the tests.
@@ -317,8 +348,16 @@
# If argument was passed multiple times, take the last occurrence of it.
# TODO(jtattermusch): handle multiple occurrences of the same argument
- dependencyfile = protoc_arg_dict.get('--dependency_out')[-1]
- grpcout = protoc_arg_dict.get('--grpc_out')[-1]
+ dependencyfile = _get_argument_last_occurrence_or_none(
+ protoc_arg_dict, '--dependency_out')
+ grpcout = _get_argument_last_occurrence_or_none(protoc_arg_dict,
+ '--grpc_out')
+ csharpout = _get_argument_last_occurrence_or_none(protoc_arg_dict,
+ '--csharp_out')
+
+ # --grpc_out might not be set in which case use --csharp_out
+ if grpcout is None:
+ grpcout = csharpout
if len(protoc_arg_dict.get('protofile')) != 1:
# regular protoc can process multiple .proto files passed at once, but we know
@@ -335,11 +374,13 @@
_create_dependency_file(protofile=protofile,
cs_files_to_generate=cs_files_to_generate,
dependencyfile=dependencyfile,
- grpcout=grpcout)
+ grpc_out_dir=grpcout,
+ csharp_out_dir=csharpout)
_generate_cs_files(protofile=protofile,
cs_files_to_generate=cs_files_to_generate,
- out_dir=grpcout,
+ grpc_out_dir=grpcout,
+ csharp_out_dir=csharpout,
projectdir=projectdir)
_write_or_update_results_json(log_dir=log_dir,