예제 #1
0
        public void ContextPinsGlobExpansionCache(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var projectDirectory = _env.DefaultTestDirectory.FolderPath;

            _env.SetCurrentDirectory(projectDirectory);

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                _globProjects,
                context,
                project =>
            {
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount];
                evaluationCount++;

                File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.cs"), "");

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));
            }
                );
        }
        public void ReevaluationShouldNotReuseInitialContext(EvaluationContext.SharingPolicy policy)
        {
            try
            {
                EvaluationContext.TestOnlyHookOnCreate = c => SetResolverForContext(c, _resolver);

                var collection = _env.CreateProjectCollection().Collection;

                var context = EvaluationContext.Create(policy);

                var project = Project.FromXmlReader(
                    XmlReader.Create(new StringReader("<Project Sdk=\"foo\"></Project>")),
                    new ProjectOptions
                {
                    ProjectCollection = collection,
                    EvaluationContext = context,
                    LoadSettings      = ProjectLoadSettings.IgnoreMissingImports
                });

                _resolver.ResolvedCalls["foo"].ShouldBe(1);

                project.AddItem("a", "b");

                project.ReevaluateIfNecessary();

                _resolver.ResolvedCalls["foo"].ShouldBe(2);
            }
            finally
            {
                EvaluationContext.TestOnlyHookOnCreate = null;
            }
        }
        public void SharedContextShouldGetReusedWhereasIsolatedContextShouldNot(EvaluationContext.SharingPolicy policy)
        {
            var previousContext = EvaluationContext.Create(policy);

            for (var i = 0; i < 10; i++)
            {
                var currentContext = previousContext.ContextForNewProject();

                if (i == 0)
                {
                    currentContext.ShouldBeSameAs(previousContext, "first usage context was not the same as the initial context");
                }
                else
                {
                    switch (policy)
                    {
                    case EvaluationContext.SharingPolicy.Shared:
                        currentContext.ShouldBeSameAs(previousContext, $"Shared policy: usage {i} was not the same as usage {i - 1}");
                        break;

                    case EvaluationContext.SharingPolicy.Isolated:
                        currentContext.ShouldNotBeSameAs(previousContext, $"Isolated policy: usage {i} was the same as usage {i - 1}");
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(policy), policy, null);
                    }
                }

                previousContext = currentContext;
            }
        }
예제 #4
0
        public void ReevaluationShouldRespectContextLifetime(EvaluationContext.SharingPolicy policy)
        {
            var collection = _env.CreateProjectCollection().Collection;

            var context1 = EvaluationContext.Create(policy);

            var project = Project.FromXmlReader(
                XmlReader.Create(new StringReader("<Project></Project>")),
                new ProjectOptions
            {
                ProjectCollection = collection,
                EvaluationContext = context1,
                LoadSettings      = ProjectLoadSettings.IgnoreMissingImports
            });

            project.AddItem("a", "b");

            project.ReevaluateIfNecessary();

            var context2 = GetEvaluationContext(project);

            switch (policy)
            {
            case EvaluationContext.SharingPolicy.Shared:
                context1.ShouldBeSameAs(context2);
                break;

            case EvaluationContext.SharingPolicy.Isolated:
                context1.ShouldNotBeSameAs(context2);
                break;
            }
        }
        public void ProjectInstanceShouldRespectSharingPolicy(EvaluationContext.SharingPolicy policy)
        {
            try
            {
                var seenContexts = new HashSet <EvaluationContext>();

                EvaluationContext.TestOnlyHookOnCreate = c => seenContexts.Add(c);

                var collection = _env.CreateProjectCollection().Collection;

                var context = EvaluationContext.Create(policy);

                const int numIterations = 10;
                for (int i = 0; i < numIterations; i++)
                {
                    ProjectInstance.FromProjectRootElement(
                        ProjectRootElement.Create(),
                        new ProjectOptions
                    {
                        ProjectCollection = collection,
                        EvaluationContext = context,
                        LoadSettings      = ProjectLoadSettings.IgnoreMissingImports
                    });
                }

                int expectedNumContexts = policy == EvaluationContext.SharingPolicy.Shared ? 1 : numIterations;

                seenContexts.Count.ShouldBe(expectedNumContexts);
                seenContexts.ShouldAllBe(c => c.Policy == policy);
            }
            finally
            {
                EvaluationContext.TestOnlyHookOnCreate = null;
            }
        }
