Example #1
0
            public PipQueueTestExecutionEnvironment(BuildXLContext context, IConfiguration configuration, PipTable pipTable, string tempDirectory, ISandboxConnection SandboxConnection = null)
            {
                Contract.Requires(context != null);
                Contract.Requires(configuration != null);

                Context              = context;
                LoggingContext       = CreateLoggingContextForTest();
                Configuration        = configuration;
                FileContentTable     = FileContentTable.CreateNew();
                ContentFingerprinter = new PipContentFingerprinter(
                    context.PathTable,
                    artifact => State.FileContentManager.GetInputContent(artifact).FileContentInfo,
                    ExtraFingerprintSalts.Default(),
                    pathExpander: PathExpander);
                PipTable            = pipTable;
                PipFragmentRenderer = this.CreatePipFragmentRenderer();
                IpcProvider         = IpcFactory.GetProvider();
                var tracker = FileChangeTracker.CreateDisabledTracker(LoggingContext);

                Cache = InMemoryCacheFactory.Create();
                LocalDiskContentStore = new LocalDiskContentStore(LoggingContext, context.PathTable, FileContentTable, tracker);

                m_sandboxConnectionKext  = SandboxConnection;
                m_expectedWrittenContent = new ConcurrentDictionary <FileArtifact, ContentHash>();
                m_wellKnownFiles         = new ConcurrentDictionary <FileArtifact, ContentHash>();
                m_producers      = new ConcurrentDictionary <FileArtifact, Pip>();
                m_filesystemView = new TestPipGraphFilesystemView(Context.PathTable);
                var fileSystemView = new FileSystemView(Context.PathTable, m_filesystemView, LocalDiskContentStore);

                TempCleaner = new TestMoveDeleteCleaner(tempDirectory);

                State = new PipExecutionState(
                    configuration,
                    cache: new PipTwoPhaseCache(LoggingContext, Cache, context, PathExpander),
                    unsafeConfiguration: configuration.Sandbox.UnsafeSandboxConfiguration,
                    preserveOutputsSalt: ContentHashingUtilities.CreateRandom(),
                    fileAccessWhitelist: FileAccessWhitelist,
                    directoryMembershipFingerprinter: this,
                    pathExpander: PathExpander,
                    executionLog: null,
                    fileSystemView: fileSystemView,
                    fileContentManager: new FileContentManager(this, new NullOperationTracker()),
                    directoryMembershipFinterprinterRuleSet: null);

                m_sealContentsById = new ConcurrentBigMap <DirectoryArtifact, int[]>();

                ProcessInContainerManager = new ProcessInContainerManager(LoggingContext, context.PathTable);
            }
