Exemple #1
0
        public void CompatibleFrameworksInPackage()
        {
            TestProject testProject = new()
            {
                Name             = "TestPackage",
                TargetFrameworks = "netstandard2.0;net5.0",
            };

            string sourceCode = @"
namespace PackageValidationTests
{
    public class First
    {
        public void test() { }
#if NETSTANDARD2_0
        public void test(string test) { }
#endif
    }
}";

            testProject.SourceFiles.Add("Hello.cs", sourceCode);
            TestAsset   asset       = _testAssetsManager.CreateTestProject(testProject, testProject.Name);
            PackCommand packCommand = new PackCommand(Log, Path.Combine(asset.TestRoot, testProject.Name));
            var         result      = packCommand.Execute();

            Assert.Equal(string.Empty, result.StdErr);
            Package package = NupkgParser.CreatePackage(packCommand.GetNuGetPackage(), null);

            new CompatibleFrameworkInPackageValidator(string.Empty, null, _log).Validate(package);
            Assert.NotEmpty(_log.errors);
            // TODO: add asserts for assembly and header metadata.
            Assert.Contains("CP0002 Member 'PackageValidationTests.First.test(string)' exists on the left but not on the right", _log.errors);
        }
Exemple #2
0
        protected override void ExecuteCore()
        {
            RuntimeGraph runtimeGraph = null;

            if (!string.IsNullOrEmpty(RuntimeGraph))
            {
                runtimeGraph = JsonRuntimeFormat.ReadRuntimeGraph(RuntimeGraph);
            }

            Dictionary <string, HashSet <string> > apiCompatReferences = new();

            if (ReferencePaths != null)
            {
                foreach (ITaskItem taskItem in ReferencePaths)
                {
                    string tfm = taskItem.GetMetadata("TargetFramework");
                    if (string.IsNullOrEmpty(tfm))
                    {
                        continue;
                    }

                    string referencePath = taskItem.GetMetadata("Identity");
                    if (!File.Exists(referencePath))
                    {
                        continue;
                    }

                    if (!apiCompatReferences.TryGetValue(tfm, out HashSet <string> directories))
                    {
                        directories = new();
                        apiCompatReferences.Add(tfm, directories);
                    }

                    directories.Add(referencePath);
                }
            }

            Package             package = NupkgParser.CreatePackage(PackageTargetPath, runtimeGraph);
            CompatibilityLogger logger  = new(Log, CompatibilitySuppressionFilePath, GenerateCompatibilitySuppressionFile);

            new CompatibleTfmValidator(NoWarn, null, RunApiCompat, EnableStrictModeForCompatibleTfms, logger, apiCompatReferences).Validate(package);
            new CompatibleFrameworkInPackageValidator(NoWarn, null, EnableStrictModeForCompatibleFrameworksInPackage, logger, apiCompatReferences).Validate(package);

            if (!DisablePackageBaselineValidation && !string.IsNullOrEmpty(BaselinePackageTargetPath))
            {
                Package baselinePackage = NupkgParser.CreatePackage(BaselinePackageTargetPath, runtimeGraph);
                new BaselinePackageValidator(baselinePackage, NoWarn, null, RunApiCompat, logger, apiCompatReferences).Validate(package);
            }

            if (GenerateCompatibilitySuppressionFile)
            {
                logger.GenerateSuppressionsFile(CompatibilitySuppressionFilePath);
            }
        }
Exemple #3
0
        public void MultipleCompatibleFrameworksInPackage()
        {
            string      name        = Path.GetFileNameWithoutExtension(Path.GetTempFileName());
            TestProject testProject = new()
            {
                Name             = name,
                TargetFrameworks = "netstandard2.0;netcoreapp3.1;net5.0",
            };

            string sourceCode = @"
namespace PackageValidationTests
{
    public class First
    {
        public void test() { }
#if NETSTANDARD2_0
        public void test(string test) { }
#endif
#if NETCOREAPP3_1
        public void test(bool test) { }
#endif
    }
}";

            testProject.SourceFiles.Add("Hello.cs", sourceCode);
            TestAsset   asset       = _testAssetsManager.CreateTestProject(testProject, testProject.Name);
            PackCommand packCommand = new PackCommand(Log, Path.Combine(asset.TestRoot, testProject.Name));
            var         result      = packCommand.Execute();

            Assert.Equal(string.Empty, result.StdErr);
            Package package = NupkgParser.CreatePackage(packCommand.GetNuGetPackage(), null);

            new CompatibleFrameworkInPackageValidator(string.Empty, null, false, _log).Validate(package);
            Assert.NotEmpty(_log.errors);

            string assemblyName = $"{asset.TestProject.Name}.dll";

            // TODO: add asserts for assembly and header metadata.
            Assert.Contains($"CP0002 Member 'PackageValidationTests.First.test(string)' exists on lib/netstandard2.0/{assemblyName} but not on lib/netcoreapp3.1/{assemblyName}", _log.errors);
            Assert.Contains($"CP0002 Member 'PackageValidationTests.First.test(bool)' exists on lib/netcoreapp3.1/{assemblyName} but not on lib/net5.0/{assemblyName}", _log.errors);
        }
Exemple #4
0
        public void ValidatePackageWithReferences()
        {
            TestLogger log = new TestLogger();

            string testDependencySource = @"namespace PackageValidationTests { public class ItermediateBaseClass
#if NETSTANDARD2_0
: IBaseInterface 
#endif
{ } }";

            TestProject testSubDependency = CreateTestProject(@"namespace PackageValidationTests { public interface IBaseInterface { } }", "netstandard2.0");
            TestProject testDependency    = CreateTestProject(
                testDependencySource,
                "netstandard2.0;net5.0",
                new[] { testSubDependency });
            TestProject testProject = CreateTestProject(@"namespace PackageValidationTests { public class First : ItermediateBaseClass { } }", "netstandard2.0;net5.0", new[] { testDependency });

            TestAsset   asset       = _testAssetsManager.CreateTestProject(testProject, testProject.Name);
            PackCommand packCommand = new PackCommand(Log, Path.Combine(asset.TestRoot, testProject.Name));
            var         result      = packCommand.Execute();

            Assert.Equal(string.Empty, result.StdErr);
            Package package = NupkgParser.CreatePackage(packCommand.GetNuGetPackage(), null);

            // First we run without references. Without references, ApiCompat should not be able to see that class First
            // removed an interface due to it's base class removing that implementation. We validate that APICompat doesn't
            // log errors when not using references.
            new CompatibleFrameworkInPackageValidator("CP1003", null, false, log, null).Validate(package);
            Assert.Empty(log.errors);

            // Now we do pass in references. With references, ApiCompat should now detect that an interface was removed in a
            // dependent assembly, causing one of our types to stop implementing that assembly. We validate that a CP0008 is logged.
            Dictionary <string, HashSet <string> > references = new()
            {
                { "netstandard2.0", new HashSet <string> {
                      Path.Combine(asset.TestRoot, asset.TestProject.Name, "bin", "Debug", "netstandard2.0")
                  } },
                { "net5.0", new HashSet <string> {
                      Path.Combine(asset.TestRoot, asset.TestProject.Name, "bin", "Debug", "net5.0")
                  } }
            };