Files
hfb_sys/backend/internal/modules/systemconfig/publish_options_test.go
T

162 lines
4.6 KiB
Go

package systemconfig
import (
"encoding/json"
"strings"
"testing"
)
func TestDecodeCP1252Mojibake(t *testing.T) {
original := `{"label":"6级子弹","price":"0.26元/发","punct":"(:,)"}`
mojibake := encodeCP1252Mojibake(original)
decoded, ok := decodeCP1252Mojibake(mojibake)
if !ok {
t.Fatal("期望识别出 CP1252 乱码")
}
if decoded != original {
t.Fatalf("还原结果 = %q, want %q", decoded, original)
}
if _, ok := decodeCP1252Mojibake(original); ok {
t.Fatal("正常中文不应被误判为乱码")
}
if _, ok := decodeCP1252Mojibake("plain ascii"); ok {
t.Fatal("纯 ASCII 不应被误判为乱码")
}
}
func TestRepairMojibakeJSONRepairsIndividualFields(t *testing.T) {
raw := `{"normal":"正常字段","broken":"` + encodeCP1252Mojibake("6级子弹") + `"}`
repaired := repairMojibakeJSON(raw)
var payload map[string]string
if err := json.Unmarshal([]byte(repaired), &payload); err != nil {
t.Fatalf("还原后的 JSON 无法解析: %v", err)
}
if payload["normal"] != "正常字段" {
t.Fatalf("正常字段被破坏: %q", payload["normal"])
}
if payload["broken"] != "6级子弹" {
t.Fatalf("乱码字段未还原: %q", payload["broken"])
}
}
func TestNormalizePublishOptionsValueMigratesLegacyQuantityItems(t *testing.T) {
legacy := `{
"server_options": ["QQ"],
"quantity_items": [
{"key": "kit5", "label": "5级全装套数量", "price": "5元/个"},
{"key": "level6Ammo", "label": "6级子弹", "price": "0.26元/发"}
]
}`
normalized, err := normalizePublishOptionsValue(legacy)
if err != nil {
t.Fatalf("规范化失败: %v", err)
}
var options PublishOptionsDTO
if err := json.Unmarshal([]byte(normalized), &options); err != nil {
t.Fatalf("解析规范化结果失败: %v", err)
}
if options.SchemaVersion != publishOptionsSchemaVersion {
t.Fatalf("schema_version = %d, want %d", options.SchemaVersion, publishOptionsSchemaVersion)
}
for _, item := range options.QuantityItems {
if item.Key == "kit5" {
t.Fatal("旧版 kit5 选项应被迁移掉")
}
}
if !hasQuantityItemKey(options.QuantityItems, "level6Ammo") {
t.Fatal("迁移后的默认选项缺少 level6Ammo")
}
}
func TestNormalizePublishOptionsValuePreservesCurrentSchema(t *testing.T) {
options := DefaultPublishOptions()
for index := range options.ScreenshotSlots {
if options.ScreenshotSlots[index].Key == "tencentSecurity" {
options.ScreenshotSlots[index].Required = true
}
}
options.QuantityItems = append(options.QuantityItems, PublishQuantityItem{
Key: "kit5",
Label: "自定义旧选项",
Price: "9元/个",
})
raw, err := json.Marshal(options)
if err != nil {
t.Fatalf("构造当前版本配置失败: %v", err)
}
normalized, err := normalizePublishOptionsValue(string(raw))
if err != nil {
t.Fatalf("规范化失败: %v", err)
}
var got PublishOptionsDTO
if err := json.Unmarshal([]byte(normalized), &got); err != nil {
t.Fatalf("解析规范化结果失败: %v", err)
}
if !hasQuantityItemKey(got.QuantityItems, "kit5") {
t.Fatal("当前版本配置中的自定义项不应被旧版迁移清掉")
}
for _, slot := range got.ScreenshotSlots {
if slot.Key == "tencentSecurity" && !slot.Required {
t.Fatal("当前版本配置中 tencentSecurity.required=true 不应被覆盖")
}
}
}
func TestNormalizePublishOptionsValueRepairsMojibake(t *testing.T) {
options := DefaultPublishOptions()
raw, err := json.Marshal(options)
if err != nil {
t.Fatalf("构造配置失败: %v", err)
}
mojibake := encodeCP1252Mojibake(string(raw))
normalized, err := normalizePublishOptionsValue(mojibake)
if err != nil {
t.Fatalf("规范化乱码配置失败: %v", err)
}
var got PublishOptionsDTO
if err := json.Unmarshal([]byte(normalized), &got); err != nil {
t.Fatalf("解析规范化结果失败: %v", err)
}
if !containsString(got.ServerOptions, "微信") {
t.Fatalf("乱码未恢复,server_options = %#v", got.ServerOptions)
}
if got.SchemaVersion != publishOptionsSchemaVersion {
t.Fatalf("schema_version = %d, want %d", got.SchemaVersion, publishOptionsSchemaVersion)
}
}
func encodeCP1252Mojibake(value string) string {
var builder strings.Builder
for _, item := range []byte(value) {
if item >= 0x80 && item <= 0x9F {
builder.WriteRune(cp1252HighRunes[item-0x80])
continue
}
builder.WriteRune(rune(item))
}
return builder.String()
}
func hasQuantityItemKey(items []PublishQuantityItem, key string) bool {
for _, item := range items {
if item.Key == key {
return true
}
}
return false
}
func containsString(items []string, target string) bool {
for _, item := range items {
if item == target {
return true
}
}
return false
}