Example #2
0
        /// <nodoc/>
        public SchedulerIntegrationTestBase(ITestOutputHelper output) : base(output)
        {
            m_testOutputHelper           = output;
            CaptureAllDiagnosticMessages = false;

            // Each event listener that we want to capture events from must be listed here
            foreach (var eventSource in BuildXLApp.GeneratedEventSources)
            {
                RegisterEventSource(eventSource);
            }

            // Go through the command line configuration handling used by the real app to get the appropriate defaults
            ICommandLineConfiguration config;

            XAssert.IsTrue(Args.TryParseArguments(new[] { "/c:" + Path.Combine(TemporaryDirectory, "config.dc") }, Context.PathTable, null, out config), "Failed to construct arguments");
            Configuration = new CommandLineConfiguration(config);

            Cache = InMemoryCacheFactory.Create();

            FileContentTable = FileContentTable.CreateNew(LoggingContext);

            // Disable defaults that write disk IO but are not critical to correctness or performance
            Configuration.Logging.StoreFingerprints      = false;
            Configuration.Logging.LogExecution           = false;
            Configuration.Engine.TrackBuildsInUserFolder = false;
            Configuration.Engine.CleanTempDirectories    = false;
            Configuration.Sandbox.EnsureTempDirectoriesExistenceBeforePipExecution = true;

            // Skip hash source file pips
            // Some error becomes a contract exception when SkipHashSourceFile is enabled.
            // Mostly on methods that traverse graph, e.g., DirectedGraph.GetOutgoingEdges();
            // BUG 1472567
            // Configuration.Schedule.SkipHashSourceFile = true;

            // Compute static pip fingerprints for incremental scheduling tests.
            Configuration.Schedule.ComputePipStaticFingerprints = true;

            // Disable currently enabled unsafe option.
            Configuration.Sandbox.UnsafeSandboxConfigurationMutable.IgnoreCreateProcessReport = false;

            // Populate file system capabilities.
            // Here, for example, we use copy-on-write instead of hardlinks when Unix file system supports copy-on-write.
            // Particular tests can override this by setting Configuration.Engine.UseHardlinks.
            BuildXLEngine.PopulateFileSystemCapabilities(Configuration, Configuration, Context.PathTable, LoggingContext);

            // Reset pip graph builder to use the populated configuration.
            ResetPipGraphBuilder();
        }
        public async Task TruncatedTableResultsInRecoverableException()
        {
            WriteTestFiles();

            var originalTable = FileContentTable.CreateNew();

            RecordContentHash(originalTable, m_testFileA, s_hashA);
            RecordContentHash(originalTable, m_testFileB, s_hashB);
            await SaveTable(originalTable);

            TruncateTable();

            var fileContentTable = await LoadTable();

            XAssert.AreEqual(null, fileContentTable, "Table shouldn't have loaded due to missing data");
        }
        public void RecycledFileContentTableKeepsInformation()
        {
            WriteTestFiles();

            var originalTable = FileContentTable.CreateNew(LoggingContext);

            RecordContentHash(originalTable, m_testFileA, s_hashA);
            RecordContentHash(originalTable, m_testFileB, s_hashB);

            var newTable = FileContentTable.CreateFromTable(originalTable, LoggingContext);

            ExpectHashKnown(newTable, m_testFileA, s_hashA);
            ExpectHashKnown(newTable, m_testFileB, s_hashB);

            VerifyTable(newTable);
        }
        public async Task CanRoundTripMultipleEntries()
        {
            WriteTestFiles();

            var originalTable = FileContentTable.CreateNew();

            RecordContentHash(originalTable, m_testFileA, s_hashA);
            RecordContentHash(originalTable, m_testFileB, s_hashB);

            FileContentTable loadedTable = await SaveAndReloadTable(originalTable);

            ExpectHashKnown(loadedTable, m_testFileA, s_hashA);
            ExpectHashKnown(loadedTable, m_testFileB, s_hashB);

            VerifyTable(loadedTable);
        }
