diff --git a/performance/.editorconfig b/performance/.editorconfig
new file mode 100644
index 000000000..0082aa2a0
--- /dev/null
+++ b/performance/.editorconfig
@@ -0,0 +1,9 @@
+# See https://github.com/dotnet/roslyn-analyzers/blob/main/.editorconfig for an example on different settings and how they're used
+
+[*.cs]
+
+# Disabled
+dotnet_diagnostic.CA1309.severity = silent # Use ordinal StringComparison - this isn't important for tests and just adds clutter
+dotnet_diagnostic.CA1305.severity = silent # Specify IFormatProvider - this isn't important for tests and just adds clutter
+dotnet_diagnostic.CA1707.severity = silent # Identifiers should not contain underscores - this helps make test names more readable
+dotnet_diagnostic.CA2201.severity = silent # Do not raise reserved exception types - tests can throw whatever they want
\ No newline at end of file
diff --git a/performance/SqlTriggerBindingPerformance.cs b/performance/SqlTriggerBindingPerformance.cs
index 43a63f5ea..233339f43 100644
--- a/performance/SqlTriggerBindingPerformance.cs
+++ b/performance/SqlTriggerBindingPerformance.cs
@@ -4,17 +4,16 @@
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Extensions.Sql.Samples.TriggerBindingSamples;
using Microsoft.Azure.WebJobs.Extensions.Sql.Tests.Common;
-using Microsoft.Azure.WebJobs.Extensions.Sql.Tests.Integration;
using BenchmarkDotNet.Attributes;
namespace Microsoft.Azure.WebJobs.Extensions.Sql.Performance
{
- public class SqlTriggerBindingPerformance : SqlTriggerBindingIntegrationTests
+ [MemoryDiagnoser]
+ public class SqlTriggerBindingPerformance : SqlTriggerBindingPerformanceTestBase
{
[GlobalSetup]
public void GlobalSetup()
{
- this.EnableChangeTrackingForTable("Products");
this.StartFunctionHost(nameof(ProductsTrigger), SupportedLanguages.CSharp);
}
@@ -34,18 +33,5 @@ await this.WaitForProductChanges(
id => id * 100,
this.GetBatchProcessingTimeout(1, count));
}
-
- [IterationCleanup]
- public void IterationCleanup()
- {
- // Delete all rows in Products table after each iteration
- this.ExecuteNonQuery("TRUNCATE TABLE Products");
- }
-
- [GlobalCleanup]
- public void GlobalCleanup()
- {
- this.Dispose();
- }
}
}
\ No newline at end of file
diff --git a/performance/SqlTriggerBindingPerformanceTestBase.cs b/performance/SqlTriggerBindingPerformanceTestBase.cs
new file mode 100644
index 000000000..d891118a0
--- /dev/null
+++ b/performance/SqlTriggerBindingPerformanceTestBase.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+using Microsoft.Azure.WebJobs.Extensions.Sql.Tests.Integration;
+using BenchmarkDotNet.Attributes;
+
+namespace Microsoft.Azure.WebJobs.Extensions.Sql.Performance
+{
+ public class SqlTriggerBindingPerformanceTestBase : SqlTriggerBindingIntegrationTests
+ {
+ [IterationSetup]
+ public void IterationSetup()
+ {
+ this.SetChangeTrackingForTable("Products", true);
+ }
+
+ [IterationCleanup]
+ public void IterationCleanup()
+ {
+ this.DisposeFunctionHosts();
+ this.SetChangeTrackingForTable("Products", false);
+ // Delete all rows in Products table after each iteration so we start fresh each time
+ this.ExecuteNonQuery("TRUNCATE TABLE Products");
+ // Delete the leases table, otherwise we may end up getting blocked by leases from a previous run
+ this.ExecuteNonQuery(@"DECLARE @cmd varchar(100)
+DECLARE cmds CURSOR FOR
+SELECT 'DROP TABLE az_func.' + Name + ''
+FROM sys.tables
+WHERE Name LIKE 'Leases_%'
+
+OPEN cmds
+WHILE 1 = 1
+BEGIN
+ FETCH cmds INTO @cmd
+ IF @@fetch_status != 0 BREAK
+ EXEC(@cmd)
+END
+CLOSE cmds;
+DEALLOCATE cmds");
+ }
+
+ [GlobalCleanup]
+ public void GlobalCleanup()
+ {
+ this.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Integration/IntegrationTestBase.cs b/test/Integration/IntegrationTestBase.cs
index 5d6a80a8e..934db3bdc 100644
--- a/test/Integration/IntegrationTestBase.cs
+++ b/test/Integration/IntegrationTestBase.cs
@@ -394,18 +394,7 @@ public void Dispose()
this.LogOutput($"Failed to close connection. Error: {e1.Message}");
}
- foreach (Process functionHost in this.FunctionHostList)
- {
- try
- {
- functionHost.Kill();
- functionHost.Dispose();
- }
- catch (Exception e2)
- {
- this.LogOutput($"Failed to stop function host, Error: {e2.Message}");
- }
- }
+ this.DisposeFunctionHosts();
try
{
@@ -432,6 +421,26 @@ public void Dispose()
GC.SuppressFinalize(this);
}
+ ///
+ /// Disposes all the running function hosts
+ ///
+ protected void DisposeFunctionHosts()
+ {
+ foreach (Process functionHost in this.FunctionHostList)
+ {
+ try
+ {
+ functionHost.Kill();
+ functionHost.Dispose();
+ }
+ catch (Exception ex)
+ {
+ this.LogOutput($"Failed to stop function host, Error: {ex.Message}");
+ }
+ }
+ this.FunctionHostList.Clear();
+ }
+
protected async Task SendInputRequest(string functionName, string query = "")
{
string requestUri = $"http://localhost:{this.Port}/api/{functionName}/{query}";
diff --git a/test/Integration/SqlTriggerBindingIntegrationTests.cs b/test/Integration/SqlTriggerBindingIntegrationTests.cs
index a1f6d4c80..738c9f3c7 100644
--- a/test/Integration/SqlTriggerBindingIntegrationTests.cs
+++ b/test/Integration/SqlTriggerBindingIntegrationTests.cs
@@ -29,7 +29,7 @@ public SqlTriggerBindingIntegrationTests(ITestOutputHelper output = null) : base
[Fact]
public async Task SingleOperationTriggerTest()
{
- this.EnableChangeTrackingForTable("Products");
+ this.SetChangeTrackingForTable("Products");
this.StartFunctionHost(nameof(ProductsTrigger), SupportedLanguages.CSharp);
int firstId = 1;
@@ -82,7 +82,7 @@ public async Task BatchSizeOverrideTriggerTest()
const int batchSize = SqlTableChangeMonitor