73 lines
3.4 KiB
Python
73 lines
3.4 KiB
Python
|
|
"""Project a file inventory into reviewed, runnable test entry points."""
|
||
|
|
import fnmatch
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
|
||
|
|
def relative_path(settings, item):
|
||
|
|
source = next((s for s in settings.sources if s["id"] == item["source_group"]), None)
|
||
|
|
if not source:
|
||
|
|
return None
|
||
|
|
try:
|
||
|
|
return Path(item["source_path"]).relative_to(Path(source["path"])).as_posix()
|
||
|
|
except ValueError:
|
||
|
|
return None
|
||
|
|
|
||
|
|
|
||
|
|
def definition(settings, item):
|
||
|
|
if item["kind"] == "managed":
|
||
|
|
return next((d for d in settings.test_definitions
|
||
|
|
if d.get("managed_profile") == item["config"]["profile"]), {})
|
||
|
|
path = relative_path(settings, item)
|
||
|
|
return next((d for d in settings.test_definitions
|
||
|
|
if d.get("source_group") == item["source_group"] and d.get("entry") == path), None)
|
||
|
|
|
||
|
|
|
||
|
|
def is_entry(settings, item):
|
||
|
|
return definition(settings, item) is not None
|
||
|
|
|
||
|
|
|
||
|
|
def members(settings, item, inventory):
|
||
|
|
spec = definition(settings, item)
|
||
|
|
if spec is None:
|
||
|
|
raise ValueError("此文件是内部源码,请从测试项目入口查看相关文件")
|
||
|
|
result = []
|
||
|
|
for candidate in inventory:
|
||
|
|
path = relative_path(settings, candidate)
|
||
|
|
match = next((m for m in spec.get("members", [])
|
||
|
|
if candidate["source_group"] == m["source_group"] and path is not None
|
||
|
|
and (m["pattern"] == "**/*" or fnmatch.fnmatchcase(path, m["pattern"]))), None)
|
||
|
|
if candidate["id"] != item["id"] and match is None:
|
||
|
|
continue
|
||
|
|
role = "entry" if candidate["id"] == item["id"] else (match or {}).get("role", "support")
|
||
|
|
if role == "support" and path and ("tests" in Path(path).parts or Path(path).name.startswith("release-")):
|
||
|
|
role = "self_test"
|
||
|
|
result.append({"id": candidate["id"], "name": Path(candidate["source_path"]).name,
|
||
|
|
"source_path": candidate["source_path"], "relative_path": path or Path(candidate["source_path"]).name,
|
||
|
|
"source_group": candidate["source_group"], "role": role, "status": candidate["status"]})
|
||
|
|
return sorted(result, key=lambda f: (f["role"] != "entry", f["source_group"], f["relative_path"]))
|
||
|
|
|
||
|
|
|
||
|
|
def describe(settings, item, inventory):
|
||
|
|
from .native_plans import public_execution
|
||
|
|
result = dict(item)
|
||
|
|
spec = definition(settings, item)
|
||
|
|
result["is_test"] = spec is not None
|
||
|
|
result["execution"] = public_execution(settings, item)
|
||
|
|
if spec is None:
|
||
|
|
result.update(test_kind="source", category="source", file_count=1, enabled=False)
|
||
|
|
return result
|
||
|
|
example = item.get("synthetic", False) or item["id"] in settings.example_script_ids
|
||
|
|
result.update(test_kind=spec.get("kind", "test"), category="example" if example else "test",
|
||
|
|
file_count=len(members(settings, item, inventory)))
|
||
|
|
if item["kind"] == "external" and item["name"] == Path(item["source_path"]).name:
|
||
|
|
result["name"] = spec.get("name", item["name"])
|
||
|
|
if not item.get("description"):
|
||
|
|
result["description"] = spec.get("description", "")
|
||
|
|
return result
|
||
|
|
|
||
|
|
|
||
|
|
def tests(settings, inventory, include_examples=False):
|
||
|
|
result = [describe(settings, item, inventory) for item in inventory if is_entry(settings, item)]
|
||
|
|
result = [item for item in result if include_examples or item["category"] != "example"]
|
||
|
|
return sorted(result, key=lambda s: (not s["enabled"], s["category"] == "example", s["source_group"], s["name"]))
|