Skip to content

Commit

Permalink
[MetricsAdvisor] Added tests for the AnomalyAlertConfiguration CRUD o…
Browse files Browse the repository at this point in the history
…perations (Azure#17671)
  • Loading branch information
kinelski authored and annelo-msft committed Feb 17, 2021
1 parent eab659e commit 467ab7b
Show file tree
Hide file tree
Showing 28 changed files with 6,828 additions and 1,351 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading.Tasks;
using Azure.AI.MetricsAdvisor.Administration;
using Azure.AI.MetricsAdvisor.Models;
using NUnit.Framework;

namespace Azure.AI.MetricsAdvisor.Tests
{
/// <summary>
/// Represents an <see cref="AnomalyAlertConfiguration"/> that has been created for testing purposes.
/// In order to create a new instance of this class, the <see cref="CreateAlertConfigurationAsync"/>
/// static method must be invoked. The created configuration will be deleted upon disposal.
/// </summary>
public class DisposableAlertConfiguration : IAsyncDisposable
{
/// <summary>
/// The client to use for deleting the configuration upon disposal.
/// </summary>
private readonly MetricsAdvisorAdministrationClient _adminClient;

/// <summary>
/// Initializes a new instance of the <see cref="DisposableAlertConfiguration"/> class.
/// </summary>
/// <param name="adminClient">The client to use for deleting the configuration upon disposal.</param>
/// <param name="id">The identifier of the alert configuration this instance is associated with.</param>
private DisposableAlertConfiguration(MetricsAdvisorAdministrationClient adminClient, string id)
{
_adminClient = adminClient;
Id = id;
}

/// <summary>
/// The identifier of the alert configuration this instance is associated with.
/// </summary>
public string Id { get; }

/// <summary>
/// Creates an alert configuration using the specified <see cref="MetricsAdvisorAdministrationClient"/>.
/// A <see cref="DisposableAlertConfiguration"/> instance is returned, from which the ID of the created
/// configuration can be obtained. Upon disposal, the associated configuration will be deleted.
/// </summary>
/// <param name="adminClient">The client to use for creating and for deleting the configuration.</param>
/// <param name="hook">Specifies how the created <see cref="AnomalyAlertConfiguration"/> should be configured.</param>
/// <returns>A <see cref="DisposableAlertConfiguration"/> instance from which the ID of the created configuration can be obtained.</returns>
public static async Task<DisposableAlertConfiguration> CreateAlertConfigurationAsync(MetricsAdvisorAdministrationClient adminClient, AnomalyAlertConfiguration alertConfiguration)
{
string configId = await adminClient.CreateAlertConfigurationAsync(alertConfiguration);

Assert.That(configId, Is.Not.Null.And.Not.Empty);

return new DisposableAlertConfiguration(adminClient, configId);
}

/// <summary>
/// Deletes the configuration this instance is associated with.
/// </summary>
public async ValueTask DisposeAsync() => await _adminClient.DeleteAlertConfigurationAsync(Id);
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Threading;
using Azure.AI.MetricsAdvisor.Administration;
using Azure.AI.MetricsAdvisor.Models;
using Azure.Core.TestFramework;
using NUnit.Framework;

namespace Azure.AI.MetricsAdvisor.Tests
{
public class AnomalyAlertConfigurationTests : ClientTestBase
{
public AnomalyAlertConfigurationTests(bool isAsync) : base(isAsync)
{
}

private string FakeGuid => "00000000-0000-0000-0000-000000000000";

[Test]
public void CreateAlertConfigurationValidatesArguments()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

Assert.That(() => adminClient.CreateAlertConfigurationAsync(null), Throws.InstanceOf<ArgumentNullException>());

Assert.That(() => adminClient.CreateAlertConfiguration(null), Throws.InstanceOf<ArgumentNullException>());
}

[Test]
public void CreateAlertConfigurationRespectsTheCancellationToken()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

var metricConfigs = new List<MetricAnomalyAlertConfiguration>()
{
new MetricAnomalyAlertConfiguration(FakeGuid, MetricAnomalyAlertScope.GetScopeForWholeSeries())
};
var config = new AnomalyAlertConfiguration("configName", new List<string>(), metricConfigs);

using var cancellationSource = new CancellationTokenSource();
cancellationSource.Cancel();

Assert.That(() => adminClient.CreateAlertConfigurationAsync(config, cancellationSource.Token), Throws.InstanceOf<OperationCanceledException>());
Assert.That(() => adminClient.CreateAlertConfiguration(config, cancellationSource.Token), Throws.InstanceOf<OperationCanceledException>());
}

[Test]
public void UpdateAlertConfigurationValidatesArguments()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

var metricConfigs = new List<MetricAnomalyAlertConfiguration>()
{
new MetricAnomalyAlertConfiguration(FakeGuid, MetricAnomalyAlertScope.GetScopeForWholeSeries())
};
var config = new AnomalyAlertConfiguration("configName", new List<string>(), metricConfigs);

Assert.That(() => adminClient.UpdateAlertConfigurationAsync(null, config), Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => adminClient.UpdateAlertConfigurationAsync("", config), Throws.InstanceOf<ArgumentException>());
Assert.That(() => adminClient.UpdateAlertConfigurationAsync("configId", config), Throws.InstanceOf<ArgumentException>().With.InnerException.TypeOf(typeof(FormatException)));
Assert.That(() => adminClient.UpdateAlertConfigurationAsync(FakeGuid, null), Throws.InstanceOf<ArgumentNullException>());

Assert.That(() => adminClient.UpdateAlertConfiguration(null, config), Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => adminClient.UpdateAlertConfiguration("", config), Throws.InstanceOf<ArgumentException>());
Assert.That(() => adminClient.UpdateAlertConfiguration("configId", config), Throws.InstanceOf<ArgumentException>().With.InnerException.TypeOf(typeof(FormatException)));
Assert.That(() => adminClient.UpdateAlertConfiguration(FakeGuid, null), Throws.InstanceOf<ArgumentNullException>());
}

[Test]
public void UpdateAlertConfigurationRespectsTheCancellationToken()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

var metricConfigs = new List<MetricAnomalyAlertConfiguration>()
{
new MetricAnomalyAlertConfiguration(FakeGuid, MetricAnomalyAlertScope.GetScopeForWholeSeries())
};
var config = new AnomalyAlertConfiguration("configName", new List<string>(), metricConfigs);

using var cancellationSource = new CancellationTokenSource();
cancellationSource.Cancel();

Assert.That(() => adminClient.UpdateAlertConfigurationAsync(FakeGuid, config, cancellationSource.Token), Throws.InstanceOf<OperationCanceledException>());
Assert.That(() => adminClient.UpdateAlertConfiguration(FakeGuid, config, cancellationSource.Token), Throws.InstanceOf<OperationCanceledException>());
}

[Test]
public void GetAlertConfigurationValidatesArguments()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

Assert.That(() => adminClient.GetAlertConfigurationAsync(null), Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => adminClient.GetAlertConfigurationAsync(""), Throws.InstanceOf<ArgumentException>());
Assert.That(() => adminClient.GetAlertConfigurationAsync("configId"), Throws.InstanceOf<ArgumentException>().With.InnerException.TypeOf(typeof(FormatException)));

Assert.That(() => adminClient.GetAlertConfiguration(null), Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => adminClient.GetAlertConfiguration(""), Throws.InstanceOf<ArgumentException>());
Assert.That(() => adminClient.GetAlertConfiguration("configId"), Throws.InstanceOf<ArgumentException>().With.InnerException.TypeOf(typeof(FormatException)));
}

