class ProcessorSetWebServiceTests(TestCaseWithFactory):
    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(ProcessorSetWebServiceTests, self).setUp()
        self.webservice = LaunchpadWebServiceCaller()

    def test_getByName(self):
        self.factory.makeProcessor(name='transmeta')
        logout()

        processor = self.webservice.named_get('/+processors',
                                              'getByName',
                                              name='transmeta',
                                              api_version='devel').jsonBody()
        self.assertEqual('transmeta', processor['name'])

    def test_default_collection(self):
        # Make it easy to filter out sample data
        store = IStore(Processor)
        store.execute("UPDATE Processor SET name = 'sample_data_' || name")
        self.factory.makeProcessor(name='q1')
        self.factory.makeProcessor(name='i686')
        self.factory.makeProcessor(name='g4')

        logout()

        collection = self.webservice.get('/+processors?ws.size=10',
                                         api_version='devel').jsonBody()
        self.assertEqual(
            ['g4', 'i686', 'q1'],
            sorted(processor['name'] for processor in collection['entries']
                   if not processor['name'].startswith('sample_data_')))
class ProcessorSetWebServiceTests(TestCaseWithFactory):
    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(ProcessorSetWebServiceTests, self).setUp()
        self.webservice = LaunchpadWebServiceCaller()

    def test_getByName(self):
        self.factory.makeProcessor(name='transmeta')
        logout()

        processor = self.webservice.named_get(
            '/+processors', 'getByName', name='transmeta',
            api_version='devel').jsonBody()
        self.assertEquals('transmeta', processor['name'])

    def test_default_collection(self):
        # Make it easy to filter out sample data
        store = IStore(Processor)
        store.execute("UPDATE Processor SET name = 'sample_data_' || name")
        self.factory.makeProcessor(name='q1')
        self.factory.makeProcessor(name='i686')
        self.factory.makeProcessor(name='g4')

        logout()

        collection = self.webservice.get(
            '/+processors?ws.size=10', api_version='devel').jsonBody()
        self.assertEquals(
            ['g4', 'i686', 'q1'],
            sorted(
            processor['name'] for processor in collection['entries']
            if not processor['name'].startswith('sample_data_')))
    def test_attachments(self):
        # A bug's attachments and the union of its messages' attachments
        # are the same set.
        with admin_logged_in():
            bug = self.factory.makeBug()
            created_attachment_ids = set(
                self.factory.makeBugAttachment(bug).id for i in range(3))
            bug_url = api_url(bug)
        self.assertThat(created_attachment_ids, HasLength(3))
        logout()

        webservice = LaunchpadWebServiceCaller('test', None)
        bug_attachments = webservice.get(
            bug_url + '/attachments').jsonBody()['entries']
        bug_attachment_ids = set(
            int(att['self_link'].rsplit('/', 1)[1]) for att in bug_attachments)
        self.assertContentEqual(created_attachment_ids, bug_attachment_ids)

        messages = webservice.get(bug_url + '/messages').jsonBody()['entries']
        message_attachments = []
        for message in messages[1:]:
            attachments_url = message['bug_attachments_collection_link']
            attachments = webservice.get(attachments_url).jsonBody()['entries']
            self.assertThat(attachments, HasLength(1))
            message_attachments.append(attachments[0])
        message_attachment_ids = set(
            int(att['self_link'].rsplit('/', 1)[1])
            for att in message_attachments)
        self.assertContentEqual(bug_attachment_ids, message_attachment_ids)
 def test_object_not_found(self):
     """Missing top-level objects generate 404s but not OOPS."""
     webservice = LaunchpadWebServiceCaller(
         'launchpad-library', 'salgado-change-anything')
     response = webservice.get('/%s/123456789' % self.object_type)
     self.assertEqual(response.status, 404)
     self.assertEqual(response.getheader('x-lazr-oopsid'), None)
 def test_attachments_query_counts_constant(self):
     # XXX j.c.sackett 2010-09-02 bug=619017
     # This test was being thrown off by the reference bug. To get around
     # the problem, flush and reset are called on the bug storm cache
     # before each call to the webservice. When lp's storm is updated
     # to release the committed fix for this bug, please see about
     # updating this test.
     login(USER_EMAIL)
     self.bug = self.factory.makeBug()
     store = Store.of(self.bug)
     self.factory.makeBugAttachment(self.bug)
     self.factory.makeBugAttachment(self.bug)
     webservice = LaunchpadWebServiceCaller('launchpad-library',
                                            'salgado-change-anything')
     collector = RequestTimelineCollector()
     collector.register()
     self.addCleanup(collector.unregister)
     url = '/bugs/%d/attachments?ws.size=75' % self.bug.id
     # First request.
     store.flush()
     store.reset()
     response = webservice.get(url)
     self.assertThat(collector, HasQueryCount(LessThan(24)))
     with_2_count = collector.count
     self.assertEqual(response.status, 200)
     login(USER_EMAIL)
     for i in range(5):
         self.factory.makeBugAttachment(self.bug)
     logout()
     # Second request.
     store.flush()
     store.reset()
     response = webservice.get(url)
     self.assertThat(collector, HasQueryCount(Equals(with_2_count)))
 def test_messages_query_counts_constant(self):
     # XXX Robert Collins 2010-09-15 bug=619017
     # This test may be thrown off by the reference bug. To get around the
     # problem, flush and reset are called on the bug storm cache before
     # each call to the webservice. When lp's storm is updated to release
     # the committed fix for this bug, please see about updating this test.
     login(USER_EMAIL)
     bug = self.factory.makeBug()
     store = Store.of(bug)
     self.factory.makeBugComment(bug)
     self.factory.makeBugComment(bug)
     self.factory.makeBugComment(bug)
     webservice = LaunchpadWebServiceCaller(
         'launchpad-library', 'salgado-change-anything')
     collector = QueryCollector()
     collector.register()
     self.addCleanup(collector.unregister)
     url = '/bugs/%d/messages?ws.size=75' % bug.id
     # First request.
     store.flush()
     store.reset()
     response = webservice.get(url)
     self.assertThat(collector, HasQueryCount(LessThan(24)))
     with_2_count = collector.count
     self.failUnlessEqual(response.status, 200)
     login(USER_EMAIL)
     for i in range(50):
         self.factory.makeBugComment(bug)
     self.factory.makeBugAttachment(bug)
     logout()
     # Second request.
     store.flush()
     store.reset()
     response = webservice.get(url)
     self.assertThat(collector, HasQueryCount(Equals(with_2_count)))
 def test_messages_query_counts_constant(self):
     # XXX Robert Collins 2010-09-15 bug=619017
     # This test may be thrown off by the reference bug. To get around the
     # problem, flush and reset are called on the bug storm cache before
     # each call to the webservice. When lp's storm is updated to release
     # the committed fix for this bug, please see about updating this test.
     login(USER_EMAIL)
     bug = self.factory.makeBug()
     store = Store.of(bug)
     self.factory.makeBugComment(bug)
     self.factory.makeBugComment(bug)
     self.factory.makeBugComment(bug)
     webservice = LaunchpadWebServiceCaller('launchpad-library',
                                            'salgado-change-anything')
     collector = QueryCollector()
     collector.register()
     self.addCleanup(collector.unregister)
     url = '/bugs/%d/messages?ws.size=75' % bug.id
     # First request.
     store.flush()
     store.reset()
     response = webservice.get(url)
     self.assertThat(collector, HasQueryCount(LessThan(24)))
     with_2_count = collector.count
     self.failUnlessEqual(response.status, 200)
     login(USER_EMAIL)
     for i in range(50):
         self.factory.makeBugComment(bug)
     self.factory.makeBugAttachment(bug)
     logout()
     # Second request.
     store.flush()
     store.reset()
     response = webservice.get(url)
     self.assertThat(collector, HasQueryCount(Equals(with_2_count)))
