Skip to content

Commit

Permalink
test for integrity remove (#17628)
Browse files Browse the repository at this point in the history
* test for integrity remove

* manifest and conaninfo.txt corruptions

* more checks in tests
  • Loading branch information
memsharded authored Jan 27, 2025
1 parent 2cb50a2 commit c1b4db5
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
10 changes: 6 additions & 4 deletions conan/api/subapi/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,10 +394,12 @@ def _get_cache_packages_binary_info(cache, prefs) -> Dict[PkgReference, dict]:
# Read conaninfo
info_path = os.path.join(pkg_layout.package(), CONANINFO)
if not os.path.exists(info_path):
raise ConanException(f"Corrupted package '{pkg_layout.reference}' "
f"without conaninfo.txt in: {info_path}")
conan_info_content = load(info_path)
info = load_binary_info(conan_info_content)
ConanOutput().error(f"Corrupted package '{pkg_layout.reference}' "
f"without conaninfo.txt in: {info_path}")
info = {}
else:
conan_info_content = load(info_path)
info = load_binary_info(conan_info_content)
pref = pkg_layout.reference
# The key shoudln't have the latest package revision, we are asking for package configs
pref.revision = None
Expand Down
12 changes: 10 additions & 2 deletions conan/internal/cache/integrity_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ def check(self, upload_data):
def _recipe_corrupted(self, ref: RecipeReference):
layout = self._cache.recipe_layout(ref)
output = ConanOutput()
read_manifest, expected_manifest = layout.recipe_manifests()
try:
read_manifest, expected_manifest = layout.recipe_manifests()
except FileNotFoundError:
output.error(f"{ref.repr_notime()}: Manifest missing", error_type="exception")
return True
# Filter exports_sources from read manifest if there are no exports_sources locally
# This happens when recipe is downloaded without sources (not built from source)
export_sources_folder = layout.export_sources()
Expand All @@ -52,7 +56,11 @@ def _recipe_corrupted(self, ref: RecipeReference):
def _package_corrupted(self, ref: PkgReference):
layout = self._cache.pkg_layout(ref)
output = ConanOutput()
read_manifest, expected_manifest = layout.package_manifests()
try:
read_manifest, expected_manifest = layout.package_manifests()
except FileNotFoundError:
output.error(f"{ref.repr_notime()}: Manifest missing", error_type="exception")
return True

if read_manifest != expected_manifest:
output.error(f"{ref}: Manifest mismatch", error_type="exception")
Expand Down
80 changes: 80 additions & 0 deletions test/integration/command_v2/test_cache_integrity.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,92 @@ def test_cache_integrity():
layout = t.created_layout()
conaninfo = os.path.join(layout.package(), "conaninfo.txt")
save(conaninfo, "[settings]")
t.run("create . --name pkg4 --version=4.0")
layout = t.created_layout()
conaninfo = os.path.join(layout.package(), "conaninfo.txt")
save(conaninfo, "[settings]")

t.run("cache check-integrity *", assert_error=True)
assert "pkg1/1.0: Integrity checked: ok" in t.out
assert "pkg1/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Integrity checked: ok" in t.out
assert "ERROR: pkg2/2.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Manifest mismatch" in t.out
assert "ERROR: pkg3/3.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Manifest mismatch" in t.out
assert "ERROR: pkg4/4.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Manifest mismatch" in t.out

t.run("remove pkg2/2.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c")
t.run("remove pkg3/3.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c")
t.run("remove pkg4/4.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c")
t.run("cache check-integrity *")
assert "pkg1/1.0: Integrity checked: ok" in t.out
assert "pkg2/2.0: Integrity checked: ok" in t.out
assert "pkg3/3.0: Integrity checked: ok" in t.out
assert "pkg4/4.0: Integrity checked: ok" in t.out


def test_cache_integrity_missing_recipe_manifest():
t = TestClient()
t.save({"conanfile.py": GenConanfile()})
t.run("create . --name pkg1 --version 1.0")
t.run("create . --name pkg2 --version=2.0")
layout = t.exported_layout()
manifest = os.path.join(layout.export(), "conanmanifest.txt")
os.remove(manifest)
t.run("create . --name pkg3 --version=3.0")

t.run("cache check-integrity *", assert_error=True)
assert "pkg1/1.0: Integrity checked: ok" in t.out
assert "ERROR: pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd: Manifest missing" in t.out
assert "pkg3/3.0: Integrity checked: ok" in t.out
assert "ERROR: There are corrupted artifacts, check the error logs" in t.out

t.run("remove pkg2* -c")
t.run("cache check-integrity *")
assert "pkg1/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Integrity checked: ok" in t.out
assert "pkg3/3.0: Integrity checked: ok" in t.out
assert "Integrity check: ok" in t.out


def test_cache_integrity_missing_package_manifest():
t = TestClient()
t.save({"conanfile.py": GenConanfile()})
t.run("create . --name pkg1 --version 1.0")
t.run("create . --name pkg2 --version=2.0")
layout = t.created_layout()
manifest = os.path.join(layout.package(), "conanmanifest.txt")
os.remove(manifest)
t.run("create . --name pkg3 --version=3.0")

t.run("cache check-integrity *", assert_error=True)
assert "pkg1/1.0: Integrity checked: ok" in t.out
assert "ERROR: pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd" \
":da39a3ee5e6b4b0d3255bfef95601890afd80709" \
"#0ba8627bd47edc3a501e8f0eb9a79e5e: Manifest missing" in t.out
assert "pkg3/3.0: Integrity checked: ok" in t.out
assert "ERROR: There are corrupted artifacts, check the error logs" in t.out

t.run("remove pkg2* -c")
t.run("cache check-integrity *")
assert "pkg1/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Integrity checked: ok" in t.out
assert "pkg3/3.0: Integrity checked: ok" in t.out
assert "Integrity check: ok" in t.out


def test_cache_integrity_missing_package_conaninfo():
t = TestClient()
t.save({"conanfile.py": GenConanfile()})
t.run("create . --name pkg1 --version 1.0")
t.run("create . --name pkg2 --version=2.0")
layout = t.created_layout()
conaninfo = os.path.join(layout.package(), "conaninfo.txt")
os.remove(conaninfo)

t.run("cache check-integrity *", assert_error=True)
assert "pkg1/1.0: Integrity checked: ok" in t.out
assert "ERROR: pkg2/2.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Manifest mismatch" in t.out

t.run("remove pkg2* -c")
t.run("cache check-integrity *")
assert "pkg1/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Integrity checked: ok" in t.out


def test_cache_integrity_export_sources():
Expand Down

0 comments on commit c1b4db5

Please sign in to comment.