Skip to content

Commit b9135ce

Browse files
authored
Merge pull request #839 from LalatenduMohanty/838
Adding a test to validate working of resolver cache
2 parents 222f3f8 + 4662340 commit b9135ce

1 file changed

Lines changed: 84 additions & 0 deletions

File tree

tests/test_resolver.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,23 @@
3636
<!--SERIAL 22812307-->
3737
"""
3838

39+
_numpy_simple_response = """
40+
<!DOCTYPE html>
41+
<html>
42+
<head>
43+
<meta name="pypi:repository-version" content="1.1">
44+
<title>Links for numpy</title>
45+
</head>
46+
<body>
47+
<h1>Links for numpy</h1>
48+
<a href="https://files.pythonhosted.org/packages/numpy-1.24.0-py3-none-any.whl">numpy-1.24.0-py3-none-any.whl</a><br/>
49+
<a href="https://files.pythonhosted.org/packages/numpy-1.26.4-py3-none-any.whl">numpy-1.26.4-py3-none-any.whl</a><br/>
50+
<a href="https://files.pythonhosted.org/packages/numpy-2.0.0-py3-none-any.whl">numpy-2.0.0-py3-none-any.whl</a><br/>
51+
<a href="https://files.pythonhosted.org/packages/numpy-2.2.0-py3-none-any.whl">numpy-2.2.0-py3-none-any.whl</a><br/>
52+
</body>
53+
</html>
54+
"""
55+
3956

4057
@pytest.fixture(autouse=True)
4158
def reset_cache():
@@ -151,6 +168,73 @@ def test_provider_cache_key_github(github_fromager_resolver) -> None:
151168
assert provider.cache_key == "python-wheel-build/fromager"
152169

153170

171+
def test_cache_not_overly_aggressive() -> None:
172+
"""Test that resolver cache doesn't poison subsequent resolutions.
173+
174+
This test demonstrates the fix for issue #766 where the cache would
175+
store only candidates matching the first requirement's constraints,
176+
preventing subsequent less-constrained requirements from seeing
177+
newer versions.
178+
179+
Scenario:
180+
1. First requirement: numpy<2 (e.g., from aotriton build dependency)
181+
2. Second requirement: numpy (e.g., from torch build dependency)
182+
183+
Before the fix: Second resolution would incorrectly use numpy 1.26.4
184+
After the fix: Second resolution correctly uses numpy 2.2.0
185+
"""
186+
with requests_mock.Mocker() as r:
187+
r.get(
188+
"https://pypi.org/simple/numpy/",
189+
text=_numpy_simple_response,
190+
)
191+
192+
# First resolution: numpy<2 (simulating aotriton's build requirement)
193+
provider1 = resolver.PyPIProvider(include_sdists=False)
194+
reporter1: resolvelib.BaseReporter = resolvelib.BaseReporter()
195+
resolver1 = resolvelib.Resolver(provider1, reporter1)
196+
197+
result1 = resolver1.resolve([Requirement("numpy<2")])
198+
candidate1 = result1.mapping["numpy"]
199+
200+
assert candidate1.version == Version("1.26.4")
201+
202+
# Verify cache was populated with ALL candidates (not just <2)
203+
cache = resolver.BaseProvider.resolver_cache
204+
assert "numpy" in cache
205+
cached_candidates = cache["numpy"][
206+
(resolver.PyPIProvider, "https://pypi.org/simple/")
207+
]
208+
209+
# Critical: Cache should have ALL 4 versions, not just the 2 that matched numpy<2
210+
assert len(cached_candidates) == 4
211+
versions = {c.version for c in cached_candidates}
212+
assert versions == {
213+
Version("1.24.0"),
214+
Version("1.26.4"),
215+
Version("2.0.0"),
216+
Version("2.2.0"),
217+
}
218+
219+
# Second resolution: numpy (no constraint, simulating torch's build requirement)
220+
# This creates a new provider instance, but the cache is shared via the class-level
221+
# BaseProvider.resolver_cache, demonstrating that the cache works across instances
222+
provider2 = resolver.PyPIProvider(include_sdists=False)
223+
reporter2: resolvelib.BaseReporter = resolvelib.BaseReporter()
224+
resolver2 = resolvelib.Resolver(provider2, reporter2)
225+
226+
result2 = resolver2.resolve([Requirement("numpy")])
227+
candidate2 = result2.mapping["numpy"]
228+
229+
# Critical assertion: Should get latest version (2.2.0), not 1.26.4
230+
# This is the bug that issue #766 reported - before the fix, this would
231+
# incorrectly return 1.26.4 because the cache only had <2 versions
232+
assert candidate2.version == Version("2.2.0")
233+
234+
# Verify cache is still intact with all candidates
235+
assert len(cached_candidates) == 4
236+
237+
154238
def test_provider_choose_wheel_prereleases():
155239
with requests_mock.Mocker() as r:
156240
r.get(

0 commit comments

Comments
 (0)