1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 4 using System; 5 using System.Collections.Generic; 6 using System.IO; 7 using System.Resources; 8 using System.Threading; 9 10 using Microsoft.Build.Framework; 11 using Microsoft.Build.Shared; 12 using Microsoft.Build.Tasks; 13 using Microsoft.Build.Utilities; 14 using Xunit; 15 16 17 18 #pragma warning disable 0219 19 20 #if FEATURE_FILE_TRACKER 21 22 namespace Microsoft.Build.UnitTests.TrackedDependencies 23 { 24 sealed public class TrackedDependenciesTests 25 { 26 private readonly int _sleepTimeMilliseconds = NativeMethodsShared.IsWindows ? 100 : 1000; 27 TrackedDependenciesTests()28 public TrackedDependenciesTests() 29 { 30 string tempPath = Path.GetTempPath(); 31 string tempTestFilesPath = Path.Combine(tempPath, "TestFiles"); 32 33 if (Directory.Exists("TestFiles")) 34 { 35 for (int i = 0; i < 5; i++) 36 { 37 try 38 { 39 Directory.Delete("TestFiles", true /* recursive */); 40 break; 41 } 42 catch (Exception) 43 { 44 Thread.Sleep(1000); 45 // Eat exceptions from the delete 46 } 47 } 48 } 49 50 if (Directory.Exists(tempTestFilesPath)) 51 { 52 for (int i = 0; i < 5; i++) 53 { 54 try 55 { 56 Directory.Delete(tempTestFilesPath, true /* recursive */); 57 break; 58 } 59 catch (Exception) 60 { 61 Thread.Sleep(1000); 62 // Eat exceptions from the delete 63 } 64 } 65 } 66 67 Directory.CreateDirectory(tempTestFilesPath); 68 Directory.CreateDirectory("TestFiles"); 69 70 // Sleep for a period before each test is run so that 71 // there is enough time for files to have distinct 72 // last modified times - this ensures that the tracking 73 // dependency caching of tracking logs (which is based on 74 // last write time) can be relied upon 75 Thread.Sleep(_sleepTimeMilliseconds); 76 } 77 78 /// <summary> 79 /// Tests DependencyTableCache.FormatNormalizedTlogRootingMarker, which should do effectively the same 80 /// thing as FileTracker.FormatRootingMarker, except with some extra initial normalization to get rid of 81 /// pesky PIDs and TIDs in the tlog names. 82 /// </summary> 83 [Fact] FormatNormalizedRootingMarkerTests()84 public void FormatNormalizedRootingMarkerTests() 85 { 86 Dictionary<ITaskItem[], string> tests = new Dictionary<ITaskItem[], string>(); 87 tests.Add 88 ( 89 new ITaskItem[1] { new TaskItem("Debug\\link.9999-cvtres.write.1.tlog") }, 90 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.[ID]-cvtres.write.[ID].tlog").ToUpperInvariant() 91 ); 92 tests.Add 93 ( 94 new ITaskItem[1] { new TaskItem("Debug\\link.0000-cvtres.read.1.tlog") }, 95 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.[ID]-cvtres.read.[ID].tlog").ToUpperInvariant() 96 ); 97 tests.Add 98 ( 99 new ITaskItem[1] { new TaskItem("Debug\\link.4567-cvtres.write.1.tlog") }, 100 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.[ID]-cvtres.write.[ID].tlog").ToUpperInvariant() 101 ); 102 tests.Add 103 ( 104 new ITaskItem[1] { new TaskItem("Debug\\link.9999.write.1.tlog") }, 105 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.[ID].write.[ID].tlog").ToUpperInvariant() 106 ); 107 tests.Add 108 ( 109 new ITaskItem[1] { new TaskItem("Debug\\link.0000.read.1.tlog") }, 110 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.[ID].read.[ID].tlog").ToUpperInvariant() 111 ); 112 tests.Add 113 ( 114 new ITaskItem[1] { new TaskItem("Debug\\link.4567.write.1.tlog") }, 115 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.[ID].write.[ID].tlog").ToUpperInvariant() 116 ); 117 tests.Add 118 ( 119 new ITaskItem[1] { new TaskItem("Debug\\link2345.write.1.tlog") }, 120 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link2345.write.[ID].tlog").ToUpperInvariant() 121 ); 122 tests.Add 123 ( 124 new ITaskItem[1] { new TaskItem("link.4567.write.1.tlog") }, 125 Path.Combine(Directory.GetCurrentDirectory(), "link.[ID].write.[ID].tlog").ToUpperInvariant() 126 ); 127 tests.Add 128 ( 129 new ITaskItem[1] { new TaskItem("Debug\\a.1234.b\\link.4567.write.1.tlog") }, 130 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\a.1234.b\\link.[ID].write.[ID].tlog").ToUpperInvariant() 131 ); 132 tests.Add 133 ( 134 new ITaskItem[1] { new TaskItem("link.write.tlog") }, 135 Path.Combine(Directory.GetCurrentDirectory(), "link.write.tlog").ToUpperInvariant() 136 ); 137 tests.Add 138 ( 139 new ITaskItem[1] { new TaskItem("link%20with%20spaces.write.3.tlog") }, 140 Path.Combine(Directory.GetCurrentDirectory(), "link with spaces.write.[ID].tlog").ToUpperInvariant() 141 ); 142 tests.Add 143 ( 144 new ITaskItem[2] { new TaskItem("link.write.tlog"), new TaskItem("Debug\\link2345.write.1.tlog") }, 145 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link2345.write.[ID].tlog").ToUpperInvariant() + "|" + 146 Path.Combine(Directory.GetCurrentDirectory(), "link.write.tlog").ToUpperInvariant() 147 ); 148 tests.Add 149 ( 150 new ITaskItem[1] { new TaskItem("link.write.tlog1234") }, 151 Path.Combine(Directory.GetCurrentDirectory(), "link.write.tlog1234").ToUpperInvariant() 152 ); 153 tests.Add 154 ( 155 new ITaskItem[1] { new TaskItem("1234link.write.tlog") }, 156 Path.Combine(Directory.GetCurrentDirectory(), "1234link.write.tlog").ToUpperInvariant() 157 ); 158 tests.Add 159 ( 160 new ITaskItem[1] { new TaskItem("link-1234.write.tlog") }, 161 Path.Combine(Directory.GetCurrentDirectory(), "link-1234.write.tlog").ToUpperInvariant() 162 ); 163 tests.Add 164 ( 165 new ITaskItem[1] { new TaskItem("C:\\Debug\\a.1234.b\\link.4567.write.1.tlog") }, 166 "C:\\DEBUG\\A.1234.B\\LINK.[ID].WRITE.[ID].TLOG" 167 ); 168 tests.Add 169 ( 170 new ITaskItem[1] { new TaskItem("a\\") }, 171 Path.Combine(Directory.GetCurrentDirectory(), "a\\").ToUpperInvariant() 172 ); 173 tests.Add 174 ( 175 new ITaskItem[1] { new TaskItem("Debug\\link.45\\67.write.1.tlog") }, 176 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.45\\67.write.[ID].tlog").ToUpperInvariant() 177 ); 178 tests.Add 179 ( 180 new ITaskItem[1] { new TaskItem("Debug\\link.4567.write.1.tlog\\") }, 181 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.4567.write.1.tlog\\").ToUpperInvariant() 182 ); 183 tests.Add 184 ( 185 new ITaskItem[0] { }, 186 "" 187 ); 188 tests.Add 189 ( 190 new ITaskItem[3] 191 { 192 new TaskItem("Debug\\link.write.1.tlog"), 193 new TaskItem("Debug\\link.2345.write.1.tlog"), 194 new TaskItem("Debug\\link.2345-cvtres.6789-mspdbsrv.1111.write.4.tlog") 195 }, 196 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.write.[ID].tlog").ToUpperInvariant() + "|" + 197 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.[ID]-cvtres.[ID]-mspdbsrv.[ID].write.[ID].tlog").ToUpperInvariant() + "|" + 198 Path.Combine(Directory.GetCurrentDirectory(), "Debug\\link.[ID].write.[ID].tlog").ToUpperInvariant() 199 ); 200 tests.Add 201 ( 202 new ITaskItem[3] { new TaskItem("link.1234-write.1.tlog"), new TaskItem("link.1234-write.3.tlog"), new TaskItem("cl.write.2.tlog") }, 203 Path.Combine(Directory.GetCurrentDirectory(), "cl.write.[ID].tlog").ToUpperInvariant() + "|" + 204 Path.Combine(Directory.GetCurrentDirectory(), "link.[ID]-write.[ID].tlog").ToUpperInvariant() 205 ); 206 tests.Add 207 ( 208 new ITaskItem[3] { new TaskItem("lINk.1234-write.1.tlog"), new TaskItem("link.1234-WRitE.3.tlog"), new TaskItem("cl.write.2.tlog") }, 209 Path.Combine(Directory.GetCurrentDirectory(), "cl.write.[ID].tlog").ToUpperInvariant() + "|" + 210 Path.Combine(Directory.GetCurrentDirectory(), "link.[ID]-write.[ID].tlog").ToUpperInvariant() 211 ); 212 tests.Add 213 ( 214 new ITaskItem[3] { new TaskItem("a\\link.1234-write.1.tlog"), new TaskItem("b\\link.1234-write.3.tlog"), new TaskItem("cl.write.2.tlog") }, 215 Path.Combine(Directory.GetCurrentDirectory(), "a\\link.[ID]-write.[ID].tlog").ToUpperInvariant() + "|" + 216 Path.Combine(Directory.GetCurrentDirectory(), "b\\link.[ID]-write.[ID].tlog").ToUpperInvariant() + "|" + 217 Path.Combine(Directory.GetCurrentDirectory(), "cl.write.[ID].tlog").ToUpperInvariant() 218 ); 219 tests.Add 220 ( 221 new ITaskItem[1] { new TaskItem("foo\\.tlog") }, 222 Path.Combine(Directory.GetCurrentDirectory(), "foo\\.tlog").ToUpperInvariant() 223 ); 224 tests.Add 225 ( 226 new ITaskItem[1] { new TaskItem("foo\\1.tlog") }, 227 Path.Combine(Directory.GetCurrentDirectory(), "foo\\1.tlog").ToUpperInvariant() 228 ); 229 tests.Add 230 ( 231 new ITaskItem[1] { new TaskItem("\\1.tlog") }, 232 Path.Combine(Path.GetPathRoot(Directory.GetCurrentDirectory()), "1.tlog").ToUpperInvariant() 233 ); 234 tests.Add 235 ( 236 new ITaskItem[1] { new TaskItem(".1.tlog") }, 237 Path.Combine(Directory.GetCurrentDirectory(), ".[ID].tlog").ToUpperInvariant() 238 ); 239 tests.Add 240 ( 241 new ITaskItem[1] { new TaskItem("-2") }, 242 Path.Combine(Directory.GetCurrentDirectory(), "-2").ToUpperInvariant() 243 ); 244 tests.Add 245 ( 246 new ITaskItem[1] { new TaskItem(".2") }, 247 Path.Combine(Directory.GetCurrentDirectory(), ".2").ToUpperInvariant() 248 ); 249 tests.Add 250 ( 251 new ITaskItem[1] { new TaskItem("2-") }, 252 Path.Combine(Directory.GetCurrentDirectory(), "2-").ToUpperInvariant() 253 ); 254 tests.Add 255 ( 256 new ITaskItem[1] { new TaskItem("2.") }, 257 Path.Combine(Directory.GetCurrentDirectory(), "2").ToUpperInvariant() 258 ); 259 tests.Add 260 ( 261 new ITaskItem[1] { new TaskItem("\\.1.tlog") }, 262 Path.Combine(Path.GetPathRoot(Directory.GetCurrentDirectory()), ".[ID].tlog").ToUpperInvariant() 263 ); 264 tests.Add 265 ( 266 new ITaskItem[1] { new TaskItem("\\") }, 267 Path.GetPathRoot(Directory.GetCurrentDirectory()).ToUpperInvariant() 268 ); 269 tests.Add 270 ( 271 new ITaskItem[1] { new TaskItem("\\\\share\\foo.read.8.tlog") }, 272 "\\\\share\\foo.read.[ID].tlog".ToUpperInvariant() 273 ); 274 foreach (KeyValuePair<ITaskItem[], string> test in tests) 275 { 276 Assert.Equal(test.Value, DependencyTableCache.FormatNormalizedTlogRootingMarker(test.Key)); // "Incorrectly formatted rooting marker" 277 } 278 279 bool exceptionCaught = false; 280 try 281 { 282 DependencyTableCache.FormatNormalizedTlogRootingMarker(new ITaskItem[1] { new TaskItem("\\\\") }); 283 } 284 catch (ArgumentException) 285 { 286 exceptionCaught = true; 287 } 288 289 Assert.True(exceptionCaught); // "Should have failed to format a rooting marker from a malformed UNC path" 290 } 291 292 [Fact] CreateTrackedDependencies()293 public void CreateTrackedDependencies() 294 { 295 Console.WriteLine("Test: CreateTrackedDependencies"); 296 ITaskItem[] sources = null; 297 ITaskItem[] outputs = null; 298 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 299 ( 300 DependencyTestHelper.MockTask, 301 null, 302 sources, 303 null, 304 outputs, 305 false, /* no minimal rebuild optimization */ 306 false /* shred composite rooting markers */ 307 ); 308 Assert.NotNull(d); 309 } 310 311 [Fact] SingleCanonicalCL()312 public void SingleCanonicalCL() 313 { 314 Console.WriteLine("Test: SingleCanonicalCL"); 315 // Prepare files 316 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 317 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 318 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 319 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 320 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 321 "#Command some-command", 322 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 323 Path.GetFullPath(Path.Combine("TestFiles", "oNe.h")), 324 }); 325 326 // Touch one 327 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 328 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 329 330 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 331 ( 332 DependencyTestHelper.MockTask, 333 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 334 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 335 null, 336 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 337 false, /* no minimal rebuild optimization */ 338 false /* shred composite rooting markers */ 339 ); 340 341 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 342 343 Assert.Equal(1, outofdate.Length); 344 Assert.Equal(outofdate[0].ItemSpec, "TestFiles\\one.cpp"); 345 } 346 347 [Fact] NonExistentTlog()348 public void NonExistentTlog() 349 { 350 Console.WriteLine("Test: NonExistentTlog"); 351 // Prepare files 352 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 353 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 354 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 355 356 // Just to be sure, delete the test tlog. 357 File.Delete(Path.Combine("TestFiles", "one.tlog")); 358 359 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 360 ( 361 DependencyTestHelper.MockTask, 362 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 363 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 364 null, 365 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 366 false, /* no minimal rebuild optimization */ 367 false /* shred composite rooting markers */ 368 ); 369 370 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 371 372 Assert.Equal(1, outofdate.Length); 373 Assert.Equal(outofdate[0].ItemSpec, Path.Combine("TestFiles", "one.cpp")); 374 } 375 376 [Fact] EmptyTLog()377 public void EmptyTLog() 378 { 379 Console.WriteLine("Test: EmptyTLog"); 380 381 // Prepare files 382 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 383 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 384 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 385 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tlog"), ""); 386 387 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 388 ( 389 DependencyTestHelper.MockTask, 390 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 391 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 392 null, 393 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 394 false, /* no minimal rebuild optimization */ 395 false /* shred composite rooting markers */ 396 ); 397 398 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 399 400 Assert.Equal(1, outofdate.Length); 401 Assert.Equal(outofdate[0].ItemSpec, Path.Combine("TestFiles", "one.cpp")); 402 } 403 404 [Fact] InvalidReadTLogName()405 public void InvalidReadTLogName() 406 { 407 Console.WriteLine("Test: InvalidReadTLogName"); 408 409 // Prepare files 410 DependencyTestHelper.WriteAll("TestFiles\\one.h", ""); 411 DependencyTestHelper.WriteAll("TestFiles\\one.cpp", ""); 412 DependencyTestHelper.WriteAll("TestFiles\\one.obj", ""); 413 DependencyTestHelper.WriteAll("TestFiles\\one.tlog", ""); 414 415 MockTask task = DependencyTestHelper.MockTask; 416 417 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 418 ( 419 task, 420 DependencyTestHelper.ItemArray(new TaskItem("TestFiles\\|one|.tlog")), 421 DependencyTestHelper.ItemArray(new TaskItem("TestFiles\\one.cpp")), 422 null, 423 DependencyTestHelper.ItemArray(new TaskItem("TestFiles\\one.obj")), 424 false, /* no minimal rebuild optimization */ 425 false /* shred composite rooting markers */ 426 ); 427 428 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 429 430 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have an error." 431 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 432 } 433 434 [Fact] ReadTLogWithInitialEmptyLine()435 public void ReadTLogWithInitialEmptyLine() 436 { 437 Console.WriteLine("Test: ReadTLogWithInitialEmptyLine"); 438 439 // Prepare files 440 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 441 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 442 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 443 444 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { "", "^FOO" }); 445 MockTask task = DependencyTestHelper.MockTask; 446 447 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 448 ( 449 task, 450 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 451 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 452 null, 453 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 454 false, /* no minimal rebuild optimization */ 455 false /* shred composite rooting markers */ 456 ); 457 458 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 459 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 460 } 461 462 [Fact] ReadTLogWithEmptyLineImmediatelyAfterRoot()463 public void ReadTLogWithEmptyLineImmediatelyAfterRoot() 464 { 465 Console.WriteLine("Test: ReadTLogWithEmptyLineImmediatelyAfterRoot"); 466 467 // Prepare files 468 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 469 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 470 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 471 472 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { "^FOO", "", "FOO" }); 473 MockTask task = DependencyTestHelper.MockTask; 474 475 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 476 ( 477 task, 478 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 479 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 480 null, 481 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 482 false, /* no minimal rebuild optimization */ 483 false /* shred composite rooting markers */ 484 ); 485 486 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 487 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 488 } 489 490 [Fact] ReadTLogWithEmptyLineBetweenRoots()491 public void ReadTLogWithEmptyLineBetweenRoots() 492 { 493 Console.WriteLine("Test: ReadTLogWithEmptyLineImmediatelyAfterRoot"); 494 495 // Prepare files 496 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 497 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 498 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 499 500 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { "^FOO", "FOO", "", "^BAR", "BAR" }); 501 MockTask task = DependencyTestHelper.MockTask; 502 503 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 504 ( 505 task, 506 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 507 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 508 null, 509 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 510 false, /* no minimal rebuild optimization */ 511 false /* shred composite rooting markers */ 512 ); 513 514 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 515 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 516 } 517 518 [Fact] ReadTLogWithEmptyRoot()519 public void ReadTLogWithEmptyRoot() 520 { 521 Console.WriteLine("Test: ReadTLogWithEmptyRoot"); 522 523 // Prepare files 524 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 525 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 526 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 527 528 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { "^", "FOO" }); 529 MockTask task = DependencyTestHelper.MockTask; 530 531 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 532 ( 533 task, 534 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 535 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 536 null, 537 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 538 false, /* no minimal rebuild optimization */ 539 false /* shred composite rooting markers */ 540 ); 541 542 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 543 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 544 } 545 546 [Fact] ReadTLogWithDuplicateInRoot()547 public void ReadTLogWithDuplicateInRoot() 548 { 549 Console.WriteLine("Test: ReadTLogWithDuplicateInRoot"); 550 551 //Prepare files 552 DependencyTestHelper.WriteAll("TestFiles\\one.h", ""); 553 DependencyTestHelper.WriteAll("TestFiles\\foo.cpp", ""); 554 DependencyTestHelper.WriteAll("TestFiles\\one.obj", ""); 555 556 ITaskItem[] sources = new ITaskItem[] { new TaskItem("TestFiles\\foo.cpp"), new TaskItem("TestFiles\\foo.cpp") }; 557 558 File.WriteAllLines("TestFiles\\one.tlog", new string[] { "^TestFiles\\foo.cpp|TestFiles\\foo.cpp", "TestFiles\\bar.cpp", "TestFiles\\foo.cpp" }); 559 MockTask task = DependencyTestHelper.MockTask; 560 561 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 562 ( 563 task, 564 DependencyTestHelper.ItemArray(new TaskItem("TestFiles\\one.tlog")), 565 sources, 566 null, 567 DependencyTestHelper.ItemArray(new TaskItem("TestFiles\\one.obj")), 568 false, /* no minimal rebuild optimization */ 569 false /* shred composite rooting markers */ 570 ); 571 572 Assert.NotEqual(0, d.DependencyTable.Count); // "Dependency Table should not be empty." 573 } 574 575 [Fact] InvalidWriteTLogName()576 public void InvalidWriteTLogName() 577 { 578 Console.WriteLine("Test: InvalidWriteTLogName"); 579 580 MockTask task = DependencyTestHelper.MockTask; 581 582 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles 583 ( 584 task, 585 DependencyTestHelper.ItemArray(new TaskItem("TestFiles\\|one|.write.tlog")) 586 ); 587 588 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have an error." 589 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 590 } 591 592 [Fact] WriteTLogWithInitialEmptyLine()593 public void WriteTLogWithInitialEmptyLine() 594 { 595 Console.WriteLine("Test: WriteTLogWithInitialEmptyLine"); 596 597 // Prepare files 598 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { "", "^FOO" }); 599 MockTask task = DependencyTestHelper.MockTask; 600 601 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles 602 ( 603 task, 604 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))) 605 ); 606 607 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 608 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 609 } 610 611 [Fact] WriteTLogWithEmptyLineImmediatelyAfterRoot()612 public void WriteTLogWithEmptyLineImmediatelyAfterRoot() 613 { 614 Console.WriteLine("Test: ReadTLogWithEmptyLineImmediatelyAfterRoot"); 615 616 // Prepare files 617 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { "^FOO", "", "FOO" }); 618 MockTask task = DependencyTestHelper.MockTask; 619 620 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles 621 ( 622 task, 623 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))) 624 ); 625 626 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 627 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 628 } 629 630 [Fact] WriteTLogWithEmptyLineBetweenRoots()631 public void WriteTLogWithEmptyLineBetweenRoots() 632 { 633 Console.WriteLine("Test: WriteTLogWithEmptyLineImmediatelyAfterRoot"); 634 635 // Prepare files 636 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { "^FOO", "FOO", "", "^BAR", "BAR" }); 637 MockTask task = DependencyTestHelper.MockTask; 638 639 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles 640 ( 641 task, 642 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))) 643 ); 644 645 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 646 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 647 } 648 649 [Fact] WriteTLogWithEmptyRoot()650 public void WriteTLogWithEmptyRoot() 651 { 652 Console.WriteLine("Test: WriteTLogWithEmptyRoot"); 653 654 // Prepare files 655 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { "^", "FOO" }); 656 MockTask task = DependencyTestHelper.MockTask; 657 658 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles 659 ( 660 task, 661 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))) 662 ); 663 664 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 665 Assert.Equal(0, d.DependencyTable.Count); // "DependencyTable should be empty." 666 } 667 668 [Fact] PrimarySourceNotInTlog()669 public void PrimarySourceNotInTlog() 670 { 671 Console.WriteLine("Test: PrimarySourceNotInTlog"); 672 // Prepare files 673 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 674 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 675 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 676 677 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 678 // Primary Source; not appearing in this Tlog.. 679 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 680 "#Command some-command", 681 Path.GetFullPath(Path.Combine("TestFiles", "foo.cpp")), 682 Path.GetFullPath(Path.Combine("TestFiles", "foo.h")), 683 }); 684 685 // Touch the obj - normally this would mean uptodate, but since there 686 // is no tlog entry for the primary source, we want a rebuild of it. 687 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 688 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 689 690 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 691 ( 692 DependencyTestHelper.MockTask, 693 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 694 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 695 null, 696 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 697 false, /* no minimal rebuild optimization */ 698 false /* shred composite rooting markers */ 699 ); 700 701 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 702 703 Assert.Equal(1, outofdate.Length); 704 Assert.Equal(outofdate[0].ItemSpec, Path.Combine("TestFiles", "one.cpp")); 705 } 706 707 [Fact] MultipleCanonicalCL()708 public void MultipleCanonicalCL() 709 { 710 Console.WriteLine("Test: MultipleCanonicalCL"); 711 // Prepare files 712 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 713 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 714 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 715 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 716 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 717 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 718 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 719 "#Command some-command", 720 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 721 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 722 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 723 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 724 }); 725 726 // Touch one 727 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 728 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 729 730 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 731 ( 732 DependencyTestHelper.MockTask, 733 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 734 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 735 null, 736 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 737 false, /* no minimal rebuild optimization */ 738 false /* shred composite rooting markers */ 739 ); 740 741 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 742 743 Assert.Equal(1, outofdate.Length); 744 Assert.Equal(outofdate[0].ItemSpec, Path.Combine("TestFiles", "one.cpp")); 745 } 746 747 [Fact] MultipleCanonicalCLCompactMissingOnSuccess()748 public void MultipleCanonicalCLCompactMissingOnSuccess() 749 { 750 Console.WriteLine("Test: MultipleCanonicalCLCompactMissingOnSuccess"); 751 // Prepare files 752 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 753 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 754 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 755 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 756 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 757 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 758 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 759 "#Command some-command", 760 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 761 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 762 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 763 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 764 }); 765 766 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 767 "#Command some-command", 768 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 769 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 770 Path.GetFullPath(Path.Combine("TestFiles", "sometempfile.obj")) 771 }); 772 773 CanonicalTrackedOutputFiles compactOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 774 compactOutputs.RemoveDependenciesFromEntryIfMissing(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 775 compactOutputs.SaveTlog(); 776 777 // Compact the read tlog 778 CanonicalTrackedInputFiles compactInputs = new CanonicalTrackedInputFiles 779 ( 780 DependencyTestHelper.MockTask, 781 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 782 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 783 null, 784 compactOutputs, 785 false, /* no minimal rebuild optimization */ 786 false /* shred composite rooting markers */ 787 ); 788 789 compactInputs.RemoveDependenciesFromEntryIfMissing(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 790 compactInputs.SaveTlog(); 791 792 CanonicalTrackedOutputFiles outputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 793 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 794 795 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 796 ( 797 DependencyTestHelper.MockTask, 798 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 799 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 800 null, 801 outputs, 802 false, /* no minimal rebuild optimization */ 803 false /* shred composite rooting markers */ 804 ); 805 806 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 807 808 Assert.Equal(0, outofdate.Length); 809 } 810 811 [Fact] MultipleCanonicalCLCompactMissingOnSuccessMultiEntry()812 public void MultipleCanonicalCLCompactMissingOnSuccessMultiEntry() 813 { 814 Console.WriteLine("Test: MultipleCanonicalCLCompactMissingOnSuccessMultiEntry"); 815 // Prepare files 816 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 817 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 818 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 819 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 820 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 821 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 822 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 823 "#Command some-command", 824 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 825 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 826 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 827 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 828 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 829 Path.GetFullPath(Path.Combine("TestFiles", "two1.h")), 830 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 831 }); 832 833 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 834 "#Command some-command", 835 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 836 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 837 Path.GetFullPath(Path.Combine("TestFiles", "sometempfile.obj")), 838 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 839 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 840 Path.GetFullPath(Path.Combine("TestFiles", "sometempfile2.obj")) 841 }); 842 843 CanonicalTrackedOutputFiles compactOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 844 compactOutputs.RemoveDependenciesFromEntryIfMissing(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 845 compactOutputs.SaveTlog(); 846 // Compact the read tlog 847 CanonicalTrackedInputFiles compactInputs = new CanonicalTrackedInputFiles 848 ( 849 DependencyTestHelper.MockTask, 850 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 851 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 852 null, 853 compactOutputs, 854 false, /* no minimal rebuild optimization */ 855 false /* shred composite rooting markers */ 856 ); 857 858 compactInputs.RemoveDependenciesFromEntryIfMissing(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 859 compactInputs.SaveTlog(); 860 861 CanonicalTrackedOutputFiles writtenOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 862 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 863 864 CanonicalTrackedInputFiles writtenInputs = new CanonicalTrackedInputFiles 865 ( 866 DependencyTestHelper.MockTask, 867 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 868 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 869 null, 870 writtenOutputs, 871 false, /* no minimal rebuild optimization */ 872 false /* shred composite rooting markers */ 873 ); 874 875 Assert.Equal(1, writtenOutputs.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))].Count); 876 Assert.Equal(4, writtenInputs.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))].Count); 877 // Everything to do with two.cpp should be left intact 878 Assert.Equal(2, writtenOutputs.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))].Count); 879 Assert.Equal(3, writtenInputs.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))].Count); 880 } 881 882 [Fact] RemoveDependencyFromEntry()883 public void RemoveDependencyFromEntry() 884 { 885 Console.WriteLine("Test: RemoveDependencyFromEntry"); 886 // Prepare files 887 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 888 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 889 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 890 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 891 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 892 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tlh"), ""); 893 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tli"), ""); 894 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 895 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 896 "#Command some-command", 897 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 898 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 899 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 900 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 901 Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")), 902 Path.GetFullPath(Path.Combine("TestFiles", "one3.tlh")), 903 Path.GetFullPath(Path.Combine("TestFiles", "one3.tli")), 904 }); 905 906 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 907 "#Command some-command", 908 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 909 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 910 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 911 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 912 Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")), 913 Path.GetFullPath(Path.Combine("TestFiles", "one3.tlh")), 914 Path.GetFullPath(Path.Combine("TestFiles", "one3.tli")), 915 }); 916 917 CanonicalTrackedOutputFiles compactOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 918 compactOutputs.RemoveDependencyFromEntry(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")))); 919 compactOutputs.SaveTlog(); 920 921 CanonicalTrackedOutputFiles writtenOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 922 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 923 924 Assert.False(writtenOutputs.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))].ContainsKey(Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")))); 925 926 CanonicalTrackedInputFiles compactInputs = new CanonicalTrackedInputFiles 927 ( 928 DependencyTestHelper.MockTask, 929 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 930 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 931 null, 932 compactOutputs, 933 false, /* no minimal rebuild optimization */ 934 false /* shred composite rooting markers */ 935 ); 936 937 compactInputs.RemoveDependencyFromEntry(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")))); 938 compactInputs.SaveTlog(); 939 940 CanonicalTrackedInputFiles writtenInputs = new CanonicalTrackedInputFiles 941 ( 942 DependencyTestHelper.MockTask, 943 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 944 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 945 null, 946 writtenOutputs, 947 false, /* no minimal rebuild optimization */ 948 false /* shred composite rooting markers */ 949 ); 950 951 Assert.False(writtenInputs.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))].ContainsKey(Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")))); 952 } 953 954 [Fact] RemoveDependencyFromEntries()955 public void RemoveDependencyFromEntries() 956 { 957 Console.WriteLine("Test: RemoveDependencyFromEntry"); 958 // Prepare files 959 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 960 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 961 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 962 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 963 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 964 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tlh"), ""); 965 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tli"), ""); 966 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 967 968 string rootingMarker = Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")); 969 970 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 971 "#Command some-command", 972 "^" + rootingMarker, 973 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 974 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 975 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 976 Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")), 977 Path.GetFullPath(Path.Combine("TestFiles", "one3.tlh")), 978 Path.GetFullPath(Path.Combine("TestFiles", "one3.tli")), 979 }); 980 981 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 982 "#Command some-command", 983 "^" + rootingMarker, 984 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 985 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 986 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 987 Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")), 988 Path.GetFullPath(Path.Combine("TestFiles", "one3.tlh")), 989 Path.GetFullPath(Path.Combine("TestFiles", "one3.tli")), 990 }); 991 992 CanonicalTrackedOutputFiles compactOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 993 compactOutputs.RemoveDependencyFromEntry(new TaskItem[] { new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp"))) }, new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")))); 994 compactOutputs.SaveTlog(); 995 996 CanonicalTrackedOutputFiles writtenOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 997 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 998 999 Assert.False(writtenOutputs.DependencyTable[rootingMarker].ContainsKey(Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")))); 1000 1001 CanonicalTrackedInputFiles compactInputs = new CanonicalTrackedInputFiles 1002 ( 1003 DependencyTestHelper.MockTask, 1004 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 1005 new TaskItem[] { new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp"))) }, 1006 null, 1007 compactOutputs, 1008 false, /* no minimal rebuild optimization */ 1009 true /* shred composite rooting markers */ 1010 ); 1011 1012 compactInputs.RemoveDependencyFromEntry(new TaskItem[] { new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp"))) }, new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")))); 1013 compactInputs.SaveTlog(); 1014 1015 CanonicalTrackedInputFiles writtenInputs = new CanonicalTrackedInputFiles 1016 ( 1017 DependencyTestHelper.MockTask, 1018 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 1019 new TaskItem[] { new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp"))) }, 1020 null, 1021 writtenOutputs, 1022 false, /* no minimal rebuild optimization */ 1023 true /* shred composite rooting markers */ 1024 ); 1025 1026 Assert.False(writtenInputs.DependencyTable[rootingMarker].ContainsKey(Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")))); 1027 } 1028 1029 [Fact] RemoveRootsWithSharedOutputs()1030 public void RemoveRootsWithSharedOutputs() 1031 { 1032 Console.WriteLine("Test: RemoveRootsWithSharedOutputs"); 1033 1034 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1035 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1036 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1037 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1038 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1039 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tlh"), ""); 1040 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tli"), ""); 1041 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1042 1043 string rootingMarker1 = Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")); 1044 string rootingMarker2 = Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")); 1045 string rootingMarker3 = Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")); 1046 1047 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 1048 "#Command some-command", 1049 "^" + rootingMarker1.ToUpperInvariant(), 1050 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1051 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1052 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1053 "^" + rootingMarker2.ToUpperInvariant(), 1054 Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")), 1055 Path.GetFullPath(Path.Combine("TestFiles", "one3.tlh")), 1056 Path.GetFullPath(Path.Combine("TestFiles", "one3.tli")), 1057 "^" + rootingMarker3.ToUpperInvariant(), 1058 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1059 Path.GetFullPath(Path.Combine("TestFiles", "one2.obj")), 1060 }); 1061 1062 CanonicalTrackedOutputFiles outputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 1063 1064 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker1)); 1065 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker2)); 1066 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker3)); 1067 1068 outputs.RemoveRootsWithSharedOutputs(new ITaskItem[] { new TaskItem(Path.Combine("TestFiles", "one.cpp")), new TaskItem(Path.Combine("TestFiles", "three.cpp")), new TaskItem(Path.Combine("TestFiles", "two.cpp")) }); 1069 1070 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker1)); 1071 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker2)); 1072 Assert.False(outputs.DependencyTable.ContainsKey(rootingMarker3)); 1073 } 1074 1075 [Fact] RemoveRootsWithSharedOutputs_CurrentRootNotInTable()1076 public void RemoveRootsWithSharedOutputs_CurrentRootNotInTable() 1077 { 1078 Console.WriteLine("Test: RemoveRootsWithSharedOutputs"); 1079 1080 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1081 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1082 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1083 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1084 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1085 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tlh"), ""); 1086 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.tli"), ""); 1087 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1088 1089 string rootingMarker1 = Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")); 1090 string rootingMarker2 = Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")); 1091 string rootingMarker3 = Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")); 1092 1093 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 1094 "#Command some-command", 1095 "^" + rootingMarker1.ToUpperInvariant(), 1096 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1097 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1098 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1099 "^" + rootingMarker2.ToUpperInvariant(), 1100 Path.GetFullPath(Path.Combine("TestFiles", "one3.obj")), 1101 Path.GetFullPath(Path.Combine("TestFiles", "one3.tlh")), 1102 Path.GetFullPath(Path.Combine("TestFiles", "one3.tli")), 1103 "^" + rootingMarker3.ToUpperInvariant(), 1104 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1105 Path.GetFullPath(Path.Combine("TestFiles", "one2.obj")), 1106 }); 1107 1108 CanonicalTrackedOutputFiles outputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 1109 1110 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker1)); 1111 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker2)); 1112 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker3)); 1113 1114 outputs.RemoveRootsWithSharedOutputs(new ITaskItem[] { new TaskItem(Path.Combine("TestFiles", "four.cpp")), new TaskItem(Path.Combine("TestFiles", "one.cpp")), new TaskItem(Path.Combine("TestFiles", "three.cpp")), new TaskItem(Path.Combine("TestFiles", "two.cpp")) }); 1115 1116 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker1)); 1117 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker2)); 1118 Assert.True(outputs.DependencyTable.ContainsKey(rootingMarker3)); 1119 } 1120 1121 [Fact] MultipleCanonicalCLMissingDependency()1122 public void MultipleCanonicalCLMissingDependency() 1123 { 1124 Console.WriteLine("Test: MultipleCanonicalCLMissingDependency"); 1125 // Prepare files 1126 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1127 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1128 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1129 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1130 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1131 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1132 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1133 "#Command some-command", 1134 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1135 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1136 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1137 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1138 }); 1139 1140 // Delete one of our dependencies 1141 string missing = Path.GetFullPath(Path.Combine("TestFiles", "one2.h")); 1142 File.Delete(missing); 1143 1144 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1145 ( 1146 DependencyTestHelper.MockTask, 1147 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1148 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1149 null, 1150 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1151 false, /* no minimal rebuild optimization */ 1152 false /* shred composite rooting markers */ 1153 ); 1154 1155 // We're out of date, since a missing dependency indicates out-of-dateness 1156 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1157 Assert.Equal(1, outofdate.Length); 1158 1159 // The dependency has been recorded and retrieved correctly 1160 Assert.True(d.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))].ContainsKey(missing)); 1161 1162 // Save out the compacted read log - our missing dependency will be compacted away 1163 // The tlog will have to entries compacted, since we're not up to date 1164 d.RemoveEntriesForSource(d.SourcesNeedingCompilation); 1165 d.SaveTlog(); 1166 1167 // read the tlog back in again 1168 d = new CanonicalTrackedInputFiles 1169 ( 1170 DependencyTestHelper.MockTask, 1171 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1172 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1173 null, 1174 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1175 false, /* no minimal rebuild optimization */ 1176 false /* shred composite rooting markers */ 1177 ); 1178 1179 // We're out of date, since a missing dependency indicates out-of-dateness 1180 outofdate = d.ComputeSourcesNeedingCompilation(); 1181 Assert.Equal(1, outofdate.Length); 1182 1183 // We have a source outstanding for recompilation, it will not appear in 1184 // the tracking information as it will be written again 1185 Assert.False(d.DependencyTable.ContainsKey(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 1186 } 1187 1188 [Fact] MultipleCanonicalCLMissingOutputDependencyRemoved()1189 public void MultipleCanonicalCLMissingOutputDependencyRemoved() 1190 { 1191 Console.WriteLine("Test: MultipleCanonicalCLMissingOutputDependencyRemoved"); 1192 // Prepare files 1193 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1194 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1195 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1196 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1197 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 1198 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1199 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1200 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 1201 1202 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 1203 "#Command some-command", 1204 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1205 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1206 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1207 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1208 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 1209 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1210 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1211 }); 1212 1213 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 1214 "#Command some-command", 1215 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1216 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 1217 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 1218 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 1219 Path.GetFullPath(Path.Combine("TestFiles", "sometempfile2.obj")) 1220 }); 1221 1222 string missing = Path.GetFullPath(Path.Combine("TestFiles", "sometempfile2.obj")); 1223 1224 CanonicalTrackedOutputFiles compactOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 1225 // Save out the compacted read log - our missing dependency will be compacted away 1226 // Use an anonymous method to encapsulate the contains check for the tlogs 1227 compactOutputs.SaveTlog(delegate (string fullTrackedPath) 1228 { 1229 // We need to answer the question "should fullTrackedPath be included in the TLog?" 1230 return (String.Compare(fullTrackedPath, missing, StringComparison.OrdinalIgnoreCase) != 0); 1231 }); 1232 1233 // Read the Tlogs back in.. 1234 compactOutputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 1235 // Compact the read tlog 1236 CanonicalTrackedInputFiles compactInputs = new CanonicalTrackedInputFiles 1237 ( 1238 DependencyTestHelper.MockTask, 1239 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 1240 new TaskItem[] { new TaskItem(Path.Combine("TestFiles", "one.cpp")), new TaskItem(Path.Combine("TestFiles", "two.cpp")) }, 1241 null, 1242 compactOutputs, 1243 false, /* no minimal rebuild optimization */ 1244 false /* shred composite rooting markers */ 1245 ); 1246 1247 compactInputs.SaveTlog(); 1248 1249 ITaskItem[] outofDate = compactInputs.ComputeSourcesNeedingCompilation(); 1250 Assert.Equal(0, outofDate.Length); 1251 } 1252 1253 1254 [Fact] MultipleCanonicalCLMissingInputDependencyRemoved()1255 public void MultipleCanonicalCLMissingInputDependencyRemoved() 1256 { 1257 Console.WriteLine("Test: MultipleCanonicalCLMissingInputDependencyRemoved"); 1258 // Prepare files 1259 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1260 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1261 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1262 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1263 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1264 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1265 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1266 "#Command some-command", 1267 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1268 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1269 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1270 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1271 }); 1272 1273 // Delete one of our dependencies 1274 string missing = Path.GetFullPath(Path.Combine("TestFiles", "one2.h")); 1275 File.Delete(missing); 1276 1277 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1278 ( 1279 DependencyTestHelper.MockTask, 1280 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1281 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1282 null, 1283 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1284 false, /* no minimal rebuild optimization */ 1285 false /* shred composite rooting markers */ 1286 ); 1287 1288 // We're out of date, since a missing dependency indicates out-of-dateness 1289 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1290 Assert.Equal(1, outofdate.Length); 1291 1292 // The dependency has been recorded and retrieved correctly 1293 Assert.True(d.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))].ContainsKey(missing)); 1294 1295 // Save out the compacted read log - our missing dependency will be compacted away 1296 // Use an anonymous method to encapsulate the contains check for the tlogs 1297 d.SaveTlog(delegate (string fullTrackedPath) 1298 { 1299 // We need to answer the question "should fullTrackedPath be included in the TLog?" 1300 return (String.Compare(fullTrackedPath, missing, StringComparison.OrdinalIgnoreCase) != 0); 1301 }); 1302 1303 // read the tlog back in again 1304 d = new CanonicalTrackedInputFiles 1305 ( 1306 DependencyTestHelper.MockTask, 1307 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1308 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1309 null, 1310 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1311 false, /* no minimal rebuild optimization */ 1312 false /* shred composite rooting markers */ 1313 ); 1314 1315 // We're not out of date, since the missing dependency has been removed 1316 outofdate = d.ComputeSourcesNeedingCompilation(); 1317 Assert.Equal(0, outofdate.Length); 1318 } 1319 1320 1321 [Fact] MultiplePrimaryCanonicalCL()1322 public void MultiplePrimaryCanonicalCL() 1323 { 1324 Console.WriteLine("Test: MultiplePrimaryCanonicalCL"); 1325 // Prepare files 1326 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1327 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1328 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1329 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1330 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1331 1332 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two1.h"), ""); 1333 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1334 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two3.h"), ""); 1335 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 1336 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 1337 1338 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1339 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1340 "#Command some-command", 1341 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1342 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1343 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1344 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1345 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 1346 Path.GetFullPath(Path.Combine("TestFiles", "two1.h")), 1347 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 1348 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 1349 }); 1350 1351 // Touch one 1352 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1353 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1354 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1355 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1356 1357 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1358 ( 1359 DependencyTestHelper.MockTask, 1360 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1361 new ITaskItem[] { 1362 new TaskItem(Path.Combine("TestFiles", "one.cpp")), 1363 new TaskItem(Path.Combine("TestFiles", "two.cpp")), 1364 }, 1365 null, 1366 new ITaskItem[] { 1367 new TaskItem(Path.Combine("TestFiles", "one.obj")), 1368 new TaskItem(Path.Combine("TestFiles", "two.obj")), 1369 }, 1370 false, /* no minimal rebuild optimization */ 1371 false /* shred composite rooting markers */ 1372 ); 1373 1374 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1375 1376 Assert.True(outofdate.Length == 2); 1377 Assert.True((outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp") && outofdate[1].ItemSpec == Path.Combine("TestFiles", "two.cpp")) || 1378 (outofdate[1].ItemSpec == Path.Combine("TestFiles", "one.cpp") && outofdate[0].ItemSpec == Path.Combine("TestFiles", "two.cpp"))); 1379 } 1380 1381 [Fact] MultiplePrimaryCanonicalCLUnderTemp()1382 public void MultiplePrimaryCanonicalCLUnderTemp() 1383 { 1384 string currentDirectory = Directory.GetCurrentDirectory(); 1385 string tempPath = Path.GetTempPath(); 1386 1387 try 1388 { 1389 Directory.SetCurrentDirectory(tempPath); 1390 1391 Console.WriteLine("Test: MultiplePrimaryCanonicalCL"); 1392 // Prepare files 1393 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1394 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1395 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1396 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1397 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1398 1399 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two1.h"), ""); 1400 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1401 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two3.h"), ""); 1402 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 1403 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 1404 1405 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1406 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1407 "#Command some-command", 1408 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1409 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1410 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1411 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1412 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 1413 Path.GetFullPath(Path.Combine("TestFiles", "two1.h")), 1414 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 1415 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 1416 }); 1417 1418 // Touch one 1419 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1420 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1421 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1422 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1423 1424 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1425 ( 1426 DependencyTestHelper.MockTask, 1427 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1428 new ITaskItem[] { 1429 new TaskItem(Path.Combine("TestFiles", "one.cpp")), 1430 new TaskItem(Path.Combine("TestFiles", "two.cpp")), 1431 }, 1432 null, 1433 new ITaskItem[] { 1434 new TaskItem(Path.Combine("TestFiles", "one.obj")), 1435 new TaskItem(Path.Combine("TestFiles", "two.obj")), 1436 }, 1437 false, /* no minimal rebuild optimization */ 1438 false /* shred composite rooting markers */ 1439 ); 1440 1441 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1442 1443 Assert.True(outofdate.Length == 2); 1444 Assert.True((outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp") && outofdate[1].ItemSpec == Path.Combine("TestFiles", "two.cpp")) || 1445 (outofdate[1].ItemSpec == Path.Combine("TestFiles", "one.cpp") && outofdate[0].ItemSpec == Path.Combine("TestFiles", "two.cpp"))); 1446 } 1447 finally 1448 { 1449 Directory.SetCurrentDirectory(currentDirectory); 1450 } 1451 } 1452 1453 [Fact] MultiplePrimaryCanonicalCLSharedDependency()1454 public void MultiplePrimaryCanonicalCLSharedDependency() 1455 { 1456 Console.WriteLine("Test: MultiplePrimaryCanonicalCL"); 1457 // Prepare files 1458 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1459 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1460 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1461 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1462 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1463 1464 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two1.h"), ""); 1465 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two3.h"), ""); 1466 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 1467 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 1468 1469 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1470 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1471 "#Command some-command", 1472 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1473 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1474 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), // the shared dependency 1475 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1476 Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 1477 Path.GetFullPath(Path.Combine("TestFiles", "two1.h")), 1478 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), // the shared dependency 1479 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 1480 }); 1481 1482 // Touch one 1483 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1484 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1485 1486 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1487 ( 1488 DependencyTestHelper.MockTask, 1489 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1490 new ITaskItem[] { 1491 new TaskItem(Path.Combine("TestFiles", "one.cpp")), 1492 new TaskItem(Path.Combine("TestFiles", "two.cpp")), 1493 }, 1494 null, 1495 new ITaskItem[] { 1496 new TaskItem(Path.Combine("TestFiles", "one.obj")), 1497 new TaskItem(Path.Combine("TestFiles", "two.obj")), 1498 }, 1499 false, /* no minimal rebuild optimization */ 1500 false /* shred composite rooting markers */ 1501 ); 1502 1503 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1504 1505 Assert.True(outofdate.Length == 2); 1506 Assert.True((outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp") && outofdate[1].ItemSpec == Path.Combine("TestFiles", "two.cpp")) || 1507 (outofdate[1].ItemSpec == Path.Combine("TestFiles", "one.cpp") && outofdate[0].ItemSpec == Path.Combine("TestFiles", "two.cpp"))); 1508 } 1509 1510 [Fact] MultipleCanonicalCLAcrossCommand1()1511 public void MultipleCanonicalCLAcrossCommand1() 1512 { 1513 Console.WriteLine("Test: MultipleCanonicalCLAcrossCommand1"); 1514 // Prepare files 1515 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1516 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1517 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1518 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1519 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1520 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1521 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1522 "#Command some-command", 1523 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1524 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1525 "#Command some-command1", 1526 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1527 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1528 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1529 }); 1530 1531 // Touch one 1532 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1533 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1534 1535 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1536 ( 1537 DependencyTestHelper.MockTask, 1538 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1539 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1540 null, 1541 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1542 false, /* no minimal rebuild optimization */ 1543 false /* shred composite rooting markers */ 1544 ); 1545 1546 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1547 1548 Assert.True(outofdate.Length == 1); 1549 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 1550 } 1551 1552 [Fact] MultipleCanonicalCLAcrossCommand2()1553 public void MultipleCanonicalCLAcrossCommand2() 1554 { 1555 Console.WriteLine("Test: MultipleCanonicalCLAcrossCommand2"); 1556 // Prepare files 1557 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1558 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1559 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1560 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1561 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1562 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1563 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1564 "#Command some-command", 1565 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1566 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1567 "#Command some-command1", 1568 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1569 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1570 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1571 }); 1572 1573 // Touch one 1574 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1575 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1576 1577 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1578 ( 1579 DependencyTestHelper.MockTask, 1580 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1581 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1582 null, 1583 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1584 false, /* no minimal rebuild optimization */ 1585 false /* shred composite rooting markers */ 1586 ); 1587 1588 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1589 1590 Assert.True(outofdate.Length == 1); 1591 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 1592 } 1593 1594 [Fact] MultipleCanonicalCLAcrossCommandNonDependency()1595 public void MultipleCanonicalCLAcrossCommandNonDependency() 1596 { 1597 Console.WriteLine("Test: MultipleCanonicalCLAcrossCommandNonDependency"); 1598 // Prepare files 1599 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1600 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1601 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1602 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two1.h"), ""); 1603 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1604 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two3.h"), ""); 1605 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 1606 1607 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1608 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1609 "#Command some-command", 1610 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1611 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1612 "#Command some-command1", 1613 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), // this root marker represents the end of the dependencies for one.cpp 1614 Path.GetFullPath(Path.Combine("TestFiles", "two1.h")), 1615 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 1616 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 1617 }); 1618 1619 // Touch one 1620 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1621 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1622 1623 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1624 ( 1625 DependencyTestHelper.MockTask, 1626 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1627 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1628 null, 1629 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1630 false, /* no minimal rebuild optimization */ 1631 false /* shred composite rooting markers */ 1632 ); 1633 1634 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1635 1636 Assert.Equal(0, outofdate.Length); 1637 } 1638 1639 [Fact] MultipleCanonicalCLAcrossTlogs1()1640 public void MultipleCanonicalCLAcrossTlogs1() 1641 { 1642 Console.WriteLine("Test: MultipleCanonicalCLAcrossTlogs1"); 1643 // Prepare files 1644 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1645 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1646 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1647 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1648 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1649 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1650 File.WriteAllLines(Path.Combine("TestFiles", "one1.tlog"), new string[] { 1651 "#Command some-command", 1652 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1653 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1654 }); 1655 1656 File.WriteAllLines(Path.Combine("TestFiles", "one2.tlog"), new string[] { 1657 "#Command some-command1", 1658 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1659 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1660 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1661 }); 1662 1663 // Touch one 1664 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1665 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1666 1667 ITaskItem[] tlogs = { 1668 new TaskItem(Path.Combine("TestFiles", "one1.tlog")), 1669 new TaskItem(Path.Combine("TestFiles", "one2.tlog")) 1670 }; 1671 1672 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1673 ( 1674 DependencyTestHelper.MockTask, 1675 tlogs, 1676 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1677 null, 1678 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1679 false, /* no minimal rebuild optimization */ 1680 false /* shred composite rooting markers */ 1681 ); 1682 1683 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1684 1685 Assert.True(outofdate.Length == 1); 1686 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 1687 } 1688 1689 [Fact] MultipleCanonicalCLAcrossTlogs2()1690 public void MultipleCanonicalCLAcrossTlogs2() 1691 { 1692 Console.WriteLine("Test: MultipleCanonicalCLAcrossTlogs2"); 1693 // Prepare files 1694 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1695 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1696 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1697 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1698 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1699 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1700 File.WriteAllLines(Path.Combine("TestFiles", "one1.tlog"), new string[] { 1701 "#Command some-command", 1702 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1703 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1704 }); 1705 1706 File.WriteAllLines(Path.Combine("TestFiles", "one2.tlog"), new string[] { 1707 "#Command some-command1", 1708 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1709 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1710 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1711 }); 1712 1713 // Touch one 1714 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1715 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1716 1717 ITaskItem[] tlogs = { 1718 new TaskItem(Path.Combine("TestFiles", "one1.tlog")), 1719 new TaskItem(Path.Combine("TestFiles", "one2.tlog")) 1720 }; 1721 1722 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1723 ( 1724 DependencyTestHelper.MockTask, 1725 tlogs, 1726 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1727 null, 1728 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1729 false, /* no minimal rebuild optimization */ 1730 false /* shred composite rooting markers */ 1731 ); 1732 1733 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1734 1735 Assert.True(outofdate.Length == 1); 1736 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 1737 } 1738 1739 [Fact] SingleRootedCL()1740 public void SingleRootedCL() 1741 { 1742 Console.WriteLine("Test: SingleRootedCL"); 1743 // Prepare files 1744 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 1745 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1746 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1747 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1748 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1749 "#Command some-command", 1750 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1751 Path.GetFullPath(Path.Combine("TestFiles", "one.h")), 1752 }); 1753 1754 // Touch one 1755 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1756 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 1757 1758 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1759 ( 1760 DependencyTestHelper.MockTask, 1761 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 1762 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1763 null, 1764 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1765 false, /* no minimal rebuild optimization */ 1766 false /* shred composite rooting markers */ 1767 ); 1768 1769 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1770 1771 Assert.True(outofdate.Length == 1); 1772 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 1773 } 1774 1775 [Fact] MultipleRootedCLAcrossTlogs1()1776 public void MultipleRootedCLAcrossTlogs1() 1777 { 1778 Console.WriteLine("Test: MultipleRootedCLAcrossTlogs1"); 1779 // Prepare files 1780 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1781 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1782 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1783 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1784 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1785 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1786 File.WriteAllLines(Path.Combine("TestFiles", "one1.tlog"), new string[] { 1787 "#Command some-command", 1788 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1789 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1790 }); 1791 1792 File.WriteAllLines(Path.Combine("TestFiles", "one2.tlog"), new string[] { 1793 "#Command some-command1", 1794 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1795 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1796 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1797 }); 1798 1799 // Touch one 1800 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1801 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1802 1803 ITaskItem[] tlogs = { 1804 new TaskItem(Path.Combine("TestFiles", "one1.tlog")), 1805 new TaskItem(Path.Combine("TestFiles", "one2.tlog")) 1806 }; 1807 1808 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1809 ( 1810 DependencyTestHelper.MockTask, 1811 tlogs, 1812 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1813 null, 1814 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1815 false, /* no minimal rebuild optimization */ 1816 false /* shred composite rooting markers */ 1817 ); 1818 1819 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1820 1821 Assert.True(outofdate.Length == 1); 1822 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 1823 } 1824 1825 [Fact] MultipleRootedCL()1826 public void MultipleRootedCL() 1827 { 1828 Console.WriteLine("Test: MultipleRootedCL"); 1829 // Prepare files 1830 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1831 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1832 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1833 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1834 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1835 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two1.h"), ""); 1836 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1837 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two3.h"), ""); 1838 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 1839 1840 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1841 File.WriteAllLines(Path.Combine("TestFiles", "one1.tlog"), new string[] { 1842 "#Command some-command", 1843 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1844 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1845 "#Command some-command1", 1846 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 1847 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 1848 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 1849 }); 1850 1851 // Touch one 1852 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1853 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1854 1855 ITaskItem[] tlogs = { 1856 new TaskItem(Path.Combine("TestFiles", "one1.tlog")), 1857 new TaskItem(Path.Combine("TestFiles", "one2.tlog")) 1858 }; 1859 1860 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1861 ( 1862 DependencyTestHelper.MockTask, 1863 tlogs, 1864 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "two.cpp"))), 1865 null, 1866 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1867 false, /* no minimal rebuild optimization */ 1868 false /* shred composite rooting markers */ 1869 ); 1870 1871 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1872 1873 Assert.True(outofdate.Length == 1); 1874 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "two.cpp")); 1875 } 1876 1877 [Fact] MultipleRootedCLNonDependency()1878 public void MultipleRootedCLNonDependency() 1879 { 1880 Console.WriteLine("Test: MultipleRootedCLNonDependency"); 1881 // Prepare files 1882 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1883 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1884 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1885 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1886 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1887 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two1.h"), ""); 1888 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1889 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two3.h"), ""); 1890 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 1891 1892 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1893 File.WriteAllLines(Path.Combine("TestFiles", "one1.tlog"), new string[] { 1894 "#Command some-command", 1895 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1896 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1897 "#Command some-command1", 1898 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), // this root marker represents the end of the dependencies for one.cpp 1899 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 1900 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 1901 }); 1902 1903 // Touch one 1904 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1905 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 1906 1907 ITaskItem[] tlogs = { 1908 new TaskItem(Path.Combine("TestFiles", "one1.tlog")) 1909 }; 1910 1911 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1912 ( 1913 DependencyTestHelper.MockTask, 1914 tlogs, 1915 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1916 null, 1917 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1918 false, /* no minimal rebuild optimization */ 1919 false /* shred composite rooting markers */ 1920 ); 1921 1922 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1923 1924 Assert.Equal(0, outofdate.Length); 1925 } 1926 1927 [Fact] MultipleRootedCLAcrossTlogs2()1928 public void MultipleRootedCLAcrossTlogs2() 1929 { 1930 Console.WriteLine("Test: MultipleRootedCLAcrossTlogs2"); 1931 // Prepare files 1932 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 1933 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1934 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 1935 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 1936 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 1937 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1938 File.WriteAllLines(Path.Combine("TestFiles", "one1.tlog"), new string[] { 1939 "#Command some-command", 1940 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1941 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 1942 }); 1943 1944 File.WriteAllLines(Path.Combine("TestFiles", "one2.tlog"), new string[] { 1945 "#Command some-command1", 1946 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1947 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 1948 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 1949 }); 1950 1951 // Touch one 1952 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1953 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 1954 1955 ITaskItem[] tlogs = { 1956 new TaskItem(Path.Combine("TestFiles", "one1.tlog")), 1957 new TaskItem(Path.Combine("TestFiles", "one2.tlog")) 1958 }; 1959 1960 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 1961 ( 1962 DependencyTestHelper.MockTask, 1963 tlogs, 1964 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 1965 null, 1966 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 1967 false, /* no minimal rebuild optimization */ 1968 false /* shred composite rooting markers */ 1969 ); 1970 1971 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 1972 1973 Assert.True(outofdate.Length == 1); 1974 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 1975 } 1976 1977 1978 [Fact] OutputSingleCanonicalCL()1979 public void OutputSingleCanonicalCL() 1980 { 1981 Console.WriteLine("Test: OutputSingleCanonicalCL"); 1982 // Prepare files 1983 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 1984 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 1985 "#Command some-command", 1986 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 1987 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 1988 }); 1989 1990 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 1991 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog")))); 1992 1993 ITaskItem[] outputs = d.OutputsForSource(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 1994 1995 Assert.True(outputs.Length == 1); 1996 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 1997 } 1998 1999 [Fact] OutputSingleCanonicalCLAcrossTlogs()2000 public void OutputSingleCanonicalCLAcrossTlogs() 2001 { 2002 Console.WriteLine("Test: OutputSingleCanonicalCLAcrossTlogs"); 2003 // Prepare files 2004 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2005 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2006 "#Command some-command", 2007 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2008 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2009 }); 2010 2011 File.WriteAllLines(Path.Combine("TestFiles", "two.tlog"), new string[] { 2012 "#Command some-command", 2013 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2014 Path.GetFullPath(Path.Combine("TestFiles", "one.pch")), 2015 }); 2016 2017 ITaskItem[] tlogs = { 2018 new TaskItem(Path.Combine("TestFiles", "one.tlog")), 2019 new TaskItem(Path.Combine("TestFiles", "two.tlog")) 2020 }; 2021 2022 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2023 tlogs); 2024 2025 ITaskItem[] outputs = d.OutputsForSource(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 2026 2027 Assert.True(outputs.Length == 2); 2028 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2029 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "one.pch"))); 2030 } 2031 2032 [Fact] OutputNonExistentTlog()2033 public void OutputNonExistentTlog() 2034 { 2035 Console.WriteLine("Test: NonExistentTlog"); 2036 2037 // Just to be sure, delete the test tlog. 2038 File.Delete(Path.Combine("TestFiles", "one.tlog")); 2039 2040 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2041 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog")))); 2042 2043 ITaskItem[] outputs = d.OutputsForSource(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 2044 2045 Assert.Null(outputs); 2046 } 2047 2048 [Fact] OutputMultipleCanonicalCL()2049 public void OutputMultipleCanonicalCL() 2050 { 2051 Console.WriteLine("Test: OutputMultipleCanonicalCL"); 2052 2053 ITaskItem[] sources = new TaskItem[] { 2054 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2055 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2056 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")))}; 2057 2058 // Prepare files 2059 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2060 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2061 "#Command some-command", 2062 "^" + FileTracker.FormatRootingMarker(sources), 2063 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2064 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2065 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2066 }); 2067 2068 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2069 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog")))); 2070 2071 ITaskItem[] outputs = d.OutputsForSource(sources); 2072 2073 Assert.True(outputs.Length == 3); 2074 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2075 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2076 Assert.True(outputs[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2077 } 2078 2079 [Fact] OutputMultipleCanonicalCLSubrootMatch()2080 public void OutputMultipleCanonicalCLSubrootMatch() 2081 { 2082 Console.WriteLine("Test: OutputMultipleCanonicalCLSubrootMatch"); 2083 2084 // sources is a subset of source2 2085 ITaskItem[] sources = new TaskItem[] { 2086 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2087 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2088 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")))}; 2089 ITaskItem[] sources2 = new TaskItem[] { 2090 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2091 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2092 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp"))), 2093 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "four.cpp"))), 2094 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "five.cpp")))}; 2095 2096 // Prepare files 2097 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2098 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2099 "#Command some-command", 2100 "^" + FileTracker.FormatRootingMarker(sources), 2101 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2102 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2103 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2104 "^" + FileTracker.FormatRootingMarker(sources2), 2105 Path.GetFullPath(Path.Combine("TestFiles", "fOUr.obj")), 2106 Path.GetFullPath(Path.Combine("TestFiles", "fIve.obj")), 2107 Path.GetFullPath(Path.Combine("TestFiles", "sIx.obj")), 2108 Path.GetFullPath(Path.Combine("TestFiles", "sEvEn.obj")), 2109 Path.GetFullPath(Path.Combine("TestFiles", "EIght.obj")), 2110 }); 2111 2112 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2113 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog")))); 2114 2115 ITaskItem[] outputs = d.OutputsForSource(sources2, /*searchForSubRootsInCompositeRootingMarkers*/ false); 2116 2117 Assert.True(outputs.Length == 5); 2118 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fOUr.obj"))); 2119 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fIve.obj"))); 2120 Assert.True(outputs[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sIx.obj"))); 2121 Assert.True(outputs[3].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sEvEn.obj"))); 2122 Assert.True(outputs[4].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "EIght.obj"))); 2123 2124 ITaskItem[] outputs2 = d.OutputsForSource(sources2, /*searchForSubRootsInCompositeRootingMarkers*/ true); 2125 2126 Assert.True(outputs2.Length == 8); 2127 Assert.True(outputs2[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2128 Assert.True(outputs2[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2129 Assert.True(outputs2[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2130 Assert.True(outputs2[3].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fOUr.obj"))); 2131 Assert.True(outputs2[4].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fIve.obj"))); 2132 Assert.True(outputs2[5].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sIx.obj"))); 2133 Assert.True(outputs2[6].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sEvEn.obj"))); 2134 Assert.True(outputs2[7].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "EIght.obj"))); 2135 2136 // Test if sources can find the superset. 2137 ITaskItem[] outputs3 = d.OutputsForSource(sources, /*searchForSubRootsInCompositeRootingMarkers*/ true); 2138 2139 Assert.True(outputs3.Length == 8); 2140 Assert.True(outputs3[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2141 Assert.True(outputs3[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2142 Assert.True(outputs3[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2143 Assert.True(outputs3[3].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fOUr.obj"))); 2144 Assert.True(outputs3[4].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fIve.obj"))); 2145 Assert.True(outputs3[5].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sIx.obj"))); 2146 Assert.True(outputs3[6].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sEvEn.obj"))); 2147 Assert.True(outputs3[7].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "EIght.obj"))); 2148 2149 ITaskItem[] outputs4 = d.OutputsForSource(sources, /*searchForSubRootsInCompositeRootingMarkers*/ false); 2150 2151 Assert.True(outputs4.Length == 3); 2152 Assert.True(outputs4[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2153 Assert.True(outputs4[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2154 Assert.True(outputs4[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2155 } 2156 2157 [Fact] OutputMultipleCanonicalCLSubrootMisMatch()2158 public void OutputMultipleCanonicalCLSubrootMisMatch() 2159 { 2160 Console.WriteLine("Test: OutputMultipleCanonicalCLSubrootMisMatch"); 2161 2162 // sources is NOT a subset of source 2163 ITaskItem[] sources = new TaskItem[] { 2164 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2165 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2166 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")))}; 2167 ITaskItem[] sources2 = new TaskItem[] { 2168 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2169 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2170 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "four.cpp"))), 2171 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "five.cpp")))}; 2172 ITaskItem[] sources2Match = new TaskItem[] { 2173 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2174 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "four.cpp"))), 2175 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2176 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "five.cpp")))}; 2177 ITaskItem[] sourcesPlusOne = new TaskItem[] { 2178 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2179 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2180 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "eight.cpp"))), 2181 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")))}; 2182 2183 // Do note sources2Match and source2 is missing three.cpp. It is to test if the RootContainsAllSubRootComponents can handle the case. 2184 2185 // Prepare files 2186 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2187 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2188 "#Command some-command", 2189 "^" + FileTracker.FormatRootingMarker(sources), 2190 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2191 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2192 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2193 "^" + FileTracker.FormatRootingMarker(sources2), 2194 Path.GetFullPath(Path.Combine("TestFiles", "fOUr.obj")), 2195 Path.GetFullPath(Path.Combine("TestFiles", "fIve.obj")), 2196 Path.GetFullPath(Path.Combine("TestFiles", "sIx.obj")), 2197 Path.GetFullPath(Path.Combine("TestFiles", "sEvEn.obj")), 2198 Path.GetFullPath(Path.Combine("TestFiles", "EIght.obj")), 2199 }); 2200 2201 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2202 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog")))); 2203 2204 ITaskItem[] outputs = d.OutputsForSource(sources2Match, /*searchForSubRootsInCompositeRootingMarkers*/ false); 2205 2206 Assert.True(outputs.Length == 5); 2207 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fOUr.obj"))); 2208 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fIve.obj"))); 2209 Assert.True(outputs[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sIx.obj"))); 2210 Assert.True(outputs[3].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sEvEn.obj"))); 2211 Assert.True(outputs[4].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "EIght.obj"))); 2212 2213 ITaskItem[] outputs2 = d.OutputsForSource(sources2Match, /*searchForSubRootsInCompositeRootingMarkers*/ true); 2214 2215 Assert.True(outputs2.Length == 5); 2216 Assert.True(outputs2[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fOUr.obj"))); 2217 Assert.True(outputs2[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "fIve.obj"))); 2218 Assert.True(outputs2[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sIx.obj"))); 2219 Assert.True(outputs2[3].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "sEvEn.obj"))); 2220 Assert.True(outputs2[4].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "EIght.obj"))); 2221 2222 ITaskItem[] outputs3 = d.OutputsForSource(sourcesPlusOne, /*searchForSubRootsInCompositeRootingMarkers*/ true); 2223 2224 Assert.True(outputs3.Length == 3); 2225 Assert.True(outputs3[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2226 Assert.True(outputs3[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2227 Assert.True(outputs3[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2228 2229 ITaskItem[] outputs4 = d.OutputsForSource(sourcesPlusOne, /*searchForSubRootsInCompositeRootingMarkers*/ false); 2230 2231 Assert.Equal(0, outputs4.Length); 2232 } 2233 2234 [Fact] OutputMultipleCanonicalCLLongTempPath()2235 public void OutputMultipleCanonicalCLLongTempPath() 2236 { 2237 Console.WriteLine("Test: OutputMultipleCanonicalCLLongTempPath"); 2238 2239 ITaskItem[] sources = new TaskItem[] { 2240 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2241 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2242 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")))}; 2243 2244 string oldTempPath = Environment.GetEnvironmentVariable("TEMP"); 2245 string oldTmpPath = Environment.GetEnvironmentVariable("TMP"); 2246 string newTempPath = Path.GetFullPath(Path.Combine("TestFiles", "ThisIsAReallyVeryLongTemporaryPlace", "ThatIsLongerThanTheSourcePaths")); 2247 2248 Directory.CreateDirectory(newTempPath); 2249 Environment.SetEnvironmentVariable("TEMP", newTempPath); 2250 Environment.SetEnvironmentVariable("TMP", newTempPath); 2251 2252 Console.WriteLine("Test: OutputMultipleCanonicalCL"); 2253 2254 // Prepare files 2255 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2256 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2257 "#Command some-command", 2258 "^" + FileTracker.FormatRootingMarker(sources), 2259 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2260 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2261 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2262 }); 2263 2264 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2265 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog")))); 2266 2267 ITaskItem[] outputs = d.OutputsForSource(sources); 2268 2269 Environment.SetEnvironmentVariable("TEMP", oldTempPath); 2270 Environment.SetEnvironmentVariable("TMP", oldTmpPath); 2271 2272 Assert.True(outputs.Length == 3); 2273 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2274 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2275 Assert.True(outputs[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2276 } 2277 2278 [Fact] OutputMultipleCanonicalCLAcrossTLogs()2279 public void OutputMultipleCanonicalCLAcrossTLogs() 2280 { 2281 Console.WriteLine("Test: OutputMultipleCanonicalCLAcrossTLogs"); 2282 2283 ITaskItem[] sources = new TaskItem[] { 2284 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2285 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2286 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")))}; 2287 2288 // Prepare files 2289 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2290 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2291 "#Command some-command", 2292 "^" + FileTracker.FormatRootingMarker(sources), 2293 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2294 }); 2295 2296 File.WriteAllLines(Path.Combine("TestFiles", "two.tlog"), new string[] { 2297 "#Command some-command", 2298 "^" + FileTracker.FormatRootingMarker(sources), 2299 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2300 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2301 }); 2302 2303 ITaskItem[] tlogs = { 2304 new TaskItem(Path.Combine("TestFiles", "one.tlog")), 2305 new TaskItem(Path.Combine("TestFiles", "two.tlog")) 2306 }; 2307 2308 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2309 tlogs); 2310 2311 ITaskItem[] outputs = d.OutputsForSource(sources); 2312 2313 Assert.True(outputs.Length == 3); 2314 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2315 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2316 Assert.True(outputs[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2317 } 2318 2319 [Fact] OutputMultipleSingleSubRootCanonicalCL()2320 public void OutputMultipleSingleSubRootCanonicalCL() 2321 { 2322 Console.WriteLine("Test: OutputMultipleSingleSubRootCanonicalCL"); 2323 2324 ITaskItem[] sources = new TaskItem[] { 2325 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2326 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2327 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")))}; 2328 2329 // Prepare files 2330 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2331 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2332 "#Command some-command", 2333 "^" + FileTracker.FormatRootingMarker(sources), 2334 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2335 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2336 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2337 }); 2338 2339 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2340 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog")))); 2341 2342 ITaskItem[] outputs = d.OutputsForSource(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")))); 2343 2344 Assert.True(outputs.Length == 3); 2345 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2346 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2347 Assert.True(outputs[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2348 } 2349 2350 [Fact] OutputMultipleUnrecognisedRootCanonicalCL()2351 public void OutputMultipleUnrecognisedRootCanonicalCL() 2352 { 2353 Console.WriteLine("Test: OutputMultipleUnrecognisedRootCanonicalCL"); 2354 2355 // Prepare files 2356 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2357 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2358 "#Command some-command", 2359 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")), 2360 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2361 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2362 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2363 }); 2364 2365 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2366 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog")))); 2367 2368 ITaskItem[] outputs = d.OutputsForSource(new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "four.cpp")))); 2369 2370 Assert.Equal(0, outputs.Length); 2371 } 2372 2373 [Fact] OutputCLMinimalRebuildOptimization()2374 public void OutputCLMinimalRebuildOptimization() 2375 { 2376 Console.WriteLine("Test: OutputCLMinimalRebuildOptimization"); 2377 2378 // Prepare read tlog 2379 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 2380 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 2381 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 2382 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 2383 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 2384 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.cpp"), ""); 2385 Thread.Sleep(_sleepTimeMilliseconds); 2386 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 2387 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 2388 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.obj"), ""); 2389 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2390 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 2391 "#Command some-command", 2392 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2393 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2394 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2395 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2396 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 2397 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2398 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2399 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2400 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")), 2401 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2402 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2403 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2404 }); 2405 2406 // Our source files 2407 ITaskItem[] sources = { 2408 new TaskItem(Path.Combine("TestFiles", "one.cpp")), 2409 new TaskItem(Path.Combine("TestFiles", "two.cpp")), 2410 new TaskItem(Path.Combine("TestFiles", "three.cpp")), 2411 }; 2412 2413 // Prepare write tlog 2414 // This includes individual output information for each root 2415 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2416 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 2417 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2418 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 2419 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 2420 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2421 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")), 2422 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2423 "#Command some-command", 2424 "^" + FileTracker.FormatRootingMarker(sources), 2425 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 2426 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2427 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2428 }); 2429 2430 2431 // Represent our tracked and computed outputs 2432 CanonicalTrackedOutputFiles outputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 2433 2434 // Represent our tracked and provided inputs 2435 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 2436 ( 2437 DependencyTestHelper.MockTask, 2438 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 2439 sources, 2440 null, 2441 outputs, 2442 false, /* no minimal rebuild optimization */ 2443 false /* shred composite rooting markers */ 2444 ); 2445 2446 // First of all, all things should be up to date 2447 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 2448 Assert.Equal(0, outofdate.Length); 2449 2450 // Delete one of the outputs in the group 2451 File.Delete(Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2452 2453 // With optimization off, all sources in the group will need compilation 2454 d.SourcesNeedingCompilation = null; 2455 outofdate = d.ComputeSourcesNeedingCompilation(); 2456 Assert.Equal(3, outofdate.Length); 2457 2458 // With optimization on, only the source that matches the output will need compilation 2459 d = new CanonicalTrackedInputFiles 2460 ( 2461 DependencyTestHelper.MockTask, 2462 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 2463 sources, 2464 null, 2465 outputs, 2466 true, /* enable minimal rebuild optimization */ 2467 false /* shred composite rooting markers */ 2468 ); 2469 2470 outofdate = d.ComputeSourcesNeedingCompilation(); 2471 Assert.Equal(1, outofdate.Length); 2472 // And the source is.. two.cpp! 2473 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "two.cpp")); 2474 } 2475 2476 [Fact] OutputCLMinimalRebuildOptimizationComputed()2477 public void OutputCLMinimalRebuildOptimizationComputed() 2478 { 2479 Console.WriteLine("Test: OutputCLMinimalRebuildOptimizationComputed"); 2480 2481 // Prepare read tlog 2482 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 2483 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 2484 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 2485 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 2486 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 2487 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.cpp"), ""); 2488 Thread.Sleep(_sleepTimeMilliseconds); 2489 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 2490 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 2491 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.obj"), ""); 2492 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2493 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 2494 "#Command some-command", 2495 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2496 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2497 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2498 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2499 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 2500 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2501 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2502 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2503 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")), 2504 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2505 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2506 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2507 }); 2508 2509 // Our source files 2510 ITaskItem[] sources = { 2511 new TaskItem(Path.Combine("TestFiles", "one.cpp")), 2512 new TaskItem(Path.Combine("TestFiles", "two.cpp")), 2513 new TaskItem(Path.Combine("TestFiles", "three.cpp")), 2514 }; 2515 2516 // Prepare write tlog 2517 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 2518 "#Command some-command", 2519 "^" + FileTracker.FormatRootingMarker(sources), 2520 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 2521 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2522 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2523 }); 2524 2525 2526 // Represent our tracked and computed outputs 2527 CanonicalTrackedOutputFiles outputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 2528 2529 // "Compute" the additional output information for this compilation, rather than them being tracked 2530 outputs.AddComputedOutputForSourceRoot(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), Path.GetFullPath(Path.Combine("TestFiles", "one.obj"))); 2531 outputs.AddComputedOutputForSourceRoot(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2532 outputs.AddComputedOutputForSourceRoot(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")), Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2533 2534 // Represent our tracked and provided inputs 2535 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 2536 ( 2537 DependencyTestHelper.MockTask, 2538 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 2539 sources, 2540 null, 2541 outputs, 2542 false, /* no minimal rebuild optimization */ 2543 false /* shred composite rooting markers */ 2544 ); 2545 2546 // First of all, all things should be up to date 2547 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 2548 Assert.Equal(0, outofdate.Length); 2549 2550 // Delete one of the outputs in the group 2551 File.Delete(Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2552 2553 // With optimization off, all sources in the group will need compilation 2554 d.SourcesNeedingCompilation = null; 2555 outofdate = d.ComputeSourcesNeedingCompilation(); 2556 Assert.Equal(3, outofdate.Length); 2557 2558 // With optimization on, only the source that matches the output will need compilation 2559 d = new CanonicalTrackedInputFiles 2560 ( 2561 DependencyTestHelper.MockTask, 2562 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 2563 sources, 2564 null, 2565 outputs, 2566 true, /* enable minimal rebuild optimization */ 2567 false /* shred composite rooting markers */ 2568 ); 2569 2570 outofdate = d.ComputeSourcesNeedingCompilation(); 2571 Assert.Equal(1, outofdate.Length); 2572 // And the source is.. two.cpp! 2573 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "two.cpp")); 2574 } 2575 2576 [Fact] ReplaceOutputForSource()2577 public void ReplaceOutputForSource() 2578 { 2579 Console.WriteLine("Test: ReplaceOutputForSource"); 2580 2581 if (File.Exists(Path.GetFullPath(Path.Combine("TestFiles", "three.i")))) 2582 { 2583 File.Delete(Path.GetFullPath(Path.Combine("TestFiles", "three.i"))); 2584 } 2585 2586 // Prepare read tlog 2587 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 2588 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 2589 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 2590 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 2591 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 2592 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.cpp"), ""); 2593 Thread.Sleep(_sleepTimeMilliseconds); 2594 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 2595 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 2596 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.obj"), ""); 2597 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2598 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 2599 "#Command some-command", 2600 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2601 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")).ToUpperInvariant(), 2602 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2603 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2604 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 2605 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2606 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2607 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2608 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")), 2609 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2610 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2611 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2612 }); 2613 2614 // Our source files 2615 ITaskItem[] sources = { 2616 new TaskItem(Path.Combine("TestFiles", "one.cpp")), 2617 new TaskItem(Path.Combine("TestFiles", "two.cpp")), 2618 new TaskItem(Path.Combine("TestFiles", "three.cpp")), 2619 }; 2620 2621 // Prepare write tlog 2622 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 2623 "#Command some-command", 2624 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2625 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 2626 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 2627 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2628 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")), 2629 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2630 }); 2631 2632 // Represent our tracked and computed outputs 2633 CanonicalTrackedOutputFiles outputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 2634 2635 // Change the output (note that this doesn't affect the timestamp) 2636 File.Move(Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), Path.GetFullPath(Path.Combine("TestFiles", "three.i"))); 2637 2638 string threeRootingMarker = FileTracker.FormatRootingMarker(new TaskItem(Path.Combine("TestFiles", "three.cpp"))); 2639 // Remove the fact that three.obj was the tracked output 2640 bool removed = outputs.RemoveOutputForSourceRoot(threeRootingMarker, Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2641 Assert.True(removed); 2642 // "Compute" the replacement output information for this compilation, rather than the one originally tracked 2643 outputs.AddComputedOutputForSourceRoot(threeRootingMarker, Path.GetFullPath(Path.Combine("TestFiles", "three.i"))); 2644 2645 // Represent our tracked and provided inputs 2646 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 2647 ( 2648 DependencyTestHelper.MockTask, 2649 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 2650 sources, 2651 null, 2652 outputs, 2653 true, /* minimal rebuild optimization */ 2654 false /* shred composite rooting markers */ 2655 ); 2656 2657 // We should have one output for three.cpp 2658 Assert.Equal(1, outputs.DependencyTable[threeRootingMarker].Count); 2659 Assert.Equal(false, outputs.DependencyTable[threeRootingMarker].ContainsKey(Path.GetFullPath(Path.Combine("TestFiles", "three.obj")))); 2660 2661 // All things should be up to date 2662 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 2663 Assert.Equal(0, outofdate.Length); 2664 2665 // Delete the new output 2666 File.Delete(Path.GetFullPath(Path.Combine("TestFiles", "three.i"))); 2667 2668 // This means a recompile would be required for the roots 2669 d.SourcesNeedingCompilation = null; 2670 outofdate = d.ComputeSourcesNeedingCompilation(); 2671 Assert.Equal(1, outofdate.Length); 2672 } 2673 2674 [Fact] ExcludeSpecificDirectory()2675 public void ExcludeSpecificDirectory() 2676 { 2677 Console.WriteLine("Test: ExcludeSpecificDirectory"); 2678 2679 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 2680 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 2681 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 2682 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 2683 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.cpp"), ""); 2684 2685 Thread.Sleep(_sleepTimeMilliseconds); 2686 2687 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 2688 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 2689 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.obj"), ""); 2690 2691 Thread.Sleep(_sleepTimeMilliseconds); 2692 2693 Directory.CreateDirectory(Path.Combine("TestFiles", "Foo")); 2694 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "Foo", "one2.h"), ""); 2695 2696 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2697 2698 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 2699 "#Command some-command", 2700 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")).ToUpperInvariant(), 2701 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")).ToUpperInvariant(), 2702 Path.GetFullPath(Path.Combine("TestFiles", "Foo", "one2.h")).ToUpperInvariant(), 2703 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")).ToUpperInvariant(), 2704 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")).ToUpperInvariant(), 2705 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")).ToUpperInvariant(), 2706 Path.GetFullPath(Path.Combine("TestFiles", "Foo", "one2.h")).ToUpperInvariant(), 2707 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")).ToUpperInvariant(), 2708 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")).ToUpperInvariant(), 2709 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")).ToUpperInvariant(), 2710 Path.GetFullPath(Path.Combine("TestFiles", "Foo", "one2.h")).ToUpperInvariant(), 2711 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")).ToUpperInvariant(), 2712 }); 2713 2714 // Our source files 2715 ITaskItem[] sources = { 2716 new TaskItem(Path.Combine("TestFiles", "one.cpp")), 2717 new TaskItem(Path.Combine("TestFiles", "two.cpp")), 2718 new TaskItem(Path.Combine("TestFiles", "three.cpp")), 2719 }; 2720 2721 // Prepare write tlog 2722 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 2723 "#Command some-command", 2724 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")).ToUpperInvariant(), 2725 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")).ToUpperInvariant(), 2726 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")).ToUpperInvariant(), 2727 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")).ToUpperInvariant(), 2728 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")).ToUpperInvariant(), 2729 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")).ToUpperInvariant(), 2730 }); 2731 2732 // Represent our tracked and computed outputs 2733 CanonicalTrackedOutputFiles outputs = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog")))); 2734 2735 // Represent our tracked and provided inputs 2736 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 2737 ( 2738 DependencyTestHelper.MockTask, 2739 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), 2740 sources, 2741 new TaskItem[] { new TaskItem(Path.GetFullPath(Path.Combine("TeSTfiles", "Foo"))) }, 2742 outputs, 2743 true, /* minimal rebuild optimization */ 2744 false /* shred composite rooting markers */ 2745 ); 2746 2747 // All things should be up to date 2748 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 2749 Assert.Equal(0, outofdate.Length); 2750 } 2751 2752 [Fact] SaveCompactedReadTlog()2753 public void SaveCompactedReadTlog() 2754 { 2755 Console.WriteLine("Test: SaveCompactedReadTlog"); 2756 // Prepare files 2757 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 2758 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 2759 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 2760 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 2761 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 2762 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two1.h"), ""); 2763 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 2764 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two3.h"), ""); 2765 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 2766 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.obj"), ""); 2767 2768 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2769 File.WriteAllLines(Path.Combine("TestFiles", "one1.tlog"), new string[] { 2770 "#Command some-command", 2771 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2772 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 2773 }); 2774 2775 File.WriteAllLines(Path.Combine("TestFiles", "one2.tlog"), new string[] { 2776 "#Command some-command1", 2777 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 2778 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 2779 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 2780 }); 2781 2782 File.WriteAllLines(Path.Combine("TestFiles", "two1.tlog"), new string[] { 2783 "#Command some-command2", 2784 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 2785 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 2786 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 2787 }); 2788 2789 // Touch one 2790 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2791 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 2792 2793 ITaskItem[] tlogs = { 2794 new TaskItem(Path.Combine("TestFiles", "one1.tlog")), 2795 new TaskItem(Path.Combine("TestFiles", "one2.tlog")), 2796 new TaskItem(Path.Combine("TestFiles", "two1.tlog")) 2797 }; 2798 2799 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 2800 ( 2801 DependencyTestHelper.MockTask, 2802 tlogs, 2803 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 2804 null, 2805 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 2806 false, /* no minimal rebuild optimization */ 2807 false /* shred composite rooting markers */ 2808 ); 2809 2810 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 2811 2812 Assert.True(outofdate.Length == 1); 2813 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 2814 2815 d.RemoveEntriesForSource(d.SourcesNeedingCompilation); 2816 d.SaveTlog(); 2817 2818 // All the tlogs need to still be there even after compaction 2819 // It's OK for them to be empty, but their absence might mean a partial clean 2820 // A missing tlog would mean a clean build 2821 Assert.True(Microsoft.Build.Utilities.TrackedDependencies.ItemsExist(tlogs)); 2822 2823 // There should be no difference in the out of date files after compaction 2824 CanonicalTrackedInputFiles d1 = new CanonicalTrackedInputFiles 2825 ( 2826 DependencyTestHelper.MockTask, 2827 tlogs, 2828 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.cpp"))), 2829 null, 2830 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.obj"))), 2831 false, /* no minimal rebuild optimization */ 2832 false /* shred composite rooting markers */ 2833 ); 2834 2835 outofdate = d1.ComputeSourcesNeedingCompilation(); 2836 2837 Assert.True(outofdate.Length == 1); 2838 Assert.True(outofdate[0].ItemSpec == Path.Combine("TestFiles", "one.cpp")); 2839 2840 ITaskItem[] tlogs2 = { 2841 tlogs[0] 2842 }; 2843 2844 // All log information should now be in the tlog[0] 2845 CanonicalTrackedInputFiles d2 = new CanonicalTrackedInputFiles 2846 ( 2847 DependencyTestHelper.MockTask, 2848 tlogs2, 2849 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "two.cpp"))), 2850 null, 2851 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "two.obj"))), 2852 false, /* no minimal rebuild optimization */ 2853 false /* shred composite rooting markers */ 2854 ); 2855 2856 outofdate = d2.ComputeSourcesNeedingCompilation(); 2857 2858 Assert.True(outofdate.Length == 0); 2859 Assert.True(d2.DependencyTable.Count == 1); 2860 Assert.False(d2.DependencyTable.ContainsKey(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 2861 2862 // There should be no difference even if we send in all the original tlogs 2863 CanonicalTrackedInputFiles d3 = new CanonicalTrackedInputFiles 2864 ( 2865 DependencyTestHelper.MockTask, 2866 tlogs, 2867 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "two.cpp"))), 2868 null, 2869 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "two.obj"))), 2870 false, /* no minimal rebuild optimization */ 2871 false /* shred composite rooting markers */ 2872 ); 2873 2874 outofdate = d3.ComputeSourcesNeedingCompilation(); 2875 2876 Assert.True(outofdate.Length == 0); 2877 Assert.True(d3.DependencyTable.Count == 1); 2878 Assert.False(d3.DependencyTable.ContainsKey(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")))); 2879 } 2880 2881 [Fact] SaveCompactedWriteTlog()2882 public void SaveCompactedWriteTlog() 2883 { 2884 Console.WriteLine("Test: SaveCompactedWriteTlog"); 2885 TaskItem fooItem = new TaskItem("foo"); 2886 2887 ITaskItem[] sources = new TaskItem[] { 2888 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp"))), 2889 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))), 2890 new TaskItem(Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")))}; 2891 2892 string rootMarker = FileTracker.FormatRootingMarker(sources); 2893 2894 // Prepare files 2895 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2896 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 2897 "#Command some-command", 2898 "^" + rootMarker, 2899 Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj")), 2900 "^" + fooItem.GetMetadata("Fullpath"), 2901 Path.GetFullPath(Path.Combine("TestFiles", "foo1.bar")), 2902 Path.GetFullPath(Path.Combine("TestFiles", "bar1.baz")), 2903 }); 2904 2905 File.WriteAllLines(Path.Combine("TestFiles", "two.tlog"), new string[] { 2906 "#Command some-command", 2907 "^" + rootMarker, 2908 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 2909 Path.GetFullPath(Path.Combine("TestFiles", "three.obj")), 2910 "^" + fooItem.GetMetadata("Fullpath"), 2911 Path.GetFullPath(Path.Combine("TestFiles", "foo2.bar")), 2912 Path.GetFullPath(Path.Combine("TestFiles", "bar2.baz")), 2913 }); 2914 2915 ITaskItem[] tlogs = { 2916 new TaskItem(Path.Combine("TestFiles", "one.tlog")), 2917 new TaskItem(Path.Combine("TestFiles", "two.tlog")) 2918 }; 2919 2920 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2921 CanonicalTrackedOutputFiles d = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2922 tlogs); 2923 2924 ITaskItem[] outputs = d.OutputsForSource(sources); 2925 2926 Assert.Equal(3, outputs.Length); 2927 Assert.Equal(outputs[0].ItemSpec, Path.GetFullPath("TestFiles\\oNe.obj")); 2928 Assert.Equal(outputs[1].ItemSpec, Path.GetFullPath("TestFiles\\two.obj")); 2929 Assert.Equal(outputs[2].ItemSpec, Path.GetFullPath("TestFiles\\three.obj")); 2930 2931 outputs = d.OutputsForSource(fooItem); 2932 Assert.Equal(4, outputs.Length); 2933 Assert.Equal(outputs[0].ItemSpec, Path.GetFullPath("TestFiles\\foo1.bar")); 2934 Assert.Equal(outputs[1].ItemSpec, Path.GetFullPath("TestFiles\\bar1.baz")); 2935 Assert.Equal(outputs[2].ItemSpec, Path.GetFullPath("TestFiles\\foo2.bar")); 2936 Assert.Equal(outputs[3].ItemSpec, Path.GetFullPath("TestFiles\\bar2.baz")); 2937 2938 // Compact the tlog removing all entries for "foo" leaving the other entries intact 2939 d.RemoveEntriesForSource(fooItem); 2940 d.SaveTlog(); 2941 2942 // All the tlogs need to still be there even after compaction 2943 // It's OK for them to be empty, but their absence might mean a partial clean 2944 // A missing tlog would mean a clean build 2945 Assert.True(Microsoft.Build.Utilities.TrackedDependencies.ItemsExist(tlogs)); 2946 2947 // All log information should now be in the tlog[0] 2948 ITaskItem[] tlogs2 = { 2949 tlogs[0] 2950 }; 2951 2952 CanonicalTrackedOutputFiles d2 = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2953 tlogs2); 2954 2955 outputs = d2.OutputsForSource(fooItem); 2956 Assert.Equal(0, outputs.Length); 2957 2958 outputs = d2.OutputsForSource(sources); 2959 Assert.True(outputs.Length == 3); 2960 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2961 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2962 Assert.True(outputs[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2963 2964 // There should be no difference even if we send in all the original tlogs 2965 CanonicalTrackedOutputFiles d3 = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 2966 tlogs); 2967 2968 outputs = d3.OutputsForSource(fooItem); 2969 Assert.Equal(0, outputs.Length); 2970 2971 outputs = d3.OutputsForSource(sources); 2972 Assert.True(outputs.Length == 3); 2973 Assert.True(outputs[0].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "oNe.obj"))); 2974 Assert.True(outputs[1].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "two.obj"))); 2975 Assert.True(outputs[2].ItemSpec == Path.GetFullPath(Path.Combine("TestFiles", "three.obj"))); 2976 } 2977 2978 /// <summary> 2979 /// Make sure that the compacted read tlog contains the correct information when the composite rooting 2980 /// markers are kept, as in the case where there is a many-to-one relationship between inputs and 2981 /// outputs (ie. Lib, Link) 2982 /// </summary> 2983 [Fact] SaveCompactedReadTlog_MaintainCompositeRootingMarkers()2984 public void SaveCompactedReadTlog_MaintainCompositeRootingMarkers() 2985 { 2986 Console.WriteLine("Test: SaveCompactedReadTlog_MaintainCompositeRootingMarkers"); 2987 // Prepare files 2988 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 2989 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 2990 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 2991 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two1.h"), ""); 2992 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two2.h"), ""); 2993 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two3.h"), ""); 2994 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three1.h"), ""); 2995 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three2.h"), ""); 2996 2997 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 2998 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 2999 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "two.cpp"), ""); 3000 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "three.cpp"), ""); 3001 3002 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 3003 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 3004 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "twothree.obj"), ""); 3005 3006 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 3007 File.WriteAllLines(Path.Combine("TestFiles", "one1.read.tlog"), new string[] { 3008 "#Command some-command", 3009 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3010 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3011 }); 3012 3013 File.WriteAllLines(Path.Combine("TestFiles", "one2.read.tlog"), new string[] { 3014 "#Command some-command1", 3015 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3016 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3017 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3018 }); 3019 3020 File.WriteAllLines(Path.Combine("TestFiles", "two1.read.tlog"), new string[] { 3021 "#Command some-command2", 3022 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 3023 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 3024 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 3025 }); 3026 3027 File.WriteAllLines(Path.Combine("TestFiles", "three1.read.tlog"), new string[] { 3028 "#Command some-command2", 3029 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")), 3030 Path.GetFullPath(Path.Combine("TestFiles", "three1.h")) 3031 }); 3032 3033 File.WriteAllLines(Path.Combine("TestFiles", "twothree.read.tlog"), new string[] { 3034 "#Command some-command2", 3035 "^" + Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 3036 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 3037 Path.GetFullPath(Path.Combine("TestFiles", "two3.h")), 3038 Path.GetFullPath(Path.Combine("TestFiles", "three1.h")), 3039 Path.GetFullPath(Path.Combine("TestFiles", "three2.h")) 3040 }); 3041 3042 ITaskItem[] tlogs = { 3043 new TaskItem(Path.Combine("TestFiles", "one1.read.tlog")), 3044 new TaskItem(Path.Combine("TestFiles", "one2.read.tlog")), 3045 new TaskItem(Path.Combine("TestFiles", "two1.read.tlog")), 3046 new TaskItem(Path.Combine("TestFiles", "three1.read.tlog")), 3047 new TaskItem(Path.Combine("TestFiles", "twothree.read.tlog")) 3048 }; 3049 3050 ITaskItem[] inputs = { 3051 new TaskItem(Path.Combine("TestFiles", "one.cpp")), 3052 new TaskItem(Path.Combine("TestFiles", "two.cpp")), 3053 new TaskItem(Path.Combine("TestFiles", "three.cpp")) 3054 }; 3055 3056 ITaskItem[] outputs = { 3057 new TaskItem(Path.Combine("TestFiles", "one.obj")), 3058 new TaskItem(Path.Combine("TestFiles", "twothree.obj")) 3059 }; 3060 3061 CanonicalTrackedInputFiles d = new CanonicalTrackedInputFiles 3062 ( 3063 DependencyTestHelper.MockTask, 3064 tlogs, 3065 inputs, 3066 null, 3067 outputs, 3068 false, /* no minimal rebuild optimization */ 3069 true /* keep composite rooting markers */ 3070 ); 3071 3072 ITaskItem[] outofdate = d.ComputeSourcesNeedingCompilation(); 3073 3074 // nothing should be out of date 3075 Assert.Equal(0, outofdate.Length); 3076 Assert.Equal(4, d.DependencyTable.Count); 3077 3078 // dependencies should include the three .h files written into the .tlogs + the rooting marker 3079 Assert.True(d.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))].Values.Count == 4); 3080 3081 d.SaveTlog(); 3082 3083 CanonicalTrackedInputFiles d2 = new CanonicalTrackedInputFiles 3084 ( 3085 DependencyTestHelper.MockTask, 3086 tlogs, 3087 inputs, 3088 null, 3089 outputs, 3090 false, /* no minimal rebuild optimization */ 3091 true /* keep composite rooting markers */ 3092 ); 3093 3094 ITaskItem[] outofdate2 = d2.ComputeSourcesNeedingCompilation(); 3095 3096 Assert.Equal(0, outofdate.Length); 3097 Assert.Equal(4, d2.DependencyTable.Count); 3098 3099 // dependencies should include the three .h files written into the .tlogs + the two rooting marker files 3100 Assert.True(d2.DependencyTable[Path.GetFullPath(Path.Combine("TestFiles", "three.cpp")) + "|" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp"))].Values.Count == 4); 3101 } 3102 3103 [Fact] InvalidFlatTrackingTLogName()3104 public void InvalidFlatTrackingTLogName() 3105 { 3106 Console.WriteLine("Test: InvalidFlatTrackingTLogName"); 3107 3108 // Prepare files 3109 DependencyTestHelper.WriteAll("TestFiles\\one.h", ""); 3110 DependencyTestHelper.WriteAll("TestFiles\\one.cpp", ""); 3111 DependencyTestHelper.WriteAll("TestFiles\\one.obj", ""); 3112 DependencyTestHelper.WriteAll("TestFiles\\one.tlog", ""); 3113 3114 MockTask task = DependencyTestHelper.MockTask; 3115 FlatTrackingData data = new FlatTrackingData 3116 ( 3117 task, 3118 DependencyTestHelper.ItemArray(new TaskItem("TestFiles\\|one|.write.tlog")), 3119 false /* don't skip missing files */ 3120 ); 3121 3122 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 3123 Assert.Equal(0, data.DependencyTable.Count); // "DependencyTable should be empty." 3124 } 3125 3126 [Fact] FlatTrackingTLogWithInitialEmptyLine()3127 public void FlatTrackingTLogWithInitialEmptyLine() 3128 { 3129 Console.WriteLine("Test: FlatTrackingTLogWithInitialEmptyLine"); 3130 3131 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { "", "^FOO" }); 3132 3133 MockTask task = DependencyTestHelper.MockTask; 3134 FlatTrackingData data = new FlatTrackingData 3135 ( 3136 task, 3137 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 3138 false /* don't skip missing files */ 3139 ); 3140 3141 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 3142 Assert.Equal(0, data.DependencyTable.Count); // "DependencyTable should be empty." 3143 } 3144 3145 [Fact] FlatTrackingTLogWithEmptyLineImmediatelyAfterRoot()3146 public void FlatTrackingTLogWithEmptyLineImmediatelyAfterRoot() 3147 { 3148 Console.WriteLine("Test: FlatTrackingTLogWithEmptyLineImmediatelyAfterRoot"); 3149 3150 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { "^FOO", "", "FOO" }); 3151 3152 MockTask task = DependencyTestHelper.MockTask; 3153 FlatTrackingData data = new FlatTrackingData 3154 ( 3155 task, 3156 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 3157 false /* don't skip missing files */ 3158 ); 3159 3160 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 3161 Assert.Equal(0, data.DependencyTable.Count); // "DependencyTable should be empty." 3162 } 3163 3164 [Fact] FlatTrackingTLogWithEmptyLineBetweenRoots()3165 public void FlatTrackingTLogWithEmptyLineBetweenRoots() 3166 { 3167 Console.WriteLine("Test: FlatTrackingTLogWithEmptyLineBetweenRoots"); 3168 3169 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { "^FOO", "FOO", "", "^BAR", "BAR" }); 3170 3171 MockTask task = DependencyTestHelper.MockTask; 3172 FlatTrackingData data = new FlatTrackingData 3173 ( 3174 task, 3175 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 3176 false /* don't skip missing files */ 3177 ); 3178 3179 Assert.Equal(1, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should have a warning." 3180 Assert.Equal(0, data.DependencyTable.Count); // "DependencyTable should be empty." 3181 } 3182 3183 [Fact] FlatTrackingTLogWithEmptyRoot()3184 public void FlatTrackingTLogWithEmptyRoot() 3185 { 3186 Console.WriteLine("Test: FlatTrackingTLogWithEmptyRoot"); 3187 3188 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { "^", "FOO" }); 3189 3190 MockTask task = DependencyTestHelper.MockTask; 3191 FlatTrackingData data = new FlatTrackingData 3192 ( 3193 task, 3194 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 3195 false /* don't skip missing files */ 3196 ); 3197 3198 Assert.Equal(0, ((task as ITask).BuildEngine as MockEngine).Warnings); // "Should not warn -- root markers are ignored by default" 3199 Assert.Equal(1, data.DependencyTable.Count); // "DependencyTable should only contain one entry." 3200 Assert.NotNull(data.DependencyTable["FOO"]); // "FOO should be the only entry." 3201 } 3202 3203 [Fact] FlatTrackingDataMissingInputsAndOutputs()3204 public void FlatTrackingDataMissingInputsAndOutputs() 3205 { 3206 Console.WriteLine("Test: FlatTrackingDataMissingInputsAndOutputs"); 3207 // Prepare files 3208 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 3209 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 3210 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 3211 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3212 Thread.Sleep(_sleepTimeMilliseconds); 3213 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 3214 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 3215 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 3216 "#Command some-command", 3217 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3218 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3219 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3220 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3221 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 3222 Path.GetFullPath(Path.Combine("TestFiles", "two1.h")), 3223 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 3224 }); 3225 3226 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 3227 "#Command some-command", 3228 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3229 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 3230 Path.GetFullPath(Path.Combine("TestFiles", "sometempfile.obj")), 3231 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 3232 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 3233 Path.GetFullPath(Path.Combine("TestFiles", "sometempfile2.obj")) 3234 }); 3235 3236 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3237 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3238 3239 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3240 Assert.Equal(2, inputs.MissingFiles.Count); 3241 Assert.Equal(3, outputs.MissingFiles.Count); 3242 } 3243 3244 [Fact] FlatTrackingDataMissingInputs()3245 public void FlatTrackingDataMissingInputs() 3246 { 3247 Console.WriteLine("Test: FlatTrackingDataMissingInputs"); 3248 // Prepare files 3249 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 3250 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 3251 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 3252 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3253 Thread.Sleep(_sleepTimeMilliseconds); 3254 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 3255 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 3256 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 3257 "#Command some-command", 3258 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3259 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3260 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3261 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3262 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 3263 Path.GetFullPath(Path.Combine("TestFiles", "two1.h")), 3264 Path.GetFullPath(Path.Combine("TestFiles", "two2.h")), 3265 }); 3266 3267 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 3268 "#Command some-command", 3269 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3270 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 3271 }); 3272 3273 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3274 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3275 3276 // No matter which way you look at it, if we're missing inputs, we're out of date 3277 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3278 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanTracking, inputs, outputs)); 3279 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputOrOutputNewerThanTracking, inputs, outputs)); 3280 Assert.Equal(2, inputs.MissingFiles.Count); 3281 Assert.Equal(0, outputs.MissingFiles.Count); 3282 } 3283 3284 [Fact] FlatTrackingDataMissingOutputs()3285 public void FlatTrackingDataMissingOutputs() 3286 { 3287 Console.WriteLine("Test: FlatTrackingDataMissingOutputs"); 3288 // Prepare files 3289 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 3290 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 3291 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 3292 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3293 Thread.Sleep(_sleepTimeMilliseconds); 3294 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 3295 Thread.Sleep(_sleepTimeMilliseconds); // need to wait since the timestamp check needs some time to register 3296 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 3297 "#Command some-command", 3298 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3299 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3300 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3301 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3302 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 3303 }); 3304 3305 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 3306 "#Command some-command", 3307 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3308 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 3309 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 3310 Path.GetFullPath(Path.Combine("TestFiles", "sometempfile2.obj")) 3311 }); 3312 3313 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3314 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3315 3316 // No matter which way you look at it, if we're missing outputs, we're out of date 3317 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3318 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanTracking, inputs, outputs)); 3319 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputOrOutputNewerThanTracking, inputs, outputs)); 3320 Assert.Equal(0, inputs.MissingFiles.Count); 3321 Assert.Equal(2, outputs.MissingFiles.Count); 3322 } 3323 3324 [Fact] FlatTrackingDataEmptyInputTLogs()3325 public void FlatTrackingDataEmptyInputTLogs() 3326 { 3327 Console.WriteLine("Test: FlatTrackingDataEmptyInputTLogs"); 3328 // Prepare files 3329 File.WriteAllText(Path.Combine("TestFiles", "one.read.tlog"), String.Empty); 3330 File.WriteAllText(Path.Combine("TestFiles", "one.write.tlog"), String.Empty); 3331 3332 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3333 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3334 3335 // No matter which way you look at it, if we're missing inputs, we're out of date 3336 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3337 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanTracking, inputs, outputs)); 3338 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputOrOutputNewerThanTracking, inputs, outputs)); 3339 } 3340 3341 [Fact] FlatTrackingDataEmptyOutputTLogs()3342 public void FlatTrackingDataEmptyOutputTLogs() 3343 { 3344 Console.WriteLine("Test: FlatTrackingDataEmptyOutputTLogs"); 3345 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 3346 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 3347 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 3348 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3349 Thread.Sleep(_sleepTimeMilliseconds); 3350 // Prepare files 3351 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 3352 "#Command some-command", 3353 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3354 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3355 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3356 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3357 }); 3358 3359 File.WriteAllText(Path.Combine("TestFiles", "one.write.tlog"), String.Empty); 3360 3361 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3362 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3363 3364 // Inputs newer than outputs - if there are no outputs, then we're out of date 3365 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3366 // Inputs newer than tracking - if there are no outputs, then we don't care 3367 Assert.Equal(true, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanTracking, inputs, outputs)); 3368 // Inputs or Outputs newer than tracking - if there is an output tlog, even if there's no text written to it, we're not out of date 3369 Assert.Equal(true, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputOrOutputNewerThanTracking, inputs, outputs)); 3370 } 3371 3372 [Fact] FlatTrackingDataInputNewerThanTracking()3373 public void FlatTrackingDataInputNewerThanTracking() 3374 { 3375 Console.WriteLine("Test: FlatTrackingDataInputNewerThanTracking"); 3376 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 3377 "#Command some-command", 3378 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3379 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3380 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3381 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3382 "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 3383 }); 3384 3385 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 3386 "#Command some-command", 3387 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3388 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 3389 }); 3390 3391 Thread.Sleep(_sleepTimeMilliseconds); 3392 // Prepare files 3393 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 3394 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 3395 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 3396 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3397 Thread.Sleep(_sleepTimeMilliseconds); 3398 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 3399 3400 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3401 // Compact the read tlog 3402 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3403 3404 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanTracking, inputs, outputs)); 3405 3406 // Touch the tracking logs so that are more recent that any of the inputs 3407 Thread.Sleep(_sleepTimeMilliseconds); 3408 File.SetLastWriteTime(Path.Combine("TestFiles", "one.read.tlog"), DateTime.Now); 3409 File.SetLastWriteTime(Path.Combine("TestFiles", "one.write.tlog"), DateTime.Now); 3410 Thread.Sleep(_sleepTimeMilliseconds); 3411 // Touch the output so that we would be out of date with respect to the inputs, but up to date with respect to the tracking logs 3412 File.SetLastWriteTime(Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), DateTime.Now - TimeSpan.FromHours(1)); 3413 3414 outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3415 inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3416 3417 // We should be out of date with respect to the outputs 3418 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3419 // We should be up to date with respect to the tracking data 3420 Assert.Equal(true, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanTracking, inputs, outputs)); 3421 } 3422 3423 [Fact] FlatTrackingDataInputNewerThanTrackingNoOutput()3424 public void FlatTrackingDataInputNewerThanTrackingNoOutput() 3425 { 3426 Console.WriteLine("Test: FlatTrackingDataInputNewerThanTrackingNoOutput"); 3427 // Prepare files 3428 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 3429 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 3430 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 3431 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3432 3433 Thread.Sleep(_sleepTimeMilliseconds); 3434 3435 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 3436 "#Command some-command", 3437 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3438 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3439 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3440 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3441 }); 3442 3443 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "*-one.write.?.tlog"))), false); 3444 // Compact the read tlog 3445 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3446 3447 inputs.SaveTlog(); 3448 outputs.SaveTlog(); 3449 3450 outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "*-one.write.?.tlog"))), false); 3451 // Compact the read tlog 3452 inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3453 3454 Assert.Equal(true, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanTracking, inputs, outputs)); 3455 } 3456 3457 [Fact] FlatTrackingDataInputNewerThanOutput()3458 public void FlatTrackingDataInputNewerThanOutput() 3459 { 3460 Console.WriteLine("Test: FlatTrackingDataInputOrOutputNewerThanTracking"); 3461 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 3462 "#Command some-command", 3463 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3464 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3465 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3466 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3467 }); 3468 3469 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 3470 "#Command some-command", 3471 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3472 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 3473 }); 3474 // Wait so that our tlogs are old 3475 Thread.Sleep(_sleepTimeMilliseconds); 3476 3477 // Prepare the source files (later than tracking logs) 3478 // Therefore newer 3479 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 3480 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 3481 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 3482 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3483 3484 // Prepate the output files (later than tracking logs and source files 3485 // Therefore newer 3486 Thread.Sleep(_sleepTimeMilliseconds); 3487 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 3488 3489 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3490 // Compact the read tlog 3491 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3492 3493 // We should be up to date inputs vs outputs 3494 Assert.True(FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3495 3496 // We should be out of date inputs & outputs vs tracking (since we wrote the files after the tracking logs) 3497 Assert.False(FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputOrOutputNewerThanTracking, inputs, outputs)); 3498 3499 // Touch the input so that we would be out of date with respect to the outputs, and out of date with respect to the tracking logs 3500 Thread.Sleep(_sleepTimeMilliseconds); 3501 File.SetLastWriteTime(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), DateTime.Now); 3502 3503 outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3504 inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3505 3506 // We should be out of date with respect to the tracking logs 3507 Assert.False(FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanTracking, inputs, outputs), "#3"); 3508 3509 // We should be out of date with respect to the outputs 3510 Assert.False(FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs), "#4"); 3511 } 3512 3513 [Fact] FlatTrackingDataInputOrOutputNewerThanTracking()3514 public void FlatTrackingDataInputOrOutputNewerThanTracking() 3515 { 3516 Console.WriteLine("Test: FlatTrackingDataInputOrOutputNewerThanTracking"); 3517 File.WriteAllLines(Path.Combine("TestFiles", "one.read.tlog"), new string[] { 3518 "#Command some-command", 3519 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3520 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3521 Path.GetFullPath(Path.Combine("TestFiles", "one2.h")), 3522 Path.GetFullPath(Path.Combine("TestFiles", "one3.h")), 3523 }); 3524 3525 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 3526 "#Command some-command", 3527 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3528 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 3529 }); 3530 3531 Thread.Sleep(_sleepTimeMilliseconds); 3532 // Prepare files 3533 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one1.h"), ""); 3534 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one2.h"), ""); 3535 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one3.h"), ""); 3536 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3537 Thread.Sleep(_sleepTimeMilliseconds); 3538 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.obj"), ""); 3539 3540 FlatTrackingData outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3541 // Compact the read tlog 3542 FlatTrackingData inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3543 // We should be up to date inputs vs outputs 3544 Assert.Equal(true, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3545 // We should be out of date inputs & outputs vs tracking (since we wrote the files after the tracking logs) 3546 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputOrOutputNewerThanTracking, inputs, outputs)); 3547 3548 3549 // Touch the tracking logs so that are more recent that any of the inputs 3550 Thread.Sleep(_sleepTimeMilliseconds); 3551 File.SetLastWriteTime(Path.Combine("TestFiles", "one.read.tlog"), DateTime.Now); 3552 File.SetLastWriteTime(Path.Combine("TestFiles", "one.write.tlog"), DateTime.Now); 3553 Thread.Sleep(_sleepTimeMilliseconds); 3554 3555 outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3556 inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3557 3558 // We should be up to date with respect to the tracking data 3559 Assert.Equal(true, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputOrOutputNewerThanTracking, inputs, outputs)); 3560 3561 // Touch the input so that we would be out of date with respect to the outputs, but up to date with respect to the tracking logs 3562 File.SetLastWriteTime(Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), DateTime.Now); 3563 3564 outputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), false); 3565 inputs = new FlatTrackingData(DependencyTestHelper.MockTask, DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.read.tlog"))), false); 3566 3567 // We should be out of date with respect to the outputs 3568 Assert.Equal(false, FlatTrackingData.IsUpToDate(DependencyTestHelper.MockTask.Log, UpToDateCheckType.InputNewerThanOutput, inputs, outputs)); 3569 } 3570 3571 [Fact] FlatTrackingExcludeDirectories()3572 public void FlatTrackingExcludeDirectories() 3573 { 3574 Console.WriteLine("Test: FlatTrackingExcludeDirectories"); 3575 3576 // Prepare files 3577 if (!Directory.Exists(Path.Combine("TestFiles", "ToBeExcluded"))) 3578 { 3579 Directory.CreateDirectory(Path.Combine("TestFiles", "ToBeExcluded")); 3580 } 3581 3582 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "ToBeExcluded", "two.cpp"), ""); 3583 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "ToBeExcluded", "two.h"), ""); 3584 3585 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.h"), ""); 3586 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "one.cpp"), ""); 3587 3588 File.WriteAllLines(Path.Combine("TestFiles", "one.tlog"), new string[] { 3589 "#Command some-command", 3590 Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3591 Path.GetFullPath(Path.Combine("TestFiles", "one1.h")), 3592 Path.GetFullPath(Path.Combine("TestFiles", "ToBeExcluded", "two.cpp")), 3593 Path.GetFullPath(Path.Combine("TestFiles", "ToBeExcluded", "two.h")), 3594 Path.GetFullPath(Path.Combine("TestFiles", "SubdirectoryExcluded", "three.cpp")), 3595 Path.GetFullPath(Path.Combine("TestFiles", "SubdirectoryExcluded", "three.h")), 3596 }); 3597 3598 // Get the newest time w/o any exclude paths 3599 Dictionary<string, DateTime> sharedLastWriteTimeUtcCache = new Dictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase); 3600 FlatTrackingData data = new FlatTrackingData 3601 ( 3602 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 3603 null, 3604 DateTime.MinValue, 3605 null, 3606 sharedLastWriteTimeUtcCache 3607 ); 3608 3609 DateTime originalNewest = data.NewestFileTimeUtc; 3610 3611 // Force an update to the files we don't care about 3612 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "ToBeExcluded", "two.cpp"), ""); 3613 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "ToBeExcluded", "two.h"), ""); 3614 if (!Directory.Exists(Path.Combine("TestFiles", "ToBeExcluded", "SubdirectoryExcluded"))) 3615 { 3616 Directory.CreateDirectory(Path.Combine("TestFiles", "ToBeExcluded", "SubdirectoryExcluded")); 3617 } 3618 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "ToBeExcluded", "SubdirectoryExcluded", "three.cpp"), ""); 3619 DependencyTestHelper.WriteAll(Path.Combine("TestFiles", "ToBeExcluded", "SubdirectoryExcluded", "three.h"), ""); 3620 3621 // Now do a flat tracker ignoring the exclude directories and make sure the time didn't change 3622 data = new FlatTrackingData 3623 ( 3624 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.tlog"))), 3625 null, 3626 DateTime.MinValue, 3627 new string[] { Path.GetFullPath(Path.Combine("TestFiles", "ToBeExcluded")) }, 3628 sharedLastWriteTimeUtcCache 3629 ); 3630 3631 Assert.Equal(originalNewest, data.NewestFileTimeUtc); // "Timestamp changed when no tracked files changed." 3632 } 3633 3634 [Fact] TrackingDataCacheResetOnTlogChange()3635 public void TrackingDataCacheResetOnTlogChange() 3636 { 3637 Console.WriteLine("Test: FlatTrackingDataCacheResetOnTlogChange"); 3638 3639 File.WriteAllLines(Path.Combine("TestFiles", "one.write.tlog"), new string[] { 3640 "#Command some-command", 3641 "^" + Path.GetFullPath(Path.Combine("TestFiles", "one.cpp")), 3642 Path.GetFullPath(Path.Combine("TestFiles", "one.obj")), 3643 }); 3644 3645 FlatTrackingData outputs = new FlatTrackingData( 3646 DependencyTestHelper.MockTask, 3647 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), 3648 false); 3649 // Sleep once, so that NTFS has enough time to register a file modified time change 3650 Thread.Sleep(_sleepTimeMilliseconds); 3651 File.WriteAllLines( 3652 Path.Combine("TestFiles", "one.write.tlog"), 3653 new string[] 3654 { 3655 "#Command some-command", "^" + Path.GetFullPath(Path.Combine("TestFiles", "two.cpp")), 3656 Path.GetFullPath(Path.Combine("TestFiles", "two.obj")), 3657 }); 3658 3659 FlatTrackingData outputs2 = new FlatTrackingData( 3660 DependencyTestHelper.MockTask, 3661 DependencyTestHelper.ItemArray(new TaskItem(Path.Combine("TestFiles", "one.write.tlog"))), 3662 false); 3663 3664 // We should not use the cached dependency table, since it has been updated since it was last read from disk 3665 Assert.NotEqual(outputs.DependencyTable, outputs2.DependencyTable); 3666 } 3667 3668 [Fact] RootContainsSubRoots()3669 public void RootContainsSubRoots() 3670 { 3671 Console.WriteLine("Test: RootContainsSubRoots"); 3672 CanonicalTrackedOutputFiles output = new CanonicalTrackedOutputFiles(DependencyTestHelper.MockTask, 3673 null); 3674 3675 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "a|b|C|d|e|F|g")); 3676 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "a")); 3677 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "g")); 3678 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "d")); 3679 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "a|b")); 3680 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "f|g")); 3681 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "b|a")); 3682 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "g|f")); 3683 Assert.True(output.RootContainsAllSubRootComponents("a|b|c|d|e|f|g", "b|e")); 3684 } 3685 } 3686 3687 internal class MockTask : Task 3688 { MockTask(ResourceManager resourceManager)3689 public MockTask(ResourceManager resourceManager) 3690 : base(resourceManager) 3691 { 3692 } 3693 3694 public TaskLoggingHelper LogHelper 3695 { 3696 get { return Log; } 3697 } 3698 Execute()3699 public override bool Execute() 3700 { 3701 return true; 3702 } 3703 } 3704 3705 internal class DependencyTestHelper 3706 { ItemArray(ITaskItem item)3707 public static ITaskItem[] ItemArray(ITaskItem item) 3708 { 3709 List<ITaskItem> itemList = new List<ITaskItem>(); 3710 itemList.Add(item); 3711 return itemList.ToArray(); 3712 } 3713 3714 public static TaskLoggingHelper MockTaskLoggingHelper 3715 { 3716 get 3717 { 3718 MockTask t = new MockTask(Microsoft.Build.Shared.AssemblyResources.PrimaryResources); 3719 t.BuildEngine = new MockEngine(); 3720 return t.LogHelper; 3721 } 3722 } 3723 3724 public static MockTask MockTask 3725 { 3726 get 3727 { 3728 MockTask t = new MockTask(Microsoft.Build.Shared.AssemblyResources.PrimaryResources); 3729 t.BuildEngine = new MockEngine(); 3730 return t; 3731 } 3732 } 3733 WriteAll(string filename, string content)3734 public static void WriteAll(string filename, string content) 3735 { 3736 File.WriteAllText(filename, content); 3737 } 3738 } 3739 } 3740 3741 #endif 3742