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.
 
 
 

184 lines
5.8 KiB

  1. package controller
  2. import (
  3. "bytes"
  4. "net/http"
  5. "net/http/httptest"
  6. "os"
  7. "strings"
  8. "testing"
  9. "time"
  10. "github.com/QuantumNous/new-api/common"
  11. "github.com/QuantumNous/new-api/constant"
  12. "github.com/QuantumNous/new-api/model"
  13. "github.com/gin-gonic/gin"
  14. "github.com/stretchr/testify/require"
  15. "gorm.io/gorm"
  16. "gorm.io/gorm/logger"
  17. )
  18. const chinaMobileAssetE2EImageURL = "https://bkimg.cdn.bcebos.com/pic/caef76094b36acaf2edd2133a78e9a1001e9380136fe?x-bce-process=image/format,f_auto/watermark,image_d2F0ZXIvYmFpa2UyNzI,g_7,xp_5,yp_5,P_20/resize,m_lfit,limit_1,h_1080"
  19. func TestChinaMobileAssetControllerWithRealUpstream(t *testing.T) {
  20. ak := strings.TrimSpace(os.Getenv("CHINAMOBILE_ASSET_AK"))
  21. sk := strings.TrimSpace(os.Getenv("CHINAMOBILE_ASSET_SK"))
  22. poolID := strings.TrimSpace(os.Getenv("CHINAMOBILE_ASSET_POOL_ID"))
  23. if ak == "" || sk == "" {
  24. t.Skip("CHINAMOBILE_ASSET_AK and CHINAMOBILE_ASSET_SK are required")
  25. }
  26. if poolID == "" {
  27. poolID = "CIDC-CORE-00"
  28. }
  29. db := setupRealAssetE2EDB(t)
  30. createDoubaoAssetProxyChannel(t, db, 7101, constant.ChannelTypeChinaMobileSeedance, "default", "video-generation-key", common.ChannelStatusEnabled)
  31. router := setupRealAssetE2ERouter()
  32. suffix := time.Now().Format("20060102150405")
  33. groupName := "new-api-e2e-" + suffix
  34. assetName := "new-api-img-" + suffix
  35. var groupId string
  36. var assetId string
  37. defer func() {
  38. if assetId != "" {
  39. code, _ := performRealAssetE2EAction(t, router, "DeleteAsset", map[string]any{"Id": assetId})
  40. require.Equal(t, http.StatusOK, code, "cleanup DeleteAsset failed")
  41. }
  42. if groupId != "" {
  43. code, _ := performRealAssetE2EAction(t, router, "DeleteAssetGroup", map[string]any{"Id": groupId})
  44. require.Equal(t, http.StatusOK, code, "cleanup DeleteAssetGroup failed")
  45. }
  46. }()
  47. code, body := performRealAssetE2EAction(t, router, "CreateAssetGroup", map[string]any{
  48. "Name": groupName,
  49. "GroupType": "AIGC",
  50. "Description": "new-api real e2e test",
  51. })
  52. require.Equal(t, http.StatusOK, code)
  53. groupId = realAssetE2EString(t, body, "Result.GroupId")
  54. require.NotEmpty(t, groupId)
  55. code, body = performRealAssetE2EAction(t, router, "CreateAsset", map[string]any{
  56. "GroupId": groupId,
  57. "Name": assetName,
  58. "URL": chinaMobileAssetE2EImageURL,
  59. "AssetType": "Image",
  60. })
  61. require.Equal(t, http.StatusOK, code)
  62. assetId = realAssetE2EString(t, body, "Result")
  63. require.NotEmpty(t, assetId)
  64. var status string
  65. for i := 0; i < 6; i++ {
  66. code, body = performRealAssetE2EAction(t, router, "GetAsset", map[string]any{"Id": assetId})
  67. require.Equal(t, http.StatusOK, code)
  68. require.Equal(t, assetId, realAssetE2EString(t, body, "Result.Id"))
  69. status = realAssetE2EString(t, body, "Result.Status")
  70. if status != "Processing" {
  71. break
  72. }
  73. time.Sleep(3 * time.Second)
  74. }
  75. require.Equal(t, "Active", status)
  76. code, body = performRealAssetE2EAction(t, router, "ListAssets", map[string]any{
  77. "PageNumber": 1,
  78. "PageSize": 10,
  79. "Filter": map[string]any{
  80. "GroupType": "AIGC",
  81. "GroupIds": []string{groupId},
  82. },
  83. })
  84. require.Equal(t, http.StatusOK, code)
  85. require.Equal(t, float64(1), realAssetE2EValue(t, body, "Result.TotalCount"))
  86. }
  87. func setupRealAssetE2EDB(t *testing.T) *gorm.DB {
  88. t.Helper()
  89. oldDB := model.DB
  90. oldSQLitePath := common.SQLitePath
  91. oldMemoryCacheEnabled := common.MemoryCacheEnabled
  92. oldIsMasterNode := common.IsMasterNode
  93. oldUsingSQLite := common.UsingSQLite
  94. oldUsingMySQL := common.UsingMySQL
  95. oldUsingPostgreSQL := common.UsingPostgreSQL
  96. oldSQLDSN, hadSQLDSN := os.LookupEnv("SQL_DSN")
  97. common.SQLitePath = "file:" + strings.NewReplacer("/", "_", " ", "_").Replace(t.Name()) + "?mode=memory&cache=shared"
  98. common.MemoryCacheEnabled = false
  99. common.IsMasterNode = false
  100. common.UsingSQLite = false
  101. common.UsingMySQL = false
  102. common.UsingPostgreSQL = false
  103. require.NoError(t, os.Setenv("SQL_DSN", "local"))
  104. require.NoError(t, model.InitDB())
  105. model.DB = model.DB.Session(&gorm.Session{Logger: logger.Default.LogMode(logger.Silent)})
  106. db := model.DB
  107. sqlDB, err := db.DB()
  108. require.NoError(t, err)
  109. sqlDB.SetMaxOpenConns(1)
  110. require.NoError(t, db.AutoMigrate(&model.Channel{}, &model.Ability{}, &model.UserAssetChannel{}))
  111. t.Cleanup(func() {
  112. _ = sqlDB.Close()
  113. model.DB = oldDB
  114. common.SQLitePath = oldSQLitePath
  115. common.MemoryCacheEnabled = oldMemoryCacheEnabled
  116. common.IsMasterNode = oldIsMasterNode
  117. common.UsingSQLite = oldUsingSQLite
  118. common.UsingMySQL = oldUsingMySQL
  119. common.UsingPostgreSQL = oldUsingPostgreSQL
  120. if hadSQLDSN {
  121. _ = os.Setenv("SQL_DSN", oldSQLDSN)
  122. } else {
  123. _ = os.Unsetenv("SQL_DSN")
  124. }
  125. })
  126. return db
  127. }
  128. func setupRealAssetE2ERouter() *gin.Engine {
  129. router := gin.New()
  130. router.Use(func(c *gin.Context) {
  131. c.Set("id", 10)
  132. common.SetContextKey(c, constant.ContextKeyUsingGroup, "default")
  133. c.Next()
  134. })
  135. router.POST("/api/v1/volcengine/asset", DoubaoAssetProxy)
  136. return router
  137. }
  138. func performRealAssetE2EAction(t *testing.T, router *gin.Engine, action string, payload map[string]any) (int, string) {
  139. t.Helper()
  140. data, err := common.Marshal(payload)
  141. require.NoError(t, err)
  142. req := httptest.NewRequest(http.MethodPost, "/api/v1/volcengine/asset?Action="+action, bytes.NewReader(data))
  143. req.Header.Set("Content-Type", "application/json")
  144. w := httptest.NewRecorder()
  145. router.ServeHTTP(w, req)
  146. return w.Code, w.Body.String()
  147. }
  148. func realAssetE2EString(t *testing.T, data string, path string) string {
  149. t.Helper()
  150. value := realAssetE2EValue(t, data, path)
  151. s, ok := value.(string)
  152. require.Truef(t, ok, "%s is not a string: %#v", path, value)
  153. return s
  154. }
  155. func realAssetE2EValue(t *testing.T, data string, path string) any {
  156. t.Helper()
  157. var payload map[string]any
  158. require.NoError(t, common.Unmarshal([]byte(data), &payload))
  159. current := any(payload)
  160. for _, part := range strings.Split(path, ".") {
  161. m, ok := current.(map[string]any)
  162. require.Truef(t, ok, "%s is not an object at %s", path, part)
  163. current = m[part]
  164. }
  165. return current
  166. }