Skip to content

Commit

Permalink
Add end to end test for SQL Bindings (#742)
Browse files Browse the repository at this point in the history
* add sql e2e test

* remove sql trigger test

* check sql input result

* update sql java library version to 2.1.0

* remove sql trigger function

* remove GetProducts2

* Updating library version. Fixes merge conflict

---------

Co-authored-by: Lucy Zhang <luczhan@microsoft.com>
Co-authored-by: Shreyas Gopalakrishna <shreyasg@microsoft.com>
Co-authored-by: Shreyas Gopalakrishna <11889130+shreyas-gopalakrishna@users.noreply.github.com>
  • Loading branch information
4 people committed Jan 17, 2024
1 parent a298511 commit bccab20
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 6 deletions.
1 change: 1 addition & 0 deletions azure-pipelines-e2e-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ jobs:
JAVA_HOME: $(JavaHome)
AzureWebJobsStorage: $(AzureWebJobsStorage)
AzureWebJobsCosmosDBConnectionString: $(AzureWebJobsCosmosDBConnectionString)
AzureWebJobsSqlConnectionString: $(AzureWebJobsSqlConnectionString)
AzureWebJobsServiceBus: $(AzureWebJobsServiceBus)
AzureWebJobsEventHubSender_2: $(AzureWebJobsEventHubSender_2)
AzureWebJobsEventHubReceiver: $(AzureWebJobsEventHubReceiver)
Expand Down
1 change: 1 addition & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ jobs:
JAVA_HOME: $(JavaHome)
AzureWebJobsStorage: $(AzureWebJobsStorage)
AzureWebJobsCosmosDBConnectionString: $(AzureWebJobsCosmosDBConnectionString)
AzureWebJobsSqlConnectionString: $(AzureWebJobsSqlConnectionString)
AzureWebJobsServiceBus: $(AzureWebJobsServiceBus)
AzureWebJobsEventHubReceiver: $(AzureWebJobsEventHubReceiver)
AzureWebJobsEventHubSender_2: $(AzureWebJobsEventHubSender_2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Azure.Functions.Java.Tests.E2E
public static class Constants
{
public static string FunctionsHostUrl = Environment.GetEnvironmentVariable("FunctionAppUrl") ?? "http://localhost:7071";
public static string StorageConnectionStringSetting = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
public static string StorageConnectionStringSetting = Environment.GetEnvironmentVariable("AzureWebJobsStorage");


//Queue tests
Expand Down Expand Up @@ -87,11 +87,14 @@ public static class Constants
public static string ServiceBusConnectionStringSetting = Environment.GetEnvironmentVariable("AzureWebJobsServiceBus");

// Xunit Fixtures and Collections
public const string FunctionAppCollectionName = "FunctionAppCollection";

// Application Insights
public static string ApplicationInsightAPIKey = Environment.GetEnvironmentVariable("ApplicationInsightAPIKey");
public static string ApplicationInsightAPPID = Environment.GetEnvironmentVariable("ApplicationInsightAPPID");
public const string FunctionAppCollectionName = "FunctionAppCollection";

// Application Insights
public static string ApplicationInsightAPIKey = Environment.GetEnvironmentVariable("ApplicationInsightAPIKey");
public static string ApplicationInsightAPPID = Environment.GetEnvironmentVariable("ApplicationInsightAPPID");
public static string ApplicationInsightAgentVersion = Environment.GetEnvironmentVariable("ApplicationInsightAgentVersion");

// SQL Binding tests
public static string SqlConnectionStringSetting = Environment.GetEnvironmentVariable("AzureWebJobsSqlConnectionString");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace Azure.Functions.Java.Tests.E2E
{
[Collection(Constants.FunctionAppCollectionName)]
public class SqlEndToEndTests
{
private readonly FunctionAppFixture _fixture;

public SqlEndToEndTests(FunctionAppFixture fixture)
{
this._fixture = fixture;
}

[Fact]
public async Task SqlInput_Output_Succeeds()
{
TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
int id = (int) t.TotalSeconds;
var product = new Dictionary<string, object>()
{
{ "ProductId", id },
{ "Name", "test" },
{ "Cost", 100 }
};

var productString = JsonConvert.SerializeObject(product);
// Insert row into Products table using SqlOutput
Assert.True(await Utilities.InvokeHttpTriggerPost("AddProduct", productString, HttpStatusCode.OK));

// Read row from Products table using SqlInput
Assert.True(await Utilities.InvokeHttpTrigger("GetProducts", "/" + id.ToString(), HttpStatusCode.OK, productString));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,30 @@ public static async Task<bool> InvokeHttpTrigger(string functionName, string que
}
}

public static async Task<bool> InvokeHttpTriggerPost(string functionName, string bodyString, HttpStatusCode expectedStatusCode)
{
string uri = $"{Constants.FunctionsHostUrl}/api/{functionName}";
using (var request = new HttpRequestMessage(HttpMethod.Post, uri))
{
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
request.Content = new StringContent(
bodyString,
Encoding.UTF8,
"application/json"
);
var response = await httpClient.SendAsync(request);

Console.WriteLine(
$"InvokeHttpTrigger: {functionName} : {response.StatusCode} : {response.ReasonPhrase}");
if (expectedStatusCode != response.StatusCode)
{
return false;
}

return true;
}
}

public static async Task<bool> InvokeEventGridTrigger(string functionName, JObject jsonContent, HttpStatusCode expectedStatusCode=HttpStatusCode.Accepted)
{
string uri = $"{Constants.FunctionsHostUrl}/runtime/webhooks/eventgrid?functionName={functionName}";
Expand Down
1 change: 1 addition & 0 deletions endtoendtests/local.settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"AzureWebJobsCosmosDBConnectionString":"",
"AzureWebJobsEventGridOutputBindingTopicUriString": "",
"AzureWebJobsEventGridOutputBindingTopicKeyString": "",
"AzureWebJobsSqlConnectionString": "",
"FUNCTIONS_WORKER_RUNTIME": "java"
}
}
6 changes: 6 additions & 0 deletions endtoendtests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<java.version>1.8</java.version>
<azure.functions.maven.plugin.version>1.18.0</azure.functions.maven.plugin.version>
<azure.functions.java.library.version>3.1.0</azure.functions.java.library.version>
<azure.functions.java.library.sql.version>2.1.0</azure.functions.java.library.sql.version>
<durabletask.azure.functions>1.0.0-beta.1</durabletask.azure.functions>
<functionAppName>azure-functions-java-endtoendtests</functionAppName>
<functionAppRegion>westus</functionAppRegion>
Expand Down Expand Up @@ -64,6 +65,11 @@
<artifactId>azure-functions-java-library</artifactId>
<version>${azure.functions.java.library.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure.functions</groupId>
<artifactId>azure-functions-java-library-sql</artifactId>
<version>${azure.functions.java.library.sql.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft</groupId>
<artifactId>durabletask-azure-functions</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.google.gson.Gson;
import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.sql.annotation.CommandType;
import com.microsoft.azure.functions.sql.annotation.SQLInput;
import com.microsoft.azure.functions.sql.annotation.SQLOutput;
import com.microsoft.azure.functions.sql.annotation.SQLTrigger;

import java.io.IOException;
import java.lang.reflect.Array;
import java.util.*;

/**
* Azure Functions with Azure SQL DB.
*/
public class SqlTriggerTests {

@FunctionName("GetProducts")
public HttpResponseMessage GetProducts(@HttpTrigger(name = "req", methods = { HttpMethod.GET,
HttpMethod.POST }, route = "getproducts/{productid}", authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
@SQLInput(name = "products", commandText = "SELECT TOP 1 * FROM Products WHERE ProductId = @ProductId",
commandType = CommandType.Text, parameters = "@ProductId={productid}",
connectionStringSetting = "AzureWebJobsSqlConnectionString") Product[] products,
final ExecutionContext context) {

context.getLogger().info("Java HTTP trigger processed a request.");

if (products.length != 0) {
return request.createResponseBuilder(HttpStatus.OK).body(products[0].toString()).build();
} else {
return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Did not find expected product in table Products").build();
}
}

@FunctionName("AddProduct")
public HttpResponseMessage AddProduct(@HttpTrigger(name = "req", methods = { HttpMethod.GET,
HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
@SQLOutput(name = "product", commandText = "Products", connectionStringSetting = "AzureWebJobsSqlConnectionString") OutputBinding<Product> product,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");

String json = request.getBody().get();
product.setValue(new Gson().fromJson(json, Product.class));

return request.createResponseBuilder(HttpStatus.OK).body(product).build();
}

public class Product {
public int ProductId;
public String Name;
public int Cost;

public String toString() {
return "{\"ProductId\":" + ProductId + ",\"Name\":\"" + Name + "\",\"Cost\":" + Cost + "}";
}
}
}

0 comments on commit bccab20

Please sign in to comment.