Пример #1
0
        public void When_comparing_testProject_reporting_works()
        {
            Stream   htmlReport        = new MemoryStream();
            Stream   xmlReport         = new MemoryStream();
            Assembly newAssembly       = Assembly.ReflectionOnlyLoadFrom(@"TestProject\Version2\ApiCheckTestProject.dll");
            Assembly referenceAssembly = Assembly.ReflectionOnlyLoadFrom(@"TestProject\Version1\ApiCheckTestProject.dll");
            int      logCount          = 0;

            int returnValue = -1;

            Assert.DoesNotThrow(
                () =>
                returnValue = ApiComparer.CreateInstance(referenceAssembly, newAssembly)
                              .WithDetailLogging(s => logCount++)
                              .WithInfoLogging(s => logCount++)
                              .WithHtmlReport(htmlReport)
                              .WithXmlReport(xmlReport)
                              .Build()
                              .CheckApi());

            Assert.Greater(htmlReport.Length, 0);
            Assert.Greater(xmlReport.Length, 0);
            Assert.Greater(logCount, 0);
            Assert.AreEqual(62, returnValue);
        }
Пример #2
0
        private IEnumerable <ApiTestData> GetResults()
        {
            using (AssemblyLoader assemblyLoader = new AssemblyLoader())
            {
                object[] customAttributes = GetType().GetCustomAttributes(typeof(ApiTestAttribute), true);
                if (customAttributes.Length == 0)
                {
                    throw new Exception(string.Format("The test class should define the {0} at least once", typeof(ApiTestAttribute)));
                }
                foreach (object customAttribute in customAttributes)
                {
                    ApiTestAttribute apiTestAttribute = (ApiTestAttribute)customAttribute;

                    Stream comparerConfigurationStream          = GetReadStream(apiTestAttribute.ComparerConfigurationPath);
                    ComparerConfiguration comparerConfiguration = ConfigurationLoader.LoadComparerConfiguration(comparerConfigurationStream);

                    ApiComparer apiComparer = ApiComparer.CreateInstance(assemblyLoader.ReflectionOnlyLoad(apiTestAttribute.ReferenceVersionPath),
                                                                         assemblyLoader.ReflectionOnlyLoad(apiTestAttribute.NewVersionPath))
                                              .WithComparerConfiguration(comparerConfiguration)
                                              .Build();
                    apiComparer.CheckApi();
                    yield return(new ApiTestData(apiComparer.ComparerResult, apiTestAttribute.Category, apiTestAttribute.Explicit, apiTestAttribute.HandleWarningsAsErrors));
                }
            }
        }
Пример #3
0
        private static void HasNotChanged(Type type)
        {
            var projectResolver = new ProjectResolver();

            var typeLoader  = new ReflectionTypeLoader();
            var projectInfo = projectResolver.GetProjectInfo(type);

            var api = typeLoader.LoadApi(type);

            Directory.CreateDirectory(projectInfo.TestFolderPath);
            if (!projectResolver.ApiFileExists(projectInfo, type))
            {
                projectResolver.WriteApiToFile(projectInfo, type, api);
                return;
            }

            var existingApi = projectResolver.ReadApiFromFile(projectInfo, type);

            var compareStrategy = new BestGuessEndpointMatchingStrategy();
            var comparer        = new ApiComparer(compareStrategy);

            comparer.Compare(existingApi, api);

            // Nice to have:
            // Fields / Events / Delegates
            // Supporting constructor arguments on attributes
            // Multiple public types per file
            // custom struct as type
            // Re-generate the output file if there are changes to the API that aren't breaking
        }
Пример #4
0
        public void When_passing_null_should_not_throw()
        {
            Assembly assembly1 = ApiBuilder.CreateApi().Build();
            Assembly assembly2 = ApiBuilder.CreateApi().Build();

            Assert.DoesNotThrow(
                () => ApiComparer.CreateInstance(assembly1, assembly2).WithDetailLogging(null).WithHtmlReport(null).WithComparerConfiguration(null).WithInfoLogging(null).WithXmlReport(null).Build().CheckApi());
        }
Пример #5
0
 public int CheckAssemblies()
 {
     return(ApiComparer.CreateInstance(_referenceAssembly, _newAssembly)
            .WithComparerConfiguration(_comparerConfiguration)
            .WithDetailLogging(_log)
            .WithInfoLogging(_log)
            .WithHtmlReport(_htmlStream)
            .WithXmlReport(_xmlStream)
            .Build().CheckApi());
 }
Пример #6
0
        public void When_comparing_two_assemblies_reports_are_generated()
        {
            Assembly assembly1 = ApiBuilder.CreateApi().Class().Build().Build();
            Assembly assembly2 = ApiBuilder.CreateApi().Class().Build().Build();

            using (MemoryStream xmlStream = new MemoryStream())
                using (MemoryStream htmlStream = new MemoryStream())
                {
                    ApiComparer.CreateInstance(assembly1, assembly2).WithHtmlReport(htmlStream).WithXmlReport(xmlStream).Build().CheckApi();

                    Assert.Greater(htmlStream.Length, 0);
                    Assert.Greater(xmlStream.Length, 0);
                }
        }
