Beispiel #1
0
        public void WriteToJunctionTest()
        {
            //// ............ Setting up the output dir for the pips .................
            AbsolutePath originPath   = CreateUniqueDirectory(ObjectRoot);
            AbsolutePath junctionPath = CreateUniqueDirectory(ObjectRoot);
            FileArtifact junctionFile = CreateOutputFileArtifact(junctionPath.ToString(Context.PathTable));

            // .......... Creating the Junction ..........
            FileUtilities.CreateJunction(junctionPath.ToString(Context.PathTable), originPath.ToString(Context.PathTable));

            // ........... PIP A ...........
            Process pipA = CreateAndSchedulePipBuilder(new Operation[]
            {
                Operation.WriteFile(junctionFile)
            }).Process;

            // ...........PIP B...........
            var builderB = CreatePipBuilder(new Operation[]
            {
                Operation.ReadFile(junctionFile, doNotInfer: true),
                Operation.WriteFile(CreateOutputFileArtifact(originPath.ToString(Context.PathTable)))
            });

            // Currently, BuildXL does not require adding the target of a junction as input (in contrast to symlinks)
            builderB.AddInputFile(junctionFile);

            var pipB = SchedulePipBuilder(builderB);

            RunScheduler().AssertCacheMiss(pipA.PipId, pipB.Process.PipId);

            // Should have hit with junction
            RunScheduler().AssertCacheHit(pipA.PipId, pipB.Process.PipId);
        }
Beispiel #2
0
        public void ChangeIntermediateJunctionDoesNotRebuild()
        {
            const string ReadFileName = "file";

            AbsolutePath targetDirectoryA = CreateUniqueDirectory(SourceRoot, "DirA");
            AbsolutePath targetDirectoryB = CreateUniqueDirectory(SourceRoot, "DirB");

            string expandedTargetDirectoryA = targetDirectoryA.ToString(Context.PathTable);
            string expandedTargetDirectoryB = targetDirectoryB.ToString(Context.PathTable);

            AbsolutePath junction1 = CreateUniqueDirectory(SourceRoot, "Junc1");
            AbsolutePath junction2 = CreateUniqueDirectory(SourceRoot, "Junc2");

            string expandedJunction1 = junction1.ToString(Context.PathTable);
            string expandedJunction2 = junction2.ToString(Context.PathTable);

            FileArtifact targetAFile = CreateFileArtifactWithName(ReadFileName, expandedTargetDirectoryA);
            FileArtifact targetBFile = CreateFileArtifactWithName(ReadFileName, expandedTargetDirectoryB);

            WriteSourceFile(targetAFile);
            WriteSourceFile(targetBFile);

            FileArtifact junction1File = CreateFileArtifactWithName(ReadFileName, expandedJunction1);
            FileArtifact junction2File = CreateFileArtifactWithName(ReadFileName, expandedJunction2);

            // Create junction
            //     Junc1 -> Junc2 -> DirA
            FileUtilities.CreateJunction(expandedJunction2, expandedTargetDirectoryA);
            FileUtilities.CreateJunction(expandedJunction1, expandedJunction2);

            FileArtifact outputP = CreateOutputFileArtifact();

            var builderP = CreatePipBuilder(new Operation[] { Operation.CopyFile(junction2File, outputP, doNotInfer: true) });

            builderP.AddInputFile(junction1File);
            builderP.AddOutputFile(outputP.Path, FileExistence.Required);
            var pipP = SchedulePipBuilder(builderP).Process;

            DirectoryTranslator = new DirectoryTranslator();
            DirectoryTranslator.AddTranslation(expandedTargetDirectoryA, expandedJunction2);
            DirectoryTranslator.AddTranslation(expandedJunction2, expandedJunction1);

            RunScheduler().AssertSuccess().AssertCacheMiss(pipP.PipId);

            // Change junction
            //     Junc2 -> DirB
            FileUtilities.CreateJunction(expandedJunction2, expandedTargetDirectoryB);

            var result = RunScheduler().AssertSuccess();

            if (Configuration.Schedule.IncrementalScheduling)
            {
                // Junc2 is not tracked because BuildXL only track final translation, which is Junc1.
                result.AssertNotScheduled(pipP.PipId);
            }
            else
            {
                result.AssertCacheMiss(pipP.PipId);
            }
        }
        public void EnumeratedReparsePointIsTreatedAsFile()
        {
            // Create sharedOpaque/junctionDir -> target
            string sharedOpaqueDirString = Path.Combine(ObjectRoot, "sod");
            string junctionDirString     = Path.Combine(sharedOpaqueDirString, "junction");
            string targetDirString       = Path.Combine(ObjectRoot, "target");

            Directory.CreateDirectory(sharedOpaqueDirString);
            Directory.CreateDirectory(targetDirString);
            FileUtilities.CreateJunction(junctionDirString, targetDirString, createDirectoryForJunction: true);

            AbsolutePath      sharedOpaqueDirPath = AbsolutePath.Create(Context.PathTable, sharedOpaqueDirString);
            AbsolutePath      junctionDirPath     = AbsolutePath.Create(Context.PathTable, junctionDirString);
            DirectoryArtifact sharedOpaqueDir     = DirectoryArtifact.CreateWithZeroPartialSealId(sharedOpaqueDirPath);

            // Schedule a pip that enumerates the shared opaque, turning on undeclared source reads so we make sure minimal graph with alien files is used
            var enumeratorBuilder = CreatePipBuilder(new Operation[]
            {
                Operation.EnumerateDir(sharedOpaqueDir, doNotInfer: true),
                Operation.WriteFile(CreateOutputFileArtifact())
            });

            enumeratorBuilder.AddOutputDirectory(sharedOpaqueDir, global::BuildXL.Pips.Operations.SealDirectoryKind.SharedOpaque);
            enumeratorBuilder.Options |= global::BuildXL.Pips.Operations.Process.Options.AllowUndeclaredSourceReads;

            SchedulePipBuilder(enumeratorBuilder);

            var result = RunScheduler().AssertSuccess();

            var existence = result.FileSystemView.GetExistence(junctionDirPath, global::BuildXL.Scheduler.FileSystem.FileSystemViewMode.Real);

            XAssert.AreEqual(PathExistence.ExistsAsFile, existence.Result);
        }