Example #8
0
class TestOmitTargetedParameter(TestCaseWithFactory):
    """Test all values for the omit_targeted search parameter."""

    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestOmitTargetedParameter, self).setUp()
        self.owner = self.factory.makePerson()
        with person_logged_in(self.owner):
            self.distro = self.factory.makeDistribution(name='mebuntu')
        self.release = self.factory.makeDistroSeries(name='inkanyamba',
                                                     distribution=self.distro)
        self.bug = self.factory.makeBugTask(target=self.release)
        self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                    'salgado-change-anything')

    def test_omit_targeted_old_default_true(self):
        response = self.webservice.named_get('/mebuntu/inkanyamba',
                                             'searchTasks',
                                             api_version='1.0').jsonBody()
        self.assertEqual(response['total_size'], 0)

    def test_omit_targeted_new_default_false(self):
        response = self.webservice.named_get('/mebuntu/inkanyamba',
                                             'searchTasks',
                                             api_version='devel').jsonBody()
        self.assertEqual(response['total_size'], 1)
class TestBuildersCollection(TestCaseWithFactory):
    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestBuildersCollection, self).setUp()
        self.webservice = LaunchpadWebServiceCaller()

    def test_getBuildQueueSizes(self):
        logout()
        results = self.webservice.named_get(
            '/builders', 'getBuildQueueSizes', api_version='devel')
        self.assertEquals(
            ['nonvirt', 'virt'], sorted(results.jsonBody().keys()))

    def test_getBuildersForQueue(self):
        g1 = self.factory.makeProcessor('g1')
        quantum = self.factory.makeProcessor('quantum')
        self.factory.makeBuilder(
            processor=quantum, name='quantum_builder1')
        self.factory.makeBuilder(
            processor=quantum, name='quantum_builder2')
        self.factory.makeBuilder(
            processor=quantum, name='quantum_builder3', virtualized=False)
        self.factory.makeBuilder(
            processor=g1, name='g1_builder', virtualized=False)

        logout()
        results = self.webservice.named_get(
            '/builders', 'getBuildersForQueue',
            processor=api_url(quantum), virtualized=True,
            api_version='devel').jsonBody()
        self.assertEquals(
            ['quantum_builder1', 'quantum_builder2'],
            sorted(builder['name'] for builder in results['entries']))
Example #10
0
 def setUp(self):
     TestCaseWithFactory.setUp(self)
     login('[email protected] ')
     self.person = self.factory.makePerson(name='test-person',
                                           displayname='Test Person')
     self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                 'salgado-change-anything')
Example #11
0
 def setUp(self):
     super(TestGetBugData, self).setUp()
     self.owner = self.factory.makePerson()
     with person_logged_in(self.owner):
         self.product = self.factory.makeProduct()
     self.bug = self.factory.makeBug(
         target=self.product,
         information_type=InformationType.PRIVATESECURITY)
     self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                 'salgado-change-anything')
