@@ -68,6 +68,9 @@ def is_deps_satisfied(req_col, req_ver, collections):
# If there is no version in the found layer, then don't use this layer.
if not existed_ver:
continue
+ # bb is not imported at module level; by now
+ # explode_dep_versions2() has put BitBake's lib on sys.path
+ import bb.utils
(op, dep_version) = req_ver.split()
success = bb.utils.vercmp_string_op(existed_ver, dep_version, op)
if success:
new file mode 100644
@@ -0,0 +1,42 @@
+# layerindex-web - tests for layerindex/utils.py
+#
+# Licensed under the MIT license, see COPYING.MIT for details
+#
+# SPDX-License-Identifier: MIT
+
+import operator
+import sys
+import types
+
+import pytest
+
+from layerindex import utils
+
+
+@pytest.fixture
+def fake_bb(monkeypatch):
+ """A stand-in for BitBake's bb.utils, which update.py imports from the
+ BitBake checkout at runtime. Versions here are plain integers."""
+ ops = {'>=': operator.ge, '>': operator.gt, '=': operator.eq, '<=': operator.le, '<': operator.lt}
+ bb = types.ModuleType('bb')
+ bb.utils = types.ModuleType('bb.utils')
+ bb.utils.vercmp_string_op = lambda a, b, op: ops[op](int(a), int(b))
+ monkeypatch.setitem(sys.modules, 'bb', bb)
+ monkeypatch.setitem(sys.modules, 'bb.utils', bb.utils)
+
+
+@pytest.mark.parametrize('req_ver, collections, expected', [
+ # No version constraint: any matching collection will do
+ (None, {('core', '15')}, True),
+ (None, {('core', '')}, True),
+ # Versioned constraint against the collection's LAYERVERSION
+ ('>= 12', {('core', '15')}, True),
+ ('>= 16', {('core', '15')}, False),
+ ('= 15', {('core', '15')}, True),
+ # A collection without a version can't satisfy a versioned constraint
+ ('>= 12', {('core', '')}, False),
+ # Other collections don't count
+ ('>= 12', {('other', '15')}, False),
+])
+def test_is_deps_satisfied(fake_bb, req_ver, collections, expected):
+ assert utils.is_deps_satisfied('core', req_ver, collections) is expected
is_deps_satisfied() calls bb.utils.vercmp_string_op() to check a versioned dependency such as LAYERDEPENDS_foo = "core (>= 12)", but utils.py never imports bb at module level: the import in explode_dep_versions2() only binds bb inside that function. So as soon as any layer had a versioned dependency on a collection with a LAYERVERSION, update.py stopped while sorting the layers, before updating any of them: File "layerindex/update.py", line 513, in main if utils.is_deps_satisfied(req_col, req_ver, collections): File "layerindex/utils.py", line 72, in is_deps_satisfied success = bb.utils.vercmp_string_op(existed_ver, dep_version, op) NameError: name 'bb' is not defined Import bb.utils where it is used, as the other functions here do; by then explode_dep_versions2() has put BitBake's lib directory on sys.path. AI-Generated: Claude Opus 5.5 Signed-off-by: Tim Orling <tim.orling@konsulko.com> --- layerindex/utils.py | 3 +++ tests/test_utils.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/test_utils.py