using System.Globalization; using System.Text.Json; using System.Threading; using PolyTraderSharp.Services; using Xunit; namespace PolyTrader.Tests { /// /// Regressionsschutz für den Kultur-Bug in der Aktivitäts-Auswertung: Polymarket liefert /// price/size je nach Endpunkt als JSON-Zahl ODER als String ("0.53"). Wurde der /// String kulturabhängig geparst, las de-DE den Punkt als Tausendertrennzeichen – aus 0,53 wurde /// 53 (Faktor-100-Fehler im Einstandspreis der Master-Trader-Auswertung). /// /// Die Tests setzen die Thread-Kultur bewusst auf de-DE, damit sie auch auf einer invarianten /// Umgebung (z.B. Linux-CI ohne LANG) fehlschlagen würden, sobald jemand die Invariant-Angabe /// wieder entfernt. /// public class ApiNumberParsingTests { /// Führt die Prüfung unter erzwungener de-DE-Kultur aus und stellt sie danach wieder her. private static void UnderGermanCulture(System.Action assertions) { var previous = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE"); try { assertions(); } finally { Thread.CurrentThread.CurrentCulture = previous; } } private static JsonElement Prop(string json) => JsonDocument.Parse(json).RootElement.GetProperty("v"); [Theory] [InlineData("\"0.53\"", 0.53)] // der eigentliche Bug: wurde unter de-DE zu 53 [InlineData("\"0.045\"", 0.045)] [InlineData("\"1234.5\"", 1234.5)] // ohne Invariant unter de-DE: 12345 [InlineData("\"0\"", 0)] public void ParseDecimal_reads_string_values_invariantly(string jsonValue, double expected) { UnderGermanCulture(() => Assert.Equal((decimal)expected, TraderMonitorService.ParseDecimal(Prop($"{{\"v\":{jsonValue}}}")))); } [Theory] [InlineData("0.53", 0.53)] [InlineData("1234.5", 1234.5)] public void ParseDecimal_reads_numeric_values(string jsonValue, double expected) { UnderGermanCulture(() => Assert.Equal((decimal)expected, TraderMonitorService.ParseDecimal(Prop($"{{\"v\":{jsonValue}}}")))); } [Theory] [InlineData("null")] [InlineData("\"\"")] [InlineData("\"n/a\"")] [InlineData("true")] public void ParseDecimal_returns_zero_for_unusable_values(string jsonValue) { UnderGermanCulture(() => Assert.Equal(0m, TraderMonitorService.ParseDecimal(Prop($"{{\"v\":{jsonValue}}}")))); } } }