package giftdiamond import ( "context" "errors" "regexp" "testing" "github.com/DATA-DOG/go-sqlmock" ) func TestPersistedPercentStringRejectsEmptyOrInvalidValues(t *testing.T) { for _, raw := range []string{"", "bad", "-1", "101"} { if _, err := persistedPercentString(raw); err == nil { t.Fatalf("persisted percent %q must not be replaced by a code default", raw) } } if got, err := persistedPercentString("12.345"); err != nil || got != "12.35" { t.Fatalf("valid persisted percent mismatch: got=%q err=%v", got, err) } } func TestResolveRatioReturnsUnconfiguredInsteadOfSyntheticDefaults(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatalf("create sqlmock: %v", err) } defer db.Close() query := regexp.QuoteMeta(` SELECT region_id, gift_type_code, CAST(ratio_percent AS CHAR), CAST(coin_return_ratio_percent AS CHAR), status, updated_at_ms FROM gift_diamond_ratio_configs WHERE app_code = ? AND region_id = ? AND gift_type_code = ? LIMIT 1`) mock.ExpectQuery(query).WithArgs("fami", int64(25), "normal").WillReturnError(sqlmock.ErrCancelled) service := NewService(db) if _, _, err := service.resolveRatio(context.Background(), "fami", 25, "normal"); !errors.Is(err, sqlmock.ErrCancelled) { t.Fatalf("query errors must be returned: %v", err) } // 两级查询均无记录时必须返回 configured=false,不能显示 100/10/1 幽灵政策。 mock.ExpectQuery(query).WithArgs("fami", int64(25), "normal").WillReturnRows(sqlmock.NewRows([]string{"region_id", "gift_type_code", "ratio", "return_ratio", "status", "updated_at_ms"})) mock.ExpectQuery(query).WithArgs("fami", int64(0), "normal").WillReturnRows(sqlmock.NewRows([]string{"region_id", "gift_type_code", "ratio", "return_ratio", "status", "updated_at_ms"})) item, configured, err := service.resolveRatio(context.Background(), "fami", 25, "normal") if err != nil || configured || item != (ratioDTO{}) { t.Fatalf("unconfigured ratio mismatch: item=%+v configured=%t err=%v", item, configured, err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatalf("unmet SQL expectations: %v", err) } } func TestEnsureSchemaDoesNotInsertGiftMultiplierDefaults(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatalf("create sqlmock: %v", err) } defer db.Close() mock.ExpectExec("CREATE TABLE IF NOT EXISTS gift_diamond_ratio_configs").WillReturnResult(sqlmock.NewResult(0, 0)) mock.ExpectExec("ALTER TABLE gift_diamond_ratio_configs").WillReturnError(errors.New("Duplicate column name 'coin_return_ratio_percent'")) if err := NewService(db).ensureSchema(context.Background()); err != nil { t.Fatalf("ensure schema: %v", err) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatalf("startup must not issue an implicit INSERT: %v", err) } }