Ejemplo n.º 1
0
    def testForRepository(self):
        """Testing DefaultReviewer.objects.for_repository"""
        tool = Tool.objects.get(name='CVS')

        default_reviewer1 = DefaultReviewer(name="Test", file_regex=".*")
        default_reviewer1.save()

        default_reviewer2 = DefaultReviewer(name="Bar", file_regex=".*")
        default_reviewer2.save()

        repo1 = Repository(name='Test1', path='path1', tool=tool)
        repo1.save()
        default_reviewer1.repository.add(repo1)

        repo2 = Repository(name='Test2', path='path2', tool=tool)
        repo2.save()

        default_reviewers = DefaultReviewer.objects.for_repository(repo1)
        self.assert_(len(default_reviewers) == 2)
        self.assert_(default_reviewer1 in default_reviewers)
        self.assert_(default_reviewer2 in default_reviewers)

        default_reviewers = DefaultReviewer.objects.for_repository(repo2)
        self.assert_(len(default_reviewers) == 1)
        self.assert_(default_reviewer2 in default_reviewers)
Ejemplo n.º 2
0
    def testNewReviewRequest1(self):
        """Testing new_review_request view (uploading diffs)"""
        self.client.login(username='******', password='******')

        response = self.client.get('/r/new/')
        self.assertEqual(response.status_code, 200)

        testdata_dir = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            'scmtools', 'testdata')
        svn_repo_path = os.path.join(testdata_dir, 'svn_repo')

        repository = Repository(name='Subversion SVN',
                                path='file://' + svn_repo_path,
                                tool=Tool.objects.get(name='Subversion'))
        repository.save()

        diff_filename = os.path.join(testdata_dir, 'svn_makefile.diff')

        f = open(diff_filename, 'r')

        response = self.client.post('/r/new/', {
            'repository': repository.id,
            'diff_path': f,
            'basedir': '/trunk',
        })

        f.close()

        self.assertEqual(response.status_code, 302)

        r = ReviewRequest.objects.order_by('-time_added')[0]
        self.assertEqual(response['Location'],
                         'http://testserver%s' % r.get_absolute_url())
    def add_repository(self, name, url):
        """Add a repository to Review Board."""
        with wrap_env():
            self._setup_env()

            from reviewboard.scmtools.models import Repository, Tool
            tool = Tool.objects.get(name__exact='Mercurial')
            r = Repository(name=name, path=url, tool=tool)
            r.save()
            return r.id
Ejemplo n.º 4
0
    def test_get_file_exists(self):
        """Testing Kiln get_file_exists"""
        def _http_get(service, url, *args, **kwargs):
            if url == ('https://mydomain.kilnhg.com/Api/1.0/Project'
                       '?token=my-token'):
                data = json.dumps([{
                    'sSlug': 'myproject',
                    'repoGroups': [{
                        'sSlug': 'mygroup',
                        'repos': [{
                            'sSlug': 'myrepo',
                            'ixRepo': 123,
                        }]
                    }]
                }])
            else:
                self.assertEqual(
                    url,
                    'https://mydomain.kilnhg.com/Api/1.0/Repo/123/Raw/File/'
                    '%s?rev=%s&token=my-token'
                    % (encoded_path, revision))

                data = 'My data'

            return data, {}

        path = '/path'
        encoded_path = '2F70617468'
        revision = 123

        account = self._get_hosting_account()
        service = account.service
        repository = Repository(hosting_account=account,
                                tool=Tool.objects.get(name='Mercurial'))
        repository.extra_data = {
            'kiln_account_domain': 'mydomain',
            'kiln_project_name': 'myproject',
            'kiln_group_name': 'mygroup',
            'kiln_repo_name': 'myrepo',
        }
        repository.save()

        account.data.update({
            'auth_token': 'my-token',
            'kiln_account_domain': 'mydomain',
        })

        self.spy_on(service.client.http_get, call_fake=_http_get)

        result = service.get_file_exists(repository, path, revision)
        self.assertTrue(service.client.http_get.called)
        self.assertTrue(result)
    def test_get_repository_commits_with_no_support(self):
        """Testing the GET repositories/<id>/commits/ API with a repository that does not implement it"""
        hg_repo_path = os.path.join(os.path.dirname(scmtools.__file__),
                                    'testdata', 'hg_repo.bundle')
        repository = Repository(name='Test HG',
                                path=hg_repo_path,
                                tool=Tool.objects.get(name='Mercurial'))
        repository.save()

        rsp = self.apiGet(get_repository_commits_url(repository),
                          query={'start': ''},
                          expected_status=501)
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], REPO_NOT_IMPLEMENTED.code)
    def test_get_repository_commits_with_no_support(self):
        """Testing the GET repositories/<id>/commits/ API with a repository that does not implement it"""
        hg_repo_path = os.path.join(os.path.dirname(scmtools.__file__),
                                    'testdata', 'hg_repo.bundle')
        repository = Repository(name='Test HG',
                                path=hg_repo_path,
                                tool=Tool.objects.get(name='Mercurial'))
        repository.save()

        rsp = self.apiGet(
            get_repository_commits_url(repository),
            query={'start': ''},
            expected_status=501)
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], REPO_NOT_IMPLEMENTED.code)
Ejemplo n.º 7
0
    def create(self, request, name, path, tool, trust_host=False,
               bug_tracker=None, encoding=None, mirror_path=None,
               password=None, public=None, raw_file_url=None, username=None,
               visible=True, local_site_name=None, *args, **kwargs):
        """Creates a repository.

        This will create a new repository that can immediately be used for
        review requests.

        The ``tool`` is a registered SCMTool ID. This must be known beforehand,
        and can be looked up in the Review Board administration UI.

        Before saving the new repository, the repository will be checked for
        access. On success, the repository will be created and this will
        return :http:`201`.

        In the event of an access problem (authentication problems,
        bad/unknown SSH key, or unknown certificate), an error will be
        returned and the repository information won't be updated. Pass
        ``trust_host=1`` to approve bad/unknown SSH keys or certificates.
        """
        local_site = self._get_local_site(local_site_name)

        if not Repository.objects.can_create(request.user, local_site):
            return self.get_no_access_error(request)

        try:
            scmtool = Tool.objects.get(name=tool)
        except Tool.DoesNotExist:
            return INVALID_FORM_DATA, {
                'fields': {
                    'tool': ['This is not a valid SCMTool'],
                }
            }

        cert = {}
        error_result = self._check_repository(scmtool.get_scmtool_class(),
                                              path, username, password,
                                              local_site, trust_host, cert,
                                              request)

        if error_result is not None:
            return error_result

        if public is None:
            public = True

        repository = Repository(
            name=name,
            path=path,
            mirror_path=mirror_path or '',
            raw_file_url=raw_file_url or '',
            username=username or '',
            password=password or '',
            tool=scmtool,
            bug_tracker=bug_tracker or '',
            encoding=encoding or '',
            public=public,
            visible=visible,
            local_site=local_site)

        if cert:
            repository.extra_data['cert'] = cert

        try:
            repository.full_clean()
        except ValidationError as e:
            if hasattr(e, 'params') and 'field' in e.params:
                return INVALID_FORM_DATA, {
                    'fields': {
                        e.params['field']: e.message,
                    },
                }
            else:
                return REPOSITORY_ALREADY_EXISTS

        repository.save()

        return 201, {
            self.item_result_key: repository,
        }
Ejemplo n.º 8
0
    def create(self, request, name, path, tool, trust_host=False,
               bug_tracker=None, encoding=None, mirror_path=None,
               password=None, public=None, raw_file_url=None, username=None,
               visible=True, local_site_name=None, *args, **kwargs):
        """Creates a repository.

        This will create a new repository that can immediately be used for
        review requests.

        The ``tool`` is a registered SCMTool ID. This must be known beforehand,
        and can be looked up in the Review Board administration UI.

        Before saving the new repository, the repository will be checked for
        access. On success, the repository will be created and this will
        return :http:`201`.

        In the event of an access problem (authentication problems,
        bad/unknown SSH key, or unknown certificate), an error will be
        returned and the repository information won't be updated. Pass
        ``trust_host=1`` to approve bad/unknown SSH keys or certificates.
        """
        local_site = self._get_local_site(local_site_name)

        if not Repository.objects.can_create(request.user, local_site):
            return self._no_access_error(request.user)

        try:
            scmtool = Tool.objects.get(name=tool)
        except Tool.DoesNotExist:
            return INVALID_FORM_DATA, {
                'fields': {
                    'tool': ['This is not a valid SCMTool'],
                }
            }

        cert = {}
        error_result = self._check_repository(scmtool.get_scmtool_class(),
                                              path, username, password,
                                              local_site, trust_host, cert,
                                              request)

        if error_result is not None:
            return error_result

        if public is None:
            public = True

        repository = Repository(
            name=name,
            path=path,
            mirror_path=mirror_path or '',
            raw_file_url=raw_file_url or '',
            username=username or '',
            password=password or '',
            tool=scmtool,
            bug_tracker=bug_tracker or '',
            encoding=encoding or '',
            public=public,
            visible=visible,
            local_site=local_site)

        if cert:
            repository.extra_data['cert'] = cert

        try:
            repository.full_clean()
        except ValidationError as e:
            if hasattr(e, 'params') and 'field' in e.params:
                return INVALID_FORM_DATA, {
                    'fields': {
                        e.params['field']: e.message,
                    },
                }
            else:
                return REPOSITORY_ALREADY_EXISTS

        repository.save()

        return 201, {
            self.item_result_key: repository,
        }