Пример #7
0
 private IEnumerable <ApiTestData> GetResults()
 {
     using (AssemblyLoader assemblyLoader = new AssemblyLoader())
     {
         object[] customAttributes = GetType().GetCustomAttributes(typeof(ApiTestAttribute), true);
         if (customAttributes.Length == 0)
         {
             throw new Exception(string.Format("The test class should define the {0} at least once", typeof(ApiTestAttribute)));
         }
         foreach (object customAttribute in customAttributes)
         {
             ApiTestAttribute apiTestAttribute = (ApiTestAttribute)customAttribute;
             ApiComparer      apiComparer      = ApiComparer.CreateInstance(assemblyLoader.ReflectionOnlyLoad(apiTestAttribute.ReferenceVersionPath),
                                                                            assemblyLoader.ReflectionOnlyLoad(apiTestAttribute.NewVersionPath))
                                                 .Build();
             apiComparer.CheckApi();
             IList <string> ignoreList = IgnoreListLoader.LoadIgnoreList(GetReadStream(apiTestAttribute.IgnoreListPath));
             yield return(new ApiTestData(apiComparer.ComparerResult, apiTestAttribute.Category, ignoreList, apiTestAttribute.Explicit));
         }
     }
 }
Пример #8
0
        public void When_checking_with_logging_should_write_to_stream()
        {
            Assembly assembly1 = ApiBuilder.CreateApi().Class().Build().Build();
            Assembly assembly2 = ApiBuilder.CreateApi().Class().Build().Build();

            using (MemoryStream detailStream = new MemoryStream())
                using (MemoryStream infoStream = new MemoryStream())
                {
                    StreamWriter infoLog = new StreamWriter(infoStream)
                    {
                        AutoFlush = true
                    };
                    StreamWriter detailLog = new StreamWriter(detailStream)
                    {
                        AutoFlush = true
                    };

                    ApiComparer.CreateInstance(assembly1, assembly2).WithInfoLogging(infoLog.WriteLine).WithDetailLogging(detailLog.WriteLine).Build().CheckApi();

                    Assert.Greater(infoStream.Length, 0);
                    Assert.Greater(detailStream.Length, 0);
                }
        }
        void RunApiCheck(string packageName)
        {
            Console.WriteLine(">>>> Checking Api breaking change for: " + packageName + Environment.NewLine);

            var refAssemblyPath = Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\Resource\refAssemblies\" + packageName + ".dll");
            var devAssemblyPath = Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\Resource\devAssemblies\" + packageName + ".dll");
            var reportPath      = Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\Resource\reports\" + packageName + ".report.xml");
            var sb      = new StringBuilder();
            var succeed = true;

            try
            {
                using (AssemblyLoader assemblyLoader = new AssemblyLoader())
                {
                    // load assemblies
                    Assembly refAssembly = assemblyLoader.ReflectionOnlyLoad(refAssemblyPath);
                    Assembly devAssembly = assemblyLoader.ReflectionOnlyLoad(devAssemblyPath);

                    // configuration
                    ComparerConfiguration configuration = new ComparerConfiguration();
                    configuration.Severities.ParameterNameChanged = Severity.Warning;
                    configuration.Severities.AssemblyNameChanged  = Severity.Hint;
                    foreach (var allowedBreakingChange in _allowedApiBreakingChanges)
                    {
                        configuration.Ignore.Add(allowedBreakingChange);
                    }

                    // compare assemblies and write xml report
                    using (var stream = new FileStream(reportPath, FileMode.Create))
                    {
                        ApiComparer.CreateInstance(refAssembly, devAssembly)
                        .WithComparerConfiguration(configuration)
                        .WithDetailLogging(s => Console.WriteLine(s))
                        .WithInfoLogging(s => Console.WriteLine(s))
                        .WithXmlReport(stream)
                        .Build()
                        .CheckApi();
                    }
                }

                var scenarioList = new List <string>()
                {
                    "ChangedAttribute", "ChangedElement", "RemovedElement"
                };

                // check the scenarios that we might have a breaking change
                foreach (var scenario in scenarioList)
                {
                    XElement doc = XElement.Load(reportPath);

                    foreach (XElement change in doc.Descendants(scenario))
                    {
                        if (change.Attribute("Severity") != null && "Error".Equals(change.Attribute("Severity").Value))
                        {
                            succeed = false;

                            // append the parent, for instance,
                            if (change.Parent != null)
                            {
                                sb.AppendLine($"In {change.Parent.Attribute("Context").Value} : {change.Parent.Attribute("Name").Value}");
                            }

                            sb.AppendLine(change.ToString());
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ApiChangeException("Assembly comparison failed.", ex);
            }

            if (!succeed)
            {
                throw new ApiChangeException($"The following breaking changes are found: {Environment.NewLine} {sb.ToString()}");
            }
        }
Пример #10
0
 public void When_passing_invalid_values_should_throw_exception()
 {
     Assert.Throws <ArgumentNullException>(() => ApiComparer.CreateInstance(null, null));
 }