Skip to content

Commit d8ccb8d

Browse files
committed
Enable InternalsVisibleTo for test projects in Package mode
1 parent 376eecb commit d8ccb8d

8 files changed

Lines changed: 119 additions & 20 deletions

File tree

build.proj

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,23 @@
259259
-p:SigningKeyPath="$(SigningKeyPath)"
260260
</SigningKeyPathArgument>
261261

262+
<!--
263+
TestSigningKeyPath
264+
Applies to: Test* targets
265+
Description: Path to the key used to sign test assemblies. Required in Package mode when
266+
SigningKeyPath is set so that InternalsVisibleTo grants from signed driver
267+
assemblies can be fulfilled.
268+
If SigningKeyPath is set and ReferenceType is Package but TestSigningKeyPath
269+
is omitted, test builds that access internals will fail with CS0234 errors
270+
because the driver assembly's IVT requires a matching public key.
271+
Default value: [blank]
272+
Example: C:\path\to\sqlclient-test-key.snk
273+
-->
274+
<TestSigningKeyPath Condition="'$(TestSigningKeyPath)' == ''" />
275+
<TestSigningKeyPathArgument Condition="'$(TestSigningKeyPath)' != ''">
276+
-p:TestSigningKeyPath="$(TestSigningKeyPath)"
277+
</TestSigningKeyPathArgument>
278+
262279
<!--
263280
TestBlameTimeout
264281
Applies to: Test* targets
@@ -678,10 +695,6 @@
678695
<!-- TestSqlClientUnit: Runs unit tests for SqlClient -->
679696
<Target Name="TestSqlClientUnit">
680697
<PropertyGroup>
681-
<!--
682-
Note: This test exclusively uses project references, so neither ReferenceType nor any
683-
package version arguments are specified in this command.
684-
-->
685698
<LogFilePrefix>SqlClientUnit-$(OS)</LogFilePrefix>
686699
<LogFilePrefix Condition="'$(TestFramework)' != ''">$(LogFilePrefix)-$(TestFramework)</LogFilePrefix>
687700

@@ -692,6 +705,10 @@
692705
$(TestCodeCoverageArgument)
693706
$(TestFiltersArgument)
694707
$(TestFrameworkArgument)
708+
$(ReferenceTypeArgument)
709+
$(TestSigningKeyPathArgument)
710+
$(PackageVersionSqlClientArgument)
711+
$(PackageVersionSqlServerArgument)
695712
--results-directory "$(TestResultsFolderPath)"
696713
--logger:"trx;LogFilePrefix=$(LogFilePrefix)"
697714
</DotnetCommand>
@@ -860,10 +877,6 @@
860877
<!-- TestAbstractions: Runs Microsoft.Data.SqlClient.Extensions.Abstractions.Tests -->
861878
<Target Name="TestAbstractions">
862879
<PropertyGroup>
863-
<!--
864-
Note: This test exclusively uses project references, so neither ReferenceType nor any
865-
package version arguments are specified in this command.
866-
-->
867880
<LogFilePrefix>AbstractionsTests-$(OS)</LogFilePrefix>
868881
<LogFilePrefix Condition="'$(TestFramework)' != ''">$(LogFilePrefix)-$(TestFramework)</LogFilePrefix>
869882

@@ -874,6 +887,9 @@
874887
$(TestCodeCoverageArgument)
875888
$(TestFiltersArgument)
876889
$(TestFrameworkArgument)
890+
$(ReferenceTypeArgument)
891+
$(TestSigningKeyPathArgument)
892+
$(PackageVersionAbstractionsArgument)
877893
--results-directory "$(TestResultsFolderPath)"
878894
--logger:"trx;LogFilePrefix=$(LogFilePrefix)"
879895
</DotnetCommand>
@@ -977,7 +993,9 @@
977993

978994
<!-- Reference type arguments -->
979995
$(ReferenceTypeArgument)
996+
$(TestSigningKeyPathArgument)
980997
$(PackageVersionAbstractionsArgument)
998+
$(PackageVersionAzureArgument)
981999
$(PackageVersionLoggingArgument)
9821000
$(PackageVersionSqlClientArgument)
9831001
$(PackageVersionSqlServerArgument)

src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,26 @@
6262

6363
<!-- Strong name signing ============================================= -->
6464
<!-- Strong naming is being done in Directory.Build.props -->
65-
<!-- If we're not signing, we are permitted to expose our internals to tests. -->
65+
66+
<!-- Unsigned: expose internals to UnitTests in any reference mode. -->
6667
<ItemGroup Condition="'$(SigningKeyPath)' == ''">
6768
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
6869
<_Parameter1>UnitTests</_Parameter1>
6970
</AssemblyAttribute>
7071
</ItemGroup>
7172

