public void ReadRaceEventLoggedOnViolationDistributed() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new FileMonitoringViolationAnalyzer(LoggingContext, context, graph, new QueryableEmptyFileContentManager(), validateDistribution: true, ignoreDynamicWritesOnAbsentProbes: false, unexpectedFileAccessesAsErrors: true); AbsolutePath violatorOutput = CreateAbsolutePath(context, JunkPath); AbsolutePath producerOutput = CreateAbsolutePath(context, ProducedPath); Process producer = graph.AddProcess(producerOutput); Process violator = graph.AddProcess(violatorOutput); graph.SetConcurrentRange(producer, violator); AnalyzePipViolationsResult analyzePipViolationsResult = analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.Read, producerOutput) }, null, // whitelisted accesses exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); AssertTrue(!analyzePipViolationsResult.IsViolationClean); AssertErrorEventLogged(EventId.FileMonitoringError); AssertVerboseEventLogged(LogEventId.DependencyViolationReadRace); }
public void DoubleWriteReportedForPathOrderedBefore() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); AbsolutePath violatorOutput = CreateAbsolutePath(context, JunkPath); AbsolutePath producerOutput = CreateAbsolutePath(context, DoubleWritePath); Process producer = graph.AddProcess(producerOutput); Process violator = graph.AddProcess(violatorOutput); analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.ReadWrite, producerOutput) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.DoubleWrite, FileMonitoringViolationAnalyzer.AccessLevel.Write, producerOutput, violator, producer), "The violator is after the producer, so this should be a double-write on the produced path."); analyzer.AssertNoExtraViolationsCollected(); AssertErrorEventLogged(EventId.FileMonitoringError); }
public void DoubleWriteNotReportedForPathOrderedAfter() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); AbsolutePath violatorOutput = CreateAbsolutePath(context, JunkPath); AbsolutePath producerOutput = CreateAbsolutePath(context, DoubleWritePath); Process violator = graph.AddProcess(violatorOutput); Process producer = graph.AddProcess(producerOutput); analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.ReadWrite, producerOutput) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null, ReadOnlyArray <(FileArtifact, FileMaterializationInfo, PipOutputOrigin)> .Empty, out _); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.UndeclaredOutput, FileMonitoringViolationAnalyzer.AccessLevel.Write, producerOutput, violator, null), "The violator has an undeclared output but it wasn't reported."); analyzer.AssertNoExtraViolationsCollected(); AssertErrorEventLogged(EventId.FileMonitoringError); }
public void UndeclaredReadCycleReportedForPathOrderedAfter() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); AbsolutePath violatorOutput = CreateAbsolutePath(context, JunkPath); AbsolutePath producerOutput = CreateAbsolutePath(context, ProducedPath); Process violator = graph.AddProcess(violatorOutput); Process producer = graph.AddProcess(producerOutput); analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.Read, producerOutput) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.UndeclaredReadCycle, FileMonitoringViolationAnalyzer.AccessLevel.Read, producerOutput, violator, producer), "An UndeclaredReadCycle should have been reported since an earlier pip has an undeclared read of a later pip's output."); analyzer.AssertNoExtraViolationsCollected(); AssertErrorEventLogged(EventId.FileMonitoringError); }
public void UndeclaredOrderedReadReportedForPathOrderedBefore() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph, true); AbsolutePath producerOutput = CreateAbsolutePath(context, ProducedPath); AbsolutePath violatorOutput = CreateAbsolutePath(context, JunkPath); Process producer = graph.AddProcess(producerOutput); Process violator = graph.AddProcess(violatorOutput); analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.Read, producerOutput) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null, ReadOnlyArray <(FileArtifact, FileMaterializationInfo, PipOutputOrigin)> .Empty, out _); AssertVerboseEventLogged(LogEventId.DependencyViolationUndeclaredOrderedRead); AssertErrorEventLogged(EventId.FileMonitoringError); }
public void DoubleWriteEventLoggedOnViolationError() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new FileMonitoringViolationAnalyzer(LoggingContext, context, graph, new QueryableEmptyFileContentManager(), validateDistribution: false, ignoreDynamicWritesOnAbsentProbes: false, unexpectedFileAccessesAsErrors: true); AbsolutePath violatorOutput = CreateAbsolutePath(context, JunkPath); AbsolutePath producerOutput = CreateAbsolutePath(context, DoubleWritePath); Process producer = graph.AddProcess(producerOutput); Process violator = graph.AddProcess(violatorOutput); analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.ReadWrite, producerOutput) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null, ReadOnlyArray <(FileArtifact, FileMaterializationInfo, PipOutputOrigin)> .Empty, out _); AssertVerboseEventLogged(LogEventId.DependencyViolationDoubleWrite); AssertErrorEventLogged(EventId.FileMonitoringError); }
public void DoubleWritePolicyDeterminesViolationSeverity(DoubleWritePolicy doubleWritePolicy) { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer( LoggingContext, context, graph, // Set this to test the logic of base.HandleDependencyViolation(...) instead of the overriding fake doLogging: true, collectNonErrorViolations: true); AbsolutePath violatorOutput = CreateAbsolutePath(context, JunkPath); AbsolutePath producerOutput = CreateAbsolutePath(context, DoubleWritePath); Process producer = graph.AddProcess(producerOutput, doubleWritePolicy); Process violator = graph.AddProcess(violatorOutput, doubleWritePolicy); analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.ReadWrite, producerOutput) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null, ReadOnlyArray <(FileArtifact, FileMaterializationInfo, PipOutputOrigin)> .Empty, out _); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.DoubleWrite, FileMonitoringViolationAnalyzer.AccessLevel.Write, producerOutput, violator, producer), "The violator is after the producer, so this should be a double-write on the produced path."); analyzer.AssertNoExtraViolationsCollected(); AssertVerboseEventLogged(LogEventId.DependencyViolationDoubleWrite); // Based on the double write policy, the violation is an error or a warning if (doubleWritePolicy == DoubleWritePolicy.DoubleWritesAreErrors) { AssertErrorEventLogged(EventId.FileMonitoringError); } else { AssertWarningEventLogged(EventId.FileMonitoringWarning); } }
public void InvalidAccessedPathExcludedFromAnalysis() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); var declaredOuput = CreateAbsolutePath(context, X("/X/out/declared")); var process = graph.AddProcess(declaredOuput); var result = analyzer.AnalyzePipViolations( process, new[] { CreateViolationForInvalidPath(RequestedAccess.Read, X("c/invalid:name_1.txt")) }, new[] { CreateViolationForInvalidPath(RequestedAccess.Read, X("c/invalid:name_2.txt")) }, exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null ); XAssert.IsTrue(result.IsViolationClean); }
public void UndeclaredOutput() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); AbsolutePath declaredOutput = CreateAbsolutePath(context, X("/X/out/produced1")); AbsolutePath undeclaredOutput = CreateAbsolutePath(context, X("/X/out/produced2")); Process producer = graph.AddProcess(declaredOutput); analyzer.AnalyzePipViolations( producer, new[] { CreateViolation(RequestedAccess.Write, undeclaredOutput), }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.UndeclaredOutput, FileMonitoringViolationAnalyzer.AccessLevel.Write, undeclaredOutput, producer, null), "The violator has an undeclared output but it wasn't reported."); AssertErrorEventLogged(EventId.FileMonitoringError); }
public void ReadLevelViolationReportedForUnknownPath() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); AbsolutePath unknown = CreateAbsolutePath(context, X("/X/out/unknown")); AbsolutePath produced = CreateAbsolutePath(context, ProducedPath); Process process = graph.AddProcess(produced); analyzer.AnalyzePipViolations( process, new[] { CreateViolation(RequestedAccess.Read, unknown) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.MissingSourceDependency, FileMonitoringViolationAnalyzer.AccessLevel.Read, unknown, process, null), "A MissingSourceDependency should have been reported with no suggested value"); analyzer.AssertNoExtraViolationsCollected(); AssertErrorEventLogged(EventId.FileMonitoringError); }
private Dictionary <string, global::BuildXL.Pips.Operations.Process> AddPips(QueryablePipDependencyGraph graph, string graphSpec) { var edges = GraphWithCycles .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) .Select(parseLine) .ToArray(); var nodes = edges.SelectMany(edge => new[] { edge.from }.Concat(edge.to)).ToHashSet(); var pips = nodes .Select(n => (name: n, proc: graph.AddProcess(ToAbsolutePath(X($"/x/out/{n}.out"))))) .ToDictionary(kvp => kvp.name, kvp => kvp.proc); foreach (var edge in edges) { foreach (var to in edge.to) { graph.AddDataflowDependency(from: pips[edge.from].PipId, to: pips[to].PipId); } } return(pips); (string from, string[] to) parseLine(string line) { var splits = line.Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray(); XAssert.IsTrue(splits.Length <= 2); var lhs = splits[0]; var rhs = splits.Length > 1 ? splits[1] : string.Empty; return(from : lhs, to : rhs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray()); } }
public void ReadRaceReportedForConcurrentPath() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); AbsolutePath violatorOutput = CreateAbsolutePath(context, JunkPath); AbsolutePath producerOutput = CreateAbsolutePath(context, ProducedPath); Process producer = graph.AddProcess(producerOutput); Process violator = graph.AddProcess(violatorOutput); graph.SetConcurrentRange(producer, violator); analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.Read, producerOutput) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null, ReadOnlyArray <(FileArtifact, FileMaterializationInfo, PipOutputOrigin)> .Empty, out _); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.ReadRace, FileMonitoringViolationAnalyzer.AccessLevel.Read, producerOutput, violator, producer), "The violator is concurrent with the producer, so this should be a read-race on the produced path."); analyzer.AssertNoExtraViolationsCollected(); AssertErrorEventLogged(EventId.FileMonitoringError); }
public void AggregateLogMessageOnUndeclaredReadWrite() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); AbsolutePath declaredOuput = CreateAbsolutePath(context, X("/X/out/declared")); AbsolutePath undeclaredRead = CreateAbsolutePath(context, X("/X/out/undeclaredR")); AbsolutePath undeclaredWrite = CreateAbsolutePath(context, X("/X/out/undeclaredW")); AbsolutePath undeclaredReadWrite = CreateAbsolutePath(context, X("/X/out/undeclaredRW")); Process process = graph.AddProcess(declaredOuput); analyzer.AnalyzePipViolations( process, new[] { CreateViolation(RequestedAccess.Read, undeclaredRead), CreateViolation(RequestedAccess.Write, undeclaredWrite), CreateViolation(RequestedAccess.Read, undeclaredReadWrite), CreateViolation(RequestedAccess.Write, undeclaredReadWrite) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null, ReadOnlyArray <(FileArtifact, FileMaterializationInfo, PipOutputOrigin)> .Empty, out _); AssertErrorEventLogged(EventId.FileMonitoringError); // The ending of the expected log message. // The order of files here is based on the sorting in FileMonitoringViolationAnalyzer.AggregateAccessViolationPaths() StringBuilder expectedLog = new StringBuilder(); expectedLog.AppendLine("- Disallowed file accesses were detected (R = read, W = write):"); // process that 'caused' the violations expectedLog.AppendLine($"Disallowed file accesses performed by: {ReportedExecutablePath}"); // aggregated paths expectedLog.AppendLine(ReportedFileAccess.ReadDescriptionPrefix + undeclaredRead.ToString(context.PathTable)); expectedLog.AppendLine(ReportedFileAccess.WriteDescriptionPrefix + undeclaredReadWrite.ToString(context.PathTable)); expectedLog.AppendLine(ReportedFileAccess.WriteDescriptionPrefix + undeclaredWrite.ToString(context.PathTable)); var eventLog = OperatingSystemHelper.IsUnixOS ? EventListener.GetLog().Replace("\r", "") : EventListener.GetLog(); XAssert.IsTrue(eventLog.EndsWith(expectedLog.ToString())); }
public void ReadUndeclaredOutput() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph, true); AbsolutePath producerOutput = CreateAbsolutePath(context, ProducedPath); AbsolutePath undeclaredOutput = CreateAbsolutePath(context, X("/X/out/produced2")); AbsolutePath consumerOutput = CreateAbsolutePath(context, JunkPath); AbsolutePath consumerOutput2 = CreateAbsolutePath(context, X("/X/out/junk2")); Process producerViolator = graph.AddProcess(producerOutput); Process consumerViolator = graph.AddProcess(consumerOutput); Process consumerViolator2 = graph.AddProcess(consumerOutput2); analyzer.AnalyzePipViolations( consumerViolator, new[] { CreateViolation(RequestedAccess.Read, undeclaredOutput), }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); analyzer.AnalyzePipViolations( producerViolator, new[] { CreateViolation(RequestedAccess.Write, undeclaredOutput), }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); analyzer.AnalyzePipViolations( consumerViolator2, new[] { CreateViolation(RequestedAccess.Read, undeclaredOutput) }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.UndeclaredOutput, FileMonitoringViolationAnalyzer.AccessLevel.Write, undeclaredOutput, producerViolator, null), "The violator has wrote undeclared output but it wasn't reported."); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.ReadUndeclaredOutput, FileMonitoringViolationAnalyzer.AccessLevel.Read, undeclaredOutput, consumerViolator2, producerViolator), "The violator read an undeclared output but it wasn't reported as ReadUndeclaredOutput."); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.MissingSourceDependency, FileMonitoringViolationAnalyzer.AccessLevel.Read, undeclaredOutput, consumerViolator2, null), "The violator read an undeclared output but it wasn't reported as MissingSourceDependency."); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.ReadUndeclaredOutput, FileMonitoringViolationAnalyzer.AccessLevel.Read, undeclaredOutput, consumerViolator, producerViolator), "The violator read an undeclared output but it wasn't reported as ReadUndeclaredOutput."); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.MissingSourceDependency, FileMonitoringViolationAnalyzer.AccessLevel.Read, undeclaredOutput, consumerViolator, null), "The violator read an undeclared output but it wasn't reported as MissingSourceDependency."); AssertVerboseEventLogged(LogEventId.DependencyViolationReadUndeclaredOutput, 2); AssertVerboseEventLogged(LogEventId.DependencyViolationUndeclaredOutput); AssertVerboseEventLogged(LogEventId.DependencyViolationMissingSourceDependency, 2); AssertErrorEventLogged(EventId.FileMonitoringError, 3); }
public void MultipleViolationsReportedForSinglePip() { BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); var graph = new QueryablePipDependencyGraph(context); var analyzer = new TestFileMonitoringViolationAnalyzer(LoggingContext, context, graph); AbsolutePath produced1 = CreateAbsolutePath(context, X("/X/out/produced1")); AbsolutePath produced2 = CreateAbsolutePath(context, X("/X/out/produced2")); AbsolutePath produced3 = CreateAbsolutePath(context, X("/X/out/produced3")); Process producer1 = graph.AddProcess(produced1); Process producer2 = graph.AddProcess(produced2); Process producer3 = graph.AddProcess(produced3); Process violator = graph.AddProcess(CreateAbsolutePath(context, X("/X/out/violator"))); graph.SetConcurrentRange(producer3, violator); analyzer.AnalyzePipViolations( violator, new[] { CreateViolation(RequestedAccess.Read, produced3), CreateViolation(RequestedAccess.Read, produced2), CreateViolation(RequestedAccess.Write, produced1), }, new ReportedFileAccess[0], exclusiveOpaqueDirectoryContent: null, sharedOpaqueDirectoryWriteAccesses: null, allowedUndeclaredReads: null, absentPathProbesUnderOutputDirectories: null); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.ReadRace, FileMonitoringViolationAnalyzer.AccessLevel.Read, produced3, violator, producer3), "The violator is concurrent with the producer, so this should be a read-race on the produced path."); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.UndeclaredOrderedRead, FileMonitoringViolationAnalyzer.AccessLevel.Read, produced2, violator, producer2), "The violator has an undeclared read on the producer but it wasn't reported."); analyzer.AssertContainsViolation( new DependencyViolation( FileMonitoringViolationAnalyzer.DependencyViolationType.DoubleWrite, FileMonitoringViolationAnalyzer.AccessLevel.Write, produced1, violator, producer1), "The violator is after the producer, so this should be a double-write on the produced path."); analyzer.AssertNoExtraViolationsCollected(); AssertErrorEventLogged(EventId.FileMonitoringError); }