Beispiel #1
0
        private Task <SandboxedProcessResult> RunJavaScriptGraphBuilderAsync(
            string nodeExeLocation,
            AbsolutePath outputFile,
            BuildParameters.IBuildParameters buildParameters,
            AbsolutePath toolLocation)
        {
            AbsolutePath toolPath        = m_configuration.Layout.BuildEngineDirectory.Combine(m_context.PathTable, RelativePathToGraphConstructionTool);
            string       outputDirectory = outputFile.GetParent(m_context.PathTable).ToString(m_context.PathTable);

            var cmdExeArtifact = FileArtifact.CreateSourceFile(AbsolutePath.Create(m_context.PathTable, Environment.GetEnvironmentVariable("COMSPEC")));

            var toolArguments = GetGraphConstructionToolArguments(outputFile, toolLocation, toolPath, nodeExeLocation);

            Tracing.Logger.Log.ConstructingGraphScript(m_context.LoggingContext, toolArguments);

            return(FrontEndUtilities.RunSandboxedToolAsync(
                       m_context,
                       cmdExeArtifact.Path.ToString(m_context.PathTable),
                       buildStorageDirectory: outputDirectory,
                       fileAccessManifest: FrontEndUtilities.GenerateToolFileAccessManifest(m_context, outputFile.GetParent(m_context.PathTable)),
                       arguments: toolArguments,
                       workingDirectory: m_resolverSettings.Root.ToString(m_context.PathTable),
                       description: $"{Name} graph builder",
                       buildParameters));
        }
Beispiel #2
0
        public void CreateFileArtifact()
        {
            var          pt      = new PathTable();
            AbsolutePath da1     = AbsolutePath.Create(pt, A("c"));
            RelativePath relPath = RelativePath.Create(pt.StringTable, R("a", "b"));
            FileArtifact fa      = FileArtifact.CreateSourceFile(da1.Combine(pt, relPath));

            XAssert.AreEqual(A("c", "a", "b"), fa.Path.ToString(pt));

            da1 = AbsolutePath.Create(pt, A("c"));
            PathAtom atom = PathAtom.Create(pt.StringTable, "a");

            fa = FileArtifact.CreateSourceFile(da1.Combine(pt, atom));
            XAssert.AreEqual(A("c", "a"), fa.Path.ToString(pt));

            da1  = AbsolutePath.Create(pt, A("c"));
            atom = PathAtom.Create(pt.StringTable, "a");
            PathAtom atom2 = PathAtom.Create(pt.StringTable, "b");

            fa = FileArtifact.CreateSourceFile(da1.Combine(pt, atom, atom2));
            XAssert.AreEqual(A("c", "a", "b"), fa.Path.ToString(pt));

            da1   = AbsolutePath.Create(pt, A("c"));
            atom  = PathAtom.Create(pt.StringTable, "a");
            atom2 = PathAtom.Create(pt.StringTable, "b");
            PathAtom atom3 = PathAtom.Create(pt.StringTable, "c");

            fa = FileArtifact.CreateSourceFile(da1.Combine(pt, atom, atom2, atom3));
            XAssert.AreEqual(A("c", "a", "b", "c"), fa.Path.ToString(pt));
        }
Beispiel #3
0
        public void TestPipOutputFingerprinting(FileExistence existence, FileExistence anotherExistence)
        {
            // Arrange
            var          pathTable  = m_context.PathTable;
            var          executable = FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, X("/x/pkgs/tool.exe")));
            AbsolutePath outputPath = AbsolutePath.Create(pathTable, X("/x/obj/working/out.bin"));

            FileArtifactWithAttributes output = new FileArtifactWithAttributes(outputPath, rewriteCount: 1, fileExistence: existence);
            Process process = DefaultBuilder.WithOutputs(output).Build();

            Process processSecondVersion = DefaultBuilder.WithOutputs(output.CreateNextWrittenVersion()).Build();

            var outputWithDifferenceExistence  = new FileArtifactWithAttributes(outputPath, rewriteCount: 1, fileExistence: anotherExistence);
            var processWithDifferenceExistence = DefaultBuilder.WithOutputs(outputWithDifferenceExistence).Build();

            var fingerprinter = CreateFingerprinter(executable);

            // Act
            var fingerprint = fingerprinter.ComputeFingerprint(process);

            // Assert
            XAssert.AreEqual(fingerprint, fingerprinter.ComputeFingerprint(processSecondVersion),
                             "RewriteCount should not affect the fingerprint");
            XAssert.AreNotEqual(fingerprint, fingerprinter.ComputeFingerprint(processWithDifferenceExistence),
                                "Two process with the same output path but with different attributes should produce different fingerprints");
        }
        private void AddInputs(NinjaNode node, ProcessBuilder processBuilder)
        {
            foreach (AbsolutePath input in node.Inputs.Where(i => !m_outputFileArtifacts.ContainsKey(i))) // We only want source files. If the file is in m_outputFileArtifacts then it was output by someone else
            {                                                                                             // and we have that dependency expressed in node.
                processBuilder.AddInputFile(FileArtifact.CreateSourceFile(input));
            }

            foreach (NinjaNode dependency in node.Dependencies)
            {
                bool outputsPresent = m_processOutputs.TryGetValue(dependency, out ProcessOutputs processOutputs);

                string ListOutputs(NinjaNode n) => string.Join(" ", n.Outputs.Select(x => x.GetName(m_context.PathTable).ToString(m_context.StringTable)).ToList());

                if (!outputsPresent)
                {
                    Contract.Assert(false, $"Pips must have been presented in dependency order: [build { ListOutputs(dependency) }] missing, dependency of [build { ListOutputs(node)} ]");
                }

                foreach (FileArtifact output in processOutputs.GetOutputFiles())
                {
                    if (node.Inputs.Contains(output.Path))
                    {
                        processBuilder.AddInputFile(output);
                    }
                }
            }
        }
        /// <nodoc />
        public bool TryWriteFile(
            AbsolutePath destination,
            PipData content,
            WriteFileEncoding encoding,
            string[] tags,
            string description,
            out FileArtifact fileArtifact)
        {
            Contract.Requires(destination.IsValid);
            Contract.Requires(content.IsValid);

            fileArtifact = FileArtifact.CreateSourceFile(destination).CreateNextWrittenVersion();
            var pip = new WriteFile(
                fileArtifact,
                content,
                encoding,
                ToStringIds(tags),
                CreatePipProvenance(description));

            if (PipGraph != null)
            {
                return(PipGraph.AddWriteFile(pip, GetValuePipId()));
            }

            return(true);
        }
