Skip to content

Commit cdc6c7f

Browse files
committed
test: fix timezone tests to work with different TZ IDs on windows and linux, and fix mocker behavior on .NET 4.x
1 parent a174714 commit cdc6c7f

3 files changed

Lines changed: 36 additions & 16 deletions

File tree

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
11
using System;
2-
using System.Reflection;
2+
using System.Collections.Generic;
33

44
namespace NetCoreForce.Client.Tests
5-
{
5+
{
66
/// <summary>
7-
/// Sample TimeZone IDs for use in tests
7+
/// Sample TimeZone IDs for use in tests.
8+
/// Windows and Linux/macOS use different TimeZoneInfo ID formats (Windows-native vs IANA),
9+
/// so the appropriate ID for the current OS is exposed here.
810
/// </summary>
911
public static class TimeZoneIds
1012
{
11-
public static string TimeZoneIdNewYork = "America/New_York";
12-
public static string TimeZoneIdPhoenix = "America/Phoenix";
13-
public static string TimeZoneIdLondon = "Europe/London";
14-
public static string TimeZoneIdTokyo = "Asia/Tokyo";
13+
private static readonly bool IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;
14+
15+
public static string NewYork => IsWindows ? "Eastern Standard Time" : "America/New_York";
16+
public static string Phoenix => IsWindows ? "US Mountain Standard Time" : "America/Phoenix"; // no DST
17+
public static string London => IsWindows ? "GMT Standard Time" : "Europe/London";
18+
public static string Tokyo => IsWindows ? "Tokyo Standard Time" : "Asia/Tokyo";
19+
public static string Kathmandu => IsWindows ? "Nepal Standard Time" : "Asia/Kathmandu"; // UTC+5:45
20+
public static string Auckland => IsWindows ? "New Zealand Standard Time" : "Pacific/Auckland";
21+
public static string Moscow => IsWindows ? "Russian Standard Time" : "Europe/Moscow";
22+
public static string Shanghai => IsWindows ? "China Standard Time" : "Asia/Shanghai";
23+
24+
public static IEnumerable<string> All => new[]
25+
{
26+
NewYork, Phoenix, London, Tokyo, Kathmandu, Auckland, Moscow, Shanghai
27+
};
1528
}
1629
}

‎src/NetCoreForce.Client.Tests/TimeZoneInfoMocker.cs‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,24 @@ public LocalTimeZoneInfoMocker(TimeZoneInfo mockTimeZoneInfo)
1313
SetLocalTimeZone(mockTimeZoneInfo);
1414
}
1515

16+
// the private field backing TimeZoneInfo.Local is named "_localTimeZone" on modern .NET,
17+
// but "m_localTimeZone" on .NET Framework
18+
private static readonly string[] LocalTimeZoneFieldNames = { "_localTimeZone", "m_localTimeZone" };
19+
1620
private static void SetLocalTimeZone(TimeZoneInfo timeZoneInfo)
1721
{
1822
var info = typeof(TimeZoneInfo).GetField("s_cachedData", BindingFlags.NonPublic | BindingFlags.Static);
1923
object cachedData = info.GetValue(null);
2024

21-
var field = cachedData.GetType().GetField("_localTimeZone", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Instance);
25+
FieldInfo field = null;
26+
foreach (string fieldName in LocalTimeZoneFieldNames)
27+
{
28+
field = cachedData.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
29+
if (field != null) break;
30+
}
31+
32+
if (field == null) throw new InvalidOperationException("Unable to find the local time zone field on TimeZoneInfo.CachedData");
33+
2234
field.SetValue(cachedData, timeZoneInfo);
2335
}
2436

‎src/NetCoreForce.Client.Tests/TimeZoneInfoMockerTests.cs‎

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,10 @@ namespace NetCoreForce.Client.Tests
1010
{
1111
public class TimeZoneInfoMockerTests
1212
{
13+
public static TheoryData<string> TimeZoneIdData => new TheoryData<string>(TimeZoneIds.All);
14+
1315
[Theory]
14-
[InlineData("America/New_York")]
15-
[InlineData("America/Phoenix")]
16-
[InlineData("Europe/London")]
17-
[InlineData("Asia/Tokyo")]
18-
[InlineData("Asia/Kathmandu")] // Nepal Time (UTC+5:45)
19-
[InlineData("Pacific/Auckland")]
20-
[InlineData("Europe/Moscow")]
21-
[InlineData("Asia/Shanghai")]
16+
[MemberData(nameof(TimeZoneIdData))]
2217
public void TestLocalTimeZoneInfoMocker(string timeZoneId)
2318
{
2419
TimeZoneInfo localTimeZoneInfo = TimeZoneInfo.Local;

0 commit comments

Comments
 (0)