From fd09ed571dfed98d09948bf6c40e1683defd8b9c Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Tue, 2 Feb 2016 15:42:04 +1030 Subject: [PATCH] wrote some tests to verify linqpad scripts as part of integration --- Octokit.Tests.Integration/SelfTests.cs | 170 ++++++++++++++++++++++++- build.fsx | 21 +-- 2 files changed, 181 insertions(+), 10 deletions(-) diff --git a/Octokit.Tests.Integration/SelfTests.cs b/Octokit.Tests.Integration/SelfTests.cs index b2362323..55b53626 100644 --- a/Octokit.Tests.Integration/SelfTests.cs +++ b/Octokit.Tests.Integration/SelfTests.cs @@ -1,4 +1,11 @@ -using Xunit; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Xml.Linq; +using Xunit; namespace Octokit.Tests.Integration { @@ -13,5 +20,166 @@ namespace Octokit.Tests.Integration var errors = typeof(SelfTests).Assembly.GetAsyncVoidMethodsList(); Assert.Equal("", errors); } + + /// + /// Extract the current directory from the running assembly + /// + static Lazy currentDirectory = new Lazy(() => + { + var uri = new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase); + return Path.GetDirectoryName(uri.LocalPath); + }); + + public static string CurrentDirectory + { + get { return currentDirectory.Value; } + } + + /// + /// Recurse from where the tests are running until you find the root + /// with the .gitignore file - kids, don't try this at home + /// + static Lazy repositoryRoot = new Lazy(() => + { + var directory = CurrentDirectory; + + do + { + var parent = Directory.GetParent(directory); + directory = parent.FullName; + } while (!File.Exists(Path.Combine(directory, ".gitignore"))); + + return directory; + }); + + public static string RepositoryRoot + { + get { return repositoryRoot.Value; } + } + + public static IEnumerable LinqpadScripts + { + get + { + var samples = Path.Combine(RepositoryRoot, "samples", "linqpad-samples"); + return Directory.EnumerateFiles(samples).Select(file => new[] { file }); + } + } + + // transform the metadata provided by each Linqpad script + + // + // Octokit + // Octokit.Reactive + // Rx - Main + // Octokit + // System.Reactive.Linq + // System.Threading.Tasks + // + + // into a version we can run against local assemblies: + + //ref C: \users\shiftkey\code\Octokit\Octokit\bin\Release\net45\Octokit.dll; + //ref C: \users\shiftkey\code\Octokit\Octokit.Reactive\bin\Release\net45\Octokit.Reactive.dll; + //ref C: \users\shiftkey\code\Octokit\packages\System.Reactive.Linq\lib\net45\System.Reactive.Linq.dll; + // + // using Octokit; + // using System.Reactive.Linq; + // using System.Threading.Tasks; + + + static string RewriteLinqpadScriptToUseLocalAssemblies(string filePath) + { + var text = File.ReadAllText(filePath); + + var openTag = ""; + var openTagIndex = text.IndexOf(openTag); + var closeTag = ""; + var closeTagIndex = text.IndexOf(closeTag); + + if (openTagIndex == -1 || closeTagIndex == -1) + { + throw new InvalidOperationException(); + } + + var endOfMetadata = closeTagIndex + closeTag.Length; + + // write to temp file on disk + var tempFilePath = Path.GetTempFileName(); + + using (var stream = File.OpenWrite(tempFilePath)) + using (var writer = new StreamWriter(stream)) + { + // reference all known assemblies + writer.WriteLine("ref {0}\\System.Reactive.Core.dll;", CurrentDirectory); + writer.WriteLine("ref {0}\\System.Reactive.Interfaces.dll;", CurrentDirectory); + writer.WriteLine("ref {0}\\System.Reactive.Linq.dll;", CurrentDirectory); + writer.WriteLine("ref {0}\\Octokit.dll;", CurrentDirectory); + writer.WriteLine("ref {0}\\Octokit.Reactive.dll;", CurrentDirectory); + writer.WriteLine("ref C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.Net.Http.dll;"); + writer.WriteLine(); + + var xmlText = text.Substring(openTagIndex, endOfMetadata); + var rest = text.Substring(endOfMetadata); + + var doc = XDocument.Parse(xmlText); + + // add namespaces specified in xml + var namespaces = doc.Descendants() + .Where(x => x.Name == "Namespace") + .Select(x => x.Value.ToString()); + + foreach (var @namespace in namespaces) + { + writer.WriteLine("using {0};", @namespace); + } + + writer.WriteLine(); + writer.WriteLine(rest); + + writer.Flush(); + } + + return tempFilePath; + } + + static Process ExecuteProcess(string filePath) + { + var lprun = Path.Combine(RepositoryRoot, "tools", "LINQPad", "lprun.exe"); + + // launch process to test script + var info = new ProcessStartInfo + { + FileName = lprun, + Arguments = string.Format("-compileonly -lang=Program {0}", filePath), + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + }; + + var process = Process.Start(info); + process.WaitForExit(); + + return process; + } + + [Theory] + [MemberData("LinqpadScripts")] + public void LinqpadSnippetsCompileCorrectly(string filePath) + { + var tempFilePath = RewriteLinqpadScriptToUseLocalAssemblies(filePath); + var process = ExecuteProcess(tempFilePath); + + var output = process.StandardOutput.ReadToEnd(); + var error = process.StandardError.ReadToEnd(); + var exitCode = process.ExitCode; + + File.Delete(tempFilePath); + + Assert.True(exitCode == 0); + Assert.Empty(output); + Assert.Empty(error); + } } } diff --git a/build.fsx b/build.fsx index d231cc2d..8697aaf2 100644 --- a/build.fsx +++ b/build.fsx @@ -149,15 +149,18 @@ Target "SourceLink" (fun _ -> ) Target "ValidateLINQPadSamples"(fun _ -> - directoryInfo(samplesDir @@ "linqpad-samples") - |> filesInDir - |> Array.map(fun f -> f.FullName) - |> Seq.iter (fun sample -> - let result = ExecProcess (fun info -> - info.FileName <- linqPadDir @@ "lprun.exe" - info.Arguments <- " -compileonly " + sample) (TimeSpan.FromMinutes 5.0) - if result <> 0 then failwithf "lprun.exe returned with a non-zero exit code for %s" sample - ) + "The current LINQPad snippets reference the latest release of Octokit on NuGet, which may be very far behind what is currently on master. " + + "These tests have been ported to SelfTests in the integration test suite. If someone would like to port them to F#, have a read of the discussion in https://github.com/octokit/octokit.net/issues/983." + |> traceImportant + // directoryInfo(samplesDir @@ "linqpad-samples") + // |> filesInDir + // |> Array.map(fun f -> f.FullName) + // |> Seq.iter (fun sample -> + // let result = ExecProcess (fun info -> + // info.FileName <- linqPadDir @@ "lprun.exe" + // info.Arguments <- " -compileonly " + sample) (TimeSpan.FromMinutes 5.0) + // if result <> 0 then failwithf "lprun.exe returned with a non-zero exit code for %s" sample + // ) ) Target "CreateOctokitPackage" (fun _ ->