new file mode 100644
--- /dev/null
+++ b/pylib/mozreview/mozreview/tests/test_flags_in_db.py
@@ -0,0 +1,259 @@
+import djblets
+import factory
+import json
+import pytest
+import unittest
+
+import reviewboard.testing
+
+from django.core.exceptions import ValidationError
+from django.db.models import signals
+from django.contrib.auth.models import User
+from mock import patch
+
+from reviewboard.reviews import models as rbmodels
+from mozreview import models as mrmodels
+from mozreview.extra_data import (
+ COMMITS_KEY,
+ IDENTIFIER_KEY,
+ REVIEW_FLAG_KEY,
+ is_parent,
+ is_pushed,
+)
+from mozreview.tests.helpers import BaseFactory, UserFactory
+from mozreview.signal_handlers import (
+ manage_flags_on_rr_publishing,
+ get_flag_value,
+ save_flag_on_review_publishing,
+)
+from mozreview.review_helpers import get_reviewers_status
+
+
+# Shut off reviewboard's post-review-creation signal hooks, which try to touch
+# the database.
+@factory.django.mute_signals(signals.post_init)
+class ReviewRequestFactory(BaseFactory):
+ class Meta:
+ model = rbmodels.ReviewRequest
+ strategy = factory.BUILD_STRATEGY
+
+ submitter = factory.SubFactory(UserFactory)
+ description = 'spam'
+
+ @factory.post_generation
+ def approved(review_request, create, extracted, **kwargs):
+ # The `_approved` property is a complex lazy calculation on
+ # ReviewRequest objects. We'll short-circuit it here.
+
+ if extracted is None:
+ # No bool provided by caller, set a default value
+ extracted = True
+
+ review_request._approved = extracted
+
+
+class ReviewFactory(BaseFactory):
+ class Meta:
+ model = rbmodels.Review
+ strategy = factory.BUILD_STRATEGY
+
+ public = True
+ user = factory.SubFactory(UserFactory)
+ review_request = factory.SubFactory(ReviewRequestFactory)
+
+
+class MozReviewFlagTypeFactory(BaseFactory):
+ class Meta:
+ model = mrmodels.MozReviewFlagType
+ strategy = factory.BUILD_STRATEGY
+
+ name = 'review'
+ prefix = 'r'
+ values_json = '["+", "-", "?"]'
+
+# We need only one object of `MozReviewFlagType`
+review_flag_type = MozReviewFlagTypeFactory()
+
+
+class MozReviewFlagFactory(BaseFactory):
+ class Meta:
+ model = mrmodels.MozReviewFlag
+ strategy = factory.BUILD_STRATEGY
+
+ type = review_flag_type
+ review_request = factory.SubFactory(ReviewRequestFactory)
+ setter = factory.SubFactory(UserFactory)
+
+
+class TestModels(unittest.TestCase):
+ def test_get_value_from_wrong_prefix(self):
+ with self.assertRaises(ValueError):
+ review_flag_type.get_value_from_status('wrong')
+
+ def test_get_value_from_wrong_status(self):
+ with self.assertRaises(ValueError):
+ review_flag_type.get_value_from_status('r!')
+
+ def test_get_value_from_right_status(self):
+ for value in review_flag_type.values:
+ assert review_flag_type.get_value_from_status(
+ 'r%s' % value) == value
+
+ def test_flag_status(self):
+ for value in review_flag_type.values:
+ flag = MozReviewFlagFactory(value=value)
+ assert flag.status == 'r%s' % value
+
+ def test_validation_wrong_value(self):
+ with self.assertRaises(ValidationError):
+ mrmodels.MozReviewFlag.validate_value('!', review_flag_type)
+
+ def test_validation_wrong_user(self):
+ # value ? is allowed for declared reviewers only
+ with self.assertRaises(ValidationError):
+ mrmodels.MozReviewFlag.validate_value('?', review_flag_type,
+ ReviewFactory(),
+ UserFactory(),
+ [])
+
+ def test_validation_right_values(self):
+ for value in review_flag_type.values:
+ self.assertIsNone(mrmodels.MozReviewFlag.validate_value(
+ value, review_flag_type))
+
+ def test_validation_right_user(self):
+ user = UserFactory()
+ self.assertIsNone(mrmodels.MozReviewFlag.validate_value(
+ '?', review_flag_type, ReviewFactory(), user, [user]))
+
+
+@pytest.mark.django_db
+class TestFlagType(djblets.testing.testcases.TestModelsLoaderMixin,
+ reviewboard.testing.TestCase):
+
+ tests_app = 'mozreview'
+
+ def test_get_flag_type_review(self):
+ ft = mrmodels.MozReviewFlagType.objects.get_review_type()
+ assert ft.name == 'review'
+ assert ft.values == ['+', '-', '?']
+
+
+@pytest.mark.django_db
+class TestOnReviewRequestPublishing(
+ djblets.testing.testcases.TestModelsLoaderMixin,
+ reviewboard.testing.TestCase):
+
+ tests_app = 'mozreview'
+ fixtures = ['test_users']
+
+ def _create_review_request_with_review(self, reviewer=None,
+ ship_it=True, status='r+'):
+ if not reviewer:
+ reviewer = self.reviewer
+ diffset = self.create_diffset(self.rr)
+ filediff = self.create_filediff(diffset)
+
+ # Create a review.
+ review = self.create_review(self.rr, user=reviewer, ship_it=ship_it)
+ # Add a flag to a review
+ review.extra_data = json.dumps({REVIEW_FLAG_KEY: status})
+ self.create_diff_comment(review, filediff, text='comment')
+ return review
+
+ def setUp(self):
+ super(TestOnReviewRequestPublishing, self).setUp()
+ self.user = User.objects.get(pk=1)
+ self.reviewer = User.objects.get(pk=2)
+ self.rr = self.create_review_request(submitter=self.user,
+ create_repository=True)
+ self.flag_type = mrmodels.MozReviewFlagType.objects.get_review_type()
+
+ def test_setting_flag_on_new_reviewer(self):
+ self.rr.target_people.add(self.reviewer)
+ rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+ assert rrd.target_people.count() == self.rr.target_people.count()
+ manage_flags_on_rr_publishing(self.rr, rrd, self.reviewer, False)
+ assert self.reviewer.flags_set.count() == 1
+ assert self.reviewer.flags_set.all()[0].status == 'r?'
+
+ def test_setting_flag_on_reviewer_by_review_publishing(self):
+ self.rr.target_people.add(self.reviewer)
+ review = self._create_review_request_with_review()
+ value = get_flag_value('r+', review, self.flag_type, self.reviewer,
+ [self.reviewer])
+ assert value == '+'
+ flag = save_flag_on_review_publishing('+', self.flag_type,
+ self.reviewer, review)
+ assert flag.value == '+'
+ assert flag.requestee == self.reviewer
+ assert flag.setter == self.reviewer
+ assert flag in review.flags.all()
+ reviewers_status = get_reviewers_status(self.rr)
+ assert self.reviewer.username in reviewers_status
+ assert reviewers_status[self.reviewer.username]['review_flag'] == 'r+'
+ assert reviewers_status[self.reviewer.username]['ship_it'] == True
+
+ def test_resetting_flag_on_rr_publishing(self):
+ self.rr.target_people.add(self.reviewer)
+ review = self._create_review_request_with_review()
+ rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+ # manage flags with a diffset
+ manage_flags_on_rr_publishing(self.rr, rrd, self.user, True)
+ reviewers_status = get_reviewers_status(self.rr)
+ assert self.reviewer.username in reviewers_status
+ assert reviewers_status[self.reviewer.username]['review_flag'] == 'r?'
+ assert reviewers_status[self.reviewer.username]['ship_it'] == False
+ flag = self.reviewer.flags_requested.latest()
+ assert flag.setter == self.user
+ assert flag.requestee == self.reviewer
+
+ def test_removing_flag_on_rr_publishing(self):
+ review = self._create_review_request_with_review()
+ save_flag_on_review_publishing('+', self.flag_type,
+ self.reviewer, review)
+ flag = self.reviewer.flags_requested.latest()
+ assert flag.requestee == self.reviewer
+ assert flag.setter == self.reviewer
+ rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+ manage_flags_on_rr_publishing(self.rr, rrd, self.user, True)
+ reviewers_status = get_reviewers_status(self.rr)
+ assert self.reviewer.username not in reviewers_status
+
+ def test_removing_requestee_from_flag_on_rr_publishing(self):
+ self.rr.target_people.add(self.reviewer)
+ review = self._create_review_request_with_review()
+ save_flag_on_review_publishing('+', self.flag_type,
+ self.reviewer, review)
+ rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+ rrd.target_people.remove(self.reviewer)
+ manage_flags_on_rr_publishing(self.rr, rrd, self.user, False)
+ flag = self.reviewer.flags_set.latest()
+ assert flag.setter == self.reviewer
+ assert flag.requestee is None
+ assert flag.review == review
+ assert flag.status == 'r+'
+
+ def test_readding_requestee_to_flag_after_removed(self):
+ self.rr.target_people.add(self.reviewer)
+ review = self._create_review_request_with_review()
+ save_flag_on_review_publishing('+', self.flag_type,
+ self.reviewer, review)
+ rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+ rrd.target_people.remove(self.reviewer)
+ manage_flags_on_rr_publishing(self.rr, rrd, self.user, False)
+ flag = self.reviewer.flags_set.latest()
+ assert flag.requestee is None
+ rrd.target_people.add(self.reviewer)
+ manage_flags_on_rr_publishing(self.rr, rrd, self.user, False)
+ flag = self.reviewer.flags_set.latest()
+ assert flag.requestee == self.reviewer
+
+ def test_adding_reviewer_to_target_people_on_rr_publishing(self):
+ rrd = rbmodels.ReviewRequestDraft.create(self.rr)
+ rrd.target_people.add(self.reviewer)
+ manage_flags_on_rr_publishing(self.rr, rrd, self.user, False)
+ flag = self.user.flags_set.latest()
+ assert flag.setter == self.user
+ assert flag.requestee == self.reviewer
+ assert flag.status == 'r?'