From 2fe5db442f081c6f7a7142e90cb54d976b863225 Mon Sep 17 00:00:00 2001 From: ImmutableJeffrey Date: Thu, 30 Apr 2026 16:42:14 +1000 Subject: [PATCH] fix(audience): lowercase DistributionPlatform at Init The DistributionPlatforms constants ship lowercase ("steam", "epic", "gog", "itch", "standalone"), but a studio passing "Steam" or "STEAM" shipped that casing on the wire and split dashboard rows from constant-using studios in the same project. Init now lowercases config.DistributionPlatform once at the boundary so the rest of the SDK and the wire format see a single canonical form. Mutates the caller's AudienceConfig instance the same way the existing block already does for PersistentDataPath. Adds 4 test cases: - Init_LowercasesDistributionPlatform_WhenCallerPassesMixedCase - Init_LowercasesDistributionPlatform_WhenCallerPassesAllUpperCase - Init_LeavesDistributionPlatformUnchanged_WhenAlreadyLowercase - Init_LeavesDistributionPlatformNull_WhenNotSet Discovered during SDK-150 docs review (immutable/documentation#69). --- .../Audience/Runtime/ImmutableAudience.cs | 7 ++++ .../Tests/Runtime/ImmutableAudienceTests.cs | 41 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/Packages/Audience/Runtime/ImmutableAudience.cs b/src/Packages/Audience/Runtime/ImmutableAudience.cs index f346ed710..443936181 100644 --- a/src/Packages/Audience/Runtime/ImmutableAudience.cs +++ b/src/Packages/Audience/Runtime/ImmutableAudience.cs @@ -113,6 +113,13 @@ public static void Init(AudienceConfig config) if (string.IsNullOrEmpty(config.PersistentDataPath)) throw new ArgumentException("PersistentDataPath is required", nameof(config)); + // Normalize casing so dashboards aggregate consistently. The + // DistributionPlatforms constants ship lowercase; a studio that + // passes "Steam" or "STEAM" would otherwise split rows from + // constant-using studios in the same project. + if (!string.IsNullOrEmpty(config.DistributionPlatform)) + config.DistributionPlatform = config.DistributionPlatform.ToLowerInvariant(); + ConsentLevel consentAtInit; Session? sessionToStart; lock (_initLock) diff --git a/src/Packages/Audience/Tests/Runtime/ImmutableAudienceTests.cs b/src/Packages/Audience/Tests/Runtime/ImmutableAudienceTests.cs index 60b2e4cb2..848e0e2fd 100644 --- a/src/Packages/Audience/Tests/Runtime/ImmutableAudienceTests.cs +++ b/src/Packages/Audience/Tests/Runtime/ImmutableAudienceTests.cs @@ -1117,6 +1117,47 @@ public void Init_GameLaunch_IncludesDistributionPlatform() c.Contains("\"game_launch\"") && c.Contains("\"steam\""))); } + [Test] + public void Init_LowercasesDistributionPlatform_WhenCallerPassesMixedCase() + { + var config = MakeConfig(); + config.DistributionPlatform = "Steam"; + ImmutableAudience.Init(config); + + Assert.AreEqual("steam", config.DistributionPlatform, + "Init should lowercase mixed-case DistributionPlatform so dashboards aggregate consistently."); + } + + [Test] + public void Init_LowercasesDistributionPlatform_WhenCallerPassesAllUpperCase() + { + var config = MakeConfig(); + config.DistributionPlatform = "STEAM"; + ImmutableAudience.Init(config); + + Assert.AreEqual("steam", config.DistributionPlatform); + } + + [Test] + public void Init_LeavesDistributionPlatformUnchanged_WhenAlreadyLowercase() + { + var config = MakeConfig(); + config.DistributionPlatform = "steam"; + ImmutableAudience.Init(config); + + Assert.AreEqual("steam", config.DistributionPlatform); + } + + [Test] + public void Init_LeavesDistributionPlatformNull_WhenNotSet() + { + var config = MakeConfig(); + Assert.IsNull(config.DistributionPlatform); + ImmutableAudience.Init(config); + + Assert.IsNull(config.DistributionPlatform); + } + [Test] public void Init_ConsentNone_DoesNotFireGameLaunch() {