162 lines
4.6 KiB
Go
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
|
|
}
|