package dto import ( "encoding/json" "math" "strconv" "testing" ) func TestIDRoundTripsDecimalStringsAndLegacyNumbers(t *testing.T) { for _, value := range []uint64{1, math.MaxInt32, math.MaxInt32 + 1, 1<<53 - 1, 1 << 53, 1<<53 + 1, math.MaxInt64, math.MaxUint64} { want := strconv.FormatUint(value, 10) for _, raw := range []string{want, strconv.Quote(want)} { var request BusinessBindingRequest if err := json.Unmarshal([]byte(`{"platformBusierId":`+raw+`}`), &request); err != nil || uint64(request.PlatformBusierID) != value { t.Fatalf("decode %s: %v, %d", raw, err, request.PlatformBusierID) } encoded, err := json.Marshal(request.PlatformBusierID) if err != nil || string(encoded) != strconv.Quote(want) { t.Fatalf("encode %s: %s, %v", raw, encoded, err) } } } for _, raw := range []string{`null`, `true`, `-1`, `1.5`, `1e3`, `18446744073709551616`, `""`, `"-1"`, `"1.0"`, `"1e3"`, `" 1"`, `"+1"`, `"18446744073709551616"`} { var id ID if err := json.Unmarshal([]byte(raw), &id); err == nil { t.Fatalf("accepted invalid ID %s", raw) } } } func TestLegacyResponsesPreserveLargeIDsAndNumericMetrics(t *testing.T) { const value = uint64(1<<53 + 1) signed := int64(value) for _, response := range []any{ ChannelResponse{ID: value, ParentID: value, BusierID: value}, ChannelCreateResult{ID: value}, ChannelBindOption{PlatformBusierID: value}, ChannelGameResponse{GameID: value, RegisterCount: 3}, BusinessBindingResponse{PlatformBusierID: value}, BusinessPromoteResponse{PromoteID: value, PlatformBusierID: value}, ChannelPortraitBasic{PromoteID: value, ParentPromoteID: func() *uint64 { v := value; return &v }()}, RegistrationResponse{ID: value, UserID: value, FirstGameID: &signed, PromoteID: &signed}, SpendResponse{ID: value, UserID: &signed, GameID: &signed, PromoteID: &signed}, ChannelAnalyticsRow{PromoteID: &signed}, GameAnalyticsRow{GameID: &signed}, PerformanceChannel{ID: value}, PortraitRank{PromoteID: value}, } { raw, err := json.Marshal(response) if err != nil { t.Fatal(err) } var browser map[string]any if err := json.Unmarshal(raw, &browser); err != nil { t.Fatal(err) } for _, key := range []string{"id", "userId", "parentId", "busierId", "platformBusierId", "promoteId", "parentPromoteId", "gameId", "fgameId"} { actual, exists := browser[key] if !exists || actual == nil || actual == float64(0) || actual == "0" { continue } if actual != "9007199254740993" { t.Fatalf("%T.%s lost ID: %v", response, key, actual) } } if count, ok := browser["registerCount"]; ok && count != float64(3) { t.Fatalf("metric changed type: %v", count) } } }