From 0224bde447ccf3f8c94f49eb741f41569d7210e2 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Mon, 29 Jul 2024 13:53:30 -0400 Subject: [PATCH 1/2] feat: back targetingKey with internal map (#288) v1 backport of https://github.com/open-feature/dotnet-sdk/pull/287 --------- Signed-off-by: Todd Baert --- src/OpenFeature/Model/EvaluationContext.cs | 23 +++++-- .../Model/EvaluationContextBuilder.cs | 23 +------ .../OpenFeatureEvaluationContextTests.cs | 68 +++++++++++++++++++ 3 files changed, 87 insertions(+), 27 deletions(-) diff --git a/src/OpenFeature/Model/EvaluationContext.cs b/src/OpenFeature/Model/EvaluationContext.cs index 6db585a1..cedfba60 100644 --- a/src/OpenFeature/Model/EvaluationContext.cs +++ b/src/OpenFeature/Model/EvaluationContext.cs @@ -11,26 +11,30 @@ namespace OpenFeature.Model /// Evaluation context public sealed class EvaluationContext { + /// + /// The index for the "targeting key" property when the EvaluationContext is serialized or expressed as a dictionary. + /// + internal const string TargetingKeyIndex = "targetingKey"; + + private readonly Structure _structure; /// /// Internal constructor used by the builder. /// - /// The targeting key - /// The content of the context. - internal EvaluationContext(string targetingKey, Structure content) + /// + internal EvaluationContext(Structure content) { - this.TargetingKey = targetingKey; this._structure = content; } + /// /// Private constructor for making an empty . /// private EvaluationContext() { this._structure = Structure.Empty; - this.TargetingKey = string.Empty; } /// @@ -89,7 +93,14 @@ public IImmutableDictionary AsDictionary() /// /// Returns the targeting key for the context. /// - public string TargetingKey { get; } + public string TargetingKey + { + get + { + this._structure.TryGetValue(TargetingKeyIndex, out Value targetingKey); + return targetingKey?.AsString; + } + } /// /// Return an enumerator for all values diff --git a/src/OpenFeature/Model/EvaluationContextBuilder.cs b/src/OpenFeature/Model/EvaluationContextBuilder.cs index 89174cf6..30e2ffe0 100644 --- a/src/OpenFeature/Model/EvaluationContextBuilder.cs +++ b/src/OpenFeature/Model/EvaluationContextBuilder.cs @@ -14,8 +14,6 @@ public sealed class EvaluationContextBuilder { private readonly StructureBuilder _attributes = Structure.Builder(); - internal string TargetingKey { get; private set; } - /// /// Internal to only allow direct creation by . /// @@ -28,7 +26,7 @@ internal EvaluationContextBuilder() { } /// This builder public EvaluationContextBuilder SetTargetingKey(string targetingKey) { - this.TargetingKey = targetingKey; + this._attributes.Set(EvaluationContext.TargetingKeyIndex, targetingKey); return this; } @@ -138,23 +136,6 @@ public EvaluationContextBuilder Set(string key, DateTime value) /// This builder public EvaluationContextBuilder Merge(EvaluationContext context) { - string newTargetingKey = ""; - - if (!string.IsNullOrWhiteSpace(TargetingKey)) - { - newTargetingKey = TargetingKey; - } - - if (!string.IsNullOrWhiteSpace(context.TargetingKey)) - { - newTargetingKey = context.TargetingKey; - } - - if (!string.IsNullOrWhiteSpace(newTargetingKey)) - { - this.TargetingKey = newTargetingKey; - } - foreach (var kvp in context) { this.Set(kvp.Key, kvp.Value); @@ -169,7 +150,7 @@ public EvaluationContextBuilder Merge(EvaluationContext context) /// An immutable public EvaluationContext Build() { - return new EvaluationContext(this.TargetingKey, this._attributes.Build()); + return new EvaluationContext(this._attributes.Build()); } } } diff --git a/test/OpenFeature.Tests/OpenFeatureEvaluationContextTests.cs b/test/OpenFeature.Tests/OpenFeatureEvaluationContextTests.cs index 0b8ee097..8de8a283 100644 --- a/test/OpenFeature.Tests/OpenFeatureEvaluationContextTests.cs +++ b/test/OpenFeature.Tests/OpenFeatureEvaluationContextTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using AutoFixture; using FluentAssertions; using OpenFeature.Model; @@ -151,5 +152,72 @@ public void Should_Be_Able_To_Get_All_Values() context.Count.Should().Be(count); } + + [Fact] + public void TryGetValue_WhenCalledWithExistingKey_ReturnsTrueAndExpectedValue() + { + // Arrange + var key = "testKey"; + var expectedValue = new Value("testValue"); + var structure = new Structure(new Dictionary { { key, expectedValue } }); + var evaluationContext = new EvaluationContext(structure); + + // Act + var result = evaluationContext.TryGetValue(key, out var actualValue); + + // Assert + Assert.True(result); + Assert.Equal(expectedValue, actualValue); + } + + [Fact] + public void GetValueOnTargetingKeySetWithTargetingKey_Equals_TargetingKey() + { + // Arrange + var value = "my_targeting_key"; + var evaluationContext = EvaluationContext.Builder().SetTargetingKey(value).Build(); + + // Act + var result = evaluationContext.TryGetValue(EvaluationContext.TargetingKeyIndex, out var actualFromStructure); + var actualFromTargetingKey = evaluationContext.TargetingKey; + + // Assert + Assert.True(result); + Assert.Equal(value, actualFromStructure?.AsString); + Assert.Equal(value, actualFromTargetingKey); + } + + [Fact] + public void GetValueOnTargetingKeySetWithStructure_Equals_TargetingKey() + { + // Arrange + var value = "my_targeting_key"; + var evaluationContext = EvaluationContext.Builder().Set(EvaluationContext.TargetingKeyIndex, new Value(value)).Build(); + + // Act + var result = evaluationContext.TryGetValue(EvaluationContext.TargetingKeyIndex, out var actualFromStructure); + var actualFromTargetingKey = evaluationContext.TargetingKey; + + // Assert + Assert.True(result); + Assert.Equal(value, actualFromStructure?.AsString); + Assert.Equal(value, actualFromTargetingKey); + } + + [Fact] + public void GetValueOnTargetingKeySetWithNonStringValue_Equals_Null() + { + // Arrange + var evaluationContext = EvaluationContext.Builder().Set(EvaluationContext.TargetingKeyIndex, new Value(1)).Build(); + + // Act + var result = evaluationContext.TryGetValue(EvaluationContext.TargetingKeyIndex, out var actualFromStructure); + var actualFromTargetingKey = evaluationContext.TargetingKey; + + // Assert + Assert.True(result); + Assert.Null(actualFromStructure?.AsString); + Assert.Null(actualFromTargetingKey); + } } } From 2974a170cd2e679b43d86fe0554b749f56baa49a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:13:24 -0400 Subject: [PATCH 2/2] chore(v1): release 1.6.0 (#289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :robot: I have created a release *beep* *boop* --- ## [1.6.0](https://github.com/open-feature/dotnet-sdk/compare/v1.5.2...v1.6.0) (2024-07-29) ### ✨ New Features * back targetingKey with internal map ([#288](https://github.com/open-feature/dotnet-sdk/issues/288)) ([0224bde](https://github.com/open-feature/dotnet-sdk/commit/0224bde447ccf3f8c94f49eb741f41569d7210e2)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 7 +++++++ README.md | 4 ++-- build/Common.prod.props | 2 +- version.txt | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 453ca4c5..0d1bebe1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.5.2" + ".": "1.6.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b4a5153..4ceb5c46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.6.0](https://github.com/open-feature/dotnet-sdk/compare/v1.5.2...v1.6.0) (2024-07-29) + + +### ✨ New Features + +* back targetingKey with internal map ([#288](https://github.com/open-feature/dotnet-sdk/issues/288)) ([0224bde](https://github.com/open-feature/dotnet-sdk/commit/0224bde447ccf3f8c94f49eb741f41569d7210e2)) + ## [1.5.2](https://github.com/open-feature/dotnet-sdk/compare/v1.5.1...v1.5.2) (2024-07-26) diff --git a/README.md b/README.md index fed4c7ae..f458e7ae 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ [![Specification](https://img.shields.io/static/v1?label=specification&message=v0.7.0&color=yellow&style=for-the-badge)](https://github.com/open-feature/spec/releases/tag/v0.7.0) [ - ![Release](https://img.shields.io/static/v1?label=release&message=v1.5.2&color=blue&style=for-the-badge) -](https://github.com/open-feature/dotnet-sdk/releases/tag/v1.5.2) + ![Release](https://img.shields.io/static/v1?label=release&message=v1.6.0&color=blue&style=for-the-badge) +](https://github.com/open-feature/dotnet-sdk/releases/tag/v1.6.0) [![Slack](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Codecov](https://codecov.io/gh/open-feature/dotnet-sdk/branch/main/graph/badge.svg?token=MONAVJBXUJ)](https://codecov.io/gh/open-feature/dotnet-sdk) diff --git a/build/Common.prod.props b/build/Common.prod.props index 7d8a25be..985d4257 100644 --- a/build/Common.prod.props +++ b/build/Common.prod.props @@ -9,7 +9,7 @@ - 1.5.2 + 1.6.0 git https://github.com/open-feature/dotnet-sdk OpenFeature is an open standard for feature flag management, created to support a robust feature flag ecosystem using cloud native technologies. OpenFeature will provide a unified API and SDK, and a developer-first, cloud-native implementation, with extensibility for open source and commercial offerings. diff --git a/version.txt b/version.txt index 4cda8f19..dc1e644a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.5.2 +1.6.0