Example #12
0
 def setUp(self):
     super(TestOmitTargetedParameter, self).setUp()
     self.owner = self.factory.makePerson()
     with person_logged_in(self.owner):
         self.distro = self.factory.makeDistribution(name='mebuntu')
     self.release = self.factory.makeDistroSeries(name='inkanyamba',
                                                  distribution=self.distro)
     self.bug = self.factory.makeBugTask(target=self.release)
     self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                 'salgado-change-anything')
Example #13
0
 def test_newWebhook_permissions(self):
     self.useFixture(FeatureFixture({'webhooks.new.enabled': 'true'}))
     webservice = LaunchpadWebServiceCaller()
     response = webservice.named_post(self.target_url,
                                      'newWebhook',
                                      delivery_url='http://example.com/ep',
                                      event_types=[self.event_type],
                                      api_version='devel')
     self.assertEqual(401, response.status)
     self.assertIn('launchpad.Edit', response.body)
 def test_alias_redirects_in_webservice(self):
     # When a redirect occurs for a product, it should remain in the
     # webservice.
     product = self.factory.makeProduct(name='lemur')
     removeSecurityProxy(product).setAliases(['monkey'])
     webservice = LaunchpadWebServiceCaller('launchpad-library',
                                            'salgado-change-anything')
     response = webservice.get('/monkey')
     self.assertEqual('http://api.launchpad.dev/beta/lemur',
                      response.getheader('location'))
    def setUp(self):
        super(TestQuestionRepresentation, self).setUp()
        with celebrity_logged_in('admin'):
            self.question = self.factory.makeQuestion(
                title="This is a question")
            self.target_name = self.question.target.name

        self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                    'salgado-change-anything')
        self.webservice.default_api_version = 'devel'
class TestBugDescriptionRepresentation(TestCaseWithFactory):
    """Test ways of interacting with Bug webservice representations."""

    layer = DatabaseFunctionalLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        login(ADMIN_EMAIL)
        # Make two bugs, one whose description points to the other, so it will
        # get turned into a HTML link.
        self.bug_one = self.factory.makeBug(title="generic")
        self.bug_two = self.factory.makeBug(
            description="Useless bugs are useless. See Bug %d." % (
            self.bug_one.id))

        self.webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything')

    def findBugDescription(self, response):
        """Find the bug description field in an XHTML document fragment."""
        soup = BeautifulSoup(response.body)
        dt = soup.find('dt', text="description").parent
        dd = dt.findNextSibling('dd')
        return str(dd.contents.pop())

    def test_GET_xhtml_representation(self):
        response = self.webservice.get(
            '/bugs/' + str(self.bug_two.id),
            'application/xhtml+xml')
        self.assertEqual(response.status, 200)

        self.assertEqual(
            self.findBugDescription(response),
            u'<p>Useless bugs are useless. '
            'See <a href="/bugs/%d" class="bug-link">Bug %d</a>.</p>' % (
            self.bug_one.id, self.bug_one.id))

    def test_PATCH_xhtml_representation(self):
        new_description = "See bug %d" % self.bug_one.id

        bug_two_json = self.webservice.get(
            '/bugs/%d' % self.bug_two.id).jsonBody()

        response = self.webservice.patch(
            bug_two_json['self_link'],
            'application/json',
            dumps(dict(description=new_description)),
            headers=dict(accept='application/xhtml+xml'))

        self.assertEqual(response.status, 209)

        self.assertEqual(
            self.findBugDescription(response),
            u'<p>See <a href="/bugs/%d" class="bug-link">bug %d</a></p>' % (
            self.bug_one.id, self.bug_one.id))
 def test_alias_redirects_in_webservice(self):
     # When a redirect occurs for a product, it should remain in the
     # webservice.
     product = self.factory.makeProduct(name='lemur')
     removeSecurityProxy(product).setAliases(['monkey'])
     webservice = LaunchpadWebServiceCaller(
         'launchpad-library', 'salgado-change-anything')
     response = webservice.get('/monkey')
     self.assertEqual(
         'http://api.launchpad.dev/beta/lemur',
         response.getheader('location'))
    def setUp(self):
        TestCaseWithFactory.setUp(self)
        login(ADMIN_EMAIL)
        # Make two bugs, one whose description points to the other, so it will
        # get turned into a HTML link.
        self.bug_one = self.factory.makeBug(title="generic")
        self.bug_two = self.factory.makeBug(
            description="Useless bugs are useless. See Bug %d." %
            (self.bug_one.id))

        self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                    'salgado-change-anything')
