Skip to content
This repository has been archived by the owner on Feb 23, 2021. It is now read-only.

Commit

Permalink
configuring stress runs to use latest runtime, framework and test bin…
Browse files Browse the repository at this point in the history
…aries
  • Loading branch information
bryanar authored and bryanar committed Oct 11, 2016
1 parent da64e1f commit b9ab723
Show file tree
Hide file tree
Showing 25 changed files with 429 additions and 233 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Expand Up @@ -254,3 +254,8 @@ Session.vim
.netrwhist
*~

local_run.rsp
local_run_win10.rsp
out.txt
usedvalues.txt
.vscode/
Binary file added AnyOS.AnyCPU.Debug-Test-Archive-List.txt
Binary file not shown.
2 changes: 1 addition & 1 deletion BuildToolsVersion.txt
@@ -1 +1 @@
1.0.26-prerelease-00527-01
1.0.26-prerelease-00716-01
4 changes: 2 additions & 2 deletions build.cmd
Expand Up @@ -41,7 +41,7 @@ call :build %*
goto :AfterBuild

:build
%_buildprefix% msbuild "%_buildproj%" /nologo /maxcpucount /verbosity:minimal /nodeReuse:false /fileloggerparameters:Verbosity=normal;LogFile="%_buildlog%";Append %* %_buildpostfix%
%_buildprefix% msbuild "%_buildproj%" /nologo /verbosity:minimal /nodeReuse:false /fileloggerparameters:Verbosity=diagnostic;LogFile="%_buildlog%";Append %* %_buildpostfix%
set BUILDERRORLEVEL=%ERRORLEVEL%
goto :eof

Expand All @@ -52,4 +52,4 @@ echo.
findstr /ir /c:".*Warning(s)" /c:".*Error(s)" /c:"Time Elapsed.*" "%_buildlog%"
echo Build Exit Code = %BUILDERRORLEVEL%

exit /b %BUILDERRORLEVEL%
exit /b %BUILDERRORLEVEL%
32 changes: 32 additions & 0 deletions build_test.cmd
@@ -0,0 +1,32 @@
@echo off
setlocal

:: Note: We've disabled node reuse because it causes file locking issues.
:: The issue is that we extend the build with our own targets which
:: means that that rebuilding cannot successfully delete the task
:: assembly.

if not defined VisualStudioVersion (
if defined VS140COMNTOOLS (
call "%VS140COMNTOOLS%\VsDevCmd.bat"
goto :EnvSet
)

if defined VS120COMNTOOLS (
call "%VS120COMNTOOLS%\VsDevCmd.bat"
goto :EnvSet
)

echo Error: build.cmd requires Visual Studio 2013 or 2015.
echo Please see https://github.com/dotnet/corefx/blob/master/Documentation/developer-guide.md for build instructions.
exit /b 1
)

:EnvSet

:: The property FilterToTestTFM is temporarily required because of https://github.com/dotnet/buildtools/commit/e9007c16b1832dbd0ea9669fa578b61900b7f724
call msbuild test/genstress.proj %*
set BUILDERRORLEVEL=%ERRORLEVEL%


exit /b %BUILDERRORLEVEL%
Expand Up @@ -26,7 +26,6 @@ function Add-CertificateToKeyVault([string] $secretKey, [SecureString] $securePa
Add-AzureKeyVaultKey -VaultName $globalVar_keyVaultName -Name $secretKey -KeyFilePath $pathToPfx -KeyFilePassword $securePassword -Destination Software
}

