concurrent-session-limit.test.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { describe, expect, it } from "vitest";
  2. import {
  3. normalizeConcurrentSessionLimit,
  4. resolveKeyConcurrentSessionLimit,
  5. resolveKeyUserConcurrentSessionLimits,
  6. } from "@/lib/rate-limit/concurrent-session-limit";
  7. describe("resolveKeyConcurrentSessionLimit", () => {
  8. const cases: Array<{
  9. title: string;
  10. keyLimit: number | null | undefined;
  11. userLimit: number | null | undefined;
  12. expected: number;
  13. }> = [
  14. { title: "Key > 0 时应优先使用 Key", keyLimit: 10, userLimit: 15, expected: 10 },
  15. { title: "Key 为 0 时应回退到 User", keyLimit: 0, userLimit: 15, expected: 15 },
  16. { title: "Key 为 null 时应回退到 User", keyLimit: null, userLimit: 15, expected: 15 },
  17. { title: "Key 为 undefined 时应回退到 User", keyLimit: undefined, userLimit: 15, expected: 15 },
  18. {
  19. title: "Key 为 NaN 时应回退到 User",
  20. keyLimit: Number.NaN,
  21. userLimit: 15,
  22. expected: 15,
  23. },
  24. {
  25. title: "Key 为 Infinity 时应回退到 User",
  26. keyLimit: Number.POSITIVE_INFINITY,
  27. userLimit: 15,
  28. expected: 15,
  29. },
  30. { title: "Key < 0 时应回退到 User", keyLimit: -1, userLimit: 15, expected: 15 },
  31. { title: "Key 为小数时应向下取整", keyLimit: 5.9, userLimit: 15, expected: 5 },
  32. { title: "Key 小数 < 1 时应回退到 User", keyLimit: 0.9, userLimit: 15, expected: 15 },
  33. { title: "User 为小数时应向下取整", keyLimit: 0, userLimit: 7.8, expected: 7 },
  34. {
  35. title: "Key 与 User 均未设置/无效时应返回 0(无限制)",
  36. keyLimit: undefined,
  37. userLimit: null,
  38. expected: 0,
  39. },
  40. {
  41. title: "Key 为 0 且 User 为 Infinity 时应返回 0(无限制)",
  42. keyLimit: 0,
  43. userLimit: Number.POSITIVE_INFINITY,
  44. expected: 0,
  45. },
  46. ];
  47. for (const testCase of cases) {
  48. it(testCase.title, () => {
  49. expect(resolveKeyConcurrentSessionLimit(testCase.keyLimit, testCase.userLimit)).toBe(
  50. testCase.expected
  51. );
  52. });
  53. }
  54. });
  55. describe("normalizeConcurrentSessionLimit", () => {
  56. const cases: Array<{ title: string; input: number | null | undefined; expected: number }> = [
  57. { title: "null 应归一化为 0", input: null, expected: 0 },
  58. { title: "undefined 应归一化为 0", input: undefined, expected: 0 },
  59. { title: "0 应归一化为 0", input: 0, expected: 0 },
  60. { title: "负数应归一化为 0", input: -1, expected: 0 },
  61. { title: "NaN 应归一化为 0", input: Number.NaN, expected: 0 },
  62. { title: "Infinity 应归一化为 0", input: Number.POSITIVE_INFINITY, expected: 0 },
  63. { title: "正整数应保持不变", input: 15, expected: 15 },
  64. { title: "小数应向下取整", input: 7.9, expected: 7 },
  65. { title: "小数 < 1 应向下取整为 0", input: 0.9, expected: 0 },
  66. ];
  67. for (const testCase of cases) {
  68. it(testCase.title, () => {
  69. expect(normalizeConcurrentSessionLimit(testCase.input)).toBe(testCase.expected);
  70. });
  71. }
  72. });
  73. describe("resolveKeyUserConcurrentSessionLimits", () => {
  74. it("Key 未设置且 User 已设置时:effectiveKeyLimit 应继承 User,且 enabled=true", () => {
  75. const result = resolveKeyUserConcurrentSessionLimits(0, 15);
  76. expect(result).toEqual({ effectiveKeyLimit: 15, normalizedUserLimit: 15, enabled: true });
  77. });
  78. it("Key 已设置且 User 已设置时:Key 优先,User 保留为 normalizedUserLimit", () => {
  79. const result = resolveKeyUserConcurrentSessionLimits(10, 15);
  80. expect(result).toEqual({ effectiveKeyLimit: 10, normalizedUserLimit: 15, enabled: true });
  81. });
  82. it("Key/User 均未设置时:enabled=false", () => {
  83. const result = resolveKeyUserConcurrentSessionLimits(0, null);
  84. expect(result).toEqual({ effectiveKeyLimit: 0, normalizedUserLimit: 0, enabled: false });
  85. });
  86. });