summaryrefslogtreecommitdiffstats
path: root/library/python/testing/custom_linter_util
diff options
context:
space:
mode:
authoralevitskii <[email protected]>2025-09-04 10:00:21 +0300
committeralevitskii <[email protected]>2025-09-04 10:19:32 +0300
commit8da3e97c84353501738d1ff485708bf8b7185eb8 (patch)
treedfe1363035f5daa04064c8cdacc3835b3a5cdf90 /library/python/testing/custom_linter_util
parent4c3f3af78aac956c2d034edb4a0d7c778b9fe9d3 (diff)
DEPENDS on linter wrappers to get them exported to opensource
DEPENDS on linter wrappers to get them exported to oss commit_hash:286fa6981744f667a509749a33afcc3421903842
Diffstat (limited to 'library/python/testing/custom_linter_util')
-rw-r--r--library/python/testing/custom_linter_util/linter_params.py83
-rw-r--r--library/python/testing/custom_linter_util/reporter.py41
-rw-r--r--library/python/testing/custom_linter_util/tests/test_params.py83
-rw-r--r--library/python/testing/custom_linter_util/tests/test_reporter.py68
-rw-r--r--library/python/testing/custom_linter_util/tests/ya.make12
-rw-r--r--library/python/testing/custom_linter_util/ya.make12
6 files changed, 299 insertions, 0 deletions
diff --git a/library/python/testing/custom_linter_util/linter_params.py b/library/python/testing/custom_linter_util/linter_params.py
new file mode 100644
index 00000000000..d3d00b51465
--- /dev/null
+++ b/library/python/testing/custom_linter_util/linter_params.py
@@ -0,0 +1,83 @@
+# XXX: This module is used in linter tools in `tools/` which are run by test_tool.
+# test_tool and `tools/` have different release cycles. Beware when modifying.
+import argparse
+import json
+from dataclasses import dataclass
+from typing import Optional
+
+
+@dataclass
+class LinterArgs:
+ source_root: str
+ project_path: str
+ output_path: str
+ lint_name: str
+ depends: dict[str, str]
+ global_resources: dict[str, str]
+ configs: list[str]
+ extra_params: dict[str, str]
+ report_file: str
+ files: list[str]
+
+
+def get_params(raw_args: Optional[list[str]] = None) -> LinterArgs:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--params")
+ parser.add_argument("--source-root")
+ parser.add_argument("--project-path")
+ parser.add_argument("--output-path")
+ parser.add_argument("--lint-name", default="")
+ parser.add_argument("--depends", action="append")
+ parser.add_argument("--global-resource", action="append", dest="global_resources")
+ parser.add_argument("--config", action="append", dest="configs")
+ parser.add_argument("--extra-param", action="append", dest="extra_params")
+ parser.add_argument("--report-file", default="-")
+ parser.add_argument("files", nargs="*")
+ args = parser.parse_args(raw_args)
+
+ if args.params:
+ with open(args.params) as f:
+ params = json.load(f)
+ source_root = params["source_root"]
+ project_path = params["project_path"]
+ output_path = params["output_path"]
+ lint_name = params.get("lint_name", "")
+ depends = params.get("depends", {})
+ global_resources = params.get("global_resources", {})
+ configs = params.get("configs", [])
+ extra_params = params.get("extra_params", {})
+ report_file = params["report_file"]
+ files = params["files"]
+ else:
+ source_root = args.source_root
+ project_path = args.project_path
+ output_path = args.output_path
+ lint_name = args.lint_name
+ depends = _parse_kv_arg(args.depends, ":")
+ global_resources = _parse_kv_arg(args.global_resources, ":")
+ configs = args.configs if args.configs else []
+ extra_params = _parse_kv_arg(args.extra_params, "=")
+ report_file = args.report_file
+ files = args.files
+
+ return LinterArgs(
+ source_root=source_root,
+ project_path=project_path,
+ output_path=output_path,
+ lint_name=lint_name,
+ depends=depends,
+ global_resources=global_resources,
+ configs=configs,
+ extra_params=extra_params,
+ report_file=report_file,
+ files=files,
+ )
+
+
+def _parse_kv_arg(arg, sep):
+ result = {}
+ if arg:
+ for item in arg:
+ var, val = item.split(sep, 1)
+ result[var] = val
+ return result
diff --git a/library/python/testing/custom_linter_util/reporter.py b/library/python/testing/custom_linter_util/reporter.py
new file mode 100644
index 00000000000..5e3d11bd339
--- /dev/null
+++ b/library/python/testing/custom_linter_util/reporter.py
@@ -0,0 +1,41 @@
+# XXX: This module is used in linter tools in `tools/` which are run by test_tool.
+# test_tool and `tools/` have different release cycles. Beware when modifying.
+import json
+import sys
+from enum import Enum
+from typing import Optional
+
+
+class LintStatus(Enum):
+ GOOD = "GOOD"
+ FAIL = "FAIL"
+ SKIPPED = "SKIPPED"
+
+
+class LintReport():
+ def __init__(self):
+ self._report = {}
+
+ def add(self, file_name: str, status: LintStatus, message: str = "", elapsed: float = 0.0):
+ self._report[file_name] = {
+ "status": status.value,
+ "message": message,
+ "elapsed": elapsed,
+ }
+
+ def dump(self, report_file, pretty: Optional[bool] = None):
+ data = {
+ "report": self._report,
+ }
+ if report_file == "-":
+ if pretty is None:
+ pretty = True
+ self._do_dump(sys.stdout, data, pretty)
+ else:
+ with open(report_file, "w") as f:
+ self._do_dump(f, data, pretty)
+
+ @staticmethod
+ def _do_dump(dest, data, pretty):
+ indent = 4 if pretty else None
+ json.dump(data, dest, indent=indent)
diff --git a/library/python/testing/custom_linter_util/tests/test_params.py b/library/python/testing/custom_linter_util/tests/test_params.py
new file mode 100644
index 00000000000..025bb3eef22
--- /dev/null
+++ b/library/python/testing/custom_linter_util/tests/test_params.py
@@ -0,0 +1,83 @@
+import json
+
+from library.python.testing.custom_linter_util import linter_params
+from yatest.common import work_path
+
+
+SOURCE_ROOT = "TEST_SOURCE_ROOT"
+PROJECT_PATH = "TEST_PROJECT_PATH"
+OUTPUT_PATH = "TEST_OUTPUT_PATH"
+REPORT_FILE = "TEST_REPORT_FILE"
+LINT_NAME = "important-lint"
+DEPS = {
+ "dep1": "/path/to/dep1",
+ "dep2": "/path/to/dep2",
+}
+GLOBAL_RESOURCES = {
+ "TOOL1_GLOBAL_RESOURCES": "/path/to/resource1",
+ "TOOL2_GLOBAL_RESOURCES": "/path/to/resource2",
+}
+CONFIGS = ["path/to/config1", "path/to/config2"]
+EXTRA_PARAMS = {
+ "var1": "val1",
+ "var2": "val2",
+}
+FILES = ["file1.cpp", "file2.cpp"]
+
+EXPECTED = linter_params.LinterArgs(
+ source_root=SOURCE_ROOT,
+ project_path=PROJECT_PATH,
+ output_path=OUTPUT_PATH,
+ report_file=REPORT_FILE,
+ lint_name=LINT_NAME,
+ depends=DEPS,
+ global_resources=GLOBAL_RESOURCES,
+ configs=CONFIGS,
+ extra_params=EXTRA_PARAMS,
+ files=FILES,
+)
+
+
+def test_cmd_line_params():
+ raw_args = [
+ "--source-root", SOURCE_ROOT,
+ "--project-path", PROJECT_PATH,
+ "--output-path", OUTPUT_PATH,
+ "--report-file", REPORT_FILE,
+ "--lint-name", LINT_NAME,
+ ]
+ for rel, abs in DEPS.items():
+ raw_args += ["--depends", ":".join([rel, abs])]
+ for var, path in GLOBAL_RESOURCES.items():
+ raw_args += ["--global-resource", ":".join([var, path])]
+ for cfg in CONFIGS:
+ raw_args += ["--config", cfg]
+ for var, val in EXTRA_PARAMS.items():
+ raw_args += ["--extra-param", "=".join([var, val])]
+ raw_args += FILES
+
+ got = linter_params.get_params(raw_args)
+
+ assert got == EXPECTED
+
+
+def test_json_params():
+ params_file = work_path("params.josn")
+ params = {
+ "source_root": SOURCE_ROOT,
+ "project_path": PROJECT_PATH,
+ "output_path": OUTPUT_PATH,
+ "report_file": REPORT_FILE,
+ "lint_name": LINT_NAME,
+ "depends": DEPS,
+ "global_resources": GLOBAL_RESOURCES,
+ "configs": CONFIGS,
+ "extra_params": EXTRA_PARAMS,
+ "files": FILES,
+ }
+ with open(params_file, "w") as f:
+ json.dump(params, f)
+
+ got = linter_params.get_params(["--params", params_file])
+
+ assert got == EXPECTED
diff --git a/library/python/testing/custom_linter_util/tests/test_reporter.py b/library/python/testing/custom_linter_util/tests/test_reporter.py
new file mode 100644
index 00000000000..81bfa3c9ef0
--- /dev/null
+++ b/library/python/testing/custom_linter_util/tests/test_reporter.py
@@ -0,0 +1,68 @@
+import json
+
+from library.python.testing.custom_linter_util.reporter import LintReport, LintStatus
+from yatest.common import output_path, context
+
+
+def dump_and_load(report):
+ report_file = output_path(context.test_name)
+ report.dump(report_file=report_file)
+ with open(report_file) as f:
+ return json.load(f)
+
+
+def test_empty_report():
+ report = LintReport()
+ got = dump_and_load(report)
+ assert got == {"report": {}}
+
+
+def test_good_test():
+ report = LintReport()
+ report.add("file.cpp", LintStatus.GOOD)
+
+ got = dump_and_load(report)
+
+ assert got == {
+ "report": {
+ "file.cpp": {
+ "status": "GOOD",
+ "message": "",
+ "elapsed": 0.0,
+ }
+ }
+ }
+
+
+def test_skipped_test():
+ report = LintReport()
+ report.add("file.cpp", LintStatus.SKIPPED, "Generated file", elapsed=1.0)
+
+ got = dump_and_load(report)
+
+ assert got == {
+ "report": {
+ "file.cpp": {
+ "status": "SKIPPED",
+ "message": "Generated file",
+ "elapsed": 1.0,
+ }
+ }
+ }
+
+
+def test_failed_test():
+ report = LintReport()
+ report.add("file.cpp", LintStatus.FAIL, "Test failed", elapsed=2.0)
+
+ got = dump_and_load(report)
+
+ assert got == {
+ "report": {
+ "file.cpp": {
+ "status": "FAIL",
+ "message": "Test failed",
+ "elapsed": 2.0,
+ }
+ }
+ }
diff --git a/library/python/testing/custom_linter_util/tests/ya.make b/library/python/testing/custom_linter_util/tests/ya.make
new file mode 100644
index 00000000000..1fde32d937a
--- /dev/null
+++ b/library/python/testing/custom_linter_util/tests/ya.make
@@ -0,0 +1,12 @@
+PY3TEST()
+
+TEST_SRCS(
+ test_params.py
+ test_reporter.py
+)
+
+PEERDIR(
+ library/python/testing/custom_linter_util
+)
+
+END()
diff --git a/library/python/testing/custom_linter_util/ya.make b/library/python/testing/custom_linter_util/ya.make
new file mode 100644
index 00000000000..c761b09afcd
--- /dev/null
+++ b/library/python/testing/custom_linter_util/ya.make
@@ -0,0 +1,12 @@
+PY3_LIBRARY()
+
+PY_SRCS(
+ linter_params.py
+ reporter.py
+)
+
+END()
+
+RECURSE_FOR_TESTS(
+ tests
+)