Skip to content

Commit

Permalink
Feature-variationid, Case Sensitive support, userID can be null (#13)
Browse files Browse the repository at this point in the history
* implement 'variation id' feature

* add unit and integration test for variationid

* RELEASE v5.3

Co-authored-by: andrew-cat <[email protected]>
  • Loading branch information
endret and andrew-cat authored Sep 1, 2020
1 parent 45d5acd commit 00c467d
Show file tree
Hide file tree
Showing 19 changed files with 817 additions and 85 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ ConfigCat is a <a href="https://configcat.com" target="_blank">hosted feature fl

[![Build status](https://ci.appveyor.com/api/projects/status/3kygp783vc2uv9xr?svg=true)](https://ci.appveyor.com/project/ConfigCat/net-sdk) [![NuGet Version](https://buildstats.info/nuget/ConfigCat.Client)](https://www.nuget.org/packages/ConfigCat.Client/)
[![codecov](https://codecov.io/gh/configcat/.net-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/configcat/.net-sdk)
![License](https://img.shields.io/github/license/configcat/.net-sdk.svg)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/configcat/.net-sdk/blob/master/LICENSE)

## Getting Started

Expand Down
83 changes: 83 additions & 0 deletions src/ConfigCat.Client.Tests/BasicConfigCatClientIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,88 @@ private static async Task GetValueAsyncAndAssert(IConfigCatClient client, string
Assert.AreEqual(expectedValue, actual);
Assert.AreNotEqual(defaultValue, actual);
}

[TestMethod]
public void GetVariationId()
{
IConfigCatClient manualPollClient = ConfigCatClientBuilder
.Initialize(SDKKEY)
.WithLogger(consoleLogger)
.WithManualPoll()
.Create();

manualPollClient.ForceRefresh();
var actual = manualPollClient.GetVariationId("stringDefaultCat", "default");

Assert.AreEqual("7a0be518", actual);
}

[TestMethod]
public async Task GetVariationIdAsync()
{
IConfigCatClient manualPollClient = ConfigCatClientBuilder
.Initialize(SDKKEY)
.WithLogger(consoleLogger)
.WithManualPoll()
.Create();

await manualPollClient.ForceRefreshAsync();

var actual = await manualPollClient.GetVariationIdAsync("stringDefaultCat", "default");

Assert.AreEqual("7a0be518", actual);
}

[TestMethod]
public void GetAllVariationId()
{
// Arrange

const string expectedJsonString = "[\"7a0be518\",\"83372510\",\"2459598d\",\"ce564c3a\",\"44ab483a\",\"d227b334\",\"93f5a1c0\",\"bb66b1f3\",\"09513143\",\"489a16d2\",\"607147d5\",\"11634414\",\"faadbf54\",\"5af8acc7\",\"183ee713\",\"baff2362\"]";

var expectedValue = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(expectedJsonString);

IConfigCatClient manualPollClient = ConfigCatClientBuilder
.Initialize(SDKKEY)
.WithLogger(consoleLogger)
.WithManualPoll()
.Create();

manualPollClient.ForceRefresh();

// Act

var actual = manualPollClient.GetAllVariationId(new User("[email protected]"));

// Assert
Assert.AreEqual(16, expectedValue.Length);
CollectionAssert.AreEquivalent(expectedValue, actual.ToArray());
}

[TestMethod]
public async Task GetAllVariationIdAsync()
{
// Arrange

const string expectedJsonString = "[\"7a0be518\",\"83372510\",\"2459598d\",\"ce564c3a\",\"44ab483a\",\"d227b334\",\"93f5a1c0\",\"bb66b1f3\",\"09513143\",\"489a16d2\",\"607147d5\",\"11634414\",\"faadbf54\",\"5af8acc7\",\"183ee713\",\"baff2362\"]";

var expectedValue = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(expectedJsonString);

IConfigCatClient manualPollClient = ConfigCatClientBuilder
.Initialize(SDKKEY)
.WithLogger(consoleLogger)
.WithManualPoll()
.Create();

await manualPollClient.ForceRefreshAsync();

// Act

var actual = await manualPollClient.GetAllVariationIdAsync(new User("[email protected]"));

// Assert
Assert.AreEqual(16, expectedValue.Length);
CollectionAssert.AreEquivalent(expectedValue, actual.ToArray());
}
}
}
6 changes: 6 additions & 0 deletions src/ConfigCat.Client.Tests/ConfigCat.Client.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<None Update="data\sample_v4.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="data\sample_variationid_v4.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="data\testmatrix.csv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand All @@ -56,6 +59,9 @@
<None Update="data\testmatrix_sensitive.csv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="data\testmatrix_variationid.csv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
150 changes: 150 additions & 0 deletions src/ConfigCat.Client.Tests/ConfigCatClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,5 +345,155 @@ public void GetAllKeys_DeserializeFailed_ShouldReturnsWithEmptyArray()
Assert.AreEqual(0, actualKeys.Count());
loggerMock.Verify(m => m.Warning(It.IsAny<string>()), Times.Once);
}

[TestMethod]
public void GetVariationId_EvaluateServiceThrowException_ShouldReturnDefaultValue()
{
// Arrange

const string defaultValue = "Victory for the Firstborn!";

evaluateMock
.Setup(m => m.EvaluateVariationId(It.IsAny<ProjectConfig>(), It.IsAny<string>(), defaultValue, null))
.Throws<Exception>();

var client = new ConfigCatClient(configService.Object, loggerMock.Object, evaluateMock.Object, deserializerMock.Object);

// Act

var actual = client.GetVariationId(null, defaultValue);

// Assert

Assert.AreEqual(defaultValue, actual);
}

[TestMethod]
public async Task GetVariationIdAsync_EvaluateServiceThrowException_ShouldReturnDefaultValue()
{
// Arrange

const string defaultValue = "Victory for the Firstborn!";

evaluateMock
.Setup(m => m.EvaluateVariationId(It.IsAny<ProjectConfig>(), It.IsAny<string>(), defaultValue, null))
.Throws<Exception>();

var client = new ConfigCatClient(configService.Object, loggerMock.Object, evaluateMock.Object, deserializerMock.Object);

// Act

var actual = await client.GetVariationIdAsync(null, defaultValue);

// Assert

Assert.AreEqual(defaultValue, actual);
}

[TestMethod]
public void GetVariationId_DeserializeFailed_ShouldReturnsWithEmptyArray()
{
// Arrange

var configServiceMock = new Mock<IConfigService>();
var loggerMock = new Mock<ILogger>();
var evaluatorMock = new Mock<IRolloutEvaluator>();
var configDeserializerMock = new Mock<IConfigDeserializer>();

configServiceMock.Setup(m => m.GetConfigAsync()).ReturnsAsync(ProjectConfig.Empty);
IDictionary<string, Setting> o = new Dictionary<string, Setting>();
configDeserializerMock
.Setup(m => m.TryDeserialize(It.IsAny<ProjectConfig>(), out o))
.Returns(false);

IConfigCatClient instance = new ConfigCatClient(
configServiceMock.Object,
loggerMock.Object,
evaluatorMock.Object,
configDeserializerMock.Object);

// Act

var actual = instance.GetAllVariationId();

// Assert

Assert.IsNotNull(actual);
Assert.AreEqual(0, actual.Count());
loggerMock.Verify(m => m.Warning(It.IsAny<string>()), Times.Once);
}

[TestMethod]
public async Task GetVariationIdAsync_DeserializeFailed_ShouldReturnsWithEmptyArray()
{
// Arrange

var configServiceMock = new Mock<IConfigService>();
var loggerMock = new Mock<ILogger>();
var evaluatorMock = new Mock<IRolloutEvaluator>();
var configDeserializerMock = new Mock<IConfigDeserializer>();

configServiceMock.Setup(m => m.GetConfigAsync()).ReturnsAsync(ProjectConfig.Empty);
IDictionary<string, Setting> o = new Dictionary<string, Setting>();
configDeserializerMock
.Setup(m => m.TryDeserialize(It.IsAny<ProjectConfig>(), out o))
.Returns(false);

IConfigCatClient instance = new ConfigCatClient(
configServiceMock.Object,
loggerMock.Object,
evaluatorMock.Object,
configDeserializerMock.Object);

// Act

var actual = await instance.GetAllVariationIdAsync();

// Assert

Assert.IsNotNull(actual);
Assert.AreEqual(0, actual.Count());
loggerMock.Verify(m => m.Warning(It.IsAny<string>()), Times.Once);
}

[TestMethod]
public void GetAllVariationId_ConfigServiceThrowException_ShouldReturnEmptyEnumerable()
{
// Arrange

configService
.Setup(m => m.GetConfigAsync())
.Throws<Exception>();

var client = new ConfigCatClient(configService.Object, loggerMock.Object, evaluateMock.Object, deserializerMock.Object);

// Act

var actual = client.GetAllVariationId(null);

// Assert

Assert.AreEqual(Enumerable.Empty<string>(), actual);
}

[TestMethod]
public async Task GetAllVariationIdAsync_ConfigServiceThrowException_ShouldReturnEmptyEnumerable()
{
// Arrange

configService
.Setup(m => m.GetConfigAsync())
.Throws<Exception>();

var client = new ConfigCatClient(configService.Object, loggerMock.Object, evaluateMock.Object, deserializerMock.Object);

// Act

var actual = await client.GetAllVariationIdAsync(null);

// Assert

Assert.AreEqual(Enumerable.Empty<string>(), actual);
}
}
}
3 changes: 2 additions & 1 deletion src/ConfigCat.Client.Tests/ConfigEvaluatorTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ public async Task MatrixTest(Action<string, string, User> assertation)
}
}

[TestCategory("MatrixTests")]
[TestMethod]
public async Task GetValue_MatrixTests()
public async Task Run_MatrixTests()
{
await MatrixTest(AssertValue);
}
Expand Down
74 changes: 73 additions & 1 deletion src/ConfigCat.Client.Tests/ConfigServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public async Task AutoPollConfigService_RefreshConfigAsync_ShouldOnceInvokeCache
}

[TestMethod]
public async Task AutoPollConfigService_RefreshConfigAsync_ConfigCahged_ShouldRaiseEvent()
public async Task AutoPollConfigService_RefreshConfigAsync_ConfigChanged_ShouldRaiseEvent()
{
// Arrange

Expand Down Expand Up @@ -281,6 +281,78 @@ public async Task AutoPollConfigService_RefreshConfigAsync_ConfigCahged_ShouldRa
Assert.AreEqual(1, eventChanged);
}

[TestMethod]
public void AutoPollConfigService_Dispose_ShouldStopTimer()
{
// Arrange

long counter = 0;
long e1, e2;

this.cacheMock
.Setup(m => m.Get())
.Returns(cachedPc);

this.fetcherMock
.Setup(m => m.Fetch(cachedPc))
.Callback(() => Interlocked.Increment(ref counter))
.Returns(Task.FromResult(cachedPc));

var service = new AutoPollConfigService(
fetcherMock.Object,
cacheMock.Object,
TimeSpan.FromSeconds(0.2d),
TimeSpan.Zero,
loggerMock.Object,
true);

// Act
Thread.Sleep(TimeSpan.FromSeconds(1));
e1 = Interlocked.Read(ref counter);
service.Dispose();

// Assert

Thread.Sleep(TimeSpan.FromSeconds(2));
e2 = Interlocked.Read(ref counter);
Console.WriteLine(e2 - e1);
Assert.IsTrue(e2 - e1 <= 1);
}

[TestMethod]
public void AutoPollConfigService_WithoutTimer_InvokeDispose_ShouldDisposeService()
{
// Arrange

long counter = -1;
long e1;

this.cacheMock
.Setup(m => m.Get())
.Returns(cachedPc);

this.fetcherMock
.Setup(m => m.Fetch(cachedPc))
.Callback(() => Interlocked.Increment(ref counter))
.Returns(Task.FromResult(cachedPc));

var service = new AutoPollConfigService(
fetcherMock.Object,
cacheMock.Object,
TimeSpan.FromSeconds(0.2d),
TimeSpan.Zero,
loggerMock.Object,
false);

// Act
Thread.Sleep(TimeSpan.FromSeconds(1));
e1 = Interlocked.Read(ref counter);
service.Dispose();

// Assert
Assert.AreEqual(-1, e1);
}

[TestMethod]
public async Task ManualPollConfigService_GetConfigAsync_ShouldInvokeCacheGet()
{
Expand Down
Loading

0 comments on commit 00c467d

Please sign in to comment.