Example #6
0
        public void GenerateHashWithDifferentEvaluationFilters()
        {
            WriteFile("config.ds", "SampleConfig");

            var context1 = BuildXLContext.CreateInstanceForTesting();

            var configuration1 = ConfigurationHelpers.GetDefaultForTesting(context1.PathTable, AbsolutePath.Create(context1.PathTable, Path.Combine(TemporaryDirectory, "config.ds")));

            var evaluationFilter1 = new EvaluationFilter(
                context1.SymbolTable,
                context1.PathTable,
                new FullSymbol[0],
                new[]
            {
                AbsolutePath.Create(context1.PathTable, Path.Combine(TemporaryDirectory, $"testFile1.txt")),
            },
                CollectionUtilities.EmptyArray <StringId>());

            var evaluationFilter2 = new EvaluationFilter(
                context1.SymbolTable,
                context1.PathTable,
                new FullSymbol[0],
                new[]
            {
                AbsolutePath.Create(context1.PathTable, Path.Combine(TemporaryDirectory, $"testFile2.txt")),
            },
                CollectionUtilities.EmptyArray <StringId>());

            configuration1.Layout.ObjectDirectory                = AbsolutePath.Create(context1.PathTable, Path.Combine(TemporaryDirectory, $"ObjectDirectory1"));
            configuration1.Layout.TempDirectory                  = AbsolutePath.Create(context1.PathTable, Path.Combine(TemporaryDirectory, $"TempDirectory1"));
            configuration1.Layout.SourceDirectory                = AbsolutePath.Create(context1.PathTable, Path.Combine(TemporaryDirectory, $"SourceDirectory1"));
            configuration1.Logging.SubstTarget                   = AbsolutePath.Create(context1.PathTable, Path.Combine(TemporaryDirectory, $"SubstTarget1"));
            configuration1.Engine.CompressGraphFiles             = false;
            configuration1.Schedule.SkipHashSourceFile           = false;
            configuration1.Schedule.ComputePipStaticFingerprints = false;

            var loggingContext1 = CreateLoggingContextForTest();

            var fileContentTable1 = FileContentTable.CreateNew(loggingContext1);

            var oldFingerprint  = GraphFingerprinter.TryComputeFingerprint(loggingContext1, configuration1.Startup, configuration1, context1.PathTable, evaluationFilter1, fileContentTable1, "111aaa", null).ExactFingerprint;
            var newFingerprint1 = GraphFingerprinter.TryComputeFingerprint(loggingContext1, configuration1.Startup, configuration1, context1.PathTable, evaluationFilter2, fileContentTable1, "111aaa", null).ExactFingerprint;

            var comparison = oldFingerprint.CompareFingerprint(newFingerprint1);

            Assert.Equal(GraphCacheMissReason.EvaluationFilterChanged, comparison);
        }
        public async Task ChangedContentInvalidatesEntryAfterRoundtrip()
        {
            WriteTestFiles();

            var originalTable = FileContentTable.CreateNew();

            RecordContentHash(originalTable, m_testFileA, s_hashA);
            ExpectHashKnown(originalTable, m_testFileA, s_hashA);
            await SaveTable(originalTable);

            ModifyContents(m_testFileA);

            FileContentTable loadedTable = await LoadTable();

            ExpectHashUnknown(loadedTable, m_testFileA);

            VerifyTable(loadedTable);
        }
        public void RecyclingFileContentTableIsTheSameAsSavingAndLoadingFromFile()
        {
            WriteTestFiles();

            var table = FileContentTable.CreateNew(LoggingContext, entryTimeToLive: 2);

            RecordContentHash(table, m_testFileA, s_hashA);                    // TTL(A) = 2

            table = FileContentTable.CreateFromTable(table, LoggingContext);   // TTL(A) = 1
            table = FileContentTable.CreateFromTable(table, LoggingContext);   // TTL(A) = 0

            RecordContentHash(table, m_testFileB, s_hashB);                    // TTL(B) = 2

            table = FileContentTable.CreateFromTable(table, LoggingContext);
            ExpectHashUnknown(table, m_testFileA);                             // A Evicted
            ExpectHashKnown(table, m_testFileB, s_hashB);                      // TTL(B) = 1

            VerifyTable(table);
        }
        public async Task UnusedEntriesAreEvictedWithMinimumTimeToLive()
        {
            WriteTestFiles();

            var originalTable = FileContentTable.CreateNew(entryTimeToLive: 1);

            RecordContentHash(originalTable, m_testFileA, s_hashA);
            RecordContentHash(originalTable, m_testFileB, s_hashB);

            FileContentTable loadedTable = await SaveAndReloadTable(originalTable);

            ExpectHashKnown(loadedTable, m_testFileB, s_hashB);

            FileContentTable laterLoadedTable = await SaveAndReloadTable(loadedTable);

            ExpectHashKnown(laterLoadedTable, m_testFileB, s_hashB);
            ExpectHashUnknown(laterLoadedTable, m_testFileA);

            VerifyTable(laterLoadedTable);
        }
        public async Task GetAndRecordContentHashAsyncWithMatch()
        {
            ContentHash fakeHash = ContentHashingUtilities.CreateRandom();

            var fileContentTable = FileContentTable.CreateNew();

            WriteFile(FileA, "Some string");

            using (FileStream fs = File.OpenRead(GetFullPath(FileA)))
            {
                // Note that this content hash is clearly wrong, but also not all zeroes.
                fileContentTable.RecordContentHash(fs, fakeHash);
            }

            FileContentTableExtensions.VersionedFileIdentityAndContentInfoWithOrigin result =
                await fileContentTable.GetAndRecordContentHashAsync(GetFullPath(FileA));

            XAssert.AreEqual(FileContentTableExtensions.ContentHashOrigin.Cached, result.Origin);
            XAssert.AreEqual(fakeHash, result.VersionedFileIdentityAndContentInfo.FileContentInfo.Hash);
        }
        public async Task TruncatedTableResultsCanBeDiscardedWithWarning()
        {
            WriteTestFiles();

            var originalTable = FileContentTable.CreateNew();

            RecordContentHash(originalTable, m_testFileA, s_hashA);
            RecordContentHash(originalTable, m_testFileB, s_hashB);
            await SaveTable(originalTable);

            TruncateTable();

            FileContentTable loadedTable = await LoadOrCreateTable();

            ExpectHashUnknown(loadedTable, m_testFileA);
            ExpectHashUnknown(loadedTable, m_testFileB);

            AssertInformationalEventLogged(EventId.StorageLoadFileContentTable);

            VerifyTable(loadedTable);
        }
        public async Task WriteBytesIfContentMismatchedAsyncWithMismatchedDestination()
        {
            const string TargetContent = "Target!!!!!!!!!";

            var fileContentTable = FileContentTable.CreateNew();

            WriteFile(FileB, "Nope");

            FileContentTableExtensions.VersionedFileIdentityAndContentInfoWithOrigin targetInfo =
                await fileContentTable.GetAndRecordContentHashAsync(GetFullPath(FileB));

            XAssert.AreEqual(FileContentTableExtensions.ContentHashOrigin.NewlyHashed, targetInfo.Origin);

            await
            VerifyWriteBytesIfContentMismatchedAsync(
                fileContentTable,
                FileB,
                TargetContent,
                expectWrite : true,
                originalDestinationInfo : targetInfo.VersionedFileIdentityAndContentInfo);
        }
        public async Task GetAndRecordContentHashAsyncWithMismatch()
        {
            var fileContentTable = FileContentTable.CreateNew();

            using (FileStream fs = File.Open(GetFullPath(FileA), FileMode.CreateNew, FileAccess.Write))
            {
                // Register an empty file.
                fileContentTable.RecordContentHash(fs, ContentHashingUtilities.EmptyHash);

                byte[] content = Encoding.UTF8.GetBytes("Some new content");
                await fs.WriteAsync(content, 0, content.Length);
            }

            FileContentTableExtensions.VersionedFileIdentityAndContentInfoWithOrigin result =
                await fileContentTable.GetAndRecordContentHashAsync(GetFullPath(FileA));

            XAssert.AreEqual(FileContentTableExtensions.ContentHashOrigin.NewlyHashed, result.Origin);
            XAssert.AreEqual(
                await ContentHashingUtilities.HashFileAsync(GetFullPath(FileA)),
                result.VersionedFileIdentityAndContentInfo.FileContentInfo.Hash);
        }
        public async Task CopyIfContentMismatchedAsyncWithAbsentDestination()
        {
            const string TargetContent = "Target!!!!!!!!!";

            var fileContentTable = FileContentTable.CreateNew();

            WriteFile(FileA, TargetContent);

            FileContentTableExtensions.VersionedFileIdentityAndContentInfoWithOrigin sourceInfo =
                await fileContentTable.GetAndRecordContentHashAsync(GetFullPath(FileA));

            XAssert.AreEqual(FileContentTableExtensions.ContentHashOrigin.NewlyHashed, sourceInfo.Origin);

            await
            VerifyCopyIfContentMismatchedAsync(
                fileContentTable,
                FileA,
                FileB,
                sourceInfo.VersionedFileIdentityAndContentInfo.FileContentInfo,
                expectedCopy : true);
        }