# TODO: Load in real certificate with legitimate start date and end date.
function Register-DumplingWithAzureAD
{
#login to Azure
Expand Down
Expand Up @@ -46,7 +46,6 @@ public override void Run()
await receivedMessage.CompleteAsync();
// TODO: Debug/Understand: the received message is disposed of after the await call returns. Is this a framework/runtime bug?
await DumplingEventHub.FireEvent(new DataWorkerMessageReceivedEvent());
using (var reader = new StreamReader(body))
{
Expand Down
1 change: 0 additions & 1 deletion src/dumpling-service/dumpling.deploy/Program.cs
Expand Up @@ -199,7 +199,6 @@ private static void Main(string[] args)
// StreamAnalytics is deployed via the Azure UI.
// classic webrole - deployed by an azure build process
// classic worker role - deployed by an azure build process
// todo: add storage deployment.
};

Task.WaitAll(deployTasks);
Expand Down
4 changes: 2 additions & 2 deletions src/stress.codegen/LoadTestProjectFileGenerator.cs
Expand Up @@ -42,7 +42,7 @@ private static string GenerateTestPropertiesSnippet(LoadTestInfo loadTest)

private static string GenerateSourceFileItemsSnippet(LoadTestInfo loadTest)
{
StringBuilder snippet = new StringBuilder();
StringBuilder snippet = new StringBuilder();

foreach (var file in loadTest.SourceFiles)
{
Expand Down Expand Up @@ -88,7 +88,7 @@ private static string GenerateTestReferencesSnippet(LoadTestInfo loadTest)

foreach (var assmref in test.ReferenceInfo.ReferencedAssemblies)
{
if (uniqueAssemblies.Add(assmref.Name) && !packageInfo.dependencies.ContainsKey(Path.GetFileNameWithoutExtension(assmref.Name)))
if (uniqueAssemblies.Add(assmref.Name) && packageInfo.dependencies[Path.GetFileNameWithoutExtension(assmref.Name)] == null)
{
string refSnippet = $@"
<Reference Include='{assmref.Name}'>
Expand Down
68 changes: 59 additions & 9 deletions src/stress.codegen/MergeAllProjectJsonsTask.cs
Expand Up @@ -8,37 +8,87 @@
using System.IO;
using System.Diagnostics;
using System.Windows;
using Newtonsoft.Json.Linq;

namespace stress.codegen
{

// This merge class walks all of the directory tree of InPath and produces a merged project json file. Then we
// 'trim it down' to the type of run we'd like to support, and write that final project.json to disk at OutPath.
public class MergeAllProjectJsonsTask : Task
{
// assumptions:
// we assume that anyos test project.jsons (AND ONLY THESE; any other ones will mess up the merge) are
// present in the directory or subdirectories of InPath
[Required]
public string InPath { get; set; }


// the path to the project.json we are spawning.
[Required]
public string OutPath { get; set; }

// not currently being used, but they exist to allow tests to be 'upgraded' in place.
public string OldPrerelease { get; set; }
public string NewPrerelease { get; set; }

// set this to true when you want to debug. It causes a message box to show with the process id of the executing
// msbuild instance that you can attach your debugger to. The execution of code will sit until you click ok.
public bool Debug { get; set; }

public override bool Execute()
// this method walks the directory tree of inPath and uses the Newtonsoft JObject::Merge to merge together
// our project jsons.
// we require there to be at least ONE project.json present somewhere in the directory tree of inPath
private JObject MergeProjectJsonsIn(string inPath)
{
if (Debug)
var projectJsons = Directory.EnumerateFiles(InPath, "project.json", SearchOption.AllDirectories).Select(p => JObject.Parse(File.ReadAllText(p)));
JObject merged = new JObject(projectJsons.First());

foreach (var file in projectJsons)
{
MessageBox.Show($"PID:{Process.GetCurrentProcess().Id} Attach debugger now.", "Debug GenerateStressSuiteTask", MessageBoxButton.OK);
merged.Merge(file);
}

return merged;
}

// this method:
// strips out test-runtime object if it is present in the dependencies list.
// removes all frameworks except for the one that is to be targeted for the run
private void ProduceAnyOsProjectJson(string outPath, JObject merged, string targetFramework)
{
// remove test-runtime if it is present.
(merged["dependencies"] as JObject)?.Property("test-runtime")?.Remove();

Dictionary<string, HashSet<string>> assmVersions = new Dictionary<string, HashSet<string>>();

var projectJsons = Directory.EnumerateFiles(InPath, "project.json", SearchOption.AllDirectories).Select(p => ProjectJsonDependencyInfo.FromFile(p));
// remove all supports.
merged["supports"]?.Children<JProperty>().ToList().ForEach(x => x.Remove());

// remove all frameworks except the specified one
merged["frameworks"]?.Children<JProperty>().Where(x => x.Name != targetFramework).ToList().ForEach(x => x.Remove());

var merged = ProjectJsonDependencyInfo.MergeToLatest(projectJsons, OldPrerelease, NewPrerelease);
// since we are creating an anyos test launcher we should list all known runtimes here.
merged["runtimes"] = new JObject();
merged["runtimes"]["win10-x64"] = new JObject();
merged["runtimes"]["win7-x64"] = new JObject();
merged["runtimes"]["win7-x86"] = new JObject();
merged["runtimes"]["ubuntu.14.04-x64"] = new JObject();
merged["runtimes"]["osx.10.10-x64"] = new JObject();
merged["runtimes"]["centos.7-x64"] = new JObject();
merged["runtimes"]["rhel.7-x64"] = new JObject();
merged["runtimes"]["debian.8-x64"] = new JObject();

merged.ToFile(OutPath);
// serialize, then write the project json file to OutPath
File.WriteAllText(OutPath, JsonConvert.SerializeObject(merged));
}

public override bool Execute()
{
if (Debug)
{
MessageBox.Show($"PID:{Process.GetCurrentProcess().Id} Attach debugger now.", "Debug GenerateStressSuiteTask", MessageBoxButton.OK);
}

ProduceAnyOsProjectJson(OutPath, MergeProjectJsonsIn(InPath), "netstandard1.7");

return true;
}
}
Expand Down
100 changes: 25 additions & 75 deletions src/stress.codegen/ProjectJsonDependencyInfo.cs
Expand Up @@ -9,129 +9,79 @@

namespace stress.codegen
{
[Serializable]
public class ProjectJsonDependencyInfo
{
public Dictionary<string, string> dependencies;
public JObject dependencies;

public Dictionary<string, Dictionary<string, string[]>> frameworks;
public JObject frameworks;

public Dictionary<string, Dictionary<string, string>> runtimes;
public JObject runtimes;

public JObject supports;

public ProjectJsonDependencyInfo()
{
dependencies = new Dictionary<string, string>();
dependencies = new JObject();

frameworks = new Dictionary<string, Dictionary<string, string[]>>();
frameworks["netcoreapp1.0"] = new Dictionary<string, string[]>() { { "imports", new string[] { "dnxcore50", "portable-net45+win8" } } };
frameworks = new JObject();

runtimes = new Dictionary<string, Dictionary<string, string>>()
{
{ "win", new Dictionary<string, string>() },
{ "win7-x64", new Dictionary<string, string>() },
{ "win7-x86", new Dictionary<string, string>() },
{ "ubuntu.14.04-x64", new Dictionary<string, string>() },
{ "osx.10.10-x64", new Dictionary<string, string>() },
{ "centos.7-x64", new Dictionary<string, string>() },
{ "rhel.7-x64", new Dictionary<string, string>() },
{ "debian.8-x64", new Dictionary<string, string>() },
};
runtimes = new JObject();

supports = new JObject();

supports.Add("coreFx.Test.netcoreapp1.0", new JObject());
}

public void ToFile(string path)
{
// Serialize the RunConfiguration
JsonSerializer serializer = JsonSerializer.CreateDefault();

using (FileStream fs = new FileStream(path, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(fs))
{
serializer.Serialize(writer, this);
}
}
File.WriteAllText(path, JsonConvert.SerializeObject(this));
}

public static ProjectJsonDependencyInfo FromFile(string path)
{
ProjectJsonDependencyInfo dependInfo = new ProjectJsonDependencyInfo();

ProjectJsonDependencyInfo dependInfo = null;
//if a project.json file exists next to the test binary load it
if (File.Exists(path))
{
var serializer = JsonSerializer.CreateDefault();
var data = JObject.Parse(File.ReadAllText(path));

using (var srdr = new StreamReader(File.OpenRead(path)))
{
var jrdr = new JsonTextReader(srdr);
(data["dependencies"] as JObject)?.Property("test-runtime")?.Remove();

var obj = serializer.Deserialize<JObject>(jrdr);

foreach(var prop in FindAllDependencyProperties(obj))
{
dependInfo.dependencies[prop.Key] = prop.Value;
}
}
dependInfo = data.ToObject<ProjectJsonDependencyInfo>();
}

return dependInfo;
}

public static IEnumerable<KeyValuePair<string, string>> FindAllDependencyProperties(JObject projectJsonObj)
public static JEnumerable<JProperty> FetchPrimaryDependenciesProperties(JObject projectJsonObj)
{
return projectJsonObj
.Descendants()
.OfType<JProperty>()
.Where(property => property.Name == "dependencies")
.Select(property => property.Value)
.SelectMany(o => o.Children<JProperty>())
.Where(p => !p.Name.Contains("TargetingPack"))
.Select(p => GetDependencyPair(p))
.Where(p => !string.IsNullOrEmpty(p.Value));
return projectJsonObj["dependencies"].Children<JProperty>();
}

public static KeyValuePair<string, string> GetDependencyPair(JProperty dependProp)
{
string dependencyVersion;

if (dependProp.Value is JObject)
{
dependencyVersion = dependProp.Value["version"]?.Value<string>();
}
else if (dependProp.Value is JValue)
{
dependencyVersion = dependProp.Value.ToObject<string>();
}
else
{
throw new ArgumentException("Unrecognized dependency element");
}

return new KeyValuePair<string, string>(dependProp.Name, dependencyVersion);
}

public static ProjectJsonDependencyInfo MergeToLatest(IEnumerable<ProjectJsonDependencyInfo> projectJsons, string oldprerelease = null, string newprerelease = null)
{
var merged = new ProjectJsonDependencyInfo();

merged.dependencies = new Dictionary<string, string>();
merged.dependencies = new JObject();

foreach (var pjson in projectJsons)
{
if (pjson.dependencies != null)
{
foreach (var depend in pjson.dependencies)
{
var depVer = ComplexVersion.Parse(depend.Value);
if(newprerelease != null && depVer.Prerelease == oldprerelease)
var depVer = ComplexVersion.Parse(depend.Value.Value<string>());

if (newprerelease != null && depVer.Prerelease != null && depVer.Prerelease == oldprerelease)
{
depVer.Prerelease = newprerelease;
}

//if the dependency is not present in the merged dependencies OR the version in the current pjson is a greater than the one in merged
//if string.Compare returns > 0 then depend.Value is greater than the one in merged, this should mean a later version
if (!merged.dependencies.ContainsKey(depend.Key) || (ComplexVersion.Parse(merged.dependencies[depend.Key]) < depVer))
if (merged.dependencies[depend.Key] == null || (ComplexVersion.Parse(merged.dependencies[depend.Key].Value<string>()) < depVer))
{
merged.dependencies[depend.Key] = depVer.ToString();
}
Expand Down

0 comments on commit b9ab723

Please sign in to comment.