73+
<!--
74+
Signed + Package mode: expose internals to UnitTests signed with the test key.
75+
Signed + Project mode is intentionally omitted: production-signed assemblies should not
76+
grant internal access to test assemblies during local development. Tests that need internals
77+
in Project mode run unsigned; only the CI package-validation pipeline uses signed packages.
78+
-->
79+
<ItemGroup Condition="'$(SigningKeyPath)' != '' AND '$(ReferenceType)' == 'Package'">
80+
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
81+
<_Parameter1>UnitTests, PublicKey=00240000048000001401000006020000002400005253413100080000010001003D19684676DA365F331D00CE7BD4B8EF03E74102F39A5681B40622703D68F0298ECACECC723D3FFC1EA9365AF4958578550EA1EBEEC084B0B3757F3762449F5365E872802A4B548056760764FAD062BFEE81ED26183109AD46810E7E6E965419D0A10473680144D20C1BFE1027A5F586CA987523C06F5C126C44EA7D4F51EB023867A9F294315F95775ACEFD2D678186919458DFCCB4DE2E9F53AEFC766C7CBCEC474ED21C1616E5A9414D366D91D121C39F5FE6641295ADC058EF3FB10593BCDE2E82D9F217C2634909EEF496CD53AE78ABBEA572B871D72EBFC5378205950ABA97C7CCC2B9635D96933D5F9C9624D71FF53EE2094CF3A6BD38534D66E414B7</_Parameter1>
82+
</AssemblyAttribute>
83+
</ItemGroup>
84+
7285
<!-- Build Output ==================================================== -->
7386
<PropertyGroup>
7487
<ArtifactPath>$(RepoRoot)artifacts/</ArtifactPath>

src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212
<IsTestProject>false</IsTestProject>
1313
</PropertyGroup>
1414

15+
<!-- Strong name signing ============================================= -->
16+
<!-- Sign with the test key so signed test assemblies can reference this project. -->
17+
<PropertyGroup Condition="'$(TestSigningKeyPath)' != ''">
18+
<SignAssembly>true</SignAssembly>
19+
<AssemblyOriginatorKeyFile>$(TestSigningKeyPath)</AssemblyOriginatorKeyFile>
20+
</PropertyGroup>
21+
1522
<!-- Target Frameworks =============================================== -->
1623
<PropertyGroup>
1724
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
@@ -26,7 +33,10 @@
2633
<!-- References ====================================================== -->
2734
<!-- Test target reference -->
2835
<ItemGroup>
29-
<ProjectReference Include="$(RepoRoot)src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj" />
36+
<ProjectReference Include="$(RepoRoot)src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj"
37+
Condition="'$(ReferenceType)' != 'Package'" />
38+
<PackageReference Include="Microsoft.Data.SqlClient"
39+
Condition="'$(ReferenceType)' == 'Package'" />
3040
</ItemGroup>
3141

3242
<!-- References for netfx -->

src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,51 @@
3636
</None>
3737
</ItemGroup>
3838

39+
<!-- Strong name signing ============================================= -->
40+
<!-- When a test signing key is provided, sign UnitTests so IVT from signed SqlClient works. -->
41+
<PropertyGroup Condition="'$(TestSigningKeyPath)' != ''">
42+
<SignAssembly>true</SignAssembly>
43+
<AssemblyOriginatorKeyFile>$(TestSigningKeyPath)</AssemblyOriginatorKeyFile>
44+
</PropertyGroup>
45+
3946
<!-- References ====================================================== -->
4047
<!-- Test target reference -->
41-
<ItemGroup>
42-
<!--
43-
The Unit Test project only supports ReferenceType = Project since it needs access to the
44-
internals of sibling packages.
45-
-->
48+
<ItemGroup Condition="'$(ReferenceType)' != 'Package'">
4649
<ProjectReference Include="$(RepoRoot)src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj" />
4750
<ProjectReference Include="$(RepoRoot)src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj" />
4851
</ItemGroup>
4952

