channel_upstream_update_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package controller
  2. import (
  3. "testing"
  4. "github.com/QuantumNous/new-api/dto"
  5. "github.com/QuantumNous/new-api/model"
  6. "github.com/stretchr/testify/require"
  7. )
  8. func TestNormalizeModelNames(t *testing.T) {
  9. result := normalizeModelNames([]string{
  10. " gpt-4o ",
  11. "",
  12. "gpt-4o",
  13. "gpt-4.1",
  14. " ",
  15. })
  16. require.Equal(t, []string{"gpt-4o", "gpt-4.1"}, result)
  17. }
  18. func TestMergeModelNames(t *testing.T) {
  19. result := mergeModelNames(
  20. []string{"gpt-4o", "gpt-4.1"},
  21. []string{"gpt-4.1", " gpt-4.1-mini ", "gpt-4o"},
  22. )
  23. require.Equal(t, []string{"gpt-4o", "gpt-4.1", "gpt-4.1-mini"}, result)
  24. }
  25. func TestSubtractModelNames(t *testing.T) {
  26. result := subtractModelNames(
  27. []string{"gpt-4o", "gpt-4.1", "gpt-4.1-mini"},
  28. []string{"gpt-4.1", "not-exists"},
  29. )
  30. require.Equal(t, []string{"gpt-4o", "gpt-4.1-mini"}, result)
  31. }
  32. func TestIntersectModelNames(t *testing.T) {
  33. result := intersectModelNames(
  34. []string{"gpt-4o", "gpt-4.1", "gpt-4.1", "not-exists"},
  35. []string{"gpt-4.1", "gpt-4o-mini", "gpt-4o"},
  36. )
  37. require.Equal(t, []string{"gpt-4o", "gpt-4.1"}, result)
  38. }
  39. func TestApplySelectedModelChanges(t *testing.T) {
  40. t.Run("add and remove together", func(t *testing.T) {
  41. result := applySelectedModelChanges(
  42. []string{"gpt-4o", "gpt-4.1", "claude-3"},
  43. []string{"gpt-4.1-mini"},
  44. []string{"claude-3"},
  45. )
  46. require.Equal(t, []string{"gpt-4o", "gpt-4.1", "gpt-4.1-mini"}, result)
  47. })
  48. t.Run("add wins when conflict with remove", func(t *testing.T) {
  49. result := applySelectedModelChanges(
  50. []string{"gpt-4o"},
  51. []string{"gpt-4.1"},
  52. []string{"gpt-4.1"},
  53. )
  54. require.Equal(t, []string{"gpt-4o", "gpt-4.1"}, result)
  55. })
  56. }
  57. func TestCollectPendingApplyUpstreamModelChanges(t *testing.T) {
  58. settings := dto.ChannelOtherSettings{
  59. UpstreamModelUpdateLastDetectedModels: []string{" gpt-4o ", "gpt-4o", "gpt-4.1"},
  60. UpstreamModelUpdateLastRemovedModels: []string{" old-model ", "", "old-model"},
  61. }
  62. pendingAddModels, pendingRemoveModels := collectPendingApplyUpstreamModelChanges(settings)
  63. require.Equal(t, []string{"gpt-4o", "gpt-4.1"}, pendingAddModels)
  64. require.Equal(t, []string{"old-model"}, pendingRemoveModels)
  65. }
  66. func TestChannelUpstreamModelUpdateSelectFieldsIncludeModelMapping(t *testing.T) {
  67. require.Contains(t, channelUpstreamModelUpdateSelectFields, "model_mapping")
  68. }
  69. func TestNormalizeChannelModelMapping(t *testing.T) {
  70. modelMapping := `{
  71. " alias-model ": " upstream-model ",
  72. "": "invalid",
  73. "invalid-target": ""
  74. }`
  75. channel := &model.Channel{
  76. ModelMapping: &modelMapping,
  77. }
  78. result := normalizeChannelModelMapping(channel)
  79. require.Equal(t, map[string]string{
  80. "alias-model": "upstream-model",
  81. }, result)
  82. }
  83. func TestCollectPendingUpstreamModelChangesFromModels_WithModelMapping(t *testing.T) {
  84. pendingAddModels, pendingRemoveModels := collectPendingUpstreamModelChangesFromModels(
  85. []string{"alias-model", "gpt-4o", "stale-model"},
  86. []string{"gpt-4o", "gpt-4.1", "mapped-target"},
  87. []string{"gpt-4.1"},
  88. map[string]string{
  89. "alias-model": "mapped-target",
  90. },
  91. )
  92. require.Equal(t, []string{}, pendingAddModels)
  93. require.Equal(t, []string{"stale-model"}, pendingRemoveModels)
  94. }
  95. func TestCollectPendingUpstreamModelChangesFromModels_WithIgnoredRegexPatterns(t *testing.T) {
  96. pendingAddModels, pendingRemoveModels := collectPendingUpstreamModelChangesFromModels(
  97. []string{"gpt-4o"},
  98. []string{"gpt-4o", "claude-3-5-sonnet", "sora-video", "gpt-4.1"},
  99. []string{"regex:^sora-.*$", "gpt-4.1"},
  100. nil,
  101. )
  102. require.Equal(t, []string{"claude-3-5-sonnet"}, pendingAddModels)
  103. require.Equal(t, []string{}, pendingRemoveModels)
  104. }
  105. func TestBuildUpstreamModelUpdateTaskNotificationContent_OmitOverflowDetails(t *testing.T) {
  106. channelSummaries := make([]upstreamModelUpdateChannelSummary, 0, 12)
  107. for i := 0; i < 12; i++ {
  108. channelSummaries = append(channelSummaries, upstreamModelUpdateChannelSummary{
  109. ChannelName: "channel-" + string(rune('A'+i)),
  110. AddCount: i + 1,
  111. RemoveCount: i,
  112. })
  113. }
  114. content := buildUpstreamModelUpdateTaskNotificationContent(
  115. 24,
  116. 12,
  117. 56,
  118. 21,
  119. 9,
  120. []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
  121. channelSummaries,
  122. []string{
  123. "gpt-4.1", "gpt-4.1-mini", "o3", "o4-mini", "gemini-2.5-pro", "claude-3.7-sonnet",
  124. "qwen-max", "deepseek-r1", "llama-3.3-70b", "mistral-large", "command-r-plus", "doubao-pro-32k",
  125. "hunyuan-large",
  126. },
  127. []string{
  128. "gpt-3.5-turbo", "claude-2.1", "gemini-1.5-pro", "mixtral-8x7b", "qwen-plus", "glm-4",
  129. "yi-large", "moonshot-v1", "doubao-lite",
  130. },
  131. )
  132. require.Contains(t, content, "其余 4 个渠道已省略")
  133. require.Contains(t, content, "其余 1 个已省略")
  134. require.Contains(t, content, "失败渠道 ID(展示 10/12)")
  135. require.Contains(t, content, "其余 2 个已省略")
  136. }
  137. func TestShouldSendUpstreamModelUpdateNotification(t *testing.T) {
  138. channelUpstreamModelUpdateNotifyState.Lock()
  139. channelUpstreamModelUpdateNotifyState.lastNotifiedAt = 0
  140. channelUpstreamModelUpdateNotifyState.lastChangedChannels = 0
  141. channelUpstreamModelUpdateNotifyState.lastFailedChannels = 0
  142. channelUpstreamModelUpdateNotifyState.Unlock()
  143. baseTime := int64(2000000)
  144. require.True(t, shouldSendUpstreamModelUpdateNotification(baseTime, 6, 0))
  145. require.False(t, shouldSendUpstreamModelUpdateNotification(baseTime+3600, 6, 0))
  146. require.True(t, shouldSendUpstreamModelUpdateNotification(baseTime+3600, 7, 0))
  147. require.False(t, shouldSendUpstreamModelUpdateNotification(baseTime+7200, 7, 0))
  148. require.True(t, shouldSendUpstreamModelUpdateNotification(baseTime+8000, 0, 3))
  149. require.False(t, shouldSendUpstreamModelUpdateNotification(baseTime+9000, 0, 3))
  150. require.True(t, shouldSendUpstreamModelUpdateNotification(baseTime+10000, 0, 4))
  151. require.True(t, shouldSendUpstreamModelUpdateNotification(baseTime+90000, 7, 0))
  152. require.True(t, shouldSendUpstreamModelUpdateNotification(baseTime+90001, 0, 0))
  153. }