token_cache_key_test.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. //go:build unit
  2. package service
  3. import (
  4. "testing"
  5. "github.com/stretchr/testify/require"
  6. )
  7. func TestGeminiTokenCacheKey(t *testing.T) {
  8. tests := []struct {
  9. name string
  10. account *Account
  11. expected string
  12. }{
  13. {
  14. name: "with_project_id",
  15. account: &Account{
  16. ID: 100,
  17. Credentials: map[string]any{
  18. "project_id": "my-project-123",
  19. },
  20. },
  21. expected: "gemini:my-project-123",
  22. },
  23. {
  24. name: "project_id_with_whitespace",
  25. account: &Account{
  26. ID: 101,
  27. Credentials: map[string]any{
  28. "project_id": " project-with-spaces ",
  29. },
  30. },
  31. expected: "gemini:project-with-spaces",
  32. },
  33. {
  34. name: "empty_project_id_fallback_to_account_id",
  35. account: &Account{
  36. ID: 102,
  37. Credentials: map[string]any{
  38. "project_id": "",
  39. },
  40. },
  41. expected: "gemini:account:102",
  42. },
  43. {
  44. name: "whitespace_only_project_id_fallback_to_account_id",
  45. account: &Account{
  46. ID: 103,
  47. Credentials: map[string]any{
  48. "project_id": " ",
  49. },
  50. },
  51. expected: "gemini:account:103",
  52. },
  53. {
  54. name: "no_project_id_key_fallback_to_account_id",
  55. account: &Account{
  56. ID: 104,
  57. Credentials: map[string]any{},
  58. },
  59. expected: "gemini:account:104",
  60. },
  61. {
  62. name: "nil_credentials_fallback_to_account_id",
  63. account: &Account{
  64. ID: 105,
  65. Credentials: nil,
  66. },
  67. expected: "gemini:account:105",
  68. },
  69. }
  70. for _, tt := range tests {
  71. t.Run(tt.name, func(t *testing.T) {
  72. result := GeminiTokenCacheKey(tt.account)
  73. require.Equal(t, tt.expected, result)
  74. })
  75. }
  76. }
  77. func TestAntigravityTokenCacheKey(t *testing.T) {
  78. tests := []struct {
  79. name string
  80. account *Account
  81. expected string
  82. }{
  83. {
  84. name: "with_project_id",
  85. account: &Account{
  86. ID: 200,
  87. Credentials: map[string]any{
  88. "project_id": "ag-project-456",
  89. },
  90. },
  91. expected: "ag:ag-project-456",
  92. },
  93. {
  94. name: "project_id_with_whitespace",
  95. account: &Account{
  96. ID: 201,
  97. Credentials: map[string]any{
  98. "project_id": " ag-project-spaces ",
  99. },
  100. },
  101. expected: "ag:ag-project-spaces",
  102. },
  103. {
  104. name: "empty_project_id_fallback_to_account_id",
  105. account: &Account{
  106. ID: 202,
  107. Credentials: map[string]any{
  108. "project_id": "",
  109. },
  110. },
  111. expected: "ag:account:202",
  112. },
  113. {
  114. name: "whitespace_only_project_id_fallback_to_account_id",
  115. account: &Account{
  116. ID: 203,
  117. Credentials: map[string]any{
  118. "project_id": " ",
  119. },
  120. },
  121. expected: "ag:account:203",
  122. },
  123. {
  124. name: "no_project_id_key_fallback_to_account_id",
  125. account: &Account{
  126. ID: 204,
  127. Credentials: map[string]any{},
  128. },
  129. expected: "ag:account:204",
  130. },
  131. {
  132. name: "nil_credentials_fallback_to_account_id",
  133. account: &Account{
  134. ID: 205,
  135. Credentials: nil,
  136. },
  137. expected: "ag:account:205",
  138. },
  139. }
  140. for _, tt := range tests {
  141. t.Run(tt.name, func(t *testing.T) {
  142. result := AntigravityTokenCacheKey(tt.account)
  143. require.Equal(t, tt.expected, result)
  144. })
  145. }
  146. }
  147. func TestOpenAITokenCacheKey(t *testing.T) {
  148. tests := []struct {
  149. name string
  150. account *Account
  151. expected string
  152. }{
  153. {
  154. name: "basic_account",
  155. account: &Account{
  156. ID: 300,
  157. },
  158. expected: "openai:account:300",
  159. },
  160. {
  161. name: "account_with_credentials",
  162. account: &Account{
  163. ID: 301,
  164. Credentials: map[string]any{
  165. "access_token": "test-token",
  166. },
  167. },
  168. expected: "openai:account:301",
  169. },
  170. {
  171. name: "account_id_zero",
  172. account: &Account{
  173. ID: 0,
  174. },
  175. expected: "openai:account:0",
  176. },
  177. {
  178. name: "large_account_id",
  179. account: &Account{
  180. ID: 9999999999,
  181. },
  182. expected: "openai:account:9999999999",
  183. },
  184. }
  185. for _, tt := range tests {
  186. t.Run(tt.name, func(t *testing.T) {
  187. result := OpenAITokenCacheKey(tt.account)
  188. require.Equal(t, tt.expected, result)
  189. })
  190. }
  191. }
  192. func TestGrokTokenCacheKey(t *testing.T) {
  193. tests := []struct {
  194. name string
  195. account *Account
  196. expected string
  197. }{
  198. {
  199. name: "basic_account",
  200. account: &Account{
  201. ID: 350,
  202. },
  203. expected: "grok:account:350",
  204. },
  205. {
  206. name: "account_with_email_uses_account_id",
  207. account: &Account{
  208. ID: 351,
  209. Credentials: map[string]any{
  210. "email": "same-user@example.com",
  211. },
  212. },
  213. expected: "grok:account:351",
  214. },
  215. {
  216. name: "account_id_zero",
  217. account: &Account{
  218. ID: 0,
  219. },
  220. expected: "grok:account:0",
  221. },
  222. {
  223. name: "nil_account",
  224. account: nil,
  225. expected: "grok:account:0",
  226. },
  227. }
  228. for _, tt := range tests {
  229. t.Run(tt.name, func(t *testing.T) {
  230. result := GrokTokenCacheKey(tt.account)
  231. require.Equal(t, tt.expected, result)
  232. })
  233. }
  234. }
  235. func TestGrokTokenCacheKeySeparatesAccountsWithSameEmail(t *testing.T) {
  236. first := &Account{
  237. ID: 351,
  238. Credentials: map[string]any{
  239. "email": "same-user@example.com",
  240. },
  241. }
  242. second := &Account{
  243. ID: 352,
  244. Credentials: map[string]any{
  245. "email": "same-user@example.com",
  246. },
  247. }
  248. require.NotEqual(t, GrokTokenCacheKey(first), GrokTokenCacheKey(second))
  249. }
  250. func TestClaudeTokenCacheKey(t *testing.T) {
  251. tests := []struct {
  252. name string
  253. account *Account
  254. expected string
  255. }{
  256. {
  257. name: "basic_account",
  258. account: &Account{
  259. ID: 400,
  260. },
  261. expected: "claude:account:400",
  262. },
  263. {
  264. name: "account_with_credentials",
  265. account: &Account{
  266. ID: 401,
  267. Credentials: map[string]any{
  268. "access_token": "claude-token",
  269. },
  270. },
  271. expected: "claude:account:401",
  272. },
  273. {
  274. name: "account_id_zero",
  275. account: &Account{
  276. ID: 0,
  277. },
  278. expected: "claude:account:0",
  279. },
  280. {
  281. name: "large_account_id",
  282. account: &Account{
  283. ID: 9999999999,
  284. },
  285. expected: "claude:account:9999999999",
  286. },
  287. }
  288. for _, tt := range tests {
  289. t.Run(tt.name, func(t *testing.T) {
  290. result := ClaudeTokenCacheKey(tt.account)
  291. require.Equal(t, tt.expected, result)
  292. })
  293. }
  294. }
  295. func TestCacheKeyUniqueness(t *testing.T) {
  296. // 确保不同平台的缓存键不会冲突
  297. account := &Account{ID: 123}
  298. openaiKey := OpenAITokenCacheKey(account)
  299. claudeKey := ClaudeTokenCacheKey(account)
  300. require.NotEqual(t, openaiKey, claudeKey, "OpenAI and Claude cache keys should be different")
  301. require.Contains(t, openaiKey, "openai:")
  302. require.Contains(t, claudeKey, "claude:")
  303. }