Skip to content

Commit a771fe0

Browse files
committed
Enable InternalsVisibleTo for test projects in Package mode
- SqlClient, Abstractions, Azure: emit IVT with test public key when SigningKeyPath is set and ReferenceType=Package; emit unsigned IVT otherwise. - UnitTests: in Package mode, compile against the runtime implementation DLL (runtimes/{rid}/lib/{tfm}/) instead of the ref assembly so the compiler can resolve internal types exposed via IVT. - Sign TDS tool projects (TDS, TDS.EndPoint, TDS.Servers) and TestUtilities with TestSigningKeyPath so signed test assemblies can reference them. - build.proj: declare TestSigningKeyPath and plumb it into test targets.
1 parent 52e7d4b commit a771fe0

6 files changed

Lines changed: 64 additions & 9 deletions

File tree

build.proj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@
265265
Description: Path to the key used to sign test assemblies. Required in Package mode when
266266
SigningKeyPath is set so that InternalsVisibleTo grants from signed driver
267267
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.
268271
Default value: [blank]
269272
Example: C:\path\to\sqlclient-test-key.snk
270273
-->

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@
7070
</AssemblyAttribute>
7171
</ItemGroup>
7272

73-
<!-- Signed + Package mode: expose internals to UnitTests signed with the test key. -->
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+
-->
7479
<ItemGroup Condition="'$(SigningKeyPath)' != '' AND '$(ReferenceType)' == 'Package'">
7580
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
7681
<_Parameter1>UnitTests, PublicKey=00240000048000001401000006020000002400005253413100080000010001003D19684676DA365F331D00CE7BD4B8EF03E74102F39A5681B40622703D68F0298ECACECC723D3FFC1EA9365AF4958578550EA1EBEEC084B0B3757F3762449F5365E872802A4B548056760764FAD062BFEE81ED26183109AD46810E7E6E965419D0A10473680144D20C1BFE1027A5F586CA987523C06F5C126C44EA7D4F51EB023867A9F294315F95775ACEFD2D678186919458DFCCB4DE2E9F53AEFC766C7CBCEC474ED21C1616E5A9414D366D91D121C39F5FE6641295ADC058EF3FB10593BCDE2E82D9F217C2634909EEF496CD53AE78ABBEA572B871D72EBFC5378205950ABA97C7CCC2B9635D96933D5F9C9624D71FF53EE2094CF3A6BD38534D66E414B7</_Parameter1>

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

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,41 @@
4545

4646
<!-- References ====================================================== -->
4747
<!-- Test target reference -->
48-
<ItemGroup>
49-
<ProjectReference Include="$(RepoRoot)src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj"
50-
Condition="'$(ReferenceType)' != 'Package'" />
48+
<ItemGroup Condition="'$(ReferenceType)' != 'Package'">
49+
<ProjectReference Include="$(RepoRoot)src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj" />
50+
<ProjectReference Include="$(RepoRoot)src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj" />
51+
</ItemGroup>
52+
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. -->
5174
<PackageReference Include="Microsoft.Data.SqlClient"
52-
Condition="'$(ReferenceType)' == 'Package'" />
53-
<ProjectReference Include="$(RepoRoot)src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj"
54-
Condition="'$(ReferenceType)' != 'Package'" />
55-
<PackageReference Include="Microsoft.SqlServer.Server"
56-
Condition="'$(ReferenceType)' == 'Package'" />
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" />
5783
</ItemGroup>
5884

5985
<!-- References for netframework -->

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)