public async Task CheckProcessTreeTimoutOnNestedChildProcessTimeoutWhenRootProcessExitedAsync() { var processInfo = CreateProcessInfoWithKextConnection(Operation.Echo("hi")); processInfo.NestedProcessTerminationTimeout = TimeSpan.FromMilliseconds(100); // Set the last enqueue time to now s_connection.MinReportQueueEnqueueTime = Sandbox.GetMachAbsoluteTime(); var process = CreateAndStartSandboxedProcess(processInfo); var taskCancelationSource = new CancellationTokenSource(); var time = Sandbox.GetMachAbsoluteTime(); var childProcessPath = "/dummy/exe2"; var instructions = new List <ReportInstruction>() { new ReportInstruction() { Process = process, Operation = FileOperation.OpProcessStart, Stats = new Sandbox.AccessReportStatistics() { EnqueueTime = time + ((ulong)TimeSpan.FromSeconds(1).Ticks * 100), DequeueTime = time + ((ulong)TimeSpan.FromSeconds(2).Ticks * 100), }, Pid = 1235, Path = childProcessPath, Allowed = true }, new ReportInstruction() { Process = process, Operation = FileOperation.OpProcessExit, Stats = new Sandbox.AccessReportStatistics() { EnqueueTime = time + ((ulong)TimeSpan.FromSeconds(3).Ticks * 100), DequeueTime = time + ((ulong)TimeSpan.FromSeconds(4).Ticks * 100), }, Pid = process.ProcessId, Path = "/dummy/exe", Allowed = true }, new ReportInstruction() { Process = process, Operation = FileOperation.OpKAuthCreateDir, Stats = new Sandbox.AccessReportStatistics() { EnqueueTime = time + ((ulong)TimeSpan.FromSeconds(5).Ticks * 100), DequeueTime = time + ((ulong)TimeSpan.FromSeconds(6).Ticks * 100), }, Pid = 1235, Path = childProcessPath, Allowed = true }, }; ContinouslyPostAccessReports(process, taskCancelationSource.Token, instructions); var result = await process.GetResultAsync(); taskCancelationSource.Cancel(); XAssert.IsTrue(result.Killed, "Expected process to have been killed"); XAssert.IsFalse(result.TimedOut, "Didn't expect process to have timed out"); XAssert.IsNotNull(result.SurvivingChildProcesses, "Expected surviving child processes"); XAssert.IsTrue(result.SurvivingChildProcesses.Any(p => p.Path == childProcessPath), $"Expected surviving child processes to contain {childProcessPath}; " + $"instead it contains: {string.Join(", ", result.SurvivingChildProcesses.Select(p => p.Path))}"); }
public async Task Stress() { const int N = 5; const int M = N * N; var context = BuildXLContext.CreateInstanceForTesting(); var loggingContext = CreateLoggingContextForTest(); var pathTable = context.PathTable; using (var tempFiles = new TempFileStorage(canGetFileNames: true)) { var config = ConfigHelpers.CreateDefault(pathTable, tempFiles.GetUniqueFileName(), tempFiles); using (var pipTable = new PipTable( context.PathTable, context.SymbolTable, initialBufferSize: 1024, maxDegreeOfParallelism: (Environment.ProcessorCount + 2) / 3, debug: false)) { var executionEnvironment = new PipQueueTestExecutionEnvironment(context, config, pipTable, GetSandboxedKextConnection()); Func <RunnablePip, Task <PipResult> > taskFactory = async(runnablePip) => { PipResult result; var operationTracker = new OperationTracker(runnablePip.LoggingContext); var pip = runnablePip.Pip; using (var operationContext = operationTracker.StartOperation(PipExecutorCounter.PipRunningStateDuration, pip.PipId, pip.PipType, runnablePip.LoggingContext)) { result = await TestPipExecutor.ExecuteAsync(operationContext, executionEnvironment, pip); } executionEnvironment.MarkExecuted(pip); return(result); }; string executable = CmdHelper.OsShellExe; FileArtifact executableArtifact = FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, executable)); // This is the only file artifact we reference without a producer. Rather than scheduling a hashing pip, let's just invent one (so fingerprinting can succeed). executionEnvironment.AddWellKnownFile(executableArtifact, WellKnownContentHashes.UntrackedFile); using (var phase1PipQueue = new PipQueue(executionEnvironment.Configuration.Schedule)) { // phase 1: create some files var baseFileArtifacts = new List <FileArtifact>(); for (int i = 0; i < N; i++) { string destination = tempFiles.GetUniqueFileName(); AbsolutePath destinationAbsolutePath = AbsolutePath.Create(pathTable, destination); FileArtifact destinationArtifact = FileArtifact.CreateSourceFile(destinationAbsolutePath).CreateNextWrittenVersion(); baseFileArtifacts.Add(destinationArtifact); PipData contents = PipDataBuilder.CreatePipData( context.StringTable, " ", PipDataFragmentEscaping.CRuntimeArgumentRules, i.ToString(CultureInfo.InvariantCulture)); var writeFile = new WriteFile(destinationArtifact, contents, WriteFileEncoding.Utf8, ReadOnlyArray <StringId> .Empty, PipProvenance.CreateDummy(context)); var pipId = pipTable.Add((uint)(i + 1), writeFile); var contentHash = ContentHashingUtilities.HashString(contents.ToString(pathTable)); executionEnvironment.AddExpectedWrite(writeFile, destinationArtifact, contentHash); var runnable = RunnablePip.Create(loggingContext, executionEnvironment, pipId, pipTable.GetPipType(pipId), 0, taskFactory, 0); runnable.Start(new OperationTracker(loggingContext), loggingContext); runnable.SetDispatcherKind(DispatcherKind.IO); phase1PipQueue.Enqueue(runnable); } phase1PipQueue.SetAsFinalized(); phase1PipQueue.DrainQueues(); await Task.WhenAll( Enumerable.Range(0, 2).Select( async range => { using (var phase2PipQueue = new PipQueue(executionEnvironment.Configuration.Schedule)) { // phase 2: do some more with those files var pips = new ConcurrentDictionary <PipId, Tuple <string, int> >(); var checkerTasks = new ConcurrentQueue <Task>(); Action <PipId, Task <PipResult> > callback = (id, task) => { XAssert.IsTrue(task.Status == TaskStatus.RanToCompletion); XAssert.IsFalse(task.Result.Status.IndicatesFailure()); Tuple <string, int> t; if (!pips.TryRemove(id, out t)) { XAssert.Fail(); } checkerTasks.Enqueue( Task.Run( () => { string actual = File.ReadAllText(t.Item1).Trim(); // TODO: Make this async XAssert.AreEqual(actual, t.Item2.ToString()); })); }; var r = new Random(0); for (int i = 0; i < M; i++) { int sourceIndex = r.Next(baseFileArtifacts.Count); FileArtifact sourceArtifact = baseFileArtifacts[sourceIndex]; string destination = tempFiles.GetUniqueFileName(); AbsolutePath destinationAbsolutePath = AbsolutePath.Create(pathTable, destination); FileArtifact destinationArtifact = FileArtifact.CreateSourceFile(destinationAbsolutePath).CreateNextWrittenVersion(); Pip pip; DispatcherKind queueKind; switch (r.Next(2)) { case 0: pip = new CopyFile(sourceArtifact, destinationArtifact, ReadOnlyArray <StringId> .Empty, PipProvenance.CreateDummy(context)); queueKind = DispatcherKind.IO; executionEnvironment.AddExpectedWrite(pip, destinationArtifact, executionEnvironment.GetExpectedContent(sourceArtifact)); break; case 1: string workingDirectory = OperatingSystemHelper.IsUnixOS ? "/tmp" : Environment.GetFolderPath(Environment.SpecialFolder.Windows); AbsolutePath workingDirectoryAbsolutePath = AbsolutePath.Create(pathTable, workingDirectory); var pipData = OperatingSystemHelper.IsUnixOS ? PipDataBuilder.CreatePipData(pathTable.StringTable, " ", PipDataFragmentEscaping.CRuntimeArgumentRules, "-c", "'", "cp", sourceArtifact, destinationArtifact, "'") : PipDataBuilder.CreatePipData(pathTable.StringTable, " ", PipDataFragmentEscaping.CRuntimeArgumentRules, "/d", "/c", "copy", "/B", sourceArtifact, destinationArtifact); queueKind = DispatcherKind.CPU; pip = new Process( executableArtifact, workingDirectoryAbsolutePath, pipData, FileArtifact.Invalid, PipData.Invalid, ReadOnlyArray <EnvironmentVariable> .Empty, FileArtifact.Invalid, FileArtifact.Invalid, FileArtifact.Invalid, tempFiles.GetUniqueDirectory(pathTable), null, null, ReadOnlyArray <FileArtifact> .FromWithoutCopy(executableArtifact, sourceArtifact), ReadOnlyArray <FileArtifactWithAttributes> .FromWithoutCopy(destinationArtifact.WithAttributes()), ReadOnlyArray <DirectoryArtifact> .Empty, ReadOnlyArray <DirectoryArtifact> .Empty, ReadOnlyArray <PipId> .Empty, ReadOnlyArray <AbsolutePath> .From(CmdHelper.GetCmdDependencies(pathTable)), ReadOnlyArray <AbsolutePath> .From(CmdHelper.GetCmdDependencyScopes(pathTable)), ReadOnlyArray <StringId> .Empty, ReadOnlyArray <int> .Empty, ReadOnlyArray <ProcessSemaphoreInfo> .Empty, provenance: PipProvenance.CreateDummy(context), toolDescription: StringId.Invalid, additionalTempDirectories: ReadOnlyArray <AbsolutePath> .Empty); executionEnvironment.AddExpectedWrite(pip, destinationArtifact, executionEnvironment.GetExpectedContent(sourceArtifact)); break; default: Contract.Assert(false); continue; } var pipId = pipTable.Add((uint)((range *M) + N + i + 1), pip); Func <RunnablePip, Task> taskFactoryWithCallback = async(runnablePip) => { var task = taskFactory(runnablePip); var pipResult = await task; callback(pipId, task); }; var runnable = RunnablePip.Create(loggingContext, executionEnvironment, pipId, pipTable.GetPipType(pipId), 0, taskFactoryWithCallback, 0); runnable.Start(new OperationTracker(loggingContext), loggingContext); runnable.SetDispatcherKind(queueKind); phase2PipQueue.Enqueue(runnable); if (!pips.TryAdd(pipId, Tuple.Create(destination, sourceIndex))) { Contract.Assert(false); } } phase2PipQueue.SetAsFinalized(); phase2PipQueue.DrainQueues(); XAssert.AreEqual(0, pips.Count); await Task.WhenAll(checkerTasks); } })); } } } }
public async Task CheckProcessTreeTimoutOnNestedChildProcessTimeoutWhenRootProcessExitedAsync() { var processInfo = CreateProcessInfoWithSandboxConnection(Operation.Echo("hi")); processInfo.NestedProcessTerminationTimeout = TimeSpan.FromMilliseconds(10); // Set the last enqueue time to now s_connection.MinReportQueueEnqueueTime = Sandbox.GetMachAbsoluteTime(); using (var process = CreateAndStartSandboxedProcess(processInfo)) { var time = s_connection.MinReportQueueEnqueueTime; var childProcessPath = "/dummy/exe2"; var childProcessPid = process.ProcessId + 1; // first post some reports indicating that // - a child process was spawned // - the main process exited // (not posting that the child process exited) var postTask1 = GetContinuouslyPostAccessReportsTask(process, new List <ReportInstruction> { new ReportInstruction() { Process = process, Operation = FileOperation.OpProcessStart, Stats = new Sandbox.AccessReportStatistics() { EnqueueTime = time + ((ulong)TimeSpan.FromMilliseconds(100).Ticks * 100), DequeueTime = time + ((ulong)TimeSpan.FromMilliseconds(200).Ticks * 100), }, Pid = childProcessPid, Path = childProcessPath, Allowed = true }, new ReportInstruction() { Process = process, Operation = FileOperation.OpProcessExit, Stats = new Sandbox.AccessReportStatistics() { EnqueueTime = time + ((ulong)TimeSpan.FromMilliseconds(300).Ticks * 100), DequeueTime = time + ((ulong)TimeSpan.FromMilliseconds(400).Ticks * 100), }, Pid = process.ProcessId, Path = "/dummy/exe", Allowed = true }, new ReportInstruction() { Process = process, Operation = FileOperation.OpKAuthCreateDir, Stats = new Sandbox.AccessReportStatistics() { EnqueueTime = time + ((ulong)TimeSpan.FromMilliseconds(500).Ticks * 100), DequeueTime = time + ((ulong)TimeSpan.FromMilliseconds(600).Ticks * 100), }, Pid = childProcessPid, Path = childProcessPath, Allowed = true }, }); // SandboxedProcessMac should decide to kill the process because its child survived; // when it does that, it will call this callback. When that happens, we must post // OpProcessTreeCompleted because SandboxedProcessMac will keep waiting for it. s_connection.ProcessTerminated += (pipId, pid) => { postTask1.GetAwaiter().GetResult(); ContinuouslyPostAccessReports(process, new List <ReportInstruction> { new ReportInstruction() { Process = process, Operation = FileOperation.OpProcessTreeCompleted, Stats = new Sandbox.AccessReportStatistics() { EnqueueTime = time + ((ulong)TimeSpan.FromMilliseconds(900).Ticks * 100), DequeueTime = time + ((ulong)TimeSpan.FromMilliseconds(1000).Ticks * 100), }, Pid = process.ProcessId, Path = "/dummy/exe", Allowed = true } }); }; var result = await process.GetResultAsync(); await postTask1; // await here as well just to make AsyncFixer happy XAssert.IsTrue(result.Killed, "Expected process to have been killed"); XAssert.IsFalse(result.TimedOut, "Didn't expect process to have timed out"); XAssert.IsNotNull(result.SurvivingChildProcesses, "Expected surviving child processes"); XAssert.IsTrue(result.SurvivingChildProcesses.Any(p => p.Path == childProcessPath), $"Expected surviving child processes to contain {childProcessPath}; " + $"instead it contains: {string.Join(", ", result.SurvivingChildProcesses.Select(p => p.Path))}"); } }
private void AssertDirectoryEmpty(string directoryPath) { DirectoryInfo di = new DirectoryInfo(directoryPath); XAssert.IsFalse(di.EnumerateFileSystemInfos().Any(), "Directory was not cleaned"); }
public void TryCreate() { var pt = new PathTable(); AbsolutePath p; XAssert.IsTrue(AbsolutePath.TryCreate(pt, @"C:\AAA\CCC", out p)); XAssert.AreEqual(@"C:\AAA\CCC", p.ToString(pt)); XAssert.IsTrue(AbsolutePath.TryCreate(pt, @"C:\..", out p)); XAssert.AreEqual(@"C:\", p.ToString(pt)); XAssert.IsTrue(AbsolutePath.TryCreate(pt, @"C:\..\..\..\..", out p)); XAssert.AreEqual(@"C:\", p.ToString(pt)); XAssert.IsTrue(AbsolutePath.TryCreate(pt, @"C:\a\..\b.txt", out p)); XAssert.AreEqual(@"C:\b.txt", p.ToString(pt)); XAssert.IsTrue(AbsolutePath.TryCreate(pt, @"C:\a\..\..\..\..\b.txt", out p)); XAssert.AreEqual(@"C:\b.txt", p.ToString(pt)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @"C\::AAA", out p)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @"AAA:", out p)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @":AAA", out p)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @"..", out p)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @".", out p)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @"C:\:", out p)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @"1:\", out p)); p = AbsolutePath.Create(pt, @"C:/"); XAssert.AreEqual(@"C:\", p.ToString(pt)); p = AbsolutePath.Create(pt, @"C:\"); XAssert.AreEqual(@"C:\", p.ToString(pt)); p = AbsolutePath.Create(pt, @"C:\."); XAssert.AreEqual(@"C:\", p.ToString(pt)); p = AbsolutePath.Create(pt, @"C:\BBB"); XAssert.AreEqual(@"C:\BBB", p.ToString(pt)); p = AbsolutePath.Create(pt, @"C:\BBB\."); XAssert.AreEqual(@"C:\BBB", p.ToString(pt)); p = AbsolutePath.Create(pt, @"C:\BBB\.."); XAssert.AreEqual(@"C:\", p.ToString(pt)); p = AbsolutePath.Create(pt, @"C:\BBB\CCC\.."); XAssert.AreEqual(@"C:\BBB", p.ToString(pt)); // now test out UNC paths XAssert.IsTrue(AbsolutePath.TryCreate(pt, @"\\srv\AAA\CCC", out p)); XAssert.AreEqual(@"\\srv\AAA\CCC", p.ToString(pt)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @"\\srv\..", out p)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @"\\srv\..\..", out p)); XAssert.IsFalse(AbsolutePath.TryCreate(pt, @"\\srv\:", out p)); p = AbsolutePath.Create(pt, @"\\srv\"); XAssert.AreEqual(@"\\srv", p.ToString(pt)); p = AbsolutePath.Create(pt, @"\\srv\."); XAssert.AreEqual(@"\\srv", p.ToString(pt)); p = AbsolutePath.Create(pt, @"\\srv\BBB"); XAssert.AreEqual(@"\\srv\BBB", p.ToString(pt)); p = AbsolutePath.Create(pt, @"\\srv\BBB\."); XAssert.AreEqual(@"\\srv\BBB", p.ToString(pt)); p = AbsolutePath.Create(pt, @"\\srv\BBB\.."); XAssert.AreEqual(@"\\srv", p.ToString(pt)); p = AbsolutePath.Create(pt, @"\\srv\BBB\CCC\.."); XAssert.AreEqual(@"\\srv\BBB", p.ToString(pt)); }
public void MissAugmentedWeakFingerprintIsClassifiedAsPathSetMissButAlwaysPostCacheExecution() { Configuration.Cache.AugmentWeakFingerprintPathSetThreshold = 2; var directory = CreateUniqueDirectoryArtifact(); var sourceFile = CreateSourceFile(directory.Path); var readFileA = CreateSourceFile(directory.Path); var readFileB = CreateSourceFile(directory.Path); var readFileC = CreateSourceFile(directory.Path); var readFileD = CreateSourceFile(directory.Path); var sealedDirectory = CreateAndScheduleSealDirectoryArtifact( directory.Path, global::BuildXL.Pips.Operations.SealDirectoryKind.SourceAllDirectories); var builder = CreatePipBuilder(new[] { Operation.ReadFileFromOtherFile(sourceFile, doNotInfer: true), Operation.WriteFile(CreateOutputFileArtifact()) }); builder.AddInputDirectory(sealedDirectory); var process = SchedulePipBuilder(builder).Process; // Pip will read file source and file A. // Two-phase cache will contain mapping // wp => (#{source, A}, sp1) File.WriteAllText(ArtifactToString(sourceFile), ArtifactToString(readFileA)); RunScheduler().AssertCacheMiss(process.PipId); // Pip will read file source and file B. // Two-phase cache will contain mapping // wp => (#{source, B}, sp2), (#{source, A}, sp1) File.WriteAllText(ArtifactToString(sourceFile), ArtifactToString(readFileB)); RunScheduler().AssertCacheMiss(process.PipId); // Pip will read file source and file C. // Two-phase cache will contain mappings // wp => (#{source}, aug_marker), (#{source, B}, sp2), (#{source, A}, sp1) // aug_wp1 => (#{source, C}, sp3) // // Fingerprint store contains mapping // pip => (wp, #{source, C}, sp3) File.WriteAllText(ArtifactToString(sourceFile), ArtifactToString(readFileC)); var result = RunScheduler().AssertCacheMiss(process.PipId); // Modify source to point to file D. File.WriteAllText(ArtifactToString(sourceFile), ArtifactToString(readFileD)); RunScheduler(m_testHooks).AssertCacheMiss(process.PipId); XAssert.IsTrue(m_testHooks.FingerprintStoreTestHooks.TryGetCacheMiss(process.PipId, out var cacheMiss)); XAssert.AreEqual(CacheMissAnalysisResult.PathSetHashMismatch, cacheMiss.DetailAndResult.Result); // Cache miss analysis wasn't performed post cache look-up because at that time // fingerprint store has "pip => (wp, #{source, C}, sp3)" mapping, and none of // the strong fingerprint computation data has #{source, C} as pathset hash. // Note that the list of strong fingerprint computation data won't include #{source, C} // form aug_wp1 mapping because of miss augmented weak fingerprint. XAssert.IsFalse(cacheMiss.IsFromCacheLookUp); }
public void ReportedFileAccessCreate() { var pathTable = new PathTable(); AbsolutePath file1 = AbsolutePath.Create(pathTable, A("t", "file1.txt")); var process = new ReportedProcess(0, string.Empty); ReportedFileAccess rfa1 = ReportedFileAccess.Create( ReportedFileOperation.CreateFile, process, RequestedAccess.Read, FileAccessStatus.Allowed, true, 0, ReportedFileAccess.NoUsn, DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_NONE, CreationDisposition.OPEN_ALWAYS, FlagsAndAttributes.FILE_ATTRIBUTE_NORMAL, file1); XAssert.AreEqual(rfa1.Status, FileAccessStatus.Allowed); XAssert.AreEqual(rfa1.ManifestPath, file1); XAssert.AreEqual(rfa1.Path, null); XAssert.AreEqual(A("t", "file1.txt"), rfa1.GetPath(pathTable)); XAssert.AreEqual(rfa1.OpenedFileOrDirectoryAttributes, (FlagsAndAttributes)FlagsAndAttributesConstants.InvalidFileAttributes); XAssert.IsFalse(rfa1.IsOpenedHandleDirectory()); ReportedFileAccess rfa2 = ReportedFileAccess.Create( ReportedFileOperation.CreateFile, process, RequestedAccess.Read, FileAccessStatus.CannotDeterminePolicy, true, 0, new Usn(0), DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_NONE, CreationDisposition.OPEN_ALWAYS, FlagsAndAttributes.FILE_ATTRIBUTE_NORMAL, FlagsAndAttributes.FILE_ATTRIBUTE_DIRECTORY, pathTable, A("t", "file1.txt")); XAssert.AreEqual(rfa2.Status, FileAccessStatus.CannotDeterminePolicy); XAssert.AreEqual(rfa2.ManifestPath, file1); XAssert.AreEqual(rfa2.Path, null); XAssert.AreEqual(A("t", "file1.txt"), rfa2.GetPath(pathTable)); XAssert.AreEqual(rfa2.OpenedFileOrDirectoryAttributes, FlagsAndAttributes.FILE_ATTRIBUTE_DIRECTORY); XAssert.IsTrue(rfa2.IsOpenedHandleDirectory()); ReportedFileAccess rfa3 = ReportedFileAccess.Create( ReportedFileOperation.CreateFile, process, RequestedAccess.Read, FileAccessStatus.Denied, true, 0, ReportedFileAccess.NoUsn, DesiredAccess.GENERIC_READ, ShareMode.FILE_SHARE_NONE, CreationDisposition.OPEN_ALWAYS, FlagsAndAttributes.FILE_ATTRIBUTE_NORMAL, FlagsAndAttributes.FILE_ATTRIBUTE_NORMAL, pathTable, A("t", "file2.txt")); XAssert.AreEqual(rfa3.Status, FileAccessStatus.Denied); XAssert.AreEqual(rfa3.ManifestPath, AbsolutePath.Invalid); XAssert.AreEqual(rfa3.Path, A("t", "file2.txt")); XAssert.AreEqual(A("t", "file2.txt"), rfa3.GetPath(pathTable)); XAssert.AreEqual(rfa3.OpenedFileOrDirectoryAttributes, FlagsAndAttributes.FILE_ATTRIBUTE_NORMAL); XAssert.IsFalse(rfa3.IsOpenedHandleDirectory()); }
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); } }
public void ChildProcessCanBreakawayWhenConfigured(bool letInfiniteWaiterSurvive) { // Skip this test if running on .NET Framework with vstest // Reason: when this is the case and code coverage is turned on, launching breakaway // processes here causes the code coverage monitoring process to hang. if (!OperatingSystemHelper.IsDotNetCore && IsRunningInVsTestTestHost()) { return; } // We use InfiniteWaiter (a process that waits forever) as a long-living process that we can actually check it can // escape the job object var fam = new FileAccessManifest( Context.PathTable, childProcessesToBreakawayFromSandbox: letInfiniteWaiterSurvive ? new[] { InfiniteWaiterToolName } : null) { FailUnexpectedFileAccesses = false }; // We instruct the regular test process to spawn InfiniteWaiter as a child var info = ToProcessInfo( ToProcess( Operation.SpawnExe( Context.PathTable, CreateFileArtifactWithName(InfiniteWaiterToolName, TestDeploymentDir))), fileAccessManifest: fam); // Let's shorten the default time to wait for nested processes, since we are spawning // a process that never ends and we don't want this test to wait for that long info.NestedProcessTerminationTimeout = TimeSpan.FromMilliseconds(10); var result = RunProcess(info).GetAwaiter().GetResult(); XAssert.AreEqual(0, result.ExitCode); if (!letInfiniteWaiterSurvive) { // If we didn't let infinite waiter escape, we should have killed it when the job object was finalized XAssert.IsTrue(result.Killed); XAssert.Contains( result.SurvivingChildProcesses.Select(p => p?.Path).Where(p => p != null).Select(p => System.IO.Path.GetFileName(p).ToUpperInvariant()), InfiniteWaiterToolName.ToUpperInvariant()); } else { // If we did let it escape, then nothing should have been killed (nor tried to survive and later killed, from the job object point of view) XAssert.IsFalse(result.Killed); if (result.SurvivingChildProcesses != null && result.SurvivingChildProcesses.Any()) { var survivors = string.Join( ", ", result.SurvivingChildProcesses.Select(p => p?.Path != null ? System.IO.Path.GetFileName(p.Path) : "<unknown>")); XAssert.Fail($"Unexpected {result.SurvivingChildProcesses.Count()} surviving child processes: {survivors}"); } // Let's retrieve the child process and confirm it survived var infiniteWaiterInfo = RetrieveChildProcessesCreatedBySpawnExe(result).Single(); // The fact that this does not throw confirms survival var dummyWaiter = Process.GetProcessById(infiniteWaiterInfo.pid); // Just being protective, let's make sure we are talking about the same process XAssert.AreEqual(infiniteWaiterInfo.processName, dummyWaiter.ProcessName); // Now let's kill the surviving process, since we don't want it to linger around unnecessarily dummyWaiter.Kill(); } }
private static void AssertCannotScheduleSealPartialDirectory(TestEnv env, AbsolutePath path, params FileArtifact[] contents) { bool result = TryScheduleSealDirectory(env, path, SealDirectoryKind.Partial, contents: contents, outputDirectoryContents: CollectionUtilities.EmptyArray <DirectoryArtifact>(), out _); XAssert.IsFalse(result, "Unexpectedly succedeeded at sealing a partial directory at " + env.Paths.Expand(path)); }
public void IsValid() { AbsolutePath path = AbsolutePath.Invalid; XAssert.IsFalse(path.IsValid); }
public void LazyWriteFileMaterializationCopyTest() { var sourceFile = CreateSourceFile(); WriteSourceFile(sourceFile); // Graph: // W <- C <- C <- P var writeFileOutputContent = "WriteFileOutput"; var lazyWriteFileOutputToBeCopied = WriteFile(CreateOutputFileArtifact(), writeFileOutputContent); var lazyCopyWriteFileOutput = CopyFile(lazyWriteFileOutputToBeCopied, CreateOutputFileArtifact(), tags: new[] { "copy1" }); var lazyCopyWriteFileOutput2 = CopyFile(lazyCopyWriteFileOutput, CreateOutputFileArtifact(), tags: new[] { "copy2" }); // ...........PIP A........... var builderA = CreatePipBuilder(new Operation[] { Operation.ReadFile(lazyCopyWriteFileOutput2), Operation.ReadFile(sourceFile), Operation.WriteFile(CreateOutputFileArtifact()) }); builderA.AddTags(Context.StringTable, "pipA"); var pipA = SchedulePipBuilder(builderA); //// ...........Setting Modes........... Configuration.Schedule.EnableLazyOutputMaterialization = true; Configuration.Schedule.EnableLazyWriteFileMaterialization = true; // run scheduler and assert cache miss RunScheduler().AssertCacheMiss(pipA.Process.PipId);// nothing in cache // Exist since pipA must run and the write file output is an input XAssert.IsTrue(Exists(lazyCopyWriteFileOutput2)); // Now just run against pip A // those pips exist in cache and then there is no reason to run // those pips (in this case pipA) Configuration.Filter = "tag='pipA'"; // Delete these files on disk Delete(lazyWriteFileOutputToBeCopied); Delete(lazyCopyWriteFileOutput); Delete(lazyCopyWriteFileOutput2); // Run scheduler but grab artificats from cache (should be there from last run)... RunScheduler().AssertCacheHit(pipA.Process.PipId); // Does not exist since pipA had cache hit and since lazy materialization // is on there is not need to materialize the artifacts from the write file pip XAssert.IsFalse(Exists(lazyWriteFileOutputToBeCopied)); XAssert.IsFalse(Exists(lazyCopyWriteFileOutput)); XAssert.IsFalse(Exists(lazyCopyWriteFileOutput2)); // Clear the cache so no outputs can be retrieved from cache ClearArtifactCache(); // Delete these files on disk Delete(lazyWriteFileOutputToBeCopied); Delete(lazyCopyWriteFileOutput); Delete(lazyCopyWriteFileOutput2); // Write source file to force cache miss WriteSourceFile(sourceFile); // run scheduler and assert cache hit RunScheduler().AssertCacheMiss(pipA.Process.PipId); // Write file output should exist (needed to materialize copy file) XAssert.IsTrue(Exists(lazyWriteFileOutputToBeCopied)); // Intermediate copy should not exist XAssert.IsFalse(Exists(lazyCopyWriteFileOutput)); // Final copy should exist on disk since its required by pipA XAssert.IsTrue(Exists(lazyCopyWriteFileOutput2)); }
public void LazyWriteFileMaterializationTest() { // setting up the output dir for the pips string writeFileOutput = Path.Combine(ObjectRoot, @"write\writeFile.txt"); AbsolutePath writeFileOutputPath = AbsolutePath.Create(Context.PathTable, writeFileOutput); var sourceFile = CreateSourceFile(); WriteSourceFile(sourceFile); // Graph: // W <- P var writeFileOutputContent = "WriteFileOutput"; var lazyWriteFileOutput = WriteFile(writeFileOutputPath, writeFileOutputContent); // ...........PIP A........... var builderA = CreatePipBuilder(new Operation[] { Operation.ReadFile(lazyWriteFileOutput), Operation.ReadFile(sourceFile), Operation.WriteFile(CreateOutputFileArtifact()) }); builderA.AddTags(Context.StringTable, "pipA"); var pipA = SchedulePipBuilder(builderA); //// ...........Setting Modes........... Configuration.Schedule.EnableLazyOutputMaterialization = true; Configuration.Schedule.EnableLazyWriteFileMaterialization = true; // run scheduler and assert cache miss RunScheduler().AssertCacheMiss(pipA.Process.PipId);// nothing in cache // Exist since pipA must run and the write file output is an input XAssert.IsTrue(Exists(lazyWriteFileOutput)); // Now just run against pip A // those pips exist in cache and then there is no reason to run // those pips (in this case pipA) Configuration.Filter = "tag='pipA'"; // Delete these files on disk Delete(lazyWriteFileOutput); // Run scheduler but grab artificats from cache (should be there from last run)... RunScheduler().AssertCacheHit(pipA.Process.PipId); // Does not exist since pipA had cache hit and since lazy materialization // is on there is not need to materialize the artifacts from the write file pip XAssert.IsFalse(Exists(lazyWriteFileOutput)); // Clear the cache so no outputs can be retrieved from cache ClearArtifactCache(); // Write source file to force cache miss WriteSourceFile(sourceFile); // run scheduler and assert cache hit RunScheduler().AssertCacheMiss(pipA.Process.PipId); // Write file output must be materialized as its an input to the pip XAssert.IsTrue(Exists(lazyWriteFileOutput)); }
public ScheduleRunResult AssertFailure() { XAssert.IsFalse(Success, "Expected scheduler to run with at least one pip failing"); return(this); }
public void RetryDeleteDirectoryContentsIfContentsPendingDelete() { try { // Need to disable POSIX delete to reproduce the Windows pending deletion state, // which does not exist in POSIX FileUtilities.PosixDeleteMode = PosixDeleteMode.NoRun; string dir = Path.Combine(TemporaryDirectory, "dir"); Directory.CreateDirectory(dir); string nestedFile = Path.Combine(dir, "nestedFile"); File.WriteAllText(nestedFile, "asdf"); SafeFileHandle nestedFileHandle; FileUtilities.TryCreateOrOpenFile( nestedFile, FileDesiredAccess.GenericWrite, FileShare.ReadWrite | FileShare.Delete, FileMode.Open, FileFlagsAndAttributes.None, out nestedFileHandle); // Hold open a handle to \file, but allow all file sharing permissions using (nestedFileHandle) { // Sanity check that pending delete doesn't always return true XAssert.IsFalse(FileUtilities.IsPendingDelete(nestedFileHandle)); Exception exception = null; try { // Fails because of the open file that cannot be deleted FileUtilities.DeleteDirectoryContents(dir, true); } catch (BuildXLException e) { exception = e; XAssert.IsTrue(e.Message.StartsWith(FileUtilitiesMessages.DeleteDirectoryContentsFailed + NormalizeDirectoryPath(dir))); // Rebuild the exception message using StringBuilder to handle breaklines StringBuilder builder = new StringBuilder(); builder.AppendLine(NormalizeDirectoryPath(nestedFile)); builder.AppendLine(FileUtilitiesMessages.NoProcessesUsingHandle); builder.AppendLine(FileUtilitiesMessages.PathMayBePendingDeletion); XAssert.IsTrue(e.Message.Contains(builder.ToString())); } XAssert.IsTrue(exception != null); // Check the open handle forced the file to be placed on the Windows pending deletion queue XAssert.IsTrue(FileUtilities.IsPendingDelete(nestedFileHandle)); } // After the file handle is closed, the delete goes through XAssert.IsFalse(File.Exists(nestedFile)); // Check for retries and ERROR_DIR_NOT_EMPTY AssertVerboseEventLogged(EventId.RetryOnFailureException, Helpers.DefaultNumberOfAttempts); string logs = EventListener.GetLog(); var numMatches = Regex.Matches(logs, Regex.Escape("Native: RemoveDirectoryW for RemoveDirectory failed (0x91: The directory is not empty")).Count; XAssert.AreEqual(Helpers.DefaultNumberOfAttempts, numMatches); } finally { // Re-enable POSIX delete for the remainder of tests FileUtilities.PosixDeleteMode = PosixDeleteMode.RunFirst; } }
public Task BigStrings() { var harness = new StringTableTestHarness(); var st = harness.StringTable; var s1 = new string('x', StringTable.BytesPerBuffer - 1); var s2 = new string('y', StringTable.BytesPerBuffer); var s3 = new string('z', StringTable.BytesPerBuffer + 1); StringId id1 = harness.AddString(s1); StringId id2 = harness.AddString(s2); StringId id3 = harness.AddString(s3); harness.AddString(s3 + "繙"); XAssert.AreEqual(s1.Length, st.GetLength(id1)); XAssert.AreEqual(s2.Length, st.GetLength(id2)); XAssert.AreEqual(s3.Length, st.GetLength(id3)); var buf = new char[StringTable.BytesPerBuffer + 1]; st.CopyString(id1, buf, 0); for (int j = 0; j < s1.Length; j++) { XAssert.AreEqual(s1[j], buf[j]); } st.CopyString(id2, buf, 0); for (int j = 0; j < s2.Length; j++) { XAssert.AreEqual(s2[j], buf[j]); } st.CopyString(id3, buf, 0); for (int j = 0; j < s3.Length; j++) { XAssert.AreEqual(s3[j], buf[j]); } XAssert.IsTrue(st.CaseInsensitiveEquals(id1, st.AddString(s1))); XAssert.IsTrue(st.CaseInsensitiveEquals(id2, st.AddString(s2))); XAssert.IsTrue(st.CaseInsensitiveEquals(id3, st.AddString(s3))); XAssert.IsTrue(st.Equals(s1, id1)); XAssert.IsTrue(st.Equals(s2, id2)); XAssert.IsTrue(st.Equals(s3, id3)); XAssert.IsFalse(st.CaseInsensitiveEquals(id1, st.AddString(s2))); XAssert.IsFalse(st.CaseInsensitiveEquals(id1, st.AddString(s3))); XAssert.IsFalse(st.CaseInsensitiveEquals(id2, st.AddString(s1))); XAssert.IsFalse(st.CaseInsensitiveEquals(id2, st.AddString(s3))); XAssert.IsFalse(st.CaseInsensitiveEquals(id3, st.AddString(s1))); XAssert.IsFalse(st.CaseInsensitiveEquals(id3, st.AddString(s2))); XAssert.IsFalse(st.Equals(s2, id1)); XAssert.IsFalse(st.Equals(s3, id1)); XAssert.IsFalse(st.Equals(s1, id2)); XAssert.IsFalse(st.Equals(s3, id2)); XAssert.IsFalse(st.Equals(s1, id3)); XAssert.IsFalse(st.Equals(s2, id3)); return(harness.RunCommonTestsAsync()); }
public void FailToFindAllOpenHandlesPendingDeletion() { string dir = Path.Combine(TemporaryDirectory, "dir"); Directory.CreateDirectory(dir); string file = Path.Combine(dir, "file"); File.WriteAllText(file, "asdf"); SafeFileHandle fileHandle; FileUtilities.TryCreateOrOpenFile( file, FileDesiredAccess.GenericWrite, FileShare.ReadWrite | FileShare.Delete, FileMode.Open, FileFlagsAndAttributes.None, out fileHandle); // Hold open a handle to \file, but allow all file sharing permissions using (fileHandle) { XAssert.IsFalse(FileUtilities.IsPendingDelete(fileHandle)); // This will succeed without throwing an exception File.Delete(file); // But the open handle forces the file to be placed on a pending deletion queue XAssert.IsTrue(FileUtilities.IsPendingDelete(fileHandle)); // Fail to detect open handles for files pending deletion HashSet <string> deletedPaths = new HashSet <string>() { file }; string openHandles = FileUtilities.FindAllOpenHandlesInDirectory(TemporaryDirectory, pathsPossiblyPendingDelete: deletedPaths); // Rebuild the exception message using StringBuilder to handle breaklines StringBuilder builder = new StringBuilder(); builder.AppendLine(file); builder.AppendLine(FileUtilitiesMessages.NoProcessesUsingHandle); builder.AppendLine(FileUtilitiesMessages.PathMayBePendingDeletion); // Before Windows 10 Version 1903, attempting to create a file handle to a file pending deletion would throw an access exception, including calling File.Exists // With Windows 10 Version 1903 and later, creating handles to files on the pending deletion queue does not throw exceptions and pending deletion files are considered deleted by File.Exists // This change in behavior is NOT true for directories, see testing below for the directory behavior XAssert.IsTrue(openHandles.Contains(builder.ToString()) || /* Check for Windows 10 Version 1903 and later */ !File.Exists(file)); XAssert.IsFalse(openHandles.Contains(FileUtilitiesMessages.ActiveHandleUsage + file)); } XAssert.IsFalse(File.Exists(file)); SafeFileHandle dirHandle; FileUtilities.TryCreateOrOpenFile( dir, FileDesiredAccess.GenericWrite, FileShare.ReadWrite | FileShare.Delete, FileMode.Open, FileFlagsAndAttributes.FileFlagBackupSemantics, out dirHandle); // Hold open a handle to \dir, but allow all sharing permissions using (dirHandle) { XAssert.IsFalse(FileUtilities.IsPendingDelete(dirHandle)); // This will succeed without throwing an exception Directory.Delete(dir); // But the open handle forces the directory to be placed on a pending deletion queue XAssert.IsTrue(FileUtilities.IsPendingDelete(dirHandle)); // Fail to detect open handles for dirs pending deletion HashSet <string> deletedPaths = new HashSet <string>() { dir }; string openHandles = FileUtilities.FindAllOpenHandlesInDirectory(TemporaryDirectory, pathsPossiblyPendingDelete: deletedPaths); // Rebuild the exception message using StringBuilder to handle breaklines StringBuilder builder = new StringBuilder(); builder.AppendLine(dir); builder.AppendLine(FileUtilitiesMessages.NoProcessesUsingHandle); builder.AppendLine(FileUtilitiesMessages.PathMayBePendingDeletion); XAssert.IsTrue(openHandles.Contains(builder.ToString())); XAssert.IsFalse(openHandles.Contains(FileUtilitiesMessages.ActiveHandleUsage + dir)); } XAssert.IsFalse(Directory.Exists(dir)); }
public void TestSemaphoreSet() { SemaphoreSet <int> semaphores = new SemaphoreSet <int>(); int[] limits = new int[] { 1, 2, 3, 10 }; int originalLimitsLength = limits.Length; for (int i = 0; i < limits.Length; i++) { int semaphoreIndex = semaphores.CreateSemaphore(i, limits[i]); XAssert.AreEqual(i, semaphoreIndex); } for (int i = 0; i < limits.Length; i++) { var limit = limits[i]; for (int usage = 1; usage <= limit + 1; usage++) { int semaphoreIndex = semaphores.CreateSemaphore(i, limits[i]); XAssert.AreEqual(i, semaphoreIndex); var semaphoreIncrements = new int[i + 1]; semaphoreIncrements[i] = 1; bool acquired = semaphores.TryAcquireResources(ItemResources.Create(semaphoreIncrements)); bool expectAcquired = usage <= limit; XAssert.AreEqual(expectAcquired, acquired); } } // Now verify semaphores can be acquired in the copy var copiedSemaphores = semaphores.CreateSharingCopy(); for (int i = 0; i < limits.Length; i++) { var limit = limits[i]; for (int usage = 1; usage <= limit + 1; usage++) { var semaphoreIncrements = new int[i + 1]; semaphoreIncrements[i] = 1; bool acquired = copiedSemaphores.TryAcquireResources(ItemResources.Create(semaphoreIncrements)); bool expectAcquired = usage <= limit; XAssert.AreEqual(expectAcquired, acquired); } } limits = limits.Concat(new int[] { 6, 8 }).ToArray(); // Create new semaphores in the copy and verify that semaphores can be used in original for (int i = 0; i < limits.Length; i++) { int semaphoreIndex = copiedSemaphores.CreateSemaphore(i, limits[i]); XAssert.AreEqual(i, semaphoreIndex); } for (int i = originalLimitsLength; i < limits.Length; i++) { var limit = limits[i]; for (int usage = 1; usage <= limit + 1; usage++) { var semaphoreIncrements = new int[i + 1]; semaphoreIncrements[i] = 1; bool acquired = semaphores.TryAcquireResources(ItemResources.Create(semaphoreIncrements)); bool expectAcquired = usage <= limit; XAssert.AreEqual(expectAcquired, acquired); } } // Now verify new semaphores can be acquired in the copy for (int i = originalLimitsLength; i < limits.Length; i++) { var limit = limits[i]; for (int usage = 1; usage <= limit + 1; usage++) { var semaphoreIncrements = new int[i + 1]; semaphoreIncrements[i] = 1; bool acquired = copiedSemaphores.TryAcquireResources(ItemResources.Create(semaphoreIncrements)); bool expectAcquired = usage <= limit; XAssert.AreEqual(expectAcquired, acquired); } } // Now release the resources in the copy for (int i = 0; i < limits.Length; i++) { var limit = limits[i]; for (int usage = 1; usage <= limit; usage++) { var semaphoreIncrements = new int[i + 1]; semaphoreIncrements[i] = 1; copiedSemaphores.ReleaseResources(ItemResources.Create(semaphoreIncrements)); } } // Verify that resources still can't be acquired on original for (int i = 0; i < limits.Length; i++) { var semaphoreIncrements = new int[i + 1]; semaphoreIncrements[i] = 1; bool acquired = semaphores.TryAcquireResources(ItemResources.Create(semaphoreIncrements)); XAssert.IsFalse(acquired); } }
public async Task ReadFileRandomAccess() { const int NumberOfReads = 16; const int NumberOfWordsPerRead = 64 * 1024; const int NumberOfBytesPerRead = NumberOfWordsPerRead * 4; const int NumberOfWords = NumberOfWordsPerRead * NumberOfReads; const int TotalSize = NumberOfWords * 4; string path = GetFullPath("file"); using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Delete)) { using (var writer = new BinaryWriter(fs, Encoding.UTF8, leaveOpen: true)) { for (int i = 0; i < NumberOfWords; i++) { writer.Write((int)i); } } } #if !FEATURE_CORECLR using (var io = new IOCompletionManager()) #else IIOCompletionManager io = null; #endif { using ( IAsyncFile file = AsyncFileFactory.CreateOrOpen( path, FileDesiredAccess.GenericRead, FileShare.Read | FileShare.Delete, FileMode.Open, FileFlagsAndAttributes.None, io)) { XAssert.IsTrue(file.CanRead); XAssert.IsFalse(file.CanWrite); var readBuffer = new byte[TotalSize]; var readTasks = new Task[NumberOfReads]; for (int i = 0; i < readTasks.Length; i++) { int offset = NumberOfBytesPerRead * i; readTasks[i] = Task.Run( async() => { byte[] localBuffer = new byte[NumberOfBytesPerRead]; int readSoFar = 0; while (readSoFar < NumberOfBytesPerRead) { FileAsyncIOResult result = await file.ReadAsync(localBuffer, bytesToRead: NumberOfBytesPerRead - readSoFar, fileOffset: offset + readSoFar); XAssert.AreEqual(FileAsyncIOStatus.Succeeded, result.Status); XAssert.IsTrue(result.BytesTransferred > 0); XAssert.IsTrue(readSoFar + result.BytesTransferred <= NumberOfBytesPerRead); Buffer.BlockCopy(localBuffer, 0, readBuffer, offset + readSoFar, result.BytesTransferred); readSoFar += result.BytesTransferred; } Contract.Assert(readSoFar == NumberOfBytesPerRead); }); } for (int i = 0; i < readTasks.Length; i++) { await readTasks[i]; } using (var reader = new BinaryReader(new MemoryStream(readBuffer, writable: false), Encoding.UTF8, leaveOpen: false)) { for (int i = 0; i < NumberOfWords; i++) { XAssert.AreEqual(i, reader.ReadInt32()); } } } } }
public void ErrorAndWarningListener() { string text; using (var writer = new StringWriter(CultureInfo.InvariantCulture)) { using (var listener = new ErrorAndWarningEventListener(Events.Log, writer, DateTime.UtcNow, true, false, warningNumber => WarningState.AsWarning)) { Events log = Events.Log; // should be captured log.CriticalEvent("Cookie 1 "); log.ErrorEvent("Cookie 2 "); // shouldn't be captured log.WarningEvent("Cookie 3 "); log.AlwaysEvent("Cookie 4 "); log.InfoEvent("Cookie 5 "); log.VerboseEvent("Cookie 6 "); } text = writer.ToString(); } XAssert.IsTrue(Regex.IsMatch(text, ".*Cookie 1 .*")); XAssert.IsTrue(Regex.IsMatch(text, ".*Cookie 2 .*")); XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 3 .*")); XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 4 .*")); XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 5 .*")); XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 6 .*")); using (var writer = new StringWriter(CultureInfo.InvariantCulture)) { using (var listener = new ErrorAndWarningEventListener(Events.Log, writer, DateTime.UtcNow, false, true, warningNumber => WarningState.AsWarning)) { Events log = Events.Log; // should be captured log.WarningEvent("Cookie 3 "); // shouldn't be captured log.CriticalEvent("Cookie 1 "); log.ErrorEvent("Cookie 2 "); log.AlwaysEvent("Cookie 4 "); log.InfoEvent("Cookie 5 "); log.VerboseEvent("Cookie 6 "); } text = writer.ToString(); } XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 1 .*")); XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 2 .*")); XAssert.IsTrue(Regex.IsMatch(text, ".*Cookie 3 .*")); XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 4 .*")); XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 5 .*")); XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 6 .*")); // repeat the same tests, but now suppress the warning message (i.e., emulate /noWarn:10002 (EventId.WarningEvent)) // WarningMapper applies only to warning-level events, so we can check only that one // since the warning is being suppressed, nothing should be captured using (var writer = new StringWriter(CultureInfo.InvariantCulture)) { using (var listener = new ErrorAndWarningEventListener(Events.Log, writer, DateTime.UtcNow, true, false, warningNumber => WarningState.Suppressed)) { Events log = Events.Log; log.WarningEvent("Cookie 3 "); } text = writer.ToString(); } XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 3 .*")); using (var writer = new StringWriter(CultureInfo.InvariantCulture)) { using (var listener = new ErrorAndWarningEventListener(Events.Log, writer, DateTime.UtcNow, false, true, warningNumber => WarningState.Suppressed)) { Events log = Events.Log; log.WarningEvent("Cookie 3 "); } text = writer.ToString(); } XAssert.IsFalse(Regex.IsMatch(text, ".*Cookie 3 .*")); }
private void VerifyPipDataFromCursorEnd(PipData.FragmentEnumerator enumerator) { XAssert.IsFalse(enumerator.MoveNext()); }
public void TrackingEventListener() { const int NumVerbose = 9; const int NumInfo = 8; const int NumWarning = 7; const int NumError = 6; const int NumCritical = 5; const int NumAlways = 4; using (var listener = new TrackingEventListener(Events.Log)) { Events log = Events.Log; for (int i = 0; i < NumVerbose; i++) { log.VerboseEvent("1"); } for (int i = 0; i < NumInfo; i++) { log.InfoEvent("1"); } for (int i = 0; i < NumWarning; i++) { log.WarningEvent("1"); } for (int i = 0; i < NumError; i++) { log.ErrorEvent("1"); } for (int i = 0; i < NumCritical; i++) { log.CriticalEvent("1"); } for (int i = 0; i < NumAlways; i++) { log.AlwaysEvent("1"); } XAssert.AreEqual(listener.VerboseCount, NumVerbose); XAssert.AreEqual(listener.InformationalCount, NumInfo); XAssert.AreEqual(listener.WarningCount, NumWarning); XAssert.AreEqual(listener.TotalErrorCount, NumError + NumCritical); XAssert.AreEqual(listener.CriticalCount, NumCritical); XAssert.AreEqual(listener.AlwaysCount, NumAlways); XAssert.IsTrue(listener.HasFailures); XAssert.IsTrue(listener.HasFailuresOrWarnings); } using (var listener = new TrackingEventListener(Events.Log)) { Events log = Events.Log; XAssert.IsFalse(listener.HasFailures); XAssert.IsFalse(listener.HasFailuresOrWarnings); log.WarningEvent("1"); XAssert.IsFalse(listener.HasFailures); XAssert.IsTrue(listener.HasFailuresOrWarnings); log.ErrorEvent("1"); XAssert.IsTrue(listener.HasFailures); XAssert.IsTrue(listener.HasFailuresOrWarnings); } using (var listener = new TrackingEventListener(Events.Log)) { Events log = Events.Log; log.CriticalEvent("1"); XAssert.IsTrue(listener.HasFailures); XAssert.IsTrue(listener.HasFailuresOrWarnings); } using (var listener = new TrackingEventListener(Events.Log, warningMapper: _ => WarningState.AsError)) { Events log = Events.Log; log.WarningEvent("1"); XAssert.AreEqual(1, listener.TotalErrorCount); XAssert.IsTrue(listener.HasFailures); XAssert.IsTrue(listener.HasFailuresOrWarnings); } }
public void ScrubFilesNotInContentsWhenFullySealDir(bool shouldScrub) { // simulating two builds here, // the second build should scrub the stray files // if they are in a fully sealed directory var sourceDir = DirectoryArtifact.CreateWithZeroPartialSealId(CreateUniqueDirectory()); var sourceDirStr = ArtifactToString(sourceDir); var file1 = CreateOutputFileArtifact(sourceDirStr); var file1Str = ArtifactToString(file1); var file2 = CreateOutputFileArtifact(sourceDirStr); var file2Str = ArtifactToString(file2); var sealDir = DirectoryArtifact.CreateWithZeroPartialSealId(CreateUniqueDirectory()); var sealDirStr = ArtifactToString(sealDir); var nestedDir1 = AbsolutePath.Create(Context.PathTable, Path.Combine(sealDirStr, "nested1")); var nestedDir1Str = nestedDir1.ToString(Context.PathTable); var nestedDir2 = AbsolutePath.Create(Context.PathTable, Path.Combine(sealDirStr, "nested2")); var nestedDir2Str = nestedDir2.ToString(Context.PathTable); var sealFile1 = CreateOutputFileArtifact(nestedDir1Str); var sealFile1Str = ArtifactToString(sealFile1); var sealFile2 = CreateOutputFileArtifact(nestedDir2Str); var sealFile2Str = ArtifactToString(sealFile2); // the first build depends on file1 and file2 var builderA = CreatePipBuilder(new Operation[] { Operation.WriteFile(file1, "First build write file1"), Operation.WriteFile(file2, "First build write file2"), }); SchedulePipBuilder(builderA); var builderB = CreatePipBuilder(new Operation[] { Operation.CopyFile(file1, sealFile1), Operation.CopyFile(file2, sealFile2), }); SchedulePipBuilder(builderB); SealDirectory(sealDir, SealDirectoryKind.Full, true, sealFile1, sealFile2); RunScheduler().AssertSuccess(); XAssert.IsTrue(File.Exists(sealFile1Str), $"File in the content list when seal was supposed to exist: {sealFile1Str}"); XAssert.IsTrue(File.Exists(sealFile2Str), $"File in the content list when seal was supposed to exist: {sealFile2Str}"); ResetPipGraphBuilder(); // the second build only depends on file1 var builderC = CreatePipBuilder(new Operation[] { Operation.WriteFile(file1, "Second build write file1"), }); SchedulePipBuilder(builderC); var builderD = CreatePipBuilder(new Operation[] { Operation.CopyFile(file1, sealFile1), }); SchedulePipBuilder(builderD); SealDirectory(sealDir, SealDirectoryKind.Full, shouldScrub, sealFile1); var opslist = new List <Operation>(); opslist.Add(Operation.ReadFile(sealFile1)); opslist.Add(Operation.WriteFile(CreateOutputFileArtifact())); if (!shouldScrub) { opslist.Add(Operation.ReadFile(sealFile2, true)); } var builderE = CreatePipBuilder(opslist); SchedulePipBuilder(builderE); XAssert.IsTrue(File.Exists(sealFile1Str), $"File in the content list when seal was supposed to exist: {sealFile1Str}"); if (shouldScrub) { RunScheduler().AssertSuccess(); XAssert.IsFalse(Directory.Exists(nestedDir2Str), $"unseal directory wasn't supposed to exist: {nestedDir2Str}"); XAssert.IsFalse(File.Exists(sealFile2Str), $"File not in the content list when seal wasn't supposed to exist: {sealFile2Str}"); } else { RunScheduler().AssertFailure(); AssertErrorEventLogged(EventId.FileMonitoringError); AssertVerboseEventLogged(EventId.PipProcessDisallowedFileAccess); AssertWarningEventLogged(EventId.ProcessNotStoredToCacheDueToFileMonitoringViolations); XAssert.IsTrue(Directory.Exists(nestedDir2Str), $"unseal directory was supposed to exist: {nestedDir2Str}"); XAssert.IsTrue(File.Exists(sealFile2Str), $"File not in the content list when seal was supposed to exist: {sealFile2Str}"); } }
private void ExpectHashUnknown(FileContentTable table, AbsolutePath path) { VersionedFileIdentityAndContentInfo?maybeKnownHash = table.TryGetKnownContentHash(path.ToString(m_pathTable)); XAssert.IsFalse(maybeKnownHash.HasValue, "Loaded table has an unexpected entry for {0}", path.ToString(m_pathTable)); }
public void SerializeSandboxedProcessInfo(bool useNullFileStorage, bool useRootJail) { var pt = new PathTable(); var fam = new FileAccessManifest(pt, CreateDirectoryTranslator()) { FailUnexpectedFileAccesses = false, IgnoreCodeCoverage = false, ReportFileAccesses = false, ReportUnexpectedFileAccesses = false, MonitorChildProcesses = false }; var vac = new ValidationDataCreator(fam, pt); vac.AddScope(A("C", "Users", "AppData"), FileAccessPolicy.AllowAll); vac.AddPath(A("C", "Source", "source.txt"), FileAccessPolicy.AllowReadAlways); vac.AddPath(A("C", "Out", "out.txt"), FileAccessPolicy.AllowAll); SandboxedProcessStandardFiles standardFiles = null; ISandboxedProcessFileStorage fileStorage; if (useNullFileStorage) { fileStorage = null; } else { standardFiles = new SandboxedProcessStandardFiles(A("C", "pip", "pip.out"), A("C", "pip", "pip.err")); fileStorage = new StandardFileStorage(standardFiles); } var envVars = new Dictionary <string, string>() { ["Var1"] = "Val1", ["Var2"] = "Val2", }; IBuildParameters buildParameters = BuildParameters.GetFactory().PopulateFromDictionary(envVars); var sidebandLogFile = A("C", "engine-cache", "sideband-logs", "log-1"); var loggerRootDirs = new[] { A("C", "out", "dir1"), A("C", "out", "dir2") }; var sharedOpaqueOutputLogger = new SidebandWriter(DefaultSidebandMetadata, sidebandLogFile, loggerRootDirs); SandboxedProcessInfo info = new SandboxedProcessInfo( pt, fileStorage, A("C", "tool", "tool.exe"), fam, true, null, LoggingContext, sidebandWriter: sharedOpaqueOutputLogger) { Arguments = @"/arg1:val1 /arg2:val2", WorkingDirectory = A("C", "Source"), RootJailInfo = useRootJail ? (RootJailInfo?)new RootJailInfo(A("C", "RootJail"), 123, 234) : null, EnvironmentVariables = buildParameters, Timeout = TimeSpan.FromMinutes(15), PipSemiStableHash = 0x12345678, PipDescription = nameof(SerializeSandboxedProcessInfo), TimeoutDumpDirectory = A("C", "Timeout"), SandboxKind = global::BuildXL.Utilities.Configuration.SandboxKind.Default, AllowedSurvivingChildProcessNames = new[] { "conhost.exe", "mspdbsrv.exe" }, NestedProcessTerminationTimeout = SandboxedProcessInfo.DefaultNestedProcessTerminationTimeout, StandardInputSourceInfo = StandardInputInfo.CreateForData("Data"), StandardObserverDescriptor = new SandboxObserverDescriptor() { WarningRegex = new ExpandedRegexDescriptor("*warn", System.Text.RegularExpressions.RegexOptions.Compiled) }, }; // Serialize and deserialize. SandboxedProcessInfo readInfo = null; using (var stream = new MemoryStream()) { info.Serialize(stream); stream.Position = 0; readInfo = SandboxedProcessInfo.Deserialize( stream, new global::BuildXL.Utilities.Instrumentation.Common.LoggingContext("Test"), null); } using (readInfo.SidebandWriter) { // Verify. XAssert.AreEqual(info.FileName, readInfo.FileName); XAssert.AreEqual(info.Arguments, readInfo.Arguments); XAssert.AreEqual(info.WorkingDirectory, readInfo.WorkingDirectory); XAssert.AreEqual(info.RootJailInfo?.RootJail, readInfo.RootJailInfo?.RootJail); XAssert.AreEqual(info.RootJailInfo?.UserId, readInfo.RootJailInfo?.UserId); XAssert.AreEqual(info.RootJailInfo?.GroupId, readInfo.RootJailInfo?.GroupId); var readEnvVars = readInfo.EnvironmentVariables.ToDictionary(); XAssert.AreEqual(envVars.Count, readEnvVars.Count); foreach (var kvp in envVars) { XAssert.AreEqual(kvp.Value, readEnvVars[kvp.Key]); } XAssert.AreEqual(info.Timeout, readInfo.Timeout); XAssert.AreEqual(info.PipSemiStableHash, readInfo.PipSemiStableHash); XAssert.AreEqual(info.PipDescription, readInfo.PipDescription); XAssert.AreEqual(info.TimeoutDumpDirectory, readInfo.TimeoutDumpDirectory); XAssert.AreEqual(info.SandboxKind, readInfo.SandboxKind); XAssert.AreEqual(info.AllowedSurvivingChildProcessNames.Length, readInfo.AllowedSurvivingChildProcessNames.Length); for (int i = 0; i < info.AllowedSurvivingChildProcessNames.Length; ++i) { XAssert.AreEqual(info.AllowedSurvivingChildProcessNames[i], readInfo.AllowedSurvivingChildProcessNames[i]); } XAssert.AreEqual(info.NestedProcessTerminationTimeout, readInfo.NestedProcessTerminationTimeout); XAssert.AreEqual(info.StandardInputSourceInfo, readInfo.StandardInputSourceInfo); if (useNullFileStorage) { XAssert.IsNull(readInfo.SandboxedProcessStandardFiles); XAssert.IsNull(readInfo.FileStorage); } else { XAssert.IsNotNull(readInfo.SandboxedProcessStandardFiles); XAssert.AreEqual(standardFiles.StandardOutput, readInfo.SandboxedProcessStandardFiles.StandardOutput); XAssert.AreEqual(standardFiles.StandardError, readInfo.SandboxedProcessStandardFiles.StandardError); XAssert.AreEqual(standardFiles.StandardOutput, readInfo.FileStorage.GetFileName(SandboxedProcessFile.StandardOutput)); XAssert.AreEqual(standardFiles.StandardError, readInfo.FileStorage.GetFileName(SandboxedProcessFile.StandardError)); } XAssert.IsFalse(readInfo.ContainerConfiguration.IsIsolationEnabled); XAssert.AreEqual(sidebandLogFile, readInfo.SidebandWriter.SidebandLogFile); XAssert.ArrayEqual(loggerRootDirs, readInfo.SidebandWriter.RootDirectories.ToArray()); if (!OperatingSystemHelper.IsUnixOS) { // this validator examines serialized FAM bytes using the same Windows-only native parser used by Detours ValidationDataCreator.TestManifestRetrieval(vac.DataItems, readInfo.FileAccessManifest, false); } } }
public void TestConcurrentBigMapOperations() { var map = new ConcurrentBigMap <int, string>(); XAssert.IsTrue(map.TryAdd(0, "value")); XAssert.IsFalse(map.TryAdd(0, "not added value")); XAssert.AreEqual("value", map[0]); map[0] = "newValue"; map[1] = "value1"; var value0 = "newValue"; XAssert.AreEqual(value0, map[0]); XAssert.IsTrue(map.ContainsKey(0)); XAssert.IsTrue(map.ContainsKey(1)); XAssert.IsFalse(map.ContainsKey(12)); XAssert.AreEqual(2, map.Count); // Test TryGetValue string value1; XAssert.IsTrue(map.TryGetValue(1, out value1)); XAssert.AreEqual("value1", value1); string value31; XAssert.IsFalse(map.TryGetValue(31, out value31)); // Test update XAssert.IsFalse(map.TryUpdate(1, "notUpdatedValue1", "notActualValue1")); XAssert.AreEqual("value1", map[1]); XAssert.IsTrue(map.TryUpdate(1, "updatedValue1", "value1")); value1 = map[1]; XAssert.AreEqual("updatedValue1", value1); // Test remove int beforeFailedRemoveCount = map.Count; string value23; XAssert.IsFalse(map.TryRemove(23, out value23)); XAssert.AreEqual(beforeFailedRemoveCount, map.Count); map.Add(23, "value23"); XAssert.AreEqual(beforeFailedRemoveCount + 1, map.Count); XAssert.IsTrue(map.TryRemove(23, out value23)); XAssert.AreEqual("value23", value23); XAssert.AreEqual(beforeFailedRemoveCount, map.Count); Assert.Equal(new int[] { 0, 1 }, map.Keys.ToArray()); Assert.Equal(new string[] { value0, value1 }, map.Values.ToArray()); XAssert.AreEqual(2, map.Count); string addedData = "added data"; string notAddedData = "not added data"; var result = map.GetOrAdd(2, addedData, (key, data0) => data0); XAssert.IsFalse(result.IsFound); XAssert.AreEqual(addedData, result.Item.Value); XAssert.AreEqual(addedData, map[2]); // Ensure entry is not updated for get or add result = map.GetOrAdd(2, notAddedData, (key, data0) => data0); XAssert.IsTrue(result.IsFound); XAssert.AreEqual(addedData, result.Item.Value); XAssert.AreEqual(addedData, map[2]); Func <int, string, string, string> updateFunction = (key, data0, currentValue) => "updated " + currentValue; var updatedData = updateFunction(2, notAddedData, addedData); result = map.AddOrUpdate(2, notAddedData, (key, data0) => data0, updateFunction); XAssert.IsTrue(result.IsFound); XAssert.AreEqual(addedData, result.OldItem.Value); XAssert.AreEqual(updatedData, result.Item.Value); XAssert.AreEqual(updatedData, map[2]); result = map.AddOrUpdate(3, addedData, (key, data0) => data0, updateFunction); XAssert.IsFalse(result.IsFound); XAssert.AreEqual(addedData, result.Item.Value); XAssert.AreEqual(addedData, map[3]); TestOperationsHelper(parallel: false); }
/// <summary> /// Asserts that a file relative to <see cref="TemporaryStorageTestBase.TemporaryDirectory" /> exists. /// </summary> protected void AssertFileDoesNotExist(string relPath) { string path = GetFullPath(relPath); XAssert.IsFalse(File.Exists(path), "Expected path {0} to be absent", path); }
public void TestRedirectUserProfileDirectory() { // first run to create all necessary directories leading to obj directory SetupTestData(); RunEngine(); string currentUserProfile = SpecialFolderUtilities.GetFolderPath(Environment.SpecialFolder.UserProfile); string junctionPath = Path.Combine(Configuration.Layout.ObjectDirectory.ToString(Context.PathTable), "buildXLUserProfile"); bool specialFolderInitializerWasCalled = false; var translatedDirectory = new List <TranslateDirectoryData>(); var properties = new Dictionary <string, string>(); var expectedProperties = new Dictionary <string, string> { { "APPDATA", Path.Combine(junctionPath, "AppData", "Roaming") }, { "LOCALAPPDATA", Path.Combine(junctionPath, "AppData", "Local") }, { "USERPROFILE", junctionPath }, { "USERNAME", "buildXLUserProfile" }, { "HOMEDRIVE", Path.GetPathRoot(junctionPath).TrimEnd('\\') }, { "HOMEPATH", junctionPath.Substring(Path.GetPathRoot(junctionPath).TrimEnd('\\').Length) }, { "INTERNETCACHE", Path.Combine(junctionPath, "AppData", "Local", "Microsoft", "Windows", "INetCache") }, { "INTERNETHISTORY", Path.Combine(junctionPath, "AppData", "Local", "Microsoft", "Windows", "History") }, { "INETCOOKIES", Path.Combine(junctionPath, "AppData", "Local", "Microsoft", "Windows", "INetCookies") }, { "LOCALLOW", Path.Combine(junctionPath, "AppData", "LocalLow") }, }; // add the variables to the dictionary, so we can verify that the method overrides the existing values foreach (var envVar in expectedProperties.Keys) { properties.Add(envVar, string.Empty); } try { var success = BuildXLEngine.RedirectUserProfileDirectory( Configuration.Layout.ObjectDirectory, translatedDirectory, properties, dict => { specialFolderInitializerWasCalled = true; }, true, Context.PathTable, LoggingContext); // must have finished successfully XAssert.IsTrue(success); // verify the env block is properly populated XAssert.AreSetsEqual(expectedProperties.Keys, properties.Keys, true); XAssert.IsFalse(expectedProperties.Any(kvp => properties[kvp.Key] != kvp.Value)); XAssert.IsTrue(specialFolderInitializerWasCalled); // verify junction var openResult = FileUtilities.TryOpenDirectory(junctionPath, FileDesiredAccess.FileReadAttributes, FileShare.ReadWrite, FileFlagsAndAttributes.FileFlagOpenReparsePoint, out var handle); XAssert.IsTrue(openResult.Succeeded); using (handle) { var possibleTarget = FileUtilities.TryGetReparsePointTarget(handle, junctionPath); XAssert.IsTrue(possibleTarget.Succeeded); XAssert.AreEqual(FileSystemWin.NtPathPrefix + currentUserProfile, possibleTarget.Result); } // verify that we added a new directory translation AbsolutePath.TryCreate(Context.PathTable, currentUserProfile, out var fromPath); AbsolutePath.TryCreate(Context.PathTable, junctionPath, out var toPath); XAssert.IsTrue(translatedDirectory.Count == 1); XAssert.IsTrue(translatedDirectory[0].FromPath == fromPath && translatedDirectory[0].ToPath == toPath); } finally { // clean the junction after the test var possibleProbe = FileUtilities.TryProbePathExistence(junctionPath, false); if (possibleProbe.Succeeded && possibleProbe.Result != PathExistence.Nonexistent) { // we attempt to delete the junction, but we do not care if we failed to do FileUtilities.TryRemoveDirectory(junctionPath, out int errCode); } } }
public async Task TestGcBasic() { string cacheConfig = TestType.NewCache(nameof(TestGcBasic), true); BasicFilesystemCache cache = (await InitializeCacheAsync(cacheConfig).SuccessAsync()) as BasicFilesystemCache; XAssert.IsNotNull(cache, "Failed to create cache for GC tests!"); // Verify that we don't have prior content in the cache XAssert.AreEqual(0, new CacheEntries(cache).Count, "Test cache did not start out empty!"); PipDefinition[] pipsSession1 = { new PipDefinition("Pip1", pipSize: 3), new PipDefinition("Pip2", pipSize: 4), new PipDefinition("Pip3", pipSize: 5) }; CacheEntries session1Files = await BuildPipsAndGetCacheEntries(cache, "Session1", pipsSession1); // Nothing should change on this GC since the files and are all referenced FullGc(cache); session1Files.AssertExists(); session1Files.AgeAll(); // Everything is rooted so nothing should happen here FullGc(cache); XAssert.IsFalse(new CacheEntries(cache).AreDifferences(session1Files), "We changed the cache when we should not have!"); // Now, if we delete the session, we should collect things. cache.DeleteSession("Session1"); FullGc(cache); // All of the fingerprints should be changed to pending but nothing should be deleted CacheEntries session1gcFpPending = new CacheEntries(cache); XAssert.AreEqual(session1Files.Count, session1gcFpPending.Count, "Nothing should have been added or deleted!"); XAssert.IsFalse(session1gcFpPending.FingerprintFiles.Keys.Any(IsNotPendingDelete), "All fingerprints should be pending delete"); XAssert.IsFalse(session1gcFpPending.CasFiles.Keys.Any(IsPendingDelete), "All cas should not be pending delete"); // Nothing to happen here as the pending files are too new FullGc(cache); // Nothing changed... XAssert.IsFalse(new CacheEntries(cache).AreDifferences(session1gcFpPending), "We changed the cache when we should not have!"); // Now age the pending delete such that they are collected session1gcFpPending.AgeAll(); FullGc(cache); CacheEntries session1gcCas1 = new CacheEntries(cache); XAssert.AreEqual(0, session1gcCas1.FingerprintFiles.Count, "Should have collected all fingerprints"); // And, we should have moved to pending all CAS items (since there is no pending) XAssert.IsFalse(session1gcCas1.CasFiles.Keys.Any(IsNotPendingDelete), "All cas should be pending delete"); FullGc(cache); // Should do nothing as they are not old enough pending XAssert.IsFalse(new CacheEntries(cache).AreDifferences(session1gcCas1), "We changed the cache when we should not have!"); // After getting all to be old, this should finally GC it all session1gcCas1.AgeAll(); FullGc(cache); XAssert.AreEqual(0, new CacheEntries(cache).Count, "Should have collected everything."); AssertSuccess(await cache.ShutdownAsync()); }
public void IsValid() { HierarchicalNameId path = HierarchicalNameId.Invalid; XAssert.IsFalse(path.IsValid); }