Merge branch 'fix/ipc-27-descriptor-test'
This commit is contained in:
@@ -3,22 +3,24 @@ using Google.Protobuf;
|
||||
using Google.Protobuf.Reflection;
|
||||
using ZB.MOM.WW.MxGateway.Contracts;
|
||||
using ZB.MOM.WW.MxGateway.Contracts.Proto;
|
||||
using ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy;
|
||||
|
||||
namespace ZB.MOM.WW.MxGateway.Tests.Contracts;
|
||||
|
||||
public sealed class ClientProtoInputTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Guards the published client descriptor set against silent staleness. Every message
|
||||
/// and field compiled into the in-process contract (which the build regenerates from the current
|
||||
/// <c>.proto</c> sources) must appear in the committed protoset. A missing symbol means the
|
||||
/// descriptor was not regenerated after a proto change; run
|
||||
/// <c>scripts/publish-client-proto-inputs.ps1</c> and commit the refreshed protoset.
|
||||
/// Guards the published client descriptor set against silent staleness. Every message,
|
||||
/// field, enum, enum value, service, and method compiled into the in-process contract
|
||||
/// (which the build regenerates from the current <c>.proto</c> sources) must appear in the
|
||||
/// committed protoset. A missing symbol means the descriptor was not regenerated after a
|
||||
/// proto change; run <c>scripts/publish-client-proto-inputs.ps1</c> and commit the
|
||||
/// refreshed protoset.
|
||||
/// The check is semantic (symbol presence) rather than byte-wise, so it is independent of protoc
|
||||
/// version and does not require protoc on the test runner.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Descriptor_ContainsEveryContractMessageAndField()
|
||||
public void Descriptor_ContainsEveryContractSymbol()
|
||||
{
|
||||
DirectoryInfo repositoryRoot = FindRepositoryRoot();
|
||||
string descriptorPath = Path.Combine(
|
||||
@@ -34,20 +36,65 @@ public sealed class ClientProtoInputTests
|
||||
|
||||
HashSet<string> publishedMessages = new(StringComparer.Ordinal);
|
||||
HashSet<string> publishedFields = new(StringComparer.Ordinal);
|
||||
HashSet<string> publishedEnums = new(StringComparer.Ordinal);
|
||||
HashSet<string> publishedServices = new(StringComparer.Ordinal);
|
||||
foreach (FileDescriptorProto file in descriptorSet.File)
|
||||
{
|
||||
foreach (DescriptorProto message in file.MessageType)
|
||||
{
|
||||
CollectPublishedSymbols(file.Package, message, publishedMessages, publishedFields);
|
||||
CollectPublishedSymbols(file.Package, message, publishedMessages, publishedFields, publishedEnums);
|
||||
}
|
||||
|
||||
foreach (EnumDescriptorProto enumType in file.EnumType)
|
||||
{
|
||||
CollectPublishedEnumSymbols(file.Package, enumType, publishedEnums);
|
||||
}
|
||||
|
||||
foreach (ServiceDescriptorProto service in file.Service)
|
||||
{
|
||||
string serviceFullName = string.IsNullOrEmpty(file.Package) ? service.Name : file.Package + "." + service.Name;
|
||||
publishedServices.Add(serviceFullName);
|
||||
foreach (MethodDescriptorProto method in service.Method)
|
||||
{
|
||||
publishedServices.Add(serviceFullName + "/" + method.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<string> missing = [];
|
||||
foreach (FileDescriptor file in new[] { MxaccessGatewayReflection.Descriptor, MxaccessWorkerReflection.Descriptor })
|
||||
FileDescriptor[] contractFiles =
|
||||
[
|
||||
MxaccessGatewayReflection.Descriptor,
|
||||
MxaccessWorkerReflection.Descriptor,
|
||||
GalaxyRepositoryReflection.Descriptor,
|
||||
];
|
||||
foreach (FileDescriptor file in contractFiles)
|
||||
{
|
||||
foreach (MessageDescriptor message in file.MessageTypes)
|
||||
{
|
||||
CollectMissingContractSymbols(message, publishedMessages, publishedFields, missing);
|
||||
CollectMissingContractSymbols(message, publishedMessages, publishedFields, publishedEnums, missing);
|
||||
}
|
||||
|
||||
foreach (EnumDescriptor enumType in file.EnumTypes)
|
||||
{
|
||||
CollectMissingEnumSymbols(enumType, publishedEnums, missing);
|
||||
}
|
||||
|
||||
foreach (ServiceDescriptor service in file.Services)
|
||||
{
|
||||
if (!publishedServices.Contains(service.FullName))
|
||||
{
|
||||
missing.Add(service.FullName);
|
||||
}
|
||||
|
||||
foreach (MethodDescriptor method in service.Methods)
|
||||
{
|
||||
string key = service.FullName + "/" + method.Name;
|
||||
if (!publishedServices.Contains(key))
|
||||
{
|
||||
missing.Add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +109,8 @@ public sealed class ClientProtoInputTests
|
||||
string package,
|
||||
DescriptorProto message,
|
||||
HashSet<string> messages,
|
||||
HashSet<string> fields)
|
||||
HashSet<string> fields,
|
||||
HashSet<string> enums)
|
||||
{
|
||||
string fullName = string.IsNullOrEmpty(package) ? message.Name : package + "." + message.Name;
|
||||
messages.Add(fullName);
|
||||
@@ -74,7 +122,26 @@ public sealed class ClientProtoInputTests
|
||||
|
||||
foreach (DescriptorProto nested in message.NestedType)
|
||||
{
|
||||
CollectPublishedSymbols(fullName, nested, messages, fields);
|
||||
CollectPublishedSymbols(fullName, nested, messages, fields, enums);
|
||||
}
|
||||
|
||||
foreach (EnumDescriptorProto enumType in message.EnumType)
|
||||
{
|
||||
CollectPublishedEnumSymbols(fullName, enumType, enums);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CollectPublishedEnumSymbols(
|
||||
string containingScope,
|
||||
EnumDescriptorProto enumType,
|
||||
HashSet<string> enums)
|
||||
{
|
||||
string enumFullName = string.IsNullOrEmpty(containingScope) ? enumType.Name : containingScope + "." + enumType.Name;
|
||||
enums.Add(enumFullName);
|
||||
|
||||
foreach (EnumValueDescriptorProto value in enumType.Value)
|
||||
{
|
||||
enums.Add(enumFullName + "/" + value.Name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +149,7 @@ public sealed class ClientProtoInputTests
|
||||
MessageDescriptor message,
|
||||
HashSet<string> publishedMessages,
|
||||
HashSet<string> publishedFields,
|
||||
HashSet<string> publishedEnums,
|
||||
List<string> missing)
|
||||
{
|
||||
if (!publishedMessages.Contains(message.FullName))
|
||||
@@ -100,7 +168,32 @@ public sealed class ClientProtoInputTests
|
||||
|
||||
foreach (MessageDescriptor nested in message.NestedTypes)
|
||||
{
|
||||
CollectMissingContractSymbols(nested, publishedMessages, publishedFields, missing);
|
||||
CollectMissingContractSymbols(nested, publishedMessages, publishedFields, publishedEnums, missing);
|
||||
}
|
||||
|
||||
foreach (EnumDescriptor enumType in message.EnumTypes)
|
||||
{
|
||||
CollectMissingEnumSymbols(enumType, publishedEnums, missing);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CollectMissingEnumSymbols(
|
||||
EnumDescriptor enumType,
|
||||
HashSet<string> publishedEnums,
|
||||
List<string> missing)
|
||||
{
|
||||
if (!publishedEnums.Contains(enumType.FullName))
|
||||
{
|
||||
missing.Add(enumType.FullName);
|
||||
}
|
||||
|
||||
foreach (EnumValueDescriptor value in enumType.Values)
|
||||
{
|
||||
string key = enumType.FullName + "/" + value.Name;
|
||||
if (!publishedEnums.Contains(key))
|
||||
{
|
||||
missing.Add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user