public async Task TestMatchFramework()
        {
            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);

            var diff = await comparer.GenerateAsync(SkiaPackageId, SkiaV600Number, SkiaV601Number);

            Assert.Equal(2, diff.AddedFrameworks.Length);
            Assert.Equal(2, diff.RemovedFrameworks.Length);
            Assert.Equal(7, diff.UnchangedFrameworks.Length);
            Assert.Single(diff.SimilarFrameworks);

            var mac2 = NuGetFramework.Parse("Xamarin.Mac,Version=v2.0");
            var mac0 = NuGetFramework.Parse("Xamarin.Mac,Version=v0.0");

            Assert.Contains(mac2, diff.SimilarFrameworks.Keys);
            Assert.Equal(mac0, diff.SimilarFrameworks[mac2]);

            const string mac2Dll = "lib/Xamarin.Mac20/SkiaSharp.dll";
            const string mac0Dll = "lib/XamarinMac/SkiaSharp.dll";

            Assert.Contains(mac2, diff.SimilarAssemblies.Keys);
            Assert.Contains((mac2Dll, mac0Dll), diff.SimilarAssemblies[mac2]);
        }
        public async Task TestCompareTwoLocalFiles()
        {
            var oldPath = GenerateTestOutputPath();
            var newPath = GenerateTestOutputPath();

            using (var wc = new WebClient())
            {
                await wc.DownloadFileTaskAsync(FormsV20Url1, oldPath);

                await wc.DownloadFileTaskAsync(FormsV3Url2, newPath);
            }

            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);

            var diff = await comparer.GenerateAsync(oldPath, newPath);

            Assert.Equal(NuGetVersion.Parse(FormsV20Number1), diff.OldIdentity.Version);
            Assert.Equal(NuGetVersion.Parse(FormsV30Number2), diff.NewIdentity.Version);

            Assert.NotEmpty(diff.AddedFrameworks);
            Assert.NotEmpty(diff.RemovedFrameworks);
            Assert.NotEmpty(diff.UnchangedFrameworks);

            Assert.NotEmpty(diff.AddedAssemblies);
            Assert.NotEmpty(diff.RemovedAssemblies);
            Assert.NotEmpty(diff.UnchangedAssemblies);
        }
        public async Task TestCompletePackageDiffIsGeneratedCorrectly()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);
            comparer.SaveAssemblyMarkdownDiff = true;
            comparer.IgnoreSimilarFrameworks  = true;

            // download extra dependencies
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.v7.AppCompat", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Fragment", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Core.Utils", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Compat", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Core.UI", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.v7.CardView", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Design", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Tizen.NET", "4.0.0", "netstandard2.0");

            await comparer.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, diffDir);

            var files = Directory.GetFiles(diffDir, "*.md", SearchOption.AllDirectories);

            Assert.Equal(27, files.Length);
        }
        public async Task TestMatchPortableUpgradeToNetStandard()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);
            comparer.SaveAssemblyMarkdownDiff = true;

            await comparer.SaveCompleteDiffToDirectoryAsync(SkiaPackageId, SkiaV560Number, SkiaV601Number, diffDir);

            var xnupkg = XDocument.Load(Path.Combine(diffDir, "SkiaSharp.nupkg.diff.xml"));
            var xFws   = xnupkg.Root
                         .Element("package")
                         .Element("frameworks")
                         .Elements("framework");

            var xPclFw = xFws.Single(f => f.Attribute("name").Value == ".NETPortable");

            Assert.Equal("missing", xPclFw.Attribute("presence").Value);
            Assert.Empty(xPclFw.Descendants());

            var xStdFw  = xFws.Single(f => f.Attribute("name").Value == ".NETStandard");
            var xStdAss = xStdFw.Element("assemblies").Element("assembly");

            Assert.Equal("lib/netstandard1.3/SkiaSharp.dll", xStdAss.Attribute("path").Value);
            Assert.Equal("lib/portable-net45+win8+wpa81+wp8/SkiaSharp.dll", xStdAss.Attribute("old_path").Value);
            var netStdFile = File.ReadAllText(Path.Combine(diffDir, "netstandard1.3", "SkiaSharp.dll.diff.md"));
            var netFile    = File.ReadAllText(Path.Combine(diffDir, "net45", "SkiaSharp.dll.diff.md"));

            // replace the new .NET Standard type
            netFile = netFile.Replace("System.IAsyncDisposable, System.IDisposable", "System.IDisposable");

            Assert.Equal(netStdFile, netFile);
        }
        public async Task TestMatchNetStandardPortableReusePortable()
        {
            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);

            var diff = await comparer.GenerateAsync(SkiaPackageId, SkiaV560Number, SkiaV600Number);

            Assert.Equal(2, diff.AddedFrameworks.Length);
            Assert.Empty(diff.RemovedFrameworks);
            Assert.Equal(7, diff.UnchangedFrameworks.Length);
            Assert.Single(diff.SimilarFrameworks);

            var netstd = NuGetFramework.Parse(".NETStandard,Version=v1.3");
            var pcl    = NuGetFramework.Parse(".NETPortable,Version=v0.0,Profile=Profile259");

            Assert.Contains(netstd, diff.SimilarFrameworks.Keys);
            Assert.Equal(pcl, diff.SimilarFrameworks[netstd]);

            const string netstdDll = "lib/netstandard1.3/SkiaSharp.dll";
            const string pclDll    = "lib/portable-net45+win8+wpa81+wp8/SkiaSharp.dll";

            Assert.Contains(netstd, diff.SimilarAssemblies.Keys);
            Assert.Contains((netstdDll, pclDll), diff.SimilarAssemblies[netstd]);
        }
        public async Task TestMatchSameFrameworkAndVersionButDifferentSpelling()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);
            comparer.SaveAssemblyMarkdownDiff = true;
            comparer.IgnoreSimilarFrameworks  = true;

            await comparer.SaveCompleteDiffToDirectoryAsync(SkiaPackageId, SkiaV600Number, SkiaV601Number, diffDir);

            var xnupkg = XDocument.Load(Path.Combine(diffDir, "SkiaSharp.nupkg.diff.xml"));
            var xFws   = xnupkg.Root
                         .Element("package")
                         .Element("frameworks")
                         .Elements("framework");

            var xIosFws = xFws.Single(f => f.Attribute("name").Value == "Xamarin.iOS");

            Assert.Null(xIosFws.Attribute("presence"));
            var xIosAss = xIosFws.Element("assemblies").Element("assembly");

            Assert.Equal("lib/Xamarin.iOS/SkiaSharp.dll", xIosAss.Attribute("path").Value);
            Assert.Equal("lib/XamariniOS/SkiaSharp.dll", xIosAss.Attribute("old_path").Value);
            var netStdFile = File.ReadAllText(Path.Combine(diffDir, "netstandard1.3", "SkiaSharp.dll.diff.md"));
            var iosFile    = File.ReadAllText(Path.Combine(diffDir, "Xamarin.iOS", "SkiaSharp.dll.diff.md"));

            Assert.Equal(netStdFile, iosFile);
        }
        public async Task TestCompletePackageDiffIsGeneratedCorrectlyWithAddedAssembliesButWithoutAllReferences()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.IgnoreResolutionErrors = true;

            await comparer.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, diffDir);
        }
        public async Task TestCompleteSkiaPackageDiffIsGeneratedCorrectly()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.SaveAssemblyMarkdownDiff = true;
            comparer.SearchPaths.AddRange(searchPaths);

            await comparer.SaveCompleteDiffToDirectoryAsync(SkiaPackageId, SkiaV600Number, SkiaV602Number, diffDir);
        }
        public async Task TestCompletePackageDiffThrowsWithoutAllReferencesAndFlag()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.IgnoreResolutionErrors = false;

            var task = comparer.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, diffDir);
            await Assert.ThrowsAsync <AssemblyResolutionException>(() => task);
        }
        public async Task TestCompletePackageDiffIsTheSameEvenWithoutReferences()
        {
            var missingDir = GenerateTestOutputPath();
            var allDir     = GenerateTestOutputPath();

            // generate diff with missing references
            var missing = new NuGetDiff();

            missing.IgnoreResolutionErrors    = true;
            missing.IgnoreInheritedInterfaces = true;
            missing.SaveAssemblyMarkdownDiff  = true;
            missing.IgnoreAddedAssemblies     = true;
            missing.IgnoreSimilarFrameworks   = true;
            await missing.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, missingDir);

            // generate diff with everything
            var all = new NuGetDiff();

            all.SearchPaths.AddRange(searchPaths);
            all.IgnoreInheritedInterfaces = true;
            all.SaveAssemblyMarkdownDiff  = true;
            all.IgnoreAddedAssemblies     = true;
            all.IgnoreSimilarFrameworks   = true;
            await AddDependencyAsync(all, "Xamarin.Android.Support.v7.AppCompat", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(all, "Xamarin.Android.Support.Fragment", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(all, "Xamarin.Android.Support.Core.Utils", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(all, "Xamarin.Android.Support.Compat", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(all, "Xamarin.Android.Support.Core.UI", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(all, "Xamarin.Android.Support.v7.CardView", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(all, "Xamarin.Android.Support.Design", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(all, "Tizen.NET", "4.0.0", "netstandard2.0");

            await all.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, allDir);

            // test the markdown files as the xml will be different as some dependency type will not be loaded
            // are there the same files
            var missingFiles = Directory.GetFiles(missingDir, "*.md", SearchOption.AllDirectories);
            var allFiles     = Directory.GetFiles(allDir, "*.md", SearchOption.AllDirectories);
            var missingDic   = missingFiles.ToDictionary(f => Path.GetRelativePath(missingDir, f), f => f);
            var allDic       = allFiles.ToDictionary(f => Path.GetRelativePath(allDir, f), f => f);

            Assert.Equal(14, missingDic.Count);
            Assert.Equal(14, allDic.Count);
            Assert.Equal(allDic.Keys, missingDic.Keys);
            foreach (var pair in allDic)
            {
                var allFile = await File.ReadAllTextAsync(pair.Value);

                var missingFile = await File.ReadAllTextAsync(missingDic[pair.Key]);

                Assert.Equal(allFile, missingFile);
            }
        }
        public async Task TestMatchFrameworksWithAllFrameworks()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);
            comparer.IgnoreResolutionErrors   = true;
            comparer.SaveAssemblyApiInfo      = true;
            comparer.SaveAssemblyXmlDiff      = true;
            comparer.SaveAssemblyMarkdownDiff = true;

            await comparer.SaveCompleteDiffToDirectoryAsync(AndroidSupportPackageId, AndroidSupportV27Number, AndroidSupportV28Number, diffDir);
        }
        public async Task TestCompletePackageDiffIsGeneratedCorrectlyWithoutAllReferencesAndIgnoreNonBreaking()
        {
            var breakingDir       = GenerateTestOutputPath();
            var ignoreBreakingDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.IgnoreResolutionErrors   = true;
            comparer.IgnoreAddedAssemblies    = true;
            comparer.SaveAssemblyMarkdownDiff = true;

            comparer.IgnoreNonBreakingChanges = false;
            await comparer.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, breakingDir);

            comparer.IgnoreNonBreakingChanges = true;
            await comparer.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, ignoreBreakingDir);
        }
        public async Task TestComparePackage()
        {
            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);

            var diff = await comparer.GenerateAsync(FormsPackageId, FormsV20Number1, FormsV30Number2);

            Assert.Equal(NuGetVersion.Parse(FormsV20Number1), diff.OldIdentity.Version);
            Assert.Equal(NuGetVersion.Parse(FormsV30Number2), diff.NewIdentity.Version);

            Assert.NotEmpty(diff.AddedFrameworks);
            Assert.NotEmpty(diff.RemovedFrameworks);
            Assert.NotEmpty(diff.UnchangedFrameworks);

            Assert.NotEmpty(diff.AddedAssemblies);
            Assert.NotEmpty(diff.RemovedAssemblies);
            Assert.NotEmpty(diff.UnchangedAssemblies);
        }
        public async Task TestMatchSameFrameworkButDifferentVersionFailsWhenSimilarIsDisabled()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);
            comparer.SaveAssemblyMarkdownDiff = true;
            comparer.IgnoreSimilarFrameworks  = true;

            await comparer.SaveCompleteDiffToDirectoryAsync(SkiaPackageId, SkiaV600Number, SkiaV601Number, diffDir);

            var xnupkg = XDocument.Load(Path.Combine(diffDir, "SkiaSharp.nupkg.diff.xml"));
            var xFws   = xnupkg.Root
                         .Element("package")
                         .Element("frameworks")
                         .Elements("framework");

            var xMacFws = xFws.Where(f => f.Attribute("name").Value == "Xamarin.Mac").ToArray();

            Assert.Equal(2, xMacFws.Length);

            var xMac0Fw = xMacFws.Single(f => f.Attribute("version").Value == "0.0.0.0");

            Assert.Equal("missing", xMac0Fw.Attribute("presence").Value);
            Assert.Empty(xMac0Fw.Descendants());

            var xMac2Fw = xMacFws.Single(f => f.Attribute("version").Value == "2.0.0.0");

            Assert.Equal("extra", xMac2Fw.Attribute("presence").Value);

            var xMac2Ass = xMac2Fw.Element("assemblies").Element("assembly");

            Assert.Equal("lib/Xamarin.Mac20/SkiaSharp.dll", xMac2Ass.Attribute("path").Value);
            Assert.Null(xMac2Ass.Attribute("old_path"));

            var netStdFile = File.ReadAllText(Path.Combine(diffDir, "netstandard1.3", "SkiaSharp.dll.diff.md"));
            var mac2File   = File.ReadAllText(Path.Combine(diffDir, "Xamarin.Mac20", "SkiaSharp.dll.diff.md"));

            Assert.NotEqual(netStdFile, mac2File);
            Assert.True(netStdFile.Length < mac2File.Length);
        }
        public async Task TestDoesIgnoreMembers()
        {
            var path = GenerateTestOutputPath();

            // generate diff with missing references
            var missing = new NuGetDiff
            {
                IgnoreResolutionErrors    = true,
                IgnoreInheritedInterfaces = true,
                SaveAssemblyMarkdownDiff  = true,
                IgnoreAddedAssemblies     = true,
                IgnoreSimilarFrameworks   = true,
                IgnoreMemberRegex         =
                {
                    @"\.IServiceProviderExtensions\:",
                }
            };

            await missing.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, path);

            var allFile = await File.ReadAllTextAsync(Path.Combine(path, "MonoAndroid10/Xamarin.Forms.Core.dll.diff.md"));

            Assert.DoesNotContain("IServiceProviderExtensions", allFile);
        }
        public async Task TestCompletePackageDiffIsGeneratedCorrectlyWithAllAssemblyInfo()
        {
            var diffDir = GenerateTestOutputPath();

            var comparer = new NuGetDiff();

            comparer.SearchPaths.AddRange(searchPaths);
            comparer.SaveAssemblyApiInfo      = true;
            comparer.SaveAssemblyHtmlDiff     = true;
            comparer.SaveAssemblyMarkdownDiff = true;
            comparer.SaveAssemblyXmlDiff      = true;

            // download extra dependencies
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.v7.AppCompat", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Fragment", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Core.Utils", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Compat", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Core.UI", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.v7.CardView", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Xamarin.Android.Support.Design", "25.4.0.2", "MonoAndroid70");
            await AddDependencyAsync(comparer, "Tizen.NET", "4.0.0", "netstandard2.0");

            await comparer.SaveCompleteDiffToDirectoryAsync(FormsPackageId, FormsV25Number1, FormsV31Number1, diffDir);
        }
        private async Task AddDependencyAsync(NuGetDiff comparer, string id, string version, string platform)
        {
            await comparer.ExtractCachedPackageAsync(id, version);

            comparer.SearchPaths.Add(Path.Combine(comparer.GetCachedPackageDirectory(id, version), "lib", platform));
        }