Skip to content

Commit

Permalink
Implement suggestions from PR review
Browse files Browse the repository at this point in the history
- Restructure e2e test folder structure
- Add e2e test readme/build instructions
- Move installed temp files to $env:TEMP or equivalent
- Do as many checks as possible before creating Process() object
  • Loading branch information
andystaples committed Jan 10, 2025
1 parent 9a68303 commit f171de5
Show file tree
Hide file tree
Showing 20 changed files with 176 additions and 73 deletions.
2 changes: 1 addition & 1 deletion WebJobs.Extensions.DurableTask.sln
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DFPerfScenariosV4", "test\D
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.DurableTask.Tests", "test\Worker.Extensions.DurableTask.Tests\Worker.Extensions.DurableTask.Tests.csproj", "{76DEC17C-BF6A-498A-8E8A-7D6CB2E03284}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetIsolatedE2ETests", "test\DotnetIsolatedE2ETests\DotnetIsolatedE2ETests.csproj", "{63628712-4196-4865-B268-5BA3D8F08DE1}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "E2ETests", "test\e2e\Tests\E2ETests.csproj", "{63628712-4196-4865-B268-5BA3D8F08DE1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
42 changes: 42 additions & 0 deletions test/e2e/Apps/BasicDotNetIsolated/BasicDotNetIsolated.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "app", "app.csproj", "{A3D6D881-0115-409E-92F0-3D50FB152524}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "obj", "obj", "{44B4C292-28D2-4963-89FE-41DDC7C13E97}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debug", "Debug", "{CF64E527-9C6F-447E-AD05-0EE52407CCF1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net8.0", "net8.0", "{9ABF536C-4F1B-42F5-AAFE-7AD88832DBDB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkerExtensions", "obj\Debug\net8.0\WorkerExtensions\WorkerExtensions.csproj", "{65AF45AC-6495-4740-BB7C-67BD125DF158}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A3D6D881-0115-409E-92F0-3D50FB152524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3D6D881-0115-409E-92F0-3D50FB152524}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3D6D881-0115-409E-92F0-3D50FB152524}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3D6D881-0115-409E-92F0-3D50FB152524}.Release|Any CPU.Build.0 = Release|Any CPU
{65AF45AC-6495-4740-BB7C-67BD125DF158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65AF45AC-6495-4740-BB7C-67BD125DF158}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65AF45AC-6495-4740-BB7C-67BD125DF158}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65AF45AC-6495-4740-BB7C-67BD125DF158}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CF64E527-9C6F-447E-AD05-0EE52407CCF1} = {44B4C292-28D2-4963-89FE-41DDC7C13E97}
{9ABF536C-4F1B-42F5-AAFE-7AD88832DBDB} = {CF64E527-9C6F-447E-AD05-0EE52407CCF1}
{65AF45AC-6495-4740-BB7C-67BD125DF158} = {9ABF536C-4F1B-42F5-AAFE-7AD88832DBDB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D4D85C8B-ADB6-47BE-A565-B37D31B6FCD5}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="3.1.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.3.2" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="3.0.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.2.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.18.1" />
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,9 @@ namespace Microsoft.Azure.Durable.Tests.DotnetIsolatedE2E
{
public static class FixtureHelpers
{
public static Process GetFuncHostProcess(bool enableAuth = false)
public static Process GetFuncHostProcess(string appPath, bool enableAuth = false)
{
var funcProcess = new Process();
var rootDir = Path.GetFullPath(@"../../../../..");
var e2eAppBinPath = Path.Combine(rootDir, @"test/DotnetIsolatedE2EApps/MainApp/bin");
string? e2eHostJson = Directory.GetFiles(e2eAppBinPath, "host.json", SearchOption.AllDirectories).FirstOrDefault();

if (e2eHostJson == null)
{
throw new InvalidOperationException($"Could not find a built worker app under '{e2eAppBinPath}'");
}

var e2eAppPath = Path.GetDirectoryName(e2eHostJson);

var cliPath = Path.Combine(rootDir, @"test/DotnetIsolatedE2ETests/Azure.Functions.Cli/func");
var cliPath = Path.Combine(Path.GetTempPath(), @"DurableTaskExtensionE2ETests/Azure.Functions.Cli/func");

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Expand All @@ -36,14 +24,16 @@ public static Process GetFuncHostProcess(bool enableAuth = false)

if (!File.Exists(cliPath))
{
throw new InvalidOperationException($"Could not find '{cliPath}'. Try running '{Path.Combine(rootDir, "setup-e2e-tests.ps1")}' to install it.");
throw new InvalidOperationException($"Could not find '{cliPath}'. Try running '{Path.Combine("build-e2e-test.ps1")}' to install it.");
}

var funcProcess = new Process();

funcProcess.StartInfo.UseShellExecute = false;
funcProcess.StartInfo.RedirectStandardError = true;
funcProcess.StartInfo.RedirectStandardOutput = true;
funcProcess.StartInfo.CreateNoWindow = true;
funcProcess.StartInfo.WorkingDirectory = e2eAppPath;
funcProcess.StartInfo.WorkingDirectory = appPath;
funcProcess.StartInfo.FileName = cliPath;
funcProcess.StartInfo.ArgumentList.Add("host");
funcProcess.StartInfo.ArgumentList.Add("start");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ public class FunctionAppFixture : IAsyncLifetime
{
private readonly ILogger _logger;
private bool _disposed;
private Process _funcProcess;
private Process? _funcProcess;

private JobObjectRegistry _jobObjectRegistry;
private JobObjectRegistry? _jobObjectRegistry;

public FunctionAppFixture(IMessageSink messageSink)
{
// initialize logging
ILoggerFactory loggerFactory = new LoggerFactory();
TestLogs = new TestLoggerProvider(messageSink);
loggerFactory.AddProvider(TestLogs);
_logger = loggerFactory.CreateLogger<FunctionAppFixture>();
this.TestLogs = new TestLoggerProvider(messageSink);
loggerFactory.AddProvider(this.TestLogs);
this._logger = loggerFactory.CreateLogger<FunctionAppFixture>();
}

public async Task InitializeAsync()
Expand All @@ -33,16 +33,33 @@ public async Task InitializeAsync()
if (Constants.FunctionsHostUrl.Contains("localhost"))
{
// kill existing func processes
_logger.LogInformation("Shutting down any running functions hosts..");
this._logger.LogInformation("Shutting down any running functions hosts..");
FixtureHelpers.KillExistingProcessesMatchingName("func");

// start functions process
_logger.LogInformation($"Starting functions host for {Constants.FunctionAppCollectionName}...");
_funcProcess = FixtureHelpers.GetFuncHostProcess();
string workingDir = _funcProcess.StartInfo.WorkingDirectory;
_logger.LogInformation($" Working dir: '${workingDir}' Exists: '{Directory.Exists(workingDir)}'");
string fileName = _funcProcess.StartInfo.FileName;
_logger.LogInformation($" File name: '${fileName}' Exists: '{File.Exists(fileName)}'");
this._logger.LogInformation($"Starting functions host for {Constants.FunctionAppCollectionName}...");

string rootDir = Path.GetFullPath(@"../../../../../../");
string e2eAppBinPath = Path.Combine(rootDir, @"test/e2e/Apps/BasicDotNetIsolated/bin");
string? e2eHostJson = Directory.GetFiles(e2eAppBinPath, "host.json", SearchOption.AllDirectories).FirstOrDefault();

if (e2eHostJson == null)
{
throw new InvalidOperationException($"Could not find a built worker app under '{e2eAppBinPath}'");
}

string? e2eAppPath = Path.GetDirectoryName(e2eHostJson);

if (e2eAppPath == null)
{
throw new InvalidOperationException($"Located host.json for app at {e2eHostJson} but could not resolve the app base directory");
}

this._funcProcess = FixtureHelpers.GetFuncHostProcess(e2eAppPath);
string workingDir = this._funcProcess.StartInfo.WorkingDirectory;
this._logger.LogInformation($" Working dir: '${workingDir}' Exists: '{Directory.Exists(workingDir)}'");
string fileName = this._funcProcess.StartInfo.FileName;
this._logger.LogInformation($" File name: '${fileName}' Exists: '{File.Exists(fileName)}'");

//TODO: This may be added back if we want cosmos tests
//await CosmosDBHelpers.TryCreateDocumentCollectionsAsync(_logger);
Expand All @@ -56,17 +73,17 @@ public async Task InitializeAsync()
// _funcProcess.StartInfo.EnvironmentVariables["DURABLE_ATTACH_DEBUGGER"] = "True";
//}

FixtureHelpers.StartProcessWithLogging(_funcProcess, _logger);
FixtureHelpers.StartProcessWithLogging(this._funcProcess, this._logger);

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// ensure child processes are cleaned up
_jobObjectRegistry = new JobObjectRegistry();
_jobObjectRegistry.Register(_funcProcess);
_jobObjectRegistry.Register(this._funcProcess);
}

var httpClient = new HttpClient();
_logger.LogInformation("Waiting for host to be running...");
this._logger.LogInformation("Waiting for host to be running...");
await TestUtility.RetryAsync(async () =>
{
try
Expand All @@ -77,24 +94,24 @@ await TestUtility.RetryAsync(async () =>
if (doc.RootElement.TryGetProperty("state", out JsonElement value) &&
value.GetString() == "Running")
{
_logger.LogInformation($" Current state: Running");
this._logger.LogInformation($" Current state: Running");
return true;
}

_logger.LogInformation($" Current state: {value}");
this._logger.LogInformation($" Current state: {value}");
return false;
}
catch
{
if (_funcProcess.HasExited)
{
// Something went wrong starting the host - check the logs
_logger.LogInformation($" Current state: process exited - something may have gone wrong.");
this._logger.LogInformation($" Current state: process exited - something may have gone wrong.");
return false;
}

// Can get exceptions before host is running.
_logger.LogInformation($" Current state: process starting");
this._logger.LogInformation($" Current state: process starting");
return false;
}
}, userMessageCallback: () => string.Join(System.Environment.NewLine, TestLogs.CoreToolsLogs));
Expand All @@ -114,25 +131,25 @@ await TestUtility.RetryAsync(async () =>

public Task DisposeAsync()
{
if (!_disposed)
if (!this._disposed)
{
if (_funcProcess != null)
if (this._funcProcess != null)
{
try
{
_funcProcess.Kill();
_funcProcess.Dispose();
this._funcProcess.Kill();
this._funcProcess.Dispose();
}
catch
{
// process may not have started
}
}

_jobObjectRegistry?.Dispose();
this._jobObjectRegistry?.Dispose();
}

_disposed = true;
this._disposed = true;

return Task.CompletedTask;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private static HttpRequestMessage GetTestRequest(string functionName, string que

private static async Task<HttpResponseMessage> GetResponseMessage(HttpRequestMessage request)
{
HttpResponseMessage response = null;
HttpResponseMessage? response = null;
using (var httpClient = new HttpClient())
{
response = await httpClient.SendAsync(request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.Azure.Durable.Tests.DotnetIsolatedE2E
internal class TestLoggerProvider : ILoggerProvider, ILogger
{
private readonly IMessageSink _messageSink;
private ITestOutputHelper _currentTestOutput;
private ITestOutputHelper? _currentTestOutput;
IList<string> _logs = new List<string>();

public TestLoggerProvider(IMessageSink messageSink)
Expand All @@ -32,7 +32,7 @@ public IDisposable UseTestLogger(ITestOutputHelper testOutput)
return new DisposableOutput(this);
}

public IDisposable BeginScope<TState>(TState state)
public IDisposable? BeginScope<TState>(TState state) where TState : notnull
{
return null;
}
Expand All @@ -51,7 +51,7 @@ public bool IsEnabled(LogLevel logLevel)
return true;
}

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
string formattedString = formatter(state, exception);
_messageSink.OnMessage(new DiagnosticMessage(formattedString));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static IConfigurationBuilder AddTestSettings(this IConfigurationBuilder b
return builder.AddJsonFile(configPath, true);
}

public static async Task RetryAsync(Func<Task<bool>> condition, int timeout = 60 * 1000, int pollingInterval = 2 * 1000, bool throwWhenDebugging = false, Func<string> userMessageCallback = null)
public static async Task RetryAsync(Func<Task<bool>> condition, int timeout = 60 * 1000, int pollingInterval = 2 * 1000, bool throwWhenDebugging = false, Func<string>? userMessageCallback = null)
{
DateTime start = DateTime.Now;
while (!await condition())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public bool Register(Process proc)
}

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr CreateJobObject(object a, string lpName);
private static extern IntPtr CreateJobObject(object? a, string? lpName);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,16 @@ param(
[Switch]
$SkipCoreTools,

[Switch]
$UseCoreToolsBuildFromIntegrationTests,

[Switch]
$SkipBuildOnPack
)

$ProjectBaseDirectory = "$PSScriptRoot\..\..\"
$ProjectBaseDirectory = "$PSScriptRoot\..\..\..\"
$ProjectTemporaryPath = Join-Path ([System.IO.Path]::GetTempPath()) "DurableTaskExtensionE2ETests"
mkdir $ProjectTemporaryPath -ErrorAction SilentlyContinue > $Null
$WebJobsExtensionProjectDirectory = Join-Path $ProjectBaseDirectory "src\WebJobs.Extensions.DurableTask"
$WorkerExtensionProjectDirectory = Join-Path $ProjectBaseDirectory "src\Worker.Extensions.DurableTask"
# $E2ETestProjectDirectory = "$ProjectBaseDirectory\test\DotnetIsolatedE2ETests"
$E2EAppProjectDirectory = Join-Path $ProjectBaseDirectory "test\DotnetIsolatedE2EApps/MainApp"
$E2EAppProjectDirectory = Join-Path $ProjectBaseDirectory "test\e2e\Apps\BasicDotNetIsolated"

$FunctionsRuntimeVersion = 4

Expand All @@ -41,7 +39,7 @@ function StopOnFailedExecution {
}
}

$FUNC_CLI_DIRECTORY = Join-Path $PSScriptRoot 'Azure.Functions.Cli'
$FUNC_CLI_DIRECTORY = Join-Path $ProjectTemporaryPath 'Azure.Functions.Cli'
if($SkipCoreTool -or (Test-Path $FUNC_CLI_DIRECTORY))
{
Write-Host "---Skipping Core Tools download---"
Expand All @@ -66,20 +64,10 @@ else
}
}

if ($UseCoreToolsBuildFromIntegrationTests.IsPresent)
{
Write-Host ""
Write-Host "Install the Core Tools for Integration Tests..."
$coreToolsURL = "https://functionsintegclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/Azure.Functions.Cli.$os-$arch.zip"
$versionUrl = "https://functionsintegclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/version.txt"
}
else
if ([string]::IsNullOrWhiteSpace($coreToolsURL))
{
if ([string]::IsNullOrWhiteSpace($coreToolsURL))
{
$coreToolsURL = "https://functionsclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/Azure.Functions.Cli.$os-$arch.zip"
$versionUrl = "https://functionsclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/version.txt"
}
$coreToolsURL = "https://functionsclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/Azure.Functions.Cli.$os-$arch.zip"
$versionUrl = "https://functionsclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/version.txt"
}

Write-Host ""
Expand Down Expand Up @@ -118,7 +106,7 @@ Write-Host "Building WebJobs extension project"

Set-Location $WebJobsExtensionProjectDirectory
if (!(Test-Path "./out")) {
mkdir ./out
mkdir ./out -ErrorAction SilentlyContinue > $Null
}
Get-ChildItem -Path ./out -Include * -File -Recurse | ForEach-Object { $_.Delete()}
dotnet build -c Debug "$WebJobsExtensionProjectDirectory\WebJobs.Extensions.DurableTask.csproj" --output ./out
Expand All @@ -131,7 +119,7 @@ Write-Host "Building worker extension project"

Set-Location $WorkerExtensionProjectDirectory
if (!(Test-Path "./out")) {
mkdir ./out
mkdir ./out -ErrorAction SilentlyContinue > $Null
}
Get-ChildItem -Path ./out -Include * -File -Recurse | ForEach-Object { $_.Delete()}
dotnet build -c Debug "$WorkerExtensionProjectDirectory\Worker.Extensions.DurableTask.csproj" --output ./out
Expand Down Expand Up @@ -172,7 +160,8 @@ if ($SkipStorageEmulator -And $SkipCosmosDBEmulator)
}
else
{
.\start-emulators.ps1 -SkipStorageEmulator:$SkipStorageEmulator -SkipCosmosDBEmulator:$true
# Set-Location $ProjectTemporaryPath
.\start-emulators.ps1 -SkipStorageEmulator:$SkipStorageEmulator -StartCosmosDBEmulator:$false -EmulatorStartDir $ProjectTemporaryPath
}

StopOnFailedExecution
Loading

0 comments on commit f171de5

Please sign in to comment.