You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

149 lines
4.5 KiB

  1. package relay
  2. import (
  3. "net/http"
  4. "net/http/httptest"
  5. "testing"
  6. "github.com/QuantumNous/new-api/common"
  7. "github.com/QuantumNous/new-api/constant"
  8. "github.com/QuantumNous/new-api/model"
  9. relaycommon "github.com/QuantumNous/new-api/relay/common"
  10. "github.com/QuantumNous/new-api/types"
  11. "github.com/gin-gonic/gin"
  12. "github.com/glebarez/sqlite"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/stretchr/testify/require"
  15. "gorm.io/gorm"
  16. )
  17. func setupRelayTaskTestDB(t *testing.T) {
  18. t.Helper()
  19. db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
  20. require.NoError(t, err)
  21. require.NoError(t, db.AutoMigrate(&model.Task{}, &model.Channel{}))
  22. sqlDB, err := db.DB()
  23. require.NoError(t, err)
  24. sqlDB.SetMaxOpenConns(1)
  25. origDB := model.DB
  26. origUsingSQLite := common.UsingSQLite
  27. origRedisEnabled := common.RedisEnabled
  28. model.DB = db
  29. common.UsingSQLite = true
  30. common.RedisEnabled = false
  31. t.Cleanup(func() {
  32. model.DB = origDB
  33. common.UsingSQLite = origUsingSQLite
  34. common.RedisEnabled = origRedisEnabled
  35. require.NoError(t, sqlDB.Close())
  36. })
  37. }
  38. func TestResolveOriginTask_RestoresMatrixOriginPricing(t *testing.T) {
  39. setupRelayTaskTestDB(t)
  40. require.NoError(t, model.DB.Create(&model.Channel{
  41. Id: 11,
  42. Type: constant.ChannelTypeMiniMax,
  43. Key: "test-key",
  44. Status: common.ChannelStatusEnabled,
  45. Name: "hailuo",
  46. Group: "default",
  47. Models: "matrix-video",
  48. }).Error)
  49. require.NoError(t, model.DB.Create(&model.Task{
  50. TaskID: "task_origin",
  51. UserId: 7,
  52. ChannelId: 11,
  53. Properties: model.Properties{
  54. OriginModelName: "matrix-video",
  55. },
  56. PrivateData: model.TaskPrivateData{
  57. BillingContext: &model.TaskBillingContext{
  58. BillingMode: types.BillingModeMatrix,
  59. BillingUnit: types.BillingUnitPer1MTokens,
  60. TokenUnitPriceUSD: 0.5,
  61. PricingSnapshot: map[string]any{
  62. "resolution": "720P",
  63. "price": 0.5,
  64. "billing_unit": types.BillingUnitPer1MTokens,
  65. "pricing_mode": string(types.PricingModeMatched),
  66. },
  67. PerCallBilling: false,
  68. },
  69. },
  70. }).Error)
  71. c := newRelayTaskRemixContext(t, "task_origin")
  72. info := &relaycommon.RelayInfo{UserId: 7, TaskRelayInfo: &relaycommon.TaskRelayInfo{}}
  73. taskErr := ResolveOriginTask(c, info)
  74. require.Nil(t, taskErr)
  75. require.NotNil(t, info.OriginPricing)
  76. require.NotNil(t, info.LockedChannel)
  77. assert.Equal(t, constant.TaskActionRemix, info.Action)
  78. assert.Equal(t, "matrix-video", info.OriginModelName)
  79. assert.Equal(t, types.BillingModeMatrix, info.OriginPricing.BillingMode)
  80. assert.Equal(t, types.BillingUnitPer1MTokens, info.OriginPricing.BillingUnit)
  81. assert.Equal(t, 0.5, info.OriginPricing.TokenUnitPriceUSD)
  82. assert.Equal(t, "720P", info.OriginPricing.Snapshot["resolution"])
  83. lockedChannel, ok := info.LockedChannel.(*model.Channel)
  84. require.True(t, ok)
  85. assert.Equal(t, 11, lockedChannel.Id)
  86. }
  87. func TestResolveOriginTask_RestoresLegacyOriginPricing(t *testing.T) {
  88. setupRelayTaskTestDB(t)
  89. require.NoError(t, model.DB.Create(&model.Channel{
  90. Id: 12,
  91. Type: constant.ChannelTypeOpenAI,
  92. Key: "test-key",
  93. Status: common.ChannelStatusEnabled,
  94. Name: "sora",
  95. Group: "default",
  96. Models: "legacy-video",
  97. }).Error)
  98. require.NoError(t, model.DB.Create(&model.Task{
  99. TaskID: "task_legacy",
  100. UserId: 7,
  101. ChannelId: 12,
  102. Properties: model.Properties{
  103. OriginModelName: "legacy-video",
  104. },
  105. PrivateData: model.TaskPrivateData{
  106. BillingContext: &model.TaskBillingContext{
  107. ModelPrice: 0.2,
  108. OtherRatios: map[string]float64{"seconds": 10, "size": 1.666667},
  109. PerCallBilling: true,
  110. },
  111. },
  112. }).Error)
  113. c := newRelayTaskRemixContext(t, "task_legacy")
  114. info := &relaycommon.RelayInfo{UserId: 7, TaskRelayInfo: &relaycommon.TaskRelayInfo{}}
  115. taskErr := ResolveOriginTask(c, info)
  116. require.Nil(t, taskErr)
  117. require.NotNil(t, info.OriginPricing)
  118. require.NotNil(t, info.LockedChannel)
  119. assert.Equal(t, "legacy-video", info.OriginModelName)
  120. assert.Equal(t, 0.2, info.OriginPricing.PriceUSD)
  121. assert.Equal(t, map[string]float64{"seconds": 10, "size": 1.666667}, info.OriginPricing.OtherRatios)
  122. assert.True(t, info.OriginPricing.PerCallBilling)
  123. lockedChannel, ok := info.LockedChannel.(*model.Channel)
  124. require.True(t, ok)
  125. assert.Equal(t, 12, lockedChannel.Id)
  126. }
  127. func newRelayTaskRemixContext(t *testing.T, originTaskID string) *gin.Context {
  128. t.Helper()
  129. gin.SetMode(gin.TestMode)
  130. w := httptest.NewRecorder()
  131. c, _ := gin.CreateTestContext(w)
  132. c.Request = httptest.NewRequest(http.MethodPost, "/v1/videos/"+originTaskID+"/remix", nil)
  133. c.Params = gin.Params{{Key: "video_id", Value: originTaskID}}
  134. return c
  135. }