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

Custom Host E2E Tests #4201

Open
wants to merge 74 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 73 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
55f8b79
Core Tools OOP Host (#3802)
aishwaryabh Sep 24, 2024
06abd8a
Custom host changes for VS Scenario (#3831)
aishwaryabh Sep 24, 2024
48e0160
Fix build to remove uploadToStorage (#3839)
aishwaryabh Sep 26, 2024
8e51cb0
Adding artifact assembler tool which consolidates the artifacts and p…
kshyju Sep 27, 2024
bf37f55
Updating the artifact name to include "_inproc" suffix (#3849)
kshyju Sep 27, 2024
b774dc0
Small refactor and new tests (#3835)
fabiocav Oct 1, 2024
1b49034
Updating coretools to detect unsupported inproc6 sdk scenario (#3825)
surgupta-msft Oct 3, 2024
a471fb9
Restructuring custom host to improve error handling (#3861)
mattchenderson Oct 4, 2024
ed00ddf
Create Artifacts for releasing OOP core tools (#3848)
aishwaryabh Oct 7, 2024
cb9428a
Adding package reference (#3872)
aishwaryabh Oct 9, 2024
2821f48
Templates version update (#3883)
surgupta-msft Oct 15, 2024
bc790c6
Create metadata.json file in conslidated artifacts intermediate pipel…
aishwaryabh Oct 17, 2024
48490a7
template update (#4151)
aishwaryabh Nov 6, 2024
0d55b5d
Update templates for dotnet isolated worker 2.x (#4189)
jviau Nov 13, 2024
01502f8
adding tests for custom host
aishwaryabh Nov 18, 2024
5fceed1
removing zipping for now
aishwaryabh Nov 18, 2024
c83e950
trying to print out value
aishwaryabh Nov 20, 2024
5d9f276
update artifact assembler
aishwaryabh Nov 20, 2024
d9aeb26
removing extra delete file lol
aishwaryabh Nov 20, 2024
6058a5c
adding env variables
aishwaryabh Nov 21, 2024
b72b76f
add language
aishwaryabh Nov 21, 2024
d0bbf1b
trying to see if this works for e2e tests
aishwaryabh Nov 21, 2024
89cce7a
this should work
aishwaryabh Nov 21, 2024
e33cfe4
setting language
aishwaryabh Nov 22, 2024
4c0beb6
trying out new change
aishwaryabh Nov 22, 2024
d321529
trying to set env variable
aishwaryabh Nov 22, 2024
f81f400
updating start tests
aishwaryabh Nov 22, 2024
b789909
setting env variable
aishwaryabh Nov 22, 2024
382e5d9
updating cli tester
aishwaryabh Nov 22, 2024
ae308b6
trying to set testVsArtifacts
aishwaryabh Nov 22, 2024
291d2f4
setting paths back to normal
aishwaryabh Nov 22, 2024
11dad61
local settings json parser print current directory
aishwaryabh Nov 22, 2024
ec1cd91
adding local.settings.json
aishwaryabh Nov 22, 2024
8cbbe6b
tests should fail now if they actually fail
aishwaryabh Nov 22, 2024
bbd5fb9
adding net6 inproc tests
aishwaryabh Nov 22, 2024
6d4c5fd
updating path
aishwaryabh Nov 25, 2024
44820b5
start tests net6 update
aishwaryabh Nov 25, 2024
d294ca0
updating zipping to happen
aishwaryabh Nov 25, 2024
cdc2632
updating test project
aishwaryabh Nov 25, 2024
78ee1f2
fixing e2e test project
aishwaryabh Nov 25, 2024
5284e1d
add trailing comma and test comment
aishwaryabh Nov 25, 2024
ea886d1
updating tests to not exit with expected error
aishwaryabh Nov 25, 2024
3ef34c8
adding tests for custom host
aishwaryabh Nov 18, 2024
21d4bb7
removing zipping for now
aishwaryabh Nov 18, 2024
3d3a5f9
trying to print out value
aishwaryabh Nov 20, 2024
8ce45a2
update artifact assembler
aishwaryabh Nov 20, 2024
3002ea3
removing extra delete file lol
aishwaryabh Nov 20, 2024
f31c58f
adding env variables
aishwaryabh Nov 21, 2024
1ce18f6
add language
aishwaryabh Nov 21, 2024
e0f10e0
trying to see if this works for e2e tests
aishwaryabh Nov 21, 2024
c8c8cc2
this should work
aishwaryabh Nov 21, 2024
b144ac4
setting language
aishwaryabh Nov 22, 2024
bf63368
trying out new change
aishwaryabh Nov 22, 2024
77e5ca8
trying to set env variable
aishwaryabh Nov 22, 2024
3a94e8e
updating start tests
aishwaryabh Nov 22, 2024
0dec7fd
setting env variable
aishwaryabh Nov 22, 2024
c6bffdd
updating cli tester
aishwaryabh Nov 22, 2024
22a5a98
trying to set testVsArtifacts
aishwaryabh Nov 22, 2024
c36a121
setting paths back to normal
aishwaryabh Nov 22, 2024
edc0cda
local settings json parser print current directory
aishwaryabh Nov 22, 2024
4335061
adding local.settings.json
aishwaryabh Nov 22, 2024
e21c72e
tests should fail now if they actually fail
aishwaryabh Nov 22, 2024
a1fcb65
adding net6 inproc tests
aishwaryabh Nov 22, 2024
436bc68
updating path
aishwaryabh Nov 25, 2024
d8a7ef5
start tests net6 update
aishwaryabh Nov 25, 2024
1207323
updating zipping to happen
aishwaryabh Nov 25, 2024
ad23dc6
updating test project
aishwaryabh Nov 25, 2024
c2b4527
fixing e2e test project
aishwaryabh Nov 25, 2024
644ad75
add trailing comma and test comment
aishwaryabh Nov 25, 2024
e121d76
updating tests to not exit with expected error
aishwaryabh Nov 25, 2024
4ac4fad
merging in latest changes
aishwaryabh Nov 26, 2024
a86f93d
updating artifact assembler
aishwaryabh Nov 26, 2024
e6dbec8
forgot to update assembler
aishwaryabh Nov 26, 2024
7bb2ac9
changing environment variable back to normal
aishwaryabh Nov 26, 2024
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
12 changes: 0 additions & 12 deletions src/Azure.Functions.ArtifactAssembler/ArtifactAssembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,20 +201,8 @@ private async Task CreateVisualStudioCoreToolsAsync()
EnsureArtifactDirectoryExist(coreToolsHostArtifactDirPath);
await Task.Run(() => FileUtilities.CopyDirectory(coreToolsHostArtifactDirPath, consolidatedArtifactDirPath));
Directory.Delete(coreToolsHostArtifactDirPath, true);

// consolidatedArtifactDirPath now contains custom core-tools host, in-proc6 and in-proc8 sub directories. Create a zip file.
var zipPath = Path.Combine(customHostTargetArtifactDir, $"{consolidatedArtifactDirName}.zip");
await Task.Run(() => FileUtilities.CreateZipFile(consolidatedArtifactDirPath, zipPath));
Console.WriteLine($"Successfully created target runtime zip at: {zipPath}");

Directory.Delete(consolidatedArtifactDirPath, true);
}

// Delete directories
Directory.Delete(_inProc6ExtractedRootDir, true);
Directory.Delete(_inProc8ExtractedRootDir, true);
Directory.Delete(_coreToolsHostExtractedRootDir, true);

Console.WriteLine("Finished assembling Visual Studio Core Tools artifacts");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@

namespace Azure.Functions.ArtifactAssembler
{
internal sealed class CliArtifactZipper
internal sealed class ArtifactZipper
{
private readonly string _rootWorkingDirectory;
public CliArtifactZipper(string rootWorkingDirectory)
public ArtifactZipper(string rootWorkingDirectory)
{
_rootWorkingDirectory = rootWorkingDirectory;
}

internal void ZipCliArtifacts()
{
Console.WriteLine("Zipping CLI Artifacts");
string stagingDirectory = Path.Combine(_rootWorkingDirectory, Constants.StagingDirName, Constants.CliOutputArtifactDirectoryName);

// Get all directories in the staging directory
Expand Down Expand Up @@ -49,6 +50,40 @@ internal void ZipCliArtifacts()
Console.WriteLine("All directories zipped successfully!");
}

internal void ZipVisualStudioArtifacts()
{
Console.WriteLine("Zipping Visual Studio Artifacts");
string stagingDirectory = Path.Combine(_rootWorkingDirectory, Constants.StagingDirName, Constants.VisualStudioOutputArtifactDirectoryName);

// Get all directories in the staging directory
var directories = Directory.EnumerateDirectories(stagingDirectory);

foreach (var dir in directories)
{
// Define zip file path and name
string zipFileName = $"{new DirectoryInfo(dir).Name}.zip";
string zipFilePath = Path.Combine(stagingDirectory, zipFileName);

// Compress directory into zip file
FileUtilities.CreateZipFile(dir, zipFilePath);
Console.WriteLine($"Zipped: {dir} -> {zipFilePath}");

// Verify zip creation and delete original directory to free up space
if (File.Exists(zipFilePath))
{
Console.WriteLine($"Successfully created zip: {zipFilePath}");
Directory.Delete(dir, true);
Console.WriteLine($"Deleted original directory: {dir}");
}
else
{
Console.WriteLine($"Failed to create zip for: {dir}");
}
}

Console.WriteLine("All directories zipped successfully!");
}

internal void CreateWorkerDirectoryIfDoesNotExist(string dir)
{
string workersPath = Path.Combine(dir, "workers");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ internal static class EnvironmentVariables
internal const string CoreToolsHostLinuxArtifactName = "CORETOOLS_HOST_LINUX_ARTIFACT_NAME";
internal const string OutOfProcArtifactName = "OUT_OF_PROC_ARTIFACT_NAME";
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
param (
[string]$StagingDirectory
)

# Set the path to test project (.csproj) and runtime settings
$testProjectPath = "..\..\test\Azure.Functions.Cli.Tests\Azure.Functions.Cli.Tests.csproj"
$runtimeSettings = "..\..\test\Azure.Functions.Cli.Tests\E2E\StartTests_artifact_consolidation_visualstudio.runsettings"

[System.Environment]::SetEnvironmentVariable("FUNCTIONS_WORKER_RUNTIME", "dotnet", "Process")

dotnet build $testProjectPath

# Loop through each subdirectory within the parent directory
Get-ChildItem -Path $StagingDirectory -Directory | ForEach-Object {
$subDir = $_.FullName
Write-Host "name of current file: $subDir"
if ($subDir -like "*win-x*") {
Write-Host "Current directory: $subDir"
# Find func.exe in the subdirectory
$funcExePath = Get-ChildItem -Path $subDir -Filter "func.exe" -ErrorAction SilentlyContinue

if ($funcExePath) {
$funcExePathFullName = $funcExePath.FullName
Write-Host "Setting FUNC_PATH to: $funcExePathFullName"

# Set the environment variable FUNC_PATH to the func.exe or func path
[System.Environment]::SetEnvironmentVariable("FUNC_PATH", $funcExePath.FullName, "Process")

# Run dotnet test with the environment variable set
Write-Host "Running 'dotnet test' on test project: $testProjectPath"
dotnet test $testProjectPath --no-build --settings $runtimeSettings --logger "console;verbosity=detailed"

if ($LASTEXITCODE -ne 0) {
# If the exit code is non-zero, throw an error
Write-Host "Tests failed with exit code $LASTEXITCODE"
throw "dotnet test failed within $subDir. Exiting with error."
} else {
# If the exit code is zero, tests passed
Write-Host "All tests passed successfully within $subDir"
}
} else {
Write-Host "No func.exe or func found in: $subDir"
}
}
}
5 changes: 3 additions & 2 deletions src/Azure.Functions.ArtifactAssembler/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ static async Task<int> Main(string[] args)
// Check if an argument for zipping is passed
if (args.Length > 0 && args[0].Equals("zip", StringComparison.OrdinalIgnoreCase))
{
var zipCliArtifacts = new CliArtifactZipper(currentWorkingDirectory);
zipCliArtifacts.ZipCliArtifacts();
var zipArtifacts = new ArtifactZipper(currentWorkingDirectory);
zipArtifacts.ZipCliArtifacts();
zipArtifacts.ZipVisualStudioArtifacts();
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
<ProjectReference Include="..\..\src\Azure.Functions.Cli\Azure.Functions.Cli.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="E2E\TestProject\" />
</ItemGroup>

<PropertyGroup>
<RunSettingsFilePath>$(MSBuildProjectDirectory)\E2E\StartTests_default.runsettings</RunSettingsFilePath>
</PropertyGroup>
Expand Down
14 changes: 11 additions & 3 deletions test/Azure.Functions.Cli.Tests/E2E/Helpers/CliTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static CliTester()

public static async Task Run(RunConfiguration[] runConfigurations, ITestOutputHelper output = null, string workingDir = null, bool startHost = false)
{
bool wasWorkingDirPassedIn = (workingDir != null);
string workingDirectory = workingDir ?? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());

bool cleanupDirectory = string.IsNullOrEmpty(workingDir);
Expand All @@ -54,7 +55,7 @@ public static async Task Run(RunConfiguration[] runConfigurations, ITestOutputHe

try
{
await InternalRun(workingDirectory, runConfigurations, output, startHost);
await InternalRun(workingDirectory, runConfigurations, output, startHost, wasWorkingDirPassedIn);
}
finally
{
Expand All @@ -73,7 +74,7 @@ public static async Task Run(RunConfiguration[] runConfigurations, ITestOutputHe
}
}

private static async Task InternalRun(string workingDir, RunConfiguration[] runConfigurations, ITestOutputHelper output, bool startHost)
private static async Task InternalRun(string workingDir, RunConfiguration[] runConfigurations, ITestOutputHelper output, bool startHost, bool wasWorkingDirPassedIn)
{
await using var hostExe = new Executable(_func, StartHostCommand, workingDirectory: workingDir);
var stdout = new StringBuilder();
Expand Down Expand Up @@ -132,6 +133,13 @@ string cmd when cmd.StartsWith("dotnet", StringComparison.OrdinalIgnoreCase) =>
catch (Exception e)
{
logErr($"Error while running test: {e.Message}");
// Throw an error if working directory was passed in
// For some reason, tests don't fail with the working directory not being the default one so we need this specification
if(wasWorkingDirPassedIn)
{
exitError = true;
}

}
finally
{
Expand Down Expand Up @@ -166,7 +174,7 @@ string cmd when cmd.StartsWith("dotnet", StringComparison.OrdinalIgnoreCase) =>
}
}

// AssertExitError(runConfiguration, exitError);
AssertExitError(runConfiguration, exitError);
AssertFiles(runConfiguration, workingDir);
AssertDirectories(runConfiguration, workingDir);
AssertOutputContent(runConfiguration, stdout);
Expand Down
6 changes: 6 additions & 0 deletions test/Azure.Functions.Cli.Tests/E2E/Helpers/TestTraits.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,11 @@ internal static class TestTraits
/// We still want to run these tests in the PR/ official core tools pipelines and in the artifact consolidation pipeline for a sanity check before publishing the artifacts.
/// </summary>
public const string UseInConsolidatedArtifactGeneration = "UseInConsolidatedArtifactGeneration";

/// <summary>
/// Tests with UseInVisualStudioConsolidatedArtifactGeneration label will not be run in the default scenario and only in the artifact consolidation pipeline
/// Otherwise tests with this label will fail in the PR/ official core tools pipelines since the nested inproc artifacts are not present.
/// </summary>
public const string UseInVisualStudioConsolidatedArtifactGeneration = "UseInVisualStudioConsolidatedArtifactGeneration";
}
}
73 changes: 70 additions & 3 deletions test/Azure.Functions.Cli.Tests/E2E/StartTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,76 @@ await CliTester.Run(new RunConfiguration[]
}, _output);
}

[Fact]
[Trait(TestTraits.Group, TestTraits.UseInVisualStudioConsolidatedArtifactGeneration)]
public async Task Start_InProc_Net8_VisualStudio_SuccessfulFunctionExecution_WithSpecifyingRuntime()
{
await CliTester.Run(new RunConfiguration[]
{
new RunConfiguration
{
Commands = new[]
{
$"start --port {_funcHostPort} --verbose --dotnet"
},
ExpectExit = false,
Test = async (workingDir, p, _) =>
{
using (var client = new HttpClient() { BaseAddress = new Uri($"http://localhost:{_funcHostPort}") })
{
(await WaitUntilReady(client)).Should().BeTrue(because: _serverNotReady);
var response = await client.GetAsync("/api/Function1?name=Test");
var result = await response.Content.ReadAsStringAsync();
p.Kill();
result.Should().Be("Hello, Test. This HTTP triggered function executed successfully.", because: "response from default function should be 'Hello, {name}. This HTTP triggered function executed successfully.'");

if (_output is Xunit.Sdk.TestOutputHelper testOutputHelper)
{
testOutputHelper.Output.Should().Contain("Loading .NET 8 host");
}
}
},
CommandTimeout = TimeSpan.FromSeconds(300),
}
}, _output, "../../../E2E/TestProject/TestNet8InProcProject");

}

[Fact]
[Trait(TestTraits.Group, TestTraits.UseInVisualStudioConsolidatedArtifactGeneration)]
public async Task Start_InProc_Net6_VisualStudio_SuccessfulFunctionExecution_WithSpecifyingRuntime()
{
await CliTester.Run(new RunConfiguration[]
{
new RunConfiguration
{
Commands = new[]
{
$"start --port {_funcHostPort} --verbose --dotnet"
},
ExpectExit = false,
Test = async (workingDir, p, _) =>
{
using (var client = new HttpClient() { BaseAddress = new Uri($"http://localhost:{_funcHostPort}") })
{
(await WaitUntilReady(client)).Should().BeTrue(because: _serverNotReady);
var response = await client.GetAsync("/api/Function2?name=Test");
var result = await response.Content.ReadAsStringAsync();
p.Kill();
result.Should().Be("Hello, Test. This HTTP triggered function executed successfully.", because: "response from default function should be 'Hello, {name}. This HTTP triggered function executed successfully.'");

if (_output is Xunit.Sdk.TestOutputHelper testOutputHelper)
{
testOutputHelper.Output.Should().Contain("Loading .NET 6 host");
}
}
},
CommandTimeout = TimeSpan.FromSeconds(300),
}
}, _output, "../../../E2E/TestProject/TestNet6InProcProject");

}

[Fact]
public async Task Start_DotnetIsolated_Net9_SuccessfulFunctionExecution()
{
Expand Down Expand Up @@ -1385,7 +1455,6 @@ await CliTester.Run(new RunConfiguration[]
$"start --port {_funcHostPort}"
},
ExpectExit = true,
ExitInError = true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exitInError does not work when we have to assert the exit error, so I removed this since it was not relevant anymore

OutputContains = new[] { "Extension bundle configuration should not be present" },
},
}, _output);
Expand Down Expand Up @@ -1420,7 +1489,6 @@ await CliTester.Run(new RunConfiguration[]
$"start --port {_funcHostPort}"
},
ExpectExit = true,
ExitInError = true,
OutputContains = new[] { "Host.json file in missing" },
},
}, _output);
Expand Down Expand Up @@ -1570,7 +1638,6 @@ await CliTester.Run(new RunConfiguration[]
},
CommandTimeout = TimeSpan.FromSeconds(300),
ExpectExit = true,
ExitInError = true,
OutputContains = new[]
{
"Missing value for AzureWebJobsStorage in local.settings.json. This is required for all triggers other than httptrigger, kafkatrigger, orchestrationTrigger, activityTrigger, entityTrigger",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<TestCaseFilter>(Group = UseInVisualStudioConsolidatedArtifactGeneration)</TestCaseFilter>
</RunConfiguration>
</RunSettings>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<TestCaseFilter>(Group != RequiresNestedInProcArtifacts)</TestCaseFilter>
<TestCaseFilter>(Group != RequiresNestedInProcArtifacts AND Group != UseInVisualStudioConsolidatedArtifactGeneration)</TestCaseFilter>
</RunConfiguration>
</RunSettings>
Loading