chore: import upstream snapshot with attribution
OpenSSF Scorecard / scorecard (push) Failing after 0s
DCO / dco (push) Failing after 0s
CodeQL SAST / analyze (push) Failing after 1s
Deploy Pages / deploy (push) Failing after 1s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:28:05 +08:00
commit 41cb1c0170
1830 changed files with 38276124 additions and 0 deletions
+271
View File
@@ -0,0 +1,271 @@
/*
* test_py_lsp_bench.c — parity-tracking benchmark for py_lsp.
*
* The fixture is a synthetic but representative ~250-line Python file
* that exercises every parity feature py_lsp implements:
* - imports + dotted submodule walks (os.path)
* - dataclass + class-body annotated fields
* - inheritance with super() calls (method + __init__)
* - Self return type (fluent chains)
* - generic containers + comprehension element typing
* - dict / list / tuple subscript value types
* - narrowing (isinstance / is not None / walrus + None)
* - match/case class patterns
* - async / await
* - classmethod / staticmethod
* - @property attribute access
* - SQLAlchemy 2.0-style Mapped[T] annotations
* - Pydantic-style BaseModel with field annotations
* - typing.Annotated / ClassVar / Final / InitVar wrappers
* - generator yield with for-loop element typing
* - operator dunder dispatch
* - typing.cast / assert_type
* - common stdlib calls (logging, pathlib, json, functools)
*
* Asserts: resolution ratio >= 50% under sanitizers (production target
* is 95%+ — see docs/BENCHMARK_PYTHON.md).
*/
#include "test_framework.h"
#include "cbm.h"
#include "lsp/py_lsp.h"
#include <stdlib.h>
#include <time.h>
static const char *bench_source =
"import os\n"
"import os.path\n"
"import json\n"
"import logging\n"
"import functools\n"
"from dataclasses import dataclass, field\n"
"from pathlib import Path\n"
"from collections import defaultdict\n"
"from typing import (\n"
" Optional, Self, cast, ClassVar, Final, Annotated, Generator,\n"
" NamedTuple, Protocol\n"
")\n"
"\n"
"log = logging.getLogger('bench')\n"
"\n"
"@dataclass\n"
"class Config:\n"
" name: str\n"
" debug: bool\n"
" extras: list[str]\n"
" LIMIT: ClassVar[int] = 100\n"
" def display(self) -> str:\n"
" return self.name\n"
" def with_debug(self, on: bool) -> Self:\n"
" self.debug = on\n"
" return self\n"
"\n"
"class Mapped:\n"
" pass\n"
"\n"
"class User:\n"
" id: Annotated[int, 'primary_key']\n"
" name: Final[str]\n"
" email: str\n"
" posts: list[str]\n"
" def __init__(self, id: int, name: str, email: str):\n"
" self.id = id\n"
" self.name = name\n"
" self.email = email\n"
" self.posts = []\n"
" def display_name(self) -> str:\n"
" return self.name\n"
" @property\n"
" def domain(self) -> str:\n"
" return self.email.split('@')[1]\n"
"\n"
"class BaseStore:\n"
" def __init__(self, root: Path):\n"
" self.root: Path = root\n"
" self.metadata: dict[str, str] = {}\n"
" def get(self, key: str) -> Optional[str]:\n"
" return self.metadata.get(key)\n"
" def put(self, key: str, value: str) -> None:\n"
" self.metadata[key] = value\n"
" def keys(self) -> list[str]:\n"
" return list(self.metadata.keys())\n"
"\n"
"class FileStore(BaseStore):\n"
" def __init__(self, root: Path):\n"
" super().__init__(root)\n"
" self.cache: dict[str, str] = {}\n"
" @classmethod\n"
" def open(cls, root: Path) -> Self:\n"
" return cls(root)\n"
" @staticmethod\n"
" def is_writable(p: Path) -> bool:\n"
" return True\n"
" def get(self, key: str) -> Optional[str]:\n"
" if key in self.cache:\n"
" return self.cache[key]\n"
" full = self.root / key\n"
" if full.exists():\n"
" text = full.read_text()\n"
" self.cache[key] = text\n"
" return text\n"
" return None\n"
" def put(self, key: str, value: str) -> None:\n"
" super().put(key, value)\n"
" self.cache[key] = value\n"
"\n"
"class Result:\n"
" def __init__(self, ok: bool, value: Optional[str]):\n"
" self.ok = ok\n"
" self.value = value\n"
" def display(self) -> str:\n"
" return self.value or 'empty'\n"
"\n"
"class App:\n"
" def __init__(self, cfg: Config, store: BaseStore):\n"
" self.cfg = cfg\n"
" self.store = store\n"
" self.users: dict[int, User] = {}\n"
" self.counts: dict[str, int] = defaultdict(int)\n"
" self.logger = logging.getLogger('app')\n"
" def display_config(self) -> str:\n"
" return self.cfg.display()\n"
" def add_user(self, u: User) -> None:\n"
" self.users[u.id] = u\n"
" self.logger.info('added %s', u.display_name())\n"
" def get_user(self, uid: int) -> Optional[User]:\n"
" return self.users.get(uid)\n"
" def lookup(self, key: str) -> Result:\n"
" result = self.store.get(key)\n"
" self.counts[key] += 1\n"
" return Result(result is not None, result)\n"
" def write(self, key: str, value: str) -> None:\n"
" self.store.put(key, value)\n"
" self.logger.info('wrote %s', key)\n"
" def display_results(self, results: list[Result]) -> list[str]:\n"
" return [r.display() for r in results]\n"
" def display_users(self) -> list[str]:\n"
" return [u.display_name() for u in self.users.values()]\n"
" def filter_active(self, keys: list[str]) -> list[str]:\n"
" return [k for k in keys if self.lookup(k).ok]\n"
" def with_debug(self) -> Self:\n"
" self.cfg = self.cfg.with_debug(True)\n"
" return self\n"
"\n"
"@functools.lru_cache(maxsize=128)\n"
"def slow_lookup(key: str) -> Optional[str]:\n"
" return None\n"
"\n"
"def parse_response(payload: str) -> dict[str, str]:\n"
" return json.loads(payload)\n"
"\n"
"async def fetch(key: str) -> Optional[str]:\n"
" return slow_lookup(key)\n"
"\n"
"async def fetch_many(keys: list[str]) -> list[Optional[str]]:\n"
" out: list[Optional[str]] = []\n"
" for k in keys:\n"
" v = await fetch(k)\n"
" out.append(v)\n"
" return out\n"
"\n"
"def gen_users(n: int) -> Generator[User, None, None]:\n"
" for i in range(n):\n"
" yield User(i, 'name' + str(i), 'a@b.com')\n"
"\n"
"def classify(x) -> str:\n"
" match x:\n"
" case Config():\n"
" return x.display()\n"
" case User():\n"
" return x.display_name()\n"
" case Result():\n"
" return x.display()\n"
" case App():\n"
" return x.display_config()\n"
" case _:\n"
" return 'unknown'\n"
"\n"
"def maybe_get(s: Optional[BaseStore], key: str) -> Optional[str]:\n"
" if s is not None:\n"
" return s.get(key)\n"
" return None\n"
"\n"
"def first_writable(stores: list[BaseStore]) -> Optional[BaseStore]:\n"
" for s in stores:\n"
" if isinstance(s, FileStore):\n"
" return s\n"
" return None\n"
"\n"
"def main() -> None:\n"
" cfg = Config('app', True, ['x', 'y'])\n"
" fs = FileStore.open(Path(os.getcwd()))\n"
" app = App(cfg, fs)\n"
" app.with_debug().write('a', '1')\n"
" res = app.lookup('a')\n"
" classify(cfg)\n"
" classify(res)\n"
" classify(app)\n"
" payload = parse_response('{}')\n"
" log.info('payload=%s', payload)\n"
" for u in gen_users(3):\n"
" app.add_user(u)\n"
" summary = app.display_users()\n"
" log.info('users=%d', len(summary))\n";
static double elapsed_ms(struct timespec t0, struct timespec t1) {
double s = (double)(t1.tv_sec - t0.tv_sec);
double ns = (double)(t1.tv_nsec - t0.tv_nsec);
return s * 1000.0 + ns / 1000000.0;
}
TEST(pylsp_bench_resolution_ratio) {
/* Perf benchmark: time-budgeted. Under ASan+UBSan the budget is scaled up
* (see the sanitizer-aware budget below) and the result is freed before
* asserting so a budget miss doesn't leak. */
int slen = (int)strlen(bench_source);
struct timespec t0;
struct timespec t1;
clock_gettime(CLOCK_MONOTONIC, &t0);
CBMFileResult *r = cbm_extract_file(bench_source, slen, CBM_LANG_PYTHON,
"test", "bench.py", 0, NULL, NULL);
clock_gettime(CLOCK_MONOTONIC, &t1);
ASSERT_NOT_NULL(r);
double ms = elapsed_ms(t0, t1);
int calls = r->calls.count;
int resolved = r->resolved_calls.count;
int loc = 0;
for (const char *p = bench_source; *p; p++) {
if (*p == '\n') loc++;
}
double ratio = calls > 0 ? (double)resolved / (double)calls : 0.0;
printf(" bench: %d lines, %d calls, %d resolved (%.0f%%), %.2f ms\n",
loc, calls, resolved, ratio * 100.0, ms);
/* Free the result BEFORE asserting so a budget miss doesn't leak. */
cbm_free_result(r);
ASSERT_GTE(calls, 1);
ASSERT_GTE(resolved, 1);
/* Floor at 50% under sanitizers; production target is 95% per
* docs/BENCHMARK_PYTHON.md. */
if (calls >= 30) {
ASSERT_GTE(resolved * 2, calls);
}
/* Time budget. ASan+UBSan instrumentation slows the parse ~5-10×, so
* scale the budget when a sanitizer is active. Native: 150 ms for a
* ~200-line fixture; sanitized: 1500 ms. */
#ifdef __SANITIZE_ADDRESS__
ASSERT(ms < 1500.0);
#else
ASSERT(ms < 150.0);
#endif
PASS();
}
SUITE(py_lsp_bench) {
RUN_TEST(pylsp_bench_resolution_ratio);
}