Skip to content

Commit

Permalink
feat: Implement cache lookup value in emulator (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mielek authored Jan 10, 2025
1 parent 61cee0a commit fbfe33c
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/Testing/Document/MockCacheLookupValueProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@ internal Setup(

public void WithCallback(Action<GatewayContext, CacheLookupValueConfig> callback) =>
_handler.CallbackSetup.Add((_predicate, callback).ToTuple());

public void WithValue(object value) => _handler.ValueSetup.Add((_predicate, value).ToTuple());
}
}
3 changes: 3 additions & 0 deletions src/Testing/Document/TestDocumentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ public static MockPoliciesProvider<IOnErrorContext> SetupOnError(this TestDocume

public static CertificateStore SetupCertificateStore(this TestDocument document) =>
document.Context.CertificateStore;

public static CacheStore SetupCacheStore(this TestDocument document) =>
document.Context.CacheStore;
}
42 changes: 42 additions & 0 deletions src/Testing/Emulator/Data/CacheStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Data;

public class CacheStore
{
private readonly Dictionary<string, object> _internalCache = new();
private readonly Dictionary<string, object> _externalCache = new();

private bool _isExternalCacheSetup = false;

internal Dictionary<string, object>? GetCache(string type) =>
type switch
{
"internal" => _internalCache,
"external" => _isExternalCacheSetup ? _externalCache : null,
"prefer-external" => _isExternalCacheSetup ? _externalCache : _internalCache,
_ => throw new ArgumentException($"Unrecognized type {type}", nameof(type)),
};

public IReadOnlyDictionary<string, object> InternalCache => _internalCache;
public IReadOnlyDictionary<string, object> ExternalCache => _externalCache;

public CacheStore WithExternalCacheSetup(bool isSetup = true)
{
_isExternalCacheSetup = isSetup;
return this;
}

public CacheStore WithExternalCacheValue(string key, object value)
{
_externalCache.Add(key, value);
return this;
}

public CacheStore WithInternalCacheValue(string key, object value)
{
_internalCache.Add(key, value);
return this;
}
}
32 changes: 31 additions & 1 deletion src/Testing/Emulator/Policies/CacheLookupValueHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,40 @@ namespace Azure.ApiManagement.PolicyToolkit.Testing.Emulator.Policies;
]
internal class CacheLookupValueHandler : PolicyHandler<CacheLookupValueConfig>
{
public List<Tuple<
Func<GatewayContext, CacheLookupValueConfig, bool>,
object
>> ValueSetup { get; } = new();

public override string PolicyName => nameof(IInboundContext.CacheLookupValue);

protected override void Handle(GatewayContext context, CacheLookupValueConfig config)
{
throw new NotImplementedException();
var fromSetup = ValueSetup.Find(tuple => tuple.Item1(context, config))?.Item2;
if (fromSetup is not null)
{
context.Variables[config.VariableName] = fromSetup;
return;
}

var cachingType = config.CachingType ?? "prefer-external";


var store = context.CacheStore.GetCache(cachingType);
if (store is null)
{
return;
}

if (store.TryGetValue(config.Key, out var value))
{
context.Variables[config.VariableName] = value;
return;
}

if (config.DefaultValue is not null)
{
context.Variables[config.VariableName] = config.DefaultValue;
}
}
}
1 change: 1 addition & 0 deletions src/Testing/GatewayContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class GatewayContext : MockExpressionContext
internal readonly SectionContextProxy<IOutboundContext> OutboundProxy;
internal readonly SectionContextProxy<IOnErrorContext> OnErrorProxy;
internal readonly CertificateStore CertificateStore = new();
internal readonly CacheStore CacheStore = new();

