@@ -16,7 +16,10 @@ namespace Microsoft.Build.UnitTests
1616#if FEATURE_CODETASKFACTORY
1717
1818 using System . CodeDom . Compiler ;
19+ using System . IO . Compression ;
20+ using Microsoft . Build . Logging ;
1921 using Microsoft . Build . Tasks . UnitTests ;
22+ using Shouldly ;
2023
2124 public sealed class CodeTaskFactoryTests
2225 {
@@ -1200,6 +1203,79 @@ public void EmbedsGeneratedFileInBinlogWhenFailsToCompile()
12001203 CodeTaskFactoryEmbeddedFileInBinlogTestHelper . BuildAndCheckForEmbeddedFileInBinlog (
12011204 FactoryType . CodeTaskFactory , "HelloTask" , taskXml , false ) ;
12021205 }
1206+
1207+ [ Fact ]
1208+ public void ShouldEmitSingleGeneratedFileIntoBinlog ( )
1209+ {
1210+ using var env = TestEnvironment . Create ( ) ;
1211+
1212+ // Define task XML for Import.targets
1213+ string taskXml = @"
1214+ <Project>
1215+ <UsingTask
1216+ TaskName=""CustomTask""
1217+ TaskFactory=""CodeTaskFactory""
1218+ AssemblyFile=""$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll"">
1219+ <ParameterGroup>
1220+ <InputParameter ParameterType=""System.String"" />
1221+ <OutputParameter ParameterType=""System.String"" Output=""True"" />
1222+ </ParameterGroup>
1223+ <Task>
1224+ <Using Namespace=""System"" />
1225+ <Code Type=""Fragment"" Language=""cs"">
1226+ <![CDATA[
1227+ Console.WriteLine(this.InputParameter);
1228+ this.OutputParameter = ""Hello "" + this.InputParameter;
1229+ ]]>
1230+ </Code>
1231+ </Task>
1232+ </UsingTask>
1233+ </Project>" ;
1234+
1235+ TransientTestFile importTargetsFile = env . CreateFile ( "Import.targets" , taskXml ) ;
1236+
1237+ // Define Another.proj content
1238+ string anotherContent = $@ "<Project>
1239+ <Import Project=""{ importTargetsFile . Path } "" />
1240+ <Target Name=""AnotherTarget"">
1241+ <CustomTask InputParameter=""Foo"">
1242+ <Output PropertyName=""TaskOutput"" TaskParameter=""OutputParameter"" />
1243+ </CustomTask>
1244+ <Message Text=""Output: $(TaskOutput)"" />
1245+ </Target>
1246+ </Project>" ;
1247+
1248+ TransientTestFile anotherProjFile = env . CreateFile ( "Another.proj" , anotherContent ) ;
1249+
1250+ // Define main.csproj content
1251+ string projectFileContent = $@ "<Project>
1252+ <Import Project=""{ importTargetsFile . Path } "" />
1253+ <Target Name=""Build"">
1254+ <MSBuild Projects=""{ anotherProjFile . Path } "" Targets=""AnotherTarget"" />
1255+ <CustomTask InputParameter=""Bar"" />
1256+ </Target>
1257+ </Project>" ;
1258+
1259+ TransientTestFile binlog = env . ExpectFile ( ".binlog" ) ;
1260+
1261+ var binaryLogger = new BinaryLogger ( )
1262+ {
1263+ Parameters = $ "LogFile={ binlog . Path } ",
1264+ CollectProjectImports = BinaryLogger . ProjectImportsCollectionMode . ZipFile ,
1265+ } ;
1266+
1267+ Helpers . BuildProjectWithNewOMAndBinaryLogger ( projectFileContent , binaryLogger , out bool result , out string projectDirectory ) ;
1268+
1269+ Assert . True ( result ) ;
1270+
1271+ string projectImportsZipPath = Path . ChangeExtension ( binlog . Path , ".ProjectImports.zip" ) ;
1272+ using var fileStream = new FileStream ( projectImportsZipPath , FileMode . Open ) ;
1273+ using var zipArchive = new ZipArchive ( fileStream , ZipArchiveMode . Read ) ;
1274+
1275+ // check to make sure that only 1 tmp file is created
1276+ var tmpFiles = zipArchive . Entries . Where ( zE => zE . Name . EndsWith ( "CustomTask-compilation-file.tmp" ) ) . ToList ( ) ;
1277+ tmpFiles . Count . ShouldBe ( 1 , $ "Expected exactly one file ending with 'CustomTask-compilation-file.tmp' in ProjectImports.zip, but found { tmpFiles . Count } .") ;
1278+ }
12031279 }
12041280#else
12051281 public sealed class CodeTaskFactoryTests
0 commit comments