Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion samples/samples-js/ProductsTrigger/function.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"name": "changes",
"type": "sqlTrigger",
"direction": "in",
"tableName": "Products",
"tableName": "dbo.Products",
"connectionStringSetting": "SqlConnectionString"
}
],
Expand Down
2 changes: 1 addition & 1 deletion samples/samples-powershell/ProductsTrigger/function.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"name": "changes",
"type": "sqlTrigger",
"direction": "in",
"tableName": "Products",
"tableName": "dbo.Products",
"connectionStringSetting": "SqlConnectionString"
}
],
Expand Down
2 changes: 1 addition & 1 deletion samples/samples-python/ProductsTrigger/function.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"name": "changes",
"type": "sqlTrigger",
"direction": "in",
"tableName": "Products",
"tableName": "dbo.Products",
"connectionStringSetting": "SqlConnectionString"
}
],
Expand Down
4 changes: 2 additions & 2 deletions test/Integration/SqlTriggerBindingIntegrationTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ void MonitorOutputData(object sender, DataReceivedEventArgs e)
/// <param name="functionName">Name of the user function that should cause error in trigger listener</param>
/// <param name="useTestFolder">Whether the functions host should be launched from test folder</param>
/// <param name="expectedErrorMessage">Expected error message string</param>
protected void StartFunctionHostAndWaitForError(string functionName, bool useTestFolder, string expectedErrorMessage)
protected void StartFunctionHostAndWaitForError(string functionName, SupportedLanguages lang, bool useTestFolder, string expectedErrorMessage)
{
string errorMessage = null;
var tcs = new TaskCompletionSource<bool>();
Expand All @@ -165,7 +165,7 @@ void OutputHandler(object sender, DataReceivedEventArgs e)
};

// All trigger integration tests are only using C# functions for testing at the moment.
this.StartFunctionHost(functionName, SupportedLanguages.CSharp, useTestFolder, OutputHandler);
this.StartFunctionHost(functionName, lang, useTestFolder, OutputHandler);

