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
4 changes: 4 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,9 @@
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageVersion Include="AvalonEdit" Version="6.3.0.90" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<!-- Test packages -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>
</Project>
63 changes: 63 additions & 0 deletions PostSharp.Engineering.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,99 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostSharp.Engineering.Syste
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PostSharp.Engineering.McpApprovalServer", "src\PostSharp.Engineering.McpApprovalServer\PostSharp.Engineering.McpApprovalServer.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostSharp.Engineering.BuildTools.Tests", "src\PostSharp.Engineering.BuildTools.Tests\PostSharp.Engineering.BuildTools.Tests.csproj", "{500C0F23-7CC8-4B59-9792-E0040EAEC806}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{79C98592-B228-448D-B590-95FD9C8E3123}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Debug|x64.ActiveCfg = Debug|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Debug|x64.Build.0 = Debug|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Debug|x86.ActiveCfg = Debug|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Debug|x86.Build.0 = Debug|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Release|Any CPU.Build.0 = Release|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Release|x64.ActiveCfg = Release|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Release|x64.Build.0 = Release|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Release|x86.ActiveCfg = Release|Any CPU
{79C98592-B228-448D-B590-95FD9C8E3123}.Release|x86.Build.0 = Release|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Debug|x64.ActiveCfg = Debug|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Debug|x64.Build.0 = Debug|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Debug|x86.ActiveCfg = Debug|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Debug|x86.Build.0 = Debug|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Release|Any CPU.Build.0 = Release|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Release|x64.ActiveCfg = Release|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Release|x64.Build.0 = Release|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Release|x86.ActiveCfg = Release|Any CPU
{E7879F3E-FEE6-4E89-A265-52A1297BBCBC}.Release|x86.Build.0 = Release|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Debug|x64.ActiveCfg = Debug|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Debug|x64.Build.0 = Debug|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Debug|x86.ActiveCfg = Debug|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Debug|x86.Build.0 = Debug|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Release|Any CPU.Build.0 = Release|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Release|x64.ActiveCfg = Release|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Release|x64.Build.0 = Release|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Release|x86.ActiveCfg = Release|Any CPU
{53B2C52E-9095-4D49-8C34-5507BB941EE6}.Release|x86.Build.0 = Release|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Debug|x64.ActiveCfg = Debug|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Debug|x64.Build.0 = Debug|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Debug|x86.ActiveCfg = Debug|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Debug|x86.Build.0 = Debug|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Release|Any CPU.Build.0 = Release|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Release|x64.ActiveCfg = Release|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Release|x64.Build.0 = Release|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Release|x86.ActiveCfg = Release|Any CPU
{B6DB99A8-CF03-44CB-9C5E-2FEC7888DA3E}.Release|x86.Build.0 = Release|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x64.ActiveCfg = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x64.Build.0 = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x86.ActiveCfg = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|x86.Build.0 = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x64.ActiveCfg = Release|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x64.Build.0 = Release|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.ActiveCfg = Release|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.Build.0 = Release|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Debug|Any CPU.Build.0 = Debug|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Debug|x64.ActiveCfg = Debug|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Debug|x64.Build.0 = Debug|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Debug|x86.ActiveCfg = Debug|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Debug|x86.Build.0 = Debug|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Release|Any CPU.ActiveCfg = Release|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Release|Any CPU.Build.0 = Release|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Release|x64.ActiveCfg = Release|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Release|x64.Build.0 = Release|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Release|x86.ActiveCfg = Release|Any CPU
{500C0F23-7CC8-4B59-9792-E0040EAEC806}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{500C0F23-7CC8-4B59-9792-E0040EAEC806} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EE2C48C5-7AD7-4852-A39D-A3C5C94000A9}
EndGlobalSection
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright (c) SharpCrafters s.r.o. See the LICENSE.md file in the root directory of this repository root for details.

using PostSharp.Engineering.BuildTools.Build;
using PostSharp.Engineering.BuildTools.ContinuousIntegration;
using PostSharp.Engineering.BuildTools.ContinuousIntegration.Model;
using PostSharp.Engineering.BuildTools.Dependencies.Definitions;
using PostSharp.Engineering.BuildTools.Dependencies.Model;
using System.Linq;
using Xunit;

namespace PostSharp.Engineering.BuildTools.Tests;

