api-key-vacuum-filter-reloading.test.ts 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
  2. function setEnv(values: Record<string, string | undefined>): void {
  3. for (const [key, value] of Object.entries(values)) {
  4. if (value === undefined) {
  5. // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
  6. delete process.env[key];
  7. } else {
  8. process.env[key] = value;
  9. }
  10. }
  11. }
  12. describe("ApiKeyVacuumFilter:重建窗口安全性", () => {
  13. const originalEnv: Record<string, string | undefined> = {};
  14. beforeEach(() => {
  15. vi.resetModules();
  16. // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
  17. delete (globalThis as unknown as { __CCH_API_KEY_VACUUM_FILTER__?: unknown })
  18. .__CCH_API_KEY_VACUUM_FILTER__;
  19. for (const k of ["NEXT_RUNTIME", "ENABLE_API_KEY_VACUUM_FILTER"]) {
  20. originalEnv[k] = process.env[k];
  21. }
  22. setEnv({
  23. NEXT_RUNTIME: "nodejs",
  24. ENABLE_API_KEY_VACUUM_FILTER: "true",
  25. });
  26. });
  27. afterEach(() => {
  28. setEnv(originalEnv);
  29. vi.unstubAllGlobals();
  30. vi.useRealTimers();
  31. // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
  32. delete (globalThis as unknown as { __CCH_API_KEY_VACUUM_FILTER__?: unknown })
  33. .__CCH_API_KEY_VACUUM_FILTER__;
  34. });
  35. test("loadingPromise 存在时应返回 null(不短路)", async () => {
  36. const [{ apiKeyVacuumFilter }, { VacuumFilter }] = await Promise.all([
  37. import("@/lib/security/api-key-vacuum-filter"),
  38. import("@/lib/vacuum-filter/vacuum-filter"),
  39. ]);
  40. const vf = new VacuumFilter({
  41. maxItems: 16,
  42. fingerprintBits: 32,
  43. maxKickSteps: 100,
  44. seed: "unit-test-reloading",
  45. });
  46. expect(vf.add("k1")).toBe(true);
  47. (apiKeyVacuumFilter as unknown as { vf: VacuumFilter }).vf = vf;
  48. (apiKeyVacuumFilter as unknown as { loadingPromise: Promise<void> | null }).loadingPromise =
  49. new Promise<void>(() => {});
  50. expect(apiKeyVacuumFilter.isDefinitelyNotPresent("k1")).toBeNull();
  51. expect(apiKeyVacuumFilter.isDefinitelyNotPresent("missing")).toBeNull();
  52. });
  53. test("ENABLE_API_KEY_VACUUM_FILTER=0:应禁用过滤器(不短路)", async () => {
  54. setEnv({ ENABLE_API_KEY_VACUUM_FILTER: "0" });
  55. const { apiKeyVacuumFilter } = await import("@/lib/security/api-key-vacuum-filter");
  56. expect(apiKeyVacuumFilter.getStats().enabled).toBe(false);
  57. expect(apiKeyVacuumFilter.isDefinitelyNotPresent("missing")).toBeNull();
  58. });
  59. test("未设置 ENABLE_API_KEY_VACUUM_FILTER:应默认启用(仅负向短路)", async () => {
  60. vi.resetModules();
  61. // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
  62. delete (globalThis as unknown as { __CCH_API_KEY_VACUUM_FILTER__?: unknown })
  63. .__CCH_API_KEY_VACUUM_FILTER__;
  64. setEnv({ NEXT_RUNTIME: "nodejs", ENABLE_API_KEY_VACUUM_FILTER: undefined });
  65. const { apiKeyVacuumFilter } = await import("@/lib/security/api-key-vacuum-filter");
  66. expect(apiKeyVacuumFilter.getStats().enabled).toBe(true);
  67. });
  68. });