-
Notifications
You must be signed in to change notification settings - Fork 321
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[c# grpc] Allow [Bond.Attribute] on methods
* This fixes broken C# codegen when a service method has attributes. * Add both C++ and C# unit test to make sure that service and method attributes are properly generated and accessible. Fixes #617
- Loading branch information
Showing
13 changed files
with
266 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
#include "services_grpc.h" | ||
|
||
#include <boost/test/unit_test.hpp> | ||
|
||
#include <algorithm> | ||
#include <iterator> | ||
#include <map> | ||
#include <string> | ||
|
||
using unit_test::SimpleService; | ||
|
||
static bool AttributeMapsEqual( | ||
const std::map<std::string, std::string>& lhs, | ||
const std::map<std::string, std::string>& rhs) | ||
{ | ||
return lhs.size() == rhs.size() | ||
&& std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); | ||
} | ||
|
||
BOOST_AUTO_TEST_SUITE(ServiceAttributesTests) | ||
|
||
BOOST_AUTO_TEST_CASE(AttributesOnService_CanBeFound) | ||
{ | ||
static const std::map<std::string, std::string> expected | ||
{ | ||
{ "SomeAttribute", "service value" } | ||
}; | ||
|
||
BOOST_CHECK( | ||
AttributeMapsEqual( | ||
expected, | ||
SimpleService::Schema::metadata.attributes)); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE_TEMPLATE( | ||
AttributesOnMethods_CanBeFound, | ||
Method, | ||
SimpleService::Schema::methods) | ||
{ | ||
static const std::map<std::string, std::map<std::string, std::string>> expectedPerMethod | ||
{ | ||
{ | ||
"IntToInt", | ||
{ | ||
{ "SomeAttribute", "method value" }, | ||
{ "DifferentAttribute", "" } | ||
} | ||
}, | ||
{ | ||
"NothingToInt", | ||
{ | ||
{"NothingToInt", "no clash"} | ||
} | ||
}, | ||
{ "IntToNothing", { } }, | ||
{"NothingToNothing", { } } | ||
}; | ||
|
||
const auto expected = expectedPerMethod.find(Method::metadata.name); | ||
BOOST_CHECK(expected != std::end(expectedPerMethod)); | ||
BOOST_CHECK(AttributeMapsEqual(expected->second, Method::metadata.attributes)); | ||
} | ||
|
||
BOOST_AUTO_TEST_SUITE_END() | ||
|
||
bool init_unit_test() | ||
{ | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import "bond/core/bond.bond" | ||
|
||
namespace unit_test; | ||
|
||
[SomeAttribute("service value")] | ||
service SimpleService | ||
{ | ||
[SomeAttribute("method value")] | ||
[DifferentAttribute("")] // empty string, but present | ||
bond.Box<int32> IntToInt(bond.Box<int32>); | ||
|
||
[NothingToInt("no clash")] | ||
bond.Box<int32> NothingToInt(); | ||
|
||
nothing IntToNothing(bond.Box<int32>); | ||
|
||
nothing NothingToNothing(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/gen/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="12.0" DefaultTargets="BondCodegenCs" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<Import Project="$(MSBuildExtensionsPath32)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath32)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | ||
<Import Project="$(MSBuildThisFileDirectory)\..\..\..\build\nuget\Common.props" /> | ||
<PropertyGroup> | ||
<BOND_INCLUDE_PATH>..\..\..\..\idl</BOND_INCLUDE_PATH> | ||
<BondOutputDirectory>gen\</BondOutputDirectory> | ||
<BondOptions>--grpc</BondOptions> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<BondCodegen Include="..\..\..\test\grpc\services.bond" /> | ||
</ItemGroup> | ||
<Import Project="$(MSBuildThisFileDirectory)\..\..\..\build\nuget\Common.targets" /> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace UnitTest.Grpc | ||
{ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using NUnit.Framework; | ||
using NUnit.Framework.Constraints; | ||
|
||
[TestFixture] | ||
class AttributesTests | ||
{ | ||
private static Dictionary<string, Dictionary<string, string>> ExpectedMethodAttributes = new Dictionary | ||
<string, Dictionary<string, string>> | ||
{ | ||
{ | ||
"IntToInt", | ||
new Dictionary<string, string> | ||
{ | ||
{"SomeAttribute", "method value"}, | ||
{ | ||
"DifferentAttribute", string.Empty | ||
} | ||
} | ||
}, | ||
{ | ||
"NothingToInt", | ||
new Dictionary<string, string> | ||
{ | ||
{"NothingToInt", "no clash"} | ||
} | ||
}, | ||
{"IntToNothing", new Dictionary<string, string>()}, | ||
{"NothingToNothing", new Dictionary<string, string>()} | ||
}; | ||
|
||
[Test] | ||
public void ServiceAttributes_CanBeFound() | ||
{ | ||
var serviceTypeInfo = typeof(SimpleService).GetTypeInfo(); | ||
var bondAttributes = | ||
serviceTypeInfo.GetCustomAttributes<Bond.AttributeAttribute>() | ||
.ToDictionary(ba => ba.Name, ba => ba.Value); | ||
|
||
CollectionAssert.AreEquivalent( | ||
new Dictionary<string, string> {{"SomeAttribute", "service value"}}, | ||
bondAttributes); | ||
} | ||
|
||
[Test] | ||
public void MethodAttributes_OnServiceBase_CanBeFound() | ||
{ | ||
var serviceBaseTypeInfo = typeof(SimpleService.SimpleServiceBase).GetTypeInfo(); | ||
var methodAttributes = serviceBaseTypeInfo.DeclaredMethods.Where(mi => mi.IsPublic && mi.IsAbstract) | ||
.ToDictionary(mi => mi.Name, CollectMethodAttributes); | ||
|
||
CollectionAssert.AreEquivalent(ExpectedMethodAttributes, methodAttributes); | ||
} | ||
|
||
[Test] | ||
public void MethodAttributes_OnClient_CanBeFound() | ||
{ | ||
var clientTypeInfo = typeof(SimpleService.SimpleServiceClient).GetTypeInfo(); | ||
var clientMethods = clientTypeInfo.DeclaredMethods.Where(mi => mi.IsPublic && mi.IsVirtual); | ||
|
||
foreach (MethodInfo mi in clientMethods) | ||
{ | ||
string grpcMethodName = ClientNameToGrpcMethodName(mi.Name); | ||
|
||
Dictionary<string, string> expected; | ||
bool found = ExpectedMethodAttributes.TryGetValue(grpcMethodName, out expected); | ||
Assert.IsTrue(found, "No expected attributes found for '{0}'", grpcMethodName); | ||
|
||
Dictionary<string, string> actual = CollectMethodAttributes(mi); | ||
|
||
CollectionAssert.AreEquivalent(expected, actual, "Attribute mismatch for '{0}'", grpcMethodName); | ||
} | ||
} | ||
|
||
static Dictionary<string, string> CollectMethodAttributes(MethodInfo mi) | ||
{ | ||
return mi.GetCustomAttributes<Bond.AttributeAttribute>().ToDictionary(ba => ba.Name, ba => ba.Value); | ||
} | ||
|
||
static string ClientNameToGrpcMethodName(string clientName) | ||
{ | ||
const string clientNameSuffix = "Async"; | ||
Assert.That(clientName, new EndsWithConstraint(clientNameSuffix)); | ||
return clientName.Substring(0, clientName.Length - clientNameSuffix.Length); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import "bond/core/bond.bond" | ||
|
||
namespace UnitTest; | ||
|
||
[SomeAttribute("service value")] | ||
service SimpleService | ||
{ | ||
[SomeAttribute("method value")] | ||
[DifferentAttribute("")] // empty string, but present | ||
bond.Box<int32> IntToInt(bond.Box<int32>); | ||
|
||
[NothingToInt("no clash")] | ||
bond.Box<int32> NothingToInt(); | ||
|
||
nothing IntToNothing(bond.Box<int32>); | ||
|
||
nothing NothingToNothing(); | ||
} |