Coverage for tests/tool_version_constraints_test.py: 100%
45 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-17 19:08 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-17 19:08 +0000
1#
2# --------------------------------------------------------------------------------
3# SPDX-FileCopyrightText: 2024-2026 Martin Jan Köhler and Harald Pretl
4# Johannes Kepler University, Institute for Integrated Circuits.
5#
6# This file is part of KPEX
7# (see https://github.com/iic-jku/klayout-pex).
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
21# SPDX-License-Identifier: GPL-3.0-or-later
22# --------------------------------------------------------------------------------
23#
25from __future__ import annotations
27import unittest
29import allure
30from packaging.specifiers import SpecifierSet
31from packaging.version import Version
33from klayout_pex.pdk_config import PDK
34from klayout_pex.tool_version_constraints import (
35 TOOL_VERSION_CONSTRAINTS,
36 Severity,
37 Tool,
38 ToolVersionConstraint,
39 applicable_constraints,
40 effective_version_range,
41)
44@allure.parent_suite('Unit Tests')
45@allure.tag('Tool Versions', 'Version Constraints')
46class Test(unittest.TestCase):
47 def test_magic_reports_its_patch_level_as_a_revision(self):
48 # the banner every MAGIC run prints, and what 'magic --version' gives
49 assert Tool.MAGIC.parse_version(
50 'Magic 8.3 revision 681 - Compiled on Di. 11 Aug. 2026 15:53:45 CEST.'
51 ) == Version('8.3.681')
52 assert Tool.MAGIC.parse_version('8.3.681') == Version('8.3.681')
53 assert Tool.MAGIC.parse_version('no version in here') is None
55 def test_a_packaging_release_is_not_part_of_the_tool_version(self):
56 assert Tool.KLAYOUT.parse_version('KLayout 0.30.4') == Version('0.30.4')
57 assert Tool.KLAYOUT.parse_version('klayout_0.30.4-1_amd64') == Version('0.30.4')
58 assert Tool.FASTERCAP.parse_version('FasterCap 6.0.9') == Version('6.0.9')
60 def test_constraints_compile_to_one_effective_range(self):
61 assert effective_version_range(Tool.KLAYOUT) == SpecifierSet('>=0.30.1,>=0.30.2,>=0.30.3')
62 assert effective_version_range(Tool.KLAYOUT).contains(Version('0.30.4'))
63 assert not effective_version_range(Tool.KLAYOUT).contains(Version('0.30.2'))
65 def test_a_pdk_constraint_is_part_of_that_pdk_s_range(self):
66 for_sky130a = effective_version_range(Tool.MAGIC, pdk=PDK.SKY130A)
67 assert for_sky130a == effective_version_range(Tool.MAGIC)
68 assert {c.tool for c in applicable_constraints(Tool.MAGIC, PDK.SKY130A)} == {Tool.MAGIC}
70 def test_an_excluded_version_is_the_only_one_rejected(self):
71 constraint = ToolVersionConstraint(
72 id='TEST_EXCLUSION', tool=Tool.KLAYOUT, specifier='!= 0.30.5',
73 reason="a hypothetical regression")
74 assert constraint.is_satisfied_by(Version('0.30.4'))
75 assert not constraint.is_satisfied_by(Version('0.30.5'))
76 assert constraint.is_satisfied_by(Version('0.30.6'))
78 def test_a_pdk_constraint_applies_only_to_that_pdk(self):
79 constraint = ToolVersionConstraint(
80 id='TEST_PDK_SCOPED', tool=Tool.MAGIC, specifier='>= 8.3.540',
81 reason="a PDK-specific requirement", pdk=PDK.SKY130A)
82 assert constraint.applies_to(PDK.SKY130A)
83 assert not constraint.applies_to(PDK.IHP_SG13G2)
84 assert not constraint.applies_to(None)
86 def test_every_declared_constraint_is_well_formed(self):
87 ids = [c.id for c in TOOL_VERSION_CONSTRAINTS]
88 assert len(ids) == len(set(ids)), "constraint IDs have to be unique"
89 for constraint in TOOL_VERSION_CONSTRAINTS:
90 with self.subTest(constraint=constraint.id):
91 assert constraint.id.isupper()
92 assert constraint.reason, "a constraint has to say why it exists"
93 assert constraint.severity in (Severity.ERROR, Severity.WARNING)
94 assert str(constraint.specifier_set) != ''