public void ValidateBasicCacheMissCounters() { AbsolutePath.TryCreate(Context.PathTable, ReadonlyRoot, out var readonlyRootPath); var readonlyRootDir = DirectoryArtifact.CreateWithZeroPartialSealId(readonlyRootPath); var childDir = DirectoryArtifact.CreateWithZeroPartialSealId(CreateUniqueDirectory(ReadonlyRoot)); // Enumerate /readonlyroot and /readonlyroot/childDir Process enumeratorPip = CreateAndSchedulePipBuilder(new Operation[] { Operation.EnumerateDir(childDir), Operation.WriteFile(CreateOutputFileArtifact()) }).Process; Process writerPip = CreateAndSchedulePipBuilder(new Operation[] { Operation.WriteFile(CreateOutputFileArtifact()) }).Process; ScheduleRunResult result1 = RunScheduler(); result1.AssertCacheMiss(enumeratorPip.PipId, writerPip.PipId); result1.AssertNumWeakFingerprintMisses(2); // Create /childDir/nestedFile, causing strong fingerprint miss FileArtifact nestedFile = CreateSourceFile(ArtifactToString(childDir)); ScheduleRunResult result2 = RunScheduler(); result2.AssertCacheHit(writerPip.PipId); // Weak fingerprint hit on both pips result2.AssertNumWeakFingerprintMisses(0); // Strong fingerprint miss on enumeratorPip result2.AssertCacheMiss(enumeratorPip.PipId); result2.AssertNumStrongFingerprintMisses(1); }
public void ExtraFingerprintSaltsTest() { var dir = Path.Combine(ObjectRoot, "Dir"); var dirPath = AbsolutePath.Create(Context.PathTable, dir); FileArtifact input = CreateSourceFile(root: dirPath, prefix: "input-file"); FileArtifact output = CreateOutputFileArtifact(root: dirPath, prefix: "output-file"); var pipBuilder = CreatePipBuilder(new[] { Operation.ReadFile(input), Operation.WriteFile(output) }); var pip = SchedulePipBuilder(pipBuilder); SetExtraSalts("FirstSalt", true); ScheduleRunResult initialbuild = RunScheduler().AssertCacheMiss(pip.Process.PipId); var oldSessionId = initialbuild.Session.Id; var oldRelatedSessionId = initialbuild.Session.RelatedId; ScheduleRunResult cacheHitBuild = RunScheduler().AssertCacheHit(pip.Process.PipId); SetExtraSalts("SecondSalt", false); ScheduleRunResult cacheMissBuild = RunScheduler().AssertCacheMiss(pip.Process.PipId); string[] messages = { nameof(ExtraFingerprintSalts.FingerprintSalt), nameof(ExtraFingerprintSalts.MaskUntrackedAccesses), nameof(ExtraFingerprintSalts.NormalizeReadTimestamps), nameof(ExtraFingerprintSalts.PipWarningsPromotedToErrors), nameof(ExtraFingerprintSalts.ValidateDistribution), oldSessionId, oldRelatedSessionId }; RunAnalyzer(cacheHitBuild, cacheMissBuild).AssertPipMiss(pip.Process, PipCacheMissType.MissForDescriptorsDueToWeakFingerprints, messages); }
public void EventualFilesystemUsedForProbe() { // pipA enumerates the directory where its output and pipB's output goes. It is forced to run before B because // B consumes its output var outA = CreateOutputFileArtifact(ObjectRoot); var opsA = new Operation[] { Operation.Probe(CreateSourceFile()), Operation.EnumerateDir(CreateOutputDirectoryArtifact(ObjectRoot)), Operation.WriteFile(outA) }; Process pipA = CreateAndSchedulePipBuilder(opsA).Process; var opsB = new Operation[] { Operation.Probe(outA), Operation.WriteFile(CreateOutputFileArtifact(ObjectRoot)) }; Process pipB = CreateAndSchedulePipBuilder(opsB).Process; // Perform build with full graph filesystem. Both output files should be produced ScheduleRunResult result = RunScheduler().AssertSuccess(); result.AssertCacheMiss(pipA.PipId); result.AssertCacheMiss(pipB.PipId); // Perform build with full graph filesystem. Both processes should be a cache hit, even though the directory // that got enumerated changed state ScheduleRunResult result2 = RunScheduler().AssertSuccess(); XAssert.AreEqual(PipResultStatus.UpToDate, result2.PipResults[pipA.PipId]); XAssert.AreEqual(PipResultStatus.UpToDate, result2.PipResults[pipB.PipId]); }
public void ReadRaceFromOpaqueDirectory() { var opaqueOutput = CreateOutputDirectoryArtifact(); var outputWithinOpaque = CreateOutputFileArtifact(opaqueOutput.Path.ToString(Context.PathTable)); Directory.CreateDirectory(opaqueOutput.Path.ToString(Context.PathTable)); File.WriteAllText(outputWithinOpaque.Path.ToString(Context.PathTable), "content"); Configuration.Schedule.MaxProcesses = 1; var builderA = CreatePipBuilder(new Operation[] { Operation.WriteFile(CreateOutputFileArtifact(ObjectRoot)), Operation.WriteFile(outputWithinOpaque, doNotInfer: true) }); builderA.AddOutputDirectory(opaqueOutput, SealDirectoryKind.Opaque); var writer = SchedulePipBuilder(builderA); var builderB = CreatePipBuilder(new Operation[] { Operation.WriteFile(CreateOutputFileArtifact(ObjectRoot)), Operation.ReadFile(outputWithinOpaque, doNotInfer: true) }); var reader = SchedulePipBuilder(builderB); ScheduleRunResult result = RunScheduler(constraintExecutionOrder: new[] { ((Pip)writer.Process, (Pip)reader.Process) }).AssertFailure();
/// <summary> /// Runs an execution analyzer in <see cref="AnalysisMode"/>. /// </summary> /// <param name="buildA"> /// The scheduler run to analyze /// </param> /// <param name="buildB"> /// Optional second scheduler run to analyze for modes that /// compare execution logs /// </param> /// <param name="additionalArgs"> /// Additional options applicable to only this particular analyzer run /// </param> /// <returns> /// string path to results file /// </returns> public AnalyzerResult RunAnalyzer(ScheduleRunResult buildA, ScheduleRunResult buildB = null, IEnumerable <Option> additionalArgs = null) { // The test class must set an analysis mode in the constructor XAssert.IsTrue(AnalysisMode != AnalysisMode.None); // The test class must set the default command line args in the constructor XAssert.IsTrue(ModeSpecificDefaultArgs != null); string[] commandLineArgs = BuildCommandLineArgs(buildA, buildB: buildB, additionalArgs: additionalArgs); // Run the analyzer with console output redirected to analyzer result var result = new AnalyzerResult(); using (var console = new ConsoleRedirector(ref result.StandardOutput)) { result.ExitCode = Program.Main(commandLineArgs); } if (ResultFileToRead != null) { XAssert.IsTrue(File.Exists(ResultFileToRead)); result.FileOutput = File.ReadAllText(ResultFileToRead); } return(result); }
public void ProcessMustRunLocalDueToTag() { // Force run remotely. Configuration.Schedule.RemotingThresholdMultiplier = 0.0; // This configuration will test that must-run-local tags take precendence over can-run-remote tags. const string MustRunLocalTag = nameof(MustRunLocalTag); Configuration.Schedule.ProcessMustRunLocalTags = new List <string> { MustRunLocalTag }; Configuration.Schedule.ProcessCanRunRemoteTags = new List <string> { MustRunLocalTag }; ProcessBuilder builder = CreatePipBuilder(new[] { Operation.ReadFile(CreateSourceFile()), Operation.WriteFile(CreateOutputFileArtifact()) }); builder.AddTags(Context.StringTable, MustRunLocalTag); ProcessWithOutputs process = SchedulePipBuilder(builder); ScheduleRunResult result = RunScheduler().AssertSuccess(); XAssert.AreEqual(0, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRunRemoteProcesses)); XAssert.AreEqual(1, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRunLocallyProcessesOnRemotingWorker)); XAssert.AreEqual(0, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRemoteFallbackRetries)); }
public void NonCacheableWhitelistPipMiss() { FileArtifact whitelistFile = CreateSourceFile(); var entry = new BuildXLConfiguration.Mutable.FileAccessWhitelistEntry() { Value = "testValue", PathFragment = ArtifactToString(whitelistFile), }; Configuration.FileAccessWhiteList.Add(entry); Process pip = CreateAndSchedulePipBuilder(new Operation[] { Operation.ReadFile(whitelistFile, doNotInfer: true), Operation.WriteFile(CreateOutputFileArtifact()) }).Process; ScheduleRunResult buildA = RunScheduler().AssertCacheMiss(pip.PipId); ScheduleRunResult buildB = RunScheduler().AssertCacheMiss(pip.PipId); var messages = new string[] { "disallowed file accesses", PipCacheMissType.MissForDescriptorsDueToWeakFingerprints.ToString() }; RunAnalyzer(buildA, buildB).AssertPipMiss( pip, PipCacheMissType.MissForDescriptorsDueToWeakFingerprints, messages); }
public void OutputMissingTest() { var dir = Path.Combine(ObjectRoot, "Dir"); var dirPath = AbsolutePath.Create(Context.PathTable, dir); FileArtifact input = CreateSourceFile(root: dirPath, prefix: "input-file"); FileArtifact output = CreateOutputFileArtifact(root: dirPath, prefix: "output-file"); FileArtifact stdOut = CreateOutputFileArtifact(root: dirPath, prefix: "stdOut-file"); FileArtifact stdErr = CreateOutputFileArtifact(root: dirPath, prefix: "stdErr-file"); var pipBuilder = CreatePipBuilder(new[] { Operation.ReadFile(input), Operation.WriteFile(output) }); pipBuilder.SetStandardOutputFile(stdOut.Path); pipBuilder.SetStandardErrorFile(stdErr.Path); var pip = SchedulePipBuilder(pipBuilder); RunScheduler().AssertCacheMiss(pip.Process.PipId); ScheduleRunResult cacheHitBuild = RunScheduler().AssertCacheHit(pip.Process.PipId); DiscardFileContentInArtifactCacheIfExists(output); DiscardFileContentInArtifactCacheIfExists(stdOut); DiscardFileContentInArtifactCacheIfExists(stdErr); File.Delete(ArtifactToString(output)); File.Delete(ArtifactToString(stdOut)); File.Delete(ArtifactToString(stdErr)); ScheduleRunResult cacheMissBuild = RunScheduler().AssertCacheMiss(pip.Process.PipId); string[] messages = { ArtifactToPrint(output), ArtifactToPrint(stdOut), ArtifactToPrint(stdErr) }; RunAnalyzer(cacheHitBuild, cacheMissBuild).AssertPipMiss(pip.Process, PipCacheMissType.MissForProcessOutputContent, messages); }
public async Task <double> Complete(ScheduleRunResult result) { if (_traceId == Guid.Empty) { return(0); } _stopwatch.Stop(); await _dbContext.Database.ExecuteSqlRawAsync( $"update scheduletraces set result={result.GetHashCode().ToString()},elapsedtime={Math.Round(_stopwatch.Elapsed.TotalSeconds, 3).ToString()},endtime=now() where traceid='{_traceId.ToString()}'"); if (result == ScheduleRunResult.Success) { await _dbContext.Database.ExecuteSqlRawAsync( $"update tracestatistics set success=success+1,other=other-1,lastupdatetime=now() where datenum={_dateNum}"); } else if (result == ScheduleRunResult.Failed) { await _dbContext.Database.ExecuteSqlRawAsync( $"update tracestatistics set fail=fail+1,other=other-1,lastupdatetime=now() where datenum={_dateNum}"); } return(Math.Round(_stopwatch.Elapsed.TotalMilliseconds, 3)); }
public void UndeclaredOrderReadFromOpaqueDirectory() { var opaqueOutput = CreateOutputDirectoryArtifact(); var outputWithinOpaque = CreateOutputFileArtifact(opaqueOutput.Path.ToString(Context.PathTable)); var aOutput = CreateOutputFileArtifact(ObjectRoot); var builderA = CreatePipBuilder(new Operation[] { Operation.WriteFile(aOutput), Operation.WriteFile(outputWithinOpaque, doNotInfer: true) }); builderA.AddOutputDirectory(opaqueOutput, SealDirectoryKind.Opaque); SchedulePipBuilder(builderA); var builderB = CreatePipBuilder(new Operation[] { Operation.WriteFile(CreateOutputFileArtifact(ObjectRoot)), Operation.ReadFile(outputWithinOpaque, doNotInfer: true), Operation.ReadFile(aOutput) }); SchedulePipBuilder(builderB); ScheduleRunResult result = RunScheduler().AssertFailure(); AssertErrorEventLogged(SchedulerLogEventId.FileMonitoringError); AssertWarningEventLogged(SchedulerLogEventId.ProcessNotStoredToCacheDueToFileMonitoringViolations); AssertVerboseEventLogged(global::BuildXL.Scheduler.Tracing.LogEventId.DependencyViolationUndeclaredOrderedRead); }
public void TestLogPackedExecution() { FileArtifact srcA = CreateSourceFile(); FileArtifact outA = CreateOutputFileArtifact(); Process pipA = CreateAndSchedulePipBuilder(new Operation[] { Operation.ReadFile(srcA), Operation.WriteFile(outA) }).Process; // Make pipB dependent on pipA FileArtifact srcB = CreateSourceFile(); Process pipB = CreateAndSchedulePipBuilder(new Operation[] { Operation.ReadFile(srcB), Operation.ReadFile(outA), Operation.WriteFile(CreateOutputFileArtifact()) }).Process; ScheduleRunResult result = RunScheduler(); // .AssertCacheMiss(pipA.PipId, pipB.PipId); AbsolutePath executionLogPath = result.Config.Logging.ExecutionLog; string packedExecutionPath = Path.ChangeExtension(executionLogPath.ToString(Context.PathTable), "PXL"); // Packed eXecution Log // Try reading it PackedExecution pex = new PackedExecution(); pex.LoadFromDirectory(packedExecutionPath); Assert.True(pex.PipTable.Count > 0); }
private void UpdateRunTrace(Guid traceId, double elapsed, ScheduleRunResult result) { if (traceId == Guid.Empty) { return; } _db.Database.ExecuteSqlRaw($"update scheduletraces set result={(int)result},elapsedtime={elapsed},endtime='{DateTime.Now}' where traceid='{traceId}'"); }
protected void AssertProcessPipCountersByFilterSumToPipExecutorCounters(ScheduleRunResult result, PipExecutorCounter pipExecutorCounter, PipCountersByGroup pipCountersByGroup) { var explicitCounter = result.ProcessPipCountersByFilter.ExplicitlyScheduledProcesses.GetElapsedTime(pipCountersByGroup); var implicitCounter = result.ProcessPipCountersByFilter.ImplicitlyScheduledProcesses.GetElapsedTime(pipCountersByGroup); var executorCounter = result.PipExecutorCounters.GetElapsedTime(pipExecutorCounter); AssertOkTimeDiff(executorCounter, explicitCounter + implicitCounter, "(explicit: " + explicitCounter.TotalMilliseconds + "ms, implicit: " + implicitCounter.TotalMilliseconds + "ms, executor: " + executorCounter.TotalMilliseconds + "ms)"); }
private async Task UpdateRunTrace(Guid traceId, double elapsed, ScheduleRunResult result) { if (traceId == Guid.Empty) { return; } await _db.Database.ExecuteSqlRawAsync($"update scheduletraces set result={(int)result},elapsedtime={elapsed},endtime=now() where traceid='{traceId}'"); }
public void UnallowedDirectoryCreation(bool failOnUnexpectedFileAccesses) { // If we allow directory creation under writable mounts, the test is not applicable because the directory it tries to create // is in the scope of a writable mount, i.e., it will always be an allowed operation. Configuration.Sandbox.EnforceAccessPoliciesOnDirectoryCreation = true; Configuration.Sandbox.UnsafeSandboxConfigurationMutable.UnexpectedFileAccessesAreErrors = failOnUnexpectedFileAccesses; var declaredOutput = CreateOutputFileArtifact(); var dir = CreateOutputDirectoryArtifact(); var builderA = CreatePipBuilder(new Operation[] { Operation.WriteFile(declaredOutput), Operation.CreateDir(dir, doNotInfer: true), }); SchedulePipBuilder(builderA); // It's a clean build, 'dir' is not present, we should always detect directory creation (have errors/warnings). ScheduleRunResult result = RunScheduler(); if (failOnUnexpectedFileAccesses) { result.AssertFailure(); AssertErrorEventLogged(ProcessesLogEventId.PipProcessError); AssertErrorEventLogged(SchedulerLogEventId.FileMonitoringError); // Double check that the directory was not created Test.BuildXL.TestUtilities.Xunit.XAssert.IsFalse(Directory.Exists(dir.Path.ToString(Context.PathTable)), "Directory should not exist"); } else { result.AssertSuccess(); AssertWarningEventLogged(SchedulerLogEventId.FileMonitoringWarning); AssertWarningEventLogged(SchedulerLogEventId.ProcessNotStoredToCacheDueToFileMonitoringViolations, count: 2); } // Now test that BuildXL has the same behavior even if the directory is already on disk. // NOTE: on Unix we couldn't find a syscall that always requests to create a directory even if one already exists, hence not testing the following if (!OperatingSystemHelper.IsUnixOS) { // Create the directory manually Directory.CreateDirectory(dir.Path.ToString(Context.PathTable)); result = RunScheduler(); if (failOnUnexpectedFileAccesses) { result.AssertFailure(); AssertErrorEventLogged(ProcessesLogEventId.PipProcessError); AssertErrorEventLogged(SchedulerLogEventId.FileMonitoringError); } else { result.AssertSuccess(); AssertWarningEventLogged(SchedulerLogEventId.FileMonitoringWarning); AssertWarningEventLogged(SchedulerLogEventId.ProcessNotStoredToCacheDueToFileMonitoringViolations, count: 2); } } }
public void TestAllPipsOption() { FileArtifact srcA = CreateSourceFile(); FileArtifact outA = CreateOutputFileArtifact(); Process pipA = CreateAndSchedulePipBuilder(new Operation[] { Operation.ReadFile(srcA), Operation.WriteFile(outA) }).Process; // Make pipB dependent on pipA FileArtifact srcB = CreateSourceFile(); Process pipB = CreateAndSchedulePipBuilder(new Operation[] { Operation.ReadFile(srcB), Operation.ReadFile(outA), Operation.WriteFile(CreateOutputFileArtifact()) }).Process; RunScheduler().AssertCacheMiss(pipA.PipId, pipB.PipId); ScheduleRunResult buildA = RunScheduler().AssertCacheHit(pipA.PipId, pipB.PipId); // Force miss on pipA File.WriteAllText(ArtifactToPrint(srcA), "asdf"); // Force miss on pipB File.WriteAllText(ArtifactToPrint(srcB), "hjkl"); ScheduleRunResult buildB = RunScheduler().AssertCacheMiss(pipA.PipId, pipB.PipId); AnalyzerResult result = RunAnalyzer(buildA, buildB); result.AssertPipMiss( pipA, PipCacheMissType.MissForDescriptorsDueToWeakFingerprints, ArtifactToPrint(srcA)); // Don't analyze downstream pip misses XAssert.IsFalse(result.FileOutput.Contains(pipB.FormattedSemiStableHash)); Option allPips = new Option { Name = "allPips", }; AnalyzerResult allPipsResult = RunAnalyzer(buildA, buildB, additionalArgs: new Option[] { allPips }); allPipsResult.AssertPipMiss( pipA, PipCacheMissType.MissForDescriptorsDueToWeakFingerprints, ArtifactToPrint(srcA)); // Analyze downstream pips, runtime cache miss does not have an all pips option allPipsResult.AssertAnalyzerPipMiss( pipA, PipCacheMissType.MissForDescriptorsDueToWeakFingerprints, ArtifactToPrint(srcB)); }
/// <summary> /// Saves the result of the BuildXL execution to disk and creates /// a <see cref="Option"/> for execution analyzers representing the /// execution result's location on disk. /// </summary> private Option PrepareAndCreateExecutionLogArg(ScheduleRunResult build) { // Save the execution state to disk to use as inputs into the analyzer SaveExecutionStateToDiskAsync(build).GetAwaiter().GetResult(); // Build the command line arguments for the analyzer return(new Option { Name = "xl", Value = build.Config.Logging.LogsDirectory.ToString(Context.PathTable), }); }
[FactIfSupported(requiresWindowsBasedOperatingSystem: true)] /* No AppData folder on Unix */ public void CreateDirectoryOnSystemMountWhereAllowed() { // testing with a stricter behavior Configuration.Sandbox.EnforceAccessPoliciesOnDirectoryCreation = true; string appDataRoamingPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData); Test.BuildXL.TestUtilities.Xunit.XAssert.IsFalse(string.IsNullOrEmpty(appDataRoamingPath)); var appData = AbsolutePath.Create(Context.PathTable, appDataRoamingPath); Expander.Add( Context.PathTable, new SemanticPathInfo( rootName: PathAtom.Create(Context.PathTable.StringTable, "AppDataRoaming"), root: appData, allowHashing: true, readable: true, writable: false, system: true, allowCreateDirectory: true)); string cookiesPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Cookies); if (!string.IsNullOrEmpty(cookiesPath)) { AbsolutePath cookies = AbsolutePath.Create(Context.PathTable, cookiesPath); Expander.Add( Context.PathTable, new SemanticPathInfo( rootName: PathAtom.Create(Context.PathTable.StringTable, "INetCookies"), root: cookies, allowHashing: true, readable: true, writable: false, system: true, allowCreateDirectory: true)); } var builderA = CreatePipBuilder(new Operation[] { Operation.WriteFile(CreateOutputFileArtifact()), Operation.CreateDir(DirectoryArtifact.CreateWithZeroPartialSealId(appData), doNotInfer: true), }); SchedulePipBuilder(builderA); ScheduleRunResult result = RunScheduler(); result.AssertSuccess(); }
public void DirectoryEnumerationReadOnlyMountStrongFingerprintMiss() { string[] messages; DirectoryArtifact dir = DirectoryArtifact.CreateWithZeroPartialSealId(CreateUniqueDirectory(ReadonlyRoot)); Directory.CreateDirectory(ArtifactToPrint(dir)); Process pip = CreateAndSchedulePipBuilder(new Operation[] { Operation.EnumerateDir(dir), Operation.WriteFile(CreateOutputFileArtifact()) }).Process; RunScheduler().AssertCacheMiss(pip.PipId); ScheduleRunResult buildA = RunScheduler().AssertCacheHit(pip.PipId); // Strong fingerprint miss: AbsentPathProbe => DirectoryEnumeration // (empty directory enumeration conflates to absent path probe) FileArtifact nestedFile = CreateSourceFile(ArtifactToPrint(dir)); ScheduleRunResult buildB = RunScheduler().AssertCacheMiss(pip.PipId); messages = new string[] { ArtifactToPrint(dir), ObservedInputType.AbsentPathProbe.ToString(), ObservedInputType.DirectoryEnumeration.ToString() }; RunAnalyzer(buildA, buildB).AssertPipMiss(pip, PipCacheMissType.MissForDescriptorsDueToStrongFingerprints, messages); // Strong fingerprint miss: Added new files to enumerated directory FileArtifact addedFile = CreateSourceFile(ArtifactToPrint(dir)); FileArtifact victimFile = CreateSourceFile(ArtifactToPrint(dir)); ScheduleRunResult buildC = RunScheduler().AssertCacheMiss(pip.PipId); messages = new string[] { ArtifactToPrint(dir), Path.GetFileName(ArtifactToPrint(addedFile)), Path.GetFileName(ArtifactToPrint(victimFile)) }; RunAnalyzer(buildB, buildC).AssertPipMiss( pip, PipCacheMissType.MissForDescriptorsDueToStrongFingerprints, ArtifactToPrint(dir), Path.GetFileName(ArtifactToPrint(addedFile)), Path.GetFileName(ArtifactToPrint(victimFile))); // Strong fingerprint miss: Deleted file in enumerated directory File.Delete(ArtifactToPrint(victimFile)); ScheduleRunResult buildD = RunScheduler().AssertCacheMiss(pip.PipId); messages = new string[] { ArtifactToPrint(dir), Path.GetFileName(ArtifactToPrint(victimFile)) }; RunAnalyzer(buildC, buildD).AssertPipMiss( pip, PipCacheMissType.MissForDescriptorsDueToStrongFingerprints, messages); }
/// <summary> /// 更新运行记录 /// </summary> /// <param name="traceId"></param> /// <param name="timeSpan"></param> /// <param name="result"></param> /// <returns></returns> public bool UpdateRunTrace(Guid traceId, double timeSpan, ScheduleRunResult result) { if (traceId == Guid.Empty) { return(false); } _repositoryFactory.ScheduleTraces.UpdateBy(x => x.TraceId == traceId, x => new ScheduleTraceEntity { EndTime = DateTime.Now, Result = (int)result, ElapsedTime = timeSpan }); return(_unitOfWork.Commit() > 0); }
/// <summary> /// Validates that pips are scheduled. /// </summary> public static ScheduleRunResult AssertScheduled(this ScheduleRunResult @this, params PipId[] pipIds) { @this.AssertSuccess(); PipResultStatus status; for (int i = 0; i < pipIds.Length; i++) { PipId pipId = pipIds[i]; bool exists = @this.PipResults.TryGetValue(pipId, out status); XAssert.IsTrue(exists, "A pip is not scheduled, but it should have been scheduled. Pip at 0-based parameter index: " + i); } return(@this); }
public void RunSingleProcessRemotely() { // Force run remotely. Configuration.Schedule.RemotingThresholdMultiplier = 0.0; ProcessBuilder builder = CreatePipBuilder(new[] { Operation.ReadFile(CreateSourceFile()), Operation.WriteFile(CreateOutputFileArtifact()) }); ProcessWithOutputs process = SchedulePipBuilder(builder); ScheduleRunResult result = RunScheduler().AssertSuccess(); XAssert.AreEqual(1, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRunRemoteProcesses)); XAssert.AreEqual(0, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRunLocallyProcessesOnRemotingWorker)); XAssert.AreEqual(0, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRemoteFallbackRetries)); RunScheduler().AssertCacheHit(process.Process.PipId); }
public void PreserveOutputsWithTrustLevelModification() { Configuration.Sandbox.UnsafeSandboxConfigurationMutable.PreserveOutputs = PreserveOutputsMode.Enabled; Configuration.Sandbox.UnsafeSandboxConfigurationMutable.PreserveOutputsTrustLevel = 3; var input = CreateSourceFile(); var outputPreservedA = CreateOutputFileArtifact(Path.Combine(ObjectRoot, @"nested\out\filePreservedA")); var builderA = CreatePipBuilder(new Operation[] { Operation.ReadFile(input), Operation.WriteFile(outputPreservedA, CONTENT), }); // processA won't perserve outputs builderA.Options |= Process.Options.AllowPreserveOutputs; builderA.PreserveOutputsTrustLevel = 2; var processAndOutputsA = SchedulePipBuilder(builderA); RunSchedulerAndGetOutputContents(outputPreservedA, false, processAndOutputsA.Process.PipId); XAssert.AreEqual(CONTENT, File.ReadAllText(ArtifactToString(outputPreservedA))); // after decreasing global preserve output trust level to 1, process A will not be scheduled Configuration.Sandbox.UnsafeSandboxConfigurationMutable.PreserveOutputsTrustLevel = 1; ScheduleRunResult result = RunScheduler(); if (Configuration.Schedule.IncrementalScheduling) { result.AssertNotScheduled(processAndOutputsA.Process.PipId); } else { result.AssertCacheHit(processAndOutputsA.Process.PipId); } XAssert.AreEqual(CONTENT, File.ReadAllText(ArtifactToString(outputPreservedA))); // once we change back global TL to 3, process A will be scheduled again Configuration.Sandbox.UnsafeSandboxConfigurationMutable.PreserveOutputsTrustLevel = 3; result = RunScheduler(); if (Configuration.Schedule.IncrementalScheduling) { result.AssertScheduled(processAndOutputsA.Process.PipId); } else { result.AssertCacheMiss(processAndOutputsA.Process.PipId); } XAssert.AreEqual(CONTENT, File.ReadAllText(ArtifactToString(outputPreservedA))); }
public void RemoteFallbackProcessRetryToRunLocally() { RemoteProcessManagerFactory.RemoteProcessManager = new Lazy <IRemoteProcessManager>(() => new TestRemoteProcessManager(shouldRunLocally: true)); // Force run remotely. Configuration.Schedule.RemotingThresholdMultiplier = 0.0; ProcessBuilder builder = CreatePipBuilder(new[] { Operation.ReadFile(CreateSourceFile()), Operation.WriteFile(CreateOutputFileArtifact()) }); ProcessWithOutputs process = SchedulePipBuilder(builder); ScheduleRunResult result = RunScheduler().AssertSuccess(); XAssert.AreEqual(1, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRunRemoteProcesses)); XAssert.AreEqual(1, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRunLocallyProcessesOnRemotingWorker)); XAssert.AreEqual(1, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRemoteFallbackRetries)); }
/// <summary> /// Validates that pips are not scheduled. /// </summary> public static ScheduleRunResult AssertNotScheduled(this ScheduleRunResult @this, params PipId[] pipIds) { XAssert.IsTrue(pipIds.Length > 0, "Scheduling assertions should specify the pip ids in question"); @this.AssertSuccess(); PipResultStatus status; for (int i = 0; i < pipIds.Length; i++) { PipId pipId = pipIds[i]; bool exists = @this.PipResults.TryGetValue(pipId, out status); XAssert.IsFalse(exists, "A pip is scheduled, but it should have not been scheduled. Pip at 0-based parameter index: " + i + " (status: " + status + ")"); } return(@this); }
public void FingerprintStoreSession( ScheduleRunResult result, Action <FingerprintStoreClass> storeOps, bool cacheLookupStore = false, bool readOnly = true, FingerprintStoreTestHooks testHooks = null) { var storeDirectory = cacheLookupStore ? result.Config.Logging.CacheLookupFingerprintStoreLogDirectory.ToString(Context.PathTable) : result.Config.Layout.FingerprintStoreDirectory.ToString(Context.PathTable); using (var fingerprintStore = Open(storeDirectory, readOnly: readOnly, testHooks: testHooks).Result) { storeOps(fingerprintStore); } }
public void CacheMissesOfMultiplePipsTest(bool cacheMissBatch, bool exceedMaxLogSize) { Configuration.Logging.CacheMissBatch = cacheMissBatch; Configuration.Logging.OptimizeConsoleOutputForAzureDevOps = true; var dir = Path.Combine(ObjectRoot, "Dir"); var dirPath = AbsolutePath.Create(Context.PathTable, dir); var pipNumber = 102; var processes = new List <Process>(); for (var i = 0; i < pipNumber; i++) { FileArtifact input = CreateSourceFile(root: dirPath); FileArtifact output = CreateOutputFileArtifact(root: dirPath); var pipBuilder = CreatePipBuilder(new[] { Operation.ReadFile(input), Operation.WriteFile(output) }); if (exceedMaxLogSize) { pipBuilder.ToolDescription = StringId.Create(Context.StringTable, new string('*', Configuration.Logging.AriaIndividualMessageSizeLimitBytes / pipNumber)); } var pip = SchedulePipBuilder(pipBuilder); processes.Add(pip.Process); } SetExtraSalts("FirstSalt", true); ScheduleRunResult initialbuild = RunScheduler().AssertCacheMiss(processes.Select(p => p.PipId).ToArray()); ScheduleRunResult cacheHitBuild = RunScheduler().AssertCacheHit(processes.Select(p => p.PipId).ToArray()); SetExtraSalts("SecondSalt", false); ScheduleRunResult cacheMissBuild = RunScheduler(m_testHooks).AssertCacheMiss(processes.Select(p => p.PipId).ToArray()); for (var i = 0; i < pipNumber; i++) { XAssert.IsTrue(m_testHooks.FingerprintStoreTestHooks.TryGetCacheMiss(processes[i].PipId, out var cacheMiss)); XAssert.AreEqual(CacheMissAnalysisResult.WeakFingerprintMismatch, cacheMiss.DetailAndResult.Result); } if (cacheMissBatch) { AssertVerboseEventLogged(SharedLogEventId.CacheMissAnalysisBatchResults, allowMore: true); } else { AssertVerboseEventLogged(SharedLogEventId.CacheMissAnalysis, allowMore: true); } }
public void ExternalToolPreserveWarning() { ProcessBuilder builder = CreatePipBuilder(new[] { Operation.ReadFile(CreateSourceFile()), Operation.Echo("WARN this is a warning"), Operation.WriteFile(CreateOutputFileArtifact()) }); builder.Options |= Process.Options.RequiresAdmin; builder.WarningRegex = new RegexDescriptor(StringId.Create(Context.StringTable, @"^WARN"), System.Text.RegularExpressions.RegexOptions.IgnoreCase); ProcessWithOutputs process = SchedulePipBuilder(builder); ScheduleRunResult result = RunScheduler().AssertSuccess(); AssertWarningEventLogged(EventId.PipProcessWarning, count: 1); }
public void DirectoryMembershipFingerprintMissing() { DirectoryArtifact dir = DirectoryArtifact.CreateWithZeroPartialSealId(CreateUniqueDirectory(ReadonlyRoot)); Directory.CreateDirectory(ArtifactToPrint(dir)); Process pip = CreateAndSchedulePipBuilder(new Operation[] { Operation.EnumerateDir(dir), Operation.WriteFile(CreateOutputFileArtifact()) }).Process; RunScheduler().AssertCacheMiss(pip.PipId); ScheduleRunResult buildA = RunScheduler().AssertCacheHit(pip.PipId); // Strong fingerprint miss: AbsentPathProbe => DirectoryEnumeration // (empty directory enumeration conflates to absent path probe) FileArtifact nestedFile = CreateSourceFile(ArtifactToPrint(dir)); ScheduleRunResult buildB = RunScheduler().AssertCacheMiss(pip.PipId); // On a strong fingerprint miss, both the execution and cache lookup store will store fingerprints using (var executionStore = FingerprintStore.Open(ResultToStoreDirectory(buildB)).Result) using (var cacheLookupStore = FingerprintStore.Open(ResultToStoreDirectory(buildB, cacheLookupStore: true)).Result) { XAssert.IsTrue(executionStore.TryGetFingerprintStoreEntryBySemiStableHash(pip.FormattedSemiStableHash, out var entry)); XAssert.IsTrue(cacheLookupStore.TryGetFingerprintStoreEntryBySemiStableHash(pip.FormattedSemiStableHash, out var cacheLookupEntry)); // Parse the entry for the directory membership fingerprint key var reader = new JsonReader(entry.StrongFingerprintEntry.StrongFingerprintToInputs.Value); XAssert.IsTrue(reader.TryGetPropertyValue(ObservedInputConstants.DirectoryEnumeration, out string directoryMembershipFingerprint)); // Remove the directory memberhsip entry executionStore.RemoveContentHashForTesting(directoryMembershipFingerprint); cacheLookupStore.RemoveContentHashForTesting(directoryMembershipFingerprint); } var result = RunAnalyzer(buildA, buildB).AssertPipMiss( pip, PipCacheMissType.MissForDescriptorsDueToStrongFingerprints, ArtifactToPrint(dir), ObservedInputType.AbsentPathProbe.ToString(), ObservedInputType.DirectoryEnumeration.ToString()); result.AssertAnalyzerOutput(CacheMissAnalysisUtilities.RepeatedStrings.MissingDirectoryMembershipFingerprint); }
public void AllMultipleProcessesRunLocally() { Configuration.Schedule.RemotingThresholdMultiplier = 4; Configuration.Schedule.NumOfRemoteAgentLeases = 2; Configuration.Schedule.MaxProcesses = 1; for (int i = 0; i < 5; ++i) { ProcessBuilder builder = CreatePipBuilder(new[] { Operation.ReadFile(CreateSourceFile()), Operation.WriteFile(CreateOutputFileArtifact()) }); SchedulePipBuilder(builder); } ScheduleRunResult result = RunScheduler().AssertSuccess(); XAssert.AreEqual(0, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRunRemoteProcesses)); XAssert.AreEqual(5, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRunLocallyProcessesOnRemotingWorker)); XAssert.AreEqual(0, result.PipExecutorCounters.GetCounterValue(global::BuildXL.Scheduler.PipExecutorCounter.TotalRemoteFallbackRetries)); }