billing_service_image_test.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //go:build unit
  2. package service
  3. import (
  4. "testing"
  5. "github.com/stretchr/testify/require"
  6. )
  7. // TestCalculateImageCost_DefaultPricing 测试无分组配置时使用默认价格
  8. func TestCalculateImageCost_DefaultPricing(t *testing.T) {
  9. svc := &BillingService{} // pricingService 为 nil,使用硬编码默认值
  10. // 2K 尺寸,默认价格 $0.134 * 1.5 = $0.201
  11. cost := svc.CalculateImageCost("gemini-3-pro-image", "2K", 1, nil, 1.0)
  12. require.InDelta(t, 0.201, cost.TotalCost, 0.0001)
  13. require.InDelta(t, 0.201, cost.ActualCost, 0.0001)
  14. // 多张图片
  15. cost = svc.CalculateImageCost("gemini-3-pro-image", "2K", 3, nil, 1.0)
  16. require.InDelta(t, 0.603, cost.TotalCost, 0.0001)
  17. }
  18. // TestCalculateImageCost_GroupCustomPricing 测试分组自定义价格
  19. func TestCalculateImageCost_GroupCustomPricing(t *testing.T) {
  20. svc := &BillingService{}
  21. price1K := 0.10
  22. price2K := 0.15
  23. price4K := 0.30
  24. groupConfig := &ImagePriceConfig{
  25. Price1K: &price1K,
  26. Price2K: &price2K,
  27. Price4K: &price4K,
  28. }
  29. // 1K 使用分组价格
  30. cost := svc.CalculateImageCost("gemini-3-pro-image", "1K", 2, groupConfig, 1.0)
  31. require.InDelta(t, 0.20, cost.TotalCost, 0.0001)
  32. // 2K 使用分组价格
  33. cost = svc.CalculateImageCost("gemini-3-pro-image", "2K", 1, groupConfig, 1.0)
  34. require.InDelta(t, 0.15, cost.TotalCost, 0.0001)
  35. // 4K 使用分组价格
  36. cost = svc.CalculateImageCost("gemini-3-pro-image", "4K", 1, groupConfig, 1.0)
  37. require.InDelta(t, 0.30, cost.TotalCost, 0.0001)
  38. }
  39. func TestCalculateImageCost_NormalizesInvalidSizeTo2K(t *testing.T) {
  40. svc := &BillingService{}
  41. price2K := 0.25
  42. groupConfig := &ImagePriceConfig{Price2K: &price2K}
  43. for _, imageSize := range []string{"", "auto", "not-a-size"} {
  44. t.Run(imageSize, func(t *testing.T) {
  45. cost := svc.CalculateImageCost("gemini-3-pro-image", imageSize, 2, groupConfig, 1.0)
  46. require.InDelta(t, 0.50, cost.TotalCost, 0.0001)
  47. require.InDelta(t, 0.50, cost.ActualCost, 0.0001)
  48. })
  49. }
  50. }
  51. // TestCalculateImageCost_4KDoublePrice 测试 4K 默认价格翻倍
  52. func TestCalculateImageCost_4KDoublePrice(t *testing.T) {
  53. svc := &BillingService{}
  54. // 4K 尺寸,默认价格翻倍 $0.134 * 2 = $0.268
  55. cost := svc.CalculateImageCost("gemini-3-pro-image", "4K", 1, nil, 1.0)
  56. require.InDelta(t, 0.268, cost.TotalCost, 0.0001)
  57. }
  58. // TestCalculateImageCost_RateMultiplier 测试费率倍数
  59. func TestCalculateImageCost_RateMultiplier(t *testing.T) {
  60. svc := &BillingService{}
  61. // 费率倍数 1.5x
  62. cost := svc.CalculateImageCost("gemini-3-pro-image", "2K", 1, nil, 1.5)
  63. require.InDelta(t, 0.201, cost.TotalCost, 0.0001) // TotalCost = 0.134 * 1.5
  64. require.InDelta(t, 0.3015, cost.ActualCost, 0.0001) // ActualCost = 0.201 * 1.5
  65. // 费率倍数 2.0x
  66. cost = svc.CalculateImageCost("gemini-3-pro-image", "2K", 2, nil, 2.0)
  67. require.InDelta(t, 0.402, cost.TotalCost, 0.0001)
  68. require.InDelta(t, 0.804, cost.ActualCost, 0.0001)
  69. }
  70. // TestCalculateImageCost_ZeroCount 测试 imageCount=0
  71. func TestCalculateImageCost_ZeroCount(t *testing.T) {
  72. svc := &BillingService{}
  73. cost := svc.CalculateImageCost("gemini-3-pro-image", "2K", 0, nil, 1.0)
  74. require.Equal(t, 0.0, cost.TotalCost)
  75. require.Equal(t, 0.0, cost.ActualCost)
  76. }
  77. // TestCalculateImageCost_NegativeCount 测试 imageCount=-1
  78. func TestCalculateImageCost_NegativeCount(t *testing.T) {
  79. svc := &BillingService{}
  80. cost := svc.CalculateImageCost("gemini-3-pro-image", "2K", -1, nil, 1.0)
  81. require.Equal(t, 0.0, cost.TotalCost)
  82. require.Equal(t, 0.0, cost.ActualCost)
  83. }
  84. // TestCalculateImageCost_ZeroRateMultiplier 锁定新行为:倍率 0 直接按 0 计费
  85. // (保存时已强制 > 0;若仍有 0 泄漏到计费层,零消耗比历史的 1.0 更安全)。
  86. func TestCalculateImageCost_ZeroRateMultiplier(t *testing.T) {
  87. svc := &BillingService{}
  88. cost := svc.CalculateImageCost("gemini-3-pro-image", "2K", 1, nil, 0)
  89. require.InDelta(t, 0.201, cost.TotalCost, 0.0001)
  90. require.InDelta(t, 0.0, cost.ActualCost, 1e-10)
  91. }
  92. // TestGetImageUnitPrice_GroupPriorityOverDefault 测试分组价格优先于默认价格
  93. func TestGetImageUnitPrice_GroupPriorityOverDefault(t *testing.T) {
  94. svc := &BillingService{}
  95. price2K := 0.20
  96. groupConfig := &ImagePriceConfig{
  97. Price2K: &price2K,
  98. }
  99. // 分组配置了 2K 价格,应该使用分组价格而不是默认的 $0.134
  100. cost := svc.CalculateImageCost("gemini-3-pro-image", "2K", 1, groupConfig, 1.0)
  101. require.InDelta(t, 0.20, cost.TotalCost, 0.0001)
  102. }
  103. // TestGetImageUnitPrice_PartialGroupConfig 测试分组部分配置时回退默认
  104. func TestGetImageUnitPrice_PartialGroupConfig(t *testing.T) {
  105. svc := &BillingService{}
  106. // 只配置 1K 价格
  107. price1K := 0.10
  108. groupConfig := &ImagePriceConfig{
  109. Price1K: &price1K,
  110. }
  111. // 1K 使用分组价格
  112. cost := svc.CalculateImageCost("gemini-3-pro-image", "1K", 1, groupConfig, 1.0)
  113. require.InDelta(t, 0.10, cost.TotalCost, 0.0001)
  114. // 2K 回退默认价格 $0.201 (1.5倍)
  115. cost = svc.CalculateImageCost("gemini-3-pro-image", "2K", 1, groupConfig, 1.0)
  116. require.InDelta(t, 0.201, cost.TotalCost, 0.0001)
  117. // 4K 回退默认价格 $0.268 (翻倍)
  118. cost = svc.CalculateImageCost("gemini-3-pro-image", "4K", 1, groupConfig, 1.0)
  119. require.InDelta(t, 0.268, cost.TotalCost, 0.0001)
  120. }
  121. // TestGetDefaultImagePrice_FallbackHardcoded 测试 PricingService 无数据时使用硬编码默认值
  122. func TestGetDefaultImagePrice_FallbackHardcoded(t *testing.T) {
  123. svc := &BillingService{} // pricingService 为 nil
  124. // 1K 默认价格 $0.134,2K 默认价格 $0.201 (1.5倍)
  125. cost := svc.CalculateImageCost("gemini-3-pro-image", "1K", 1, nil, 1.0)
  126. require.InDelta(t, 0.134, cost.TotalCost, 0.0001)
  127. cost = svc.CalculateImageCost("gemini-3-pro-image", "2K", 1, nil, 1.0)
  128. require.InDelta(t, 0.201, cost.TotalCost, 0.0001)
  129. }