Skip to content

Commit

Permalink
Fix binding to byte[] (#241)
Browse files Browse the repository at this point in the history
  • Loading branch information
pragnagopa authored Nov 14, 2018
1 parent 80ad72f commit 9cde033
Show file tree
Hide file tree
Showing 20 changed files with 285 additions and 108 deletions.
8 changes: 6 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ cache:
after_build:
- ps: |
.\setup-tests.ps1
$proc = start-process -filepath c:\projects\azure-functions-java-worker\Azure.Functions.Cli\func.exe -WorkingDirectory "c:\projects\azure-functions-java-worker\endtoendtests\target\azure-functions\azure-functions-java-endtoendtests" -ArgumentList "host start" -PassThru
$proc = start-process -filepath c:\projects\azure-functions-java-worker\Azure.Functions.Cli\func.exe -WorkingDirectory "c:\projects\azure-functions-java-worker\endtoendtests\target\azure-functions\azure-functions-java-endtoendtests" -ArgumentList "host start" -RedirectStandardOutput "output.txt" -RedirectStandardError "error.txt" -PassThru
# wait for host to start
Start-Sleep -s 30
Expand All @@ -53,5 +53,9 @@ test_script:
.\run-tests.ps1
on_finish:
- ps: Stop-Process -Id $proc.Id -Erroraction Ignore
- ps: |
Stop-Process -Id $proc.Id -Erroraction Ignore
# Output standard input stream and error stream
Write-Output "Standard input stream :" (gc ".\output.txt")
Write-Output "Standard error stream :" (gc ".\error.txt")
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
</ItemGroup>

<ItemGroup>
<None Update="testBlobTrigger.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public static class Constants
public static string OutputBindingQueueNameMetadata = "test-output-java-metadata";
public static string TestQueueMessage = "Hello, World";

//Blob tests
public static string TriggerInputBindingBlobContainer = "test-triggerinput-java";
public static string InputBindingBlobContainer = "test-input-java";
public static string OutputBindingBlobContainer = "test-output-java";

// CosmosDB tests
public static string CosmosDBConnectionStringSetting = Environment.GetEnvironmentVariable("AzureWebJobsCosmosDBConnectionString");
public static string DocDbDatabaseName = "ItemDb";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.WindowsAzure.Storage.Blob;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -81,5 +82,26 @@ public async Task QueueOutput_POJOList_Succeeds()
IEnumerable<string> queueMessages = await StorageHelpers.ReadMessagesFromQueue(Constants.OutputBindingQueueNamePOJO);
Assert.True(queueMessages.All(msg => msg.Contains(expectedQueueMessage)));
}

[Fact]
public async Task BlobTriggerToBlob_Succeeds()
{
string fileName = Guid.NewGuid().ToString();

//cleanup
await StorageHelpers.ClearBlobContainers();

//Setup
await StorageHelpers.CreateBlobContainers();
await StorageHelpers.UpdloadFileToContainer(Constants.InputBindingBlobContainer, fileName);

//Trigger
await StorageHelpers.UpdloadFileToContainer(Constants.TriggerInputBindingBlobContainer, fileName);

//Verify
string result = await StorageHelpers.DownloadFileFromContainer(Constants.OutputBindingBlobContainer, fileName);

Assert.Equal("Hello World", result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Queue;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace Azure.Functions.Java.Tests.E2E
Expand All @@ -12,6 +15,7 @@ class StorageHelpers
{
public static CloudStorageAccount _storageAccount = CloudStorageAccount.Parse(Constants.StorageConnectionStringSetting);
public static CloudQueueClient _queueClient = _storageAccount.CreateCloudQueueClient();
public static CloudBlobClient _cloudBlobClient = _storageAccount.CreateCloudBlobClient();

public async static Task DeleteQueue(string queueName)
{
Expand Down Expand Up @@ -51,7 +55,7 @@ await Utilities.RetryAsync(async () =>
{
retrievedMessage = await queue.GetMessageAsync();
return retrievedMessage != null;
});
}, pollingInterval: 4000);
await queue.DeleteMessageAsync(retrievedMessage);
return retrievedMessage.AsString;
}
Expand All @@ -73,5 +77,74 @@ await Utilities.RetryAsync(async () =>
}
return messages;
}


public async static Task ClearBlobContainers()
{
await ClearBlobContainer(Constants.TriggerInputBindingBlobContainer);
await ClearBlobContainer(Constants.InputBindingBlobContainer);
await ClearBlobContainer(Constants.OutputBindingBlobContainer);
}

