def test_build_download_error_60(self, mock_temp_dir, mock_koji, mock_check_output, tmpdir): """ Assert that build fails when spectool throws error 60. """ # Create temporary file file = os.path.join(tmpdir, "Lectitio_Divinitatus") with open(file, "w") as f: f.write("The Emperor is God") mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", "rpmdev-bumpspec", b"Downloading Lectitio_Divinitatus", CalledProcessError(60, None), ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} with pytest.raises(DownloadException) as exc: self.builder.build(package, opts) assert exc.value.message == ( "Unable to validate the TLS certificate for one of the package's " "Source URLs")
def test_validate_response_not_ok(self): """ Assert that validation raises HTTPException when response code is not 200. """ # Mock requests_session response = mock.Mock() response.status_code = 500 self.validator.requests_session.get.return_value = response # Prepare package package = Package(name="test", version="1.0", distro="Fedora") with pytest.raises(HTTPException) as ex: self.validator.validate(package) assert ex.value.error_code == 500 assert (ex.value.message == "Error encountered on request {}/_dg/anitya/rpms/{}".format( self.validator.url, package.name)) # Parameters for requests get call timeout = (5, 20) self.validator.requests_session.get.assert_called_with( self.validator.url + "/_dg/anitya/rpms/{}".format(package.name), timeout=timeout, )
def test_validate_retired(self): """ Assert that PDC returns correct output when package is retired. """ # Mock requests_session response = mock.Mock() response.status_code = 200 response.json.return_value = { "count": 0, } self.validator.requests_session.get.return_value = response # Prepare package package = Package(name="test", version="1.1", distro="Fedora") result = self.validator.validate(package) # Parameters for requests get call timeout = (5, 20) params = ( ("name", self.validator.branch), ("global_component", package.name), ("type", self.validator.package_type), ("active", True), ) self.validator.requests_session.get.assert_called_with( self.validator.url + "/rest_api/v1/component-branches/", params=params, timeout=timeout, ) assert result["retired"] is True assert result["active_branches"] == 0
def test_build_rpmdev_bumpspec_error(self, mock_temp_dir, mock_check_output, tmpdir): """ Assert that build fails with BuilderException when rpmdev-bumpspec raises error. """ mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", CalledProcessError(1, "rpmdev-bumpspec", output=b"Some output", stderr=b"Failed miserably"), ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} with pytest.raises(BuilderException) as exc: self.builder.build(package, opts) assert (exc.value.message == "Command 'rpmdev-bumpspec' returned non-zero exit status 1.") assert exc.value.value == {} assert exc.value.std_out == "Some output" assert exc.value.std_err == "Failed miserably"
def test_build_download_error_1(self, mock_temp_dir, mock_koji, mock_check_output, tmpdir): """ Assert that build fails when spectool throws error 1. """ # Create temporary file file = os.path.join(tmpdir, "Lectitio_Divinitatus") with open(file, "w") as f: f.write("The Emperor is God") mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", "rpmdev-bumpspec", b"Downloading Lectitio_Divinitatus", CalledProcessError(1, None), ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} with pytest.raises(DownloadException) as exc: self.builder.build(package, opts) assert exc.value.message == ( "The specfile contains a Source URL with an unknown protocol; it should" 'be "https", "http", or "ftp".')
def test_validate_no_monitoring(self): """ Assert that validation returns correct output when monitoring is not set. """ # Mock requests_session response = mock.Mock() response.status_code = 200 response.json.return_value = { "monitoring": "no-monitoring", } self.validator.requests_session.get.return_value = response # Prepare package package = Package(name="test", version="1.1", distro="Fedora") result = self.validator.validate(package) # Parameters for requests get call timeout = (5, 20) self.validator.requests_session.get.assert_called_with( self.validator.url + "/_dg/anitya/rpms/{}".format(package.name), timeout=timeout, ) assert result["monitoring"] is False assert result["all_versions"] is False assert result["stable_only"] is False assert result["scratch_build"] is False
def test_validate_old(self): """ Assert that validation returns correct output when the version is older. """ url = "http://testing.url" timeout = (5, 20) # Mock requests_session requests_session = mock.Mock() response = mock.Mock() response.status_code = 200 response.json.return_value = {"version": "1.1", "release": "1.fc34"} requests_session.get.return_value = response # Prepare package package = Package(name="test", version="1.0", distro="Fedora") validator = MDApi(url, requests_session, timeout) result = validator.validate(package) requests_session.get.assert_called_with( url + "/koji/srcpkg/test", timeout=timeout ) assert result["newer"] is False assert result["version"] == "1.1" assert result["release"] == "1.fc34"
def test_build_session_missing(self, mock_temp_dir, mock_koji, mock_check_output, tmpdir): """ Assert that build fails when we can't obtain a koji session. """ # Create temporary file file = os.path.join(tmpdir, "Lectitio_Divinitatus") with open(file, "w") as f: f.write("The Emperor is God") mock_session = mock.Mock() mock_session.krb_login.return_value = None mock_koji.ClientSession.return_value = mock_session mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", "rpmdev-bumpspec", b"Downloading Lectitio_Divinitatus", b"Downloaded: Lectitio_Divinitatus", b"rpmbuild foobar.srpm", ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} with pytest.raises(BuilderException) as exc: self.builder.build(package, opts) assert exc.value.message == ("Can't authenticate with Koji!")
def test_validate_response_not_ok(self): """ Assert that validation raises HTTPException when response code is not 200. """ url = "http://testing.url" timeout = (5, 20) # Mock requests_session requests_session = mock.Mock() response = mock.Mock() response.status_code = 500 # Prepare package package = Package(name="test", version="1.0", distro="Fedora") validator = MDApi(url, requests_session, timeout) validator.requests_session.get.return_value = response with pytest.raises(HTTPException) as ex: validator.validate(package) assert ex.value.error_code == 500 assert ( ex.value.message == "Error encountered on request {}/koji/srcpkg/test".format(url) ) requests_session.get.assert_called_with( url + "/koji/srcpkg/test", timeout=timeout )
def test_build_download_unexpected_error(self, mock_temp_dir, mock_koji, mock_check_output, tmpdir): """ Assert that build fails when spectool throws unexpected error. """ # Create temporary file file = os.path.join(tmpdir, "Lectitio_Divinitatus") with open(file, "w") as f: f.write("The Emperor is God") mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", "rpmdev-bumpspec", b"Downloading Lectitio_Divinitatus", CalledProcessError(100, "spectool -g", output=b"Some output"), ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} with pytest.raises(DownloadException) as exc: self.builder.build(package, opts) assert exc.value.message == ( "An unexpected error occurred while downloading the new package sources; " "please report this as a bug on the-new-hotness issue tracker.\n" "Error output:\n" "None")
def test_build_identical_new_sources(self, mock_temp_dir, mock_koji, mock_check_output, tmpdir): """ Assert that correct output is returned when sources from current package and new build are identical. """ # Create temporary file file = os.path.join(tmpdir, "Lectitio_Divinitatus") with open(file, "w") as f: f.write("The Emperor is God") # Mock patch file file = os.path.join(tmpdir, "patch") with open(file, "w") as f: f.write("This is a patch") mock_session = mock.Mock() mock_session.build.return_value = 1000 mock_session.krb_login.return_value = True mock_koji.ClientSession.return_value = mock_session mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", "rpmdev-bumpspec", (b"Fake line\n" b"Downloading Lectitio_Divinitatus\n"), b"Downloaded: Lectitio_Divinitatus\nDownloaded: Lectitio_Divinitatus\n", b"rpmbuild foobar.srpm", "git config", "git config", "git commit", file.encode(), ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} output = self.builder.build(package, opts) assert output == { "build_id": 1000, "patch": "This is a patch", "patch_filename": file, "message": ("One or more of the new sources for this package are identical to " "the old sources. This is most likely caused either by identical source files " "between releases, for example service files, or the specfile does not use " "version macro in its source URLs. If this is the second case, then please " "update the specfile to use version macro in its source URLs.\n" "Here is the list of the files with SHA512 checksums:\n" "Old: ['Lectitio_Divinitatus'] -> New: ['Lectitio_Divinitatus', " "'Lectitio_Divinitatus'] (96140cc21155a13c9bfa03377410ac63e3" "f7e6aef22cc3bf09c4efbfad1c7ced45e150e391c23271dfe49df71c60f" "1547fbe70ed47d5bc515ff00271309939f7)\n"), }
def test_submit_patch_missing_opts(self, opts): """ Assert that PatcherException is raised when the opts are missing. """ # Prepare package package = Package(name="test", version="1.0", distro="Fedora") patch = "Fix everything" with pytest.raises(PatcherException) as exc: self.patcher.submit_patch(package, patch, opts) assert exc.value.message == ( "Additional parameters are missing! " "Please provide `bz_id` and `patch_filename`.")
def test_notify(self): """ Assert that message is sent correctly. """ # Prepare package package = Package(name="test", version="1.0", distro="Fedora") topic = "update.drop" body = {"trigger": {"msg": {}, "topic": "topic"}, "reason": "Heresy"} opts = {"body": body} with mock_sends(UpdateDrop): output = self.notifier.notify(package, topic, opts) assert list(output.keys()) == ["msg_id"]
def test_notify_missing_opts(self): """ Assert that NotifierException is raised when opts are missing. """ # Prepare package package = Package(name="test", version="1.0", distro="Fedora") topic = "update.drop" with pytest.raises(NotifierException) as exc: self.notifier.notify(package, topic, {}) assert exc.value.message == ( "Additional parameters are missing! " "Please provide `body` for the message." )
def test_notify_connection_exception(self, mock_fm_publish): """ Assert that NotifierException is raised when connection error occurs. """ # Prepare package package = Package(name="test", version="1.0", distro="Fedora") topic = "update.drop" body = {"trigger": {"msg": "msg", "topic": "topic"}, "reason": "Heresy"} mock_fm_publish.side_effect = ConnectionException() opts = {"body": body} with pytest.raises(NotifierException) as exc: self.notifier.notify(package, topic, opts) assert exc.value.message.startswith("Error sending the message")
def test_build_git_commit_error(self, mock_temp_dir, mock_koji, mock_check_output, tmpdir): """ Assert that build fails with BuilderException when git commit raises error. """ # Create temporary file file = os.path.join(tmpdir, "Lectitio_Divinitatus") with open(file, "w") as f: f.write("The Emperor is God") mock_session = mock.Mock() mock_session.build.return_value = 1000 mock_session.krb_login.return_value = True mock_koji.ClientSession.return_value = mock_session mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", "rpmdev-bumpspec", (b"Fake line\n" b"Downloading Lectitio_Divinitatus\n"), b"Downloaded: Lectitio_Divinitatus\n", b"rpmbuild foobar.srpm", "git config", "git config", CalledProcessError(1, "git commit", output=b"Some output", stderr=b"Failed miserably"), file.encode(), ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} with pytest.raises(BuilderException) as exc: self.builder.build(package, opts) assert (exc.value.message == "Command 'git commit' returned non-zero exit status 1.") assert exc.value.value["build_id"] == 1000 assert exc.value.std_out == "Some output" assert exc.value.std_err == "Failed miserably"
def test_notify_unknown_topic(self, mock_fm_get_class): """ Assert that NotifierException is raised when topic is not found. """ # Prepare package package = Package(name="test", version="1.0", distro="Fedora") topic = "foobar" body = {"trigger": {"msg": "msg", "topic": "topic"}, "reason": "Heresy"} mock_fm_get_class.return_value = "" opts = {"body": body} with pytest.raises(NotifierException) as exc: self.notifier.notify(package, topic, opts) assert exc.value.message == ("Unknown topic provided 'hotness.foobar'")
def test_submit_patch(self, mock_temp_dir, tmpdir): """ Assert that submit_patch works correctly. """ # Prepare package package = Package(name="test", version="1.0", distro="Fedora") patch = "Fix everything" opts = {"bz_id": 100, "patch_filename": "patch"} mock_temp_dir.return_value.__enter__.return_value = tmpdir filepath = os.path.join(tmpdir, "patch") output = self.patcher.submit_patch(package, patch, opts) self.patcher.bugzilla.attachfile.assert_called_with( 100, filepath, "Update to 1.0 (#100)", is_patch=True) assert output == { "bz_id": 100, }
def test_validate_response_not_ok(self): """ Assert that validation raises HTTPException when response code is not 200. """ # Mock requests_session response = mock.Mock() response.status_code = 500 self.validator.requests_session.get.return_value = response # Prepare package package = Package(name="test", version="1.0", distro="Fedora") with pytest.raises(HTTPException) as ex: self.validator.validate(package) assert ex.value.error_code == 500 assert ( ex.value.message == "Error encountered on request {}/rest_api/v1/component-branches/".format( self.validator.url ) ) # Parameters for requests get call timeout = (5, 20) params = ( ("name", self.validator.branch), ("global_component", package.name), ("type", self.validator.package_type), ("active", True), ) self.validator.requests_session.get.assert_called_with( self.validator.url + "/rest_api/v1/component-branches/", params=params, timeout=timeout, )
def test_build_rpmbuild_error(self, mock_temp_dir, mock_check_output, tmpdir): """ Assert that build fails with BuilderException when rpmbuild raises error. """ # Create temporary file file = os.path.join(tmpdir, "Lectitio_Divinitatus") with open(file, "w") as f: f.write("The Emperor is God") mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", "rpmdev-bumpspec", (b"Fake line\n" b"Downloading Lectitio_Divinitatus\n"), b"Downloaded: Lectitio_Divinitatus\n", CalledProcessError(1, "rpmdevbuild", output=b"Some output", stderr=b"Failed miserably"), ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} with pytest.raises(BuilderException) as exc: self.builder.build(package, opts) assert (exc.value.message == "Command 'rpmdevbuild' returned non-zero exit status 1.") assert exc.value.value["message"] != "" assert exc.value.std_out == "Some output" assert exc.value.std_err == "Failed miserably"
def test_build(self, mock_temp_dir, mock_koji, mock_check_output, tmpdir): """ Assert that correct output is returned when build starts without issue. """ # Create temporary file file = os.path.join(tmpdir, "Lectitio_Divinitatus") with open(file, "w") as f: f.write("The Emperor is God") file = os.path.join(tmpdir, "Codex_Astartes") with open(file, "w") as f: f.write("Adeptus Astartes") # Mock patch file filename = "patch" file = os.path.join(tmpdir, filename) with open(file, "w") as f: f.write("This is a patch") mock_session = mock.Mock() mock_session.build.return_value = 1000 mock_session.krb_login.return_value = True mock_koji.ClientSession.return_value = mock_session mock_temp_dir.return_value.__enter__.return_value = tmpdir mock_check_output.side_effect = [ "git clone", "rpmdev-bumpspec", b"Downloading Lectitio_Divinitatus", b"Downloaded: Codex_Astartes", b"rpmbuild foobar.srpm", "git config", "git config", "git commit", filename.encode(), ] # Prepare package package = Package(name="test", version="1.0", distro="Fedora") opts = {"bz_id": 100} output = self.builder.build(package, opts) assert output == { "build_id": 1000, "patch": "This is a patch", "patch_filename": filename, "message": "", } mock_temp_dir.assert_called_with(prefix="thn-", dir="/var/tmp") mock_koji.ClientSession.assert_called_with( self.builder.server_url, self.builder.krb_sessionopts) mock_session.krb_login.assert_called_with( principal=self.builder.krb_principal, keytab=self.builder.krb_keytab, ccache=self.builder.krb_ccache, proxyuser=self.builder.krb_proxyuser, ) mock_session.uploadWrapper.assert_called_once() mock_session.build.assert_called_once() mock_check_output.assert_has_calls([ mock.call(["git", "clone", self.builder.git_url, tmpdir], stderr=mock.ANY), mock.call( [ "/usr/bin/rpmdev-bumpspec", "--new", "1.0", "-c", "Update to 1.0 (#100)", "-u", self.builder.user_email[0] + " " + self.builder.user_email[1], tmpdir + "/test.spec", ], stderr=mock.ANY, ), mock.call(["fedpkg", "--user", "hotness", "sources"], cwd=tmpdir), mock.call( [ "spectool", "-g", str(tmpdir + "/test.spec"), ], cwd=tmpdir, ), mock.call( [ "rpmbuild", "-D", "_sourcedir .", "-D", "_topdir .", "-bs", tmpdir + "/test.spec", ], cwd=tmpdir, stderr=mock.ANY, ), mock.call( ["git", "config", "user.name", self.builder.user_email[0]], cwd=tmpdir, stderr=mock.ANY, ), mock.call( ["git", "config", "user.email", self.builder.user_email[1]], cwd=tmpdir, stderr=mock.ANY, ), mock.call( ["git", "commit", "-a", "-m", "Update to 1.0 (#100)"], cwd=tmpdir, stderr=mock.ANY, ), mock.call(["git", "format-patch", "HEAD^"], cwd=tmpdir, stderr=mock.ANY), ])