diff --git a/eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Models/RequestPathPattern.cs b/eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Models/RequestPathPattern.cs index 4910099ae28b..e3ea29a8d5b0 100644 --- a/eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Models/RequestPathPattern.cs +++ b/eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Models/RequestPathPattern.cs @@ -81,17 +81,23 @@ private static IReadOnlyList ParseSegments(string path) /// public bool IsAncestorOf(RequestPathPattern other) { + // Ancestor detection: compare only constant segments, skip variable segments. // To be the parent of other, you must at least be shorter than other. if (other.Count <= Count) return false; for (int i = 0; i < Count; i++) { - // we need the segment to be identical when strict is true (which is the default value) - // when strict is false, we also need the segment to be identical if it is constant. - // but if it is a reference, we only require they have the same type, do not require they have the same variable name. - // This case happens a lot during the management group parent detection - different RP calls this different things - if (!this[i].Equals(other[i])) + if (this[i].IsConstant) + { + if (!this[i].Equals(other[i])) + return false; + } + else // variable segment + { + if (!other[i].IsConstant) + continue; return false; + } } return true; } diff --git a/eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/test/RequestPathPatternTests.cs b/eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/test/RequestPathPatternTests.cs new file mode 100644 index 000000000000..469e88c3b1ef --- /dev/null +++ b/eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/test/RequestPathPatternTests.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Generator.Management.Models; +using NUnit.Framework; + +namespace Azure.Generator.Management.Tests +{ + public class RequestPathPatternTests + { + [TestCase("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}", "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}", true)] + [TestCase("/subscriptions/{subscriptionId}", "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}", true)] + [TestCase("/subscriptions/{subscriptionId}", "/providers/Microsoft.Management/managementGroups/{managementGroupId}", false)] + public void IsAncestorOf_BasicCases(string ancestor, string descendant, bool expected) + { + var ancestorPattern = new RequestPathPattern(ancestor); + var descendantPattern = new RequestPathPattern(descendant); + Assert.AreEqual(expected, ancestorPattern.IsAncestorOf(descendantPattern)); + } + + [Test] + public void IsAncestorOf_AncestorMustBeShorterThanDescendant() + { + var ancestorPattern = new RequestPathPattern("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}"); + var childPattern = new RequestPathPattern("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}"); + // Ancestor and child are the same length, should return false + Assert.IsFalse(ancestorPattern.IsAncestorOf(childPattern)); + + var longerAncestor = new RequestPathPattern("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage"); + var shorterChild = new RequestPathPattern("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}"); + // Ancestor is longer than child, should return false + Assert.IsFalse(longerAncestor.IsAncestorOf(shorterChild)); + } + + [Test] + public void IsAncestorOf_VariableSegmentCheck() + { + var ancestorPattern = new RequestPathPattern("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}"); + var descendantPattern = new RequestPathPattern("/subscriptions/{otherSub}/resourceGroups/{otherGroup}/providers/Microsoft.Storage/storageAccounts/{accountName}"); + Assert.IsTrue(ancestorPattern.IsAncestorOf(descendantPattern)); + } + + [Test] + public void IsAncestorOf_ConstantSegmentMismatch() + { + var ancestorPattern = new RequestPathPattern("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}"); + var descendantPattern = new RequestPathPattern("/tenants/{tenantId}/resourceGroups/{resourceGroupName}"); + Assert.IsFalse(ancestorPattern.IsAncestorOf(descendantPattern)); + } + } +}