public async Task TestSpec2SpecMapGeneratedByTypeChecker(SimpleGraph file2file) { var helper = new WorkspaceEvaluationHelper(TestOutputDirectory, null, forTesting: true); var repo = GenerateFullWorkspaceRepo(helper, file2file); var workspace = await helper.ParseAsync(repo); var semanticModel = helper.Typecheck(workspace); Func <int, AbsolutePath> specIdxToSpecPath = (specIdx) => SpecIdxToSpecPath(repo, specIdx); var relevantSpecPaths = file2file.Nodes.Select(specIdxToSpecPath).ToList(); Func <RoaringBitSet, IEnumerable <AbsolutePath> > materializeRelevant = (bitSet) => { bitSet.MaterializeSetIfNeeded(string.Empty, (s, i) => workspace.GetAllSourceFiles()[i].GetAbsolutePath(helper.PathTable)); return(bitSet.MaterializedSetOfPaths.Intersect(relevantSpecPaths)); }; // test the spec2spec map generated by TypeChecker XAssert.All( file2file.Nodes, specIdx => { var specSourceFile = workspace.GetSourceFile(SpecIdxToSpecPath(repo, specIdx)); var computedDependencies = materializeRelevant(semanticModel.GetFileDependenciesOf(specSourceFile)); var computedDependents = materializeRelevant(semanticModel.GetFileDependentFilesOf(specSourceFile)); var expectedDependents = file2file.OutgoingEdges(specIdx).Select(e => specIdxToSpecPath(e.Dest)); var expectedDependencies = file2file.IncomingEdges(specIdx).Select(e => specIdxToSpecPath(e.Src)); XAssert.SetEqual(expectedDependencies, computedDependents); XAssert.SetEqual(expectedDependents, computedDependencies); }); }
private async Task DoPartialEvalTest(SimpleGraph file2file, int[] changed, int[] expectedDownstream, int[] expectedUpstream, int[] expectedIndirectUpstream, int[] expectedAffected) { ComputeAndCheckSpecStates(file2file, changed, expectedDownstream, expectedUpstream, expectedIndirectUpstream, expectedAffected); // helpers var helper = new WorkspaceEvaluationHelper(TestOutputDirectory, null, forTesting: true); var repo = GenerateFullWorkspaceRepo(helper, file2file); Func <int, AbsolutePath> specIdxToSpecPath = (specIdx) => SpecIdxToSpecPath(repo, specIdx); // create workspace and semantic model var workspace = await helper.ParseAsync(repo); var semanticModel = helper.Typecheck(workspace); var changedWithDownstream = changed.Union(expectedDownstream).ToArray(); var changedWithDownstreamPaths = changedWithDownstream.Select(specIdxToSpecPath).ToArray(); // test workspace 'closure of dependent files' computation var specDepProvider = new WorkspaceBasedSpecDependencyProvider(workspace, helper.PathTable); var dependentPathsClosure = specDepProvider.ComputeReflectiveClosureOfDependentFiles(changed.Select(specIdxToSpecPath)); XAssert.SetEqual(changedWithDownstreamPaths.ToStrings(helper.PathTable), dependentPathsClosure.ToStrings(helper.PathTable)); // test workspace 'closure of dependency files' computation var dependencyPathsClosure = specDepProvider .ComputeReflectiveClosureOfDependencyFiles(changedWithDownstreamPaths) .Intersect(file2file.Nodes.Select(specIdxToSpecPath)); // this leaves only spec files from TestModule, i.e., filters out prelude files etc. var expectedAffectedPaths = expectedAffected.Select(specIdxToSpecPath); XAssert.SetEqual(expectedAffectedPaths.ToStrings(helper.PathTable), dependencyPathsClosure.ToStrings(helper.PathTable)); // full evaluation var interpreter = await helper.ConvertAsync(workspace, oldPipGraph : null); var pipGraph = await helper.EvaluateAsync(workspace, interpreter); AssertPipGraphContent(pipGraph, file2file, helper.StringTable); // partial evaluation var helper2 = new WorkspaceEvaluationHelper(TestOutputDirectory, helper.FrontEndContext, forTesting: true); var partialRepo = GenerateWorkspaceRepo(helper2, file2file, expectedAffected); var pipGraph2 = await helper2.EvaluateWithGraphPatchingAsync( repo : partialRepo, oldPipGraph : pipGraph, changedSpecs : changedWithDownstreamPaths, specsToIgnore : expectedUpstream.Union(expectedIndirectUpstream).Select(specIdxToSpecPath)); // assert we still get the full graph AssertPipGraphContent(pipGraph2, file2file, helper2.StringTable); }
private ModuleRepository GenerateWorkspaceRepo(WorkspaceEvaluationHelper helper, SimpleGraph file2file, int[] selectedFiles) { XAssert.IsTrue(file2file.IsDAG(), "Must be a DAG"); var specs = selectedFiles .Select(i => { var specsToImport = file2file.OutgoingEdges(i).Select(e => e.Dest).ToList(); var specContent = GenerateSpec(i, specsToImport); return(new ModuleRepository.NameContentPair(GetSpecName(i), specContent)); }) .Concat(new[] { new ModuleRepository.NameContentPair(HelperSpecName, GetHelperSpecContent()), new ModuleRepository.NameContentPair(Qualifier, GetSpecWithDefaultQualifierContent()), }) .ToArray(); return(helper.NewModuleRepoWithPrelude().AddContent(TestModule, specs)); }
public async Task TestSimple() { const string Spec0 = "import {Transformer} from 'Sdk.Transformers';\r\nexport const x = Transformer.copyFile(f`src-x.txt`, Context.getNewOutputDirectory('test').combine('dest-x.txt'));"; const string Spec1 = "import {Transformer} from 'Sdk.Transformers';\r\nexport const y = Transformer.copyFile(f`src-y.txt`, Context.getNewOutputDirectory('test').combine('dest-y.txt'));"; var helperFull = new WorkspaceEvaluationHelper(TestOutputDirectory, context: null, forTesting: true); var testModule = ModuleDescriptor.CreateForTesting("MyModule1"); // evaluate full var repo = helperFull.NewModuleRepoWithPrelude().AddContent(testModule, Spec0, Spec1); var pipGraph = await helperFull.EvaluateAsync(repo); var fullGraphPipCounts = new Dictionary <PipType, int> { [PipType.CopyFile] = 2, }; AssertPipGraphCounts(pipGraph, fullGraphPipCounts); // evaluate partial without patching --> result is a smaller graph { var helperPartial = new WorkspaceEvaluationHelper(TestOutputDirectory, context: helperFull.FrontEndContext, forTesting: true); var partialRepo = helperPartial.NewModuleRepoWithPrelude().AddContent(testModule, Spec0); var newPipGraph = await helperPartial.EvaluateAsync(partialRepo); AssertPipGraphCounts(newPipGraph, new Dictionary <PipType, int> { [PipType.CopyFile] = 1, }); } // evaluate partial with patching --> same as full graph { // NOTE: must start with previous PathTable, because some paths from the old build might not be seen in the partial workspace var helperPartial = new WorkspaceEvaluationHelper(TestOutputDirectory, context: helperFull.FrontEndContext, forTesting: true); var partialRepo = helperPartial.NewModuleRepoWithPrelude().AddContent(testModule, Spec0); var changedSpecs = new[] { repo.GetPathToModuleAndSpec(testModule, 0) }; var newPipGraph = await helperPartial.EvaluateWithGraphPatchingAsync(partialRepo, oldPipGraph : pipGraph, changedSpecs : changedSpecs, specsToIgnore : null); AssertPipGraphCounts(newPipGraph, fullGraphPipCounts); } }
private ModuleRepository GenerateFullWorkspaceRepo(WorkspaceEvaluationHelper helper, SimpleGraph file2file) { return(GenerateWorkspaceRepo(helper, file2file, selectedFiles: file2file.Nodes.ToArray())); }