Example #15
0
        public void StrictModeFlushesDirtyMemoryMappedPages()
        {
            var table = FileContentTable.CreateNew();

            string testFileAExpandedPath = m_testFileA.ToString(m_pathTable);

            // Writing a file via a memory mapping leaves 'dirty' pages in cache that get lazily flushed to FS.
            // We want to verify that passing strict: true flushes those pages, so that the recorded USN is stable (not invalidated due to lazy flushes).
            using (FileStream file = FileUtilities.CreateFileStream(testFileAExpandedPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete | FileShare.Read))
            {
                file.SetLength(1024 * 1024);
                using (var memoryMappedFile = MemoryMappedFile.CreateFromFile(
                           file,
                           mapName: null,
                           capacity: 0,
                           access: MemoryMappedFileAccess.ReadWrite,
#if !DISABLE_FEATURE_MEMORYMAP_SECURITY
                           memoryMappedFileSecurity: null,
#endif
                           inheritability: HandleInheritability.None,
                           leaveOpen: false))
                {
                    using (var accessor = memoryMappedFile.CreateViewAccessor())
                    {
                        for (int i = 0; i < 1024 * 1024; i += 4)
                        {
                            accessor.Write(i, (int)0xAB);
                        }
                    }
                }

                RecordContentHash(table, m_testFileA, s_hashA, strict: true);
            }

            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(10);
                ExpectHashKnown(table, m_testFileA, s_hashA);
            }
        }