Beispiel #6
0
        /// <summary>
        /// Creates a source artifact and populates it with <see cref="WriteSourceFile"/>.
        /// Creating a backing file is necessary since source artifacts must exist at the beginning of a build.
        ///
        /// If <paramref name="root"/> is not specified, <see cref="SourceRoot"/> is used as the parent directory.
        ///
        /// If <paramref name="prefix"/> is not specified, <see cref="SourceRootPrefix"/> is used as the file name prefix.
        /// </summary>
        protected FileArtifact CreateSourceFileWithPrefix(string root = null, string prefix = null)
        {
            FileArtifact sourceFile = FileArtifact.CreateSourceFile(CreateUniqueSourcePath(prefix ?? SourceRootPrefix, root));

            WriteSourceFile(sourceFile);
            return(sourceFile);
        }
Beispiel #7
0
        protected PipTestBase(ITestOutputHelper output) : base(output)
        {
            Context = BuildXLContext.CreateInstanceForTesting();
            PathTable.DebugPathTable = Context.PathTable;

            TestBinRoot     = Path.GetDirectoryName(AssemblyHelper.GetAssemblyLocation(System.Reflection.Assembly.GetExecutingAssembly()));
            TestBinRootPath = AbsolutePath.Create(Context.PathTable, TestBinRoot);
            SourceRoot      = Path.Combine(TemporaryDirectory, SourceRootPrefix);
            SourceRootPath  = AbsolutePath.Create(Context.PathTable, SourceRoot);

            CmdExecutable = FileArtifact.CreateSourceFile(AbsolutePath.Create(Context.PathTable, CmdHelper.OsShellExe));

            string testProcessFolder = Path.Combine(TestBinRoot, "TestProcess");
            string platformDir       = Dispatch.CurrentOS().ToString();
            string exe = Path.Combine(testProcessFolder, platformDir, TestProcessToolName);

            TestProcessExecutable = FileArtifact.CreateSourceFile(AbsolutePath.Create(Context.PathTable, exe));

            // Test process depends on C://Windows (when running on Windows)
            TestProcessDependencies = OperatingSystemHelper.IsUnixOS
                ? new AbsolutePath[0]
                : new AbsolutePath[] { AbsolutePath.Create(Context.PathTable, Environment.GetFolderPath(Environment.SpecialFolder.Windows)) };

            ObjectRoot     = Path.Combine(TemporaryDirectory, ObjectRootPrefix);
            ObjectRootPath = AbsolutePath.Create(Context.PathTable, ObjectRoot);

            CacheRoot = Path.Combine(TemporaryDirectory, CacheRootPrefix);

            BaseSetup();
        }
        /// <nodoc />
        public bool TryCopyFile(
            FileArtifact source,
            AbsolutePath destination,
            CopyFile.Options options,
            string[] tags,
            string description,
            out FileArtifact fileArtifact)
        {
            Contract.Requires(source.IsValid);
            Contract.Requires(destination.IsValid);

            fileArtifact = FileArtifact.CreateSourceFile(destination).CreateNextWrittenVersion();
            var pip = new CopyFile(
                source,
                fileArtifact,
                ToStringIds(tags),
                CreatePipProvenance(description),
                options);

            if (PipGraph != null)
            {
                return(PipGraph.AddCopyFile(pip, GetValuePipId()));
            }

            return(true);
        }
