Skip to content

Instantly share code, notes, and snippets.

@PolarbearDK
Last active January 5, 2016 09:15
Show Gist options
  • Save PolarbearDK/2c41dc401727de26568f to your computer and use it in GitHub Desktop.
Save PolarbearDK/2c41dc401727de26568f to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using NUnit.Framework;
namespace UnitTests
{
/// <summary>
/// Verify that all projects uses same version of NuGet packages.
/// This is done by analyzing packages.config files.
/// Projects targeting different Framework Versions are allowed to use different package versions.
/// </summary>
[TestFixture]
public class VerifyNuGetPackagesUnitTest
{
[Test]
public void VerifyNuGetPackagesTest()
{
// Get solution directory three levels up assuming code runs from UnitTests/bin/Debug
var directoryName = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(Environment.CurrentDirectory)));
Assert.That(
AnalyzeNuGetPackageFiles(directoryName),
"One or more package uses different version or target framework");
}
private bool AnalyzeNuGetPackageFiles(string path)
{
var list = new List<Package>();
XmlSerializer serializer = new XmlSerializer(typeof(Package[]), new XmlRootAttribute("packages"));
var result = true;
foreach (var packageFile in
Directory
.GetFiles(path, "packages.config", SearchOption.AllDirectories)
.Where(x => x.IndexOf(@"\obj\", 0, StringComparison.InvariantCultureIgnoreCase) == -1))
{
// Find TargetFrameworkVersion of *.*proj file in same folder as package file.
var targetFrameworkVersion = GetTargetFrameworkVersion(packageFile);
using (FileStream myFileStream = File.OpenRead(packageFile))
{
var packages = (Package[]) serializer.Deserialize(myFileStream);
foreach (var package in packages)
{
package.PackageFile = packageFile;
package.TargetFrameworkVersion = targetFrameworkVersion;
list.Add(package);
}
}
}
var grouped = list.GroupBy(x => new { x.Id, x.TargetFrameworkVersion});
foreach (var group in grouped)
{
List<string> errors = new List<string>();
if (group.GroupBy(x => x.Version).Count() != 1)
{
errors.Add("version");
}
if (group.GroupBy(x => x.TargetFramework).Count() != 1)
{
errors.Add("target framework");
}
if(errors.Count > 0)
{
Console.WriteLine($"Package {group.Key.Id} TargetFrameworkVersion {group.Key.TargetFrameworkVersion} has different {string.Join(" and ", errors)}" );
foreach (var package in group)
{
Console.WriteLine($" Version={package.Version} TargetFramework={package.TargetFramework} PackageFile={package.PackageFile}");
}
result = false;
}
}
return result;
}
private static readonly Regex VersionRegex = new Regex(@"<TargetFrameworkVersion>(?<version>\S*)</TargetFrameworkVersion>", RegexOptions.Compiled|RegexOptions.Singleline);
private string GetTargetFrameworkVersion(string packageFile)
{
var files =
Directory
.GetFiles(Path.GetDirectoryName(packageFile), "*.*proj", SearchOption.TopDirectoryOnly);
switch (files.Length)
{
case 0:
throw new ApplicationException("No project file matched " + packageFile);
case 1:
var projectFile = files[0];
var match = VersionRegex.Matches(File.ReadAllText(projectFile));
if (match.Count == 1)
{
return match[0].Groups["version"].Value;
}
throw new ApplicationException("Unable to extract TargetFrameworkVersion from " + projectFile);
default:
throw new ApplicationException("Multiple projects matched " + packageFile);
}
}
}
[XmlType("package")]
public class Package
{
[XmlAttribute("id")]
public string Id { get; set; }
[XmlAttribute("version")]
public string Version { get; set; }
[XmlAttribute("targetFramework")]
public string TargetFramework { get; set; }
/// <summary>
/// Source file
/// </summary>
[XmlIgnore]
public string PackageFile { get; set; }
/// <summary>
/// Related *proj file TargetFrameworkVersion
/// </summary>
[XmlIgnore]
public string TargetFrameworkVersion { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment