From 5b5f9a38b07b1798c710125d06798f5606b9ec6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Tue, 23 Jan 2024 17:52:27 +0000
Subject: [PATCH 01/30] Add FlagMetadata class to OpenFeature.Model
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 src/OpenFeature/Model/FlagMetadata.cs
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
new file mode 100644
index 00000000..3a5f6fb5
--- /dev/null
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -0,0 +1,7 @@
+namespace OpenFeature.Model
+{
+ public sealed class FlagMetadata
+ {
+
+ }
+}
From be07fd0737fce1a41271ecd353cf1b1e9e33c0b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Tue, 23 Jan 2024 17:54:43 +0000
Subject: [PATCH 02/30] Update FlagEvaluationDetails and ResolutionDetails
classes with FlagMetadata property
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagEvaluationDetails.cs | 11 +++++++++--
src/OpenFeature/Model/ResolutionDetails.cs | 11 +++++++++--
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/src/OpenFeature/Model/FlagEvaluationDetails.cs b/src/OpenFeature/Model/FlagEvaluationDetails.cs
index af31ca6d..cff22a8b 100644
--- a/src/OpenFeature/Model/FlagEvaluationDetails.cs
+++ b/src/OpenFeature/Model/FlagEvaluationDetails.cs
@@ -6,7 +6,7 @@ namespace OpenFeature.Model
/// The contract returned to the caller that describes the result of the flag evaluation process.
///
/// Flag value type
- ///
+ ///
public sealed class FlagEvaluationDetails
{
///
@@ -45,6 +45,11 @@ public sealed class FlagEvaluationDetails
///
public string Variant { get; }
+ ///
+ /// A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number.
+ ///
+ public FlagMetadata FlagMetadata { get; }
+
///
/// Initializes a new instance of the class.
///
@@ -54,8 +59,9 @@ public sealed class FlagEvaluationDetails
/// Reason
/// Variant
/// Error message
+ /// Flag metadata
public FlagEvaluationDetails(string flagKey, T value, ErrorType errorType, string reason, string variant,
- string errorMessage = null)
+ string errorMessage = null, FlagMetadata flagMetadata = null)
{
this.Value = value;
this.FlagKey = flagKey;
@@ -63,6 +69,7 @@ public FlagEvaluationDetails(string flagKey, T value, ErrorType errorType, strin
this.Reason = reason;
this.Variant = variant;
this.ErrorMessage = errorMessage;
+ this.FlagMetadata = flagMetadata;
}
}
}
diff --git a/src/OpenFeature/Model/ResolutionDetails.cs b/src/OpenFeature/Model/ResolutionDetails.cs
index 024f36de..9319096f 100644
--- a/src/OpenFeature/Model/ResolutionDetails.cs
+++ b/src/OpenFeature/Model/ResolutionDetails.cs
@@ -7,7 +7,7 @@ namespace OpenFeature.Model
/// Describes the details of the feature flag being evaluated
///
/// Flag value type
- ///
+ ///
public sealed class ResolutionDetails
{
///
@@ -44,6 +44,11 @@ public sealed class ResolutionDetails
///
public string Variant { get; }
+ ///
+ /// A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number.
+ ///
+ public FlagMetadata FlagMetadata { get; }
+
///
/// Initializes a new instance of the class.
///
@@ -53,8 +58,9 @@ public sealed class ResolutionDetails
/// Reason
/// Variant
/// Error message
+ /// Flag metadata
public ResolutionDetails(string flagKey, T value, ErrorType errorType = ErrorType.None, string reason = null,
- string variant = null, string errorMessage = null)
+ string variant = null, string errorMessage = null, FlagMetadata flagMetadata = null)
{
this.Value = value;
this.FlagKey = flagKey;
@@ -62,6 +68,7 @@ public ResolutionDetails(string flagKey, T value, ErrorType errorType = ErrorTyp
this.Reason = reason;
this.Variant = variant;
this.ErrorMessage = errorMessage;
+ this.FlagMetadata = flagMetadata;
}
}
}
From 454a2778b2add1bff0e5564ee0ea8986f94adcd6 Mon Sep 17 00:00:00 2001
From: Austin Drenski
Date: Tue, 23 Jan 2024 14:16:50 -0500
Subject: [PATCH 03/30] chore: SourceLink is built-in for .NET SDK 8.0.100+
(#198)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Austin Drenski
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
build/Common.prod.props | 7 -------
build/Common.props | 1 -
src/Directory.Build.targets | 7 -------
3 files changed, 15 deletions(-)
diff --git a/build/Common.prod.props b/build/Common.prod.props
index 6735f173..b797ea0d 100644
--- a/build/Common.prod.props
+++ b/build/Common.prod.props
@@ -28,11 +28,4 @@
-
- true
- true
- true
- snupkg
-
-
diff --git a/build/Common.props b/build/Common.props
index 43424f59..afd3c08a 100644
--- a/build/Common.props
+++ b/build/Common.props
@@ -21,7 +21,6 @@
-->
[8.0.0,)
[2.0,)
- [1.0.0,2.0)
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
index 44742c36..bef896bf 100644
--- a/src/Directory.Build.targets
+++ b/src/Directory.Build.targets
@@ -1,11 +1,4 @@
-
-
- all
- runtime; build; native; contentfiles; analyzers
-
-
-
$([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))
From fc817a6172acc47c21d20a759d7b9d8a19caec96 Mon Sep 17 00:00:00 2001
From: Austin Drenski
Date: Tue, 23 Jan 2024 15:09:48 -0500
Subject: [PATCH 04/30] chore: Sync release.yml with ci.yml following #173
(#195)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Austin Drenski
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
.github/workflows/release.yml | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 04f4aedc..01dc95a8 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -7,7 +7,7 @@ on:
jobs:
release-package:
- runs-on: windows-latest
+ runs-on: ubuntu-latest
steps:
- uses: google-github-actions/release-please-action@v3
@@ -34,19 +34,10 @@ jobs:
if: ${{ steps.release.outputs.releases_created }}
run: dotnet restore
- - name: Build
- if: ${{ steps.release.outputs.releases_created }}
- run: |
- dotnet build --configuration Release --no-restore -p:Deterministic=true
-
- name: Pack
if: ${{ steps.release.outputs.releases_created }}
- run: |
- dotnet pack OpenFeature.proj --configuration Release --no-build
+ run: dotnet pack --no-restore
- name: Publish to Nuget
if: ${{ steps.release.outputs.releases_created }}
- run: |
- dotnet nuget push src/OpenFeature/bin/Release/OpenFeature.${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }}.nupkg `
- --api-key ${{secrets.NUGET_TOKEN}} `
- --source https://api.nuget.org/v3/index.json
+ run: dotnet nuget push "src/**/*.nupkg" --api-key "${{ secrets.NUGET_TOKEN }}" --source https://api.nuget.org/v3/index.json
From ace936edca3aadf7d4f7fda9a874b33a8255da97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Tue, 23 Jan 2024 21:14:38 +0000
Subject: [PATCH 05/30] build: Update OpenFeature.sln (#202)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
OpenFeature.sln | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/OpenFeature.sln b/OpenFeature.sln
index 5ed0e809..887eb389 100644
--- a/OpenFeature.sln
+++ b/OpenFeature.sln
@@ -36,7 +36,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature.Tests", "test\O
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature.Benchmarks", "test\OpenFeature.Benchmarks\OpenFeature.Benchmarks.csproj", "{90E7EAD3-251E-4490-AF78-E758E33518E5}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature.E2ETests", "test\OpenFeature.E2ETests\OpenFeature.E2ETests.csproj", "{90E7EAD3-251E-4490-AF78-E758E33518E5}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenFeature.E2ETests", "test\OpenFeature.E2ETests\OpenFeature.E2ETests.csproj", "{7398C446-2630-4F8C-9278-4E807720E9E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -52,10 +52,10 @@ Global
{49BB42BA-10A6-4DA3-A7D5-38C968D57837}.Debug|Any CPU.Build.0 = Debug|Any CPU
{49BB42BA-10A6-4DA3-A7D5-38C968D57837}.Release|Any CPU.ActiveCfg = Release|Any CPU
{49BB42BA-10A6-4DA3-A7D5-38C968D57837}.Release|Any CPU.Build.0 = Release|Any CPU
- {90E7EAD3-251E-4490-AF78-E758E33518E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {90E7EAD3-251E-4490-AF78-E758E33518E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {90E7EAD3-251E-4490-AF78-E758E33518E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {90E7EAD3-251E-4490-AF78-E758E33518E5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7398C446-2630-4F8C-9278-4E807720E9E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7398C446-2630-4F8C-9278-4E807720E9E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7398C446-2630-4F8C-9278-4E807720E9E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7398C446-2630-4F8C-9278-4E807720E9E5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -63,7 +63,7 @@ Global
GlobalSection(NestedProjects) = preSolution
{07A6E6BD-FB7E-4B3B-9CBE-65AE9D0EB223} = {C97E9975-E10A-4817-AE2C-4DD69C3C02D4}
{49BB42BA-10A6-4DA3-A7D5-38C968D57837} = {65FBA159-23E0-4CF9-881B-F78DBFF198E9}
- {90E7EAD3-251E-4490-AF78-E758E33518E5} = {65FBA159-23E0-4CF9-881B-F78DBFF198E9}
+ {7398C446-2630-4F8C-9278-4E807720E9E5} = {65FBA159-23E0-4CF9-881B-F78DBFF198E9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {41F01B78-FB06-404F-8AD0-6ED6973F948F}
From bd4a48a4a7f2d55d7bf4b7832abfa9a54cacf938 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 24 Jan 2024 12:33:08 +1000
Subject: [PATCH 06/30] chore(deps): update actions/upload-artifact action to
v4.3.0 (#203)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ca5f5083..1a96f789 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -83,7 +83,7 @@ jobs:
- name: Publish NuGet packages (fork)
if: github.event.pull_request.head.repo.fork == true
- uses: actions/upload-artifact@v4.2.0
+ uses: actions/upload-artifact@v4.3.0
with:
name: nupkgs
path: src/**/*.nupkg
From adb57ab0a9d450428a56ddd6a1a280c45d34a7c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Wed, 24 Jan 2024 09:04:57 +0000
Subject: [PATCH 07/30] Adding a GetValue.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index 3a5f6fb5..ac182a3f 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -1,7 +1,27 @@
+using System;
+using System.Collections.Immutable;
+
+#nullable enable
namespace OpenFeature.Model
{
public sealed class FlagMetadata
{
+ private readonly ImmutableDictionary _metadata;
+
+ public FlagMetadata(ImmutableDictionary metadata)
+ {
+ this._metadata = metadata;
+ }
+
+ public T? GetValue(string key) where T : struct
+ {
+ var hasValue = this._metadata.TryGetValue(key, out var value);
+ if (!hasValue)
+ {
+ return null;
+ }
+ return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(T)}");
+ }
}
}
From 0034d51c4cbf4c6d0e7d98b6d281bfe9411e09a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Wed, 24 Jan 2024 17:26:12 +0000
Subject: [PATCH 08/30] Adding more Get methods.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 31 +++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index ac182a3f..4ddf484a 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -13,6 +13,37 @@ public FlagMetadata(ImmutableDictionary metadata)
this._metadata = metadata;
}
+ public string? GetString(string key)
+ {
+ var hasValue = this._metadata.TryGetValue(key, out var value);
+ if (!hasValue)
+ {
+ return null;
+ }
+
+ return value is string tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(string)}");
+ }
+
+ public bool? GetBool(string key)
+ {
+ return this.GetValue(key);
+ }
+
+ public int? GetInt(string key)
+ {
+ return this.GetValue(key);
+ }
+
+ public double? GetDouble(string key)
+ {
+ return this.GetValue(key);
+ }
+
+ public decimal? GetDecimal(string key)
+ {
+ return this.GetValue(key);
+ }
+
public T? GetValue(string key) where T : struct
{
var hasValue = this._metadata.TryGetValue(key, out var value);
From d8956cd817ab94df71ee9050a6f3b855980bda28 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Wed, 24 Jan 2024 17:44:10 +0000
Subject: [PATCH 09/30] Adding empty constructor.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index 4ddf484a..18b25226 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Collections.Immutable;
#nullable enable
@@ -6,13 +7,17 @@ namespace OpenFeature.Model
{
public sealed class FlagMetadata
{
- private readonly ImmutableDictionary _metadata;
+ private readonly Dictionary _metadata;
- public FlagMetadata(ImmutableDictionary metadata)
+ public FlagMetadata(Dictionary metadata)
{
this._metadata = metadata;
}
+ public FlagMetadata() : this([])
+ {
+ }
+
public string? GetString(string key)
{
var hasValue = this._metadata.TryGetValue(key, out var value);
From a8978a054a06a97465b12e2ac0430e42ceca0d10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Wed, 24 Jan 2024 17:48:08 +0000
Subject: [PATCH 10/30] Adding top level namespace.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 81 +++++++++++++--------------
1 file changed, 40 insertions(+), 41 deletions(-)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index 18b25226..1fc0c6c5 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -3,61 +3,60 @@
using System.Collections.Immutable;
#nullable enable
-namespace OpenFeature.Model
+namespace OpenFeature.Model;
+
+public sealed class FlagMetadata
{
- public sealed class FlagMetadata
+ private readonly Dictionary _metadata;
+
+ public FlagMetadata(Dictionary metadata)
{
- private readonly Dictionary _metadata;
+ this._metadata = metadata;
+ }
- public FlagMetadata(Dictionary metadata)
- {
- this._metadata = metadata;
- }
+ public FlagMetadata() : this([])
+ {
+ }
- public FlagMetadata() : this([])
+ public string? GetString(string key)
+ {
+ var hasValue = this._metadata.TryGetValue(key, out var value);
+ if (!hasValue)
{
+ return null;
}
- public string? GetString(string key)
- {
- var hasValue = this._metadata.TryGetValue(key, out var value);
- if (!hasValue)
- {
- return null;
- }
+ return value is string tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(string)}");
+ }
- return value is string tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(string)}");
- }
+ public bool? GetBool(string key)
+ {
+ return this.GetValue(key);
+ }
- public bool? GetBool(string key)
- {
- return this.GetValue(key);
- }
+ public int? GetInt(string key)
+ {
+ return this.GetValue(key);
+ }
- public int? GetInt(string key)
- {
- return this.GetValue(key);
- }
+ public double? GetDouble(string key)
+ {
+ return this.GetValue(key);
+ }
- public double? GetDouble(string key)
- {
- return this.GetValue(key);
- }
+ public decimal? GetDecimal(string key)
+ {
+ return this.GetValue(key);
+ }
- public decimal? GetDecimal(string key)
+ public T? GetValue(string key) where T : struct
+ {
+ var hasValue = this._metadata.TryGetValue(key, out var value);
+ if (!hasValue)
{
- return this.GetValue(key);
+ return null;
}
- public T? GetValue(string key) where T : struct
- {
- var hasValue = this._metadata.TryGetValue(key, out var value);
- if (!hasValue)
- {
- return null;
- }
-
- return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(T)}");
- }
+ return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(T)}");
}
}
From f40ce57e78b5f6233f9a02509911800f8671fdef Mon Sep 17 00:00:00 2001
From: Michael Beemer
Date: Wed, 24 Jan 2024 14:48:00 -0500
Subject: [PATCH 11/30] docs: update the feature table key
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The linter on the docs page complains that this should be a header instead of an emphasis. This PR changes the key to use a blockquote, which works better anyway.
Signed-off-by: Michael Beemer
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index a572a40f..88c49734 100644
--- a/README.md
+++ b/README.md
@@ -80,7 +80,7 @@ public async Task Example()
| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
-_Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌_
+> Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌
### Providers
From 824ffc26940852f4494e3037d9c25235f9e855fc Mon Sep 17 00:00:00 2001
From: Austin Drenski
Date: Fri, 26 Jan 2024 15:23:52 -0500
Subject: [PATCH 12/30] chore: Enable Central Package Management (CPM) (#178)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Austin Drenski
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
Directory.Packages.props | 32 +++++++++++++++++++
build/Common.props | 15 ++-------
build/Common.tests.props | 18 +----------
src/OpenFeature/OpenFeature.csproj | 6 ++--
.../OpenFeature.Benchmarks.csproj | 4 +--
.../OpenFeature.E2ETests.csproj | 23 +++++++------
.../OpenFeature.Tests.csproj | 16 +++++-----
7 files changed, 60 insertions(+), 54 deletions(-)
create mode 100644 Directory.Packages.props
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 00000000..e76ac475
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,32 @@
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/Common.props b/build/Common.props
index afd3c08a..b0700847 100644
--- a/build/Common.props
+++ b/build/Common.props
@@ -14,21 +14,12 @@
true
-
-
- [8.0.0,)
- [2.0,)
-
-
-
-
+
+
-
+
diff --git a/build/Common.tests.props b/build/Common.tests.props
index 060e749d..590fc99d 100644
--- a/build/Common.tests.props
+++ b/build/Common.tests.props
@@ -16,22 +16,6 @@
-
+
-
-
-
- [4.17.0]
- [0.13.1]
- [3.1.2]
- [6.7.0]
- [2.3.3]
- [17.2.0]
- [5.0.0]
- [2.4.3,3.0)
- [2.4.1,3.0)
-
diff --git a/src/OpenFeature/OpenFeature.csproj b/src/OpenFeature/OpenFeature.csproj
index a6a5828f..da82b999 100644
--- a/src/OpenFeature/OpenFeature.csproj
+++ b/src/OpenFeature/OpenFeature.csproj
@@ -7,9 +7,9 @@
-
-
-
+
+
+
diff --git a/test/OpenFeature.Benchmarks/OpenFeature.Benchmarks.csproj b/test/OpenFeature.Benchmarks/OpenFeature.Benchmarks.csproj
index 60c2231b..81342e09 100644
--- a/test/OpenFeature.Benchmarks/OpenFeature.Benchmarks.csproj
+++ b/test/OpenFeature.Benchmarks/OpenFeature.Benchmarks.csproj
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/test/OpenFeature.E2ETests/OpenFeature.E2ETests.csproj b/test/OpenFeature.E2ETests/OpenFeature.E2ETests.csproj
index 628b4b31..e0093787 100644
--- a/test/OpenFeature.E2ETests/OpenFeature.E2ETests.csproj
+++ b/test/OpenFeature.E2ETests/OpenFeature.E2ETests.csproj
@@ -7,24 +7,23 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/test/OpenFeature.Tests/OpenFeature.Tests.csproj b/test/OpenFeature.Tests/OpenFeature.Tests.csproj
index 83689e5a..9ceac0dc 100644
--- a/test/OpenFeature.Tests/OpenFeature.Tests.csproj
+++ b/test/OpenFeature.Tests/OpenFeature.Tests.csproj
@@ -7,20 +7,20 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
+
+
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
From f70fc61bee5cbafb5c26e508ae27a2d5a6e6ce8e Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 26 Jan 2024 15:40:54 -0500
Subject: [PATCH 13/30] chore(deps): update codecov/codecov-action action to
v3.1.5 (#209)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
.github/workflows/code-coverage.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml
index 5e6fb5d4..3fadffc8 100644
--- a/.github/workflows/code-coverage.yml
+++ b/.github/workflows/code-coverage.yml
@@ -27,7 +27,7 @@ jobs:
- name: Run Test
run: dotnet test --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
- - uses: codecov/codecov-action@v3.1.4
+ - uses: codecov/codecov-action@v3.1.5
with:
env_vars: OS
name: Code Coverage for ${{ matrix.os }}
From 58bd313c66dc643ee82cb962b2d2c0275337ae2e Mon Sep 17 00:00:00 2001
From: Austin Drenski
Date: Fri, 26 Jan 2024 16:31:28 -0500
Subject: [PATCH 14/30] chore: More sln cleanup (#206)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
See: open-feature#202
Signed-off-by: Austin Drenski
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
OpenFeature.sln | 70 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 61 insertions(+), 9 deletions(-)
diff --git a/OpenFeature.sln b/OpenFeature.sln
index 887eb389..6f1cce8d 100644
--- a/OpenFeature.sln
+++ b/OpenFeature.sln
@@ -3,22 +3,61 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature", "src\OpenFeature\OpenFeature.csproj", "{07A6E6BD-FB7E-4B3B-9CBE-65AE9D0EB223}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".", ".", "{E8916D4F-B97E-42D6-8620-ED410A106F94}"
+ ProjectSection(SolutionItems) = preProject
+ README.md = README.md
+ CONTRIBUTING.md = CONTRIBUTING.md
+ .editorconfig = .editorconfig
+ .gitignore = .gitignore
+ .gitmodules = .gitmodules
+ .release-please-manifest.json = .release-please-manifest.json
+ CHANGELOG.md = CHANGELOG.md
+ CODEOWNERS = CODEOWNERS
+ global.json = global.json
+ LICENSE = LICENSE
+ release-please-config.json = release-please-config.json
+ renovate.json = renovate.json
+ version.txt = version.txt
+ EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{72005F60-C2E8-40BF-AE95-893635134D7D}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".config", ".config", "{9392E03B-4E6B-434C-8553-B859424388B1}"
ProjectSection(SolutionItems) = preProject
+ .config\dotnet-tools.json = .config\dotnet-tools.json
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{2B172AA0-A5A6-4D94-BA1F-B79D59B0C2D8}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{C4746B8C-FE19-440B-922C-C2377F906FE8}"
+ ProjectSection(SolutionItems) = preProject
+ .github\workflows\ci.yml = .github\workflows\ci.yml
.github\workflows\code-coverage.yml = .github\workflows\code-coverage.yml
.github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml
- build\Common.prod.props = build\Common.prod.props
- build\Common.props = build\Common.props
- build\Common.tests.props = build\Common.tests.props
- CONTRIBUTING.md = CONTRIBUTING.md
.github\workflows\dotnet-format.yml = .github\workflows\dotnet-format.yml
+ .github\workflows\e2e.yml = .github\workflows\e2e.yml
.github\workflows\lint-pr.yml = .github\workflows\lint-pr.yml
- .github\workflows\linux-ci.yml = .github\workflows\linux-ci.yml
- README.md = README.md
.github\workflows\release.yml = .github\workflows\release.yml
- .github\workflows\windows-ci.yml = .github\workflows\windows-ci.yml
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{09BAB3A2-E94C-490A-861C-7D1E11BB7024}"
+ ProjectSection(SolutionItems) = preProject
+ .github\ISSUE_TEMPLATE\bug.yaml = .github\ISSUE_TEMPLATE\bug.yaml
+ .github\ISSUE_TEMPLATE\documentation.yaml = .github\ISSUE_TEMPLATE\documentation.yaml
+ .github\ISSUE_TEMPLATE\feature.yaml = .github\ISSUE_TEMPLATE\feature.yaml
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".vscode", ".vscode", "{4BB69DB3-9653-4197-9589-37FA6D658CB7}"
+ ProjectSection(SolutionItems) = preProject
+ .vscode\launch.json = .vscode\launch.json
+ .vscode\tasks.json = .vscode\tasks.json
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{72005F60-C2E8-40BF-AE95-893635134D7D}"
+ ProjectSection(SolutionItems) = preProject
+ build\Common.prod.props = build\Common.prod.props
+ build\Common.props = build\Common.props
+ build\Common.tests.props = build\Common.tests.props
+ build\openfeature-icon.png = build\openfeature-icon.png
+ build\xunit.runner.json = build\xunit.runner.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C97E9975-E10A-4817-AE2C-4DD69C3C02D4}"
@@ -32,6 +71,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{65FBA159-2
test\Directory.Build.props = test\Directory.Build.props
EndProjectSection
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature", "src\OpenFeature\OpenFeature.csproj", "{07A6E6BD-FB7E-4B3B-9CBE-65AE9D0EB223}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature.Tests", "test\OpenFeature.Tests\OpenFeature.Tests.csproj", "{49BB42BA-10A6-4DA3-A7D5-38C968D57837}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature.Benchmarks", "test\OpenFeature.Benchmarks\OpenFeature.Benchmarks.csproj", "{90E7EAD3-251E-4490-AF78-E758E33518E5}"
@@ -52,6 +93,10 @@ Global
{49BB42BA-10A6-4DA3-A7D5-38C968D57837}.Debug|Any CPU.Build.0 = Debug|Any CPU
{49BB42BA-10A6-4DA3-A7D5-38C968D57837}.Release|Any CPU.ActiveCfg = Release|Any CPU
{49BB42BA-10A6-4DA3-A7D5-38C968D57837}.Release|Any CPU.Build.0 = Release|Any CPU
+ {90E7EAD3-251E-4490-AF78-E758E33518E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90E7EAD3-251E-4490-AF78-E758E33518E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90E7EAD3-251E-4490-AF78-E758E33518E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90E7EAD3-251E-4490-AF78-E758E33518E5}.Release|Any CPU.Build.0 = Release|Any CPU
{7398C446-2630-4F8C-9278-4E807720E9E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7398C446-2630-4F8C-9278-4E807720E9E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7398C446-2630-4F8C-9278-4E807720E9E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -63,7 +108,14 @@ Global
GlobalSection(NestedProjects) = preSolution
{07A6E6BD-FB7E-4B3B-9CBE-65AE9D0EB223} = {C97E9975-E10A-4817-AE2C-4DD69C3C02D4}
{49BB42BA-10A6-4DA3-A7D5-38C968D57837} = {65FBA159-23E0-4CF9-881B-F78DBFF198E9}
+ {90E7EAD3-251E-4490-AF78-E758E33518E5} = {65FBA159-23E0-4CF9-881B-F78DBFF198E9}
{7398C446-2630-4F8C-9278-4E807720E9E5} = {65FBA159-23E0-4CF9-881B-F78DBFF198E9}
+ {C4746B8C-FE19-440B-922C-C2377F906FE8} = {2B172AA0-A5A6-4D94-BA1F-B79D59B0C2D8}
+ {09BAB3A2-E94C-490A-861C-7D1E11BB7024} = {2B172AA0-A5A6-4D94-BA1F-B79D59B0C2D8}
+ {72005F60-C2E8-40BF-AE95-893635134D7D} = {E8916D4F-B97E-42D6-8620-ED410A106F94}
+ {9392E03B-4E6B-434C-8553-B859424388B1} = {E8916D4F-B97E-42D6-8620-ED410A106F94}
+ {2B172AA0-A5A6-4D94-BA1F-B79D59B0C2D8} = {E8916D4F-B97E-42D6-8620-ED410A106F94}
+ {4BB69DB3-9653-4197-9589-37FA6D658CB7} = {E8916D4F-B97E-42D6-8620-ED410A106F94}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {41F01B78-FB06-404F-8AD0-6ED6973F948F}
From 48b9e6c7ab4c833c18b153da1d56cd3503597785 Mon Sep 17 00:00:00 2001
From: Austin Drenski
Date: Sat, 27 Jan 2024 15:09:03 -0500
Subject: [PATCH 15/30] chore: Sync ci.yml with contrib repo (#196)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Austin Drenski
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
.github/workflows/ci.yml | 54 ++++++++++++++++-------------
.github/workflows/code-coverage.yml | 16 ++++++---
.github/workflows/e2e.yml | 3 ++
.github/workflows/release.yml | 3 ++
CONTRIBUTING.md | 35 +++++++++++++++++++
nuget.config | 22 ++++++++++++
6 files changed, 104 insertions(+), 29 deletions(-)
create mode 100644 nuget.config
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1a96f789..c7fc8be9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,4 +1,4 @@
-name: Test
+name: CI
on:
push:
@@ -11,44 +11,41 @@ on:
- '**.md'
jobs:
- unit-tests-linux:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
+ build:
+ strategy:
+ matrix:
+ os: [ ubuntu-latest, windows-latest ]
- - name: Setup .NET SDK
- uses: actions/setup-dotnet@v4
- with:
- dotnet-version: |
- 6.0.x
- 7.0.x
-
- - name: Run Tests
- run: dotnet test test/OpenFeature.Tests/ --configuration Release --logger GitHubActions
+ runs-on: ${{ matrix.os }}
- unit-tests-windows:
- runs-on: windows-latest
steps:
- - uses: actions/checkout@v4
+ - name: Checkout
+ uses: actions/checkout@v4
with:
fetch-depth: 0
+ submodules: recursive
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
+ env:
+ NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
dotnet-version: |
6.0.x
7.0.x
+ source-url: https://nuget.pkg.github.com/open-feature/index.json
+
+ - name: Restore
+ run: dotnet restore
+
+ - name: Build
+ run: dotnet build --no-restore
- - name: Run Tests
- run: dotnet test test\OpenFeature.Tests\ --configuration Release --logger GitHubActions
+ - name: Test
+ run: dotnet test --no-build --logger GitHubActions
packaging:
- needs:
- - unit-tests-linux
- - unit-tests-windows
+ needs: build
permissions:
contents: read
@@ -57,14 +54,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ submodules: recursive
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
+ env:
+ NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
dotnet-version: |
6.0.x
7.0.x
+ source-url: https://nuget.pkg.github.com/open-feature/index.json
- name: Restore
run: dotnet restore
diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml
index 3fadffc8..3a409ae8 100644
--- a/.github/workflows/code-coverage.yml
+++ b/.github/workflows/code-coverage.yml
@@ -12,9 +12,11 @@ on:
jobs:
build-test-report:
- runs-on: ubuntu-latest
- env:
- OS: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ ubuntu-latest, windows-latest ]
+
+ runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@@ -23,13 +25,19 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
+ env:
+ NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ dotnet-version: |
+ 6.0.x
+ 7.0.x
+ source-url: https://nuget.pkg.github.com/open-feature/index.json
- name: Run Test
run: dotnet test --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
- uses: codecov/codecov-action@v3.1.5
with:
- env_vars: OS
name: Code Coverage for ${{ matrix.os }}
fail_ci_if_error: true
verbose: true
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index c0927b60..50a0b812 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -25,10 +25,13 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
+ env:
+ NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
dotnet-version: |
6.0.x
7.0.x
+ source-url: https://nuget.pkg.github.com/open-feature/index.json
- name: Initialize Tests
run: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 01dc95a8..859a9078 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -25,10 +25,13 @@ jobs:
- name: Setup .NET SDK
if: ${{ steps.release.outputs.releases_created }}
uses: actions/setup-dotnet@v4
+ env:
+ NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
dotnet-version: |
6.0.x
7.0.x
+ source-url: https://nuget.pkg.github.com/open-feature/index.json
- name: Install dependencies
if: ${{ steps.release.outputs.releases_created }}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 77eef66a..9f8cf33c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -155,3 +155,38 @@ dotnet restore
dotnet build --configuration Release --output "./release" --no-restore
dotnet release/OpenFeature.Benchmarks.dll
```
+
+## Consuming pre-release packages
+
+1. Acquire a [GitHub personal access token (PAT)](https://docs.github.com/github/authenticating-to-github/creating-a-personal-access-token) scoped for `read:packages` and verify the permissions:
+ ```console
+ $ gh auth login --scopes read:packages
+
+ ? What account do you want to log into? GitHub.com
+ ? What is your preferred protocol for Git operations? HTTPS
+ ? How would you like to authenticate GitHub CLI? Login with a web browser
+
+ ! First copy your one-time code: ****-****
+ Press Enter to open github.com in your browser...
+
+ ✓ Authentication complete.
+ - gh config set -h github.com git_protocol https
+ ✓ Configured git protocol
+ ✓ Logged in as ********
+ ```
+
+ ```console
+ $ gh auth status
+
+ github.com
+ ✓ Logged in to github.com as ******** (~/.config/gh/hosts.yml)
+ ✓ Git operations for github.com configured to use https protocol.
+ ✓ Token: gho_************************************
+ ✓ Token scopes: gist, read:org, read:packages, repo, workflow
+ ```
+2. Run the following command to configure your local environment to consume packages from GitHub Packages:
+ ```console
+ $ dotnet nuget update source github-open-feature --username $(gh api user --jq .email) --password $(gh auth token) --store-password-in-clear-text
+
+ Package source "github-open-feature" was successfully updated.
+ ```
diff --git a/nuget.config b/nuget.config
new file mode 100644
index 00000000..5a0edf43
--- /dev/null
+++ b/nuget.config
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From 03250833bcb67c11e9bb1f5551cad2ece8c66c3f Mon Sep 17 00:00:00 2001
From: Austin Drenski
Date: Mon, 29 Jan 2024 08:43:26 -0500
Subject: [PATCH 16/30] fix: Fix NU1009 reference assembly warning (#222)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Austin Drenski
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
Directory.Packages.props | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index e76ac475..97c4baa6 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -7,7 +7,6 @@
-
@@ -29,4 +28,8 @@
+
+
+
+
From d7ba40f4ba9f00b31da8869fe0f877f0feab95a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Tue, 30 Jan 2024 16:03:33 +0000
Subject: [PATCH 17/30] Refactor FlagMetadata class to use ImmutableDictionary
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit refactors the FlagMetadata class in the OpenFeature.Model namespace to use ImmutableDictionary instead of Dictionary for the _metadata field. This change ensures that the metadata dictionary is immutable, providing better thread safety and preventing unintended modifications. The GetString method is also moved to the bottom of the class for better organization.
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index 1fc0c6c5..9bd9108a 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -7,28 +7,17 @@ namespace OpenFeature.Model;
public sealed class FlagMetadata
{
- private readonly Dictionary _metadata;
+ private readonly ImmutableDictionary _metadata;
public FlagMetadata(Dictionary metadata)
{
- this._metadata = metadata;
+ this._metadata = metadata.ToImmutableDictionary();
}
public FlagMetadata() : this([])
{
}
- public string? GetString(string key)
- {
- var hasValue = this._metadata.TryGetValue(key, out var value);
- if (!hasValue)
- {
- return null;
- }
-
- return value is string tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(string)}");
- }
-
public bool? GetBool(string key)
{
return this.GetValue(key);
@@ -59,4 +48,15 @@ public FlagMetadata() : this([])
return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(T)}");
}
+
+ public string? GetString(string key)
+ {
+ var hasValue = this._metadata.TryGetValue(key, out var value);
+ if (!hasValue)
+ {
+ return null;
+ }
+
+ return value is string tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(string)}");
+ }
}
From b04f01c25dcbf73caa8a6d504d703ab5a9f8dc59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Tue, 30 Jan 2024 16:15:26 +0000
Subject: [PATCH 18/30] Adding initial tests.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 9 +-
test/OpenFeature.Tests/FlagMetadataTest.cs | 108 +++++++++++++++++++++
2 files changed, 110 insertions(+), 7 deletions(-)
create mode 100644 test/OpenFeature.Tests/FlagMetadataTest.cs
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index 9bd9108a..ffe36362 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -30,15 +30,10 @@ public FlagMetadata() : this([])
public double? GetDouble(string key)
{
- return this.GetValue(key);
- }
-
- public decimal? GetDecimal(string key)
- {
- return this.GetValue(key);
+ return this.GetValue(key);
}
- public T? GetValue(string key) where T : struct
+ private T? GetValue(string key) where T : struct
{
var hasValue = this._metadata.TryGetValue(key, out var value);
if (!hasValue)
diff --git a/test/OpenFeature.Tests/FlagMetadataTest.cs b/test/OpenFeature.Tests/FlagMetadataTest.cs
new file mode 100644
index 00000000..d2ca7453
--- /dev/null
+++ b/test/OpenFeature.Tests/FlagMetadataTest.cs
@@ -0,0 +1,108 @@
+using System.Collections.Generic;
+using OpenFeature.Model;
+using Xunit;
+
+namespace OpenFeature.Tests
+{
+ public class FlagMetadataTest
+ {
+ [Fact]
+ public void GetBool_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary();
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetBool("nonexistentKey");
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetBool_Should_Return_Value_If_Key_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary
+ {
+ { "boolKey", true }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetBool("boolKey");
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Fact]
+ public void GetInt_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary();
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetInt("nonexistentKey");
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetInt_Should_Return_Value_If_Key_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary
+ {
+ {
+ "intKey", 1
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetInt("intKey");
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(1, result);
+ }
+
+ [Fact]
+ public void GetDouble_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary();
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetDouble("nonexistentKey");
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetDouble_Should_Return_Value_If_Key_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary
+ {
+ {
+ "doubleKey", 1.2
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetDouble("doubleKey");
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(1.2, result);
+ }
+ }
+}
From 0fb919c103b20baa37a2615bee54cb31956a636c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Tue, 30 Jan 2024 16:17:31 +0000
Subject: [PATCH 19/30] Moved code and fixed code smells.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 8 ++---
test/OpenFeature.Tests/FlagMetadataTest.cs | 34 ++++++++++++++++++++++
2 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index ffe36362..5105d299 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -33,7 +33,7 @@ public FlagMetadata() : this([])
return this.GetValue(key);
}
- private T? GetValue(string key) where T : struct
+ public string? GetString(string key)
{
var hasValue = this._metadata.TryGetValue(key, out var value);
if (!hasValue)
@@ -41,10 +41,10 @@ public FlagMetadata() : this([])
return null;
}
- return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(T)}");
+ return value as string ?? throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(string)}");
}
- public string? GetString(string key)
+ private T? GetValue(string key) where T : struct
{
var hasValue = this._metadata.TryGetValue(key, out var value);
if (!hasValue)
@@ -52,6 +52,6 @@ public FlagMetadata() : this([])
return null;
}
- return value is string tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(string)}");
+ return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(T)}");
}
}
diff --git a/test/OpenFeature.Tests/FlagMetadataTest.cs b/test/OpenFeature.Tests/FlagMetadataTest.cs
index d2ca7453..e4e08c13 100644
--- a/test/OpenFeature.Tests/FlagMetadataTest.cs
+++ b/test/OpenFeature.Tests/FlagMetadataTest.cs
@@ -104,5 +104,39 @@ public void GetDouble_Should_Return_Value_If_Key_Found()
Assert.NotNull(result);
Assert.Equal(1.2, result);
}
+
+ [Fact]
+ public void GetString_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary();
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetString("nonexistentKey");
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetString_Should_Return_Value_If_Key_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary
+ {
+ {
+ "stringKey", "11"
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetString("stringKey");
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("11", result);
+ }
}
}
From 4ad9ca5cd179c9be4944ff89a3920923ea0502b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Tue, 30 Jan 2024 16:33:00 +0000
Subject: [PATCH 20/30] Fix code. Added unit tests.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 4 +-
test/OpenFeature.Tests/FlagMetadataTest.cs | 97 ++++++++++++++++++++--
2 files changed, 90 insertions(+), 11 deletions(-)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index 5105d299..039829f2 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -41,7 +41,7 @@ public FlagMetadata() : this([])
return null;
}
- return value as string ?? throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(string)}");
+ return value as string ?? throw new InvalidCastException($"Cannot cast {value?.GetType()} to {typeof(string)}");
}
private T? GetValue(string key) where T : struct
@@ -52,6 +52,6 @@ public FlagMetadata() : this([])
return null;
}
- return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType().ToString() ?? "Nullable"} to {typeof(T)}");
+ return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType()} to {typeof(T)}");
}
}
diff --git a/test/OpenFeature.Tests/FlagMetadataTest.cs b/test/OpenFeature.Tests/FlagMetadataTest.cs
index e4e08c13..d169714c 100644
--- a/test/OpenFeature.Tests/FlagMetadataTest.cs
+++ b/test/OpenFeature.Tests/FlagMetadataTest.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using OpenFeature.Model;
using Xunit;
@@ -10,8 +11,7 @@ public class FlagMetadataTest
public void GetBool_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
- var metadata = new Dictionary();
- var flagMetadata = new FlagMetadata(metadata);
+ var flagMetadata = new FlagMetadata();
// Act
var result = flagMetadata.GetBool("nonexistentKey");
@@ -26,7 +26,9 @@ public void GetBool_Should_Return_Value_If_Key_Found()
// Arrange
var metadata = new Dictionary
{
- { "boolKey", true }
+ {
+ "boolKey", true
+ }
};
var flagMetadata = new FlagMetadata(metadata);
@@ -38,12 +40,31 @@ public void GetBool_Should_Return_Value_If_Key_Found()
}
[Fact]
- public void GetInt_Should_Return_Null_If_Key_Not_Found()
+ public void GetBool_Should_Throw_Value_Is_Invalid()
{
// Arrange
- var metadata = new Dictionary();
+ var metadata = new Dictionary
+ {
+ {
+ "wrongKey", "11a"
+ }
+ };
var flagMetadata = new FlagMetadata(metadata);
+ // Act
+ var exception = Assert.Throws(() => flagMetadata.GetBool("wrongKey"));
+
+ // Assert
+ Assert.NotNull(exception);
+ Assert.Equal("Cannot cast System.String to System.Boolean", exception.Message);
+ }
+
+ [Fact]
+ public void GetInt_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var flagMetadata = new FlagMetadata();
+
// Act
var result = flagMetadata.GetInt("nonexistentKey");
@@ -72,12 +93,31 @@ public void GetInt_Should_Return_Value_If_Key_Found()
}
[Fact]
- public void GetDouble_Should_Return_Null_If_Key_Not_Found()
+ public void GetInt_Should_Throw_Value_Is_Invalid()
{
// Arrange
- var metadata = new Dictionary();
+ var metadata = new Dictionary
+ {
+ {
+ "wrongKey", "11a"
+ }
+ };
var flagMetadata = new FlagMetadata(metadata);
+ // Act
+ var exception = Assert.Throws(() => flagMetadata.GetInt("wrongKey"));
+
+ // Assert
+ Assert.NotNull(exception);
+ Assert.Equal("Cannot cast System.String to System.Int32", exception.Message);
+ }
+
+ [Fact]
+ public void GetDouble_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var flagMetadata = new FlagMetadata();
+
// Act
var result = flagMetadata.GetDouble("nonexistentKey");
@@ -106,12 +146,31 @@ public void GetDouble_Should_Return_Value_If_Key_Found()
}
[Fact]
- public void GetString_Should_Return_Null_If_Key_Not_Found()
+ public void GetDouble_Should_Throw_Value_Is_Invalid()
{
// Arrange
- var metadata = new Dictionary();
+ var metadata = new Dictionary
+ {
+ {
+ "wrongKey", "11a"
+ }
+ };
var flagMetadata = new FlagMetadata(metadata);
+ // Act
+ var exception = Assert.Throws(() => flagMetadata.GetDouble("wrongKey"));
+
+ // Assert
+ Assert.NotNull(exception);
+ Assert.Equal("Cannot cast System.String to System.Double", exception.Message);
+ }
+
+ [Fact]
+ public void GetString_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var flagMetadata = new FlagMetadata();
+
// Act
var result = flagMetadata.GetString("nonexistentKey");
@@ -138,5 +197,25 @@ public void GetString_Should_Return_Value_If_Key_Found()
Assert.NotNull(result);
Assert.Equal("11", result);
}
+
+ [Fact]
+ public void GetString_Should_Throw_Value_Is_Invalid()
+ {
+ // Arrange
+ var metadata = new Dictionary
+ {
+ {
+ "wrongKey", new object()
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var exception = Assert.Throws(() => flagMetadata.GetString("wrongKey"));
+
+ // Assert
+ Assert.NotNull(exception);
+ Assert.Equal("Cannot cast System.Object to System.String", exception.Message);
+ }
}
}
From 9813d3ca15133bf1b35269b52a6c4c7f528b70e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Tue, 30 Jan 2024 16:37:10 +0000
Subject: [PATCH 21/30] Change namespace scope. Added nullable check.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
test/OpenFeature.Tests/FlagMetadataTest.cs | 362 ++++++++++-----------
1 file changed, 181 insertions(+), 181 deletions(-)
diff --git a/test/OpenFeature.Tests/FlagMetadataTest.cs b/test/OpenFeature.Tests/FlagMetadataTest.cs
index d169714c..5c34d2e2 100644
--- a/test/OpenFeature.Tests/FlagMetadataTest.cs
+++ b/test/OpenFeature.Tests/FlagMetadataTest.cs
@@ -3,219 +3,219 @@
using OpenFeature.Model;
using Xunit;
-namespace OpenFeature.Tests
+#nullable enable
+namespace OpenFeature.Tests;
+
+public class FlagMetadataTest
{
- public class FlagMetadataTest
+ [Fact]
+ public void GetBool_Should_Return_Null_If_Key_Not_Found()
{
- [Fact]
- public void GetBool_Should_Return_Null_If_Key_Not_Found()
- {
- // Arrange
- var flagMetadata = new FlagMetadata();
+ // Arrange
+ var flagMetadata = new FlagMetadata();
- // Act
- var result = flagMetadata.GetBool("nonexistentKey");
+ // Act
+ var result = flagMetadata.GetBool("nonexistentKey");
- // Assert
- Assert.Null(result);
- }
+ // Assert
+ Assert.Null(result);
+ }
- [Fact]
- public void GetBool_Should_Return_Value_If_Key_Found()
+ [Fact]
+ public void GetBool_Should_Return_Value_If_Key_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary
{
- // Arrange
- var metadata = new Dictionary
{
- {
- "boolKey", true
- }
- };
- var flagMetadata = new FlagMetadata(metadata);
+ "boolKey", true
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
- // Act
- var result = flagMetadata.GetBool("boolKey");
+ // Act
+ var result = flagMetadata.GetBool("boolKey");
- // Assert
- Assert.True(result);
- }
+ // Assert
+ Assert.True(result);
+ }
- [Fact]
- public void GetBool_Should_Throw_Value_Is_Invalid()
+ [Fact]
+ public void GetBool_Should_Throw_Value_Is_Invalid()
+ {
+ // Arrange
+ var metadata = new Dictionary
{
- // Arrange
- var metadata = new Dictionary
{
- {
- "wrongKey", "11a"
- }
- };
- var flagMetadata = new FlagMetadata(metadata);
-
- // Act
- var exception = Assert.Throws(() => flagMetadata.GetBool("wrongKey"));
-
- // Assert
- Assert.NotNull(exception);
- Assert.Equal("Cannot cast System.String to System.Boolean", exception.Message);
- }
-
- [Fact]
- public void GetInt_Should_Return_Null_If_Key_Not_Found()
- {
- // Arrange
- var flagMetadata = new FlagMetadata();
+ "wrongKey", "11a"
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var exception = Assert.Throws(() => flagMetadata.GetBool("wrongKey"));
+
+ // Assert
+ Assert.NotNull(exception);
+ Assert.Equal("Cannot cast System.String to System.Boolean", exception.Message);
+ }
+
+ [Fact]
+ public void GetInt_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var flagMetadata = new FlagMetadata();
- // Act
- var result = flagMetadata.GetInt("nonexistentKey");
+ // Act
+ var result = flagMetadata.GetInt("nonexistentKey");
- // Assert
- Assert.Null(result);
- }
+ // Assert
+ Assert.Null(result);
+ }
- [Fact]
- public void GetInt_Should_Return_Value_If_Key_Found()
+ [Fact]
+ public void GetInt_Should_Return_Value_If_Key_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary
{
- // Arrange
- var metadata = new Dictionary
{
- {
- "intKey", 1
- }
- };
- var flagMetadata = new FlagMetadata(metadata);
-
- // Act
- var result = flagMetadata.GetInt("intKey");
-
- // Assert
- Assert.NotNull(result);
- Assert.Equal(1, result);
- }
-
- [Fact]
- public void GetInt_Should_Throw_Value_Is_Invalid()
+ "intKey", 1
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetInt("intKey");
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(1, result);
+ }
+
+ [Fact]
+ public void GetInt_Should_Throw_Value_Is_Invalid()
+ {
+ // Arrange
+ var metadata = new Dictionary
{
- // Arrange
- var metadata = new Dictionary
{
- {
- "wrongKey", "11a"
- }
- };
- var flagMetadata = new FlagMetadata(metadata);
-
- // Act
- var exception = Assert.Throws(() => flagMetadata.GetInt("wrongKey"));
-
- // Assert
- Assert.NotNull(exception);
- Assert.Equal("Cannot cast System.String to System.Int32", exception.Message);
- }
-
- [Fact]
- public void GetDouble_Should_Return_Null_If_Key_Not_Found()
- {
- // Arrange
- var flagMetadata = new FlagMetadata();
+ "wrongKey", "11a"
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var exception = Assert.Throws(() => flagMetadata.GetInt("wrongKey"));
- // Act
- var result = flagMetadata.GetDouble("nonexistentKey");
+ // Assert
+ Assert.NotNull(exception);
+ Assert.Equal("Cannot cast System.String to System.Int32", exception.Message);
+ }
+
+ [Fact]
+ public void GetDouble_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var flagMetadata = new FlagMetadata();
- // Assert
- Assert.Null(result);
- }
+ // Act
+ var result = flagMetadata.GetDouble("nonexistentKey");
- [Fact]
- public void GetDouble_Should_Return_Value_If_Key_Found()
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetDouble_Should_Return_Value_If_Key_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary
{
- // Arrange
- var metadata = new Dictionary
{
- {
- "doubleKey", 1.2
- }
- };
- var flagMetadata = new FlagMetadata(metadata);
-
- // Act
- var result = flagMetadata.GetDouble("doubleKey");
-
- // Assert
- Assert.NotNull(result);
- Assert.Equal(1.2, result);
- }
-
- [Fact]
- public void GetDouble_Should_Throw_Value_Is_Invalid()
+ "doubleKey", 1.2
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetDouble("doubleKey");
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal(1.2, result);
+ }
+
+ [Fact]
+ public void GetDouble_Should_Throw_Value_Is_Invalid()
+ {
+ // Arrange
+ var metadata = new Dictionary
{
- // Arrange
- var metadata = new Dictionary
{
- {
- "wrongKey", "11a"
- }
- };
- var flagMetadata = new FlagMetadata(metadata);
-
- // Act
- var exception = Assert.Throws(() => flagMetadata.GetDouble("wrongKey"));
-
- // Assert
- Assert.NotNull(exception);
- Assert.Equal("Cannot cast System.String to System.Double", exception.Message);
- }
-
- [Fact]
- public void GetString_Should_Return_Null_If_Key_Not_Found()
- {
- // Arrange
- var flagMetadata = new FlagMetadata();
+ "wrongKey", "11a"
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
- // Act
- var result = flagMetadata.GetString("nonexistentKey");
+ // Act
+ var exception = Assert.Throws(() => flagMetadata.GetDouble("wrongKey"));
- // Assert
- Assert.Null(result);
- }
+ // Assert
+ Assert.NotNull(exception);
+ Assert.Equal("Cannot cast System.String to System.Double", exception.Message);
+ }
+
+ [Fact]
+ public void GetString_Should_Return_Null_If_Key_Not_Found()
+ {
+ // Arrange
+ var flagMetadata = new FlagMetadata();
- [Fact]
- public void GetString_Should_Return_Value_If_Key_Found()
+ // Act
+ var result = flagMetadata.GetString("nonexistentKey");
+
+ // Assert
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void GetString_Should_Return_Value_If_Key_Found()
+ {
+ // Arrange
+ var metadata = new Dictionary
{
- // Arrange
- var metadata = new Dictionary
{
- {
- "stringKey", "11"
- }
- };
- var flagMetadata = new FlagMetadata(metadata);
-
- // Act
- var result = flagMetadata.GetString("stringKey");
-
- // Assert
- Assert.NotNull(result);
- Assert.Equal("11", result);
- }
-
- [Fact]
- public void GetString_Should_Throw_Value_Is_Invalid()
+ "stringKey", "11"
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var result = flagMetadata.GetString("stringKey");
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("11", result);
+ }
+
+ [Fact]
+ public void GetString_Should_Throw_Value_Is_Invalid()
+ {
+ // Arrange
+ var metadata = new Dictionary
{
- // Arrange
- var metadata = new Dictionary
{
- {
- "wrongKey", new object()
- }
- };
- var flagMetadata = new FlagMetadata(metadata);
-
- // Act
- var exception = Assert.Throws(() => flagMetadata.GetString("wrongKey"));
-
- // Assert
- Assert.NotNull(exception);
- Assert.Equal("Cannot cast System.Object to System.String", exception.Message);
- }
+ "wrongKey", new object()
+ }
+ };
+ var flagMetadata = new FlagMetadata(metadata);
+
+ // Act
+ var exception = Assert.Throws(() => flagMetadata.GetString("wrongKey"));
+
+ // Assert
+ Assert.NotNull(exception);
+ Assert.Equal("Cannot cast System.Object to System.String", exception.Message);
}
}
From cc910375fb0c3c86726a6b025993833ad242ada0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Wed, 31 Jan 2024 16:06:54 +0000
Subject: [PATCH 22/30] Refactor FlagMetadata class to inherit from
BaseMetadata
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/BaseMetadata.cs | 57 +++++++++++++++++++++++++++
src/OpenFeature/Model/FlagMetadata.cs | 46 ++-------------------
2 files changed, 60 insertions(+), 43 deletions(-)
create mode 100644 src/OpenFeature/Model/BaseMetadata.cs
diff --git a/src/OpenFeature/Model/BaseMetadata.cs b/src/OpenFeature/Model/BaseMetadata.cs
new file mode 100644
index 00000000..1b27494a
--- /dev/null
+++ b/src/OpenFeature/Model/BaseMetadata.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+
+#nullable enable
+namespace OpenFeature.Model;
+
+public abstract class BaseMetadata
+{
+ private readonly ImmutableDictionary _metadata;
+
+ internal BaseMetadata(Dictionary metadata)
+ {
+ this._metadata = metadata.ToImmutableDictionary();
+ }
+
+ internal BaseMetadata() : this([])
+ {
+ }
+
+ public virtual bool? GetBool(string key)
+ {
+ return this.GetValue(key);
+ }
+
+ public virtual int? GetInt(string key)
+ {
+ return this.GetValue(key);
+ }
+
+ public virtual double? GetDouble(string key)
+ {
+ return this.GetValue(key);
+ }
+
+ public virtual string? GetString(string key)
+ {
+ var hasValue = this._metadata.TryGetValue(key, out var value);
+ if (!hasValue)
+ {
+ return null;
+ }
+
+ return value as string ?? throw new InvalidCastException($"Cannot cast {value?.GetType()} to {typeof(string)}");
+ }
+
+ private T? GetValue(string key) where T : struct
+ {
+ var hasValue = this._metadata.TryGetValue(key, out var value);
+ if (!hasValue)
+ {
+ return null;
+ }
+
+ return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType()} to {typeof(T)}");
+ }
+}
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index 039829f2..d3dfe76b 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -5,53 +5,13 @@
#nullable enable
namespace OpenFeature.Model;
-public sealed class FlagMetadata
+public sealed class FlagMetadata : BaseMetadata
{
- private readonly ImmutableDictionary _metadata;
-
- public FlagMetadata(Dictionary metadata)
- {
- this._metadata = metadata.ToImmutableDictionary();
- }
-
- public FlagMetadata() : this([])
- {
- }
-
- public bool? GetBool(string key)
- {
- return this.GetValue(key);
- }
-
- public int? GetInt(string key)
+ public FlagMetadata()
{
- return this.GetValue(key);
}
- public double? GetDouble(string key)
+ public FlagMetadata(Dictionary metadata) : base(metadata)
{
- return this.GetValue(key);
- }
-
- public string? GetString(string key)
- {
- var hasValue = this._metadata.TryGetValue(key, out var value);
- if (!hasValue)
- {
- return null;
- }
-
- return value as string ?? throw new InvalidCastException($"Cannot cast {value?.GetType()} to {typeof(string)}");
- }
-
- private T? GetValue(string key) where T : struct
- {
- var hasValue = this._metadata.TryGetValue(key, out var value);
- if (!hasValue)
- {
- return null;
- }
-
- return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType()} to {typeof(T)}");
}
}
From 8a6859ee6d415ddfde7e6fac45478f4f5102728e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Wed, 31 Jan 2024 16:26:21 +0000
Subject: [PATCH 23/30] Adding documentation.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/BaseMetadata.cs | 24 ++++++++++++++++++++++++
src/OpenFeature/Model/FlagMetadata.cs | 11 +++++++++++
2 files changed, 35 insertions(+)
diff --git a/src/OpenFeature/Model/BaseMetadata.cs b/src/OpenFeature/Model/BaseMetadata.cs
index 1b27494a..039253d2 100644
--- a/src/OpenFeature/Model/BaseMetadata.cs
+++ b/src/OpenFeature/Model/BaseMetadata.cs
@@ -5,6 +5,9 @@
#nullable enable
namespace OpenFeature.Model;
+///
+/// Represents the base class for metadata objects.
+///
public abstract class BaseMetadata
{
private readonly ImmutableDictionary _metadata;
@@ -18,21 +21,42 @@ internal BaseMetadata() : this([])
{
}
+ ///
+ /// Gets the boolean value associated with the specified key.
+ ///
+ /// The key of the value to retrieve.
+ /// The boolean value associated with the key, or null if the key is not found.
public virtual bool? GetBool(string key)
{
return this.GetValue(key);
}
+ ///
+ /// Gets the integer value associated with the specified key.
+ ///
+ /// The key of the value to retrieve.
+ /// The integer value associated with the key, or null if the key is not found.
public virtual int? GetInt(string key)
{
return this.GetValue(key);
}
+ ///
+ /// Gets the double value associated with the specified key.
+ ///
+ /// The key of the value to retrieve.
+ /// The double value associated with the key, or null if the key is not found.
public virtual double? GetDouble(string key)
{
return this.GetValue(key);
}
+ ///
+ /// Gets the string value associated with the specified key.
+ ///
+ /// The key of the value to retrieve.
+ /// The string value associated with the key, or null if the key is not found.
+ /// Thrown when the value cannot be cast to a string.
public virtual string? GetString(string key)
{
var hasValue = this._metadata.TryGetValue(key, out var value);
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index d3dfe76b..9fc8d496 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -5,12 +5,23 @@
#nullable enable
namespace OpenFeature.Model;
+///
+/// Represents the metadata associated with a feature flag.
+///
public sealed class FlagMetadata : BaseMetadata
{
+ ///
+ /// Constructor for the class.
+ ///
public FlagMetadata()
{
}
+
+ ///
+ /// Constructor for the class.
+ ///
+ /// The dictionary containing the metadata.
public FlagMetadata(Dictionary metadata) : base(metadata)
{
}
From 5a2dcc9c3544c379f27f786dd9f4b6e2b66ab61f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Fri, 2 Feb 2024 14:28:21 +0000
Subject: [PATCH 24/30] Adding reference.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/ProviderEvents.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/OpenFeature/Model/ProviderEvents.cs b/src/OpenFeature/Model/ProviderEvents.cs
index da68aef4..ca7c7e1a 100644
--- a/src/OpenFeature/Model/ProviderEvents.cs
+++ b/src/OpenFeature/Model/ProviderEvents.cs
@@ -36,6 +36,7 @@ public class ProviderEventPayload
///
/// Metadata information for the event.
///
+ // TODO: This needs to be changed to a EventMetadata object
public Dictionary EventMetadata { get; set; }
}
}
From c59c30e7bf95a3ad4d65dd2c76e3ee58ac5d9e04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Fri, 2 Feb 2024 14:32:04 +0000
Subject: [PATCH 25/30] Adding reference to the spec.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index 9fc8d496..fdab3c07 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -8,6 +8,7 @@ namespace OpenFeature.Model;
///
/// Represents the metadata associated with a feature flag.
///
+///
public sealed class FlagMetadata : BaseMetadata
{
///
From cdb8a86072efee176855c2531f8b239a5df13588 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Fri, 2 Feb 2024 14:43:52 +0000
Subject: [PATCH 26/30] Small fix.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/FlagMetadata.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs
index fdab3c07..db666b7f 100644
--- a/src/OpenFeature/Model/FlagMetadata.cs
+++ b/src/OpenFeature/Model/FlagMetadata.cs
@@ -14,11 +14,10 @@ public sealed class FlagMetadata : BaseMetadata
///
/// Constructor for the class.
///
- public FlagMetadata()
+ public FlagMetadata() : this([])
{
}
-
///
/// Constructor for the class.
///
From c1ae3324612d1f23ba45401585c5fe4dd15b7cb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Fri, 2 Feb 2024 14:55:37 +0000
Subject: [PATCH 27/30] Added some conditions.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/BaseMetadata.cs | 5 ++---
test/OpenFeature.Tests/FlagMetadataTest.cs | 25 ++++++++++++++++++++++
2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/src/OpenFeature/Model/BaseMetadata.cs b/src/OpenFeature/Model/BaseMetadata.cs
index 039253d2..dd4653b2 100644
--- a/src/OpenFeature/Model/BaseMetadata.cs
+++ b/src/OpenFeature/Model/BaseMetadata.cs
@@ -56,7 +56,6 @@ internal BaseMetadata() : this([])
///
/// The key of the value to retrieve.
/// The string value associated with the key, or null if the key is not found.
- /// Thrown when the value cannot be cast to a string.
public virtual string? GetString(string key)
{
var hasValue = this._metadata.TryGetValue(key, out var value);
@@ -65,7 +64,7 @@ internal BaseMetadata() : this([])
return null;
}
- return value as string ?? throw new InvalidCastException($"Cannot cast {value?.GetType()} to {typeof(string)}");
+ return value as string ?? null;
}
private T? GetValue(string key) where T : struct
@@ -76,6 +75,6 @@ internal BaseMetadata() : this([])
return null;
}
- return value is T tValue ? tValue : throw new InvalidCastException($"Cannot cast {value?.GetType()} to {typeof(T)}");
+ return value is T tValue ? tValue : null;
}
}
diff --git a/test/OpenFeature.Tests/FlagMetadataTest.cs b/test/OpenFeature.Tests/FlagMetadataTest.cs
index 5c34d2e2..78c41c7c 100644
--- a/test/OpenFeature.Tests/FlagMetadataTest.cs
+++ b/test/OpenFeature.Tests/FlagMetadataTest.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using OpenFeature.Model;
+using OpenFeature.Tests.Internal;
using Xunit;
#nullable enable
@@ -9,6 +10,8 @@ namespace OpenFeature.Tests;
public class FlagMetadataTest
{
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetBool_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
@@ -22,6 +25,8 @@ public void GetBool_Should_Return_Null_If_Key_Not_Found()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetBool_Should_Return_Value_If_Key_Found()
{
// Arrange
@@ -41,6 +46,8 @@ public void GetBool_Should_Return_Value_If_Key_Found()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetBool_Should_Throw_Value_Is_Invalid()
{
// Arrange
@@ -61,6 +68,8 @@ public void GetBool_Should_Throw_Value_Is_Invalid()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetInt_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
@@ -74,6 +83,8 @@ public void GetInt_Should_Return_Null_If_Key_Not_Found()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetInt_Should_Return_Value_If_Key_Found()
{
// Arrange
@@ -94,6 +105,8 @@ public void GetInt_Should_Return_Value_If_Key_Found()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetInt_Should_Throw_Value_Is_Invalid()
{
// Arrange
@@ -114,6 +127,8 @@ public void GetInt_Should_Throw_Value_Is_Invalid()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetDouble_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
@@ -127,6 +142,8 @@ public void GetDouble_Should_Return_Null_If_Key_Not_Found()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetDouble_Should_Return_Value_If_Key_Found()
{
// Arrange
@@ -147,6 +164,8 @@ public void GetDouble_Should_Return_Value_If_Key_Found()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetDouble_Should_Throw_Value_Is_Invalid()
{
// Arrange
@@ -167,6 +186,8 @@ public void GetDouble_Should_Throw_Value_Is_Invalid()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetString_Should_Return_Null_If_Key_Not_Found()
{
// Arrange
@@ -180,6 +201,8 @@ public void GetString_Should_Return_Null_If_Key_Not_Found()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetString_Should_Return_Value_If_Key_Found()
{
// Arrange
@@ -200,6 +223,8 @@ public void GetString_Should_Return_Value_If_Key_Found()
}
[Fact]
+ [Specification("1.4.14",
+ "If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
public void GetString_Should_Throw_Value_Is_Invalid()
{
// Arrange
From c14361ffc568f6f294ad6e74e3c07ed576c8c31b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Fri, 2 Feb 2024 14:56:14 +0000
Subject: [PATCH 28/30] Adding more specs.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
test/OpenFeature.Tests/FlagMetadataTest.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/test/OpenFeature.Tests/FlagMetadataTest.cs b/test/OpenFeature.Tests/FlagMetadataTest.cs
index 78c41c7c..1989e8ef 100644
--- a/test/OpenFeature.Tests/FlagMetadataTest.cs
+++ b/test/OpenFeature.Tests/FlagMetadataTest.cs
@@ -27,6 +27,7 @@ public void GetBool_Should_Return_Null_If_Key_Not_Found()
[Fact]
[Specification("1.4.14",
"If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
+ [Specification("1.4.14.1", "Condition: `Flag metadata` MUST be immutable.")]
public void GetBool_Should_Return_Value_If_Key_Found()
{
// Arrange
@@ -85,6 +86,7 @@ public void GetInt_Should_Return_Null_If_Key_Not_Found()
[Fact]
[Specification("1.4.14",
"If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
+ [Specification("1.4.14.1", "Condition: `Flag metadata` MUST be immutable.")]
public void GetInt_Should_Return_Value_If_Key_Found()
{
// Arrange
@@ -144,6 +146,7 @@ public void GetDouble_Should_Return_Null_If_Key_Not_Found()
[Fact]
[Specification("1.4.14",
"If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
+ [Specification("1.4.14.1", "Condition: `Flag metadata` MUST be immutable.")]
public void GetDouble_Should_Return_Value_If_Key_Found()
{
// Arrange
@@ -203,6 +206,7 @@ public void GetString_Should_Return_Null_If_Key_Not_Found()
[Fact]
[Specification("1.4.14",
"If the `flag metadata` field in the `flag resolution` structure returned by the configured `provider` is set, the `evaluation details` structure's `flag metadata` field MUST contain that value. Otherwise, it MUST contain an empty record.")]
+ [Specification("1.4.14.1", "Condition: `Flag metadata` MUST be immutable.")]
public void GetString_Should_Return_Value_If_Key_Found()
{
// Arrange
From 2b2a64f2633cd4cbdba449443fc88a77df36cc47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Fri, 2 Feb 2024 15:23:41 +0000
Subject: [PATCH 29/30] Fixing unit tests.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
test/OpenFeature.Tests/FlagMetadataTest.cs | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/test/OpenFeature.Tests/FlagMetadataTest.cs b/test/OpenFeature.Tests/FlagMetadataTest.cs
index 1989e8ef..88d248de 100644
--- a/test/OpenFeature.Tests/FlagMetadataTest.cs
+++ b/test/OpenFeature.Tests/FlagMetadataTest.cs
@@ -61,11 +61,10 @@ public void GetBool_Should_Throw_Value_Is_Invalid()
var flagMetadata = new FlagMetadata(metadata);
// Act
- var exception = Assert.Throws(() => flagMetadata.GetBool("wrongKey"));
+ var result = flagMetadata.GetBool("wrongKey");
// Assert
- Assert.NotNull(exception);
- Assert.Equal("Cannot cast System.String to System.Boolean", exception.Message);
+ Assert.Null(result);
}
[Fact]
@@ -121,11 +120,10 @@ public void GetInt_Should_Throw_Value_Is_Invalid()
var flagMetadata = new FlagMetadata(metadata);
// Act
- var exception = Assert.Throws(() => flagMetadata.GetInt("wrongKey"));
+ var result = flagMetadata.GetInt("wrongKey");
// Assert
- Assert.NotNull(exception);
- Assert.Equal("Cannot cast System.String to System.Int32", exception.Message);
+ Assert.Null(result);
}
[Fact]
@@ -181,11 +179,10 @@ public void GetDouble_Should_Throw_Value_Is_Invalid()
var flagMetadata = new FlagMetadata(metadata);
// Act
- var exception = Assert.Throws(() => flagMetadata.GetDouble("wrongKey"));
+ var result = flagMetadata.GetDouble("wrongKey");
// Assert
- Assert.NotNull(exception);
- Assert.Equal("Cannot cast System.String to System.Double", exception.Message);
+ Assert.Null(result);
}
[Fact]
@@ -241,10 +238,9 @@ public void GetString_Should_Throw_Value_Is_Invalid()
var flagMetadata = new FlagMetadata(metadata);
// Act
- var exception = Assert.Throws(() => flagMetadata.GetString("wrongKey"));
+ var result = flagMetadata.GetString("wrongKey");
// Assert
- Assert.NotNull(exception);
- Assert.Equal("Cannot cast System.Object to System.String", exception.Message);
+ Assert.Null(result);
}
}
From 2761bff2d91571063bb132a644145bc2ece0c920 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?=
<2493377+askpt@users.noreply.github.com>
Date: Mon, 12 Feb 2024 08:13:00 +0000
Subject: [PATCH 30/30] Remove default constructor from BaseMetadata class
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
---
src/OpenFeature/Model/BaseMetadata.cs | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/OpenFeature/Model/BaseMetadata.cs b/src/OpenFeature/Model/BaseMetadata.cs
index dd4653b2..1e1fa211 100644
--- a/src/OpenFeature/Model/BaseMetadata.cs
+++ b/src/OpenFeature/Model/BaseMetadata.cs
@@ -17,10 +17,6 @@ internal BaseMetadata(Dictionary metadata)
this._metadata = metadata.ToImmutableDictionary();
}
- internal BaseMetadata() : this([])
- {
- }
-
///
/// Gets the boolean value associated with the specified key.
///