private void SimpleSymlinkInputCheck(DateTime symlinkWriteTime, DateTime targetWriteTime, DateTime outputWriteTime, bool expectedOutOfDate) { var inputs = new List <string>(); var outputs = new List <string>(); string inputTarget = "NONEXISTENT_FILE"; string inputSymlink = "NONEXISTENT_FILE"; string outputTarget = "NONEXISTENT_FILE"; try { inputTarget = FileUtilities.GetTemporaryFile(); _testOutputHelper.WriteLine($"Created input file {inputTarget}"); File.SetLastWriteTime(inputTarget, targetWriteTime); inputSymlink = FileUtilities.GetTemporaryFile(null, ".linkin", createFile: false); if (!CreateSymbolicLink(inputSymlink, inputTarget, 0)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } // File.SetLastWriteTime on the symlink sets the target write time, // so set the symlink's write time the hard way using (SafeFileHandle handle = NativeMethodsShared.CreateFile( inputSymlink, NativeMethodsShared.GENERIC_READ | 0x100 /* FILE_WRITE_ATTRIBUTES */, NativeMethodsShared.FILE_SHARE_READ, IntPtr.Zero, NativeMethodsShared.OPEN_EXISTING, NativeMethodsShared.FILE_ATTRIBUTE_NORMAL | NativeMethodsShared.FILE_FLAG_OPEN_REPARSE_POINT, IntPtr.Zero)) { if (handle.IsInvalid) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } long symlinkWriteTimeTicks = symlinkWriteTime.ToFileTimeUtc(); if (!SetFileTime(handle, ref symlinkWriteTimeTicks, ref symlinkWriteTimeTicks, ref symlinkWriteTimeTicks)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } } _testOutputHelper.WriteLine($"Created input link {inputSymlink}"); outputTarget = FileUtilities.GetTemporaryFile(); _testOutputHelper.WriteLine($"Created output file {outputTarget}"); File.SetLastWriteTime(outputTarget, outputWriteTime); inputs.Add(inputSymlink); outputs.Add(outputTarget); DependencyAnalysisLogDetail detail; Assert.Equal(expectedOutOfDate, TargetUpToDateChecker.IsAnyOutOfDate(out detail, Directory.GetCurrentDirectory(), inputs, outputs)); } finally { if (File.Exists(inputTarget)) { File.Delete(inputTarget); } if (File.Exists(inputSymlink)) { File.Delete(inputSymlink); } if (File.Exists(outputTarget)) { File.Delete(outputTarget); } } }