public async static Task CreateBlobContainers()
{
await CreateBlobContainer(Constants.TriggerInputBindingBlobContainer);
await CreateBlobContainer(Constants.InputBindingBlobContainer);
await CreateBlobContainer(Constants.OutputBindingBlobContainer);
}

public async static Task UpdloadFileToContainer(string containerName, string expectedFileName)
{
string sourceFile = $"{expectedFileName}.txt";
File.WriteAllText(sourceFile, "Hello World");
CloudBlobContainer cloudBlobContainer = _cloudBlobClient.GetContainerReference(containerName);
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(sourceFile);
await cloudBlockBlob.UploadFromFileAsync(sourceFile);
}

public async static Task<string> DownloadFileFromContainer(string containerName, string expectedFileName)
{
string destinationFile = $"{expectedFileName}_DOWNLOADED.txt";
string sourceFile = $"{expectedFileName}.txt";
CloudBlobContainer cloudBlobContainer = _cloudBlobClient.GetContainerReference(containerName);
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(sourceFile);
await Utilities.RetryAsync(async () =>
{
return await cloudBlockBlob.ExistsAsync();
}, pollingInterval: 4000);
await cloudBlockBlob.DownloadToFileAsync(destinationFile, FileMode.Create);
return File.ReadAllText(destinationFile);
}


private static async Task<CloudBlobContainer> CreateBlobContainer(string containerName)
{
BlobContainerPermissions permissions = new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
};
CloudBlobContainer cloudBlobContainer = _cloudBlobClient.GetContainerReference(containerName);
await cloudBlobContainer.CreateIfNotExistsAsync();
await cloudBlobContainer.SetPermissionsAsync(permissions);
return cloudBlobContainer;
}

private static async Task ClearBlobContainer(string containerName)
{
CloudBlobContainer cloudBlobContainer = _cloudBlobClient.GetContainerReference(containerName);
BlobContinuationToken blobContinuationToken = null;
do
{
var results = await cloudBlobContainer.ListBlobsSegmentedAsync(null, blobContinuationToken);
// Get the value of the continuation token returned by the listing call.
blobContinuationToken = results.ContinuationToken;
foreach (IListBlobItem item in results.Results)
{
Console.WriteLine(item.Uri);
CloudBlob cloudBlob = cloudBlobContainer.GetBlobReference(item.Uri.ToString());
await cloudBlob.DeleteIfExistsAsync();
}
} while (blobContinuationToken != null); // Loop while the continuation token is not null.
}
}
}
2 changes: 1 addition & 1 deletion endtoendtests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<azure.functions.maven.plugin.version>1.2.0-SNAPSHOT</azure.functions.maven.plugin.version>
<azure.functions.maven.plugin.version>1.2.0</azure.functions.maven.plugin.version>
<azure.functions.java.library.version>1.2.0</azure.functions.java.library.version>
<functionAppName>azure-functions-java-endtoendtests</functionAppName>
<functionAppRegion>westus</functionAppRegion>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;

import java.util.List;
import java.util.Optional;

import com.microsoft.azure.functions.*;

/**
Expand All @@ -10,29 +14,16 @@ public class BlobTriggerTests {
/**
* This function will be invoked when a new or updated blob is detected at the specified path. The blob contents are provided as input to this function.
*/
@FunctionName("BlobTrigger")
@StorageAccount("AzureWebJobsStorage")
public void blobTrigger(
@BlobTrigger(name = "content", path = "myblob/{fileName}", dataType = "binary") byte[] content,
@BindingName("fileName") String fileName,
final ExecutionContext context
) {
context.getLogger().info("Java Blob trigger function processed a blob.\n Name: " + fileName + "\n Size: " + content.length + " Bytes");
}

/**
* This function will be invoked when a message add to queue. And the message is the file name to make a copy. Make sure the file exist or you will get an error
*/

