Skip to content

Commit

Permalink
Merge pull request #150 from Azure/version-4.0.0
Browse files Browse the repository at this point in the history
Release 4.0.0 - Management API support + retry policy
  • Loading branch information
stankovski authored Aug 14, 2020
2 parents a098dec + 9d1d41c commit 634d9f3
Show file tree
Hide file tree
Showing 125 changed files with 7,794 additions and 4,075 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This repository contains source code for Azure Notification Hubs .NET SDK as wel

## Building Code

To build the `Microsoft.Azure.NotificationHubs`, you need support for [.NET Standard 2.0](https://docs.microsoft.com/en-us/dotnet/standard/net-standard). This requires a minimum of .NET Core 2.0, .NET Framework 4.6.1 or Mono 5.4. This project ships with two unit test files, one for .NET Core 2.0, and one for .NET Framework 4.6.1 or Mono.
To build the `Microsoft.Azure.NotificationHubs`, you need support for [.NET Standard 2.0](https://docs.microsoft.com/en-us/dotnet/standard/net-standard). This requires a minimum of .NET Core 3.1, .NET Framework 4.6.1 or Mono 5.4. This project ships with two unit test files, one for .NET Core 3.1, and one for .NET Framework 4.6.1 or Mono.

## Contributing

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,312 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. 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.IO;
using System.Runtime.CompilerServices;
using Microsoft.Azure.NotificationHubs.Messaging;
using Microsoft.Azure.NotificationHubs.Tests;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Auth;
using Microsoft.Azure.Storage.Blob;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Xunit;

namespace Microsoft.Azure.NotificationHubs.DotNetCore.Tests
{
public class ManagementApiE2ETests
{
private const string IncorrectConnectionString = "Endpoint=sb://sample-test.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SharedAccessKey";
private const string NotificationHubNamespaceUriString = "NotificationHubNamespaceUriString";
private const string NotificationHubConnectionString = "NotificationHubConnectionString";
private const string NotificationHubName = "NotificationHubName";
private const string InputFileName = "ImportRegistrations.txt";

private const string StorageAccount = "StorageAccount";
private const string StoragePassword = "StoragePassword";
private const string StorageEndpointString = "StorageEndpointString";
private const string ContainerName = "ContainerName";

private NamespaceManager _namespaceManager;
private NotificationHubSettings _notificationHubSettings;
private string _notificationHubName;
private readonly Uri _inputFileSasUri;
private readonly Uri _outputContainerSasUri;
private readonly TestServerProxy _testServer;

private string _namespaceUriString;
private string _notificationHubConnectionString;

public ManagementApiE2ETests()
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();

_namespaceUriString = Environment.GetEnvironmentVariable(NotificationHubNamespaceUriString.ToUpperInvariant()) ?? configuration[NotificationHubNamespaceUriString];
_notificationHubConnectionString = Environment.GetEnvironmentVariable(NotificationHubConnectionString.ToUpperInvariant()) ?? configuration[NotificationHubConnectionString];
_notificationHubName = Environment.GetEnvironmentVariable(NotificationHubName.ToUpperInvariant()) ?? configuration[NotificationHubName];

var storageAccount = Environment.GetEnvironmentVariable(StorageAccount.ToUpperInvariant()) ?? configuration[StorageAccount];
var storagePassword = Environment.GetEnvironmentVariable(StoragePassword.ToUpperInvariant()) ?? configuration[StoragePassword];
var storageEndpointAddress = Environment.GetEnvironmentVariable(StorageEndpointString.ToUpperInvariant()) ?? configuration[StorageEndpointString];
var containerName = Environment.GetEnvironmentVariable(ContainerName.ToUpperInvariant()) ?? configuration[ContainerName];


_testServer = new TestServerProxy();
if (_notificationHubConnectionString == "<insert value here before running tests>")
{
_notificationHubConnectionString = "Endpoint=sb://sample.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=xxxxxx";
_namespaceManager = CreateNamespaceManager(RecordingMode.Playback, _notificationHubConnectionString);
}
else
{
_namespaceManager = CreateNamespaceManager(RecordingMode.Recording, _notificationHubConnectionString);
}
if (storageAccount != "<insert value here before running tests>")
{
CleanUp();
_testServer.RecordingMode = RecordingMode.Recording;
var storageEndpoint = new StorageUri(new Uri(storageEndpointAddress));
var blobClient = new CloudBlobClient(
storageEndpoint,
new StorageCredentials(storageAccount, storagePassword));

var container = blobClient.GetContainerReference(containerName);

_outputContainerSasUri = GetOutputDirectoryUrl(container);
_inputFileSasUri = GetInputFileUrl(container, InputFileName);
}
else
{
_testServer.RecordingMode = RecordingMode.Playback;
_outputContainerSasUri = new Uri("https://test.blob.core.windows.net/");
_inputFileSasUri = new Uri("https://test.blob.core.windows.net/");
}
}

[Fact]
public void ManagementApi_ShouldCreateGetOrDeleteHubOrRecieveConflictException()
{
LoadMockData();
try
{
bool notificationHubExists = true;
IEnumerable<NotificationHubDescription> notificationHubDescriptions;

// Check that GetNotification returns MessagingEntityNotFoundException than hub does not exist
Assert.Throws<MessagingEntityNotFoundException>(() => _namespaceManager.GetNotificationHub(_notificationHubName));

// Check that NotificationHubExists returns false when notification hub does not exist
notificationHubExists = _namespaceManager.NotificationHubExists(_notificationHubName);
Assert.False(notificationHubExists);

// Check that GetNotificationHubs returns collection without hub
notificationHubDescriptions = _namespaceManager.GetNotificationHubs();
Assert.DoesNotContain(notificationHubDescriptions, nhd => nhd.Path == _notificationHubName);

// Check that CreateNotificationHub method create hub with correct Path
var createNotificationHubDescription = _namespaceManager.CreateNotificationHub(_notificationHubName);
Assert.Equal(_notificationHubName, createNotificationHubDescription.Path);

// Check that NotificationHubExists return true when notification hub exist
notificationHubExists = _namespaceManager.NotificationHubExists(_notificationHubName);
Assert.True(notificationHubExists);

// Check that GetNotificationHubs returns collection with existed hub
notificationHubDescriptions = _namespaceManager.GetNotificationHubs();
Assert.Single(notificationHubDescriptions);

// Check that CreateNotificationHub returns MessagingEntityAlreadyExistsException than hub is alredy exist
Assert.Throws<MessagingEntityAlreadyExistsException>(() => _namespaceManager.CreateNotificationHub(_notificationHubName));

// Check that GetNotificationHub returns correct hub
var getNotificationHubDescription = _namespaceManager.GetNotificationHub(_notificationHubName);
Assert.NotNull(getNotificationHubDescription);

// Check that UpdateNotificationHub correctly update hub
createNotificationHubDescription.IsDisabled = true;
var updatedNotificationHubDescription = _namespaceManager.UpdateNotificationHub(createNotificationHubDescription);
Assert.True(updatedNotificationHubDescription.IsDisabled);

// Check that DeleteNotificationHub correctly remove hub
_namespaceManager.DeleteNotificationHub(_notificationHubName);

// Check that NotificationHubExists return false when notification hub is not exist
notificationHubExists = _namespaceManager.NotificationHubExists(_notificationHubName);
Assert.False(notificationHubExists);

// Check that GetNotificationHubs returns collection without not existed hub
notificationHubDescriptions = _namespaceManager.GetNotificationHubs();
Assert.Empty(notificationHubDescriptions);

// Check that DeleteNotificationHub returns MessagingEntityNotFoundException than hub is not exist
Assert.Throws<MessagingEntityNotFoundException>(() => _namespaceManager.DeleteNotificationHub(_notificationHubName));
}
finally
{
RecordTestResults();
}
}

[Fact]
public async void ManagementApi_ShouldReceiveCorrectJobs()
{
LoadMockData();
try
{
_namespaceManager.CreateNotificationHub(_notificationHubName);

var notificationHubJob = new NotificationHubJob
{
JobType = NotificationHubJobType.ImportCreateRegistrations,
OutputContainerUri = _outputContainerSasUri,
ImportFileUri = _inputFileSasUri
};

var submitedNotificationHubJob
= await _namespaceManager.SubmitNotificationHubJobAsync(notificationHubJob, _notificationHubName);
Assert.NotNull(submitedNotificationHubJob);
Assert.NotEmpty(submitedNotificationHubJob.JobId);

var recievedNotificationHubJob
= await _namespaceManager.GetNotificationHubJobAsync(submitedNotificationHubJob.JobId, _notificationHubName);

Assert.Equal(submitedNotificationHubJob.JobId, recievedNotificationHubJob.JobId);
}
finally
{
RecordTestResults();
}
}

[Fact]
public void ManagementApi_FailsWithAuthorizationException()
{
LoadMockData();
try
{
var namespaceManager = CreateNamespaceManager(_testServer.RecordingMode, IncorrectConnectionString);

// Check that CreateNotificationHub returns UnauthorizedAccessException when connection string is incorrect
Assert.Throws<UnauthorizedException>(() => namespaceManager.CreateNotificationHub(_notificationHubName));

// We must create hub to recieve UnauthorizedAccessException when GetNotificationHub and DeleteNotificationHub execute
var notificationHubDescription = _namespaceManager.CreateNotificationHub(_notificationHubName);

// Check that GetNotificationHub returns UnauthorizedAccessException when connection string is incorrect
Assert.Throws<UnauthorizedException>(() => namespaceManager.GetNotificationHub(_notificationHubName));

// Check that NotificationHubExists returns UnauthorizedAccessException when connection string is incorrect
Assert.Throws<UnauthorizedException>(() => namespaceManager.NotificationHubExists(_notificationHubName));

// Check that UpdateNotificationHub returns UnauthorizedAccessException when connection string is incorrect
Assert.Throws<UnauthorizedException>(() => namespaceManager.UpdateNotificationHub(notificationHubDescription));

// Check that DeleteNotificationHub returns UnauthorizedAccessException when connection string is incorrect
Assert.Throws<UnauthorizedException>(() => namespaceManager.DeleteNotificationHub(_notificationHubName));
}
finally
{
RecordTestResults();
}
}

private void CleanUp()
{
try
{
_namespaceManager.DeleteNotificationHub(_notificationHubName);
}
catch
{
// no-op
}
}

private static Uri GetInputFileUrl(CloudBlobContainer container, string filePath)
{
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
{
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(4),
Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Create
};

var sasToken = container.GetBlockBlobReference(filePath).GetSharedAccessSignature(sasConstraints);
return new Uri(container.Uri + "/" + filePath + sasToken);
}

private static Uri GetOutputDirectoryUrl(CloudBlobContainer container)
{
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
{
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(4),
Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List | SharedAccessBlobPermissions.Read
};

string sasContainerToken = container.GetSharedAccessSignature(sasConstraints);
return new Uri(container.Uri + sasContainerToken);
}

private string GetMockDataFilePath(string methodName)
{
string[] dataFilePaths = new string[]
{
Path.Combine("MockData", $"{methodName}.http")
};

foreach (var dataFilePath in dataFilePaths)
{
if (File.Exists(dataFilePath))
{
return dataFilePath;
}
}
return null;
}

private void LoadMockData([CallerMemberName] string methodName = "")
{
if (_testServer.RecordingMode == RecordingMode.Playback)
{
string filePath = GetMockDataFilePath(methodName);
if (filePath == null)
{
throw new Exception($"Cannot find data file for method '{methodName}'. Test data must be recorded first.");
}

var payloads = JsonConvert.DeserializeObject<TestServerSession>(File.ReadAllText(filePath));

_testServer.LoadResponses(payloads);
_testServer.BaseUri = "http://test";
}
}

private void RecordTestResults([CallerMemberName] string methodName = "")
{
if (_testServer.RecordingMode == RecordingMode.Recording)
{
File.WriteAllText($"MockData\\{methodName}.http", JsonConvert.SerializeObject(_testServer.Session));
}
}

private NamespaceManager CreateNamespaceManager(RecordingMode recordingMode, string connectionString)
{
if (recordingMode == RecordingMode.Playback)
{
_notificationHubName = "test";
_namespaceUriString = "https://sample.servicebus.windows.net/";
}

var namespaceManagerSettings = new NotificationHubSettings();
namespaceManagerSettings.MessageHandler = _testServer;
return new NamespaceManager(connectionString, namespaceManagerSettings);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.console" Version="2.3.1" />
<PackageReference Include="xunit.runner.msbuild" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="11.1.7" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 634d9f3

Please sign in to comment.