Beispiel #9
0
        /// <summary>
        /// Adds all predicted dependencies as inputs, plus all individual inputs predicted for the project
        /// </summary>
        /// <remarks>
        /// Adding all predicted dependencies is key to get the right scheduling. On the other hand, all predicted inputs
        /// are not really needed since we are running in undeclared read mode. However, they contribute to make the weak fingerprint stronger (that
        /// otherwise will likely be just a shared opaque output at the root).
        /// </remarks>
        private void ProcessInputs(
            ProjectWithPredictions project,
            ProcessBuilder processBuilder)
        {
            // Add all predicted inputs
            foreach (AbsolutePath buildInput in project.PredictedInputFiles)
            {
                processBuilder.AddInputFile(FileArtifact.CreateSourceFile(buildInput));
            }

            IEnumerable <ProjectWithPredictions> references;

            // The default for EnableTransitiveProjectReferences is false, so it has to be true explicitly to kick in
            if (m_resolverSettings.EnableTransitiveProjectReferences == true)
            {
                // In this case all the transitive closure is automatically exposed to the project as direct references
                var transitiveReferences = new HashSet <ProjectWithPredictions>();
                ComputeTransitiveDependenciesFor(project, transitiveReferences);
                references = transitiveReferences;
            }
            else
            {
                // Only direct dependencies are declared.
                // Add all known explicit inputs from project references. But rule out
                // projects that have a known empty list of targets: those projects are not scheduled, so
                // there is nothing to consume from them.
                references = project.ProjectReferences.Where(projectReference => !projectReference.PredictedTargetsToExecute.TargetsAreKnownToBeEmpty);
            }

            var argumentsBuilder = processBuilder.ArgumentsBuilder;

            foreach (ProjectWithPredictions projectReference in references)
            {
                bool outputsPresent = m_processOutputsPerProject.TryGetValue(projectReference, out MSBuildProjectOutputs projectOutputs);
                if (!outputsPresent)
                {
                    Contract.Assert(false, $"Pips must have been presented in dependency order: {projectReference.FullPath.ToString(PathTable)} missing, dependency of {project.FullPath.ToString(PathTable)}");
                }

                // Add all known output directories
                foreach (StaticDirectory output in projectOutputs.OutputDirectories)
                {
                    processBuilder.AddInputDirectory(output.Root);
                }

                // If the dependency was built in isolation, this project needs to access the generated cache files
                if (projectOutputs.BuildsInIsolation)
                {
                    var outputCache = projectOutputs.OutputCacheFile;
                    processBuilder.AddInputFile(outputCache);
                    // Instruct MSBuild to use the cache file from the associated dependency as an input.
                    // Flag /irc is the short form of /inputResultsCaches, and part of MSBuild 'build in isolation' mode.
                    using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.NoEscaping, string.Empty))
                    {
                        argumentsBuilder.Add(PipDataAtom.FromString("/irc:"));
                        argumentsBuilder.Add(PipDataAtom.FromAbsolutePath(outputCache));
                    }
                }
            }
        }
Beispiel #10
0
        private Task <SandboxedProcessResult> RunRushGraphBuilderAsync(
            AbsolutePath outputFile,
            BuildParameters.IBuildParameters buildParameters)
        {
            AbsolutePath toolPath        = m_configuration.Layout.BuildEngineDirectory.Combine(m_context.PathTable, RelativePathToGraphConstructionTool);
            string       outputDirectory = outputFile.GetParent(m_context.PathTable).ToString(m_context.PathTable);

            // We always use cmd.exe as the tool so if the node.exe location is not provided we can just pass 'node.exe' and let PATH do the work.
            var    cmdExeArtifact = FileArtifact.CreateSourceFile(AbsolutePath.Create(m_context.PathTable, Environment.GetEnvironmentVariable("COMSPEC")));
            string nodeExe        = m_resolverSettings.NodeExeLocation.HasValue ?
                                    m_resolverSettings.NodeExeLocation.Value.Path.ToString(m_context.PathTable) :
                                    "node.exe";
            string pathToRushJson = m_resolverSettings.Root.Combine(m_context.PathTable, "rush.json").ToString(m_context.PathTable);

            // TODO: add qualifier support.
            // The graph construction tool expects: <path-to-rush.json> <path-to-output-graph> [<debug|release>]
            string toolArguments = $@"/C """"{nodeExe}"" ""{toolPath.ToString(m_context.PathTable)}"" ""{pathToRushJson}"" ""{outputFile.ToString(m_context.PathTable)}"" debug""";

            return(FrontEndUtilities.RunSandboxedToolAsync(
                       m_context,
                       cmdExeArtifact.Path.ToString(m_context.PathTable),
                       buildStorageDirectory: outputDirectory,
                       fileAccessManifest: FrontEndUtilities.GenerateToolFileAccessManifest(m_context, outputFile.GetParent(m_context.PathTable)),
                       arguments: toolArguments,
                       workingDirectory: m_configuration.Layout.SourceDirectory.ToString(m_context.PathTable),
                       description: "Rush graph builder",
                       buildParameters));
        }
Beispiel #11
0
        /// <nodoc />
        private async Task <EvaluationResult> ValidateAndStoreIncrementalDownloadStateAsync(DownloadData downloadData)
        {
            // If the hash is given in the download setting, use the corresponding hashType(hash algorithm) to get the content hash of the downloaded file.
            var downloadedHash = await GetContentHashAsync(downloadData.DownloadedFilePath, HashTypeParser(downloadData.Settings.Hash));

            if (downloadData.ContentHash.HasValue)
            {
                // Validate downloaded hash if specified
                if (downloadData.ContentHash != downloadedHash)
                {
                    m_logger.DownloadMismatchedHash(
                        m_context.LoggingContext,
                        downloadData.Settings.ModuleName,
                        downloadData.Settings.Url,
                        downloadData.Settings.Hash,
                        downloadedHash.ToString());
                    return(EvaluationResult.Error);
                }
            }
            else
            {
                try
                {
                    var incrementalState = new DownloadIncrementalState(downloadData, downloadedHash);
                    await incrementalState.SaveAsync(m_context);
                }
                catch (BuildXLException e)
                {
                    m_logger.ErrorStoringIncrementality(m_context.LoggingContext, downloadData.Settings.ModuleName, e.Message);
                    return(EvaluationResult.Error);
                }
            }

            return(new EvaluationResult(FileArtifact.CreateSourceFile(downloadData.DownloadedFilePath)));
        }
