1+ public class BuildTargetsTests
2+ {
3+ [ Test ]
4+ public async Task BuildCopiesEmptyFiles ( )
5+ {
6+ using var temp = new TempDirectory ( ) ;
7+
8+ var ( nugetSource , packageVersion ) = FindPackageInfo ( ) ;
9+ WriteCsproj ( temp , packageVersion ) ;
10+ WriteNugetConfig ( temp , nugetSource ) ;
11+
12+ var exitCode = await DotnetBuild ( temp ) ;
13+ That ( exitCode , Is . EqualTo ( 0 ) ) ;
14+
15+ var emptyFilesDir = Path . Combine ( temp . Path , "bin" , "Release" , "net10.0" , "EmptyFiles" ) ;
16+ That ( Directory . Exists ( emptyFilesDir ) , Is . True , "EmptyFiles directory should exist after build" ) ;
17+ That ( Directory . GetFiles ( emptyFilesDir , "*" , SearchOption . AllDirectories ) , Is . Not . Empty , "EmptyFiles directory should contain files" ) ;
18+ }
19+
20+ [ Test ]
21+ public async Task RecoverFromDeletedEmptyFilesDirectory ( )
22+ {
23+ using var temp = new TempDirectory ( ) ;
24+
25+ var ( nugetSource , packageVersion ) = FindPackageInfo ( ) ;
26+ WriteCsproj ( temp , packageVersion ) ;
27+ WriteNugetConfig ( temp , nugetSource ) ;
28+
29+ // First build
30+ var exitCode = await DotnetBuild ( temp ) ;
31+ That ( exitCode , Is . EqualTo ( 0 ) ) ;
32+
33+ var emptyFilesDir = Path . Combine ( temp . Path , "bin" , "Release" , "net10.0" , "EmptyFiles" ) ;
34+ That ( Directory . Exists ( emptyFilesDir ) , Is . True , "EmptyFiles directory should exist after first build" ) ;
35+
36+ // Delete EmptyFiles directory from output (leave obj/ intact so marker file survives)
37+ Directory . Delete ( emptyFilesDir , true ) ;
38+ That ( Directory . Exists ( emptyFilesDir ) , Is . False ) ;
39+
40+ // Second build — should recover
41+ exitCode = await DotnetBuild ( temp ) ;
42+ That ( exitCode , Is . EqualTo ( 0 ) ) ;
43+
44+ That ( Directory . Exists ( emptyFilesDir ) , Is . True , "EmptyFiles directory should exist after second build" ) ;
45+ That ( Directory . GetFiles ( emptyFilesDir , "*" , SearchOption . AllDirectories ) , Is . Not . Empty , "EmptyFiles directory should contain files after recovery" ) ;
46+ }
47+
48+ static void WriteCsproj ( TempDirectory temp , string version )
49+ {
50+ var csproj = $ """
51+ <Project Sdk="Microsoft.NET.Sdk">
52+ <PropertyGroup>
53+ <TargetFramework>net10.0</TargetFramework>
54+ <RestorePackagesPath>packages</RestorePackagesPath>
55+ </PropertyGroup>
56+ <ItemGroup>
57+ <PackageReference Include="EmptyFiles" Version="{ version } " />
58+ </ItemGroup>
59+ </Project>
60+ """ ;
61+ File . WriteAllText ( Path . Combine ( temp . Path , "Project.csproj" ) , csproj ) ;
62+ }
63+
64+ static void WriteNugetConfig ( TempDirectory temp , string nugetSource )
65+ {
66+ var config = $ """
67+ <?xml version="1.0" encoding="utf-8"?>
68+ <configuration>
69+ <packageSources>
70+ <clear />
71+ <add key="local" value="{ nugetSource } " />
72+ </packageSources>
73+ </configuration>
74+ """ ;
75+ File . WriteAllText ( Path . Combine ( temp . Path , "nuget.config" ) , config ) ;
76+ }
77+
78+ static async Task < int > DotnetBuild ( TempDirectory temp )
79+ {
80+ var startInfo = new ProcessStartInfo ( "dotnet" , "build --configuration Release --disable-build-servers -nodeReuse:false /p:UseSharedCompilation=false" )
81+ {
82+ WorkingDirectory = temp . Path ,
83+ RedirectStandardOutput = true ,
84+ RedirectStandardError = true ,
85+ UseShellExecute = false ,
86+ CreateNoWindow = true ,
87+ } ;
88+
89+ using var process = Process . Start ( startInfo ) ! ;
90+ var stdout = await process . StandardOutput . ReadToEndAsync ( ) ;
91+ var stderr = await process . StandardError . ReadToEndAsync ( ) ;
92+ await process . WaitForExitAsync ( ) ;
93+
94+ await TestContext . Out . WriteLineAsync ( "STDOUT:" ) ;
95+ await TestContext . Out . WriteLineAsync ( stdout ) ;
96+ await TestContext . Out . WriteLineAsync ( "STDERR:" ) ;
97+ await TestContext . Out . WriteLineAsync ( stderr ) ;
98+
99+ return process . ExitCode ;
100+ }
101+
102+ static ( string nugetSource , string packageVersion ) FindPackageInfo ( )
103+ {
104+ var nugetSource = FindNugetSource ( ) ;
105+ var packageVersion = FindPackageVersion ( nugetSource ) ;
106+ return ( nugetSource , packageVersion ) ;
107+ }
108+
109+ static string FindNugetSource ( )
110+ {
111+ var nugetsDir = Path . GetFullPath ( Path . Combine ( ProjectFiles . SolutionDirectory , ".." , "nugets" ) ) ;
112+ if ( Directory . Exists ( nugetsDir ) )
113+ {
114+ return nugetsDir ;
115+ }
116+
117+ throw new InvalidOperationException ( $ "Cannot find nugets directory at { nugetsDir } ") ;
118+ }
119+
120+ static string FindPackageVersion ( string nugetSource )
121+ {
122+ var nupkg = Directory
123+ . GetFiles ( nugetSource , "EmptyFiles.*.nupkg" )
124+ . FirstOrDefault ( _ => ! Path . GetFileName ( _ ) . StartsWith ( "EmptyFiles.Tool" ) ) ??
125+ throw new InvalidOperationException ( $ "Cannot find EmptyFiles nupkg in { nugetSource } ") ;
126+
127+ var fileName = Path . GetFileNameWithoutExtension ( nupkg ) ;
128+ return fileName [ "EmptyFiles." . Length ..] ;
129+ }
130+ }
0 commit comments