예제 #6
0
        public void ContextDisambiguatesRelativeGlobsOutsideOfProjectCone(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var project1Root          = _env.DefaultTestDirectory.CreateDirectory("Project1");
            var project1Directory     = project1Root.CreateDirectory("1").Path;
            var project1GlobDirectory = project1Root.CreateDirectory("Glob").CreateDirectory("1").Path;

            var project2Root          = _env.DefaultTestDirectory.CreateDirectory("Project2");
            var project2Directory     = project2Root.CreateDirectory("2").Path;
            var project2GlobDirectory = project2Root.CreateDirectory("Glob").CreateDirectory("2").Path;

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(project1GlobDirectory, $"1.{evaluationCount}.cs"), "");
            File.WriteAllText(Path.Combine(project2GlobDirectory, $"2.{evaluationCount}.cs"), "");

            EvaluateProjects(
                new []
            {
                new ProjectSpecification(
                    Path.Combine(project1Directory, "1"),
                    @"<Project>
                            <ItemGroup>
                                <i Include=`../Glob/**/*.cs` />
                            </ItemGroup>
                        </Project>"),
                new ProjectSpecification(
                    Path.Combine(project2Directory, "2"),
                    @"<Project>
                            <ItemGroup>
                                <i Include=`../Glob/**/*.cs` />
                            </ItemGroup>
                        </Project>")
            },
                context,
                project =>
            {
                var projectName = Path.GetFileNameWithoutExtension(project.FullPath);

                // globs have the fixed directory part prepended, so add it to the expected results
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]
                                            .Select(i => Path.Combine("..", "Glob", projectName, $"{projectName}.{i}"))
                                            .ToArray();

                var actualGlobExpansion = project.GetItems("i");
                ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion);

                evaluationCount++;

                File.WriteAllText(Path.Combine(project1GlobDirectory, $"1.{evaluationCount}.cs"), "");
                File.WriteAllText(Path.Combine(project2GlobDirectory, $"2.{evaluationCount}.cs"), "");
            }
                );
        }
        public void ContextCachesExistenceChecksInGetDirectoryNameOfFileAbove(EvaluationContext.SharingPolicy policy)
        {
            var context = EvaluationContext.Create(policy);

            var subdirectory     = _env.DefaultTestDirectory.CreateDirectory("subDirectory");
            var subdirectoryFile = subdirectory.CreateFile("a");

            _env.DefaultTestDirectory.CreateFile("a");

            int evaluationCount = 0;

            EvaluateProjects(
                new []
            {
                $@"<Project>
                      <PropertyGroup>
                        <SearchedPath>$([MSBuild]::GetDirectoryNameOfFileAbove('{subdirectory.Path}', 'a'))</SearchedPath>
                      </PropertyGroup>
                    </Project>"
            },
                context,
                project =>
            {
                evaluationCount++;

                var searchedPath = project.GetProperty("SearchedPath");

                switch (policy)
                {
                case EvaluationContext.SharingPolicy.Shared:
                    searchedPath.EvaluatedValue.ShouldBe(subdirectory.Path);
                    break;

                case EvaluationContext.SharingPolicy.Isolated:
                    searchedPath.EvaluatedValue.ShouldBe(
                        evaluationCount == 1
                                    ? subdirectory.Path
                                    : _env.DefaultTestDirectory.Path);
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(policy), policy, null);
                }

                if (evaluationCount == 1)
                {
                    // this will cause the upper file to get picked up in the Isolated policy
                    subdirectoryFile.Delete();
                }
            });

            evaluationCount.ShouldBe(2);
        }
        public void ContextCachesExistenceChecksInConditions(EvaluationContext.SharingPolicy policy)
        {
            var projectDirectory = _env.DefaultTestDirectory.FolderPath;

            _env.SetCurrentDirectory(projectDirectory);

            var context = EvaluationContext.Create(policy);

            var theFile = Path.Combine(projectDirectory, "0.cs");

            File.WriteAllText(theFile, "");

            var evaluationCount = 0;

            EvaluateProjects(
                _projectsWithConditions,
                context,
                project =>
            {
                evaluationCount++;

                if (File.Exists(theFile))
                {
                    File.Delete(theFile);
                }

                if (evaluationCount == 1)
                {
                    project.GetPropertyValue("p").ShouldBe("val");
                }
                else
                {
                    switch (policy)
                    {
                    case EvaluationContext.SharingPolicy.Shared:
                        project.GetPropertyValue("p").ShouldBe("val");
                        break;

                    case EvaluationContext.SharingPolicy.Isolated:
                        project.GetPropertyValue("p").ShouldBeEmpty();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(policy), policy, null);
                    }
                }
            }
                );
        }