Beispiel #12
0
        private bool TrySetBuildToolExecutor(
            PipConstructionHelper pipConstructionHelper,
            ProcessBuilder processBuilder,
            ProjectWithPredictions project)
        {
            // If we should use the dotnet core version of msbuild, the executable for the pip is dotnet.exe instead of msbuild.exe, and
            // the first argument is msbuild.dll
            FileArtifact cmdExeArtifact;

            if (m_resolverSettings.ShouldRunDotNetCoreMSBuild())
            {
                cmdExeArtifact = FileArtifact.CreateSourceFile(m_dotnetExePath);
                processBuilder.ArgumentsBuilder.Add(PipDataAtom.FromAbsolutePath(m_msBuildPath));
            }
            else
            {
                cmdExeArtifact = FileArtifact.CreateSourceFile(m_msBuildPath);
            }

            processBuilder.Executable = cmdExeArtifact;
            processBuilder.AddInputFile(cmdExeArtifact);
            processBuilder.AddCurrentHostOSDirectories();
            processBuilder.AddUntrackedAppDataDirectories();
            processBuilder.AddUntrackedProgramDataDirectories();

            // Temp directory setup including setting TMP and TEMP env vars. The path to
            // the temp dir is generated in a consistent fashion between BuildXL runs to
            // ensure environment value (and hence pip hash) consistency.
            processBuilder.EnableTempDirectory();

            processBuilder.ToolDescription = StringId.Create(m_context.StringTable, I($"{m_moduleDefinition.Descriptor.Name} - {project.FullPath.ToString(PathTable)}"));

            return(true);
        }
Beispiel #13
0
        public void ProbeWithinSealedSourceDirectory()
        {
            var output            = CreateOutputFileArtifact(ObjectRoot);
            var input             = CreateSourceFile(SourceRoot);
            var absentPath        = FileArtifact.CreateSourceFile(CreateUniqueSourcePath(SourceRoot));
            DirectoryArtifact dir = SealDirectory(SourceRootPath, SealDirectoryKind.SourceAllDirectories);

            var builder = CreatePipBuilder(new Operation[]
            {
                Operation.ReadFile(input),
                Operation.ReadFile(absentPath, doNotInfer: true),
                Operation.WriteFile(output)
            });

            builder.AddInputDirectory(dir);
            Process p = SchedulePipBuilder(builder).Process;

            RunScheduler().AssertSuccess();
            RunScheduler().AssertCacheHit(p.PipId);

            // Make the absent path exist and make sure it is cached appropriately
            WriteSourceFile(absentPath);
            RunScheduler().AssertFailure();
            AssertVerboseEventLogged(ProcessesLogEventId.PipProcessDisallowedFileAccess);
            AssertVerboseEventLogged(LogEventId.DependencyViolationMissingSourceDependency);
            AssertWarningEventLogged(LogEventId.ProcessNotStoredToCacheDueToFileMonitoringViolations);
            AssertErrorEventLogged(LogEventId.FileMonitoringError);
        }
Beispiel #14
0
        public void ConsumeFilterPassingFile(bool topOnly)
        {
            FileArtifact source;

            if (topOnly)
            {
                source = FileArtifact.CreateSourceFile(SourceRootPath.Combine(Context.PathTable, "file.txt"));
            }
            else
            {
                var nestedDir = AbsolutePath.Create(Context.PathTable, Path.Combine(SourceRoot, "nested"));
                source = FileArtifact.CreateSourceFile(nestedDir.Combine(Context.PathTable, "file.txt"));
            }

            WriteSourceFile(source);
            var output = CreateOutputFileArtifact(ObjectRoot);

            SealDirectory     sealedDirectory = CreateSourceSealDirectory(SourceRootPath, topOnly ? SealDirectoryKind.SourceTopDirectoryOnly : SealDirectoryKind.SourceAllDirectories, "*.txt", "*.cs");
            DirectoryArtifact dir             = PipGraphBuilder.AddSealDirectory(sealedDirectory);

            var builder = CreatePipBuilder(new Operation[]
            {
                Operation.ReadFile(source, doNotInfer: true),
                Operation.WriteFile(output),
            });

            builder.AddInputDirectory(dir);
            SchedulePipBuilder(builder);

            RunScheduler().AssertSuccess();
        }
Beispiel #15
0
        private static void ScheduleConsumeSourceFile(TestEnv env, AbsolutePath directory, string relativePath)
        {
            FileArtifact source = FileArtifact.CreateSourceFile(env.Paths.CreateAbsolutePath(directory, env.Paths.CreateRelativePath(relativePath)));
            AbsolutePath output = env.Paths.CreateAbsolutePath(env.ObjectRoot, Guid.NewGuid().ToString());

            env.PipConstructionHelper.TryCopyFile(source, output, CopyFile.Options.None, null, "Pretend a source file is used", out _);
        }