Beispiel #4
0
        private DirectoryTranslator.RawInputTranslation CreateInputTranslationWithJunction(
            PathTable pathTable,
            string[] relativeSource,
            string[] relativeTarget,
            bool createSourceDirectory = true,
            bool createTargetDirectory = true,
            bool createJunction        = true)
        {
            string fullSource = Path.Combine(TestOutputDirectory, R(relativeSource));
            string fullTarget = Path.Combine(TestOutputDirectory, R(relativeTarget));

            if (createJunction)
            {
                // If junction is requested, then ensure that source and target directories exist.
                createSourceDirectory = true;
                createTargetDirectory = true;
            }

            if (createSourceDirectory)
            {
                FileUtilities.CreateDirectory(fullSource);
            }

            if (createTargetDirectory)
            {
                FileUtilities.CreateDirectory(fullTarget);
            }

            if (createJunction)
            {
                FileUtilities.CreateJunction(fullSource, fullTarget);
            }

            return(DirectoryTranslator.RawInputTranslation.Create(AbsolutePath.Create(pathTable, fullSource), AbsolutePath.Create(pathTable, fullTarget)));
        }
Beispiel #5
0
        public void ReadSymlinkOnJunctionTest(bool translate)
        {
            // ............ Setting up the output dir for the pips .................
            AbsolutePath targetPath   = CreateUniqueDirectory(ObjectRoot);
            AbsolutePath junctionPath = CreateUniqueDirectory(ObjectRoot);

            // .......... Creating the Junction ..........
            FileUtilities.CreateJunction(junctionPath.ToString(Context.PathTable), targetPath.ToString(Context.PathTable));

            ReparsePointWithSymlinkTest(targetPath.ToString(Context.PathTable), junctionPath.ToString(Context.PathTable), translate);
        }
Beispiel #6
0
 private void CreateJunction(OperationContext context, AbsolutePath source, AbsolutePath target)
 {
     context.PerformOperation(
         Tracer,
         () =>
     {
         Directory.CreateDirectory(target.Path);
         Directory.CreateDirectory(source.Path);
         FileUtilities.CreateJunction(source.Path, target.Path);
         return(BoolResult.Success);
     },
         extraStartMessage: $"{source}=>{target}").ThrowIfFailure();
 }