@FunctionName("BlobHandler")
@FunctionName("BlobTriggerToBlobTest")
@StorageAccount("AzureWebJobsStorage")
public void blobHandler(
@QueueTrigger(name = "myBlobQueue", queueName = "myblobqueue", connection = "AzureWebJobsStorage") String myBlobQueue,
@BlobInput(name = "myInputBlob", path = "myblob/{queueTrigger}", dataType = "binary") byte[] myInputBlob,
@BlobOutput(name = "myOutputBlob", path = "myblob/{queueTrigger}-Copy", dataType = "binary") OutputBinding<byte[]> myOutputBlob,
public void BlobTriggerToBlobTest(
@BlobTrigger(name = "triggerBlob", path = "test-triggerinput-java/{name}", dataType = "binary") byte[] triggerBlob,
@BindingName("name") String fileName,
@BlobInput(name = "inputBlob", path = "test-input-java/{name}", dataType = "binary") byte[] inputBlob,
@BlobOutput(name = "outputBlob", path = "test-output-java/{name}", dataType = "binary") OutputBinding<byte[]> outputBlob,
final ExecutionContext context
) {
context.getLogger().info("Azure blob function is making a copy of " + myBlobQueue);
myOutputBlob.setValue(myInputBlob);
}
context.getLogger().info("Java Blob trigger function processed a blob.\n Name: " + fileName + "\n Size: " + triggerBlob.length + " Bytes");
outputBlob.setValue(inputBlob);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.microsoft.azure.functions.endtoendtests;
package com.microsoft.azure.functions.endtoend;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<azure.functions.java.library.version>1.2.1</azure.functions.java.library.version>
<azure.functions.java.library.version>1.2.0</azure.functions.java.library.version>
</properties>

<licenses>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

import com.google.protobuf.ByteString;

final class RpcByteArrayDataSource extends DataSource<byte[]> {
RpcByteArrayDataSource(String name, ByteString value) { super(name, value.toByteArray(), BYTE_ARRAY_DATA_OPERATIONS); }
final public class RpcByteArrayDataSource extends DataSource<byte[]> {
public RpcByteArrayDataSource(String name, ByteString value) {
super(name, value.toByteArray(), BYTE_ARRAY_DATA_OPERATIONS);
}

private static final DataOperations<byte[], Object> BYTE_ARRAY_DATA_OPERATIONS = new DataOperations<>();
static {
BYTE_ARRAY_DATA_OPERATIONS.addOperation(Byte[].class, ArrayUtils::toObject);
}
private static final DataOperations<byte[], Object> BYTE_ARRAY_DATA_OPERATIONS = new DataOperations<>();
static {
BYTE_ARRAY_DATA_OPERATIONS.addOperation(Byte[].class, ArrayUtils::toObject);
BYTE_ARRAY_DATA_OPERATIONS.addOperation(byte[].class, ArrayUtils::clone);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.microsoft.azure.functions.worker.binding.tests;

import static org.junit.Assert.assertEquals;

import java.lang.invoke.WrongMethodTypeException;
import java.util.Optional;

import org.apache.commons.lang3.ArrayUtils;
import org.junit.Test;

import com.google.protobuf.ByteString;
import com.microsoft.azure.functions.worker.binding.BindingData;
import com.microsoft.azure.functions.worker.binding.RpcByteArrayDataSource;

public class RpcByteArrayDataSourceTests {

@Test
public void rpcByteArrayDataSource_To_byteArray() {
String sourceKey = "testByteArray";
String expectedString = "Example String";
byte[] inputBytes = expectedString.getBytes();
ByteString inputByteString = ByteString.copyFrom(inputBytes);
RpcByteArrayDataSource stringData = new RpcByteArrayDataSource(sourceKey, inputByteString);


Optional<BindingData> actualBindingData = stringData.computeByName(sourceKey, byte[].class);
BindingData actualArg = actualBindingData.orElseThrow(WrongMethodTypeException::new);
byte[] actualBytes = (byte[])actualArg.getValue();
String actualString = new String (actualBytes);
assertEquals(actualString, expectedString);
}

@Test
public void rpcByteArrayDataSource_To_ByteArray() {
String sourceKey = "testByteArray";
String expectedString = "Example String";
byte[] inputBytes = expectedString.getBytes();
ByteString inputByteString = ByteString.copyFrom(inputBytes);
RpcByteArrayDataSource stringData = new RpcByteArrayDataSource(sourceKey, inputByteString);


Optional<BindingData> actualBindingData = stringData.computeByName(sourceKey, Byte[].class);
BindingData actualArg = actualBindingData.orElseThrow(WrongMethodTypeException::new);
Byte[] actualBytes = (Byte[])actualArg.getValue();
String actualString = new String (ArrayUtils.toPrimitive(actualBytes));
assertEquals(actualString, expectedString);
}
}
Loading

0 comments on commit 9cde033

Please sign in to comment.