Skip to content
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
Expand Up @@ -11,6 +11,7 @@
using Microsoft.Mcp.Core.Helpers;
using Microsoft.Mcp.Core.Models.Command;
using Microsoft.Mcp.Core.Options;
using Microsoft.Mcp.Tests.Helpers;
using NSubstitute;
using Xunit;

Expand Down Expand Up @@ -42,7 +43,7 @@ public SubscriptionCommandTests()
public void Validate_WithEnvironmentVariableOnly_PassesValidation()
{
// Arrange
EnvironmentHelpers.SetAzureSubscriptionId("env-subs");
TestEnvironment.SetAzureSubscriptionId("env-subs");

// Act
var parseResult = _commandDefinition.Parse([]);
Expand All @@ -55,7 +56,8 @@ public void Validate_WithEnvironmentVariableOnly_PassesValidation()
public async Task ExecuteAsync_WithEnvironmentVariableOnly_CallsServiceWithCorrectSubscription()
{
// Arrange
EnvironmentHelpers.SetAzureSubscriptionId("env-subs");
TestEnvironment.SetAzureSubscriptionId("env-subs");
var subscription = CommandHelper.GetDefaultSubscription()!;

var expectedAccounts = new ResourceQueryResults<StorageAccountInfo>(
[
Expand All @@ -65,7 +67,7 @@ public async Task ExecuteAsync_WithEnvironmentVariableOnly_CallsServiceWithCorre

_storageService.GetAccountDetails(
Arg.Is<string?>(s => string.IsNullOrEmpty(s)),
Arg.Is("env-subs"),
Arg.Is(subscription),
Arg.Any<string>(),
Arg.Any<RetryPolicyOptions>(),
Arg.Any<CancellationToken>())
Expand All @@ -82,7 +84,7 @@ public async Task ExecuteAsync_WithEnvironmentVariableOnly_CallsServiceWithCorre
// Verify the service was called with the environment variable subscription
_ = _storageService.Received(1).GetAccountDetails(
Arg.Is<string?>(s => string.IsNullOrEmpty(s)),
"env-subs",
subscription,
Arg.Any<string>(),
Arg.Any<RetryPolicyOptions>(),
Arg.Any<CancellationToken>());
Expand All @@ -92,7 +94,9 @@ public async Task ExecuteAsync_WithEnvironmentVariableOnly_CallsServiceWithCorre
public async Task ExecuteAsync_WithBothOptionAndEnvironmentVariable_PrefersOption()
{
// Arrange
EnvironmentHelpers.SetAzureSubscriptionId("env-subs");
TestEnvironment.SetAzureSubscriptionId("env-subs");
var ignoredSubscription = CommandHelper.GetDefaultSubscription()!;
var expectedSubscription = "option-subs";

Comment thread
alzimmermsft marked this conversation as resolved.
var expectedAccounts = new ResourceQueryResults<StorageAccountInfo>(
[
Expand All @@ -102,13 +106,13 @@ public async Task ExecuteAsync_WithBothOptionAndEnvironmentVariable_PrefersOptio

_storageService.GetAccountDetails(
Arg.Is<string?>(s => string.IsNullOrEmpty(s)),
Arg.Is("option-subs"),
Arg.Is(expectedSubscription),
Arg.Any<string>(),
Arg.Any<RetryPolicyOptions>(),
Arg.Any<CancellationToken>())
.Returns(Task.FromResult(expectedAccounts));

var parseResult = _commandDefinition.Parse(["--subscription", "option-subs"]);
var parseResult = _commandDefinition.Parse(["--subscription", expectedSubscription]);

// Act
var response = await _command.ExecuteAsync(_context, parseResult, TestContext.Current.CancellationToken);
Expand All @@ -119,13 +123,13 @@ public async Task ExecuteAsync_WithBothOptionAndEnvironmentVariable_PrefersOptio
// Verify the service was called with the option subscription, not the environment variable
_ = _storageService.Received(1).GetAccountDetails(
Arg.Is<string?>(s => string.IsNullOrEmpty(s)),
"option-subs",
expectedSubscription,
Arg.Any<string>(),
Arg.Any<RetryPolicyOptions>(),
Arg.Any<CancellationToken>());
_ = _storageService.DidNotReceive().GetAccountDetails(
Arg.Is<string?>(s => string.IsNullOrEmpty(s)),
"env-subs",
ignoredSubscription,
Arg.Any<string>(),
Arg.Any<RetryPolicyOptions>(),
Arg.Any<CancellationToken>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Azure.Mcp.Core.Areas.Group.Commands;
using Microsoft.Extensions.Logging;
using Microsoft.Mcp.Core.Helpers;
using Microsoft.Mcp.Tests.Helpers;
using NSubstitute;
using Xunit;

Expand All @@ -13,35 +14,37 @@ public class CommandHelperTests
public void GetSubscription_EmptySubscriptionParameter_ReturnsEnvironmentValue()
{
// Arrange
EnvironmentHelpers.SetAzureSubscriptionId("env-subs");
TestEnvironment.SetAzureSubscriptionId("env-subs");
var subscription = CommandHelper.GetDefaultSubscription();
var parseResult = GetParseResult(["--subscription", ""]);

// Act
var actual = CommandHelper.GetSubscription(parseResult);

// Assert
Assert.Equal("env-subs", actual);
Assert.Equal(subscription, actual);
}

[Fact]
public void GetSubscription_MissingSubscriptionParameter_ReturnsEnvironmentValue()
{
// Arrange
EnvironmentHelpers.SetAzureSubscriptionId("env-subs");
TestEnvironment.SetAzureSubscriptionId("env-subs");
var subscription = CommandHelper.GetDefaultSubscription();
var parseResult = GetParseResult([]);

// Act
var actual = CommandHelper.GetSubscription(parseResult);

// Assert
Assert.Equal("env-subs", actual);
Assert.Equal(subscription, actual);
}

[Fact]
public void GetSubscription_ValidSubscriptionParameter_ReturnsParameterValue()
{
// Arrange
EnvironmentHelpers.SetAzureSubscriptionId("env-subs");
TestEnvironment.SetAzureSubscriptionId("env-subs");
var parseResult = GetParseResult(["--subscription", "param-subs"]);

// Act
Expand All @@ -55,54 +58,78 @@ public void GetSubscription_ValidSubscriptionParameter_ReturnsParameterValue()
public void GetSubscription_ParameterValueContainingSubscription_ReturnsEnvironmentValue()
{
// Arrange
EnvironmentHelpers.SetAzureSubscriptionId("env-subs");
TestEnvironment.SetAzureSubscriptionId("env-subs");
var subscription = CommandHelper.GetDefaultSubscription();
var parseResult = GetParseResult(["--subscription", "Azure subscription 1"]);

// Act
var actual = CommandHelper.GetSubscription(parseResult);

// Assert
Assert.Equal("env-subs", actual);
Assert.Equal(subscription, actual);
}

[Fact]
public void GetSubscription_ParameterValueContainingDefault_ReturnsEnvironmentValue()
{
// Arrange
EnvironmentHelpers.SetAzureSubscriptionId("env-subs");
TestEnvironment.SetAzureSubscriptionId("env-subs");
var subscription = CommandHelper.GetDefaultSubscription();
var parseResult = GetParseResult(["--subscription", "Some default name"]);

// Act
var actual = CommandHelper.GetSubscription(parseResult);

// Assert
Assert.Equal("env-subs", actual);
Assert.Equal(subscription, actual);
}

[Fact]
public void GetSubscription_NoEnvironmentVariableParameterValueContainingDefault_ReturnsParameterValue()
{
// Arrange
TestEnvironment.ClearAzureSubscriptionId();
var subscription = CommandHelper.GetProfileSubscription();
var parseResult = GetParseResult(["--subscription", "Some default name"]);

// Act
var actual = CommandHelper.GetSubscription(parseResult);

// Assert
Assert.Equal("Some default name", actual);
// If-else this test as being logged in with Azure CLI cannot be mocked out at this time.
// So, if the running environment is logged in the subscription will be defaulted to the Azure CLI subscription.
if (subscription != null)
{
Assert.Equal(subscription, actual);
}
else
{
Assert.Equal("Some default name", actual);
}
}

[Fact]
public void GetSubscription_NoEnvironmentVariableParameterValueContainingSubscription_ReturnsParameterValue()
{
// Arrange
TestEnvironment.ClearAzureSubscriptionId();
var subscription = CommandHelper.GetProfileSubscription();
var parseResult = GetParseResult(["--subscription", "Azure subscription 1"]);

// Act
var actual = CommandHelper.GetSubscription(parseResult);

// Assert
Assert.Equal("Azure subscription 1", actual);
// If-else this test as being logged in with Azure CLI cannot be mocked out at this time.
// So, if the running environment is logged in the subscription will be defaulted to the Azure CLI subscription.
if (subscription != null)
{
Assert.Equal(subscription, actual);
}
else
{
Assert.Equal("Azure subscription 1", actual);
}
}
Comment thread
alzimmermsft marked this conversation as resolved.

private static ParseResult GetParseResult(params string[] args)
Expand Down
4 changes: 3 additions & 1 deletion core/Microsoft.Mcp.Core/src/Helpers/CommandHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public static bool HasSubscriptionAvailable(CommandResult commandResult)
public static string? GetDefaultSubscription()
{
// Primary: Azure CLI profile (set via 'az account set') - cached to avoid repeated file I/O
var profileDefault = s_profileDefault.Value;
var profileDefault = GetProfileSubscription();
if (!string.IsNullOrEmpty(profileDefault))
{
return profileDefault;
Expand All @@ -62,5 +62,7 @@ public static bool HasSubscriptionAvailable(CommandResult commandResult)
return EnvironmentHelpers.GetAzureSubscriptionId();
}

internal static string? GetProfileSubscription() => s_profileDefault.Value;

private static bool IsPlaceholder(string value) => value.Contains("subscription") || value.Contains("default");
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,24 @@ namespace Microsoft.Mcp.Core.Helpers;

public static class EnvironmentHelpers
{
private const string AzureSubscriptionIdEnvironmentVariable = "AZURE_SUBSCRIPTION_ID";
internal const string AzureSubscriptionIdEnvironmentVariable = "AZURE_SUBSCRIPTION_ID";

public static bool GetEnvironmentVariableAsBool(string envVarName)
{
return Environment.GetEnvironmentVariable(envVarName) switch
=> Environment.GetEnvironmentVariable(envVarName) switch
{
"true" => true,
"True" => true,
"T" => true,
"1" => true,
_ => false
};
}

/// <summary>
/// Gets the Azure subscription ID from the AZURE_SUBSCRIPTION_ID environment variable.
/// </summary>
/// <returns>The subscription ID if available, null otherwise.</returns>
public static string? GetAzureSubscriptionId()
{
return Environment.GetEnvironmentVariable(AzureSubscriptionIdEnvironmentVariable);
}

/// <summary>
/// Sets the AZURE_SUBSCRIPTION_ID environment variable.
/// This method is primarily intended for testing scenarios.
/// </summary>
/// <param name="subscriptionId">The subscription ID to set, or null to clear the variable.</param>
public static void SetAzureSubscriptionId(string? subscriptionId)
{
Environment.SetEnvironmentVariable(AzureSubscriptionIdEnvironmentVariable, subscriptionId);
}
=> Environment.GetEnvironmentVariable(AzureSubscriptionIdEnvironmentVariable);

public static bool IsPlaybackTesting()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.Mcp.Core.Helpers;

namespace Microsoft.Mcp.Tests.Helpers;

/// <summary>
Expand All @@ -16,5 +18,20 @@ public enum TestMode
public static class TestEnvironment
{
public static bool IsRunningInCi =>
string.Equals(Environment.GetEnvironmentVariable("CI"), "true", StringComparison.OrdinalIgnoreCase) || !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TF_BUILD"));
string.Equals(Environment.GetEnvironmentVariable("CI"), "true", StringComparison.OrdinalIgnoreCase) ||
!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TF_BUILD"));

/// <summary>
/// Sets the AZURE_SUBSCRIPTION_ID environment variable.
/// </summary>
/// <param name="subscriptionId">The subscription ID to set, or null to clear the variable.</param>
/// <returns>Either the AZURE_SUBSCRIPTION_ID environment variable value that was set or the logged into Azure CLI subscription.</returns>
public static void SetAzureSubscriptionId(string subscriptionId)
=> Environment.SetEnvironmentVariable(EnvironmentHelpers.AzureSubscriptionIdEnvironmentVariable, subscriptionId);

/// <summary>
/// Clears the AZURE_SUBSCRIPTION_ID environment variable.
/// </summary>
public static void ClearAzureSubscriptionId()
=> Environment.SetEnvironmentVariable(EnvironmentHelpers.AzureSubscriptionIdEnvironmentVariable, null);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.Mcp.Core.Helpers;
using Microsoft.Mcp.Core.Models.Command;
using Microsoft.Mcp.Core.Options;
using Microsoft.Mcp.Tests.Helpers;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using Xunit;
Expand Down Expand Up @@ -54,7 +55,7 @@ public void Constructor_InitializesCommandCorrectly()
public async Task ExecuteAsync_ValidatesInputCorrectly(string args, bool shouldSucceed)
{
// Ensure environment variable fallback does not interfere with validation tests
EnvironmentHelpers.SetAzureSubscriptionId(null);
TestEnvironment.ClearAzureSubscriptionId();
// Arrange
if (shouldSucceed)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.Mcp.Core.Helpers;
using Microsoft.Mcp.Core.Models.Command;
using Microsoft.Mcp.Core.Options;
using Microsoft.Mcp.Tests.Helpers;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using Xunit;
Expand Down Expand Up @@ -53,11 +54,11 @@ public void Constructor_InitializesCommandCorrectly()
[InlineData("", false)]
public async Task ExecuteAsync_ValidatesInputCorrectly(string args, bool shouldSucceed)
{
var originalSubscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID");
var originalSubscriptionId = EnvironmentHelpers.GetAzureSubscriptionId();
try
{
// Ensure environment variable fallback does not interfere with validation tests
EnvironmentHelpers.SetAzureSubscriptionId(null);
TestEnvironment.ClearAzureSubscriptionId();
// Arrange
if (shouldSucceed)
{
Expand Down Expand Up @@ -87,7 +88,10 @@ public async Task ExecuteAsync_ValidatesInputCorrectly(string args, bool shouldS
}
finally
{
EnvironmentHelpers.SetAzureSubscriptionId(originalSubscriptionId);
if (originalSubscriptionId != null)
{
TestEnvironment.SetAzureSubscriptionId(originalSubscriptionId);
}
Comment thread
alzimmermsft marked this conversation as resolved.
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Microsoft.Mcp.Core.Helpers;
using Microsoft.Mcp.Core.Models.Command;
using Microsoft.Mcp.Core.Options;
using Microsoft.Mcp.Tests.Helpers;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using Xunit;
Expand Down Expand Up @@ -107,7 +108,7 @@ public async Task ExecuteAsync_ValidatesInputCorrectly(string args, bool shouldS
if (args.Contains("--vault") && !args.Contains("--subscription") && shouldSucceed)
{
// Provide subscription via environment variable
EnvironmentHelpers.SetAzureSubscriptionId(KnownSubscriptionId);
TestEnvironment.SetAzureSubscriptionId(KnownSubscriptionId);
}
else if (!args.Contains("--subscription"))
{
Expand Down
Loading