// The functions host generally logs the error message within a second after starting up.
const int BufferTimeForErrorInSeconds = 15;
Expand Down
54 changes: 36 additions & 18 deletions test/Integration/SqlTriggerBindingIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ await this.WaitForProductChanges(
/// Verifies that manually setting the batch size using the original config var correctly changes the
/// number of changes processed at once.
/// </summary>
[Fact]
public async Task BatchSizeOverrideTriggerTest()
[Theory]
[SqlInlineData()]
[UnsupportedLanguages(SupportedLanguages.Java, SupportedLanguages.OutOfProc)]
public async Task BatchSizeOverrideTriggerTest(SupportedLanguages lang)
{
// Use enough items to require 4 batches to be processed but then
// set the max batch size to the same value so they can all be processed in one
Expand All @@ -97,7 +99,7 @@ public async Task BatchSizeOverrideTriggerTest()
maxBatchSize.ToString());
this.StartFunctionHost(
nameof(ProductsTriggerWithValidation),
SupportedLanguages.CSharp,
lang,
useTestFolder: true,
customOutputHandler: handler,
environmentVariables: new Dictionary<string, string>() {
Expand All @@ -120,8 +122,10 @@ await this.WaitForProductChanges(
/// <summary>
/// Verifies that manually setting the max batch size correctly changes the number of changes processed at once
/// </summary>
[Fact]
public async Task MaxBatchSizeOverrideTriggerTest()
[Theory]
[SqlInlineData()]
[UnsupportedLanguages(SupportedLanguages.Java, SupportedLanguages.OutOfProc)]
public async Task MaxBatchSizeOverrideTriggerTest(SupportedLanguages lang)
{
// Use enough items to require 4 batches to be processed but then
// set the max batch size to the same value so they can all be processed in one
Expand All @@ -139,7 +143,7 @@ public async Task MaxBatchSizeOverrideTriggerTest()
maxBatchSize.ToString());
this.StartFunctionHost(
nameof(ProductsTriggerWithValidation),
SupportedLanguages.CSharp,
lang,
useTestFolder: true,
customOutputHandler: handler,
environmentVariables: new Dictionary<string, string>() {
Expand Down Expand Up @@ -203,13 +207,15 @@ await this.WaitForProductChanges(
/// Verifies that if several changes have happened to the table row since last invocation, then a single net
/// change for that row is passed to the user function.
/// </summary>
[Fact]
public async Task MultiOperationTriggerTest()
[Theory]
[SqlInlineData()]
[UnsupportedLanguages(SupportedLanguages.Java)]
public async Task MultiOperationTriggerTest(SupportedLanguages lang)
{
int firstId = 1;
int lastId = 5;
this.SetChangeTrackingForTable("Products");
this.StartFunctionHost(nameof(ProductsTrigger), SupportedLanguages.CSharp);
this.StartFunctionHost(nameof(ProductsTrigger), lang);

// 1. Insert + multiple updates to a row are treated as single insert with latest row values.
await this.WaitForProductChanges(
Expand Down Expand Up @@ -408,15 +414,17 @@ public async Task MultiFunctionTriggerTest()
/// <summary>
/// Ensures correct functionality with user functions running across multiple functions host processes.
/// </summary>
[Fact]
public async Task MultiHostTriggerTest()
[Theory]
[SqlInlineData()]
[UnsupportedLanguages(SupportedLanguages.Java)]
public async Task MultiHostTriggerTest(SupportedLanguages lang)
{
this.SetChangeTrackingForTable("Products");

// Prepare three function host processes.
this.StartFunctionHost(nameof(ProductsTrigger), SupportedLanguages.CSharp);
this.StartFunctionHost(nameof(ProductsTrigger), SupportedLanguages.CSharp);
this.StartFunctionHost(nameof(ProductsTrigger), SupportedLanguages.CSharp);
this.StartFunctionHost(nameof(ProductsTrigger), lang);
this.StartFunctionHost(nameof(ProductsTrigger), lang);
this.StartFunctionHost(nameof(ProductsTrigger), lang);

int firstId = 1;
int lastId = 90;
Expand Down Expand Up @@ -463,6 +471,7 @@ public void TableNotPresentTriggerTest()
{
this.StartFunctionHostAndWaitForError(
nameof(TableNotPresentTrigger),
SupportedLanguages.CSharp,
true,
"Could not find table: 'dbo.TableNotPresent'.");
}
Expand All @@ -475,6 +484,7 @@ public void PrimaryKeyNotCreatedTriggerTest()
{
this.StartFunctionHostAndWaitForError(
nameof(PrimaryKeyNotPresentTrigger),
SupportedLanguages.CSharp,
true,
"Could not find primary key created in table: 'dbo.ProductsWithoutPrimaryKey'.");
}
Expand All @@ -488,6 +498,7 @@ public void ReservedPrimaryKeyColumnNamesTriggerTest()
{
this.StartFunctionHostAndWaitForError(
nameof(ReservedPrimaryKeyColumnNamesTrigger),
SupportedLanguages.CSharp,
true,
"Found reserved column name(s): '_az_func_ChangeVersion', '_az_func_AttemptCount', '_az_func_LeaseExpirationTime' in table: 'dbo.ProductsWithReservedPrimaryKeyColumnNames'." +
" Please rename them to be able to use trigger binding.");
Expand All @@ -501,6 +512,7 @@ public void UnsupportedColumnTypesTriggerTest()
{
this.StartFunctionHostAndWaitForError(
nameof(UnsupportedColumnTypesTrigger),
SupportedLanguages.CSharp,
true,
"Found column(s) with unsupported type(s): 'Location' (type: geography), 'Geometry' (type: geometry), 'Organization' (type: hierarchyid)" +
" in table: 'dbo.ProductsWithUnsupportedColumnTypes'.");
Expand All @@ -509,11 +521,14 @@ public void UnsupportedColumnTypesTriggerTest()
/// <summary>
/// Tests the error message when change tracking is not enabled on the user table.
/// </summary>
[Fact]
public void ChangeTrackingNotEnabledTriggerTest()
[Theory]
[SqlInlineData()]
[UnsupportedLanguages(SupportedLanguages.Java)]
public void ChangeTrackingNotEnabledTriggerTest(SupportedLanguages lang)
{
this.StartFunctionHostAndWaitForError(
nameof(ProductsTrigger),
lang,
false,
"Could not find change tracking enabled for table: 'dbo.Products'.");
}
Expand Down Expand Up @@ -541,14 +556,17 @@ public async void GetMetricsTest()
/// <summary>
/// Tests that when using an unsupported database the expected error is thrown
/// </summary>
[Fact]
public void UnsupportedDatabaseThrows()
[Theory]
[SqlInlineData()]
[UnsupportedLanguages(SupportedLanguages.Java)]
public void UnsupportedDatabaseThrows(SupportedLanguages lang)
{
// Change database compat level to unsupported version
this.ExecuteNonQuery($"ALTER DATABASE {this.DatabaseName} SET COMPATIBILITY_LEVEL = 120");

this.StartFunctionHostAndWaitForError(
nameof(ProductsTrigger),
lang,
false,
"SQL bindings require a database compatibility level of 130 or higher to function. Current compatibility level = 120");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"bindings": [
{
"name": "changes",
"type": "sqlTrigger",
"direction": "in",
"tableName": "dbo.Products",
"connectionStringSetting": "SqlConnectionString"
}
],
"disabled": false
}
10 changes: 10 additions & 0 deletions test/Integration/test-js/ProductsTriggerWithValidation/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

module.exports = async function (context, changes) {
const expectedMaxBatchSize = process.env["TEST_EXPECTED_MAX_BATCH_SIZE"]
if (expectedMaxBatchSize && expectedMaxBatchSize != changes.length) {
throw new Error(`Invalid max batch size, got ${changes.length} changes but expected ${expectedMaxBatchSize}`)
}
context.log(`SQL Changes: ${JSON.stringify(changes)}`)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"bindings": [
{
"name": "changes",
"type": "sqlTrigger",
"direction": "in",
"tableName": "dbo.Products",
"connectionStringSetting": "SqlConnectionString"
}
],
"disabled": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.

using namespace System.Net

param($changes)

$expectedMaxBatchSize = $env:TEST_EXPECTED_MAX_BATCH_SIZE
if ($expectedMaxBatchSize -and $expectedMaxBatchSize -ne $changes.Count) {
throw "Invalid max batch size, got $($changes.Count) changes but expected $expectedMaxBatchSize"
}

$changesJson = $changes | ConvertTo-Json
$changesJson = $changesJson -replace [Environment]::NewLine,"";
Write-Host "SQL Changes: $changesJson"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import json
import logging
import os

def main(changes):
expectedMaxBatchSize = os.environ.get("TEST_EXPECTED_MAX_BATCH_SIZE")
length = len(json.loads(changes))
if expectedMaxBatchSize and int(expectedMaxBatchSize) != length:
raise Exception("Invalid max batch size, got %d changes but expected %s" % (length, expectedMaxBatchSize))
logging.info("SQL Changes: %s", changes)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"bindings": [
{
"name": "changes",
"type": "sqlTrigger",
"direction": "in",
"tableName": "dbo.Products",
"connectionStringSetting": "SqlConnectionString"
}
],
"disabled": false
}