Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use OmniSharp's embedded Mono version for integration tests. #101

Merged
merged 2 commits into from
May 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,5 @@ tools/**
!tools/packages.config
BuildArtifacts/
tests/integration/tools/
tests/integration/mono/
.dotnet/
61 changes: 59 additions & 2 deletions setup.cake
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ ToolSettings.SetToolSettings(context: Context,

var binArtifactPath = BuildParameters.Paths.Directories.PublishedApplications.Combine("Cake.Bakery/net461");
var zipArtifactsPath = BuildParameters.Paths.Directories.Build.Combine("Packages/Zip");
var omnisharpBaseDownloadURL = "https://omnisharpdownload.blob.core.windows.net/ext";
var omnisharpMonoRuntimeMacOS = $"{omnisharpBaseDownloadURL}/mono.osx-5.12.0.226.zip";
var omnisharpMonoRuntimeLinux32= $"{omnisharpBaseDownloadURL}/mono.linux-x86-5.12.0.226.zip";
var omnisharpMonoRuntimeLinux64= $"{omnisharpBaseDownloadURL}/mono.linux-x86_64-5.12.0.226.zip";
var omnisharpMonoFramework = $"{omnisharpBaseDownloadURL}/framework-5.12.0.226.zip";

Task("Copy-License")
.IsDependentOn("DotNetCore-Build")
Expand Down Expand Up @@ -155,19 +160,71 @@ Task("Init-Integration-Tests")
"./tests/integration/packages");
});

Task("Download-Mono-Assets")
.WithCriteria(() => !BuildParameters.IsRunningOnWindows)
.Does(() =>
{
CleanDirectories(new [] {
"./tests/integration/mono",
"./tests/integration/mono/framework"
});

string downloadUrl = null;
switch(Context.Environment.Platform.Family)
{
case PlatformFamily.OSX:
downloadUrl = omnisharpMonoRuntimeMacOS;
break;
case PlatformFamily.Linux:
downloadUrl = Context.Environment.Platform.Is64Bit ?
omnisharpMonoRuntimeLinux64 :
omnisharpMonoRuntimeLinux32;
break;
default:
break;
}

if (string.IsNullOrEmpty(downloadUrl))
{
return;
}

var zipFile = DownloadFile(downloadUrl);
Unzip(zipFile, "./tests/integration/mono");

zipFile = DownloadFile(omnisharpMonoFramework);
Unzip(zipFile, "./tests/integration/mono/framework");

StartProcess("chmod", "u+x ./tests/integration/mono/run");
var monoExec = GetFiles("./tests/integration/mono/bin/mono.*").First().FullPath;
StartProcess("chmod", $"u+x {monoExec}");
});

Task("Run-Bakery-Integration-Tests")
.IsDependentOn("Init-Integration-Tests")
.IsDependentOn("Download-Mono-Assets")
.IsDependeeOf("AppVeyor")
.IsDependeeOf("Default")
.Does(() =>
{
CakeExecuteScript("./tests/integration/tests.cake", new CakeSettings {
var settings = new CakeSettings {
Verbosity = Context.Log.Verbosity,
WorkingDirectory = "./tests/integration/",
Arguments = new Dictionary<string, string> {
{ "NuGet_Source", MakeAbsolute(new DirectoryPath("./tests/integration/packages")).FullPath }
}
});
};

CakeExecuteScript("./tests/integration/tests.cake", settings);

// If not running on Windows, also run with OmniSharp Mono.
if (!BuildParameters.IsRunningOnWindows)
{
settings.ArgumentCustomization = args => args.Prepend($"--no-omnisharp {MakeAbsolute(Context.Environment.ApplicationRoot).CombineWithFilePath("Cake.exe")}");
settings.ToolPath = "./tests/integration/mono/run";

CakeExecuteScript("./tests/integration/tests.cake", settings);
}
});

Task("Sign-Binaries")
Expand Down
119 changes: 115 additions & 4 deletions tests/integration/tests.cake
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,112 @@ using Cake.Scripting.Transport.Tcp.Client;
using Microsoft.Extensions.Logging;
using Xunit;

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
if (args.Name.StartsWith("System.Runtime.InteropServices.RuntimeInformation"))
{
return System.Reflection.Assembly.Load(new System.Reflection.AssemblyName("System.Runtime.InteropServices.RuntimeInformation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"));
}
return null;
};

class MonoScriptGenerationProcess : IScriptGenerationProcess
{
private readonly ILogger _logger;
private Process _process;

public MonoScriptGenerationProcess(string serverExecutablePath, ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger(typeof(MonoScriptGenerationProcess));
ServerExecutablePath = serverExecutablePath;
}

public void Dispose()
{
_process?.Kill();
_process?.WaitForExit();
_process?.Dispose();
}

public void Start(int port, string workingDirectory)
{
var (fileName, arguments) = GetMonoRuntime();

if (fileName == null)
{
// Something went wrong figurint out mono runtime,
// try executing exe and let mono handle it.
fileName = ServerExecutablePath;
}
else
{
// Else set exe as argument
arguments += $"\"{ServerExecutablePath}\"";
}

arguments += $" --port={port}";
if (_logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
{
arguments += " --verbose";
}

var startInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
WorkingDirectory = workingDirectory,
};

_logger.LogDebug("Starting \"{fileName}\" with arguments \"{arguments}\"", startInfo.FileName, startInfo.Arguments);
_process = Process.Start(startInfo);
_process.ErrorDataReceived += (s, e) =>
{
if (e.Data != null)
{
_logger.LogError(e.Data);
}
};
_process.BeginErrorReadLine();
_process.OutputDataReceived += (s, e) =>
{
if (e.Data != null)
{
_logger.LogDebug(e.Data);
}
};
_process.BeginOutputReadLine();
}

private (string, string) GetMonoRuntime()
{
// Check using ps how process was started.
var startInfo = new ProcessStartInfo
{
FileName = "sh",
Arguments = $"-c \"ps -fp {Process.GetCurrentProcess().Id} | tail -n1 | awk '{{print $8}}'\"",
RedirectStandardOutput = true,
UseShellExecute = false,
};
var process = Process.Start(startInfo);
var runtime = process.StandardOutput.ReadToEnd().TrimEnd('\n');
process.WaitForExit();

// If OmniSharp bundled Mono runtime, use bootstrap script.
var script = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(runtime), "../run");
if (System.IO.File.Exists(script))
{
return (script, "--no-omnisharp ");
}

// Else use mono directly.
return (runtime, string.Empty);
}

public string ServerExecutablePath { get; set; }
}

// Globals
IScriptGenerationService service;
const string CakeHelloWorldFile = "helloworld.cake";
Expand Down Expand Up @@ -52,10 +158,15 @@ Setup((context) => {
var loggerFactory = new LoggerFactory()
.AddConsole(Microsoft.Extensions.Logging.LogLevel.Debug);

service = new ScriptGenerationClient(
MakeAbsolute(context.Tools.Resolve("Cake.Bakery.exe")).FullPath,
MakeAbsolute(context.Environment.WorkingDirectory).FullPath,
loggerFactory);
service = Context.IsRunningOnUnix() ?
new ScriptGenerationClient(
new MonoScriptGenerationProcess(MakeAbsolute(context.Tools.Resolve("Cake.Bakery.exe")).FullPath, loggerFactory),
MakeAbsolute(context.Environment.WorkingDirectory).FullPath,
loggerFactory) :
new ScriptGenerationClient(
MakeAbsolute(context.Tools.Resolve("Cake.Bakery.exe")).FullPath,
MakeAbsolute(context.Environment.WorkingDirectory).FullPath,
loggerFactory);
});

Task("Should-Generate-From-File")
Expand Down