Beispiel #16
0
        public void ConsumeFilterNotPassingFile()
        {
            FileArtifact source = FileArtifact.CreateSourceFile(SourceRootPath.Combine(Context.PathTable, "file.txt"));

            WriteSourceFile(source);
            var output = CreateOutputFileArtifact(ObjectRoot);

            SealDirectory     sealedDirectory = CreateSourceSealDirectory(SourceRootPath, SealDirectoryKind.SourceTopDirectoryOnly, "*.cs");
            DirectoryArtifact dir             = PipGraphBuilder.AddSealDirectory(sealedDirectory);

            var builder = CreatePipBuilder(new Operation[]
            {
                Operation.ReadFile(source, doNotInfer: true),
                Operation.WriteFile(output),
            });

            builder.AddInputDirectory(dir);
            SchedulePipBuilder(builder);

            RunScheduler().AssertFailure();
            AssertVerboseEventLogged(ProcessesLogEventId.PipProcessDisallowedFileAccess);
            AssertVerboseEventLogged(LogEventId.DependencyViolationMissingSourceDependency);
            AssertWarningEventLogged(LogEventId.ProcessNotStoredToCacheDueToFileMonitoringViolations);
            AssertErrorEventLogged(LogEventId.FileMonitoringError);
        }
        public void TestFailingPipDump(bool failPip)
        {
            BaseSetup();

            FileArtifact sourceArtifact      = failPip ? FileArtifact.CreateSourceFile(CreateUniqueSourcePath(SourceRootPrefix)) : CreateSourceFile();
            FileArtifact destinationArtifact = CreateOutputFileArtifact();
            var          copyFile            = CreateCopyFile(sourceArtifact, destinationArtifact);

            PipGraphBuilder.AddCopyFile(copyFile);

            var schedulerResult = RunScheduler();

            var logFolder   = Path.Combine(schedulerResult.Config.Logging.LogsDirectory.ToString(Context.PathTable), "FailedPips");
            var pipDumpFile = Path.Combine(logFolder, $"{copyFile.FormattedSemiStableHash}.json");

            if (failPip)
            {
                schedulerResult.AssertFailure();
                SetExpectedFailures(1, 0); // One error logged for the failing pip
                AssertErrorCount();

                Assert.True(Directory.Exists(logFolder));
                Assert.True(File.Exists(pipDumpFile));
                Assert.True(new FileInfo(pipDumpFile).Length > 0); //Ensure that some content was written to the file
            }
            else
            {
                schedulerResult.AssertSuccess();
                // FailedPips log folder should not have been created when we run successfully
                Assert.False(Directory.Exists(logFolder));
                Assert.False(File.Exists(pipDumpFile));
            }
        }
Beispiel #18
0
        private void DoTestRenderer(PathTable pathTable, PipFragmentRenderer renderer, string expectedHash)
        {
            // StringId
            var strValue = "my string";

            XAssert.AreEqual(strValue, renderer.Render(PipFragment.FromString(strValue, pathTable.StringTable)));

            var pathStr   = A("t", "file1.txt");
            var path      = AbsolutePath.Create(pathTable, pathStr);
            var srcFile   = FileArtifact.CreateSourceFile(path);
            var outFile   = FileArtifact.CreateOutputFile(srcFile);
            var rwFile    = outFile.CreateNextWrittenVersion();
            var rw2File   = rwFile.CreateNextWrittenVersion();
            var opaqueDir = DirectoryArtifact.CreateDirectoryArtifactForTesting(path, 0);
            var sharedDir = new DirectoryArtifact(path, 1, isSharedOpaque: true);

            // AbsolutePath
            XAssert.AreEqual(pathStr, renderer.Render(PipFragment.FromAbsolutePathForTesting(path)));
            XAssert.AreEqual(pathStr, renderer.Render(PipFragment.FromAbsolutePathForTesting(srcFile)));
            XAssert.AreEqual(pathStr, renderer.Render(PipFragment.FromAbsolutePathForTesting(outFile)));
            XAssert.AreEqual(pathStr, renderer.Render(PipFragment.FromAbsolutePathForTesting(rwFile)));
            XAssert.AreEqual(pathStr, renderer.Render(PipFragment.FromAbsolutePathForTesting(rw2File)));

            // VsoHash
            XAssert.AreEqual(expectedHash, renderer.Render(PipFragment.VsoHashFromFileForTesting(srcFile)));
            XAssert.AreEqual(expectedHash, renderer.Render(PipFragment.VsoHashFromFileForTesting(outFile)));
            XAssert.AreEqual(expectedHash, renderer.Render(PipFragment.VsoHashFromFileForTesting(rwFile)));
            XAssert.AreEqual(expectedHash, renderer.Render(PipFragment.VsoHashFromFileForTesting(rw2File)));

            XAssert.AreEqual(DirectoryId.ToString(opaqueDir), renderer.Render(PipFragment.DirectoryIdForTesting(opaqueDir)));
            XAssert.AreEqual(DirectoryId.ToString(sharedDir), renderer.Render(PipFragment.DirectoryIdForTesting(sharedDir)));
        }
