DeviceBridgeTests/Services/ConnectionStatusSubscriptionServiceTests.cs (62 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Threading;
using System.Threading.Tasks;
using DeviceBridge.Models;
using DeviceBridge.Providers;
using DeviceBridgeTests.Common;
using Microsoft.Azure.Devices.Client;
using Microsoft.QualityTools.Testing.Fakes;
using Moq;
using NLog;
using NUnit.Framework;
namespace DeviceBridge.Services.Tests
{
[TestFixture]
public class ConnectionStatusSubscriptionServiceTests
{
private Mock<IStorageProvider> _storageProviderMock = new Mock<IStorageProvider>();
private Mock<IConnectionManager> _connectionManagerMock = new Mock<IConnectionManager>();
private Mock<ISubscriptionCallbackFactory> _subscriptionCallbackFactoryMock = new Mock<ISubscriptionCallbackFactory>();
[Test]
[Description("Fetches from the DB the connection status subscription for the specific device Id and returns as is")]
public async Task GetConnectionStatusSubscription()
{
using (ShimsContext.Create())
{
var testSub = TestUtils.GetTestSubscription("test-device-id", DeviceSubscriptionType.ConnectionStatus);
_storageProviderMock.Setup(p => p.GetDeviceSubscription(It.IsAny<Logger>(), "test-device-id", DeviceSubscriptionType.ConnectionStatus, It.IsAny<CancellationToken>())).Returns(Task.FromResult(testSub));
var subscriptionService = new ConnectionStatusSubscriptionService(LogManager.GetCurrentClassLogger(), _connectionManagerMock.Object, _storageProviderMock.Object, _subscriptionCallbackFactoryMock.Object);
var result = await subscriptionService.GetConnectionStatusSubscription(LogManager.GetCurrentClassLogger(), "test-device-id", default);
Assert.AreEqual(testSub, result);
}
}
[Test]
[Description("Checks behavior and synchronization of connection status subscription operations")]
public async Task CreateAndDeleteConnectionStatusSubscription()
{
using (ShimsContext.Create())
{
_storageProviderMock.Invocations.Clear();
// Check create.
var testSub = TestUtils.GetTestSubscription("test-device-id", DeviceSubscriptionType.ConnectionStatus);
_storageProviderMock.Setup(p => p.CreateOrUpdateDeviceSubscription(It.IsAny<Logger>(), "test-device-id", DeviceSubscriptionType.ConnectionStatus, "http://abc", It.IsAny<CancellationToken>())).Returns(Task.FromResult(testSub));
var subscriptionService = new ConnectionStatusSubscriptionService(LogManager.GetCurrentClassLogger(), _connectionManagerMock.Object, _storageProviderMock.Object, _subscriptionCallbackFactoryMock.Object);
SemaphoreSlim createSemaphore = null;
TestUtils.CaptureSemaphoreOnWait(capturedSemaphore => createSemaphore = capturedSemaphore);
var result = await subscriptionService.CreateOrUpdateConnectionStatusSubscription(LogManager.GetCurrentClassLogger(), "test-device-id", "http://abc", default);
Assert.AreEqual(testSub, result);
_connectionManagerMock.Verify(p => p.SetConnectionStatusCallback("test-device-id", It.IsAny<Func<ConnectionStatus, ConnectionStatusChangeReason, Task>>()), Times.Once);
// Check delete.
SemaphoreSlim deleteSemaphore = null;
TestUtils.CaptureSemaphoreOnWait(capturedSemaphore => deleteSemaphore = capturedSemaphore);
await subscriptionService.DeleteConnectionStatusSubscription(LogManager.GetCurrentClassLogger(), "test-device-id", default);
_storageProviderMock.Verify(p => p.DeleteDeviceSubscription(It.IsAny<Logger>(), "test-device-id", DeviceSubscriptionType.ConnectionStatus, default));
_connectionManagerMock.Verify(p => p.RemoveConnectionStatusCallback("test-device-id"), Times.Once);
// Check that create and delete lock on the same mutex.
Assert.AreEqual(createSemaphore, deleteSemaphore);
// Check that operation in a different device Id locks on a different mutex.
SemaphoreSlim anotherDeviceSemaphore = null;
TestUtils.CaptureSemaphoreOnWait(capturedSemaphore => anotherDeviceSemaphore = capturedSemaphore);
await subscriptionService.DeleteConnectionStatusSubscription(LogManager.GetCurrentClassLogger(), "another-device-id", default);
Assert.AreNotEqual(deleteSemaphore, anotherDeviceSemaphore);
}
}
}
}