def test_unpack_file_url_download_bad_hash(self, tmpdir, data, monkeypatch): """ Test when existing download has different hash from the file url fragment """ self.prep(tmpdir, data) # add in previous download (copy simple-2.0 as simple-1.0 so it's wrong # hash) dest_file = os.path.join(self.download_dir, self.dist_file) copy(self.dist_path2, dest_file) dist_path_md5 = hashlib.md5(open(self.dist_path, 'rb').read()).hexdigest() dist_path2_md5 = hashlib.md5(open(dest_file, 'rb').read()).hexdigest() assert dist_path_md5 != dist_path2_md5 self.dist_url.url = "%s#md5=%s" % (self.dist_url.url, dist_path_md5) unpack_file_url(self.dist_url, self.build_dir, download_dir=self.download_dir, hashes=Hashes({'md5': [dist_path_md5]})) # confirm hash is for simple1-1.0 # the previous bad download has been removed assert (hashlib.md5( open(dest_file, 'rb').read()).hexdigest() == dist_path_md5), hashlib.md5( open(dest_file, 'rb').read()).hexdigest()
def test_unpack_file_url_bad_hash(self, tmpdir, data, monkeypatch): """ Test when the file url hash fragment is wrong """ self.prep(tmpdir, data) self.dist_url.url = "%s#md5=bogus" % self.dist_url.url with pytest.raises(HashMismatch): unpack_file_url(self.dist_url, self.build_dir, hashes=Hashes({'md5': ['bogus']}))
def test_success(self, tmpdir): """Make sure no error is raised when at least one hash matches. Test check_against_path because it calls everything else. """ file = tmpdir / 'to_hash' file.write('hello') hashes = Hashes({ 'sha256': ['2cf24dba5fb0a30e26e83b2ac5b9e29e' '1b161e5c1fa7425e73043362938b9824'], 'sha224': ['wrongwrong'], 'md5': ['5d41402abc4b2a76b9719d911017c592']}) hashes.check_against_path(file)
def download_url(url, download_dir, sha256=None): cmd = DownloadCommand() options, _ = cmd.parse_args([]) link = Link(url) session = cmd._build_session(options) hashes = Hashes({"sha256": [sha256]}) if sha256 else None downloaded_path = _check_download_dir(link, download_dir, hashes) if downloaded_path: return downloaded_path try: downloaded_path, _ = _download_http_url(Link(url), session, download_dir, hashes) except HashMismatch0 as e: expected = e.allowed["sha256"][0] actual = e.gots["sha256"].hexdigest() raise HashMismatch(url, expected, actual) else: return _ensure_expected_download_path(downloaded_path, link)
def hashes(self, trust_internet=True): """Return a hash-comparer that considers my option- and URL-based hashes to be known-good. Hashes in URLs--ones embedded in the requirements file, not ones downloaded from an index server--are almost peers with ones from flags. They satisfy --require-hashes (whether it was implicitly or explicitly activated) but do not activate it. md5 and sha224 are not allowed in flags, which should nudge people toward good algos. We always OR all hashes together, even ones from URLs. :param trust_internet: Whether to trust URL-based (#md5=...) hashes downloaded from the internet, as by populate_link() """ good_hashes = self.options.get('hashes', {}).copy() link = self.link if trust_internet else self.original_link if link and link.hash: good_hashes.setdefault(link.hash_name, []).append(link.hash) return Hashes(good_hashes)
def test_unpack_http_url_bad_downloaded_checksum(mock_unpack_file): """ If already-downloaded file has bad checksum, re-download. """ base_url = 'http://www.example.com/somepackage.tgz' contents = b'downloaded' download_hash = hashlib.new('sha1', contents) link = Link(base_url + '#sha1=' + download_hash.hexdigest()) session = Mock() session.get = Mock() response = session.get.return_value = MockResponse(contents) response.headers = {'content-type': 'application/x-tar'} response.url = base_url download_dir = mkdtemp() try: downloaded_file = os.path.join(download_dir, 'somepackage.tgz') _write_file(downloaded_file, 'some contents') unpack_http_url( link, 'location', download_dir=download_dir, session=session, hashes=Hashes({'sha1': [download_hash.hexdigest()]}) ) # despite existence of downloaded file with bad hash, downloaded again session.get.assert_called_once_with( 'http://www.example.com/somepackage.tgz', headers={"Accept-Encoding": "identity"}, stream=True, ) # cached file is replaced with newly downloaded file with open(downloaded_file) as fh: assert fh.read() == 'downloaded' finally: rmtree(download_dir)
def test_non_zero(self): """Test that truthiness tests tell whether any known-good hashes exist.""" assert Hashes({'sha256': 'dummy'}) assert not Hashes() assert not Hashes({})
def test_unknown_hash(self): """Hashes should raise InstallationError when it encounters an unknown hash.""" hashes = Hashes({'badbad': ['dummy']}) with pytest.raises(InstallationError): hashes.check_against_file(BytesIO(b'hello'))
def test_failure(self): """Hashes should raise HashMismatch when no hashes match.""" hashes = Hashes({'sha256': ['wrongwrong']}) with pytest.raises(HashMismatch): hashes.check_against_file(BytesIO(b'hello'))