Example #16
0
 /// <summary>
 /// Creates a file content table.
 /// </summary>
 protected FileContentTable CreateFileContentTable()
 {
     return(FileContentTable.CreateNew(LoggingContext));
 }
Example #17
0
        private async Task ProcessWindowsCallHelper(
            string functionName,
            SandboxConfiguration config            = null,
            IEnumerable <string> extraDependencies = null,
            IEnumerable <string> extraOutputs      = null,
            int callCount                   = 1,
            string commandPrefix            = "",
            bool readsAndWritesDirectories  = false,
            bool untrackedOutputs           = false,
            string[] expectedWarningStrings = null,
            string[] expectedErrorStrings   = null)
        {
            if (config == null)
            {
                config = new SandboxConfiguration {
                    FileAccessIgnoreCodeCoverage = true, FailUnexpectedFileAccesses = true
                };
            }

            var context          = BuildXLContext.CreateInstanceForTesting();
            var pathTable        = context.PathTable;
            var fileContentTable = FileContentTable.CreateNew(LoggingContext);

            // have to force the config for truncation
            config.OutputReportingMode = OutputReportingMode.FullOutputOnWarningOrError;

            bool expectSuccess = expectedErrorStrings == null && expectedWarningStrings == null;

            using (var tempFiles = new TempFileStorage(canGetFileNames: true, rootPath: TemporaryDirectory))
            {
                string currentCodeFolder = Path.GetDirectoryName(AssemblyHelper.GetAssemblyLocation(Assembly.GetExecutingAssembly()));
                Contract.Assume(currentCodeFolder != null);

                string executable = Path.Combine(currentCodeFolder, DetourTestFolder, "DetoursTests.exe");

                string       workingDirectory             = tempFiles.GetUniqueDirectory();
                AbsolutePath workingDirectoryAbsolutePath = AbsolutePath.Create(pathTable, workingDirectory);

                XAssert.IsTrue(File.Exists(executable), "Could not find the test file: " + executable);
                FileArtifact executableFileArtifact = FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, executable));

                var extraUntrackedScopes = new List <AbsolutePath>();

                var dependencies = new List <FileArtifact> {
                    executableFileArtifact
                };
                if (extraDependencies != null)
                {
                    foreach (string file in extraDependencies)
                    {
                        string       filePath = Path.Combine(workingDirectory, file);
                        AbsolutePath path     = AbsolutePath.Create(pathTable, filePath);

                        if (readsAndWritesDirectories)
                        {
                            Directory.CreateDirectory(filePath);

                            // We don't support directories as inputs in BuildXL yet.
                            extraUntrackedScopes.Add(path);
                        }
                        else
                        {
                            File.WriteAllText(filePath, "Definitely a file");
                            FileArtifact fileArtifact = FileArtifact.CreateSourceFile(path);
                            dependencies.Add(fileArtifact);
                        }
                    }
                }

                var outputs = new List <FileArtifactWithAttributes>();
                if (extraOutputs != null)
                {
                    foreach (string file in extraOutputs)
                    {
                        string       filePath = Path.Combine(workingDirectory, file);
                        AbsolutePath path     = AbsolutePath.Create(pathTable, filePath);

                        if (readsAndWritesDirectories)
                        {
                            // We don't support directory outputs in BuildXL at the moment, so e.g. deleting a directory needs to be untracked.
                            extraUntrackedScopes.Add(path);
                        }
                        else if (untrackedOutputs)
                        {
                            extraUntrackedScopes.Add(path);
                        }
                        else
                        {
                            FileArtifact fileArtifact = FileArtifact.CreateSourceFile(path).CreateNextWrittenVersion();
                            outputs.Add(fileArtifact.WithAttributes());
                        }
                    }
                }

                var tempDirectory        = tempFiles.GetUniqueDirectory();
                var environmentVariables = new List <EnvironmentVariable>();
                var environmentValue     = new PipDataBuilder(pathTable.StringTable);
                var tempPath             = AbsolutePath.Create(pathTable, tempDirectory);
                environmentValue.Add(tempPath);
                environmentVariables.Add(new EnvironmentVariable(StringId.Create(pathTable.StringTable, "TMP"), environmentValue.ToPipData(" ", PipDataFragmentEscaping.NoEscaping)));
                environmentVariables.Add(new EnvironmentVariable(StringId.Create(pathTable.StringTable, "TEMP"), environmentValue.ToPipData(" ", PipDataFragmentEscaping.NoEscaping)));

                var untrackedPaths  = CmdHelper.GetCmdDependencies(pathTable);
                var untrackedScopes = extraUntrackedScopes.Concat(CmdHelper.GetCmdDependencyScopes(pathTable).Concat(new[] { tempPath })).Distinct();

                var pip = new Process(
                    executableFileArtifact,
                    workingDirectoryAbsolutePath,
                    PipDataBuilder.CreatePipData(pathTable.StringTable, " ", PipDataFragmentEscaping.NoEscaping, commandPrefix + functionName + "Logging"),
                    FileArtifact.Invalid,
                    PipData.Invalid,
                    ReadOnlyArray <EnvironmentVariable> .From(environmentVariables),
                    FileArtifact.Invalid,
                    FileArtifact.Invalid,
                    FileArtifact.Invalid,
                    tempFiles.GetUniqueDirectory(pathTable),
                    null,
                    null,
                    ReadOnlyArray <FileArtifact> .From(dependencies),
                    ReadOnlyArray <FileArtifactWithAttributes> .From(outputs),
                    ReadOnlyArray <DirectoryArtifact> .Empty,
                    ReadOnlyArray <DirectoryArtifact> .Empty,
                    ReadOnlyArray <PipId> .Empty,
                    ReadOnlyArray <AbsolutePath> .From(untrackedPaths),
                    ReadOnlyArray <AbsolutePath> .From(untrackedScopes),
                    ReadOnlyArray <StringId> .Empty,
                    ReadOnlyArray <int> .Empty,
                    ReadOnlyArray <ProcessSemaphoreInfo> .Empty,
                    provenance: PipProvenance.CreateDummy(context),
                    toolDescription: StringId.Invalid,
                    additionalTempDirectories: ReadOnlyArray <AbsolutePath> .Empty);

                if (expectSuccess)
                {
                    await AssertProcessSucceedsAsync(
                        context,
                        config,
                        pip);
                }
                else
                {
                    await AssertProcessCompletesWithStatusAsync(
                        SandboxedProcessPipExecutionStatus.ExecutionFailed,
                        context,
                        config,
                        pip,
                        null);
                }
            }

            int expectedErrorCount   = 0;
            int expectedWarningCount = 0;
            IEnumerable <string> requiredLogMessageSubstrings = new string[] { };

            if (expectedErrorStrings != null)
            {
                expectedErrorCount           = expectedErrorStrings.Count();
                requiredLogMessageSubstrings = requiredLogMessageSubstrings.Concat(expectedErrorStrings);
            }

            if (expectedWarningStrings != null)
            {
                expectedWarningCount         = expectedWarningStrings.Count();
                requiredLogMessageSubstrings = requiredLogMessageSubstrings.Concat(expectedWarningStrings);
            }

            SetExpectedFailures(expectedErrorCount, expectedWarningCount, requiredLogMessageSubstrings.ToArray());
        }
Example #18
0
        /// <summary>
        /// Creates an execution environment for a single pip. To run pips incrementally, the <paramref name="fileContentTable"/> and <paramref name="pipCache"/> should be specified.
        /// </summary>
        public DummyPipExecutionEnvironment(
            LoggingContext loggingContext,
            PipExecutionContext context,
            IConfiguration config,
            FileContentTable fileContentTable = null,
            EngineCache pipCache = null,
            SemanticPathExpander semanticPathExpander           = null,
            PipContentFingerprinter.PipDataLookup pipDataLookup = null,
            FileAccessWhitelist fileAccessWhitelist             = null,
            bool allowUnspecifiedSealedDirectories = false,
            PipTable pipTable        = null,
            IIpcProvider ipcProvider = null,
            IKextConnection sandboxedKextConnection = null)
        {
            Contract.Requires(context != null);
            Contract.Requires(config != null);

            LoggingContext = loggingContext;
            Context        = context;

            // Ensure paths visible when debugging
            PathTable.DebugPathTable = Context.PathTable;
            Configuration            = config;
            PipTable             = pipTable;
            PathExpander         = semanticPathExpander ?? SemanticPathExpander.Default;
            ContentFingerprinter = new PipContentFingerprinter(
                Context.PathTable,
                artifact => State.FileContentManager.GetInputContent(artifact).FileContentInfo,
                new ExtraFingerprintSalts(config, PipFingerprintingVersion.TwoPhaseV2, fingerprintSalt: null, searchPathToolsHash: null),
                pathExpander: PathExpander,
                pipDataLookup: pipDataLookup);
            PipFragmentRenderer = this.CreatePipFragmentRenderer();
            IpcProvider         = ipcProvider ?? IpcFactory.GetProvider();

            FileContentTable    = fileContentTable ?? FileContentTable.CreateNew();
            Cache               = pipCache;
            FileAccessWhitelist = fileAccessWhitelist;
            m_allowUnspecifiedSealedDirectories = allowUnspecifiedSealedDirectories;
            m_sandboxedKextConnection           = sandboxedKextConnection;

            if (Cache == null)
            {
                Cache = InMemoryCacheFactory.Create(context);
            }

            var tracker = FileChangeTracker.CreateDisabledTracker(LoggingContext);

            LocalDiskContentStore = new LocalDiskContentStore(loggingContext, context.PathTable, FileContentTable, tracker);
            PipGraphView          = new TestPipGraphFilesystemView(Context.PathTable);
            m_operationTracker    = new OperationTracker(loggingContext);

            var fileSystemView = new FileSystemView(Context.PathTable, PipGraphView, LocalDiskContentStore);

            var preserveOutputsSalt = UnsafeOptions.PreserveOutputsNotUsed;

            if (config.Sandbox.UnsafeSandboxConfiguration.PreserveOutputs != PreserveOutputsMode.Disabled)
            {
                preserveOutputsSalt = ContentHashingUtilities.HashString(Guid.NewGuid().ToString());
            }

            State = new PipExecutionState(
                config,
                cache: new PipTwoPhaseCache(loggingContext, Cache, context, PathExpander),
                fileAccessWhitelist: FileAccessWhitelist,
                directoryMembershipFingerprinter: this,
                pathExpander: PathExpander,
                executionLog: ExecutionLogRecorder,
                fileSystemView: fileSystemView,
                fileContentManager: GetFileContentManager(),
                directoryMembershipFinterprinterRuleSet: null,
                unsafeConfiguration: config.Sandbox.UnsafeSandboxConfiguration,
                preserveOutputsSalt: preserveOutputsSalt,
                serviceManager: new DummyServiceManager());

            m_sealContentsById = new ConcurrentBigMap <DirectoryArtifact, int[]>();

            ProcessInContainerManager = new ProcessInContainerManager(LoggingContext, context.PathTable);
        }
