diff --git a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/CollectBundleResourcesTaskTests.cs b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/CollectBundleResourcesTaskTests.cs index e83faf0659e..3d48c63f0c7 100644 --- a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/CollectBundleResourcesTaskTests.cs +++ b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/CollectBundleResourcesTaskTests.cs @@ -36,5 +36,67 @@ public void LogicalNameOutsideAppBundle () Environment.CurrentDirectory = currentDirectory; } } + + // Ref: https://github.com/dotnet/macios/issues/23898 + // Items defined by an SDK (not default items) where the defining + // project is in a completely different directory tree than the + // project should still resolve their LogicalName correctly. + [Test] + public void ContentDefinedBySdkFarFromProject () + { + var currentDirectory = Environment.CurrentDirectory; + try { + var tmpdir = Cache.CreateTemporaryDirectory (); + + // Simulate the project directory + var projDir = Path.Combine (tmpdir, "src", "MyProject"); + Directory.CreateDirectory (projDir); + + // Simulate an SDK directory far from the project (like a Razor/Blazor SDK) + var sdkDir = Path.Combine (tmpdir, "sdk", "packs", "Microsoft.NET.Sdk.Razor", "10.0.0", "build"); + Directory.CreateDirectory (sdkDir); + + Environment.CurrentDirectory = projDir; + + // Create several content files in the project directory + var files = new [] { "wwwroot/background.png", "wwwroot/script.js", "Component1.razor" }; + var items = new List (); + foreach (var file in files) { + var fullPath = Path.Combine (projDir, file); + Directory.CreateDirectory (Path.GetDirectoryName (fullPath)!); + File.WriteAllText (fullPath, "content"); + + var item = new TaskItem (file); + // The defining project is the SDK file, not a default item + item.SetMetadata ("LocalDefiningProjectFullPath", Path.Combine (sdkDir, "Microsoft.NET.Sdk.Razor.DefaultItems.props")); + item.SetMetadata ("LocalMSBuildProjectFullPath", Path.Combine (projDir, "MyProject.csproj")); + items.Add (item); + } + + var task = CreateTask (); + task.ProjectDir = projDir + Path.DirectorySeparatorChar; + task.ResourcePrefix = ""; + task.BundleResources = items.ToArray (); + ExecuteTask (task); + + // With the bug, the LogicalName would be something like + // '../../../../../src/MyProject/wwwroot/background.png' which starts + // with '../' and gets rejected with a warning. + // After fix, items should be included with correct LogicalNames. + Assert.That (Engine.Logger.WarningsEvents.Count, Is.EqualTo (0), $"Warnings: {string.Join (", ", Engine.Logger.WarningsEvents.Select (e => e.Message))}"); + Assert.That (Engine.Logger.ErrorEvents.Count, Is.EqualTo (0), $"Errors: {string.Join (", ", Engine.Logger.ErrorEvents.Select (e => e.Message))}"); + Assert.That (task.BundleResourcesWithLogicalNames.Length, Is.EqualTo (3), "BundleResourcesWithLogicalNames count"); + + var logicalNames = task.BundleResourcesWithLogicalNames + .Select (i => i.GetMetadata ("LogicalName")) + .OrderBy (n => n) + .ToArray (); + Assert.That (logicalNames [0], Is.EqualTo ("Component1.razor"), "LogicalName[0]"); + Assert.That (logicalNames [1], Is.EqualTo ("wwwroot/background.png"), "LogicalName[1]"); + Assert.That (logicalNames [2], Is.EqualTo ("wwwroot/script.js"), "LogicalName[2]"); + } finally { + Environment.CurrentDirectory = currentDirectory; + } + } } }