diff --git a/scripts/tooling/tests/conftest.py b/scripts/tooling/tests/conftest.py new file mode 100644 index 0000000000..dd99175da5 --- /dev/null +++ b/scripts/tooling/tests/conftest.py @@ -0,0 +1,216 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +"""Shared pytest fixtures and test utilities.""" + +import json +from pathlib import Path + +import pytest +from lib.known_good import KnownGood, Module, load_known_good + +# --------------------------------------------------------------------------- +# Constants +# --------------------------------------------------------------------------- + +MINIMAL_JSON = { + "modules": { + "target_sw": { + "score_baselibs": { + "repo": "https://github.com/eclipse-score/baselibs.git", + "hash": "abc123", + } + } + }, + "timestamp": "2026-01-01T00:00:00+00:00Z", +} + +FULL_JSON = { + "modules": { + "target_sw": { + "score_baselibs": { + "repo": "https://github.com/eclipse-score/baselibs.git", + "hash": "158fe6a7b791c58f6eac5f7e4662b8db0cf9ac6e", + "bazel_patches": ["//patches/baselibs:003-acl-fixes-for-aarch64.patch"], + "metadata": { + "extra_test_config": [ + "//score/json:base_library=nlohmann", + "//score/memory/shared/flags:use_typedshmd=False", + ], + "exclude_test_targets": [ + "//score/language/safecpp/aborts_upon_exception:abortsuponexception_toolchain_test", + "//score/containers:dynamic_array_test", + "//score/mw/log/configuration:*", + "//score/json/examples:*", + ], + "langs": ["cpp"], + }, + }, + "score_persistency": { + "repo": "https://github.com/eclipse-score/persistency.git", + "hash": "438bf9b5c447fd41ad43b321679dd3d1b3a6c737", + "metadata": {"code_root_path": "//src/..."}, + }, + }, + "tooling": { + "score_crates": { + "repo": "https://github.com/eclipse-score/score-crates.git", + "hash": "90539da0fd3e7e23e01f2b4de1679f7dfadd3b6b", + }, + "score_itf": { + "repo": "https://github.com/eclipse-score/itf.git", + "hash": "44c75debab696a9c967455110a2c32f201159cdd", + }, + }, + }, + "timestamp": "2026-01-01T00:00:00+00:00Z", +} + +KNOWN_GOOD_JSON = Path(__file__).parents[3] / "known_good.json" + + +# --------------------------------------------------------------------------- +# Helper functions +# --------------------------------------------------------------------------- + + +def make_known_good(**overrides) -> KnownGood: + """Build a minimal KnownGood with one module. + + Args: + **overrides: Additional fields to override in the module data. + + Returns: + KnownGood instance with a single module in target_sw group. + """ + module_data = { + "repo": "https://github.com/eclipse-score/baselibs.git", + "hash": "abc123def456abc123def456abc123def456abc123", + **overrides, + } + module = Module.from_dict("score_baselibs", module_data) + return KnownGood( + modules={"target_sw": {"score_baselibs": module}}, + timestamp="2026-01-01T00:00:00+00:00Z", + ) + + +# --------------------------------------------------------------------------- +# Fixtures - File-based +# --------------------------------------------------------------------------- + + +@pytest.fixture +def minimal_json_file(tmp_path: Path) -> Path: + """Create a temporary JSON file with minimal known good data.""" + p = tmp_path / "known_good.json" + p.write_text(json.dumps(MINIMAL_JSON)) + return p + + +@pytest.fixture +def full_json_file(tmp_path: Path) -> Path: + """Create a temporary JSON file with full known good data.""" + p = tmp_path / "known_good.json" + p.write_text(json.dumps(FULL_JSON)) + return p + + +# --------------------------------------------------------------------------- +# Fixtures - KnownGood objects +# --------------------------------------------------------------------------- + + +@pytest.fixture +def minimal_known_good() -> KnownGood: + """Create a minimal KnownGood instance.""" + return make_known_good() + + +@pytest.fixture +def multi_group_known_good() -> KnownGood: + """Create a KnownGood instance with multiple groups.""" + m1 = Module.from_dict( + "score_baselibs", + { + "repo": "https://github.com/eclipse-score/baselibs.git", + "hash": "aaa", + }, + ) + m2 = Module.from_dict( + "score_crates", + { + "repo": "https://github.com/eclipse-score/score-crates.git", + "hash": "bbb", + }, + ) + return KnownGood( + modules={ + "target_sw": {"score_baselibs": m1}, + "tooling": {"score_crates": m2}, + }, + timestamp="2026-02-01T00:00:00+00:00Z", + ) + + +@pytest.fixture +def real_known_good() -> KnownGood: + """Load the actual known_good.json from the repository root.""" + return load_known_good(KNOWN_GOOD_JSON) + + +# --------------------------------------------------------------------------- +# Fixtures - Test data for check_approvals +# --------------------------------------------------------------------------- + + +@pytest.fixture +def modules_maintainers(): + """Sample modules and maintainers for testing.""" + return { + "module_a": [ + { + "name": "Alice Developer", + "email": "alice@example.com", + "github": "alice", + "github_user_id": 100, + }, + { + "name": "Bob Developer", + "email": "bob@example.com", + "github": "bob", + "github_user_id": 101, + }, + ], + "module_b": [ + { + "name": "Charlie Developer", + "email": "charlie@example.com", + "github": "charlie", + "github_user_id": 102, + } + ], + "module_c": [ + { + "name": "Diana Developer", + "email": "diana@example.com", + "github": "diana", + "github_user_id": 103, + }, + { + "name": "Eve Developer", + "email": "eve@example.com", + "github": "eve", + "github_user_id": 104, + }, + ], + } diff --git a/scripts/tooling/tests/test_check_approvals.py b/scripts/tooling/tests/test_check_approvals.py index 93ad686d3a..e3ff5ed83d 100644 --- a/scripts/tooling/tests/test_check_approvals.py +++ b/scripts/tooling/tests/test_check_approvals.py @@ -18,49 +18,6 @@ from scripts.tooling.cli.release.check_approvals import check_pr_reviews -@pytest.fixture -def modules_maintainers(): - """Sample modules and maintainers for testing.""" - return { - "module_a": [ - { - "name": "Alice Developer", - "email": "alice@example.com", - "github": "alice", - "github_user_id": 100, - }, - { - "name": "Bob Developer", - "email": "bob@example.com", - "github": "bob", - "github_user_id": 101, - }, - ], - "module_b": [ - { - "name": "Charlie Developer", - "email": "charlie@example.com", - "github": "charlie", - "github_user_id": 102, - } - ], - "module_c": [ - { - "name": "Diana Developer", - "email": "diana@example.com", - "github": "diana", - "github_user_id": 103, - }, - { - "name": "Eve Developer", - "email": "eve@example.com", - "github": "eve", - "github_user_id": 104, - }, - ], - } - - def _create_mock_review(user_id: int, username: str, state: str, submitted_at: datetime) -> Mock: """Create a mock GitHub review object. diff --git a/scripts/tooling/tests/test_known_good.py b/scripts/tooling/tests/test_known_good.py index 797a3992fc..2b23eddae1 100644 --- a/scripts/tooling/tests/test_known_good.py +++ b/scripts/tooling/tests/test_known_good.py @@ -11,48 +11,11 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* import json -import pytest from pathlib import Path +import pytest from lib.known_good import KnownGood, Metadata, Module, load_known_good - -KNOWN_GOOD_JSON = Path(__file__).parents[3] / "known_good.json" - -MINIMAL_JSON = { - "modules": { - "target_sw": { - "score_baselibs": { - "repo": "https://github.com/eclipse-score/baselibs.git", - "hash": "abc123", - } - } - }, - "timestamp": "2026-01-01T00:00:00+00:00Z", -} - - -# --------------------------------------------------------------------------- -# Fixtures -# --------------------------------------------------------------------------- - - -@pytest.fixture -def minimal_json_file(tmp_path: Path) -> Path: - p = tmp_path / "known_good.json" - p.write_text(json.dumps(MINIMAL_JSON)) - return p - - -@pytest.fixture -def full_json_file(tmp_path: Path) -> Path: - """Copy the real known_good.json into a temp location.""" - content = KNOWN_GOOD_JSON.read_text(encoding="utf-8") - p = tmp_path / "known_good.json" - p.write_text(content) - return p - - # --------------------------------------------------------------------------- # load_known_good – happy path # --------------------------------------------------------------------------- @@ -100,12 +63,11 @@ def test_module_field_values(self, minimal_json_file: Path): # --------------------------------------------------------------------------- -# load_known_good – real file +# load_known_good – full file # --------------------------------------------------------------------------- -@pytest.mark.skipif(not KNOWN_GOOD_JSON.exists(), reason="known_good.json not found") -class TestLoadKnownGoodRealFile: +class TestLoadKnownGoodFullFile: def test_loads_without_error(self, full_json_file: Path): load_known_good(full_json_file) @@ -136,6 +98,42 @@ def test_owner_repo_property(self, full_json_file: Path): m = load_known_good(full_json_file).modules["target_sw"]["score_baselibs"] assert m.owner_repo == "eclipse-score/baselibs" + def test_metadata_extra_test_config(self, full_json_file: Path): + known_good = load_known_good(full_json_file) + baselibs = known_good.modules["target_sw"]["score_baselibs"] + persistency = known_good.modules["target_sw"]["score_persistency"] + assert baselibs.metadata.extra_test_config == [ + "//score/json:base_library=nlohmann", + "//score/memory/shared/flags:use_typedshmd=False", + ] + assert persistency.metadata.extra_test_config == [] + + def test_metadata_exclude_test_targets(self, full_json_file: Path): + known_good = load_known_good(full_json_file) + baselibs = known_good.modules["target_sw"]["score_baselibs"] + persistency = known_good.modules["target_sw"]["score_persistency"] + assert baselibs.metadata.exclude_test_targets == [ + "//score/language/safecpp/aborts_upon_exception:abortsuponexception_toolchain_test", + "//score/containers:dynamic_array_test", + "//score/mw/log/configuration:*", + "//score/json/examples:*", + ] + assert persistency.metadata.exclude_test_targets == [] + + def test_metadata_code_root_path(self, full_json_file: Path): + known_good = load_known_good(full_json_file) + baselibs = known_good.modules["target_sw"]["score_baselibs"] + persistency = known_good.modules["target_sw"]["score_persistency"] + assert baselibs.metadata.code_root_path == "//score/..." + assert persistency.metadata.code_root_path == "//src/..." + + def test_metadata_langs(self, full_json_file: Path): + known_good = load_known_good(full_json_file) + baselibs = known_good.modules["target_sw"]["score_baselibs"] + persistency = known_good.modules["target_sw"]["score_persistency"] + assert baselibs.metadata.langs == ["cpp"] + assert persistency.metadata.langs == ["cpp", "rust"] + # --------------------------------------------------------------------------- # Metadata defaults diff --git a/scripts/tooling/tests/test_report.py b/scripts/tooling/tests/test_report.py index 5b9a020177..2ddf21c441 100644 --- a/scripts/tooling/tests/test_report.py +++ b/scripts/tooling/tests/test_report.py @@ -12,70 +12,10 @@ # ******************************************************************************* import json import re -from pathlib import Path - -import pytest from cli.misc.html_report import TEMPLATE_DIR, generate_report, write_report -from lib.known_good import KnownGood, load_known_good -from lib.known_good.module import Metadata, Module - - -# --------------------------------------------------------------------------- -# Fixtures -# --------------------------------------------------------------------------- - -KNOWN_GOOD_JSON = Path(__file__).parents[3] / "known_good.json" - - -def _make_known_good(**overrides) -> KnownGood: - """Build a minimal KnownGood with one module.""" - module_data = { - "repo": "https://github.com/eclipse-score/baselibs.git", - "hash": "abc123def456abc123def456abc123def456abc123", - **overrides, - } - module = Module.from_dict("score_baselibs", module_data) - return KnownGood( - modules={"target_sw": {"score_baselibs": module}}, - timestamp="2026-01-01T00:00:00+00:00Z", - ) - - -@pytest.fixture -def minimal_known_good() -> KnownGood: - return _make_known_good() - - -@pytest.fixture -def multi_group_known_good() -> KnownGood: - m1 = Module.from_dict( - "score_baselibs", - { - "repo": "https://github.com/eclipse-score/baselibs.git", - "hash": "aaa", - }, - ) - m2 = Module.from_dict( - "score_crates", - { - "repo": "https://github.com/eclipse-score/score-crates.git", - "hash": "bbb", - }, - ) - return KnownGood( - modules={ - "target_sw": {"score_baselibs": m1}, - "tooling": {"score_crates": m2}, - }, - timestamp="2026-02-01T00:00:00+00:00Z", - ) - - -@pytest.fixture -def real_known_good() -> KnownGood: - return load_known_good(KNOWN_GOOD_JSON) - +from lib.known_good import KnownGood +from lib.known_good.module import Module # --------------------------------------------------------------------------- # generate_report – return type and structure @@ -284,7 +224,6 @@ def test_creates_parent_dirs_via_path(self, tmp_path, minimal_known_good): # --------------------------------------------------------------------------- -@pytest.mark.skipif(not KNOWN_GOOD_JSON.exists(), reason="known_good.json not found") class TestReportFromRealFile: def test_generates_without_error(self, real_known_good): html = generate_report(real_known_good, TEMPLATE_DIR)