Ejemplo n.º 9
0
    def create_repository(self, with_local_site=False, name='Test Repo',
                          tool_name='Git', path=None, local_site=None,
                          extra_data=None, **kwargs):
        """Create a Repository for testing.

        The Repository may optionally be attached to a
        :py:class:`~reviewboard.site.models.LocalSite`. It's also populated
        with default data that can be overridden by the caller.

        Args:
            with_local_site (bool, optional):
                Whether to create the repository using a Local Site. This
                will choose one based on :py:attr:`local_site_name`.

                If ``local_site`` is provided, this argument is ignored.

            name (unicode, optional):
                The name of the repository.

            tool_name (unicode, optional):
                The name of the registered SCM Tool for the repository.

            path (unicode, optional):
                The path for the repository. If not provided, one will be
                computed.

            local_site (reviewboard.site.models.LocalSite, optional):
                The explicit Local Site to attach.

            extra_data (dict, optional):
                Explicit extra_data to attach to the repository.

            **kwargs (dict):
                Additional fields to set on the repository.

        Returns:
            reviewboard.scmtools.models.Repository:
            The new repository.
        """
        if not local_site:
            if with_local_site:
                local_site = self.get_local_site(name=self.local_site_name)
            else:
                local_site = None

        testdata_dir = os.path.join(os.path.dirname(scmtools.__file__),
                                    'testdata')

        if not path:
            if tool_name in ('Git', 'Test',
                             'TestToolSupportsPendingChangeSets'):
                path = os.path.join(testdata_dir, 'git_repo')
            elif tool_name == 'Subversion':
                path = 'file://' + os.path.join(testdata_dir, 'svn_repo')
            elif tool_name == 'Mercurial':
                path = os.path.join(testdata_dir, 'hg_repo.bundle')
            elif tool_name == 'CVS':
                path = os.path.join(testdata_dir, 'cvs_repo')
            elif tool_name == 'Perforce':
                path = 'localhost:1666'
            else:
                raise NotImplementedError

        repository = Repository(name=name,
                                local_site=local_site,
                                tool=Tool.objects.get(name=tool_name),
                                path=path,
                                **kwargs)

        if extra_data is not None:
            repository.extra_data = extra_data

        repository.save()

        return repository
