From 657f74c56548f6745657012c08380aad770b443f Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Tue, 24 Jun 2014 09:48:12 +0200 Subject: [PATCH 1/7] Detect when there is only one repo as a candidate. --- osc-check_repo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osc-check_repo.py b/osc-check_repo.py index 7d11c966..ece89af5 100644 --- a/osc-check_repo.py +++ b/osc-check_repo.py @@ -324,8 +324,9 @@ def _check_repo_group(self, id_, requests, opts): execution_plan[_repo].append((rq, _repo, rq.downloads[_repo])) else: _other_repo = [r for r in rq.downloads if r != _repo] - _other_repo = _other_repo[0] # XXX TODO - Recurse here to create combinations - execution_plan[_repo].append((rq, _other_repo, rq.downloads[_other_repo])) + if _other_repo: + _other_repo = _other_repo[0] # XXX TODO - Recurse here to create combinations + execution_plan[_repo].append((rq, _other_repo, rq.downloads[_other_repo])) repo_checker_error = '' for _repo, dirstolink in execution_plan.items(): From 46c5c5c00165efbc718b23664471ea7e7f9a35ad Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Tue, 24 Jun 2014 14:11:06 +0200 Subject: [PATCH 2/7] Initial tests for checkrepo. --- tests/checkrepo_tests.py | 55 +++++++++++++++++ tests/fixtures/request/1000 | 1 + tests/fixtures/request/1001 | 1 + .../source/openSUSE:Factory:Staging:J/_meta | 1 + .../openSUSE:Factory:Staging:J/_project | 1 + .../source/openSUSE:Factory:Staging:J/emacs | 1 + .../source/openSUSE:Factory:Staging:J/python | 1 + tests/obs.py | 59 ++++++++++++++++--- 8 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 tests/checkrepo_tests.py create mode 120000 tests/fixtures/request/1000 create mode 120000 tests/fixtures/request/1001 create mode 120000 tests/fixtures/source/openSUSE:Factory:Staging:J/_meta create mode 120000 tests/fixtures/source/openSUSE:Factory:Staging:J/_project create mode 120000 tests/fixtures/source/openSUSE:Factory:Staging:J/emacs create mode 120000 tests/fixtures/source/openSUSE:Factory:Staging:J/python diff --git a/tests/checkrepo_tests.py b/tests/checkrepo_tests.py new file mode 100644 index 00000000..9881f9c6 --- /dev/null +++ b/tests/checkrepo_tests.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 SUSE Linux Products GmbH +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import unittest + +from obs import APIURL +from obs import OBS +from osclib.checkrepo import CheckRepo + + +class TestCheckRepoCalls(unittest.TestCase): + """Tests for various check repo calls.""" + + def setUp(self): + """Initialize the configuration.""" + + self.obs = OBS() + self.checkrepo = CheckRepo(APIURL) + + def test_packages_grouping(self): + """Validate the creation of the groups.""" + grouped = { + 1000: 'openSUSE:Factory:Staging:J', + 1001: 'openSUSE:Factory:Staging:J', + 501: 'openSUSE:Factory:Staging:C', + 502: 'openSUSE:Factory:Staging:C', + 333: 'openSUSE:Factory:Staging:B' + } + groups = { + 'openSUSE:Factory:Staging:J': [1000, 1001], + 'openSUSE:Factory:Staging:C': [501, 502], + 'openSUSE:Factory:Staging:B': [333] + } + self.assertEqual(self.checkrepo.grouped, grouped) + self.assertEqual(self.checkrepo.groups, groups) + + def test_pending_request(self): + """Test CheckRepo.get_request.""" + self.assertEqual(len(self.checkrepo.pending_requests()), 2) diff --git a/tests/fixtures/request/1000 b/tests/fixtures/request/1000 new file mode 120000 index 00000000..a69ada53 --- /dev/null +++ b/tests/fixtures/request/1000 @@ -0,0 +1 @@ +template_request.xml \ No newline at end of file diff --git a/tests/fixtures/request/1001 b/tests/fixtures/request/1001 new file mode 120000 index 00000000..a69ada53 --- /dev/null +++ b/tests/fixtures/request/1001 @@ -0,0 +1 @@ +template_request.xml \ No newline at end of file diff --git a/tests/fixtures/source/openSUSE:Factory:Staging:J/_meta b/tests/fixtures/source/openSUSE:Factory:Staging:J/_meta new file mode 120000 index 00000000..c7cbea64 --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory:Staging:J/_meta @@ -0,0 +1 @@ +../openSUSE:Factory:Staging:A/_meta \ No newline at end of file diff --git a/tests/fixtures/source/openSUSE:Factory:Staging:J/_project b/tests/fixtures/source/openSUSE:Factory:Staging:J/_project new file mode 120000 index 00000000..d9212163 --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory:Staging:J/_project @@ -0,0 +1 @@ +../openSUSE:Factory:Staging:A/_project \ No newline at end of file diff --git a/tests/fixtures/source/openSUSE:Factory:Staging:J/emacs b/tests/fixtures/source/openSUSE:Factory:Staging:J/emacs new file mode 120000 index 00000000..69ceb52d --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory:Staging:J/emacs @@ -0,0 +1 @@ +../linksource.xml \ No newline at end of file diff --git a/tests/fixtures/source/openSUSE:Factory:Staging:J/python b/tests/fixtures/source/openSUSE:Factory:Staging:J/python new file mode 120000 index 00000000..69ceb52d --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory:Staging:J/python @@ -0,0 +1 @@ +../linksource.xml \ No newline at end of file diff --git a/tests/obs.py b/tests/obs.py index c81d1bb6..46a06f31 100644 --- a/tests/obs.py +++ b/tests/obs.py @@ -159,6 +159,24 @@ class OBS(object): 'by_who': 'openSUSE:Factory:Staging:C', 'package': 'mariadb', }, + '1000': { + 'request': 'review', + 'review': 'new', + 'who': 'Admin', + 'by': 'user', + 'id': '1000', + 'by_who': 'factory-repo-checker', + 'package': 'emacs', + }, + '1001': { + 'request': 'review', + 'review': 'new', + 'who': 'Admin', + 'by': 'user', + 'id': '1001', + 'by_who': 'factory-repo-checker', + 'package': 'python', + }, } self.staging_project = { @@ -180,8 +198,14 @@ class OBS(object): 'C': { 'project': 'openSUSE:Factory:Staging:C', 'title': 'A project ready to be accepted', - 'description': ("requests:\n - {id: 501, package: apparmor, author: Admin}\n" - " - {id: 502, package: mariadb, author: Admin}"), + 'description': ('requests:\n - {id: 501, package: apparmor, author: Admin}\n' + ' - {id: 502, package: mariadb, author: Admin}'), + }, + 'J': { + 'project': 'openSUSE:Factory:Staging:J', + 'title': 'A project to be checked', + 'description': ('requests:\n- {id: 1000, package: emacs, author: Admin}\n' + '- {id: 1001, package: python, author: Admin}'), }, } @@ -201,6 +225,16 @@ class OBS(object): 'pkg': 'mariadb', 'devprj': 'home:Admin', }, + 'openSUSE:Factory:Staging:J/emacs': { + 'prj': 'openSUSE:Factory:Staging:J', + 'pkg': 'emacs', + 'devprj': 'editors', + }, + 'openSUSE:Factory:Staging:J/python': { + 'prj': 'openSUSE:Factory:Staging:J', + 'pkg': 'python', + 'devprj': 'devel:languages:python:Factory', + }, } self.meta = {} @@ -295,6 +329,7 @@ class OBS(object): " * Request#502 for package mariadb submitted by Admin\n") } ], + 'openSUSE:Factory:Staging:J': [], } # To track comments created during test execution, even if they have @@ -397,7 +432,7 @@ class OBS(object): # /source/ # - @GET(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C]/_project')) + @GET(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|J]/_project')) def source_staging_project_project(self, request, uri, headers): """Return the _project information for a staging project.""" # Load the proper fixture and adjust mtime according the @@ -419,7 +454,7 @@ class OBS(object): return response - @GET(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|U](/\w+)?/_meta')) + @GET(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|U|J](/\w+)?/_meta')) def source_staging_project_meta(self, request, uri, headers): """Return the _meta information for a staging project.""" key = re.search(r'openSUSE:Factory:Staging:(\w(?:/\w+)?)/_meta', uri).group(1) @@ -441,7 +476,7 @@ class OBS(object): return response - @PUT(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|U](/\w+)?/_meta')) + @PUT(re.compile(r'/source/openSUSE:Factory:Staging:[A|B|C|U|J](/\w+)?/_meta')) def put_source_staging_project_meta(self, request, uri, headers): """Set the _meta information for a staging project.""" key = re.search(r'openSUSE:Factory:Staging:(\w(?:/\w+)?)/_meta', uri).group(1) @@ -590,15 +625,21 @@ class OBS(object): def search_request(self, request, uri, headers): """Return a search result for /search/request.""" query = urlparse.urlparse(uri).query - assert query == "match=state/@name='review'+and+review[@by_group='factory-staging'+and+@state='new']" + assert query in ( + "match=state/@name='review'+and+review[@by_group='factory-staging'+and+@state='new']", + "match=state/@name='review'+and+review[@by_user='factory-repo-checker'+and+@state='new']" + ) response = (404, headers, 'Not found') + by, by_who = re.search(r"@by_(user|group)='([-\w]+)'", query).groups() + state = re.search(r"@state='(\w+)'", query).group(1) + requests = [rq for rq in self.requests.values() if rq['request'] == 'review' - and rq['review'] == 'new' - and rq['by'] == 'group' - and rq['by_who'] == 'factory-staging'] + and rq['review'] == state + and rq['by'] == by + and rq['by_who'] == by_who] try: _requests = '\n'.join(self._request(rq['id']) for rq in requests) From 53d7614f973aa49ccd6d839ce1d24adf2aabce27 Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Tue, 24 Jun 2014 14:28:57 +0200 Subject: [PATCH 3/7] Fix description. --- tests/obs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/obs.py b/tests/obs.py index 46a06f31..7465cceb 100644 --- a/tests/obs.py +++ b/tests/obs.py @@ -198,8 +198,8 @@ class OBS(object): 'C': { 'project': 'openSUSE:Factory:Staging:C', 'title': 'A project ready to be accepted', - 'description': ('requests:\n - {id: 501, package: apparmor, author: Admin}\n' - ' - {id: 502, package: mariadb, author: Admin}'), + 'description': ('requests:\n- {id: 501, package: apparmor, author: Admin}\n' + '- {id: 502, package: mariadb, author: Admin}'), }, 'J': { 'project': 'openSUSE:Factory:Staging:J', From c206367acbea187cdf71876d5380e963378535be Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Wed, 25 Jun 2014 10:42:31 +0200 Subject: [PATCH 4/7] Initial steps to detect valid packages in the cache. --- osc-check_repo.py | 39 ++------------- osclib/checkrepo.py | 113 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 97 insertions(+), 55 deletions(-) diff --git a/osc-check_repo.py b/osc-check_repo.py index ece89af5..24d37723 100644 --- a/osc-check_repo.py +++ b/osc-check_repo.py @@ -29,15 +29,11 @@ from osc.core import Request # Expand sys.path to search modules inside the pluging directory _plugin_dir = os.path.expanduser('~/.osc-plugins') sys.path.append(_plugin_dir) -from osclib.checkrepo import CheckRepo +from osclib.checkrepo import CheckRepo, DOWNLOADS from osclib.cycle import CycleDetector from osclib.memoize import CACHEDIR -# Directory where download binary packages. -DOWNLOADS = os.path.expanduser('~/co/downloads') - - def _check_repo_find_submit_request(self, opts, project, package): xpath = "(action/target/@project='%s' and "\ "action/target/@package='%s' and "\ @@ -94,48 +90,19 @@ def _check_repo_get_binary(self, apiurl, prj, repo, arch, package, file, target, get_binary_file(apiurl, prj, repo, arch, file, package=package, target_filename=target) -def _get_verifymd5(self, request, rev): - try: - url = makeurl(self.get_api_url(), ['source', request.src_project, request.src_package, '?view=info&rev=%s' % rev]) - root = ET.parse(http_GET(url)).getroot() - except urllib2.HTTPError, e: - print 'ERROR in URL %s [%s]' % (url, e) - return [] - return root.attrib['verifymd5'] - - -def _checker_compare_disturl(self, disturl, request): - distmd5 = os.path.basename(disturl).split('-')[0] - if distmd5 == request.srcmd5: - return True - - vrev1 = self._get_verifymd5(request, request.srcmd5) - vrev2 = self._get_verifymd5(request, distmd5) - if vrev1 == vrev2: - return True - print 'ERROR Revision missmatch: %s, %s' % (vrev1, vrev2) - return False - - def _download_and_check_disturl(self, request, todownload, opts): for _project, _repo, arch, fn, mt in todownload: repodir = os.path.join(DOWNLOADS, request.src_package, _project, _repo) if not os.path.exists(repodir): os.makedirs(repodir) t = os.path.join(repodir, fn) - # print 'Downloading ...', _project, _repo, arch, request.src_package, fn, t, mt self._check_repo_get_binary(opts.apiurl, _project, _repo, arch, request.src_package, fn, t, mt) request.downloads[_repo].append(t) if fn.endswith('.rpm'): - pid = subprocess.Popen(['rpm', '--nosignature', '--queryformat', '%{DISTURL}', '-qp', t], - stdout=subprocess.PIPE, close_fds=True) - os.waitpid(pid.pid, 0)[1] - disturl = pid.stdout.readlines()[0] - - if not self._checker_compare_disturl(disturl, request): - request.error = '[%s] %s does not match revision %s' % (request, disturl, request.srcmd5) + if not self.checkrepo.check_disturl(request, t): + request.error = '[#%s] DISTURL does not match revision %s' % (request.request_id, request.srcmd5) def _check_repo_download(self, request, opts): diff --git a/osclib/checkrepo.py b/osclib/checkrepo.py index 144e60c7..da2d05a8 100644 --- a/osclib/checkrepo.py +++ b/osclib/checkrepo.py @@ -14,6 +14,8 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +import os +import subprocess from urllib import quote_plus import urllib2 from xml.etree import cElementTree as ET @@ -25,6 +27,10 @@ from osclib.stagingapi import StagingAPI from osclib.memoize import memoize +# Directory where download binary packages. +DOWNLOADS = os.path.expanduser('~/co/downloads') + + class Request(object): """Simple request container.""" @@ -70,11 +76,11 @@ class Request(object): self.missings = [] def __repr__(self): - return 'SUBMIT(%s) %s/%s -> %s/%s' % (self.request_id, - self.src_project, - self.src_package, - self.tgt_project, - self.tgt_package) + return '#%s %s/%s -> %s/%s' % (self.request_id, + self.src_project, + self.src_package, + self.tgt_project, + self.tgt_package) class CheckRepo(object): @@ -120,7 +126,7 @@ class CheckRepo(object): } code = 404 - url = makeurl(self.apiurl, ['request', str(request_id)], query=query) + url = makeurl(self.apiurl, ('request', str(request_id)), query=query) try: root = ET.parse(http_POST(url, data=message)).getroot() code = root.attrib['code'] @@ -152,7 +158,7 @@ class CheckRepo(object): return requests @memoize() - def build(self, repository, project, package, arch): + def build(self, project, repository, arch, package): """Return the build XML document from OBS.""" xml = '' try: @@ -287,9 +293,13 @@ class CheckRepo(object): # Get source information about the SR: # - Source MD5 # - Entries (.tar.gz, .changes, .spec ...) and MD5 + query = { + 'rev': rq.revision, + 'expand': 1 + } try: url = makeurl(self.apiurl, ['source', rq.src_project, rq.src_package], - {'rev': rq.revision, 'expand': 1}) + query=query) root = ET.parse(http_GET(url)).getroot() except urllib2.HTTPError, e: print 'ERROR in URL %s [%s]' % (url, e) @@ -323,8 +333,12 @@ class CheckRepo(object): # - with the name of the .spec file. for spec in specs: - spec_info = self.staging.get_package_information(rq.src_project, - spec) + try: + spec_info = self.staging.get_package_information(rq.src_project, + spec) + except urllib2.HTTPError as e: + print "Can't gather package information for (%s, %s)" % (rq.src_project, spec) + rq.updated = True if (spec_info['project'] != rq.src_project or spec_info['package'] != rq.src_package) and not rq.updated: @@ -384,15 +398,71 @@ class CheckRepo(object): return repos_to_check - def is_binary(self, repository, project, package, arch): + def is_binary(self, project, repository, arch, package): """Return True if is a binary package.""" - root_xml = self.build(repository, project, package, arch) + root_xml = self.build(project, repository, arch, package) root = ET.fromstring(root_xml) for binary in root.findall('binary'): # If there are binaries, we're out. return False return True + def _disturl(self, filename): + """Get the DISTURL from a RPM file.""" + pid = subprocess.Popen(('rpm', '--nosignature', '--queryformat', '%{DISTURL}', '-qp', filename), + stdout=subprocess.PIPE, close_fds=True) + os.waitpid(pid.pid, 0)[1] + disturl = pid.stdout.readlines()[0] + return disturl + return os.path.basename(disturl).split('-')[0] + + def _md5_disturl(self, disturl): + """Get the md5 from the DISTURL from a RPM file.""" + return os.path.basename(disturl).split('-')[0] + + def _get_verifymd5(self, request, revision): + """Return the verifymd5 attribute from a request.""" + query = { + 'view': 'info', + 'rev': revision, + } + try: + url = makeurl(self.apiurl, ('source', request.src_project, request.src_package), + query=query) + root = ET.parse(http_GET(url)).getroot() + except urllib2.HTTPError, e: + print 'ERROR in URL %s [%s]' % (url, e) + return [] + return root.attrib['verifymd5'] + + def check_disturl(self, request, filename): + """Try to match the srcmd5 of a request with the one in the RPM package.""" + disturl = self._disturl(filename) + md5_disturl = self._md5_disturl(disturl) + + if md5_disturl == request.srcmd5: + return True + + vrev1 = self._get_verifymd5(request, request.srcmd5) + vrev2 = self._get_verifymd5(request, md5_disturl) + if vrev1 == vrev2: + return True + + return False + + def is_request_cached(self, request): + """Search the request in the local cache.""" + result = False + + package_dir = os.path.join(DOWNLOADS, request.src_package) + rpm_packages = [] + for dirpath, dirnames, filenames in os.walk(package_dir): + rpm_packages.extend(os.path.join(dirpath, f) for f in filenames if f.endswith('.rpm')) + + result = any(self.check_disturl(request, rpm) for rpm in rpm_packages) + + return result + def is_buildsuccess(self, request): """Return True if the request is correctly build @@ -433,10 +503,10 @@ class CheckRepo(object): if 'missing' in arch.attrib: for package in arch.attrib['missing'].split(','): if not self.is_binary( - repository.attrib['name'], request.src_project, - package, - arch.attrib['arch']): + repository.attrib['name'], + arch.attrib['arch'], + package): missings[package] = 1 if arch.attrib['result'] not in ('succeeded', 'excluded'): isgood = False @@ -484,13 +554,18 @@ class CheckRepo(object): # Next line not needed, but for documentation request.updated = True return False + if foundbuilding: msg = '%s is still building for repository %s' % (request.src_package, foundbuilding) print msg - self.change_review_state(request.request_id, 'new', message=msg) - # Next line not needed, but for documentation - request.updated = True - return False + if self.is_request_cached(request): + print 'Found cached version.' + else: + self.change_review_state(request.request_id, 'new', message=msg) + # Next line not needed, but for documentation + request.updated = True + return False + if foundfailed: msg = '%s failed to build in repository %s - not accepting' % (request.src_package, foundfailed) # failures might be temporary, so don't autoreject but wait for a human to check From c593116f2a54d703ecaf8d187cb93a080be3bd10 Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Wed, 25 Jun 2014 11:59:07 +0200 Subject: [PATCH 5/7] Remove the print in check_specs. --- osc-check_repo.py | 14 ++++++++++++-- osclib/checkrepo.py | 1 - 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/osc-check_repo.py b/osc-check_repo.py index 24d37723..2372d0ee 100644 --- a/osc-check_repo.py +++ b/osc-check_repo.py @@ -370,6 +370,12 @@ def mirror_full(plugin_dir, repo_dir): os.system(script) +def _print_request_and_specs(self, request_and_specs): + print request_and_specs[0] + for spec in request_and_specs[1:]: + print ' * ', spec + + @cmdln.alias('check', 'cr') @cmdln.option('-s', '--skip', action='store_true', help='skip review') def do_check_repo(self, subcmd, opts, *args): @@ -410,11 +416,15 @@ def do_check_repo(self, subcmd, opts, *args): if not ids: # Return a list, we flat here with .extend() for request in self.checkrepo.pending_requests(): - requests.extend(self.checkrepo.check_specs(request=request)) + request_and_specs = self.checkrepo.check_specs(request=request) + self._print_request_and_specs(request_and_specs) + requests.extend(request_and_specs) else: # We have a list, use them. for request_id in ids: - requests.extend(self.checkrepo.check_specs(request_id=request_id)) + request_and_specs = self.checkrepo.check_specs(request_id=request_id) + self._print_request_and_specs(request_and_specs) + requests.extend(request_and_specs) # Order the packs before grouping requests = sorted(requests, key=lambda p: p.request_id, reverse=True) diff --git a/osclib/checkrepo.py b/osclib/checkrepo.py index da2d05a8..0725dac9 100644 --- a/osclib/checkrepo.py +++ b/osclib/checkrepo.py @@ -286,7 +286,6 @@ class CheckRepo(object): return requests rq = Request(element=request) - print rq rq.group = self.grouped.get(request_id, request_id) requests.append(rq) From b297237a79a8ce0501447694f55776c500111596 Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Wed, 25 Jun 2014 12:55:07 +0200 Subject: [PATCH 6/7] Fix a missing continue. --- osclib/checkrepo.py | 1 + 1 file changed, 1 insertion(+) diff --git a/osclib/checkrepo.py b/osclib/checkrepo.py index 0725dac9..93eebece 100644 --- a/osclib/checkrepo.py +++ b/osclib/checkrepo.py @@ -338,6 +338,7 @@ class CheckRepo(object): except urllib2.HTTPError as e: print "Can't gather package information for (%s, %s)" % (rq.src_project, spec) rq.updated = True + continue if (spec_info['project'] != rq.src_project or spec_info['package'] != rq.src_package) and not rq.updated: From ccfb48511e4a74d4974a051db59880083e0fc211 Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Wed, 25 Jun 2014 14:17:52 +0200 Subject: [PATCH 7/7] Add initial test for check_specs. --- tests/checkrepo_tests.py | 11 +++++++++++ tests/fixtures/source/home:Admin/apparmor | 2 +- tests/fixtures/source/home:Admin/emacs | 1 + tests/fixtures/source/home:Admin/gcc | 2 +- tests/fixtures/source/home:Admin/mariadb | 2 +- tests/fixtures/source/home:Admin/puppet | 2 +- tests/fixtures/source/home:Admin/python | 1 + tests/fixtures/source/home:Admin/source.xml | 1 + .../source/home:Admin/source_expanded.xml | 4 ++++ tests/fixtures/source/home:Admin/wine | 2 +- tests/obs.py | 18 +++++++++++++++--- 11 files changed, 38 insertions(+), 8 deletions(-) create mode 120000 tests/fixtures/source/home:Admin/emacs create mode 120000 tests/fixtures/source/home:Admin/python create mode 100644 tests/fixtures/source/home:Admin/source.xml create mode 100644 tests/fixtures/source/home:Admin/source_expanded.xml mode change 100644 => 120000 tests/fixtures/source/home:Admin/wine diff --git a/tests/checkrepo_tests.py b/tests/checkrepo_tests.py index 9881f9c6..00c03cc8 100644 --- a/tests/checkrepo_tests.py +++ b/tests/checkrepo_tests.py @@ -53,3 +53,14 @@ class TestCheckRepoCalls(unittest.TestCase): def test_pending_request(self): """Test CheckRepo.get_request.""" self.assertEqual(len(self.checkrepo.pending_requests()), 2) + + def test_check_specs(self): + """Test CheckRepo.check_specs.""" + for request in self.checkrepo.pending_requests(): + request_and_specs = self.checkrepo.check_specs(request=request) + self.assertEqual(len(request_and_specs), 1) + self.assertTrue(request_and_specs[0].request_id in (1000, 1001)) + for request_id in (1000, 1001): + request_and_specs = self.checkrepo.check_specs(request_id=request_id) + self.assertEqual(len(request_and_specs), 1) + self.assertEqual(request_and_specs[0].request_id, request_id) diff --git a/tests/fixtures/source/home:Admin/apparmor b/tests/fixtures/source/home:Admin/apparmor index bd42d64f..dcac5227 120000 --- a/tests/fixtures/source/home:Admin/apparmor +++ b/tests/fixtures/source/home:Admin/apparmor @@ -1 +1 @@ -wine \ No newline at end of file +source.xml \ No newline at end of file diff --git a/tests/fixtures/source/home:Admin/emacs b/tests/fixtures/source/home:Admin/emacs new file mode 120000 index 00000000..8017ca6f --- /dev/null +++ b/tests/fixtures/source/home:Admin/emacs @@ -0,0 +1 @@ +source_expanded.xml \ No newline at end of file diff --git a/tests/fixtures/source/home:Admin/gcc b/tests/fixtures/source/home:Admin/gcc index bd42d64f..dcac5227 120000 --- a/tests/fixtures/source/home:Admin/gcc +++ b/tests/fixtures/source/home:Admin/gcc @@ -1 +1 @@ -wine \ No newline at end of file +source.xml \ No newline at end of file diff --git a/tests/fixtures/source/home:Admin/mariadb b/tests/fixtures/source/home:Admin/mariadb index bd42d64f..dcac5227 120000 --- a/tests/fixtures/source/home:Admin/mariadb +++ b/tests/fixtures/source/home:Admin/mariadb @@ -1 +1 @@ -wine \ No newline at end of file +source.xml \ No newline at end of file diff --git a/tests/fixtures/source/home:Admin/puppet b/tests/fixtures/source/home:Admin/puppet index bd42d64f..dcac5227 120000 --- a/tests/fixtures/source/home:Admin/puppet +++ b/tests/fixtures/source/home:Admin/puppet @@ -1 +1 @@ -wine \ No newline at end of file +source.xml \ No newline at end of file diff --git a/tests/fixtures/source/home:Admin/python b/tests/fixtures/source/home:Admin/python new file mode 120000 index 00000000..8017ca6f --- /dev/null +++ b/tests/fixtures/source/home:Admin/python @@ -0,0 +1 @@ +source_expanded.xml \ No newline at end of file diff --git a/tests/fixtures/source/home:Admin/source.xml b/tests/fixtures/source/home:Admin/source.xml new file mode 100644 index 00000000..4439fb15 --- /dev/null +++ b/tests/fixtures/source/home:Admin/source.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/fixtures/source/home:Admin/source_expanded.xml b/tests/fixtures/source/home:Admin/source_expanded.xml new file mode 100644 index 00000000..30f89df7 --- /dev/null +++ b/tests/fixtures/source/home:Admin/source_expanded.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/fixtures/source/home:Admin/wine b/tests/fixtures/source/home:Admin/wine deleted file mode 100644 index 4439fb15..00000000 --- a/tests/fixtures/source/home:Admin/wine +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/tests/fixtures/source/home:Admin/wine b/tests/fixtures/source/home:Admin/wine new file mode 120000 index 00000000..dcac5227 --- /dev/null +++ b/tests/fixtures/source/home:Admin/wine @@ -0,0 +1 @@ +source.xml \ No newline at end of file diff --git a/tests/obs.py b/tests/obs.py index 7465cceb..d15be9bc 100644 --- a/tests/obs.py +++ b/tests/obs.py @@ -228,12 +228,12 @@ class OBS(object): 'openSUSE:Factory:Staging:J/emacs': { 'prj': 'openSUSE:Factory:Staging:J', 'pkg': 'emacs', - 'devprj': 'editors', + 'devprj': 'home:Admin', }, 'openSUSE:Factory:Staging:J/python': { 'prj': 'openSUSE:Factory:Staging:J', 'pkg': 'python', - 'devprj': 'devel:languages:python:Factory', + 'devprj': 'home:Admin', }, } @@ -306,6 +306,18 @@ class OBS(object): 'name': 'mariadb', 'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb', }, + 'home:Admin/emacs': { + 'rev': '1', + 'vrev': '1', + 'name': 'emacs', + 'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb', + }, + 'home:Admin/python': { + 'rev': '1', + 'vrev': '1', + 'name': 'python', + 'srcmd5': 'de7a9f5e3bedb01980465f3be3d236cb', + }, } self.comments = { @@ -525,7 +537,7 @@ class OBS(object): return response - @GET(re.compile(r'/source/home:Admin/\w+')) + @GET(re.compile(r'/source/home:Admin/\w+(\?rev=\w+&expand=1)?')) def source_project(self, request, uri, headers): """Return information of a source package.""" package = re.search(r'/source/([\w:]+/\w+)', uri).group(1)