Merge lp:~wgrant/launchpad/replace-archiveuploader-doctests-0 into lp:launchpad
- replace-archiveuploader-doctests-0
- Merge into devel
Proposed by
William Grant
on 2010-07-24
| Status: | Merged |
|---|---|
| Approved by: | Robert Collins on 2010-07-24 |
| Approved revision: | no longer in the source branch. |
| Merged at revision: | 11269 |
| Proposed branch: | lp:~wgrant/launchpad/replace-archiveuploader-doctests-0 |
| Merge into: | lp:launchpad |
| Diff against target: |
765 lines (+219/-350) 8 files modified
lib/lp/archiveuploader/nascentupload.py (+4/-22) lib/lp/archiveuploader/tests/nascentupload-announcements.txt (+3/-6) lib/lp/archiveuploader/tests/nascentupload-security-uploads.txt (+3/-0) lib/lp/archiveuploader/tests/nascentupload.txt (+22/-22) lib/lp/archiveuploader/tests/nascentuploadfile.txt (+4/-264) lib/lp/archiveuploader/tests/test_dscfile.py (+137/-2) lib/lp/archiveuploader/tests/test_utils.py (+46/-29) lib/lp/soyuz/tests/test_doc.py (+0/-5) |
| To merge this branch: | bzr merge lp:~wgrant/launchpad/replace-archiveuploader-doctests-0 |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Robert Collins (community) | 2010-07-24 | Approve on 2010-07-24 | |
|
Review via email:
|
|||
Commit Message
Replaced some archiveuploader doctests with unit tests, and moved some remaining archiveuploader doctests from Soyuz to archiveuploader.
Description of the Change
Three things:
- Replaces some archiveuploader doctest sections with unit tests.
- Removes a couple of attributes from NascentUpload that were used by only one test -- that test now calculates them itself.
- Moves some missed archiveuploader doctests from lp.soyuz to lp.archiveuploader.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
| 1 | === modified file 'lib/lp/archiveuploader/nascentupload.py' |
| 2 | --- lib/lp/archiveuploader/nascentupload.py 2010-07-15 09:42:28 +0000 |
| 3 | +++ lib/lp/archiveuploader/nascentupload.py 2010-07-24 09:41:13 +0000 |
| 4 | @@ -82,10 +82,6 @@ |
| 5 | archindep = False |
| 6 | archdep = False |
| 7 | |
| 8 | - # Defined in check_sourceful_consistency() |
| 9 | - native = False |
| 10 | - hasorig = False |
| 11 | - |
| 12 | # Defined if we successfully do_accept() and storeObjectsInDatabase() |
| 13 | queue_root = None |
| 14 | |
| 15 | @@ -308,31 +304,17 @@ |
| 16 | assert self.sourceful, ( |
| 17 | "Source consistency check called for a non-source upload") |
| 18 | |
| 19 | - dsc = 0 |
| 20 | - native_tarball = 0 |
| 21 | - orig_tarball = 0 |
| 22 | - |
| 23 | - for uploaded_file in self.changes.files: |
| 24 | - filetype = determine_source_file_type(uploaded_file.filename) |
| 25 | - if filetype == SourcePackageFileType.DSC: |
| 26 | - dsc += 1 |
| 27 | - elif (filetype == SourcePackageFileType.NATIVE_TARBALL |
| 28 | - and not isinstance(uploaded_file, CustomUploadFile)): |
| 29 | - native_tarball += 1 |
| 30 | - elif filetype == SourcePackageFileType.ORIG_TARBALL: |
| 31 | - orig_tarball += 1 |
| 32 | - |
| 33 | + dsc = len([ |
| 34 | + file for file in self.changes.files |
| 35 | + if determine_source_file_type(file.filename) == |
| 36 | + SourcePackageFileType.DSC]) |
| 37 | |
| 38 | # It is never sane to upload more than one source at a time. |
| 39 | if dsc > 1: |
| 40 | self.reject("Changes file lists more than one .dsc") |
| 41 | - |
| 42 | if dsc == 0: |
| 43 | self.reject("Sourceful upload without a .dsc") |
| 44 | |
| 45 | - self.native = bool(native_tarball) |
| 46 | - self.hasorig = bool(orig_tarball) |
| 47 | - |
| 48 | def _check_binaryful_consistency(self): |
| 49 | """Heuristic checks on a binaryful upload. |
| 50 | |
| 51 | |
| 52 | === renamed file 'lib/lp/soyuz/doc/nascentupload-announcements.txt' => 'lib/lp/archiveuploader/tests/nascentupload-announcements.txt' |
| 53 | --- lib/lp/soyuz/doc/nascentupload-announcements.txt 2010-05-27 09:08:10 +0000 |
| 54 | +++ lib/lp/archiveuploader/tests/nascentupload-announcements.txt 2010-07-24 09:41:13 +0000 |
| 55 | @@ -39,6 +39,8 @@ |
| 56 | |
| 57 | We need to be logged into the security model in order to get any further |
| 58 | |
| 59 | + >>> from canonical.testing.layers import LaunchpadZopelessLayer |
| 60 | + >>> LaunchpadZopelessLayer.switchDbUser('launchpad') |
| 61 | >>> login('foo.bar@canonical.com') |
| 62 | |
| 63 | Helper functions to examine emails that were sent: |
| 64 | @@ -58,17 +60,12 @@ |
| 65 | address and allow uploads to universe: |
| 66 | |
| 67 | >>> from canonical.launchpad.interfaces import ( |
| 68 | - ... SeriesStatus, IComponentSet, IDistributionSet, |
| 69 | - ... ILibraryFileAliasSet) |
| 70 | + ... SeriesStatus, IDistributionSet, ILibraryFileAliasSet) |
| 71 | >>> ubuntu = getUtility(IDistributionSet)['ubuntu'] |
| 72 | >>> hoary = ubuntu['hoary'] |
| 73 | >>> hoary.status = SeriesStatus.DEVELOPMENT |
| 74 | >>> hoary.changeslist = "hoary-announce@lists.ubuntu.com" |
| 75 | - >>> from canonical.launchpad.database import ComponentSelection |
| 76 | - >>> universe = getUtility(IComponentSet)['universe'] |
| 77 | - >>> trash = ComponentSelection(distroseries=hoary, component=universe) |
| 78 | >>> fake_chroot = getUtility(ILibraryFileAliasSet)[1] |
| 79 | - >>> trash = hoary['i386'].addOrUpdateChroot(fake_chroot) |
| 80 | >>> trash = hoary['hppa'].addOrUpdateChroot(fake_chroot) |
| 81 | |
| 82 | NEW source upload to RELEASE pocket via 'sync' policy (it presents |
| 83 | |
| 84 | === renamed file 'lib/lp/soyuz/doc/nascentupload-security-uploads.txt' => 'lib/lp/archiveuploader/tests/nascentupload-security-uploads.txt' |
| 85 | --- lib/lp/soyuz/doc/nascentupload-security-uploads.txt 2009-05-13 14:05:27 +0000 |
| 86 | +++ lib/lp/archiveuploader/tests/nascentupload-security-uploads.txt 2010-07-24 09:41:13 +0000 |
| 87 | @@ -31,6 +31,8 @@ |
| 88 | respective processorfamily and processor. Let's create them |
| 89 | on-the-fly: |
| 90 | |
| 91 | + >>> from canonical.testing.layers import LaunchpadZopelessLayer |
| 92 | + >>> LaunchpadZopelessLayer.switchDbUser('launchpad') |
| 93 | >>> from canonical.launchpad.interfaces import IDistributionSet |
| 94 | >>> from canonical.launchpad.database import ( |
| 95 | ... Processor, ProcessorFamily) |
| 96 | @@ -45,6 +47,7 @@ |
| 97 | |
| 98 | >>> import transaction |
| 99 | >>> transaction.commit() |
| 100 | + >>> LaunchpadZopelessLayer.switchDbUser('uploader') |
| 101 | |
| 102 | |
| 103 | == Mixed Security Upload == |
| 104 | |
| 105 | === renamed file 'lib/lp/soyuz/doc/nascentupload.txt' => 'lib/lp/archiveuploader/tests/nascentupload.txt' |
| 106 | --- lib/lp/soyuz/doc/nascentupload.txt 2010-05-21 12:12:58 +0000 |
| 107 | +++ lib/lp/archiveuploader/tests/nascentupload.txt 2010-07-24 09:41:13 +0000 |
| 108 | @@ -10,27 +10,13 @@ |
| 109 | >>> login('foo.bar@canonical.com') |
| 110 | |
| 111 | For the purpose of this test, hoary needs to be an open (development) |
| 112 | -distroseries so that we can upload to it. It also needs to allow uploads |
| 113 | -to the universe component. |
| 114 | - |
| 115 | -This test normally runs as the "uploader" db user but it does not have |
| 116 | -permission to add a new ComponentSelection, so we temporarily switch to |
| 117 | -"launchpad" to handle this. |
| 118 | +distroseries so that we can upload to it. |
| 119 | |
| 120 | >>> from canonical.launchpad.interfaces import ( |
| 121 | - ... SeriesStatus, IComponentSet, IDistributionSet) |
| 122 | - >>> from canonical.launchpad.database import ComponentSelection |
| 123 | + ... SeriesStatus, IDistributionSet) |
| 124 | >>> ubuntu = getUtility(IDistributionSet)['ubuntu'] |
| 125 | >>> hoary = ubuntu['hoary'] |
| 126 | >>> hoary.status = SeriesStatus.DEVELOPMENT |
| 127 | - >>> universe = getUtility(IComponentSet)['universe'] |
| 128 | - >>> from canonical.testing import LaunchpadZopelessLayer |
| 129 | - >>> from canonical.database.sqlbase import commit |
| 130 | - >>> commit() |
| 131 | - >>> LaunchpadZopelessLayer.switchDbUser('launchpad') |
| 132 | - >>> trash = ComponentSelection(distroseries=hoary, component=universe) |
| 133 | - >>> commit() |
| 134 | - >>> LaunchpadZopelessLayer.switchDbUser('uploader') |
| 135 | |
| 136 | A NascentUpload is a collection of files in a directory. They |
| 137 | represent what may turn out to be an acceptable upload to a launchpad |
| 138 | @@ -152,9 +138,21 @@ |
| 139 | |
| 140 | ed_source is uses ORIG + DIFF form: |
| 141 | |
| 142 | - >>> ed_source_upload.native |
| 143 | + >>> from lp.archiveuploader.utils import determine_source_file_type |
| 144 | + >>> from lp.registry.interfaces.sourcepackage import SourcePackageFileType |
| 145 | + >>> def determine_file_types(upload): |
| 146 | + ... return [determine_source_file_type(uf.filename) |
| 147 | + ... for uf in upload.changes.files] |
| 148 | + >>> def has_orig(upload): |
| 149 | + ... return (SourcePackageFileType.ORIG_TARBALL |
| 150 | + ... in determine_file_types(upload)) |
| 151 | + >>> def has_native(upload): |
| 152 | + ... return (SourcePackageFileType.NATIVE_TARBALL |
| 153 | + ... in determine_file_types(upload)) |
| 154 | + |
| 155 | + >>> has_native(ed_source_upload) |
| 156 | False |
| 157 | - >>> ed_source_upload.hasorig |
| 158 | + >>> has_orig(ed_source_upload) |
| 159 | True |
| 160 | |
| 161 | For *sourceful* uploads 'archdep' and 'archindep' are always False: |
| 162 | @@ -197,9 +195,9 @@ |
| 163 | As expected 'native' and 'hasorig' doesn't make any sense for binary |
| 164 | uploads, so they are alway False: |
| 165 | |
| 166 | - >>> ed_binary_upload.native |
| 167 | + >>> has_native(ed_binary_upload) |
| 168 | False |
| 169 | - >>> ed_binary_upload.hasorig |
| 170 | + >>> has_orig(ed_binary_upload) |
| 171 | False |
| 172 | |
| 173 | Since the binary policy lets things through unsigned, we don't try and |
| 174 | @@ -287,9 +285,9 @@ |
| 175 | ancestries (it saves a lot of bandwidth). So, the upload is not |
| 176 | 'native', neither 'hasorig': |
| 177 | |
| 178 | - >>> ed_mixed_upload.native |
| 179 | + >>> has_native(ed_mixed_upload) |
| 180 | False |
| 181 | - >>> ed_mixed_upload.hasorig |
| 182 | + >>> has_orig(ed_mixed_upload) |
| 183 | False |
| 184 | |
| 185 | But if we check the DSC we will find the reference to the already |
| 186 | @@ -716,7 +714,9 @@ |
| 187 | to set hoary to CURRENT in order to do this because we're not allowed |
| 188 | to upload to -UPDATES in a DEVELOPMENT series. |
| 189 | |
| 190 | + >>> from canonical.testing import LaunchpadZopelessLayer |
| 191 | >>> LaunchpadZopelessLayer.switchDbUser('launchpad') |
| 192 | + >>> from canonical.database.sqlbase import commit |
| 193 | >>> hoary.status = SeriesStatus.CURRENT |
| 194 | >>> commit() |
| 195 | >>> LaunchpadZopelessLayer.switchDbUser('uploader') |
| 196 | |
| 197 | === modified file 'lib/lp/archiveuploader/tests/nascentuploadfile.txt' |
| 198 | --- lib/lp/archiveuploader/tests/nascentuploadfile.txt 2010-06-16 09:08:16 +0000 |
| 199 | +++ lib/lp/archiveuploader/tests/nascentuploadfile.txt 2010-07-24 09:41:13 +0000 |
| 200 | @@ -155,161 +155,10 @@ |
| 201 | |
| 202 | === CustomUploadFile identification === |
| 203 | |
| 204 | -Source and Binary files are easily recognized by a regexp on the |
| 205 | -filenames: |
| 206 | - |
| 207 | - >>> from lp.archiveuploader.utils import ( |
| 208 | - ... re_isadeb, re_issource) |
| 209 | - |
| 210 | -The binary regexp matches 'deb', 'ddeb' and 'udeb' filenames. |
| 211 | - |
| 212 | - >>> deb_match = re_isadeb.match('foo-bar_1.0_i386.deb') |
| 213 | - >>> deb_match.group(0) |
| 214 | - 'foo-bar_1.0_i386.deb' |
| 215 | - >>> deb_match.group(1) |
| 216 | - 'foo-bar' |
| 217 | - >>> deb_match.group(2) |
| 218 | - '1.0' |
| 219 | - >>> deb_match.group(3) |
| 220 | - 'i386' |
| 221 | - |
| 222 | - >>> ddeb_match = re_isadeb.match('foo-bar_1.0_i386.ddeb') |
| 223 | - >>> ddeb_match.group(0) |
| 224 | - 'foo-bar_1.0_i386.ddeb' |
| 225 | - >>> ddeb_match.group(1) |
| 226 | - 'foo-bar' |
| 227 | - >>> ddeb_match.group(2) |
| 228 | - '1.0' |
| 229 | - >>> ddeb_match.group(3) |
| 230 | - 'i386' |
| 231 | - |
| 232 | - >>> udeb_match = re_isadeb.match('foo-bar_1.0_i386.udeb') |
| 233 | - >>> udeb_match.group(0) |
| 234 | - 'foo-bar_1.0_i386.udeb' |
| 235 | - >>> udeb_match.group(1) |
| 236 | - 'foo-bar' |
| 237 | - >>> udeb_match.group(2) |
| 238 | - '1.0' |
| 239 | - >>> udeb_match.group(3) |
| 240 | - 'i386' |
| 241 | - |
| 242 | -The source regexp matches 'orig.tar.gz', 'tar.gz', 'diff.gz' and 'dsc' |
| 243 | -filenames. |
| 244 | - |
| 245 | - >>> src_match = re_issource.match('foo_1.0.orig.tar.gz') |
| 246 | - >>> src_match.group(0) |
| 247 | - 'foo_1.0.orig.tar.gz' |
| 248 | - >>> src_match.group(1) |
| 249 | - 'foo' |
| 250 | - >>> src_match.group(2) |
| 251 | - '1.0' |
| 252 | - >>> src_match.group(3) |
| 253 | - 'orig.tar.gz' |
| 254 | - |
| 255 | - >>> src_match = re_issource.match('foo_1.0.tar.gz') |
| 256 | - >>> src_match.group(0) |
| 257 | - 'foo_1.0.tar.gz' |
| 258 | - >>> src_match.group(1) |
| 259 | - 'foo' |
| 260 | - >>> src_match.group(2) |
| 261 | - '1.0' |
| 262 | - >>> src_match.group(3) |
| 263 | - 'tar.gz' |
| 264 | - |
| 265 | - >>> src_match = re_issource.match('foo_1.0.tar.bz2') |
| 266 | - >>> src_match.group(0) |
| 267 | - 'foo_1.0.tar.bz2' |
| 268 | - >>> src_match.group(1) |
| 269 | - 'foo' |
| 270 | - >>> src_match.group(2) |
| 271 | - '1.0' |
| 272 | - >>> src_match.group(3) |
| 273 | - 'tar.bz2' |
| 274 | - |
| 275 | - >>> src_match = re_issource.match('foo_1.0.diff.gz') |
| 276 | - >>> src_match.group(0) |
| 277 | - 'foo_1.0.diff.gz' |
| 278 | - >>> src_match.group(1) |
| 279 | - 'foo' |
| 280 | - >>> src_match.group(2) |
| 281 | - '1.0' |
| 282 | - >>> src_match.group(3) |
| 283 | - 'diff.gz' |
| 284 | - |
| 285 | - >>> src_match = re_issource.match('foo_1.0.dsc') |
| 286 | - >>> src_match.group(0) |
| 287 | - 'foo_1.0.dsc' |
| 288 | - >>> src_match.group(1) |
| 289 | - 'foo' |
| 290 | - >>> src_match.group(2) |
| 291 | - '1.0' |
| 292 | - >>> src_match.group(3) |
| 293 | - 'dsc' |
| 294 | - |
| 295 | - >>> src_match = re_issource.match('foo_1.0.debian.tar.gz') |
| 296 | - >>> src_match.group(0) |
| 297 | - 'foo_1.0.debian.tar.gz' |
| 298 | - >>> src_match.group(1) |
| 299 | - 'foo' |
| 300 | - >>> src_match.group(2) |
| 301 | - '1.0' |
| 302 | - >>> src_match.group(3) |
| 303 | - 'debian.tar.gz' |
| 304 | - |
| 305 | - >>> src_match = re_issource.match('foo_1.0.debian.tar.bz2') |
| 306 | - >>> src_match.group(0) |
| 307 | - 'foo_1.0.debian.tar.bz2' |
| 308 | - >>> src_match.group(1) |
| 309 | - 'foo' |
| 310 | - >>> src_match.group(2) |
| 311 | - '1.0' |
| 312 | - >>> src_match.group(3) |
| 313 | - 'debian.tar.bz2' |
| 314 | - |
| 315 | - >>> src_match = re_issource.match('foo_1.0.orig-foo.tar.gz') |
| 316 | - >>> src_match.group(0) |
| 317 | - 'foo_1.0.orig-foo.tar.gz' |
| 318 | - >>> src_match.group(1) |
| 319 | - 'foo' |
| 320 | - >>> src_match.group(2) |
| 321 | - '1.0' |
| 322 | - >>> src_match.group(3) |
| 323 | - 'orig-foo.tar.gz' |
| 324 | - |
| 325 | - >>> src_match = re_issource.match('foo_1.0.orig-bar.tar.bz2') |
| 326 | - >>> src_match.group(0) |
| 327 | - 'foo_1.0.orig-bar.tar.bz2' |
| 328 | - >>> src_match.group(1) |
| 329 | - 'foo' |
| 330 | - >>> src_match.group(2) |
| 331 | - '1.0' |
| 332 | - >>> src_match.group(3) |
| 333 | - 'orig-bar.tar.bz2' |
| 334 | - |
| 335 | - >>> src_match = re_issource.match('foo_1.0.porig-bar.tar.bz2') |
| 336 | - >>> src_match.group(0) |
| 337 | - 'foo_1.0.porig-bar.tar.bz2' |
| 338 | - >>> src_match.group(1) |
| 339 | - 'foo' |
| 340 | - >>> src_match.group(2) |
| 341 | - '1.0.porig-bar' |
| 342 | - >>> src_match.group(3) |
| 343 | - 'tar.bz2' |
| 344 | - |
| 345 | -And finally some failures: |
| 346 | - |
| 347 | - >>> re_isadeb.match('foo-bar_1.0_i386.bed') is None |
| 348 | - True |
| 349 | - |
| 350 | - >>> re_issource.match('foo_1.0.c') is None |
| 351 | - True |
| 352 | - |
| 353 | - >>> re_issource.match('foo_1.0.diff.bz2') is None |
| 354 | - True |
| 355 | - |
| 356 | -However a custom upload is essencially a tarball, so it also matches |
| 357 | -the is_source regexp: |
| 358 | - |
| 359 | +A custom upload is essentially a tarball, so it matches the is_source |
| 360 | +regexp, even though it isn't actually a source file: |
| 361 | + |
| 362 | + >>> from lp.archiveuploader.utils import re_issource |
| 363 | >>> src_match = re_issource.match('dist-upgrader_1.0.tar.gz') |
| 364 | >>> src_match.group(0) |
| 365 | 'dist-upgrader_1.0.tar.gz' |
| 366 | @@ -600,115 +449,6 @@ |
| 367 | ['File ed_0.2-20.dsc mentioned in the changes has a size mismatch. 578 != 500'] |
| 368 | |
| 369 | |
| 370 | -=== Format file type verification === |
| 371 | - |
| 372 | -DSCFile performs additional verification on the types of the referenced |
| 373 | -files, confirming that they are suitable for the source package's |
| 374 | -format. There is an error generator to verify each format. |
| 375 | - |
| 376 | - >>> from lp.archiveuploader.dscfile import (check_format_1_0_files, |
| 377 | - ... check_format_3_0_native_files, check_format_3_0_quilt_files) |
| 378 | - >>> from lp.registry.interfaces.sourcepackage import SourcePackageFileType |
| 379 | - |
| 380 | -==== 1.0 ==== |
| 381 | - |
| 382 | -A 1.0 source can contain either a tar.gz or an orig.tar.gz and diff.gz. |
| 383 | - |
| 384 | - >>> list(check_format_1_0_files('foo_1.dsc', { |
| 385 | - ... SourcePackageFileType.ORIG_TARBALL: 1, |
| 386 | - ... SourcePackageFileType.DIFF: 1, |
| 387 | - ... SourcePackageFileType.DEBIAN_TARBALL: 0, |
| 388 | - ... SourcePackageFileType.NATIVE_TARBALL: 0, |
| 389 | - ... }, {}, 0)) |
| 390 | - [] |
| 391 | - |
| 392 | - >>> list(check_format_1_0_files('foo_1.dsc', { |
| 393 | - ... SourcePackageFileType.NATIVE_TARBALL: 1, |
| 394 | - ... SourcePackageFileType.ORIG_TARBALL: 0, |
| 395 | - ... SourcePackageFileType.DIFF: 0, |
| 396 | - ... SourcePackageFileType.DEBIAN_TARBALL: 0, |
| 397 | - ... }, {}, 0)) |
| 398 | - [] |
| 399 | - |
| 400 | -But if we have some other combination, or bzip2 compression, errors |
| 401 | -will be generated. |
| 402 | - |
| 403 | - >>> list(check_format_1_0_files('foo_1.dsc', { |
| 404 | - ... SourcePackageFileType.NATIVE_TARBALL: 1, |
| 405 | - ... SourcePackageFileType.ORIG_TARBALL: 1, |
| 406 | - ... SourcePackageFileType.DIFF: 1, |
| 407 | - ... SourcePackageFileType.DEBIAN_TARBALL: 0, |
| 408 | - ... }, {}, 1)) |
| 409 | - [UploadError('foo_1.dsc: is format 1.0 but uses bzip2 compression.',), UploadError('foo_1.dsc: must have exactly one tar.gz, or an orig.tar.gz and diff.gz',)] |
| 410 | - |
| 411 | -The files are also bad if there are any components: |
| 412 | - |
| 413 | - >>> list(check_format_1_0_files('foo_1.dsc', { |
| 414 | - ... SourcePackageFileType.ORIG_TARBALL: 1, |
| 415 | - ... SourcePackageFileType.DIFF: 1, |
| 416 | - ... SourcePackageFileType.DEBIAN_TARBALL: 0, |
| 417 | - ... SourcePackageFileType.NATIVE_TARBALL: 0, |
| 418 | - ... }, {'foo': 1}, 0)) |
| 419 | - [UploadError('foo_1.dsc: must have exactly one tar.gz, or an orig.tar.gz and diff.gz',)] |
| 420 | - |
| 421 | -==== 3.0 (native) ==== |
| 422 | - |
| 423 | -A 3.0 (native) source must contain just a tar.(gz|bz2). |
| 424 | - |
| 425 | - >>> list(check_format_3_0_native_files('foo_1.dsc', { |
| 426 | - ... SourcePackageFileType.NATIVE_TARBALL: 1, |
| 427 | - ... SourcePackageFileType.ORIG_TARBALL: 0, |
| 428 | - ... SourcePackageFileType.DIFF: 0, |
| 429 | - ... SourcePackageFileType.DEBIAN_TARBALL: 0, |
| 430 | - ... }, {}, 1)) |
| 431 | - [] |
| 432 | - |
| 433 | - >>> list(check_format_3_0_native_files('foo_1.dsc', { |
| 434 | - ... SourcePackageFileType.NATIVE_TARBALL: 1, |
| 435 | - ... SourcePackageFileType.ORIG_TARBALL: 1, |
| 436 | - ... SourcePackageFileType.DIFF: 0, |
| 437 | - ... SourcePackageFileType.DEBIAN_TARBALL: 0, |
| 438 | - ... }, {}, 1)) |
| 439 | - [UploadError('foo_1.dsc: must have only a tar.*.',)] |
| 440 | - |
| 441 | - >>> list(check_format_3_0_native_files('foo_1.dsc', { |
| 442 | - ... SourcePackageFileType.NATIVE_TARBALL: 1, |
| 443 | - ... SourcePackageFileType.ORIG_TARBALL: 0, |
| 444 | - ... SourcePackageFileType.DIFF: 0, |
| 445 | - ... SourcePackageFileType.DEBIAN_TARBALL: 0, |
| 446 | - ... }, {'foo': 1}, 0)) |
| 447 | - [UploadError('foo_1.dsc: must have only a tar.*.',)] |
| 448 | - |
| 449 | -==== 3.0 (quilt) ==== |
| 450 | - |
| 451 | -A 3.0 (quilt) source must have an orig.tar.*, a debian.tar.*, and at |
| 452 | -most one orig-COMPONENT.tar.* for each COMPONENT. |
| 453 | - |
| 454 | - >>> list(check_format_3_0_quilt_files('foo_1.dsc', { |
| 455 | - ... SourcePackageFileType.ORIG_TARBALL: 1, |
| 456 | - ... SourcePackageFileType.DEBIAN_TARBALL: 1, |
| 457 | - ... SourcePackageFileType.NATIVE_TARBALL: 0, |
| 458 | - ... SourcePackageFileType.DIFF: 0, |
| 459 | - ... }, {'foo': 1}, 1)) |
| 460 | - [] |
| 461 | - |
| 462 | - >>> list(check_format_3_0_quilt_files('foo_1.dsc', { |
| 463 | - ... SourcePackageFileType.NATIVE_TARBALL: 1, |
| 464 | - ... SourcePackageFileType.ORIG_TARBALL: 1, |
| 465 | - ... SourcePackageFileType.DIFF: 0, |
| 466 | - ... SourcePackageFileType.DEBIAN_TARBALL: 1, |
| 467 | - ... }, {}, 1)) |
| 468 | - [UploadError('foo_1.dsc: must have only an orig.tar.*, a debian.tar.*, and optionally orig-*.tar.*',)] |
| 469 | - |
| 470 | - >>> list(check_format_3_0_quilt_files('foo_1.dsc', { |
| 471 | - ... SourcePackageFileType.ORIG_TARBALL: 1, |
| 472 | - ... SourcePackageFileType.DEBIAN_TARBALL: 1, |
| 473 | - ... SourcePackageFileType.NATIVE_TARBALL: 0, |
| 474 | - ... SourcePackageFileType.DIFF: 0, |
| 475 | - ... }, {'foo': 2}, 0)) |
| 476 | - [UploadError('foo_1.dsc: has more than one orig-foo.tar.*.',)] |
| 477 | - |
| 478 | - |
| 479 | === Sub-DSC files or DSCUploadedFiles === |
| 480 | |
| 481 | Sub-DSCFiles are DSCUploadedFile objects. |
| 482 | |
| 483 | === renamed file 'lib/lp/soyuz/doc/safe_fix_maintainer.txt' => 'lib/lp/archiveuploader/tests/safe_fix_maintainer.txt' |
| 484 | === modified file 'lib/lp/archiveuploader/tests/test_dscfile.py' |
| 485 | --- lib/lp/archiveuploader/tests/test_dscfile.py 2010-07-20 15:25:30 +0000 |
| 486 | +++ lib/lp/archiveuploader/tests/test_dscfile.py 2010-07-24 09:41:13 +0000 |
| 487 | @@ -7,16 +7,22 @@ |
| 488 | |
| 489 | import os |
| 490 | |
| 491 | -from canonical.config import config |
| 492 | from canonical.launchpad.scripts.logger import QuietFakeLogger |
| 493 | from canonical.testing.layers import LaunchpadZopelessLayer |
| 494 | from lp.archiveuploader.dscfile import ( |
| 495 | - DSCFile, findChangelog, findCopyright) |
| 496 | + DSCFile, findChangelog, findCopyright, format_to_file_checker_map) |
| 497 | from lp.archiveuploader.nascentuploadfile import UploadError |
| 498 | from lp.archiveuploader.tests import datadir, mock_logger_quiet |
| 499 | from lp.archiveuploader.uploadpolicy import BuildDaemonUploadPolicy |
| 500 | +from lp.registry.interfaces.sourcepackage import SourcePackageFileType |
| 501 | +from lp.soyuz.interfaces.sourcepackageformat import SourcePackageFormat |
| 502 | from lp.testing import TestCase, TestCaseWithFactory |
| 503 | |
| 504 | +ORIG_TARBALL = SourcePackageFileType.ORIG_TARBALL |
| 505 | +DEBIAN_TARBALL = SourcePackageFileType.DEBIAN_TARBALL |
| 506 | +NATIVE_TARBALL = SourcePackageFileType.NATIVE_TARBALL |
| 507 | +DIFF = SourcePackageFileType.DIFF |
| 508 | + |
| 509 | |
| 510 | class TestDscFile(TestCase): |
| 511 | |
| 512 | @@ -146,3 +152,132 @@ |
| 513 | dsc_file.cleanUp() |
| 514 | finally: |
| 515 | os.chmod(tempdir, 0755) |
| 516 | + |
| 517 | + |
| 518 | +class BaseTestSourceFileVerification(TestCase): |
| 519 | + |
| 520 | + def assertErrorsForFiles(self, expected, files, components={}, |
| 521 | + bzip2_count=0): |
| 522 | + """Check problems with the given set of files for the given format. |
| 523 | + |
| 524 | + :param expected: a list of expected errors, as strings. |
| 525 | + :param format: the `SourcePackageFormat` to check against. |
| 526 | + :param files: a dict mapping `SourcePackageFileType`s to counts. |
| 527 | + :param components: a dict mapping orig component tarball components |
| 528 | + to counts. |
| 529 | + :param bzip2_count: number of files using bzip2 compression. |
| 530 | + """ |
| 531 | + full_files = { |
| 532 | + NATIVE_TARBALL: 0, |
| 533 | + ORIG_TARBALL: 0, |
| 534 | + DIFF: 0, |
| 535 | + DEBIAN_TARBALL: 0, |
| 536 | + } |
| 537 | + full_files.update(files) |
| 538 | + self.assertEquals( |
| 539 | + expected, |
| 540 | + [str(e) for e in format_to_file_checker_map[self.format]( |
| 541 | + 'foo_1.dsc', full_files, components, bzip2_count)]) |
| 542 | + |
| 543 | + def assertFilesOK(self, files, components={}, bzip2_count=0): |
| 544 | + """Check that the given set of files is OK for the given format. |
| 545 | + |
| 546 | + :param format: the `SourcePackageFormat` to check against. |
| 547 | + :param files: a dict mapping `SourcePackageFileType`s to counts. |
| 548 | + :param components: a dict mapping orig component tarball components |
| 549 | + to counts. |
| 550 | + :param bzip2_count: number of files using bzip2 compression. |
| 551 | + """ |
| 552 | + self.assertErrorsForFiles([], files, components, bzip2_count) |
| 553 | + |
| 554 | + |
| 555 | +class Test10SourceFormatVerification(BaseTestSourceFileVerification): |
| 556 | + |
| 557 | + format = SourcePackageFormat.FORMAT_1_0 |
| 558 | + |
| 559 | + wrong_files_error = ('foo_1.dsc: must have exactly one tar.gz, or an ' |
| 560 | + 'orig.tar.gz and diff.gz') |
| 561 | + bzip2_error = 'foo_1.dsc: is format 1.0 but uses bzip2 compression.' |
| 562 | + |
| 563 | + def testFormat10Debian(self): |
| 564 | + # A 1.0 source can contain an original tarball and a Debian diff |
| 565 | + self.assertFilesOK({ORIG_TARBALL: 1, DIFF: 1}) |
| 566 | + |
| 567 | + def testFormat10Native(self): |
| 568 | + # A 1.0 source can contain a native tarball. |
| 569 | + self.assertFilesOK({NATIVE_TARBALL: 1}) |
| 570 | + |
| 571 | + def testFormat10CannotHaveWrongFiles(self): |
| 572 | + # A 1.0 source cannot have a combination of native and |
| 573 | + # non-native files, and cannot have just one of the non-native |
| 574 | + # files. |
| 575 | + for combination in ( |
| 576 | + {DIFF: 1}, {ORIG_TARBALL: 1}, {ORIG_TARBALL: 1, DIFF: 1, |
| 577 | + NATIVE_TARBALL: 1}): |
| 578 | + self.assertErrorsForFiles([self.wrong_files_error], combination) |
| 579 | + |
| 580 | + # A 1.0 source with component tarballs is invalid. |
| 581 | + self.assertErrorsForFiles( |
| 582 | + [self.wrong_files_error], {ORIG_TARBALL: 1, DIFF: 1}, {'foo': 1}) |
| 583 | + |
| 584 | + def testFormat10CannotUseBzip2(self): |
| 585 | + # 1.0 sources cannot use bzip2 compression. |
| 586 | + self.assertErrorsForFiles( |
| 587 | + [self.bzip2_error], {NATIVE_TARBALL: 1}, {}, 1) |
| 588 | + |
| 589 | + |
| 590 | +class Test30QuiltSourceFormatVerification(BaseTestSourceFileVerification): |
| 591 | + |
| 592 | + format = SourcePackageFormat.FORMAT_3_0_QUILT |
| 593 | + |
| 594 | + wrong_files_error = ('foo_1.dsc: must have only an orig.tar.*, a ' |
| 595 | + 'debian.tar.* and optionally orig-*.tar.*') |
| 596 | + comp_conflict_error = 'foo_1.dsc: has more than one orig-bar.tar.*.' |
| 597 | + |
| 598 | + def testFormat30Quilt(self): |
| 599 | + # A 3.0 (quilt) source must contain an orig tarball and a debian |
| 600 | + # tarball. It may also contain at most one component tarball for |
| 601 | + # each component, and can use gzip or bzip2 compression. |
| 602 | + for components in ({}, {'foo': 1}, {'foo': 1, 'bar': 1}): |
| 603 | + for bzip2_count in (0, 1): |
| 604 | + self.assertFilesOK( |
| 605 | + {ORIG_TARBALL: 1, DEBIAN_TARBALL: 1}, components, |
| 606 | + bzip2_count) |
| 607 | + |
| 608 | + def testFormat30QuiltCannotHaveConflictingComponentTarballs(self): |
| 609 | + # Multiple conflicting tarballs for a single component are |
| 610 | + # invalid. |
| 611 | + self.assertErrorsForFiles( |
| 612 | + [self.comp_conflict_error], |
| 613 | + {ORIG_TARBALL: 1, DEBIAN_TARBALL: 1}, {'foo': 1, 'bar': 2}) |
| 614 | + |
| 615 | + def testFormat30QuiltCannotHaveWrongFiles(self): |
| 616 | + # 3.0 (quilt) sources may not have a diff or native tarball. |
| 617 | + for filetype in (DIFF, NATIVE_TARBALL): |
| 618 | + self.assertErrorsForFiles( |
| 619 | + [self.wrong_files_error], |
| 620 | + {ORIG_TARBALL: 1, DEBIAN_TARBALL: 1, filetype: 1}) |
| 621 | + |
| 622 | + |
| 623 | +class Test30QuiltSourceFormatVerification(BaseTestSourceFileVerification): |
| 624 | + |
| 625 | + format = SourcePackageFormat.FORMAT_3_0_NATIVE |
| 626 | + |
| 627 | + wrong_files_error = 'foo_1.dsc: must have only a tar.*.' |
| 628 | + |
| 629 | + def testFormat30Native(self): |
| 630 | + # 3.0 (native) sources must contain just a native tarball. They |
| 631 | + # may use gzip or bzip2 compression. |
| 632 | + for bzip2_count in (0, 1): |
| 633 | + self.assertFilesOK({NATIVE_TARBALL: 1}, {}, |
| 634 | + bzip2_count) |
| 635 | + |
| 636 | + def testFormat30NativeCannotHaveWrongFiles(self): |
| 637 | + # 3.0 (quilt) sources may not have a diff, Debian tarball, orig |
| 638 | + # tarball, or any component tarballs. |
| 639 | + for filetype in (DIFF, DEBIAN_TARBALL, ORIG_TARBALL): |
| 640 | + self.assertErrorsForFiles( |
| 641 | + [self.wrong_files_error], {NATIVE_TARBALL: 1, filetype: 1}) |
| 642 | + # A 3.0 (native) source with component tarballs is invalid. |
| 643 | + self.assertErrorsForFiles( |
| 644 | + [self.wrong_files_error], {NATIVE_TARBALL: 1}, {'foo': 1}) |
| 645 | |
| 646 | === modified file 'lib/lp/archiveuploader/tests/test_utils.py' |
| 647 | --- lib/lp/archiveuploader/tests/test_utils.py 2010-07-18 00:26:33 +0000 |
| 648 | +++ lib/lp/archiveuploader/tests/test_utils.py 2010-07-24 09:41:13 +0000 |
| 649 | @@ -5,23 +5,19 @@ |
| 650 | |
| 651 | # arch-tag: 90e6eb79-83a2-47e8-9f8b-3c687079c923 |
| 652 | |
| 653 | -import unittest |
| 654 | -import sys |
| 655 | +from testtools import TestCase |
| 656 | |
| 657 | from lp.registry.interfaces.sourcepackage import SourcePackageFileType |
| 658 | from lp.soyuz.interfaces.binarypackagerelease import BinaryPackageFileType |
| 659 | from lp.archiveuploader.tests import datadir |
| 660 | - |
| 661 | - |
| 662 | -class TestUtilities(unittest.TestCase): |
| 663 | - |
| 664 | - def testImport(self): |
| 665 | - """lp.archiveuploader.utils should be importable""" |
| 666 | - import lp.archiveuploader.utils |
| 667 | +from lp.archiveuploader.utils import (determine_binary_file_type, |
| 668 | + determine_source_file_type, re_isadeb, re_issource) |
| 669 | + |
| 670 | + |
| 671 | +class TestUtilities(TestCase): |
| 672 | |
| 673 | def test_determine_source_file_type(self): |
| 674 | """lp.archiveuploader.utils.determine_source_file_type should work.""" |
| 675 | - from lp.archiveuploader.utils import determine_source_file_type |
| 676 | |
| 677 | # .dsc -> DSC |
| 678 | self.assertEquals( |
| 679 | @@ -74,8 +70,6 @@ |
| 680 | |
| 681 | def test_determine_binary_file_type(self): |
| 682 | """lp.archiveuploader.utils.determine_binary_file_type should work.""" |
| 683 | - from lp.archiveuploader.utils import determine_binary_file_type |
| 684 | - |
| 685 | # .deb -> DEB |
| 686 | self.assertEquals( |
| 687 | determine_binary_file_type('foo_1.0-1_all.deb'), |
| 688 | @@ -222,20 +216,43 @@ |
| 689 | pass |
| 690 | |
| 691 | |
| 692 | -def test_suite(): |
| 693 | - suite = unittest.TestSuite() |
| 694 | - loader = unittest.TestLoader() |
| 695 | - suite.addTest(loader.loadTestsFromTestCase(TestUtilities)) |
| 696 | - return suite |
| 697 | - |
| 698 | - |
| 699 | -def main(argv): |
| 700 | - suite = test_suite() |
| 701 | - runner = unittest.TextTestRunner(verbosity = 2) |
| 702 | - if not runner.run(suite).wasSuccessful(): |
| 703 | - return 1 |
| 704 | - return 0 |
| 705 | - |
| 706 | - |
| 707 | -if __name__ == '__main__': |
| 708 | - sys.exit(main(sys.argv)) |
| 709 | +class TestFilenameRegularExpressions(TestCase): |
| 710 | + |
| 711 | + def test_re_isadeb(self): |
| 712 | + # Verify that the three binary extensions match the regexp. |
| 713 | + for extension in ('deb', 'ddeb', 'udeb'): |
| 714 | + self.assertEquals( |
| 715 | + ('foo-bar', '1.0', 'i386', extension), |
| 716 | + re_isadeb.match('foo-bar_1.0_i386.%s' % extension).groups()) |
| 717 | + |
| 718 | + # Some other extension doesn't match. |
| 719 | + self.assertIs(None, re_isadeb.match('foo-bar_1.0_i386.notdeb')) |
| 720 | + |
| 721 | + # A missing architecture also doesn't match. |
| 722 | + self.assertIs(None, re_isadeb.match('foo-bar_1.0.deb')) |
| 723 | + |
| 724 | + def test_re_issource(self): |
| 725 | + # Verify that various source extensions match the regexp. |
| 726 | + extensions = ( |
| 727 | + 'dsc', 'tar.gz', 'tar.bz2', 'diff.gz', 'orig.tar.gz', |
| 728 | + 'orig.tar.bz2', 'orig-bar.tar.gz', 'orig-bar.tar.bz2', |
| 729 | + 'debian.tar.gz', 'debian.tar.bz2') |
| 730 | + for extension in extensions: |
| 731 | + self.assertEquals( |
| 732 | + ('foo-bar', '1.0', extension), |
| 733 | + re_issource.match('foo-bar_1.0.%s' % extension).groups()) |
| 734 | + |
| 735 | + # While orig-*.tar.gz is all interpreted as extension, *orig-*.tar.gz |
| 736 | + # is taken to have an extension of just 'tar.gz'. |
| 737 | + self.assertEquals( |
| 738 | + ('foo-bar', '1.0.porig-bar', 'tar.gz'), |
| 739 | + re_issource.match('foo-bar_1.0.porig-bar.tar.gz').groups()) |
| 740 | + |
| 741 | + # Some other extension doesn't match. |
| 742 | + self.assertIs(None, re_issource.match('foo-bar_1.0.notdsc')) |
| 743 | + |
| 744 | + # A badly formatted name also doesn't match. |
| 745 | + self.assertIs(None, re_issource.match('foo-bar.dsc')) |
| 746 | + |
| 747 | + # bzip2 compression for files which must be gzipped is invalid. |
| 748 | + self.assertIs(None, re_issource.match('foo-bar_1.0.diff.bz2')) |
| 749 | |
| 750 | === renamed file 'lib/lp/soyuz/doc/uploadpolicy.txt' => 'lib/lp/archiveuploader/tests/uploadpolicy.txt' |
| 751 | === modified file 'lib/lp/soyuz/tests/test_doc.py' |
| 752 | --- lib/lp/soyuz/tests/test_doc.py 2010-04-30 09:49:59 +0000 |
| 753 | +++ lib/lp/soyuz/tests/test_doc.py 2010-07-24 09:41:13 +0000 |
| 754 | @@ -123,11 +123,6 @@ |
| 755 | |
| 756 | |
| 757 | special = { |
| 758 | - 'nascentupload.txt': LayeredDocFileSuite( |
| 759 | - '../doc/nascentupload.txt', |
| 760 | - setUp=uploaderSetUp, tearDown=uploaderTearDown, |
| 761 | - layer=LaunchpadZopelessLayer, |
| 762 | - ), |
| 763 | 'build-notification.txt': LayeredDocFileSuite( |
| 764 | '../doc/build-notification.txt', |
| 765 | setUp=builddmasterSetUp, |

Thanks. You might like to start using testscenarios for the permutations rather than looping - its easier to debug failures that way.