Beispiel #19
0
        public void TestDumpPipLiteWithPassingAndFailingPips()
        {
            var passingCopyFile = new CopyFile(CreateSourceFile(), CreateOutputFileArtifact(), new List <StringId>().ToReadOnlyArray(), PipProvenance.CreateDummy(Context));
            var failingCopyFile = new CopyFile(FileArtifact.CreateSourceFile(CreateUniqueSourcePath(SourceRootPrefix)), CreateOutputFileArtifact(), new List <StringId>().ToReadOnlyArray(), PipProvenance.CreateDummy(Context));

            PipGraphBuilder.AddCopyFile(passingCopyFile);
            PipGraphBuilder.AddCopyFile(failingCopyFile);

            var schedulerResult = RunScheduler().AssertFailure();

            var logFolder          = Path.Combine(schedulerResult.Config.Logging.LogsDirectory.ToString(Context.PathTable), "FailedPips");
            var failingPipDumpFile = Path.Combine(logFolder, $"{failingCopyFile.FormattedSemiStableHash}.json");
            var passingPipDumpFile = Path.Combine(logFolder, $"{passingCopyFile.FormattedSemiStableHash}.json");


            List <Option> options = new List <Option>
            {
                new Option()
                {
                    Name = "d+"
                }
            };

            RunAnalyzer(schedulerResult, null, options);

            Assert.True(Directory.Exists(logFolder));
            Assert.True(File.Exists(failingPipDumpFile));
            Assert.True(!File.Exists(passingPipDumpFile));
        }
Beispiel #20
0
        public void AffectedSourceInsideSourceSealDirectory()
        {
            var sourceDirectory           = CreateUniqueDirectory(SourceRootPath);
            var fileInsideSourceDirectory = CreateSourceFile(sourceDirectory, "file_");
            var sourceSealDirectory       = CreateSourceSealDirectory(sourceDirectory, SealDirectoryKind.SourceTopDirectoryOnly, "file_*");

            PipGraphBuilder.AddSealDirectory(sourceSealDirectory);

            var changeAffectedWrittenFile = CreateUniqueObjPath("change");
            var pipBuilder = CreatePipBuilder(new Operation[]
            {
                // Ensure that pip reads the changeAffectedWrittenFile if it exists.
                Operation.ReadFile(FileArtifact.CreateSourceFile(changeAffectedWrittenFile), doNotInfer: true),
                Operation.ReadFile(fileInsideSourceDirectory, doNotInfer: true),
                Operation.WriteFile(CreateOutputFileArtifact()),
            });

            pipBuilder.AddInputDirectory(sourceSealDirectory.Directory);
            pipBuilder.SetChangeAffectedInputListWrittenFile(changeAffectedWrittenFile);
            SchedulePipBuilder(pipBuilder);
            var inputChangesFile = CreateOutputFileArtifact();

            File.WriteAllText(ArtifactToString(inputChangesFile), ArtifactToString(fileInsideSourceDirectory));
            Configuration.Schedule.InputChanges = inputChangesFile;

            RunScheduler().AssertSuccess();

            var actualAffectedInput = File.ReadAllText(changeAffectedWrittenFile.ToString(Context.PathTable));

            XAssert.AreEqual(ArtifactToString(fileInsideSourceDirectory), actualAffectedInput);
        }
Beispiel #21
0
        private ContentFingerprint CreateFingerprintForPartialSealWithMember(string fileName)
        {
            using (TestEnv env = TestEnv.CreateTestEnvWithPausedScheduler())
            {
                AbsolutePath root   = env.Paths.CreateAbsolutePath(@"\\dummyPath\Root");
                FileArtifact member = FileArtifact.CreateSourceFile(root.Combine(env.PathTable, fileName));

                var staticDirectory = env.PipConstructionHelper.SealDirectoryPartial(
                    root,
                    new[] { member });

                var pipBuilder = CreatePipBuilderWithTag(env, nameof(TestPartialSealDirectoryMembersAffectFingerprints));
                var outputPath = env.Paths.CreateAbsolutePath(@"\\dummyPath\out");
                pipBuilder.AddOutputFile(outputPath);
                pipBuilder.AddInputDirectory(staticDirectory);

                env.PipConstructionHelper.AddProcess(pipBuilder);
                var graph      = AssertSuccessGraphBuilding(env);
                var producerId = graph.TryGetProducer(FileArtifact.CreateOutputFile(outputPath));

                XAssert.IsTrue(producerId.IsValid);
                XAssert.IsTrue(graph.TryGetPipFingerprint(producerId, out ContentFingerprint fingerprint));

                return(fingerprint);
            }
        }