class TestBugDescriptionRepresentation(TestCaseWithFactory):
    """Test ways of interacting with Bug webservice representations."""

    layer = DatabaseFunctionalLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        login(ADMIN_EMAIL)
        # Make two bugs, one whose description points to the other, so it will
        # get turned into a HTML link.
        self.bug_one = self.factory.makeBug(title="generic")
        self.bug_two = self.factory.makeBug(
            description="Useless bugs are useless. See Bug %d." %
            (self.bug_one.id))

        self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                    'salgado-change-anything')

    def findBugDescription(self, response):
        """Find the bug description field in an XHTML document fragment."""
        soup = BeautifulSoup(response.body)
        dt = soup.find('dt', text="description").parent
        dd = dt.findNextSibling('dd')
        return str(dd.contents.pop())

    def test_GET_xhtml_representation(self):
        response = self.webservice.get('/bugs/' + str(self.bug_two.id),
                                       'application/xhtml+xml')
        self.assertEqual(response.status, 200)

        self.assertEqual(
            self.findBugDescription(response), u'<p>Useless bugs are useless. '
            'See <a href="/bugs/%d" class="bug-link">Bug %d</a>.</p>' %
            (self.bug_one.id, self.bug_one.id))

    def test_PATCH_xhtml_representation(self):
        new_description = "See bug %d" % self.bug_one.id

        bug_two_json = self.webservice.get('/bugs/%d' %
                                           self.bug_two.id).jsonBody()

        response = self.webservice.patch(
            bug_two_json['self_link'],
            'application/json',
            dumps(dict(description=new_description)),
            headers=dict(accept='application/xhtml+xml'))

        self.assertEqual(response.status, 209)

        self.assertEqual(
            self.findBugDescription(response),
            u'<p>See <a href="/bugs/%d" class="bug-link">bug %d</a></p>' %
            (self.bug_one.id, self.bug_one.id))
 def setUp(self):
     TestCaseWithFactory.setUp(self)
     login('[email protected] ')
     self.bug = self.factory.makeBug()
     commenter = self.factory.makePerson()
     self.bug.newMessage(commenter, 'Comment Subject', 'Comment content')
     comments = get_comments_for_bugtask(self.bug.bugtasks[0])
     self.comment = comments[1]
     comment_view = getMultiAdapter((self.comment, LaunchpadTestRequest()),
                                    name="+box")
     self.expected_comment_html = str(comment_view())
     self.message_path = '/%s/+bug/%s/comments/1' % (
         self.bug.bugtasks[0].product.name, self.bug.id)
     self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                 'salgado-change-anything')
Example #21
0
 def test_api_branches_query_count(self):
     webservice = LaunchpadWebServiceCaller()
     collector = RequestTimelineCollector()
     collector.register()
     self.addCleanup(collector.unregister)
     # Get 'all' of the 50 branches this collection is limited to - rather
     # than the default in-test-suite pagination size of 5.
     url = "/branches?ws.size=50"
     logout()
     response = webservice.get(url,
         headers={'User-Agent': 'AnonNeedsThis'})
     self.assertEqual(response.status, 200,
         "Got %d for url %r with response %r" % (
         response.status, url, response.body))
     self.assertThat(collector, HasQueryCount(LessThan(17)))
Example #22
0
class TestGetBugData(TestCaseWithFactory):
    """Tests for the /bugs getBugData operation."""

    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestGetBugData, self).setUp()
        self.owner = self.factory.makePerson()
        with person_logged_in(self.owner):
            self.product = self.factory.makeProduct()
        self.bug = self.factory.makeBug(
            target=self.product,
            information_type=InformationType.PRIVATESECURITY)
        self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                    'salgado-change-anything')

    def search(self, api_version, **kwargs):
        return self.webservice.named_get('/bugs',
                                         'getBugData',
                                         api_version=api_version,
                                         **kwargs).jsonBody()

    def test_search_returns_results(self):
        # A matching search returns results.
        response = self.search("devel", bug_id=self.bug.id)
        self.assertEqual(self.bug.id, response[0]['id'])

    def test_search_returns_no_results(self):
        # A non-matching search returns no results.
        response = self.search("devel", bug_id=0)
        self.assertEqual(len(response), 0)
 def setUp(self):
     TestCaseWithFactory.setUp(self)
     login('[email protected] ')
     self.person = self.factory.makePerson(
         name='test-person', displayname='Test Person')
     self.webservice = LaunchpadWebServiceCaller(
         'launchpad-library', 'salgado-change-anything')
Example #24
0
 def test_global_search_by_tag(self):
     project1 = self.factory.makeProduct()
     project2 = self.factory.makeProduct()
     bug1 = self.factory.makeBug(target=project1, tags=["foo"])
     self.factory.makeBug(target=project1, tags=["bar"])
     bug3 = self.factory.makeBug(target=project2, tags=["foo"])
     self.factory.makeBug(target=project2, tags=["baz"])
     webservice = LaunchpadWebServiceCaller("launchpad-library",
                                            "salgado-change-anything")
     response = webservice.named_get("/bugs",
                                     "searchTasks",
                                     api_version="devel",
                                     tags="foo").jsonBody()
     self.assertEqual(2, response["total_size"])
     self.assertContentEqual([bug1.id, bug3.id], [
         int(entry["bug_link"].split("/")[-1])
         for entry in response["entries"]
     ])
    def test_user_access_to_private_bug_attachment(self):
        # Users having access to private bugs can also read attachments
        # of these bugs.
        self.bug.setPrivate(True, self.bug_owner)
        other_user = self.factory.makePerson()
        launchpad = launchpadlib_for('test', self.bug_owner, version='devel')
        ws_bug = ws_object(launchpad, self.bug)
        ws_bugattachment = ws_bug.attachments[0]

        # The attachment contains a link to a HostedBytes resource;
        # the response to a GET request of this URL is a redirect to a
        # Librarian URL.  We cannot simply access these Librarian URLs
        # for restricted Librarian files because the host name used in
        # the URLs is different for each file, and our test envireonment
        # does not support wildcard DNS, and because the Launchpadlib
        # browser automatically follows redirects.
        # LaunchpadWebServiceCaller, on the other hand, gives us
        # access to a raw HTTPResonse object.
        webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything')
        response = webservice.get(ws_bugattachment.data._wadl_resource._url)
        self.assertEqual(303, response.status)

        # The Librarian URL has, for our test case, the form
        # "https://NNNN.restricted.launchpad.dev:PORT/NNNN/foo.txt?token=..."
        # where NNNN and PORT are integers.
        parsed_url = urlparse(response.getHeader('location'))
        self.assertEqual('https', parsed_url.scheme)
        mo = re.search(
            r'^i\d+\.restricted\..+:\d+$', parsed_url.netloc)
        self.assertIsNot(None, mo, parsed_url.netloc)
        mo = re.search(r'^/\d+/foo\.txt$', parsed_url.path)
        self.assertIsNot(None, mo)
        params = parse_qs(parsed_url.query)
        self.assertEqual(['token'], params.keys())

        # If a user which cannot access the private bug itself tries to
        # to access the attachment, an NotFound error is raised.
        other_launchpad = launchpadlib_for(
            'test_unauthenticated', other_user, version='devel')
        self.assertRaises(
            RestfulNotFound, other_launchpad._browser.get,
            ws_bugattachment.data._wadl_resource._url)
    def test_canBeUnsubscribedByUser(self):
        # Test canBeUnsubscribedByUser() API.
        webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything',
            domain='api.launchpad.dev:8085')

        with person_logged_in(ANONYMOUS):
            db_spec = self.factory.makeSpecification()
            db_person = self.factory.makePerson()
            launchpad = self.factory.makeLaunchpadService()

            spec = ws_object(launchpad, db_spec)
            person = ws_object(launchpad, db_person)
            subscription = spec.subscribe(person=person, essential=True)
            transaction.commit()

        result = webservice.named_get(
            subscription['self_link'], 'canBeUnsubscribedByUser').jsonBody()
        self.assertTrue(result)
    def setUp(self):
        super(TestQuestionRepresentation, self).setUp()
        with celebrity_logged_in('admin'):
            self.question = self.factory.makeQuestion(
                title="This is a question")
            self.target_name = self.question.target.name

        self.webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything')
        self.webservice.default_api_version = 'devel'