[Test]
public void GetAlertConfigurationRespectsTheCancellationToken()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

using var cancellationSource = new CancellationTokenSource();
cancellationSource.Cancel();

Assert.That(() => adminClient.GetAlertConfigurationAsync(FakeGuid, cancellationSource.Token), Throws.InstanceOf<OperationCanceledException>());
Assert.That(() => adminClient.GetAlertConfiguration(FakeGuid, cancellationSource.Token), Throws.InstanceOf<OperationCanceledException>());
}

[Test]
public void GetAlertConfigurationsValidatesArguments()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

Assert.That(() => adminClient.GetAlertConfigurationsAsync(null), Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => adminClient.GetAlertConfigurationsAsync(""), Throws.InstanceOf<ArgumentException>());
Assert.That(() => adminClient.GetAlertConfigurationsAsync("metricId"), Throws.InstanceOf<ArgumentException>().With.InnerException.TypeOf(typeof(FormatException)));

Assert.That(() => adminClient.GetAlertConfigurations(null), Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => adminClient.GetAlertConfigurations(""), Throws.InstanceOf<ArgumentException>());
Assert.That(() => adminClient.GetAlertConfigurations("metricId"), Throws.InstanceOf<ArgumentException>().With.InnerException.TypeOf(typeof(FormatException)));
}

[Test]
public void GetAlertConfigurationsRespectsTheCancellationToken()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

using var cancellationSource = new CancellationTokenSource();
cancellationSource.Cancel();

IAsyncEnumerator<AnomalyAlertConfiguration> asyncEnumerator = adminClient.GetAlertConfigurationsAsync(FakeGuid, cancellationSource.Token).GetAsyncEnumerator();
Assert.That(async () => await asyncEnumerator.MoveNextAsync(), Throws.InstanceOf<OperationCanceledException>());

IEnumerator<AnomalyAlertConfiguration> enumerator = adminClient.GetAlertConfigurations(FakeGuid, cancellationSource.Token).GetEnumerator();
Assert.That(() => enumerator.MoveNext(), Throws.InstanceOf<OperationCanceledException>());
}

[Test]
public void DeleteAlertConfigurationValidatesArguments()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