Beispiel #22
0
        public void IncrementalSchedulingIsRobustAgainstFileCreationMidBuild()
        {
            var directoryPath       = CreateUniqueDirectory(ReadonlyRoot);
            var fileInsideDirectory = FileArtifact.CreateSourceFile(Combine(directoryPath, "fileToBeCreated"));

            FileArtifact  outputA         = CreateOutputFileArtifact();
            SealDirectory sealedDirectory = CreateAndScheduleSealDirectory(directoryPath, SealDirectoryKind.Partial, fileInsideDirectory);

            var builderA = CreatePipBuilder(new Operation[]
            {
                Operation.Probe(fileInsideDirectory, doNotInfer: true),
                Operation.WriteFile(outputA, "Hello World A!")
            });

            builderA.AddInputDirectory(sealedDirectory.Directory);

            var pipA = SchedulePipBuilder(builderA);

            FileArtifact outputB     = CreateOutputFileArtifact();
            FileArtifact rougeOutput = CreateOutputFileArtifact(directoryPath);

            var builderB = CreatePipBuilder(new Operation[]
            {
                Operation.ReadFile(outputA),
                Operation.WriteFile(outputB, "Hello World B!"),
                Operation.WriteFile(fileInsideDirectory, "Whatever", doNotInfer: true)
            });

            builderB.AddUntrackedDirectoryScope(sealedDirectory.Directory);

            var pipB = SchedulePipBuilder(builderB);

            FileArtifact outputC = CreateOutputFileArtifact();

            var builderC = CreatePipBuilder(new Operation[]
            {
                Operation.ReadFile(outputB),
                Operation.Probe(fileInsideDirectory, doNotInfer: true),
                Operation.WriteFile(outputC, "Hello World C!")
            });

            builderC.AddInputDirectory(sealedDirectory.Directory);

            var pipC = SchedulePipBuilder(builderC);

            var result = RunScheduler().AssertScheduled(
                pipA.Process.PipId,
                pipB.Process.PipId,
                pipC.Process.PipId);

            // File creation blows away incremental scheduling state.
            RunScheduler()
            .AssertScheduled(
                pipA.Process.PipId,
                pipB.Process.PipId,
                pipC.Process.PipId)
            .AssertCacheMiss(pipA.Process.PipId, pipC.Process.PipId)
            .AssertCacheHit(pipB.Process.PipId);
        }
Beispiel #23
0
        public void AllowlistOnSpawnProcess(bool includeExecutableLink)
        {
            FileArtifact exe     = FileArtifact.CreateSourceFile(AbsolutePath.Create(Context.PathTable, CmdHelper.OsShellExe));
            FileArtifact exeLink = FileArtifact.CreateSourceFile(CreateUniqueSourcePath());

            XAssert.IsTrue(FileUtilities.TryCreateSymbolicLink(exeLink.Path.ToString(Context.PathTable), exe.Path.ToString(Context.PathTable), true).Succeeded);

            Configuration.CacheableFileAccessAllowlist.Add(new Configuration.Mutable.FileAccessAllowlistEntry()
            {
                ToolPath = exeLink, PathRegex = ".*"
            });

            FileArtifact output = CreateOutputFileArtifact();

            var builder = CreatePipBuilder(new[]
            {
                Operation.SpawnExe(
                    Context.PathTable,
                    exeLink,
                    string.Format(OperatingSystemHelper.IsUnixOS ? "-c \"echo 'hi' > {0}\"" : "/d /c echo 'hi' > {0}", output.Path.ToString(Context.PathTable))),
            });

            builder.AddOutputFile(output.Path);

            if (includeExecutableLink)
            {
                builder.AddInputFile(exeLink);
            }

            foreach (var dep in CmdHelper.GetCmdDependencies(Context.PathTable))
            {
                builder.AddUntrackedFile(dep);
            }

            foreach (var dep in CmdHelper.GetCmdDependencyScopes(Context.PathTable))
            {
                builder.AddUntrackedDirectoryScope(dep);
            }

            SchedulePipBuilder(builder);

            if (includeExecutableLink)
            {
                RunScheduler().AssertSuccess();
                XAssert.AreEqual("hi", File.ReadAllText(ArtifactToString(output)).Trim().Trim('\''));
            }
            else
            {
                RunScheduler().AssertFailure();

                // DFA on exeLink because it is not specified as input.
                // Although there's a cacheable allowlist entry for exeLink, that entry only holds for file accessed by exeLink.
                // In this case, exeLink is accessed by the test process, so there's a read operation by the test process on exeLink, hence DFA.
                AssertErrorEventLogged(LogEventId.FileMonitoringError, 1);
                AssertLogContains(false, $"R  {exeLink.Path.ToString(Context.PathTable)}");

                AssertWarningEventLogged(LogEventId.ProcessNotStoredToCacheDueToFileMonitoringViolations, 1);
            }
        }
Beispiel #24
0
        private static EvaluationResult GetFileValue(Context context, ModuleLiteral env, EvaluationStackFrame args)
        {
            AbsolutePath path = GetPathValue(context, args);

            return(path.IsValid
                ? EvaluationResult.Create(FileArtifact.CreateSourceFile(path))
                : EvaluationResult.Undefined);
        }
Beispiel #25
0
        /// <summary>
        /// Creates a symbolic link to a shell executable and returns a FileArtifact with a path to the executable
        /// </summary>
        protected FileArtifact CreateOsShellExecutableSymbolicLink()
        {
            FileArtifact exe     = FileArtifact.CreateSourceFile(AbsolutePath.Create(Context.PathTable, CmdHelper.OsShellExe));
            FileArtifact exeLink = FileArtifact.CreateSourceFile(CreateUniqueSourcePath());

            XAssert.IsTrue(FileUtilities.TryCreateSymbolicLink(exeLink.Path.ToString(Context.PathTable), exe.Path.ToString(Context.PathTable), true).Succeeded);

            return(exeLink);
        }
Beispiel #26
0
        public Task DirectlyReportedNonexistentFailsWithAllowRead(AccessType accessType)
        {
            var file = FileArtifact.CreateSourceFile(CreateUniqueSourcePath());

            return(VerifyReporting(
                       accessType,
                       (manifest) => manifest.AddPath(file, values: FileAccessPolicy.AllowRead | FileAccessPolicy.ReportAccess, mask: FileAccessPolicy.MaskNothing),
                       ExpectDeniedAccess(file, exists: false)));
        }
