Adding E2E test infrastructure and Cosmos E2E test (#100)
This commit is contained in:
Родитель
451240bce6
Коммит
088ee4c28a
|
@ -3,6 +3,8 @@
|
|||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
Azure.Functions.Cli
|
||||
|
||||
# For local nuget packages
|
||||
[Ll]ocal/
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestUtility", "test\TestUtility\TestUtility.csproj", "{C30B77A7-4085-422E-AADE-A4322989F5F8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -67,6 +69,10 @@ Global
|
|||
{BFB2832E-C3AB-4F09-B285-B24E535EC858}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BFB2832E-C3AB-4F09-B285-B24E535EC858}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BFB2832E-C3AB-4F09-B285-B24E535EC858}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C30B77A7-4085-422E-AADE-A4322989F5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C30B77A7-4085-422E-AADE-A4322989F5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C30B77A7-4085-422E-AADE-A4322989F5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C30B77A7-4085-422E-AADE-A4322989F5F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -78,6 +84,7 @@ Global
|
|||
{5C38C5A3-83A5-4E2F-9B32-204C2225E890} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378}
|
||||
{6B64FE04-BA90-49FC-893A-DF12EF15280C} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348}
|
||||
{BFB2832E-C3AB-4F09-B285-B24E535EC858} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378}
|
||||
{C30B77A7-4085-422E-AADE-A4322989F5F8} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A}
|
||||
|
|
|
@ -22,22 +22,27 @@ variables:
|
|||
|
||||
steps:
|
||||
- task: UseDotNet@2
|
||||
displayName: 'Use .NET Core sdk'
|
||||
displayName: 'Use .NET 5 sdk'
|
||||
inputs:
|
||||
packageType: sdk
|
||||
version: 5.0.100
|
||||
performMultiLevelLookup: true
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Build projects'
|
||||
inputs:
|
||||
command: 'build'
|
||||
arguments: '-c Release'
|
||||
projects: '**/*.csproj'
|
||||
|
||||
- pwsh: ./setup-e2e-tests.ps1
|
||||
displayName: "Setup E2E tests"
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Run tests'
|
||||
inputs:
|
||||
command: 'test'
|
||||
projects: 'test/**/*.csproj'
|
||||
projects: 'test/**/*Tests.csproj'
|
||||
|
||||
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
|
||||
displayName: 'Sdk: ESRP CodeSigning - Authenticode'
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
function RunTest([string] $project, [string] $description,[bool] $skipBuild = $false, $filter = $null) {
|
||||
Write-Host "Running test: $description" -ForegroundColor DarkCyan
|
||||
Write-Host "-----------------------------------------------------------------------------" -ForegroundColor DarkCyan
|
||||
Write-Host
|
||||
|
||||
$cmdargs = "test", "$project", "-v", "q", "-l", "trx", "-r",".\testResults"
|
||||
|
||||
if ($filter) {
|
||||
$cmdargs += "--filter", "$filter"
|
||||
}
|
||||
|
||||
& dotnet $cmdargs | Out-Host
|
||||
$r = $?
|
||||
|
||||
Write-Host
|
||||
Write-Host "-----------------------------------------------------------------------------" -ForegroundColor DarkCyan
|
||||
Write-Host
|
||||
|
||||
return $r
|
||||
}
|
||||
|
||||
$tests = @(
|
||||
@{project ="$PSScriptRoot/test/E2ETests/E2ETests/E2ETests.csproj"; description="E2E integration tests"}
|
||||
)
|
||||
|
||||
$success = $true
|
||||
$testRunSucceeded = $true
|
||||
|
||||
foreach ($test in $tests){
|
||||
$testRunSucceeded = RunTest $test.project $test.description $testRunSucceeded $test.filter
|
||||
$success = $testRunSucceeded -and $success
|
||||
}
|
||||
|
||||
if (-not $success) { exit 1 }
|
|
@ -32,12 +32,12 @@
|
|||
<None Include="$(OutputPath)Mono.Cecil.dll">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>tools\netstandard2.0</PackagePath>
|
||||
</None>
|
||||
</None>
|
||||
|
||||
<None Include="$(FunctionsGeneratorOutputPath)Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>tools\netstandard2.0</PackagePath>
|
||||
</None>
|
||||
</None>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -47,4 +47,10 @@
|
|||
<PackageReference Include="System.Text.Json" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FunctionMetadataLoaderExtension\FunctionMetadataLoaderExtension.csproj">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
# A function that checks exit codes and fails script if an error is found
|
||||
function StopOnFailedExecution {
|
||||
if ($LastExitCode)
|
||||
{
|
||||
exit $LastExitCode
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host
|
||||
Write-Host "---Core Tools download---"
|
||||
|
||||
$skipCliDownload = $false
|
||||
if($args[0])
|
||||
{
|
||||
$skipCliDownload = $args[0]
|
||||
Write-Host "Skipping CLI Download"
|
||||
}
|
||||
|
||||
$currDir = Get-Location
|
||||
$output = "$currDir\Azure.Functions.Cli.zip"
|
||||
if(!$skipCliDownload)
|
||||
{
|
||||
Write-Host "Deleting Functions Core Tools if exists...."
|
||||
Remove-Item -Force ./Azure.Functions.Cli.zip -ErrorAction Ignore
|
||||
Remove-Item -Recurse -Force ./Azure.Functions.Cli -ErrorAction Ignore
|
||||
|
||||
if (-not (Test-Path env:CORE_TOOLS_URL))
|
||||
{
|
||||
$env:CORE_TOOLS_URL = "https://functionsclibuilds.blob.core.windows.net/builds/3/latest/Azure.Functions.Cli.win-x86.zip"
|
||||
}
|
||||
|
||||
Write-Host "Downloading Functions Core Tools to $output"
|
||||
Invoke-RestMethod -Uri 'https://functionsclibuilds.blob.core.windows.net/builds/3/latest/version.txt' -OutFile version.txt
|
||||
Write-Host "Using Functions Core Tools version: $(Get-Content -Raw version.txt)"
|
||||
Remove-Item version.txt
|
||||
|
||||
$wc = New-Object System.Net.WebClient
|
||||
$wc.DownloadFile($env:CORE_TOOLS_URL, $output)
|
||||
|
||||
$destinationPath = ".\Azure.Functions.Cli"
|
||||
Write-Host "Extracting Functions Core Tools to $destinationPath"
|
||||
Expand-Archive ".\Azure.Functions.Cli.zip" -DestinationPath $destinationPath
|
||||
}
|
||||
|
||||
if (Test-Path $output)
|
||||
{
|
||||
Remove-Item $output
|
||||
}
|
||||
|
||||
Write-Host "------"
|
||||
|
||||
.\tools\devpack.ps1 -E2E
|
||||
|
||||
.\tools\start-emulators.ps1
|
||||
|
||||
StopOnFailedExecution
|
|
@ -1,9 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Functions.Worker.Context;
|
||||
using Microsoft.Azure.Functions.Worker.Pipeline;
|
||||
|
@ -64,12 +63,10 @@ namespace Microsoft.Azure.Functions.Worker
|
|||
|
||||
foreach (var binding in executionContext.OutputBindings)
|
||||
{
|
||||
dynamic d = binding.Value;
|
||||
var rpcVal = d.GetValue();
|
||||
var parameterBinding = new ParameterBinding
|
||||
{
|
||||
Name = binding.Key,
|
||||
Data = RpcExtensions.ToRpc(rpcVal)
|
||||
Data = binding.Value.ToRpc()
|
||||
};
|
||||
response.OutputData.Add(parameterBinding);
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace Microsoft.Azure.Functions.Worker
|
|||
else
|
||||
{
|
||||
// TODO: Is this correct? Passing a null body causes the entire
|
||||
// response to become the body in functions. Need to investigate.
|
||||
// response to become the body in functions. Need to investigate.
|
||||
http.Body = string.Empty.ToRpc();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Azure.Functions.Worker.E2EApp.Cosmos;
|
||||
using Microsoft.Azure.Functions.Worker.Pipeline;
|
||||
using Microsoft.Azure.WebJobs;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Worker.E2EApp
|
||||
{
|
||||
public static class CosmosFunction
|
||||
{
|
||||
[FunctionName("CosmosTrigger")]
|
||||
public static void Run([CosmosDBTrigger(
|
||||
databaseName: "%CosmosDb%",
|
||||
collectionName: "%CosmosCollIn%",
|
||||
ConnectionStringSetting = "CosmosConnection",
|
||||
LeaseCollectionName = "leases",
|
||||
CreateLeaseCollectionIfNotExists = true)] IReadOnlyList<MyDocument> input,
|
||||
[CosmosDB(
|
||||
databaseName: "%CosmosDb%",
|
||||
collectionName: "%CosmosCollOut%",
|
||||
ConnectionStringSetting = "CosmosConnection",
|
||||
CreateIfNotExists = true)] OutputBinding<IEnumerable<object>> output,
|
||||
FunctionExecutionContext context)
|
||||
{
|
||||
if (input != null && input.Count > 0)
|
||||
{
|
||||
foreach (var doc in input)
|
||||
{
|
||||
context.Logger.LogInformation($"id: {doc.Id}");
|
||||
}
|
||||
|
||||
output.SetValue(input.Select(p => new { id = p.Id }));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace Microsoft.Azure.Functions.Worker.E2EApp.Cosmos
|
||||
{
|
||||
public class MyDocument
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
public int Number { get; set; }
|
||||
|
||||
public bool Boolean { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
|
||||
<OutputType>Exe</OutputType>
|
||||
<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
|
||||
<AssemblyName>Microsoft.Azure.Functions.Worker.E2EApp</AssemblyName>
|
||||
<RootNamespace>Microsoft.Azure.Functions.Worker.E2EApp</RootNamespace>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.0.0-preview3" />
|
||||
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.8" />
|
||||
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.0.2" />
|
||||
<PackageReference Include="Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\DotNetWorker\DotNetWorker.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="host.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="local.settings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,32 @@
|
|||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Functions.Worker.Configuration;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Worker.E2EApps.CosmosApp
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
var host = new HostBuilder()
|
||||
.ConfigureAppConfiguration(c =>
|
||||
{
|
||||
c.AddCommandLine(args);
|
||||
})
|
||||
.ConfigureFunctionsWorker((c, b) =>
|
||||
{
|
||||
b.UseFunctionExecutionMiddleware();
|
||||
|
||||
b.Services
|
||||
.AddOptions<JsonSerializerOptions>()
|
||||
.Configure(o => o.PropertyNameCaseInsensitive = true);
|
||||
})
|
||||
.Build();
|
||||
|
||||
await host.RunAsync();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "2.0",
|
||||
"logging": {
|
||||
"applicationInsights": {
|
||||
"samplingExcludedTypes": "Request",
|
||||
"samplingSettings": {
|
||||
"isEnabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"IsEncrypted": false,
|
||||
"Values": {
|
||||
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
|
||||
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
|
||||
"CosmosConnection": "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
|
||||
"CosmosDb": "ItemDb",
|
||||
"CosmosCollIn": "ItemCollectionIn",
|
||||
"CosmosCollOut": "ItemCollectionOut"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Tests.E2ETests
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public static IConfiguration Configuration = TestUtility.GetTestConfiguration();
|
||||
public static string FunctionsHostUrl = Configuration["FunctionAppUrl"] ?? "http://localhost:7071";
|
||||
|
||||
//Queue tests
|
||||
public static class Queue
|
||||
{
|
||||
public static string StorageConnectionStringSetting = Configuration["AzureWebJobsStorage"];
|
||||
public static string OutputBindingName = "test-output-node";
|
||||
public static string InputBindingName = "test-input-node";
|
||||
}
|
||||
|
||||
// CosmosDB tests
|
||||
public static class CosmosDB
|
||||
{
|
||||
public static string EmulatorConnectionString = "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
|
||||
public static string CosmosDBConnectionStringSetting = Configuration["AzureWebJobsCosmosDBConnectionString"] ?? EmulatorConnectionString;
|
||||
public static string DbName = "ItemDb";
|
||||
public static string InputCollectionName = "ItemCollectionIn";
|
||||
public static string OutputCollectionName = "ItemCollectionOut";
|
||||
public static string LeaseCollectionName = "leases";
|
||||
}
|
||||
|
||||
// EventHubs
|
||||
public static class EventHubs
|
||||
{
|
||||
public static string EventHubsConnectionStringSetting = Configuration["AzureWebJobsEventHubSender"];
|
||||
|
||||
public static class Json_Test
|
||||
{
|
||||
public static string OutputName = "test-output-object-node";
|
||||
public static string InputName = "test-input-object-node";
|
||||
}
|
||||
|
||||
public static class String_Test
|
||||
{
|
||||
public static string OutputName = "test-output-string-node";
|
||||
public static string InputName = "test-input-string-node";
|
||||
}
|
||||
|
||||
public static class Cardinality_One_Test
|
||||
{
|
||||
public static string InputName = "test-input-one-node";
|
||||
public static string OutputName = "test-output-one-node";
|
||||
}
|
||||
}
|
||||
|
||||
// Xunit Fixtures and Collections
|
||||
public const string FunctionAppCollectionName = "FunctionAppCollection";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Tests.E2ETests
|
||||
{
|
||||
[Collection(Constants.FunctionAppCollectionName)]
|
||||
public class CosmosDBEndToEndTests : IDisposable
|
||||
{
|
||||
private readonly IDisposable _disposeLog;
|
||||
private readonly FunctionAppFixture _fixture;
|
||||
|
||||
public CosmosDBEndToEndTests(FunctionAppFixture fixture, ITestOutputHelper testOutput)
|
||||
{
|
||||
_fixture = fixture;
|
||||
_disposeLog = _fixture.TestLogs.UseTestLogger(testOutput);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CosmosDBTriggerAndOutput_Succeeds()
|
||||
{
|
||||
string expectedDocId = Guid.NewGuid().ToString();
|
||||
try
|
||||
{
|
||||
//Trigger
|
||||
await CosmosDBHelpers.CreateDocument(expectedDocId);
|
||||
|
||||
//Read
|
||||
var documentId = await CosmosDBHelpers.ReadDocument(expectedDocId);
|
||||
Assert.Equal(expectedDocId, documentId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Clean up
|
||||
await CosmosDBHelpers.DeleteTestDocuments(expectedDocId);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_disposeLog?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Microsoft.Azure.Functions.Worker.E2ETests</AssemblyName>
|
||||
<RootNamespace>Microsoft.Azure.Functions.Worker.E2ETests</RootNamespace>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.13.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Moq" Version="4.14.7" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\TestUtility\TestUtility.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="xunit.runner.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30907.101
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "E2ETests", "E2ETests.csproj", "{D8F06DF8-BA70-46B6-A4FC-FCC5A4B2C5ED}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{A5270BA7-7A26-41E0-B48E-26EBEF1A6AF2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtility", "..\..\TestUtility\TestUtility.csproj", "{1EC49D94-DFE9-4C4D-8D3E-E683AC930085}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker", "..\..\..\src\DotNetWorker\DotNetWorker.csproj", "{30E9E94D-B936-4ECA-97F2-1B54824CE045}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "E2EApp", "..\E2EApps\E2EApp\E2EApp.csproj", "{D37818A3-3821-4F7F-B92B-41E4038C63CC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D8F06DF8-BA70-46B6-A4FC-FCC5A4B2C5ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D8F06DF8-BA70-46B6-A4FC-FCC5A4B2C5ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D8F06DF8-BA70-46B6-A4FC-FCC5A4B2C5ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D8F06DF8-BA70-46B6-A4FC-FCC5A4B2C5ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1EC49D94-DFE9-4C4D-8D3E-E683AC930085}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1EC49D94-DFE9-4C4D-8D3E-E683AC930085}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1EC49D94-DFE9-4C4D-8D3E-E683AC930085}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1EC49D94-DFE9-4C4D-8D3E-E683AC930085}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{30E9E94D-B936-4ECA-97F2-1B54824CE045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{30E9E94D-B936-4ECA-97F2-1B54824CE045}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{30E9E94D-B936-4ECA-97F2-1B54824CE045}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{30E9E94D-B936-4ECA-97F2-1B54824CE045}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D37818A3-3821-4F7F-B92B-41E4038C63CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D37818A3-3821-4F7F-B92B-41E4038C63CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D37818A3-3821-4F7F-B92B-41E4038C63CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D37818A3-3821-4F7F-B92B-41E4038C63CC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{D37818A3-3821-4F7F-B92B-41E4038C63CC} = {A5270BA7-7A26-41E0-B48E-26EBEF1A6AF2}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {89DAAC07-473A-4DEC-957E-62A8D7F2494B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Tests.E2ETests
|
||||
|
||||
{
|
||||
public static class FixtureHelpers
|
||||
{
|
||||
public static Process GetFuncHostProcess(bool enableAuth = false)
|
||||
{
|
||||
var funcProcess = new Process();
|
||||
var rootDir = Path.GetFullPath(@"..\..\..\..\..\..");
|
||||
var e2eAppBinPath = Path.Combine(rootDir, @"test\E2ETests\E2EApps\E2EApp\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, @"Azure.Functions.Cli\func.exe");
|
||||
if (!File.Exists(cliPath))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find '{cliPath}'. Try running '{Path.Combine(rootDir, "setup-e2e-tests.ps1")}' to install it.");
|
||||
}
|
||||
|
||||
funcProcess.StartInfo.UseShellExecute = false;
|
||||
funcProcess.StartInfo.RedirectStandardError = true;
|
||||
funcProcess.StartInfo.RedirectStandardOutput = true;
|
||||
funcProcess.StartInfo.CreateNoWindow = true;
|
||||
funcProcess.StartInfo.WorkingDirectory = e2eAppPath;
|
||||
funcProcess.StartInfo.FileName = Path.Combine(rootDir, @"Azure.Functions.Cli\func.exe");
|
||||
funcProcess.StartInfo.ArgumentList.Add("host");
|
||||
funcProcess.StartInfo.ArgumentList.Add("start");
|
||||
funcProcess.StartInfo.ArgumentList.Add("--csharp");
|
||||
if (enableAuth)
|
||||
{
|
||||
funcProcess.StartInfo.ArgumentList.Add("--enableAuth");
|
||||
}
|
||||
|
||||
return funcProcess;
|
||||
}
|
||||
|
||||
public static void StartProcessWithLogging(Process funcProcess, ILogger logger)
|
||||
{
|
||||
funcProcess.ErrorDataReceived += (sender, e) => logger.LogError(e?.Data);
|
||||
funcProcess.OutputDataReceived += (sender, e) => logger.LogInformation(e?.Data);
|
||||
|
||||
funcProcess.Start();
|
||||
|
||||
funcProcess.BeginErrorReadLine();
|
||||
funcProcess.BeginOutputReadLine();
|
||||
}
|
||||
|
||||
public static void KillExistingFuncHosts()
|
||||
{
|
||||
foreach (var func in Process.GetProcessesByName("func"))
|
||||
{
|
||||
func.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Functions.Worker.E2ETests.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Tests.E2ETests
|
||||
{
|
||||
public class FunctionAppFixture : IAsyncLifetime
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private bool _disposed;
|
||||
private Process _funcProcess;
|
||||
|
||||
public FunctionAppFixture(IMessageSink messageSink)
|
||||
{
|
||||
// initialize logging
|
||||
ILoggerFactory loggerFactory = new LoggerFactory();
|
||||
TestLogs = new TestLoggerProvider(messageSink);
|
||||
loggerFactory.AddProvider(TestLogs);
|
||||
_logger = loggerFactory.CreateLogger<FunctionAppFixture>();
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
// start host via CLI if testing locally
|
||||
if (Constants.FunctionsHostUrl.Contains("localhost"))
|
||||
{
|
||||
// kill existing func processes
|
||||
_logger.LogInformation("Shutting down any running functions hosts..");
|
||||
FixtureHelpers.KillExistingFuncHosts();
|
||||
|
||||
// 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)}'");
|
||||
|
||||
await CosmosDBHelpers.CreateDocumentCollections();
|
||||
|
||||
FixtureHelpers.StartProcessWithLogging(_funcProcess, _logger);
|
||||
|
||||
await TestUtility.RetryAsync(() =>
|
||||
{
|
||||
return Task.FromResult(TestLogs.CoreToolsLogs.Any(p => p.Contains("Host lock lease acquired by instance ID")));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
internal TestLoggerProvider TestLogs { get; private set; }
|
||||
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_logger.LogInformation("FunctionAppFixture disposing.");
|
||||
|
||||
if (_funcProcess != null)
|
||||
{
|
||||
_logger.LogInformation($"Shutting down functions host for {Constants.FunctionAppCollectionName}");
|
||||
_funcProcess.Kill();
|
||||
_funcProcess.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
[CollectionDefinition(Constants.FunctionAppCollectionName)]
|
||||
public class FunctionAppCollection : ICollectionFixture<FunctionAppFixture>
|
||||
{
|
||||
// This class has no code, and is never created. Its purpose is simply
|
||||
// to be the place to apply [CollectionDefinition] and all the
|
||||
// ICollectionFixture<> interfaces.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.Documents;
|
||||
using Microsoft.Azure.Documents.Client;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Tests.E2ETests
|
||||
{
|
||||
public static class CosmosDBHelpers
|
||||
{
|
||||
private static DocumentClient _docDbClient;
|
||||
private static Uri inputCollectionsUri = UriFactory.CreateDocumentCollectionUri(Constants.CosmosDB.DbName, Constants.CosmosDB.InputCollectionName);
|
||||
private static Uri outputCollectionsUri = UriFactory.CreateDocumentCollectionUri(Constants.CosmosDB.DbName, Constants.CosmosDB.OutputCollectionName);
|
||||
private static Uri leasesCollectionsUri = UriFactory.CreateDocumentCollectionUri(Constants.CosmosDB.DbName, Constants.CosmosDB.LeaseCollectionName);
|
||||
|
||||
static CosmosDBHelpers()
|
||||
{
|
||||
var builder = new System.Data.Common.DbConnectionStringBuilder();
|
||||
builder.ConnectionString = Constants.CosmosDB.CosmosDBConnectionStringSetting;
|
||||
var serviceUri = new Uri(builder["AccountEndpoint"].ToString());
|
||||
_docDbClient = new DocumentClient(serviceUri, builder["AccountKey"].ToString());
|
||||
}
|
||||
|
||||
// keep
|
||||
public async static Task CreateDocument(string docId)
|
||||
{
|
||||
Document documentToTest = new Document()
|
||||
{
|
||||
Id = docId
|
||||
};
|
||||
|
||||
_ = await _docDbClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(Constants.CosmosDB.DbName, Constants.CosmosDB.InputCollectionName), documentToTest);
|
||||
}
|
||||
|
||||
// keep
|
||||
public async static Task<string> ReadDocument(string docId)
|
||||
{
|
||||
var docUri = UriFactory.CreateDocumentUri(Constants.CosmosDB.DbName, Constants.CosmosDB.OutputCollectionName, docId);
|
||||
Document retrievedDocument = null;
|
||||
await TestUtility.RetryAsync(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
retrievedDocument = await _docDbClient.ReadDocumentAsync(docUri, new RequestOptions { PartitionKey = new PartitionKey(docId) });
|
||||
return true;
|
||||
}
|
||||
catch (DocumentClientException ex) when (ex.Error.Code == "NotFound")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}, pollingInterval: 500);
|
||||
|
||||
return retrievedDocument?.Id;
|
||||
}
|
||||
|
||||
// keep
|
||||
public async static Task DeleteTestDocuments(string docId)
|
||||
{
|
||||
var inputDocUri = UriFactory.CreateDocumentUri(Constants.CosmosDB.DbName, Constants.CosmosDB.InputCollectionName, docId);
|
||||
await DeleteDocument(inputDocUri);
|
||||
var outputDocUri = UriFactory.CreateDocumentUri(Constants.CosmosDB.DbName, Constants.CosmosDB.OutputCollectionName, docId);
|
||||
await DeleteDocument(outputDocUri);
|
||||
}
|
||||
|
||||
private async static Task DeleteDocument(Uri docUri)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _docDbClient.DeleteDocumentAsync(docUri);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
// keep
|
||||
public async static Task CreateDocumentCollections()
|
||||
{
|
||||
Database db = await _docDbClient.CreateDatabaseIfNotExistsAsync(new Database { Id = Constants.CosmosDB.DbName });
|
||||
Uri dbUri = UriFactory.CreateDatabaseUri(db.Id);
|
||||
|
||||
await CreateCollection(dbUri, Constants.CosmosDB.InputCollectionName);
|
||||
await CreateCollection(dbUri, Constants.CosmosDB.OutputCollectionName);
|
||||
await CreateCollection(dbUri, Constants.CosmosDB.LeaseCollectionName);
|
||||
}
|
||||
|
||||
public async static Task DeleteDocumentCollections()
|
||||
{
|
||||
await DeleteCollection(inputCollectionsUri);
|
||||
await DeleteCollection(outputCollectionsUri);
|
||||
await DeleteCollection(leasesCollectionsUri);
|
||||
}
|
||||
|
||||
private async static Task DeleteCollection(Uri collectionUri)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _docDbClient.DeleteDocumentCollectionAsync(collectionUri);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Ignore
|
||||
}
|
||||
}
|
||||
|
||||
private async static Task CreateCollection(Uri dbUri, string collectioName)
|
||||
{
|
||||
var pkd = new PartitionKeyDefinition();
|
||||
pkd.Paths.Add("/id");
|
||||
DocumentCollection collection = new DocumentCollection()
|
||||
{
|
||||
Id = collectioName,
|
||||
PartitionKey = pkd
|
||||
};
|
||||
await _docDbClient.CreateDocumentCollectionIfNotExistsAsync(dbUri, collection,
|
||||
new RequestOptions()
|
||||
{
|
||||
PartitionKey = new PartitionKey("/id"),
|
||||
OfferThroughput = 400
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Worker.E2ETests.Helpers
|
||||
{
|
||||
internal class TestLoggerProvider : ILoggerProvider, ILogger
|
||||
{
|
||||
private readonly IMessageSink _messageSink;
|
||||
private ITestOutputHelper _currentTestOutput;
|
||||
IList<string> _logs = new List<string>();
|
||||
|
||||
public TestLoggerProvider(IMessageSink messageSink)
|
||||
{
|
||||
_messageSink = messageSink;
|
||||
}
|
||||
|
||||
public IEnumerable<string> CoreToolsLogs => _logs.ToArray();
|
||||
|
||||
// This needs to be created/disposed per-test so we can associate logs
|
||||
// with the specific running test.
|
||||
public IDisposable UseTestLogger(ITestOutputHelper testOutput)
|
||||
{
|
||||
// reset these every test
|
||||
_currentTestOutput = testOutput;
|
||||
return new DisposableOutput(this);
|
||||
}
|
||||
|
||||
public IDisposable BeginScope<TState>(TState state)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
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));
|
||||
_logs.Add(formattedString);
|
||||
_currentTestOutput?.WriteLine(formattedString);
|
||||
}
|
||||
|
||||
private class DisposableOutput : IDisposable
|
||||
{
|
||||
private readonly TestLoggerProvider _xunitLogger;
|
||||
|
||||
public DisposableOutput(TestLoggerProvider xunitLogger)
|
||||
{
|
||||
_xunitLogger = xunitLogger;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_xunitLogger._currentTestOutput = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
|
||||
"diagnosticMessages": true
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.Azure.Functions.Tests
|
||||
{
|
||||
public static class TestUtility
|
||||
{
|
||||
public static IConfiguration GetTestConfiguration()
|
||||
{
|
||||
return new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.AddTestSettings()
|
||||
.Build();
|
||||
}
|
||||
|
||||
public static IConfigurationBuilder AddTestSettings(this IConfigurationBuilder builder)
|
||||
{
|
||||
string configPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".azurefunctions", "appsettings.tests.json");
|
||||
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)
|
||||
{
|
||||
DateTime start = DateTime.Now;
|
||||
while (!await condition())
|
||||
{
|
||||
await Task.Delay(pollingInterval);
|
||||
|
||||
bool shouldThrow = !Debugger.IsAttached || (Debugger.IsAttached && throwWhenDebugging);
|
||||
if (shouldThrow && (DateTime.Now - start).TotalMilliseconds > timeout)
|
||||
{
|
||||
string error = "Condition not reached within timeout.";
|
||||
if (userMessageCallback != null)
|
||||
{
|
||||
error += " " + userMessageCallback();
|
||||
}
|
||||
throw new ApplicationException(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AssemblyName>Microsoft.Azure.Functions.Tests.TestUtility</AssemblyName>
|
||||
<RootNamespace>Microsoft.Azure.Functions.Tests.TestUtility</RootNamespace>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,8 +1,31 @@
|
|||
# Packs the SDK locally, updates the Sample to use this package, and then builds the sample.
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[Switch]
|
||||
$E2E
|
||||
)
|
||||
|
||||
|
||||
# Packs the SDK locally, and (by default) updates the Sample to use this package, then builds.
|
||||
# Specify --E2E to instead target the E2E test app.
|
||||
|
||||
$rootPath = Split-Path -Parent $PSScriptRoot
|
||||
$project = "$rootPath\samples\FunctionApp\FunctionApp.csproj"
|
||||
|
||||
`dotnet pack $rootPath\sdk\sdk\Sdk.csproj -o $rootPath\local
|
||||
`dotnet remove $rootPath\samples\FunctionApp\FunctionApp.csproj package Microsoft.Azure.Functions.Worker.Sdk
|
||||
`dotnet add $rootPath\samples\FunctionApp\FunctionApp.csproj package Microsoft.Azure.Functions.Worker.Sdk -s $rootPath\local --prerelease
|
||||
`dotnet build $rootPath\samples\FunctionApp\FunctionApp.csproj
|
||||
if($E2E -eq $true)
|
||||
{
|
||||
$project = "$rootPath\test\E2ETests\E2EApps\E2EApp\E2EApp.csproj"
|
||||
}
|
||||
|
||||
$localPack = "$rootPath\local"
|
||||
Write-Host
|
||||
Write-Host "---Updating project with local SDK pack---"
|
||||
Write-Host "Packing SDK to $localPack"
|
||||
& "dotnet" "pack" "$rootPath\sdk\sdk\Sdk.csproj" "-v" "q" "-o" "$localPack" "-nologo"
|
||||
Write-Host
|
||||
Write-Host "Updating SDK package reference in $project"
|
||||
& "dotnet" "remove" $project "package" "Microsoft.Azure.Functions.Worker.Sdk"
|
||||
& "dotnet" "add" $project "package" "Microsoft.Azure.Functions.Worker.Sdk" "-s" "$localPack" "--prerelease"
|
||||
Write-Host
|
||||
Write-Host "Building $project"
|
||||
& "dotnet" "build" $project "-v" "q" "-nologo"
|
||||
Write-Host "------"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "---Starting CosmosDB emulator---"
|
||||
$cosmosStatus = Get-CosmosDbEmulatorStatus
|
||||
|
||||
if ($cosmosStatus -ne "Running")
|
||||
{
|
||||
Start-CosmosDbEmulator -NoWait
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
|
||||
Write-Host "Cosmos status: $cosmosStatus"
|
||||
Write-Host "------"
|
||||
Write-Host ""
|
||||
Write-Host "---Starting Storage emulator---"
|
||||
& "${Env:ProgramFiles(x86)}\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe" "start"
|
||||
Write-Host "------"
|
||||
Write-Host ""
|
||||
Write-Host "---Checking CosmosDB emulator status---"
|
||||
while ($cosmosStatus -ne "Running")
|
||||
{
|
||||
$cosmosStatus = Get-CosmosDbEmulatorStatus
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
Write-Host "Cosmos status: $cosmosStatus"
|
||||
Write-Host "------"
|
||||
Write-Host ""
|
Загрузка…
Ссылка в новой задаче