/// <summary> /// Verifies the resulting arguments after full graph construction. /// </summary> /// <param name="graph">Resulting graph.</param> /// <param name="fragmentOrigin">Graph fragment where the arguments are constructed.</param> /// <param name="outputInFragmentOrigin">Output file to identify pip.</param> /// <param name="expectedArguments">Expected arguments.</param> private void VerifyResultingArguments(PipGraph graph, TestPipGraphFragment fragmentOrigin, FileArtifact outputInFragmentOrigin, PipData expectedArguments) { var pipId = graph.TryGetProducer(FileArtifact.CreateOutputFile(RemapFragmentPath(fragmentOrigin, outputInFragmentOrigin))); XAssert.IsTrue(pipId.IsValid); Pip pip = graph.PipTable.HydratePip(pipId, PipQueryContext.PipGraphGetProducingPip); XAssert.IsNotNull(pip); PipData actualArguments = PipData.Invalid; if (pip is Process process) { actualArguments = process.Arguments; } else if (pip is IpcPip ipcPip) { actualArguments = ipcPip.MessageBody; } else { XAssert.Fail("No arguments associated with pip"); } string expected = expectedArguments.ToString(Context.PathTable).ToUpperInvariant(); string actual = actualArguments.ToString(Context.PathTable).ToUpperInvariant(); XAssert.AreEqual(expected, actual); }
private (IIpcMoniker ipcMoniker, PipId servicePipId) CreateService(TestPipGraphFragment fragment) { var ipcMoniker = fragment.GetIpcMoniker(); var apiServerMoniker = fragment.GetApiServerMoniker(); var shutdownBuilder = fragment.GetProcessBuilder(); new ArgumentsBuilder(shutdownBuilder) .AddIpcMonikerOption("--ipcMoniker", ipcMoniker) .AddIpcMonikerOption("--serverMoniker", apiServerMoniker) .AddOutputOption("--output", fragment.CreateOutputFile("shutdown.txt")); shutdownBuilder.ServiceKind = global::BuildXL.Pips.Operations.ServicePipKind.ServiceShutdown; (Process shutdownProcess, ProcessOutputs _) = fragment.ScheduleProcessBuilder(shutdownBuilder); var finalProcessBuilder = fragment.GetIpcProcessBuilder(); new ArgumentsBuilder(finalProcessBuilder) .AddOption("--command", "final") .AddIpcMonikerOption("--ipcMoniker", ipcMoniker); var finalOutputFile = fragment.CreateOutputFile("final.txt"); var finalizationPip = fragment.ScheduleIpcPip( ipcMoniker, null, finalProcessBuilder, finalOutputFile, true); XAssert.IsTrue(finalizationPip.IsValid); var serviceProcessBuilder = fragment.GetProcessBuilder(); new ArgumentsBuilder(serviceProcessBuilder) .AddIpcMonikerOption("--ipcMoniker", ipcMoniker) .AddIpcMonikerOption("--serverMoniker", apiServerMoniker) .AddOutputOption("--output", fragment.CreateOutputFile("service.txt")); serviceProcessBuilder.ServiceKind = global::BuildXL.Pips.Operations.ServicePipKind.Service; serviceProcessBuilder.ShutDownProcessPipId = shutdownProcess.PipId; serviceProcessBuilder.FinalizationPipIds = ReadOnlyArray <PipId> .FromWithoutCopy(new[] { finalizationPip }); (Process serviceProcess, ProcessOutputs _) = fragment.ScheduleProcessBuilder(serviceProcessBuilder); var createProcessBuilder = fragment.GetIpcProcessBuilder(); new ArgumentsBuilder(createProcessBuilder) .AddOption("--command", "create") .AddIpcMonikerOption("--ipcMoniker", ipcMoniker); var createOutputFile = fragment.CreateOutputFile("create.txt"); var createPip = fragment.ScheduleIpcPip( ipcMoniker, serviceProcess.PipId, createProcessBuilder, createOutputFile, false); XAssert.IsTrue(createPip.IsValid); return(ipcMoniker, serviceProcess.PipId); }
/// <summary> /// Verifies that the file/directory output by a fragment exists in the resulting graph. /// </summary> /// <param name="graph">Resulting graph.</param> /// <param name="fragmentOrigin">Graph fragment where the output originates.</param> /// <param name="outputPath">Path to output file/directory.</param> private void VerifyProducerExists(PipGraph graph, TestPipGraphFragment fragmentOrigin, AbsolutePath outputPath) { AbsolutePath remappedOutputPath = RemapFragmentPath(fragmentOrigin, outputPath); var pipId = graph.TryGetProducer(FileArtifact.CreateOutputFile(remappedOutputPath)); if (!pipId.IsValid) { pipId = graph.TryGetProducer(DirectoryArtifact.CreateWithZeroPartialSealId(remappedOutputPath)); } XAssert.IsTrue(pipId.IsValid, $"Producer of '{outputPath.ToString(fragmentOrigin.Context.PathTable)}' from fragment '{fragmentOrigin.ModuleName}' could not be found in the resulting graph"); }
/// <summary> /// Verifies that the arguments constructed in the fragment (string) matches with the one in the resulting graph. /// </summary> /// <param name="graph">Resulting graph.</param> /// <param name="fragmentOrigin">Graph fragment where the arguments are constructed.</param> /// <param name="processInFragment">Process in fragments whose arguments are to be verified.</param> private void VerifyMatchingArguments(PipGraph graph, TestPipGraphFragment fragmentOrigin, Process processInFragment) { var outputPath = processInFragment.FileOutputs.First().ToFileArtifact().Path; var pipId = graph.TryGetProducer(FileArtifact.CreateOutputFile(RemapFragmentPath(fragmentOrigin, outputPath))); XAssert.IsTrue(pipId.IsValid); Process processInGraph = graph.PipTable.HydratePip(pipId, PipQueryContext.PipGraphGetProducingPip) as Process; XAssert.IsNotNull(processInGraph); string argumentsInFragment = processInFragment.Arguments.ToString(fragmentOrigin.Context.PathTable).ToUpperInvariant(); string argumentsInGraph = processInGraph.Arguments.ToString(Context.PathTable).ToUpperInvariant(); XAssert.AreEqual(argumentsInFragment, argumentsInGraph); }
private PipGraph DeserializeFragments(bool dependent, params TestPipGraphFragment[] fragments) { var fragmentManager = new PipGraphFragmentManager(LoggingContext, Context, PipGraphBuilder, default); for (int i = 0; i < fragments.Length; ++i) { TestPipGraphFragment fragment = fragments[i]; bool success = fragmentManager.AddFragmentFileToGraph( AbsolutePath.Create(Context.PathTable, GetIndexedFragmentPath(fragment, i)), fragment.ModuleName, i > 0 && dependent ? new[] { AbsolutePath.Create(Context.PathTable, GetIndexedFragmentPath(fragments[i - 1], i - 1)) } : new AbsolutePath[0]); XAssert.IsTrue(success, $"Adding fragment {fragment.ModuleName} from file '{GetFragmentPath(fragment)}' to graph is unsuccessful"); } Task.WaitAll(fragmentManager.GetAllFragmentTasks().Select(t => t.Item2).ToArray()); XAssert.IsTrue(fragmentManager.GetAllFragmentTasks().All(t => t.Item2.Result), "Adding all fragments to graph is unsuccessful"); return(PipGraphBuilder.Build()); }
/// <summary> /// Remaps a path produced by a fragment to path of the resulting graph. /// </summary> /// <param name="fragment">Fragment where the path originates.</param> /// <param name="path">A path.</param> /// <returns></returns> private AbsolutePath RemapFragmentPath(TestPipGraphFragment fragment, AbsolutePath path) => AbsolutePath.Create(Context.PathTable, path.ToString(fragment.Context.PathTable));
private string GetIndexedFragmentPath(TestPipGraphFragment fragment, int index) => GetFragmentPath(fragment) + "-" + index;
private string GetFragmentPath(TestPipGraphFragment fragment) => Path.Combine(TemporaryDirectory, fragment.ModuleName);
public static (IIpcMoniker ipcMoniker, PipId servicePipId) CreateService(TestPipGraphFragment fragment, ServiceRelatedPips pips = null) { var ipcMoniker = fragment.GetIpcMoniker(); var apiServerMoniker = fragment.GetApiServerMoniker(); var shutdownBuilder = fragment.GetProcessBuilder(); new ArgumentsBuilder(shutdownBuilder) .AddIpcMonikerOption("--ipcMoniker ", ipcMoniker) .AddIpcMonikerOption("--serverMoniker ", apiServerMoniker) .AddOutputFileOption("--output ", fragment.CreateOutputFile("shutdown.txt")) .Finish(); shutdownBuilder.ServiceKind = ServicePipKind.ServiceShutdown; (Process shutdownProcess, ProcessOutputs _) = fragment.ScheduleProcessBuilder(shutdownBuilder); var finalProcessBuilder = fragment.GetIpcProcessBuilder(); new ArgumentsBuilder(finalProcessBuilder) .AddStringOption("--command ", "final") .AddIpcMonikerOption("--ipcMoniker ", ipcMoniker) .Finish(); var finalOutputFile = fragment.CreateOutputFile("final.txt"); var finalizationPip = fragment.ScheduleIpcPip( ipcMoniker, null, finalProcessBuilder, finalOutputFile, true); XAssert.IsTrue(finalizationPip.PipId.IsValid); var serviceProcessBuilder = fragment.GetProcessBuilder(); new ArgumentsBuilder(serviceProcessBuilder) .AddIpcMonikerOption("--ipcMoniker ", ipcMoniker) .AddIpcMonikerOption("--serverMoniker ", apiServerMoniker) .AddOutputFileOption("--output ", fragment.CreateOutputFile("service.txt")) .Finish(); serviceProcessBuilder.ServiceKind = ServicePipKind.Service; serviceProcessBuilder.ShutDownProcessPipId = shutdownProcess.PipId; serviceProcessBuilder.FinalizationPipIds = ReadOnlyArray <PipId> .FromWithoutCopy(new[] { finalizationPip.PipId }); (Process serviceProcess, ProcessOutputs _) = fragment.ScheduleProcessBuilder(serviceProcessBuilder); var createProcessBuilder = fragment.GetIpcProcessBuilder(); new ArgumentsBuilder(createProcessBuilder) .AddStringOption("--command ", "create") .AddIpcMonikerOption("--ipcMoniker ", ipcMoniker) .Finish(); var createOutputFile = fragment.CreateOutputFile("create.txt"); var createPip = fragment.ScheduleIpcPip( ipcMoniker, serviceProcess.PipId, createProcessBuilder, createOutputFile, false); XAssert.IsTrue(createPip.PipId.IsValid); if (pips != null) { pips.ShutDown = shutdownProcess; pips.Final = finalizationPip; pips.ServiceStart = serviceProcess; pips.Create = createPip; } return(ipcMoniker, serviceProcess.PipId); }
/// <summary> /// Verifies that the file output by a fragment exists in the resulting graph. /// </summary> /// <param name="graph">Resulting graph.</param> /// <param name="fragmentOrigin">Graph fragment where the output originates.</param> /// <param name="outputPath">Path to output file.</param> private void VerifyProducerExists(PipGraph graph, TestPipGraphFragment fragmentOrigin, AbsolutePath outputPath) { var pipId = graph.TryGetProducer(FileArtifact.CreateOutputFile(RemapFragmentPath(fragmentOrigin, outputPath))); XAssert.IsTrue(pipId.IsValid, $"Producer of '{outputPath.ToString(fragmentOrigin.Context.PathTable)}' from fragment '{fragmentOrigin.ModuleName}' could not be found in the resulting graph"); }