Log warning when skipping tests; Log failures when static init fails; General Cleanup and reorganizing (#243)

This commit is contained in:
Steve Molloy 2024-10-02 23:15:27 -07:00 коммит произвёл GitHub
Родитель 6514fea05b
Коммит ca2b3b74b0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 425 добавлений и 197 удалений

18
test.cmd Normal file
Просмотреть файл

@ -0,0 +1,18 @@
@ECHO OFF
setlocal
set EnableNuGetPackageRestore=true
set MSBUILDEXE=msbuild.exe
set cfgOption=/p:Configuration=Release
REM set cfgOption=/p:Configuration=Debug
REM set cfgOption=/p:Configuration=Debug;Release
if not "%1"=="" set cfgOption=/p:Configuration=
set logOptions=/v:n /flp:Summary;Verbosity=diag;LogFile=msbuild.log /flp1:warningsonly;logfile=msbuild.wrn /flp2:errorsonly;logfile=msbuild.err
REM set logOptions=/v:diag /flp:Summary;Verbosity=diag;LogFile=msbuild.log /flp1:warningsonly;logfile=msbuild.wrn /flp2:errorsonly;logfile=msbuild.err
%MSBUILDEXE% "%~dp0\MicrosoftConfigurationBuilders.msbuild" /t:UnitTest %logOptions% /maxcpucount /nodeReuse:false %cfgOption%%*
endlocal

Просмотреть файл

@ -2,9 +2,10 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Web;
using Azure.Data.AppConfiguration;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.Configuration.ConfigurationBuilders;
using Xunit;
@ -32,61 +33,145 @@ namespace Test
public class AzureAppConfigTests
{
private static readonly string kva_value_old = "versionedValue-Older";
private static readonly string kva_value_new = "versionedValue-Current";
private static readonly string kvb_value = "mappedValue";
private static readonly string kvUriRegex = "{\"uri\":\".+\"}";
private static readonly string placeholderEndPoint = "https://placeholder-EndPoint.example.com";
private static readonly string commonEndPoint;
private static readonly string customEndPoint;
private static readonly string keyVaultName;
private static readonly DateTimeOffset customEpochPlaceholder = DateTimeOffset.Parse("December 31, 1999 11:59pm");
private static readonly DateTimeOffset customEpoch;
// There is probably a better way of doing this. But we're just piggy-backing off of the
// custom Key Vault we use for the AzureKeyVaultConfigBuilder test suite. We assume the
// values of secrets in those tests. Do the same here.
private readonly string kva_value_old = "versionedValue-Older";
private readonly string kva_value_new = "versionedValue-Current";
private readonly string kvb_value = "mappedValue";
private readonly string kvUriRegex = "{\"uri\":\".+\"}";
private static Exception StaticCtorException;
// Update this to true to enable AzConfig tests.
public static bool AppConfigTestsEnabled => false;
// Update this to true if the structure of the config store matches what is described below.
// OTOH, if the 'history' of the entries has been lost (cleared after 7 or 30 days depending
// on the subscription plan) then only the most recent values remain and test verification
// will neccessarily be different. Set this to false if 'history' has been cleared away.
public static bool AzConfigHistoryInTact => false;
public static bool AppConfigTestsEnabled
{
get
{
// Convenience for local development. Leave this commented when committing.
//return false;
// If we have connection info, consider these tests enabled.
if (String.IsNullOrWhiteSpace(commonEndPoint))
return false;
if (String.IsNullOrWhiteSpace(customEndPoint))
return false;
if (String.IsNullOrWhiteSpace(keyVaultName))
return false;
return true;
}
}
static AzureAppConfigTests()
{
// The Common config store gets filled out, but the store itself is assumed to already exist.
commonEndPoint = Environment.GetEnvironmentVariable("Microsoft.Configuration.ConfigurationBuilders.Test.AzConfig.Common");
ConfigurationClient cfgClient = new ConfigurationClient(new Uri(commonEndPoint), new DefaultAzureCredential());
foreach (string key in CommonBuilderTests.CommonKeyValuePairs)
{
// No need to check for the setting first. We're going to write over it anyway to make sure
// it is free of labels and such.
ConfigurationSetting setting = new ConfigurationSetting(key, CommonBuilderTests.CommonKeyValuePairs[key], null);
cfgClient.SetConfigurationSetting(setting, false); // Overwrite without exception
}
// The Custom config store is assumed to exist and already be filled out. The key vault references
// leverage the custom key vault used in the KV config builder tests.
//
// kva: versioned-key == versionedValue-Current
// versionedValue-Older
// kvb: mapped-test-key == mappedValue
// Time --> Beginning (labelA) |epoch| (labelA) (labelB)
// epochDTO DateTimeOffset-of-the-epoch (show up after epoch)
// caseTestSetting altCaseTestValue newCaseTestValue
// testSetting oldTestValue altTestValue newTestValue newAltValue
// newTestSetting ntOGValue ntValueA
// superTestSetting oldSuperValue newSuperAlpha newSuperBeta
// keyVaultSetting kva_value_old kva_value_new kva_value_old kvb_value
// superKeyVaultSetting kvb_value kva_value_old kva_value_new
//
// curious about onlyNewLabA andNewLabB
customEndPoint = Environment.GetEnvironmentVariable("Microsoft.Configuration.ConfigurationBuilders.Test.AzConfig.Custom");
cfgClient = new ConfigurationClient(new Uri(customEndPoint), new DefaultAzureCredential());
customEpoch = DateTimeOffset.Parse(cfgClient.GetConfigurationSetting("epochDTO").Value.Value);
keyVaultName = Environment.GetEnvironmentVariable("Microsoft.Configuration.ConfigurationBuilders.Test.AKV.Custom");
// If tests are disabled, there is no need to do anything in here.
if (!AppConfigTestsEnabled) { return; }
try
{
// The Common config store gets filled out, but the store itself is assumed to already exist.
ConfigurationClient cfgClient = new ConfigurationClient(new Uri(commonEndPoint), new DefaultAzureCredential());
foreach (string key in CommonBuilderTests.CommonKeyValuePairs)
{
UpdateConfigSetting(cfgClient, key, CommonBuilderTests.CommonKeyValuePairs[key]);
}
// The Custom config store also gets re-filled out, but the store itself is assumed to already exist.
// Leverage the custom key vault used in the KV config builder tests.
//
// kva: versioned-key == versionedValue-Current
// versionedValue-Older
// kvb: mapped-test-key == mappedValue
// Time --> Beginning (labelA) |epoch| (labelA) (labelB)
// epochDTO DateTimeOffset-of-the-epoch (show up after epoch)
// caseTestSetting altCaseTestValue newCaseTestValue
// testSetting oldTestValue altTestValue newTestValue newAltValue
// newTestSetting ntOGValue ntValueA
// superTestSetting oldSuperValue newSuperAlpha newSuperBeta
// keyVaultSetting kva_value_old kva_value_new kva_value_old kvb_value
// superKeyVaultSetting kvb_value kva_value_old kva_value_new
//
// curious about onlyNewLabA andNewLabB
// First, ensure the KeyVault values are populated in Key Vault
SecretClient kvClient = new SecretClient(new Uri($"https://{keyVaultName}.vault.azure.net"), new DefaultAzureCredential());
var kvb_cur = AzureTests.EnsureCurrentSecret(kvClient, "mapped-test-key", "mappedValue");
var kva_old = AzureTests.EnsureActiveSecret(kvClient, "versioned-key", "versionedValue-Older");
var kva_cur = AzureTests.EnsureCurrentSecret(kvClient, "versioned-key", "versionedValue-Current");
// Now re-create the config settings
cfgClient = new ConfigurationClient(new Uri(customEndPoint), new DefaultAzureCredential());
// Start by clearing all the setting to get a fresh look. (Incidentally, I think clearing these values only does so
// at this point in time. Meaning if you set a SettingSelector with a timestamp from just before this, you'll still
// see the old, dirty value. Which makes establishing this "clean" point with no values before our epoch time
// all the more important.)
ClearConfigSettings(cfgClient);
// First create config settings with timestamps before the epoch
UpdateConfigSetting(cfgClient, "testSetting", "oldTestValue");
UpdateConfigSetting(cfgClient, "superTestSetting", "oldSuperValue");
UpdateConfigSecret(cfgClient, "keyVaultSetting", kva_old);
UpdateConfigSecret(cfgClient, "superKeyVaultSetting", kvb_cur);
UpdateConfigSetting(cfgClient, "caseTestSetting", "altCaseTestValue", "labelA");
UpdateConfigSetting(cfgClient, "testSetting", "altTestValue", "labelA");
UpdateConfigSecret(cfgClient, "keyVaultSetting", kva_cur, "labelA");
// Remember the epoch. Don't take time directly, as machine time might be off from server time.
UpdateConfigSetting(cfgClient, "epochDTO", "useTimeStampOfThisSetting-" + DateTime.Now.Ticks);
System.Threading.Thread.Sleep(3000);
customEpoch = ((DateTimeOffset)cfgClient.GetConfigurationSetting("epochDTO").Value.LastModified).AddSeconds(1);
// Then ensure/create config settins after the epoch
UpdateConfigSetting(cfgClient, "caseTestSetting", "newCaseTestValue");
UpdateConfigSetting(cfgClient, "testSetting", "newTestValue");
UpdateConfigSetting(cfgClient, "newTestSetting", "ntOGValue");
UpdateConfigSecret(cfgClient, "keyVaultSetting", kva_old);
UpdateConfigSecret(cfgClient, "superKeyVaultSetting", kva_old);
UpdateConfigSetting(cfgClient, "testSetting", "newAltValue", "labelA");
UpdateConfigSetting(cfgClient, "newTestSetting", "ntValueA", "labelA");
UpdateConfigSetting(cfgClient, "superTestSetting", "newSuperAlpha", "labelA");
UpdateConfigSecret(cfgClient, "keyVaultSetting", kvb_cur, "labelA");
UpdateConfigSetting(cfgClient, "superTestSetting", "newSuperBeta", "labelB");
UpdateConfigSecret(cfgClient, "superKeyVaultSetting", kva_cur, "labelB");
}
catch (Exception ex)
{
StaticCtorException = ex;
}
}
public AzureAppConfigTests()
{
// Errors in the static constructor get swallowed by the testrunner. :(
// But this hacky method will bubble up any exceptions we encounter there.
if (StaticCtorException != null)
throw new Exception("Static ctor encountered an exception:", StaticCtorException);
}
static ConfigurationSetting UpdateConfigSetting(ConfigurationClient client, string key, string value, string label = null)
=> client.SetConfigurationSetting(new ConfigurationSetting(key, value, label), false); // Overwrite without exception
static SecretReferenceConfigurationSetting UpdateConfigSecret(ConfigurationClient client, string key, KeyVaultSecret secret, string label = null)
=> (SecretReferenceConfigurationSetting)client.SetConfigurationSetting(new SecretReferenceConfigurationSetting(key, secret.Id, label), false);
static void ClearConfigSettings(ConfigurationClient client)
{
SettingSelector selector = new SettingSelector() { KeyFilter = "*", LabelFilter = "*" };
foreach (ConfigurationSetting rev in client.GetRevisions(selector))
{
client.DeleteConfigurationSetting(rev);
}
}
// ======================================================================
// CommonBuilderTests
@ -108,14 +193,14 @@ namespace Test
// ======================================================================
// AzureAppConfig parameters
// ======================================================================
[AppConfigFact]
[Fact]
public void AzureAppConfig_DefaultSettings()
{
var builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigDefault",
new NameValueCollection() { { "endpoint", customEndPoint } });
new NameValueCollection() { { "endpoint", placeholderEndPoint } });
// Endpoint matches, ConnectionString is null
Assert.Equal(customEndPoint, builder.Endpoint);
Assert.Equal(placeholderEndPoint, builder.Endpoint);
Assert.Null(builder.ConnectionString);
// KeyFilter
@ -138,13 +223,13 @@ namespace Test
}
[AppConfigFact]
[Fact]
public void AzureAppConfig_Settings()
{
// Endpoint is case insensitive, connection string is null
var builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigSettings1",
new NameValueCollection() { { "EndpOInt", customEndPoint } });
Assert.Equal(customEndPoint, builder.Endpoint);
new NameValueCollection() { { "EndpOInt", placeholderEndPoint } });
Assert.Equal(placeholderEndPoint, builder.Endpoint);
Assert.Null(builder.ConnectionString);
// ConnectionString is case insensitive, Endpoint is null
@ -160,40 +245,47 @@ namespace Test
// Both Endpoint and ConnectionString given, Endpoint used, ConnectionString null
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigSettings3",
new NameValueCollection() { { "connectionString", fakeCS }, { "endpoint", customEndPoint } });
Assert.Equal(customEndPoint, builder.Endpoint);
new NameValueCollection() { { "connectionString", fakeCS }, { "endpoint", placeholderEndPoint } });
Assert.Equal(placeholderEndPoint, builder.Endpoint);
Assert.Null(builder.ConnectionString);
// UseKeyVault is case insensitive, allows reading KeyVault values
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigSettings4",
// These tests require executing the builder, which needs a valid endpoint.
if (AppConfigTestsEnabled)
{
// UseKeyVault is case insensitive, allows reading KeyVault values
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigSettings4",
new NameValueCollection() { { "endpoint", customEndPoint }, { "UsEaZuReKeYvAuLt", "tRUe" } });
Assert.Equal(customEndPoint, builder.Endpoint);
Assert.True(builder.UseAzureKeyVault);
Assert.Equal(kva_value_old, builder.GetValue("keyVaultSetting"));
var allValues = builder.GetAllValues("");
Assert.Equal(kva_value_old, TestHelper.GetValueFromCollection(allValues, "superKeyVaultSetting"));
Assert.Equal(customEndPoint, builder.Endpoint);
Assert.True(builder.UseAzureKeyVault);
Assert.Equal(kva_value_old, builder.GetValue("keyVaultSetting"));
var allValues = builder.GetAllValues("");
Assert.Equal(kva_value_old, TestHelper.GetValueFromCollection(allValues, "superKeyVaultSetting"));
// UseKeyVault is case insensitive, does not allow reading KeyVault values
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigSettings5",
new NameValueCollection() { { "endpoint", customEndPoint }, { "useAzureKeyVault", "false" } });
Assert.Equal(customEndPoint, builder.Endpoint);
Assert.False(builder.UseAzureKeyVault);
Assert.Matches(kvUriRegex, builder.GetValue("keyVaultSetting")); // Don't care what the uri is... just that is it a URI instead of a value
allValues = builder.GetAllValues("");
Assert.Matches(kvUriRegex, TestHelper.GetValueFromCollection(allValues, "superKeyVaultSetting"));
// UseKeyVault is case insensitive, does not allow reading KeyVault values
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigSettings5",
new NameValueCollection() { { "endpoint", customEndPoint }, { "useAzureKeyVault", "false" } });
Assert.Equal(customEndPoint, builder.Endpoint);
Assert.False(builder.UseAzureKeyVault);
Assert.Matches(kvUriRegex, builder.GetValue("keyVaultSetting")); // Don't care what the uri is... just that is it a URI instead of a value
allValues = builder.GetAllValues("");
Assert.Matches(kvUriRegex, TestHelper.GetValueFromCollection(allValues, "superKeyVaultSetting"));
}
}
public static IEnumerable<object[]> GetFilterTestParameters()
{
// xUnit evaluates MemberData before ever constructing this class. So we can't use customEpoch or any class variable here.
foreach (KeyValueMode mode in new [] { KeyValueMode.Strict, KeyValueMode.Greedy })
{
foreach (var dto in new object[] { null, DateTimeOffset.MinValue, customEpoch, DateTimeOffset.MaxValue })
foreach (var dto in new object[] { null, DateTimeOffset.MinValue, customEpochPlaceholder, DateTimeOffset.MaxValue })
{
yield return new object[] { mode, null, null, dto, false };
yield return new object[] { mode, "", "", dto, true };
yield return new object[] { mode, "super*", null, dto, true };
yield return new object[] { mode, null, "labelA", dto, true };
yield return new object[] { mode, "super*", "labelA", dto, false };
yield return new object[] { mode, "Super*", null, dto, false }; // Case sensitive key filter
yield return new object[] { mode, null, "labela", dto, false }; // Case sensitive label filter
}
}
}
@ -202,6 +294,10 @@ namespace Test
[MemberData(nameof(GetFilterTestParameters))]
public void AzureAppConfig_Filters(KeyValueMode mode, string keyFilter, string labelFilter, DateTimeOffset dtFilter, bool useAzure)
{
// xUnit evaluates MemberData before ever constructing this class. Make sure we're using the correct epoch time.
if (dtFilter == customEpochPlaceholder)
dtFilter = customEpoch;
bool isOld = (dtFilter == customEpoch);
// Trying all sorts of combinations with just one test and lots of theory data
@ -217,7 +313,7 @@ namespace Test
// ======================================================================
// Errors
// ======================================================================
[AppConfigTheory]
[Theory]
[InlineData(KeyValueEnabled.Optional)]
[InlineData(KeyValueEnabled.Enabled)]
[InlineData(KeyValueEnabled.Disabled)]
@ -262,7 +358,7 @@ namespace Test
exception = Record.Exception(() =>
{
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigErrors4",
new NameValueCollection() { { "endpoint", customEndPoint }, { "labelFilter", "invalid*" }, { "enabled", enabled.ToString() } });
new NameValueCollection() { { "endpoint", placeholderEndPoint }, { "labelFilter", "invalid*" }, { "enabled", enabled.ToString() } });
});
if (enabled != KeyValueEnabled.Disabled)
TestHelper.ValidateWrappedException<ArgumentException>(exception, "AzureAppConfigErrors4", "not supported in label filters");
@ -271,7 +367,7 @@ namespace Test
exception = Record.Exception(() =>
{
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigErrors5",
new NameValueCollection() { { "endpoint", customEndPoint }, { "labelFilter", "invalid,comma" }, { "enabled", enabled.ToString() } });
new NameValueCollection() { { "endpoint", placeholderEndPoint }, { "labelFilter", "invalid,comma" }, { "enabled", enabled.ToString() } });
});
if (enabled != KeyValueEnabled.Disabled)
TestHelper.ValidateWrappedException<ArgumentException>(exception, "AzureAppConfigErrors5", "not supported in label filters");
@ -282,7 +378,7 @@ namespace Test
exception = Record.Exception(() =>
{
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigErrors6",
new NameValueCollection() { { "endpoint", customEndPoint }, { "acceptDateTime", "neither a date nor time" }, { "enabled", enabled.ToString() } });
new NameValueCollection() { { "endpoint", placeholderEndPoint }, { "acceptDateTime", "neither a date nor time" }, { "enabled", enabled.ToString() } });
});
if (enabled != KeyValueEnabled.Disabled)
TestHelper.ValidateWrappedException<FormatException>(exception, "AzureAppConfigErrors6");
@ -293,32 +389,36 @@ namespace Test
exception = Record.Exception(() =>
{
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigErrors7",
new NameValueCollection() { { "endpoint", customEndPoint }, { "useAzureKeyVault", "neither tru nor fals" }, { "enabled", enabled.ToString() } });
new NameValueCollection() { { "endpoint", placeholderEndPoint }, { "useAzureKeyVault", "neither tru nor fals" }, { "enabled", enabled.ToString() } });
});
if (enabled != KeyValueEnabled.Disabled)
TestHelper.ValidateWrappedException<FormatException>(exception, "AzureAppConfigErrors7");
else
Assert.Null(exception);
// Invalid key name (can't be '.', '..', or contain '%'... not that we care, but we should handle the error gracefully)
// Oddly, AppConfig doesn't return an error here. Just quietly returns nothing. So expect no exception.
exception = Record.Exception(() =>
// These tests require executing the builder, which needs a valid endpoint.
if (AppConfigTestsEnabled)
{
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigErrors8",
new NameValueCollection() { { "endpoint", customEndPoint }, { "enabled", enabled.ToString() } });
Assert.Null(builder.GetValue("bad%keyname"));
});
Assert.Null(exception);
// Invalid key name (can't be '.', '..', or contain '%'... not that we care, but we should handle the error gracefully)
// Oddly, AppConfig doesn't return an error here. Just quietly returns nothing. So expect no exception.
exception = Record.Exception(() =>
{
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigErrors8",
new NameValueCollection() { { "endpoint", customEndPoint }, { "enabled", enabled.ToString() } });
Assert.Null(builder.GetValue("bad%keyname"));
});
Assert.Null(exception);
// Invalid key character with key filter (use of key filter should trigger greedy-style pre-load even in strict mode)
// Oddly again, AppConfig doesn't return an error here. Just quietly returns nothing. So expect no exception.
exception = Record.Exception(() =>
{
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigErrors9",
new NameValueCollection() { { "endpoint", customEndPoint }, { "keyFilter", "bad%Filter*" }, { "enabled", enabled.ToString() } });
Assert.Null(builder.GetValue("bad%FilterFetchesThisValue"));
});
Assert.Null(exception);
// Invalid key character with key filter (use of key filter should trigger greedy-style pre-load even in strict mode)
// Oddly again, AppConfig doesn't return an error here. Just quietly returns nothing. So expect no exception.
exception = Record.Exception(() =>
{
builder = TestHelper.CreateBuilder<AzureAppConfigurationBuilder>(() => new AzureAppConfigurationBuilder(), "AzureAppConfigErrors9",
new NameValueCollection() { { "endpoint", customEndPoint }, { "keyFilter", "bad%Filter*" }, { "enabled", enabled.ToString() } });
Assert.Null(builder.GetValue("bad%FilterFetchesThisValue"));
});
Assert.Null(exception);
}
// TODO: Can we produce an invalid KeyVault reference? That should throw an error.
}
@ -374,21 +474,13 @@ namespace Test
if (oldTimes)
{
Assert.Equal(untouched ?? "altCaseTestValue", appSettings.Settings["casetestsetting"]?.Value);
if (AzConfigHistoryInTact)
{
Assert.Equal("oldTestValue", appSettings.Settings["testSetting"]?.Value);
Assert.Matches(kvregex ?? kva_value_old, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Matches(kvregex ?? kvb_value, appSettings.Settings["superKeyVaultSetting"]?.Value);
}
else
{
Assert.Equal(untouched, appSettings.Settings["testSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["superKeyVaultSetting"]?.Value);
}
Assert.Equal("oldTestValue", appSettings.Settings["testSetting"]?.Value);
Assert.Matches(kvregex ?? kva_value_old, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Matches(kvregex ?? kvb_value, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["newTestSetting"]?.Value);
Assert.Equal("oldSuperValue", appSettings.Settings["superTestSetting"]?.Value);
Assert.Equal(greedy ? (AzConfigHistoryInTact ? 5 : 2) : 6, appSettings.Settings.Count); // "newTestSetting" is staged "in the xml" when not greedy.
// "newTestSetting" is only in the pre-built config for non-greedy. "epochDTO" isn't ever, but gets sucked in when greedy. In the end, they cancel out.
Assert.Equal(6, appSettings.Settings.Count);
}
else
{
@ -398,7 +490,7 @@ namespace Test
Assert.Equal("oldSuperValue", appSettings.Settings["superTestSetting"]?.Value);
Assert.Matches(kvregex ?? kva_value_old, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Matches(kvregex ?? kva_value_old, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(greedy ? 7 : 6, appSettings.Settings.Count); // "newTestSetting" show up in any mode now. "epochDTO" as well in greedy.
Assert.Equal(greedy ? 7 : 6, appSettings.Settings.Count); // "newTestSetting" now shows up in any mode. (+epochDTO in greedy)
}
}
// ---------- Key Filter Only ----------
@ -409,23 +501,44 @@ namespace Test
Assert.Equal("untouched", appSettings.Settings["casetestsetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["testSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["newTestSetting"]?.Value);
Assert.Equal("oldSuperValue", appSettings.Settings["superTestSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["keyVaultSetting"]?.Value);
if (AzConfigHistoryInTact)
if (builder.KeyFilter == builder.KeyFilter.ToLower())
{
// Key filter is case-sensitive: 'super*' will match keys in AppConfig...
Assert.Equal("oldSuperValue", appSettings.Settings["superTestSetting"]?.Value);
Assert.Matches(kvregex ?? kvb_value, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(greedy ? 3 : 6, appSettings.Settings.Count);
}
else
{
// ... but 'SUPER*' will not match any keys in AppConfig.
// (Values retrieved from App Config are applied to .Net config case-insensitively, but that's another testcase.)
Assert.Equal(untouched, appSettings.Settings["superTestSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(greedy ? (AzConfigHistoryInTact ? 3 : 2) : 6, appSettings.Settings.Count);
Assert.Equal(greedy ? 1 : 6, appSettings.Settings.Count);
}
}
else
{
Assert.Equal("untouched", appSettings.Settings["casetestsetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["testSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["newTestSetting"]?.Value);
Assert.Equal("oldSuperValue", appSettings.Settings["superTestSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Matches(kvregex ?? kva_value_old, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(greedy ? 3 : 6, appSettings.Settings.Count);
if (builder.KeyFilter == builder.KeyFilter.ToLower())
{
// Key filter is case-sensitive: 'super*' will match keys in AppConfig...
Assert.Equal("oldSuperValue", appSettings.Settings["superTestSetting"]?.Value);
Assert.Matches(kvregex ?? kva_value_old, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(greedy ? 3 : 6, appSettings.Settings.Count);
}
else
{
// ... but 'SUPER*' will not match any keys in AppConfig.
// (Values retrieved from App Config are applied to .Net config case-insensitively, but that's another testcase.)
Assert.Equal(untouched, appSettings.Settings["superTestSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(greedy ? 1 : 6, appSettings.Settings.Count);
}
}
}
// ---------- Label Filter Only ----------
@ -433,36 +546,57 @@ namespace Test
{
if (oldTimes)
{
Assert.Equal(untouched ?? "altCaseTestValue", appSettings.Settings["casetestsetting"]?.Value);
if (AzConfigHistoryInTact)
{
Assert.Equal("altTestValue", appSettings.Settings["testSetting"]?.Value);
Assert.Matches(kvregex ?? kva_value_new, appSettings.Settings["keyVaultSetting"]?.Value);
}
else
{
Assert.Equal(untouched, appSettings.Settings["testSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["keyVaultSetting"]?.Value);
}
Assert.Equal(untouched, appSettings.Settings["newTestSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["superTestSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(greedy ? (AzConfigHistoryInTact ? 3 : 1): 6, appSettings.Settings.Count);
if (builder.LabelFilter != builder.LabelFilter.ToLower())
{
// Label filter is case-sensitive: 'labelA' will match labels in AppConfig...
Assert.Equal(untouched ?? "altCaseTestValue", appSettings.Settings["casetestsetting"]?.Value);
Assert.Equal("altTestValue", appSettings.Settings["testSetting"]?.Value);
Assert.Matches(kvregex ?? kva_value_new, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Equal(greedy ? 3 : 6, appSettings.Settings.Count);
}
else
{
// ... but 'labela' will not match any labels in AppConfig.
Assert.Equal("untouched", appSettings.Settings["casetestsetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["testSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Equal(greedy ? 1 : 6, appSettings.Settings.Count);
}
}
else
{
Assert.Equal(untouched ?? "altCaseTestValue", appSettings.Settings["casetestsetting"]?.Value);
Assert.Equal("newAltValue", appSettings.Settings["testSetting"]?.Value);
Assert.Equal("ntValueA", appSettings.Settings["newTestSetting"]?.Value);
Assert.Equal("newSuperAlpha", appSettings.Settings["superTestSetting"]?.Value);
Assert.Matches(kvregex ?? kvb_value, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["superKeyVaultSetting"]?.Value);
Assert.Equal(greedy ? 5 : 6, appSettings.Settings.Count);
if (builder.LabelFilter != builder.LabelFilter.ToLower())
{
// Label filter is case-sensitive: 'labelA' will match labels in AppConfig...
Assert.Equal(untouched ?? "altCaseTestValue", appSettings.Settings["casetestsetting"]?.Value);
Assert.Equal("newAltValue", appSettings.Settings["testSetting"]?.Value);
Assert.Equal("ntValueA", appSettings.Settings["newTestSetting"]?.Value);
Assert.Equal("newSuperAlpha", appSettings.Settings["superTestSetting"]?.Value);
Assert.Matches(kvregex ?? kvb_value, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Equal(greedy ? 5 : 6, appSettings.Settings.Count);
}
else
{
// ... but 'labela' will not match any labels in AppConfig.
Assert.Equal("untouched", appSettings.Settings["casetestsetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["testSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["newTestSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["superTestSetting"]?.Value);
Assert.Equal(untouched, appSettings.Settings["keyVaultSetting"]?.Value);
Assert.Equal(greedy ? 1 : 6, appSettings.Settings.Count);
}
}
}
// ---------- Both Key and Label Filter ----------
else
{
// Key and Label filters are case-sensitive... but they are tested independently of each other.
// If providing testcase scenarios where both filters bump against case-sensitivity, then this
// section will need to be updated accordingly.
if (oldTimes)
{
Assert.Equal("untouched", appSettings.Settings["casetestsetting"]?.Value);

Просмотреть файл

@ -1,7 +1,7 @@
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics;
using Azure;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
@ -32,55 +32,123 @@ namespace Test
public class AzureTests
{
private readonly string commonKeyVault;
private readonly string customKeyVault;
private readonly string customVersionCurrent;
private readonly string customVersionOld;
private readonly string customVersionNotExist = "abcVersionDoesNotExistXyz";
private static readonly string placeholderKeyVault = "placeholder-KeyVault";
private static readonly string commonKeyVault;
private static readonly string customKeyVault;
private static readonly string customVersionCurrent;
private static readonly string customVersionOld;
private static readonly string customVersionNotExist = "abcVersionDoesNotExistXyz";
private static Exception StaticCtorException;
public static bool AzureTestsEnabled => false;
public static bool AzureTestsEnabled
{
get
{
// Convenience for local development. Leave this commented when committing.
//return false;
// If we have connection info, consider these tests enabled.
if (String.IsNullOrWhiteSpace(commonKeyVault))
return false;
if (String.IsNullOrWhiteSpace(customKeyVault))
return false;
return true;
}
}
static AzureTests()
{
commonKeyVault = Environment.GetEnvironmentVariable("Microsoft.Configuration.ConfigurationBuilders.Test.AKV.Common");
customKeyVault = Environment.GetEnvironmentVariable("Microsoft.Configuration.ConfigurationBuilders.Test.AKV.Custom");
// If tests are disabled, there is no need to do anything in here.
if (!AzureTestsEnabled) { return; }
try
{
// The Common KeyVault gets verified/filled out, but is assumed to already exist.
SecretClient commonClient = new SecretClient(new Uri($"https://{commonKeyVault}.vault.azure.net"), new DefaultAzureCredential());
foreach (string key in CommonBuilderTests.CommonKeyValuePairs)
{
EnsureCurrentSecret(commonClient, key, CommonBuilderTests.CommonKeyValuePairs[key]);
}
// The Custom KeyVault also gets verified/filled out and also is assumed to already exist.
// mapped-test-key == mappedValue
// versioned-key == versionedValue-Current
// versionedValue-Older
// The actual version string of the versioned key does not matter. Just have at least two enabled versions.
SecretClient customClient = new SecretClient(new Uri($"https://{customKeyVault}.vault.azure.net"), new DefaultAzureCredential());
EnsureCurrentSecret(customClient, "mapped-test-key", "mappedValue");
// Secrets that get created in the absence of the correct key/value are the active version by default. Be sure to
// check for the expected active value last.
var vSecret = EnsureActiveSecret(customClient, "versioned-key", "versionedValue-Older");
customVersionOld = vSecret.Properties.Version;
vSecret = EnsureCurrentSecret(customClient, "versioned-key", "versionedValue-Current");
customVersionCurrent = vSecret.Properties.Version;
}
catch (Exception ex)
{
StaticCtorException = ex;
}
}
public AzureTests()
{
// The Common KeyVault gets verified/filled out, but is assumed to already exist.
commonKeyVault = Environment.GetEnvironmentVariable("Microsoft.Configuration.ConfigurationBuilders.Test.AKV.Common");
SecretClient commonClient = new SecretClient(new Uri($"https://{commonKeyVault}.vault.azure.net"), new DefaultAzureCredential());
foreach (string key in CommonBuilderTests.CommonKeyValuePairs)
{
try
{
var secret = commonClient.GetSecret(key).Value;
// Errors in the static constructor get swallowed by the testrunner. :(
// But this hacky method will bubble up any exceptions we encounter there.
if (StaticCtorException != null)
throw new Exception("Static ctor encountered an exception:", StaticCtorException);
}
// Make sure it's not hidden
internal static KeyVaultSecret EnsureActiveSecret(SecretClient client, string key, string value)
{
try
{
foreach (var prop in client.GetPropertiesOfSecretVersions(key))
{
var secret = client.GetSecret(key, prop.Version).Value;
if (secret.Value == value)
{
// Make sure it's active
if (!secret.Properties.Enabled.GetValueOrDefault())
{
secret.Properties.Enabled = true;
client.UpdateSecretProperties(secret.Properties);
}
return secret;
}
}
}
catch (RequestFailedException) { }
// Didn't find the secret, so create it now.
return client.SetSecret(key, value);
}
internal static KeyVaultSecret EnsureCurrentSecret(SecretClient client, string key, string value)
{
try
{
var secret = client.GetSecret(key).Value;
if (secret != null && secret.Value == value)
{
// Make sure it's active
if (!secret.Properties.Enabled.GetValueOrDefault())
{
secret.Properties.Enabled = true;
commonClient.UpdateSecretProperties(secret.Properties);
client.UpdateSecretProperties(secret.Properties);
}
// Make sure it's got the correct value
if (secret.Value != CommonBuilderTests.CommonKeyValuePairs[key])
commonClient.SetSecret(key, CommonBuilderTests.CommonKeyValuePairs[key]);
}
catch (RequestFailedException)
{
// Didn't find the secret, so create it now.
commonClient.SetSecret(key, CommonBuilderTests.CommonKeyValuePairs[key]);
return secret;
}
}
catch (RequestFailedException) { }
// The Custom KeyVault is assumed to exist and already be filled out. Do just one quick sanity value check. It looks like this:
// mapped-test-key == mappedValue
// versioned-key == versionedValue-Current
// versionedValue-Older
// The actual version string of the versioned key does not matter. Just have at least two enabled versions.
customKeyVault = Environment.GetEnvironmentVariable("Microsoft.Configuration.ConfigurationBuilders.Test.AKV.Custom");
SecretClient customClient = new SecretClient(new Uri($"https://{customKeyVault}.vault.azure.net"), new DefaultAzureCredential());
var vaultCheck = customClient.GetSecret("versioned-key")?.Value;
customVersionCurrent = vaultCheck.Properties.Version;
foreach (SecretProperties secretProps in customClient.GetPropertiesOfSecretVersions("versioned-key"))
if (secretProps.Enabled.Value && secretProps.Version != customVersionCurrent)
customVersionOld = secretProps.Version;
// Didn't find the secret, so create it now.
return client.SetSecret(key, value);
}
// ======================================================================
@ -110,15 +178,15 @@ namespace Test
// ======================================================================
// AzureKeyVault parameters
// ======================================================================
[KeyVaultFact]
[Fact]
public void AzureKeyVault_DefaultSettings()
{
var builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultDefault",
new NameValueCollection() { { "vaultName", customKeyVault } });
new NameValueCollection() { { "vaultName", placeholderKeyVault } });
// VaultName, Uri
Assert.Equal(customKeyVault, builder.VaultName);
Assert.Equal($"https://{customKeyVault}.vault.azure.net", builder.Uri);
Assert.Equal(placeholderKeyVault, builder.VaultName);
Assert.Equal($"https://{placeholderKeyVault}.vault.azure.net", builder.Uri);
// Version
Assert.Null(builder.Version);
@ -138,55 +206,59 @@ namespace Test
Assert.Equal("-", builder.CharacterMap["\\"]);
}
[KeyVaultFact]
[Fact]
public void AzureKeyVault_Settings()
{
// VaultName is case insensitive, Uri follows.
var builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings1",
new NameValueCollection() { { "VauLTnaMe", customKeyVault } });
Assert.Equal(customKeyVault, builder.VaultName);
Assert.Equal($"https://{customKeyVault}.vault.azure.net", builder.Uri);
new NameValueCollection() { { "VauLTnaMe", placeholderKeyVault } });
Assert.Equal(placeholderKeyVault, builder.VaultName);
Assert.Equal($"https://{placeholderKeyVault}.vault.azure.net", builder.Uri);
// Empty Uri, but valid vaultName
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings2",
new NameValueCollection() { { "vaultName", customKeyVault }, { "uri", "" } });
Assert.Equal($"https://{customKeyVault}.vault.azure.net", builder.Uri);
Assert.Equal(customKeyVault, builder.VaultName);
new NameValueCollection() { { "vaultName", placeholderKeyVault }, { "uri", "" } });
Assert.Equal($"https://{placeholderKeyVault}.vault.azure.net", builder.Uri);
Assert.Equal(placeholderKeyVault, builder.VaultName);
// Uri is case insensitive, VaultName is not inferred.
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings3",
new NameValueCollection() { { "uRI", $"https://{customKeyVault}.VaulT.Azure.NET" } });
Assert.Equal($"https://{customKeyVault}.VaulT.Azure.NET", builder.Uri);
new NameValueCollection() { { "uRI", $"https://{placeholderKeyVault}.VaulT.Azure.NET" } });
Assert.Equal($"https://{placeholderKeyVault}.VaulT.Azure.NET", builder.Uri);
Assert.Null(builder.VaultName);
// Both Uri and VaultName. Uri wins.
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings4",
new NameValueCollection() { { "vaultName", customKeyVault }, { "uri", $"https://{customKeyVault}.vAUlt.AzUre.NET" } });
Assert.Equal($"https://{customKeyVault}.vAUlt.AzUre.NET", builder.Uri);
new NameValueCollection() { { "vaultName", placeholderKeyVault }, { "uri", $"https://{placeholderKeyVault}.vAUlt.AzUre.NET" } });
Assert.Equal($"https://{placeholderKeyVault}.vAUlt.AzUre.NET", builder.Uri);
Assert.Null(builder.VaultName);
// Uri with invalid VaultName. Uri wins and everything is ok.
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings5",
new NameValueCollection() { { "vaultName", "invalid_vault_name" }, { "uri", $"https://{customKeyVault}.vAUlt.AzUre.NET" } });
Assert.Equal($"https://{customKeyVault}.vAUlt.AzUre.NET", builder.Uri);
new NameValueCollection() { { "vaultName", "invalid_vault_name" }, { "uri", $"https://{placeholderKeyVault}.vAUlt.AzUre.NET" } });
Assert.Equal($"https://{placeholderKeyVault}.vAUlt.AzUre.NET", builder.Uri);
Assert.Null(builder.VaultName);
// Preload is case insensitive for name and value.
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings6",
new NameValueCollection() { { "vaultName", customKeyVault }, { "PreLoadsecretNAMEs", "TrUe" } });
Assert.Equal(customKeyVault, builder.VaultName);
Assert.Equal($"https://{customKeyVault}.vault.azure.net", builder.Uri);
new NameValueCollection() { { "vaultName", placeholderKeyVault }, { "PreLoadsecretNAMEs", "TrUe" } });
Assert.Equal(placeholderKeyVault, builder.VaultName);
Assert.Equal($"https://{placeholderKeyVault}.vault.azure.net", builder.Uri);
Assert.True(builder.Preload);
// Request secrets with mapped characters. Two keys => same secret is ok. Strict [CharMapping happens before GetValue; use PCS()]
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings7",
new NameValueCollection() { { "vaultName", customKeyVault } });
ValidateExpectedConfig(builder);
// These tests require executing the builder, which needs a valid endpoint.
if (AzureTestsEnabled)
{
// Request secrets with mapped characters. Two keys => same secret is ok. Strict [CharMapping happens before GetValue; use PCS()]
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings7",
new NameValueCollection() { { "vaultName", customKeyVault } });
ValidateExpectedConfig(builder);
// Request secrets with mapped characters. Two keys => same secret is ok. Greedy [CharMapping happens before GetAllValues; use PCS()]
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings8",
new NameValueCollection() { { "vaultName", customKeyVault }, { "mode", "Greedy" } });
ValidateExpectedConfig(builder);
// Request secrets with mapped characters. Two keys => same secret is ok. Greedy [CharMapping happens before GetAllValues; use PCS()]
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultSettings8",
new NameValueCollection() { { "vaultName", customKeyVault }, { "mode", "Greedy" } });
ValidateExpectedConfig(builder);
}
}
[KeyVaultTheory]
@ -194,6 +266,10 @@ namespace Test
[InlineData(false)]
public void AzureKeyVault_Version(bool preload)
{
var customKeyVault = Environment.GetEnvironmentVariable("Microsoft.Configuration.ConfigurationBuilders.Test.AKV.Custom");
SecretClient customClient = new SecretClient(new Uri($"https://{customKeyVault}.vault.azure.net"), new DefaultAzureCredential());
var vSecret = EnsureActiveSecret(customClient, "versioned-key", "versionedValue-Older");
// Version is case insensitive
var builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultVersion1",
new NameValueCollection() { { "vaultName", customKeyVault }, { "vERsIOn", customVersionCurrent }, { "preloadSecretNames", preload.ToString() } });
@ -273,7 +349,7 @@ namespace Test
// ======================================================================
// Errors
// ======================================================================
[KeyVaultTheory]
[Theory]
[InlineData(KeyValueEnabled.Optional)]
[InlineData(KeyValueEnabled.Enabled)]
[InlineData(KeyValueEnabled.Disabled)]
@ -326,7 +402,7 @@ namespace Test
// ConnectionString and vaultName given
exception = Record.Exception(() => {
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultErrors5",
new NameValueCollection() { { "vaultName", customKeyVault }, { "ConNecTioNstRinG", "does not matter" }, { "enabled", enabled.ToString() } });
new NameValueCollection() { { "vaultName", placeholderKeyVault }, { "ConNecTioNstRinG", "does not matter" }, { "enabled", enabled.ToString() } });
});
if (enabled != KeyValueEnabled.Disabled)
TestHelper.ValidateWrappedException<ArgumentException>(exception, "AzureKeyVaultErrors5");
@ -336,7 +412,7 @@ namespace Test
// ConnectionString and Uri given
exception = Record.Exception(() => {
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultErrors6",
new NameValueCollection() { { "uri", $"https://{customKeyVault}.vault.azure.net" }, { "ConNecTioNstRinG", "does not matter" }, { "enabled", enabled.ToString() } });
new NameValueCollection() { { "uri", $"https://{placeholderKeyVault}.vault.azure.net" }, { "ConNecTioNstRinG", "does not matter" }, { "enabled", enabled.ToString() } });
});
if (enabled != KeyValueEnabled.Disabled)
TestHelper.ValidateWrappedException<ArgumentException>(exception, "AzureKeyVaultErrors6");
@ -346,7 +422,7 @@ namespace Test
// !Preload and Greedy disagree
exception = Record.Exception(() => {
builder = TestHelper.CreateBuilder<AzureKeyVaultConfigBuilder>(() => new AzureKeyVaultConfigBuilder(), "AzureKeyVaultErrors7",
new NameValueCollection() { { "vaultName", customKeyVault }, { "mode", "Greedy" }, { "preloadSecretNames", "false" }, { "enabled", enabled.ToString() } });
new NameValueCollection() { { "vaultName", placeholderKeyVault }, { "mode", "Greedy" }, { "preloadSecretNames", "false" }, { "enabled", enabled.ToString() } });
});
if (enabled != KeyValueEnabled.Disabled)
TestHelper.ValidateWrappedException<ArgumentException>(exception, "AzureKeyVaultErrors7");