1 using System; 2 using System.Collections.Generic; 3 using System.Diagnostics; 4 using System.IO; 5 using System.Linq; 6 using System.Reflection; 7 using System.Text; 8 using System.Threading.Tasks; 9 using Microsoft.Build.Evaluation; 10 using Microsoft.Build.Shared; 11 using Shouldly; 12 using Xunit; 13 14 namespace Microsoft.Build.Engine.UnitTests 15 { 16 public class BuildEnvironmentHelper_Tests 17 { 18 #if USE_MSBUILD_DLL_EXTN 19 private const string MSBuildExeName = "MSBuild.dll"; 20 #else 21 private const string MSBuildExeName = "MSBuild.exe"; 22 #endif 23 24 [Fact] GetExecutablePath()25 public void GetExecutablePath() 26 { 27 var msbuildPath = Path.GetDirectoryName(FileUtilities.ExecutingAssemblyPath); 28 string expectedMSBuildPath = Path.Combine(msbuildPath, MSBuildExeName).ToLowerInvariant(); 29 30 string configFilePath = BuildEnvironmentHelper.Instance.CurrentMSBuildConfigurationFile.ToLowerInvariant(); 31 string toolsDirectoryPath = BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory.ToLowerInvariant(); 32 string actualMSBuildPath = BuildEnvironmentHelper.Instance.CurrentMSBuildExePath.ToLowerInvariant(); 33 34 configFilePath.ShouldBe($"{actualMSBuildPath}.config"); 35 actualMSBuildPath.ShouldBe(expectedMSBuildPath); 36 Path.GetDirectoryName(expectedMSBuildPath).ShouldBe(toolsDirectoryPath); 37 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.Standalone); 38 } 39 40 [Fact] FindBuildEnvironmentByEnvironmentVariable()41 public void FindBuildEnvironmentByEnvironmentVariable() 42 { 43 using (var env = new EmptyStandaloneEnviroment(MSBuildExeName)) 44 { 45 var path = env.BuildDirectory; 46 var msBuildPath = Path.Combine(path, MSBuildExeName); 47 var msBuildConfig = Path.Combine(path, $"{MSBuildExeName}.config"); 48 49 env.WithEnvironment("MSBUILD_EXE_PATH", env.MSBuildExePath); 50 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 51 52 BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory.ShouldBe(path); 53 BuildEnvironmentHelper.Instance.CurrentMSBuildExePath.ShouldBe(msBuildPath); 54 BuildEnvironmentHelper.Instance.CurrentMSBuildConfigurationFile.ShouldBe(msBuildConfig); 55 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeFalse(); 56 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBeNull(); 57 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeFalse(); 58 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.Standalone); 59 } 60 } 61 62 [Fact] 63 [Trait("Category", "nonlinuxtests")] 64 [Trait("Category", "nonosxtests")] FindBuildEnvironmentFromCommandLineVisualStudio()65 public void FindBuildEnvironmentFromCommandLineVisualStudio() 66 { 67 using (var env = new EmptyVSEnviroment()) 68 { 69 // All we know about is path to msbuild.exe as the command-line arg[0] 70 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.MSBuildExePath, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 71 72 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 73 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory64); 74 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeFalse(); 75 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeFalse(); 76 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 77 } 78 } 79 80 [Fact] FindBuildEnvironmentFromCommandLineStandalone()81 public void FindBuildEnvironmentFromCommandLineStandalone() 82 { 83 // Path will not be under a Visual Studio install like path. 84 using (var env = new EmptyStandaloneEnviroment(MSBuildExeName)) 85 { 86 // All we know about is path to msbuild.exe as the command-line arg[0] 87 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.MSBuildExePath, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 88 89 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 90 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory); 91 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeFalse(); 92 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeFalse(); 93 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.Standalone); 94 } 95 } 96 97 [Fact] 98 [Trait("Category", "nonlinuxtests")] 99 [Trait("Category", "nonosxtests")] FindBuildEnvironmentFromRunningProcessVisualStudio()100 public void FindBuildEnvironmentFromRunningProcessVisualStudio() 101 { 102 using (var env = new EmptyVSEnviroment()) 103 { 104 // All we know about is path to msbuild.exe as the current process 105 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, () => env.MSBuildExePath, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 106 107 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 108 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory64); 109 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeFalse(); 110 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeFalse(); 111 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 112 } 113 } 114 115 [Fact] FindBuildEnvironmentFromRunningProcessStandalone()116 public void FindBuildEnvironmentFromRunningProcessStandalone() 117 { 118 // Path will not be under a Visual Studio install like path. 119 using (var env = new EmptyStandaloneEnviroment(MSBuildExeName)) 120 { 121 // All we know about is path to msbuild.exe as the current process 122 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, () => env.MSBuildExePath, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 123 124 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 125 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory); 126 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeFalse(); 127 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeFalse(); 128 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.Standalone); 129 } 130 } 131 132 [Fact] FindBuildEnvironmentFromExecutingAssemblyAsDll()133 public void FindBuildEnvironmentFromExecutingAssemblyAsDll() 134 { 135 // Ensure the correct file is found (.dll not .exe) 136 using (var env = new EmptyStandaloneEnviroment("MSBuild.dll")) 137 { 138 // All we know about is path to msbuild.exe as the current process 139 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, () => env.MSBuildExePath, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 140 141 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 142 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory); 143 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeFalse(); 144 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeFalse(); 145 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.Standalone); 146 } 147 } 148 149 [Fact] FindBuildEnvironmentFromAppContextDirectory()150 public void FindBuildEnvironmentFromAppContextDirectory() 151 { 152 using (var env = new EmptyStandaloneEnviroment(MSBuildExeName)) 153 { 154 // Only the app base directory will be available 155 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, ReturnNull, () => env.BuildDirectory, env.VsInstanceMock, env.EnvironmentMock, () => false); 156 157 // Make sure we get the right MSBuild entry point. On .NET Core this will be MSBuild.dll, otherwise MSBuild.exe 158 Path.GetFileName(BuildEnvironmentHelper.Instance.CurrentMSBuildExePath).ShouldBe(MSBuildExeName); 159 160 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 161 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory); 162 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeFalse(); 163 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeFalse(); 164 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.Standalone); 165 } 166 } 167 168 [Fact] 169 [Trait("Category", "nonlinuxtests")] 170 [Trait("Category", "nonosxtests")] FindBuildEnvironmentFromVisualStudioRoot()171 public void FindBuildEnvironmentFromVisualStudioRoot() 172 { 173 using (var env = new EmptyVSEnviroment()) 174 { 175 // All we know about is path to DevEnv.exe 176 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.DevEnvPath, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 177 178 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 179 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory64); 180 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 181 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeTrue(); 182 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeFalse(); 183 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 184 } 185 } 186 187 [Fact] 188 [Trait("Category", "nonlinuxtests")] 189 [Trait("Category", "nonosxtests")] BuildEnvironmentDetectsVisualStudioByEnvironment()190 public void BuildEnvironmentDetectsVisualStudioByEnvironment() 191 { 192 using (var env = new EmptyVSEnviroment()) 193 { 194 env.WithEnvironment("VSINSTALLDIR", env.TempFolderRoot); 195 env.WithEnvironment("VisualStudioVersion", "15.0"); 196 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 197 198 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 199 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 200 } 201 } 202 203 [Fact] 204 [Trait("Category", "nonlinuxtests")] 205 [Trait("Category", "nonosxtests")] BuildEnvironmentDetectsVisualStudioByMSBuildProcess()206 public void BuildEnvironmentDetectsVisualStudioByMSBuildProcess() 207 { 208 using (var env = new EmptyVSEnviroment()) 209 { 210 // We only know we're in msbuild.exe, we should still be able to attempt to find Visual Studio 211 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.MSBuildExePath, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 212 213 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 214 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 215 } 216 } 217 218 [Fact] 219 [Trait("Category", "nonlinuxtests")] 220 [Trait("Category", "nonosxtests")] BuildEnvironmentDetectsVisualStudioByMSBuildProcessAmd64()221 public void BuildEnvironmentDetectsVisualStudioByMSBuildProcessAmd64() 222 { 223 using (var env = new EmptyVSEnviroment()) 224 { 225 // We only know we're in amd64\msbuild.exe, we should still be able to attempt to find Visual Studio 226 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.MSBuildExePath64, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 227 228 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 229 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 230 } 231 } 232 233 [Theory] 234 [Trait("Category", "nonlinuxtests")] 235 [Trait("Category", "nonosxtests")] 236 [InlineData("15.0")] 237 [InlineData("15.3")] BuildEnvironmentDetectsVisualStudioFromSetupInstance(string visualStudioVersion)238 public void BuildEnvironmentDetectsVisualStudioFromSetupInstance(string visualStudioVersion) 239 { 240 using (var env = new EmptyVSEnviroment()) 241 { 242 env.WithVsInstance(new VisualStudioInstance("Invalid path", @"c:\_doesnotexist", new Version(visualStudioVersion))); 243 env.WithVsInstance(new VisualStudioInstance("VS", env.TempFolderRoot, new Version(visualStudioVersion))); 244 245 // This test has no context to find MSBuild other than Visual Studio root. 246 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 247 248 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 249 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 250 } 251 } 252 253 [Fact] BuildEnvironmentVisualStudioNotFoundWhenVersionMismatch()254 public void BuildEnvironmentVisualStudioNotFoundWhenVersionMismatch() 255 { 256 using (var env = new EmptyVSEnviroment()) 257 { 258 env.WithVsInstance(new VisualStudioInstance("Invalid path", @"c:\_doesnotexist", new Version("15.0"))); 259 env.WithVsInstance(new VisualStudioInstance("VS", env.TempFolderRoot, new Version("14.0"))); 260 261 // This test has no context to find MSBuild other than Visual Studio root. 262 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 263 264 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBeNull(); 265 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.None); 266 } 267 } 268 269 [Fact] BuildEnvironmentDetectsRunningTests()270 public void BuildEnvironmentDetectsRunningTests() 271 { 272 BuildEnvironmentHelper.Instance.RunningTests.ShouldBeTrue(); 273 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeFalse(); 274 } 275 276 [Fact] 277 [Trait("Category", "nonlinuxtests")] 278 [Trait("Category", "nonosxtests")] BuildEnvironmentDetectsVisualStudioByProcessName()279 public void BuildEnvironmentDetectsVisualStudioByProcessName() 280 { 281 using (var env = new EmptyVSEnviroment()) 282 { 283 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.DevEnvPath, () => env.MSBuildExePath, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 284 285 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeTrue(); 286 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 287 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 288 } 289 } 290 291 [Fact] 292 [Trait("Category", "nonlinuxtests")] 293 [Trait("Category", "nonosxtests")] BuildEnvironmentDetectsVisualStudioByBlendProcess()294 public void BuildEnvironmentDetectsVisualStudioByBlendProcess() 295 { 296 using (var env = new EmptyVSEnviroment()) 297 { 298 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.BlendPath, () => env.MSBuildExePath, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 299 300 BuildEnvironmentHelper.Instance.RunningInVisualStudio.ShouldBeTrue(); 301 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 302 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 303 } 304 } 305 306 [Fact] 307 [Trait("Category", "nonlinuxtests")] 308 [Trait("Category", "nonosxtests")] BuildEnvironmentFindsAmd64()309 public void BuildEnvironmentFindsAmd64() 310 { 311 using (var env = new EmptyVSEnviroment()) 312 { 313 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.DevEnvPath, ReturnNull, 314 ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 315 316 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 317 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory64); 318 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 319 } 320 } 321 322 [Fact] 323 [Trait("Category", "nonlinuxtests")] 324 [Trait("Category", "nonosxtests")] BuildEnvironmentFindsAmd64RunningInAmd64NoVS()325 public void BuildEnvironmentFindsAmd64RunningInAmd64NoVS() 326 { 327 using (var env = new EmptyStandaloneEnviroment(MSBuildExeName, writeFakeFiles:true, includeAmd64Folder:true)) 328 { 329 var msBuild64Exe = Path.Combine(env.BuildDirectory, "amd64", MSBuildExeName); 330 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => msBuild64Exe, ReturnNull, ReturnNull, 331 env.VsInstanceMock, env.EnvironmentMock, () => false); 332 333 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 334 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(Path.Combine(env.BuildDirectory, "amd64")); 335 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBeNull(); 336 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.Standalone); 337 } 338 } 339 340 [Fact] 341 [Trait("Category", "nonlinuxtests")] 342 [Trait("Category", "nonosxtests")] BuildEnvironmentFindsAmd64NoVS()343 public void BuildEnvironmentFindsAmd64NoVS() 344 { 345 using (var env = new EmptyStandaloneEnviroment(MSBuildExeName, writeFakeFiles: true, includeAmd64Folder: true)) 346 { 347 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.MSBuildExePath, ReturnNull, 348 ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 349 350 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 351 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(Path.Combine(env.BuildDirectory, "amd64")); 352 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.Standalone); 353 } 354 } 355 356 [Fact] 357 [Trait("Category", "nonlinuxtests")] 358 [Trait("Category", "nonosxtests")] BuildEnvironmentFindsAmd64RunningInAmd64()359 public void BuildEnvironmentFindsAmd64RunningInAmd64() 360 { 361 using (var env = new EmptyVSEnviroment()) 362 { 363 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => env.MSBuildExePath64, ReturnNull, ReturnNull, env.VsInstanceMock, env.EnvironmentMock, () => false); 364 365 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 366 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory64); 367 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 368 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 369 } 370 } 371 372 [Fact] BuildEnvironmentNoneWhenNotAvailable()373 public void BuildEnvironmentNoneWhenNotAvailable() 374 { 375 using (var env = new EmptyStandaloneEnviroment(MSBuildExeName)) 376 { 377 var entryProcess = Path.Combine(Path.GetTempPath(), "foo.exe"); 378 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(() => entryProcess, ReturnNull, ReturnNull, 379 env.VsInstanceMock, env.EnvironmentMock, () => false); 380 381 BuildEnvironmentHelper.Instance.CurrentMSBuildExePath.ShouldBe(entryProcess); 382 BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory.ShouldBe(Path.GetDirectoryName(entryProcess)); 383 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBeNull(); 384 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.None); 385 } 386 } 387 388 [Fact] 389 [Trait("Category", "nonlinuxtests")] 390 [Trait("Category", "nonosxtests")] BuildEnvironmentVSFromMSBuildAssembly()391 public void BuildEnvironmentVSFromMSBuildAssembly() 392 { 393 using (var env = new EmptyVSEnviroment()) 394 { 395 var msBuildAssembly = Path.Combine(env.BuildDirectory, "Microsoft.Build.dll"); 396 397 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, () => msBuildAssembly, ReturnNull, 398 env.VsInstanceMock, env.EnvironmentMock, () => false); 399 400 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 401 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory64); 402 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 403 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 404 } 405 } 406 407 [Fact] 408 [Trait("Category", "nonlinuxtests")] 409 [Trait("Category", "nonosxtests")] BuildEnvironmentVSFromMSBuildAssemblyAmd64()410 public void BuildEnvironmentVSFromMSBuildAssemblyAmd64() 411 { 412 using (var env = new EmptyVSEnviroment()) 413 { 414 var msBuildAssembly = Path.Combine(env.BuildDirectory64, "Microsoft.Build.dll"); 415 416 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(ReturnNull, () => msBuildAssembly, ReturnNull, 417 env.VsInstanceMock, env.EnvironmentMock, () => false); 418 419 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32.ShouldBe(env.BuildDirectory); 420 BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64.ShouldBe(env.BuildDirectory64); 421 BuildEnvironmentHelper.Instance.VisualStudioInstallRootDirectory.ShouldBe(env.TempFolderRoot); 422 BuildEnvironmentHelper.Instance.Mode.ShouldBe(BuildEnvironmentMode.VisualStudio); 423 } 424 } 425 ReturnNull()426 private static string ReturnNull() 427 { 428 return null; 429 } 430 431 private class EmptyVSEnviroment : EmptyStandaloneEnviroment 432 { 433 public string DevEnvPath { get; } 434 435 public string BlendPath { get; } 436 437 public string BuildDirectory64 { get; } 438 439 public string MSBuildExePath64 => Path.Combine(BuildDirectory64, MSBuildExeName); 440 EmptyVSEnviroment()441 public EmptyVSEnviroment() : base("msbuild.exe", false) 442 { 443 try 444 { 445 var files = new[] { "msbuild.exe", "msbuild.exe.config" }; 446 BuildDirectory = Path.Combine(TempFolderRoot, "MSBuild", "15.0", "Bin"); 447 BuildDirectory64 = Path.Combine(BuildDirectory, "amd64"); 448 DevEnvPath = Path.Combine(TempFolderRoot, "Common7", "IDE", "devenv.exe"); 449 BlendPath = Path.Combine(TempFolderRoot, "Common7", "IDE", "blend.exe"); 450 451 Directory.CreateDirectory(BuildDirectory); 452 foreach (var file in files) 453 { 454 File.WriteAllText(Path.Combine(BuildDirectory, file), string.Empty); 455 } 456 457 Directory.CreateDirectory(BuildDirectory64); 458 foreach (var file in files) 459 { 460 File.WriteAllText(Path.Combine(BuildDirectory64, file), string.Empty); 461 } 462 463 Directory.CreateDirectory(Path.Combine(TempFolderRoot, "Common7", "IDE")); 464 File.WriteAllText(DevEnvPath, string.Empty); 465 } 466 catch (Exception) 467 { 468 FileUtilities.DeleteDirectoryNoThrow(BuildDirectory, true); 469 throw; 470 } 471 } 472 } 473 474 private class EmptyStandaloneEnviroment : IDisposable 475 { 476 public string TempFolderRoot { get; } 477 478 public string BuildDirectory { get; protected set; } 479 480 public string MSBuildExeName { get; } 481 482 public string MSBuildExePath => Path.Combine(BuildDirectory, MSBuildExeName); 483 484 private readonly Dictionary<string, string> _mockEnvironment = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); 485 486 private readonly List<VisualStudioInstance> _mockInstances = new List<VisualStudioInstance>(); 487 EmptyStandaloneEnviroment(string msBuildExeName, bool writeFakeFiles = true, bool includeAmd64Folder = false)488 public EmptyStandaloneEnviroment(string msBuildExeName, bool writeFakeFiles = true, bool includeAmd64Folder = false) 489 { 490 try 491 { 492 MSBuildExeName = msBuildExeName; 493 TempFolderRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); 494 BuildDirectory = Path.Combine(TempFolderRoot, "MSBuild"); 495 496 Directory.CreateDirectory(BuildDirectory); 497 if (writeFakeFiles) 498 { 499 File.WriteAllText(MSBuildExePath, string.Empty); 500 File.WriteAllText($"{MSBuildExePath}.config", string.Empty); 501 502 if (includeAmd64Folder) 503 { 504 Directory.CreateDirectory(Path.Combine(BuildDirectory, "amd64")); 505 File.WriteAllText(Path.Combine(BuildDirectory, "amd64", msBuildExeName), string.Empty); 506 File.WriteAllText(Path.Combine(BuildDirectory, "amd64", $"{MSBuildExePath}.config"), string.Empty); 507 } 508 } 509 } 510 catch (Exception) 511 { 512 FileUtilities.DeleteDirectoryNoThrow(BuildDirectory, true); 513 throw; 514 } 515 } 516 WithEnvironment(string variable, string value)517 public void WithEnvironment(string variable, string value) 518 { 519 _mockEnvironment.Add(variable, value); 520 } 521 WithVsInstance(VisualStudioInstance instance)522 public void WithVsInstance(VisualStudioInstance instance) 523 { 524 _mockInstances.Add(instance); 525 } 526 EnvironmentMock(string variable)527 public string EnvironmentMock(string variable) 528 { 529 return _mockEnvironment.ContainsKey(variable) ? _mockEnvironment[variable] : null; 530 } 531 VsInstanceMock()532 public IEnumerable<VisualStudioInstance> VsInstanceMock() 533 { 534 return _mockInstances; 535 } 536 Dispose()537 public void Dispose() 538 { 539 FileUtilities.DeleteDirectoryNoThrow(TempFolderRoot, true); 540 BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly(runningTests: () => true); 541 } 542 } 543 } 544 } 545