From 31bd60fcfc78fc152bb37ba9b9152f21788297cd Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 22 Jan 2023 09:04:30 -0500 Subject: [PATCH 1/2] LuaScript: use invariant regex on parameter parsing (fixes #2350) This changes the regex to use RegexOptions.CultureInvariant and adds an easy way to do tests like this in the future with `[Fact, TestCulture("tr-TR")]` for example, which will set and restore the culture for a specific test. --- .../ScriptParameterMapper.cs | 2 +- .../Helpers/Attributes.cs | 47 +++++++++++++++++++ .../ScriptingTests.cs | 23 +++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/StackExchange.Redis/ScriptParameterMapper.cs b/src/StackExchange.Redis/ScriptParameterMapper.cs index 2c0e76314..88be5d338 100644 --- a/src/StackExchange.Redis/ScriptParameterMapper.cs +++ b/src/StackExchange.Redis/ScriptParameterMapper.cs @@ -24,7 +24,7 @@ public ScriptParameters(RedisKey[] keys, RedisValue[] args) } } - private static readonly Regex ParameterExtractor = new Regex(@"@(? ([a-z]|_) ([a-z]|_|\d)*)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + private static readonly Regex ParameterExtractor = new Regex(@"@(? ([a-z]|_) ([a-z]|_|\d)*)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.CultureInvariant); private static string[] ExtractParameters(string script) { diff --git a/tests/StackExchange.Redis.Tests/Helpers/Attributes.cs b/tests/StackExchange.Redis.Tests/Helpers/Attributes.cs index aa285c15a..2dce70904 100644 --- a/tests/StackExchange.Redis.Tests/Helpers/Attributes.cs +++ b/tests/StackExchange.Redis.Tests/Helpers/Attributes.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using Xunit.Abstractions; @@ -184,3 +186,48 @@ public static RunSummary Update(this RunSummary summary, SkippableMessageBus bus return summary; } } + +/// +/// Supports changing culture for the duration of a single test. +/// and with another culture. +/// +/// +/// Based on: https://bartwullems.blogspot.com/2022/03/xunit-change-culture-during-your-test.html +/// +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] +public class TestCultureAttribute : BeforeAfterTestAttribute +{ + private readonly CultureInfo culture; + private CultureInfo? originalCulture; + + /// + /// Replaces the culture and UI culture of the current thread with . + /// + /// The name of the culture. + public TestCultureAttribute(string culture) => this.culture = new CultureInfo(culture, false); + + /// + /// Stores the current and + /// and replaces them with the new cultures defined in the constructor. + /// + /// The method under test + public override void Before(MethodInfo methodUnderTest) + { + originalCulture = Thread.CurrentThread.CurrentCulture; + Thread.CurrentThread.CurrentCulture = culture; + CultureInfo.CurrentCulture.ClearCachedData(); + } + + /// + /// Restores the original to . + /// + /// The method under test + public override void After(MethodInfo methodUnderTest) + { + if (originalCulture is not null) + { + Thread.CurrentThread.CurrentCulture = originalCulture; + CultureInfo.CurrentCulture.ClearCachedData(); + } + } +} diff --git a/tests/StackExchange.Redis.Tests/ScriptingTests.cs b/tests/StackExchange.Redis.Tests/ScriptingTests.cs index 8164983de..ad290259e 100644 --- a/tests/StackExchange.Redis.Tests/ScriptingTests.cs +++ b/tests/StackExchange.Redis.Tests/ScriptingTests.cs @@ -1113,6 +1113,29 @@ public async Task TestEvalShaReadOnlyAsync() Assert.Equal("bar", result.ToString()); } + [Fact, TestCulture("en-US")] + public void LuaScriptEnglishParameters() => LuaScriptParameterShared(); + + [Fact, TestCulture("tr-TR")] + public void LuaScriptTurkishParameters() => LuaScriptParameterShared(); + + private void LuaScriptParameterShared() + { + const string Script = "redis.call('set', @key, @testIId)"; + var prepared = LuaScript.Prepare(Script); + var key = Me(); + var p = new { key = (RedisKey)key, testIId = "hello" }; + + prepared.ExtractParameters(p, null, out RedisKey[]? keys, out RedisValue[]? args); + Assert.NotNull(keys); + Assert.Single(keys); + Assert.Equal(key, keys[0]); + Assert.NotNull(args); + Assert.Equal(2, args.Length); + Assert.Equal(key, args[0]); + Assert.Equal("hello", args[1]); + } + private static void TestNullValue(RedisResult? value) { Assert.True(value == null || value.IsNull); From 35ac485aeceb0446fc9cd722f3ea87541f5fdffd Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 22 Jan 2023 09:31:17 -0500 Subject: [PATCH 2/2] Add release notes --- docs/ReleaseNotes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 2fafa9f72..864c04a0a 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -8,7 +8,7 @@ Current package versions: ## Unreleased -No pending changes for the next release yet. +- Fix [#2350](https://github.com/StackExchange/StackExchange.Redis/issues/2350): Properly parse lua script paramters in all cultures ([#2351 by NickCraver](https://github.com/StackExchange/StackExchange.Redis/pull/2351)) ## 2.6.90