Assert.That(() => adminClient.DeleteAlertConfigurationAsync(null), Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => adminClient.DeleteAlertConfigurationAsync(""), Throws.InstanceOf<ArgumentException>());
Assert.That(() => adminClient.DeleteAlertConfigurationAsync("configId"), Throws.InstanceOf<ArgumentException>().With.InnerException.TypeOf(typeof(FormatException)));

Assert.That(() => adminClient.DeleteAlertConfiguration(null), Throws.InstanceOf<ArgumentNullException>());
Assert.That(() => adminClient.DeleteAlertConfiguration(""), Throws.InstanceOf<ArgumentException>());
Assert.That(() => adminClient.DeleteAlertConfiguration("configId"), Throws.InstanceOf<ArgumentException>().With.InnerException.TypeOf(typeof(FormatException)));
}

[Test]
public void DeleteAlertConfigurationRespectsTheCancellationToken()
{
MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

using var cancellationSource = new CancellationTokenSource();
cancellationSource.Cancel();

Assert.That(() => adminClient.DeleteAlertConfigurationAsync(FakeGuid, cancellationSource.Token), Throws.InstanceOf<OperationCanceledException>());
Assert.That(() => adminClient.DeleteAlertConfiguration(FakeGuid, cancellationSource.Token), Throws.InstanceOf<OperationCanceledException>());
}

private MetricsAdvisorAdministrationClient GetMetricsAdvisorAdministrationClient()
{
var fakeEndpoint = new Uri("http://notreal.azure.com");
var fakeCredential = new MetricsAdvisorKeyCredential("fakeSubscriptionKey", "fakeApiKey");

return new MetricsAdvisorAdministrationClient(fakeEndpoint, fakeCredential);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Azure.AI.MetricsAdvisor.Models;
using Azure.Core.TestFramework;
Expand Down Expand Up @@ -153,72 +152,6 @@ public async Task GetDataFeedIngestionProgress()
Assert.That(progress, Is.Not.Null);
}

[RecordedTest]
public async Task AnomalyAlertConfigurationOperations()
{
var adminClient = GetMetricsAdvisorAdministrationClient();

// Create a Detection Configuration
DataFeed feed = await GetFirstDataFeed(adminClient);
string createdAnomalyDetectionConfigurationId = await CreateDetectionConfiguration(adminClient).ConfigureAwait(false);

var alertConfigToCreate = new AnomalyAlertConfiguration(
Recording.GenerateAlphaNumericId("test"),
new List<string>(),
new List<MetricAnomalyAlertConfiguration>
{
new MetricAnomalyAlertConfiguration(
createdAnomalyDetectionConfigurationId,
new MetricAnomalyAlertScope(
MetricAnomalyAlertScopeType.TopN,
new DimensionKey(new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("test", "test2")
}),
new TopNGroupScope(8, 4, 2)))
});

string createdAlertConfigId = await adminClient.CreateAlertConfigurationAsync(alertConfigToCreate).ConfigureAwait(false);

Assert.That(createdAlertConfigId, Is.Not.Null);

// Validate that we can Get the newly created config
AnomalyAlertConfiguration getAlertConfig = await adminClient.GetAlertConfigurationAsync(createdAlertConfigId).ConfigureAwait(false);

List<AnomalyAlertConfiguration> getAlertConfigs = new List<AnomalyAlertConfiguration>();

await foreach (var config in adminClient.GetAlertConfigurationsAsync(createdAnomalyDetectionConfigurationId))
{
getAlertConfigs.Add(config);
}

Assert.That(getAlertConfig.Id, Is.EqualTo(createdAlertConfigId));
Assert.That(getAlertConfigs.Any(c => c.Id == createdAlertConfigId));

getAlertConfig.Description = "Updated";
getAlertConfig.CrossMetricsOperator = MetricAnomalyAlertConfigurationsOperator.And;

await adminClient.UpdateAlertConfigurationAsync(getAlertConfig.Id, getAlertConfig).ConfigureAwait(false);

// Validate that the update succeeded.
getAlertConfig = await adminClient.GetAlertConfigurationAsync(createdAlertConfigId).ConfigureAwait(false);

Assert.That(getAlertConfig.Description, Is.EqualTo(getAlertConfig.Description));

// Update again starting with our locally created model.
alertConfigToCreate.Description = "updated again!";
alertConfigToCreate.CrossMetricsOperator = MetricAnomalyAlertConfigurationsOperator.And;
await adminClient.UpdateAlertConfigurationAsync(getAlertConfig.Id, alertConfigToCreate).ConfigureAwait(false);

// Validate that the update succeeded.
getAlertConfig = await adminClient.GetAlertConfigurationAsync(createdAlertConfigId).ConfigureAwait(false);

Assert.That(getAlertConfig.Description, Is.EqualTo(alertConfigToCreate.Description));

// Cleanup
await adminClient.DeleteAlertConfigurationAsync(createdAlertConfigId).ConfigureAwait(false);
}

[RecordedTest]
public async Task ResetDataFeedIngestionStatus()
{
Expand Down
Loading

0 comments on commit 467ab7b

Please sign in to comment.