예제 #9
0
        public void ContextDisambiguatesRelativeGlobsUnderProjectCone(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var projectDirectory1 = _env.DefaultTestDirectory.CreateDirectory("1").Path;
            var projectDirectory2 = _env.DefaultTestDirectory.CreateDirectory("2").Path;

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(projectDirectory1, $"1.{evaluationCount}.cs"), "");
            File.WriteAllText(Path.Combine(projectDirectory2, $"2.{evaluationCount}.cs"), "");

            EvaluateProjects(
                new []
            {
                new ProjectSpecification(
                    Path.Combine(projectDirectory1, "1"),
                    @"<Project>
                            <ItemGroup>
                                <i Include=`**/*.cs` />
                            </ItemGroup>
                        </Project>"),
                new ProjectSpecification(
                    Path.Combine(projectDirectory2, "2"),
                    @"<Project>
                            <ItemGroup>
                                <i Include=`**/*.cs` />
                            </ItemGroup>
                        </Project>"),
            },
                context,
                project =>
            {
                var projectName = Path.GetFileNameWithoutExtension(project.FullPath);

                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]
                                            .Select(i => $"{projectName}.{i}")
                                            .ToArray();

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));

                evaluationCount++;

                File.WriteAllText(Path.Combine(projectDirectory1, $"1.{evaluationCount}.cs"), "");
                File.WriteAllText(Path.Combine(projectDirectory2, $"2.{evaluationCount}.cs"), "");
            }
                );
        }
