Merge lp:~michael.nelson/rnr-server/731376-other-origins-2 into lp:rnr-server
- 731376-other-origins-2
- Merge into trunk
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 | ||||
Related bugs: |
|
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:/
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:/
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.
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.
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
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.""" |
Approved - I'll put line 27 back in in another branch.