Example #19
0
        /// <summary>
        /// Creates a file content table.
        /// </summary>
        protected FileContentTable CreateFileContentTable()
        {
            Contract.Ensures(Contract.Result <FileContentTable>() != null);

            return(FileContentTable.CreateNew(LoggingContext));
        }
Example #20
0
        private static async Task <bool> CreateAndRunPip(
            PipProgram program,
            string tempDirectory,
            string outFile,
            IEnumerable <string> restInstructions,
            bool is64Bit)
        {
            Contract.Requires(restInstructions != null);
            Contract.Requires(tempDirectory != null);
            Contract.Requires(!string.IsNullOrEmpty(outFile));

            BuildXLContext context = BuildXLContext.CreateInstanceForTesting();

            using (var fileAccessListener = new FileAccessListener(Events.Log))
            {
                fileAccessListener.RegisterEventSource(BuildXL.Processes.ETWLogger.Log);

                var loggingContext   = BuildXLTestBase.CreateLoggingContextForTest();
                var fileContentTable = FileContentTable.CreateNew(loggingContext);
                var config           = ConfigurationHelpers.GetDefaultForTesting(context.PathTable, AbsolutePath.Create(context.PathTable, Path.Combine(tempDirectory, "config.dc")));
                config.Sandbox.LogObservedFileAccesses = true;

                Pip pip = null;

                var instructions = restInstructions as string[] ?? restInstructions.ToArray();

                switch (program)
                {
                case PipProgram.Cmd:
                    pip = CreateCmdPip(context, tempDirectory, outFile, is64Bit);
                    break;

                case PipProgram.Self:
                    pip = CreateSelfPip(context, tempDirectory, outFile, instructions, is64Bit);
                    break;
                }

                Contract.Assume(pip != null);

                var isSubstUsed = FileUtilities.TryGetSubstSourceAndTarget(tempDirectory, out var substSource, out var substTarget, out var errorMessage);
                XAssert.IsFalse(!isSubstUsed && errorMessage != null, errorMessage);

                PipResult executeResult = await Execute(
                    context,
                    fileContentTable,
                    config,
                    pip,
                    isSubstUsed
                    ?(substSource, substTarget)
                    : default((string, string)?));

                bool valid = false;

                switch (program)
                {
                case PipProgram.Cmd:
                    valid = ValidateCmd(fileAccessListener.FileAccesses, outFile, is64Bit);
                    break;

                case PipProgram.Self:
                    valid = ValidateSelf(
                        fileAccessListener.FileAccesses,
                        instructions.Length > 0 ? instructions[0] : string.Empty,
                        outFile,
                        is64Bit);
                    break;
                }

                return(executeResult.Status == PipResultStatus.Succeeded && valid);
            }
        }
