Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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]);
        }
Example #4
0
        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();
Example #5
0
        /// <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));
        }
Example #7
0
        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);
        }
Example #8
0
        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);
        }
Example #9
0
        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));
        }
Example #10
0
        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);
        }
Example #12
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}'");
 }
Example #13
0
        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)");
        }
Example #14
0
 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}'");
 }
Example #15
0
        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);
                }
            }
        }
Example #16
0
        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));
        }
Example #17
0
        /// <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),
            });
        }
Example #18
0
        [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();
        }
Example #19
0
        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);
        }
Example #22
0
        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)));
        }
Example #24
0
        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);
        }
Example #26
0
        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);
            }
        }
Example #27
0
        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);
        }
Example #29
0
        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);
        }
Example #30
0
        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));
        }