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 NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
|
@ -36,19 +37,51 @@ namespace AspNetCoreSdkTests
|
|||
[TestCaseSource(nameof(RunData))]
|
||||
public void Run(Template template)
|
||||
{
|
||||
Assert.AreEqual(HttpStatusCode.OK, template.HttpResponseAfterRun.StatusCode);
|
||||
Assert.AreEqual(HttpStatusCode.OK, template.HttpsResponseAfterRun.StatusCode);
|
||||
var statusCode = template.HttpResponseAfterRun.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]
|
||||
[TestCaseSource(nameof(ExecData))]
|
||||
public void Exec(Template template)
|
||||
{
|
||||
Assert.AreEqual(HttpStatusCode.OK, template.HttpResponseAfterExec.StatusCode);
|
||||
Assert.AreEqual(HttpStatusCode.OK, template.HttpsResponseAfterExec.StatusCode);
|
||||
var statusCode = template.HttpResponseAfterExec.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
|
||||
Template.GetInstance<ClassLibraryTemplate>(NuGetPackageSource.None, RuntimeIdentifier.None),
|
||||
|
|
@ -103,13 +136,13 @@ namespace AspNetCoreSdkTests
|
|||
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> PublishData => BuildData;
|
||||
|
||||
public static IEnumerable<TestCaseData> RunData =
|
||||
private static readonly IEnumerable<TestCaseData> _runData =
|
||||
from tcd in BuildData
|
||||
let t = (Template)tcd.Arguments[0]
|
||||
// Only interested in verifying web applications
|
||||
|
|
@ -118,6 +151,18 @@ namespace AspNetCoreSdkTests
|
|||
where (t.RuntimeIdentifier == RuntimeIdentifier.None)
|
||||
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 =
|
||||
from tcd in PublishData
|
||||
let t = (Template)tcd.Arguments[0]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AspNetCoreSdkTests.Templates
|
||||
{
|
||||
|
|
@ -10,6 +11,12 @@ namespace AspNetCoreSdkTests.Templates
|
|||
|
||||
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 =>
|
||||
base.ExpectedFilesAfterPublish
|
||||
.Concat(new[]
|
||||
|
|
@ -23,7 +30,7 @@ namespace AspNetCoreSdkTests.Templates
|
|||
Path.Combine("ClientApp", "dist", "glyphicons-halflings-regular.fa2772327f55d8198301.woff"),
|
||||
Path.Combine("ClientApp", "dist", "index.html"),
|
||||
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", "styles.2727681ffee5a66f9fe6.bundle.css"),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ namespace AspNetCoreSdkTests.Templates
|
|||
private Lazy<IEnumerable<string>> _objFilesAfterRestore;
|
||||
private Lazy<(IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles)> _filesAfterBuild;
|
||||
private Lazy<IEnumerable<string>> _filesAfterPublish;
|
||||
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https)> _httpResponsesAfterRun;
|
||||
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https)> _httpResponsesAfterExec;
|
||||
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError )> _httpResponsesAfterRun;
|
||||
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)> _httpResponsesAfterExec;
|
||||
|
||||
public NuGetPackageSource NuGetPackageSource { get; private set; }
|
||||
public RuntimeIdentifier RuntimeIdentifier { get; private set; }
|
||||
|
|
@ -50,10 +50,10 @@ namespace AspNetCoreSdkTests.Templates
|
|||
_filesAfterPublish = new Lazy<IEnumerable<string>>(
|
||||
GetFilesAfterPublish, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||
|
||||
_httpResponsesAfterRun = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https)>(
|
||||
_httpResponsesAfterRun = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)>(
|
||||
GetHttpResponsesAfterRun, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||
|
||||
_httpResponsesAfterExec = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https)>(
|
||||
_httpResponsesAfterExec = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)>(
|
||||
GetHttpResponsesAfterExec, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||
}
|
||||
|
||||
|
|
@ -69,11 +69,15 @@ namespace AspNetCoreSdkTests.Templates
|
|||
public IEnumerable<string> ObjFilesAfterRestore => _objFilesAfterRestore.Value;
|
||||
public IEnumerable<string> ObjFilesAfterBuild => _filesAfterBuild.Value.ObjFiles;
|
||||
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 HttpsResponseAfterRun => _httpResponsesAfterRun.Value.Https;
|
||||
public string ServerOutputAfterRun => _httpResponsesAfterRun.Value.ServerOutput;
|
||||
public string ServerErrorAfterRun => _httpResponsesAfterRun.Value.ServerError;
|
||||
public HttpResponseMessage HttpResponseAfterExec => _httpResponsesAfterExec.Value.Http;
|
||||
public HttpResponseMessage HttpsResponseAfterExec => _httpResponsesAfterExec.Value.Https;
|
||||
public string ServerOutputAfterExec => _httpResponsesAfterExec.Value.ServerOutput;
|
||||
public string ServerErrorAfterExec => _httpResponsesAfterExec.Value.ServerError;
|
||||
|
||||
public virtual IEnumerable<string> ExpectedObjFilesAfterRestore => new[]
|
||||
{
|
||||
|
|
@ -115,7 +119,7 @@ namespace AspNetCoreSdkTests.Templates
|
|||
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
|
||||
_ = BinFilesAfterBuild;
|
||||
|
|
@ -123,7 +127,7 @@ namespace AspNetCoreSdkTests.Templates
|
|||
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
|
||||
_ = FilesAfterPublish;
|
||||
|
|
@ -131,13 +135,18 @@ namespace AspNetCoreSdkTests.Templates
|
|||
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)
|
||||
{
|
||||
try
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
@ -171,7 +180,7 @@ namespace AspNetCoreSdkTests.Templates
|
|||
}
|
||||
}
|
||||
|
||||
private HttpResponseMessage GetAsync(Uri requestUri)
|
||||
private HttpResponseMessage Get(Uri requestUri)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ namespace AspNetCoreSdkTests.Util
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue