Merge lp:~michael.nelson/rnr-server/731376-other-origins-2 into lp:rnr-server

Proposed by Michael Nelson
Status: Merged
Approved by: Michael Nelson
Approved revision: 160
Merged at revision: 152
Proposed branch: lp:~michael.nelson/rnr-server/731376-other-origins-2
Merge into: lp:rnr-server
Prerequisite: lp:~michael.nelson/rnr-server/731736-other-origins
Diff against target: 687 lines (+360/-86)
10 files modified
django_project/config_dev/config/main.cfg (+0/-8)
django_project/config_dev/schema.py (+5/-2)
src/reviewsapp/forms.py (+12/-8)
src/reviewsapp/preflight.py (+6/-1)
src/reviewsapp/tests/factory.py (+5/-0)
src/reviewsapp/tests/test_data/software_center_apps.json (+135/-0)
src/reviewsapp/tests/test_handlers.py (+10/-5)
src/reviewsapp/tests/test_preflight.py (+56/-27)
src/reviewsapp/tests/test_utilities.py (+70/-13)
src/reviewsapp/utilities.py (+61/-22)
To merge this branch: bzr merge lp:~michael.nelson/rnr-server/731376-other-origins-2
Reviewer Review Type Date Requested Status
Danny Tamez (community) Approve
Review via email: mp+53229@code.launchpad.net

Commit message

[r=zematynnad][bug=731376] Enable reviews of packages in pay ppas.

Description of the change

Overview
========
This branch continues on from:

https://code.launchpad.net/~michael.nelson/rnr-server/731736-other-origins/+merge/53007

adding the functionality to verify packages specified on reviews for purchase software.

Details
=======

All the tests work on mocked APIs, and you can test the real deal with something like:

https://pastebin.canonical.com/44659/

I also added a preflight check to ensure the sca available apps are available via the network, and updated the preflight tests so that they don't hit the network.

To post a comment you must log in.
Revision history for this message
Danny Tamez (zematynnad) wrote :

Approved - I'll put line 27 back in in another branch.

review: Approve
Revision history for this message
Michael Nelson (michael.nelson) wrote :

On Mon, Mar 14, 2011 at 7:06 PM, Danny Tamez <email address hidden>wrote:

> Review: Approve
> Approved - I'll put line 27 back in in another branch.
>

Thanks Danny - Ah, I'd only deleted line 27 because it wasn't being used...
if it's for another branch you've got ready I'll just leave it in.

Cheers.

Revision history for this message
ISD Branch Mangler (isd-branches-mangler) wrote :