Example #28
0
    def test_canBeUnsubscribedByUser(self):
        # Test canBeUnsubscribedByUser() API.
        webservice = LaunchpadWebServiceCaller('launchpad-library',
                                               'salgado-change-anything',
                                               domain='api.launchpad.dev:8085')

        with person_logged_in(ANONYMOUS):
            db_spec = self.factory.makeSpecification()
            db_person = self.factory.makePerson()
            launchpad = self.factory.makeLaunchpadService()

            spec = ws_object(launchpad, db_spec)
            person = ws_object(launchpad, db_person)
            subscription = spec.subscribe(person=person, essential=True)
            transaction.commit()

        result = webservice.named_get(subscription['self_link'],
                                      'canBeUnsubscribedByUser').jsonBody()
        self.assertTrue(result)
 def test_email_address_obfuscated(self):
     # Email addresses are obfuscated for anonymous users.
     bug = self._makeBug()
     logout()
     webservice = LaunchpadWebServiceCaller()
     result = webservice(ws_url(bug)).jsonBody()
     self.assertEqual(self.bug_title % self.email_address_obfuscated,
                      result['title'])
     self.assertEqual(self.bug_description % self.email_address_obfuscated,
                      result['description'])
 def test_getByReference(self):
     random = self.factory.makePerson()
     body = LaunchpadWebServiceCaller('consumer', '').named_get(
         '/archives', 'getByReference', reference='ubuntu',
         api_version='devel').jsonBody()
     self.assertEqual(body['reference'], 'ubuntu')
     body = webservice_for_person(random).named_get(
         '/archives', 'getByReference', reference='ubuntu',
         api_version='devel').jsonBody()
     self.assertEqual(body['reference'], 'ubuntu')
Example #31
0
    def test_user_access_to_private_bug_attachment(self):
        # Users having access to private bugs can also read attachments
        # of these bugs.
        self.bug.setPrivate(True, self.bug_owner)
        other_user = self.factory.makePerson()
        launchpad = launchpadlib_for('test', self.bug_owner, version='devel')
        ws_bug = ws_object(launchpad, self.bug)
        ws_bugattachment = ws_bug.attachments[0]

        # The attachment contains a link to a HostedBytes resource;
        # the response to a GET request of this URL is a redirect to a
        # Librarian URL.  We cannot simply access these Librarian URLs
        # for restricted Librarian files because the host name used in
        # the URLs is different for each file, and our test envireonment
        # does not support wildcard DNS, and because the Launchpadlib
        # browser automatically follows redirects.
        # LaunchpadWebServiceCaller, on the other hand, gives us
        # access to a raw HTTPResonse object.
        webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything')
        response = webservice.get(ws_bugattachment.data._wadl_resource._url)
        self.assertEqual(303, response.status)

        # The Librarian URL has, for our test case, the form
        # "https://NNNN.restricted.launchpad.dev:PORT/NNNN/foo.txt?token=..."
        # where NNNN and PORT are integers.
        parsed_url = urlparse(response.getHeader('location'))
        self.assertEqual('https', parsed_url.scheme)
        mo = re.search(
            r'^i\d+\.restricted\..+:\d+$', parsed_url.netloc)
        self.assertIsNot(None, mo, parsed_url.netloc)
        mo = re.search(r'^/\d+/foo\.txt$', parsed_url.path)
        self.assertIsNot(None, mo)
        params = parse_qs(parsed_url.query)
        self.assertEqual(['token'], params.keys())

        # If a user which cannot access the private bug itself tries to
        # to access the attachment, an NotFound error is raised.
        other_launchpad = launchpadlib_for(
            'test_unauthenticated', other_user, version='devel')
        self.assertRaises(
            RestfulNotFound, other_launchpad._browser.get,
            ws_bugattachment.data._wadl_resource._url)
 def test_xhtml_email_address_obfuscated(self):
     # Email addresses are obfuscated in the XML representation for
     # anonymous users.
     bug = self._makeBug()
     logout()
     webservice = LaunchpadWebServiceCaller()
     result = webservice(ws_url(bug),
                         headers={'Accept': 'application/xhtml+xml'})
     self.assertNotIn(self.email_address, result.body)
     self.assertIn(self.email_address_obfuscated_escaped, result.body)
    def setUp(self):
        TestCaseWithFactory.setUp(self)
        login(ADMIN_EMAIL)
        # Make two bugs, one whose description points to the other, so it will
        # get turned into a HTML link.
        self.bug_one = self.factory.makeBug(title="generic")
        self.bug_two = self.factory.makeBug(
            description="Useless bugs are useless. See Bug %d." % (
            self.bug_one.id))

        self.webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything')
