Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MetricsAdvisor] Added tests for the AnomalyAlertConfiguration CRUD operations #17671

Merged
merged 7 commits into from
Dec 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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