Example #21
0
        public async Task ParallelRecordForHardlinksRemembersHash()
        {
            if (!FileUtilities.IsPreciseFileVersionSupportedByEnlistmentVolume)
            {
                // TODO: Currently fails on OS that does not support precise file version.
                return;
            }

            var table = FileContentTable.CreateNew(LoggingContext);

            const int    ThreadCount    = 16;
            const int    IterationCount = 20;
            const string OriginalFile   = "Original";

            WriteFile(OriginalFile, "Data");

            CreateHardLinkStatus testLinkStatus = FileUtilities.TryCreateHardLink(GetFullPath("TestLink"), GetFullPath(OriginalFile));

            if (testLinkStatus == CreateHardLinkStatus.FailedSinceNotSupportedByFilesystem)
            {
                return;
            }

            XAssert.AreEqual(CreateHardLinkStatus.Success, testLinkStatus);

            var linkTasks = new Task[ThreadCount];
            var barrier   = new Barrier(ThreadCount);

            for (int j = 0; j < IterationCount; j++)
            {
                for (int i = 0; i < ThreadCount; i++)
                {
                    int threadId = i;
                    linkTasks[threadId] = Task.Run(
                        () =>
                    {
                        string relativePath = "Link-" + threadId;
                        AbsolutePath path   = GetFullPath(m_pathTable, relativePath);

                        barrier.SignalAndWait();

                        FileUtilities.DeleteFile(GetFullPath(relativePath));
                        CreateHardLinkStatus linkStatus = FileUtilities.TryCreateHardLink(GetFullPath(relativePath), GetFullPath(OriginalFile));
#if PLATFORM_OSX
                        // Catalina seems to have issues when doing mutli-threaded delete / link operations, let's retry several times..
                        if (linkStatus != CreateHardLinkStatus.Success)
                        {
                            var count = 0;
                            while (count < ThreadCount)
                            {
                                FileUtilities.DeleteFile(GetFullPath(relativePath));
                                linkStatus = FileUtilities.TryCreateHardLink(GetFullPath(relativePath), GetFullPath(OriginalFile));
                                count++;
                            }
                        }
#endif
                        XAssert.AreEqual(CreateHardLinkStatus.Success, linkStatus);
                        RecordContentHash(table, path, s_hashA);
                    });
                }

                await Task.WhenAll(linkTasks);

                ExpectHashKnown(table, GetFullPath(m_pathTable, OriginalFile), s_hashA);
            }
        }