@@ -101,76 +101,100 @@ public enum BinlogRoundtripTestReplayMode
101101 [ InlineData ( s_testProject2 , BinlogRoundtripTestReplayMode . RawEvents ) ]
102102 public void TestBinaryLoggerRoundtrip ( string projectText , BinlogRoundtripTestReplayMode replayMode )
103103 {
104- var binaryLogger = new BinaryLogger ( ) ;
104+ // NOTE:
105+ // We want both loggers to see the same value of EnableTargetOutputLogging, otherwise, the last assertion will fail.
106+ // See logic around showTargetOutputs.
107+ // In short, this controls whether or not the "Target output items:" part is shown.
108+ // Traits.Instance is weird, it's not always a singleton, depending on whether or not BuildEnvironmentState.s_runningTests is true.
109+ // The s_runningTests check is also not that straightforward.
110+ // Calls to ResetInstance_ForUnitTestsOnly (by tests that ran earlier than this test) might end up setting s_runningTests to false.
111+ // So the current approach is extremely vulnerable to the order of tests being run, and also for test filters.
112+ // When s_runningTests is true, we don't use a singleton, and in this case, one logger shows target outputs while the other doesn't.
113+ // When s_runningTests is false, Traits.Instance is truly a singleton and so both see the same value.
114+ // To stabilize this specific test, we explicitly set EnableTargetOutputLogging to true so we guarantee that both loggers see the same value.
115+ // Long-term, unifying s_runningTests to always be true in unit tests (or even removing it completely, if possible) is the best approach.
116+ var initialEnableTargetOutputLogging = Traits . Instance . EnableTargetOutputLogging ;
117+ using var env = TestEnvironment . Create ( ) ;
118+ try
119+ {
120+ env . SetEnvironmentVariable ( "MSBUILDTARGETOUTPUTLOGGING" , "1" ) ;
121+ Traits . Instance . EnableTargetOutputLogging = true ;
105122
106- binaryLogger . Parameters = _logFile ;
123+ var binaryLogger = new BinaryLogger ( ) ;
107124
108- var mockLogFromBuild = new MockLogger ( ) ;
125+ binaryLogger . Parameters = _logFile ;
109126
110- var parallelFromBuildText = new StringBuilder ( ) ;
111- var parallelFromBuild = new ParallelConsoleLogger ( Framework . LoggerVerbosity . Diagnostic , t => parallelFromBuildText . Append ( t ) , colorSet : null , colorReset : null ) ;
112- parallelFromBuild . Parameters = "NOPERFORMANCESUMMARY" ;
127+ var mockLogFromBuild = new MockLogger ( ) ;
113128
114- // build and log into binary logger, mock logger and parallel console loggers
115- // no logging on evaluation
116- using ( ProjectCollection collection = new ( ) )
117- {
118- Project project = ObjectModelHelpers . CreateInMemoryProject ( collection , projectText ) ;
119- project . Build ( new ILogger [ ] { binaryLogger , mockLogFromBuild , parallelFromBuild } ) . ShouldBeTrue ( ) ;
120- }
129+ var parallelFromBuildText = new StringBuilder ( ) ;
130+ var parallelFromBuild = new ParallelConsoleLogger ( Framework . LoggerVerbosity . Diagnostic , t => parallelFromBuildText . Append ( t ) , colorSet : null , colorReset : null ) ;
131+ parallelFromBuild . Parameters = "NOPERFORMANCESUMMARY" ;
121132
122- string fileToReplay ;
123- switch ( replayMode )
124- {
125- case BinlogRoundtripTestReplayMode . NoReplay :
126- fileToReplay = _logFile ;
127- break ;
128- case BinlogRoundtripTestReplayMode . Structured :
129- case BinlogRoundtripTestReplayMode . RawEvents :
130- {
131- var logReader = new BinaryLogReplayEventSource ( ) ;
132- fileToReplay = _env . ExpectFile ( ".binlog" ) . Path ;
133- if ( replayMode == BinlogRoundtripTestReplayMode . Structured )
134- {
135- // need dummy handler to force structured replay
136- logReader . BuildFinished += ( _ , _ ) => { } ;
137- }
133+ // build and log into binary logger, mock logger and parallel console loggers
134+ // no logging on evaluation
135+ using ( ProjectCollection collection = new ( ) )
136+ {
137+ Project project = ObjectModelHelpers . CreateInMemoryProject ( collection , projectText ) ;
138+ project . Build ( new ILogger [ ] { binaryLogger , mockLogFromBuild , parallelFromBuild } ) . ShouldBeTrue ( ) ;
139+ }
138140
139- BinaryLogger outputBinlog = new BinaryLogger ( )
141+ string fileToReplay ;
142+ switch ( replayMode )
143+ {
144+ case BinlogRoundtripTestReplayMode . NoReplay :
145+ fileToReplay = _logFile ;
146+ break ;
147+ case BinlogRoundtripTestReplayMode . Structured :
148+ case BinlogRoundtripTestReplayMode . RawEvents :
140149 {
141- Parameters = fileToReplay
142- } ;
143- outputBinlog . Initialize ( logReader ) ;
144- logReader . Replay ( _logFile ) ;
145- outputBinlog . Shutdown ( ) ;
146- }
147- break ;
148- default :
149- throw new ArgumentOutOfRangeException ( nameof ( replayMode ) , replayMode , null ) ;
150- }
150+ var logReader = new BinaryLogReplayEventSource ( ) ;
151+ fileToReplay = _env . ExpectFile ( ".binlog" ) . Path ;
152+ if ( replayMode == BinlogRoundtripTestReplayMode . Structured )
153+ {
154+ // need dummy handler to force structured replay
155+ logReader . BuildFinished += ( _ , _ ) => { } ;
156+ }
157+
158+ BinaryLogger outputBinlog = new BinaryLogger ( )
159+ {
160+ Parameters = fileToReplay
161+ } ;
162+ outputBinlog . Initialize ( logReader ) ;
163+ logReader . Replay ( _logFile ) ;
164+ outputBinlog . Shutdown ( ) ;
165+ }
166+ break ;
167+ default :
168+ throw new ArgumentOutOfRangeException ( nameof ( replayMode ) , replayMode , null ) ;
169+ }
151170
152- var mockLogFromPlayback = new MockLogger ( ) ;
171+ var mockLogFromPlayback = new MockLogger ( ) ;
153172
154- var parallelFromPlaybackText = new StringBuilder ( ) ;
155- var parallelFromPlayback = new ParallelConsoleLogger ( Framework . LoggerVerbosity . Diagnostic , t => parallelFromPlaybackText . Append ( t ) , colorSet : null , colorReset : null ) ;
156- parallelFromPlayback . Parameters = "NOPERFORMANCESUMMARY" ;
173+ var parallelFromPlaybackText = new StringBuilder ( ) ;
174+ var parallelFromPlayback = new ParallelConsoleLogger ( Framework . LoggerVerbosity . Diagnostic , t => parallelFromPlaybackText . Append ( t ) , colorSet : null , colorReset : null ) ;
175+ parallelFromPlayback . Parameters = "NOPERFORMANCESUMMARY" ;
157176
158- var binaryLogReader = new BinaryLogReplayEventSource ( ) ;
159- mockLogFromPlayback . Initialize ( binaryLogReader ) ;
160- parallelFromPlayback . Initialize ( binaryLogReader ) ;
177+ var binaryLogReader = new BinaryLogReplayEventSource ( ) ;
178+ mockLogFromPlayback . Initialize ( binaryLogReader ) ;
179+ parallelFromPlayback . Initialize ( binaryLogReader ) ;
161180
162- // read the binary log and replay into mockLogger2
163- binaryLogReader . Replay ( fileToReplay ) ;
164- mockLogFromPlayback . Shutdown ( ) ;
165- parallelFromPlayback . Shutdown ( ) ;
181+ // read the binary log and replay into mockLogger2
182+ binaryLogReader . Replay ( fileToReplay ) ;
183+ mockLogFromPlayback . Shutdown ( ) ;
184+ parallelFromPlayback . Shutdown ( ) ;
166185
167- // the binlog will have more information than recorded by the text log
168- mockLogFromPlayback . FullLog . ShouldContainWithoutWhitespace ( mockLogFromBuild . FullLog ) ;
186+ // the binlog will have more information than recorded by the text log
187+ mockLogFromPlayback . FullLog . ShouldContainWithoutWhitespace ( mockLogFromBuild . FullLog ) ;
169188
170- var parallelExpected = parallelFromBuildText . ToString ( ) ;
171- var parallelActual = parallelFromPlaybackText . ToString ( ) ;
189+ var parallelExpected = parallelFromBuildText . ToString ( ) ;
190+ var parallelActual = parallelFromPlaybackText . ToString ( ) ;
172191
173- parallelActual . ShouldContainWithoutWhitespace ( parallelExpected ) ;
192+ parallelActual . ShouldContainWithoutWhitespace ( parallelExpected ) ;
193+ }
194+ finally
195+ {
196+ Traits . Instance . EnableTargetOutputLogging = initialEnableTargetOutputLogging ;
197+ }
174198 }
175199
176200 /// <summary>
0 commit comments