fix: make locale-independence real, not assumed — parsing, casing, comparison
Follow-up to the retail-text fix. "Green under sv-SE" is not the same as "runs on any locale", so this establishes the latter by running the suite under cultures chosen to break different things, and fixing what they broke. ar-SA found a genuine defect the Swedish runner cannot see: the resolution parser read "1920x-1" through the ambient culture, and ar-SA's negative sign is not ASCII '-', so the parse failed and the height silently became 0 instead of -1. Both copies of that parser (App settings targets and the UI settings store) now parse invariantly. Audited every remaining culture-sensitive operation in src/ rather than fixing only what a test happened to catch: - Numeric Parse/TryParse with no IFormatProvider: 11 sites, all reading MACHINE-readable input — env vars (ACDREAM_LIGHT_DEBUG, ACDREAM_NET_DROP_*, streaming/quality knobs), CLI arguments, "1920x1080" settings keys, a chat command's price argument, and the launcher's bake thread count, which is handed straight to a child process command line. All pinned to InvariantCulture. - ToUpper()/ToLower() with no culture: none. The Turkish-I class was already clean, and tr-TR confirms it. - StartsWith/EndsWith/IndexOf(string) with no StringComparison: one — ChatInputParser's "@" prefix test, which is a culture-sensitive comparison for a single ASCII character. Now the ordinal char overload. Verified: 13,958 tests pass identically under the machine default, sv-SE, tr-TR, ar-SA, and de-DE. (The two launcher test assemblies are excluded from this run only because a running acdream-launcher.exe holds its own binary; the one launcher change here is the thread-count parse.) Dates remain on the current culture by intent, unchanged from the previous commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
6a15dd063c
commit
955c618013
11 changed files with 64 additions and 16 deletions
|
|
@ -1,3 +1,4 @@
|
|||
using System.Globalization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -134,8 +135,10 @@ internal static class DisplayModeCatalog
|
|||
mode = default;
|
||||
string[] parts = spec.Split('x', 2);
|
||||
if (parts.Length == 2
|
||||
&& int.TryParse(parts[0], out int w)
|
||||
&& int.TryParse(parts[1], out int h)
|
||||
&& int.TryParse(
|
||||
parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out int w)
|
||||
&& int.TryParse(
|
||||
parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int h)
|
||||
&& w > 0
|
||||
&& h > 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using AcDream.App.Audio;
|
||||
using AcDream.App.Net;
|
||||
|
|
@ -206,9 +207,14 @@ internal sealed class SilkRuntimeDisplayWindowTarget : IRuntimeDisplayWindowTarg
|
|||
if (string.IsNullOrWhiteSpace(spec))
|
||||
return false;
|
||||
string[] parts = spec.Split('x', 2);
|
||||
// Invariant: a resolution spec is a machine-readable settings key, not
|
||||
// localized input. Parsing it with the ambient culture made "1920x-1"
|
||||
// fail outright under ar-SA, whose negative sign is not ASCII "-".
|
||||
return parts.Length == 2
|
||||
&& int.TryParse(parts[0], out width)
|
||||
&& int.TryParse(parts[1], out height)
|
||||
&& int.TryParse(
|
||||
parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out width)
|
||||
&& int.TryParse(
|
||||
parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out height)
|
||||
&& width > 0
|
||||
&& height > 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Globalization;
|
||||
using System;
|
||||
|
||||
namespace AcDream.App.Streaming;
|
||||
|
|
@ -73,5 +74,8 @@ internal static class StreamingDiagnostics
|
|||
/// at the parser rather than let the two halves of one commit disagree.
|
||||
/// </summary>
|
||||
internal static int? ParseRadius(string? raw) =>
|
||||
int.TryParse(raw, out int value) && value >= 1 ? value : null;
|
||||
int.TryParse(raw, NumberStyles.Integer, CultureInfo.InvariantCulture, out int value)
|
||||
&& value >= 1
|
||||
? value
|
||||
: null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Globalization;
|
||||
using AcDream.Core.Physics;
|
||||
using AcDream.Core.Ui;
|
||||
using AcDream.Core.Social;
|
||||
|
|
@ -724,7 +725,8 @@ public sealed class ClientCommandController
|
|||
uint maximumPrice = 0u;
|
||||
foreach (string part in parts)
|
||||
{
|
||||
if (uint.TryParse(part, out uint price))
|
||||
if (uint.TryParse(
|
||||
part, NumberStyles.Integer, CultureInfo.InvariantCulture, out uint price))
|
||||
{
|
||||
if (price == 0)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue