Make all tests pass on Linux (#8)
- Select filename to execute based on RuntimeIdentifier - Include server log in error message if Run or Exec http requests fail - Angular: Normalize hash in main.[HASH].bundle.js - React: Disable parallelism to avoid exceeding default fs.inotify.max_user_watches limit
This commit is contained in:
parent
5dfdf604a9
commit
0fa02f424f
|
|
@ -1,5 +1,6 @@
|
||||||
using AspNetCoreSdkTests.Templates;
|
using AspNetCoreSdkTests.Templates;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
@ -36,19 +37,51 @@ namespace AspNetCoreSdkTests
|
||||||
[TestCaseSource(nameof(RunData))]
|
[TestCaseSource(nameof(RunData))]
|
||||||
public void Run(Template template)
|
public void Run(Template template)
|
||||||
{
|
{
|
||||||
Assert.AreEqual(HttpStatusCode.OK, template.HttpResponseAfterRun.StatusCode);
|
var statusCode = template.HttpResponseAfterRun.StatusCode;
|
||||||
Assert.AreEqual(HttpStatusCode.OK, template.HttpsResponseAfterRun.StatusCode);
|
Assert.AreEqual(HttpStatusCode.OK, statusCode,
|
||||||
|
GetMessage(statusCode, template.ServerOutputAfterRun, template.ServerErrorAfterRun));
|
||||||
|
|
||||||
|
statusCode = template.HttpsResponseAfterRun.StatusCode;
|
||||||
|
Assert.AreEqual(HttpStatusCode.OK, statusCode,
|
||||||
|
GetMessage(statusCode, template.ServerOutputAfterRun, template.ServerErrorAfterRun));
|
||||||
|
}
|
||||||
|
|
||||||
|
[NonParallelizable]
|
||||||
|
[Test]
|
||||||
|
[TestCaseSource(nameof(RunNonParallelizableData))]
|
||||||
|
public void RunNonParallelizable(Template template)
|
||||||
|
{
|
||||||
|
Run(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[TestCaseSource(nameof(ExecData))]
|
[TestCaseSource(nameof(ExecData))]
|
||||||
public void Exec(Template template)
|
public void Exec(Template template)
|
||||||
{
|
{
|
||||||
Assert.AreEqual(HttpStatusCode.OK, template.HttpResponseAfterExec.StatusCode);
|
var statusCode = template.HttpResponseAfterExec.StatusCode;
|
||||||
Assert.AreEqual(HttpStatusCode.OK, template.HttpsResponseAfterExec.StatusCode);
|
Assert.AreEqual(HttpStatusCode.OK, statusCode,
|
||||||
|
GetMessage(statusCode, template.ServerOutputAfterExec, template.ServerErrorAfterExec));
|
||||||
|
|
||||||
|
statusCode = template.HttpsResponseAfterExec.StatusCode;
|
||||||
|
Assert.AreEqual(HttpStatusCode.OK, statusCode,
|
||||||
|
GetMessage(statusCode, template.ServerOutputAfterExec, template.ServerErrorAfterExec));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<Template> _restoreTemplates = new[]
|
private static string GetMessage(HttpStatusCode statusCode, string serverOutput, string serverError)
|
||||||
|
{
|
||||||
|
return String.Join(Environment.NewLine,
|
||||||
|
$"StatusCode: {statusCode}",
|
||||||
|
string.Empty,
|
||||||
|
"ServerOutput",
|
||||||
|
"------------",
|
||||||
|
serverOutput,
|
||||||
|
string.Empty,
|
||||||
|
"ServerError",
|
||||||
|
"------------",
|
||||||
|
serverError);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly IEnumerable<Template> _restoreTemplates = new[]
|
||||||
{
|
{
|
||||||
// Framework-dependent
|
// Framework-dependent
|
||||||
Template.GetInstance<ClassLibraryTemplate>(NuGetPackageSource.None, RuntimeIdentifier.None),
|
Template.GetInstance<ClassLibraryTemplate>(NuGetPackageSource.None, RuntimeIdentifier.None),
|
||||||
|
|
@ -103,13 +136,13 @@ namespace AspNetCoreSdkTests
|
||||||
Template.GetInstance<WebApiTemplate>(NuGetPackageSource.NuGetOrg, RuntimeIdentifier.OSX_x64),
|
Template.GetInstance<WebApiTemplate>(NuGetPackageSource.NuGetOrg, RuntimeIdentifier.OSX_x64),
|
||||||
};
|
};
|
||||||
|
|
||||||
public static IEnumerable<TestCaseData> RestoreData = _restoreTemplates.Select(t => new TestCaseData(t));
|
public static IEnumerable<TestCaseData> RestoreData = _restoreTemplates.Select(t => new TestCaseData(t)).ToList();
|
||||||
|
|
||||||
public static IEnumerable<TestCaseData> BuildData => RestoreData;
|
public static IEnumerable<TestCaseData> BuildData => RestoreData;
|
||||||
|
|
||||||
public static IEnumerable<TestCaseData> PublishData => BuildData;
|
public static IEnumerable<TestCaseData> PublishData => BuildData;
|
||||||
|
|
||||||
public static IEnumerable<TestCaseData> RunData =
|
private static readonly IEnumerable<TestCaseData> _runData =
|
||||||
from tcd in BuildData
|
from tcd in BuildData
|
||||||
let t = (Template)tcd.Arguments[0]
|
let t = (Template)tcd.Arguments[0]
|
||||||
// Only interested in verifying web applications
|
// Only interested in verifying web applications
|
||||||
|
|
@ -118,6 +151,18 @@ namespace AspNetCoreSdkTests
|
||||||
where (t.RuntimeIdentifier == RuntimeIdentifier.None)
|
where (t.RuntimeIdentifier == RuntimeIdentifier.None)
|
||||||
select tcd;
|
select tcd;
|
||||||
|
|
||||||
|
// On Linux, calling "dotnet run" on multiple React templates in parallel may fail since the default
|
||||||
|
// fs.inotify.max_user_watches is too low. One workaround is to increase fs.inotify.max_user_watches,
|
||||||
|
// but this means tests will fail on a default machine. A simpler workaround is to disable parallel
|
||||||
|
// execution for these tests.
|
||||||
|
public static IEnumerable<TestCaseData> RunNonParallelizableData =
|
||||||
|
from tcd in _runData
|
||||||
|
let t = (Template)tcd.Arguments[0]
|
||||||
|
where (t is ReactTemplate)
|
||||||
|
select tcd;
|
||||||
|
|
||||||
|
public static IEnumerable<TestCaseData> RunData = _runData.Except(RunNonParallelizableData);
|
||||||
|
|
||||||
public static IEnumerable<TestCaseData> ExecData =
|
public static IEnumerable<TestCaseData> ExecData =
|
||||||
from tcd in PublishData
|
from tcd in PublishData
|
||||||
let t = (Template)tcd.Arguments[0]
|
let t = (Template)tcd.Arguments[0]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace AspNetCoreSdkTests.Templates
|
namespace AspNetCoreSdkTests.Templates
|
||||||
{
|
{
|
||||||
|
|
@ -10,6 +11,12 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
|
|
||||||
public override string Name => "angular";
|
public override string Name => "angular";
|
||||||
|
|
||||||
|
// For some reason, the generated hash in main.[HASH].bundle.js is different on Windows and Linux, despite
|
||||||
|
// the file contents being identical. Replacing the generated hash with "[HASH]" allows the tests to pass
|
||||||
|
// on both platforms.
|
||||||
|
public override IEnumerable<string> FilesAfterPublish =>
|
||||||
|
base.FilesAfterPublish.Select(f => Regex.Replace(f, @"main\.[0-9a-f]*\.bundle\.js$", "main.[HASH].bundle.js"));
|
||||||
|
|
||||||
public override IEnumerable<string> ExpectedFilesAfterPublish =>
|
public override IEnumerable<string> ExpectedFilesAfterPublish =>
|
||||||
base.ExpectedFilesAfterPublish
|
base.ExpectedFilesAfterPublish
|
||||||
.Concat(new[]
|
.Concat(new[]
|
||||||
|
|
@ -23,7 +30,7 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
Path.Combine("ClientApp", "dist", "glyphicons-halflings-regular.fa2772327f55d8198301.woff"),
|
Path.Combine("ClientApp", "dist", "glyphicons-halflings-regular.fa2772327f55d8198301.woff"),
|
||||||
Path.Combine("ClientApp", "dist", "index.html"),
|
Path.Combine("ClientApp", "dist", "index.html"),
|
||||||
Path.Combine("ClientApp", "dist", "inline.318b50c57b4eba3d437b.bundle.js"),
|
Path.Combine("ClientApp", "dist", "inline.318b50c57b4eba3d437b.bundle.js"),
|
||||||
Path.Combine("ClientApp", "dist", "main.d2eed1593a6df639e365.bundle.js"),
|
Path.Combine("ClientApp", "dist", "main.[HASH].bundle.js"),
|
||||||
Path.Combine("ClientApp", "dist", "polyfills.bf95165a1d5098766b92.bundle.js"),
|
Path.Combine("ClientApp", "dist", "polyfills.bf95165a1d5098766b92.bundle.js"),
|
||||||
Path.Combine("ClientApp", "dist", "styles.2727681ffee5a66f9fe6.bundle.css"),
|
Path.Combine("ClientApp", "dist", "styles.2727681ffee5a66f9fe6.bundle.css"),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
private Lazy<IEnumerable<string>> _objFilesAfterRestore;
|
private Lazy<IEnumerable<string>> _objFilesAfterRestore;
|
||||||
private Lazy<(IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles)> _filesAfterBuild;
|
private Lazy<(IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles)> _filesAfterBuild;
|
||||||
private Lazy<IEnumerable<string>> _filesAfterPublish;
|
private Lazy<IEnumerable<string>> _filesAfterPublish;
|
||||||
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https)> _httpResponsesAfterRun;
|
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError )> _httpResponsesAfterRun;
|
||||||
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https)> _httpResponsesAfterExec;
|
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)> _httpResponsesAfterExec;
|
||||||
|
|
||||||
public NuGetPackageSource NuGetPackageSource { get; private set; }
|
public NuGetPackageSource NuGetPackageSource { get; private set; }
|
||||||
public RuntimeIdentifier RuntimeIdentifier { get; private set; }
|
public RuntimeIdentifier RuntimeIdentifier { get; private set; }
|
||||||
|
|
@ -50,10 +50,10 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
_filesAfterPublish = new Lazy<IEnumerable<string>>(
|
_filesAfterPublish = new Lazy<IEnumerable<string>>(
|
||||||
GetFilesAfterPublish, LazyThreadSafetyMode.ExecutionAndPublication);
|
GetFilesAfterPublish, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
|
||||||
_httpResponsesAfterRun = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https)>(
|
_httpResponsesAfterRun = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)>(
|
||||||
GetHttpResponsesAfterRun, LazyThreadSafetyMode.ExecutionAndPublication);
|
GetHttpResponsesAfterRun, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
|
|
||||||
_httpResponsesAfterExec = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https)>(
|
_httpResponsesAfterExec = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)>(
|
||||||
GetHttpResponsesAfterExec, LazyThreadSafetyMode.ExecutionAndPublication);
|
GetHttpResponsesAfterExec, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,11 +69,15 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
public IEnumerable<string> ObjFilesAfterRestore => _objFilesAfterRestore.Value;
|
public IEnumerable<string> ObjFilesAfterRestore => _objFilesAfterRestore.Value;
|
||||||
public IEnumerable<string> ObjFilesAfterBuild => _filesAfterBuild.Value.ObjFiles;
|
public IEnumerable<string> ObjFilesAfterBuild => _filesAfterBuild.Value.ObjFiles;
|
||||||
public IEnumerable<string> BinFilesAfterBuild => _filesAfterBuild.Value.BinFiles;
|
public IEnumerable<string> BinFilesAfterBuild => _filesAfterBuild.Value.BinFiles;
|
||||||
public IEnumerable<string> FilesAfterPublish => _filesAfterPublish.Value;
|
public virtual IEnumerable<string> FilesAfterPublish => _filesAfterPublish.Value;
|
||||||
public HttpResponseMessage HttpResponseAfterRun => _httpResponsesAfterRun.Value.Http;
|
public HttpResponseMessage HttpResponseAfterRun => _httpResponsesAfterRun.Value.Http;
|
||||||
public HttpResponseMessage HttpsResponseAfterRun => _httpResponsesAfterRun.Value.Https;
|
public HttpResponseMessage HttpsResponseAfterRun => _httpResponsesAfterRun.Value.Https;
|
||||||
|
public string ServerOutputAfterRun => _httpResponsesAfterRun.Value.ServerOutput;
|
||||||
|
public string ServerErrorAfterRun => _httpResponsesAfterRun.Value.ServerError;
|
||||||
public HttpResponseMessage HttpResponseAfterExec => _httpResponsesAfterExec.Value.Http;
|
public HttpResponseMessage HttpResponseAfterExec => _httpResponsesAfterExec.Value.Http;
|
||||||
public HttpResponseMessage HttpsResponseAfterExec => _httpResponsesAfterExec.Value.Https;
|
public HttpResponseMessage HttpsResponseAfterExec => _httpResponsesAfterExec.Value.Https;
|
||||||
|
public string ServerOutputAfterExec => _httpResponsesAfterExec.Value.ServerOutput;
|
||||||
|
public string ServerErrorAfterExec => _httpResponsesAfterExec.Value.ServerError;
|
||||||
|
|
||||||
public virtual IEnumerable<string> ExpectedObjFilesAfterRestore => new[]
|
public virtual IEnumerable<string> ExpectedObjFilesAfterRestore => new[]
|
||||||
{
|
{
|
||||||
|
|
@ -115,7 +119,7 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
return IOUtil.GetFiles(Path.Combine(TempDir, DotNetUtil.PublishOutput));
|
return IOUtil.GetFiles(Path.Combine(TempDir, DotNetUtil.PublishOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
private (HttpResponseMessage Http, HttpResponseMessage Https) GetHttpResponsesAfterRun()
|
private (HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError) GetHttpResponsesAfterRun()
|
||||||
{
|
{
|
||||||
// Run depends on Build
|
// Run depends on Build
|
||||||
_ = BinFilesAfterBuild;
|
_ = BinFilesAfterBuild;
|
||||||
|
|
@ -123,7 +127,7 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
return GetHttpResponses(DotNetUtil.Run(TempDir, RuntimeIdentifier));
|
return GetHttpResponses(DotNetUtil.Run(TempDir, RuntimeIdentifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
private (HttpResponseMessage Http, HttpResponseMessage Https) GetHttpResponsesAfterExec()
|
private (HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError) GetHttpResponsesAfterExec()
|
||||||
{
|
{
|
||||||
// Exec depends on Publish
|
// Exec depends on Publish
|
||||||
_ = FilesAfterPublish;
|
_ = FilesAfterPublish;
|
||||||
|
|
@ -131,13 +135,18 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
return GetHttpResponses(DotNetUtil.Exec(TempDir, Name, RuntimeIdentifier));
|
return GetHttpResponses(DotNetUtil.Exec(TempDir, Name, RuntimeIdentifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
private (HttpResponseMessage Http, HttpResponseMessage Https) GetHttpResponses(
|
private (HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError) GetHttpResponses(
|
||||||
(Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) process)
|
(Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) process)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var (httpUrl, httpsUrl) = ScrapeUrls(process);
|
var (httpUrl, httpsUrl) = ScrapeUrls(process);
|
||||||
return (GetAsync(new Uri(new Uri(httpUrl), RelativeUrl)), GetAsync(new Uri(new Uri(httpsUrl), RelativeUrl)));
|
return (
|
||||||
|
Get(new Uri(new Uri(httpUrl), RelativeUrl)),
|
||||||
|
Get(new Uri(new Uri(httpsUrl), RelativeUrl)),
|
||||||
|
process.OutputBuilder.ToString(),
|
||||||
|
process.ErrorBuilder.ToString()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
@ -171,7 +180,7 @@ namespace AspNetCoreSdkTests.Templates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpResponseMessage GetAsync(Uri requestUri)
|
private HttpResponseMessage Get(Uri requestUri)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ namespace AspNetCoreSdkTests.Util
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var path = Path.Combine(workingDirectory, PublishOutput, $"{name}.exe");
|
var file = (runtimeIdentifier == RuntimeIdentifier.Win_x64) ? $"{name}.exe" : name;
|
||||||
|
var path = Path.Combine(workingDirectory, PublishOutput, file);
|
||||||
return StartProcess(path, _urls, workingDirectory);
|
return StartProcess(path, _urls, workingDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue