Skip to content
Open
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
@@ -1,57 +1,72 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
using Microsoft.Extensions.Configuration.AzureAppConfiguration.Extensions;
using System;
using System.Collections.Generic;

namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.Models
{
internal class KeyValueWatcher
{
/// <summary>
/// Key of the key-value to be watched.
/// </summary>
public string Key { get; set; }

/// <summary>
/// Label of the key-value to be watched.
/// </summary>
public string Label { get; set; }

/// <summary>
/// Tags of the key-value to be watched.
/// </summary>
public IEnumerable<string> Tags { get; set; }

/// <summary>
/// A flag to refresh all key-values.
/// </summary>
public bool RefreshAll { get; set; }

/// <summary>
/// The minimum time that must elapse before the key-value is refreshed.
/// </summary>
public TimeSpan RefreshInterval { get; set; }

/// <summary>
/// The next time when this key-value can be refreshed.
/// </summary>
public DateTimeOffset NextRefreshTime { get; set; }

public override bool Equals(object obj)
{
if (obj is KeyValueWatcher kvWatcher)
{
return Key == kvWatcher.Key && Label.NormalizeNull() == kvWatcher.Label.NormalizeNull();
}

return false;
}

public override int GetHashCode()
{
return Label != null ? Key.GetHashCode() ^ Label.GetHashCode() : Key.GetHashCode();
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
using Microsoft.Extensions.Configuration.AzureAppConfiguration.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.Models
{
internal class KeyValueWatcher
{
/// <summary>
/// Key of the key-value to be watched.
/// </summary>
public string Key { get; set; }

/// <summary>
/// Label of the key-value to be watched.
/// </summary>
public string Label { get; set; }

/// <summary>
/// Tags of the key-value to be watched.
/// </summary>
public IEnumerable<string> Tags { get; set; }

/// <summary>
/// A flag to refresh all key-values.
/// </summary>
public bool RefreshAll { get; set; }

/// <summary>
/// The minimum time that must elapse before the key-value is refreshed.
/// </summary>
public TimeSpan RefreshInterval { get; set; }

/// <summary>
/// The next time when this key-value can be refreshed.
/// </summary>
public DateTimeOffset NextRefreshTime { get; set; }

public override bool Equals(object obj)
{
if (obj is KeyValueWatcher kvWatcher)
{
return Key == kvWatcher.Key &&
Label.NormalizeNull() == kvWatcher.Label.NormalizeNull() &&
(Tags == null ? kvWatcher.Tags == null : kvWatcher.Tags != null && new HashSet<string>(Tags).SetEquals(kvWatcher.Tags));
}

return false;
}

public override int GetHashCode()
{
string tagFiltersString = string.Empty;

// Consistency with KeyValueSelector: Normalize tags into a sorted string
if (Tags != null && Tags.Any())
{
var sortedTags = new SortedSet<string>(Tags);
tagFiltersString = string.Join("\n", sortedTags);
}

return HashCode.Combine(
Key,
Label.NormalizeNull(),
tagFiltersString);
}
}
}
25 changes: 25 additions & 0 deletions tests/Tests.AzureAppConfiguration/Unit/TagFiltersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration.FeatureManagement;
using Microsoft.Extensions.Configuration.AzureAppConfiguration.Models;
using Moq;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -158,6 +159,30 @@ private ConfigurationSetting CreateFeatureFlagSetting(string featureId, string l
return setting;
}

[Fact]
public void KeyValueWatcher_EqualityAndHash_IncludesTags()
{
var tags = new List<string> { "v1", "v2" };

var watcher1 = new KeyValueWatcher { Key = "TestKey", Tags = tags };
var watcher2 = new KeyValueWatcher { Key = "TestKey", Tags = new List<string> { "v2", "v1" } }; // Different order

// Test Equality (should be true if you updated Equals to use SetEquals)
Assert.Equal(watcher1, watcher2);

// Test HashCode
Assert.Equal(watcher1.GetHashCode(), watcher2.GetHashCode());

var watcher3 = new KeyValueWatcher { Key = "TestKey", Tags = tags };
var watcher4 = new KeyValueWatcher { Key = "TestKey", Tags = new List<string> { "v2", "v1", "v3" } }; // Different tags

// Test Equality (should be true if you updated Equals to use SetEquals)
Assert.NotEqual(watcher3, watcher4);

// Test HashCode
Assert.NotEqual(watcher3.GetHashCode(), watcher4.GetHashCode());
}

[Fact]
public void TagFiltersTests_BasicTagFiltering()
{
Expand Down
Loading