50-
<Target Name="ValidateReferenceType"
51-
BeforeTargets="Restore;PrepareForBuild"
52-
Condition="'$(ReferenceType)' != 'Project'">
53-
<Error Text="Microsoft.Data.SqlClient.UnitTests.csproj only supports ReferenceType=Project." />
54-
</Target>
53+
<!--
54+
Package mode: Unit tests exercise internal types that only exist in the implementation assembly
55+
(runtimes/{rid}/lib/{tfm}/), not in the ref assembly (ref/{tfm}/). We exclude the ref
56+
compile asset and reference the runtime DLL directly so the compiler can see internals.
57+
58+
TODO: This is fragile, depending on our SqlClient NuGet package layout and supported TFMs. This
59+
could all be avoided if we didn't ship ref assemblies.
60+
-->
61+
<PropertyGroup Condition="'$(ReferenceType)' == 'Package'">
62+
<_SqlClientRid Condition="'$(OS)' != 'Windows_NT'">unix</_SqlClientRid>
63+
<_SqlClientRid Condition="'$(OS)' == 'Windows_NT'">win</_SqlClientRid>
64+
<!-- Map test TFM to the closest available package TFM (package ships net8.0/net9.0/net462) -->
65+
<_SqlClientPackageTfm Condition="'$(TargetFramework)' == 'net8.0'">net8.0</_SqlClientPackageTfm>
66+
<_SqlClientPackageTfm Condition="'$(TargetFramework)' == 'net462'">net462</_SqlClientPackageTfm>
67+
<_SqlClientPackageTfm Condition="'$(_SqlClientPackageTfm)' == ''">net9.0</_SqlClientPackageTfm>
68+
</PropertyGroup>
69+
<ItemGroup Condition="'$(ReferenceType)' == 'Package'">
70+
<!-- Brings in transitive dependencies and runtime deployment; ExcludeAssets="compile" prevents
71+
the compiler from using the ref assembly (which only contains public API surface).
72+
GeneratePathProperty="true" causes NuGet restore to emit $(PkgMicrosoft_Data_SqlClient)
73+
pointing to the extracted package folder in the global packages cache. -->
74+
<PackageReference Include="Microsoft.Data.SqlClient"
75+
GeneratePathProperty="true"
76+
ExcludeAssets="compile" />
77+
<!-- Compile against the implementation assembly so the compiler can resolve internal types
78+
exposed via InternalsVisibleTo. The path uses $(PkgMicrosoft_Data_SqlClient) generated
79+
above to locate the runtime DLL inside the NuGet package layout. -->
80+
<Reference Include="Microsoft.Data.SqlClient"
81+
HintPath="$(PkgMicrosoft_Data_SqlClient)/runtimes/$(_SqlClientRid)/lib/$(_SqlClientPackageTfm)/Microsoft.Data.SqlClient.dll" />
82+
<PackageReference Include="Microsoft.SqlServer.Server" />
83+
</ItemGroup>
5584

5685
<!-- References for netframework -->
5786
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">

src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
<PropertyGroup>
33
<TargetFramework>netstandard2.0</TargetFramework>
44
</PropertyGroup>
5+
6+
<!-- Strong name signing ============================================= -->
7+
<!-- Sign with the test key so signed test assemblies can reference this project. -->
8+
<PropertyGroup Condition="'$(TestSigningKeyPath)' != ''">
9+
<SignAssembly>true</SignAssembly>
10+
<AssemblyOriginatorKeyFile>$(TestSigningKeyPath)</AssemblyOriginatorKeyFile>
11+
</PropertyGroup>
12+
513
<Target Name="CopyConfig" BeforeTargets="Compile">
614
<Copy SourceFiles="config.default.json" DestinationFiles="config.json" Condition="!Exists('config.json')" />
715
</Target>

src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.EndPoint/TDS.EndPoint.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33
<RootNamespace>Microsoft.SqlServer.TDS.EndPoint</RootNamespace>
44
<AssemblyName>Microsoft.SqlServer.TDS.EndPoint</AssemblyName>
55
<TargetFramework>netstandard2.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<!-- Sign when a test key is provided so signed test assemblies can reference this. -->
9+
<PropertyGroup Condition="'$(TestSigningKeyPath)' != ''">
10+
<SignAssembly>true</SignAssembly>
11+
<AssemblyOriginatorKeyFile>$(TestSigningKeyPath)</AssemblyOriginatorKeyFile>
12+
</PropertyGroup>
13+
14+
<PropertyGroup>
615
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
716
</PropertyGroup>
817
<ItemGroup>

src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDS.Servers.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
<AssemblyName>Microsoft.SqlServer.TDS.Servers</AssemblyName>
55
<TargetFramework>netstandard2.0</TargetFramework>
66
</PropertyGroup>
7+
8+
<!-- Sign when a test key is provided so signed test assemblies can reference this. -->
9+
<PropertyGroup Condition="'$(TestSigningKeyPath)' != ''">
10+
<SignAssembly>true</SignAssembly>
11+
<AssemblyOriginatorKeyFile>$(TestSigningKeyPath)</AssemblyOriginatorKeyFile>
12+
</PropertyGroup>
713
<ItemGroup>
814
<ProjectReference Include="$(RepoRoot)src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.EndPoint/TDS.EndPoint.csproj" />
915
<ProjectReference Include="$(RepoRoot)src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS/TDS.csproj" />

src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS/TDS.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,10 @@
44
<AssemblyName>Microsoft.SqlServer.TDS</AssemblyName>
55
<TargetFramework>netstandard2.0</TargetFramework>
66
</PropertyGroup>
7+
8+
<!-- Sign when a test key is provided so signed test assemblies can reference this. -->
9+
<PropertyGroup Condition="'$(TestSigningKeyPath)' != ''">
10+
<SignAssembly>true</SignAssembly>
11+
<AssemblyOriginatorKeyFile>$(TestSigningKeyPath)</AssemblyOriginatorKeyFile>
12+
</PropertyGroup>
713
</Project>

0 commit comments

Comments
 (0)