class TestBuilderEntry(TestCaseWithFactory):
    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestBuilderEntry, self).setUp()
        self.webservice = LaunchpadWebServiceCaller()

    def test_exports_processor(self):
        processor = self.factory.makeProcessor('s1')
        builder = self.factory.makeBuilder(processor=processor)

        logout()
        entry = self.webservice.get(
            api_url(builder), api_version='devel').jsonBody()
        self.assertEndsWith(entry['processor_link'], '/+processors/s1')
Example #35
0
class TestBuilderEntry(TestCaseWithFactory):
    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestBuilderEntry, self).setUp()
        self.webservice = LaunchpadWebServiceCaller()

    def test_exports_processor(self):
        processor = self.factory.makeProcessor('s1')
        builder = self.factory.makeBuilder(processor=processor)

        logout()
        entry = self.webservice.get(api_url(builder),
                                    api_version='devel').jsonBody()
        self.assertEndsWith(entry['processor_link'], '/+processors/s1')
Example #36
0
class TestBuildersCollection(TestCaseWithFactory):
    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestBuildersCollection, self).setUp()
        self.webservice = LaunchpadWebServiceCaller()

    def test_getBuildQueueSizes(self):
        logout()
        results = self.webservice.named_get('/builders',
                                            'getBuildQueueSizes',
                                            api_version='devel')
        self.assertEquals(['nonvirt', 'virt'],
                          sorted(results.jsonBody().keys()))

    def test_getBuildersForQueue(self):
        g1 = self.factory.makeProcessor('g1')
        quantum = self.factory.makeProcessor('quantum')
        self.factory.makeBuilder(processor=quantum, name='quantum_builder1')
        self.factory.makeBuilder(processor=quantum, name='quantum_builder2')
        self.factory.makeBuilder(processor=quantum,
                                 name='quantum_builder3',
                                 virtualized=False)
        self.factory.makeBuilder(processor=g1,
                                 name='g1_builder',
                                 virtualized=False)

        logout()
        results = self.webservice.named_get('/builders',
                                            'getBuildersForQueue',
                                            processor=api_url(quantum),
                                            virtualized=True,
                                            api_version='devel').jsonBody()
        self.assertEquals(['quantum_builder1', 'quantum_builder2'],
                          sorted(builder['name']
                                 for builder in results['entries']))
 def setUp(self):
     TestCaseWithFactory.setUp(self)
     login('[email protected] ')
     self.bug = self.factory.makeBug()
     commenter = self.factory.makePerson()
     self.bug.newMessage(
         commenter, 'Comment Subject', 'Comment content')
     comments = get_comments_for_bugtask(self.bug.bugtasks[0])
     self.comment = comments[1]
     comment_view = getMultiAdapter(
         (self.comment, LaunchpadTestRequest()), name="+box")
     self.expected_comment_html = str(comment_view())
     self.message_path = '/%s/+bug/%s/comments/1' % (
         self.bug.bugtasks[0].product.name, self.bug.id)
     self.webservice = LaunchpadWebServiceCaller(
         'launchpad-library', 'salgado-change-anything')
 def test_etags_differ_for_anon_and_non_anon_represetations(self):
     # When a webservice client retrieves data anonymously, this
     # data should not be used in later write requests, if the
     # text fields contain obfuscated email addresses. The etag
     # for a GET request is calculated after the email address
     # obfuscation and thus differs from the etag returned for
     # not obfuscated data, so clients usings etags to check if the
     # cached data is up to date will not use the obfuscated data
     # in PATCH or PUT requests.
     bug = self._makeBug()
     user = self.factory.makePerson()
     webservice = webservice_for_person(user)
     etag_logged_in = webservice(ws_url(bug)).getheader('etag')
     logout()
     webservice = LaunchpadWebServiceCaller()
     etag_logged_out = webservice(ws_url(bug)).getheader('etag')
     self.assertNotEqual(etag_logged_in, etag_logged_out)
