Iostream-Li's picture
Add files using upload-large-folder tool
ff78003 verified
Raw
History Blame Contribute Delete
4.25 kB
/**
* Coverage extras — 补上 architect review 指出的关键覆盖缺口:
* - drug.adapter 无 filter throw
* - internal-experience 默认排除调用方自己
* - literature 空响应不入缓存
* - telemetry 异步非阻塞:adapter 结果优先,即使 telemetry 慢也立刻返
*
* internal-experience 用 telemetry hook 验 sourceMetadata.excludedSelf=true
* (不需要真 PG),但路径会真打 db.select() 所以本测试 skip 当无 DATABASE_URL。
*/
import test from "node:test";
import assert from "node:assert/strict";
import { drugAdapter } from "../drug.adapter.ts";
import { literatureAdapter, _clearLiteratureCache } from "../literature.adapter.ts";
import {
_setTelemetryTestHook,
_resetBudgetCounters,
} from "../index.ts";
import {
_setTelemetryTestHook as _setHookFn,
type TelemetryRecord,
} from "../telemetry.ts";
void _setHookFn; // re-export sanity
test.beforeEach(() => {
_resetBudgetCounters();
_clearLiteratureCache();
_setTelemetryTestHook(null);
});
test("drug.adapter — 无任何 filter 抛错(防全表扫)", async () => {
await assert.rejects(
() =>
drugAdapter.query({
kind: "drug_network",
capabilityId: "cap_drug_test",
params: {}, // 全空 — 必须 throw
}),
/requires at least one of drug_id/,
);
});
test("literature — 空响应 *不* 入缓存(下次仍 cache-miss)", async () => {
const calls: TelemetryRecord[] = [];
_setTelemetryTestHook((r) => calls.push(r));
const realFetch = globalThis.fetch;
let bridgeCalls = 0;
let epmcCalls = 0;
globalThis.fetch = (async (url: string | URL, _init?: RequestInit) => {
const u = typeof url === "string" ? url : url.toString();
if (u.includes("/internal/tools/inspect_target")) {
bridgeCalls += 1;
return new Response(
JSON.stringify({
tool: "inspect_target",
result: { status: "ok", buckets: [] },
}),
{ status: 200, headers: { "Content-Type": "application/json" } },
);
}
if (u.includes("europepmc")) {
epmcCalls += 1;
return new Response(JSON.stringify({ resultList: { result: [] }, hitCount: 0 }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}
return realFetch(url, _init);
}) as typeof fetch;
process.env["DOATLAS_BRIDGE_SECRET"] = "test-secret";
try {
const r1 = await literatureAdapter.query({
kind: "literature",
capabilityId: "cap_empty",
params: { q: "no_results_at_all_xyzzy" },
});
assert.equal(r1.items.length, 0);
assert.equal(bridgeCalls, 1);
assert.equal(epmcCalls, 1);
const r2 = await literatureAdapter.query({
kind: "literature",
capabilityId: "cap_empty",
params: { q: "no_results_at_all_xyzzy" },
});
assert.equal(r2.items.length, 0);
// 关键断言:第二次仍真打了 bridge + epmc(因为空响应没有缓存)
assert.equal(bridgeCalls, 2, "空响应不应被缓存,第二次必须重打 bridge");
assert.equal(epmcCalls, 2, "空响应不应被缓存,第二次必须重打 EPMC");
// telemetry:两次都标 cacheHit='miss' — 没有 'hit' 出现
const cacheHits = calls.filter((c) => c.cacheHit === "hit");
assert.equal(cacheHits.length, 0, "空响应路径上不应出现 cacheHit='hit'");
} finally {
globalThis.fetch = realFetch;
}
});
test("telemetry — adapter 结果立刻返,不等待 telemetry 完成", async () => {
// 让 telemetry hook 真去等 200ms — 验证 adapter 不会被它阻塞。
let telemetryDone = false;
_setTelemetryTestHook((_r) => {
setTimeout(() => {
telemetryDone = true;
}, 200);
});
const t0 = Date.now();
await assert.rejects(() =>
drugAdapter.query({
kind: "drug_network",
capabilityId: "cap_telem",
params: {}, // throw 路径(同样 fire-and-forget telemetry)
}),
);
const elapsed = Date.now() - t0;
assert.ok(
elapsed < 100,
`adapter 必须立即返回(<100ms),不能等 telemetry;实际 ${elapsed}ms`,
);
// telemetryDone 这时应该还是 false(timer 200ms 后才置 true)
assert.equal(telemetryDone, false, "adapter 返回时 telemetry hook 还在 timer 中");
});