The prerequisite lp:~michael.nelson/rnr-server/731736-other-origins has not yet been merged into lp:rnr-server.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'django_project/config_dev/config/main.cfg'
2--- django_project/config_dev/config/main.cfg 2011-03-15 09:47:29 +0000
3+++ django_project/config_dev/config/main.cfg 2011-03-11 21:09:10 +0000
4@@ -98,14 +98,6 @@
5 cache_review_stats_seconds = 14400
6 token_cache_expiry_hours = 4
7 reviewsapp_media_root = src/reviewsapp/media
8-commercial_origins = lp-ppa-commercial-ppa-uploaders-fluendo-dvd
9- lp-ppa-commercial-ppa-uploaders-fluendo-plugins
10- lp-ppa-commercial-ppa-uploaders-fluendo-wmv-plugins
11- lp-ppa-commercial-ppa-uploaders-brukkon
12- lp-ppa-commercial-ppa-uploaders-vendetta-online
13- lp-ppa-commercial-ppa-uploaders-world-of-goo
14- lp-ppa-commercial-ppa-uploaders-illumination
15-
16
17 [sso_api]
18 sso_api_service_root = https://login.staging.ubuntu.com/api/1.0
19
20=== modified file 'django_project/config_dev/schema.py'
21--- django_project/config_dev/schema.py 2011-03-15 09:47:29 +0000
22+++ django_project/config_dev/schema.py 2011-03-15 09:47:29 +0000
23@@ -4,7 +4,6 @@
24 IntConfigOption, LinesConfigOption, StringConfigOption)
25 from django_configglue.schema import schemas
26
27-from reviewsapp.middleware import StatisticsLoggingMiddleware
28
29 DjangoSchema = schemas.get(django.get_version())
30
31@@ -56,7 +55,6 @@
32 rnr.token_cache_expiry_hours = IntConfigOption(default=4)
33 rnr.reviewsapp_media_root = StringConfigOption()
34 rnr.allow_multiple_reviews_for_testing = BoolConfigOption(default=False)
35- rnr.commercial_origins = LinesConfigOption(item=StringConfigOption())
36
37 # Launchpad
38 launchpad = ConfigSection()
39@@ -69,3 +67,8 @@
40 piston = ConfigSection()
41 piston.oauth_data_store = StringConfigOption()
42
43+ # Softwarecenter agent.
44+ sca = ConfigSection()
45+ sca.sca_host_url = StringConfigOption(
46+ default='https://software-center.ubuntu.com/')
47+ sca.sca_apps_cache_timeout = IntConfigOption(default=3600)
48
49=== modified file 'src/reviewsapp/forms.py'
50--- src/reviewsapp/forms.py 2011-03-15 09:47:29 +0000
51+++ src/reviewsapp/forms.py 2011-03-15 09:47:29 +0000
52@@ -128,14 +128,14 @@
53 distroseries = self.cleaned_data['distroseries']
54 arch_tag=self.cleaned_data['arch_tag']
55
56- require_lp_check = False
57+ require_repository_check = False
58 repository = None
59 # First we grab the repository - if it exists.
60 try:
61 repository = Repository.objects.get(
62 origin=origin, distroseries=distroseries)
63 except Repository.DoesNotExist:
64- require_lp_check = True
65+ require_repository_check = True
66
67 if repository is not None:
68 # Check whether there are any existing reviews for this
69@@ -148,16 +148,20 @@
70 if review_count == 0:
71 # This is the first review for this software_item in the
72 # repository with the given arch.
73- require_lp_check = True
74+ require_repository_check = True
75
76- if require_lp_check:
77- valid_in_lp = WebServices().lp_verify_packagename_in_repository(
78+ if require_repository_check:
79+ ws = WebServices()
80+ valid_in_lp = ws.lp_verify_packagename_in_repository(
81 package_name, origin, distroseries, arch_tag=arch_tag)
82
83 if not valid_in_lp:
84- raise forms.ValidationError(
85- ': package {0} not in {1} {2} for {2}'.format(
86- package_name, origin, distroseries, arch_tag))
87+ valid_in_sca = ws.sca_verify_packagename_in_repository(
88+ package_name, origin, distroseries, arch_tag=arch_tag)
89+ if not valid_in_sca:
90+ raise forms.ValidationError(
91+ ': package {0} not in {1} {2} for {2}'.format(
92+ package_name, origin, distroseries, arch_tag))
93
94 # Now we know the given data corresponds to a published binary
95 # on launchpad, so we can populate the cleaned data, creating
96
97=== modified file 'src/reviewsapp/preflight.py'
98--- src/reviewsapp/preflight.py 2011-03-04 15:11:42 +0000
99+++ src/reviewsapp/preflight.py 2011-03-15 09:47:29 +0000
100@@ -63,7 +63,7 @@
101 def check_launchpad_api_access(self):
102 """
103 Make sure that the access to the Launchpad API (anonymous) works.
104-
105+
106 """
107 # Pull one data item from Launchpad
108 bug = WebServices().launchpad_service.bugs[1]
109@@ -76,4 +76,9 @@
110 parser = settings.__CONFIGGLUE_PARSER__
111 return parser.is_valid()
112
113+ def check_sca_validation(self):
114+ pubs = WebServices().get_sca_publishings_for('maverick', 'i386')
115+ return type(pubs) == dict
116+
117+
118 register(RNRPreflight)
119
120=== modified file 'src/reviewsapp/tests/factory.py'
121--- src/reviewsapp/tests/factory.py 2011-03-09 11:20:36 +0000
122+++ src/reviewsapp/tests/factory.py 2011-03-15 09:47:29 +0000
123@@ -25,6 +25,7 @@
124 ]
125
126
127+import os
128 from datetime import datetime
129 from itertools import count
130
131@@ -198,6 +199,10 @@
132 token.save()
133 return token, consumer
134
135+ def get_test_file(self, file_name):
136+ return os.path.join(os.path.dirname(__file__), 'test_data',
137+ file_name)
138+
139
140 class TestCaseWithFactory(TestCase, TestToolsTestCase):
141
142
143=== added directory 'src/reviewsapp/tests/test_data'
144=== added file 'src/reviewsapp/tests/test_data/software_center_apps.json'
145--- src/reviewsapp/tests/test_data/software_center_apps.json 1970-01-01 00:00:00 +0000
146+++ src/reviewsapp/tests/test_data/software_center_apps.json 2011-03-15 09:47:29 +0000
147@@ -0,0 +1,135 @@
148+[
149+ {
150+ "archive_id": "commercial-ppa-uploaders/fluendo-dvd",
151+ "signing_key_id": "1024R/75254D99",
152+ "description": "Play DVD-Videos\r\n\r\nFluendo DVD Player is a software application specially designed to\r\nreproduce DVD on Linux/Unix platforms, which provides end users with\r\nhigh quality standards.\r\n\r\nThe following features are provided:\r\n* Full DVD Playback\r\n* DVD Menu support\r\n* Fullscreen support\r\n* Dolby Digital pass-through\r\n* Dolby Digital 5.1 output and stereo downmixing support\r\n* Resume from last position support\r\n* Subtitle support\r\n* Audio selection support\r\n* Multiple Angles support\r\n* Support for encrypted discs\r\n* Multiregion, works in all regions\r\n* Multiple video deinterlacing algorithms",
153+ "package_name": "fluendo-dvd",
154+ "series": {
155+ "maverick": [
156+ "i386",
157+ "amd64"
158+ ]
159+ },
160+ "price": "24.95",
161+ "icon_data": "...",
162+ "screenshot_url": "http://software-center.ubuntu.com/screenshots/f/fluendo-dvd-maverick.png",
163+ "archive_root": "https://private-ppa.launchpad.net/",
164+ "tos_url": "http://software-center.ubuntu.com/tos/fluendo-eula.html",
165+ "categories": "GNOME;GTK;Video;Player;Application;AudioVideo",
166+ "name": "Fluendo DVD Player"
167+ },
168+ {
169+ "archive_id": "commercial-ppa-uploaders/fluendo-plugins",
170+ "signing_key_id": "1024R/75254D99",
171+ "description": "Complete set of multimedia plugins provided by Fluendo. \r\nThis product contains plug-ins which allow you to play certain proprietary audio and video formats. These plug-ins are not included in the default Ubuntu distribution because they are not free software. Ubuntu is driven by strong support for the principles of free and open source software, and these principles govern what we can and will include in Ubuntu. However, we recognise the common need for plug-ins such as these, and offer them here to provide a safe and legal way for our users to play back video and audio in the formats they wish. These plug-ins automatically integrate with GStreamer, the multimedia framework that Ubuntu uses for video and sound applications.\r\n\r\nThe Fluendo Complete Playback Pack includes all the plug-ins you need in a single package. This pack includes:\r\n\r\nWindows Media Audio Decoder Stereo (Windows Media 7, 8, 9, 10, Pro, Lossless and Speech)\r\nWindows Media Video Decoder (Windows Media 7, 8, 9 and VC1)\r\nWindows Media ASF Demuxer\r\nWindows Media MMS Networking\r\nMPEG2 Video Decoder\r\nMPEG4 Part 2 Video Decoder\r\nDivX 3.11 Alpha ;-) Video Decoder\r\nH.264/AVC Video Decoder\r\nMPEG2 Program Stream and Transport Stream demuxer\r\nMPEG4 ISO Demuxer\r\nMP3 Audio Decoder\r\nAAC Audio Decoder\r\nLPCM Audio Decoder\r\nVDPAU/VAAPI\r\nClutter support to render hardware accelerated video in Clutter 3D Texture\r\nAC3 Audio Decoder (Dolby Digital) for Totem Media Player only\r\niLBC Audio Decoder\r\nADPCM Audio Decoder",
172+ "package_name": "gstreamer0.10-fluendo-plugins",
173+ "series": {
174+ "maverick": [
175+ "i386",
176+ "amd64"
177+ ]
178+ },
179+ "price": "34.95",
180+ "icon_data": "...",
181+ "screenshot_url": "",
182+ "archive_root": "https://private-ppa.launchpad.net/",
183+ "tos_url": "",
184+ "categories": "AudioVideo;Audio;Music",
185+ "name": "Fluendo Complete Playback Pack"
186+ },
187+ {
188+ "archive_id": "commercial-ppa-uploaders/brukkon",
189+ "signing_key_id": "1024R/75254D99",
190+ "description": "puzzle game inspired by sokoban\r\n\r\nBrukkon (Old High German: to bridge a gap) is a challenging logic puzzle\r\ngame available for Linux. To solve one of the 35 challenging puzzle levels,\r\nyou have to guide a little robot to its spare parts. This version includes 5\r\nextra levels exclusive for Ubuntu users. \r\n\r\nYou do this by moving the robot over platforms and removing barricades in\r\nits way. The movable ground tiles keep moving in the direction they were sent,\r\nuntil they are stopped by either another tile or by the level borders. Some\r\nof them can go in all four directions, some of them are limited to horizontal\r\nor vertical movement. The robot can stop on non colored movable tiles and be\r\nmoved with the puzzle element to overcome water areas - or bridge a gap, which is\r\nwhere the name comes from. The robot can not go onto colored puzzle tiles,\r\nsometimes you need to remove the tiles by moving four or more puzzle tiles\r\nof the same color in a row to remove them. Some ground tiles are broken and\r\nvanish after the robot moved over them once - so be sure to move wise, or\r\nthe puzzle could become unsolvable, although you can restart at any time and as\r\noften as you like.\r\n\r\nAfter successfully solving a puzzle, you can submit the number of moves and\r\nthe time you took to a online high score and compare it with other players.\r\n\r\nThe real challenge comes by trying to reduce the number of moves you need\r\nto solve the puzzle levels. You can reduce the number of moves by moving more\r\nplatforms simultaneously and use them to stop other platforms by driving\r\nthem in their way.\r\n\r\nBrukkon also features beautiful relaxed music and several graphics themes\r\nwith day and night and different weather situations. Two different camera\r\npositions can be freely configured and you can switch quickly between them by tapping\r\nthe space bar.",
191+ "package_name": "brukkon",
192+ "series": {
193+ "maverick": [
194+ "i386",
195+ "amd64"
196+ ]
197+ },
198+ "price": "7.00",
199+ "icon_data": "...",
200+ "screenshot_url": "http://software-center.ubuntu.com/screenshots/b/brukkon-maverick.png",
201+ "archive_root": "https://private-ppa.launchpad.net/",
202+ "tos_url": "",
203+ "categories": "Game;LogicGame",
204+ "name": "Brukkon"
205+ },
206+ {
207+ "archive_id": "commercial-ppa-uploaders/vendetta-online",
208+ "signing_key_id": "1024R/75254D99",
209+ "description": "3D space combat MMORPG\r\nVendetta Online is a 3D space combat MMORPG. This MMO permits thousands of players to interact as the pilots of spaceships in a vast universe. Users may build their characters in any direction they desire, becoming rich captains of industry, military heroes, or outlaws.\r\n\r\nA fast-paced, realtime \"twitch\" style combat model gives intense action, coupled with the backdrop of RPG gameplay in a massive online galaxy. Three major player factions form a delicate balance of power, with several NPC sub-factions creating situations of economic struggle, political intrigue and conflict. The completely persistent universe and detailed storyline add to the depth of immersion, resulting in a unique online experience.",
210+ "package_name": "vendetta-online",
211+ "series": {
212+ "maverick": [
213+ "i386",
214+ "amd64"
215+ ]
216+ },
217+ "price": "0.00",
218+ "icon_data": "...",
219+ "screenshot_url": "http://software-center.ubuntu.com/screenshots/v/vendetta-online-maverick.png",
220+ "archive_root": "https://private-ppa.launchpad.net/",
221+ "tos_url": "",
222+ "categories": "Game;RolePlaying",
223+ "name": "Vendetta Online"
224+ },
225+ {
226+ "archive_id": "commercial-ppa-uploaders/fluendo-wmv-plugins",
227+ "signing_key_id": "1024R/75254D99",
228+ "description": "Plug-ins for the most common Windows Media formats. \r\nThis product contains plug-ins which allow you to play certain proprietary audio and video formats. These plug-ins are not included in the default Ubuntu distribution because they are not free software. Ubuntu is driven by strong support for the principles of free and open source software, and these principles govern what we can and will include in Ubuntu. However, we recognise the common need for plug-ins such as these, and offer them here to provide a safe and legal way for our users to play back video and audio in the formats they wish. These plug-ins automatically integrate with GStreamer, the multimedia framework that Ubuntu uses for video and sound applications.\r\n\r\nThe Fluendo Windows Media Pack provides plug-ins for all the common Windows Media formats. This pack includes:\r\n\r\nWindows Media Audio Decoder (Windows Media 7, 8, 9, 10, Pro, Lossless and Speech)\r\nWindows Media Video Decoder (Windows Media 7, 8, 9 and VC1)\r\nWindows Media MMS Protocol Support\r\nWindows Media ASF Demuxer\r\nMP3 Audio decoder\r\nLPCM Audio decoder",
229+ "package_name": "gstreamer0.10-fluendo-plugins-wmv",
230+ "series": {
231+ "maverick": [
232+ "i386",
233+ "amd64"
234+ ]
235+ },
236+ "price": "24.95",
237+ "icon_data": "...",
238+ "screenshot_url": "",
239+ "archive_root": "https://private-ppa.launchpad.net/",
240+ "tos_url": "",
241+ "categories": "AudioVideo;Audio;Music",
242+ "name": "Fluendo Windows Media Pack"
243+ },
244+ {
245+ "archive_id": "commercial-ppa-uploaders/world-of-goo",
246+ "signing_key_id": "1024R/75254D99",
247+ "description": "Physics based puzzle/construction game.\r\nDrag and drop living, squirming, talking globs of goo to build structures, bridges, cannonballs, zeppelins, and giant tongues. The millions of innocent goo balls that live in the beautiful World of Goo are curious to explore.\r\n\r\nBut they don't know that they are in a game, or that they are extremely delicious. The most addicting and awe-inspiring puzzle game will set you on an adventure that you'll never forget!",
248+ "package_name": "worldofgoo",
249+ "series": {
250+ "maverick": [
251+ "i386",
252+ "amd64"
253+ ]
254+ },
255+ "price": "19.95",
256+ "icon_data": "...",
257+ "screenshot_url": "http://software-center.ubuntu.com/screenshots/w/worldofgoo-maverick.png",
258+ "archive_root": "https://private-ppa.launchpad.net/",
259+ "tos_url": "",
260+ "categories": "Game;Simulation",
261+ "name": "World of Goo"
262+ },
263+ {
264+ "archive_id": "commercial-ppa-uploaders/illumination",
265+ "signing_key_id": "1024R/75254D99",
266+ "description": "Visually create desktop, mobile and web apps.\r\nIllumination Software Creator allows anyone to create their own software applications... without writing a single line of \u201ccode\u201d.\r\n\r\nThe idea is simple: Arrange colorful building blocks of functionality however you like to create your own, unique, piece of software. No reading large computer programming books. No steep learning curve.\r\n\r\nFrom one, 100% visual project you can build the following:\r\n\r\n- Python/GTK Desktop apps\r\n- Python GTK Maemo (N900) apps\r\n- Android apps\r\n- Adobe Flash rich web apps",
267+ "package_name": "illumination",
268+ "series": {
269+ "maverick": [
270+ "i386",
271+ "amd64"
272+ ]
273+ },
274+ "price": "39.85",
275+ "icon_data": "...",
276+ "screenshot_url": "http://software-center.ubuntu.com/screenshots/i/illumination-maverick.png",
277+ "archive_root": "https://private-ppa.launchpad.net/",
278+ "tos_url": "",
279+ "categories": "GNOME;Application;Development;",
280+ "name": "Illumination Software Creator"
281+ }
282+]
283
284=== modified file 'src/reviewsapp/tests/test_handlers.py'
285--- src/reviewsapp/tests/test_handlers.py 2011-03-15 09:47:29 +0000
286+++ src/reviewsapp/tests/test_handlers.py 2011-03-15 09:47:29 +0000
287@@ -476,7 +476,7 @@
288 }
289 super(SubmitReviewHandlerTestCase, self).setUp()
290
291- def _post_new_review(self, data, user=None, lp_verify_result=True):
292+ def _post_new_review(self, data, user=None, verify_result=True):
293 # Post a review as an authenticated user.
294 url = reverse('rnr-api-reviews')
295
296@@ -484,15 +484,20 @@
297 user = self.factory.makeUser()
298 self.client.login(username=user.username, password='test')
299
300+ # Ensure we don't hit the network for our tests.
301 is_authed_fn = 'reviewsapp.auth.SSOOAuthAuthentication.is_authenticated'
302 lp_verify_fn = ('reviewsapp.utilities.WebServices.'
303 'lp_verify_packagename_in_repository')
304+ sca_verify_fn = ('reviewsapp.utilities.WebServices.'
305+ 'sca_verify_packagename_in_repository')
306 with patch(is_authed_fn) as mock_is_authenticated:
307 mock_is_authenticated.return_value = True
308 with patch(lp_verify_fn) as mock_lp_verify_method:
309- mock_lp_verify_method.return_value = lp_verify_result
310- response = self.client.post(
311- url, data=data, content_type='application/json')
312+ mock_lp_verify_method.return_value = verify_result
313+ with patch(sca_verify_fn) as mock_sca_verify_method:
314+ mock_sca_verify_method.return_value = verify_result
315+ response = self.client.post(
316+ url, data=data, content_type='application/json')
317 return response
318
319 def test_bogus_data(self):
320@@ -550,7 +555,7 @@
321 package_name='inkscape').count())
322
323 response = self._post_new_review(
324- simplejson.dumps(self.required_data), lp_verify_result=False)
325+ simplejson.dumps(self.required_data), verify_result=False)
326
327 self.assertEqual(httplib.BAD_REQUEST, response.status_code)
328 self.assertEqual(0, Repository.objects.filter(
329
330=== modified file 'src/reviewsapp/tests/test_preflight.py'
331--- src/reviewsapp/tests/test_preflight.py 2011-02-23 13:48:45 +0000
332+++ src/reviewsapp/tests/test_preflight.py 2011-03-15 09:47:29 +0000
333@@ -1,49 +1,78 @@
334-# import paymentservice
335-# import testconsumer
336+# -*- coding: utf-8 -*-
337+# This file is part of Software Center Ratings and Reviews
338+# Copyright (C) 2010-2011 Canonical Ltd.
339+#
340+# This program is free software: you can redistribute it and/or modify
341+# it under the terms of the GNU Affero General Public License as
342+# published by the Free Software Foundation, either version 3 of the
343+# License, or (at your option) any later version.
344+#
345+# This program is distributed in the hope that it will be useful,
346+# but WITHOUT ANY WARRANTY; without even the implied warranty of
347+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
348+# GNU Affero General Public License for more details.
349+#
350+# You should have received a copy of the GNU Affero General Public License
351+# along with this program. If not, see <http://www.gnu.org/licenses/>.
352+
353+"""Tests for the preflight integration."""
354+
355+from __future__ import (
356+ absolute_import,
357+ with_statement,
358+ )
359+
360+__metaclass__ = type
361+__all__ = [
362+ 'TestPreflight',
363+ ]
364+
365+from mock import patch
366
367 from django.contrib.auth.models import User, Group
368-from django.test import TestCase
369-
370-
371-class TestPreflight(TestCase):
372-
373- def setUp(self):
374- self.user = User.objects.create_user(username='test',
375- email='test@test.com', password='test')
376- self.group = Group.objects.get(name='rnr-developers')
377- self.url = '/preflight/'
378+
379+from reviewsapp.tests.factory import TestCaseWithFactory
380+
381+
382+class TestPreflight(TestCaseWithFactory):
383+
384+ def _request_preflight(self, authenticated=True, user=None):
385+ if authenticated:
386+ if user is None:
387+ user = self.factory.makeUser()
388+ group = Group.objects.get(name='rnr-developers')
389+ user.groups.add(group)
390+ login = self.client.login(username=user.username, password='test')
391+ self.assertTrue(login, 'Could not log in')
392+
393+ with patch('preflight.models.gather_checks') as mock_gather_checks:
394+ mock_gather_checks.return_value = []
395+ response = self.client.get('/preflight/')
396+ return response
397
398 def test_anonymous(self):
399- response = self.client.get(self.url)
400+ response = self._request_preflight(authenticated=False)
401
402 self.assertEqual(404, response.status_code)
403
404 def test_logged_in_no_group(self):
405- login = self.client.login(username='test', password='test')
406- self.assertTrue(login, 'Could not log in')
407+ user = self.factory.makeUser(username='test')
408
409- response = self.client.get(self.url)
410+ response = self._request_preflight(user=user)
411
412 self.assertEqual(404, response.status_code)
413
414 def test_logged_in_wrong_group(self):
415 g = Group.objects.create(name='someothergroup')
416- self.user.groups.add(g)
417- self.user.save()
418- login = self.client.login(username='test', password='test')
419- self.assertTrue(login)
420+ user = self.factory.makeUser(username='test')
421+ user.groups.add(g)
422
423- response = self.client.get(self.url)
424+ response = self._request_preflight(user=user)
425
426 self.assertEqual(404, response.status_code)
427
428 def test_success(self):
429- self.user.groups.add(self.group)
430- self.user.save()
431- login = self.client.login(username='test', password='test')
432- self.assertTrue(login)
433-
434- response = self.client.get(self.url)
435+ response = self._request_preflight()
436
437 self.assertEqual(200, response.status_code)
438 libs = set([x['name'] for x in response.context[0]['versions']])
439
440=== modified file 'src/reviewsapp/tests/test_utilities.py'
441--- src/reviewsapp/tests/test_utilities.py 2011-03-15 09:47:29 +0000
442+++ src/reviewsapp/tests/test_utilities.py 2011-03-15 09:47:29 +0000
443@@ -20,10 +20,11 @@
444
445 __metaclass__ = type
446 __all__ = [
447+ 'FullClaimedIdTestCase',
448 'IdentityProviderTestCase',
449 'InvalidatePaginatedReviewsTestCase',
450 'LaunchpadTestCase',
451- 'FullClaimedIdTestCase',
452+ 'SCATestCase',
453 ]
454
455 import os
456@@ -32,7 +33,6 @@
457 from django.conf import settings
458 from django.core.cache import cache
459 from django.core.urlresolvers import reverse
460-from django.http import HttpRequest
461 from launchpadlib.errors import HTTPError
462 from mock import patch, Mock
463 from mockssoservice.mockserver import MockSSOServer, new_token
464@@ -182,17 +182,6 @@
465 status='Published', exact_match=True)
466 self.assertTrue(result)
467
468- def test_commercial_package(self):
469- lp_api, ubuntu, archive = self._make_mock_launchpad()
470-
471- with patch_settings(COMMERCIAL_ORIGINS=['lp-ppa-commercial-one']):
472- result = self._verify_package(lp_api, 'anything',
473- 'lp-ppa-commercial-one', 'anything', 'anything')
474-
475- # XXX The result should not always be true... we need a way to
476- # know the content of commercial ppas.
477- self.assertTrue(result)
478-
479 def test_unknown_origin(self):
480 lp_api, ubuntu, archive = self._make_mock_launchpad()
481
482@@ -244,6 +233,74 @@
483 "foobar", "ubuntu", "lucid", 'i386')
484
485
486+class SCATestCase(TestCaseWithFactory):
487+
488+ def _request_sca_pubs_for(self, distroseries, arch_tag, disable_cache=True):
489+ with patch('urllib.urlretrieve') as mock_urlretrieve:
490+ mock_urlretrieve.return_value = (
491+ self.factory.get_test_file('software_center_apps.json'), None)
492+ if disable_cache:
493+ with patch('django.core.cache') as mock_cache:
494+ mock_cache.get.return_value = False
495+ published_apps = WebServices().get_sca_publishings_for(
496+ distroseries, arch_tag)
497+ else:
498+ published_apps = WebServices().get_sca_publishings_for(
499+ distroseries, arch_tag)
500+ return published_apps, mock_urlretrieve
501+
502+ def test_get_sca_publishings(self):
503+ published_apps, ignored = self._request_sca_pubs_for(
504+ 'maverick', 'i386')
505+
506+ self.assertEqual({
507+ 'lp-ppa-commercial-ppa-uploaders-brukkon': 'brukkon',
508+ 'lp-ppa-commercial-ppa-uploaders-fluendo-dvd': 'fluendo-dvd',
509+ 'lp-ppa-commercial-ppa-uploaders-fluendo-plugins':
510+ 'gstreamer0.10-fluendo-plugins',
511+ 'lp-ppa-commercial-ppa-uploaders-fluendo-wmv-plugins':
512+ 'gstreamer0.10-fluendo-plugins-wmv',
513+ 'lp-ppa-commercial-ppa-uploaders-illumination': 'illumination',
514+ 'lp-ppa-commercial-ppa-uploaders-vendetta-online': 'vendetta-online',
515+ 'lp-ppa-commercial-ppa-uploaders-world-of-goo': 'worldofgoo',
516+ }, published_apps)
517+
518+ def test_retrieved_url(self):
519+ with patch_settings(SCA_HOST_URL='http://example.com/'):
520+ ignored, mock_urlretrieve = self._request_sca_pubs_for(
521+ 'natty', 'amd64')
522+
523+ mock_urlretrieve.assert_called_with(
524+ 'http://example.com/apps/en/ubuntu/natty/amd64/')
525+
526+ def test_get_sca_publishings_cached(self):
527+ published_apps, mock_url_retrieve = self._request_sca_pubs_for(
528+ 'maverick', 'i386', disable_cache=False)
529+ published_apps, mock_urlretrieve = self._request_sca_pubs_for(
530+ 'maverick', 'i386', disable_cache=False)
531+
532+ self.assertEqual(0, mock_urlretrieve.call_count)
533+
534+ def _request_sca_verify(self, pkgname, origin, distroseries, arch_tag):
535+ with patch('urllib.urlretrieve') as mock_urlretrieve:
536+ mock_urlretrieve.return_value = (
537+ self.factory.get_test_file('software_center_apps.json'), None)
538+ ws = WebServices()
539+ return ws.sca_verify_packagename_in_repository(
540+ pkgname, origin, distroseries, arch_tag)
541+
542+ def test_sca_verify_packagename(self):
543+ self.assertTrue(self._request_sca_verify(
544+ 'brukkon', 'lp-ppa-commercial-ppa-uploaders-brukkon',
545+ 'maverick', 'i386'))
546+ self.assertFalse(self._request_sca_verify(
547+ 'fluendo-dvd', 'lp-ppa-commercial-ppa-uploaders-brukkon',
548+ 'maverick', 'i386'))
549+ self.assertFalse(self._request_sca_verify(
550+ 'brukkon', 'lp-ppa-commercial-ppa-uploaders-doesnt-exist',
551+ 'maverick', 'i386'))
552+
553+
554 class InvalidatePaginatedReviewsTestCase(TestCaseWithFactory):
555 def _url_for_package(self, package_name, origin='ubuntu',
556 distro_series='lucid', language='en', version='1.0', page=None):
557
558=== modified file 'src/reviewsapp/utilities.py'
559--- src/reviewsapp/utilities.py 2011-03-15 09:47:29 +0000
560+++ src/reviewsapp/utilities.py 2011-03-15 09:47:29 +0000
561@@ -27,7 +27,6 @@
562 ]
563
564 import logging
565-import os
566 import urllib
567 from httplib2 import ServerNotFoundError
568
569@@ -37,6 +36,8 @@
570 from django.http import HttpRequest
571 from django.utils.cache import get_cache_key
572 from django.utils.http import urlquote_plus
573+from django.utils import simplejson
574+
575 from launchpadlib.launchpad import Launchpad
576 from launchpadlib.uris import lookup_service_root
577 from lazr.restfulclient.authorize import BasicHttpAuthorizer
578@@ -120,10 +121,10 @@
579 def _fake_validate_token(self, token, openid_identifier, signature):
580 """ This is a version of validate_token that gets the
581 token_secret, consumer_secret from the plaintext signature.
582-
583+
584 It will break once we use a real signature for oauth, but
585 its very useful for testing as it does not require the special
586- priviledges required for the call to
587+ priviledges required for the call to
588 identity_provider.authentications.validate_token()
589
590 The token can still be validated (and will be) with a
591@@ -159,7 +160,7 @@
592
593 def lp_verify_packagename_in_repository(self, pkgname, origin, distroseries,
594 arch_tag):
595- """Verify that a given package exists in a distroseries.
596+ """Verify that a given package exists in a distroseries on LP.
597
598 :param pkgname: The name of the package to check.
599 :param origin: The repository origin identifier.
600@@ -177,24 +178,6 @@
601 app_review_board = self.launchpad_service.people[
602 'app-review-board']
603 archive = app_review_board.getPPAByName(name='ppa')
604- elif origin in settings.COMMERCIAL_ORIGINS:
605- # XXX 2011-03-11 michaeln bug=733170 PPA origins are
606- # currently ambiguous.
607- # We should check this in a way that doesn't require
608- # settings, either pulling the data from SCA, or request
609- # that LP updates IArchive to allow public access to
610- # getPublishedBinaries() for commercial PPAs (but not
611- # private-only).
612- # XXX - chat with achuni about options - dict in settings?
613- # Perhaps for now just a non-configglue setting with a
614- # complex dict:
615- # 'lp-ppa-commercial-ppa-uploaders-fluendo-dvd': {
616- # 'package_name': 'fluendo-dvd',
617- # 'releases': {
618- # 'natty': ['i386', 'amd64'],
619- # ...
620- # And then we can make this available on SCA as json/api.
621- return True
622 else:
623 return False
624
625@@ -218,6 +201,62 @@
626 return True
627 return False
628
629+ def sca_verify_packagename_in_repository(self, pkgname, origin,
630+ distroseries, arch_tag):
631+ """Verify that a given package exists in a distroseries on SCA.
632+
633+ :param pkgname: The name of the package to check.
634+ :param origin: The repository origin identifier.
635+ :param distroseries: The name of distribution series.
636+ :param arch_tag: The machine architecture (i386, amd64...)
637+ :return: Whether the package was found or not.
638+ :rtype: bool
639+ """
640+ sca_publishings = self.get_sca_publishings_for(distroseries, arch_tag)
641+ if origin in sca_publishings:
642+ # XXX 2011-03-11 michaeln bug=733170 PPA origins are
643+ # currently ambiguous.
644+ published_apps = self.get_sca_publishings_for(distroseries, arch_tag)
645+ return pkgname == published_apps[origin]
646+
647+ return False
648+
649+ def get_sca_publishings_for(self, distroseries, arch_tag):
650+ """A helper that builds a dict of publishings for sca-sold apps.
651+
652+ XXX michaeln 2011-03-14 bug=734747 Optional parms for available_apps.
653+ It would be great if we could just pull /apps/en/ubuntu/ and use
654+ each items 'series' dict to populate this, rather than pulling each
655+ distroserie/arch separately. If we can assume that an app sold via
656+ softwarecenter will always be available for maverick i386, then we
657+ could do just the one call too.
658+ """
659+ cache_key = 'sca_{0}_{1}'.format(distroseries, arch_tag)
660+ result = cache.get(cache_key)
661+ if result is not None:
662+ return result
663+
664+ # XXX michaeln 2011-03-14 Update to use sca piston client.
665+ # Once production SCA includes the piston client version we can
666+ # use that instead. At time of writing the following url works
667+ # on staging but not production sca:
668+ # api/2.0/applications/en/ubuntu/maverick/i386/
669+ filename, headers = urllib.urlretrieve(
670+ settings.SCA_HOST_URL +
671+ 'apps/en/ubuntu/{0}/{1}/'.format(distroseries, arch_tag))
672+
673+ with open(filename, 'r') as sca_apps_file:
674+ sca_apps = simplejson.load(sca_apps_file)
675+
676+ # We ensure the keys match Launchpad's current (ambiguous)
677+ # origin identifiers - Launchpad bug 733170.
678+ app_names = dict([(
679+ 'lp-ppa-' + app['archive_id'].replace('/', '-'),
680+ app['package_name'],
681+ ) for app in sca_apps])
682+ cache.set(cache_key, app_names, settings.SCA_APPS_CACHE_TIMEOUT)
683+ return app_names
684+
685
686 def cache_key_for_url(url):
687 """Return the key used by django's caching system for a (non-varied) url."""

Subscribers

People subscribed via source and target branches