class TestBugCommentRepresentation(TestCaseWithFactory):
    """Test ways of interacting with BugComment webservice representations."""

    layer = DatabaseFunctionalLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        login('[email protected] ')
        self.bug = self.factory.makeBug()
        commenter = self.factory.makePerson()
        self.bug.newMessage(
            commenter, 'Comment Subject', 'Comment content')
        comments = get_comments_for_bugtask(self.bug.bugtasks[0])
        self.comment = comments[1]
        comment_view = getMultiAdapter(
            (self.comment, LaunchpadTestRequest()), name="+box")
        self.expected_comment_html = str(comment_view())
        self.message_path = '/%s/+bug/%s/comments/1' % (
            self.bug.bugtasks[0].product.name, self.bug.id)
        self.webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything')

    def assertRenderedCommentsEqual(self, a_comment, another_comment):
        """Assert that two rendered comments are equal.

        It replaces parts that depend of the current time with fixed
        strings, so that two comments rendered at different times are
        still considered equal.
        """
        when_regexp = re.compile(r'>\d+ .*? ago<')
        a_comment = when_regexp.sub('>WHEN<', a_comment)
        another_comment = when_regexp.sub('>WHEN<', another_comment)
        self.assertEqual(a_comment, another_comment)

    def test_GET_xhtml_representation(self):
        # The XHTML of a BugComment is exactly the same as how it's
        # rendered in the web UI. The existing +box view is re-used to
        # render it.
        response = self.webservice.get(
            self.message_path, 'application/xhtml+xml')

        self.assertEqual(response.status, 200)

        rendered_comment = response.body
        self.assertRenderedCommentsEqual(
            rendered_comment, self.expected_comment_html)
class TestBugCommentRepresentation(TestCaseWithFactory):
    """Test ways of interacting with BugComment webservice representations."""

    layer = DatabaseFunctionalLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        login('[email protected] ')
        self.bug = self.factory.makeBug()
        commenter = self.factory.makePerson()
        self.bug.newMessage(commenter, 'Comment Subject', 'Comment content')
        comments = get_comments_for_bugtask(self.bug.bugtasks[0])
        self.comment = comments[1]
        comment_view = getMultiAdapter((self.comment, LaunchpadTestRequest()),
                                       name="+box")
        self.expected_comment_html = str(comment_view())
        self.message_path = '/%s/+bug/%s/comments/1' % (
            self.bug.bugtasks[0].product.name, self.bug.id)
        self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                    'salgado-change-anything')

    def assertRenderedCommentsEqual(self, a_comment, another_comment):
        """Assert that two rendered comments are equal.

        It replaces parts that depend of the current time with fixed
        strings, so that two comments rendered at different times are
        still considered equal.
        """
        when_regexp = re.compile(r'>\d+ .*? ago<')
        a_comment = when_regexp.sub('>WHEN<', a_comment)
        another_comment = when_regexp.sub('>WHEN<', another_comment)
        self.assertEqual(a_comment, another_comment)

    def test_GET_xhtml_representation(self):
        # The XHTML of a BugComment is exactly the same as how it's
        # rendered in the web UI. The existing +box view is re-used to
        # render it.
        response = self.webservice.get(self.message_path,
                                       'application/xhtml+xml')

        self.assertEqual(response.status, 200)

        rendered_comment = response.body
        self.assertRenderedCommentsEqual(rendered_comment,
                                         self.expected_comment_html)
 def test_getByReference_private(self):
     with admin_logged_in():
         archive = self.factory.makeArchive(private=True)
         owner = archive.owner
         reference = archive.reference
         random = self.factory.makePerson()
     body = LaunchpadWebServiceCaller('consumer', '').named_get(
         '/archives', 'getByReference', reference=reference,
         api_version='devel').jsonBody()
     self.assertIs(None, body)
     body = webservice_for_person(random).named_get(
         '/archives', 'getByReference', reference=reference,
         api_version='devel').jsonBody()
     self.assertIs(None, body)
     body = webservice_for_person(owner).named_get(
         '/archives', 'getByReference', reference=reference,
         api_version='devel').jsonBody()
     self.assertEqual(body['reference'], reference)
class TestPersonRepresentation(TestCaseWithFactory):

    layer = DatabaseFunctionalLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        login('[email protected] ')
        self.person = self.factory.makePerson(
            name='test-person', displayname='Test Person')
        self.webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything')

    def test_GET_xhtml_representation(self):
        # Remove the security proxy because IPerson.name is protected.
        person_name = removeSecurityProxy(self.person).name
        response = self.webservice.get(
            '/~%s' % person_name, 'application/xhtml+xml')

        self.assertEqual(response.status, 200)

        rendered_comment = response.body
        self.assertEquals(
            rendered_comment,
            '<a href="/~test-person" class="sprite person">Test Person</a>')
Example #43
0
class TestPersonRepresentation(TestCaseWithFactory):

    layer = DatabaseFunctionalLayer

    def setUp(self):
        TestCaseWithFactory.setUp(self)
        login('[email protected] ')
        self.person = self.factory.makePerson(name='test-person',
                                              displayname='Test Person')
        self.webservice = LaunchpadWebServiceCaller('launchpad-library',
                                                    'salgado-change-anything')

    def test_GET_xhtml_representation(self):
        # Remove the security proxy because IPerson.name is protected.
        person_name = removeSecurityProxy(self.person).name
        response = self.webservice.get('/~%s' % person_name,
                                       'application/xhtml+xml')

        self.assertEqual(response.status, 200)

        rendered_comment = response.body
        self.assertEquals(
            rendered_comment,
            '<a href="/~test-person" class="sprite person">Test Person</a>')
 def setUp(self):
     super(ProcessorSetWebServiceTests, self).setUp()
     self.webservice = LaunchpadWebServiceCaller()
 def setUp(self):
     super(PersonSetWebServiceTests, self).setUp()
     self.webservice = LaunchpadWebServiceCaller('test', None)
     logout()