Beispiel #7
0
        public void UseJunctionRoots()
        {
            AbsolutePath targetPath      = CreateUniqueDirectory(SourceRoot);
            AbsolutePath junctionPath    = CreateUniqueDirectory(SourceRoot);
            string       targetPathStr   = targetPath.ToString(Context.PathTable);
            string       junctionPathStr = junctionPath.ToString(Context.PathTable);

            // .......... Creating the Junction ..........
            FileUtilities.CreateJunction(junctionPath.ToString(Context.PathTable), targetPathStr);

            FileArtifact sourceFile = CreateSourceFile(junctionPathStr);

            Configuration.Engine.DirectoriesToTranslate.Add(
                new BuildXLConfiguration.TranslateDirectoryData(
                    targetPath.ToString(Context.PathTable) + @"\<" + junctionPath.ToString(Context.PathTable) + @"\", targetPath, junctionPath));

            DirectoryTranslator.AddTranslation(targetPath, junctionPath, Context.PathTable);

            var pipBuilder = CreatePipBuilder(new Operation[]
            {
                Operation.ReadFile(sourceFile),
                Operation.WriteFile(CreateOutputFileArtifact())
            });

            SchedulePipBuilder(pipBuilder);
            RunScheduler().AssertSuccess();

            // Remove junction and recreate one with the same target
            AssertTrue(FileUtilities.TryRemoveDirectory(junctionPathStr, out var hr));
            Directory.CreateDirectory(junctionPathStr);
            FileUtilities.CreateJunction(junctionPath.ToString(Context.PathTable), targetPathStr);

            RunScheduler().AssertSuccess();
            AssertVerboseEventLogged(EventId.ValidateJunctionRoot);
            AssertVerboseEventLogged(StorageLogEventId.IgnoredRecordsDueToUnchangedJunctionRootCount);

            // Remove junction and recreate one with the same target
            AssertTrue(FileUtilities.TryRemoveDirectory(junctionPathStr, out var hr2));
            Directory.CreateDirectory(junctionPathStr);
            FileUtilities.CreateJunction(junctionPath.ToString(Context.PathTable), targetPathStr);

            RunScheduler().AssertSuccess();
            AssertVerboseEventLogged(EventId.ValidateJunctionRoot);
            AssertVerboseEventLogged(StorageLogEventId.IgnoredRecordsDueToUnchangedJunctionRootCount);
        }
Beispiel #8
0
        public void ChangeJunctionWithTranslateDirectoryShouldRebuild()
        {
            const string ReadFileName = "file";

            AbsolutePath targetDirectoryA = CreateUniqueDirectory(SourceRoot, "DirA");
            AbsolutePath targetDirectoryB = CreateUniqueDirectory(SourceRoot, "DirB");
            AbsolutePath targetDirectoryC = CreateUniqueDirectory(SourceRoot, "DirC");

            string expandedTargetDirectoryA = targetDirectoryA.ToString(Context.PathTable);
            string expandedTargetDirectoryB = targetDirectoryB.ToString(Context.PathTable);
            string expandedTargetDirectoryC = targetDirectoryC.ToString(Context.PathTable);

            AbsolutePath junction1 = CreateUniqueDirectory(SourceRoot, "Junc1");
            AbsolutePath junction2 = CreateUniqueDirectory(SourceRoot, "Junc2");

            string expandedJunction1 = junction1.ToString(Context.PathTable);
            string expandedJunction2 = junction2.ToString(Context.PathTable);

            FileArtifact targetAFile = CreateFileArtifactWithName(ReadFileName, expandedTargetDirectoryA);
            FileArtifact targetBFile = CreateFileArtifactWithName(ReadFileName, expandedTargetDirectoryB);
            FileArtifact targetCFile = CreateFileArtifactWithName(ReadFileName, expandedTargetDirectoryC);

            WriteSourceFile(targetAFile);
            WriteSourceFile(targetBFile);
            WriteSourceFile(targetCFile);

            FileArtifact junction1File = CreateFileArtifactWithName(ReadFileName, expandedJunction1);
            FileArtifact junction2File = CreateFileArtifactWithName(ReadFileName, expandedJunction2);

            // Create junction
            //     Junc1 -> DirA
            //     Junc2 -> DirC
            FileUtilities.CreateJunction(expandedJunction1, expandedTargetDirectoryA);
            FileUtilities.CreateJunction(expandedJunction2, expandedTargetDirectoryC);

            FileArtifact outputP = CreateOutputFileArtifact();
            FileArtifact outputQ = CreateOutputFileArtifact();

            var builderP = CreatePipBuilder(new Operation[] { Operation.CopyFile(junction1File, outputP) });
            var pipP     = SchedulePipBuilder(builderP).Process;

            var builderQ = CreatePipBuilder(new Operation[] { Operation.CopyFile(targetCFile, outputQ, doNotInfer: true) });

            builderQ.AddInputFile(junction2File);
            builderQ.AddOutputFile(outputQ.Path, FileExistence.Required);
            var pipQ = SchedulePipBuilder(builderQ).Process;

            DirectoryTranslator = new DirectoryTranslator();
            DirectoryTranslator.AddTranslation(expandedTargetDirectoryA, expandedJunction1);
            DirectoryTranslator.AddTranslation(expandedTargetDirectoryC, expandedJunction2);

            RunScheduler().AssertSuccess().AssertCacheMiss(pipP.PipId, pipQ.PipId);

            // Change junction
            //     Junc2 -> DirB
            FileUtilities.CreateJunction(expandedJunction1, expandedTargetDirectoryB);

            var result = RunScheduler().AssertSuccess().AssertCacheMiss(pipP.PipId);

            if (Configuration.Schedule.IncrementalScheduling)
            {
                // pipQ should not be affected at all.
                result.AssertNotScheduled(pipQ.PipId);
            }
            else
            {
                // pipQ is scheduled but results in cache hit.
                result.AssertScheduled(pipQ.PipId).AssertCacheHit(pipQ.PipId);
            }
        }
Beispiel #9
0
        public void ChangeJunctionShouldRebuild()
        {
            const string ReadFileName = "file";

            AbsolutePath targetDirectoryA = CreateUniqueDirectory(SourceRoot, "DirA");
            AbsolutePath targetDirectoryB = CreateUniqueDirectory(SourceRoot, "DirB");

            string expandedTargetDirectoryA = targetDirectoryA.ToString(Context.PathTable);
            string expandedTargetDirectoryB = targetDirectoryB.ToString(Context.PathTable);

            AbsolutePath junction1 = CreateUniqueDirectory(SourceRoot, "Junc1");

            string expandedJunction1 = junction1.ToString(Context.PathTable);

            FileArtifact targetAFile = CreateFileArtifactWithName(ReadFileName, expandedTargetDirectoryA);
            FileArtifact targetBFile = CreateFileArtifactWithName(ReadFileName, expandedTargetDirectoryB);

            WriteSourceFile(targetAFile);
            WriteSourceFile(targetBFile);

            FileArtifact junction1File = CreateFileArtifactWithName(ReadFileName, expandedJunction1);

            // Create junction
            //     Junc1 -> DirA
            FileUtilities.CreateJunction(expandedJunction1, expandedTargetDirectoryA);

            FileArtifact outputP = CreateOutputFileArtifact();
            FileArtifact outputQ = CreateOutputFileArtifact();

            var pipP = SchedulePipBuilder(CreatePipBuilder(new Operation[] { Operation.CopyFile(junction1File, outputP) })).Process;

            // We don't need directory translator here because pipP reads through junction1File.
            // But we want to show that incremental scheduling is not sensitive to directory translator.
            DirectoryTranslator = new DirectoryTranslator();
            DirectoryTranslator.AddTranslation(expandedTargetDirectoryA, expandedJunction1);

            RunScheduler().AssertSuccess().AssertCacheMiss(pipP.PipId);

            // Change junction
            //     Junc1 -> DirB
            FileUtilities.CreateJunction(expandedJunction1, expandedTargetDirectoryB);

            DirectoryTranslator = new DirectoryTranslator();
            DirectoryTranslator.AddTranslation(expandedTargetDirectoryB, expandedJunction1);

            RunScheduler().AssertSuccess().AssertCacheMiss(pipP.PipId);

            // Modify DirB\File
            WriteSourceFile(targetBFile);
            RunScheduler().AssertSuccess().AssertCacheMiss(pipP.PipId);

            // Modify DirA\File
            WriteSourceFile(targetAFile);

            // Note that, even though DirA\File has nothing to do with the build as the junction has changed to DirB,
            // incremental scheduling, when enabled, will still mark pipP dirty. In the first build the file change tracker
            // tracked DirA\File, and introduced a mapping from FileId(DirA\File) to Path(Junc1\File). Thus, when DirA\File
            // changes, Path(Junc1\File) is affected, and since pipP specifies Path(Junc1\File) as its input, pipP is affected as well.
            RunScheduler().AssertSuccess().AssertScheduled(pipP.PipId).AssertCacheHit(pipP.PipId);

            // Modify again DirA\File.
            // After the above run, the mapping FileId(DirA\File) to Path(Junc1\File) has been removed, and thus,
            // any change to DirA\File should not affect pipP.
            WriteSourceFile(targetAFile);

            var result = RunScheduler().AssertSuccess();

            if (Configuration.Schedule.IncrementalScheduling)
            {
                result.AssertNotScheduled(pipP.PipId);
            }
            else
            {
                result.AssertCacheHit(pipP.PipId);
            }
        }