예제 #10
0
        public void ContextSdkResolverIsUsed(EvaluationContext.SharingPolicy policy, int sdkLookupsForFoo, int sdkLookupsForBar)
        {
            try
            {
                EvaluationContext.TestOnlyAlterStateOnCreate = c => SetResolverForContext(c, _resolver);

                var context = EvaluationContext.Create(policy);
                EvaluateProjects(context);

                _resolver.ResolvedCalls["foo"].ShouldBe(sdkLookupsForFoo);
                _resolver.ResolvedCalls["bar"].ShouldBe(sdkLookupsForBar);
                _resolver.ResolvedCalls.Count.ShouldBe(2);
            }
            finally
            {
                EvaluationContext.TestOnlyAlterStateOnCreate = null;
            }
        }
        public void ContextPinsSdkResolverCache(EvaluationContext.SharingPolicy policy, int sdkLookupsForFoo, int sdkLookupsForBar)
        {
            try
            {
                EvaluationContext.TestOnlyHookOnCreate = c => SetResolverForContext(c, _resolver);

                var context = EvaluationContext.Create(policy);
                EvaluateProjects(_sdkResolutionProjects, context, null);

                _resolver.ResolvedCalls.Count.ShouldBe(2);
                _resolver.ResolvedCalls["foo"].ShouldBe(sdkLookupsForFoo);
                _resolver.ResolvedCalls["bar"].ShouldBe(sdkLookupsForBar);
            }
            finally
            {
                EvaluationContext.TestOnlyHookOnCreate = null;
            }
        }
        public void ContextCachesImportGlobExpansions(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var projectDirectory = _env.DefaultTestDirectory.Path;

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.props"), $"<Project><ItemGroup><i Include=`{evaluationCount}.cs`/></ItemGroup></Project>".Cleanup());

            EvaluateProjects(
                _projectsWithGlobImports,
                context,
                project =>
            {
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount];
                evaluationCount++;

                File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.props"), $"<Project><ItemGroup><i Include=`{evaluationCount}.cs`/></ItemGroup></Project>".Cleanup());

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));
            }
                );
        }
        private void ContextCachesCommonOutOfProjectCone(bool itemSpecPathIsRelative, EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var testDirectory = _env.DefaultTestDirectory;
            var globDirectory = testDirectory.CreateDirectory("GlobDirectory");

            var itemSpecDirectoryPart = itemSpecPathIsRelative
                ? Path.Combine("..", "GlobDirectory")
                : globDirectory.Path;

            Directory.CreateDirectory(globDirectory.Path);

            // Globs with a directory part will produce items prepended with that directory part
            foreach (var globExpansion in expectedGlobExpansions)
            {
                for (var i = 0; i < globExpansion.Length; i++)
                {
                    globExpansion[i] = Path.Combine(itemSpecDirectoryPart, globExpansion[i]);
                }
            }

            var projectSpecs = new[]
            {
                $@"<Project>
                <ItemGroup>
                    <i Include=`{Path.Combine("{0}", "**", "*.cs")}`/>
                </ItemGroup>
            </Project>",
                $@"<Project>
                <ItemGroup>
                    <i Include=`{Path.Combine("{0}", "**", "*.cs")}`/>
                </ItemGroup>
            </Project>"
            }
            .Select(p => string.Format(p, itemSpecDirectoryPart))
            .Select((p, i) => new ProjectSpecification(Path.Combine(testDirectory.Path, $"ProjectDirectory{i}", $"Project{i}.proj"), p));

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                projectSpecs,
                context,
                project =>
            {
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount];
                evaluationCount++;

                File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), "");

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));
            }
                );
        }
 // projects should cache glob expansions when the __relative__ glob is shared between projects and points outside of project cone
 public void ContextCachesCommonOutOfProjectConeRelativeGlob(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
 {
     ContextCachesCommonOutOfProjectCone(itemSpecPathIsRelative: true, policy: policy, expectedGlobExpansions: expectedGlobExpansions);
 }
        public void ContextDisambiguatesDistinctRelativeGlobsPointingOutsideOfSameProjectCone(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var globDirectory = _env.DefaultTestDirectory.CreateDirectory("glob");

            var projectRoot = _env.DefaultTestDirectory.CreateDirectory("proj");

            var project1Directory = projectRoot.CreateDirectory("Project1");

            var project2SubDir = projectRoot.CreateDirectory("subdirectory");

            var project2Directory = project2SubDir.CreateDirectory("Project2");

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                new []
            {
                new ProjectSpecification(
                    Path.Combine(project1Directory.Path, "1"),
                    @"<Project>
                            <ItemGroup>
                                <i Include=`../../glob/*.cs` />
                            </ItemGroup>
                        </Project>"),
                new ProjectSpecification(
                    Path.Combine(project2Directory.Path, "2"),
                    @"<Project>
                            <ItemGroup>
                                <i Include=`../../../glob/*.cs` />
                            </ItemGroup>
                        </Project>")
            },
                context,
                project =>
            {
                var projectName            = Path.GetFileNameWithoutExtension(project.FullPath);
                var globFixedDirectoryPart = projectName.EndsWith("1")
                        ? Path.Combine("..", "..", "glob")
                        : Path.Combine("..", "..", "..", "glob");

                // globs have the fixed directory part prepended, so add it to the expected results
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]
                                            .Select(i => Path.Combine(globFixedDirectoryPart, i))
                                            .ToArray();

                var actualGlobExpansion = project.GetItems("i");
                ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion);

                evaluationCount++;

                File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), "");
            }
                );
        }
        public void ContextDisambiguatesAFullyQualifiedGlobPointingInAnotherRelativeGlobsCone(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            if (policy == EvaluationContext.SharingPolicy.Shared)
            {
                // This test case has a dependency on our glob expansion caching policy. If the evaluation context is reused
                // between evaluations and files are added to the filesystem between evaluations, the cache may be returning
                // stale results. Run only the Isolated variant.
                return;
            }

            var project1Directory     = _env.DefaultTestDirectory.CreateDirectory("Project1");
            var project1GlobDirectory = project1Directory.CreateDirectory("Glob").CreateDirectory("1").Path;

            var project2Directory = _env.DefaultTestDirectory.CreateDirectory("Project2");

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(project1GlobDirectory, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                new []
            {
                // first project uses a relative path
                new ProjectSpecification(
                    Path.Combine(project1Directory.Path, "1"),
                    $@"<Project>
                            <ItemGroup>
                                <i Include=`{Path.Combine("Glob", "**", "*.cs")}` />
                            </ItemGroup>
                        </Project>"),
                // second project reaches out into first project's cone via a fully qualified path
                new ProjectSpecification(
                    Path.Combine(project2Directory.Path, "2"),
                    $@"<Project>
                            <ItemGroup>
                                <i Include=`{Path.Combine(project1Directory.Path, "Glob", "**", "*.cs")}` />
                            </ItemGroup>
                        </Project>")
            },
                context,
                project =>
            {
                var projectName = Path.GetFileNameWithoutExtension(project.FullPath);

                // globs have the fixed directory part prepended, so add it to the expected results
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]
                                            .Select(i => Path.Combine("Glob", "1", i))
                                            .ToArray();

                // project 2 has fully qualified directory parts, so make the results for 2 fully qualified
                if (projectName.Equals("2"))
                {
                    expectedGlobExpansion = expectedGlobExpansion
                                            .Select(i => Path.Combine(project1Directory.Path, i))
                                            .ToArray();
                }

                var actualGlobExpansion = project.GetItems("i");
                ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion);

                evaluationCount++;

                File.WriteAllText(Path.Combine(project1GlobDirectory, $"{evaluationCount}.cs"), "");
            }
                );
        }
        // projects should cache glob expansions when the glob is shared between projects and points outside of project cone
        public void ContextCachesCommonOutOfProjectConeGlob(bool itemSpecPathIsRelative, EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var testDirectory = _env.DefaultTestDirectory.FolderPath;
            var globDirectory = Path.Combine(testDirectory, "GlobDirectory");

            var itemSpecDirectoryPart = itemSpecPathIsRelative
                ? Path.Combine("..", "GlobDirectory")
                : globDirectory;

            itemSpecDirectoryPart = itemSpecDirectoryPart.WithTrailingSlash();

            Directory.CreateDirectory(globDirectory);

            // Globs with a directory part will produce items prepended with that directory part
            foreach (var globExpansion in expectedGlobExpansions)
            {
                for (var i = 0; i < globExpansion.Length; i++)
                {
                    globExpansion[i] = Path.Combine(itemSpecDirectoryPart, globExpansion[i]);
                }
            }

            var projectSpecs = _projectsWithOutOfConeGlobs
                               .Select(p => string.Format(p, itemSpecDirectoryPart))
                               .Select((p, i) => new ProjectSpecification(Path.Combine(testDirectory, $"ProjectDirectory{i}", $"Project{i}.proj"), p));

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(globDirectory, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                projectSpecs,
                context,
                project =>
            {
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount];
                evaluationCount++;

                File.WriteAllText(Path.Combine(globDirectory, $"{evaluationCount}.cs"), "");

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));
            }
                );
        }