public void LongPathAccessControlTest() { // Skip this test if running on .NET Framework with vstest // Reason: new FileInfo(longPath) fails with PathTooLongException (interestingly, it works fine when executed by xunit) if (!OperatingSystemHelper.IsDotNetCore && IsRunningInVsTestTestHost()) { return; } var rootDir = Path.Combine(TemporaryDirectory, "dir"); var longPath = Enumerable.Range(0, NativeIOConstants.MaxDirectoryPath).Aggregate(rootDir, (path, _) => Path.Combine(path, "dir")); var file = Path.Combine(longPath, "fileWithWriteAccess.txt"); FileUtilities.CreateDirectory(longPath); SafeFileHandle fileHandle; var result = FileUtilities.TryCreateOrOpenFile( file, FileDesiredAccess.GenericWrite, FileShare.Delete, FileMode.Create, FileFlagsAndAttributes.FileAttributeNormal, out fileHandle); XAssert.IsTrue(result.Succeeded); FileUtilities.SetFileAccessControl(file, FileSystemRights.WriteAttributes, true); XAssert.IsTrue(FileUtilities.HasWritableAccessControl(file)); // Delete the created directory fileHandle.Close(); FileUtilities.DeleteDirectoryContents(rootDir, deleteRootDirectory: true); XAssert.FileDoesNotExist(file); }
public void DeleteFile(RepoConfig repoCfg) { using var helper = Clone(repoCfg); // track an existing file var filePath = helper.GetPath(@"src\files\changingFile.txt"); var result = helper.TrackPath(filePath); XAssert.AreEqual(PathExistence.ExistsAsFile, result.Existence); // delete that file File.Delete(filePath); // snap changes and assert that a 'DeleteFile' USN entry was recorded helper.SnapCheckPoint(); helper.AssertDeleteFile(filePath); XAssert.FileDoesNotExist(filePath); }
public void TestPipRemovedFromGraph(bool invalidatePipA) { // Setup: PipA, PipB => sharedOpaqueDir; reset; reschedule only PipA var sharedOpaqueDir = Path.Combine(ObjectRoot, $"sod-{nameof(TestPipRemovedFromGraph)}"); var sodOutA = CreateOutputFileArtifact(sharedOpaqueDir, prefix: "PipA"); var sourceA = CreateSourceFile(); var pipBuilderA = CreateSharedOpaqueProducer(sharedOpaqueDir, FileArtifact.Invalid, sourceA, filesToProduceDynamically: sodOutA); var sodOutB = CreateOutputFileArtifact(sharedOpaqueDir, prefix: "PipB"); var pipBuilderB = CreateSharedOpaqueProducer(sharedOpaqueDir, filesToProduceDynamically: sodOutB); var pipA1 = SchedulePipBuilder(pipBuilderA); var pipB1 = SchedulePipBuilder(pipBuilderB); RunScheduler().AssertCacheMiss(pipA1.Process.PipId, pipB1.Process.PipId); AssertSharedOpaqueOutputDeletionNotPostponed(); // reset ResetPipGraphBuilder(); // reschedule only pipA if (invalidatePipA) { File.WriteAllText(ToString(sourceA), "New content"); } var pipA2 = SchedulePipBuilder(pipBuilderA); // pipB has been removed from the graph // => its outputs should be deleted before execution // => for pipA delayed deletion should still be enabled var result = RunScheduler(); AssertSharedOpaqueOutputDeletionPostponed(numLazilyDeleted: invalidatePipA ? 1 : 0); AssertInformationalEventLogged(EventId.DeletingOutputsFromExtraneousSidebandFilesStarted, count: 1); XAssert.FileDoesNotExist(ToString(sodOutB)); if (invalidatePipA) { result.AssertCacheMiss(pipA2.Process.PipId); } else { result.AssertCacheHit(pipA2.Process.PipId); } }
public void TestSidebandFileIsAlwaysProducedForPipsWithSharedOpaqueDirectoryOutputs() { // Setup: PipA => sharedOpaqueDir => PipB var sharedOpaqueDir = Path.Combine(ObjectRoot, $"sod-{nameof(TestSidebandFileIsAlwaysProducedForPipsWithSharedOpaqueDirectoryOutputs)}"); var pipA = CreateAndScheduleSharedOpaqueProducer( sharedOpaqueDir, fileToProduceStatically: FileArtifact.Invalid, sourceFileToRead: CreateSourceFile(), filesToProduceDynamically: new FileArtifact[0]); var pipB = CreateAndSchedulePipBuilder(new Operation[] { Operation.WriteFile(CreateOutputFileArtifact()) }); var result = RunScheduler().AssertCacheMiss(pipA.Process.PipId, pipB.Process.PipId); XAssert.FileExists(GetSidebandFile(result, pipA.Process), "Sideband file must be produced for all pips with SOD outputs, even when they don't write a single file into SOD"); XAssert.FileDoesNotExist(GetSidebandFile(result, pipB.Process), "Sideband file should not be produced for pips without any SOD outputs"); }
public void GvfsProjectionDoesNotChangeUponLocalCommit() { using var helper = Clone(new RepoConfig(RepoKind.Gvfs, RepoInit.UseExisting)); helper.SnapCheckPoint(); // create a new file var file = helper.GetPath(@"newLocalFile.txt"); XAssert.FileDoesNotExist(file); TestOutput.WriteLine("Creating new file: " + file); File.WriteAllText(file, "hi"); // commit to master; assert that GVFS projection hasn't changed helper.Git("add ."); helper.Git("commit -m hi"); helper.SnapCheckPoint(); helper.AssertNoChange(helper.GetGvfsProjectionFilePath()); // create a new local branch, modify the new file, and commit it; assert that GVFS projection hasn't changed var newBranchName = "tmp/new-local-branch"; helper.Git($"checkout -b {newBranchName}"); using var reseter = new RepoReseter(helper, newBranchName); // This guy will delete the newly created branch TestOutput.WriteLine("Modifying file: " + file); File.AppendAllText(file, "there"); helper.Git("commit -am there"); helper.SnapCheckPoint(); helper.AssertNoChange(helper.GetGvfsProjectionFilePath()); // delete the file, commit that as a new change; assert GVFS projection still hasn't changed TestOutput.WriteLine("Deleting file: " + file); helper.Git($"rm -f {file}"); helper.Git("commit -am deleted"); helper.SnapCheckPoint(); XAssert.FileDoesNotExist(file); helper.AssertNoChange(helper.GetGvfsProjectionFilePath()); }
public void StdFileCopyTest(global::BuildXL.Utilities.Configuration.OutputReportingMode outputReportingMode) { EventListener.NestedLoggerHandler += eventData => { if (eventData.EventId == (int)LogEventId.PipProcessError) { var loggedMessage = eventData.Payload.ToArray()[5].ToString(); var extraLoggedMessage = eventData.Payload.ToArray()[6].ToString(); m_loggedPipFailures.Add(loggedMessage); m_loggedPipFailures.Add(extraLoggedMessage); } }; Configuration.Sandbox.OutputReportingMode = outputReportingMode; var text = @" * BEFORE * * <error> * * err1 * * </error> * * AFTER * * <error>err2</error> * <error>err3</error> * "; var errRegex = "error"; var ops = SplitLines(text) .Select(l => Operation.Echo(l, true)) .Concat(new[] { Operation.WriteFile(CreateOutputFileArtifact()), Operation.Fail() }); var pipBuilder = CreatePipBuilder(ops); pipBuilder.ErrorRegex = new RegexDescriptor(StringId.Create(Context.StringTable, errRegex), RegexOptions.None); pipBuilder.EnableMultiLineErrorScanning = false; Process pip = SchedulePipBuilder(pipBuilder).Process; var runResult = RunScheduler(); runResult.AssertFailure(); AssertErrorEventLogged(LogEventId.PipProcessError); string expectedPrintedError; var stdFilePathInLogDir = Path.Combine(runResult.Config.Logging.LogsDirectory.ToString(Context.PathTable), SandboxedProcessPipExecutor.StdOutputsDirNameInLog, pip.FormattedSemiStableHash, SandboxedProcessFile.StandardError.DefaultFileName()); if (outputReportingMode == global::BuildXL.Utilities.Configuration.OutputReportingMode.TruncatedOutputOnError) { expectedPrintedError = @" * <error> * * </error> * * <error>err2</error> * <error>err3</error> * This message has been filtered by a regex. Please find the complete stdout/stderr in the following file(s) in the log directory."; XAssert.FileExists(stdFilePathInLogDir, $"StandardError file {stdFilePathInLogDir} should had been copied to log directory"); } else { expectedPrintedError = @" * <error> * * </error> * * <error>err2</error> * <error>err3</error> * This message has been filtered by a regex. Please find the complete stdout/stderr in the following file(s) or in the DX0066 event in the log file."; XAssert.FileDoesNotExist(stdFilePathInLogDir, $"StandardError file {stdFilePathInLogDir} should had been copied to log directory"); } XAssert.ArrayEqual( SplitLines(expectedPrintedError), m_loggedPipFailures.SelectMany(SplitLines).ToArray()); // Rerun the pip and the std file will be copied to the log directory too runResult = RunScheduler(); runResult.AssertFailure(); string extension = Path.GetExtension(stdFilePathInLogDir); var basename = stdFilePathInLogDir.Substring(0, stdFilePathInLogDir.Length - extension.Length); stdFilePathInLogDir = $"{basename}.1{extension}"; if (outputReportingMode == global::BuildXL.Utilities.Configuration.OutputReportingMode.TruncatedOutputOnError) { XAssert.FileExists(stdFilePathInLogDir, $"StandardError file {stdFilePathInLogDir} should had been copied to log directory"); } else { XAssert.FileDoesNotExist(stdFilePathInLogDir, $"StandardError file {stdFilePathInLogDir} should had been copied to log directory"); } AssertErrorEventLogged(LogEventId.PipProcessError); }