public class ParametrizedDependencyAliasTests
{
[Fact]
public void NoAlias_KeyEqualsName()
{
// Use an existing definition to avoid scaffolding ProductFamily registration.
var definition = MetalamaDependencies.V2026_1.Metalama;
var dependency = definition.ToDependency();

Assert.Null( dependency.Alias );
Assert.Equal( definition.Name, dependency.Key );
Assert.Equal( definition.NameWithoutDot, dependency.KeyWithoutDot );
Assert.Equal( DependencyArtifactPickup.Snapshot, dependency.ArtifactPickup );
}

[Fact]
public void WithAlias_KeyAndKeyWithoutDotUseAlias()
{
var definition = MetalamaDependencies.V2026_0.Metalama;
var dependency = definition.WithAlias( "Metalama20260" );

Assert.Equal( "Metalama20260", dependency.Alias );
Assert.Equal( "Metalama20260", dependency.Key );
Assert.Equal( "Metalama20260", dependency.KeyWithoutDot );
Assert.Equal( definition.Name, dependency.Name ); // Name accessor still surfaces the definition's Name
}

[Fact]
public void WithAlias_StripsDots()
{
var definition = MetalamaDependencies.V2026_0.Metalama;
var dependency = definition.WithAlias( "Foo.Bar.Baz" );

Assert.Equal( "Foo.Bar.Baz", dependency.Alias );
Assert.Equal( "Foo.Bar.Baz", dependency.Key );
Assert.Equal( "FooBarBaz", dependency.KeyWithoutDot );
}

[Fact]
public void WithLastSuccessfulOnly_SetsArtifactPickup()
{
var definition = MetalamaDependencies.V2026_0.Metalama;
var dependency = definition.WithAlias( "Metalama20260" ).WithLastSuccessfulOnly();

Assert.Equal( DependencyArtifactPickup.LastSuccessful, dependency.ArtifactPickup );
Assert.Equal( "Metalama20260", dependency.Alias );
}

[Fact]
public void Composes_ConfigurationMappingPlusAliasPlusLastSuccessful()
{
var definition = MetalamaDependencies.V2026_0.Metalama;
var publicMapping = new ConfigurationSpecific<BuildConfiguration>(
BuildConfiguration.Public,
BuildConfiguration.Public,
BuildConfiguration.Public );

var dependency = definition
.ToDependency( publicMapping )
.WithAlias( "Metalama20260" )
.WithLastSuccessfulOnly();

Assert.Equal( BuildConfiguration.Public, dependency.ConfigurationMapping[BuildConfiguration.Debug] );
Assert.Equal( BuildConfiguration.Public, dependency.ConfigurationMapping[BuildConfiguration.Release] );
Assert.Equal( BuildConfiguration.Public, dependency.ConfigurationMapping[BuildConfiguration.Public] );
Assert.Equal( "Metalama20260", dependency.Alias );
Assert.Equal( DependencyArtifactPickup.LastSuccessful, dependency.ArtifactPickup );
}

[Fact]
public void DependencyConfiguration_KeyFallsBackToDefinitionNameWhenNoParametrized()
{
var definition = MetalamaDependencies.V2026_1.Metalama;
var configuration = new DependencyConfiguration( definition, BuildConfiguration.Debug );

Assert.Null( configuration.Parametrized );
Assert.Equal( definition.Name, configuration.Key );
Assert.Equal( definition.NameWithoutDot, configuration.KeyWithoutDot );
Assert.Equal( DependencyArtifactPickup.Snapshot, configuration.ArtifactPickup );
}

[Fact]
public void DependencyConfiguration_KeyUsesAliasFromParametrized()
{
var definition = MetalamaDependencies.V2026_0.Metalama;
var parametrizedDependency = definition.WithAlias( "Metalama20260" ).WithLastSuccessfulOnly();
var configuration = new DependencyConfiguration( definition, BuildConfiguration.Public ) { Parametrized = parametrizedDependency };

Assert.Equal( "Metalama20260", configuration.Key );
Assert.Equal( "Metalama20260", configuration.KeyWithoutDot );
Assert.Equal( DependencyArtifactPickup.LastSuccessful, configuration.ArtifactPickup );
}

[Fact]
public void TwoAliasedRefsToSameDefinitionNameAreLookedUpByKeyWithoutThrowing()
{
// Reproduces the configuration that triggered the Copilot review's first comment: two ParametrizedDependency
// entries with the same Definition.Name but different Aliases. Looking them up by Key must succeed unambiguously
// for each. A naive Name-based SingleOrDefault would throw — the array-level assertion at the end documents
// why the Product lookup methods only filter on Key.
var definition = MetalamaDependencies.V2026_0.Metalama;
var first = definition.WithAlias( "First" );
var second = definition.WithAlias( "Second" );

var dependencies = new[] { first, second };

Assert.Same( first, dependencies.SingleOrDefault( d => d.Key == "First" ) );
Assert.Same( second, dependencies.SingleOrDefault( d => d.Key == "Second" ) );
Assert.Null( dependencies.SingleOrDefault( d => d.Key == "Other" ) );

// Documents the throw that the Name fallback (now removed) would have produced.
Assert.Throws<System.InvalidOperationException>( () => dependencies.SingleOrDefault( d => d.Name == definition.Name ) );
}

[Fact]
public void DependencyConfiguration_EqualityIgnoresParametrized()
{
// (Definition, Configuration) tuple is the equality key. Two configurations with the same Definition+Configuration
// but different Parametrized references must compare equal so HashSet deduplication in GetAllDependencies stays correct.
var definition = MetalamaDependencies.V2026_1.Metalama;
var first = new DependencyConfiguration( definition, BuildConfiguration.Debug );
var second = new DependencyConfiguration( definition, BuildConfiguration.Debug ) { Parametrized = definition.ToDependency() };

Assert.Equal( first, second );
Assert.Equal( first.GetHashCode(), second.GetHashCode() );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\PostSharp.Engineering.BuildTools\PostSharp.Engineering.BuildTools.csproj" />
</ItemGroup>

</Project>
Loading
Loading