Skip to content

Commit 78f6629

Browse files
authored
Ensures unique generation of operation ids for paths with composable overloaded functions where all functions in path are overloaded (#595)
* Ensure unique operation ids for composable functions with both overloaded * Update test to validate fix * Update release notes
1 parent b919ea8 commit 78f6629

File tree

3 files changed

+60
-23
lines changed

3 files changed

+60
-23
lines changed

src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<TargetFrameworks>net8.0</TargetFrameworks>
1616
<PackageId>Microsoft.OpenApi.OData</PackageId>
1717
<SignAssembly>true</SignAssembly>
18-
<Version>2.0.0-preview.4</Version>
18+
<Version>2.0.0-preview.5</Version>
1919
<Description>This package contains the codes you need to convert OData CSDL to Open API Document of Model.</Description>
2020
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
2121
<PackageTags>Microsoft OpenApi OData EDM</PackageTags>
@@ -28,8 +28,9 @@
2828
- Adds nullable to double schema conversions #581
2929
- Updates tag names for actions/functions operations #585
3030
- Creates unique operation ids for paths with composable overloaded functions #580
31-
- Further fixes for double/decimal/float schema conversions #581
32-
- Replaced integer types by number types
31+
- Further fixes for double/decimal/float schema conversions #581
32+
- Replaced integer types by number types
33+
- Further fix for generating unique operation ids for paths with composable overloaded functions where all functions in path are overloaded #594
3334
</PackageReleaseNotes>
3435
<AssemblyName>Microsoft.OpenApi.OData.Reader</AssemblyName>
3536
<AssemblyOriginatorKeyFile>..\..\tool\Microsoft.OpenApi.OData.snk</AssemblyOriginatorKeyFile>

src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ protected override void SetBasicInfo(OpenApiOperation operation)
107107
if (opSegment.Operation is IEdmFunction function && Context.Model.IsOperationOverload(function))
108108
{
109109
// Hash the segment to avoid duplicate operationIds
110-
pathHash = segment.GetPathHash(Context.Settings);
110+
pathHash = string.IsNullOrEmpty(pathHash)
111+
? opSegment.GetPathHash(Context.Settings)
112+
: (pathHash + opSegment.GetPathHash(Context.Settings)).GetHashSHA256()[..4];
111113
}
112114

113115
identifiers.Add(segment.Identifier);

test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -310,22 +310,29 @@ public void CreateOperationForComposableOverloadEdmFunctionReturnsCorrectOperati
310310
customer.AddKeys(customer.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
311311
model.AddElement(customer);
312312

313-
EdmFunction function = new("NS", "MyFunction", EdmCoreModel.Instance.GetString(false), true, null, false);
314-
function.AddParameter("entity", new EdmEntityTypeReference(customer, false));
315-
function.AddParameter("param", EdmCoreModel.Instance.GetString(false));
316-
model.AddElement(function);
313+
// Overloaded function 1
314+
EdmFunction function1 = new("NS", "MyFunction1", EdmCoreModel.Instance.GetString(false), true, null, false);
315+
function1.AddParameter("entity", new EdmEntityTypeReference(customer, false));
316+
model.AddElement(function1);
317317

318-
function = new EdmFunction("NS", "MyFunction", EdmCoreModel.Instance.GetString(false), true, null, false);
319-
function.AddParameter("entity", new EdmEntityTypeReference(customer, false));
320-
function.AddParameter("param", EdmCoreModel.Instance.GetString(false));
321-
function.AddParameter("param2", EdmCoreModel.Instance.GetString(false));
322-
model.AddElement(function);
318+
// Overloaded function 1
319+
EdmFunction function2 = new("NS", "MyFunction1", EdmCoreModel.Instance.GetString(false), true, null, false);
320+
function2.AddParameter("entity", new EdmEntityTypeReference(customer, false));
321+
function2.AddParameter("param", EdmCoreModel.Instance.GetString(false));
323322

324-
EdmFunction function2 = new("NS", "MyFunction2", EdmCoreModel.Instance.GetString(false), true, null, false);
325-
function2.AddParameter("entity2", new EdmEntityTypeReference(customer, false));
326-
function2.AddParameter("param3", EdmCoreModel.Instance.GetString(false));
327323
model.AddElement(function2);
328324

325+
// Overloaded function 2
326+
EdmFunction function3 = new("NS", "MyFunction2", EdmCoreModel.Instance.GetString(false), true, null, false);
327+
function3.AddParameter("entity2", new EdmEntityTypeReference(customer, false));
328+
model.AddElement(function3);
329+
330+
// Overloaded function 2
331+
EdmFunction function4 = new("NS", "MyFunction2", EdmCoreModel.Instance.GetString(false), true, null, false);
332+
function4.AddParameter("entity2", new EdmEntityTypeReference(customer, false));
333+
function4.AddParameter("param", EdmCoreModel.Instance.GetString(false));
334+
model.AddElement(function4);
335+
329336
EdmEntityContainer container = new("NS", "Default");
330337
EdmEntitySet customers = new(container, "Customers", customer);
331338
model.AddElement(container);
@@ -337,24 +344,51 @@ public void CreateOperationForComposableOverloadEdmFunctionReturnsCorrectOperati
337344
};
338345
ODataContext context = new(model, settings);
339346

340-
ODataPath path = new(new ODataNavigationSourceSegment(customers),
347+
ODataPath path1 = new(new ODataNavigationSourceSegment(customers),
341348
new ODataKeySegment(customer),
342-
new ODataOperationSegment(function),
343-
new ODataOperationSegment(function2));
349+
new ODataOperationSegment(function1),
350+
new ODataOperationSegment(function3));
351+
352+
ODataPath path2 = new(new ODataNavigationSourceSegment(customers),
353+
new ODataKeySegment(customer),
354+
new ODataOperationSegment(function1),
355+
new ODataOperationSegment(function4));
356+
357+
ODataPath path3 = new(new ODataNavigationSourceSegment(customers),
358+
new ODataKeySegment(customer),
359+
new ODataOperationSegment(function2),
360+
new ODataOperationSegment(function3));
361+
362+
ODataPath path4 = new(new ODataNavigationSourceSegment(customers),
363+
new ODataKeySegment(customer),
364+
new ODataOperationSegment(function2),
365+
new ODataOperationSegment(function4));
344366

345367
// Act
346-
var operation = _operationHandler.CreateOperation(context, path);
368+
var operation1 = _operationHandler.CreateOperation(context, path1);
369+
var operation2 = _operationHandler.CreateOperation(context, path2);
370+
var operation3 = _operationHandler.CreateOperation(context, path3);
371+
var operation4 = _operationHandler.CreateOperation(context, path4);
347372

348373
// Assert
349-
Assert.NotNull(operation);
374+
Assert.NotNull(operation1);
375+
Assert.NotNull(operation2);
376+
Assert.NotNull(operation3);
377+
Assert.NotNull(operation4);
350378

351379
if (enableOperationId)
352380
{
353-
Assert.Equal("Customers.Customer.MyFunction.MyFunction2-df74", operation.OperationId);
381+
Assert.Equal("Customers.Customer.MyFunction1.MyFunction2-c53d", operation1.OperationId);
382+
Assert.Equal("Customers.Customer.MyFunction1.MyFunction2-4d93", operation2.OperationId);
383+
Assert.Equal("Customers.Customer.MyFunction1.MyFunction2-a2b2", operation3.OperationId);
384+
Assert.Equal("Customers.Customer.MyFunction1.MyFunction2-7bea", operation4.OperationId);
354385
}
355386
else
356387
{
357-
Assert.Null(operation.OperationId);
388+
Assert.Null(operation1.OperationId);
389+
Assert.Null(operation2.OperationId);
390+
Assert.Null(operation3.OperationId);
391+
Assert.Null(operation4.OperationId);
358392
}
359393
}
360394

0 commit comments

Comments
 (0)