Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using FluentAssertions;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xunit;

namespace Microsoft.NET.Build.Tasks.UnitTests
{
public class GivenASelectRuntimeIdentifierSpecificItems
{
[Fact]
public void ItSelectsCompatibleItems()
{
// Arrange
var testRuntimeGraphPath = CreateTestRuntimeGraph();
var items = new[]
{
CreateTaskItem("Item1", "linux-x64"),
CreateTaskItem("Item2", "win-x64"),
CreateTaskItem("Item3", "linux"),
CreateTaskItem("Item4", "ubuntu.18.04-x64")
};

var task = new SelectRuntimeIdentifierSpecificItems()
{
TargetRuntimeIdentifier = "ubuntu.18.04-x64",
Items = items,
RuntimeIdentifierGraphPath = testRuntimeGraphPath,
BuildEngine = new MockBuildEngine()
};

// Act
bool result = task.Execute();

// Assert
result.Should().BeTrue();
task.SelectedItems.Should().HaveCount(3); // linux-x64, linux, ubuntu.18.04-x64 should be compatible
task.SelectedItems.Should().Contain(i => i.ItemSpec == "Item1"); // linux-x64
task.SelectedItems.Should().Contain(i => i.ItemSpec == "Item3"); // linux
task.SelectedItems.Should().Contain(i => i.ItemSpec == "Item4"); // ubuntu.18.04-x64
task.SelectedItems.Should().NotContain(i => i.ItemSpec == "Item2"); // win-x64
}

[Fact]
public void ItSelectsItemsWithExactMatch()
{
// Arrange
var testRuntimeGraphPath = CreateTestRuntimeGraph();
var items = new[]
{
CreateTaskItem("Item1", "win-x64"),
CreateTaskItem("Item2", "linux-x64")
};

var task = new SelectRuntimeIdentifierSpecificItems()
{
TargetRuntimeIdentifier = "win-x64",
Items = items,
RuntimeIdentifierGraphPath = testRuntimeGraphPath,
BuildEngine = new MockBuildEngine()
};

// Act
bool result = task.Execute();

// Assert
result.Should().BeTrue();
task.SelectedItems.Should().HaveCount(1);
task.SelectedItems[0].ItemSpec.Should().Be("Item1");
}

[Fact]
public void ItSkipsItemsWithoutRuntimeIdentifierMetadata()
{
// Arrange
var testRuntimeGraphPath = CreateTestRuntimeGraph();
var items = new[]
{
CreateTaskItem("Item1", "linux-x64"),
CreateTaskItem("Item2", null), // No runtime identifier
CreateTaskItem("Item3", "") // Empty runtime identifier
};

var task = new SelectRuntimeIdentifierSpecificItems()
{
TargetRuntimeIdentifier = "linux-x64",
Items = items,
RuntimeIdentifierGraphPath = testRuntimeGraphPath,
BuildEngine = new MockBuildEngine()
};

// Act
bool result = task.Execute();

// Assert
result.Should().BeTrue();
task.SelectedItems.Should().HaveCount(1);
task.SelectedItems[0].ItemSpec.Should().Be("Item1");
}

[Fact]
public void ItUsesCustomRuntimeIdentifierMetadata()
{
// Arrange
var testRuntimeGraphPath = CreateTestRuntimeGraph();
var item = new TaskItem("Item1");
item.SetMetadata("CustomRID", "linux-x64");

var task = new SelectRuntimeIdentifierSpecificItems()
{
TargetRuntimeIdentifier = "ubuntu.18.04-x64",
Items = new[] { item },
RuntimeIdentifierItemMetadata = "CustomRID",
RuntimeIdentifierGraphPath = testRuntimeGraphPath,
BuildEngine = new MockBuildEngine()
};

// Act
bool result = task.Execute();

// Assert
result.Should().BeTrue();
task.SelectedItems.Should().HaveCount(1);
task.SelectedItems[0].ItemSpec.Should().Be("Item1");
}

[Fact]
public void ItReturnsEmptyArrayWhenNoItemsProvided()
{
// Arrange
var testRuntimeGraphPath = CreateTestRuntimeGraph();

var task = new SelectRuntimeIdentifierSpecificItems()
{
TargetRuntimeIdentifier = "linux-x64",
Items = new ITaskItem[0],
RuntimeIdentifierGraphPath = testRuntimeGraphPath,
BuildEngine = new MockBuildEngine()
};

// Act
bool result = task.Execute();

// Assert
result.Should().BeTrue();
task.SelectedItems.Should().BeEmpty();
}

private static TaskItem CreateTaskItem(string itemSpec, string? runtimeIdentifier)
{
var item = new TaskItem(itemSpec);
if (!string.IsNullOrEmpty(runtimeIdentifier))
{
item.SetMetadata("RuntimeIdentifier", runtimeIdentifier);
}
return item;
}

private static string CreateTestRuntimeGraph()
{
// Create a minimal runtime graph for testing
var runtimeGraph = @"{
""runtimes"": {
""linux"": {},
""linux-x64"": {
""#import"": [""linux""]
},
""ubuntu"": {
""#import"": [""linux""]
},
""ubuntu.18.04"": {
""#import"": [""ubuntu""]
},
""ubuntu.18.04-x64"": {
""#import"": [""ubuntu.18.04"", ""linux-x64""]
},
""win"": {},
""win-x64"": {
""#import"": [""win""]
}
}
}";

var tempFile = Path.GetTempFileName();
File.WriteAllText(tempFile, runtimeGraph);
return tempFile;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Build.Framework;
using NuGet.RuntimeModel;

namespace Microsoft.NET.Build.Tasks;

/// <summary>
/// MSBuild task that filters a set of Items by matching on compatible RuntimeIdentifier.
/// This task filters an Item list by those items that contain a specific Metadata that is
/// compatible with a specified Runtime Identifier, according to a given RuntimeIdentifierGraph file.
/// </summary>
public class SelectRuntimeIdentifierSpecificItems : TaskBase
{
/// <summary>
/// The target runtime identifier to check compatibility against.
/// </summary>
[Required]
public string TargetRuntimeIdentifier { get; set; } = null!;

/// <summary>
/// The list of candidate items to filter.
/// </summary>
[Required]
public ITaskItem[] Items { get; set; } = null!;

/// <summary>
/// The name of the MSBuild metadata to check on each item. Defaults to "RuntimeIdentifier".
/// </summary>
public string? RuntimeIdentifierItemMetadata { get; set; } = "RuntimeIdentifier";

/// <summary>
/// Path to the RuntimeIdentifierGraph file.
/// </summary>
[Required]
public string RuntimeIdentifierGraphPath { get; set; } = null!;

/// <summary>
/// The filtered items that are compatible with the <see cref="TargetRuntimeIdentifier"/>
/// </summary>
[Output]
public ITaskItem[]? SelectedItems { get; set; }

protected override void ExecuteCore()
{
if (Items.Length == 0)
{
SelectedItems = Array.Empty<ITaskItem>();
return;
}

string ridMetadata = RuntimeIdentifierItemMetadata ?? "RuntimeIdentifier";

RuntimeGraph runtimeGraph = new RuntimeGraphCache(this).GetRuntimeGraph(RuntimeIdentifierGraphPath);

var selectedItems = new List<ITaskItem>();

foreach (var item in Items)
{
string? itemRuntimeIdentifier = item.GetMetadata(ridMetadata);

if (string.IsNullOrEmpty(itemRuntimeIdentifier))
{
// Item doesn't have the runtime identifier metadata, skip it
continue;
}

// Check if the item's runtime identifier is compatible with the target runtime identifier
if (runtimeGraph.AreCompatible(TargetRuntimeIdentifier, itemRuntimeIdentifier))
{
selectedItems.Add(item);
}
}

SelectedItems = selectedItems.ToArray();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ Copyright (c) .NET Foundation. All rights reserved.

<UsingTask TaskName="Microsoft.NET.Build.Tasks.GetDefaultPlatformTargetForNetFramework"
AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />
<UsingTask TaskName="Microsoft.NET.Build.Tasks.SelectRuntimeIdentifierSpecificItems"
AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />

<!--
Switch our default .NETFramework CPU architecture choice back to AnyCPU before
Expand Down
Loading