Skip to main content
Glama

Azure MCP Server

Official
MIT License
1,161
  • Linux
  • Apple
CheckCommandTests.cs19.6 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System.CommandLine.Parsing; using System.Text.Json; using AzureMcp.Core.Models.Command; using AzureMcp.Quota.Commands.Usage; using AzureMcp.Quota.Services; using AzureMcp.Quota.Services.Util; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; namespace AzureMcp.Quota.UnitTests.Commands.Usage; [Trait("Area", "Quota")] public sealed class CheckCommandTests { private readonly IServiceProvider _serviceProvider; private readonly IQuotaService _quotaService; private readonly ILogger<CheckCommand> _logger; private readonly CheckCommand _command; private readonly Parser _parser; public CheckCommandTests() { _quotaService = Substitute.For<IQuotaService>(); _logger = Substitute.For<ILogger<CheckCommand>>(); var services = new ServiceCollection(); services.AddSingleton(_quotaService); _serviceProvider = services.BuildServiceProvider(); _command = new CheckCommand(_logger); _parser = new Parser(_command.GetCommand()); } [Fact] public async Task Should_check_azure_quota_success() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; var resourceTypes = "Microsoft.App, Microsoft.Storage/storageAccounts"; var expectedQuotaInfo = new Dictionary<string, List<UsageInfo>> { { "Microsoft.App", new List<UsageInfo> { new("ContainerApps", 100, 5, "Count"), new("ContainerAppsEnvironments", 10, 2, "Count") } }, { "Microsoft.Storage/storageAccounts", new List<UsageInfo> { new("StorageAccounts", 250, 15, "Count"), new("TotalStorageSize", 500, 150, "TB") } } }; _quotaService.GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 2 && list.Contains("Microsoft.App") && list.Contains("Microsoft.Storage/storageAccounts")), subscriptionId, region) .Returns(expectedQuotaInfo); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(200, result.Status); Assert.NotNull(result.Results); // Verify the service was called with the correct parameters await _quotaService.Received(1).GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 2 && list.Contains("Microsoft.App") && list.Contains("Microsoft.Storage/storageAccounts")), subscriptionId, region); // Verify the response structure var json = JsonSerializer.Serialize(result.Results); var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true }; var response = JsonSerializer.Deserialize<CheckCommand.UsageCheckCommandResult>(json, options); Assert.NotNull(response); Assert.NotNull(response.UsageInfo); Assert.Equal(2, response.UsageInfo.Count); // Verify Microsoft.App quotas Assert.True(response.UsageInfo.ContainsKey("Microsoft.App")); var appQuotas = response.UsageInfo["Microsoft.App"]; Assert.Equal(2, appQuotas.Count); Assert.Contains(appQuotas, q => q.Name == "ContainerApps" && q.Limit == 100 && q.Used == 5); Assert.Contains(appQuotas, q => q.Name == "ContainerAppsEnvironments" && q.Limit == 10 && q.Used == 2); // Verify Microsoft.Storage/storageAccounts quotas Assert.True(response.UsageInfo.ContainsKey("Microsoft.Storage/storageAccounts")); var storageQuotas = response.UsageInfo["Microsoft.Storage/storageAccounts"]; Assert.Equal(2, storageQuotas.Count); Assert.Contains(storageQuotas, q => q.Name == "StorageAccounts" && q.Limit == 250 && q.Used == 15); Assert.Contains(storageQuotas, q => q.Name == "TotalStorageSize" && q.Limit == 500 && q.Used == 150); } [Fact] public async Task Should_ReturnError_empty_resource_types() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; var resourceTypes = ""; _quotaService.GetAzureQuotaAsync( Arg.Any<List<string>>(), subscriptionId, region) .Returns(new Dictionary<string, List<UsageInfo>>()); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(400, result.Status); } [Fact] public async Task Should_handle_service_exception() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; var resourceTypes = "Microsoft.App"; var expectedException = new Exception("Service error occurred"); _quotaService.GetAzureQuotaAsync( Arg.Any<List<string>>(), subscriptionId, region) .ThrowsAsync(expectedException); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(500, result.Status); Assert.Contains("Service error occurred", result.Message); } [Fact] public async Task Should_parse_resource_types_with_spaces() { // Arrange var subscriptionId = "test-subscription-id"; var region = "westus2"; var resourceTypes = " Microsoft.Web/sites , Microsoft.Storage/storageAccounts , Microsoft.Compute/virtualMachines "; var expectedQuotaInfo = new Dictionary<string, List<UsageInfo>> { { "Microsoft.Web/sites", new List<UsageInfo> { new("WebApps", 10, 3, "Count") } }, { "Microsoft.Storage/storageAccounts", new List<UsageInfo> { new("StorageAccounts", 250, 15, "Count") } }, { "Microsoft.Compute/virtualMachines", new List<UsageInfo> { new("VMs", 50, 10, "Count") } } }; _quotaService.GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 3 && list.Contains("Microsoft.Web/sites") && list.Contains("Microsoft.Storage/storageAccounts") && list.Contains("Microsoft.Compute/virtualMachines")), subscriptionId, region) .Returns(expectedQuotaInfo); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(200, result.Status); // Verify the service was called with correctly parsed resource types await _quotaService.Received(1).GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 3 && list.Contains("Microsoft.Web/sites") && list.Contains("Microsoft.Storage/storageAccounts") && list.Contains("Microsoft.Compute/virtualMachines")), subscriptionId, region); } [Fact] public async Task Should_return_null_results_when_no_quotas_found() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; var resourceTypes = "Microsoft.App"; _quotaService.GetAzureQuotaAsync( Arg.Any<List<string>>(), subscriptionId, region) .Returns(new Dictionary<string, List<UsageInfo>>()); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(200, result.Status); Assert.Null(result.Results); // Should be null when no quotas are found } [Fact] public async Task Should_handle_whitespace_only_resource_types() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; var resourceTypes = " "; var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(400, result.Status); } [Fact] public async Task Should_handle_mixed_casing_resource_types() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; var resourceTypes = "MICROSOFT.APP, microsoft.storage/storageaccounts, Microsoft.Compute/VirtualMachines"; var expectedQuotaInfo = new Dictionary<string, List<UsageInfo>> { { "MICROSOFT.APP", new List<UsageInfo> { new("ContainerApps", 100, 5, "Count") } }, { "microsoft.storage/storageaccounts", new List<UsageInfo> { new("StorageAccounts", 250, 15, "Count") } }, { "Microsoft.Compute/VirtualMachines", new List<UsageInfo> { new("VMs", 50, 10, "Count") } } }; _quotaService.GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 3 && list.Contains("MICROSOFT.APP") && list.Contains("microsoft.storage/storageaccounts") && list.Contains("Microsoft.Compute/VirtualMachines")), subscriptionId, region) .Returns(expectedQuotaInfo); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(200, result.Status); Assert.NotNull(result.Results); // Verify the service was called with the correct casing preserved await _quotaService.Received(1).GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 3 && list.Contains("MICROSOFT.APP") && list.Contains("microsoft.storage/storageaccounts") && list.Contains("Microsoft.Compute/VirtualMachines")), subscriptionId, region); } [Fact] public async Task Should_handle_unsupported_provider_returns_no_limit() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; var resourceTypes = "Microsoft.UnsupportedProvider/resourceType"; var expectedQuotaInfo = new Dictionary<string, List<UsageInfo>> { { "Microsoft.UnsupportedProvider/resourceType", new List<UsageInfo> { new("Microsoft.UnsupportedProvider/resourceType", 0, 0, null, "No Limit") } } }; _quotaService.GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 1 && list.Contains("Microsoft.UnsupportedProvider/resourceType")), subscriptionId, region) .Returns(expectedQuotaInfo); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(200, result.Status); Assert.NotNull(result.Results); // Verify the service was called with the correct parameters await _quotaService.Received(1).GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 1 && list.Contains("Microsoft.UnsupportedProvider/resourceType")), subscriptionId, region); // Verify the response structure var json = JsonSerializer.Serialize(result.Results); var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true }; var response = JsonSerializer.Deserialize<CheckCommand.UsageCheckCommandResult>(json, options); Assert.NotNull(response); Assert.NotNull(response.UsageInfo); Assert.True(response.UsageInfo.ContainsKey("Microsoft.UnsupportedProvider/resourceType")); var usageInfo = response.UsageInfo["Microsoft.UnsupportedProvider/resourceType"]; Assert.Single(usageInfo); Assert.Equal("No Limit", usageInfo[0].Description); Assert.Equal(0, usageInfo[0].Limit); Assert.Equal(0, usageInfo[0].Used); } [Fact] public async Task Should_handle_very_long_resource_types_list() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; // Create a very long list of resource types var resourceTypesList = new List<string>(); for (int i = 1; i <= 50; i++) { resourceTypesList.Add($"Microsoft.TestProvider{i}/resourceType{i}"); } var resourceTypes = string.Join(", ", resourceTypesList); var expectedQuotaInfo = new Dictionary<string, List<UsageInfo>>(); foreach (var resourceType in resourceTypesList) { expectedQuotaInfo.Add(resourceType, new List<UsageInfo> { new($"Resource{resourceType.Split('/')[1]}", 100, 10, "Count") }); } _quotaService.GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 50), subscriptionId, region) .Returns(expectedQuotaInfo); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(200, result.Status); Assert.NotNull(result.Results); // Verify the service was called with all 50 resource types await _quotaService.Received(1).GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 50), subscriptionId, region); // Verify the response contains all expected resource types var json = JsonSerializer.Serialize(result.Results); var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true }; var response = JsonSerializer.Deserialize<CheckCommand.UsageCheckCommandResult>(json, options); Assert.NotNull(response); Assert.NotNull(response.UsageInfo); Assert.Equal(50, response.UsageInfo.Count); } [Fact] public async Task Should_handle_network_failure_returns_descriptive_usage_info() { // Arrange var subscriptionId = "test-subscription-id"; var region = "eastus"; var resourceTypes = "Microsoft.Storage/storageAccounts"; var expectedQuotaInfo = new Dictionary<string, List<UsageInfo>> { { "Microsoft.Storage/storageAccounts", new List<UsageInfo> { new("Microsoft.Storage/storageAccounts", 0, 0, null, "Network failure occurred while retrieving quota information") } } }; _quotaService.GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 1 && list.Contains("Microsoft.Storage/storageAccounts")), subscriptionId, region) .Returns(expectedQuotaInfo); var args = _parser.Parse([ "--subscription", subscriptionId, "--region", region, "--resource-types", resourceTypes ]); var context = new CommandContext(_serviceProvider); // Act var result = await _command.ExecuteAsync(context, args); // Assert Assert.NotNull(result); Assert.Equal(200, result.Status); Assert.NotNull(result.Results); // Verify the service was called with the correct parameters await _quotaService.Received(1).GetAzureQuotaAsync( Arg.Is<List<string>>(list => list.Count == 1 && list.Contains("Microsoft.Storage/storageAccounts")), subscriptionId, region); // Verify the response structure contains descriptive error in Description var json = JsonSerializer.Serialize(result.Results); var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true }; var response = JsonSerializer.Deserialize<CheckCommand.UsageCheckCommandResult>(json, options); Assert.NotNull(response); Assert.NotNull(response.UsageInfo); Assert.True(response.UsageInfo.ContainsKey("Microsoft.Storage/storageAccounts")); var usageInfo = response.UsageInfo["Microsoft.Storage/storageAccounts"]; Assert.Single(usageInfo); Assert.Equal("Network failure occurred while retrieving quota information", usageInfo[0].Description); Assert.Equal(0, usageInfo[0].Limit); Assert.Equal(0, usageInfo[0].Used); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Azure/azure-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server