public GatewayContext()
{
Expand Down
157 changes: 157 additions & 0 deletions test/Test.Testing/Emulator/Policies/CacheLookupValueTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Azure.ApiManagement.PolicyToolkit.Authoring;
using Azure.ApiManagement.PolicyToolkit.Testing;
using Azure.ApiManagement.PolicyToolkit.Testing.Document;

namespace Test.Emulator.Emulator.Policies;

[TestClass]
public class CacheLookupValueTests
{
class SimpleCacheLookupValuePreferExternal : IDocument
{
public void Inbound(IInboundContext context)
{
context.CacheLookupValue(new CacheLookupValueConfig()
{
Key = "key", VariableName = "variable", CachingType = "prefer-external"
});
}
}

class SimpleCacheLookupValueFromInternal : IDocument
{
public void Inbound(IInboundContext context)
{
context.CacheLookupValue(new CacheLookupValueConfig()
{
Key = "key", VariableName = "variable", CachingType = "internal"
});
}
}

class SimpleCacheLookupValueFromExternal : IDocument
{
public void Inbound(IInboundContext context)
{
context.CacheLookupValue(new CacheLookupValueConfig()
{
Key = "key", VariableName = "variable", CachingType = "external"
});
}
}

class SimpleCacheLookupValueWithDefaultValue : IDocument
{
public void Inbound(IInboundContext context)
{
context.CacheLookupValue(new CacheLookupValueConfig()
{
Key = "key", VariableName = "variable", DefaultValue = "test-value"
});
}
}

[TestMethod]
public void CacheLookupValue_Callback()
{
var test = new SimpleCacheLookupValuePreferExternal().AsTestDocument();
var executedCallback = false;
test.SetupInbound().CacheLookupValue().WithCallback((_, _) =>
{
executedCallback = true;
});

test.RunInbound();

executedCallback.Should().BeTrue();
}

[TestMethod]
public void CacheLookupValue_WithValueCallback()
{
var test = new SimpleCacheLookupValuePreferExternal().AsTestDocument();
test.SetupInbound().CacheLookupValue().WithValue("test");

test.RunInbound();

test.Context.Variables.Should().ContainKey("variable").WhoseValue.Should().Be("test");
}

[TestMethod]
public void CacheLookupValue_PreferExternal_SetupCacheStore_WithInternalValue()
{
var test = new SimpleCacheLookupValuePreferExternal().AsTestDocument();
test.SetupCacheStore().WithInternalCacheValue("key", "test");

test.RunInbound();

test.Context.Variables.Should().ContainKey("variable").WhoseValue.Should().Be("test");
}

[TestMethod]
public void CacheLookupValue_PreferExternal_SetupCacheStore_WithExternalCacheSetup()
{
var test = new SimpleCacheLookupValuePreferExternal().AsTestDocument();
test.SetupCacheStore().WithExternalCacheSetup().WithExternalCacheValue("key", "test");

test.RunInbound();

test.Context.Variables.Should().ContainKey("variable").WhoseValue.Should().Be("test");
}

[TestMethod]
public void CacheLookupValue_WithDefaultValue()
{
var test = new SimpleCacheLookupValueWithDefaultValue().AsTestDocument();

test.RunInbound();

test.Context.Variables.Should().ContainKey("variable").WhoseValue.Should().Be("test-value");
}

[TestMethod]
public void CacheLookupValue_InternalCache_WillNotFindValueFromExternalCache()
{
var test = new SimpleCacheLookupValueFromInternal().AsTestDocument();
test.SetupCacheStore().WithExternalCacheSetup().WithExternalCacheValue("key", "test");

test.RunInbound();

test.Context.Variables.Should().NotContainKey("variable");
}

[TestMethod]
public void CacheLookupValue_Internal_WillNotFindValueInInternalCache()
{
var test = new SimpleCacheLookupValueFromInternal().AsTestDocument();

test.RunInbound();

test.Context.Variables.Should().NotContainKey("variable");
}

[TestMethod]
public void CacheLookupValue_ExternalCache_WillNotFindValueInInternalCache()
{
var test = new SimpleCacheLookupValueFromExternal().AsTestDocument();
test.SetupCacheStore().WithInternalCacheValue("key", "test");

test.RunInbound();

test.Context.Variables.Should().NotContainKey("variable");
}

[TestMethod]
public void CacheLookupValue_ExternalCache_WillNotFindValue_WhenExternalCacheNotSetup()
{
var test = new SimpleCacheLookupValueFromExternal().AsTestDocument();
test.SetupCacheStore().WithExternalCacheValue("key", "test");

test.RunInbound();

test.Context.Variables.Should().NotContainKey("variable");
}
}

0 comments on commit fbfe33c

Please sign in to comment.