Ejemplo n.º 10
0
class WebAPITests(TestCase, EmailTestHelper):
    """Testing the webapi support."""

    fixtures = ["test_users", "test_reviewrequests", "test_scmtools"]

    def setUp(self):
        initialize()

        siteconfig = SiteConfiguration.objects.get_current()
        siteconfig.set("mail_send_review_mail", True)
        siteconfig.save()
        mail.outbox = []

        svn_repo_path = os.path.join(os.path.dirname(__file__), "../scmtools/testdata/svn_repo")
        self.repository = Repository(
            name="Subversion SVN", path="file://" + svn_repo_path, tool=Tool.objects.get(name="Subversion")
        )
        self.repository.save()

        self.client.login(username="******", password="******")
        self.user = User.objects.get(username="******")

    def tearDown(self):
        self.client.logout()

    def apiGet(self, path, query={}):
        print "Getting /api/json/%s/" % path
        print "Query data: %s" % query
        response = self.client.get("/api/json/%s/" % path, query)
        self.assertEqual(response.status_code, 200)
        print "Raw response: %s" % response.content
        rsp = simplejson.loads(response.content)
        print "Response: %s" % rsp
        return rsp

    def apiPost(self, path, query={}):
        print "Posting to /api/json/%s/" % path
        print "Post data: %s" % query
        response = self.client.post("/api/json/%s/" % path, query)
        self.assertEqual(response.status_code, 200)
        print "Raw response: %s" % response.content
        rsp = simplejson.loads(response.content)
        print "Response: %s" % rsp
        return rsp

    def testRepositoryList(self):
        """Testing the repositories API"""
        rsp = self.apiGet("repositories")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["repositories"]), Repository.objects.count())

    def testUserList(self):
        """Testing the users API"""
        rsp = self.apiGet("users")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["users"]), User.objects.count())

    def testUserListQuery(self):
        """Testing the users API with custom query"""
        rsp = self.apiGet("users", {"query": "gru"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["users"]), 1)  # grumpy

    def testGroupList(self):
        """Testing the groups API"""
        rsp = self.apiGet("groups")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["groups"]), Group.objects.count())

    def testGroupListQuery(self):
        """Testing the groups API with custom query"""
        rsp = self.apiGet("groups", {"query": "dev"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["groups"]), 1)  # devgroup

    def testGroupStar(self):
        """Testing the groups/star API"""
        rsp = self.apiGet("groups/devgroup/star")
        self.assertEqual(rsp["stat"], "ok")
        self.assert_(Group.objects.get(name="devgroup") in self.user.get_profile().starred_groups.all())

    def testGroupStarDoesNotExist(self):
        """Testing the groups/star API with Does Not Exist error"""
        rsp = self.apiGet("groups/invalidgroup/star")
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.DOES_NOT_EXIST.code)

    def testGroupUnstar(self):
        """Testing the groups/unstar API"""
        # First, star it.
        self.testGroupStar()

        rsp = self.apiGet("groups/devgroup/unstar")
        self.assertEqual(rsp["stat"], "ok")
        self.assert_(Group.objects.get(name="devgroup") not in self.user.get_profile().starred_groups.all())

    def testGroupUnstarDoesNotExist(self):
        """Testing the groups/unstar API with Does Not Exist error"""
        rsp = self.apiGet("groups/invalidgroup/unstar")
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestList(self):
        """Testing the reviewrequests/all API"""
        rsp = self.apiGet("reviewrequests/all")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.public().count())

    def testReviewRequestListWithStatus(self):
        """Testing the reviewrequests/all API with custom status"""
        rsp = self.apiGet("reviewrequests/all", {"status": "submitted"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.public(status="S").count())

        rsp = self.apiGet("reviewrequests/all", {"status": "discarded"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.public(status="D").count())

        rsp = self.apiGet("reviewrequests/all", {"status": "all"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.public(status=None).count())

    def testReviewRequestListCount(self):
        """Testing the reviewrequests/all/count API"""
        rsp = self.apiGet("reviewrequests/all/count")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["count"], ReviewRequest.objects.public().count())

    def testReviewRequestsToGroup(self):
        """Testing the reviewrequests/to/group API"""
        rsp = self.apiGet("reviewrequests/to/group/devgroup")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_group("devgroup").count())

    def testReviewRequestsToGroupWithStatus(self):
        """Testing the reviewrequests/to/group API with custom status"""
        rsp = self.apiGet("reviewrequests/to/group/devgroup", {"status": "submitted"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_group("devgroup", status="S").count())

        rsp = self.apiGet("reviewrequests/to/group/devgroup", {"status": "discarded"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_group("devgroup", status="D").count())

    def testReviewRequestsToGroupCount(self):
        """Testing the reviewrequests/to/group/count API"""
        rsp = self.apiGet("reviewrequests/to/group/devgroup/count")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["count"], ReviewRequest.objects.to_group("devgroup").count())

    def testReviewRequestsToUser(self):
        """Testing the reviewrequests/to/user API"""
        rsp = self.apiGet("reviewrequests/to/user/grumpy")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_user("grumpy").count())

    def testReviewRequestsToUserWithStatus(self):
        """Testing the reviewrequests/to/user API with custom status"""
        rsp = self.apiGet("reviewrequests/to/user/grumpy", {"status": "submitted"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_user("grumpy", status="S").count())

        rsp = self.apiGet("reviewrequests/to/user/grumpy", {"status": "discarded"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_user("grumpy", status="D").count())

    def testReviewRequestsToUserCount(self):
        """Testing the reviewrequests/to/user/count API"""
        rsp = self.apiGet("reviewrequests/to/user/grumpy/count")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["count"], ReviewRequest.objects.to_user("grumpy").count())

    def testReviewRequestsToUserDirectly(self):
        """Testing the reviewrequests/to/user/directly API"""
        rsp = self.apiGet("reviewrequests/to/user/doc/directly")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_user_directly("doc").count())

    def testReviewRequestsToUserDirectlyWithStatus(self):
        """Testing the reviewrequests/to/user/directly API with custom status"""
        rsp = self.apiGet("reviewrequests/to/user/doc/directly", {"status": "submitted"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_user_directly("doc", status="S").count())

        rsp = self.apiGet("reviewrequests/to/user/doc/directly", {"status": "discarded"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.to_user_directly("doc", status="D").count())

    def testReviewRequestsToUserDirectlyCount(self):
        """Testing the reviewrequests/to/user/directly/count API"""
        rsp = self.apiGet("reviewrequests/to/user/doc/directly/count")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["count"], ReviewRequest.objects.to_user_directly("doc").count())

    def testReviewRequestsFromUser(self):
        """Testing the reviewrequests/from/user API"""
        rsp = self.apiGet("reviewrequests/from/user/grumpy")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.from_user("grumpy").count())

    def testReviewRequestsFromUserWithStatus(self):
        """Testing the reviewrequests/from/user API with custom status"""
        rsp = self.apiGet("reviewrequests/from/user/grumpy", {"status": "submitted"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.from_user("grumpy", status="S").count())

        rsp = self.apiGet("reviewrequests/from/user/grumpy", {"status": "discarded"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["review_requests"]), ReviewRequest.objects.from_user("grumpy", status="D").count())

    def testReviewRequestsFromUserCount(self):
        """Testing the reviewrequests/from/user/count API"""
        rsp = self.apiGet("reviewrequests/from/user/grumpy/count")
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["count"], ReviewRequest.objects.from_user("grumpy").count())

    def testNewReviewRequest(self):
        """Testing the reviewrequests/new API"""
        rsp = self.apiPost("reviewrequests/new", {"repository_path": self.repository.path})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["review_request"]["repository"]["id"], self.repository.id)

        # See if we can fetch this. Also return it for use in other
        # unit tests.
        return ReviewRequest.objects.get(pk=rsp["review_request"]["id"])

    def testNewReviewRequestWithInvalidRepository(self):
        """Testing the reviewrequests/new API with Invalid Repository error"""
        rsp = self.apiPost("reviewrequests/new", {"repository_path": "gobbledygook"})
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.INVALID_REPOSITORY.code)

    def testNewReviewRequestAsUser(self):
        """Testing the reviewrequests/new API with submit_as"""
        self.user.is_superuser = True
        self.user.save()

        rsp = self.apiPost("reviewrequests/new", {"repository_path": self.repository.path, "submit_as": "doc"})
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["review_request"]["repository"]["id"], self.repository.id)
        self.assertEqual(rsp["review_request"]["submitter"]["username"], "doc")

        ReviewRequest.objects.get(pk=rsp["review_request"]["id"])

    def testNewReviewRequestAsUserPermissionDenied(self):
        """Testing the reviewrequests/new API with submit_as and Permission Denied error"""
        rsp = self.apiPost("reviewrequests/new", {"repository_path": self.repository.path, "submit_as": "doc"})
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.PERMISSION_DENIED.code)

    def testReviewRequest(self):
        """Testing the reviewrequests/<id> API"""
        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiGet("reviewrequests/%s" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["review_request"]["id"], review_request.id)
        self.assertEqual(rsp["review_request"]["summary"], review_request.summary)

    def testReviewRequestPermissionDenied(self):
        """Testing the reviewrequests/<id> API with Permission Denied error"""
        review_request = ReviewRequest.objects.filter(public=False).exclude(submitter=self.user)[0]
        rsp = self.apiGet("reviewrequests/%s" % review_request.id)
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.PERMISSION_DENIED.code)

    def testReviewRequestByChangenum(self):
        """Testing the reviewrequests/repository/changenum API"""
        review_request = ReviewRequest.objects.filter(changenum__isnull=False)[0]
        rsp = self.apiGet(
            "reviewrequests/repository/%s/changenum/%s" % (review_request.repository.id, review_request.changenum)
        )
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["review_request"]["id"], review_request.id)
        self.assertEqual(rsp["review_request"]["summary"], review_request.summary)
        self.assertEqual(rsp["review_request"]["changenum"], review_request.changenum)

    def testReviewRequestStar(self):
        """Testing the reviewrequests/star API"""
        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiGet("reviewrequests/%s/star" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")
        self.assert_(review_request in self.user.get_profile().starred_review_requests.all())

    def testReviewRequestStarDoesNotExist(self):
        """Testing the reviewrequests/star API with Does Not Exist error"""
        rsp = self.apiGet("reviewrequests/999/star")
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestUnstar(self):
        """Testing the reviewrequests/unstar API"""
        # First, star it.
        self.testReviewRequestStar()

        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiGet("reviewrequests/%s/unstar" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")
        self.assert_(review_request not in self.user.get_profile().starred_review_requests.all())

    def testReviewRequestUnstarWithDoesNotExist(self):
        """Testing the reviewrequests/unstar API with Does Not Exist error"""
        rsp = self.apiGet("reviewrequests/999/unstar")
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestDelete(self):
        """Testing the reviewrequests/delete API"""
        self.user.user_permissions.add(Permission.objects.get(codename="delete_reviewrequest"))
        self.user.save()
        self.assert_(self.user.has_perm("reviews.delete_reviewrequest"))

        review_request_id = ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiGet("reviewrequests/%s/delete" % review_request_id)
        self.assertEqual(rsp["stat"], "ok")
        self.assertRaises(ReviewRequest.DoesNotExist, ReviewRequest.objects.get, pk=review_request_id)

    def testReviewRequestDeletePermissionDenied(self):
        """Testing the reviewrequests/delete API with Permission Denied error"""
        review_request_id = ReviewRequest.objects.exclude(submitter=self.user)[0].id
        rsp = self.apiGet("reviewrequests/%s/delete" % review_request_id)
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.PERMISSION_DENIED.code)

    def testReviewRequestDeleteDoesNotExist(self):
        """Testing the reviewrequests/delete API with Does Not Exist error"""
        self.user.user_permissions.add(Permission.objects.get(codename="delete_reviewrequest"))
        self.user.save()
        self.assert_(self.user.has_perm("reviews.delete_reviewrequest"))

        rsp = self.apiGet("reviewrequests/999/delete")
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestDraftSet(self):
        """Testing the reviewrequests/draft/set API"""
        summary = "My Summary"
        description = "My Description"
        testing_done = "My Testing Done"
        branch = "My Branch"
        bugs = ""

        review_request_id = ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost(
            "reviewrequests/%s/draft/set" % review_request_id,
            {
                "summary": summary,
                "description": description,
                "testing_done": testing_done,
                "branch": branch,
                "bugs_closed": bugs,
            },
        )

        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["draft"]["summary"], summary)
        self.assertEqual(rsp["draft"]["description"], description)
        self.assertEqual(rsp["draft"]["testing_done"], testing_done)
        self.assertEqual(rsp["draft"]["branch"], branch)
        self.assertEqual(rsp["draft"]["bugs_closed"], [])

        draft = ReviewRequestDraft.objects.get(pk=rsp["draft"]["id"])
        self.assertEqual(draft.summary, summary)
        self.assertEqual(draft.description, description)
        self.assertEqual(draft.testing_done, testing_done)
        self.assertEqual(draft.branch, branch)
        self.assertEqual(draft.get_bug_list(), [])

    def testReviewRequestDraftSetField(self):
        """Testing the reviewrequests/draft/set/<field> API"""
        bugs_closed = "123,456"
        review_request_id = ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/set/bugs_closed" % review_request_id, {"value": bugs_closed})

        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["bugs_closed"], bugs_closed.split(","))

    def testReviewRequestDraftSetFieldInvalidName(self):
        """Testing the reviewrequests/draft/set/<field> API with invalid name"""
        review_request_id = ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/set/foobar" % review_request_id, {"value": "foo"})

        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.INVALID_ATTRIBUTE.code)
        self.assertEqual(rsp["attribute"], "foobar")

    def testReviewRequestPublishSendsEmail(self):
        """Testing the reviewrequests/publish API"""
        # Set some data first.
        self.testReviewRequestDraftSet()

        review_request = ReviewRequest.objects.from_user(self.user.username)[0]

        rsp = self.apiPost("reviewrequests/%s/publish" % review_request.id)

        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(mail.outbox), 1)

    def testReviewRequestDraftSetFieldNoPermission(self):
        """Testing the reviewrequests/draft/set/<field> API without valid permissions"""
        bugs_closed = "123,456"
        review_request_id = ReviewRequest.objects.from_user("admin")[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/set/bugs_closed" % review_request_id, {"value": bugs_closed})

        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.PERMISSION_DENIED.code)

    # draft/save is deprecated. Tests were copied to *DraftPublish*().
    # This is still here only to make sure we don't break backwards
    # compatibility.
    def testReviewRequestDraftSave(self):
        """Testing the reviewrequests/draft/save API"""
        # Set some data first.
        self.testReviewRequestDraftSet()

        review_request_id = ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request_id)

        self.assertEqual(rsp["stat"], "ok")

        review_request = ReviewRequest.objects.get(pk=review_request_id)
        self.assertEqual(review_request.summary, "My Summary")
        self.assertEqual(review_request.description, "My Description")
        self.assertEqual(review_request.testing_done, "My Testing Done")
        self.assertEqual(review_request.branch, "My Branch")

    def testReviewRequestDraftSaveDoesNotExist(self):
        """Testing the reviewrequests/draft/save API with Does Not Exist error"""
        review_request_id = ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request_id)

        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestDraftPublish(self):
        """Testing the reviewrequests/draft/publish API"""
        # Set some data first.
        self.testReviewRequestDraftSet()

        review_request_id = ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/publish" % review_request_id)

        self.assertEqual(rsp["stat"], "ok")

        review_request = ReviewRequest.objects.get(pk=review_request_id)
        self.assertEqual(review_request.summary, "My Summary")
        self.assertEqual(review_request.description, "My Description")
        self.assertEqual(review_request.testing_done, "My Testing Done")
        self.assertEqual(review_request.branch, "My Branch")

        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].subject, "Review Request: My Summary")
        self.assertValidRecipients(["doc", "grumpy"], [])

    def testReviewRequestDraftPublishDoesNotExist(self):
        """Testing the reviewrequests/draft/publish API with Does Not Exist error"""
        review_request = ReviewRequest.objects.from_user(self.user.username)[0]
        rsp = self.apiPost("reviewrequests/%s/draft/publish" % review_request.id)

        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestDraftDiscard(self):
        """Testing the reviewrequests/draft/discard API"""
        review_request = ReviewRequest.objects.from_user(self.user.username)[0]
        summary = review_request.summary
        description = review_request.description

        # Set some data.
        self.testReviewRequestDraftSet()

        rsp = self.apiPost("reviewrequests/%s/draft/discard" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")

        review_request = ReviewRequest.objects.get(pk=review_request.id)
        self.assertEqual(review_request.summary, summary)
        self.assertEqual(review_request.description, description)

    def testReviewDraftSave(self):
        """Testing the reviewrequests/reviews/draft/save API"""
        body_top = ""
        body_bottom = "My Body Bottom"
        ship_it = True

        # Clear out any reviews on the first review request we find.
        review_request = ReviewRequest.objects.public()[0]
        review_request.reviews = []
        review_request.save()

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/draft/save" % review_request.id,
            {"shipit": ship_it, "body_top": body_top, "body_bottom": body_bottom},
        )

        reviews = review_request.reviews.filter(user=self.user)
        self.assertEqual(len(reviews), 1)
        review = reviews[0]

        self.assertEqual(review.ship_it, ship_it)
        self.assertEqual(review.body_top, body_top)
        self.assertEqual(review.body_bottom, body_bottom)
        self.assertEqual(review.public, False)

        self.assertEqual(len(mail.outbox), 0)

    def testReviewDraftPublish(self):
        """Testing the reviewrequests/reviews/draft/publish API"""
        body_top = "My Body Top"
        body_bottom = ""
        ship_it = True

        # Clear out any reviews on the first review request we find.
        review_request = ReviewRequest.objects.public()[0]
        review_request.reviews = []
        review_request.save()

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/draft/publish" % review_request.id,
            {"shipit": ship_it, "body_top": body_top, "body_bottom": body_bottom},
        )

        self.assertEqual(rsp["stat"], "ok")

        reviews = review_request.reviews.filter(user=self.user)
        self.assertEqual(len(reviews), 1)
        review = reviews[0]

        self.assertEqual(review.ship_it, ship_it)
        self.assertEqual(review.body_top, body_top)
        self.assertEqual(review.body_bottom, body_bottom)
        self.assertEqual(review.public, True)

        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].subject, "Re: Review Request: Interdiff Revision Test")
        self.assertValidRecipients(["admin", "grumpy"], [])

    def testReviewDraftDelete(self):
        """Testing the reviewrequests/reviews/draft/delete API"""
        # Set up the draft to delete.
        self.testReviewDraftSave()

        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiPost("reviewrequests/%s/reviews/draft/delete" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(review_request.reviews.count(), 0)

    def testReviewDraftDeleteDoesNotExist(self):
        """Testing the reviewrequests/reviews/draft/delete API with Does Not Exist error"""
        # Set up the draft to delete
        self.testReviewDraftPublish()

        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiPost("reviewrequests/%s/reviews/draft/delete" % review_request.id)
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.DOES_NOT_EXIST.code)

    def testReviewDraftComments(self):
        """Testing the reviewrequests/reviews/draft/comments API"""
        diff_comment_text = "Test diff comment"
        screenshot_comment_text = "Test screenshot comment"
        x, y, w, h = 2, 2, 10, 10

        screenshot = self.testNewScreenshot()
        review_request = screenshot.review_request.get()
        diffset = self.testNewDiff(review_request)
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")

        self.postNewDiffComment(review_request, diff_comment_text)
        self.postNewScreenshotComment(review_request, screenshot, screenshot_comment_text, x, y, w, h)

        rsp = self.apiGet("reviewrequests/%s/reviews/draft/comments" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["comments"]), 1)
        self.assertEqual(len(rsp["screenshot_comments"]), 1)
        self.assertEqual(rsp["comments"][0]["text"], diff_comment_text)
        self.assertEqual(rsp["screenshot_comments"][0]["text"], screenshot_comment_text)

    def testReviewsList(self):
        """Testing the reviewrequests/reviews API"""
        review_request = Review.objects.all()[0].review_request
        rsp = self.apiGet("reviewrequests/%s/reviews" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["reviews"]), review_request.reviews.count())

    def testReviewsListCount(self):
        """Testing the reviewrequests/reviews/count API"""
        review_request = Review.objects.all()[0].review_request
        rsp = self.apiGet("reviewrequests/%s/reviews/count" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["reviews"], review_request.reviews.count())

    def testReviewCommentsList(self):
        """Testing the reviewrequests/reviews/comments API"""
        review = Review.objects.filter(comments__pk__gt=0)[0]

        rsp = self.apiGet("reviewrequests/%s/reviews/%s/comments" % (review.review_request.id, review.id))
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["comments"]), review.comments.count())

    def testReviewCommentsCount(self):
        """Testing the reviewrequests/reviews/comments/count API"""
        review = Review.objects.filter(comments__pk__gt=0)[0]

        rsp = self.apiGet("reviewrequests/%s/reviews/%s/comments/count" % (review.review_request.id, review.id))
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["count"], review.comments.count())

    def testReplyDraftComment(self):
        """Testing the reviewrequests/reviews/replies/draft API with comment"""
        comment_text = "My Comment Text"

        comment = Comment.objects.all()[0]
        review = comment.review.get()

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/%s/replies/draft" % (review.review_request.id, review.id),
            {"type": "comment", "id": comment.id, "value": comment_text},
        )

        self.assertEqual(rsp["stat"], "ok")

        reply_comment = Comment.objects.get(pk=rsp["comment"]["id"])
        self.assertEqual(reply_comment.text, comment_text)

    def testReplyDraftScreenshotComment(self):
        """Testing the reviewrequests/reviews/replies/draft API with screenshot_comment"""
        comment_text = "My Comment Text"

        comment = self.testScreenshotCommentsSet()
        review = comment.review.get()

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/%s/replies/draft" % (review.review_request.id, review.id),
            {"type": "screenshot_comment", "id": comment.id, "value": comment_text},
        )

        self.assertEqual(rsp["stat"], "ok")

        reply_comment = ScreenshotComment.objects.get(pk=rsp["screenshot_comment"]["id"])
        self.assertEqual(reply_comment.text, comment_text)

    def testReplyDraftBodyTop(self):
        """Testing the reviewrequests/reviews/replies/draft API with body_top"""
        body_top = "My Body Top"

        review = Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/%s/replies/draft" % (review.review_request.id, review.id),
            {"type": "body_top", "value": body_top},
        )

        self.assertEqual(rsp["stat"], "ok")

        reply = Review.objects.get(pk=rsp["reply"]["id"])
        self.assertEqual(reply.body_top, body_top)

    def testReplyDraftBodyBottom(self):
        """Testing the reviewrequests/reviews/replies/draft API with body_bottom"""
        body_bottom = "My Body Bottom"

        review = Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/%s/replies/draft" % (review.review_request.id, review.id),
            {"type": "body_bottom", "value": body_bottom},
        )

        self.assertEqual(rsp["stat"], "ok")

        reply = Review.objects.get(pk=rsp["reply"]["id"])
        self.assertEqual(reply.body_bottom, body_bottom)

    def testReplyDraftSave(self):
        """Testing the reviewrequests/reviews/replies/draft/save API"""
        review = Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/%s/replies/draft" % (review.review_request.id, review.id),
            {"type": "body_top", "value": "Test"},
        )

        self.assertEqual(rsp["stat"], "ok")
        reply_id = rsp["reply"]["id"]

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft/save" % (review.review_request.id, review.id))
        self.assertEqual(rsp["stat"], "ok")

        reply = Review.objects.get(pk=reply_id)
        self.assertEqual(reply.public, True)

        self.assertEqual(len(mail.outbox), 1)

    def testReplyDraftDiscard(self):
        """Testing the reviewrequests/reviews/replies/draft/discard API"""
        review = Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/%s/replies/draft" % (review.review_request.id, review.id),
            {"type": "body_top", "value": "Test"},
        )

        self.assertEqual(rsp["stat"], "ok")
        reply_id = rsp["reply"]["id"]

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft/discard" % (review.review_request.id, review.id))
        self.assertEqual(rsp["stat"], "ok")

        self.assertEqual(Review.objects.filter(pk=reply_id).count(), 0)

    def testRepliesList(self):
        """Testing the reviewrequests/reviews/replies API"""
        review = Review.objects.filter(base_reply_to__isnull=True, public=True)[0]
        self.testReplyDraftSave()

        rsp = self.apiGet("reviewrequests/%s/reviews/%s/replies" % (review.review_request.id, review.id))
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["replies"]), len(review.public_replies()))

        for reply in review.public_replies():
            self.assertEqual(rsp["replies"][0]["id"], reply.id)
            self.assertEqual(rsp["replies"][0]["body_top"], reply.body_top)
            self.assertEqual(rsp["replies"][0]["body_bottom"], reply.body_bottom)

    def testRepliesListCount(self):
        """Testing the reviewrequests/reviews/replies/count API"""
        review = Review.objects.filter(base_reply_to__isnull=True, public=True)[0]
        self.testReplyDraftSave()

        rsp = self.apiGet("reviewrequests/%s/reviews/%s/replies/count" % (review.review_request.id, review.id))
        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(rsp["count"], len(review.public_replies()))

    def testNewDiff(self, review_request=None):
        """Testing the reviewrequests/diff/new API"""

        if review_request is None:
            review_request = self.testNewReviewRequest()

        diff_filename = os.path.join(
            os.path.dirname(os.path.dirname(__file__)), "scmtools", "testdata", "svn_makefile.diff"
        )
        f = open(diff_filename, "r")
        rsp = self.apiPost("reviewrequests/%s/diff/new" % review_request.id, {"path": f, "basedir": "/trunk"})
        f.close()

        self.assertEqual(rsp["stat"], "ok")

        # Return this so it can be used in other tests.
        return DiffSet.objects.get(pk=rsp["diffset_id"])

    def testNewDiffInvalidFormData(self):
        """Testing the reviewrequests/diff/new API with Invalid Form Data"""
        review_request = self.testNewReviewRequest()

        rsp = self.apiPost("reviewrequests/%s/diff/new" % review_request.id)
        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.INVALID_FORM_DATA.code)
        self.assert_("path" in rsp["fields"])
        self.assert_("basedir" in rsp["fields"])

    def testNewScreenshot(self):
        """Testing the reviewrequests/screenshot/new API"""
        review_request = self.testNewReviewRequest()

        f = open(self.__getTrophyFilename(), "r")
        self.assert_(f)
        rsp = self.apiPost("reviewrequests/%s/screenshot/new" % review_request.id, {"path": f})
        f.close()

        self.assertEqual(rsp["stat"], "ok")

        # Return the screenshot so we can use it in other tests.
        return Screenshot.objects.get(pk=rsp["screenshot_id"])

    def testNewScreenshotPermissionDenied(self):
        """Testing the reviewrequests/screenshot/new API with Permission Denied error"""
        review_request = ReviewRequest.objects.filter(public=True).exclude(submitter=self.user)[0]

        f = open(self.__getTrophyFilename(), "r")
        self.assert_(f)
        rsp = self.apiPost("reviewrequests/%s/screenshot/new" % review_request.id, {"caption": "Trophy", "path": f})
        f.close()

        self.assertEqual(rsp["stat"], "fail")
        self.assertEqual(rsp["err"]["code"], webapi.PERMISSION_DENIED.code)

    def postNewDiffComment(self, review_request, comment_text):
        """Utility function for posting a new diff comment."""
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = self.apiPost(
            "reviewrequests/%s/diff/%s/file/%s/line/%s/comments"
            % (review_request.id, diffset.revision, filediff.id, 10),
            {"action": "set", "text": comment_text, "num_lines": 5},
        )

        self.assertEqual(rsp["stat"], "ok")

        return rsp

    def testDiffCommentsSet(self):
        """Testing the reviewrequests/diff/file/line/comments set API"""
        comment_text = "This is a test comment."

        review_request = ReviewRequest.objects.public()[0]
        review_request.reviews = []

        rsp = self.postNewDiffComment(review_request, comment_text)

        self.assertEqual(len(rsp["comments"]), 1)
        self.assertEqual(rsp["comments"][0]["text"], comment_text)

    def testDiffCommentsDelete(self):
        """Testing the reviewrequests/diff/file/line/comments delete API"""
        comment_text = "This is a test comment."

        self.testDiffCommentsSet()

        review_request = ReviewRequest.objects.public()[0]
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = self.apiPost(
            "reviewrequests/%s/diff/%s/file/%s/line/%s/comments"
            % (review_request.id, diffset.revision, filediff.id, 10),
            {"action": "delete", "num_lines": 5},
        )

        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["comments"]), 0)

    def testDiffCommentsList(self):
        """Testing the reviewrequests/diff/file/line/comments list API"""
        self.testDiffCommentsSet()

        review_request = ReviewRequest.objects.public()[0]
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = self.apiGet(
            "reviewrequests/%s/diff/%s/file/%s/line/%s/comments"
            % (review_request.id, diffset.revision, filediff.id, 10)
        )

        self.assertEqual(rsp["stat"], "ok")

        comments = Comment.objects.filter(filediff=filediff)
        self.assertEqual(len(rsp["comments"]), comments.count())

        for i in range(0, len(rsp["comments"])):
            self.assertEqual(rsp["comments"][i]["text"], comments[i].text)

    def testInterDiffCommentsSet(self):
        """Testing the reviewrequests/diff/file/line/comments interdiff set API"""
        comment_text = "This is a test comment."

        # Create a review request for this test.
        review_request = self.testNewReviewRequest()

        # Upload the first diff and publish the draft.
        diffset_id = self.testNewDiff(review_request).id
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")

        # Upload the second diff and publish the draft.
        interdiffset_id = self.testNewDiff(review_request).id
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request.id)
        self.assertEqual(rsp["stat"], "ok")

        # Reload the diffsets, now that they've been modified.
        diffset = DiffSet.objects.get(pk=diffset_id)
        interdiffset = DiffSet.objects.get(pk=interdiffset_id)

        # Get the interdiffs
        filediff = diffset.files.all()[0]
        interfilediff = interdiffset.files.all()[0]

        rsp = self.apiPost(
            "reviewrequests/%s/diff/%s-%s/file/%s-%s/line/%s/comments"
            % (review_request.id, diffset.revision, interdiffset.revision, filediff.id, interfilediff.id, 10),
            {"action": "set", "text": comment_text, "num_lines": 5},
        )

        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["comments"]), 1)
        self.assertEqual(rsp["comments"][0]["text"], comment_text)

        # Return some information for use in other tests.
        return (review_request, diffset, interdiffset, filediff, interfilediff)

    def testInterDiffCommentsDelete(self):
        """Testing the reviewrequests/diff/file/line/comments interdiff delete API"""
        comment_text = "This is a test comment."

        review_request, diffset, interdiffset, filediff, interfilediff = self.testInterDiffCommentsSet()

        rsp = self.apiPost(
            "reviewrequests/%s/diff/%s-%s/file/%s-%s/line/%s/comments"
            % (review_request.id, diffset.revision, interdiffset.revision, filediff.id, interfilediff.id, 10),
            {"action": "delete", "num_lines": 5},
        )

        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["comments"]), 0)

    def testInterDiffCommentsList(self):
        """Testing the reviewrequests/diff/file/line/comments interdiff list API"""
        review_request, diffset, interdiffset, filediff, interfilediff = self.testInterDiffCommentsSet()

        rsp = self.apiGet(
            "reviewrequests/%s/diff/%s-%s/file/%s-%s/line/%s/comments"
            % (review_request.id, diffset.revision, interdiffset.revision, filediff.id, interfilediff.id, 10)
        )

        self.assertEqual(rsp["stat"], "ok")

        comments = Comment.objects.filter(filediff=filediff, interfilediff=interfilediff)
        self.assertEqual(len(rsp["comments"]), comments.count())

        for i in range(0, len(rsp["comments"])):
            self.assertEqual(rsp["comments"][i]["text"], comments[i].text)

    def postNewScreenshotComment(self, review_request, screenshot, comment_text, x, y, w, h):
        """Utility function for posting a new screenshot comment."""
        rsp = self.apiPost(
            "reviewrequests/%s/s/%s/comments/%sx%s+%s+%s" % (review_request.id, screenshot.id, w, h, x, y),
            {"action": "set", "text": comment_text},
        )

        self.assertEqual(rsp["stat"], "ok")
        return rsp

    def testScreenshotCommentsSet(self):
        """Testing the reviewrequests/s/comments set API"""
        comment_text = "This is a test comment."
        x, y, w, h = (2, 2, 10, 10)

        screenshot = self.testNewScreenshot()
        review_request = screenshot.review_request.get()

        rsp = self.postNewScreenshotComment(review_request, screenshot, comment_text, x, y, w, h)

        self.assertEqual(len(rsp["comments"]), 1)
        self.assertEqual(rsp["comments"][0]["text"], comment_text)
        self.assertEqual(rsp["comments"][0]["x"], x)
        self.assertEqual(rsp["comments"][0]["y"], y)
        self.assertEqual(rsp["comments"][0]["w"], w)
        self.assertEqual(rsp["comments"][0]["h"], h)

        # Return this so it can be used in other tests.
        return ScreenshotComment.objects.get(pk=rsp["comments"][0]["id"])

    def testScreenshotCommentsDelete(self):
        """Testing the reviewrequests/s/comments delete API"""
        comment = self.testScreenshotCommentsSet()
        screenshot = comment.screenshot
        review_request = screenshot.review_request.get()

        rsp = self.apiPost(
            "reviewrequests/%s/s/%s/comments/%sx%s+%s+%s"
            % (review_request.id, screenshot.id, comment.w, comment.h, comment.x, comment.y),
            {"action": "delete"},
        )

        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["comments"]), 0)

    def testScreenshotCommentsDeleteNonExistant(self):
        """Testing the reviewrequests/s/comments delete API with non-existant comment"""
        comment = self.testScreenshotCommentsSet()
        screenshot = comment.screenshot
        review_request = screenshot.review_request.get()

        rsp = self.apiPost(
            "reviewrequests/%s/s/%s/comments/%sx%s+%s+%s" % (review_request.id, screenshot.id, 1, 2, 3, 4),
            {"action": "delete"},
        )

        self.assertEqual(rsp["stat"], "ok")
        self.assertEqual(len(rsp["comments"]), 0)

    def testScreenshotCommentsList(self):
        """Testing the reviewrequests/s/comments list API"""
        comment = self.testScreenshotCommentsSet()
        screenshot = comment.screenshot
        review_request = screenshot.review_request.get()

        rsp = self.apiGet(
            "reviewrequests/%s/s/%s/comments/%sx%s+%s+%s"
            % (review_request.id, screenshot.id, comment.w, comment.h, comment.x, comment.y)
        )

        self.assertEqual(rsp["stat"], "ok")

        comments = ScreenshotComment.objects.filter(screenshot=screenshot)
        self.assertEqual(len(rsp["comments"]), comments.count())

        for i in range(0, len(rsp["comments"])):
            self.assertEqual(rsp["comments"][i]["text"], comments[i].text)
            self.assertEqual(rsp["comments"][i]["x"], comments[i].x)
            self.assertEqual(rsp["comments"][i]["y"], comments[i].y)
            self.assertEqual(rsp["comments"][i]["w"], comments[i].w)
            self.assertEqual(rsp["comments"][i]["h"], comments[i].h)

    def __getTrophyFilename(self):
        return os.path.join(settings.HTDOCS_ROOT, "media", "rb", "images", "trophy.png")