Beispiel #27
0
        /// <nodoc />
        public static FileArtifact GetOutputFile(this ProcessOutputs processOutputs, AbsolutePath path)
        {
            if (!processOutputs.TryGetOutputFile(FileArtifact.CreateSourceFile(path), out var file))
            {
                throw new InvalidOperationException();
            }

            return(file);
        }
Beispiel #28
0
        /// <summary>
        /// Gets a process builder.
        /// </summary>
        public ProcessBuilder GetProcessBuilder()
        {
            var builder = ProcessBuilder.CreateForTesting(Context.PathTable);

            builder.Executable = FileArtifact.CreateSourceFile(m_sourceRoot.Combine(Context.PathTable, "test.exe"));
            builder.AddInputFile(builder.Executable);

            return(builder);
        }
Beispiel #29
0
            /// <nodoc />
            public MacOsDefaults(PathTable pathTable, PipGraph.Builder pipGraph)
            {
                m_provenance = new PipProvenance(
                    0,
                    ModuleId.Invalid,
                    StringId.Invalid,
                    FullSymbol.Invalid,
                    LocationData.Invalid,
                    QualifierId.Unqualified,
                    PipData.Invalid);

                m_inputFiles =
                    new[]
                {
                    FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, MacPaths.Etc)),
                    FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, MacPaths.TmpDir)),
                };

                // Sealed Source inputs
                m_inputDirectories =
                    new[]
                {
                    GetSourceSeal(pathTable, pipGraph, MacPaths.Applications),
                    GetSourceSeal(pathTable, pipGraph, MacPaths.UsrBin),
                    GetSourceSeal(pathTable, pipGraph, MacPaths.UsrInclude),
                    GetSourceSeal(pathTable, pipGraph, MacPaths.UsrLib),
                    GetSourceSeal(pathTable, pipGraph, MacPaths.Library),
                    GetSourceSeal(pathTable, pipGraph, MacPaths.UserProvisioning),
                };

                m_untrackedFiles =
                    new[]
                {
                    // login.keychain is created by the OS the first time any process invokes an OS API that references the keychain.
                    // Untracked because build state will not be stored there and code signing will fail if required certs are in the keychain
                    FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, MacPaths.UserKeyChainsDb)),
                    FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, MacPaths.UserKeyChains)),
                    FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, MacPaths.UserCFTextEncoding)),
                };

                m_untrackedDirectories =
                    new[]
                {
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.Bin),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.Dev),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.Private),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.Sbin),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.SystemLibrary),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.UsrLibexec),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.UsrShare),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.UsrStandalone),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.UsrSbin),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.Var),
                    DirectoryArtifact.CreateWithZeroPartialSealId(pathTable, MacPaths.UserPreferences),
                };
            }
Beispiel #30
0
        /// <nodoc />
        private async Task <EvaluationResult> ValidateAndStoreIncrementalExtractState(PipConstructionHelper pipConstructionHelper, DownloadData downloadData)
        {
            var archive = downloadData.DownloadedFilePath.ToString(m_context.PathTable);
            var target  = downloadData.ContentsFolder.Path.ToString(m_context.PathTable);

            try
            {
                var allFiles = new List <FileArtifact>();

                var enumeratResult = FileUtilities.EnumerateDirectoryEntries(target, true, "*",
                                                                             (dir, fileName, attributes) =>
                {
                    if ((attributes & FileAttributes.Directory) == 0)
                    {
                        var filePath = Path.Combine(dir, fileName);
                        allFiles.Add(FileArtifact.CreateSourceFile(AbsolutePath.Create(m_context.PathTable, filePath)));
                    }
                });

                if (!enumeratResult.Succeeded)
                {
                    var error = new Win32Exception(enumeratResult.NativeErrorCode);
                    m_logger.ErrorListingPackageContents(m_context.LoggingContext, downloadData.Settings.ModuleName, archive, target, error.Message);
                    return(EvaluationResult.Error);
                }

                if (allFiles.Count == 0)
                {
                    m_logger.ErrorListingPackageContents(m_context.LoggingContext, downloadData.Settings.ModuleName, archive, target, "file list is empty");
                    return(EvaluationResult.Error);
                }

                var sortedFiles = SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> .CloneAndSort(
                    allFiles,
                    OrdinalFileArtifactComparer.Instance);

                var hashes = new Dictionary <AbsolutePath, ContentHash>();
                foreach (var file in allFiles)
                {
                    var hash = await GetContentHashAsync(file);

                    hashes.Add(file.Path, hash);
                }

                var incrementalState = new ExtractIncrementalState(downloadData, sortedFiles, hashes);
                await incrementalState.SaveAsync(m_context);

                return(SealDirectory(pipConstructionHelper, downloadData, downloadData.ContentsFolder, sortedFiles));
            }
            catch (Exception e)
                when(e is BuildXLException || e is IOException || e is UnauthorizedAccessException)
                {
                    m_logger.ErrorExtractingArchive(m_context.LoggingContext, downloadData.Settings.ModuleName, archive, target, e.Message);
                    return(EvaluationResult.Error);
                }
        }