class PersonSetWebServiceTests(TestCaseWithFactory):

    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(PersonSetWebServiceTests, self).setUp()
        self.webservice = LaunchpadWebServiceCaller('test', None)
        logout()

    def assertReturnsPeople(self, expected_names, path):
        self.assertEqual(
            expected_names,
            [person['name'] for person in
             self.webservice.get(path).jsonBody()['entries']])

    def test_default_content(self):
        # /people lists the 50 people with the most karma, excluding
        # those with no karma at all.
        self.assertEqual(
            4, len(self.webservice.get('/people').jsonBody()['entries']))

    def test_find(self):
        # It's possible to find people by name.
        with admin_logged_in():
            person_name = self.factory.makePerson().name
        self.assertReturnsPeople(
            [person_name], '/people?ws.op=find&text=%s' % person_name)

    def test_findTeam(self):
        # The search can be restricted to teams.
        with admin_logged_in():
            person_name = self.factory.makePerson().name
            team_name = self.factory.makeTeam(
                name='%s-team' % person_name).name
        self.assertReturnsPeople(
            [team_name], '/people?ws.op=findTeam&text=%s' % person_name)

    def test_findPerson(self):
        # The search can be restricted to people.
        with admin_logged_in():
            person_name = self.factory.makePerson().name
            self.factory.makeTeam(name='%s-team' % person_name)
        self.assertReturnsPeople(
            [person_name], '/people?ws.op=findPerson&text=%s' % person_name)

    def test_find_by_date(self):
        # Creation date filtering is supported.
        self.assertReturnsPeople(
            [u'bac'],
            '/people?ws.op=findPerson&text='
            '&created_after=2008-06-27&created_before=2008-07-01')

    def test_getByEmail(self):
        # You can get a person by their email address.
        with admin_logged_in():
            person = self.factory.makePerson()
            person_name = person.name
            person_email = person.preferredemail.email
        self.assertEqual(
            person_name,
            self.webservice.get(
                '/people?ws.op=getByEmail&email=%s' % person_email
                ).jsonBody()['name'])

    def test_getByEmail_checks_format(self):
        # A malformed email address is rejected.
        e = self.assertRaises(
            ValueError,
            self.webservice.get(
                '/people?ws.op=getByEmail&email=foo@').jsonBody)
        # XXX wgrant bug=1088358: This escaping shouldn't be here; it's
        # not HTML.
        self.assertEqual("email: Invalid email &#x27;foo@&#x27;.", e[0])

    def test_getByOpenIDIdentifier(self):
        # You can get a person by their OpenID identifier URL.
        with admin_logged_in():
            person = self.factory.makePerson()
            person_name = person.name
            person_openid = person.account.openid_identifiers.one().identifier
        self.assertEqual(
            person_name,
            self.webservice.get(
                '/people?ws.op=getByOpenIDIdentifier&'
                'identifier=http://openid.launchpad.dev/%%2Bid/%s'
                % person_openid,
                api_version='devel').jsonBody()['name'])
 def setUp(self):
     super(TestBuildersCollection, self).setUp()
     self.webservice = LaunchpadWebServiceCaller()
Example #48
0
 def setUp(self):
     super(ProcessorSetWebServiceTests, self).setUp()
     self.webservice = LaunchpadWebServiceCaller()
 def setUp(self):
     super(TestBuilderEntry, self).setUp()
     self.webservice = LaunchpadWebServiceCaller()
class TestQuestionRepresentation(TestCaseWithFactory):
    """Test ways of interacting with Question webservice representations."""

    layer = DatabaseFunctionalLayer

    def setUp(self):
        super(TestQuestionRepresentation, self).setUp()
        with celebrity_logged_in('admin'):
            self.question = self.factory.makeQuestion(
                title="This is a question")
            self.target_name = self.question.target.name

        self.webservice = LaunchpadWebServiceCaller(
            'launchpad-library', 'salgado-change-anything')
        self.webservice.default_api_version = 'devel'

    def findQuestionTitle(self, response):
        """Find the question title field in an XHTML document fragment."""
        soup = BeautifulSoup(response.body)
        dt = soup.find('dt', text="title").parent
        dd = dt.findNextSibling('dd')
        return str(dd.contents.pop())

    def test_top_level_question_get(self):
        # The top level question set can be used via the api to get
        # a question by id via redirect without url hacking.
        response = self.webservice.get(
            '/questions/%s' % self.question.id, 'application/xhtml+xml')
        self.assertEqual(response.status, 200)

    def test_GET_xhtml_representation(self):
        # A question's xhtml representation is available on the api.
        response = self.webservice.get(
            '/%s/+question/%d' % (self.target_name,
                self.question.id),
            'application/xhtml+xml')
        self.assertEqual(response.status, 200)

        self.assertEqual(
            self.findQuestionTitle(response),
            "<p>This is a question</p>")

    def test_PATCH_xhtml_representation(self):
        # You can update the question through the api with PATCH.
        new_title = "No, this is a question"

        question_json = self.webservice.get(
            '/%s/+question/%d' % (self.target_name,
                self.question.id)).jsonBody()

        response = self.webservice.patch(
            question_json['self_link'],
            'application/json',
            dumps(dict(title=new_title)),
            headers=dict(accept='application/xhtml+xml'))

        self.assertEqual(response.status, 209)

        self.assertEqual(
            self.findQuestionTitle(response),
            "<p>No, this is a question</p>")