Ejemplo n.º 11
0
class WebAPITests(TestCase):
    """Testing the webapi support."""
    fixtures = ['test_users', 'test_reviewrequests', 'test_scmtools']

    def setUp(self):
        svn_repo_path = os.path.join(os.path.dirname(__file__),
                                     '../scmtools/testdata/svn_repo')
        self.repository = Repository(name='Subversion SVN',
                                     path='file://' + svn_repo_path,
                                     tool=Tool.objects.get(name='Subversion'))
        self.repository.save()

        self.client.login(username="******", password="******")
        self.user = User.objects.get(username="******")

    def tearDown(self):
        self.client.logout()

    def apiGet(self, path, query={}):
        print "Getting /api/json/%s/" % path
        print "Query data: %s" % query
        response = self.client.get("/api/json/%s/" % path, query)
        self.assertEqual(response.status_code, 200)
        print "Raw response: %s" % response.content
        rsp = simplejson.loads(response.content)
        print "Response: %s" % rsp
        return rsp

    def apiPost(self, path, query={}):
        print "Posting to /api/json/%s/" % path
        print "Post data: %s" % query
        response = self.client.post("/api/json/%s/" % path, query)
        self.assertEqual(response.status_code, 200)
        print "Raw response: %s" % response.content
        rsp = simplejson.loads(response.content)
        print "Response: %s" % rsp
        return rsp

    def testRepositoryList(self):
        """Testing the repositories API"""
        rsp = self.apiGet("repositories")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['repositories']), Repository.objects.count())

    def testUserList(self):
        """Testing the users API"""
        rsp = self.apiGet("users")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['users']), User.objects.count())

    def testUserListQuery(self):
        """Testing the users API with custom query"""
        rsp = self.apiGet("users", {'query': 'gru'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['users']), 1) # grumpy

    def testGroupList(self):
        """Testing the groups API"""
        rsp = self.apiGet("groups")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['groups']), Group.objects.count())

    def testGroupListQuery(self):
        """Testing the groups API with custom query"""
        rsp = self.apiGet("groups", {'query': 'dev'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['groups']), 1) #devgroup

    def testGroupStar(self):
        """Testing the groups/star API"""
        rsp = self.apiGet("groups/devgroup/star")
        self.assertEqual(rsp['stat'], 'ok')
        self.assert_(Group.objects.get(name="devgroup") in
                     self.user.get_profile().starred_groups.all())

    def testGroupStarDoesNotExist(self):
        """Testing the groups/star API with Does Not Exist error"""
        rsp = self.apiGet("groups/invalidgroup/star")
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.DOES_NOT_EXIST.code)

    def testGroupUnstar(self):
        """Testing the groups/unstar API"""
        # First, star it.
        self.testGroupStar()

        rsp = self.apiGet("groups/devgroup/unstar")
        self.assertEqual(rsp['stat'], 'ok')
        self.assert_(Group.objects.get(name="devgroup") not in
                     self.user.get_profile().starred_groups.all())

    def testGroupUnstarDoesNotExist(self):
        """Testing the groups/unstar API with Does Not Exist error"""
        rsp = self.apiGet("groups/invalidgroup/unstar")
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestList(self):
        """Testing the reviewrequests/all API"""
        rsp = self.apiGet("reviewrequests/all")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public().count())

    def testReviewRequestListWithStatus(self):
        """Testing the reviewrequests/all API with custom status"""
        rsp = self.apiGet("reviewrequests/all", {'status': 'submitted'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public(status='S').count())

        rsp = self.apiGet("reviewrequests/all", {'status': 'discarded'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public(status='D').count())

        rsp = self.apiGet("reviewrequests/all", {'status': 'all'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.public(status=None).count())

    def testReviewRequestListCount(self):
        """Testing the reviewrequests/all/count API"""
        rsp = self.apiGet("reviewrequests/all/count")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['count'], ReviewRequest.objects.public().count())

    def testReviewRequestsToGroup(self):
        """Testing the reviewrequests/to/group API"""
        rsp = self.apiGet("reviewrequests/to/group/devgroup")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.to_group("devgroup").count())

    def testReviewRequestsToGroupWithStatus(self):
        """Testing the reviewrequests/to/group API with custom status"""
        rsp = self.apiGet("reviewrequests/to/group/devgroup",
                          {'status': 'submitted'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_group("devgroup", status='S').count())

        rsp = self.apiGet("reviewrequests/to/group/devgroup",
                          {'status': 'discarded'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_group("devgroup", status='D').count())

    def testReviewRequestsToGroupCount(self):
        """Testing the reviewrequests/to/group/count API"""
        rsp = self.apiGet("reviewrequests/to/group/devgroup/count")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['count'],
                         ReviewRequest.objects.to_group("devgroup").count())

    def testReviewRequestsToUser(self):
        """Testing the reviewrequests/to/user API"""
        rsp = self.apiGet("reviewrequests/to/user/grumpy")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.to_user("grumpy").count())

    def testReviewRequestsToUserWithStatus(self):
        """Testing the reviewrequests/to/user API with custom status"""
        rsp = self.apiGet("reviewrequests/to/user/grumpy",
                          {'status': 'submitted'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_user("grumpy", status='S').count())

        rsp = self.apiGet("reviewrequests/to/user/grumpy",
                          {'status': 'discarded'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_user("grumpy", status='D').count())

    def testReviewRequestsToUserCount(self):
        """Testing the reviewrequests/to/user/count API"""
        rsp = self.apiGet("reviewrequests/to/user/grumpy/count")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['count'],
                         ReviewRequest.objects.to_user("grumpy").count())

    def testReviewRequestsToUserDirectly(self):
        """Testing the reviewrequests/to/user/directly API"""
        rsp = self.apiGet("reviewrequests/to/user/doc/directly")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.to_user_directly("doc").count())

    def testReviewRequestsToUserDirectlyWithStatus(self):
        """Testing the reviewrequests/to/user/directly API with custom status"""
        rsp = self.apiGet("reviewrequests/to/user/doc/directly",
                          {'status': 'submitted'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_user_directly("doc", status='S').count())

        rsp = self.apiGet("reviewrequests/to/user/doc/directly",
                          {'status': 'discarded'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.to_user_directly("doc", status='D').count())

    def testReviewRequestsToUserDirectlyCount(self):
        """Testing the reviewrequests/to/user/directly/count API"""
        rsp = self.apiGet("reviewrequests/to/user/doc/directly/count")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['count'],
                         ReviewRequest.objects.to_user_directly("doc").count())

    def testReviewRequestsFromUser(self):
        """Testing the reviewrequests/from/user API"""
        rsp = self.apiGet("reviewrequests/from/user/grumpy")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
                         ReviewRequest.objects.from_user("grumpy").count())

    def testReviewRequestsFromUserWithStatus(self):
        """Testing the reviewrequests/from/user API with custom status"""
        rsp = self.apiGet("reviewrequests/from/user/grumpy",
                          {'status': 'submitted'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.from_user("grumpy", status='S').count())

        rsp = self.apiGet("reviewrequests/from/user/grumpy",
                          {'status': 'discarded'})
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['review_requests']),
            ReviewRequest.objects.from_user("grumpy", status='D').count())

    def testReviewRequestsFromUserCount(self):
        """Testing the reviewrequests/from/user/count API"""
        rsp = self.apiGet("reviewrequests/from/user/grumpy/count")
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['count'],
                         ReviewRequest.objects.from_user("grumpy").count())

    def testNewReviewRequest(self):
        """Testing the reviewrequests/new API"""
        rsp = self.apiPost("reviewrequests/new", {
            'repository_path': self.repository.path,
        })
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['review_request']['repository']['id'],
                         self.repository.id)

        # See if we can fetch this. Also return it for use in other
        # unit tests.
        return ReviewRequest.objects.get(pk=rsp['review_request']['id'])

    def testNewReviewRequestWithInvalidRepository(self):
        """Testing the reviewrequests/new API with Invalid Repository error"""
        rsp = self.apiPost("reviewrequests/new", {
            'repository_path': 'gobbledygook',
        })
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.INVALID_REPOSITORY.code)

    def testNewReviewRequestAsUser(self):
        """Testing the reviewrequests/new API with submit_as"""
        self.user.is_superuser = True
        self.user.save()

        rsp = self.apiPost("reviewrequests/new", {
            'repository_path': self.repository.path,
            'submit_as': 'doc',
        })
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['review_request']['repository']['id'],
                         self.repository.id)
        self.assertEqual(rsp['review_request']['submitter']['username'], 'doc')

        ReviewRequest.objects.get(pk=rsp['review_request']['id'])

    def testNewReviewRequestAsUserPermissionDenied(self):
        """Testing the reviewrequests/new API with submit_as and Permission Denied error"""
        rsp = self.apiPost("reviewrequests/new", {
            'repository_path': self.repository.path,
            'submit_as': 'doc',
        })
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.PERMISSION_DENIED.code)

    def testReviewRequest(self):
        """Testing the reviewrequests/<id> API"""
        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiGet("reviewrequests/%s" % review_request.id)
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['review_request']['id'], review_request.id)
        self.assertEqual(rsp['review_request']['summary'],
                         review_request.summary)

    def testReviewRequestPermissionDenied(self):
        """Testing the reviewrequests/<id> API with Permission Denied error"""
        review_request = ReviewRequest.objects.filter(public=False).\
            exclude(submitter=self.user)[0]
        rsp = self.apiGet("reviewrequests/%s" % review_request.id)
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.PERMISSION_DENIED.code)

    def testReviewRequestByChangenum(self):
        """Testing the reviewrequests/repository/changenum API"""
        review_request = \
            ReviewRequest.objects.filter(changenum__isnull=False)[0]
        rsp = self.apiGet("reviewrequests/repository/%s/changenum/%s" %
                          (review_request.repository.id,
                           review_request.changenum))
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['review_request']['id'], review_request.id)
        self.assertEqual(rsp['review_request']['summary'],
                         review_request.summary)
        self.assertEqual(rsp['review_request']['changenum'],
                         review_request.changenum)

    def testReviewRequestStar(self):
        """Testing the reviewrequests/star API"""
        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiGet("reviewrequests/%s/star" % review_request.id)
        self.assertEqual(rsp['stat'], 'ok')
        self.assert_(review_request in
                     self.user.get_profile().starred_review_requests.all())

    def testReviewRequestStarDoesNotExist(self):
        """Testing the reviewrequests/star API with Does Not Exist error"""
        rsp = self.apiGet("reviewrequests/999/star")
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestUnstar(self):
        """Testing the reviewrequests/unstar API"""
        # First, star it.
        self.testReviewRequestStar()

        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiGet("reviewrequests/%s/unstar" % review_request.id)
        self.assertEqual(rsp['stat'], 'ok')
        self.assert_(review_request not in
                     self.user.get_profile().starred_review_requests.all())

    def testReviewRequestUnstarWithDoesNotExist(self):
        """Testing the reviewrequests/unstar API with Does Not Exist error"""
        rsp = self.apiGet("reviewrequests/999/unstar")
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestDelete(self):
        """Testing the reviewrequests/delete API"""
        self.user.user_permissions.add(
            Permission.objects.get(codename='delete_reviewrequest'))
        self.user.save()
        self.assert_(self.user.has_perm('reviews.delete_reviewrequest'))

        review_request_id = \
            ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiGet("reviewrequests/%s/delete" % review_request_id)
        self.assertEqual(rsp['stat'], 'ok')
        self.assertRaises(ReviewRequest.DoesNotExist,
                          ReviewRequest.objects.get, pk=review_request_id)

    def testReviewRequestDeletePermissionDenied(self):
        """Testing the reviewrequests/delete API with Permission Denied error"""
        review_request_id = \
            ReviewRequest.objects.exclude(submitter=self.user)[0].id
        rsp = self.apiGet("reviewrequests/%s/delete" % review_request_id)
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.PERMISSION_DENIED.code)

    def testReviewRequestDeleteDoesNotExist(self):
        """Testing the reviewrequests/delete API with Does Not Exist error"""
        self.user.user_permissions.add(
            Permission.objects.get(codename='delete_reviewrequest'))
        self.user.save()
        self.assert_(self.user.has_perm('reviews.delete_reviewrequest'))

        rsp = self.apiGet("reviewrequests/999/delete")
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestDraftSet(self):
        """Testing the reviewrequests/draft/set API"""
        summary = "My Summary"
        description = "My Description"
        testing_done = "My Testing Done"
        branch = "My Branch"
        bugs = ""

        review_request_id = \
            ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/set" % review_request_id, {
            'summary': summary,
            'description': description,
            'testing_done': testing_done,
            'branch': branch,
            'bugs_closed': bugs,
        })

        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['draft']['summary'], summary)
        self.assertEqual(rsp['draft']['description'], description)
        self.assertEqual(rsp['draft']['testing_done'], testing_done)
        self.assertEqual(rsp['draft']['branch'], branch)
        self.assertEqual(rsp['draft']['bugs_closed'], [])

        draft = ReviewRequestDraft.objects.get(pk=rsp['draft']['id'])
        self.assertEqual(draft.summary, summary)
        self.assertEqual(draft.description, description)
        self.assertEqual(draft.testing_done, testing_done)
        self.assertEqual(draft.branch, branch)
        self.assertEqual(draft.get_bug_list(), [])

    def testReviewRequestDraftSetField(self):
        """Testing the reviewrequests/draft/set/<field> API"""
        bugs_closed = '123,456'
        review_request_id = \
            ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/set/bugs_closed" %
                           review_request_id, {
            'value': bugs_closed,
        })

        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['bugs_closed'], bugs_closed.split(","))

    def testReviewRequestDraftSetFieldInvalidName(self):
        """Testing the reviewrequests/draft/set/<field> API with invalid name"""
        review_request_id = \
            ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/set/foobar" %
                           review_request_id, {
            'value': 'foo',
        })

        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.INVALID_ATTRIBUTE.code)
        self.assertEqual(rsp['attribute'], 'foobar')

    def testReviewRequestDraftSetFieldNoPermission(self):
        """Testing the reviewrequests/draft/set/<field> API without valid permissions"""
        bugs_closed = '123,456'
        review_request_id = ReviewRequest.objects.from_user('admin')[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/set/bugs_closed" %
                           review_request_id, {
            'value': bugs_closed,
        })

        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.PERMISSION_DENIED.code)

    def testReviewRequestDraftSave(self):
        """Testing the reviewrequests/draft/save API"""
        # Set some data first.
        self.testReviewRequestDraftSet()

        review_request_id = \
            ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request_id)

        self.assertEqual(rsp['stat'], 'ok')

        review_request = ReviewRequest.objects.get(pk=review_request_id)
        self.assertEqual(review_request.summary, "My Summary")
        self.assertEqual(review_request.description, "My Description")
        self.assertEqual(review_request.testing_done, "My Testing Done")
        self.assertEqual(review_request.branch, "My Branch")

    def testReviewRequestDraftSaveDoesNotExist(self):
        """Testing the reviewrequests/draft/save API with Does Not Exist error"""
        review_request_id = \
            ReviewRequest.objects.from_user(self.user.username)[0].id
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request_id)

        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.DOES_NOT_EXIST.code)

    def testReviewRequestDraftDiscard(self):
        """Testing the reviewrequests/draft/discard API"""
        review_request = ReviewRequest.objects.from_user(self.user.username)[0]
        summary = review_request.summary
        description = review_request.description

        # Set some data.
        self.testReviewRequestDraftSet()

        rsp = self.apiPost("reviewrequests/%s/draft/discard" %
                           review_request.id)
        self.assertEqual(rsp['stat'], 'ok')

        review_request = ReviewRequest.objects.get(pk=review_request.id)
        self.assertEqual(review_request.summary, summary)
        self.assertEqual(review_request.description, description)

    def testReviewDraftSave(self):
        """Testing the reviewrequests/reviews/draft/save API"""
        body_top = ""
        body_bottom = "My Body Bottom"
        ship_it = True

        # Clear out any reviews on the first review request we find.
        review_request = ReviewRequest.objects.public()[0]
        review_request.reviews = []
        review_request.save()

        rsp = self.apiPost("reviewrequests/%s/reviews/draft/save" %
                           review_request.id, {
            'shipit': ship_it,
            'body_top': body_top,
            'body_bottom': body_bottom,
        })

        reviews = review_request.reviews.filter(user=self.user)
        self.assertEqual(len(reviews), 1)
        review = reviews[0]

        self.assertEqual(review.ship_it, ship_it)
        self.assertEqual(review.body_top, body_top)
        self.assertEqual(review.body_bottom, body_bottom)
        self.assertEqual(review.public, False)

    def testReviewDraftPublish(self):
        """Testing the reviewrequests/reviews/draft/publish API"""
        body_top = "My Body Top"
        body_bottom = ""
        ship_it = True

        # Clear out any reviews on the first review request we find.
        review_request = ReviewRequest.objects.public()[0]
        review_request.reviews = []
        review_request.save()

        rsp = self.apiPost("reviewrequests/%s/reviews/draft/publish" %
                           review_request.id, {
            'shipit': ship_it,
            'body_top': body_top,
            'body_bottom': body_bottom,
        })

        self.assertEqual(rsp['stat'], 'ok')

        reviews = review_request.reviews.filter(user=self.user)
        self.assertEqual(len(reviews), 1)
        review = reviews[0]

        self.assertEqual(review.ship_it, ship_it)
        self.assertEqual(review.body_top, body_top)
        self.assertEqual(review.body_bottom, body_bottom)
        self.assertEqual(review.public, True)

    def testReviewDraftDelete(self):
        """Testing the reviewrequests/reviews/draft/delete API"""
        # Set up the draft to delete.
        self.testReviewDraftSave()

        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiPost("reviewrequests/%s/reviews/draft/delete" %
                           review_request.id)
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(review_request.reviews.count(), 0)

    def testReviewDraftDeleteDoesNotExist(self):
        """Testing the reviewrequests/reviews/draft/delete API with Does Not Exist error"""
        # Set up the draft to delete
        self.testReviewDraftPublish()

        review_request = ReviewRequest.objects.public()[0]
        rsp = self.apiPost("reviewrequests/%s/reviews/draft/delete" %
                           review_request.id)
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.DOES_NOT_EXIST.code)

    def testReviewDraftComments(self):
        """Testing the reviewrequests/reviews/draft/comments API"""
        diff_comment_text = "Test diff comment"
        screenshot_comment_text = "Test screenshot comment"
        x, y, w, h = 2, 2, 10, 10

        screenshot = self.testNewScreenshot()
        review_request = screenshot.review_request.get()
        diffset = self.testNewDiff(review_request)
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request.id)
        self.assertEqual(rsp['stat'], 'ok')

        self.postNewDiffComment(review_request, diff_comment_text)
        self.postNewScreenshotComment(review_request, screenshot,
                                      screenshot_comment_text, x, y, w, h)

        rsp = self.apiGet("reviewrequests/%s/reviews/draft/comments" %
                          review_request.id)
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['comments']), 1)
        self.assertEqual(len(rsp['screenshot_comments']), 1)
        self.assertEqual(rsp['comments'][0]['text'], diff_comment_text)
        self.assertEqual(rsp['screenshot_comments'][0]['text'],
                         screenshot_comment_text)

    def testReviewsList(self):
        """Testing the reviewrequests/reviews API"""
        review_request = Review.objects.all()[0].review_request
        rsp = self.apiGet("reviewrequests/%s/reviews" % review_request.id)
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['reviews']), review_request.reviews.count())

    def testReviewsListCount(self):
        """Testing the reviewrequests/reviews/count API"""
        review_request = Review.objects.all()[0].review_request
        rsp = self.apiGet("reviewrequests/%s/reviews/count" %
                          review_request.id)
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['reviews'], review_request.reviews.count())

    def testReviewCommentsList(self):
        """Testing the reviewrequests/reviews/comments API"""
        review = Review.objects.filter(comments__pk__gt=0)[0]

        rsp = self.apiGet("reviewrequests/%s/reviews/%s/comments" %
                          (review.review_request.id, review.id))
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['comments']), review.comments.count())

    def testReviewCommentsCount(self):
        """Testing the reviewrequests/reviews/comments/count API"""
        review = Review.objects.filter(comments__pk__gt=0)[0]

        rsp = self.apiGet("reviewrequests/%s/reviews/%s/comments/count" %
                          (review.review_request.id, review.id))
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['count'], review.comments.count())

    def testReplyDraftComment(self):
        """Testing the reviewrequests/reviews/replies/draft API with comment"""
        comment_text = "My Comment Text"

        comment = Comment.objects.all()[0]
        review = comment.review.get()

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft" %
                           (review.review_request.id, review.id), {
            'type': 'comment',
            'id': comment.id,
            'value': comment_text
        })

        self.assertEqual(rsp['stat'], 'ok')

        reply_comment = Comment.objects.get(pk=rsp['comment']['id'])
        self.assertEqual(reply_comment.text, comment_text)

    def testReplyDraftScreenshotComment(self):
        """Testing the reviewrequests/reviews/replies/draft API with screenshot_comment"""
        comment_text = "My Comment Text"

        comment = self.testScreenshotCommentsSet()
        review = comment.review.get()

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft" %
                           (review.review_request.id, review.id), {
            'type': 'screenshot_comment',
            'id': comment.id,
            'value': comment_text,
        })

        self.assertEqual(rsp['stat'], 'ok')

        reply_comment = ScreenshotComment.objects.get(
            pk=rsp['screenshot_comment']['id'])
        self.assertEqual(reply_comment.text, comment_text)

    def testReplyDraftBodyTop(self):
        """Testing the reviewrequests/reviews/replies/draft API with body_top"""
        body_top = 'My Body Top'

        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft" %
                           (review.review_request.id, review.id), {
            'type': 'body_top',
            'value': body_top,
        })

        self.assertEqual(rsp['stat'], 'ok')

        reply = Review.objects.get(pk=rsp['reply']['id'])
        self.assertEqual(reply.body_top, body_top)

    def testReplyDraftBodyBottom(self):
        """Testing the reviewrequests/reviews/replies/draft API with body_bottom"""
        body_bottom = 'My Body Bottom'

        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft" %
                           (review.review_request.id, review.id), {
            'type': 'body_bottom',
            'value': body_bottom,
        })

        self.assertEqual(rsp['stat'], 'ok')

        reply = Review.objects.get(pk=rsp['reply']['id'])
        self.assertEqual(reply.body_bottom, body_bottom)

    def testReplyDraftSave(self):
        """Testing the reviewrequests/reviews/replies/draft/save API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft" %
                           (review.review_request.id, review.id), {
            'type': 'body_top',
            'value': 'Test',
        })

        self.assertEqual(rsp['stat'], 'ok')
        reply_id = rsp['reply']['id']

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft/save" %
                           (review.review_request.id, review.id))
        self.assertEqual(rsp['stat'], 'ok')

        reply = Review.objects.get(pk=reply_id)
        self.assertEqual(reply.public, True)

    def testReplyDraftDiscard(self):
        """Testing the reviewrequests/reviews/replies/draft/discard API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]

        rsp = self.apiPost("reviewrequests/%s/reviews/%s/replies/draft" %
                           (review.review_request.id, review.id), {
            'type': 'body_top',
            'value': 'Test',
        })

        self.assertEqual(rsp['stat'], 'ok')
        reply_id = rsp['reply']['id']

        rsp = self.apiPost(
            "reviewrequests/%s/reviews/%s/replies/draft/discard" %
            (review.review_request.id, review.id))
        self.assertEqual(rsp['stat'], 'ok')

        self.assertEqual(Review.objects.filter(pk=reply_id).count(), 0)

    def testRepliesList(self):
        """Testing the reviewrequests/reviews/replies API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]
        self.testReplyDraftSave()

        rsp = self.apiGet("reviewrequests/%s/reviews/%s/replies" %
                          (review.review_request.id, review.id))
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['replies']), len(review.public_replies()))

        for reply in review.public_replies():
            self.assertEqual(rsp['replies'][0]['id'], reply.id)
            self.assertEqual(rsp['replies'][0]['body_top'], reply.body_top)
            self.assertEqual(rsp['replies'][0]['body_bottom'],
                             reply.body_bottom)

    def testRepliesListCount(self):
        """Testing the reviewrequests/reviews/replies/count API"""
        review = \
            Review.objects.filter(base_reply_to__isnull=True, public=True)[0]
        self.testReplyDraftSave()

        rsp = self.apiGet("reviewrequests/%s/reviews/%s/replies/count" %
                          (review.review_request.id, review.id))
        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(rsp['count'], len(review.public_replies()))

    def testNewDiff(self, review_request=None):
        """Testing the reviewrequests/diff/new API"""

        if review_request is None:
            review_request = self.testNewReviewRequest()

        diff_filename = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            "scmtools", "testdata", "svn_makefile.diff")
        f = open(diff_filename, "r")
        rsp = self.apiPost("reviewrequests/%s/diff/new" % review_request.id, {
            'path': f,
            'basedir': "/trunk",
        })
        f.close()

        self.assertEqual(rsp['stat'], 'ok')

        # Return this so it can be used in other tests.
        return DiffSet.objects.get(pk=rsp['diffset_id'])

    def testNewDiffInvalidFormData(self):
        """Testing the reviewrequests/diff/new API with Invalid Form Data"""
        review_request = self.testNewReviewRequest()

        rsp = self.apiPost("reviewrequests/%s/diff/new" % review_request.id)
        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.INVALID_FORM_DATA.code)
        self.assert_('path' in rsp['fields'])
        self.assert_('basedir' in rsp['fields'])

    def testNewScreenshot(self):
        """Testing the reviewrequests/screenshot/new API"""
        review_request = self.testNewReviewRequest()

        f = open(self.__getTrophyFilename(), "r")
        self.assert_(f)
        rsp = self.apiPost("reviewrequests/%s/screenshot/new" %
                           review_request.id, {
            'path': f,
        })
        f.close()

        self.assertEqual(rsp['stat'], 'ok')

        # Return the screenshot so we can use it in other tests.
        return Screenshot.objects.get(pk=rsp['screenshot_id'])

    def testNewScreenshotPermissionDenied(self):
        """Testing the reviewrequests/screenshot/new API with Permission Denied error"""
        review_request = ReviewRequest.objects.filter(public=True).\
            exclude(submitter=self.user)[0]

        f = open(self.__getTrophyFilename(), "r")
        self.assert_(f)
        rsp = self.apiPost("reviewrequests/%s/screenshot/new" %
                           review_request.id, {
            'caption': 'Trophy',
            'path': f,
        })
        f.close()

        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], webapi.PERMISSION_DENIED.code)

    def postNewDiffComment(self, review_request, comment_text):
        """Utility function for posting a new diff comment."""
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = self.apiPost(
            "reviewrequests/%s/diff/%s/file/%s/line/%s/comments" %
            (review_request.id, diffset.revision, filediff.id, 10),
            {
                'action': 'set',
                'text': comment_text,
                'num_lines': 5,
            }
        )

        self.assertEqual(rsp['stat'], 'ok')

        return rsp

    def testDiffCommentsSet(self):
        """Testing the reviewrequests/diff/file/line/comments set API"""
        comment_text = "This is a test comment."

        review_request = ReviewRequest.objects.public()[0]
        review_request.reviews = []

        rsp = self.postNewDiffComment(review_request, comment_text)

        self.assertEqual(len(rsp['comments']), 1)
        self.assertEqual(rsp['comments'][0]['text'], comment_text)

    def testDiffCommentsDelete(self):
        """Testing the reviewrequests/diff/file/line/comments delete API"""
        comment_text = "This is a test comment."

        self.testDiffCommentsSet()

        review_request = ReviewRequest.objects.public()[0]
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = self.apiPost(
            "reviewrequests/%s/diff/%s/file/%s/line/%s/comments" %
            (review_request.id, diffset.revision, filediff.id, 10),
            {
                'action': 'delete',
                'num_lines': 5,
            }
        )

        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['comments']), 0)

    def testDiffCommentsList(self):
        """Testing the reviewrequests/diff/file/line/comments list API"""
        self.testDiffCommentsSet()

        review_request = ReviewRequest.objects.public()[0]
        diffset = review_request.diffset_history.diffsets.latest()
        filediff = diffset.files.all()[0]

        rsp = self.apiGet(
            "reviewrequests/%s/diff/%s/file/%s/line/%s/comments" %
            (review_request.id, diffset.revision, filediff.id, 10))

        self.assertEqual(rsp['stat'], 'ok')

        comments = Comment.objects.filter(filediff=filediff)
        self.assertEqual(len(rsp['comments']), comments.count())

        for i in range(0, len(rsp['comments'])):
            self.assertEqual(rsp['comments'][i]['text'], comments[i].text)


    def testInterDiffCommentsSet(self):
        """Testing the reviewrequests/diff/file/line/comments interdiff set API"""
        comment_text = "This is a test comment."

        # Create a review request for this test.
        review_request = self.testNewReviewRequest()

        # Upload the first diff and publish the draft.
        diffset_id = self.testNewDiff(review_request).id
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request.id)
        self.assertEqual(rsp['stat'], 'ok')

        # Upload the second diff and publish the draft.
        interdiffset_id = self.testNewDiff(review_request).id
        rsp = self.apiPost("reviewrequests/%s/draft/save" % review_request.id)
        self.assertEqual(rsp['stat'], 'ok')

        # Reload the diffsets, now that they've been modified.
        diffset = DiffSet.objects.get(pk=diffset_id)
        interdiffset = DiffSet.objects.get(pk=interdiffset_id)

        # Get the interdiffs
        filediff = diffset.files.all()[0]
        interfilediff = interdiffset.files.all()[0]

        rsp = self.apiPost(
            "reviewrequests/%s/diff/%s-%s/file/%s-%s/line/%s/comments" %
            (review_request.id, diffset.revision, interdiffset.revision,
             filediff.id, interfilediff.id, 10),
            {
                'action': 'set',
                'text': comment_text,
                'num_lines': 5,
            }
        )

        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['comments']), 1)
        self.assertEqual(rsp['comments'][0]['text'], comment_text)

        # Return some information for use in other tests.
        return (review_request, diffset, interdiffset, filediff, interfilediff)

    def testInterDiffCommentsDelete(self):
        """Testing the reviewrequests/diff/file/line/comments interdiff delete API"""
        comment_text = "This is a test comment."

        review_request, diffset, interdiffset, filediff, interfilediff = \
            self.testInterDiffCommentsSet()

        rsp = self.apiPost(
            "reviewrequests/%s/diff/%s-%s/file/%s-%s/line/%s/comments" %
            (review_request.id, diffset.revision, interdiffset.revision,
             filediff.id, interfilediff.id, 10),
            {
                'action': 'delete',
                'num_lines': 5,
            }
        )

        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['comments']), 0)

    def testInterDiffCommentsList(self):
        """Testing the reviewrequests/diff/file/line/comments interdiff list API"""
        review_request, diffset, interdiffset, filediff, interfilediff = \
            self.testInterDiffCommentsSet()

        rsp = self.apiGet(
            "reviewrequests/%s/diff/%s-%s/file/%s-%s/line/%s/comments" %
            (review_request.id, diffset.revision, interdiffset.revision,
             filediff.id, interfilediff.id, 10))

        self.assertEqual(rsp['stat'], 'ok')

        comments = Comment.objects.filter(filediff=filediff,
                                          interfilediff=interfilediff)
        self.assertEqual(len(rsp['comments']), comments.count())

        for i in range(0, len(rsp['comments'])):
            self.assertEqual(rsp['comments'][i]['text'], comments[i].text)

    def postNewScreenshotComment(self, review_request, screenshot,
                                 comment_text, x, y, w, h):
        """Utility function for posting a new screenshot comment."""
        rsp = self.apiPost(
            "reviewrequests/%s/s/%s/comments/%sx%s+%s+%s" %
            (review_request.id, screenshot.id, w, h, x, y),
            {
                'action': 'set',
                'text': comment_text,
            }
        )

        self.assertEqual(rsp['stat'], 'ok')
        return rsp

    def testScreenshotCommentsSet(self):
        """Testing the reviewrequests/s/comments set API"""
        comment_text = "This is a test comment."
        x, y, w, h = (2, 2, 10, 10)

        screenshot = self.testNewScreenshot()
        review_request = screenshot.review_request.get()

        rsp = self.postNewScreenshotComment(review_request, screenshot,
                                            comment_text, x, y, w, h)

        self.assertEqual(len(rsp['comments']), 1)
        self.assertEqual(rsp['comments'][0]['text'], comment_text)
        self.assertEqual(rsp['comments'][0]['x'], x)
        self.assertEqual(rsp['comments'][0]['y'], y)
        self.assertEqual(rsp['comments'][0]['w'], w)
        self.assertEqual(rsp['comments'][0]['h'], h)

        # Return this so it can be used in other tests.
        return ScreenshotComment.objects.get(pk=rsp['comments'][0]['id'])

    def testScreenshotCommentsDelete(self):
        """Testing the reviewrequests/s/comments delete API"""
        comment = self.testScreenshotCommentsSet()
        screenshot = comment.screenshot
        review_request = screenshot.review_request.get()

        rsp = self.apiPost(
            "reviewrequests/%s/s/%s/comments/%sx%s+%s+%s" %
            (review_request.id, screenshot.id, comment.w, comment.h,
             comment.x, comment.y),
            {
                'action': 'delete',
            }
        )

        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['comments']), 0)

    def testScreenshotCommentsDeleteNonExistant(self):
        """Testing the reviewrequests/s/comments delete API with non-existant comment"""
        comment = self.testScreenshotCommentsSet()
        screenshot = comment.screenshot
        review_request = screenshot.review_request.get()

        rsp = self.apiPost(
            "reviewrequests/%s/s/%s/comments/%sx%s+%s+%s" %
            (review_request.id, screenshot.id, 1, 2, 3, 4),
            {
                'action': 'delete',
            }
        )

        self.assertEqual(rsp['stat'], 'ok')
        self.assertEqual(len(rsp['comments']), 0)

    def testScreenshotCommentsList(self):
        """Testing the reviewrequests/s/comments list API"""
        comment = self.testScreenshotCommentsSet()
        screenshot = comment.screenshot
        review_request = screenshot.review_request.get()

        rsp = self.apiGet(
            "reviewrequests/%s/s/%s/comments/%sx%s+%s+%s" %
            (review_request.id, screenshot.id, comment.w, comment.h,
             comment.x, comment.y))

        self.assertEqual(rsp['stat'], 'ok')

        comments = ScreenshotComment.objects.filter(screenshot=screenshot)
        self.assertEqual(len(rsp['comments']), comments.count())

        for i in range(0, len(rsp['comments'])):
            self.assertEqual(rsp['comments'][i]['text'], comments[i].text)
            self.assertEqual(rsp['comments'][i]['x'], comments[i].x)
            self.assertEqual(rsp['comments'][i]['y'], comments[i].y)
            self.assertEqual(rsp['comments'][i]['w'], comments[i].w)
            self.assertEqual(rsp['comments'][i]['h'], comments[i].h)

    def __getTrophyFilename(self):
        return os.path.join(settings.HTDOCS_ROOT,
                            "media", "rb", "images", "trophy.png")